Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Mar 2011 03:54:37 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r219292 - head/sys/dev/cxgbe
Message-ID:  <201103050354.p253sbL2002799@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103050354.p253sbL2002799>