diff options
author | Kip Macy <kmacy@FreeBSD.org> | 2007-07-10 06:01:45 +0000 |
---|---|---|
committer | Kip Macy <kmacy@FreeBSD.org> | 2007-07-10 06:01:45 +0000 |
commit | b8fe6051bfdfd8135145ef496e8849e485d196c2 (patch) | |
tree | f02f439cb70df3e187e78d4eb9bd5aac5fa67708 /sys/dev/cxgb/cxgb_sge.c | |
parent | c108b80c8c9f5c62896a6566b88269a571d0c6c0 (diff) | |
download | src-b8fe6051bfdfd8135145ef496e8849e485d196c2.tar.gz src-b8fe6051bfdfd8135145ef496e8849e485d196c2.zip |
MFp4 122896
- reduce cpu usage by as much as 25% (40% -> 30) by doing txq reclaim more efficiently
- use mtx_trylock when trying to grab the lock to avoid spinning during long encap loop
- add per-txq reclaim task
- if mbufs were successfully re-claimed try another pass
- track txq overruns with sysctl
Approved by: re (blanket)
Notes
Notes:
svn path=/head/; revision=171335
Diffstat (limited to 'sys/dev/cxgb/cxgb_sge.c')
-rw-r--r-- | sys/dev/cxgb/cxgb_sge.c | 106 |
1 files changed, 67 insertions, 39 deletions
diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c index 17e165399313..48dbe4547b0c 100644 --- a/sys/dev/cxgb/cxgb_sge.c +++ b/sys/dev/cxgb/cxgb_sge.c @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$"); uint32_t collapse_free = 0; uint32_t mb_free_vec_free = 0; +int txq_fills = 0; int collapse_mbufs = 0; static int recycle_enable = 1; @@ -186,7 +187,8 @@ int cxgb_debug = 0; static void t3_free_qset(adapter_t *sc, struct sge_qset *q); static void sge_timer_cb(void *arg); static void sge_timer_reclaim(void *arg, int ncount); -static int free_tx_desc(adapter_t *sc, struct sge_txq *q, int n, struct mbuf **m_vec); +static void sge_txq_reclaim_handler(void *arg, int ncount); +static int free_tx_desc(struct sge_txq *q, int n, struct mbuf **m_vec); /** * reclaim_completed_tx - reclaims completed Tx descriptors @@ -198,14 +200,14 @@ static int free_tx_desc(adapter_t *sc, struct sge_txq *q, int n, struct mbuf **m * queue's lock held. */ static __inline int -reclaim_completed_tx(adapter_t *adapter, struct sge_txq *q, int nbufs, struct mbuf **mvec) +reclaim_completed_tx(struct sge_txq *q, int nbufs, struct mbuf **mvec) { int reclaimed, reclaim = desc_reclaimable(q); int n = 0; mtx_assert(&q->lock, MA_OWNED); if (reclaim > 0) { - n = free_tx_desc(adapter, q, min(reclaim, nbufs), mvec); + n = free_tx_desc(q, min(reclaim, nbufs), mvec); reclaimed = min(reclaim, nbufs); q->cleaned += reclaimed; q->in_use -= reclaimed; @@ -742,6 +744,45 @@ refill_rspq(adapter_t *sc, const struct sge_rspq *q, u_int credits) V_RSPQ(q->cntxt_id) | V_CREDITS(credits)); } +static __inline void +sge_txq_reclaim_(struct sge_txq *txq) +{ + int reclaimable, i, n; + struct mbuf *m_vec[TX_CLEAN_MAX_DESC]; + struct port_info *p; + + p = txq->port; +reclaim_more: + n = 0; + reclaimable = desc_reclaimable(txq); + if (reclaimable > 0 && mtx_trylock(&txq->lock)) { + n = reclaim_completed_tx(txq, TX_CLEAN_MAX_DESC, m_vec); + mtx_unlock(&txq->lock); + } + if (n == 0) + return; + + for (i = 0; i < n; i++) { + m_freem_vec(m_vec[i]); + } + if (p && p->ifp->if_drv_flags & IFF_DRV_OACTIVE && + txq->size - txq->in_use >= TX_START_MAX_DESC) { + txq_fills++; + p->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + taskqueue_enqueue(p->tq, &p->start_task); + } + + if (n) + goto reclaim_more; +} + +static void +sge_txq_reclaim_handler(void *arg, int ncount) +{ + struct sge_txq *q = arg; + + sge_txq_reclaim_(q); +} static void sge_timer_reclaim(void *arg, int ncount) @@ -752,39 +793,15 @@ sge_timer_reclaim(void *arg, int ncount) struct sge_qset *qs; struct sge_txq *txq; struct mtx *lock; - struct mbuf *m_vec[TX_CLEAN_MAX_DESC]; - int n, reclaimable; for (i = 0; i < nqsets; i++) { qs = &sc->sge.qs[i]; txq = &qs->txq[TXQ_ETH]; - reclaimable = desc_reclaimable(txq); - if (reclaimable > 0) { - mtx_lock(&txq->lock); - n = reclaim_completed_tx(sc, txq, TX_CLEAN_MAX_DESC, m_vec); - mtx_unlock(&txq->lock); - - for (i = 0; i < n; i++) - m_freem_vec(m_vec[i]); - - if (p->ifp->if_drv_flags & IFF_DRV_OACTIVE && - txq->size - txq->in_use >= TX_START_MAX_DESC) { - p->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - taskqueue_enqueue(p->tq, &p->start_task); - } - } + sge_txq_reclaim_(txq); txq = &qs->txq[TXQ_OFLD]; - reclaimable = desc_reclaimable(txq); - if (reclaimable > 0) { - mtx_lock(&txq->lock); - n = reclaim_completed_tx(sc, txq, TX_CLEAN_MAX_DESC, m_vec); - mtx_unlock(&txq->lock); - - for (i = 0; i < n; i++) - m_freem_vec(m_vec[i]); - } - + sge_txq_reclaim_(txq); + lock = (sc->flags & USING_MSIX) ? &qs->rspq.lock : &sc->sge.qs[0].rspq.lock; @@ -1561,8 +1578,8 @@ t3_sge_stop(adapter_t *sc) for (i = 0; i < nqsets; ++i) { struct sge_qset *qs = &sc->sge.qs[i]; - taskqueue_drain(sc->tq, &qs->txq[TXQ_OFLD].qresume_tsk); - taskqueue_drain(sc->tq, &qs->txq[TXQ_CTRL].qresume_tsk); + taskqueue_drain(sc->tq, &qs->txq[TXQ_OFLD].qresume_task); + taskqueue_drain(sc->tq, &qs->txq[TXQ_CTRL].qresume_task); } } @@ -1577,7 +1594,7 @@ t3_sge_stop(adapter_t *sc) * Tx buffers. Called with the Tx queue lock held. */ int -free_tx_desc(adapter_t *sc, struct sge_txq *q, int n, struct mbuf **m_vec) +free_tx_desc(struct sge_txq *q, int n, struct mbuf **m_vec) { struct tx_sw_desc *d; unsigned int cidx = q->cidx; @@ -1738,7 +1755,7 @@ ofld_xmit(adapter_t *adap, struct sge_txq *q, struct mbuf *m) return (ret); } ndesc = calc_tx_descs_ofld(m, nsegs); -again: cleaned = reclaim_completed_tx(adap, q, TX_CLEAN_MAX_DESC, m_vec); +again: cleaned = reclaim_completed_tx(q, TX_CLEAN_MAX_DESC, m_vec); ret = check_desc_avail(adap, q, m, ndesc, TXQ_OFLD); if (__predict_false(ret)) { @@ -1795,7 +1812,7 @@ restart_offloadq(void *data, int npending) struct tx_sw_desc *stx = &q->sdesc[q->pidx]; mtx_lock(&q->lock); -again: cleaned = reclaim_completed_tx(adap, q, TX_CLEAN_MAX_DESC, m_vec); +again: cleaned = reclaim_completed_tx(q, TX_CLEAN_MAX_DESC, m_vec); while ((m = mbufq_peek(&q->sendq)) != NULL) { unsigned int gen, pidx; @@ -1934,13 +1951,13 @@ restart_tx(struct sge_qset *qs) should_restart_tx(&qs->txq[TXQ_OFLD]) && test_and_clear_bit(TXQ_OFLD, &qs->txq_stopped)) { qs->txq[TXQ_OFLD].restarts++; - taskqueue_enqueue(sc->tq, &qs->txq[TXQ_OFLD].qresume_tsk); + taskqueue_enqueue(sc->tq, &qs->txq[TXQ_OFLD].qresume_task); } if (isset(&qs->txq_stopped, TXQ_CTRL) && should_restart_tx(&qs->txq[TXQ_CTRL]) && test_and_clear_bit(TXQ_CTRL, &qs->txq_stopped)) { qs->txq[TXQ_CTRL].restarts++; - taskqueue_enqueue(sc->tq, &qs->txq[TXQ_CTRL].qresume_tsk); + taskqueue_enqueue(sc->tq, &qs->txq[TXQ_CTRL].qresume_task); } } @@ -2019,8 +2036,15 @@ t3_sge_alloc_qset(adapter_t *sc, u_int id, int nports, int irq_vec_idx, MTX_INIT(&q->txq[i].lock, q->txq[i].lockbuf, NULL, MTX_DEF); } - TASK_INIT(&q->txq[TXQ_OFLD].qresume_tsk, 0, restart_offloadq, q); - TASK_INIT(&q->txq[TXQ_CTRL].qresume_tsk, 0, restart_ctrlq, q); + q->txq[TXQ_ETH].port = pi; + + TASK_INIT(&q->txq[TXQ_OFLD].qresume_task, 0, restart_offloadq, q); + TASK_INIT(&q->txq[TXQ_CTRL].qresume_task, 0, restart_ctrlq, q); + TASK_INIT(&q->txq[TXQ_OFLD].qreclaim_task, 0, sge_txq_reclaim_handler, &q->txq[TXQ_ETH]); + TASK_INIT(&q->txq[TXQ_CTRL].qreclaim_task, 0, sge_txq_reclaim_handler, &q->txq[TXQ_OFLD]); + + + q->fl[0].gen = q->fl[1].gen = 1; q->fl[0].size = p->fl_size; @@ -2636,6 +2660,10 @@ t3_add_sysctls(adapter_t *sc) "collapse_mbufs", CTLFLAG_RW, &collapse_mbufs, 0, "collapse mbuf chains into iovecs"); + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "txq_overrun", + CTLFLAG_RD, &txq_fills, + 0, "#times txq overrun"); } /** |