Commit 7f0a168b authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnxt_en: Add completion ring pointer in TX and RX ring structures

From the TX or RX ring structure, we need to find the corresponding
completion ring during initialization.  On P5 chips, we use the MSIX/napi
entry to locate the completion ring because there is only one RX/TX
ring per MSIX.  To allow multiple TX rings for each MSIX, we need
to add a direct pointer from the TX ring and RX ring structures.
This also simplifies the existing logic.
Reviewed-by: default avatarAndy Gospodarek <andrew.gospodarek@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 34eec1f2
...@@ -331,16 +331,16 @@ static void bnxt_sched_reset_rxr(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) ...@@ -331,16 +331,16 @@ static void bnxt_sched_reset_rxr(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
} }
void bnxt_sched_reset_txr(struct bnxt *bp, struct bnxt_tx_ring_info *txr, void bnxt_sched_reset_txr(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
int idx) u16 curr)
{ {
struct bnxt_napi *bnapi = txr->bnapi; struct bnxt_napi *bnapi = txr->bnapi;
if (bnapi->tx_fault) if (bnapi->tx_fault)
return; return;
netdev_err(bp->dev, "Invalid Tx completion (ring:%d tx_pkts:%d cons:%u prod:%u i:%d)", netdev_err(bp->dev, "Invalid Tx completion (ring:%d tx_hw_cons:%u cons:%u prod:%u curr:%u)",
txr->txq_index, bnapi->tx_pkts, txr->txq_index, txr->tx_hw_cons,
txr->tx_cons, txr->tx_prod, idx); txr->tx_cons, txr->tx_prod, curr);
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
bnapi->tx_fault = 1; bnapi->tx_fault = 1;
bnxt_queue_sp_work(bp, BNXT_RESET_TASK_SP_EVENT); bnxt_queue_sp_work(bp, BNXT_RESET_TASK_SP_EVENT);
...@@ -691,13 +691,13 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) ...@@ -691,13 +691,13 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
{ {
struct bnxt_tx_ring_info *txr = bnapi->tx_ring; struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index); struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index);
u16 hw_cons = txr->tx_hw_cons;
u16 cons = txr->tx_cons; u16 cons = txr->tx_cons;
struct pci_dev *pdev = bp->pdev; struct pci_dev *pdev = bp->pdev;
int nr_pkts = bnapi->tx_pkts;
int i;
unsigned int tx_bytes = 0; unsigned int tx_bytes = 0;
int tx_pkts = 0;
for (i = 0; i < nr_pkts; i++) { while (cons != hw_cons) {
struct bnxt_sw_tx_bd *tx_buf; struct bnxt_sw_tx_bd *tx_buf;
struct sk_buff *skb; struct sk_buff *skb;
int j, last; int j, last;
...@@ -708,10 +708,11 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) ...@@ -708,10 +708,11 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
tx_buf->skb = NULL; tx_buf->skb = NULL;
if (unlikely(!skb)) { if (unlikely(!skb)) {
bnxt_sched_reset_txr(bp, txr, i); bnxt_sched_reset_txr(bp, txr, cons);
return; return;
} }
tx_pkts++;
tx_bytes += skb->len; tx_bytes += skb->len;
if (tx_buf->is_push) { if (tx_buf->is_push) {
...@@ -748,10 +749,10 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) ...@@ -748,10 +749,10 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
dev_consume_skb_any(skb); dev_consume_skb_any(skb);
} }
bnapi->tx_pkts = 0; bnapi->events &= ~BNXT_TX_CMP_EVENT;
WRITE_ONCE(txr->tx_cons, cons); WRITE_ONCE(txr->tx_cons, cons);
__netif_txq_completed_wake(txq, nr_pkts, tx_bytes, __netif_txq_completed_wake(txq, tx_pkts, tx_bytes,
bnxt_tx_avail(bp, txr), bp->tx_wake_thresh, bnxt_tx_avail(bp, txr), bp->tx_wake_thresh,
READ_ONCE(txr->dev_state) == BNXT_DEV_STATE_CLOSING); READ_ONCE(txr->dev_state) == BNXT_DEV_STATE_CLOSING);
} }
...@@ -2588,14 +2589,15 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, ...@@ -2588,14 +2589,15 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
{ {
struct bnxt_napi *bnapi = cpr->bnapi; struct bnxt_napi *bnapi = cpr->bnapi;
u32 raw_cons = cpr->cp_raw_cons; u32 raw_cons = cpr->cp_raw_cons;
struct bnxt_tx_ring_info *txr;
u32 cons; u32 cons;
int tx_pkts = 0;
int rx_pkts = 0; int rx_pkts = 0;
u8 event = 0; u8 event = 0;
struct tx_cmp *txcmp; struct tx_cmp *txcmp;
cpr->has_more_work = 0; cpr->has_more_work = 0;
cpr->had_work_done = 1; cpr->had_work_done = 1;
txr = bnapi->tx_ring;
while (1) { while (1) {
int rc; int rc;
...@@ -2610,9 +2612,15 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, ...@@ -2610,9 +2612,15 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
*/ */
dma_rmb(); dma_rmb();
if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) { if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) {
tx_pkts++; u32 opaque = txcmp->tx_cmp_opaque;
u16 tx_freed;
event |= BNXT_TX_CMP_EVENT;
txr->tx_hw_cons = TX_OPAQUE_PROD(bp, opaque);
tx_freed = (txr->tx_hw_cons - txr->tx_cons) &
bp->tx_ring_mask;
/* return full budget so NAPI will complete. */ /* return full budget so NAPI will complete. */
if (unlikely(tx_pkts >= bp->tx_wake_thresh)) { if (unlikely(tx_freed >= bp->tx_wake_thresh)) {
rx_pkts = budget; rx_pkts = budget;
raw_cons = NEXT_RAW_CMP(raw_cons); raw_cons = NEXT_RAW_CMP(raw_cons);
if (budget) if (budget)
...@@ -2666,7 +2674,6 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, ...@@ -2666,7 +2674,6 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
} }
cpr->cp_raw_cons = raw_cons; cpr->cp_raw_cons = raw_cons;
bnapi->tx_pkts += tx_pkts;
bnapi->events |= event; bnapi->events |= event;
return rx_pkts; return rx_pkts;
} }
...@@ -2674,7 +2681,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, ...@@ -2674,7 +2681,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi, static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi,
int budget) int budget)
{ {
if (bnapi->tx_pkts && !bnapi->tx_fault) if ((bnapi->events & BNXT_TX_CMP_EVENT) && !bnapi->tx_fault)
bnapi->tx_int(bp, bnapi, budget); bnapi->tx_int(bp, bnapi, budget);
if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) { if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) {
...@@ -2687,7 +2694,7 @@ static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi, ...@@ -2687,7 +2694,7 @@ static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi,
bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod); bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
} }
bnapi->events = 0; bnapi->events &= BNXT_TX_CMP_EVENT;
} }
static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
...@@ -4515,6 +4522,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp) ...@@ -4515,6 +4522,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
if (txr) { if (txr) {
txr->tx_prod = 0; txr->tx_prod = 0;
txr->tx_cons = 0; txr->tx_cons = 0;
txr->tx_hw_cons = 0;
} }
rxr = bnapi->rx_ring; rxr = bnapi->rx_ring;
...@@ -4524,6 +4532,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp) ...@@ -4524,6 +4532,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
rxr->rx_sw_agg_prod = 0; rxr->rx_sw_agg_prod = 0;
rxr->rx_next_cons = 0; rxr->rx_next_cons = 0;
} }
bnapi->events = 0;
} }
} }
...@@ -9528,8 +9537,6 @@ static void bnxt_enable_napi(struct bnxt *bp) ...@@ -9528,8 +9537,6 @@ static void bnxt_enable_napi(struct bnxt *bp)
cpr = &bnapi->cp_ring; cpr = &bnapi->cp_ring;
bnapi->in_reset = false; bnapi->in_reset = false;
bnapi->tx_pkts = 0;
if (bnapi->rx_ring) { if (bnapi->rx_ring) {
INIT_WORK(&cpr->dim.work, bnxt_dim_work); INIT_WORK(&cpr->dim.work, bnxt_dim_work);
cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
......
...@@ -68,6 +68,12 @@ struct tx_bd { ...@@ -68,6 +68,12 @@ struct tx_bd {
#define SET_TX_OPAQUE(bp, idx, bds) \ #define SET_TX_OPAQUE(bp, idx, bds) \
(((bds) << TX_OPAQUE_BDS_SHIFT) | ((idx) & (bp)->tx_ring_mask)) (((bds) << TX_OPAQUE_BDS_SHIFT) | ((idx) & (bp)->tx_ring_mask))
#define TX_OPAQUE_IDX(opq) ((opq) & TX_OPAQUE_IDX_MASK)
#define TX_OPAQUE_BDS(opq) (((opq) & TX_OPAQUE_BDS_MASK) >> \
TX_OPAQUE_BDS_SHIFT)
#define TX_OPAQUE_PROD(bp, opq) ((TX_OPAQUE_IDX(opq) + TX_OPAQUE_BDS(opq)) &\
(bp)->tx_ring_mask)
struct tx_bd_ext { struct tx_bd_ext {
__le32 tx_bd_hsize_lflags; __le32 tx_bd_hsize_lflags;
#define TX_BD_FLAGS_TCP_UDP_CHKSUM (1 << 0) #define TX_BD_FLAGS_TCP_UDP_CHKSUM (1 << 0)
...@@ -709,6 +715,7 @@ struct nqe_cn { ...@@ -709,6 +715,7 @@ struct nqe_cn {
#define BNXT_AGG_EVENT 2 #define BNXT_AGG_EVENT 2
#define BNXT_TX_EVENT 4 #define BNXT_TX_EVENT 4
#define BNXT_REDIRECT_EVENT 8 #define BNXT_REDIRECT_EVENT 8
#define BNXT_TX_CMP_EVENT 0x10
struct bnxt_sw_tx_bd { struct bnxt_sw_tx_bd {
union { union {
...@@ -801,6 +808,7 @@ struct bnxt_tx_ring_info { ...@@ -801,6 +808,7 @@ struct bnxt_tx_ring_info {
struct bnxt_napi *bnapi; struct bnxt_napi *bnapi;
u16 tx_prod; u16 tx_prod;
u16 tx_cons; u16 tx_cons;
u16 tx_hw_cons;
u16 txq_index; u16 txq_index;
u8 kick_pending; u8 kick_pending;
struct bnxt_db_info tx_db; struct bnxt_db_info tx_db;
...@@ -1027,7 +1035,6 @@ struct bnxt_napi { ...@@ -1027,7 +1035,6 @@ struct bnxt_napi {
void (*tx_int)(struct bnxt *, struct bnxt_napi *, void (*tx_int)(struct bnxt *, struct bnxt_napi *,
int budget); int budget);
int tx_pkts;
u8 events; u8 events;
u8 tx_fault:1; u8 tx_fault:1;
...@@ -2367,7 +2374,7 @@ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init); ...@@ -2367,7 +2374,7 @@ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init);
void bnxt_tx_disable(struct bnxt *bp); void bnxt_tx_disable(struct bnxt *bp);
void bnxt_tx_enable(struct bnxt *bp); void bnxt_tx_enable(struct bnxt *bp);
void bnxt_sched_reset_txr(struct bnxt *bp, struct bnxt_tx_ring_info *txr, void bnxt_sched_reset_txr(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
int idx); u16 curr);
void bnxt_report_link(struct bnxt *bp); void bnxt_report_link(struct bnxt *bp);
int bnxt_update_link(struct bnxt *bp, bool chng_link_state); int bnxt_update_link(struct bnxt *bp, bool chng_link_state);
int bnxt_hwrm_set_pause(struct bnxt *); int bnxt_hwrm_set_pause(struct bnxt *);
......
...@@ -129,17 +129,17 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) ...@@ -129,17 +129,17 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
{ {
struct bnxt_tx_ring_info *txr = bnapi->tx_ring; struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
u16 tx_hw_cons = txr->tx_hw_cons;
bool rx_doorbell_needed = false; bool rx_doorbell_needed = false;
int nr_pkts = bnapi->tx_pkts;
struct bnxt_sw_tx_bd *tx_buf; struct bnxt_sw_tx_bd *tx_buf;
u16 tx_cons = txr->tx_cons; u16 tx_cons = txr->tx_cons;
u16 last_tx_cons = tx_cons; u16 last_tx_cons = tx_cons;
int i, j, frags; int j, frags;
if (!budget) if (!budget)
return; return;
for (i = 0; i < nr_pkts; i++) { while (tx_cons != tx_hw_cons) {
tx_buf = &txr->tx_buf_ring[tx_cons]; tx_buf = &txr->tx_buf_ring[tx_cons];
if (tx_buf->action == XDP_REDIRECT) { if (tx_buf->action == XDP_REDIRECT) {
...@@ -164,13 +164,13 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) ...@@ -164,13 +164,13 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
page_pool_recycle_direct(rxr->page_pool, tx_buf->page); page_pool_recycle_direct(rxr->page_pool, tx_buf->page);
} }
} else { } else {
bnxt_sched_reset_txr(bp, txr, i); bnxt_sched_reset_txr(bp, txr, tx_cons);
return; return;
} }
tx_cons = NEXT_TX(tx_cons); tx_cons = NEXT_TX(tx_cons);
} }
bnapi->tx_pkts = 0; bnapi->events &= ~BNXT_TX_CMP_EVENT;
WRITE_ONCE(txr->tx_cons, tx_cons); WRITE_ONCE(txr->tx_cons, tx_cons);
if (rx_doorbell_needed) { if (rx_doorbell_needed) {
tx_buf = &txr->tx_buf_ring[last_tx_cons]; tx_buf = &txr->tx_buf_ring[last_tx_cons];
...@@ -275,7 +275,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, ...@@ -275,7 +275,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
case XDP_TX: case XDP_TX:
rx_buf = &rxr->rx_buf_ring[cons]; rx_buf = &rxr->rx_buf_ring[cons];
mapping = rx_buf->mapping - bp->rx_dma_offset; mapping = rx_buf->mapping - bp->rx_dma_offset;
*event = 0; *event &= BNXT_TX_CMP_EVENT;
if (unlikely(xdp_buff_has_frags(&xdp))) { if (unlikely(xdp_buff_has_frags(&xdp))) {
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(&xdp); struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(&xdp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment