]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
octeontx2: cn20k: Coordinate default rules with NIX LF lifecycle
authorRatheesh Kannoth <rkannoth@marvell.com>
Tue, 9 Jun 2026 04:04:50 +0000 (09:34 +0530)
committerJakub Kicinski <kuba@kernel.org>
Sat, 13 Jun 2026 23:16:59 +0000 (16:16 -0700)
Add NIX_LF_DONT_FREE_DFT_IDXS so the PF can send NIX LF free during hw
reinit or teardown without the AF freeing CN20K default NPC rule indexes
while the driver still owns that state (otx2_init_hw_resources and
otx2_free_hw_resources).

On CN20K, allocate default NPC rules from NIX LF alloc before
nix_interface_init, roll back with npc_cn20k_dft_rules_free on failure,
and free from NIX LF free when the new flag is not set. Tighten
rvu_mbox_handler_nix_lf_alloc error handling: use a single rc, propagate
qmem_alloc and other errors, and set -ENOMEM only when kcalloc fails
(remove the blanket -ENOMEM at the free_mem path).

Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260609040453.711932-7-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c

index dc42c81c094256bcba2a0d7c310ac063283ea5a8..e07fbf842b943af4dbc2da6ef055cc9285eb0088 100644 (file)
@@ -1009,6 +1009,7 @@ struct nix_lf_free_req {
        struct mbox_msghdr hdr;
 #define NIX_LF_DISABLE_FLOWS           BIT_ULL(0)
 #define NIX_LF_DONT_FREE_TX_VTAG       BIT_ULL(1)
+#define NIX_LF_DONT_FREE_DFT_IDXS      BIT_ULL(2)
        u64 flags;
 };
 
index f977734ae712c603e77547613b4735e12941bc1c..d8989395e875dacd33cef0037ba063b78a8417a1 100644 (file)
@@ -16,6 +16,7 @@
 #include "cgx.h"
 #include "lmac_common.h"
 #include "rvu_npc_hash.h"
+#include "cn20k/npc.h"
 
 static void nix_free_tx_vtag_entries(struct rvu *rvu, u16 pcifunc);
 static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req,
@@ -1499,9 +1500,11 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
                                  struct nix_lf_alloc_req *req,
                                  struct nix_lf_alloc_rsp *rsp)
 {
-       int nixlf, qints, hwctx_size, intf, err, rc = 0;
+       int nixlf, qints, hwctx_size, intf, rc = 0;
+       u16 bcast, mcast, promisc, ucast;
        struct rvu_hwinfo *hw = rvu->hw;
        u16 pcifunc = req->hdr.pcifunc;
+       bool rules_created = false;
        struct rvu_block *block;
        struct rvu_pfvf *pfvf;
        u64 cfg, ctx_cfg;
@@ -1555,8 +1558,8 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
                return NIX_AF_ERR_RSS_GRPS_INVALID;
 
        /* Reset this NIX LF */
-       err = rvu_lf_reset(rvu, block, nixlf);
-       if (err) {
+       rc = rvu_lf_reset(rvu, block, nixlf);
+       if (rc) {
                dev_err(rvu->dev, "Failed to reset NIX%d LF%d\n",
                        block->addr - BLKADDR_NIX0, nixlf);
                return NIX_AF_ERR_LF_RESET;
@@ -1566,13 +1569,15 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
 
        /* Alloc NIX RQ HW context memory and config the base */
        hwctx_size = 1UL << ((ctx_cfg >> 4) & 0xF);
-       err = qmem_alloc(rvu->dev, &pfvf->rq_ctx, req->rq_cnt, hwctx_size);
-       if (err)
+       rc = qmem_alloc(rvu->dev, &pfvf->rq_ctx, req->rq_cnt, hwctx_size);
+       if (rc)
                goto free_mem;
 
        pfvf->rq_bmap = kcalloc(req->rq_cnt, sizeof(long), GFP_KERNEL);
-       if (!pfvf->rq_bmap)
+       if (!pfvf->rq_bmap) {
+               rc = -ENOMEM;
                goto free_mem;
+       }
 
        rvu_write64(rvu, blkaddr, NIX_AF_LFX_RQS_BASE(nixlf),
                    (u64)pfvf->rq_ctx->iova);
@@ -1583,13 +1588,15 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
 
        /* Alloc NIX SQ HW context memory and config the base */
        hwctx_size = 1UL << (ctx_cfg & 0xF);
-       err = qmem_alloc(rvu->dev, &pfvf->sq_ctx, req->sq_cnt, hwctx_size);
-       if (err)
+       rc = qmem_alloc(rvu->dev, &pfvf->sq_ctx, req->sq_cnt, hwctx_size);
+       if (rc)
                goto free_mem;
 
        pfvf->sq_bmap = kcalloc(req->sq_cnt, sizeof(long), GFP_KERNEL);
-       if (!pfvf->sq_bmap)
+       if (!pfvf->sq_bmap) {
+               rc = -ENOMEM;
                goto free_mem;
+       }
 
        rvu_write64(rvu, blkaddr, NIX_AF_LFX_SQS_BASE(nixlf),
                    (u64)pfvf->sq_ctx->iova);
@@ -1599,13 +1606,15 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
 
        /* Alloc NIX CQ HW context memory and config the base */
        hwctx_size = 1UL << ((ctx_cfg >> 8) & 0xF);
-       err = qmem_alloc(rvu->dev, &pfvf->cq_ctx, req->cq_cnt, hwctx_size);
-       if (err)
+       rc = qmem_alloc(rvu->dev, &pfvf->cq_ctx, req->cq_cnt, hwctx_size);
+       if (rc)
                goto free_mem;
 
        pfvf->cq_bmap = kcalloc(req->cq_cnt, sizeof(long), GFP_KERNEL);
-       if (!pfvf->cq_bmap)
+       if (!pfvf->cq_bmap) {
+               rc = -ENOMEM;
                goto free_mem;
+       }
 
        rvu_write64(rvu, blkaddr, NIX_AF_LFX_CQS_BASE(nixlf),
                    (u64)pfvf->cq_ctx->iova);
@@ -1615,18 +1624,18 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
 
        /* Initialize receive side scaling (RSS) */
        hwctx_size = 1UL << ((ctx_cfg >> 12) & 0xF);
-       err = nixlf_rss_ctx_init(rvu, blkaddr, pfvf, nixlf, req->rss_sz,
-                                req->rss_grps, hwctx_size, req->way_mask,
-                                !!(req->flags & NIX_LF_RSS_TAG_LSB_AS_ADDER));
-       if (err)
+       rc = nixlf_rss_ctx_init(rvu, blkaddr, pfvf, nixlf, req->rss_sz,
+                               req->rss_grps, hwctx_size, req->way_mask,
+                               !!(req->flags & NIX_LF_RSS_TAG_LSB_AS_ADDER));
+       if (rc)
                goto free_mem;
 
        /* Alloc memory for CQINT's HW contexts */
        cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
        qints = (cfg >> 24) & 0xFFF;
        hwctx_size = 1UL << ((ctx_cfg >> 24) & 0xF);
-       err = qmem_alloc(rvu->dev, &pfvf->cq_ints_ctx, qints, hwctx_size);
-       if (err)
+       rc = qmem_alloc(rvu->dev, &pfvf->cq_ints_ctx, qints, hwctx_size);
+       if (rc)
                goto free_mem;
 
        rvu_write64(rvu, blkaddr, NIX_AF_LFX_CINTS_BASE(nixlf),
@@ -1639,8 +1648,8 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
        cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
        qints = (cfg >> 12) & 0xFFF;
        hwctx_size = 1UL << ((ctx_cfg >> 20) & 0xF);
-       err = qmem_alloc(rvu->dev, &pfvf->nix_qints_ctx, qints, hwctx_size);
-       if (err)
+       rc = qmem_alloc(rvu->dev, &pfvf->nix_qints_ctx, qints, hwctx_size);
+       if (rc)
                goto free_mem;
 
        rvu_write64(rvu, blkaddr, NIX_AF_LFX_QINTS_BASE(nixlf),
@@ -1684,10 +1693,22 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
        if (is_sdp_pfvf(rvu, pcifunc))
                intf = NIX_INTF_TYPE_SDP;
 
-       err = nix_interface_init(rvu, pcifunc, intf, nixlf, rsp,
-                                !!(req->flags & NIX_LF_LBK_BLK_SEL));
-       if (err)
-               goto free_mem;
+       if (is_cn20k(rvu->pdev)) {
+               rc = npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &bcast, &mcast,
+                                                &promisc, &ucast);
+               if (rc) {
+                       rc = npc_cn20k_dft_rules_alloc(rvu, pcifunc);
+                       if (rc)
+                               goto free_mem;
+
+                       rules_created = true;
+               }
+       }
+
+       rc = nix_interface_init(rvu, pcifunc, intf, nixlf, rsp,
+                               !!(req->flags & NIX_LF_LBK_BLK_SEL));
+       if (rc)
+               goto free_dft;
 
        /* Disable NPC entries as NIXLF's contexts are not initialized yet */
        rvu_npc_disable_default_entries(rvu, pcifunc, nixlf);
@@ -1699,9 +1720,12 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
 
        goto exit;
 
+free_dft:
+       if (is_cn20k(rvu->pdev) && rules_created)
+               npc_cn20k_dft_rules_free(rvu, pcifunc);
+
 free_mem:
        nix_ctx_free(rvu, pfvf);
-       rc = -ENOMEM;
 
 exit:
        /* Set macaddr of this PF/VF */
@@ -1775,6 +1799,9 @@ free_lf:
 
        nix_ctx_free(rvu, pfvf);
 
+       if (is_cn20k(rvu->pdev) && !(req->flags & NIX_LF_DONT_FREE_DFT_IDXS))
+               npc_cn20k_dft_rules_free(rvu, pcifunc);
+
        return 0;
 }
 
index d301a3f0f87a86d277f16d6662cf53095523f656..150d50b72c48013061c3ef4ddb105741b9cdc94d 100644 (file)
@@ -1285,11 +1285,18 @@ void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
        struct nix_mce_list *mce_list;
        int index, blkaddr, mce_idx;
        struct rvu_pfvf *pfvf;
+       u16 ptr[4];
 
        /* multicast pkt replication is not enabled for AF's VFs & SDP links */
        if (is_lbk_vf(rvu, pcifunc) || is_sdp_pfvf(rvu, pcifunc))
                return;
 
+       /* In cn20k, only CGX mapped devices have default MCAST entry */
+       if (is_cn20k(rvu->pdev) &&
+           npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0], &ptr[1],
+                                       &ptr[2], &ptr[3]))
+               return;
+
        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
        if (blkaddr < 0)
                return;
@@ -1329,9 +1336,12 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
        struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
        struct npc_mcam *mcam = &rvu->hw->mcam;
        int index, blkaddr;
+       u16 ptr[4];
 
        /* only CGX or LBK interfaces have default entries */
-       if (is_cn20k(rvu->pdev) && !npc_is_cgx_or_lbk(rvu, pcifunc))
+       if (is_cn20k(rvu->pdev) &&
+           npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0], &ptr[1],
+                                       &ptr[2], &ptr[3]))
                return;
 
        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
@@ -4085,12 +4095,10 @@ void rvu_npc_clear_ucast_entry(struct rvu *rvu, int pcifunc, int nixlf)
 
        ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                             nixlf, NIXLF_UCAST_ENTRY);
-       if (ucast_idx < 0) {
-               dev_err(rvu->dev,
-                       "%s: Error to get ucast entry for pcifunc=%#x\n",
-                       __func__, pcifunc);
+
+       /* In cn20k, default rules are freed before detach rsrc */
+       if (ucast_idx < 0)
                return;
-       }
 
        npc_enable_mcam_entry(rvu, mcam, blkaddr, ucast_idx, false);
 
index f9fbf0c176482536a43bb1d865360255dc48ab5f..b4538edb13f80652526d33428bbcadefea525f44 100644 (file)
@@ -1053,7 +1053,6 @@ irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
        /* Clear the IRQ */
        otx2_write64(pf, RVU_PF_INT, BIT_ULL(0));
 
-
        mbox_data = otx2_read64(pf, RVU_PF_PFAF_MBOX0);
 
        if (mbox_data & MBOX_UP_MSG) {
@@ -1729,7 +1728,7 @@ err_free_nix_lf:
        mutex_lock(&mbox->lock);
        free_req = otx2_mbox_alloc_msg_nix_lf_free(mbox);
        if (free_req) {
-               free_req->flags = NIX_LF_DISABLE_FLOWS;
+               free_req->flags = NIX_LF_DISABLE_FLOWS | NIX_LF_DONT_FREE_DFT_IDXS;
                if (otx2_sync_mbox_msg(mbox))
                        dev_err(pf->dev, "%s failed to free nixlf\n", __func__);
        }
@@ -1803,7 +1802,7 @@ void otx2_free_hw_resources(struct otx2_nic *pf)
        /* Reset NIX LF */
        free_req = otx2_mbox_alloc_msg_nix_lf_free(mbox);
        if (free_req) {
-               free_req->flags = NIX_LF_DISABLE_FLOWS;
+               free_req->flags = NIX_LF_DISABLE_FLOWS | NIX_LF_DONT_FREE_DFT_IDXS;
                if (!(pf->flags & OTX2_FLAG_PF_SHUTDOWN))
                        free_req->flags |= NIX_LF_DONT_FREE_TX_VTAG;
                if (otx2_sync_mbox_msg(mbox))
@@ -1926,7 +1925,6 @@ int otx2_alloc_queue_mem(struct otx2_nic *pf)
        struct otx2_qset *qset = &pf->qset;
        struct otx2_cq_poll *cq_poll;
 
-
        /* RQ and SQs are mapped to different CQs,
         * so find out max CQ IRQs (i.e CINTs) needed.
         */