From nobody Fri Jan 9 00:36:47 2026 Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C338B2EE5FC; Mon, 5 Jan 2026 02:34:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.148.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580445; cv=none; b=EdmFDqJrDJJ5e4F7EDDV31APoIJe4V/OOzkxCSuhTI1LfI8mYchuWb+ICbUzX67oetFcFZbJwDju2N32ioFB57yN6SeByMWDVYV+g/877oklhi9Y4+5hZnp+scn+5zXjxcHA/T1e9NpSCjKwoklxyqqKvzNGo2lGDNcXzeODicA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580445; c=relaxed/simple; bh=gc2kiXRwz82P27Ycuu42+RW4mxp7NsAB19LlDhnnACM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fAk1Iq6Ebumu4W3SpBzuWwI6LjoQqSdco4W/P/FsBX3VyLw8ZSlbX4E+S0gCRbKqvVUlEWGZCBniQgt2himQexCgjJm/ArqLUVBSVpde9j2itgTrzvrkX6KaRM1V1WAJK1pWBtRxRUho2hCXBDZvoFCzlctEiyXi/dXsQwD3zPY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=LTcUm85h; arc=none smtp.client-ip=67.231.148.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="LTcUm85h" Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604Mf02D3322501; Sun, 4 Jan 2026 18:33:52 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=pfpt0220; bh=e l92OnXS7O9VMLTJ6wp7T7tV9Od3gfuhsCYerinTS8g=; b=LTcUm85h0JOCsScGR /C8lVqXc9UF2gR2N41uvIeybNnLiJk5rTF4Hq5M6jmIKqdQzXyIc+7G0mtUREWJQ BDt67xmF2bNH96Ry2Dk6zfu7leMuAvxSvP0y8/Srgkn8JQ3aKf41y7YqT1+wgSzs 8/gjgQI+VxJ7TKDzpFvqKBiyinExvwG/gQvwhA1haSnZSKHyCJRVYGA43SEOUglm Ux5/oEh9/oP8/v5phad3hFQkW4cG/+SNypYgyRwz0uQeuqQ/buDe2nkf+6TJ0R4C kU9Of11K2f3QeWyHM/l/6dha3RoefJsBn7lkhRvlPhHT4u1Gji6IYlBIyYnVtrxq lH5TA== Received: from dc5-exch05.marvell.com ([199.233.59.128]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 4bfsu00ptx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:52 -0800 (PST) Received: from DC5-EXCH05.marvell.com (10.69.176.209) by DC5-EXCH05.marvell.com (10.69.176.209) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.25; Sun, 4 Jan 2026 18:34:04 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH05.marvell.com (10.69.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:34:04 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id 4F2493F7094; Sun, 4 Jan 2026 18:33:48 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 09/13] octeontx2-af: npc: cn20k: virtual index support Date: Mon, 5 Jan 2026 08:02:50 +0530 Message-ID: <20260105023254.1426488-10-rkannoth@marvell.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260105023254.1426488-1-rkannoth@marvell.com> References: <20260105023254.1426488-1-rkannoth@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: l2kagHaT-6wHHbCvB9Mu_gLBWti-mFsS X-Proofpoint-GUID: l2kagHaT-6wHHbCvB9Mu_gLBWti-mFsS X-Authority-Analysis: v=2.4 cv=AMUfTh+a c=1 sm=1 tr=0 ts=695b2310 cx=c_pps a=rEv8fa4AjpPjGxpoe8rlIQ==:117 a=rEv8fa4AjpPjGxpoe8rlIQ==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=Suy3FIYwjLXlUDo0TKgA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX+eFRb/Q0idSb d+BXRBdRxBi1Hp6In7v4fv7JHB3k6VPEtRdHb3pgHbvUqV0C1ep+iB8sYXl1F5f4vfLFlH/OnQM B8dEN3Nz9iC7+kYVHNPe7TcKqLnLr6WwrHewPtuAusOstbztfyX1zEtZqm03BWTYoDDmzWEbbJp JVsIM7ptWrPjzcIGEc1jNCcW0tVIr/HXKlhPBI0zFX/XHjFD0k/GCflyrnXR0gpQaiVcZIQxUEe 795EHkZxB872R5a+umx6JtwfNfJ1Ij6oIKJfMoEOHQCjMck796QG50bUA4TD7R4opAo5/MC8dKd 7R9rTzAtZxjC+gWmF6eOUUl50vRFKZC90gHg/f+Dm3+WdbCfsdUKP+vRTXjMxIXkKhC6+OARHiq 668lTl7nzG8v+Jcib2RfytekfunTGcTYkRnDE4NkoUagexbz4V/cEgQh1GKUrVeTc09fNsemm1u BEg8axmcbSm25cHfYBA== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2026-01-04_07,2025-12-31_01,2025-10-01_01 Content-Type: text/plain; charset="utf-8" This patch adds support for virtual MCAM index allocation and improves CN20K MCAM defragmentation handling. A new field is introduced in the non-ref, non-contiguous MCAM allocation mailbox request to indicate that virtual indexes should be returned instead of physical ones. Virtual indexes allow the hardware to move mapped MCAM entries internally, enabling defragmentation and preventing scattered allocations across subbanks. The patch also enhances defragmentation by treating non-ref, non-contiguous allocations as ideal candidates for packing sparsely used regions, which can free up subbanks for potential x2 or x4 configuration. All such allocations are tracked and always returned as virtual indexes so they remain stable even when entries are moved during defrag. During defragmentation, MCAM entries may shift between subbanks, but their virtual indexes remain unchanged. Additionally, this update fixes an issue where entry statistics were not being restored correctly after defragmentation. Signed-off-by: Ratheesh Kannoth --- .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 767 +++++++++++++++++- .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 16 +- .../net/ethernet/marvell/octeontx2/af/mbox.h | 5 + .../marvell/octeontx2/af/rvu_devlink.c | 81 +- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 22 +- .../ethernet/marvell/octeontx2/af/rvu_npc.h | 2 + .../marvell/octeontx2/af/rvu_npc_fs.c | 6 + 7 files changed, 880 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.c index 33c0047c1bcd..75e492c2dfda 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -209,6 +209,204 @@ struct npc_mcam_kex_extr *npc_mkex_extr_default_get(v= oid) return &npc_mkex_extr_default; } =20 +static u16 npc_idx2vidx(u16 idx) +{ + unsigned long index; + void *map; + u16 vidx; + int val; + + vidx =3D idx; + index =3D idx; + + map =3D xa_load(&npc_priv.xa_idx2vidx_map, index); + if (!map) + goto done; + + val =3D xa_to_value(map); + if (val =3D=3D -1) + goto done; + + vidx =3D val; + +done: + return vidx; +} + +static bool npc_is_vidx(u16 vidx) +{ + return vidx >=3D npc_priv.bank_depth * 2; +} + +static u16 npc_vidx2idx(u16 vidx) +{ + unsigned long index; + void *map; + int val; + u16 idx; + + idx =3D vidx; + index =3D vidx; + + map =3D xa_load(&npc_priv.xa_vidx2idx_map, index); + if (!map) + goto done; + + val =3D xa_to_value(map); + if (val =3D=3D -1) + goto done; + + idx =3D val; + +done: + return idx; +} + +u16 npc_cn20k_vidx2idx(u16 idx) +{ + if (!npc_priv.init_done) + return idx; + + if (!npc_is_vidx(idx)) + return idx; + + return npc_vidx2idx(idx); +} + +u16 npc_cn20k_idx2vidx(u16 idx) +{ + if (!npc_priv.init_done) + return idx; + + if (npc_is_vidx(idx)) + return idx; + + return npc_idx2vidx(idx); +} + +static int npc_vidx_maps_del_entry(struct rvu *rvu, u16 vidx, u16 *old_mid= x) +{ + u16 mcam_idx; + void *map; + + if (!npc_is_vidx(vidx)) { + dev_err(rvu->dev, + "%s:%d vidx(%u) does not map to proper mcam idx\n", + __func__, __LINE__, vidx); + return -ESRCH; + } + + mcam_idx =3D npc_vidx2idx(vidx); + + map =3D xa_erase(&npc_priv.xa_vidx2idx_map, vidx); + if (!map) { + dev_err(rvu->dev, + "%s:%d vidx(%u) does not map to proper mcam idx\n", + __func__, __LINE__, vidx); + return -ESRCH; + } + + map =3D xa_erase(&npc_priv.xa_idx2vidx_map, mcam_idx); + if (!map) { + dev_err(rvu->dev, + "%s:%d mcam idx(%u) is not valid\n", + __func__, __LINE__, vidx); + return -ESRCH; + } + + if (old_midx) + *old_midx =3D mcam_idx; + + return 0; +} + +static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx) +{ + u16 old_midx; + void *map; + int rc; + + if (!npc_is_vidx(vidx)) { + dev_err(rvu->dev, + "%s:%d vidx(%u) does not map to proper mcam idx\n", + __func__, __LINE__, vidx); + return -ESRCH; + } + + map =3D xa_erase(&npc_priv.xa_vidx2idx_map, vidx); + if (!map) { + dev_err(rvu->dev, + "%s:%d vidx(%u) could not be deleted from vidx2idx map\n", + __func__, __LINE__, vidx); + return -ESRCH; + } + + old_midx =3D xa_to_value(map); + + rc =3D xa_insert(&npc_priv.xa_vidx2idx_map, vidx, + xa_mk_value(new_midx), GFP_KERNEL); + if (rc) { + dev_err(rvu->dev, + "%s:%d vidx(%u) cannot be added to vidx2idx map\n", + __func__, __LINE__, vidx); + return rc; + } + + map =3D xa_erase(&npc_priv.xa_idx2vidx_map, old_midx); + if (!map) { + dev_err(rvu->dev, + "%s:%d old_midx(%u, vidx(%u)) cannot be added to idx2vidx map\n", + __func__, __LINE__, old_midx, vidx); + return -ESRCH; + } + + rc =3D xa_insert(&npc_priv.xa_idx2vidx_map, new_midx, + xa_mk_value(vidx), GFP_KERNEL); + if (rc) { + dev_err(rvu->dev, + "%s:%d new_midx(%u, vidx(%u)) cannot be added to idx2vidx map\n", + __func__, __LINE__, new_midx, vidx); + return rc; + } + + return 0; +} + +static int npc_vidx_maps_add_entry(struct rvu *rvu, u16 mcam_idx, int pcif= unc, + u16 *vidx) +{ + int rc, max, min; + u32 id; + + /* Virtual index start from maximum mcam index + 1 */ + max =3D npc_priv.bank_depth * 2 * 2 - 1; + min =3D npc_priv.bank_depth * 2; + + rc =3D xa_alloc(&npc_priv.xa_vidx2idx_map, &id, + xa_mk_value(mcam_idx), + XA_LIMIT(min, max), GFP_KERNEL); + if (rc) { + dev_err(rvu->dev, + "%s:%d Failed to add to vidx2idx map (%u)\n", + __func__, __LINE__, mcam_idx); + return rc; + } + + rc =3D xa_insert(&npc_priv.xa_idx2vidx_map, mcam_idx, + xa_mk_value(id), GFP_KERNEL); + if (rc) { + dev_err(rvu->dev, + "%s:%d Failed to add to idx2vidx map (%u)\n", + __func__, __LINE__, mcam_idx); + return rc; + } + + if (vidx) + *vidx =3D id; + + return 0; +} + static void npc_config_kpmcam(struct rvu *rvu, int blkaddr, const struct npc_kpu_profile_cam *kpucam, int kpm, int entry) @@ -978,6 +1176,8 @@ int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct= rvu *rvu, int blkaddr, rc; u8 nix_intf; =20 + req->entry =3D npc_cn20k_vidx2idx(req->entry); + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; @@ -1019,6 +1219,8 @@ int rvu_mbox_handler_npc_cn20k_mcam_read_entry(struct= rvu *rvu, u16 pcifunc =3D req->hdr.pcifunc; int blkaddr, rc; =20 + req->entry =3D npc_cn20k_vidx2idx(req->entry); + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; @@ -1059,6 +1261,7 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_e= ntry(struct rvu *rvu, entry_req.ref_prio =3D req->ref_prio; entry_req.ref_entry =3D req->ref_entry; entry_req.count =3D 1; + entry_req.virt =3D req->virt; =20 rc =3D rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &entry_req, &entry_rsp); @@ -1068,7 +1271,7 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_e= ntry(struct rvu *rvu, if (!entry_rsp.count) return NPC_MCAM_ALLOC_FAILED; =20 - entry =3D entry_rsp.entry; + entry =3D npc_cn20k_vidx2idx(entry_rsp.entry); mutex_lock(&mcam->lock); =20 if (is_npc_intf_tx(req->intf)) @@ -1082,7 +1285,7 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_e= ntry(struct rvu *rvu, =20 mutex_unlock(&mcam->lock); =20 - rsp->entry =3D entry; + rsp->entry =3D entry_rsp.entry; return 0; } =20 @@ -2144,24 +2347,56 @@ static int npc_idx_free(struct rvu *rvu, u16 *mcam_= idx, int count, bool maps_del) { struct npc_subbank *sb; - int idx, i; + u16 vidx, midx; + int sb_off, i; bool ret; int rc; =20 for (i =3D 0; i < count; i++) { - rc =3D npc_mcam_idx_2_subbank_idx(rvu, mcam_idx[i], - &sb, &idx); - if (rc) + if (npc_is_vidx(mcam_idx[i])) { + vidx =3D mcam_idx[i]; + midx =3D npc_vidx2idx(vidx); + } else { + midx =3D mcam_idx[i]; + vidx =3D npc_idx2vidx(midx); + } + + if (midx >=3D npc_priv.bank_depth * npc_priv.num_banks) { + dev_err(rvu->dev, + "%s:%d Invalid mcam_idx=3D%u cannot be deleted\n", + __func__, __LINE__, mcam_idx[i]); + return -EINVAL; + } + + rc =3D npc_mcam_idx_2_subbank_idx(rvu, midx, + &sb, &sb_off); + if (rc) { + dev_err(rvu->dev, + "%s:%d Failed to find subbank info for vidx=3D%u\n", + __func__, __LINE__, vidx); return rc; + } =20 - ret =3D npc_subbank_free(rvu, sb, idx); - if (ret) + ret =3D npc_subbank_free(rvu, sb, sb_off); + if (ret) { + dev_err(rvu->dev, + "%s:%d Failed to find subbank info for vidx=3D%u\n", + __func__, __LINE__, vidx); return -EINVAL; + } =20 if (!maps_del) continue; =20 - rc =3D npc_del_from_pf_maps(rvu, mcam_idx[i]); + rc =3D npc_del_from_pf_maps(rvu, midx); + if (rc) + return rc; + + /* If there is no vidx mapping; continue */ + if (vidx =3D=3D midx) + continue; + + rc =3D npc_vidx_maps_del_entry(rvu, vidx, NULL); if (rc) return rc; } @@ -2676,10 +2911,12 @@ int npc_cn20k_idx_free(struct rvu *rvu, u16 *mcam_i= dx, int count) =20 int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type, int prio, u16 *mcam_idx, int ref, int limit, - bool contig, int count) + bool contig, int count, bool virt) { + bool defrag_candidate =3D false; int i, eidx, rc, bd; bool ref_valid; + u16 vidx; =20 bd =3D npc_priv.bank_depth; =20 @@ -2697,6 +2934,7 @@ int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcif= unc, int key_type, } =20 ref_valid =3D !!(limit || ref); + defrag_candidate =3D !ref_valid && !contig && virt; if (!ref_valid) { if (contig && count > npc_priv.subbank_depth) goto try_noref_multi_subbank; @@ -2765,6 +3003,16 @@ int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pci= func, int key_type, rc =3D npc_add_to_pf_maps(rvu, mcam_idx[i], pcifunc); if (rc) return rc; + + if (!defrag_candidate) + continue; + + rc =3D npc_vidx_maps_add_entry(rvu, mcam_idx[i], pcifunc, &vidx); + if (rc) + return rc; + + /* Return vidx to caller */ + mcam_idx[i] =3D vidx; } =20 return 0; @@ -3030,6 +3278,498 @@ static int npc_pcifunc_map_create(struct rvu *rvu) return cnt; } =20 +struct npc_defrag_node { + u8 idx; + u8 key_type; + bool valid; + bool refs; + u16 free_cnt; + u16 vidx_cnt; + u16 *vidx; + struct list_head list; +}; + +static bool npc_defrag_skip_restricted_sb(int sb_id) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(npc_subbank_restricted_idxs); i++) + if (sb_id =3D=3D npc_subbank_restricted_idxs[i]) + return true; + return false; +} + +/* Find subbank with minimum number of virtual indexes */ +static struct npc_defrag_node *npc_subbank_min_vidx(struct list_head *lh) +{ + struct npc_defrag_node *node, *tnode =3D NULL; + int min =3D INT_MAX; + + list_for_each_entry(node, lh, list) { + if (!node->valid) + continue; + + /* if subbank has ref allocated mcam indexes, that subbank + * is not a good candidate to move out indexes. + */ + if (node->refs) + continue; + + if (min > node->vidx_cnt) { + min =3D node->vidx_cnt; + tnode =3D node; + } + } + + return tnode; +} + +/* Find subbank with maximum number of free spaces */ +static struct npc_defrag_node *npc_subbank_max_free(struct list_head *lh) +{ + struct npc_defrag_node *node, *tnode =3D NULL; + int max =3D INT_MIN; + + list_for_each_entry(node, lh, list) { + if (!node->valid) + continue; + + if (max < node->free_cnt) { + max =3D node->free_cnt; + tnode =3D node; + } + } + + return tnode; +} + +static int npc_defrag_alloc_free_slots(struct rvu *rvu, + struct npc_defrag_node *f, + int cnt, u16 *save) +{ + int alloc_cnt1, alloc_cnt2; + struct npc_subbank *sb; + int rc, sb_off, i; + bool deleted; + + sb =3D &npc_priv.sb[f->idx]; + + alloc_cnt1 =3D 0; + alloc_cnt2 =3D 0; + + rc =3D __npc_subbank_alloc(rvu, sb, + NPC_MCAM_KEY_X2, sb->b0b, + sb->b0t, + NPC_MCAM_LOWER_PRIO, + false, cnt, save, cnt, true, + &alloc_cnt1); + if (alloc_cnt1 < cnt) { + rc =3D __npc_subbank_alloc(rvu, sb, + NPC_MCAM_KEY_X2, sb->b1b, + sb->b1t, + NPC_MCAM_LOWER_PRIO, + false, cnt - alloc_cnt1, + save + alloc_cnt1, + cnt - alloc_cnt1, + true, &alloc_cnt2); + } + + if (alloc_cnt1 + alloc_cnt2 !=3D cnt) { + dev_err(rvu->dev, + "%s:%d Failed to alloc cnt=3D%u alloc_cnt1=3D%u alloc_cnt2=3D%u\n", + __func__, __LINE__, cnt, alloc_cnt1, alloc_cnt2); + goto fail_free_alloc; + } + return 0; + +fail_free_alloc: + for (i =3D 0; i < alloc_cnt1 + alloc_cnt2; i++) { + rc =3D npc_mcam_idx_2_subbank_idx(rvu, save[i], + &sb, &sb_off); + if (rc) { + dev_err(rvu->dev, + "%s:%d Error to find subbank for mcam idx=3D%u\n", + __func__, __LINE__, save[i]); + break; + } + + deleted =3D __npc_subbank_free(rvu, sb, sb_off); + if (!deleted) { + dev_err(rvu->dev, + "%s:%d Error to free mcam idx=3D%u\n", + __func__, __LINE__, save[i]); + break; + } + } + + return rc; +} + +static int npc_defrag_add_2_show_list(struct rvu *rvu, u16 old_midx, + u16 new_midx, u16 vidx) +{ + struct npc_defrag_show_node *node; + + node =3D kcalloc(1, sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + + node->old_midx =3D old_midx; + node->new_midx =3D new_midx; + node->vidx =3D vidx; + INIT_LIST_HEAD(&node->list); + + mutex_lock(&npc_priv.lock); + list_add_tail(&node->list, &npc_priv.defrag_lh); + mutex_unlock(&npc_priv.lock); + + return 0; +} + +static +int npc_defrag_move_vdx_to_free(struct rvu *rvu, + struct npc_defrag_node *f, + struct npc_defrag_node *v, + int cnt, u16 *save) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + int i, vidx_cnt, rc, sb_off; + u16 new_midx, old_midx, vidx; + struct npc_subbank *sb; + bool deleted; + u16 pcifunc; + int blkaddr; + void *map; + u8 bank; + u16 midx; + u64 stats; + + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + + vidx_cnt =3D v->vidx_cnt; + for (i =3D 0; i < cnt; i++) { + vidx =3D v->vidx[vidx_cnt - i - 1]; + old_midx =3D npc_vidx2idx(vidx); + new_midx =3D save[cnt - i - 1]; + + dev_dbg(rvu->dev, + "%s:%d Moving %u ---> %u (vidx=3D%u)\n", + __func__, __LINE__, + old_midx, new_midx, vidx); + + rc =3D npc_defrag_add_2_show_list(rvu, old_midx, new_midx, vidx); + if (rc) + dev_err(rvu->dev, + "%s:%d Error happened to add to show list vidx=3D%u\n", + __func__, __LINE__, vidx); + + /* Modify vidx to point to new mcam idx */ + rc =3D npc_vidx_maps_modify(rvu, vidx, new_midx); + if (rc) + return rc; + + midx =3D old_midx % mcam->banksize; + bank =3D old_midx / mcam->banksize; + stats =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(midx, bank)); + + npc_cn20k_enable_mcam_entry(rvu, blkaddr, old_midx, false); + npc_cn20k_copy_mcam_entry(rvu, blkaddr, old_midx, new_midx); + npc_cn20k_enable_mcam_entry(rvu, blkaddr, new_midx, true); + + midx =3D new_midx % mcam->banksize; + bank =3D new_midx / mcam->banksize; + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(midx, bank), + stats); + + /* Free the old mcam idx */ + rc =3D npc_mcam_idx_2_subbank_idx(rvu, old_midx, + &sb, &sb_off); + if (rc) { + dev_err(rvu->dev, + "%s:%d Unable to calculate subbank off for mcamidx=3D%u\n", + __func__, __LINE__, old_midx); + return rc; + } + + deleted =3D __npc_subbank_free(rvu, sb, sb_off); + if (!deleted) { + dev_err(rvu->dev, + "%s:%d Failed to free mcamidx=3D%u sb=3D%u sb_off=3D%u\n", + __func__, __LINE__, old_midx, sb->idx, sb_off); + return rc; + } + + /* save pcifunc */ + map =3D xa_load(&npc_priv.xa_idx2pf_map, old_midx); + pcifunc =3D xa_to_value(map); + + /* delete from pf maps */ + rc =3D npc_del_from_pf_maps(rvu, old_midx); + if (rc) { + dev_err(rvu->dev, + "%s:%d Failed to delete pf maps for mcamidx=3D%u\n", + __func__, __LINE__, old_midx); + return rc; + } + + /* add new mcam_idx to pf map */ + rc =3D npc_add_to_pf_maps(rvu, new_midx, pcifunc); + if (rc) { + dev_err(rvu->dev, + "%s:%d Failed to add pf maps for mcamidx=3D%u\n", + __func__, __LINE__, new_midx); + return rc; + } + + /* Remove from mcam maps */ + mcam->entry2pfvf_map[old_midx] =3D NPC_MCAM_INVALID_MAP; + mcam->entry2cntr_map[old_midx] =3D NPC_MCAM_INVALID_MAP; + npc_mcam_clear_bit(mcam, old_midx); + + mcam->entry2pfvf_map[new_midx] =3D pcifunc; + mcam->entry2cntr_map[new_midx] =3D pcifunc; + npc_mcam_set_bit(mcam, new_midx); + + /* Mark as invalid */ + v->vidx[vidx_cnt - i - 1] =3D -1; + save[cnt - i - 1] =3D -1; + + f->free_cnt--; + v->vidx_cnt--; + } + + return 0; +} + +static int npc_defrag_process(struct rvu *rvu, struct list_head *lh) +{ + struct npc_defrag_node *v =3D NULL; + struct npc_defrag_node *f =3D NULL; + int rc =3D 0, cnt; + u16 *save; + + while (1) { + /* Find subbank with minimum vidx */ + if (!v) { + v =3D npc_subbank_min_vidx(lh); + if (!v) + break; + } + + /* Find subbank with maximum free slots */ + if (!f) { + f =3D npc_subbank_max_free(lh); + if (!f) + break; + } + + if (!v->vidx_cnt) { + list_del_init(&v->list); + v =3D NULL; + continue; + } + + if (!f->free_cnt) { + list_del_init(&f->list); + f =3D NULL; + continue; + } + + /* If both subbanks are same, choose vidx and + * search for free list again + */ + if (f =3D=3D v) { + list_del_init(&f->list); + f =3D NULL; + continue; + } + + /* Calculate minimum free slots needs to be allocated */ + cnt =3D f->free_cnt > v->vidx_cnt ? v->vidx_cnt : + f->free_cnt; + + dev_dbg(rvu->dev, + "%s:%d cnt=3D%u free_cnt=3D%u(sb=3D%u) vidx_cnt=3D%u(sb=3D%u)\n", + __func__, __LINE__, cnt, f->free_cnt, f->idx, + v->vidx_cnt, v->idx); + + /* Allocate an array to store newly allocated + * free slots (mcam indexes) + */ + save =3D kcalloc(cnt, sizeof(*save), GFP_KERNEL); + if (!save) { + rc =3D -ENOMEM; + goto err; + } + + /* Alloc free slots for existing vidx */ + rc =3D npc_defrag_alloc_free_slots(rvu, f, cnt, save); + if (rc) { + kfree(save); + goto err; + } + + /* Move vidx to free slots; update pf_map and vidx maps, + * and free existing vidx mcam slots + */ + rc =3D npc_defrag_move_vdx_to_free(rvu, f, v, cnt, save); + if (rc) { + kfree(save); + goto err; + } + + kfree(save); + + if (!f->free_cnt) { + list_del_init(&f->list); + f =3D NULL; + } + + if (!v->vidx_cnt) { + list_del_init(&v->list); + v =3D NULL; + } + } + +err: + /* TODO: how to go back to old state ? */ + return rc; +} + +static void npc_defrag_list_clear(void) +{ + struct npc_defrag_show_node *node, *next; + + mutex_lock(&npc_priv.lock); + list_for_each_entry_safe(node, next, &npc_priv.defrag_lh, list) { + list_del_init(&node->list); + kfree(node); + } + + mutex_unlock(&npc_priv.lock); +} + +/* Only non-ref non-contigous mcam indexes + * are picked for defrag process + */ +int npc_cn20k_defrag(struct rvu *rvu) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + struct npc_defrag_node *node, *tnode; + struct list_head x4lh, x2lh, *lh; + int rc =3D 0, i, sb_off, tot; + struct npc_subbank *sb; + unsigned long index; + void *map; + u16 midx; + + /* Free previous show list */ + npc_defrag_list_clear(); + + INIT_LIST_HEAD(&x4lh); + INIT_LIST_HEAD(&x2lh); + + node =3D kcalloc(npc_priv.num_subbanks, sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + + /* Lock mcam */ + mutex_lock(&mcam->lock); + npc_lock_all_subbank(); + + /* Fill in node with subbank properties */ + for (i =3D 0; i < npc_priv.num_subbanks; i++) { + sb =3D &npc_priv.sb[i]; + + node[i].idx =3D i; + node[i].key_type =3D sb->key_type; + node[i].free_cnt =3D sb->free_cnt; + node[i].vidx =3D kcalloc(npc_priv.subbank_depth * 2, + sizeof(node[i].vidx), + GFP_KERNEL); + if (!node[i].vidx) { + rc =3D -ENOMEM; + goto free_vidx; + } + + /* If subbank is empty, dont include it in defrag + * process + */ + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { + node[i].valid =3D false; + continue; + } + + if (npc_defrag_skip_restricted_sb(i)) { + node[i].valid =3D false; + continue; + } + + node[i].valid =3D true; + INIT_LIST_HEAD(&node[i].list); + + /* Add node to x2 or x4 list */ + lh =3D sb->key_type =3D=3D NPC_MCAM_KEY_X2 ? &x2lh : &x4lh; + list_add_tail(&node[i].list, lh); + } + + /* Filling vidx[] array with all vidx in that subbank */ + xa_for_each_start(&npc_priv.xa_vidx2idx_map, index, map, + npc_priv.bank_depth * 2) { + midx =3D xa_to_value(map); + rc =3D npc_mcam_idx_2_subbank_idx(rvu, midx, + &sb, &sb_off); + if (rc) { + dev_err(rvu->dev, + "%s:%d Error to get mcam_idx for vidx=3D%lu\n", + __func__, __LINE__, index); + goto free_vidx; + } + + tnode =3D &node[sb->idx]; + tnode->vidx[tnode->vidx_cnt] =3D index; + tnode->vidx_cnt++; + } + + /* Mark all subbank which has ref allocation */ + for (i =3D 0; i < npc_priv.num_subbanks; i++) { + tnode =3D &node[i]; + + if (!tnode->valid) + continue; + + tot =3D (tnode->key_type =3D=3D NPC_MCAM_KEY_X2) ? + npc_priv.subbank_depth * 2 : npc_priv.subbank_depth; + + if (node[i].vidx_cnt !=3D tot - tnode->free_cnt) + tnode->refs =3D true; + } + + rc =3D npc_defrag_process(rvu, &x2lh); + if (rc) + goto free_vidx; + + rc =3D npc_defrag_process(rvu, &x4lh); + if (rc) + goto free_vidx; + +free_vidx: + npc_unlock_all_subbank(); + mutex_unlock(&mcam->lock); + for (i =3D 0; i < npc_priv.num_subbanks; i++) + kfree(node[i].vidx); + kfree(node); + return rc; +} + +int rvu_mbox_handler_npc_defrag(struct rvu *rvu, struct msg_req *req, + struct msg_rsp *rsp) +{ + return npc_cn20k_defrag(rvu); +} + int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast, u16 *mcast, u16 *promisc, u16 *ucast) { @@ -3415,6 +4155,8 @@ static int npc_priv_init(struct rvu *rvu) xa_init_flags(&npc_priv.xa_idx2pf_map, XA_FLAGS_ALLOC); xa_init_flags(&npc_priv.xa_pf_map, XA_FLAGS_ALLOC); xa_init_flags(&npc_priv.xa_pf2dfl_rmap, XA_FLAGS_ALLOC); + xa_init_flags(&npc_priv.xa_idx2vidx_map, XA_FLAGS_ALLOC); + xa_init_flags(&npc_priv.xa_vidx2idx_map, XA_FLAGS_ALLOC); =20 npc_create_srch_order(num_subbanks); npc_populate_restricted_idxs(num_subbanks); @@ -3433,6 +4175,9 @@ static int npc_priv_init(struct rvu *rvu) for (i =3D 0; i < npc_priv.pf_cnt; i++) xa_init_flags(&npc_priv.xa_pf2idx_map[i], XA_FLAGS_ALLOC); =20 + INIT_LIST_HEAD(&npc_priv.defrag_lh); + mutex_init(&npc_priv.lock); + return 0; } =20 @@ -3445,6 +4190,8 @@ int npc_cn20k_deinit(struct rvu *rvu) xa_destroy(&npc_priv.xa_idx2pf_map); xa_destroy(&npc_priv.xa_pf_map); xa_destroy(&npc_priv.xa_pf2dfl_rmap); + xa_destroy(&npc_priv.xa_idx2vidx_map); + xa_destroy(&npc_priv.xa_vidx2idx_map); =20 for (i =3D 0; i < npc_priv.pf_cnt; i++) xa_destroy(&npc_priv.xa_pf2idx_map[i]); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.h index f608ed286548..9e04e0f8c618 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h @@ -105,6 +105,13 @@ struct npc_subbank { u8 key_type; //NPC_MCAM_KEY_X4 or NPC_MCAM_KEY_X2 }; =20 +struct npc_defrag_show_node { + u16 old_midx; + u16 new_midx; + u16 vidx; + struct list_head list; +}; + struct npc_priv_t { int bank_depth; const int num_banks; @@ -118,6 +125,10 @@ struct npc_priv_t { struct xarray xa_idx2pf_map; // Mcam idxes to pf map. struct xarray xa_pf_map; // pcifunc to index map. struct xarray xa_pf2dfl_rmap; // pcifunc to default rule index + struct xarray xa_idx2vidx_map; // mcam idx to virtual index map. + struct xarray xa_vidx2idx_map; // mcam vidx to index map. + struct list_head defrag_lh; // defrag list head for debugfs + struct mutex lock; // lock int pf_cnt; bool init_done; }; @@ -212,7 +223,7 @@ void npc_cn20k_subbank_calc_free(struct rvu *rvu, int *= x2_free, =20 int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type, int prio, u16 *mcam_idx, int ref, int limit, - bool contig, int count); + bool contig, int count, bool virt); int npc_cn20k_idx_free(struct rvu *rvu, u16 *mcam_idx, int count); int npc_cn20k_search_order_set(struct rvu *rvu, int (*arr)[2], int cnt); const int *npc_cn20k_search_order_get(bool *restricted_order); @@ -245,5 +256,8 @@ void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blk= addr, u16 index, void npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr, int bank, int index); int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type); +u16 npc_cn20k_vidx2idx(u16 index); +u16 npc_cn20k_idx2vidx(u16 idx); +int npc_cn20k_defrag(struct rvu *rvu); =20 #endif /* NPC_CN20K_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net= /ethernet/marvell/octeontx2/af/mbox.h index 34c960b84a65..05de319f5e51 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -297,6 +297,9 @@ M(NPC_CN20K_MCAM_READ_ENTRY, 0x6019, npc_cn20k_mcam_rea= d_entry, \ npc_cn20k_mcam_read_entry_rsp) \ M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601a, npc_cn20k_read_base_steer_rule, = \ msg_req, npc_cn20k_mcam_read_base_rule_rsp) \ +M(NPC_MCAM_DEFRAG, 0x601b, npc_defrag, \ + msg_req, \ + msg_rsp) \ /* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \ M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \ nix_lf_alloc_req, nix_lf_alloc_rsp) \ @@ -1553,6 +1556,7 @@ struct npc_mcam_alloc_entry_req { u16 ref_entry; u16 count; /* Number of entries requested */ u8 kw_type; /* entry key type, valid for cn20k */ + u8 virt; /* Request virtual index */ }; =20 struct npc_mcam_alloc_entry_rsp { @@ -1688,6 +1692,7 @@ struct npc_cn20k_mcam_alloc_and_write_entry_req { u8 intf; /* Rx or Tx interface */ u8 enable_entry;/* Enable this MCAM entry ? */ u8 hw_prio; /* hardware priority, valid for cn20k */ + u8 virt; /* Allocate virtual index */ u16 reserved[4]; /* reserved for future use */ }; =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/driv= ers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c index 0f9953eaf1b0..cc83d4fc5724 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c @@ -11,6 +11,7 @@ #include "rvu_reg.h" #include "rvu_struct.h" #include "rvu_npc_hash.h" +#include "cn20k/npc.h" =20 #define DRV_NAME "octeontx2-af" =20 @@ -1256,9 +1257,66 @@ enum rvu_af_dl_param_id { RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT, RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE, RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE, + RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG, RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF, }; =20 +static int rvu_af_npc_defrag_feature_get(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx, + struct netlink_ext_ack *extack) +{ + struct rvu_devlink *rvu_dl =3D devlink_priv(devlink); + struct rvu *rvu =3D rvu_dl->rvu; + bool enabled; + + enabled =3D is_cn20k(rvu->pdev); + + snprintf(ctx->val.vstr, sizeof(ctx->val.vstr), "%s", + enabled ? "enabled" : "disabled"); + + return 0; +} + +static int rvu_af_npc_defrag(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx, + struct netlink_ext_ack *extack) +{ + struct rvu_devlink *rvu_dl =3D devlink_priv(devlink); + struct rvu *rvu =3D rvu_dl->rvu; + + npc_cn20k_defrag(rvu); + + return 0; +} + +static int rvu_af_npc_defrag_feature_validate(struct devlink *devlink, u32= id, + union devlink_param_value val, + struct netlink_ext_ack *extack) +{ + struct rvu_devlink *rvu_dl =3D devlink_priv(devlink); + struct rvu *rvu =3D rvu_dl->rvu; + u64 enable; + + if (kstrtoull(val.vstr, 10, &enable)) { + NL_SET_ERR_MSG_MOD(extack, + "Only 1 value is supported"); + return -EINVAL; + } + + if (enable !=3D 1) { + NL_SET_ERR_MSG_MOD(extack, + "Only initiating defrag is supported"); + return -EINVAL; + } + + if (is_cn20k(rvu->pdev)) + return 0; + + NL_SET_ERR_MSG_MOD(extack, + "Can defrag NPC only in cn20k silicon"); + return -EFAULT; +} + static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id, struct devlink_param_gset_ctx *ctx, struct netlink_ext_ack *extack) @@ -1561,6 +1619,15 @@ static const struct devlink_ops rvu_devlink_ops =3D { .eswitch_mode_set =3D rvu_devlink_eswitch_mode_set, }; =20 +static const struct devlink_param rvu_af_dl_param_defrag[] =3D { + DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG, + "npc_defrag", DEVLINK_PARAM_TYPE_STRING, + BIT(DEVLINK_PARAM_CMODE_RUNTIME), + rvu_af_npc_defrag_feature_get, + rvu_af_npc_defrag, + rvu_af_npc_defrag_feature_validate), +}; + int rvu_register_dl(struct rvu *rvu) { struct rvu_devlink *rvu_dl; @@ -1593,6 +1660,17 @@ int rvu_register_dl(struct rvu *rvu) goto err_dl_health; } =20 + if (is_cn20k(rvu->pdev)) { + err =3D devlink_params_register(dl, rvu_af_dl_param_defrag, + ARRAY_SIZE(rvu_af_dl_param_defrag)); + if (err) { + dev_err(rvu->dev, + "devlink defrag params register failed with error %d", + err); + goto err_dl_exact_match; + } + } + /* Register exact match devlink only for CN10K-B */ if (!rvu_npc_exact_has_match_table(rvu)) goto done; @@ -1601,7 +1679,8 @@ int rvu_register_dl(struct rvu *rvu) ARRAY_SIZE(rvu_af_dl_param_exact_match)); if (err) { dev_err(rvu->dev, - "devlink exact match params register failed with error %d", err); + "devlink exact match params register failed with error %d", + err); goto err_dl_exact_match; } =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.c index fdc6792df7bb..d36291abcbc0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -2454,7 +2454,7 @@ static void npc_unmap_mcam_entry_and_cntr(struct rvu = *rvu, * reverse bitmap too. Should be called with * 'mcam->lock' held. */ -static void npc_mcam_set_bit(struct npc_mcam *mcam, u16 index) +void npc_mcam_set_bit(struct npc_mcam *mcam, u16 index) { u16 entry, rentry; =20 @@ -2470,7 +2470,7 @@ static void npc_mcam_set_bit(struct npc_mcam *mcam, u= 16 index) * reverse bitmap too. Should be called with * 'mcam->lock' held. */ -static void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index) +void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index) { u16 entry, rentry; =20 @@ -2689,7 +2689,7 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mc= am, u16 pcifunc, ret =3D npc_cn20k_ref_idx_alloc(rvu, pcifunc, req->kw_type, req->ref_prio, rsp->entry_list, req->ref_entry, limit, - req->contig, req->count); + req->contig, req->count, !!req->virt); =20 if (ret) { rsp->count =3D 0; @@ -2709,7 +2709,7 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mc= am, u16 pcifunc, mutex_lock(&mcam->lock); /* Mark the allocated entries as used and set nixlf mapping */ for (entry =3D 0; entry < rsp->count; entry++) { - index =3D rsp->entry_list[entry]; + index =3D npc_cn20k_vidx2idx(rsp->entry_list[entry]); npc_mcam_set_bit(mcam, index); mcam->entry2pfvf_map[index] =3D pcifunc; mcam->entry2cntr_map[index] =3D NPC_MCAM_INVALID_MAP; @@ -3021,6 +3021,8 @@ int rvu_mbox_handler_npc_mcam_free_entry(struct rvu *= rvu, int blkaddr, rc =3D 0; u16 cntr; =20 + req->entry =3D npc_cn20k_vidx2idx(req->entry); + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; @@ -3151,6 +3153,8 @@ int rvu_mbox_handler_npc_mcam_ena_entry(struct rvu *r= vu, u16 pcifunc =3D req->hdr.pcifunc; int blkaddr, rc; =20 + req->entry =3D npc_cn20k_vidx2idx(req->entry); + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; @@ -3174,6 +3178,8 @@ int rvu_mbox_handler_npc_mcam_dis_entry(struct rvu *r= vu, u16 pcifunc =3D req->hdr.pcifunc; int blkaddr, rc; =20 + req->entry =3D npc_cn20k_vidx2idx(req->entry); + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; @@ -3208,8 +3214,8 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu = *rvu, =20 mutex_lock(&mcam->lock); for (index =3D 0; index < req->shift_count; index++) { - old_entry =3D req->curr_entry[index]; - new_entry =3D req->new_entry[index]; + old_entry =3D npc_cn20k_vidx2idx(req->curr_entry[index]); + new_entry =3D npc_cn20k_vidx2idx(req->new_entry[index]); =20 /* Check if both old and new entries are valid and * does belong to this PFFUNC or not. @@ -3251,7 +3257,7 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu = *rvu, /* If shift has failed then report the failed index */ if (index !=3D req->shift_count) { rc =3D NPC_MCAM_PERM_DENIED; - rsp->failed_entry_idx =3D index; + rsp->failed_entry_idx =3D npc_cn20k_idx2vidx(index); } =20 mutex_unlock(&mcam->lock); @@ -3831,6 +3837,8 @@ int rvu_mbox_handler_npc_mcam_entry_stats(struct rvu = *rvu, if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; =20 + req->entry =3D npc_cn20k_vidx2idx(req->entry); + index =3D req->entry & (mcam->banksize - 1); bank =3D npc_get_bank(mcam, req->entry); =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.h index 346e6ada158e..83c5e32e2afc 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h @@ -16,4 +16,6 @@ void npc_config_kpuaction(struct rvu *rvu, int blkaddr, int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr, u64 *size); =20 +void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index); +void npc_mcam_set_bit(struct npc_mcam *mcam, u16 index); #endif /* RVU_NPC_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drive= rs/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c index 20e98acad561..b6d9ff67f05a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -1633,6 +1633,8 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, bool enable =3D true; u16 target; =20 + req->entry =3D npc_cn20k_vidx2idx(req->entry); + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) { dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__); @@ -1786,6 +1788,10 @@ int rvu_mbox_handler_npc_delete_flow(struct rvu *rvu, struct list_head del_list; int blkaddr; =20 + req->entry =3D npc_cn20k_vidx2idx(req->entry); + req->start =3D npc_cn20k_vidx2idx(req->start); + req->end =3D npc_cn20k_vidx2idx(req->end); + INIT_LIST_HEAD(&del_list); =20 mutex_lock(&mcam->lock); --=20 2.43.0