Commit 8d5855a5 authored by David S. Miller's avatar David S. Miller

Merge branch 'bnxt_en-tx-improvements'

Michael Chan says:

====================
bnxt_en: TX path improvements

All patches in this patchset are related to improving the TX path.
There are 2 areas of improvements:

1. The TX interrupt logic currently counts the number of TX completions
to determine the number of TX SKBs to free.  We now change it so that
the TX completion will now contain the hardware consumer index
information.  The driver will keep track of the latest hardware
consumer index from the last TX completion and clean up all TX SKBs
up to that index.  This scheme aligns better with future chips and
allows xmit_more code path to be more optimized.

2. The current driver logic requires an additional MSIX for each
additional MQPRIO TX ring.  This scheme uses too many MSIX vectors if
the user enables a large number of MQPRIO TCs.  We now use a new scheme
that will use the same MSIX for all the MQPRIO TX rings for each
ethtool channel.  Each ethtool TX channel can have up to 8 MQPRIO
TX rings and now they all will share the same MSIX.

v2: Rebased

v1 posted on Oct 27 2023 right before the close of net-next:

https://lore.kernel.org/netdev/20231027232252.36111-1-michael.chan@broadcom.com/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b3d8c605 c1056a59
This diff is collapsed.
...@@ -61,6 +61,24 @@ struct tx_bd { ...@@ -61,6 +61,24 @@ struct tx_bd {
__le64 tx_bd_haddr; __le64 tx_bd_haddr;
} __packed; } __packed;
#define TX_OPAQUE_IDX_MASK 0x0000ffff
#define TX_OPAQUE_BDS_MASK 0x00ff0000
#define TX_OPAQUE_BDS_SHIFT 16
#define TX_OPAQUE_RING_MASK 0xff000000
#define TX_OPAQUE_RING_SHIFT 24
#define SET_TX_OPAQUE(bp, txr, idx, bds) \
(((txr)->tx_napi_idx << TX_OPAQUE_RING_SHIFT) | \
((bds) << TX_OPAQUE_BDS_SHIFT) | ((idx) & (bp)->tx_ring_mask))
#define TX_OPAQUE_IDX(opq) ((opq) & TX_OPAQUE_IDX_MASK)
#define TX_OPAQUE_RING(opq) (((opq) & TX_OPAQUE_RING_MASK) >> \
TX_OPAQUE_RING_SHIFT)
#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)
...@@ -530,6 +548,19 @@ struct nqe_cn { ...@@ -530,6 +548,19 @@ struct nqe_cn {
__le32 cq_handle_high; __le32 cq_handle_high;
}; };
#define BNXT_NQ_HDL_IDX_MASK 0x00ffffff
#define BNXT_NQ_HDL_TYPE_MASK 0xff000000
#define BNXT_NQ_HDL_TYPE_SHIFT 24
#define BNXT_NQ_HDL_TYPE_RX 0x00
#define BNXT_NQ_HDL_TYPE_TX 0x01
#define BNXT_NQ_HDL_IDX(hdl) ((hdl) & BNXT_NQ_HDL_IDX_MASK)
#define BNXT_NQ_HDL_TYPE(hdl) (((hdl) & BNXT_NQ_HDL_TYPE_MASK) >> \
BNXT_NQ_HDL_TYPE_SHIFT)
#define BNXT_SET_NQ_HDL(cpr) \
(((cpr)->cp_ring_type << BNXT_NQ_HDL_TYPE_SHIFT) | (cpr)->cp_idx)
#define DB_IDX_MASK 0xffffff #define DB_IDX_MASK 0xffffff
#define DB_IDX_VALID (0x1 << 26) #define DB_IDX_VALID (0x1 << 26)
#define DB_IRQ_DIS (0x1 << 27) #define DB_IRQ_DIS (0x1 << 27)
...@@ -702,6 +733,7 @@ struct nqe_cn { ...@@ -702,6 +733,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 {
...@@ -792,9 +824,12 @@ struct bnxt_db_info { ...@@ -792,9 +824,12 @@ struct bnxt_db_info {
struct bnxt_tx_ring_info { struct bnxt_tx_ring_info {
struct bnxt_napi *bnapi; struct bnxt_napi *bnapi;
struct bnxt_cp_ring_info *tx_cpr;
u16 tx_prod; u16 tx_prod;
u16 tx_cons; u16 tx_cons;
u16 tx_hw_cons;
u16 txq_index; u16 txq_index;
u8 tx_napi_idx;
u8 kick_pending; u8 kick_pending;
struct bnxt_db_info tx_db; struct bnxt_db_info tx_db;
...@@ -901,6 +936,7 @@ struct bnxt_tpa_idx_map { ...@@ -901,6 +936,7 @@ struct bnxt_tpa_idx_map {
struct bnxt_rx_ring_info { struct bnxt_rx_ring_info {
struct bnxt_napi *bnapi; struct bnxt_napi *bnapi;
struct bnxt_cp_ring_info *rx_cpr;
u16 rx_prod; u16 rx_prod;
u16 rx_agg_prod; u16 rx_agg_prod;
u16 rx_sw_agg_prod; u16 rx_sw_agg_prod;
...@@ -980,6 +1016,8 @@ struct bnxt_cp_ring_info { ...@@ -980,6 +1016,8 @@ struct bnxt_cp_ring_info {
u8 had_work_done:1; u8 had_work_done:1;
u8 has_more_work:1; u8 has_more_work:1;
u8 cp_ring_type;
u8 cp_idx;
u32 last_cp_raw_cons; u32 last_cp_raw_cons;
...@@ -1004,11 +1042,18 @@ struct bnxt_cp_ring_info { ...@@ -1004,11 +1042,18 @@ struct bnxt_cp_ring_info {
struct bnxt_ring_struct cp_ring_struct; struct bnxt_ring_struct cp_ring_struct;
struct bnxt_cp_ring_info *cp_ring_arr[2]; int cp_ring_count;
#define BNXT_RX_HDL 0 struct bnxt_cp_ring_info *cp_ring_arr;
#define BNXT_TX_HDL 1
}; };
#define BNXT_MAX_QUEUE 8
#define BNXT_MAX_TXR_PER_NAPI BNXT_MAX_QUEUE
#define bnxt_for_each_napi_tx(iter, bnapi, txr) \
for (iter = 0, txr = (bnapi)->tx_ring[0]; txr; \
txr = (iter < BNXT_MAX_TXR_PER_NAPI - 1) ? \
(bnapi)->tx_ring[++iter] : NULL)
struct bnxt_napi { struct bnxt_napi {
struct napi_struct napi; struct napi_struct napi;
struct bnxt *bp; struct bnxt *bp;
...@@ -1016,11 +1061,10 @@ struct bnxt_napi { ...@@ -1016,11 +1061,10 @@ struct bnxt_napi {
int index; int index;
struct bnxt_cp_ring_info cp_ring; struct bnxt_cp_ring_info cp_ring;
struct bnxt_rx_ring_info *rx_ring; struct bnxt_rx_ring_info *rx_ring;
struct bnxt_tx_ring_info *tx_ring; struct bnxt_tx_ring_info *tx_ring[BNXT_MAX_TXR_PER_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;
...@@ -1355,8 +1399,6 @@ struct bnxt_link_info { ...@@ -1355,8 +1399,6 @@ struct bnxt_link_info {
(PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE74_DISABLE | \ (PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE74_DISABLE | \
BNXT_FEC_RS_OFF(link_info)) BNXT_FEC_RS_OFF(link_info))
#define BNXT_MAX_QUEUE 8
struct bnxt_queue_info { struct bnxt_queue_info {
u8 queue_id; u8 queue_id;
u8 queue_profile; u8 queue_profile;
...@@ -2351,6 +2393,7 @@ int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings); ...@@ -2351,6 +2393,7 @@ int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings);
int bnxt_nq_rings_in_use(struct bnxt *bp); int bnxt_nq_rings_in_use(struct bnxt *bp);
int bnxt_hwrm_set_coal(struct bnxt *); int bnxt_hwrm_set_coal(struct bnxt *);
void bnxt_free_ctx_mem(struct bnxt *bp); void bnxt_free_ctx_mem(struct bnxt *bp);
int bnxt_num_tx_to_cp(struct bnxt *bp, int tx);
unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp); unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp);
unsigned int bnxt_get_avail_stat_ctxs_for_en(struct bnxt *bp); unsigned int bnxt_get_avail_stat_ctxs_for_en(struct bnxt *bp);
unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp); unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp);
...@@ -2360,7 +2403,7 @@ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init); ...@@ -2360,7 +2403,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 *);
......
...@@ -528,7 +528,8 @@ static int bnxt_get_num_ring_stats(struct bnxt *bp) ...@@ -528,7 +528,8 @@ static int bnxt_get_num_ring_stats(struct bnxt *bp)
bnxt_get_num_tpa_ring_stats(bp); bnxt_get_num_tpa_ring_stats(bp);
tx = NUM_RING_TX_HW_STATS; tx = NUM_RING_TX_HW_STATS;
cmn = NUM_RING_CMN_SW_STATS; cmn = NUM_RING_CMN_SW_STATS;
return rx * bp->rx_nr_rings + tx * bp->tx_nr_rings + return rx * bp->rx_nr_rings +
tx * (bp->tx_nr_rings_xdp + bp->tx_nr_rings_per_tc) +
cmn * bp->cp_nr_rings; cmn * bp->cp_nr_rings;
} }
...@@ -923,6 +924,7 @@ static int bnxt_set_channels(struct net_device *dev, ...@@ -923,6 +924,7 @@ static int bnxt_set_channels(struct net_device *dev,
bool sh = false; bool sh = false;
int tx_xdp = 0; int tx_xdp = 0;
int rc = 0; int rc = 0;
int tx_cp;
if (channel->other_count) if (channel->other_count)
return -EINVAL; return -EINVAL;
...@@ -994,8 +996,9 @@ static int bnxt_set_channels(struct net_device *dev, ...@@ -994,8 +996,9 @@ static int bnxt_set_channels(struct net_device *dev,
if (tcs > 1) if (tcs > 1)
bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs + tx_xdp; bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs + tx_xdp;
bp->cp_nr_rings = sh ? max_t(int, bp->tx_nr_rings, bp->rx_nr_rings) : tx_cp = bnxt_num_tx_to_cp(bp, bp->tx_nr_rings);
bp->tx_nr_rings + bp->rx_nr_rings; bp->cp_nr_rings = sh ? max_t(int, tx_cp, bp->rx_nr_rings) :
tx_cp + bp->rx_nr_rings;
/* After changing number of rx channels, update NTUPLE feature. */ /* After changing number of rx channels, update NTUPLE feature. */
netdev_update_features(dev); netdev_update_features(dev);
...@@ -3941,7 +3944,7 @@ static int bnxt_run_loopback(struct bnxt *bp) ...@@ -3941,7 +3944,7 @@ static int bnxt_run_loopback(struct bnxt *bp)
cpr = &rxr->bnapi->cp_ring; cpr = &rxr->bnapi->cp_ring;
if (bp->flags & BNXT_FLAG_CHIP_P5) if (bp->flags & BNXT_FLAG_CHIP_P5)
cpr = cpr->cp_ring_arr[BNXT_RX_HDL]; cpr = rxr->rx_cpr;
pkt_size = min(bp->dev->mtu + ETH_HLEN, bp->rx_copy_thresh); pkt_size = min(bp->dev->mtu + ETH_HLEN, bp->rx_copy_thresh);
skb = netdev_alloc_skb(bp->dev, pkt_size); skb = netdev_alloc_skb(bp->dev, pkt_size);
if (!skb) if (!skb)
......
...@@ -52,7 +52,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp, ...@@ -52,7 +52,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
((num_frags + 1) << TX_BD_FLAGS_BD_CNT_SHIFT) | ((num_frags + 1) << TX_BD_FLAGS_BD_CNT_SHIFT) |
bnxt_lhint_arr[len >> 9]; bnxt_lhint_arr[len >> 9];
txbd->tx_bd_len_flags_type = cpu_to_le32(flags); txbd->tx_bd_len_flags_type = cpu_to_le32(flags);
txbd->tx_bd_opaque = prod; txbd->tx_bd_opaque = SET_TX_OPAQUE(bp, txr, prod, 1 + num_frags);
txbd->tx_bd_haddr = cpu_to_le64(mapping); txbd->tx_bd_haddr = cpu_to_le64(mapping);
/* now let us fill up the frags into the next buffers */ /* now let us fill up the frags into the next buffers */
...@@ -127,19 +127,19 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp, ...@@ -127,19 +127,19 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp,
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) 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[0];
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];
...@@ -249,7 +249,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, ...@@ -249,7 +249,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
pdev = bp->pdev; pdev = bp->pdev;
offset = bp->rx_offset; offset = bp->rx_offset;
txr = rxr->bnapi->tx_ring; txr = rxr->bnapi->tx_ring[0];
/* BNXT_RX_PAGE_MODE(bp) when XDP enabled */ /* BNXT_RX_PAGE_MODE(bp) when XDP enabled */
orig_data = xdp.data; orig_data = xdp.data;
...@@ -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);
...@@ -398,7 +398,7 @@ int bnxt_xdp_xmit(struct net_device *dev, int num_frames, ...@@ -398,7 +398,7 @@ int bnxt_xdp_xmit(struct net_device *dev, int num_frames,
static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog) static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
{ {
struct net_device *dev = bp->dev; struct net_device *dev = bp->dev;
int tx_xdp = 0, rc, tc; int tx_xdp = 0, tx_cp, rc, tc;
struct bpf_prog *old; struct bpf_prog *old;
if (prog && !prog->aux->xdp_has_frags && if (prog && !prog->aux->xdp_has_frags &&
...@@ -446,7 +446,8 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog) ...@@ -446,7 +446,8 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
} }
bp->tx_nr_rings_xdp = tx_xdp; bp->tx_nr_rings_xdp = tx_xdp;
bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc + tx_xdp; bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc + tx_xdp;
bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings); tx_cp = bnxt_num_tx_to_cp(bp, bp->tx_nr_rings);
bp->cp_nr_rings = max_t(int, tx_cp, bp->rx_nr_rings);
bnxt_set_tpa_flags(bp); bnxt_set_tpa_flags(bp);
bnxt_set_ring_params(bp); bnxt_set_ring_params(bp);
......
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