socsvn commit: r306421 - soc2016/vincenzo/head/sys/dev/netmap

vincenzo at FreeBSD.org vincenzo at FreeBSD.org
Mon Jul 18 09:09:28 UTC 2016


Author: vincenzo
Date: Mon Jul 18 09:09:26 2016
New Revision: 306421
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=306421

Log:
   freebsd: ptnet: implement polling function

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:09:17 2016	(r306420)
+++ soc2016/vincenzo/head/sys/dev/netmap/if_ptnet.c	Mon Jul 18 09:09:26 2016	(r306421)
@@ -170,7 +170,9 @@
 static int	ptnet_init_locked(struct ptnet_softc *sc);
 static int	ptnet_stop(struct ptnet_softc *sc);
 static int	ptnet_transmit(struct ifnet *ifp, struct mbuf *m);
-static int	ptnet_drain_transmit_queue(struct ptnet_queue *pq);
+static int	ptnet_drain_transmit_queue(struct ptnet_queue *pq,
+					   unsigned int budget,
+					   bool may_resched);
 static void	ptnet_qflush(struct ifnet *ifp);
 static void	ptnet_tx_task(void *context, int pending);
 
@@ -196,7 +198,8 @@
 
 static unsigned	ptnet_rx_discard(struct netmap_kring *kring,
 				 unsigned int head);
-static void	ptnet_rx_eof(struct ptnet_queue *pq);
+static int	ptnet_rx_eof(struct ptnet_queue *pq, unsigned int budget,
+			     bool may_resched);
 static void	ptnet_rx_task(void *context, int pending);
 
 #ifdef DEVICE_POLLING
@@ -241,6 +244,7 @@
 #define PTNET_BUF_RING_SIZE	4096
 #define PTNET_RX_BUDGET		512
 #define PTNET_RX_BATCH		1
+#define PTNET_TX_BUDGET		512
 #define PTNET_TX_BATCH		64
 #define PTNET_HDR_SIZE		sizeof(struct virtio_net_hdr_mrg_rxbuf)
 #define PTNET_MAX_PKT_SIZE	65536
@@ -1273,7 +1277,7 @@
 	/* Like vtnet, if_igb and if_em drivers when using MSI-X interrupts,
 	 * receive-side processing is executed directly in the interrupt
 	 * service routine. Alternatively, we may schedule the taskqueue. */
-	ptnet_rx_eof(pq);
+	ptnet_rx_eof(pq, PTNET_RX_BUDGET, true);
 }
 
 /* The following offloadings-related functions are taken from the vtnet
@@ -1637,7 +1641,8 @@
 /* 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)
+ptnet_drain_transmit_queue(struct ptnet_queue *pq, unsigned int budget,
+			   bool may_resched)
 {
 	struct ptnet_softc *sc = pq->sc;
 	bool have_vnet_hdr = sc->vnet_hdr_len;
@@ -1648,6 +1653,7 @@
 	struct netmap_kring *kring;
 	struct netmap_ring *ring;
 	struct netmap_slot *slot;
+	unsigned int count = 0;
 	unsigned int minspace;
 	unsigned int head;
 	unsigned int lim;
@@ -1659,7 +1665,9 @@
 	if (!PTNET_Q_TRYLOCK(pq)) {
 		/* We failed to acquire the lock, schedule the taskqueue. */
 		RD(1, "Deferring TX work");
-		taskqueue_enqueue(pq->taskq, &pq->task);
+		if (may_resched) {
+			taskqueue_enqueue(pq->taskq, &pq->task);
+		}
 
 		return 0;
 	}
@@ -1677,7 +1685,7 @@
 	head = ring->head;
 	minspace = sc->min_tx_space;
 
-	for (;;) {
+	while (count < budget) {
 		if (PTNET_TX_NOSPACE(head, kring, minspace)) {
 			/* We ran out of slot, let's see if the host has
 			 * freed up some, by reading hwcur and hwtail from
@@ -1793,6 +1801,7 @@
 
 		m_freem(mhead);
 
+		count ++;
 		if (++batch_count == PTNET_TX_BATCH) {
 			ptnet_ring_update(pq, kring, head, NAF_FORCE_RECLAIM);
 			batch_count = 0;
@@ -1803,9 +1812,15 @@
 		ptnet_ring_update(pq, kring, head, NAF_FORCE_RECLAIM);
 	}
 
+	if (count >= budget && may_resched) {
+		DBG(RD(1, "out of budget: resched, %d mbufs pending\n",
+					drbr_inuse(ifp, pq->bufring)));
+		taskqueue_enqueue(pq->taskq, &pq->task);
+	}
+
 	PTNET_Q_UNLOCK(pq);
 
-	return 0;
+	return count;
 }
 
 static int
@@ -1845,7 +1860,9 @@
 		return err;
 	}
 
-	return ptnet_drain_transmit_queue(pq);
+	err = ptnet_drain_transmit_queue(pq, PTNET_TX_BUDGET, true);
+
+	return (err < 0) ? err : 0;
 }
 
 static unsigned int
@@ -1903,8 +1920,8 @@
 	return mtail;
 }
 
-static void
-ptnet_rx_eof(struct ptnet_queue *pq)
+static int
+ptnet_rx_eof(struct ptnet_queue *pq, unsigned int budget, bool may_resched)
 {
 	struct ptnet_softc *sc = pq->sc;
 	bool have_vnet_hdr = sc->vnet_hdr_len;
@@ -1913,10 +1930,10 @@
 	struct netmap_kring *kring = na->rx_rings + pq->kring_id;
 	struct netmap_ring *ring = kring->ring;
 	unsigned int const lim = kring->nkr_num_slots - 1;
-	unsigned int budget = PTNET_RX_BUDGET;
 	unsigned int head = ring->head;
 	unsigned int batch_count = 0;
 	struct ifnet *ifp = sc->ifp;
+	unsigned int count = 0;
 
 	PTNET_Q_LOCK(pq);
 
@@ -1926,7 +1943,7 @@
 
 	kring->nr_kflags &= ~NKR_PENDINTR;
 
-	do {
+	while (count < budget) {
 		unsigned int prev_head = head;
 		struct mbuf *mhead, *mtail;
 		struct virtio_net_hdr *vh;
@@ -2014,8 +2031,10 @@
 					__func__, head, prev_head);
 				head = prev_head;
 				m_freem(mhead);
-				taskqueue_enqueue(pq->taskq,
-						  &pq->task);
+				if (may_resched) {
+					taskqueue_enqueue(pq->taskq,
+							  &pq->task);
+				}
 				goto escape;
 			}
 
@@ -2079,6 +2098,7 @@
 			goto unlock;
 		}
 
+		count ++;
 		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
@@ -2086,14 +2106,14 @@
 			ptnet_ring_update(pq, kring, head, NAF_FORCE_READ);
 			batch_count = 0;
 		}
-	} while (--budget);
+	}
 escape:
 	if (batch_count) {
 		ptnet_ring_update(pq, kring, head, NAF_FORCE_READ);
 
 	}
 
-	if (!budget) {
+	if (count >= budget && may_resched) {
 		/* If we ran out of budget or the double-check found new
 		 * slots to process, schedule the taskqueue. */
 		DBG(RD(1, "out of budget: resched h %u t %u\n",
@@ -2102,6 +2122,8 @@
 	}
 unlock:
 	PTNET_Q_UNLOCK(pq);
+
+	return count;
 }
 
 static void
@@ -2110,7 +2132,7 @@
 	struct ptnet_queue *pq = context;
 
 	DBG(RD(1, "%s: pq #%u\n", __func__, pq->kring_id));
-	ptnet_rx_eof(pq);
+	ptnet_rx_eof(pq, PTNET_RX_BUDGET, true);
 }
 
 static void
@@ -2119,22 +2141,65 @@
 	struct ptnet_queue *pq = context;
 
 	DBG(RD(1, "%s: pq #%u\n", __func__, pq->kring_id));
-	ptnet_drain_transmit_queue(pq);
+	ptnet_drain_transmit_queue(pq, PTNET_TX_BUDGET, true);
 }
 
 #ifdef DEVICE_POLLING
+/* We don't need to handle differently POLL_AND_CHECK_STATUS and
+ * POLL_ONLY, since we don't have an Interrupt Status Register. */
 static int
-ptnet_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+ptnet_poll(struct ifnet *ifp, enum poll_cmd cmd, int budget)
 {
 	struct ptnet_softc *sc = ifp->if_softc;
+	unsigned int queue_budget;
+	unsigned int count = 0;
+	bool borrow = false;
+	int i;
 
-	/* We don't need to handle differently POLL_AND_CHECK_STATUS and
-	 * POLL_ONLY, since we don't have an Interrupt Status Register. */
+	KASSERT(sc->num_rings > 0, "Found no queues in while polling ptnet");
+	queue_budget = MIN(budget / sc->num_rings, 1);
+	RD(1, "Per-queue budget is %d", queue_budget);
+
+	while (budget) {
+		unsigned int rcnt = 0;
+
+		for (i = 0; i < sc->num_rings; i++) {
+			struct ptnet_queue *pq = sc->queues + i;
+
+			if (borrow) {
+				queue_budget = MIN(queue_budget, budget);
+				if (queue_budget == 0) {
+					break;
+				}
+			}
+
+			if (i < sc->num_tx_rings) {
+				rcnt += ptnet_drain_transmit_queue(pq,
+						   queue_budget, false);
+			} else {
+				rcnt += ptnet_rx_eof(pq, queue_budget,
+						      false);
+			}
+		}
+
+		if (!rcnt) {
+			/* A scan of the queues gave no result, we can
+			 * stop here. */
+			break;
+		}
+
+		if (rcnt > budget) {
+			/* This may happen when initial budget < sc->num_rings,
+			 * since one packet budget is given to each queue
+			 * anyway. Just pretend we didn't eat "so much". */
+			rcnt = budget;
+		}
+		count += rcnt;
+		budget -= rcnt;
+		borrow = true;
+	}
 
-	//rx_done = ptnet_rx_eof(pq)
-	// ptnet_drain_transmit_queue(pq);
-	(void)sc;
 
-	return 0; //(rx_done);
+	return count;
 }
 #endif /* DEVICE_POLLING */


More information about the svn-soc-all mailing list