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