Skip to content

Commit 8fbf58e

Browse files
Michael Chandavem330
authored andcommitted
bnxt_en: Implement RX ring reset in response to buffer errors.
On some older chips, it is necessary to do a reset when we get buffer errors associated with an RX ring. These buffer errors may become frequent if the RX ring underruns under heavy traffic. The current code does a global reset of all reasources when this happens. This works but creates a big disruption of all rings when one RX ring is having problem. This patch implements a localized RX ring reset of just the RX ring having the issue. All other rings including all TX rings will not be affected by this single RX ring reset. Only the older chips prior to the P5 class supports this reset. Because it is not a global reset, packets may still be arriving while we are calling firmware to reset that ring. We need to be sure that we don't post any buffers during this time while the ring is undergoing reset. After firmware completes successfully, the ring will be in the reset state with no buffers and we can start filling it with new buffers and posting them. Reviewed-by: Pavan Chebbi <[email protected]> Signed-off-by: Edwin Peer <[email protected]> Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7737d32 commit 8fbf58e

File tree

1 file changed

+75
-4
lines changed
  • drivers/net/ethernet/broadcom/bnxt

1 file changed

+75
-4
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt.c

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,10 @@ static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
11721172
{
11731173
if (!rxr->bnapi->in_reset) {
11741174
rxr->bnapi->in_reset = true;
1175-
set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
1175+
if (bp->flags & BNXT_FLAG_CHIP_P5)
1176+
set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
1177+
else
1178+
set_bit(BNXT_RST_RING_SP_EVENT, &bp->sp_event);
11761179
bnxt_queue_sp_work(bp);
11771180
}
11781181
rxr->rx_next_cons = 0xffff;
@@ -1773,8 +1776,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
17731776
if (rx_err & RX_CMPL_ERRORS_BUFFER_ERROR_MASK) {
17741777
bnapi->cp_ring.sw_stats.rx.rx_buf_errors++;
17751778
if (!(bp->flags & BNXT_FLAG_CHIP_P5)) {
1776-
netdev_warn(bp->dev, "RX buffer error %x\n",
1777-
rx_err);
1779+
netdev_warn_once(bp->dev, "RX buffer error %x\n",
1780+
rx_err);
17781781
bnxt_sched_reset(bp, rxr);
17791782
}
17801783
}
@@ -2250,7 +2253,7 @@ static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
22502253
bnapi->tx_pkts = 0;
22512254
}
22522255

2253-
if (bnapi->events & BNXT_RX_EVENT) {
2256+
if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) {
22542257
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
22552258

22562259
if (bnapi->events & BNXT_AGG_EVENT)
@@ -10510,6 +10513,23 @@ static void bnxt_dbg_dump_states(struct bnxt *bp)
1051010513
}
1051110514
}
1051210515

10516+
static int bnxt_hwrm_rx_ring_reset(struct bnxt *bp, int ring_nr)
10517+
{
10518+
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[ring_nr];
10519+
struct hwrm_ring_reset_input req = {0};
10520+
struct bnxt_napi *bnapi = rxr->bnapi;
10521+
struct bnxt_cp_ring_info *cpr;
10522+
u16 cp_ring_id;
10523+
10524+
cpr = &bnapi->cp_ring;
10525+
cp_ring_id = cpr->cp_ring_struct.fw_ring_id;
10526+
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_RESET, cp_ring_id, -1);
10527+
req.ring_type = RING_RESET_REQ_RING_TYPE_RX_RING_GRP;
10528+
req.ring_id = cpu_to_le16(bp->grp_info[bnapi->index].fw_grp_id);
10529+
return hwrm_send_message_silent(bp, &req, sizeof(req),
10530+
HWRM_CMD_TIMEOUT);
10531+
}
10532+
1051310533
static void bnxt_reset_task(struct bnxt *bp, bool silent)
1051410534
{
1051510535
if (!silent)
@@ -10645,6 +10665,54 @@ static void bnxt_reset(struct bnxt *bp, bool silent)
1064510665
bnxt_rtnl_unlock_sp(bp);
1064610666
}
1064710667

10668+
/* Only called from bnxt_sp_task() */
10669+
static void bnxt_rx_ring_reset(struct bnxt *bp)
10670+
{
10671+
int i;
10672+
10673+
bnxt_rtnl_lock_sp(bp);
10674+
if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
10675+
bnxt_rtnl_unlock_sp(bp);
10676+
return;
10677+
}
10678+
/* Disable and flush TPA before resetting the RX ring */
10679+
if (bp->flags & BNXT_FLAG_TPA)
10680+
bnxt_set_tpa(bp, false);
10681+
for (i = 0; i < bp->rx_nr_rings; i++) {
10682+
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
10683+
struct bnxt_cp_ring_info *cpr;
10684+
int rc;
10685+
10686+
if (!rxr->bnapi->in_reset)
10687+
continue;
10688+
10689+
rc = bnxt_hwrm_rx_ring_reset(bp, i);
10690+
if (rc) {
10691+
if (rc == -EINVAL || rc == -EOPNOTSUPP)
10692+
netdev_info_once(bp->dev, "RX ring reset not supported by firmware, falling back to global reset\n");
10693+
else
10694+
netdev_warn(bp->dev, "RX ring reset failed, rc = %d, falling back to global reset\n",
10695+
rc);
10696+
bnxt_reset_task(bp, false);
10697+
break;
10698+
}
10699+
bnxt_free_one_rx_ring_skbs(bp, i);
10700+
rxr->rx_prod = 0;
10701+
rxr->rx_agg_prod = 0;
10702+
rxr->rx_sw_agg_prod = 0;
10703+
rxr->rx_next_cons = 0;
10704+
rxr->bnapi->in_reset = false;
10705+
bnxt_alloc_one_rx_ring(bp, i);
10706+
cpr = &rxr->bnapi->cp_ring;
10707+
if (bp->flags & BNXT_FLAG_AGG_RINGS)
10708+
bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
10709+
bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
10710+
}
10711+
if (bp->flags & BNXT_FLAG_TPA)
10712+
bnxt_set_tpa(bp, true);
10713+
bnxt_rtnl_unlock_sp(bp);
10714+
}
10715+
1064810716
static void bnxt_fw_reset_close(struct bnxt *bp)
1064910717
{
1065010718
bnxt_ulp_stop(bp);
@@ -10933,6 +11001,9 @@ static void bnxt_sp_task(struct work_struct *work)
1093311001
if (test_and_clear_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event))
1093411002
bnxt_reset(bp, true);
1093511003

11004+
if (test_and_clear_bit(BNXT_RST_RING_SP_EVENT, &bp->sp_event))
11005+
bnxt_rx_ring_reset(bp);
11006+
1093611007
if (test_and_clear_bit(BNXT_FW_RESET_NOTIFY_SP_EVENT, &bp->sp_event))
1093711008
bnxt_devlink_health_report(bp, BNXT_FW_RESET_NOTIFY_SP_EVENT);
1093811009

0 commit comments

Comments
 (0)