Module Name:    src
Committed By:   msaitoh
Date:           Tue Mar  2 11:10:53 UTC 2021

Modified Files:
        src/sys/dev/pci/ixgbe: ix_txrx.c

Log Message:
Fix jcl's starvation case in ixgbe_rxeof() again.

 ix_txrx.c rev.1.64 preallocates jcl to prevent starvation but it's not
perfect. Don't use ixgbe_rx_discard() and just update the old descriptor
for reuse. It's also required for multiple descriptors case to refresh
subsequent descriptor(s). Reviewed by knakahara@.


To generate a diff of this commit:
cvs rdiff -u -r1.64 -r1.65 src/sys/dev/pci/ixgbe/ix_txrx.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/ixgbe/ix_txrx.c
diff -u src/sys/dev/pci/ixgbe/ix_txrx.c:1.64 src/sys/dev/pci/ixgbe/ix_txrx.c:1.65
--- src/sys/dev/pci/ixgbe/ix_txrx.c:1.64	Mon Jan 18 09:09:04 2021
+++ src/sys/dev/pci/ixgbe/ix_txrx.c	Tue Mar  2 11:10:53 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: ix_txrx.c,v 1.64 2021/01/18 09:09:04 knakahara Exp $ */
+/* $NetBSD: ix_txrx.c,v 1.65 2021/03/02 11:10:53 msaitoh Exp $ */
 
 /******************************************************************************
 
@@ -1319,6 +1319,11 @@ ixgbe_setup_hw_rsc(struct rx_ring *rxr)
  *      exhaustion are unnecessary, if an mbuf cannot be obtained
  *      it just returns, keeping its placeholder, thus it can simply
  *      be recalled to try again.
+ *
+ *   XXX NetBSD TODO:
+ *    - The ixgbe_rxeof() function always preallocates mbuf cluster (jcl),
+ *      so the ixgbe_refresh_mbufs() function can be simplified.
+ *
  ************************************************************************/
 static void
 ixgbe_refresh_mbufs(struct rx_ring *rxr, int limit)
@@ -1799,7 +1804,9 @@ ixgbe_rxeof(struct ix_queue *que)
 	struct ixgbe_rx_buf	*rbuf, *nbuf;
 	int			i, nextp, processed = 0;
 	u32			staterr = 0;
-	u32			count = adapter->rx_process_limit;
+	u32			count = 0;
+	u32			limit = adapter->rx_process_limit;
+	bool			discard_multidesc = false;
 #ifdef RSS
 	u16			pkt_info;
 #endif
@@ -1816,7 +1823,14 @@ ixgbe_rxeof(struct ix_queue *que)
 	}
 #endif /* DEV_NETMAP */
 
-	for (i = rxr->next_to_check; count != 0;) {
+	/*
+	 * The max number of loop is rx_process_limit. If discard_multidesc is
+	 * true, continue processing to not to send broken packet to the upper
+	 * layer.
+	 */
+	for (i = rxr->next_to_check;
+	     (count < limit) || (discard_multidesc == true);) {
+
 		struct mbuf *sendmp, *mp;
 		struct mbuf *newmp;
 		u32         rsc, ptype;
@@ -1837,7 +1851,7 @@ ixgbe_rxeof(struct ix_queue *que)
 		if ((staterr & IXGBE_RXD_STAT_DD) == 0)
 			break;
 
-		count--;
+		count++;
 		sendmp = NULL;
 		nbuf = NULL;
 		rsc = 0;
@@ -1858,17 +1872,37 @@ ixgbe_rxeof(struct ix_queue *que)
 #endif
 			rxr->rx_discarded.ev_count++;
 			ixgbe_rx_discard(rxr, i);
+			discard_multidesc = false;
 			goto next_desc;
 		}
 
 		/* pre-alloc new mbuf */
-		newmp = ixgbe_getjcl(&rxr->jcl_head, M_NOWAIT, MT_DATA, M_PKTHDR,
-		    rxr->mbuf_sz);
+		if (!discard_multidesc)
+			newmp = ixgbe_getjcl(&rxr->jcl_head, M_NOWAIT, MT_DATA,
+			    M_PKTHDR, rxr->mbuf_sz);
+		else
+			newmp = NULL;
 		if (newmp == NULL) {
 			rxr->rx_discarded.ev_count++;
-			ixgbe_rx_discard(rxr, i);
+			/*
+			 * Descriptor initialization is already done by the
+			 * above code (cur->wb.upper.status_error = 0).
+			 * So, we can reuse current rbuf->buf for new packet.
+			 *
+			 * Rewrite the buffer addr, see comment in
+			 * ixgbe_rx_discard().
+			 */
+			cur->read.pkt_addr = rbuf->addr;
+			m_freem(rbuf->fmp);
+			rbuf->fmp = NULL;
+			if (!eop) {
+				/* Discard the entire packet. */
+				discard_multidesc = true;
+			} else
+				discard_multidesc = false;
 			goto next_desc;
 		}
+		discard_multidesc = false;
 
 		bus_dmamap_sync(rxr->ptag->dt_dmat, rbuf->pmap, 0,
 		    rbuf->buf->m_pkthdr.len, BUS_DMASYNC_POSTREAD);

Reply via email to