svn commit: r295916 - head/sys/dev/hyperv/netvsc

Sepherosa Ziehau sephe at FreeBSD.org
Tue Feb 23 09:20:34 UTC 2016


Author: sephe
Date: Tue Feb 23 09:20:33 2016
New Revision: 295916
URL: https://svnweb.freebsd.org/changeset/base/295916

Log:
  hyperv/hn: Factor out hn_send_pkt() from hn_start_locked()
  
  It will be shared w/ the upcoming ifnet.if_transmit method
  implementation.
  
  No functional change.
  
  MFC after:	1 week
  Sponsored by:	Microsoft OSTC
  Differential Revision:	https://reviews.freebsd.org/D5385

Modified:
  head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c

Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Tue Feb 23 08:12:39 2016	(r295915)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Tue Feb 23 09:20:33 2016	(r295916)
@@ -905,6 +905,68 @@ done:
 }
 
 /*
+ * NOTE:
+ * If this function fails, then txd will be freed, but the mbuf
+ * associated w/ the txd will _not_ be freed.
+ */
+static int
+hn_send_pkt(struct ifnet *ifp, struct hv_device *device_ctx,
+    struct hn_tx_ring *txr, struct hn_txdesc *txd)
+{
+	int error, send_failed = 0;
+
+again:
+	/*
+	 * Make sure that txd is not freed before ETHER_BPF_MTAP.
+	 */
+	hn_txdesc_hold(txd);
+	error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt);
+	if (!error) {
+		ETHER_BPF_MTAP(ifp, txd->m);
+		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+	}
+	hn_txdesc_put(txr, txd);
+
+	if (__predict_false(error)) {
+		int freed;
+
+		/*
+		 * This should "really rarely" happen.
+		 *
+		 * XXX Too many RX to be acked or too many sideband
+		 * commands to run?  Ask netvsc_channel_rollup()
+		 * to kick start later.
+		 */
+		txr->hn_has_txeof = 1;
+		if (!send_failed) {
+			txr->hn_send_failed++;
+			send_failed = 1;
+			/*
+			 * Try sending again after set hn_has_txeof;
+			 * in case that we missed the last
+			 * netvsc_channel_rollup().
+			 */
+			goto again;
+		}
+		if_printf(ifp, "send failed\n");
+
+		/*
+		 * Caller will perform further processing on the
+		 * associated mbuf, so don't free it in hn_txdesc_put();
+		 * only unload it from the DMA map in hn_txdesc_put(),
+		 * if it was loaded.
+		 */
+		txd->m = NULL;
+		freed = hn_txdesc_put(txr, txd);
+		KASSERT(freed != 0,
+		    ("fail to free txd upon send error"));
+
+		txr->hn_send_failed++;
+	}
+	return error;
+}
+
+/*
  * Start a transmit of one or more packets
  */
 static int
@@ -922,9 +984,9 @@ hn_start_locked(struct hn_tx_ring *txr, 
 		return 0;
 
 	while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
-		int error, send_failed = 0;
 		struct hn_txdesc *txd;
 		struct mbuf *m_head;
+		int error;
 
 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
@@ -953,52 +1015,10 @@ hn_start_locked(struct hn_tx_ring *txr, 
 			/* Both txd and m_head are freed */
 			continue;
 		}
-again:
-		/*
-		 * Make sure that txd is not freed before ETHER_BPF_MTAP.
-		 */
-		hn_txdesc_hold(txd);
-		error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt);
-		if (!error) {
-			ETHER_BPF_MTAP(ifp, m_head);
-			if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-		}
-		hn_txdesc_put(txr, txd);
 
+		error = hn_send_pkt(ifp, device_ctx, txr, txd);
 		if (__predict_false(error)) {
-			int freed;
-
-			/*
-			 * This should "really rarely" happen.
-			 *
-			 * XXX Too many RX to be acked or too many sideband
-			 * commands to run?  Ask netvsc_channel_rollup()
-			 * to kick start later.
-			 */
-			txr->hn_has_txeof = 1;
-			if (!send_failed) {
-				txr->hn_send_failed++;
-				send_failed = 1;
-				/*
-				 * Try sending again after set hn_has_txeof;
-				 * in case that we missed the last
-				 * netvsc_channel_rollup().
-				 */
-				goto again;
-			}
-			if_printf(ifp, "send failed\n");
-
-			/*
-			 * This mbuf will be prepended, don't free it
-			 * in hn_txdesc_put(); only unload it from the
-			 * DMA map in hn_txdesc_put(), if it was loaded.
-			 */
-			txd->m = NULL;
-			freed = hn_txdesc_put(txr, txd);
-			KASSERT(freed != 0,
-			    ("fail to free txd upon send error"));
-
-			txr->hn_send_failed++;
+			/* txd is freed, but m_head is not */
 			IF_PREPEND(&ifp->if_snd, m_head);
 			atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
 			break;


More information about the svn-src-all mailing list