socsvn commit: r306419 - soc2016/vincenzo/head/sys/dev/netmap
vincenzo at FreeBSD.org
vincenzo at FreeBSD.org
Mon Jul 18 09:09:06 UTC 2016
Author: vincenzo
Date: Mon Jul 18 09:09:05 2016
New Revision: 306419
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=306419
Log:
freebsd: ptnet: implement a synchronization scheme for ifconfig down
Modified:
soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c
Modified: soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c
==============================================================================
--- soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c Mon Jul 18 09:08:46 2016 (r306418)
+++ soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c Mon Jul 18 09:09:05 2016 (r306419)
@@ -196,7 +196,7 @@
static unsigned ptnet_rx_discard(struct netmap_kring *kring,
unsigned int head);
-static int ptnet_rx_eof(struct ptnet_queue *pq);
+static void ptnet_rx_eof(struct ptnet_queue *pq);
static void ptnet_rx_task(void *context, int pending);
static device_method_t ptnet_methods[] = {
@@ -857,6 +857,7 @@
{
struct ifnet *ifp = sc->ifp;
struct netmap_adapter *na_dr = &sc->ptna_dr.hwup.up;
+ int i;
device_printf(sc->dev, "%s\n", __func__);
@@ -864,7 +865,14 @@
return 0; /* nothing to do */
}
- /* XXX Here we should wait for all TX and RX worker to finish. */
+ /* Clear the driver-ready flag, and synchronize with all the queues,
+ * so that after this loop we are sure nobody is working anymore with
+ * the device. This scheme is taken from the vtnet driver. */
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ for (i = 0; i < sc->num_rings; i++) {
+ PTNET_Q_LOCK(sc->queues + i);
+ PTNET_Q_UNLOCK(sc->queues + i);
+ }
ptnet_nm_register(na_dr, 0 /* off */);
@@ -874,8 +882,6 @@
}
netmap_mem_deref(na_dr->nm_mem, na_dr);
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-
return 0;
}
@@ -1196,10 +1202,6 @@
DBG(device_printf(sc->dev, "Tx interrupt #%d\n", pq->kring_id));
- if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- return;
- }
-
if (netmap_tx_irq(sc->ifp, pq->kring_id) != NM_IRQ_PASS) {
return;
}
@@ -1220,10 +1222,6 @@
DBG(device_printf(sc->dev, "Rx interrupt #%d\n", pq->kring_id));
- if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- return;
- }
-
if (netmap_rx_irq(sc->ifp, pq->kring_id, &unused) != NM_IRQ_PASS) {
return;
}
@@ -1592,6 +1590,8 @@
((((_h) < (_k)->rtail) ? 0 : (_k)->nkr_num_slots) + \
(_k)->rtail - (_h)) < (_min)
+/* This function may be called by the network stack, or by
+ * by the taskqueue thread. */
static int
ptnet_drain_transmit_queue(struct ptnet_queue *pq)
{
@@ -1612,14 +1612,6 @@
int nmbuf_bytes;
uint8_t *nmbuf;
- if (unlikely(!(ifp->if_drv_flags & IFF_DRV_RUNNING))) {
- RD(1, "Interface is down");
- return ENETDOWN;
- }
-
- /* Here we may be called by the network stack, or by
- * by the taskqueue thread. */
-
if (!PTNET_Q_TRYLOCK(pq)) {
/* We failed to acquire the lock, schedule the taskqueue. */
RD(1, "Deferring TX work");
@@ -1628,6 +1620,12 @@
return 0;
}
+ if (unlikely(!(ifp->if_drv_flags & IFF_DRV_RUNNING))) {
+ PTNET_Q_UNLOCK(pq);
+ RD(1, "Interface is down");
+ return ENETDOWN;
+ }
+
ptring = pq->ptring;
kring = na->tx_rings + pq->kring_id;
ring = kring->ring;
@@ -1861,7 +1859,7 @@
return mtail;
}
-static int
+static void
ptnet_rx_eof(struct ptnet_queue *pq)
{
struct ptnet_softc *sc = pq->sc;
@@ -1878,6 +1876,10 @@
PTNET_Q_LOCK(pq);
+ if (unlikely(!(ifp->if_drv_flags & IFF_DRV_RUNNING))) {
+ goto unlock;
+ }
+
kring->nr_kflags &= ~NKR_PENDINTR;
do {
@@ -2027,6 +2029,12 @@
(*ifp->if_input)(ifp, mhead);
PTNET_Q_LOCK(pq);
+ if (unlikely(!(ifp->if_drv_flags & IFF_DRV_RUNNING))) {
+ /* The interface has gone down while we didn't
+ * have the lock. Stop any processing and exit. */
+ goto unlock;
+ }
+
if (++batch_count == PTNET_RX_BATCH) {
/* Some packets have been pushed to the network stack.
* We need to update the CSB to tell the host about the new
@@ -2048,10 +2056,8 @@
head, ring->tail));
taskqueue_enqueue(pq->taskq, &pq->task);
}
-
+unlock:
PTNET_Q_UNLOCK(pq);
-
- return 0;
}
static void
More information about the svn-soc-all
mailing list