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;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to