em/igb/ix(4): Port two Tx/Rx fixes made to ixl in r339338

- Fix assert/panic on receive when Jumbo Frames are enabled.

From the commit I made to ixl:
"It turns out that *_isc_rxd_available is supposed to return how many
packets are available to be cleaned on the rx ring. This patch removes
a section of code where if the budget argument is 1, the function would return
one if there was a descriptor available, not necessarily a packet.

This is okay in regular mtu 1500 traffic since the max frame size is less
than the configured receive buffer size (2048), but this doesn't work when
received packets can span more than one  descriptor, as is the case when the
mtu is 9000 and the receive buffer size is 4096."

- Fix possible Tx hang because *_isc_txd_credits_update returns incorrect result

From the commit by Krzysztof Galazka to ixl: "Function isc_txd_update_credits
called with clear set to false should return 1 if there are TX descriptors
already handled by HW. It was always returning 0 causing troubles with UDP TX
traffic."

PR:             231659
Reported by:    lev@
Approved by:	re (gjb@)
Sponsored by:   Intel Corporation
This commit is contained in:
Eric Joyner 2018-10-14 05:09:43 +00:00
parent bfe5c1dcd4
commit adf93b56dc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=339354
3 changed files with 26 additions and 49 deletions

View file

@ -446,8 +446,13 @@ em_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
status = txr->tx_base[cur].upper.fields.status;
updated = !!(status & E1000_TXD_STAT_DD);
if (clear == false || updated == 0)
return (updated);
if (!updated)
return (0);
/* If clear is false just let caller know that there
* are descriptors to reclaim */
if (!clear)
return (1);
prev = txr->tx_cidx_processed;
ntxd = scctx->isc_ntxd[0];
@ -553,22 +558,14 @@ lem_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget)
u32 staterr = 0;
int cnt, i;
if (budget == 1) {
rxd = (struct e1000_rx_desc *)&rxr->rx_base[idx];
staterr = rxd->status;
return (staterr & E1000_RXD_STAT_DD);
}
for (cnt = 0, i = idx; cnt < scctx->isc_nrxd[0] && cnt <= budget;) {
rxd = (struct e1000_rx_desc *)&rxr->rx_base[i];
staterr = rxd->status;
if ((staterr & E1000_RXD_STAT_DD) == 0)
break;
if (++i == scctx->isc_nrxd[0])
i = 0;
if (staterr & E1000_RXD_STAT_EOP)
cnt++;
}
@ -586,26 +583,16 @@ em_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget)
u32 staterr = 0;
int cnt, i;
if (budget == 1) {
rxd = &rxr->rx_base[idx];
staterr = le32toh(rxd->wb.upper.status_error);
return (staterr & E1000_RXD_STAT_DD);
}
for (cnt = 0, i = idx; cnt < scctx->isc_nrxd[0] && cnt <= budget;) {
rxd = &rxr->rx_base[i];
staterr = le32toh(rxd->wb.upper.status_error);
if ((staterr & E1000_RXD_STAT_DD) == 0)
break;
if (++i == scctx->isc_nrxd[0]) {
if (++i == scctx->isc_nrxd[0])
i = 0;
}
if (staterr & E1000_RXD_STAT_EOP)
cnt++;
}
return (cnt);
}

View file

@ -321,8 +321,13 @@ igb_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
status = ((union e1000_adv_tx_desc *)&txr->tx_base[cur])->wb.status;
updated = !!(status & E1000_TXD_STAT_DD);
if (!clear || !updated)
return (updated);
if (!updated)
return (0);
/* If clear is false just let caller know that there
* are descriptors to reclaim */
if (!clear)
return (1);
prev = txr->tx_cidx_processed;
ntxd = scctx->isc_ntxd[0];
@ -392,28 +397,18 @@ igb_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget)
struct rx_ring *rxr = &que->rxr;
union e1000_adv_rx_desc *rxd;
u32 staterr = 0;
int cnt, i, iter;
int cnt, i;
if (budget == 1) {
rxd = (union e1000_adv_rx_desc *)&rxr->rx_base[idx];
staterr = le32toh(rxd->wb.upper.status_error);
return (staterr & E1000_RXD_STAT_DD);
}
for (iter = cnt = 0, i = idx; iter < scctx->isc_nrxd[0] && iter <= budget;) {
for (cnt = 0, i = idx; cnt < scctx->isc_nrxd[0] && cnt <= budget;) {
rxd = (union e1000_adv_rx_desc *)&rxr->rx_base[i];
staterr = le32toh(rxd->wb.upper.status_error);
if ((staterr & E1000_RXD_STAT_DD) == 0)
break;
if (++i == scctx->isc_nrxd[0]) {
if (++i == scctx->isc_nrxd[0])
i = 0;
}
if (staterr & E1000_RXD_STAT_EOP)
cnt++;
iter++;
}
return (cnt);
}

View file

@ -285,8 +285,13 @@ ixgbe_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
status = txr->tx_base[cur].wb.status;
updated = !!(status & IXGBE_TXD_STAT_DD);
if (clear == false || updated == 0)
return (updated);
if (!updated)
return (0);
/* If clear is false just let caller know that there
* are descriptors to reclaim */
if (!clear)
return (1);
prev = txr->tx_cidx_processed;
ntxd = scctx->isc_ntxd[0];
@ -362,17 +367,8 @@ ixgbe_isc_rxd_available(void *arg, uint16_t qsidx, qidx_t pidx, qidx_t budget)
u32 staterr;
int cnt, i, nrxd;
if (budget == 1) {
rxd = &rxr->rx_base[pidx];
staterr = le32toh(rxd->wb.upper.status_error);
return (staterr & IXGBE_RXD_STAT_DD);
}
nrxd = sc->shared->isc_nrxd[0];
// em has cnt < nrxd. off by 1 here or there?
// for (cnt = 0, i = pidx; cnt < nrxd && cnt <= budget;) {
for (cnt = 0, i = pidx; cnt < nrxd-1 && cnt <= budget;) {
for (cnt = 0, i = pidx; cnt < nrxd && cnt <= budget;) {
rxd = &rxr->rx_base[i];
staterr = le32toh(rxd->wb.upper.status_error);
@ -383,7 +379,6 @@ ixgbe_isc_rxd_available(void *arg, uint16_t qsidx, qidx_t pidx, qidx_t budget)
if (staterr & IXGBE_RXD_STAT_EOP)
cnt++;
}
return (cnt);
} /* ixgbe_isc_rxd_available */