]> www.infradead.org Git - users/hch/misc.git/commitdiff
bng_en: Allocate stat contexts
authorBhargava Marreddy <bhargava.marreddy@broadcom.com>
Fri, 19 Sep 2025 17:47:38 +0000 (23:17 +0530)
committerJakub Kicinski <kuba@kernel.org>
Tue, 23 Sep 2025 00:51:28 +0000 (17:51 -0700)
Allocate the hardware statistics context with the firmware and
register DMA memory required for ring statistics. This helps the
driver to collect ring statistics provided by the firmware.

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-8-bhargava.marreddy@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
drivers/net/ethernet/broadcom/bnge/bnge_netdev.h

index 5c178fade065ddb70107a6b1a81a08c4bca7e11a..8f20b880c113956e9fe5d20f46013a43fe51a6c8 100644 (file)
@@ -701,3 +701,59 @@ qportcfg_exit:
        bnge_hwrm_req_drop(bd, req);
        return rc;
 }
+
+void bnge_hwrm_stat_ctx_free(struct bnge_net *bn)
+{
+       struct hwrm_stat_ctx_free_input *req;
+       struct bnge_dev *bd = bn->bd;
+       int i;
+
+       if (bnge_hwrm_req_init(bd, req, HWRM_STAT_CTX_FREE))
+               return;
+
+       bnge_hwrm_req_hold(bd, req);
+       for (i = 0; i < bd->nq_nr_rings; i++) {
+               struct bnge_napi *bnapi = bn->bnapi[i];
+               struct bnge_nq_ring_info *nqr = &bnapi->nq_ring;
+
+               if (nqr->hw_stats_ctx_id != INVALID_STATS_CTX_ID) {
+                       req->stat_ctx_id = cpu_to_le32(nqr->hw_stats_ctx_id);
+                       bnge_hwrm_req_send(bd, req);
+
+                       nqr->hw_stats_ctx_id = INVALID_STATS_CTX_ID;
+               }
+       }
+       bnge_hwrm_req_drop(bd, req);
+}
+
+int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn)
+{
+       struct hwrm_stat_ctx_alloc_output *resp;
+       struct hwrm_stat_ctx_alloc_input *req;
+       struct bnge_dev *bd = bn->bd;
+       int rc, i;
+
+       rc = bnge_hwrm_req_init(bd, req, HWRM_STAT_CTX_ALLOC);
+       if (rc)
+               return rc;
+
+       req->stats_dma_length = cpu_to_le16(bd->hw_ring_stats_size);
+       req->update_period_ms = cpu_to_le32(bn->stats_coal_ticks / 1000);
+
+       resp = bnge_hwrm_req_hold(bd, req);
+       for (i = 0; i < bd->nq_nr_rings; i++) {
+               struct bnge_napi *bnapi = bn->bnapi[i];
+               struct bnge_nq_ring_info *nqr = &bnapi->nq_ring;
+
+               req->stats_dma_addr = cpu_to_le64(nqr->stats.hw_stats_map);
+
+               rc = bnge_hwrm_req_send(bd, req);
+               if (rc)
+                       break;
+
+               nqr->hw_stats_ctx_id = le32_to_cpu(resp->stat_ctx_id);
+               bn->grp_info[i].fw_stats_ctx = nqr->hw_stats_ctx_id;
+       }
+       bnge_hwrm_req_drop(bd, req);
+       return rc;
+}
index 6c03923eb5592145ebe8786a0586b6f843f7700c..1c3fd02d7e0a33cda6d3a29b77784fec377df511 100644 (file)
@@ -24,4 +24,6 @@ int bnge_hwrm_func_qcfg(struct bnge_dev *bd);
 int bnge_hwrm_func_resc_qcaps(struct bnge_dev *bd);
 int bnge_hwrm_queue_qportcfg(struct bnge_dev *bd);
 
+void bnge_hwrm_stat_ctx_free(struct bnge_net *bn);
+int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn);
 #endif /* _BNGE_HWRM_LIB_H_ */
index 1ccc027c021f374cbaa248dfb8eb5f4005558a40..9f1deb60dd248510180a3b7bccdd827db0633cf0 100644 (file)
 #define BNGE_TC_TO_RING_BASE(bd, tc)   \
        ((tc) * (bd)->tx_nr_rings_per_tc)
 
+static void bnge_free_stats_mem(struct bnge_net *bn,
+                               struct bnge_stats_mem *stats)
+{
+       struct bnge_dev *bd = bn->bd;
+
+       if (stats->hw_stats) {
+               dma_free_coherent(bd->dev, stats->len, stats->hw_stats,
+                                 stats->hw_stats_map);
+               stats->hw_stats = NULL;
+       }
+}
+
+static int bnge_alloc_stats_mem(struct bnge_net *bn,
+                               struct bnge_stats_mem *stats)
+{
+       struct bnge_dev *bd = bn->bd;
+
+       stats->hw_stats = dma_alloc_coherent(bd->dev, stats->len,
+                                            &stats->hw_stats_map, GFP_KERNEL);
+       if (!stats->hw_stats)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void bnge_free_ring_stats(struct bnge_net *bn)
+{
+       struct bnge_dev *bd = bn->bd;
+       int i;
+
+       if (!bn->bnapi)
+               return;
+
+       for (i = 0; i < bd->nq_nr_rings; i++) {
+               struct bnge_napi *bnapi = bn->bnapi[i];
+               struct bnge_nq_ring_info *nqr = &bnapi->nq_ring;
+
+               bnge_free_stats_mem(bn, &nqr->stats);
+       }
+}
+
+static int bnge_alloc_ring_stats(struct bnge_net *bn)
+{
+       struct bnge_dev *bd = bn->bd;
+       u32 size, i;
+       int rc;
+
+       size = bd->hw_ring_stats_size;
+
+       for (i = 0; i < bd->nq_nr_rings; i++) {
+               struct bnge_napi *bnapi = bn->bnapi[i];
+               struct bnge_nq_ring_info *nqr = &bnapi->nq_ring;
+
+               nqr->stats.len = size;
+               rc = bnge_alloc_stats_mem(bn, &nqr->stats);
+               if (rc)
+                       goto err_free_ring_stats;
+
+               nqr->hw_stats_ctx_id = INVALID_STATS_CTX_ID;
+       }
+       return 0;
+
+err_free_ring_stats:
+       bnge_free_ring_stats(bn);
+       return rc;
+}
+
 static void bnge_free_nq_desc_arr(struct bnge_nq_ring_info *nqr)
 {
        struct bnge_ring_struct *ring = &nqr->ring_struct;
@@ -651,6 +718,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_stats(bn);
        bnge_free_ring_grps(bn);
        bnge_free_vnics(bn);
        kfree(bn->tx_ring_map);
@@ -739,6 +807,10 @@ static int bnge_alloc_core(struct bnge_net *bn)
                txr->bnapi = bnapi2;
        }
 
+       rc = bnge_alloc_ring_stats(bn);
+       if (rc)
+               goto err_free_core;
+
        rc = bnge_alloc_vnics(bn);
        if (rc)
                goto err_free_core;
@@ -1189,6 +1261,11 @@ static int bnge_setup_interrupts(struct bnge_net *bn)
        return netif_set_real_num_queues(dev, bd->tx_nr_rings, bd->rx_nr_rings);
 }
 
+static void bnge_hwrm_resource_free(struct bnge_net *bn, bool close_path)
+{
+       bnge_hwrm_stat_ctx_free(bn);
+}
+
 static void bnge_free_irq(struct bnge_net *bn)
 {
        struct bnge_dev *bd = bn->bd;
@@ -1256,6 +1333,25 @@ err_free_irq:
        return rc;
 }
 
+static int bnge_init_chip(struct bnge_net *bn)
+{
+       int rc;
+
+#define BNGE_DEF_STATS_COAL_TICKS       1000000
+       bn->stats_coal_ticks = BNGE_DEF_STATS_COAL_TICKS;
+
+       rc = bnge_hwrm_stat_ctx_alloc(bn);
+       if (rc) {
+               netdev_err(bn->netdev, "hwrm stat ctx alloc failure rc: %d\n", rc);
+               goto err_out;
+       }
+       return 0;
+
+err_out:
+       bnge_hwrm_resource_free(bn, 0);
+       return rc;
+}
+
 static int bnge_napi_poll(struct napi_struct *napi, int budget)
 {
        int work_done = 0;
@@ -1317,6 +1413,14 @@ static int bnge_init_nic(struct bnge_net *bn)
                goto err_free_rx_ring_pair_bufs;
 
        bnge_init_vnics(bn);
+
+       rc = bnge_init_chip(bn);
+       if (rc)
+               goto err_free_ring_grps;
+       return rc;
+
+err_free_ring_grps:
+       bnge_free_ring_grps(bn);
        return rc;
 
 err_free_rx_ring_pair_bufs:
index 10bd29a833ea094da9c27019485f2771a4a53230..55497c4e7fb8a1375d1dbe58e1ca462f8cdede56 100644 (file)
@@ -225,6 +225,7 @@ struct bnge_net {
        u8                      rss_hash_key[HW_HASH_KEY_SIZE];
        u8                      rss_hash_key_valid:1;
        u8                      rss_hash_key_updated:1;
+       u32                     stats_coal_ticks;
 };
 
 #define BNGE_DEFAULT_RX_RING_SIZE      511
@@ -271,6 +272,14 @@ void bnge_set_ring_params(struct bnge_dev *bd);
             txr = (iter < BNGE_MAX_TXR_PER_NAPI - 1) ? \
             (bnapi)->tx_ring[++iter] : NULL)
 
+struct bnge_stats_mem {
+       u64             *sw_stats;
+       u64             *hw_masks;
+       void            *hw_stats;
+       dma_addr_t      hw_stats_map;
+       int             len;
+};
+
 struct bnge_cp_ring_info {
        struct bnge_napi        *bnapi;
        dma_addr_t              *desc_mapping;
@@ -286,6 +295,9 @@ struct bnge_nq_ring_info {
        struct nqe_cn           **desc_ring;
        struct bnge_ring_struct ring_struct;
 
+       struct bnge_stats_mem   stats;
+       u32                     hw_stats_ctx_id;
+
        int                             cp_ring_count;
        struct bnge_cp_ring_info        *cp_ring_arr;
 };