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 --- .../net/ethernet/marvell/octeontx2/af/mbox.h | 1 + .../ethernet/marvell/octeontx2/af/rvu_nix.c | 69 ++++++++++++------- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 20 ++++-- .../ethernet/marvell/octeontx2/nic/otx2_pf.c | 6 +- 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index dc42c81c0942..e07fbf842b94 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -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; }; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index f977734ae712..7df256a9e01c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -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,7 +1500,7 @@ 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; struct rvu_hwinfo *hw = rvu->hw; u16 pcifunc = req->hdr.pcifunc; struct rvu_block *block; @@ -1555,8 +1556,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 +1567,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 +1586,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 +1604,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 +1622,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 +1646,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 +1691,16 @@ 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_alloc(rvu, pcifunc); + if (rc) + goto free_mem; + } + + 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 +1712,12 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu, goto exit; +free_dft: + if (is_cn20k(rvu->pdev)) + 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 +1791,9 @@ int rvu_mbox_handler_nix_lf_free(struct rvu *rvu, struct nix_lf_free_req *req, 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; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c index 3c814d157ab9..ec5b2d648246 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -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); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index ee623476e5ff..81b088f5a016 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -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 @@ int otx2_init_hw_resources(struct otx2_nic *pf) 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. */ -- 2.43.0