Skip to content

Commit 37b61cd

Browse files
committed
bnxt: don't handle XDP in netpoll
Similarly to other recently fixed drivers make sure we don't try to access XDP or page pool APIs when NAPI budget is 0. NAPI budget of 0 may mean that we are in netpoll. This may result in running software IRQs in hard IRQ context, leading to deadlocks or crashes. To make sure bnapi->tx_pkts don't get wiped without handling the events, move clearing the field into the handler itself. Remember to clear tx_pkts after reset (bnxt_enable_napi()) as it's technically possible that netpoll will accumulate some tx_pkts and then a reset will happen, leaving tx_pkts out of sync with reality. Fixes: 322b87c ("bnxt_en: add page_pool support") Reviewed-by: Andy Gospodarek <[email protected]> Reviewed-by: Michael Chan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 4b31fd4 commit 37b61cd

File tree

4 files changed

+24
-14
lines changed

4 files changed

+24
-14
lines changed

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

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -633,12 +633,13 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
633633
return NETDEV_TX_OK;
634634
}
635635

636-
static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
636+
static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
637637
{
638638
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
639639
struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index);
640640
u16 cons = txr->tx_cons;
641641
struct pci_dev *pdev = bp->pdev;
642+
int nr_pkts = bnapi->tx_pkts;
642643
int i;
643644
unsigned int tx_bytes = 0;
644645

@@ -688,6 +689,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
688689
dev_kfree_skb_any(skb);
689690
}
690691

692+
bnapi->tx_pkts = 0;
691693
WRITE_ONCE(txr->tx_cons, cons);
692694

693695
__netif_txq_completed_wake(txq, nr_pkts, tx_bytes,
@@ -2569,12 +2571,11 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
25692571
return rx_pkts;
25702572
}
25712573

2572-
static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
2574+
static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi,
2575+
int budget)
25732576
{
2574-
if (bnapi->tx_pkts) {
2575-
bnapi->tx_int(bp, bnapi, bnapi->tx_pkts);
2576-
bnapi->tx_pkts = 0;
2577-
}
2577+
if (bnapi->tx_pkts)
2578+
bnapi->tx_int(bp, bnapi, budget);
25782579

25792580
if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) {
25802581
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
@@ -2603,7 +2604,7 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
26032604
*/
26042605
bnxt_db_cq(bp, &cpr->cp_db, cpr->cp_raw_cons);
26052606

2606-
__bnxt_poll_work_done(bp, bnapi);
2607+
__bnxt_poll_work_done(bp, bnapi, budget);
26072608
return rx_pkts;
26082609
}
26092610

@@ -2734,7 +2735,7 @@ static int __bnxt_poll_cqs(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
27342735
}
27352736

27362737
static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
2737-
u64 dbr_type)
2738+
u64 dbr_type, int budget)
27382739
{
27392740
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
27402741
int i;
@@ -2750,7 +2751,7 @@ static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
27502751
cpr2->had_work_done = 0;
27512752
}
27522753
}
2753-
__bnxt_poll_work_done(bp, bnapi);
2754+
__bnxt_poll_work_done(bp, bnapi, budget);
27542755
}
27552756

27562757
static int bnxt_poll_p5(struct napi_struct *napi, int budget)
@@ -2780,7 +2781,8 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
27802781
if (cpr->has_more_work)
27812782
break;
27822783

2783-
__bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL);
2784+
__bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL,
2785+
budget);
27842786
cpr->cp_raw_cons = raw_cons;
27852787
if (napi_complete_done(napi, work_done))
27862788
BNXT_DB_NQ_ARM_P5(&cpr->cp_db,
@@ -2810,7 +2812,7 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
28102812
}
28112813
raw_cons = NEXT_RAW_CMP(raw_cons);
28122814
}
2813-
__bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ);
2815+
__bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ, budget);
28142816
if (raw_cons != cpr->cp_raw_cons) {
28152817
cpr->cp_raw_cons = raw_cons;
28162818
BNXT_DB_NQ_P5(&cpr->cp_db, raw_cons);
@@ -9429,6 +9431,8 @@ static void bnxt_enable_napi(struct bnxt *bp)
94299431
cpr->sw_stats.rx.rx_resets++;
94309432
bnapi->in_reset = false;
94319433

9434+
bnapi->tx_pkts = 0;
9435+
94329436
if (bnapi->rx_ring) {
94339437
INIT_WORK(&cpr->dim.work, bnxt_dim_work);
94349438
cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;

drivers/net/ethernet/broadcom/bnxt/bnxt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,7 @@ struct bnxt_napi {
10051005
struct bnxt_tx_ring_info *tx_ring;
10061006

10071007
void (*tx_int)(struct bnxt *, struct bnxt_napi *,
1008-
int);
1008+
int budget);
10091009
int tx_pkts;
10101010
u8 events;
10111011

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,20 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp,
125125
dma_unmap_len_set(tx_buf, len, 0);
126126
}
127127

128-
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
128+
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
129129
{
130130
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
131131
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
132132
bool rx_doorbell_needed = false;
133+
int nr_pkts = bnapi->tx_pkts;
133134
struct bnxt_sw_tx_bd *tx_buf;
134135
u16 tx_cons = txr->tx_cons;
135136
u16 last_tx_cons = tx_cons;
136137
int i, j, frags;
137138

139+
if (!budget)
140+
return;
141+
138142
for (i = 0; i < nr_pkts; i++) {
139143
tx_buf = &txr->tx_buf_ring[tx_cons];
140144

@@ -161,6 +165,8 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
161165
}
162166
tx_cons = NEXT_TX(tx_cons);
163167
}
168+
169+
bnapi->tx_pkts = 0;
164170
WRITE_ONCE(txr->tx_cons, tx_cons);
165171
if (rx_doorbell_needed) {
166172
tx_buf = &txr->tx_buf_ring[last_tx_cons];

drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
1616
struct bnxt_tx_ring_info *txr,
1717
dma_addr_t mapping, u32 len,
1818
struct xdp_buff *xdp);
19-
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts);
19+
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget);
2020
bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
2121
struct xdp_buff xdp, struct page *page, u8 **data_ptr,
2222
unsigned int *len, u8 *event);

0 commit comments

Comments
 (0)