From owner-svn-src-head@FreeBSD.ORG Sat Mar 5 03:54:38 2011 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3500F1065672; Sat, 5 Mar 2011 03:54:38 +0000 (UTC) (envelope-from np@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 22BF28FC19; Sat, 5 Mar 2011 03:54:38 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p253sbKj002801; Sat, 5 Mar 2011 03:54:37 GMT (envelope-from np@svn.freebsd.org) Received: (from np@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p253sbL2002799; Sat, 5 Mar 2011 03:54:37 GMT (envelope-from np@svn.freebsd.org) Message-Id: <201103050354.p253sbL2002799@svn.freebsd.org> From: Navdeep Parhar Date: Sat, 5 Mar 2011 03:54:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r219292 - head/sys/dev/cxgbe X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Mar 2011 03:54:38 -0000 Author: np Date: Sat Mar 5 03:54:37 2011 New Revision: 219292 URL: http://svn.freebsd.org/changeset/base/219292 Log: Calculate how many descriptors can be reclaimed before calling reclaim_tx_descs Modified: head/sys/dev/cxgbe/t4_sge.c Modified: head/sys/dev/cxgbe/t4_sge.c ============================================================================== --- head/sys/dev/cxgbe/t4_sge.c Sat Mar 5 03:46:24 2011 (r219291) +++ head/sys/dev/cxgbe/t4_sge.c Sat Mar 5 03:54:37 2011 (r219292) @@ -135,6 +135,7 @@ static inline void write_ulp_cpl_sgl(str static int write_sgl_to_txd(struct sge_eq *, struct sgl *, caddr_t *); static inline void copy_to_txd(struct sge_eq *, caddr_t, caddr_t *, int); static inline void ring_tx_db(struct adapter *, struct sge_eq *); +static inline int reclaimable(struct sge_eq *); static int reclaim_tx_descs(struct sge_eq *, int, int); static void write_eqflush_wr(struct sge_eq *); static __be64 get_flit(bus_dma_segment_t *, int, int); @@ -753,22 +754,21 @@ t4_eth_tx(struct ifnet *ifp, struct sge_ struct sge_eq *eq = &txq->eq; struct buf_ring *br = eq->br; struct mbuf *next; - int rc, coalescing; + int rc, coalescing, can_reclaim; struct txpkts txpkts; struct sgl sgl; TXQ_LOCK_ASSERT_OWNED(txq); KASSERT(m, ("%s: called with nothing to do.", __func__)); + prefetch(&eq->desc[eq->pidx]); + prefetch(&eq->sdesc[eq->pidx]); + txpkts.npkt = 0;/* indicates there's nothing in txpkts */ coalescing = 0; - prefetch(&eq->sdesc[eq->pidx]); - prefetch(&eq->desc[eq->pidx]); - prefetch(&eq->maps[eq->map_pidx]); - if (eq->avail < 8) - reclaim_tx_descs(eq, 1, 8); + reclaim_tx_descs(eq, 0, 8); for (; m; m = next ? next : drbr_dequeue(ifp, br)) { @@ -824,7 +824,7 @@ t4_eth_tx(struct ifnet *ifp, struct sge_ coalescing = 0; if (eq->avail < 8) - reclaim_tx_descs(eq, 1, 8); + reclaim_tx_descs(eq, 0, 8); rc = write_txpkt_wr(pi, txq, m, &sgl); if (rc != 0) { @@ -851,7 +851,10 @@ doorbell: /* Fewer and fewer doorbells as the queue fills up */ if (eq->pending >= (1 << (fls(eq->qsize - eq->avail) / 2))) ring_tx_db(sc, eq); - reclaim_tx_descs(eq, 16, 32); + + can_reclaim = reclaimable(eq); + if (can_reclaim >= 32) + reclaim_tx_descs(eq, can_reclaim, 32); } if (txpkts.npkt > 0) @@ -874,7 +877,9 @@ doorbell: if (eq->pending) ring_tx_db(sc, eq); - reclaim_tx_descs(eq, 16, eq->qsize); + can_reclaim = reclaimable(eq); + if (can_reclaim >= 32) + reclaim_tx_descs(eq, can_reclaim, 128); return (0); } @@ -2271,32 +2276,40 @@ ring_tx_db(struct adapter *sc, struct sg eq->pending = 0; } -static int -reclaim_tx_descs(struct sge_eq *eq, int atleast, int howmany) +static inline int +reclaimable(struct sge_eq *eq) { - struct tx_sdesc *txsd; - struct tx_map *txm, *next_txm; - unsigned int cidx, can_reclaim, reclaimed, maps, next_map_cidx; - - EQ_LOCK_ASSERT_OWNED(eq); + unsigned int cidx; cidx = eq->spg->cidx; /* stable snapshot */ cidx = be16_to_cpu(cidx); if (cidx >= eq->cidx) - can_reclaim = cidx - eq->cidx; + return (cidx - eq->cidx); else - can_reclaim = cidx + eq->cap - eq->cidx; + return (cidx + eq->cap - eq->cidx); +} + +/* + * There are "can_reclaim" tx descriptors ready to be reclaimed. Reclaim as + * many as possible but stop when there are around "n" mbufs to free. + * + * The actual number reclaimed is provided as the return value. + */ +static int +reclaim_tx_descs(struct sge_eq *eq, int can_reclaim, int n) +{ + struct tx_sdesc *txsd; + struct tx_map *txm; + unsigned int reclaimed, maps; - if (can_reclaim < atleast) - return (0); + EQ_LOCK_ASSERT_OWNED(eq); - next_map_cidx = eq->map_cidx; - next_txm = txm = &eq->maps[next_map_cidx]; - prefetch(txm); + if (can_reclaim == 0) + can_reclaim = reclaimable(eq); maps = reclaimed = 0; - do { + while (can_reclaim && maps < n) { int ndesc; txsd = &eq->sdesc[eq->cidx]; @@ -2308,15 +2321,18 @@ reclaim_tx_descs(struct sge_eq *eq, int __func__, can_reclaim, ndesc)); maps += txsd->map_used; + reclaimed += ndesc; + can_reclaim -= ndesc; eq->cidx += ndesc; - if (eq->cidx >= eq->cap) + if (__predict_false(eq->cidx >= eq->cap)) eq->cidx -= eq->cap; + } - can_reclaim -= ndesc; - - } while (can_reclaim && reclaimed < howmany); + txm = &eq->maps[eq->map_cidx]; + if (maps) + prefetch(txm->m); eq->avail += reclaimed; KASSERT(eq->avail < eq->cap, /* avail tops out at (cap - 1) */ @@ -2326,22 +2342,22 @@ reclaim_tx_descs(struct sge_eq *eq, int KASSERT(eq->map_avail <= eq->map_total, ("%s: too many maps available", __func__)); - prefetch(txm->m); while (maps--) { - next_txm++; - if (++next_map_cidx == eq->map_total) { - next_map_cidx = 0; - next_txm = eq->maps; - } - prefetch(next_txm->m); + struct tx_map *next; + + next = txm + 1; + if (__predict_false(eq->map_cidx + 1 == eq->map_total)) + next = eq->maps; + prefetch(next->m); bus_dmamap_unload(eq->tx_tag, txm->map); m_freem(txm->m); txm->m = NULL; - txm = next_txm; + txm = next; + if (__predict_false(++eq->map_cidx == eq->map_total)) + eq->map_cidx = 0; } - eq->map_cidx = next_map_cidx; return (reclaimed); }