svn commit: r301864 - stable/10/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Mon Jun 13 08:38:06 UTC 2016
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);
}
}
More information about the svn-src-stable-10
mailing list