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

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
Loading
Loading
Loading
Loading
+315 −198

File changed.

Preview size limit exceeded, changes collapsed.

+51 −8
Original line number Diff line number Diff line
@@ -61,6 +61,24 @@ struct tx_bd {
	__le64 tx_bd_haddr;
} __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 {
	__le32 tx_bd_hsize_lflags;
	#define TX_BD_FLAGS_TCP_UDP_CHKSUM			(1 << 0)
@@ -530,6 +548,19 @@ struct nqe_cn {
	__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_VALID						(0x1 << 26)
#define DB_IRQ_DIS						(0x1 << 27)
@@ -702,6 +733,7 @@ struct nqe_cn {
#define BNXT_AGG_EVENT		2
#define BNXT_TX_EVENT		4
#define BNXT_REDIRECT_EVENT	8
#define BNXT_TX_CMP_EVENT	0x10

struct bnxt_sw_tx_bd {
	union {
@@ -792,9 +824,12 @@ struct bnxt_db_info {

struct bnxt_tx_ring_info {
	struct bnxt_napi	*bnapi;
	struct bnxt_cp_ring_info	*tx_cpr;
	u16			tx_prod;
	u16			tx_cons;
	u16			tx_hw_cons;
	u16			txq_index;
	u8			tx_napi_idx;
	u8			kick_pending;
	struct bnxt_db_info	tx_db;

@@ -901,6 +936,7 @@ struct bnxt_tpa_idx_map {

struct bnxt_rx_ring_info {
	struct bnxt_napi	*bnapi;
	struct bnxt_cp_ring_info	*rx_cpr;
	u16			rx_prod;
	u16			rx_agg_prod;
	u16			rx_sw_agg_prod;
@@ -980,6 +1016,8 @@ struct bnxt_cp_ring_info {

	u8			had_work_done:1;
	u8			has_more_work:1;
	u8			cp_ring_type;
	u8			cp_idx;

	u32			last_cp_raw_cons;

@@ -1004,11 +1042,18 @@ struct bnxt_cp_ring_info {

	struct bnxt_ring_struct	cp_ring_struct;

	struct bnxt_cp_ring_info *cp_ring_arr[2];
#define BNXT_RX_HDL	0
#define BNXT_TX_HDL	1
	int			cp_ring_count;
	struct bnxt_cp_ring_info *cp_ring_arr;
};

#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 napi_struct	napi;
	struct bnxt		*bp;
@@ -1016,11 +1061,10 @@ struct bnxt_napi {
	int			index;
	struct bnxt_cp_ring_info	cp_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 *,
					  int budget);
	int			tx_pkts;
	u8			events;
	u8			tx_fault:1;

@@ -1355,8 +1399,6 @@ struct bnxt_link_info {
	(PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE74_DISABLE |		\
	 BNXT_FEC_RS_OFF(link_info))

#define BNXT_MAX_QUEUE	8

struct bnxt_queue_info {
	u8	queue_id;
	u8	queue_profile;
@@ -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_hwrm_set_coal(struct bnxt *);
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_avail_stat_ctxs_for_en(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);
void bnxt_tx_disable(struct bnxt *bp);
void bnxt_tx_enable(struct bnxt *bp);
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);
int bnxt_update_link(struct bnxt *bp, bool chng_link_state);
int bnxt_hwrm_set_pause(struct bnxt *);
+7 −4
Original line number Diff line number Diff line
@@ -528,7 +528,8 @@ static int bnxt_get_num_ring_stats(struct bnxt *bp)
	     bnxt_get_num_tpa_ring_stats(bp);
	tx = NUM_RING_TX_HW_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;
}

@@ -923,6 +924,7 @@ static int bnxt_set_channels(struct net_device *dev,
	bool sh = false;
	int tx_xdp = 0;
	int rc = 0;
	int tx_cp;

	if (channel->other_count)
		return -EINVAL;
@@ -994,8 +996,9 @@ static int bnxt_set_channels(struct net_device *dev,
	if (tcs > 1)
		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) :
			       bp->tx_nr_rings + bp->rx_nr_rings;
	tx_cp = bnxt_num_tx_to_cp(bp, bp->tx_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. */
	netdev_update_features(dev);
@@ -3941,7 +3944,7 @@ static int bnxt_run_loopback(struct bnxt *bp)

	cpr = &rxr->bnapi->cp_ring;
	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);
	skb = netdev_alloc_skb(bp->dev, pkt_size);
	if (!skb)
+12 −11
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
		((num_frags + 1) << TX_BD_FLAGS_BD_CNT_SHIFT) |
		bnxt_lhint_arr[len >> 9];
	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);

	/* now let us fill up the frags into the next buffers */
@@ -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)
{
	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;
	u16 tx_hw_cons = txr->tx_hw_cons;
	bool rx_doorbell_needed = false;
	int nr_pkts = bnapi->tx_pkts;
	struct bnxt_sw_tx_bd *tx_buf;
	u16 tx_cons = txr->tx_cons;
	u16 last_tx_cons = tx_cons;
	int i, j, frags;
	int j, frags;

	if (!budget)
		return;

	for (i = 0; i < nr_pkts; i++) {
	while (tx_cons != tx_hw_cons) {
		tx_buf = &txr->tx_buf_ring[tx_cons];

		if (tx_buf->action == XDP_REDIRECT) {
@@ -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);
			}
		} else {
			bnxt_sched_reset_txr(bp, txr, i);
			bnxt_sched_reset_txr(bp, txr, tx_cons);
			return;
		}
		tx_cons = NEXT_TX(tx_cons);
	}

	bnapi->tx_pkts = 0;
	bnapi->events &= ~BNXT_TX_CMP_EVENT;
	WRITE_ONCE(txr->tx_cons, tx_cons);
	if (rx_doorbell_needed) {
		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,
	pdev = bp->pdev;
	offset = bp->rx_offset;

	txr = rxr->bnapi->tx_ring;
	txr = rxr->bnapi->tx_ring[0];
	/* BNXT_RX_PAGE_MODE(bp) when XDP enabled */
	orig_data = xdp.data;

@@ -275,7 +275,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
	case XDP_TX:
		rx_buf = &rxr->rx_buf_ring[cons];
		mapping = rx_buf->mapping - bp->rx_dma_offset;
		*event = 0;
		*event &= BNXT_TX_CMP_EVENT;

		if (unlikely(xdp_buff_has_frags(&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,
static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
{
	struct net_device *dev = bp->dev;
	int tx_xdp = 0, rc, tc;
	int tx_xdp = 0, tx_cp, rc, tc;
	struct bpf_prog *old;

	if (prog && !prog->aux->xdp_has_frags &&
@@ -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 = 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_ring_params(bp);