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:
parent
d5a7953cd7
commit
04bd99af76
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue