Date: Mon, 18 Jul 2016 09:09:27 GMT From: vincenzo@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r306421 - soc2016/vincenzo/head/sys/dev/netmap Message-ID: <201607180909.u6I99Rpu056568@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201607180909.u6I99Rpu056568>