]> www.infradead.org Git - users/hch/misc.git/commitdiff
bng_en: Initialise core resources
authorBhargava Marreddy <bhargava.marreddy@broadcom.com>
Fri, 19 Sep 2025 17:47:36 +0000 (23:17 +0530)
committerJakub Kicinski <kuba@kernel.org>
Tue, 23 Sep 2025 00:51:27 +0000 (17:51 -0700)
Add initial settings to all core resources, such as
the RX, AGG, TX, CQ, and NQ rings, as well as the VNIC.
This will help enable these resources in future patches.

Signed-off-by: Bhargava Marreddy <bhargava.marreddy@broadcom.com>
Reviewed-by: Vikas Gupta <vikas.gupta@broadcom.com>
Reviewed-by: Rajashekar Hudumula <rajashekar.hudumula@broadcom.com>
Link: https://patch.msgid.link/20250919174742.24969-6-bhargava.marreddy@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
drivers/net/ethernet/broadcom/bnge/bnge_netdev.h
drivers/net/ethernet/broadcom/bnge/bnge_rmem.h

index df05e6ea27110b0eed0b3805a97139f884af45c5..c3418b3fe053e6ba1f4506ce628a90e1e071268a 100644 (file)
@@ -547,6 +547,33 @@ static void bnge_free_vnics(struct bnge_net *bn)
        bn->nr_vnics = 0;
 }
 
+static void bnge_free_ring_grps(struct bnge_net *bn)
+{
+       kfree(bn->grp_info);
+       bn->grp_info = NULL;
+}
+
+static int bnge_init_ring_grps(struct bnge_net *bn)
+{
+       struct bnge_dev *bd = bn->bd;
+       int i;
+
+       bn->grp_info = kcalloc(bd->nq_nr_rings,
+                              sizeof(struct bnge_ring_grp_info),
+                              GFP_KERNEL);
+       if (!bn->grp_info)
+               return -ENOMEM;
+       for (i = 0; i < bd->nq_nr_rings; i++) {
+               bn->grp_info[i].fw_stats_ctx = INVALID_HW_RING_ID;
+               bn->grp_info[i].fw_grp_id = INVALID_HW_RING_ID;
+               bn->grp_info[i].rx_fw_ring_id = INVALID_HW_RING_ID;
+               bn->grp_info[i].agg_fw_ring_id = INVALID_HW_RING_ID;
+               bn->grp_info[i].nq_fw_ring_id = INVALID_HW_RING_ID;
+       }
+
+       return 0;
+}
+
 static void bnge_free_core(struct bnge_net *bn)
 {
        bnge_free_vnic_attributes(bn);
@@ -554,6 +581,7 @@ static void bnge_free_core(struct bnge_net *bn)
        bnge_free_rx_rings(bn);
        bnge_free_nq_tree(bn);
        bnge_free_nq_arrays(bn);
+       bnge_free_ring_grps(bn);
        bnge_free_vnics(bn);
        kfree(bn->tx_ring_map);
        bn->tx_ring_map = NULL;
@@ -692,6 +720,167 @@ static irqreturn_t bnge_msix(int irq, void *dev_instance)
        return IRQ_HANDLED;
 }
 
+static void bnge_init_nq_tree(struct bnge_net *bn)
+{
+       struct bnge_dev *bd = bn->bd;
+       int i, j;
+
+       for (i = 0; i < bd->nq_nr_rings; i++) {
+               struct bnge_nq_ring_info *nqr = &bn->bnapi[i]->nq_ring;
+               struct bnge_ring_struct *ring = &nqr->ring_struct;
+
+               ring->fw_ring_id = INVALID_HW_RING_ID;
+               for (j = 0; j < nqr->cp_ring_count; j++) {
+                       struct bnge_cp_ring_info *cpr = &nqr->cp_ring_arr[j];
+
+                       ring = &cpr->ring_struct;
+                       ring->fw_ring_id = INVALID_HW_RING_ID;
+               }
+       }
+}
+
+static void bnge_init_rxbd_pages(struct bnge_ring_struct *ring, u32 type)
+{
+       struct rx_bd **rx_desc_ring;
+       u32 prod;
+       int i;
+
+       rx_desc_ring = (struct rx_bd **)ring->ring_mem.pg_arr;
+       for (i = 0, prod = 0; i < ring->ring_mem.nr_pages; i++) {
+               struct rx_bd *rxbd = rx_desc_ring[i];
+               int j;
+
+               for (j = 0; j < RX_DESC_CNT; j++, rxbd++, prod++) {
+                       rxbd->rx_bd_len_flags_type = cpu_to_le32(type);
+                       rxbd->rx_bd_opaque = prod;
+               }
+       }
+}
+
+static void bnge_init_one_rx_ring_rxbd(struct bnge_net *bn,
+                                      struct bnge_rx_ring_info *rxr)
+{
+       struct bnge_ring_struct *ring;
+       u32 type;
+
+       type = (bn->rx_buf_use_size << RX_BD_LEN_SHIFT) |
+               RX_BD_TYPE_RX_PACKET_BD | RX_BD_FLAGS_EOP;
+
+       if (NET_IP_ALIGN == 2)
+               type |= RX_BD_FLAGS_SOP;
+
+       ring = &rxr->rx_ring_struct;
+       bnge_init_rxbd_pages(ring, type);
+       ring->fw_ring_id = INVALID_HW_RING_ID;
+}
+
+static void bnge_init_one_agg_ring_rxbd(struct bnge_net *bn,
+                                       struct bnge_rx_ring_info *rxr)
+{
+       struct bnge_ring_struct *ring;
+       u32 type;
+
+       ring = &rxr->rx_agg_ring_struct;
+       ring->fw_ring_id = INVALID_HW_RING_ID;
+       if (bnge_is_agg_reqd(bn->bd)) {
+               type = ((u32)BNGE_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) |
+                       RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP;
+
+               bnge_init_rxbd_pages(ring, type);
+       }
+}
+
+static void bnge_init_one_rx_ring_pair(struct bnge_net *bn, int ring_nr)
+{
+       struct bnge_rx_ring_info *rxr;
+
+       rxr = &bn->rx_ring[ring_nr];
+       bnge_init_one_rx_ring_rxbd(bn, rxr);
+
+       netif_queue_set_napi(bn->netdev, ring_nr, NETDEV_QUEUE_TYPE_RX,
+                            &rxr->bnapi->napi);
+
+       bnge_init_one_agg_ring_rxbd(bn, rxr);
+}
+
+static void bnge_init_rx_rings(struct bnge_net *bn)
+{
+       int i;
+
+#define BNGE_RX_OFFSET (NET_SKB_PAD + NET_IP_ALIGN)
+#define BNGE_RX_DMA_OFFSET NET_SKB_PAD
+       bn->rx_offset = BNGE_RX_OFFSET;
+       bn->rx_dma_offset = BNGE_RX_DMA_OFFSET;
+
+       for (i = 0; i < bn->bd->rx_nr_rings; i++)
+               bnge_init_one_rx_ring_pair(bn, i);
+}
+
+static void bnge_init_tx_rings(struct bnge_net *bn)
+{
+       int i;
+
+       bn->tx_wake_thresh = max(bn->tx_ring_size / 2, BNGE_MIN_TX_DESC_CNT);
+
+       for (i = 0; i < bn->bd->tx_nr_rings; i++) {
+               struct bnge_tx_ring_info *txr = &bn->tx_ring[i];
+               struct bnge_ring_struct *ring = &txr->tx_ring_struct;
+
+               ring->fw_ring_id = INVALID_HW_RING_ID;
+
+               netif_queue_set_napi(bn->netdev, i, NETDEV_QUEUE_TYPE_TX,
+                                    &txr->bnapi->napi);
+       }
+}
+
+static void bnge_init_vnics(struct bnge_net *bn)
+{
+       struct bnge_vnic_info *vnic0 = &bn->vnic_info[BNGE_VNIC_DEFAULT];
+       int i;
+
+       for (i = 0; i < bn->nr_vnics; i++) {
+               struct bnge_vnic_info *vnic = &bn->vnic_info[i];
+               int j;
+
+               vnic->fw_vnic_id = INVALID_HW_RING_ID;
+               vnic->vnic_id = i;
+               for (j = 0; j < BNGE_MAX_CTX_PER_VNIC; j++)
+                       vnic->fw_rss_cos_lb_ctx[j] = INVALID_HW_RING_ID;
+
+               if (bn->vnic_info[i].rss_hash_key) {
+                       if (i == BNGE_VNIC_DEFAULT) {
+                               u8 *key = (void *)vnic->rss_hash_key;
+                               int k;
+
+                               if (!bn->rss_hash_key_valid &&
+                                   !bn->rss_hash_key_updated) {
+                                       get_random_bytes(bn->rss_hash_key,
+                                                        HW_HASH_KEY_SIZE);
+                                       bn->rss_hash_key_updated = true;
+                               }
+
+                               memcpy(vnic->rss_hash_key, bn->rss_hash_key,
+                                      HW_HASH_KEY_SIZE);
+
+                               if (!bn->rss_hash_key_updated)
+                                       continue;
+
+                               bn->rss_hash_key_updated = false;
+                               bn->rss_hash_key_valid = true;
+
+                               bn->toeplitz_prefix = 0;
+                               for (k = 0; k < 8; k++) {
+                                       bn->toeplitz_prefix <<= 8;
+                                       bn->toeplitz_prefix |= key[k];
+                               }
+                       } else {
+                               memcpy(vnic->rss_hash_key, vnic0->rss_hash_key,
+                                      HW_HASH_KEY_SIZE);
+                       }
+               }
+       }
+}
+
 static void bnge_setup_msix(struct bnge_net *bn)
 {
        struct net_device *dev = bn->netdev;
@@ -836,6 +1025,20 @@ static void bnge_del_napi(struct bnge_net *bn)
        synchronize_net();
 }
 
+static int bnge_init_nic(struct bnge_net *bn)
+{
+       int rc;
+
+       bnge_init_nq_tree(bn);
+       bnge_init_rx_rings(bn);
+       bnge_init_tx_rings(bn);
+       rc = bnge_init_ring_grps(bn);
+       if (rc)
+               return rc;
+       bnge_init_vnics(bn);
+       return rc;
+}
+
 static int bnge_open_core(struct bnge_net *bn)
 {
        struct bnge_dev *bd = bn->bd;
@@ -862,9 +1065,16 @@ static int bnge_open_core(struct bnge_net *bn)
                goto err_del_napi;
        }
 
+       rc = bnge_init_nic(bn);
+       if (rc) {
+               netdev_err(bn->netdev, "bnge_init_nic err: %d\n", rc);
+               goto err_free_irq;
+       }
        set_bit(BNGE_STATE_OPEN, &bd->state);
        return 0;
 
+err_free_irq:
+       bnge_free_irq(bn);
 err_del_napi:
        bnge_del_napi(bn);
        bnge_free_core(bn);
index 115297dd82c1d4b881ef9985f25e68bd4eb0a75f..10bd29a833ea094da9c27019485f2771a4a53230 100644 (file)
@@ -118,6 +118,20 @@ struct bnge_sw_rx_agg_bd {
        dma_addr_t              mapping;
 };
 
+#define HWRM_RING_ALLOC_TX     0x1
+#define HWRM_RING_ALLOC_RX     0x2
+#define HWRM_RING_ALLOC_AGG    0x4
+#define HWRM_RING_ALLOC_CMPL   0x8
+#define HWRM_RING_ALLOC_NQ     0x10
+
+struct bnge_ring_grp_info {
+       u16     fw_stats_ctx;
+       u16     fw_grp_id;
+       u16     rx_fw_ring_id;
+       u16     agg_fw_ring_id;
+       u16     nq_fw_ring_id;
+};
+
 #define BNGE_RX_COPY_THRESH     256
 
 #define BNGE_HW_FEATURE_VLAN_ALL_RX    \
@@ -133,6 +147,28 @@ enum {
 
 #define BNGE_NET_EN_TPA                (BNGE_NET_EN_GRO | BNGE_NET_EN_LRO)
 
+/* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one extra
+ * BD because the first TX BD is always a long BD.
+ */
+#define BNGE_MIN_TX_DESC_CNT   (MAX_SKB_FRAGS + 2)
+
+#define RX_RING(bn, x) (((x) & (bn)->rx_ring_mask) >> (BNGE_PAGE_SHIFT - 4))
+#define RX_AGG_RING(bn, x)     (((x) & (bn)->rx_agg_ring_mask) >>      \
+                                (BNGE_PAGE_SHIFT - 4))
+#define RX_IDX(x)      ((x) & (RX_DESC_CNT - 1))
+
+#define TX_RING(bn, x) (((x) & (bn)->tx_ring_mask) >> (BNGE_PAGE_SHIFT - 4))
+#define TX_IDX(x)      ((x) & (TX_DESC_CNT - 1))
+
+#define CP_RING(x)     (((x) & ~(CP_DESC_CNT - 1)) >> (BNGE_PAGE_SHIFT - 4))
+#define CP_IDX(x)      ((x) & (CP_DESC_CNT - 1))
+
+#define RING_RX(bn, idx)       ((idx) & (bn)->rx_ring_mask)
+#define NEXT_RX(idx)           ((idx) + 1)
+
+#define RING_RX_AGG(bn, idx)   ((idx) & (bn)->rx_agg_ring_mask)
+#define NEXT_RX_AGG(idx)       ((idx) + 1)
+
 #define BNGE_NQ_HDL_TYPE_RX    0x00
 #define BNGE_NQ_HDL_TYPE_TX    0x01
 
@@ -176,9 +212,19 @@ struct bnge_net {
        u16                             *tx_ring_map;
        enum dma_data_direction         rx_dir;
 
+       /* grp_info indexed by napi/nq index */
+       struct bnge_ring_grp_info       *grp_info;
        struct bnge_vnic_info           *vnic_info;
        int                             nr_vnics;
        int                             total_irqs;
+
+       u32                     tx_wake_thresh;
+       u16                     rx_offset;
+       u16                     rx_dma_offset;
+
+       u8                      rss_hash_key[HW_HASH_KEY_SIZE];
+       u8                      rss_hash_key_valid:1;
+       u8                      rss_hash_key_updated:1;
 };
 
 #define BNGE_DEFAULT_RX_RING_SIZE      511
@@ -307,6 +353,9 @@ struct bnge_napi {
 #define BNGE_MAX_UC_ADDRS      4
 
 struct bnge_vnic_info {
+       u16             fw_vnic_id;
+#define BNGE_MAX_CTX_PER_VNIC  8
+       u16             fw_rss_cos_lb_ctx[BNGE_MAX_CTX_PER_VNIC];
        u8              *uc_list;
        dma_addr_t      rss_table_dma_addr;
        __le16          *rss_table;
@@ -329,5 +378,6 @@ struct bnge_vnic_info {
 #define BNGE_VNIC_RSS_FLAG     1
 #define BNGE_VNIC_MCAST_FLAG   4
 #define BNGE_VNIC_UCAST_FLAG   8
+       u32             vnic_id;
 };
 #endif /* _BNGE_NETDEV_H_ */
index 162a66c79830e01e5670a0fd4f7ebf7a47234d65..0e7684e20714d461b7aa130d16cd2927a5b28762 100644 (file)
@@ -184,6 +184,7 @@ struct bnge_ctx_mem_info {
 struct bnge_ring_struct {
        struct bnge_ring_mem_info       ring_mem;
 
+       u16                     fw_ring_id;
        union {
                u16             grp_idx;
                u16             map_idx; /* Used by NQs */