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@.
This commit is contained in:
msaitoh 2021-03-02 11:10:53 +00:00
parent d5a7953cd7
commit 04bd99af76
1 changed files with 41 additions and 7 deletions

View File

@ -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 * exhaustion are unnecessary, if an mbuf cannot be obtained
* it just returns, keeping its placeholder, thus it can simply * it just returns, keeping its placeholder, thus it can simply
* be recalled to try again. * 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 static void
ixgbe_refresh_mbufs(struct rx_ring *rxr, int limit) 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; struct ixgbe_rx_buf *rbuf, *nbuf;
int i, nextp, processed = 0; int i, nextp, processed = 0;
u32 staterr = 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 #ifdef RSS
u16 pkt_info; u16 pkt_info;
#endif #endif
@ -1816,7 +1823,14 @@ ixgbe_rxeof(struct ix_queue *que)
} }
#endif /* DEV_NETMAP */ #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 *sendmp, *mp;
struct mbuf *newmp; struct mbuf *newmp;
u32 rsc, ptype; u32 rsc, ptype;
@ -1837,7 +1851,7 @@ ixgbe_rxeof(struct ix_queue *que)
if ((staterr & IXGBE_RXD_STAT_DD) == 0) if ((staterr & IXGBE_RXD_STAT_DD) == 0)
break; break;
count--; count++;
sendmp = NULL; sendmp = NULL;
nbuf = NULL; nbuf = NULL;
rsc = 0; rsc = 0;
@ -1858,17 +1872,37 @@ ixgbe_rxeof(struct ix_queue *que)
#endif #endif
rxr->rx_discarded.ev_count++; rxr->rx_discarded.ev_count++;
ixgbe_rx_discard(rxr, i); ixgbe_rx_discard(rxr, i);
discard_multidesc = false;
goto next_desc; goto next_desc;
} }
/* pre-alloc new mbuf */ /* pre-alloc new mbuf */
newmp = ixgbe_getjcl(&rxr->jcl_head, M_NOWAIT, MT_DATA, M_PKTHDR, if (!discard_multidesc)
rxr->mbuf_sz); newmp = ixgbe_getjcl(&rxr->jcl_head, M_NOWAIT, MT_DATA,
M_PKTHDR, rxr->mbuf_sz);
else
newmp = NULL;
if (newmp == NULL) { if (newmp == NULL) {
rxr->rx_discarded.ev_count++; 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; goto next_desc;
} }
discard_multidesc = false;
bus_dmamap_sync(rxr->ptag->dt_dmat, rbuf->pmap, 0, bus_dmamap_sync(rxr->ptag->dt_dmat, rbuf->pmap, 0,
rbuf->buf->m_pkthdr.len, BUS_DMASYNC_POSTREAD); rbuf->buf->m_pkthdr.len, BUS_DMASYNC_POSTREAD);