Author: sephe
Date: Mon Jun 13 08:38:04 2016
New Revision: 301864
URL: https://svnweb.freebsd.org/changeset/base/301864

Log:
  MFC 295875,295876,295877,295916,295918
  
  295875
      hyperv/hn: Rename TX related function and struct fields a bit
  
      Preamble to implement the ifnet.if_transmit method.
  
      Reviewed by:        adrian
      Approved by:        adrian (mentor)
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5344
  
  295876
      hyperv/hn: Staticize and rename packet TX done function
  
      It is only used in hv_netvsc_drv_freebsd.c; and rename it to hn_tx_done()
      mainly to reserve "xmit" for ifnet.if_transmit implement.
  
      While I'm here, remove unapplied comment.
  
      Reviewed by:        adrian
      Approved by:        adrian (mentor)
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5345
  
  295877
      hyperv/hn: Add TX method for txeof processing.
  
      Preamble to implement ifnet.if_transmit method.
  
      Reviewed by:        adrian
      Approved by:        adrian (mentor)
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5346
  
  295916
      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
  
  295918
      hyperv/hn: Use IFQ_DRV_PREPEND instead of IF_PREPEND
  
      IF_PREPEND promises out-of-order packet sending when the TX desc list
      is depleted. It was overlooked and copied blindly when the transmission
      path was partially rewritten.
  
      MFC after:  1 week
      Sponsored by:       Microsoft OSTC
      Differential Revision:      https://reviews.freebsd.org/D5386

Modified:
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h        Mon Jun 13 08:18:45 
2016        (r301863)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h        Mon Jun 13 08:38:04 
2016        (r301864)
@@ -1026,11 +1026,12 @@ struct hn_tx_ring {
 #endif
        int             hn_txdesc_cnt;
        int             hn_txdesc_avail;
-       int             hn_txeof;
+       int             hn_has_txeof;
 
        int             hn_sched_tx;
+       void            (*hn_txeof)(struct hn_tx_ring *);
        struct taskqueue *hn_tx_taskq;
-       struct task     hn_start_task;
+       struct task     hn_tx_task;
        struct task     hn_txeof_task;
 
        struct mtx      hn_tx_lock;
@@ -1087,7 +1088,6 @@ typedef struct hn_softc {
 extern int hv_promisc_mode;
 
 void netvsc_linkstatus_callback(struct hv_device *device_obj, uint32_t status);
-void netvsc_xmit_completion(void *context);
 void hv_nv_on_receive_completion(struct hv_device *device,
     uint64_t tid, uint32_t status);
 netvsc_dev *hv_nv_on_device_add(struct hv_device *device,

Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Mon Jun 13 
08:18:45 2016        (r301863)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Mon Jun 13 
08:38:04 2016        (r301864)
@@ -304,8 +304,8 @@ static int hn_create_tx_ring(struct hn_s
 static void hn_destroy_tx_ring(struct hn_tx_ring *);
 static int hn_create_tx_data(struct hn_softc *);
 static void hn_destroy_tx_data(struct hn_softc *);
-static void hn_start_taskfunc(void *xsc, int pending);
-static void hn_txeof_taskfunc(void *xsc, int pending);
+static void hn_start_taskfunc(void *, int);
+static void hn_start_txeof_taskfunc(void *, int);
 static void hn_stop_tx_tasks(struct hn_softc *);
 static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **);
 static void hn_create_rx_data(struct hn_softc *sc);
@@ -673,17 +673,10 @@ hn_txdesc_hold(struct hn_txdesc *txd)
        atomic_add_int(&txd->refs, 1);
 }
 
-/*
- * Send completion processing
- *
- * Note:  It looks like offset 0 of buf is reserved to hold the softc
- * pointer.  The sc pointer is not currently needed in this function, and
- * it is not presently populated by the TX function.
- */
-void
-netvsc_xmit_completion(void *context)
+static void
+hn_tx_done(void *xpkt)
 {
-       netvsc_packet *packet = context;
+       netvsc_packet *packet = xpkt;
        struct hn_txdesc *txd;
        struct hn_tx_ring *txr;
 
@@ -691,7 +684,7 @@ netvsc_xmit_completion(void *context)
            packet->compl.send.send_completion_tid;
 
        txr = txd->txr;
-       txr->hn_txeof = 1;
+       txr->hn_has_txeof = 1;
        hn_txdesc_put(txr, txd);
 }
 
@@ -711,11 +704,11 @@ netvsc_channel_rollup(struct hv_device *
        }
 #endif
 
-       if (!txr->hn_txeof)
+       if (!txr->hn_has_txeof)
                return;
 
-       txr->hn_txeof = 0;
-       hn_start_txeof(txr);
+       txr->hn_has_txeof = 0;
+       txr->hn_txeof(txr);
 }
 
 /*
@@ -925,7 +918,7 @@ done:
        txd->m = m_head;
 
        /* Set the completion routine */
-       packet->compl.send.on_send_completion = netvsc_xmit_completion;
+       packet->compl.send.on_send_completion = hn_tx_done;
        packet->compl.send.send_completion_context = packet;
        packet->compl.send.send_completion_tid = (uint64_t)(uintptr_t)txd;
 
@@ -933,6 +926,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
@@ -950,9 +1005,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)
@@ -964,14 +1019,14 @@ hn_start_locked(struct hn_tx_ring *txr, 
                         * dispatch this packet sending (and sending of any
                         * following up packets) to tx taskqueue.
                         */
-                       IF_PREPEND(&ifp->if_snd, m_head);
+                       IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
                        return 1;
                }
 
                txd = hn_txdesc_get(txr);
                if (txd == NULL) {
                        txr->hn_no_txdescs++;
-                       IF_PREPEND(&ifp->if_snd, m_head);
+                       IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
                        atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
                        break;
                }
@@ -981,53 +1036,11 @@ 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_txeof = 1;
-                       if (!send_failed) {
-                               txr->hn_send_failed++;
-                               send_failed = 1;
-                               /*
-                                * Try sending again after set hn_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++;
-                       IF_PREPEND(&ifp->if_snd, m_head);
+                       /* txd is freed, but m_head is not */
+                       IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
                        atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE);
                        break;
                }
@@ -1578,7 +1591,7 @@ hn_start(struct ifnet *ifp)
                        return;
        }
 do_sched:
-       taskqueue_enqueue(txr->hn_tx_taskq, &txr->hn_start_task);
+       taskqueue_enqueue(txr->hn_tx_taskq, &txr->hn_tx_task);
 }
 
 static void
@@ -1600,7 +1613,7 @@ hn_start_txeof(struct hn_tx_ring *txr)
                mtx_unlock(&txr->hn_tx_lock);
                if (sched) {
                        taskqueue_enqueue(txr->hn_tx_taskq,
-                           &txr->hn_start_task);
+                           &txr->hn_tx_task);
                }
        } else {
 do_sched:
@@ -2172,8 +2185,8 @@ hn_create_tx_ring(struct hn_softc *sc, i
 #endif
 
        txr->hn_tx_taskq = sc->hn_tx_taskq;
-       TASK_INIT(&txr->hn_start_task, 0, hn_start_taskfunc, txr);
-       TASK_INIT(&txr->hn_txeof_task, 0, hn_txeof_taskfunc, txr);
+       TASK_INIT(&txr->hn_tx_task, 0, hn_start_taskfunc, txr);
+       TASK_INIT(&txr->hn_txeof_task, 0, hn_start_txeof_taskfunc, txr);
 
        txr->hn_direct_tx_size = hn_direct_tx_size;
        if (hv_vmbus_protocal_version >= HV_VMBUS_VERSION_WIN8_1)
@@ -2187,6 +2200,8 @@ hn_create_tx_ring(struct hn_softc *sc, i
         */
        txr->hn_sched_tx = 1;
 
+       txr->hn_txeof = hn_start_txeof; /* TODO: if_transmit */
+
        parent_dtag = bus_get_dma_tag(sc->hn_dev);
 
        /* DMA tag for RNDIS messages. */
@@ -2468,7 +2483,7 @@ hn_start_taskfunc(void *xtxr, int pendin
 }
 
 static void
-hn_txeof_taskfunc(void *xtxr, int pending __unused)
+hn_start_txeof_taskfunc(void *xtxr, int pending __unused)
 {
        struct hn_tx_ring *txr = xtxr;
 
@@ -2486,7 +2501,7 @@ hn_stop_tx_tasks(struct hn_softc *sc)
        for (i = 0; i < sc->hn_tx_ring_cnt; ++i) {
                struct hn_tx_ring *txr = &sc->hn_tx_ring[i];
 
-               taskqueue_drain(txr->hn_tx_taskq, &txr->hn_start_task);
+               taskqueue_drain(txr->hn_tx_taskq, &txr->hn_tx_task);
                taskqueue_drain(txr->hn_tx_taskq, &txr->hn_txeof_task);
        }
 }
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "[email protected]"

Reply via email to