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
......@@ -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,
int idx)
u16 curr)
{
struct bnxt_napi *bnapi = txr->bnapi;
if (bnapi->tx_fault)
return;
netdev_err(bp->dev, "Invalid Tx completion (ring:%d tx_pkts:%d cons:%u prod:%u i:%d)",
txr->txq_index, bnapi->tx_pkts,
txr->tx_cons, txr->tx_prod, idx);
netdev_err(bp->dev, "Invalid Tx completion (ring:%d tx_hw_cons:%u cons:%u prod:%u curr:%u)",
txr->txq_index, txr->tx_hw_cons,
txr->tx_cons, txr->tx_prod, curr);
WARN_ON_ONCE(1);
bnapi->tx_fault = 1;
bnxt_queue_sp_work(bp, BNXT_RESET_TASK_SP_EVENT);
......@@ -381,6 +381,8 @@ static u16 bnxt_xmit_get_cfa_action(struct sk_buff *skb)
static void bnxt_txr_db_kick(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
u16 prod)
{
/* Sync BD data before updating doorbell */
wmb();
bnxt_db_write(bp, &txr->tx_db, prod);
txr->kick_pending = 0;
}
......@@ -388,7 +390,7 @@ static void bnxt_txr_db_kick(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bnxt *bp = netdev_priv(dev);
struct tx_bd *txbd;
struct tx_bd *txbd, *txbd0;
struct tx_bd_ext *txbd1;
struct netdev_queue *txq;
int i;
......@@ -432,8 +434,6 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
txbd->tx_bd_opaque = prod;
tx_buf = &txr->tx_buf_ring[prod];
tx_buf->skb = skb;
tx_buf->nr_frags = last_frag;
......@@ -519,7 +519,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
txbd->tx_bd_len_flags_type = tx_push->tx_bd_len_flags_type;
txbd->tx_bd_haddr = txr->data_mapping;
txbd->tx_bd_opaque = SET_TX_OPAQUE(bp, txr, prod, 2);
prod = NEXT_TX(prod);
tx_push->tx_bd_opaque = txbd->tx_bd_opaque;
txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)];
memcpy(txbd, tx_push1, sizeof(*txbd));
prod = NEXT_TX(prod);
......@@ -562,6 +564,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
((last_frag + 2) << TX_BD_FLAGS_BD_CNT_SHIFT);
txbd->tx_bd_haddr = cpu_to_le64(mapping);
txbd->tx_bd_opaque = SET_TX_OPAQUE(bp, txr, prod, 2 + last_frag);
prod = NEXT_TX(prod);
txbd1 = (struct tx_bd_ext *)
......@@ -601,6 +604,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
txbd1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags);
txbd1->tx_bd_cfa_action =
cpu_to_le32(cfa_action << TX_BD_CFA_ACTION_SHIFT);
txbd0 = txbd;
for (i = 0; i < last_frag; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
......@@ -632,16 +636,17 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb_tx_timestamp(skb);
/* Sync BD data before updating doorbell */
wmb();
prod = NEXT_TX(prod);
WRITE_ONCE(txr->tx_prod, prod);
if (!netdev_xmit_more() || netif_xmit_stopped(txq))
if (!netdev_xmit_more() || netif_xmit_stopped(txq)) {
bnxt_txr_db_kick(bp, txr, prod);
else
} else {
if (free_size >= bp->tx_wake_thresh)
txbd0->tx_bd_len_flags_type |=
cpu_to_le32(TX_BD_FLAGS_NO_CMPL);
txr->kick_pending = 1;
}
tx_done:
......@@ -686,17 +691,17 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
static void __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
int budget)
{
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index);
u16 cons = txr->tx_cons;
struct pci_dev *pdev = bp->pdev;
int nr_pkts = bnapi->tx_pkts;
int i;
u16 hw_cons = txr->tx_hw_cons;
unsigned int tx_bytes = 0;
u16 cons = txr->tx_cons;
int tx_pkts = 0;
for (i = 0; i < nr_pkts; i++) {
while (cons != hw_cons) {
struct bnxt_sw_tx_bd *tx_buf;
struct sk_buff *skb;
int j, last;
......@@ -707,10 +712,11 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
tx_buf->skb = NULL;
if (unlikely(!skb)) {
bnxt_sched_reset_txr(bp, txr, i);
bnxt_sched_reset_txr(bp, txr, cons);
return;
}
tx_pkts++;
tx_bytes += skb->len;
if (tx_buf->is_push) {
......@@ -747,14 +753,25 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
dev_consume_skb_any(skb);
}
bnapi->tx_pkts = 0;
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,
READ_ONCE(txr->dev_state) == BNXT_DEV_STATE_CLOSING);
}
static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
{
struct bnxt_tx_ring_info *txr;
int i;
bnxt_for_each_napi_tx(i, bnapi, txr) {
if (txr->tx_hw_cons != txr->tx_cons)
__bnxt_tx_int(bp, txr, budget);
}
bnapi->events &= ~BNXT_TX_CMP_EVENT;
}
static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
struct bnxt_rx_ring_info *rxr,
unsigned int *offset,
......@@ -2588,7 +2605,6 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
struct bnxt_napi *bnapi = cpr->bnapi;
u32 raw_cons = cpr->cp_raw_cons;
u32 cons;
int tx_pkts = 0;
int rx_pkts = 0;
u8 event = 0;
struct tx_cmp *txcmp;
......@@ -2609,9 +2625,17 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
*/
dma_rmb();
if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) {
tx_pkts++;
u32 opaque = txcmp->tx_cmp_opaque;
struct bnxt_tx_ring_info *txr;
u16 tx_freed;
txr = bnapi->tx_ring[TX_OPAQUE_RING(opaque)];
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. */
if (unlikely(tx_pkts >= bp->tx_wake_thresh)) {
if (unlikely(tx_freed >= bp->tx_wake_thresh)) {
rx_pkts = budget;
raw_cons = NEXT_RAW_CMP(raw_cons);
if (budget)
......@@ -2655,7 +2679,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
xdp_do_flush();
if (event & BNXT_TX_EVENT) {
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
struct bnxt_tx_ring_info *txr = bnapi->tx_ring[0];
u16 prod = txr->tx_prod;
/* Sync BD data before updating doorbell */
......@@ -2665,7 +2689,6 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
}
cpr->cp_raw_cons = raw_cons;
bnapi->tx_pkts += tx_pkts;
bnapi->events |= event;
return rx_pkts;
}
......@@ -2673,7 +2696,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,
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);
if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) {
......@@ -2686,7 +2709,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);
}
bnapi->events = 0;
bnapi->events &= BNXT_TX_CMP_EVENT;
}
static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
......@@ -2826,14 +2849,11 @@ static int __bnxt_poll_cqs(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
int i, work_done = 0;
for (i = 0; i < 2; i++) {
struct bnxt_cp_ring_info *cpr2 = cpr->cp_ring_arr[i];
for (i = 0; i < cpr->cp_ring_count; i++) {
struct bnxt_cp_ring_info *cpr2 = &cpr->cp_ring_arr[i];
if (cpr2) {
work_done += __bnxt_poll_work(bp, cpr2,
budget - work_done);
cpr->has_more_work |= cpr2->has_more_work;
}
work_done += __bnxt_poll_work(bp, cpr2, budget - work_done);
cpr->has_more_work |= cpr2->has_more_work;
}
return work_done;
}
......@@ -2844,11 +2864,11 @@ static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
int i;
for (i = 0; i < 2; i++) {
struct bnxt_cp_ring_info *cpr2 = cpr->cp_ring_arr[i];
for (i = 0; i < cpr->cp_ring_count; i++) {
struct bnxt_cp_ring_info *cpr2 = &cpr->cp_ring_arr[i];
struct bnxt_db_info *db;
if (cpr2 && cpr2->had_work_done) {
if (cpr2->had_work_done) {
db = &cpr2->cp_db;
bnxt_writeq(bp, db->db_key64 | dbr_type |
RING_CMP(cpr2->cp_raw_cons), db->doorbell);
......@@ -2901,13 +2921,16 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
if (nqcmp->type == cpu_to_le16(NQ_CN_TYPE_CQ_NOTIFICATION)) {
u32 idx = le32_to_cpu(nqcmp->cq_handle_low);
u32 cq_type = BNXT_NQ_HDL_TYPE(idx);
struct bnxt_cp_ring_info *cpr2;
/* No more budget for RX work */
if (budget && work_done >= budget && idx == BNXT_RX_HDL)
if (budget && work_done >= budget &&
cq_type == BNXT_NQ_HDL_TYPE_RX)
break;
cpr2 = cpr->cp_ring_arr[idx];
idx = BNXT_NQ_HDL_IDX(idx);
cpr2 = &cpr->cp_ring_arr[idx];
work_done += __bnxt_poll_work(bp, cpr2,
budget - work_done);
cpr->has_more_work |= cpr2->has_more_work;
......@@ -2922,8 +2945,9 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
BNXT_DB_NQ_P5(&cpr->cp_db, raw_cons);
}
poll_done:
cpr_rx = cpr->cp_ring_arr[BNXT_RX_HDL];
if (cpr_rx && (bp->flags & BNXT_FLAG_DIM)) {
cpr_rx = &cpr->cp_ring_arr[0];
if (cpr_rx->cp_ring_type == BNXT_NQ_HDL_TYPE_RX &&
(bp->flags & BNXT_FLAG_DIM)) {
struct dim_sample dim_sample = {};
dim_update_sample(cpr->event_ctr,
......@@ -3395,6 +3419,15 @@ static void bnxt_free_tx_rings(struct bnxt *bp)
}
}
#define BNXT_TC_TO_RING_BASE(bp, tc) \
((tc) * (bp)->tx_nr_rings_per_tc)
#define BNXT_RING_TO_TC_OFF(bp, tx) \
((tx) % (bp)->tx_nr_rings_per_tc)
#define BNXT_RING_TO_TC(bp, tx) \
((tx) / (bp)->tx_nr_rings_per_tc)
static int bnxt_alloc_tx_rings(struct bnxt *bp)
{
int i, j, rc;
......@@ -3450,7 +3483,7 @@ static int bnxt_alloc_tx_rings(struct bnxt *bp)
spin_lock_init(&txr->xdp_tx_lock);
if (i < bp->tx_nr_rings_xdp)
continue;
if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1))
if (BNXT_RING_TO_TC_OFF(bp, i) == (bp->tx_nr_rings_per_tc - 1))
j++;
}
return 0;
......@@ -3533,36 +3566,33 @@ static void bnxt_free_cp_rings(struct bnxt *bp)
bnxt_free_ring(bp, &ring->ring_mem);
for (j = 0; j < 2; j++) {
struct bnxt_cp_ring_info *cpr2 = cpr->cp_ring_arr[j];
if (!cpr->cp_ring_arr)
continue;
if (cpr2) {
ring = &cpr2->cp_ring_struct;
bnxt_free_ring(bp, &ring->ring_mem);
bnxt_free_cp_arrays(cpr2);
kfree(cpr2);
cpr->cp_ring_arr[j] = NULL;
}
for (j = 0; j < cpr->cp_ring_count; j++) {
struct bnxt_cp_ring_info *cpr2 = &cpr->cp_ring_arr[j];
ring = &cpr2->cp_ring_struct;
bnxt_free_ring(bp, &ring->ring_mem);
bnxt_free_cp_arrays(cpr2);
}
kfree(cpr->cp_ring_arr);
cpr->cp_ring_arr = NULL;
cpr->cp_ring_count = 0;
}
}
static struct bnxt_cp_ring_info *bnxt_alloc_cp_sub_ring(struct bnxt *bp)
static int bnxt_alloc_cp_sub_ring(struct bnxt *bp,
struct bnxt_cp_ring_info *cpr)
{
struct bnxt_ring_mem_info *rmem;
struct bnxt_ring_struct *ring;
struct bnxt_cp_ring_info *cpr;
int rc;
cpr = kzalloc(sizeof(*cpr), GFP_KERNEL);
if (!cpr)
return NULL;
rc = bnxt_alloc_cp_arrays(cpr, bp->cp_nr_pages);
if (rc) {
bnxt_free_cp_arrays(cpr);
kfree(cpr);
return NULL;
return -ENOMEM;
}
ring = &cpr->cp_ring_struct;
rmem = &ring->ring_mem;
......@@ -3575,23 +3605,26 @@ static struct bnxt_cp_ring_info *bnxt_alloc_cp_sub_ring(struct bnxt *bp)
if (rc) {
bnxt_free_ring(bp, rmem);
bnxt_free_cp_arrays(cpr);
kfree(cpr);
cpr = NULL;
}
return cpr;
return rc;
}
static int bnxt_alloc_cp_rings(struct bnxt *bp)
{
bool sh = !!(bp->flags & BNXT_FLAG_SHARED_RINGS);
int i, rc, ulp_base_vec, ulp_msix;
int i, j, rc, ulp_base_vec, ulp_msix;
int tcs = netdev_get_num_tc(bp->dev);
if (!tcs)
tcs = 1;
ulp_msix = bnxt_get_ulp_msix_num(bp);
ulp_base_vec = bnxt_get_ulp_msix_base(bp);
for (i = 0; i < bp->cp_nr_rings; i++) {
for (i = 0, j = 0; i < bp->cp_nr_rings; i++) {
struct bnxt_napi *bnapi = bp->bnapi[i];
struct bnxt_cp_ring_info *cpr;
struct bnxt_cp_ring_info *cpr, *cpr2;
struct bnxt_ring_struct *ring;
int cp_count = 0, k;
int rx = 0, tx = 0;
if (!bnapi)
continue;
......@@ -3613,31 +3646,51 @@ static int bnxt_alloc_cp_rings(struct bnxt *bp)
continue;
if (i < bp->rx_nr_rings) {
struct bnxt_cp_ring_info *cpr2 =
bnxt_alloc_cp_sub_ring(bp);
cpr->cp_ring_arr[BNXT_RX_HDL] = cpr2;
if (!cpr2)
return -ENOMEM;
cpr2->bnapi = bnapi;
cp_count++;
rx = 1;
}
if (i < bp->tx_nr_rings_xdp) {
cp_count++;
tx = 1;
} else if ((sh && i < bp->tx_nr_rings) ||
(!sh && i >= bp->rx_nr_rings)) {
cp_count += tcs;
tx = 1;
}
if ((sh && i < bp->tx_nr_rings) ||
(!sh && i >= bp->rx_nr_rings)) {
struct bnxt_cp_ring_info *cpr2 =
bnxt_alloc_cp_sub_ring(bp);
cpr->cp_ring_arr[BNXT_TX_HDL] = cpr2;
if (!cpr2)
return -ENOMEM;
cpr->cp_ring_arr = kcalloc(cp_count, sizeof(*cpr),
GFP_KERNEL);
if (!cpr->cp_ring_arr)
return -ENOMEM;
cpr->cp_ring_count = cp_count;
for (k = 0; k < cp_count; k++) {
cpr2 = &cpr->cp_ring_arr[k];
rc = bnxt_alloc_cp_sub_ring(bp, cpr2);
if (rc)
return rc;
cpr2->bnapi = bnapi;
cpr2->cp_idx = k;
if (!k && rx) {
bp->rx_ring[i].rx_cpr = cpr2;
cpr2->cp_ring_type = BNXT_NQ_HDL_TYPE_RX;
} else {
int n, tc = k - rx;
n = BNXT_TC_TO_RING_BASE(bp, tc) + j;
bp->tx_ring[n].tx_cpr = cpr2;
cpr2->cp_ring_type = BNXT_NQ_HDL_TYPE_TX;
}
}
if (tx)
j++;
}
return 0;
}
static void bnxt_init_ring_struct(struct bnxt *bp)
{
int i;
int i, j;
for (i = 0; i < bp->cp_nr_rings; i++) {
struct bnxt_napi *bnapi = bp->bnapi[i];
......@@ -3682,18 +3735,16 @@ static void bnxt_init_ring_struct(struct bnxt *bp)
rmem->vmem = (void **)&rxr->rx_agg_ring;
skip_rx:
txr = bnapi->tx_ring;
if (!txr)
continue;
ring = &txr->tx_ring_struct;
rmem = &ring->ring_mem;
rmem->nr_pages = bp->tx_nr_pages;
rmem->page_size = HW_RXBD_RING_SIZE;
rmem->pg_arr = (void **)txr->tx_desc_ring;
rmem->dma_arr = txr->tx_desc_mapping;
rmem->vmem_size = SW_TXBD_RING_SIZE * bp->tx_nr_pages;
rmem->vmem = (void **)&txr->tx_buf_ring;
bnxt_for_each_napi_tx(j, bnapi, txr) {
ring = &txr->tx_ring_struct;
rmem = &ring->ring_mem;
rmem->nr_pages = bp->tx_nr_pages;
rmem->page_size = HW_TXBD_RING_SIZE;
rmem->pg_arr = (void **)txr->tx_desc_ring;
rmem->dma_arr = txr->tx_desc_mapping;
rmem->vmem_size = SW_TXBD_RING_SIZE * bp->tx_nr_pages;
rmem->vmem = (void **)&txr->tx_buf_ring;
}
}
}
......@@ -3814,11 +3865,10 @@ static void bnxt_init_cp_rings(struct bnxt *bp)
ring->fw_ring_id = INVALID_HW_RING_ID;
cpr->rx_ring_coal.coal_ticks = bp->rx_coal.coal_ticks;
cpr->rx_ring_coal.coal_bufs = bp->rx_coal.coal_bufs;
for (j = 0; j < 2; j++) {
struct bnxt_cp_ring_info *cpr2 = cpr->cp_ring_arr[j];
if (!cpr2)
continue;
if (!cpr->cp_ring_arr)
continue;
for (j = 0; j < cpr->cp_ring_count; j++) {
struct bnxt_cp_ring_info *cpr2 = &cpr->cp_ring_arr[j];
ring = &cpr2->cp_ring_struct;
ring->fw_ring_id = INVALID_HW_RING_ID;
......@@ -4493,7 +4543,7 @@ static int bnxt_alloc_stats(struct bnxt *bp)
static void bnxt_clear_ring_indices(struct bnxt *bp)
{
int i;
int i, j;
if (!bp->bnapi)
return;
......@@ -4510,10 +4560,10 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
cpr = &bnapi->cp_ring;
cpr->cp_raw_cons = 0;
txr = bnapi->tx_ring;
if (txr) {
bnxt_for_each_napi_tx(j, bnapi, txr) {
txr->tx_prod = 0;
txr->tx_cons = 0;
txr->tx_hw_cons = 0;
}
rxr = bnapi->rx_ring;
......@@ -4523,6 +4573,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
rxr->rx_sw_agg_prod = 0;
rxr->rx_next_cons = 0;
}
bnapi->events = 0;
}
}
......@@ -4649,6 +4700,8 @@ static int bnxt_alloc_mem(struct bnxt *bp, bool irq_re_init)
BNXT_RMEM_RING_PTE_FLAG;
rxr->rx_agg_ring_struct.ring_mem.flags =
BNXT_RMEM_RING_PTE_FLAG;
} else {
rxr->rx_cpr = &bp->bnapi[i]->cp_ring;
}
rxr->bnapi = bp->bnapi[i];
bp->bnapi[i]->rx_ring = &bp->rx_ring[i];
......@@ -4671,22 +4724,33 @@ static int bnxt_alloc_mem(struct bnxt *bp, bool irq_re_init)
else
j = bp->rx_nr_rings;
for (i = 0; i < bp->tx_nr_rings; i++, j++) {
for (i = 0; i < bp->tx_nr_rings; i++) {
struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
struct bnxt_napi *bnapi2;
if (bp->flags & BNXT_FLAG_CHIP_P5)
txr->tx_ring_struct.ring_mem.flags =
BNXT_RMEM_RING_PTE_FLAG;
txr->bnapi = bp->bnapi[j];
bp->bnapi[j]->tx_ring = txr;
bp->tx_ring_map[i] = bp->tx_nr_rings_xdp + i;
if (i >= bp->tx_nr_rings_xdp) {
int k = j + BNXT_RING_TO_TC_OFF(bp, i);
bnapi2 = bp->bnapi[k];
txr->txq_index = i - bp->tx_nr_rings_xdp;
bp->bnapi[j]->tx_int = bnxt_tx_int;
txr->tx_napi_idx =
BNXT_RING_TO_TC(bp, txr->txq_index);
bnapi2->tx_ring[txr->tx_napi_idx] = txr;
bnapi2->tx_int = bnxt_tx_int;
} else {
bp->bnapi[j]->flags |= BNXT_NAPI_FLAG_XDP;
bp->bnapi[j]->tx_int = bnxt_tx_int_xdp;
bnapi2 = bp->bnapi[j];
bnapi2->flags |= BNXT_NAPI_FLAG_XDP;
bnapi2->tx_ring[0] = txr;
bnapi2->tx_int = bnxt_tx_int_xdp;
j++;
}
txr->bnapi = bnapi2;
if (!(bp->flags & BNXT_FLAG_CHIP_P5))
txr->tx_cpr = &bnapi2->cp_ring;
}
rc = bnxt_alloc_stats(bp);
......@@ -5237,28 +5301,18 @@ static u16 bnxt_cp_ring_from_grp(struct bnxt *bp, struct bnxt_ring_struct *ring)
static u16 bnxt_cp_ring_for_rx(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
{
if (bp->flags & BNXT_FLAG_CHIP_P5) {
struct bnxt_napi *bnapi = rxr->bnapi;
struct bnxt_cp_ring_info *cpr;
cpr = bnapi->cp_ring.cp_ring_arr[BNXT_RX_HDL];
return cpr->cp_ring_struct.fw_ring_id;
} else {
if (bp->flags & BNXT_FLAG_CHIP_P5)
return rxr->rx_cpr->cp_ring_struct.fw_ring_id;
else
return bnxt_cp_ring_from_grp(bp, &rxr->rx_ring_struct);
}
}
static u16 bnxt_cp_ring_for_tx(struct bnxt *bp, struct bnxt_tx_ring_info *txr)
{
if (bp->flags & BNXT_FLAG_CHIP_P5) {
struct bnxt_napi *bnapi = txr->bnapi;
struct bnxt_cp_ring_info *cpr;
cpr = bnapi->cp_ring.cp_ring_arr[BNXT_TX_HDL];
return cpr->cp_ring_struct.fw_ring_id;
} else {
if (bp->flags & BNXT_FLAG_CHIP_P5)
return txr->tx_cpr->cp_ring_struct.fw_ring_id;
else
return bnxt_cp_ring_from_grp(bp, &txr->tx_ring_struct);
}
}
static int bnxt_alloc_rss_indir_tbl(struct bnxt *bp)
......@@ -6017,14 +6071,12 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
u32 map_idx;
if (bp->flags & BNXT_FLAG_CHIP_P5) {
struct bnxt_cp_ring_info *cpr2 = txr->tx_cpr;
struct bnxt_napi *bnapi = txr->bnapi;
struct bnxt_cp_ring_info *cpr, *cpr2;
u32 type2 = HWRM_RING_ALLOC_CMPL;
cpr = &bnapi->cp_ring;
cpr2 = cpr->cp_ring_arr[BNXT_TX_HDL];
ring = &cpr2->cp_ring_struct;
ring->handle = BNXT_TX_HDL;
ring->handle = BNXT_SET_NQ_HDL(cpr2);
map_idx = bnapi->index;
rc = hwrm_ring_alloc_send_msg(bp, ring, type2, map_idx);
if (rc)
......@@ -6057,13 +6109,11 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
bp->grp_info[map_idx].rx_fw_ring_id = ring->fw_ring_id;
if (bp->flags & BNXT_FLAG_CHIP_P5) {
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
struct bnxt_cp_ring_info *cpr2 = rxr->rx_cpr;
u32 type2 = HWRM_RING_ALLOC_CMPL;
struct bnxt_cp_ring_info *cpr2;
cpr2 = cpr->cp_ring_arr[BNXT_RX_HDL];
ring = &cpr2->cp_ring_struct;
ring->handle = BNXT_RX_HDL;
ring->handle = BNXT_SET_NQ_HDL(cpr2);
rc = hwrm_ring_alloc_send_msg(bp, ring, type2, map_idx);
if (rc)
goto err_out;
......@@ -6208,18 +6258,16 @@ static void bnxt_hwrm_ring_free(struct bnxt *bp, bool close_path)
struct bnxt_ring_struct *ring;
int j;
for (j = 0; j < 2; j++) {
struct bnxt_cp_ring_info *cpr2 = cpr->cp_ring_arr[j];
if (cpr2) {
ring = &cpr2->cp_ring_struct;
if (ring->fw_ring_id == INVALID_HW_RING_ID)
continue;
hwrm_ring_free_send_msg(bp, ring,
RING_FREE_REQ_RING_TYPE_L2_CMPL,
INVALID_HW_RING_ID);
ring->fw_ring_id = INVALID_HW_RING_ID;
}
for (j = 0; j < cpr->cp_ring_count && cpr->cp_ring_arr; j++) {
struct bnxt_cp_ring_info *cpr2 = &cpr->cp_ring_arr[j];
ring = &cpr2->cp_ring_struct;
if (ring->fw_ring_id == INVALID_HW_RING_ID)
continue;
hwrm_ring_free_send_msg(bp, ring,
RING_FREE_REQ_RING_TYPE_L2_CMPL,
INVALID_HW_RING_ID);
ring->fw_ring_id = INVALID_HW_RING_ID;
}
ring = &cpr->cp_ring_struct;
if (ring->fw_ring_id != INVALID_HW_RING_ID) {
......@@ -6274,7 +6322,8 @@ static int bnxt_hwrm_get_rings(struct bnxt *bp)
if (bp->flags & BNXT_FLAG_AGG_RINGS)
rx >>= 1;
if (cp < (rx + tx)) {
bnxt_trim_rings(bp, &rx, &tx, cp, false);
rx = cp / 2;
tx = rx;
if (bp->flags & BNXT_FLAG_AGG_RINGS)
rx <<= 1;
hw_resc->resv_rx_rings = rx;
......@@ -6575,6 +6624,7 @@ static int __bnxt_reserve_rings(struct bnxt *bp)
int grp, rx_rings, rc;
int vnic = 1, stat;
bool sh = false;
int tx_cp;
if (!bnxt_need_reserve_rings(bp))
return 0;
......@@ -6624,7 +6674,8 @@ static int __bnxt_reserve_rings(struct bnxt *bp)
rc = bnxt_trim_rings(bp, &rx_rings, &tx, cp, sh);
if (bp->flags & BNXT_FLAG_AGG_RINGS)
rx = rx_rings << 1;
cp = sh ? max_t(int, tx, rx_rings) : tx + rx_rings;
tx_cp = bnxt_num_tx_to_cp(bp, tx);
cp = sh ? max_t(int, tx_cp, rx_rings) : tx_cp + rx_rings;
bp->tx_nr_rings = tx;
/* If we cannot reserve all the RX rings, reset the RSS map only
......@@ -6887,10 +6938,40 @@ int bnxt_hwrm_set_ring_coal(struct bnxt *bp, struct bnxt_napi *bnapi)
return hwrm_req_send(bp, req_rx);
}
static int
bnxt_hwrm_set_rx_coal(struct bnxt *bp, struct bnxt_napi *bnapi,
struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
{
u16 ring_id = bnxt_cp_ring_for_rx(bp, bnapi->rx_ring);
req->ring_id = cpu_to_le16(ring_id);
return hwrm_req_send(bp, req);
}
static int
bnxt_hwrm_set_tx_coal(struct bnxt *bp, struct bnxt_napi *bnapi,
struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
{
struct bnxt_tx_ring_info *txr;
int i, rc;
bnxt_for_each_napi_tx(i, bnapi, txr) {
u16 ring_id;
ring_id = bnxt_cp_ring_for_tx(bp, txr);
req->ring_id = cpu_to_le16(ring_id);
rc = hwrm_req_send(bp, req);
if (rc)
return rc;
if (!(bp->flags & BNXT_FLAG_CHIP_P5))
return 0;
}
return 0;
}
int bnxt_hwrm_set_coal(struct bnxt *bp)
{
struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req_rx, *req_tx,
*req;
struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req_rx, *req_tx;
int i, rc;
rc = hwrm_req_init(bp, req_rx, HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
......@@ -6911,29 +6992,19 @@ int bnxt_hwrm_set_coal(struct bnxt *bp)
for (i = 0; i < bp->cp_nr_rings; i++) {
struct bnxt_napi *bnapi = bp->bnapi[i];
struct bnxt_coal *hw_coal;
u16 ring_id;
req = req_rx;
if (!bnapi->rx_ring) {
ring_id = bnxt_cp_ring_for_tx(bp, bnapi->tx_ring);
req = req_tx;
} else {
ring_id = bnxt_cp_ring_for_rx(bp, bnapi->rx_ring);
}
req->ring_id = cpu_to_le16(ring_id);
rc = hwrm_req_send(bp, req);
if (!bnapi->rx_ring)
rc = bnxt_hwrm_set_tx_coal(bp, bnapi, req_tx);
else
rc = bnxt_hwrm_set_rx_coal(bp, bnapi, req_rx);
if (rc)
break;
if (!(bp->flags & BNXT_FLAG_CHIP_P5))
continue;
if (bnapi->rx_ring && bnapi->tx_ring) {
req = req_tx;
ring_id = bnxt_cp_ring_for_tx(bp, bnapi->tx_ring);
req->ring_id = cpu_to_le16(ring_id);
rc = hwrm_req_send(bp, req);
if (bnapi->rx_ring && bnapi->tx_ring[0]) {
rc = bnxt_hwrm_set_tx_coal(bp, bnapi, req_tx);
if (rc)
break;
}
......@@ -9031,8 +9102,8 @@ static int bnxt_set_real_num_queues(struct bnxt *bp)
return rc;
}
static int bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max,
bool shared)
static int __bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max,
bool shared)
{
int _rx = *rx, _tx = *tx;
......@@ -9055,6 +9126,46 @@ static int bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max,
return 0;
}
static int __bnxt_num_tx_to_cp(struct bnxt *bp, int tx, int tx_sets, int tx_xdp)
{
return (tx - tx_xdp) / tx_sets + tx_xdp;
}
int bnxt_num_tx_to_cp(struct bnxt *bp, int tx)
{
int tcs = netdev_get_num_tc(bp->dev);
if (!tcs)
tcs = 1;
return __bnxt_num_tx_to_cp(bp, tx, tcs, bp->tx_nr_rings_xdp);
}
static int bnxt_num_cp_to_tx(struct bnxt *bp, int tx_cp)
{
int tcs = netdev_get_num_tc(bp->dev);
return (tx_cp - bp->tx_nr_rings_xdp) * tcs +
bp->tx_nr_rings_xdp;
}
static int bnxt_trim_rings(struct bnxt *bp, int *rx, int *tx, int max,
bool sh)
{
int tx_cp = bnxt_num_tx_to_cp(bp, *tx);
if (tx_cp != *tx) {
int tx_saved = tx_cp, rc;
rc = __bnxt_trim_rings(bp, rx, &tx_cp, max, sh);
if (rc)
return rc;
if (tx_cp != tx_saved)
*tx = bnxt_num_cp_to_tx(bp, tx_cp);
return 0;
}
return __bnxt_trim_rings(bp, rx, tx, max, sh);
}
static void bnxt_setup_msix(struct bnxt *bp)
{
const int len = sizeof(bp->irq_tbl[0].name);
......@@ -9067,7 +9178,7 @@ static void bnxt_setup_msix(struct bnxt *bp)
for (i = 0; i < tcs; i++) {
count = bp->tx_nr_rings_per_tc;
off = i * count;
off = BNXT_TC_TO_RING_BASE(bp, i);
netdev_set_tc_queue(dev, i, count, off);
}
}
......@@ -9217,7 +9328,7 @@ static int bnxt_get_num_msix(struct bnxt *bp)
static int bnxt_init_msix(struct bnxt *bp)
{
int i, total_vecs, max, rc = 0, min = 1, ulp_msix;
int i, total_vecs, max, rc = 0, min = 1, ulp_msix, tx_cp;
struct msix_entry *msix_ent;
total_vecs = bnxt_get_num_msix(bp);
......@@ -9259,9 +9370,10 @@ static int bnxt_init_msix(struct bnxt *bp)
if (rc)
goto msix_setup_exit;
tx_cp = bnxt_num_tx_to_cp(bp, bp->tx_nr_rings);
bp->cp_nr_rings = (min == 1) ?
max_t(int, bp->tx_nr_rings, bp->rx_nr_rings) :
bp->tx_nr_rings + bp->rx_nr_rings;
max_t(int, tx_cp, bp->rx_nr_rings) :
tx_cp + bp->rx_nr_rings;
} else {
rc = -ENOMEM;
......@@ -9527,8 +9639,6 @@ static void bnxt_enable_napi(struct bnxt *bp)
cpr = &bnapi->cp_ring;
bnapi->in_reset = false;
bnapi->tx_pkts = 0;
if (bnapi->rx_ring) {
INIT_WORK(&cpr->dim.work, bnxt_dim_work);
cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
......@@ -11559,15 +11669,13 @@ static int bnxt_dbg_hwrm_ring_info_get(struct bnxt *bp, u8 ring_type,
static void bnxt_dump_tx_sw_state(struct bnxt_napi *bnapi)
{
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
int i = bnapi->index;
if (!txr)
return;
struct bnxt_tx_ring_info *txr;
int i = bnapi->index, j;
netdev_info(bnapi->bp->dev, "[%d]: tx{fw_ring: %d prod: %x cons: %x}\n",
i, txr->tx_ring_struct.fw_ring_id, txr->tx_prod,
txr->tx_cons);
bnxt_for_each_napi_tx(j, bnapi, txr)
netdev_info(bnapi->bp->dev, "[%d.%d]: tx{fw_ring: %d prod: %x cons: %x}\n",
i, j, txr->tx_ring_struct.fw_ring_id, txr->tx_prod,
txr->tx_cons);
}
static void bnxt_dump_rx_sw_state(struct bnxt_napi *bnapi)
......@@ -11997,12 +12105,11 @@ static void bnxt_chk_missed_irq(struct bnxt *bp)
continue;
cpr = &bnapi->cp_ring;
for (j = 0; j < 2; j++) {
struct bnxt_cp_ring_info *cpr2 = cpr->cp_ring_arr[j];
for (j = 0; j < cpr->cp_ring_count; j++) {
struct bnxt_cp_ring_info *cpr2 = &cpr->cp_ring_arr[j];
u32 val[2];
if (!cpr2 || cpr2->has_more_work ||
!bnxt_has_work(bp, cpr2))
if (cpr2->has_more_work || !bnxt_has_work(bp, cpr2))
continue;
if (cpr2->cp_raw_cons != cpr2->last_cp_raw_cons) {
......@@ -12161,23 +12268,27 @@ static void bnxt_sp_task(struct work_struct *work)
clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
}
static void _bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx,
int *max_cp);
/* Under rtnl_lock */
int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
int tx_xdp)
{
int max_rx, max_tx, tx_sets = 1;
int max_rx, max_tx, max_cp, tx_sets = 1, tx_cp;
int tx_rings_needed, stats;
int rx_rings = rx;
int cp, vnics, rc;
int cp, vnics;
if (tcs)
tx_sets = tcs;
rc = bnxt_get_max_rings(bp, &max_rx, &max_tx, sh);
if (rc)
return rc;
if (bp->flags & BNXT_FLAG_AGG_RINGS)
rx_rings <<= 1;
_bnxt_get_max_rings(bp, &max_rx, &max_tx, &max_cp);
if (max_rx < rx)
if (max_rx < rx_rings)
return -ENOMEM;
tx_rings_needed = tx * tx_sets + tx_xdp;
......@@ -12186,11 +12297,12 @@ int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
vnics = 1;
if ((bp->flags & (BNXT_FLAG_RFS | BNXT_FLAG_CHIP_P5)) == BNXT_FLAG_RFS)
vnics += rx_rings;
vnics += rx;
if (bp->flags & BNXT_FLAG_AGG_RINGS)
rx_rings <<= 1;
cp = sh ? max_t(int, tx_rings_needed, rx) : tx_rings_needed + rx;
tx_cp = __bnxt_num_tx_to_cp(bp, tx_rings_needed, tx_sets, tx_xdp);
cp = sh ? max_t(int, tx_cp, rx) : tx_cp + rx;
if (max_cp < cp)
return -ENOMEM;
stats = cp;
if (BNXT_NEW_RM(bp)) {
cp += bnxt_get_ulp_msix_num(bp);
......@@ -12824,7 +12936,7 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
{
struct bnxt *bp = netdev_priv(dev);
bool sh = false;
int rc;
int rc, tx_cp;
if (tc > bp->max_tc) {
netdev_err(dev, "Too many traffic classes requested: %d. Max supported is %d.\n",
......@@ -12855,8 +12967,9 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
netdev_reset_tc(dev);
}
bp->tx_nr_rings += bp->tx_nr_rings_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;
if (netif_running(bp->dev))
return bnxt_open_nic(bp, true, false);
......@@ -13335,7 +13448,10 @@ static void _bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx,
if (bp->flags & BNXT_FLAG_AGG_RINGS)
*max_rx >>= 1;
if (bp->flags & BNXT_FLAG_CHIP_P5) {
bnxt_trim_rings(bp, max_rx, max_tx, *max_cp, false);
if (*max_cp < (*max_rx + *max_tx)) {
*max_rx = *max_cp / 2;
*max_tx = *max_rx;
}
/* On P5 chips, max_cp output param should be available NQs */
*max_cp = max_irq;
}
......@@ -13636,7 +13752,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
max_irqs = bnxt_get_max_irq(pdev);
dev = alloc_etherdev_mq(sizeof(*bp), max_irqs);
dev = alloc_etherdev_mqs(sizeof(*bp), max_irqs * BNXT_MAX_QUEUE,
max_irqs);
if (!dev)
return -ENOMEM;
......
......@@ -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 *);
......
......@@ -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)
......
......@@ -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);
......
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