From nobody Wed Jan 7 22:50:11 2026 Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (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 BFCF62D7DD3; Mon, 5 Jan 2026 02:33:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580431; cv=none; b=TM1qWeeN5iaRjWP6LJEodtuOP/Y/RXuWl0Es18zQ9hFjFM5NNqgFVD1hQ+1EvtkXAfsxnarPlrgtMeeBinOHnArWz+leZA1VjZhTxhhAy/F5f3Yf5uGbFQ6Ny1n/hL+JDEyFB/9xQyW2//6I61bVIhVHtbJg0kAC0xt/VvYpIdA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580431; c=relaxed/simple; bh=BJ/j+hnqBD6a8no0a29mTxv9DzXvnGXZ3RXyVeav1qo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mXJ7mN3ddnZWVf7dUXIi2+mxMR2HFT8btdpvrBfvb6eSssVowRU1A5+k2iEURukZNZcMDrDZmThcmw1K2F9PKpir9EwRzvMN+esXdKqBnl2VvWR8Z2zT37yVbw/+Fd3sRrzEJVAuA8K6AhJmnYPooeDQAR7a5U9iK2mKyE2MbgA= 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=SJbN4ifx; arc=none smtp.client-ip=67.231.156.173 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="SJbN4ifx" Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604NGBXR1142874; Sun, 4 Jan 2026 18:33:24 -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=R kYfDaPJL45G49d2cIcZR9LoJje8agz5Go8Omjeax8Q=; b=SJbN4ifxOk3Z1cS67 wf3GQmHoox0P14G75AmTrm+WfyCjifAS/PpFd+Cmpq367IHJt3RfF1U6/bmyA3j1 0PnLZmBk1m7tddf7AfcHjDPBJ2CeKaw+XmoeFt1rVNscN0V/GzjjGvXPo8Jo9ral 7Fr+iFf1fYUGZGjZeGIh4ALyI3XPE4pqNRbKujKg08xAoA70dQYc1FBPso1+qXfr zZAwNvHf8bGYgjqimiHTjZkcTWSVjdkkO44SiNTXWnuzKMbMD+rcM/V/SV8pGukQ RWZj+XAoUAbpw6Jd3JrgMqq77mx1Pf8ofkrtyGe6CgXSdudb0M86qPUxjrPxx2gI yUq0A== Received: from dc6wp-exch02.marvell.com ([4.21.29.225]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 4bf3gmj00c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:24 -0800 (PST) Received: from DC6WP-EXCH02.marvell.com (10.76.176.209) by DC6WP-EXCH02.marvell.com (10.76.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:33:23 -0800 Received: from maili.marvell.com (10.69.176.80) by DC6WP-EXCH02.marvell.com (10.76.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:33:23 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id 24C123F7094; Sun, 4 Jan 2026 18:33:19 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 01/13] octeontx2-af: npc: cn20k: Index management Date: Mon, 5 Jan 2026 08:02:42 +0530 Message-ID: <20260105023254.1426488-2-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: nSy4rEt7fbwfdcPO2ZE0Cq28IlFtmUO5 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfXwhg6n4O8wbw4 BpqG6cpEn8Lh8eYY5Xkw1uXlACStP3KMCuqS8kW7yD5Ttycr+LzF/LB/OJySaue7eWePLw54Ygr GT0UaKmJkyXKS04Foa0VNAu03g/4l4KXlZtKLaJG+4FWP4q02kMFmwWmI446Q7/Vsfid6uCY8T/ 1wn1TrlGjb8ZasvDyMMke+f52sw+8IR6Zt3uEbdca/9GQEiNrqn5OzfMIb38HIIvrB9/AOJgX32 hnRvF6o1Z51vEhzuEzjxdN9sh2hrdq7rcr01UNmqOEwHL7aIXquieNaASWrUoRNfbhBcgt5COqi lqV21zPDdADgLDjMwG+SPyvKI9WVgclHu6RCvCKQSdr8znqhituiJlYmXwEm5BeWOU1WM/oe/zJ q7zNb0bl78q3H/IbrSo/6mAGAS2WkwsbwwMN9z1FNzB5+jPSSJM02ztDviHZmKSBR1wJuJ9d9qL Mghd25RRE8OHfvUKukQ== X-Authority-Analysis: v=2.4 cv=PcXyRyhd c=1 sm=1 tr=0 ts=695b22f4 cx=c_pps a=gIfcoYsirJbf48DBMSPrZA==:117 a=gIfcoYsirJbf48DBMSPrZA==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=VwQbUJbxAAAA:8 a=5tOJgOsZKvMPXqkQsBUA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-GUID: nSy4rEt7fbwfdcPO2ZE0Cq28IlFtmUO5 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" In CN20K silicon, the MCAM is divided vertically into two banks. Each bank has a depth of 8192. The MCAM is divided horizontally into 32 subbanks, with each subbank having a depth of 256. Each subbank can accommodate either x2 keys or x4 keys. x2 keys are 256 bits in size, and x4 keys are 512 bits in size. Bank1 Bank0 |-----------------------------| | | | subbank 31 { depth 256 } | | | |-----------------------------| | | | subbank 30 | | | ------------------------------ ............................... |-----------------------------| | | | subbank 0 | | | ------------------------------| This patch implements the following allocation schemes in NPC. The allocation API accepts reference (ref), limit, contig, priority, and count values. For example, specifying ref=3D100, limit=3D200, contig=3D1, priority=3DLOW, and count=3D20 will allocate 20 contiguous MCAM entries between entries 100 and 200. 1. Contiguous allocation with ref, limit, and priority. 2. Non-contiguous allocation with ref, limit, and priority. 3. Non-contiguous allocation without ref. 4. Contiguous allocation without ref. Signed-off-by: Ratheesh Kannoth --- MAINTAINERS | 2 +- .../ethernet/marvell/octeontx2/af/Makefile | 2 +- .../marvell/octeontx2/af/cn20k/debugfs.c | 182 ++ .../marvell/octeontx2/af/cn20k/debugfs.h | 3 + .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 1798 +++++++++++++++++ .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 65 + .../ethernet/marvell/octeontx2/af/cn20k/reg.h | 3 + .../ethernet/marvell/octeontx2/af/common.h | 4 - .../net/ethernet/marvell/octeontx2/af/mbox.h | 18 + .../marvell/octeontx2/af/rvu_debugfs.c | 3 + .../ethernet/marvell/octeontx2/af/rvu_npc.c | 8 +- 11 files changed, 2081 insertions(+), 7 deletions(-) create mode 100644 drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c create mode 100644 drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h diff --git a/MAINTAINERS b/MAINTAINERS index 454b8ed119e9..0111506e8fe4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15304,7 +15304,7 @@ M: Subbaraya Sundeep L: netdev@vger.kernel.org S: Maintained F: Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst -F: drivers/net/ethernet/marvell/octeontx2/af/ +F: drivers/net/ethernet/marvell/octeontx2/af/* =20 MARVELL PEM PMU DRIVER M: Linu Cherian diff --git a/drivers/net/ethernet/marvell/octeontx2/af/Makefile b/drivers/n= et/ethernet/marvell/octeontx2/af/Makefile index 244de500963e..91b7d6e96a61 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/Makefile +++ b/drivers/net/ethernet/marvell/octeontx2/af/Makefile @@ -13,4 +13,4 @@ rvu_af-y :=3D cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.o \ rvu_cpt.o rvu_devlink.o rpm.o rvu_cn10k.o rvu_switch.o \ rvu_sdp.o rvu_npc_hash.o mcs.o mcs_rvu_if.o mcs_cnf10kb.o \ rvu_rep.o cn20k/mbox_init.o cn20k/nix.o cn20k/debugfs.o \ - cn20k/npa.o + cn20k/npa.o cn20k/npc.o diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c b/dr= ivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c index 498968bf4cf5..c7c59a98d969 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c @@ -11,7 +11,189 @@ #include =20 #include "struct.h" +#include "rvu.h" #include "debugfs.h" +#include "cn20k/npc.h" + +static void npc_subbank_srch_order_dbgfs_usage(void) +{ + pr_err("Usage: echo \"[0]=3D[8],[1]=3D7,[2]=3D30,...[31]=3D0\" > /subbank_srch_order\n"); +} + +static int +npc_subbank_srch_order_parse_n_fill(struct rvu *rvu, char *options, + int num_subbanks) +{ + unsigned long w1 =3D 0, w2 =3D 0; + char *p, *t1, *t2; + int (*arr)[2]; + int idx, val; + int cnt, ret; + + cnt =3D 0; + + options[strcspn(options, "\r\n")] =3D 0; + + arr =3D kcalloc(num_subbanks, sizeof(*arr), GFP_KERNEL); + if (!arr) + return -ENOMEM; + + while ((p =3D strsep(&options, " ,")) !=3D NULL) { + if (!*p) + continue; + + t1 =3D strsep(&p, "=3D"); + t2 =3D strsep(&p, ""); + + if (strlen(t1) < 3) { + pr_err("%s:%d Bad Token %s=3D%s\n", + __func__, __LINE__, t1, t2); + goto err; + } + + if (t1[0] !=3D '[' || t1[strlen(t1) - 1] !=3D ']') { + pr_err("%s:%d Bad Token %s=3D%s\n", + __func__, __LINE__, t1, t2); + goto err; + } + + t1[0] =3D ' '; + t1[strlen(t1) - 1] =3D ' '; + t1 =3D strim(t1); + + ret =3D kstrtoint(t1, 10, &idx); + if (ret) { + pr_err("%s:%d Bad Token %s=3D%s\n", + __func__, __LINE__, t1, t2); + goto err; + } + + ret =3D kstrtoint(t2, 10, &val); + if (ret) { + pr_err("%s:%d Bad Token %s=3D%s\n", + __func__, __LINE__, t1, t2); + goto err; + } + + (*(arr + cnt))[0] =3D idx; + (*(arr + cnt))[1] =3D val; + + cnt++; + } + + if (cnt !=3D num_subbanks) { + pr_err("Could find %u tokens, but exact %u tokens needed\n", + cnt, num_subbanks); + goto err; + } + + for (int i =3D 0; i < cnt; i++) { + w1 |=3D BIT_ULL((*(arr + i))[0]); + w2 |=3D BIT_ULL((*(arr + i))[1]); + } + + if (bitmap_weight(&w1, cnt) !=3D cnt) { + pr_err("Missed to fill for [%lu]=3D\n", + find_first_zero_bit(&w1, cnt)); + goto err; + } + + if (bitmap_weight(&w2, cnt) !=3D cnt) { + pr_err("Missed to fill value %lu\n", + find_first_zero_bit(&w2, cnt)); + goto err; + } + + npc_cn20k_search_order_set(rvu, arr, cnt); + + kfree(arr); + return 0; +err: + kfree(arr); + return -EINVAL; +} + +static ssize_t +npc_subbank_srch_order_write(struct file *file, const char __user *user_bu= f, + size_t count, loff_t *ppos) +{ + struct npc_priv_t *npc_priv; + struct rvu *rvu; + char buf[1024]; + int len; + + npc_priv =3D npc_priv_get(); + + rvu =3D file->private_data; + + len =3D simple_write_to_buffer(buf, sizeof(buf), ppos, + user_buf, count); + if (npc_subbank_srch_order_parse_n_fill(rvu, buf, + npc_priv->num_subbanks)) { + npc_subbank_srch_order_dbgfs_usage(); + return -EFAULT; + } + + return len; +} + +static ssize_t +npc_subbank_srch_order_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct npc_priv_t *npc_priv; + bool restricted_order; + const int *srch_order; + char buf[1024]; + int len =3D 0; + + npc_priv =3D npc_priv_get(); + + len +=3D snprintf(buf + len, sizeof(buf) - len, "%s", + "Usage: echo \"[0]=3D0,[1]=3D1,[2]=3D2,..[31]=3D31\" > /subban= k_srch_order\n"); + + len +=3D snprintf(buf + len, sizeof(buf) - len, "%s", + "Search order\n"); + + srch_order =3D npc_cn20k_search_order_get(&restricted_order); + + for (int i =3D 0; i < npc_priv->num_subbanks; i++) + len +=3D snprintf(buf + len, sizeof(buf) - len, "[%d]=3D%d,", + i, srch_order[i]); + + len +=3D snprintf(buf + len - 1, sizeof(buf) - len, "%s", "\n"); + + if (restricted_order) + len +=3D snprintf(buf + len, sizeof(buf) - len, + "Restricted allocation for subbanks %u, %u\n", + npc_priv->num_subbanks - 1, 0); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations npc_subbank_srch_order_ops =3D { + .open =3D simple_open, + .write =3D npc_subbank_srch_order_write, + .read =3D npc_subbank_srch_order_read, +}; + +int npc_cn20k_debugfs_init(struct rvu *rvu) +{ + struct dentry *npc_dentry; + + npc_dentry =3D debugfs_create_file("subbank_srch_order", 0644, + rvu->rvu_dbg.npc, + rvu, &npc_subbank_srch_order_ops); + if (!npc_dentry) + return -EFAULT; + + return 0; +} + +void npc_cn20k_debugfs_deinit(struct rvu *rvu) +{ + debugfs_remove_recursive(rvu->rvu_dbg.npc); +} =20 void print_nix_cn20k_sq_ctx(struct seq_file *m, struct nix_cn20k_sq_ctx_s *sq_ctx) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.h b/dr= ivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.h index a2e3a2cd6edb..0c5f05883666 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.h @@ -16,6 +16,9 @@ #include "struct.h" #include "../mbox.h" =20 +int npc_cn20k_debugfs_init(struct rvu *rvu); +void npc_cn20k_debugfs_deinit(struct rvu *rvu); + void print_nix_cn20k_sq_ctx(struct seq_file *m, struct nix_cn20k_sq_ctx_s *sq_ctx); void print_nix_cn20k_cq_ctx(struct seq_file *m, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.c new file mode 100644 index 000000000000..27b049ac4ae8 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -0,0 +1,1798 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Marvell RVU Admin Function driver + * + * Copyright (C) 2026 Marvell. + * + */ +#include +#include + +#include "cn20k/npc.h" +#include "cn20k/reg.h" + +static struct npc_priv_t npc_priv =3D { + .num_banks =3D MAX_NUM_BANKS, +}; + +static const char *npc_kw_name[NPC_MCAM_KEY_MAX] =3D { + [NPC_MCAM_KEY_DYN] =3D "DYNAMIC", + [NPC_MCAM_KEY_X2] =3D "X2", + [NPC_MCAM_KEY_X4] =3D "X4", +}; + +struct npc_priv_t *npc_priv_get(void) +{ + return &npc_priv; +} + +static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank = *sb, + u16 sub_off, u16 *mcam_idx) +{ + int off, bot; + + /* for x4 section, maximum allowed subbank index =3D + * subsection depth - 1 + */ + if (sb->key_type =3D=3D NPC_MCAM_KEY_X4 && + sub_off >=3D npc_priv.subbank_depth) { + dev_err(rvu->dev, "%s:%d bad params\n", + __func__, __LINE__); + return -EINVAL; + } + + /* for x2 section, maximum allowed subbank index =3D + * 2 * subsection depth - 1 + */ + if (sb->key_type =3D=3D NPC_MCAM_KEY_X2 && + sub_off >=3D npc_priv.subbank_depth * 2) { + dev_err(rvu->dev, "%s:%d bad params\n", + __func__, __LINE__); + return -EINVAL; + } + + /* Find subbank offset from respective subbank (w.r.t bank) */ + off =3D sub_off & (npc_priv.subbank_depth - 1); + + /* if subsection idx is in bank1, add bank depth, + * which is part of sb->b1b + */ + bot =3D sub_off >=3D npc_priv.subbank_depth ? sb->b1b : sb->b0b; + + *mcam_idx =3D bot + off; + return 0; +} + +static int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx, + struct npc_subbank **sb, + int *sb_off) +{ + int bank_off, sb_id; + + /* mcam_idx should be less than (2 * bank depth) */ + if (mcam_idx >=3D npc_priv.bank_depth * 2) { + dev_err(rvu->dev, "%s:%d bad params\n", + __func__, __LINE__); + return -EINVAL; + } + + /* find mcam offset per bank */ + bank_off =3D mcam_idx & (npc_priv.bank_depth - 1); + + /* Find subbank id */ + sb_id =3D bank_off / npc_priv.subbank_depth; + + /* Check if subbank id is more than maximum + * number of subbanks available + */ + if (sb_id >=3D npc_priv.num_subbanks) { + dev_err(rvu->dev, "%s:%d invalid subbank %d\n", + __func__, __LINE__, sb_id); + return -EINVAL; + } + + *sb =3D &npc_priv.sb[sb_id]; + + /* Subbank offset per bank */ + *sb_off =3D bank_off % npc_priv.subbank_depth; + + /* Index in a subbank should add subbank depth + * if it is in bank1 + */ + if (mcam_idx >=3D npc_priv.bank_depth) + *sb_off +=3D npc_priv.subbank_depth; + + return 0; +} + +static int __npc_subbank_contig_alloc(struct rvu *rvu, + struct npc_subbank *sb, + int key_type, int sidx, + int eidx, int prio, + int count, int t, int b, + unsigned long *bmap, + u16 *save) +{ + int k, offset, delta =3D 0; + int cnt =3D 0, sbd; + + sbd =3D npc_priv.subbank_depth; + + if (sidx >=3D npc_priv.bank_depth) + delta =3D sbd; + + switch (prio) { + case NPC_MCAM_LOWER_PRIO: + case NPC_MCAM_ANY_PRIO: + /* Find an area of size 'count' from sidx to eidx */ + offset =3D bitmap_find_next_zero_area(bmap, sbd, sidx - b, + count, 0); + + if (offset >=3D sbd) { + dev_err(rvu->dev, + "%s:%d Could not find contiguous(%d) entries\n", + __func__, __LINE__, count); + return -EFAULT; + } + + dev_dbg(rvu->dev, + "%s:%d sidx=3D%d eidx=3D%d t=3D%d b=3D%d offset=3D%d count=3D%d delta= =3D%d\n", + __func__, __LINE__, sidx, eidx, t, b, offset, + count, delta); + + for (cnt =3D 0; cnt < count; cnt++) + save[cnt] =3D offset + cnt + delta; + + break; + + case NPC_MCAM_HIGHER_PRIO: + /* Find an area of 'count' from eidx to sidx */ + for (k =3D eidx - b; cnt < count && k >=3D (sidx - b); k--) { + /* If an intermediate slot is not free, + * reset the counter (cnt) to zero as + * request is for contiguous. + */ + if (test_bit(k, bmap)) { + cnt =3D 0; + continue; + } + + save[cnt++] =3D k + delta; + } + break; + } + + /* Found 'count' number of free slots */ + if (cnt =3D=3D count) + return 0; + + dev_dbg(rvu->dev, + "%s:%d Could not find contiguous(%d) entries in subbbank=3D%u\n", + __func__, __LINE__, count, sb->idx); + return -EFAULT; +} + +static int __npc_subbank_non_contig_alloc(struct rvu *rvu, + struct npc_subbank *sb, + int key_type, int sidx, + int eidx, int prio, + int t, int b, + unsigned long *bmap, + int count, u16 *save, + bool max_alloc, int *alloc_cnt) +{ + unsigned long index; + int cnt =3D 0, delta; + int k, sbd; + + sbd =3D npc_priv.subbank_depth; + delta =3D sidx >=3D npc_priv.bank_depth ? sbd : 0; + + switch (prio) { + /* Find an area of size 'count' from sidx to eidx */ + case NPC_MCAM_LOWER_PRIO: + case NPC_MCAM_ANY_PRIO: + index =3D find_next_zero_bit(bmap, sbd, sidx - b); + if (index >=3D sbd) { + dev_err(rvu->dev, + "%s:%d Error happened to alloc %u, bitmap_weight=3D%u, sb->idx=3D%u\n", + __func__, __LINE__, count, + bitmap_weight(bmap, sbd), + sb->idx); + break; + } + + for (k =3D index; cnt < count && k <=3D (eidx - b); k++) { + /* Skip used slots */ + if (test_bit(k, bmap)) + continue; + + save[cnt++] =3D k + delta; + } + break; + + /* Find an area of 'count' from eidx to sidx */ + case NPC_MCAM_HIGHER_PRIO: + for (k =3D eidx - b; cnt < count && k >=3D (sidx - b); k--) { + /* Skip used slots */ + if (test_bit(k, bmap)) + continue; + + save[cnt++] =3D k + delta; + } + break; + } + + /* Update allocated 'cnt' to alloc_cnt */ + *alloc_cnt =3D cnt; + + /* Successfully allocated requested count slots */ + if (cnt =3D=3D count) + return 0; + + /* Allocation successful for cnt < count */ + if (max_alloc && cnt > 0) + return 0; + + dev_dbg(rvu->dev, + "%s:%d Could not find non contiguous entries(%u) in subbank(%u) cnt=3D%d= max_alloc=3D%d\n", + __func__, __LINE__, count, sb->idx, cnt, max_alloc); + + return -EFAULT; +} + +static void __npc_subbank_sboff_2_off(struct rvu *rvu, struct npc_subbank = *sb, + int sb_off, unsigned long **bmap, + int *off) +{ + int sbd; + + sbd =3D npc_priv.subbank_depth; + + *off =3D sb_off & (sbd - 1); + *bmap =3D (sb_off >=3D sbd) ? sb->b1map : sb->b0map; +} + +/* set/clear bitmap */ +static bool __npc_subbank_mark_slot(struct rvu *rvu, + struct npc_subbank *sb, + int sb_off, bool set) +{ + unsigned long *bmap; + int off; + + /* if sb_off >=3D subbank.depth, then slots are in + * bank1 + */ + __npc_subbank_sboff_2_off(rvu, sb, sb_off, &bmap, &off); + + dev_dbg(rvu->dev, + "%s:%d Marking set=3D%d sb_off=3D%d sb->idx=3D%d off=3D%d\n", + __func__, __LINE__, set, sb_off, sb->idx, off); + + if (set) { + /* Slot is already used */ + if (test_bit(off, bmap)) + return false; + + sb->free_cnt--; + set_bit(off, bmap); + return true; + } + + /* Slot is already free */ + if (!test_bit(off, bmap)) + return false; + + sb->free_cnt++; + clear_bit(off, bmap); + return true; +} + +static int __npc_subbank_mark_free(struct rvu *rvu, struct npc_subbank *sb) +{ + int rc, blkaddr; + void *val; + + sb->flags =3D NPC_SUBBANK_FLAG_FREE; + sb->key_type =3D 0; + + bitmap_clear(sb->b0map, 0, npc_priv.subbank_depth); + bitmap_clear(sb->b1map, 0, npc_priv.subbank_depth); + + if (!xa_erase(&npc_priv.xa_sb_used, sb->arr_idx)) { + dev_err(rvu->dev, "%s:%d Error to delete from xa_sb_used array\n", + __func__, __LINE__); + return -EFAULT; + } + + rc =3D xa_insert(&npc_priv.xa_sb_free, sb->arr_idx, + xa_mk_value(sb->idx), GFP_KERNEL); + if (rc) { + val =3D xa_load(&npc_priv.xa_sb_free, sb->arr_idx); + dev_err(rvu->dev, + "%s:%d Error to add sb(%u) to xa_sb_free array at arr_idx=3D%d, val=3D%= lu\n", + __func__, __LINE__, + sb->idx, sb->arr_idx, xa_to_value(val)); + } + + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + rvu_write64(rvu, blkaddr, + NPC_AF_MCAM_SECTIONX_CFG_EXT(sb->idx), + NPC_MCAM_KEY_X2); + + return rc; +} + +static int __npc_subbank_mark_used(struct rvu *rvu, struct npc_subbank *sb, + int key_type) + +{ + int rc; + + sb->flags =3D NPC_SUBBANK_FLAG_USED; + sb->key_type =3D key_type; + if (key_type =3D=3D NPC_MCAM_KEY_X4) + sb->free_cnt =3D npc_priv.subbank_depth; + else + sb->free_cnt =3D 2 * npc_priv.subbank_depth; + + bitmap_clear(sb->b0map, 0, npc_priv.subbank_depth); + bitmap_clear(sb->b1map, 0, npc_priv.subbank_depth); + + if (!xa_erase(&npc_priv.xa_sb_free, sb->arr_idx)) { + dev_err(rvu->dev, "%s:%d Error to delete from xa_sb_free array\n", + __func__, __LINE__); + return -EFAULT; + } + + rc =3D xa_insert(&npc_priv.xa_sb_used, sb->arr_idx, + xa_mk_value(sb->idx), GFP_KERNEL); + if (rc) + dev_err(rvu->dev, "%s:%d Error to add to xa_sb_used array\n", + __func__, __LINE__); + + return rc; +} + +static bool __npc_subbank_free(struct rvu *rvu, struct npc_subbank *sb, + u16 sb_off) +{ + bool deleted =3D false; + unsigned long *bmap; + int rc, off; + + deleted =3D __npc_subbank_mark_slot(rvu, sb, sb_off, false); + if (!deleted) + goto done; + + __npc_subbank_sboff_2_off(rvu, sb, sb_off, &bmap, &off); + + /* Check whether we can mark whole subbank as free */ + if (sb->key_type =3D=3D NPC_MCAM_KEY_X4) { + if (sb->free_cnt < npc_priv.subbank_depth) + goto done; + } else { + if (sb->free_cnt < 2 * npc_priv.subbank_depth) + goto done; + } + + /* All slots in subbank are unused. Mark the subbank as free + * and add to free pool + */ + rc =3D __npc_subbank_mark_free(rvu, sb); + if (rc) + dev_err(rvu->dev, "%s:%d Error to free subbank\n", + __func__, __LINE__); + +done: + return deleted; +} + +static int __maybe_unused +npc_subbank_free(struct rvu *rvu, struct npc_subbank *sb, u16 sb_off) +{ + bool deleted; + + mutex_lock(&sb->lock); + deleted =3D __npc_subbank_free(rvu, sb, sb_off); + mutex_unlock(&sb->lock); + + return deleted ? 0 : -EFAULT; +} + +static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb, + int key_type, int ref, int limit, int prio, + bool contig, int count, u16 *mcam_idx, + int idx_sz, bool max_alloc, int *alloc_cnt) +{ + int cnt, t, b, i, blkaddr; + bool new_sub_bank =3D false; + unsigned long *bmap; + u16 *save =3D NULL; + int sidx, eidx; + bool diffbank; + int bw, bfree; + int rc =3D 0; + bool ret; + + /* Check if enough space is there to return requested number of + * mcam indexes in case of contiguous allocation + */ + if (!max_alloc && count > idx_sz) { + dev_err(rvu->dev, + "%s:%d Less space, count=3D%d idx_sz=3D%d sb_id=3D%d\n", + __func__, __LINE__, count, idx_sz, sb->idx); + return -ENOSPC; + } + + /* Allocation on multiple subbank is not supported by this function. + * it means that ref and limit should be on same subbank. + * + * ref and limit values should be validated w.r.t prio as below. + * say ref =3D 100, limit =3D 200, + * if NPC_MCAM_LOWER_PRIO, allocate index 100 + * if NPC_MCAM_HIGHER_PRIO, below sanity test returns error. + * if NPC_MCAM_ANY_PRIO, allocate index 100 + * + * say ref =3D 200, limit =3D 100 + * if NPC_MCAM_LOWER_PRIO, below sanity test returns error. + * if NPC_MCAM_HIGHER_PRIO, allocate index 200 + * if NPC_MCAM_ANY_PRIO, allocate index 100 + * + * Please note that NPC_MCAM_ANY_PRIO does not have any restriction + * on "ref" and "limit" values. ie, ref > limit and limit > ref + * are valid cases. + */ + if ((prio =3D=3D NPC_MCAM_LOWER_PRIO && ref > limit) || + (prio =3D=3D NPC_MCAM_HIGHER_PRIO && ref < limit)) { + dev_err(rvu->dev, "%s:%d Wrong ref_enty(%d) or limit(%d)\n", + __func__, __LINE__, ref, limit); + return -EINVAL; + } + + /* x4 indexes are from 0 to bank size as it combines two x2 banks */ + if (key_type =3D=3D NPC_MCAM_KEY_X4 && + (ref >=3D npc_priv.bank_depth || limit >=3D npc_priv.bank_depth)) { + dev_err(rvu->dev, "%s:%d Wrong ref_enty(%d) or limit(%d) for x4\n", + __func__, __LINE__, ref, limit); + return -EINVAL; + } + + /* This function is called either bank0 or bank1 portion of a subbank. + * so ref and limit should be on same bank. + */ + diffbank =3D !!((ref & npc_priv.bank_depth) ^ + (limit & npc_priv.bank_depth)); + if (diffbank) { + dev_err(rvu->dev, "%s:%d request ref and limit should be from same bank\= n", + __func__, __LINE__); + return -EINVAL; + } + + sidx =3D min_t(int, limit, ref); + eidx =3D max_t(int, limit, ref); + + /* Find total number of slots available; both used and free */ + cnt =3D eidx - sidx + 1; + if (contig && cnt < count) { + dev_err(rvu->dev, "%s:%d Wrong ref_enty(%d) or limit(%d) for count(%d)\n= ", + __func__, __LINE__, ref, limit, count); + return -EINVAL; + } + + /* If subbank is free, check if requested number of indexes is less than + * or equal to mcam entries available in the subbank if contig. + */ + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { + if (contig && count > npc_priv.subbank_depth) { + dev_err(rvu->dev, "%s:%d Less number of entries\n", + __func__, __LINE__); + goto err; + } + + new_sub_bank =3D true; + goto process; + } + + /* Flag should be set for all used subbanks */ + WARN_ONCE(!(sb->flags & NPC_SUBBANK_FLAG_USED), + "Used flag is not set(%#x)\n", sb->flags); + + /* If subbank key type does not match with requested key_type, + * return error + */ + if (sb->key_type !=3D key_type) { + dev_dbg(rvu->dev, "%s:%d subbank key_type mismatch\n", + __func__, __LINE__); + rc =3D -EINVAL; + goto err; + } + +process: + /* if ref or limit >=3D npc_priv.bank_depth, index are in bank1. + * else bank0. + */ + if (ref >=3D npc_priv.bank_depth) { + bmap =3D sb->b1map; + t =3D sb->b1t; + b =3D sb->b1b; + } else { + bmap =3D sb->b0map; + t =3D sb->b0t; + b =3D sb->b0b; + } + + /* Calculate free slots */ + bw =3D bitmap_weight(bmap, npc_priv.subbank_depth); + bfree =3D npc_priv.subbank_depth - bw; + + if (!bfree) { + rc =3D -ENOSPC; + goto err; + } + + /* If request is for contiguous , then max we can allocate is + * equal to subbank_depth + */ + if (contig && bfree < count) { + rc =3D -ENOSPC; + dev_err(rvu->dev, "%s:%d no space for entry\n", + __func__, __LINE__); + goto err; + } + + /* 'save' array stores available indexes temporarily before + * marking it as allocated + */ + save =3D kcalloc(count, sizeof(u16), GFP_KERNEL); + if (!save) { + rc =3D -ENOMEM; + goto err; + } + + if (contig) { + rc =3D __npc_subbank_contig_alloc(rvu, sb, key_type, + sidx, eidx, prio, + count, t, b, + bmap, save); + /* contiguous allocation success means that + * requested number of free slots got + * allocated + */ + if (!rc) + *alloc_cnt =3D count; + + } else { + rc =3D __npc_subbank_non_contig_alloc(rvu, sb, key_type, + sidx, eidx, prio, + t, b, bmap, + count, save, + max_alloc, alloc_cnt); + } + + if (rc) + goto err; + + /* Mark new subbank bank as used */ + if (new_sub_bank) { + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (blkaddr < 0) { + dev_err(rvu->dev, + "%s:%d NPC block not implemented\n", + __func__, __LINE__); + goto err; + } + + rc =3D __npc_subbank_mark_used(rvu, sb, key_type); + if (rc) { + dev_err(rvu->dev, "%s:%d Error to mark subbank as used\n", + __func__, __LINE__); + goto err; + } + + /* Configure section type to key_type */ + rvu_write64(rvu, blkaddr, + NPC_AF_MCAM_SECTIONX_CFG_EXT(sb->idx), + key_type); + } + + for (i =3D 0; i < *alloc_cnt; i++) { + rc =3D npc_subbank_idx_2_mcam_idx(rvu, sb, save[i], &mcam_idx[i]); + if (rc) { + dev_err(rvu->dev, "%s:%d Error to find mcam idx for %u\n", + __func__, __LINE__, save[i]); + /* TODO: handle err case gracefully */ + goto err; + } + + /* Mark all slots as used */ + ret =3D __npc_subbank_mark_slot(rvu, sb, save[i], true); + if (!ret) { + dev_err(rvu->dev, "%s:%d Error to mark mcam_idx %u\n", + __func__, __LINE__, mcam_idx[i]); + rc =3D -EFAULT; + goto err; + } + } + +err: + kfree(save); + return rc; +} + +static int __maybe_unused +npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb, + int key_type, int ref, int limit, int prio, + bool contig, int count, u16 *mcam_idx, + int idx_sz, bool max_alloc, int *alloc_cnt) +{ + int rc; + + mutex_lock(&sb->lock); + rc =3D __npc_subbank_alloc(rvu, sb, key_type, ref, limit, prio, + contig, count, mcam_idx, idx_sz, + max_alloc, alloc_cnt); + mutex_unlock(&sb->lock); + + return rc; +} + +static int __maybe_unused +npc_del_from_pf_maps(struct rvu *rvu, u16 mcam_idx) +{ + int pcifunc, idx; + void *map; + + map =3D xa_erase(&npc_priv.xa_idx2pf_map, mcam_idx); + if (!map) { + dev_err(rvu->dev, + "%s:%d failed to erase mcam_idx(%u) from xa_idx2pf map\n", + __func__, __LINE__, mcam_idx); + return -EFAULT; + } + + pcifunc =3D xa_to_value(map); + map =3D xa_load(&npc_priv.xa_pf_map, pcifunc); + idx =3D xa_to_value(map); + + map =3D xa_erase(&npc_priv.xa_pf2idx_map[idx], mcam_idx); + if (!map) { + dev_err(rvu->dev, + "%s:%d failed to erase mcam_idx(%u) from xa_pf2idx_map map\n", + __func__, __LINE__, mcam_idx); + return -EFAULT; + } + return 0; +} + +static int __maybe_unused +npc_add_to_pf_maps(struct rvu *rvu, u16 mcam_idx, int pcifunc) +{ + int rc, idx; + void *map; + + dev_dbg(rvu->dev, + "%s:%d add2maps mcam_idx(%u) to xa_idx2pf map pcifunc=3D%#x\n", + __func__, __LINE__, mcam_idx, pcifunc); + + rc =3D xa_insert(&npc_priv.xa_idx2pf_map, mcam_idx, + xa_mk_value(pcifunc), GFP_KERNEL); + + if (rc) { + map =3D xa_load(&npc_priv.xa_idx2pf_map, mcam_idx); + dev_err(rvu->dev, + "%s:%d failed to insert mcam_idx(%u) to xa_idx2pf map, existing value= =3D%lu\n", + __func__, __LINE__, mcam_idx, xa_to_value(map)); + return -EFAULT; + } + + map =3D xa_load(&npc_priv.xa_pf_map, pcifunc); + idx =3D xa_to_value(map); + + rc =3D xa_insert(&npc_priv.xa_pf2idx_map[idx], mcam_idx, + xa_mk_value(pcifunc), GFP_KERNEL); + + if (rc) { + map =3D xa_load(&npc_priv.xa_pf2idx_map[idx], mcam_idx); + dev_err(rvu->dev, + "%s:%d failed to insert mcam_idx(%u) to xa_pf2idx_map map, earlier valu= e=3D%lu idx=3D%u\n", + __func__, __LINE__, mcam_idx, xa_to_value(map), idx); + return -EFAULT; + } + + return 0; +} + +static bool __maybe_unused +npc_subbank_suits(struct npc_subbank *sb, int key_type) +{ + mutex_lock(&sb->lock); + + if (!sb->key_type) { + mutex_unlock(&sb->lock); + return true; + } + + if (sb->key_type =3D=3D key_type) { + mutex_unlock(&sb->lock); + return true; + } + + mutex_unlock(&sb->lock); + return false; +} + +#define SB_ALIGN_UP(val) (((val) + npc_priv.subbank_depth) & \ + ~((npc_priv.subbank_depth) - 1)) +#define SB_ALIGN_DOWN(val) ALIGN_DOWN((val), npc_priv.subbank_depth) + +static void npc_subbank_iter_down(struct rvu *rvu, + int ref, int limit, + int *cur_ref, int *cur_limit, + bool *start, bool *stop) +{ + int align; + + *stop =3D false; + + /* ALIGN_DOWN the limit to current subbank boundary bottom index */ + if (*start) { + *start =3D false; + *cur_ref =3D ref; + align =3D SB_ALIGN_DOWN(ref); + if (align < limit) { + *stop =3D true; + *cur_limit =3D limit; + return; + } + *cur_limit =3D align; + return; + } + + *cur_ref =3D *cur_limit - 1; + align =3D *cur_ref - npc_priv.subbank_depth + 1; + if (align <=3D limit) { + *stop =3D true; + *cur_limit =3D limit; + return; + } + + *cur_limit =3D align; +} + +static void npc_subbank_iter_up(struct rvu *rvu, + int ref, int limit, + int *cur_ref, int *cur_limit, + bool *start, bool *stop) +{ + int align; + + *stop =3D false; + + /* ALIGN_UP the limit to current subbank boundary top index */ + if (*start) { + *start =3D false; + *cur_ref =3D ref; + + /* Find next lower prio subbank's bottom index */ + align =3D SB_ALIGN_UP(ref); + + /* Crosses limit ? */ + if (align - 1 > limit) { + *stop =3D true; + *cur_limit =3D limit; + return; + } + + /* Current subbank's top index */ + *cur_limit =3D align - 1; + return; + } + + *cur_ref =3D *cur_limit + 1; + align =3D *cur_ref + npc_priv.subbank_depth - 1; + + if (align >=3D limit) { + *stop =3D true; + *cur_limit =3D limit; + return; + } + + *cur_limit =3D align; +} + +static int __maybe_unused +npc_subbank_iter(struct rvu *rvu, int key_type, + int ref, int limit, int prio, + int *cur_ref, int *cur_limit, + bool *start, bool *stop) +{ + if (prio !=3D NPC_MCAM_HIGHER_PRIO) + npc_subbank_iter_up(rvu, ref, limit, + cur_ref, cur_limit, + start, stop); + else + npc_subbank_iter_down(rvu, ref, limit, + cur_ref, cur_limit, + start, stop); + + /* limit and ref should < bank_depth for x4 */ + if (key_type =3D=3D NPC_MCAM_KEY_X4) { + if (*cur_ref >=3D npc_priv.bank_depth) + return -EINVAL; + + if (*cur_limit >=3D npc_priv.bank_depth) + return -EINVAL; + } + /* limit and ref should < 2 * bank_depth, for x2 */ + if (*cur_ref >=3D 2 * npc_priv.bank_depth) + return -EINVAL; + + if (*cur_limit >=3D 2 * npc_priv.bank_depth) + return -EINVAL; + + return 0; +} + +static int npc_idx_free(struct rvu *rvu, u16 *mcam_idx, int count, + bool maps_del) +{ + struct npc_subbank *sb; + int idx, i; + bool ret; + int rc; + + for (i =3D 0; i < count; i++) { + rc =3D npc_mcam_idx_2_subbank_idx(rvu, mcam_idx[i], + &sb, &idx); + if (rc) + return rc; + + ret =3D npc_subbank_free(rvu, sb, idx); + if (ret) + return -EINVAL; + + if (!maps_del) + continue; + + rc =3D npc_del_from_pf_maps(rvu, mcam_idx[i]); + if (rc) + return rc; + } + + return 0; +} + +static int npc_multi_subbank_ref_alloc(struct rvu *rvu, int key_type, + int ref, int limit, int prio, + bool contig, int count, + u16 *mcam_idx) +{ + struct npc_subbank *sb; + unsigned long *bmap; + int sb_off, off, rc; + int cnt =3D 0; + bool bitset; + + if (prio !=3D NPC_MCAM_HIGHER_PRIO) { + while (ref <=3D limit) { + /* Calculate subbank and subbank index */ + rc =3D npc_mcam_idx_2_subbank_idx(rvu, ref, + &sb, &sb_off); + if (rc) + goto err; + + /* If subbank is not suitable for requested key type + * restart search from next subbank + */ + if (!npc_subbank_suits(sb, key_type)) { + ref =3D SB_ALIGN_UP(ref); + if (contig) { + rc =3D npc_idx_free(rvu, mcam_idx, + cnt, false); + if (rc) + return rc; + cnt =3D 0; + } + continue; + } + + mutex_lock(&sb->lock); + + /* If subbank is free; mark it as used */ + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { + rc =3D __npc_subbank_mark_used(rvu, sb, + key_type); + if (rc) { + mutex_unlock(&sb->lock); + dev_err(rvu->dev, + "%s:%d Error to add to use array\n", + __func__, __LINE__); + goto err; + } + } + + /* Find correct bmap */ + __npc_subbank_sboff_2_off(rvu, sb, sb_off, &bmap, &off); + + /* if bit is already set, reset 'cnt' */ + bitset =3D test_bit(off, bmap); + if (bitset) { + mutex_unlock(&sb->lock); + if (contig) { + rc =3D npc_idx_free(rvu, mcam_idx, + cnt, false); + if (rc) + return rc; + cnt =3D 0; + } + + ref++; + continue; + } + + set_bit(off, bmap); + sb->free_cnt--; + mcam_idx[cnt++] =3D ref; + mutex_unlock(&sb->lock); + + if (cnt =3D=3D count) + return 0; + ref++; + } + + /* Could not allocate request count slots */ + goto err; + } + while (ref >=3D limit) { + rc =3D npc_mcam_idx_2_subbank_idx(rvu, ref, + &sb, &sb_off); + if (rc) + goto err; + + if (!npc_subbank_suits(sb, key_type)) { + ref =3D SB_ALIGN_DOWN(ref) - 1; + if (contig) { + rc =3D npc_idx_free(rvu, mcam_idx, cnt, false); + if (rc) + return rc; + + cnt =3D 0; + } + continue; + } + + mutex_lock(&sb->lock); + + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { + rc =3D __npc_subbank_mark_used(rvu, sb, key_type); + if (rc) { + mutex_unlock(&sb->lock); + dev_err(rvu->dev, + "%s:%d Error to add to use array\n", + __func__, __LINE__); + goto err; + } + } + + __npc_subbank_sboff_2_off(rvu, sb, sb_off, &bmap, &off); + bitset =3D test_bit(off, bmap); + if (bitset) { + mutex_unlock(&sb->lock); + if (contig) { + cnt =3D 0; + rc =3D npc_idx_free(rvu, mcam_idx, cnt, false); + if (rc) + return rc; + } + ref--; + continue; + } + + mcam_idx[cnt++] =3D ref; + sb->free_cnt--; + set_bit(off, bmap); + mutex_unlock(&sb->lock); + + if (cnt =3D=3D count) + return 0; + ref--; + } + +err: + rc =3D npc_idx_free(rvu, mcam_idx, cnt, false); + if (rc) + dev_err(rvu->dev, + "%s:%d Error happened while freeing cnt=3D%u indexes\n", + __func__, __LINE__, cnt); + + return -ENOSPC; +} + +static int npc_subbank_free_cnt(struct rvu *rvu, struct npc_subbank *sb, + int key_type) +{ + int cnt, spd; + + spd =3D npc_priv.subbank_depth; + mutex_lock(&sb->lock); + + if (sb->flags & NPC_SUBBANK_FLAG_FREE) + cnt =3D key_type =3D=3D NPC_MCAM_KEY_X4 ? spd : 2 * spd; + else + cnt =3D sb->free_cnt; + + mutex_unlock(&sb->lock); + return cnt; +} + +static int npc_subbank_ref_alloc(struct rvu *rvu, int key_type, + int ref, int limit, int prio, + bool contig, int count, + u16 *mcam_idx) +{ + struct npc_subbank *sb1, *sb2; + bool max_alloc, start, stop; + int r, l, sb_idx1, sb_idx2; + int tot =3D 0, rc; + int alloc_cnt; + + max_alloc =3D !contig; + + start =3D true; + stop =3D false; + + /* Loop until we cross the ref/limit boundary */ + while (!stop) { + rc =3D npc_subbank_iter(rvu, key_type, ref, limit, prio, + &r, &l, &start, &stop); + + dev_dbg(rvu->dev, + "%s:%d ref=3D%d limit=3D%d r=3D%d l=3D%d start=3D%d stop=3D%d tot=3D%d = count=3D%d rc=3D%d\n", + __func__, __LINE__, ref, limit, r, l, + start, stop, tot, count, rc); + + if (rc) + goto err; + + /* Find subbank and subbank index for ref */ + rc =3D npc_mcam_idx_2_subbank_idx(rvu, r, &sb1, + &sb_idx1); + if (rc) + goto err; + + dev_dbg(rvu->dev, + "%s:%d ref subbank=3D%d off=3D%d\n", + __func__, __LINE__, sb1->idx, sb_idx1); + + /* Skip subbank if it is not available for the keytype */ + if (!npc_subbank_suits(sb1, key_type)) { + dev_dbg(rvu->dev, + "%s:%d not suitable sb=3D%d key_type=3D%d\n", + __func__, __LINE__, sb1->idx, key_type); + continue; + } + + /* Find subbank and subbank index for limit */ + rc =3D npc_mcam_idx_2_subbank_idx(rvu, l, &sb2, + &sb_idx2); + if (rc) + goto err; + + dev_dbg(rvu->dev, + "%s:%d limit subbank=3D%d off=3D%d\n", + __func__, __LINE__, sb_idx1, sb_idx2); + + /* subbank of ref and limit should be same */ + if (sb1 !=3D sb2) { + dev_err(rvu->dev, + "%s:%d l(%d) and r(%d) are not in same subbank\n", + __func__, __LINE__, r, l); + goto err; + } + + if (contig && + npc_subbank_free_cnt(rvu, sb1, key_type) < count) { + dev_dbg(rvu->dev, "%s:%d less count =3D%d\n", + __func__, __LINE__, + npc_subbank_free_cnt(rvu, sb1, key_type)); + continue; + } + + /* Try in one bank of a subbank */ + alloc_cnt =3D 0; + rc =3D npc_subbank_alloc(rvu, sb1, key_type, + r, l, prio, contig, + count - tot, mcam_idx + tot, + count - tot, max_alloc, + &alloc_cnt); + + tot +=3D alloc_cnt; + + dev_dbg(rvu->dev, "%s:%d Allocated tot=3D%d alloc_cnt=3D%d\n", + __func__, __LINE__, tot, alloc_cnt); + + if (!rc && count =3D=3D tot) + return 0; + } +err: + dev_dbg(rvu->dev, "%s:%d Error to allocate\n", + __func__, __LINE__); + + /* non contiguous allocation fails. We need to do clean up */ + if (max_alloc) { + rc =3D npc_idx_free(rvu, mcam_idx, tot, false); + if (rc) + dev_err(rvu->dev, + "%s:%d failed to free %u indexes\n", + __func__, __LINE__, tot); + } + + return -EFAULT; +} + +/* Minimize allocation from bottom and top subbanks for noref allocations. + * Default allocations are ref based, and will be allocated from top + * subbanks (least priority subbanks). Since default allocation is at very + * early stage of kernel netdev probes, this subbanks will be moved to + * used subbanks list. This will pave a way for noref allocation from these + * used subbanks. Skip allocation for these top and bottom, and try free + * bank next. If none slot is available, come back and search in these + * subbanks. + */ + +static int npc_subbank_restricted_idxs[2]; +static bool restrict_valid =3D true; + +static bool npc_subbank_restrict_usage(struct rvu *rvu, int index) +{ + int i; + + if (!restrict_valid) + return false; + + for (i =3D 0; i < ARRAY_SIZE(npc_subbank_restricted_idxs); i++) { + if (index =3D=3D npc_subbank_restricted_idxs[i]) + return true; + } + + return false; +} + +static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool con= tig, + int count, u16 *mcam_idx) +{ + struct npc_subbank *sb; + unsigned long index; + int tot =3D 0, rc; + bool max_alloc; + int alloc_cnt; + int idx, i; + void *val; + + max_alloc =3D !contig; + + /* Check used subbanks for free slots */ + xa_for_each(&npc_priv.xa_sb_used, index, val) { + idx =3D xa_to_value(val); + + /* Minimize allocation from restricted subbanks + * in noref allocations. + */ + if (npc_subbank_restrict_usage(rvu, idx)) + continue; + + sb =3D &npc_priv.sb[idx]; + + /* Skip if not suitable subbank */ + if (!npc_subbank_suits(sb, key_type)) + continue; + + if (contig && npc_subbank_free_cnt(rvu, sb, key_type) < count) + continue; + + /* try in bank 0. Try passing ref and limit equal to + * subbank boundaries + */ + alloc_cnt =3D 0; + rc =3D npc_subbank_alloc(rvu, sb, key_type, + sb->b0b, sb->b0t, 0, + contig, count - tot, + mcam_idx + tot, + count - tot, + max_alloc, &alloc_cnt); + + /* Non contiguous allocation may allocate less than + * requested 'count'. + */ + tot +=3D alloc_cnt; + + dev_dbg(rvu->dev, + "%s:%d Allocated %d from subbank %d, tot=3D%d count=3D%d\n", + __func__, __LINE__, alloc_cnt, sb->idx, tot, count); + + /* Successfully allocated */ + if (!rc && count =3D=3D tot) + return 0; + + /* x4 entries can be allocated from bank 0 only */ + if (key_type =3D=3D NPC_MCAM_KEY_X4) + continue; + + /* try in bank 1 for x2 */ + alloc_cnt =3D 0; + rc =3D npc_subbank_alloc(rvu, sb, key_type, + sb->b1b, sb->b1t, 0, + contig, count - tot, + mcam_idx + tot, + count - tot, max_alloc, + &alloc_cnt); + + tot +=3D alloc_cnt; + + dev_dbg(rvu->dev, + "%s:%d Allocated %d from subbank %d, tot=3D%d count=3D%d\n", + __func__, __LINE__, alloc_cnt, sb->idx, tot, count); + + if (!rc && count =3D=3D tot) + return 0; + } + + /* Allocate in free subbanks */ + xa_for_each(&npc_priv.xa_sb_free, index, val) { + idx =3D xa_to_value(val); + sb =3D &npc_priv.sb[idx]; + + /* Minimize allocation from restricted subbanks + * in noref allocations. + */ + if (npc_subbank_restrict_usage(rvu, idx)) + continue; + + if (!npc_subbank_suits(sb, key_type)) + continue; + + /* try in bank 0 */ + alloc_cnt =3D 0; + rc =3D npc_subbank_alloc(rvu, sb, key_type, + sb->b0b, sb->b0t, 0, + contig, count - tot, + mcam_idx + tot, + count - tot, + max_alloc, &alloc_cnt); + + tot +=3D alloc_cnt; + + dev_dbg(rvu->dev, + "%s:%d Allocated %d from subbank %d, tot=3D%d count=3D%d\n", + __func__, __LINE__, alloc_cnt, sb->idx, tot, count); + + /* Successfully allocated */ + if (!rc && count =3D=3D tot) + return 0; + + /* x4 entries can be allocated from bank 0 only */ + if (key_type =3D=3D NPC_MCAM_KEY_X4) + continue; + + /* try in bank 1 for x2 */ + alloc_cnt =3D 0; + rc =3D npc_subbank_alloc(rvu, sb, + key_type, sb->b1b, sb->b1t, 0, + contig, count - tot, + mcam_idx + tot, count - tot, + max_alloc, &alloc_cnt); + + tot +=3D alloc_cnt; + + dev_dbg(rvu->dev, + "%s:%d Allocated %d from subbank %d, tot=3D%d count=3D%d\n", + __func__, __LINE__, alloc_cnt, sb->idx, tot, count); + + if (!rc && count =3D=3D tot) + return 0; + } + + /* Allocate from restricted subbanks */ + for (i =3D 0; restrict_valid && + (i < ARRAY_SIZE(npc_subbank_restricted_idxs)); i++) { + idx =3D npc_subbank_restricted_idxs[i]; + sb =3D &npc_priv.sb[idx]; + + /* Skip if not suitable subbank */ + if (!npc_subbank_suits(sb, key_type)) + continue; + + if (contig && npc_subbank_free_cnt(rvu, sb, key_type) < count) + continue; + + /* try in bank 0. Try passing ref and limit equal to + * subbank boundaries + */ + alloc_cnt =3D 0; + rc =3D npc_subbank_alloc(rvu, sb, key_type, + sb->b0b, sb->b0t, 0, + contig, count - tot, + mcam_idx + tot, + count - tot, + max_alloc, &alloc_cnt); + + /* Non contiguous allocation may allocate less than + * requested 'count'. + */ + tot +=3D alloc_cnt; + + dev_dbg(rvu->dev, + "%s:%d Allocated %d from subbank %d, tot=3D%d count=3D%d\n", + __func__, __LINE__, alloc_cnt, sb->idx, tot, count); + + /* Successfully allocated */ + if (!rc && count =3D=3D tot) + return 0; + + /* x4 entries can be allocated from bank 0 only */ + if (key_type =3D=3D NPC_MCAM_KEY_X4) + continue; + + /* try in bank 1 for x2 */ + alloc_cnt =3D 0; + rc =3D npc_subbank_alloc(rvu, sb, key_type, + sb->b1b, sb->b1t, 0, + contig, count - tot, + mcam_idx + tot, + count - tot, max_alloc, + &alloc_cnt); + + tot +=3D alloc_cnt; + + dev_dbg(rvu->dev, + "%s:%d Allocated %d from subbank %d, tot=3D%d count=3D%d\n", + __func__, __LINE__, alloc_cnt, sb->idx, tot, count); + + if (!rc && count =3D=3D tot) + return 0; + } + + /* non contiguous allocation fails. We need to do clean up */ + if (max_alloc) + npc_idx_free(rvu, mcam_idx, tot, false); + + dev_dbg(rvu->dev, "%s:%d non-contig allocation fails\n", + __func__, __LINE__); + + return -EFAULT; +} + +int npc_cn20k_idx_free(struct rvu *rvu, u16 *mcam_idx, int count) +{ + return npc_idx_free(rvu, mcam_idx, count, true); +} + +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) +{ + int i, eidx, rc, bd; + bool ref_valid; + + bd =3D npc_priv.bank_depth; + + /* Special case: ref =3D=3D 0 && limit=3D 0 && prio =3D=3D HIGH && count = =3D=3D 1 + * Here user wants to allocate 0th entry + */ + if (!ref && !limit && prio =3D=3D NPC_MCAM_HIGHER_PRIO && + count =3D=3D 1) { + rc =3D npc_subbank_ref_alloc(rvu, key_type, ref, limit, + prio, contig, count, mcam_idx); + + if (rc) + return rc; + goto add2map; + } + + ref_valid =3D !!(limit || ref); + if (!ref_valid) { + if (contig && count > npc_priv.subbank_depth) + goto try_noref_multi_subbank; + + rc =3D npc_subbank_noref_alloc(rvu, key_type, contig, + count, mcam_idx); + if (!rc) + goto add2map; + +try_noref_multi_subbank: + eidx =3D (key_type =3D=3D NPC_MCAM_KEY_X4) ? bd - 1 : 2 * bd - 1; + + if (prio =3D=3D NPC_MCAM_HIGHER_PRIO) + rc =3D npc_multi_subbank_ref_alloc(rvu, key_type, + eidx, 0, + NPC_MCAM_HIGHER_PRIO, + contig, count, + mcam_idx); + else + rc =3D npc_multi_subbank_ref_alloc(rvu, key_type, + 0, eidx, + NPC_MCAM_LOWER_PRIO, + contig, count, + mcam_idx); + + if (!rc) + goto add2map; + + return rc; + } + + if ((prio =3D=3D NPC_MCAM_LOWER_PRIO && ref > limit) || + (prio =3D=3D NPC_MCAM_HIGHER_PRIO && ref < limit)) { + dev_err(rvu->dev, "%s:%d Wrong ref_enty(%d) or limit(%d)\n", + __func__, __LINE__, ref, limit); + return -EINVAL; + } + + if ((key_type =3D=3D NPC_MCAM_KEY_X4 && (ref >=3D bd || limit >=3D bd)) || + (key_type =3D=3D NPC_MCAM_KEY_X2 && + (ref >=3D 2 * bd || limit >=3D 2 * bd))) { + dev_err(rvu->dev, "%s:%d Wrong ref_enty(%d) or limit(%d)\n", + __func__, __LINE__, ref, limit); + return -EINVAL; + } + + if (contig && count > npc_priv.subbank_depth) + goto try_ref_multi_subbank; + + rc =3D npc_subbank_ref_alloc(rvu, key_type, ref, limit, + prio, contig, count, mcam_idx); + if (!rc) + goto add2map; + +try_ref_multi_subbank: + rc =3D npc_multi_subbank_ref_alloc(rvu, key_type, + ref, limit, prio, + contig, count, mcam_idx); + if (!rc) + goto add2map; + + return rc; + +add2map: + for (i =3D 0; i < count; i++) { + rc =3D npc_add_to_pf_maps(rvu, mcam_idx[i], pcifunc); + if (rc) + return rc; + } + + return 0; +} + +void npc_cn20k_subbank_calc_free(struct rvu *rvu, int *x2_free, + int *x4_free, int *sb_free) +{ + struct npc_subbank *sb; + int i; + + /* Reset all stats to zero */ + *x2_free =3D 0; + *x4_free =3D 0; + *sb_free =3D 0; + + for (i =3D 0; i < npc_priv.num_subbanks; i++) { + sb =3D &npc_priv.sb[i]; + mutex_lock(&sb->lock); + + /* Count number of free subbanks */ + if (sb->flags & NPC_SUBBANK_FLAG_FREE) { + (*sb_free)++; + goto next; + } + + /* Sumup x4 free count */ + if (sb->key_type =3D=3D NPC_MCAM_KEY_X4) { + (*x4_free) +=3D sb->free_cnt; + goto next; + } + + /* Sumup x2 free counts */ + (*x2_free) +=3D sb->free_cnt; +next: + mutex_unlock(&sb->lock); + } +} + +int +rvu_mbox_handler_npc_cn20k_get_free_count(struct rvu *rvu, + struct msg_req *req, + struct npc_cn20k_get_free_count_rsp *rsp) +{ + npc_cn20k_subbank_calc_free(rvu, &rsp->free_x2, + &rsp->free_x4, &rsp->free_subbanks); + return 0; +} + +static void npc_lock_all_subbank(void) +{ + int i; + + for (i =3D 0; i < npc_priv.num_subbanks; i++) + mutex_lock(&npc_priv.sb[i].lock); +} + +static void npc_unlock_all_subbank(void) +{ + int i; + + for (i =3D npc_priv.num_subbanks - 1; i >=3D 0; i--) + mutex_unlock(&npc_priv.sb[i].lock); +} + +static int *subbank_srch_order; + +int npc_cn20k_search_order_set(struct rvu *rvu, int (*arr)[2], int cnt) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + u8 (*fslots)[2], (*uslots)[2]; + int fcnt =3D 0, ucnt =3D 0; + struct npc_subbank *sb; + unsigned long index; + int idx, val; + void *v; + + if (cnt !=3D npc_priv.num_subbanks) + return -EINVAL; + + fslots =3D kcalloc(cnt, sizeof(*fslots), GFP_KERNEL); + if (!fslots) + return -ENOMEM; + + uslots =3D kcalloc(cnt, sizeof(*uslots), GFP_KERNEL); + if (!uslots) + return -ENOMEM; + + for (int i =3D 0; i < cnt; i++, arr++) { + idx =3D (*arr)[0]; + val =3D (*arr)[1]; + + subbank_srch_order[idx] =3D val; + } + + /* Lock mcam */ + mutex_lock(&mcam->lock); + npc_lock_all_subbank(); + + restrict_valid =3D false; + + xa_for_each(&npc_priv.xa_sb_used, index, v) { + val =3D xa_to_value(v); + (*(uslots + ucnt))[0] =3D index; + (*(uslots + ucnt))[1] =3D val; + xa_erase(&npc_priv.xa_sb_used, index); + ucnt++; + } + + xa_for_each(&npc_priv.xa_sb_free, index, v) { + val =3D xa_to_value(v); + (*(fslots + fcnt))[0] =3D index; + (*(fslots + fcnt))[1] =3D val; + xa_erase(&npc_priv.xa_sb_free, index); + fcnt++; + } + + for (int i =3D 0; i < ucnt; i++) { + idx =3D (*(uslots + i))[1]; + sb =3D &npc_priv.sb[idx]; + sb->arr_idx =3D subbank_srch_order[sb->idx]; + xa_store(&npc_priv.xa_sb_used, sb->arr_idx, + xa_mk_value(sb->idx), GFP_KERNEL); + } + + for (int i =3D 0; i < fcnt; i++) { + idx =3D (*(fslots + i))[1]; + sb =3D &npc_priv.sb[idx]; + sb->arr_idx =3D subbank_srch_order[sb->idx]; + xa_store(&npc_priv.xa_sb_free, sb->arr_idx, + xa_mk_value(sb->idx), GFP_KERNEL); + } + + npc_unlock_all_subbank(); + mutex_unlock(&mcam->lock); + + kfree(fslots); + kfree(uslots); + + return 0; +} + +const int *npc_cn20k_search_order_get(bool *restricted_order) +{ + *restricted_order =3D restrict_valid; + return subbank_srch_order; +} + +static void npc_populate_restricted_idxs(int num_subbanks) +{ + npc_subbank_restricted_idxs[0] =3D num_subbanks - 1; + npc_subbank_restricted_idxs[1] =3D 0; +} + +static void npc_create_srch_order(int cnt) +{ + int val =3D 0; + + subbank_srch_order =3D kcalloc(cnt, sizeof(int), + GFP_KERNEL); + + for (int i =3D 0; i < cnt; i +=3D 2) { + subbank_srch_order[i] =3D cnt / 2 - val - 1; + subbank_srch_order[i + 1] =3D cnt / 2 + 1 + val; + val++; + } + + subbank_srch_order[cnt - 1] =3D cnt / 2; +} + +static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int = idx) +{ + mutex_init(&sb->lock); + + sb->b0b =3D idx * npc_priv.subbank_depth; + sb->b0t =3D sb->b0b + npc_priv.subbank_depth - 1; + + sb->b1b =3D npc_priv.bank_depth + idx * npc_priv.subbank_depth; + sb->b1t =3D sb->b1b + npc_priv.subbank_depth - 1; + + sb->flags =3D NPC_SUBBANK_FLAG_FREE; + sb->idx =3D idx; + sb->arr_idx =3D subbank_srch_order[idx]; + + dev_dbg(rvu->dev, "%s:%d sb->idx=3D%u sb->arr_idx=3D%u\n", + __func__, __LINE__, sb->idx, sb->arr_idx); + + /* Keep first and last subbank at end of free array; so that + * it will be used at last + */ + xa_store(&npc_priv.xa_sb_free, sb->arr_idx, + xa_mk_value(sb->idx), GFP_KERNEL); +} + +static int npc_pcifunc_map_create(struct rvu *rvu) +{ + int pf, vf, numvfs; + int cnt =3D 0; + u16 pcifunc; + u64 cfg; + + for (pf =3D 0; pf < rvu->hw->total_pfs; pf++) { + cfg =3D rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf)); + numvfs =3D (cfg >> 12) & 0xFF; + + /* Skip not enabled PFs */ + if (!(cfg & BIT_ULL(20))) + goto chk_vfs; + + /* If Admin function, check on VFs */ + if (cfg & BIT_ULL(21)) + goto chk_vfs; + + pcifunc =3D pf << 9; + + xa_store(&npc_priv.xa_pf_map, (unsigned long)pcifunc, + xa_mk_value(cnt), GFP_KERNEL); + + cnt++; + +chk_vfs: + for (vf =3D 0; vf < numvfs; vf++) { + pcifunc =3D (pf << 9) | (vf + 1); + + xa_store(&npc_priv.xa_pf_map, (unsigned long)pcifunc, + xa_mk_value(cnt), GFP_KERNEL); + cnt++; + } + } + + return cnt; +} + +static int npc_priv_init(struct rvu *rvu) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + int blkaddr, num_banks, bank_depth; + int num_subbanks, subbank_depth; + u64 npc_const1, npc_const2 =3D 0; + struct npc_subbank *sb; + u64 cfg; + int i; + + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (blkaddr < 0) { + dev_err(rvu->dev, "%s:%d NPC block not implemented\n", + __func__, __LINE__); + return -ENODEV; + } + + npc_const1 =3D rvu_read64(rvu, blkaddr, NPC_AF_CONST1); + if (npc_const1 & BIT_ULL(63)) + npc_const2 =3D rvu_read64(rvu, blkaddr, NPC_AF_CONST2); + + num_banks =3D mcam->banks; + bank_depth =3D mcam->banksize; + + num_subbanks =3D FIELD_GET(GENMASK_ULL(39, 32), npc_const2); + npc_priv.num_subbanks =3D num_subbanks; + + subbank_depth =3D bank_depth / num_subbanks; + + npc_priv.bank_depth =3D bank_depth; + npc_priv.subbank_depth =3D subbank_depth; + + /* Get kex configured key size */ + cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(0)); + npc_priv.kw =3D FIELD_GET(GENMASK_ULL(34, 32), cfg); + + dev_info(rvu->dev, + "banks=3D%u depth=3D%u, subbanks=3D%u depth=3D%u, key type=3D%s\n", + num_banks, bank_depth, num_subbanks, subbank_depth, + npc_kw_name[npc_priv.kw]); + + npc_priv.sb =3D kcalloc(num_subbanks, sizeof(struct npc_subbank), + GFP_KERNEL); + if (!npc_priv.sb) + return -ENOMEM; + + xa_init_flags(&npc_priv.xa_sb_used, XA_FLAGS_ALLOC); + xa_init_flags(&npc_priv.xa_sb_free, XA_FLAGS_ALLOC); + xa_init_flags(&npc_priv.xa_idx2pf_map, XA_FLAGS_ALLOC); + xa_init_flags(&npc_priv.xa_pf_map, XA_FLAGS_ALLOC); + + npc_create_srch_order(num_subbanks); + npc_populate_restricted_idxs(num_subbanks); + + /* Initialize subbanks */ + for (i =3D 0, sb =3D npc_priv.sb; i < num_subbanks; i++, sb++) + npc_subbank_init(rvu, sb, i); + + /* Get number of pcifuncs in the system */ + npc_priv.pf_cnt =3D npc_pcifunc_map_create(rvu); + npc_priv.xa_pf2idx_map =3D kcalloc(npc_priv.pf_cnt, sizeof(struct xarray), + GFP_KERNEL); + if (!npc_priv.xa_pf2idx_map) + return -ENOMEM; + + for (i =3D 0; i < npc_priv.pf_cnt; i++) + xa_init_flags(&npc_priv.xa_pf2idx_map[i], XA_FLAGS_ALLOC); + + return 0; +} + +int npc_cn20k_deinit(struct rvu *rvu) +{ + int i; + + xa_destroy(&npc_priv.xa_sb_used); + xa_destroy(&npc_priv.xa_sb_free); + xa_destroy(&npc_priv.xa_idx2pf_map); + xa_destroy(&npc_priv.xa_pf_map); + + for (i =3D 0; i < npc_priv.pf_cnt; i++) + xa_destroy(&npc_priv.xa_pf2idx_map[i]); + + kfree(npc_priv.xa_pf2idx_map); + kfree(npc_priv.sb); + kfree(subbank_srch_order); + return 0; +} + +int npc_cn20k_init(struct rvu *rvu) +{ + int err; + + err =3D npc_priv_init(rvu); + if (err) { + dev_err(rvu->dev, "%s:%d Error to init\n", + __func__, __LINE__); + return err; + } + + npc_priv.init_done =3D true; + + return 0; +} diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.h new file mode 100644 index 000000000000..e1191d3d03cb --- /dev/null +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell RVU Admin Function driver + * + * Copyright (C) 2026 Marvell. + * + */ + +#ifndef NPC_CN20K_H +#define NPC_CN20K_H + +#define MAX_NUM_BANKS 2 +#define MAX_NUM_SUB_BANKS 32 +#define MAX_SUBBANK_DEPTH 256 + +enum npc_subbank_flag { + NPC_SUBBANK_FLAG_UNINIT, // npc_subbank is not initialized yet. + NPC_SUBBANK_FLAG_FREE =3D BIT(0), // No slot allocated + NPC_SUBBANK_FLAG_USED =3D BIT(1), // At least one slot allocated +}; + +struct npc_subbank { + u16 b0t, b0b, b1t, b1b; // mcam indexes of this subbank + enum npc_subbank_flag flags; + struct mutex lock; // for flags & rsrc modification + DECLARE_BITMAP(b0map, MAX_SUBBANK_DEPTH); // for x4 and x2 + DECLARE_BITMAP(b1map, MAX_SUBBANK_DEPTH); // for x2 only + u16 idx; // subbank index, 0 to npc_priv.subbank - 1 + u16 arr_idx; // Index to the free array or used array + u16 free_cnt; // number of free slots; + u8 key_type; //NPC_MCAM_KEY_X4 or NPC_MCAM_KEY_X2 +}; + +struct npc_priv_t { + int bank_depth; + const int num_banks; + int num_subbanks; + int subbank_depth; + u8 kw; // Kex configure Keywidth. + struct npc_subbank *sb; // Array of subbanks + struct xarray xa_sb_used; // xarray of used subbanks + struct xarray xa_sb_free; // xarray of free subbanks + struct xarray *xa_pf2idx_map; // Each PF to map its mcam idxes + struct xarray xa_idx2pf_map; // Mcam idxes to pf map. + struct xarray xa_pf_map; // pcifunc to index map. + int pf_cnt; + bool init_done; +}; + +struct rvu; + +struct npc_priv_t *npc_priv_get(void); +int npc_cn20k_init(struct rvu *rvu); +int npc_cn20k_deinit(struct rvu *rvu); + +void npc_cn20k_subbank_calc_free(struct rvu *rvu, int *x2_free, + int *x4_free, int *sb_free); + +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); +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); + +#endif /* NPC_CN20K_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/reg.h index affb39803120..098b0247848b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h @@ -77,5 +77,8 @@ #define RVU_MBOX_VF_INT_ENA_W1S (0x30) #define RVU_MBOX_VF_INT_ENA_W1C (0x38) =20 +/* NPC registers */ +#define NPC_AF_MCAM_SECTIONX_CFG_EXT(a) (0xf000000ull | (a) << 3) + #define RVU_MBOX_VF_VFAF_TRIGX(a) (0x2000 | (a) << 3) #endif /* RVU_MBOX_REG_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/n= et/ethernet/marvell/octeontx2/af/common.h index 8a08bebf08c2..779413a383b7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/common.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h @@ -177,10 +177,6 @@ enum nix_scheduler { #define NIX_TX_ACTIONOP_MCAST (0x3ull) #define NIX_TX_ACTIONOP_DROP_VIOL (0x5ull) =20 -#define NPC_MCAM_KEY_X1 0 -#define NPC_MCAM_KEY_X2 1 -#define NPC_MCAM_KEY_X4 2 - #define NIX_INTFX_RX(a) (0x0ull | (a) << 1) #define NIX_INTFX_TX(a) (0x1ull | (a) << 1) =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net= /ethernet/marvell/octeontx2/af/mbox.h index a3e273126e4e..73a341980f9e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -52,6 +52,14 @@ #define MBOX_DIR_PFVF_UP 6 /* PF sends messages to VF */ #define MBOX_DIR_VFPF_UP 7 /* VF replies to PF */ =20 +enum { + NPC_MCAM_KEY_X1 =3D 0, + NPC_MCAM_KEY_DYN =3D NPC_MCAM_KEY_X1, + NPC_MCAM_KEY_X2, + NPC_MCAM_KEY_X4, + NPC_MCAM_KEY_MAX, +}; + enum { TYPE_AFVF, TYPE_AFPF, @@ -275,6 +283,8 @@ M(NPC_GET_FIELD_HASH_INFO, 0x6013, npc_get_field_hash_i= nfo, M(NPC_GET_FIELD_STATUS, 0x6014, npc_get_field_status, \ npc_get_field_status_req, \ npc_get_field_status_rsp) \ +M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6015, npc_cn20k_get_free_count, \ + msg_req, npc_cn20k_get_free_count_rsp) \ /* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \ M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \ nix_lf_alloc_req, nix_lf_alloc_rsp) \ @@ -1797,6 +1807,14 @@ struct npc_mcam_read_entry_rsp { u8 enable; }; =20 +/* Available entries to use */ +struct npc_cn20k_get_free_count_rsp { + struct mbox_msghdr hdr; + int free_x2; + int free_x4; + int free_subbanks; +}; + struct npc_mcam_read_base_rule_rsp { struct mbox_msghdr hdr; struct mcam_entry entry; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/driv= ers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index 15d3cb0b9da6..425d3a43c0b8 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -3745,6 +3745,9 @@ static void rvu_dbg_npc_init(struct rvu *rvu) debugfs_create_file("rx_miss_act_stats", 0444, rvu->rvu_dbg.npc, rvu, &rvu_dbg_npc_rx_miss_act_fops); =20 + if (is_cn20k(rvu->pdev)) + npc_cn20k_debugfs_init(rvu); + if (!rvu->hw->cap.npc_exact_match_enabled) return; =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.c index c7c70429eb6c..6c5fe838717e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -16,6 +16,7 @@ #include "cgx.h" #include "npc_profile.h" #include "rvu_npc_hash.h" +#include "cn20k/npc.h" =20 #define RSVD_MCAM_ENTRIES_PER_PF 3 /* Broadcast, Promisc and AllMulticast = */ #define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */ @@ -2159,6 +2160,9 @@ int rvu_npc_init(struct rvu *rvu) npc_load_mkex_profile(rvu, blkaddr, def_pfl_name); } =20 + if (is_cn20k(rvu->pdev)) + return npc_cn20k_init(rvu); + return 0; } =20 @@ -2174,6 +2178,9 @@ void rvu_npc_freemem(struct rvu *rvu) else kfree(rvu->kpu_fwdata); mutex_destroy(&mcam->lock); + + if (is_cn20k(rvu->pdev)) + npc_cn20k_deinit(rvu); } =20 void rvu_npc_get_mcam_entry_alloc_info(struct rvu *rvu, u16 pcifunc, @@ -3029,7 +3036,6 @@ static int __npc_mcam_alloc_counter(struct rvu *rvu, if (!req->contig && req->count > NPC_MAX_NONCONTIG_COUNTERS) return NPC_MCAM_INVALID_REQ; =20 - /* Check if unused counters are available or not */ if (!rvu_rsrc_free_count(&mcam->counters)) { return NPC_MCAM_ALLOC_FAILED; --=20 2.43.0 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (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 EC02322D9E9; Mon, 5 Jan 2026 02:33:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580425; cv=none; b=uo1ck6pSnloSKa96T06bO9+ee+CxQT/wpzOATvabqSWAdvLSX/9UU6CIWihe/6F3eemjycCiDrFWw+mB4jDVqTeJCrJiJEVRwZ5+pDv8Ifd2vSPBqnxIGsk5AM+OyB0/k9WzJSjqZP5zGR0N+tPI2/VGTzclv0/SZF/wmDBGO38= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580425; c=relaxed/simple; bh=LudGXxFusoY4+fe68cUNH4VzCiYxNw3qwFB1pX5yYVU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=I62FLJFwQQjReBUCG/mDXRxTar32+EQFxeBiXfvr+hRpHr1zPKfDc33w5fBo+8Acddw5TEa4+18wOJooWymLsuZZd84lKxRQeL7qx/c7iSOqKBpSvxsNEIdRVmVrHU7d6JIdPEa+egozpHwvrYetjCNXHSNYfLe5NaJJQ1M3tTk= 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=cNhyKlfe; arc=none smtp.client-ip=67.231.156.173 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="cNhyKlfe" Received: from pps.filterd (m0431383.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604NgtFQ2346745; Sun, 4 Jan 2026 18:33:28 -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=B tcNQd9v1D2QizL9MKkrxPHS3vk1tSkfSn8XNzZhF5g=; b=cNhyKlfeflkn8lWYl WDXOrQPkyaAbcf7zjCxxj6+RL+z1z7N8DUkBVvA77ZXLEe0sE3OjWQZpyAt6SZ+i 5/s8lviPZx+EiEC2O67Ylf/vh5r/FPKrPJTzc/O6hBqyty3eZ5dyfxPojvh0bFHq AXSt2aVkuMXE8l/a4/pmalsU81snXg6ZFwrtqj9mfwJzyu3kbcnxDotEq3jUX/O3 MBAjfZUpJs7uLQ3m+c/oNCxRuYP1cVPe/AQCkvuzWT+Uot8inWFiEe//On6wQLHH zuWIyYwiMyMpENwvJygokZM+AYk+uUfIZ9wOqidqaR0RIW2MJK4xsN2ny2Ei5aTk ewJXA== Received: from dc6wp-exch02.marvell.com ([4.21.29.225]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 4bfmrbs02w-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:27 -0800 (PST) Received: from DC6WP-EXCH02.marvell.com (10.76.176.209) by DC6WP-EXCH02.marvell.com (10.76.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:33:27 -0800 Received: from maili.marvell.com (10.69.176.80) by DC6WP-EXCH02.marvell.com (10.76.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:33:27 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id D15DF5C68E6; Sun, 4 Jan 2026 18:33:23 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 02/13] octeontx2-af: npc: cn20k: KPM profile changes Date: Mon, 5 Jan 2026 08:02:43 +0530 Message-ID: <20260105023254.1426488-3-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-Authority-Analysis: v=2.4 cv=bN0b4f+Z c=1 sm=1 tr=0 ts=695b22f7 cx=c_pps a=gIfcoYsirJbf48DBMSPrZA==:117 a=gIfcoYsirJbf48DBMSPrZA==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=6-Y-9hFfzBH4qAAUAIcA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-ORIG-GUID: Rkyftwet4Ha-nUx7kUBumvErN2C56Amk X-Proofpoint-GUID: Rkyftwet4Ha-nUx7kUBumvErN2C56Amk X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX/dYrj7J6XvBV 3PM8U/Yhvsnfs3X45TkHET6Bp9bV6pUu+Cxq27rmdvGoHnEMK18GT7Ea2q8emgs/vxFFeCaUM1P FWa2e5ZVOEcdohKMekWzy9vpKpVkYo14FDld+LkmYCS7iQWLVegHlRrLPUsdvS0GNF9SGCcZesx /rw2HkLBZbIaBSkf0CN/EphrZaUgJmastMemnKQFSuwRg80wCazpbJzEIQkCiVMExk/PfPTBCHD AM6NWCWcKJg138Ru0cswg4FzXn+mqvgl1HAp/lATDSh250hcFpxpl8MuCmeAskWWY6c/g1UEbzF CxGVHmcwqQ78hPMPGJVwV2259m/BgVwgtpCXP3s3nvm9er5P0GzqhWFADj7PEmvK0YUAbTnfqkJ Y7+Z4G4+GlWT2zm1HHz9e1ePXuUFyURtiQdO/A1BL102VxZMbVf4lussagbBnZ0JU1PsOXFk5jV Op3DKg3NWO2Ugn4TJFg== 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" From: Suman Ghosh KPU (Kangaroo Processing Unit) profiles are primarily used to set the required packet pointers that will be used in later stages for key generation. In the new CN20K silicon variant, a new KPM profile is introduced alongside the existing KPU profiles. In CN20K, a total of 16 KPUs are grouped into 8 KPM profiles. As per the current hardware design, each KPM configuration contains a combination of 2 KPUs: KPM0 =3D KPU0 + KPU8 KPM1 =3D KPU1 + KPU9 ... KPM7 =3D KPU7 + KPU15 This configuration enables more efficient use of KPU resources. This patch adds support for the new KPM profile configuration. Signed-off-by: Suman Ghosh Signed-off-by: Ratheesh Kannoth --- .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 220 ++++++++++++++++++ .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 37 +++ .../ethernet/marvell/octeontx2/af/cn20k/reg.h | 17 +- .../net/ethernet/marvell/octeontx2/af/rvu.h | 4 +- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 48 ++-- .../ethernet/marvell/octeontx2/af/rvu_npc.h | 17 ++ 6 files changed, 326 insertions(+), 17 deletions(-) create mode 100644 drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.c index 27b049ac4ae8..17f9c71ad0b8 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -9,6 +9,7 @@ =20 #include "cn20k/npc.h" #include "cn20k/reg.h" +#include "rvu_npc.h" =20 static struct npc_priv_t npc_priv =3D { .num_banks =3D MAX_NUM_BANKS, @@ -20,6 +21,225 @@ static const char *npc_kw_name[NPC_MCAM_KEY_MAX] =3D { [NPC_MCAM_KEY_X4] =3D "X4", }; =20 +static void npc_config_kpmcam(struct rvu *rvu, int blkaddr, + const struct npc_kpu_profile_cam *kpucam, + int kpm, int entry) +{ + struct npc_kpu_cam cam0 =3D {0}; + struct npc_kpu_cam cam1 =3D {0}; + + cam1.state =3D kpucam->state & kpucam->state_mask; + cam1.dp0_data =3D kpucam->dp0 & kpucam->dp0_mask; + cam1.dp1_data =3D kpucam->dp1 & kpucam->dp1_mask; + cam1.dp2_data =3D kpucam->dp2 & kpucam->dp2_mask; + + cam0.state =3D ~kpucam->state & kpucam->state_mask; + cam0.dp0_data =3D ~kpucam->dp0 & kpucam->dp0_mask; + cam0.dp1_data =3D ~kpucam->dp1 & kpucam->dp1_mask; + cam0.dp2_data =3D ~kpucam->dp2 & kpucam->dp2_mask; + + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRYX_CAMX(kpm, entry, 0), *(u64 *)&cam0); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRYX_CAMX(kpm, entry, 1), *(u64 *)&cam1); +} + +static void +npc_config_kpmaction(struct rvu *rvu, int blkaddr, + const struct npc_kpu_profile_action *kpuaction, + int kpm, int entry, bool pkind) +{ + struct npc_kpm_action0 action0 =3D {0}; + struct npc_kpu_action1 action1 =3D {0}; + u64 reg; + + action1.errlev =3D kpuaction->errlev; + action1.errcode =3D kpuaction->errcode; + action1.dp0_offset =3D kpuaction->dp0_offset; + action1.dp1_offset =3D kpuaction->dp1_offset; + action1.dp2_offset =3D kpuaction->dp2_offset; + + if (pkind) + reg =3D NPC_AF_PKINDX_ACTION1(entry); + else + reg =3D NPC_AF_KPMX_ENTRYX_ACTION1(kpm, entry); + + rvu_write64(rvu, blkaddr, reg, *(u64 *)&action1); + + action0.byp_count =3D kpuaction->bypass_count; + action0.capture_ena =3D kpuaction->cap_ena; + action0.parse_done =3D kpuaction->parse_done; + action0.next_state =3D kpuaction->next_state; + action0.capture_lid =3D kpuaction->lid; + action0.capture_ltype =3D kpuaction->ltype; + action0.capture_flags =3D kpuaction->flags; + action0.ptr_advance =3D kpuaction->ptr_advance; + action0.var_len_offset =3D kpuaction->offset; + action0.var_len_mask =3D kpuaction->mask; + action0.var_len_right =3D kpuaction->right; + action0.var_len_shift =3D kpuaction->shift; + + if (pkind) + reg =3D NPC_AF_PKINDX_ACTION0(entry); + else + reg =3D NPC_AF_KPMX_ENTRYX_ACTION0(kpm, entry); + + rvu_write64(rvu, blkaddr, reg, *(u64 *)&action0); +} + +static void +npc_program_single_kpm_profile(struct rvu *rvu, int blkaddr, + int kpm, int start_entry, + const struct npc_kpu_profile *profile) +{ + int entry, num_entries, max_entries; + u64 idx; + + if (profile->cam_entries !=3D profile->action_entries) { + dev_err(rvu->dev, + "kpm%d: CAM and action entries [%d !=3D %d] not equal\n", + kpm, profile->cam_entries, profile->action_entries); + } + + max_entries =3D rvu->hw->npc_kpu_entries / 2; + entry =3D start_entry; + /* Program CAM match entries for previous kpm extracted data */ + num_entries =3D min_t(int, profile->cam_entries, max_entries); + for (idx =3D 0; entry < num_entries + start_entry; entry++, idx++) + npc_config_kpmcam(rvu, blkaddr, &profile->cam[idx], kpm, entry); + + entry =3D start_entry; + /* Program this kpm's actions */ + num_entries =3D min_t(int, profile->action_entries, max_entries); + for (idx =3D 0; entry < num_entries + start_entry; entry++, idx++) + npc_config_kpmaction(rvu, blkaddr, &profile->action[idx], + kpm, entry, false); +} + +static void +npc_enable_kpm_entry(struct rvu *rvu, int blkaddr, int kpm, int num_entrie= s) +{ + u64 entry_mask; + + entry_mask =3D npc_enable_mask(num_entries); + /* Disable first KPU_MAX_CST_ENT entries for built-in profile */ + if (!rvu->kpu.custom) + entry_mask |=3D GENMASK_ULL(KPU_MAX_CST_ENT - 1, 0); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 0), entry_mask); + if (num_entries <=3D 64) { + /* Disable all the entries in W1, W2 and W3 */ + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 1), + npc_enable_mask(0)); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 2), + npc_enable_mask(0)); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 3), + npc_enable_mask(0)); + return; + } + + num_entries =3D num_entries - 64; + entry_mask =3D npc_enable_mask(num_entries); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 1), entry_mask); + if (num_entries <=3D 64) { + /* Disable all the entries in W2 and W3 */ + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 2), + npc_enable_mask(0)); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 3), + npc_enable_mask(0)); + return; + } + + num_entries =3D num_entries - 64; + entry_mask =3D npc_enable_mask(num_entries); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 2), entry_mask); + if (num_entries <=3D 64) { + /* Disable all the entries in W3 */ + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 3), + npc_enable_mask(0)); + return; + } + + num_entries =3D num_entries - 64; + entry_mask =3D npc_enable_mask(num_entries); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(kpm, 3), entry_mask); +} + +#define KPU_OFFSET 8 +static void npc_program_kpm_profile(struct rvu *rvu, int blkaddr, int num_= kpms) +{ + const struct npc_kpu_profile *profile1, *profile2; + int idx, total_cam_entries; + + for (idx =3D 0; idx < num_kpms; idx++) { + profile1 =3D &rvu->kpu.kpu[idx]; + npc_program_single_kpm_profile(rvu, blkaddr, idx, 0, profile1); + profile2 =3D &rvu->kpu.kpu[idx + KPU_OFFSET]; + npc_program_single_kpm_profile(rvu, blkaddr, idx, + profile1->cam_entries, + profile2); + total_cam_entries =3D profile1->cam_entries + + profile2->cam_entries; + npc_enable_kpm_entry(rvu, blkaddr, idx, total_cam_entries); + rvu_write64(rvu, blkaddr, NPC_AF_KPMX_PASS2_OFFSET(idx), + profile1->cam_entries); + /* Enable the KPUs associated with this KPM */ + rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx), 0x01); + rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx + KPU_OFFSET), + 0x01); + } +} + +void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr) +{ + struct rvu_hwinfo *hw =3D rvu->hw; + int num_pkinds, idx; + + /* Disable all KPMs and their entries */ + for (idx =3D 0; idx < hw->npc_kpms; idx++) { + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(idx, 0), ~0ULL); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(idx, 1), ~0ULL); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(idx, 2), ~0ULL); + rvu_write64(rvu, blkaddr, + NPC_AF_KPMX_ENTRY_DISX(idx, 3), ~0ULL); + } + + for (idx =3D 0; idx < hw->npc_kpus; idx++) + rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx), 0x00); + + /* Load and customize KPU profile. */ + npc_load_kpu_profile(rvu); + + /* Configure KPU and KPM mapping for second pass */ + rvu_write64(rvu, blkaddr, NPC_AF_KPM_PASS2_CFG, 0x76543210); + + /* First program IKPU profile i.e PKIND configs. + * Check HW max count to avoid configuring junk or + * writing to unsupported CSR addresses. + */ + num_pkinds =3D rvu->kpu.pkinds; + num_pkinds =3D min_t(int, hw->npc_pkinds, num_pkinds); + + for (idx =3D 0; idx < num_pkinds; idx++) + npc_config_kpmaction(rvu, blkaddr, &rvu->kpu.ikpu[idx], + 0, idx, true); + + /* Program KPM CAM and Action profiles */ + npc_program_kpm_profile(rvu, blkaddr, hw->npc_kpms); +} + struct npc_priv_t *npc_priv_get(void) { return &npc_priv; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.h index e1191d3d03cb..06b1eca1ef09 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h @@ -46,6 +46,42 @@ struct npc_priv_t { bool init_done; }; =20 +struct npc_kpm_action0 { +#if defined(__BIG_ENDIAN_BITFIELD) + u64 rsvd_63_57 : 7; + u64 byp_count : 3; + u64 capture_ena : 1; + u64 parse_done : 1; + u64 next_state : 8; + u64 rsvd_43 : 1; + u64 capture_lid : 3; + u64 capture_ltype : 4; + u64 rsvd_32_35 : 4; + u64 capture_flags : 4; + u64 ptr_advance : 8; + u64 var_len_offset : 8; + u64 var_len_mask : 8; + u64 var_len_right : 1; + u64 var_len_shift : 3; +#else + u64 var_len_shift : 3; + u64 var_len_right : 1; + u64 var_len_mask : 8; + u64 var_len_offset : 8; + u64 ptr_advance : 8; + u64 capture_flags : 4; + u64 rsvd_32_35 : 4; + u64 capture_ltype : 4; + u64 capture_lid : 3; + u64 rsvd_43 : 1; + u64 next_state : 8; + u64 parse_done : 1; + u64 capture_ena : 1; + u64 byp_count : 3; + u64 rsvd_63_57 : 7; +#endif +}; + struct rvu; =20 struct npc_priv_t *npc_priv_get(void); @@ -61,5 +97,6 @@ int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc,= int key_type, 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); +void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr); =20 #endif /* NPC_CN20K_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/reg.h index 098b0247848b..073d4b815681 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h @@ -77,8 +77,21 @@ #define RVU_MBOX_VF_INT_ENA_W1S (0x30) #define RVU_MBOX_VF_INT_ENA_W1C (0x38) =20 +#define RVU_MBOX_VF_VFAF_TRIGX(a) (0x2000 | (a) << 3) /* NPC registers */ -#define NPC_AF_MCAM_SECTIONX_CFG_EXT(a) (0xf000000ull | (a) << 3) +#define NPC_AF_INTFX_EXTRACTORX_CFG(a, b) \ + (0x908000ull | (a) << 10 | (b) << 3) +#define NPC_AF_INTFX_EXTRACTORX_LTX_CFG(a, b, c) \ + (0x900000ull | (a) << 13 | (b) << 8 | (c) << 3) +#define NPC_AF_KPMX_ENTRYX_CAMX(a, b, c) \ + (0x100000ull | (a) << 14 | (b) << 6 | (c) << 3) +#define NPC_AF_KPMX_ENTRYX_ACTION0(a, b) \ + (0x100020ull | (a) << 14 | (b) << 6) +#define NPC_AF_KPMX_ENTRYX_ACTION1(a, b) \ + (0x100028ull | (a) << 14 | (b) << 6) +#define NPC_AF_KPMX_ENTRY_DISX(a, b) (0x180000ull | (a) << 6 | (b) << 3) +#define NPC_AF_KPM_PASS2_CFG 0x580 +#define NPC_AF_KPMX_PASS2_OFFSET(a) (0x190000ull | (a) << 3) +#define NPC_AF_MCAM_SECTIONX_CFG_EXT(a) (0xC000000ull | (a) << 3) =20 -#define RVU_MBOX_VF_VFAF_TRIGX(a) (0x2000 | (a) << 3) #endif /* RVU_MBOX_REG_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/= ethernet/marvell/octeontx2/af/rvu.h index e85dac2c806d..14ca28ab493a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -447,9 +447,11 @@ struct rvu_hwinfo { u8 sdp_links; u8 cpt_links; /* Number of CPT links */ u8 npc_kpus; /* No of parser units */ + u8 npc_kpms; /* Number of enhanced parser units */ + u8 npc_kex_extr; /* Number of LDATA extractors per KEX */ u8 npc_pkinds; /* No of port kinds */ u8 npc_intfs; /* No of interfaces */ - u8 npc_kpu_entries; /* No of KPU entries */ + u16 npc_kpu_entries; /* No of KPU entries */ u16 npc_counters; /* No of match stats counters */ u32 lbk_bufsize; /* FIFO size supported by LBK */ bool npc_ext_set; /* Extended register set */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.c index 6c5fe838717e..133ae6421de7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -17,6 +17,7 @@ #include "npc_profile.h" #include "rvu_npc_hash.h" #include "cn20k/npc.h" +#include "rvu_npc.h" =20 #define RSVD_MCAM_ENTRIES_PER_PF 3 /* Broadcast, Promisc and AllMulticast = */ #define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */ @@ -1410,9 +1411,9 @@ static void npc_load_mkex_profile(struct rvu *rvu, in= t blkaddr, iounmap(mkex_prfl_addr); } =20 -static void npc_config_kpuaction(struct rvu *rvu, int blkaddr, - const struct npc_kpu_profile_action *kpuaction, - int kpu, int entry, bool pkind) +void npc_config_kpuaction(struct rvu *rvu, int blkaddr, + const struct npc_kpu_profile_action *kpuaction, + int kpu, int entry, bool pkind) { struct npc_kpu_action0 action0 =3D {0}; struct npc_kpu_action1 action1 =3D {0}; @@ -1475,7 +1476,7 @@ static void npc_config_kpucam(struct rvu *rvu, int bl= kaddr, NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 1), *(u64 *)&cam1); } =20 -static inline u64 enable_mask(int count) +u64 npc_enable_mask(int count) { return (((count) < 64) ? ~(BIT_ULL(count) - 1) : (0x00ULL)); } @@ -1508,7 +1509,7 @@ static void npc_program_kpu_profile(struct rvu *rvu, = int blkaddr, int kpu, =20 /* Enable all programmed entries */ num_entries =3D min_t(int, profile->action_entries, profile->cam_entries); - entry_mask =3D enable_mask(num_entries); + entry_mask =3D npc_enable_mask(num_entries); /* Disable first KPU_MAX_CST_ENT entries for built-in profile */ if (!rvu->kpu.custom) entry_mask |=3D GENMASK_ULL(KPU_MAX_CST_ENT - 1, 0); @@ -1517,7 +1518,7 @@ static void npc_program_kpu_profile(struct rvu *rvu, = int blkaddr, int kpu, if (num_entries > 64) { rvu_write64(rvu, blkaddr, NPC_AF_KPUX_ENTRY_DISX(kpu, 1), - enable_mask(num_entries - 64)); + npc_enable_mask(num_entries - 64)); } =20 /* Enable this KPU */ @@ -1705,7 +1706,7 @@ static int npc_load_kpu_profile_fwdb(struct rvu *rvu,= const char *kpu_profile) return ret; } =20 -static void npc_load_kpu_profile(struct rvu *rvu) +void npc_load_kpu_profile(struct rvu *rvu) { struct npc_kpu_profile_adapter *profile =3D &rvu->kpu; const char *kpu_profile =3D rvu->kpu_pfl_name; @@ -1847,12 +1848,19 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkadd= r) mcam->keysize =3D cfg; =20 /* Number of banks combined per MCAM entry */ - if (cfg =3D=3D NPC_MCAM_KEY_X4) - mcam->banks_per_entry =3D 4; - else if (cfg =3D=3D NPC_MCAM_KEY_X2) - mcam->banks_per_entry =3D 2; - else - mcam->banks_per_entry =3D 1; + if (is_cn20k(rvu->pdev)) { + if (cfg =3D=3D NPC_MCAM_KEY_X2) + mcam->banks_per_entry =3D 1; + else + mcam->banks_per_entry =3D 2; + } else { + if (cfg =3D=3D NPC_MCAM_KEY_X4) + mcam->banks_per_entry =3D 4; + else if (cfg =3D=3D NPC_MCAM_KEY_X2) + mcam->banks_per_entry =3D 2; + else + mcam->banks_per_entry =3D 1; + } =20 /* Reserve one MCAM entry for each of the NIX LF to * guarantee space to install default matching DMAC rule. @@ -1982,6 +1990,15 @@ static void rvu_npc_hw_init(struct rvu *rvu, int blk= addr) hw->npc_pkinds =3D (npc_const1 >> 12) & 0xFFULL; hw->npc_kpu_entries =3D npc_const1 & 0xFFFULL; hw->npc_kpus =3D (npc_const >> 8) & 0x1FULL; + /* For Cn20k silicon, check if enhanced parser + * is present, then set the NUM_KPMS =3D NUM_KPUS / 2 and + * number of LDATA extractors per KEX. + */ + if (is_cn20k(rvu->pdev) && (npc_const1 & BIT_ULL(62))) { + hw->npc_kpms =3D hw->npc_kpus / 2; + hw->npc_kex_extr =3D (npc_const1 >> 36) & 0x3FULL; + } + hw->npc_intfs =3D npc_const & 0xFULL; hw->npc_counters =3D (npc_const >> 48) & 0xFFFFULL; =20 @@ -2116,7 +2133,10 @@ int rvu_npc_init(struct rvu *rvu) return -ENOMEM; =20 /* Configure KPU profile */ - npc_parser_profile_init(rvu, blkaddr); + if (is_cn20k(rvu->pdev)) + npc_cn20k_parser_profile_init(rvu, blkaddr); + else + npc_parser_profile_init(rvu, blkaddr); =20 /* Config Outer L2, IPv4's NPC layer info */ rvu_write64(rvu, blkaddr, NPC_AF_PCK_DEF_OL2, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.h new file mode 100644 index 000000000000..80c63618ec47 --- /dev/null +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Marvell RVU Admin Function driver + * + * Copyright (C) 2026 Marvell. + * + */ + +#ifndef RVU_NPC_H +#define RVU_NPC_H + +u64 npc_enable_mask(int count); +void npc_load_kpu_profile(struct rvu *rvu); +void npc_config_kpuaction(struct rvu *rvu, int blkaddr, + const struct npc_kpu_profile_action *kpuaction, + int kpu, int entry, bool pkind); + +#endif /* RVU_NPC_H */ --=20 2.43.0 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0a-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 CB804315D25; Mon, 5 Jan 2026 02:33:52 +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=1767580435; cv=none; b=k7BmbxJup7CAuqOOnGL8/04eROY1NS+ffoBrm0sTiPL0ZG+h/IZuYkMRqXaCF0qoxoGwfdgN9kWa/6X1cKKKUsihOIw8te/fcYuOrLuPTEj+Jv23ZBACtIPOr4vDoc+JZX7rfp34dPIxjb8Paj9ryJHyzKQ2u+uhtIcGQg8ztcc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580435; c=relaxed/simple; bh=6BZNNKKDr1you2u2o+YJUgFh590QvXj6ZU5p6CLGA8E=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UNR4DvL5BaXq63zIJI9mRFqt7LCFiYMOJlRpwj5h8XjjE5ZF1k1eY2ce3fuHN8GYRZU7sMKRmKRGOBJ89ix9sEZyEIYzI151VjCUdrrHAzgIcLEnN13i2l6uQZZ1rCfx6FKqwewVS0Yt/a4AVAy/Kaw1Ws+yvwAhLc9e8OLEVg0= 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=fXK7EiFg; 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="fXK7EiFg" Received: from pps.filterd (m0431384.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604MtNqS2644729; Sun, 4 Jan 2026 18:33:32 -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=T a46q+ybcZuKIWYvrnudRtTDCNVJocJZiBYIbjNjXk4=; b=fXK7EiFgc+a90iuRk kDu8HKI13/g3ubAWBAkuFvn1gY9yYT3WUkOnSGua0mWwFHaxEi+1nuVohKJyE3xu sMAnlbjDeT89z3M7wK9aBYfHuBs/6/MKItmPx7r4u/LP2OmlBp1u7lZBNRZ7e50l 7WqawwLAUsYMUJO+/F/7Jf2gGiKDq9iqDXTbnzfmeCYvUu6El8OXu2YcbqaEfiXc 3uPlo4jG5fzmaLel8IlF8v7f/xTInSZdi3iXgGaENg3iWu7po8qm7yhNk7MvHkUn QLyeUKiCr3lP/wGMBtCsLjjb1Yp60PeMZtypmI3gQsy+AGXzxszNBsOEh9nJRHJ6 yrPHw== Received: from dc6wp-exch02.marvell.com ([4.21.29.225]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 4bfr8bgts7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:31 -0800 (PST) Received: from DC6WP-EXCH02.marvell.com (10.76.176.209) by DC6WP-EXCH02.marvell.com (10.76.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:33:30 -0800 Received: from maili.marvell.com (10.69.176.80) by DC6WP-EXCH02.marvell.com (10.76.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:33:30 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id 4DAAA3F7094; Sun, 4 Jan 2026 18:33:27 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 03/13] octeontx2-af: npc: cn20k: Add default profile Date: Mon, 5 Jan 2026 08:02:44 +0530 Message-ID: <20260105023254.1426488-4-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: ENA22TMKfbuhqqypoqbObSPRHCJOcYJ0 X-Proofpoint-GUID: ENA22TMKfbuhqqypoqbObSPRHCJOcYJ0 X-Authority-Analysis: v=2.4 cv=P/I3RyAu c=1 sm=1 tr=0 ts=695b22fb cx=c_pps a=gIfcoYsirJbf48DBMSPrZA==:117 a=gIfcoYsirJbf48DBMSPrZA==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=NGP3fZmBk5oLfH1lOsUA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfXxgQuzJDDW+6t 3bSnBpMTjzgtLYeYTYhxbcURILUU6+/eeNq0OJHoJSAz+tglX/asUFTG5Ff7QhfP87vF1sVG3RT OaY1H+YDs8eTHzDoJRmauPmWN++KsvafeufdsCRsamJF3lwDU3MYaQUb2rPpyzIJYmP8HPEfuSp TbkiAwYD82IX88wcDMlWmU7H4Zbb6iSHbp/wIwcFCe2wARW2Kv3M2Hwq/pDxTCfKrRkkpO476zq ncmV8TAgsFAJmKqCToIr1dUgDYEgEYsuMqsd97RKAZeLKo5ZA5+J3UKSwbzpwd9ZjbwLzKdqwEL mEG+hrbPHzG9X9IZUx+iwchnG17QZXYY0aSR0AcZM9e33cuBbcgIuYhpuZIA0FPM0R3L9ixTZs6 hzLCjj3DWMb517z3Ao7MLsUl3niCJB0XRF9fHLMw7D6N47J5dBmt2ugnYbT1MCVguzzMRzmfp+9 ISC1CuHBravZdPlwdWg== 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" From: Suman Ghosh Default mkex profile for cn20k silicon. This commit changes attribute of objects to may_be_unused to avoid compiler warning Signed-off-by: Suman Ghosh Signed-off-by: Ratheesh Kannoth --- .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 170 +++++++++++++++++- .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 18 ++ .../marvell/octeontx2/af/npc_profile.h | 72 ++++---- 3 files changed, 223 insertions(+), 37 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 17f9c71ad0b8..48f49d70043e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -7,9 +7,13 @@ #include #include =20 +#include "rvu.h" +#include "npc.h" +#include "npc_profile.h" +#include "rvu_npc_hash.h" +#include "rvu_npc.h" #include "cn20k/npc.h" #include "cn20k/reg.h" -#include "rvu_npc.h" =20 static struct npc_priv_t npc_priv =3D { .num_banks =3D MAX_NUM_BANKS, @@ -21,6 +25,170 @@ static const char *npc_kw_name[NPC_MCAM_KEY_MAX] =3D { [NPC_MCAM_KEY_X4] =3D "X4", }; =20 +#define KEX_EXTR_CFG(bytesm1, hdr_ofs, ena, key_ofs) \ + (((bytesm1) << 16) | ((hdr_ofs) << 8) | ((ena) << 7) | \ + ((key_ofs) & 0x3F)) + +static struct npc_mcam_kex_extr npc_mkex_extr_default =3D { + .mkex_sign =3D MKEX_SIGN, + .name =3D "default", + .kpu_version =3D NPC_KPU_PROFILE_VER, + .keyx_cfg =3D { + /* nibble: LA..LE (ltype only) + Error code + Channel */ + [NIX_INTF_RX] =3D ((u64)NPC_MCAM_KEY_X2 << 32) | NPC_PARSE_NIBBLE_INTF_R= X | + (u64)NPC_EXACT_NIBBLE_HIT, + /* nibble: LA..LE (ltype only) */ + [NIX_INTF_TX] =3D ((u64)NPC_MCAM_KEY_X2 << 32) | NPC_PARSE_NIBBLE_INTF_T= X, + }, + .intf_extr_lid =3D { + /* Default RX MCAM KEX profile */ + [NIX_INTF_RX] =3D { NPC_LID_LA, NPC_LID_LA, NPC_LID_LB, NPC_LID_LB, + NPC_LID_LC, NPC_LID_LC, NPC_LID_LD }, + [NIX_INTF_TX] =3D { NPC_LID_LA, NPC_LID_LA, NPC_LID_LB, NPC_LID_LB, + NPC_LID_LC, NPC_LID_LD }, + }, + .intf_extr_lt =3D { + /* Default RX MCAM KEX profile */ + [NIX_INTF_RX] =3D { + [0] =3D { + /* Layer A: Ethernet: */ + [NPC_LT_LA_ETHER] =3D + /* DMAC: 6 bytes, KW1[55:8] */ + KEX_EXTR_CFG(0x05, 0x0, 0x1, NPC_KEXOF_DMAC), + [NPC_LT_LA_CPT_HDR] =3D + /* DMAC: 6 bytes, KW1[55:8] */ + KEX_EXTR_CFG(0x05, 0x0, 0x1, NPC_KEXOF_DMAC), + }, + [1] =3D { + /* Layer A: Ethernet: */ + [NPC_LT_LA_ETHER] =3D + /* Ethertype: 2 bytes, KW0[55:40] */ + KEX_EXTR_CFG(0x01, 0xc, 0x1, 0x5), + [NPC_LT_LA_CPT_HDR] =3D + /* Ethertype: 2 bytes, KW0[55:40] */ + KEX_EXTR_CFG(0x01, 0xc, 0x1, 0x5), + }, + [2] =3D { + /* Layer B: Single VLAN (CTAG) */ + [NPC_LT_LB_CTAG] =3D + /* CTAG VLAN: 2 bytes, KW1[7:0], KW0[63:56] */ + KEX_EXTR_CFG(0x01, 0x2, 0x1, 0x7), + /* Layer B: Stacked VLAN (STAG|QinQ) */ + [NPC_LT_LB_STAG_QINQ] =3D + /* Outer VLAN: 2 bytes, KW1[7:0], KW0[63:56] */ + KEX_EXTR_CFG(0x01, 0x2, 0x1, 0x7), + [NPC_LT_LB_FDSA] =3D + /* SWITCH PORT: 1 byte, KW0[63:56] */ + KEX_EXTR_CFG(0x0, 0x1, 0x1, 0x7), + }, + [3] =3D { + [NPC_LT_LB_CTAG] =3D + /* Ethertype: 2 bytes, KW0[55:40] */ + KEX_EXTR_CFG(0x01, 0x4, 0x1, 0x5), + [NPC_LT_LB_STAG_QINQ] =3D + /* Ethertype: 2 bytes, KW0[55:40] */ + KEX_EXTR_CFG(0x01, 0x8, 0x1, 0x5), + [NPC_LT_LB_FDSA] =3D + /* Ethertype: 2 bytes, KW0[55:40] */ + KEX_EXTR_CFG(0x01, 0x4, 0x1, 0x5), + }, + [4] =3D { + /* Layer C: IPv4 */ + [NPC_LT_LC_IP] =3D + /* SIP+DIP: 8 bytes, KW2[63:0] */ + KEX_EXTR_CFG(0x07, 0xc, 0x1, 0x10), + /* Layer C: IPv6 */ + [NPC_LT_LC_IP6] =3D + /* Everything up to SADDR: 8 bytes, KW2[63:0] */ + KEX_EXTR_CFG(0x07, 0x0, 0x1, 0x10), + }, + [5] =3D { + [NPC_LT_LC_IP] =3D + /* TOS: 1 byte, KW1[63:56] */ + KEX_EXTR_CFG(0x0, 0x1, 0x1, 0xf), + }, + [6] =3D { + /* Layer D:UDP */ + [NPC_LT_LD_UDP] =3D + /* SPORT+DPORT: 4 bytes, KW3[31:0] */ + KEX_EXTR_CFG(0x3, 0x0, 0x1, 0x18), + /* Layer D:TCP */ + [NPC_LT_LD_TCP] =3D + /* SPORT+DPORT: 4 bytes, KW3[31:0] */ + KEX_EXTR_CFG(0x3, 0x0, 0x1, 0x18), + }, + }, + + /* Default TX MCAM KEX profile */ + [NIX_INTF_TX] =3D { + [0] =3D { + /* Layer A: NIX_INST_HDR_S + Ethernet */ + /* NIX appends 8 bytes of NIX_INST_HDR_S at the + * start of each TX packet supplied to NPC. + */ + [NPC_LT_LA_IH_NIX_ETHER] =3D + /* PF_FUNC: 2B , KW0 [47:32] */ + KEX_EXTR_CFG(0x01, 0x0, 0x1, 0x4), + /* Layer A: HiGig2: */ + [NPC_LT_LA_IH_NIX_HIGIG2_ETHER] =3D + /* PF_FUNC: 2B , KW0 [47:32] */ + KEX_EXTR_CFG(0x01, 0x0, 0x1, 0x4), + }, + [1] =3D { + [NPC_LT_LA_IH_NIX_ETHER] =3D + /* SQ_ID 3 bytes, KW1[63:16] */ + KEX_EXTR_CFG(0x02, 0x02, 0x1, 0xa), + [NPC_LT_LA_IH_NIX_HIGIG2_ETHER] =3D + /* VID: 2 bytes, KW1[31:16] */ + KEX_EXTR_CFG(0x01, 0x10, 0x1, 0xa), + }, + [2] =3D { + /* Layer B: Single VLAN (CTAG) */ + [NPC_LT_LB_CTAG] =3D + /* CTAG VLAN[2..3] KW0[63:48] */ + KEX_EXTR_CFG(0x01, 0x2, 0x1, 0x6), + /* Layer B: Stacked VLAN (STAG|QinQ) */ + [NPC_LT_LB_STAG_QINQ] =3D + /* Outer VLAN: 2 bytes, KW0[63:48] */ + KEX_EXTR_CFG(0x01, 0x2, 0x1, 0x6), + }, + [3] =3D { + [NPC_LT_LB_CTAG] =3D + /* CTAG VLAN[2..3] KW1[15:0] */ + KEX_EXTR_CFG(0x01, 0x4, 0x1, 0x8), + [NPC_LT_LB_STAG_QINQ] =3D + /* Outer VLAN: 2 Bytes, KW1[15:0] */ + KEX_EXTR_CFG(0x01, 0x8, 0x1, 0x8), + }, + [4] =3D { + /* Layer C: IPv4 */ + [NPC_LT_LC_IP] =3D + /* SIP+DIP: 8 bytes, KW2[63:0] */ + KEX_EXTR_CFG(0x07, 0xc, 0x1, 0x10), + /* Layer C: IPv6 */ + [NPC_LT_LC_IP6] =3D + /* Everything up to SADDR: 8 bytes, KW2[63:0] */ + KEX_EXTR_CFG(0x07, 0x0, 0x1, 0x10), + }, + [5] =3D { + /* Layer D:UDP */ + [NPC_LT_LD_UDP] =3D + /* SPORT+DPORT: 4 bytes, KW3[31:0] */ + KEX_EXTR_CFG(0x3, 0x0, 0x1, 0x18), + /* Layer D:TCP */ + [NPC_LT_LD_TCP] =3D + /* SPORT+DPORT: 4 bytes, KW3[31:0] */ + KEX_EXTR_CFG(0x3, 0x0, 0x1, 0x18), + }, + }, + }, +}; + +struct npc_mcam_kex_extr *npc_mkex_extr_default_get(void) +{ + return &npc_mkex_extr_default; +} + static void npc_config_kpmcam(struct rvu *rvu, int blkaddr, const struct npc_kpu_profile_cam *kpucam, int kpm, int entry) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.h index 06b1eca1ef09..24a70f9aaec2 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h @@ -82,6 +82,23 @@ struct npc_kpm_action0 { #endif }; =20 +struct npc_mcam_kex_extr { + /* MKEX Profle Header */ + u64 mkex_sign; /* "mcam-kex-profile" (8 bytes/ASCII characters) */ + u8 name[MKEX_NAME_LEN]; /* MKEX Profile name */ + u64 cpu_model; /* Format as profiled by CPU hardware */ + u64 kpu_version; /* KPU firmware/profile version */ + u64 reserved; /* Reserved for extension */ + + /* MKEX Profle Data */ + u64 keyx_cfg[NPC_MAX_INTF]; /* NPC_AF_INTF(0..1)_KEX_CFG */ +#define NPC_MAX_EXTRACTOR 24 + /* MKEX Extractor data */ + u64 intf_extr_lid[NPC_MAX_INTF][NPC_MAX_EXTRACTOR]; + /* KEX configuration per extractor */ + u64 intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT]; +} __packed; + struct rvu; =20 struct npc_priv_t *npc_priv_get(void); @@ -98,5 +115,6 @@ int npc_cn20k_idx_free(struct rvu *rvu, u16 *mcam_idx, i= nt 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); void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr); +struct npc_mcam_kex_extr *npc_mkex_extr_default_get(void); =20 #endif /* NPC_CN20K_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h b/driv= ers/net/ethernet/marvell/octeontx2/af/npc_profile.h index 41de72c8607f..561b01fcdbde 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h @@ -489,7 +489,7 @@ enum NPC_ERRLEV_E { 0, 0, 0, 0, \ } =20 -static struct npc_kpu_profile_action ikpu_action_entries[] =3D { +static struct npc_kpu_profile_action ikpu_action_entries[] __maybe_unused = =3D { { NPC_ERRLEV_RE, NPC_EC_NOERR, 12, 16, 20, 0, 0, @@ -1068,7 +1068,7 @@ static struct npc_kpu_profile_action ikpu_action_entr= ies[] =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu1_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu1_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -1878,7 +1878,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu2_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu2_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -2823,7 +2823,7 @@ static struct npc_kpu_profile_cam kpu2_cam_entries[] = =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu3_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu3_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -3804,7 +3804,7 @@ static struct npc_kpu_profile_cam kpu3_cam_entries[] = =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu4_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu4_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -4119,7 +4119,7 @@ static struct npc_kpu_profile_cam kpu4_cam_entries[] = =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu5_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu5_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -5172,7 +5172,7 @@ static struct npc_kpu_profile_cam kpu5_cam_entries[] = =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu6_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu6_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -5901,7 +5901,7 @@ static struct npc_kpu_profile_cam kpu6_cam_entries[] = =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu7_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu7_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -6252,7 +6252,7 @@ static struct npc_kpu_profile_cam kpu7_cam_entries[] = =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu8_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu8_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -7089,7 +7089,7 @@ static struct npc_kpu_profile_cam kpu8_cam_entries[] = =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu9_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu9_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -7575,7 +7575,7 @@ static struct npc_kpu_profile_cam kpu9_cam_entries[] = =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu10_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu10_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -7746,7 +7746,7 @@ static struct npc_kpu_profile_cam kpu10_cam_entries[]= =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu11_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu11_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -8061,7 +8061,7 @@ static struct npc_kpu_profile_cam kpu11_cam_entries[]= =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu12_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu12_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -8322,7 +8322,7 @@ static struct npc_kpu_profile_cam kpu12_cam_entries[]= =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu13_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu13_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -8340,7 +8340,7 @@ static struct npc_kpu_profile_cam kpu13_cam_entries[]= =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu14_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu14_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -8358,7 +8358,7 @@ static struct npc_kpu_profile_cam kpu14_cam_entries[]= =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu15_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu15_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -8565,7 +8565,7 @@ static struct npc_kpu_profile_cam kpu15_cam_entries[]= =3D { }, }; =20 -static struct npc_kpu_profile_cam kpu16_cam_entries[] =3D { +static struct npc_kpu_profile_cam kpu16_cam_entries[] __maybe_unused =3D { NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, NPC_KPU_NOP_CAM, @@ -8628,7 +8628,7 @@ static struct npc_kpu_profile_cam kpu16_cam_entries[]= =3D { }, }; =20 -static struct npc_kpu_profile_action kpu1_action_entries[] =3D { +static struct npc_kpu_profile_action kpu1_action_entries[] __maybe_unused = =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -9368,7 +9368,7 @@ static struct npc_kpu_profile_action kpu1_action_entr= ies[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu2_action_entries[] =3D { +static struct npc_kpu_profile_action kpu2_action_entries[] __maybe_unused = =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -10209,7 +10209,7 @@ static struct npc_kpu_profile_action kpu2_action_en= tries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu3_action_entries[] =3D { +static struct npc_kpu_profile_action kpu3_action_entries[] __maybe_unused = =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -11082,7 +11082,7 @@ static struct npc_kpu_profile_action kpu3_action_en= tries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu4_action_entries[] =3D { +static struct npc_kpu_profile_action kpu4_action_entries[] __maybe_unused = =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -11363,7 +11363,7 @@ static struct npc_kpu_profile_action kpu4_action_en= tries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu5_action_entries[] =3D { +static struct npc_kpu_profile_action kpu5_action_entries[] __maybe_unused = =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -12300,7 +12300,7 @@ static struct npc_kpu_profile_action kpu5_action_en= tries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu6_action_entries[] =3D { +static struct npc_kpu_profile_action kpu6_action_entries[] __maybe_unused = =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -12949,7 +12949,7 @@ static struct npc_kpu_profile_action kpu6_action_en= tries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu7_action_entries[] =3D { +static struct npc_kpu_profile_action kpu7_action_entries[] __maybe_unused = =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -13262,7 +13262,7 @@ static struct npc_kpu_profile_action kpu7_action_en= tries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu8_action_entries[] =3D { +static struct npc_kpu_profile_action kpu8_action_entries[] __maybe_unused = =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -14007,7 +14007,7 @@ static struct npc_kpu_profile_action kpu8_action_en= tries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu9_action_entries[] =3D { +static struct npc_kpu_profile_action kpu9_action_entries[] __maybe_unused = =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -14440,7 +14440,7 @@ static struct npc_kpu_profile_action kpu9_action_en= tries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu10_action_entries[] =3D { +static struct npc_kpu_profile_action kpu10_action_entries[] __maybe_unused= =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -14593,7 +14593,7 @@ static struct npc_kpu_profile_action kpu10_action_e= ntries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu11_action_entries[] =3D { +static struct npc_kpu_profile_action kpu11_action_entries[] __maybe_unused= =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -14874,7 +14874,7 @@ static struct npc_kpu_profile_action kpu11_action_e= ntries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu12_action_entries[] =3D { +static struct npc_kpu_profile_action kpu12_action_entries[] __maybe_unused= =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -15107,7 +15107,7 @@ static struct npc_kpu_profile_action kpu12_action_e= ntries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu13_action_entries[] =3D { +static struct npc_kpu_profile_action kpu13_action_entries[] __maybe_unused= =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -15124,7 +15124,7 @@ static struct npc_kpu_profile_action kpu13_action_e= ntries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu14_action_entries[] =3D { +static struct npc_kpu_profile_action kpu14_action_entries[] __maybe_unused= =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -15141,7 +15141,7 @@ static struct npc_kpu_profile_action kpu14_action_e= ntries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu15_action_entries[] =3D { +static struct npc_kpu_profile_action kpu15_action_entries[] __maybe_unused= =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -15326,7 +15326,7 @@ static struct npc_kpu_profile_action kpu15_action_e= ntries[] =3D { }, }; =20 -static struct npc_kpu_profile_action kpu16_action_entries[] =3D { +static struct npc_kpu_profile_action kpu16_action_entries[] __maybe_unused= =3D { NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, NPC_KPU_NOP_ACTION, @@ -15383,7 +15383,7 @@ static struct npc_kpu_profile_action kpu16_action_e= ntries[] =3D { }, }; =20 -static struct npc_kpu_profile npc_kpu_profiles[] =3D { +static struct npc_kpu_profile npc_kpu_profiles[] __maybe_unused =3D { { ARRAY_SIZE(kpu1_cam_entries), ARRAY_SIZE(kpu1_action_entries), @@ -15482,7 +15482,7 @@ static struct npc_kpu_profile npc_kpu_profiles[] = =3D { }, }; =20 -static struct npc_lt_def_cfg npc_lt_defaults =3D { +static struct npc_lt_def_cfg npc_lt_defaults __maybe_unused =3D { .rx_ol2 =3D { .lid =3D NPC_LID_LA, .ltype_match =3D NPC_LT_LA_ETHER, @@ -15604,7 +15604,7 @@ static struct npc_lt_def_cfg npc_lt_defaults =3D { }, }; =20 -static struct npc_mcam_kex npc_mkex_default =3D { +static struct npc_mcam_kex npc_mkex_default __maybe_unused =3D { .mkex_sign =3D MKEX_SIGN, .name =3D "default", .kpu_version =3D NPC_KPU_PROFILE_VER, --=20 2.43.0 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (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 DB41130EF98; Mon, 5 Jan 2026 02:33:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580428; cv=none; b=TkYydDoSZdNTcDAHlp0XmP//nOOqWakIrondEX1JRFt8I/5M2F9OEzu1tDCd9OIDQ/TvyPZZd5YW9kwb75RBHmzTtaDFjYfg/pa19B0QZhKkLqOLPqBGfxOrzJAprw4E/YVKTNBqK75bJKYD1l2l+BN4a1jy+YOcv5LmJthUGZU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580428; c=relaxed/simple; bh=L12jm4t8Fk6iX+ReVFvZ2HW93yt7EYIfaScPKh0kOH0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AUGbflEgP/KdQ5L9Ucr4FP9bfS+bBJhfAs2HgAGa2t8MGlBRiyriX4iaQXugl8/I2RQkij0edv/8CfGzIkyWjt5WzSGkf2zScgGL3q3eOl6uuznY7Pf3M86Ke8bdQT/BF/sXCNtGEY/D6bVFgIvZ0tKZSfB7Y8Y0RwUigc2S0sE= 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=TBcNZORg; arc=none smtp.client-ip=67.231.156.173 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="TBcNZORg" Received: from pps.filterd (m0431383.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604NvMsM2371819; Sun, 4 Jan 2026 18:33:35 -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=c uEz7oNq4f4nAdq3YkSK19HG84VET1PaEssSt9Y6170=; b=TBcNZORgo/VHFml6k MiXrozGwNU5dwD/z9vDN+lCFSaD1C/FbpaBIVvrrI5k/TskG8vyHL72s9muRgG27 uUobPqUnY+qdTQK6Ma4Bw9MpPVIcLXxiiNGDf7Ap1CF45NwZT9bsFavsZHOEYjEt i9y6bpUWDYLDWklPczLh3vkJOELxj0zPVXGI2O688pdiuud1sm+fF+YU12lvSCI1 SDT90oyNOec1HMVNK18aA1F9f9DNULng4ZJe627WTuUqwyj1znDvhw6USGZFp7kY 1KSG5XF1QRVASUJUXrQu5JA0S4TGA/+DWbYlP8ONr3hcivvJSlldYNf1RkcAGNlg 0rkzw== Received: from dc6wp-exch02.marvell.com ([4.21.29.225]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 4bfmrbs030-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:34 -0800 (PST) Received: from DC6WP-EXCH02.marvell.com (10.76.176.209) by DC6WP-EXCH02.marvell.com (10.76.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:33:34 -0800 Received: from maili.marvell.com (10.69.176.80) by DC6WP-EXCH02.marvell.com (10.76.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:33:34 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id BDCD83F7094; Sun, 4 Jan 2026 18:33:30 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 04/13] ocetontx2-af: npc: cn20k: MKEX profile support Date: Mon, 5 Jan 2026 08:02:45 +0530 Message-ID: <20260105023254.1426488-5-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-Authority-Analysis: v=2.4 cv=bN0b4f+Z c=1 sm=1 tr=0 ts=695b22fe cx=c_pps a=gIfcoYsirJbf48DBMSPrZA==:117 a=gIfcoYsirJbf48DBMSPrZA==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=4IwJlRh9AewB62vroAYA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-ORIG-GUID: K-n8Kkofla-N4BcLSoi4p_qEFlcPtD9h X-Proofpoint-GUID: K-n8Kkofla-N4BcLSoi4p_qEFlcPtD9h X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX9dZ5O36iGOPf sqj7JmIf+A7xDIT9NgYLdQKs0eUa6Nv/f+T/TaWyWoh5BkbNu2mRRzoeKFR+ZMpup0T3YtHP+a4 gSohqcj/AXySKzx2pShs0IEGYpAgLSQzNm+IdOdjVRPaRVNBeR/SnSlnC4c3sS2quuMzcv5GziY PpMb4sNEW2Ue4dq9MLMWTgpaDfvSICU5ZumsaU+cmesUUtmx9qEZEaPd+UzKAnA/D+Qf61148k4 tJnroG4c0JSNur1wKF0Ox+RDT7Y0MyUdCnD9BIM/jNtsb1m4I8n7d8CMRhNt7jumrMx4wADXPNq IxzFR+71j9zCPM0pBRZxQd5t9cbulsq37xB+Y2XtLh/OhV0UfJ0D/e9ckQcjnGXrQFDamWF1IQK LYbVeyZHGYtC0IAMSFr/ua+shBywwFMGIZOzc+xftbVCg3PDggpE9ZqJCqFK8qDOXLDQTO0cbYh +5NideeG2CnOyv7hR7w== 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" From: Suman Ghosh In new silicon variant cn20k, a new parser profile is introduced. Instead of having two layer-data information per key field type, a new key extractor concept is introduced. As part of this change now a maximum of 24 extractor can be configured per packet parsing profile. For example, LA type(ether) can have 24 unique pasring key, LC type(ip), LD type(tcp/udp) also can have unique 24 parsing key assiciated. Signed-off-by: Suman Ghosh Signed-off-by: Ratheesh Kannoth --- .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 338 +++++++++++++++++- .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 97 +++++ .../ethernet/marvell/octeontx2/af/cn20k/reg.h | 60 +++- .../net/ethernet/marvell/octeontx2/af/mbox.h | 17 +- .../net/ethernet/marvell/octeontx2/af/npc.h | 1 + .../marvell/octeontx2/af/npc_profile.h | 12 + .../net/ethernet/marvell/octeontx2/af/rvu.h | 6 +- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 73 +++- .../ethernet/marvell/octeontx2/af/rvu_npc.h | 2 + .../marvell/octeontx2/af/rvu_npc_fs.c | 220 ++++++++++-- .../marvell/octeontx2/af/rvu_npc_hash.c | 15 + 11 files changed, 772 insertions(+), 69 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 48f49d70043e..a3c4e2c1fcba 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -29,16 +29,18 @@ static const char *npc_kw_name[NPC_MCAM_KEY_MAX] =3D { (((bytesm1) << 16) | ((hdr_ofs) << 8) | ((ena) << 7) | \ ((key_ofs) & 0x3F)) =20 +static const char cn20k_def_pfl_name[] =3D "default"; + static struct npc_mcam_kex_extr npc_mkex_extr_default =3D { - .mkex_sign =3D MKEX_SIGN, + .mkex_sign =3D MKEX_CN20K_SIGN, .name =3D "default", .kpu_version =3D NPC_KPU_PROFILE_VER, .keyx_cfg =3D { /* nibble: LA..LE (ltype only) + Error code + Channel */ - [NIX_INTF_RX] =3D ((u64)NPC_MCAM_KEY_X2 << 32) | NPC_PARSE_NIBBLE_INTF_R= X | - (u64)NPC_EXACT_NIBBLE_HIT, + [NIX_INTF_RX] =3D ((u64)NPC_MCAM_KEY_DYN << 32) | NPC_CN20K_PARSE_NIBBLE= _INTF_RX | + NPC_CN20K_PARSE_NIBBLE_ERRCODE, /* nibble: LA..LE (ltype only) */ - [NIX_INTF_TX] =3D ((u64)NPC_MCAM_KEY_X2 << 32) | NPC_PARSE_NIBBLE_INTF_T= X, + [NIX_INTF_TX] =3D ((u64)NPC_MCAM_KEY_X2 << 32) | NPC_CN20K_PARSE_NIBBLE_= INTF_TX, }, .intf_extr_lid =3D { /* Default RX MCAM KEX profile */ @@ -290,9 +292,9 @@ npc_enable_kpm_entry(struct rvu *rvu, int blkaddr, int = kpm, int num_entries) u64 entry_mask; =20 entry_mask =3D npc_enable_mask(num_entries); - /* Disable first KPU_MAX_CST_ENT entries for built-in profile */ + /* Disable first KPU_CN20K_MAX_CST_ENT entries for built-in profile */ if (!rvu->kpu.custom) - entry_mask |=3D GENMASK_ULL(KPU_MAX_CST_ENT - 1, 0); + entry_mask |=3D GENMASK_ULL(KPU_CN20K_MAX_CST_ENT - 1, 0); rvu_write64(rvu, blkaddr, NPC_AF_KPMX_ENTRY_DISX(kpm, 0), entry_mask); if (num_entries <=3D 64) { @@ -413,6 +415,275 @@ struct npc_priv_t *npc_priv_get(void) return &npc_priv; } =20 +static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr, + struct npc_mcam_kex_extr *mkex_extr, + u8 intf) +{ + u8 num_extr =3D rvu->hw->npc_kex_extr; + int extr, lt; + + if (is_npc_intf_tx(intf)) + return; + + rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf), + mkex_extr->keyx_cfg[NIX_INTF_RX]); + + /* Program EXTRACTOR */ + for (extr =3D 0; extr < num_extr; extr++) + rvu_write64(rvu, blkaddr, NPC_AF_INTFX_EXTRACTORX_CFG(intf, extr), + mkex_extr->intf_extr_lid[intf][extr]); + + /* Program EXTRACTOR_LTYPE */ + for (extr =3D 0; extr < num_extr; extr++) + for (lt =3D 0; lt < NPC_MAX_LT; lt++) + CN20K_SET_EXTR_LT(intf, extr, lt, + mkex_extr->intf_extr_lt[intf][extr][lt]); +} + +static void npc_program_mkex_tx(struct rvu *rvu, int blkaddr, + struct npc_mcam_kex_extr *mkex_extr, + u8 intf) +{ + u8 num_extr =3D rvu->hw->npc_kex_extr; + int extr, lt; + + if (is_npc_intf_rx(intf)) + return; + + rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf), + mkex_extr->keyx_cfg[NIX_INTF_TX]); + + /* Program EXTRACTOR */ + for (extr =3D 0; extr < num_extr; extr++) + rvu_write64(rvu, blkaddr, NPC_AF_INTFX_EXTRACTORX_CFG(intf, extr), + mkex_extr->intf_extr_lid[intf][extr]); + + /* Program EXTRACTOR_LTYPE */ + for (extr =3D 0; extr < num_extr; extr++) + for (lt =3D 0; lt < NPC_MAX_LT; lt++) + CN20K_SET_EXTR_LT(intf, extr, lt, + mkex_extr->intf_extr_lt[intf][extr][lt]); +} + +static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr, + struct npc_mcam_kex_extr *mkex_extr) +{ + struct rvu_hwinfo *hw =3D rvu->hw; + u8 intf; + + for (intf =3D 0; intf < hw->npc_intfs; intf++) { + npc_program_mkex_rx(rvu, blkaddr, mkex_extr, intf); + npc_program_mkex_tx(rvu, blkaddr, mkex_extr, intf); + } + + /* Programme mkex hash profile */ + npc_program_mkex_hash(rvu, blkaddr); +} + +void npc_cn20k_load_mkex_profile(struct rvu *rvu, int blkaddr, + const char *mkex_profile) +{ + struct npc_mcam_kex_extr *mcam_kex_extr; + struct device *dev =3D &rvu->pdev->dev; + void __iomem *mkex_prfl_addr =3D NULL; + u64 prfl_sz; + int ret; + + /* If user not selected mkex profile */ + if (rvu->kpu_fwdata_sz || + !strncmp(mkex_profile, cn20k_def_pfl_name, MKEX_NAME_LEN)) + goto program_mkex_extr; + + /* Setting up the mapping for mkex profile image */ + ret =3D npc_fwdb_prfl_img_map(rvu, &mkex_prfl_addr, &prfl_sz); + if (ret < 0) + goto program_mkex_extr; + + mcam_kex_extr =3D (struct npc_mcam_kex_extr __force *)mkex_prfl_addr; + + while (((s64)prfl_sz > 0) && (mcam_kex_extr->mkex_sign !=3D MKEX_END_SIGN= )) { + /* Compare with mkex mod_param name string */ + if (mcam_kex_extr->mkex_sign =3D=3D MKEX_CN20K_SIGN && + !strncmp(mcam_kex_extr->name, mkex_profile, MKEX_NAME_LEN)) { + rvu->kpu.mcam_kex_prfl.mkex_extr =3D mcam_kex_extr; + goto program_mkex_extr; + } + + mcam_kex_extr++; + prfl_sz -=3D sizeof(struct npc_mcam_kex); + } + dev_warn(dev, "Failed to load requested profile: %s\n", mkex_profile); + +program_mkex_extr: + dev_info(rvu->dev, "Using %s mkex profile\n", rvu->kpu.mcam_kex_prfl.mkex= _extr->name); + /* Program selected mkex profile */ + npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mcam_kex_prfl.mkex_extr); + if (mkex_prfl_addr) + iounmap(mkex_prfl_addr); +} + +static u8 npc_map2cn20k_flag(u8 flag) +{ + switch (flag) { + case NPC_F_LC_U_IP_FRAG: + return NPC_CN20K_F_LC_L_IP_FRAG; + + case NPC_F_LC_U_IP6_FRAG: + return NPC_CN20K_F_LC_L_IP6_FRAG; + + case NPC_F_LC_L_6TO4: + return NPC_CN20K_F_LC_L_6TO4; + + case NPC_F_LC_L_MPLS_IN_IP: + return NPC_CN20K_F_LC_U_MPLS_IN_IP; + + case NPC_F_LC_L_IP6_TUN_IP6: + return NPC_CN20K_F_LC_U_IP6_TUN_IP6; + + case NPC_F_LC_L_IP6_MPLS_IN_IP: + return NPC_CN20K_F_LC_U_IP6_MPLS_IN_IP; + + default: + break; + } + + return -1; +} + +void +npc_cn20k_update_action_entries_n_flags(struct rvu *rvu, + struct npc_kpu_profile_adapter *profile) +{ + struct npc_kpu_profile_action *action; + int entries, ltype; + u8 flags; + + for (int i =3D 0; i < profile->kpus; i++) { + action =3D profile->kpu[i].action; + entries =3D profile->kpu[i].action_entries; + + for (int j =3D 0; j < entries; j++) { + if (action[j].lid !=3D NPC_LID_LC) + continue; + + ltype =3D action[j].ltype; + + if (ltype !=3D NPC_LT_LC_IP && + ltype !=3D NPC_LT_LC_IP6 && + ltype !=3D NPC_LT_LC_IP_OPT && + ltype !=3D NPC_LT_LC_IP6_EXT) + continue; + + flags =3D action[j].flags; + + switch (flags) { + case NPC_F_LC_U_IP_FRAG: + case NPC_F_LC_U_IP6_FRAG: + case NPC_F_LC_L_6TO4: + case NPC_F_LC_L_MPLS_IN_IP: + case NPC_F_LC_L_IP6_TUN_IP6: + case NPC_F_LC_L_IP6_MPLS_IN_IP: + action[j].flags =3D npc_map2cn20k_flag(flags); + break; + default: + break; + } + } + } +} + +int npc_cn20k_apply_custom_kpu(struct rvu *rvu, struct npc_kpu_profile_ada= pter *profile) +{ + size_t hdr_sz =3D sizeof(struct npc_cn20k_kpu_profile_fwdata), offset =3D= 0; + struct npc_cn20k_kpu_profile_fwdata *fw =3D rvu->kpu_fwdata; + struct npc_kpu_profile_action *action; + struct npc_kpu_profile_cam *cam; + struct npc_kpu_fwdata *fw_kpu; + u16 kpu, entry; + int entries; + + if (rvu->kpu_fwdata_sz < hdr_sz) { + dev_warn(rvu->dev, "Invalid KPU profile size\n"); + return -EINVAL; + } + + if (le64_to_cpu(fw->signature) !=3D KPU_SIGN) { + dev_warn(rvu->dev, "Invalid KPU profile signature %llx\n", + fw->signature); + return -EINVAL; + } + + /* Verify if the using known profile structure */ + if (NPC_KPU_VER_MAJ(profile->version) > + NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER)) { + dev_warn(rvu->dev, "Not supported Major version: %d > %d\n", + NPC_KPU_VER_MAJ(profile->version), + NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER)); + return -EINVAL; + } + + /* Verify if profile is aligned with the required kernel changes */ + if (NPC_KPU_VER_MIN(profile->version) < + NPC_KPU_VER_MIN(NPC_KPU_PROFILE_VER)) { + dev_warn(rvu->dev, + "Invalid KPU profile version: %d.%d.%d expected version <=3D %d.%d.%d\= n", + NPC_KPU_VER_MAJ(profile->version), + NPC_KPU_VER_MIN(profile->version), + NPC_KPU_VER_PATCH(profile->version), + NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER), + NPC_KPU_VER_MIN(NPC_KPU_PROFILE_VER), + NPC_KPU_VER_PATCH(NPC_KPU_PROFILE_VER)); + return -EINVAL; + } + + /* Verify if profile fits the HW */ + if (fw->kpus > profile->kpus) { + dev_warn(rvu->dev, "Not enough KPUs: %d > %ld\n", fw->kpus, + profile->kpus); + return -EINVAL; + } + + profile->mcam_kex_prfl.mkex_extr =3D &fw->mkex; + if (profile->mcam_kex_prfl.mkex_extr->mkex_sign !=3D MKEX_CN20K_SIGN) { + dev_warn(rvu->dev, "Invalid MKEX profile signature:%llx\n", + profile->mcam_kex_prfl.mkex_extr->mkex_sign); + return -EINVAL; + } + + profile->custom =3D 1; + profile->name =3D fw->name; + profile->version =3D le64_to_cpu(fw->version); + profile->lt_def =3D &fw->lt_def; + + for (kpu =3D 0; kpu < fw->kpus; kpu++) { + fw_kpu =3D (struct npc_kpu_fwdata *)(fw->data + offset); + if (fw_kpu->entries > KPU_CN20K_MAX_CST_ENT) + dev_warn(rvu->dev, + "Too many custom entries on KPU%d: %d > %d\n", + kpu, fw_kpu->entries, KPU_CN20K_MAX_CST_ENT); + entries =3D min(fw_kpu->entries, KPU_CN20K_MAX_CST_ENT); + cam =3D (struct npc_kpu_profile_cam *)fw_kpu->data; + offset +=3D sizeof(*fw_kpu) + fw_kpu->entries * sizeof(*cam); + action =3D (struct npc_kpu_profile_action *)(fw->data + offset); + offset +=3D fw_kpu->entries * sizeof(*action); + if (rvu->kpu_fwdata_sz < hdr_sz + offset) { + dev_warn(rvu->dev, + "Profile size mismatch on KPU%i parsing.\n", + kpu + 1); + return -EINVAL; + } + + npc_cn20k_update_action_entries_n_flags(rvu, profile); + + for (entry =3D 0; entry < entries; entry++) { + profile->kpu[kpu].cam[entry] =3D cam[entry]; + profile->kpu[kpu].action[entry] =3D action[entry]; + } + } + + return 0; +} + static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank = *sb, u16 sub_off, u16 *mcam_idx) { @@ -1896,6 +2167,37 @@ rvu_mbox_handler_npc_cn20k_get_free_count(struct rvu= *rvu, return 0; } =20 +int rvu_mbox_handler_npc_cn20k_get_kex_cfg(struct rvu *rvu, + struct msg_req *req, + struct npc_cn20k_get_kex_cfg_rsp *rsp) +{ + int extr, lt; + + rsp->rx_keyx_cfg =3D CN20K_GET_KEX_CFG(NIX_INTF_RX); + rsp->tx_keyx_cfg =3D CN20K_GET_KEX_CFG(NIX_INTF_TX); + + /* Get EXTRACTOR LID */ + for (extr =3D 0; extr < NPC_MAX_EXTRACTOR; extr++) { + rsp->intf_extr_lid[NIX_INTF_RX][extr] =3D + CN20K_GET_EXTR_LID(NIX_INTF_RX, extr); + rsp->intf_extr_lid[NIX_INTF_TX][extr] =3D + CN20K_GET_EXTR_LID(NIX_INTF_TX, extr); + } + + /* Get EXTRACTOR LTYPE */ + for (extr =3D 0; extr < NPC_MAX_EXTRACTOR; extr++) { + for (lt =3D 0; lt < NPC_MAX_LT; lt++) { + rsp->intf_extr_lt[NIX_INTF_RX][extr][lt] =3D + CN20K_GET_EXTR_LT(NIX_INTF_RX, extr, lt); + rsp->intf_extr_lt[NIX_INTF_TX][extr][lt] =3D + CN20K_GET_EXTR_LT(NIX_INTF_TX, extr, lt); + } + } + + memcpy(rsp->mkex_pfl_name, rvu->mkex_pfl_name, MKEX_NAME_LEN); + return 0; +} + static void npc_lock_all_subbank(void) { int i; @@ -2169,6 +2471,23 @@ int npc_cn20k_deinit(struct rvu *rvu) return 0; } =20 +static int npc_setup_mcam_section(struct rvu *rvu, int key_type) +{ + int blkaddr, sec; + + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (blkaddr < 0) { + dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__); + return -ENODEV; + } + + for (sec =3D 0; sec < npc_priv.num_subbanks; sec++) + rvu_write64(rvu, blkaddr, + NPC_AF_MCAM_SECTIONX_CFG_EXT(sec), key_type); + + return 0; +} + int npc_cn20k_init(struct rvu *rvu) { int err; @@ -2180,6 +2499,13 @@ int npc_cn20k_init(struct rvu *rvu) return err; } =20 + err =3D npc_setup_mcam_section(rvu, NPC_MCAM_KEY_X2); + if (err) { + dev_err(rvu->dev, "%s: mcam section configuration failure\n", + __func__); + return err; + } + npc_priv.init_done =3D true; =20 return 0; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.h index 24a70f9aaec2..ad660a920abd 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h @@ -8,10 +8,76 @@ #ifndef NPC_CN20K_H #define NPC_CN20K_H =20 +#define MKEX_CN20K_SIGN 0x19bbfdbd160 + #define MAX_NUM_BANKS 2 #define MAX_NUM_SUB_BANKS 32 #define MAX_SUBBANK_DEPTH 256 =20 +#define CN20K_SET_EXTR_LT(intf, extr, ltype, cfg) \ + rvu_write64(rvu, BLKADDR_NPC, \ + NPC_AF_INTFX_EXTRACTORX_LTX_CFG(intf, extr, ltype), cfg) + +/* strtoull of "mkexprof" with base:36 */ +#define MKEX_END_SIGN 0xdeadbeef + +#define NPC_CN20K_BYTESM GENMASK_ULL(18, 16) +#define NPC_CN20K_PARSE_NIBBLE GENMASK_ULL(22, 0) +#define NPC_CN20K_TOTAL_NIBBLE 23 + +#define CN20K_GET_KEX_CFG(intf) \ + rvu_read64(rvu, BLKADDR_NPC, NPC_AF_INTFX_KEX_CFG(intf)) + +#define CN20K_GET_EXTR_LID(intf, extr) \ + rvu_read64(rvu, BLKADDR_NPC, \ + NPC_AF_INTFX_EXTRACTORX_CFG(intf, extr)) + +#define CN20K_SET_EXTR_LT(intf, extr, ltype, cfg) \ + rvu_write64(rvu, BLKADDR_NPC, \ + NPC_AF_INTFX_EXTRACTORX_LTX_CFG(intf, extr, ltype), cfg) + +#define CN20K_GET_EXTR_LT(intf, extr, ltype) \ + rvu_read64(rvu, BLKADDR_NPC, \ + NPC_AF_INTFX_EXTRACTORX_LTX_CFG(intf, extr, ltype)) + +/* NPC_PARSE_KEX_S nibble definitions for each field */ +#define NPC_CN20K_PARSE_NIBBLE_CHAN GENMASK_ULL(2, 0) +#define NPC_CN20K_PARSE_NIBBLE_ERRLEV BIT_ULL(3) +#define NPC_CN20K_PARSE_NIBBLE_ERRCODE GENMASK_ULL(5, 4) +#define NPC_CN20K_PARSE_NIBBLE_L2L3_BCAST BIT_ULL(6) +#define NPC_CN20K_PARSE_NIBBLE_LA_FLAGS BIT_ULL(7) +#define NPC_CN20K_PARSE_NIBBLE_LA_LTYPE BIT_ULL(8) +#define NPC_CN20K_PARSE_NIBBLE_LB_FLAGS BIT_ULL(9) +#define NPC_CN20K_PARSE_NIBBLE_LB_LTYPE BIT_ULL(10) +#define NPC_CN20K_PARSE_NIBBLE_LC_FLAGS BIT_ULL(11) +#define NPC_CN20K_PARSE_NIBBLE_LC_LTYPE BIT_ULL(12) +#define NPC_CN20K_PARSE_NIBBLE_LD_FLAGS BIT_ULL(13) +#define NPC_CN20K_PARSE_NIBBLE_LD_LTYPE BIT_ULL(14) +#define NPC_CN20K_PARSE_NIBBLE_LE_FLAGS BIT_ULL(15) +#define NPC_CN20K_PARSE_NIBBLE_LE_LTYPE BIT_ULL(16) +#define NPC_CN20K_PARSE_NIBBLE_LF_FLAGS BIT_ULL(17) +#define NPC_CN20K_PARSE_NIBBLE_LF_LTYPE BIT_ULL(18) +#define NPC_CN20K_PARSE_NIBBLE_LG_FLAGS BIT_ULL(19) +#define NPC_CN20K_PARSE_NIBBLE_LG_LTYPE BIT_ULL(20) +#define NPC_CN20K_PARSE_NIBBLE_LH_FLAGS BIT_ULL(21) +#define NPC_CN20K_PARSE_NIBBLE_LH_LTYPE BIT_ULL(22) + +/* Rx parse key extract nibble enable */ +#define NPC_CN20K_PARSE_NIBBLE_INTF_RX (NPC_CN20K_PARSE_NIBBLE_CHAN | \ + NPC_CN20K_PARSE_NIBBLE_L2L3_BCAST | \ + NPC_CN20K_PARSE_NIBBLE_LA_LTYPE | \ + NPC_CN20K_PARSE_NIBBLE_LB_LTYPE | \ + NPC_CN20K_PARSE_NIBBLE_LC_LTYPE | \ + NPC_CN20K_PARSE_NIBBLE_LD_LTYPE | \ + NPC_CN20K_PARSE_NIBBLE_LE_LTYPE) + +/* Tx parse key extract nibble enable */ +#define NPC_CN20K_PARSE_NIBBLE_INTF_TX (NPC_CN20K_PARSE_NIBBLE_LA_LTYPE | \ + NPC_CN20K_PARSE_NIBBLE_LB_LTYPE | \ + NPC_CN20K_PARSE_NIBBLE_LC_LTYPE | \ + NPC_CN20K_PARSE_NIBBLE_LD_LTYPE | \ + NPC_CN20K_PARSE_NIBBLE_LE_LTYPE) + enum npc_subbank_flag { NPC_SUBBANK_FLAG_UNINIT, // npc_subbank is not initialized yet. NPC_SUBBANK_FLAG_FREE =3D BIT(0), // No slot allocated @@ -99,6 +165,32 @@ struct npc_mcam_kex_extr { u64 intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT]; } __packed; =20 +struct npc_cn20k_kpu_profile_fwdata { +#define KPU_SIGN 0x00666f727075706b +#define KPU_NAME_LEN 32 + /** Maximum number of custom KPU entries supported by the built-in profil= e. */ +#define KPU_CN20K_MAX_CST_ENT 6 + /* KPU Profle Header */ + __le64 signature; /* "kpuprof\0" (8 bytes/ASCII characters) */ + u8 name[KPU_NAME_LEN]; /* KPU Profile name */ + __le64 version; /* KPU profile version */ + u8 kpus; + u8 reserved[7]; + + /* Default MKEX profile to be used with this KPU profile. May be + * overridden with mkex_profile module parameter. Format is same as for + * the MKEX profile to streamline processing. + */ + struct npc_mcam_kex_extr mkex; + /* LTYPE values for specific HW offloaded protocols. */ + struct npc_lt_def_cfg lt_def; + /* Dynamically sized data: + * Custom KPU CAM and ACTION configuration entries. + * struct npc_kpu_fwdata kpu[kpus]; + */ + u8 data[]; +} __packed; + struct rvu; =20 struct npc_priv_t *npc_priv_get(void); @@ -116,5 +208,10 @@ int npc_cn20k_search_order_set(struct rvu *rvu, int (*= arr)[2], int cnt); const int *npc_cn20k_search_order_get(bool *restricted_order); void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr); struct npc_mcam_kex_extr *npc_mkex_extr_default_get(void); +void npc_cn20k_load_mkex_profile(struct rvu *rvu, int blkaddr, const char = *mkex_profile); +int npc_cn20k_apply_custom_kpu(struct rvu *rvu, struct npc_kpu_profile_ada= pter *profile); =20 +void +npc_cn20k_update_action_entries_n_flags(struct rvu *rvu, + struct npc_kpu_profile_adapter *profile); #endif /* NPC_CN20K_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/reg.h index 073d4b815681..bf50d999528b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/reg.h @@ -80,18 +80,60 @@ #define RVU_MBOX_VF_VFAF_TRIGX(a) (0x2000 | (a) << 3) /* NPC registers */ #define NPC_AF_INTFX_EXTRACTORX_CFG(a, b) \ - (0x908000ull | (a) << 10 | (b) << 3) + (0x20c000ull | (a) << 16 | (b) << 8) #define NPC_AF_INTFX_EXTRACTORX_LTX_CFG(a, b, c) \ - (0x900000ull | (a) << 13 | (b) << 8 | (c) << 3) + (0x204000ull | (a) << 16 | (b) << 8 | (c) << 3) #define NPC_AF_KPMX_ENTRYX_CAMX(a, b, c) \ - (0x100000ull | (a) << 14 | (b) << 6 | (c) << 3) + (0x20000ull | (a) << 12 | (b) << 3 | (c) << 16) #define NPC_AF_KPMX_ENTRYX_ACTION0(a, b) \ - (0x100020ull | (a) << 14 | (b) << 6) + (0x40000ull | (a) << 12 | (b) << 3) #define NPC_AF_KPMX_ENTRYX_ACTION1(a, b) \ - (0x100028ull | (a) << 14 | (b) << 6) -#define NPC_AF_KPMX_ENTRY_DISX(a, b) (0x180000ull | (a) << 6 | (b) << 3) -#define NPC_AF_KPM_PASS2_CFG 0x580 -#define NPC_AF_KPMX_PASS2_OFFSET(a) (0x190000ull | (a) << 3) -#define NPC_AF_MCAM_SECTIONX_CFG_EXT(a) (0xC000000ull | (a) << 3) + (0x50000ull | (a) << 12 | (b) << 3) +#define NPC_AF_KPMX_ENTRY_DISX(a, b) (0x60000ull | (a) << 12 | (b) << 3) +#define NPC_AF_KPM_PASS2_CFG 0x10210 +#define NPC_AF_KPMX_PASS2_OFFSET(a) (0x60040ull | (a) << 12) +#define NPC_AF_MCAM_SECTIONX_CFG_EXT(a) (0xf000000ull | (a) << 3) + +#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(a, b, c) ({ \ + u64 offset; \ + offset =3D (0x8000000ull | (a) << 4 | (b) << 20 | (c) << 3); \ + offset; }) + +#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(a, b, c) ({ \ + u64 offset; \ + offset =3D (0x9000000ull | (a) << 4 | (b) << 20 | (c) << 3); \ + offset; }) + +#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(a, b, c) ({ \ + u64 offset; \ + offset =3D (0x9400000ull | (a) << 4 | (b) << 20 | (c) << 3); \ + offset; }) + +#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(a, b, c) ({ \ + u64 offset; \ + offset =3D (0x9800000ull | (a) << 4 | (b) << 20 | (c) << 3); \ + offset; }) + +#define NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(a, b, c) ({ \ + u64 offset; \ + offset =3D (0x9c00000ull | (a) << 4 | (b) << 20 | (c) << 3); \ + offset; }) + +#define NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(a, b) ({ \ + u64 offset; \ + offset =3D (0xa000000ull | (a) << 4 | (b) << 20); \ + offset; }) + +#define NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(a, b, c) ({ \ + u64 offset; \ + offset =3D (0xc000000ull | (a) << 4 | (b) << 20 | (c) << 22); \ + offset; }) + +#define NPC_AF_INTFX_MISS_ACTX(a, b) (0xf003000 | (a) << 6 | (b) << 4) + +#define NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(a, b) ({ \ + u64 offset; \ + offset =3D (0xb000000ull | (a) << 4 | (b) << 20); \ + offset; }) =20 #endif /* RVU_MBOX_REG_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net= /ethernet/marvell/octeontx2/af/mbox.h index 73a341980f9e..2b413c99a841 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -285,6 +285,8 @@ M(NPC_GET_FIELD_STATUS, 0x6014, npc_get_field_status, = \ npc_get_field_status_rsp) \ M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6015, npc_cn20k_get_free_count, \ msg_req, npc_cn20k_get_free_count_rsp) \ +M(NPC_CN20K_GET_KEX_CFG, 0x6016, npc_cn20k_get_kex_cfg, \ + msg_req, npc_cn20k_get_kex_cfg_rsp) \ /* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \ M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \ nix_lf_alloc_req, nix_lf_alloc_rsp) \ @@ -1559,7 +1561,7 @@ struct npc_mcam_free_entry_req { }; =20 struct mcam_entry { -#define NPC_MAX_KWS_IN_KEY 7 /* Number of keywords in max keywidth */ +#define NPC_MAX_KWS_IN_KEY 8 /* Number of keywords in max keywidth */ u64 kw[NPC_MAX_KWS_IN_KEY]; u64 kw_mask[NPC_MAX_KWS_IN_KEY]; u64 action; @@ -1663,6 +1665,19 @@ struct npc_get_kex_cfg_rsp { u8 mkex_pfl_name[MKEX_NAME_LEN]; }; =20 +struct npc_cn20k_get_kex_cfg_rsp { + struct mbox_msghdr hdr; + u64 rx_keyx_cfg; /* NPC_AF_INTF(0)_KEX_CFG */ + u64 tx_keyx_cfg; /* NPC_AF_INTF(1)_KEX_CFG */ +#define NPC_MAX_EXTRACTOR 24 + /* MKEX Extractor data */ + u64 intf_extr_lid[NPC_MAX_INTF][NPC_MAX_EXTRACTOR]; + /* KEX configuration per extractor */ + u64 intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT]; +#define MKEX_NAME_LEN 128 + u8 mkex_pfl_name[MKEX_NAME_LEN]; +}; + struct ptp_get_cap_rsp { struct mbox_msghdr hdr; #define PTP_CAP_HW_ATOMIC_UPDATE BIT_ULL(0) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/= ethernet/marvell/octeontx2/af/npc.h index 6c3aca6f278d..cb05ec69e0b3 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h @@ -429,6 +429,7 @@ struct nix_rx_action { =20 /* NPC_AF_INTFX_KEX_CFG field masks */ #define NPC_PARSE_NIBBLE GENMASK_ULL(30, 0) +#define NPC_TOTAL_NIBBLE 31 =20 /* NPC_PARSE_KEX_S nibble definitions for each field */ #define NPC_PARSE_NIBBLE_CHAN GENMASK_ULL(2, 0) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h b/driv= ers/net/ethernet/marvell/octeontx2/af/npc_profile.h index 561b01fcdbde..db74f7fdf028 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h @@ -321,6 +321,18 @@ enum npc_kpu_lb_lflag { NPC_F_LB_L_FDSA, }; =20 +enum npc_cn20k_kpu_lc_uflag { + NPC_CN20K_F_LC_U_MPLS_IN_IP =3D 0x20, + NPC_CN20K_F_LC_U_IP6_TUN_IP6 =3D 0x40, + NPC_CN20K_F_LC_U_IP6_MPLS_IN_IP =3D 0x80, +}; + +enum npc_cn20k_kpu_lc_lflag { + NPC_CN20K_F_LC_L_IP_FRAG =3D 2, + NPC_CN20K_F_LC_L_IP6_FRAG, + NPC_CN20K_F_LC_L_6TO4, +}; + enum npc_kpu_lc_uflag { NPC_F_LC_U_UNK_PROTO =3D 0x10, NPC_F_LC_U_IP_FRAG =3D 0x20, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/= ethernet/marvell/octeontx2/af/rvu.h index 14ca28ab493a..dd930aa05582 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -554,7 +554,11 @@ struct npc_kpu_profile_adapter { const struct npc_lt_def_cfg *lt_def; const struct npc_kpu_profile_action *ikpu; /* array[pkinds] */ const struct npc_kpu_profile *kpu; /* array[kpus] */ - struct npc_mcam_kex *mkex; + union npc_mcam_key_prfl { + struct npc_mcam_kex *mkex; + /* used for cn9k and cn10k */ + struct npc_mcam_kex_extr *mkex_extr; /* used for cn20k */ + } mcam_kex_prfl; struct npc_mcam_kex_hash *mkex_hash; bool custom; size_t pkinds; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.c index 133ae6421de7..8361d0aa4b6f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -1337,8 +1337,8 @@ static void npc_program_mkex_profile(struct rvu *rvu,= int blkaddr, npc_program_mkex_hash(rvu, blkaddr); } =20 -static int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_= addr, - u64 *size) +int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr, + u64 *size) { u64 prfl_addr, prfl_sz; =20 @@ -1394,7 +1394,7 @@ static void npc_load_mkex_profile(struct rvu *rvu, in= t blkaddr, */ if (!is_rvu_96xx_B0(rvu) || mcam_kex->keyx_cfg[NIX_INTF_RX] =3D=3D mcam_kex->keyx_cfg[NIX_INTF_= TX]) - rvu->kpu.mkex =3D mcam_kex; + rvu->kpu.mcam_kex_prfl.mkex =3D mcam_kex; goto program_mkex; } =20 @@ -1404,9 +1404,10 @@ static void npc_load_mkex_profile(struct rvu *rvu, i= nt blkaddr, dev_warn(dev, "Failed to load requested profile: %s\n", mkex_profile); =20 program_mkex: - dev_info(rvu->dev, "Using %s mkex profile\n", rvu->kpu.mkex->name); + dev_info(rvu->dev, "Using %s mkex profile\n", + rvu->kpu.mcam_kex_prfl.mkex->name); /* Program selected mkex profile */ - npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mkex); + npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mcam_kex_prfl.mkex); if (mkex_prfl_addr) iounmap(mkex_prfl_addr); } @@ -1525,7 +1526,8 @@ static void npc_program_kpu_profile(struct rvu *rvu, = int blkaddr, int kpu, rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(kpu), 0x01); } =20 -static int npc_prepare_default_kpu(struct npc_kpu_profile_adapter *profile) +static void npc_prepare_default_kpu(struct rvu *rvu, + struct npc_kpu_profile_adapter *profile) { profile->custom =3D 0; profile->name =3D def_pfl_name; @@ -1535,23 +1537,38 @@ static int npc_prepare_default_kpu(struct npc_kpu_p= rofile_adapter *profile) profile->kpu =3D npc_kpu_profiles; profile->kpus =3D ARRAY_SIZE(npc_kpu_profiles); profile->lt_def =3D &npc_lt_defaults; - profile->mkex =3D &npc_mkex_default; profile->mkex_hash =3D &npc_mkex_hash_default; =20 - return 0; + if (!is_cn20k(rvu->pdev)) { + profile->mcam_kex_prfl.mkex =3D &npc_mkex_default; + return; + } + + profile->mcam_kex_prfl.mkex_extr =3D npc_mkex_extr_default_get(); + ikpu_action_entries[NPC_RX_CPT_HDR_PKIND].offset =3D 6; + ikpu_action_entries[NPC_RX_CPT_HDR_PKIND].mask =3D 0xe0; + ikpu_action_entries[NPC_RX_CPT_HDR_PKIND].shift =3D 0x5; + ikpu_action_entries[NPC_RX_CPT_HDR_PKIND].right =3D 0x1; + + npc_cn20k_update_action_entries_n_flags(rvu, profile); } =20 static int npc_apply_custom_kpu(struct rvu *rvu, struct npc_kpu_profile_adapter *profile) { size_t hdr_sz =3D sizeof(struct npc_kpu_profile_fwdata), offset =3D 0; - struct npc_kpu_profile_fwdata *fw =3D rvu->kpu_fwdata; struct npc_kpu_profile_action *action; + struct npc_kpu_profile_fwdata *fw; struct npc_kpu_profile_cam *cam; struct npc_kpu_fwdata *fw_kpu; int entries; u16 kpu, entry; =20 + if (is_cn20k(rvu->pdev)) + return npc_cn20k_apply_custom_kpu(rvu, profile); + + fw =3D rvu->kpu_fwdata; + if (rvu->kpu_fwdata_sz < hdr_sz) { dev_warn(rvu->dev, "Invalid KPU profile size\n"); return -EINVAL; @@ -1592,7 +1609,7 @@ static int npc_apply_custom_kpu(struct rvu *rvu, profile->custom =3D 1; profile->name =3D fw->name; profile->version =3D le64_to_cpu(fw->version); - profile->mkex =3D &fw->mkex; + profile->mcam_kex_prfl.mkex =3D &fw->mkex; profile->lt_def =3D &fw->lt_def; =20 for (kpu =3D 0; kpu < fw->kpus; kpu++) { @@ -1717,7 +1734,7 @@ void npc_load_kpu_profile(struct rvu *rvu) if (!strncmp(kpu_profile, def_pfl_name, KPU_NAME_LEN)) goto revert_to_default; /* First prepare default KPU, then we'll customize top entries. */ - npc_prepare_default_kpu(profile); + npc_prepare_default_kpu(rvu, profile); =20 /* Order of preceedence for load loading NPC profile (high to low) * Firmware binary in filesystem. @@ -1780,7 +1797,7 @@ void npc_load_kpu_profile(struct rvu *rvu) return; =20 revert_to_default: - npc_prepare_default_kpu(profile); + npc_prepare_default_kpu(rvu, profile); } =20 static void npc_parser_profile_init(struct rvu *rvu, int blkaddr) @@ -2029,12 +2046,21 @@ static void rvu_npc_hw_init(struct rvu *rvu, int bl= kaddr) =20 static void rvu_npc_setup_interfaces(struct rvu *rvu, int blkaddr) { - struct npc_mcam_kex *mkex =3D rvu->kpu.mkex; + struct npc_mcam_kex_extr *mkex_extr =3D rvu->kpu.mcam_kex_prfl.mkex_extr; + struct npc_mcam_kex *mkex =3D rvu->kpu.mcam_kex_prfl.mkex; struct npc_mcam *mcam =3D &rvu->hw->mcam; struct rvu_hwinfo *hw =3D rvu->hw; u64 nibble_ena, rx_kex, tx_kex; + u64 *keyx_cfg; u8 intf; =20 + if (is_cn20k(rvu->pdev)) { + keyx_cfg =3D mkex_extr->keyx_cfg; + goto skip_miss_cntr; + } + + keyx_cfg =3D mkex->keyx_cfg; + /* Reserve last counter for MCAM RX miss action which is set to * drop packet. This way we will know how many pkts didn't match * any MCAM entry. @@ -2042,15 +2068,17 @@ static void rvu_npc_setup_interfaces(struct rvu *rv= u, int blkaddr) mcam->counters.max--; mcam->rx_miss_act_cntr =3D mcam->counters.max; =20 - rx_kex =3D mkex->keyx_cfg[NIX_INTF_RX]; - tx_kex =3D mkex->keyx_cfg[NIX_INTF_TX]; +skip_miss_cntr: + rx_kex =3D keyx_cfg[NIX_INTF_RX]; + tx_kex =3D keyx_cfg[NIX_INTF_TX]; + nibble_ena =3D FIELD_GET(NPC_PARSE_NIBBLE, rx_kex); =20 nibble_ena =3D rvu_npc_get_tx_nibble_cfg(rvu, nibble_ena); if (nibble_ena) { tx_kex &=3D ~NPC_PARSE_NIBBLE; tx_kex |=3D FIELD_PREP(NPC_PARSE_NIBBLE, nibble_ena); - mkex->keyx_cfg[NIX_INTF_TX] =3D tx_kex; + keyx_cfg[NIX_INTF_TX] =3D tx_kex; } =20 /* Configure RX interfaces */ @@ -2062,6 +2090,9 @@ static void rvu_npc_setup_interfaces(struct rvu *rvu,= int blkaddr) rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf), rx_kex); =20 + if (is_cn20k(rvu->pdev)) + continue; + /* If MCAM lookup doesn't result in a match, drop the received * packet. And map this action to a counter to count dropped * packets. @@ -2167,7 +2198,10 @@ int rvu_npc_init(struct rvu *rvu) =20 npc_config_secret_key(rvu, blkaddr); /* Configure MKEX profile */ - npc_load_mkex_profile(rvu, blkaddr, rvu->mkex_pfl_name); + if (is_cn20k(rvu->pdev)) + npc_cn20k_load_mkex_profile(rvu, blkaddr, rvu->mkex_pfl_name); + else + npc_load_mkex_profile(rvu, blkaddr, rvu->mkex_pfl_name); =20 err =3D npc_mcam_rsrcs_init(rvu, blkaddr); if (err) @@ -2177,7 +2211,10 @@ int rvu_npc_init(struct rvu *rvu) if (err) { dev_err(rvu->dev, "Incorrect mkex profile loaded using default mkex\n"); - npc_load_mkex_profile(rvu, blkaddr, def_pfl_name); + if (is_cn20k(rvu->pdev)) + npc_cn20k_load_mkex_profile(rvu, blkaddr, def_pfl_name); + else + npc_load_mkex_profile(rvu, blkaddr, def_pfl_name); } =20 if (is_cn20k(rvu->pdev)) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.h index 80c63618ec47..346e6ada158e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h @@ -13,5 +13,7 @@ void npc_load_kpu_profile(struct rvu *rvu); void npc_config_kpuaction(struct rvu *rvu, int blkaddr, const struct npc_kpu_profile_action *kpuaction, int kpu, int entry, bool pkind); +int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr, + u64 *size); =20 #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 b56395ac5a74..02b6c7294bcb 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -12,6 +12,8 @@ #include "npc.h" #include "rvu_npc_fs.h" #include "rvu_npc_hash.h" +#include "cn20k/reg.h" +#include "cn20k/npc.h" =20 static const char * const npc_flow_names[] =3D { [NPC_DMAC] =3D "dmac", @@ -81,19 +83,26 @@ const char *npc_get_field_name(u8 hdr) /* Compute keyword masks and figure out the number of keywords a field * spans in the key. */ -static void npc_set_kw_masks(struct npc_mcam *mcam, u8 type, +static void npc_set_kw_masks(struct rvu *rvu, struct npc_mcam *mcam, u8 ty= pe, u8 nr_bits, int start_kwi, int offset, u8 intf) { struct npc_key_field *field =3D &mcam->rx_key_fields[type]; u8 bits_in_kw; int max_kwi; =20 - if (mcam->banks_per_entry =3D=3D 1) - max_kwi =3D 1; /* NPC_MCAM_KEY_X1 */ - else if (mcam->banks_per_entry =3D=3D 2) - max_kwi =3D 3; /* NPC_MCAM_KEY_X2 */ - else - max_kwi =3D 6; /* NPC_MCAM_KEY_X4 */ + if (is_cn20k(rvu->pdev)) { + if (mcam->banks_per_entry =3D=3D 1) + max_kwi =3D 3; /* NPC_MCAM_KEY_X2 */ + else + max_kwi =3D 7; /* NPC_MCAM_KEY_X4 */ + } else { + if (mcam->banks_per_entry =3D=3D 1) + max_kwi =3D 1; /* NPC_MCAM_KEY_X1 */ + else if (mcam->banks_per_entry =3D=3D 2) + max_kwi =3D 3; /* NPC_MCAM_KEY_X2 */ + else + max_kwi =3D 6; /* NPC_MCAM_KEY_X4 */ + } =20 if (is_npc_intf_tx(intf)) field =3D &mcam->tx_key_fields[type]; @@ -155,7 +164,8 @@ static bool npc_is_same(struct npc_key_field *input, sizeof(struct npc_layer_mdata)) =3D=3D 0; } =20 -static void npc_set_layer_mdata(struct npc_mcam *mcam, enum key_fields typ= e, +static void npc_set_layer_mdata(struct rvu *rvu, + struct npc_mcam *mcam, enum key_fields type, u64 cfg, u8 lid, u8 lt, u8 intf) { struct npc_key_field *input =3D &mcam->rx_key_fields[type]; @@ -165,13 +175,17 @@ static void npc_set_layer_mdata(struct npc_mcam *mcam= , enum key_fields type, =20 input->layer_mdata.hdr =3D FIELD_GET(NPC_HDR_OFFSET, cfg); input->layer_mdata.key =3D FIELD_GET(NPC_KEY_OFFSET, cfg); - input->layer_mdata.len =3D FIELD_GET(NPC_BYTESM, cfg) + 1; + if (is_cn20k(rvu->pdev)) + input->layer_mdata.len =3D FIELD_GET(NPC_CN20K_BYTESM, cfg) + 1; + else + input->layer_mdata.len =3D FIELD_GET(NPC_BYTESM, cfg) + 1; input->layer_mdata.ltype =3D lt; input->layer_mdata.lid =3D lid; } =20 static bool npc_check_overlap_fields(struct npc_key_field *input1, - struct npc_key_field *input2) + struct npc_key_field *input2, + int max_kw) { int kwi; =20 @@ -182,7 +196,7 @@ static bool npc_check_overlap_fields(struct npc_key_fie= ld *input1, input1->layer_mdata.ltype !=3D input2->layer_mdata.ltype) return false; =20 - for (kwi =3D 0; kwi < NPC_MAX_KWS_IN_KEY; kwi++) { + for (kwi =3D 0; kwi < max_kw; kwi++) { if (input1->kw_mask[kwi] & input2->kw_mask[kwi]) return true; } @@ -202,6 +216,7 @@ static bool npc_check_overlap(struct rvu *rvu, int blka= ddr, struct npc_key_field *dummy, *input; int start_kwi, offset; u8 nr_bits, lid, lt, ld; + int extr; u64 cfg; =20 dummy =3D &mcam->rx_key_fields[NPC_UNKNOWN]; @@ -212,6 +227,9 @@ static bool npc_check_overlap(struct rvu *rvu, int blka= ddr, input =3D &mcam->tx_key_fields[type]; } =20 + if (is_cn20k(rvu->pdev)) + goto skip_cn10k_config; + for (lid =3D start_lid; lid < NPC_MAX_LID; lid++) { for (lt =3D 0; lt < NPC_MAX_LT; lt++) { for (ld =3D 0; ld < NPC_MAX_LD; ld++) { @@ -221,7 +239,7 @@ static bool npc_check_overlap(struct rvu *rvu, int blka= ddr, if (!FIELD_GET(NPC_LDATA_EN, cfg)) continue; memset(dummy, 0, sizeof(struct npc_key_field)); - npc_set_layer_mdata(mcam, NPC_UNKNOWN, cfg, + npc_set_layer_mdata(rvu, mcam, NPC_UNKNOWN, cfg, lid, lt, intf); /* exclude input */ if (npc_is_same(input, dummy)) @@ -230,16 +248,47 @@ static bool npc_check_overlap(struct rvu *rvu, int bl= kaddr, offset =3D (dummy->layer_mdata.key * 8) % 64; nr_bits =3D dummy->layer_mdata.len * 8; /* form KW masks */ - npc_set_kw_masks(mcam, NPC_UNKNOWN, nr_bits, + npc_set_kw_masks(rvu, mcam, NPC_UNKNOWN, nr_bits, start_kwi, offset, intf); /* check any input field bits falls in any * other field bits. */ - if (npc_check_overlap_fields(dummy, input)) + if (npc_check_overlap_fields(dummy, input, + NPC_MAX_KWS_IN_KEY - 1)) return true; } } } + return false; + +skip_cn10k_config: + for (extr =3D 0 ; extr < rvu->hw->npc_kex_extr; extr++) { + lid =3D CN20K_GET_EXTR_LID(intf, extr); + if (lid < start_lid) + continue; + for (lt =3D 0; lt < NPC_MAX_LT; lt++) { + cfg =3D CN20K_GET_EXTR_LT(intf, extr, lt); + if (!FIELD_GET(NPC_LDATA_EN, cfg)) + continue; + + memset(dummy, 0, sizeof(struct npc_key_field)); + npc_set_layer_mdata(rvu, mcam, NPC_UNKNOWN, cfg, + lid, lt, intf); + /* exclude input */ + if (npc_is_same(input, dummy)) + continue; + start_kwi =3D dummy->layer_mdata.key / 8; + offset =3D (dummy->layer_mdata.key * 8) % 64; + nr_bits =3D dummy->layer_mdata.len * 8; + /* form KW masks */ + npc_set_kw_masks(rvu, mcam, NPC_UNKNOWN, nr_bits, + start_kwi, offset, intf); + /* check any input field bits falls in any other field bits */ + if (npc_check_overlap_fields(dummy, input, + NPC_MAX_KWS_IN_KEY)) + return true; + } + } =20 return false; } @@ -253,7 +302,8 @@ static bool npc_check_field(struct rvu *rvu, int blkadd= r, enum key_fields type, return true; } =20 -static void npc_scan_exact_result(struct npc_mcam *mcam, u8 bit_number, +static void npc_scan_exact_result(struct rvu *rvu, + struct npc_mcam *mcam, u8 bit_number, u8 key_nibble, u8 intf) { u8 offset =3D (key_nibble * 4) % 64; /* offset within key word */ @@ -269,10 +319,63 @@ static void npc_scan_exact_result(struct npc_mcam *mc= am, u8 bit_number, default: return; } - npc_set_kw_masks(mcam, type, nr_bits, kwi, offset, intf); + npc_set_kw_masks(rvu, mcam, type, nr_bits, kwi, offset, intf); +} + +static void npc_cn20k_scan_parse_result(struct rvu *rvu, struct npc_mcam *= mcam, + u8 bit_number, u8 key_nibble, u8 intf) +{ + u8 offset =3D (key_nibble * 4) % 64; /* offset within key word */ + u8 kwi =3D (key_nibble * 4) / 64; /* which word in key */ + u8 nr_bits =3D 4; /* bits in a nibble */ + u8 type; + + switch (bit_number) { + case 0 ... 2: + type =3D NPC_CHAN; + break; + case 3: + type =3D NPC_ERRLEV; + break; + case 4 ... 5: + type =3D NPC_ERRCODE; + break; + case 6: + type =3D NPC_LXMB; + break; + case 8: + type =3D NPC_LA; + break; + case 10: + type =3D NPC_LB; + break; + case 12: + type =3D NPC_LC; + break; + case 14: + type =3D NPC_LD; + break; + case 16: + type =3D NPC_LE; + break; + case 18: + type =3D NPC_LF; + break; + case 20: + type =3D NPC_LG; + break; + case 22: + type =3D NPC_LH; + break; + default: + return; + } + + npc_set_kw_masks(rvu, mcam, type, nr_bits, kwi, offset, intf); } =20 -static void npc_scan_parse_result(struct npc_mcam *mcam, u8 bit_number, +static void npc_scan_parse_result(struct rvu *rvu, + struct npc_mcam *mcam, u8 bit_number, u8 key_nibble, u8 intf) { u8 offset =3D (key_nibble * 4) % 64; /* offset within key word */ @@ -280,6 +383,12 @@ static void npc_scan_parse_result(struct npc_mcam *mca= m, u8 bit_number, u8 nr_bits =3D 4; /* bits in a nibble */ u8 type; =20 + if (is_cn20k(rvu->pdev)) { + npc_cn20k_scan_parse_result(rvu, mcam, bit_number, + key_nibble, intf); + return; + } + switch (bit_number) { case 0 ... 2: type =3D NPC_CHAN; @@ -322,7 +431,7 @@ static void npc_scan_parse_result(struct npc_mcam *mcam= , u8 bit_number, return; } =20 - npc_set_kw_masks(mcam, type, nr_bits, kwi, offset, intf); + npc_set_kw_masks(rvu, mcam, type, nr_bits, kwi, offset, intf); } =20 static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8= intf) @@ -343,8 +452,13 @@ static void npc_handle_multi_layer_fields(struct rvu *= rvu, int blkaddr, u8 intf) /* Inner VLAN TCI for double tagged frames */ struct npc_key_field *vlan_tag3; u64 *features; + int i, max_kw; u8 start_lid; - int i; + + if (is_cn20k(rvu->pdev)) + max_kw =3D NPC_MAX_KWS_IN_KEY; + else + max_kw =3D NPC_MAX_KWS_IN_KEY - 1; =20 key_fields =3D mcam->rx_key_fields; features =3D &mcam->rx_features; @@ -382,7 +496,7 @@ static void npc_handle_multi_layer_fields(struct rvu *r= vu, int blkaddr, u8 intf) =20 /* if key profile programmed extracts Ethertype from multiple layers */ if (etype_ether->nr_kws && etype_tag1->nr_kws) { - for (i =3D 0; i < NPC_MAX_KWS_IN_KEY; i++) { + for (i =3D 0; i < max_kw; i++) { if (etype_ether->kw_mask[i] !=3D etype_tag1->kw_mask[i]) { dev_err(rvu->dev, "mkex: Etype pos is different for untagged and tagge= d pkts.\n"); goto vlan_tci; @@ -391,7 +505,7 @@ static void npc_handle_multi_layer_fields(struct rvu *r= vu, int blkaddr, u8 intf) key_fields[NPC_ETYPE] =3D *etype_tag1; } if (etype_ether->nr_kws && etype_tag2->nr_kws) { - for (i =3D 0; i < NPC_MAX_KWS_IN_KEY; i++) { + for (i =3D 0; i < max_kw; i++) { if (etype_ether->kw_mask[i] !=3D etype_tag2->kw_mask[i]) { dev_err(rvu->dev, "mkex: Etype pos is different for untagged and doubl= e tagged pkts.\n"); goto vlan_tci; @@ -400,7 +514,7 @@ static void npc_handle_multi_layer_fields(struct rvu *r= vu, int blkaddr, u8 intf) key_fields[NPC_ETYPE] =3D *etype_tag2; } if (etype_tag1->nr_kws && etype_tag2->nr_kws) { - for (i =3D 0; i < NPC_MAX_KWS_IN_KEY; i++) { + for (i =3D 0; i < max_kw; i++) { if (etype_tag1->kw_mask[i] !=3D etype_tag2->kw_mask[i]) { dev_err(rvu->dev, "mkex: Etype pos is different for tagged and double = tagged pkts.\n"); goto vlan_tci; @@ -431,7 +545,7 @@ static void npc_handle_multi_layer_fields(struct rvu *r= vu, int blkaddr, u8 intf) =20 /* if key profile extracts outer vlan tci from multiple layers */ if (vlan_tag1->nr_kws && vlan_tag2->nr_kws) { - for (i =3D 0; i < NPC_MAX_KWS_IN_KEY; i++) { + for (i =3D 0; i < max_kw; i++) { if (vlan_tag1->kw_mask[i] !=3D vlan_tag2->kw_mask[i]) { dev_err(rvu->dev, "mkex: Out vlan tci pos is different for tagged and = double tagged pkts.\n"); goto done; @@ -466,7 +580,10 @@ static void npc_scan_ldata(struct rvu *rvu, int blkadd= r, u8 lid, /* starting KW index and starting bit position */ int start_kwi, offset; =20 - nr_bytes =3D FIELD_GET(NPC_BYTESM, cfg) + 1; + if (is_cn20k(rvu->pdev)) + nr_bytes =3D FIELD_GET(NPC_BYTESM, cfg) + 1; + else + nr_bytes =3D FIELD_GET(NPC_CN20K_BYTESM, cfg) + 1; hdr =3D FIELD_GET(NPC_HDR_OFFSET, cfg); key =3D FIELD_GET(NPC_KEY_OFFSET, cfg); =20 @@ -489,11 +606,12 @@ do { \ if ((hstart) >=3D hdr && \ ((hstart) + (hlen)) <=3D (hdr + nr_bytes)) { \ bit_offset =3D (hdr + nr_bytes - (hstart) - (hlen)) * 8; \ - npc_set_layer_mdata(mcam, (name), cfg, lid, lt, intf); \ + npc_set_layer_mdata(rvu, mcam, (name), cfg, lid, lt, \ + intf); \ offset +=3D bit_offset; \ start_kwi +=3D offset / 64; \ offset %=3D 64; \ - npc_set_kw_masks(mcam, (name), (hlen) * 8, \ + npc_set_kw_masks(rvu, mcam, (name), (hlen) * 8, \ start_kwi, offset, intf); \ } \ } \ @@ -636,6 +754,7 @@ static int npc_scan_kex(struct rvu *rvu, int blkaddr, u= 8 intf) u8 lid, lt, ld, bitnr; u64 cfg, masked_cfg; u8 key_nibble =3D 0; + int extr; =20 /* Scan and note how parse result is going to be in key. * A bit set in PARSE_NIBBLE_ENA corresponds to a nibble from @@ -643,10 +762,22 @@ static int npc_scan_kex(struct rvu *rvu, int blkaddr,= u8 intf) * will be concatenated in key. */ cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf)); - masked_cfg =3D cfg & NPC_PARSE_NIBBLE; - for_each_set_bit(bitnr, (unsigned long *)&masked_cfg, 31) { - npc_scan_parse_result(mcam, bitnr, key_nibble, intf); - key_nibble++; + if (is_cn20k(rvu->pdev)) { + masked_cfg =3D cfg & NPC_CN20K_PARSE_NIBBLE; + for_each_set_bit(bitnr, (unsigned long *)&masked_cfg, + NPC_CN20K_TOTAL_NIBBLE) { + npc_scan_parse_result(rvu, mcam, bitnr, + key_nibble, intf); + key_nibble++; + } + } else { + masked_cfg =3D cfg & NPC_PARSE_NIBBLE; + for_each_set_bit(bitnr, (unsigned long *)&masked_cfg, + NPC_TOTAL_NIBBLE) { + npc_scan_parse_result(rvu, mcam, bitnr, + key_nibble, intf); + key_nibble++; + } } =20 /* Ignore exact match bits for mcam entries except the first rule @@ -656,10 +787,13 @@ static int npc_scan_kex(struct rvu *rvu, int blkaddr,= u8 intf) masked_cfg =3D cfg & NPC_EXACT_NIBBLE; bitnr =3D NPC_EXACT_NIBBLE_START; for_each_set_bit_from(bitnr, (unsigned long *)&masked_cfg, NPC_EXACT_NIBB= LE_END + 1) { - npc_scan_exact_result(mcam, bitnr, key_nibble, intf); + npc_scan_exact_result(rvu, mcam, bitnr, key_nibble, intf); key_nibble++; } =20 + if (is_cn20k(rvu->pdev)) + goto skip_cn10k_config; + /* Scan and note how layer data is going to be in key */ for (lid =3D 0; lid < NPC_MAX_LID; lid++) { for (lt =3D 0; lt < NPC_MAX_LT; lt++) { @@ -676,6 +810,19 @@ static int npc_scan_kex(struct rvu *rvu, int blkaddr, = u8 intf) } =20 return 0; + +skip_cn10k_config: + for (extr =3D 0 ; extr < rvu->hw->npc_kex_extr; extr++) { + lid =3D CN20K_GET_EXTR_LID(intf, extr); + for (lt =3D 0; lt < NPC_MAX_LT; lt++) { + cfg =3D CN20K_GET_EXTR_LT(intf, extr, lt); + if (!FIELD_GET(NPC_LDATA_EN, cfg)) + continue; + npc_scan_ldata(rvu, blkaddr, lid, lt, cfg, + intf); + } + } + return 0; } =20 static int npc_scan_verify_kex(struct rvu *rvu, int blkaddr) @@ -758,8 +905,8 @@ void npc_update_entry(struct rvu *rvu, enum key_fields = type, struct mcam_entry dummy =3D { {0} }; struct npc_key_field *field; u64 kw1, kw2, kw3; + int i, max_kw; u8 shift; - int i; =20 field =3D &mcam->rx_key_fields[type]; if (is_npc_intf_tx(intf)) @@ -768,7 +915,12 @@ void npc_update_entry(struct rvu *rvu, enum key_fields= type, if (!field->nr_kws) return; =20 - for (i =3D 0; i < NPC_MAX_KWS_IN_KEY; i++) { + if (is_cn20k(rvu->pdev)) + max_kw =3D NPC_MAX_KWS_IN_KEY; + else + max_kw =3D NPC_MAX_KWS_IN_KEY - 1; + + for (i =3D 0; i < max_kw; i++) { if (!field->kw_mask[i]) continue; /* place key value in kw[x] */ @@ -820,7 +972,7 @@ void npc_update_entry(struct rvu *rvu, enum key_fields = type, /* dummy is ready with values and masks for given key * field now clear and update input entry with those */ - for (i =3D 0; i < NPC_MAX_KWS_IN_KEY; i++) { + for (i =3D 0; i < max_kw; i++) { if (!field->kw_mask[i]) continue; entry->kw[i] &=3D ~field->kw_mask[i]; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c b/dri= vers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c index 999f6d93c7fe..5ae046c93a82 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c @@ -125,6 +125,9 @@ static void npc_program_mkex_hash_rx(struct rvu *rvu, i= nt blkaddr, struct npc_mcam_kex_hash *mkex_hash =3D rvu->kpu.mkex_hash; int lid, lt, ld, hash_cnt =3D 0; =20 + if (is_cn20k(rvu->pdev)) + return; + if (is_npc_intf_tx(intf)) return; =20 @@ -165,6 +168,9 @@ static void npc_program_mkex_hash_tx(struct rvu *rvu, i= nt blkaddr, struct npc_mcam_kex_hash *mkex_hash =3D rvu->kpu.mkex_hash; int lid, lt, ld, hash_cnt =3D 0; =20 + if (is_cn20k(rvu->pdev)) + return; + if (is_npc_intf_rx(intf)) return; =20 @@ -224,6 +230,9 @@ void npc_program_mkex_hash(struct rvu *rvu, int blkaddr) struct rvu_hwinfo *hw =3D rvu->hw; u64 cfg; =20 + if (is_cn20k(rvu->pdev)) + return; + /* Check if hardware supports hash extraction */ if (!hwcap->npc_hash_extract) return; @@ -288,6 +297,9 @@ void npc_update_field_hash(struct rvu *rvu, u8 intf, u32 field_hash; u8 hash_idx; =20 + if (is_cn20k(rvu->pdev)) + return; + if (!rvu->hw->cap.npc_hash_extract) { dev_dbg(rvu->dev, "%s: Field hash extract feature is not supported\n", _= _func__); return; @@ -1874,6 +1886,9 @@ int rvu_npc_exact_init(struct rvu *rvu) u64 cfg; bool rc; =20 + if (is_cn20k(rvu->pdev)) + return 0; + /* Read NPC_AF_CONST3 and check for have exact * match functionality is present */ --=20 2.43.0 From nobody Wed Jan 7 22:50:11 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 812A0311C0C; Mon, 5 Jan 2026 02:33:53 +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=1767580436; cv=none; b=Ox31yKLKSHUppJ+H2yJnVTw/QnZIMafoWG2OBEAI6BXc73AcWa7J8NjymImNtjN1+zCaEKt+hfmgihdeC9aiz6Kn4E7Xlx5nfrEwnSEb7n+RcFcuRtp25ndFrCGqoNa86gjcm/kbHZughczC7fM5bKp1rHHmk1iqgQGCVNau+n0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580436; c=relaxed/simple; bh=vLGVh64FBJwqOYlRiSaKVSQaUVauvsCTCVnD3VAq33I=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=eFwF9llo5spF8q4KGkPEtY92TzjAnThyzxUssOIyVu292o1oXqfk5/LntNtgyoFMhKGol7M5gjVH0dvSPBZW8GOzSYReqVRjc/JKB0PjBvalqkAYX2NGI/scYZxo/gSeZpp1Y63dA3z6UIs6cX6iz7+LqIEaaPiXD6iT5y1ogTI= 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=Y4kWIP3u; 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="Y4kWIP3u" 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 604Mf02C3322501; Sun, 4 Jan 2026 18:33:39 -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=j POwJYfzFyTI203gflQOnqShGIqcftCc6vmoia9mayc=; b=Y4kWIP3uwBfV5MQ5n zLxbj6Kk0zrlmfVQjahLzjHVtt9eDT14lddrkRizizicC7VGEpFqOS4LKAfWaZG/ Jpgfw77mmDA9AtBjMMfcLyLy3ihmNH08d0CSupQjgTub8X0XH866UXH8TzZ6PJPF imSzP+dXwogXqJcL3G4ecO+9Higl5IMcArHCf9eVKOOPmB/SLXK6Z5xzi6mBSRIx RHTN4ZBP3tEPcGbHhTmGmtosB4SeALxuYretCKdeEYiKLt/66BIZltTmgf3h1r1V GzLnjMdAwIus1UxTc22NHVSw4LwQt27tBOzeINNI7LKkxuS1nXefrjopEU4G7esg nzFSA== Received: from dc6wp-exch02.marvell.com ([4.21.29.225]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 4bfsu00ptj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:38 -0800 (PST) Received: from DC6WP-EXCH02.marvell.com (10.76.176.209) by DC6WP-EXCH02.marvell.com (10.76.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:33:37 -0800 Received: from maili.marvell.com (10.69.176.80) by DC6WP-EXCH02.marvell.com (10.76.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:33:37 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id 75B813F7095; Sun, 4 Jan 2026 18:33:34 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 05/13] octeontx2-af: npc: cn20k: Allocate default MCAM indexes Date: Mon, 5 Jan 2026 08:02:46 +0530 Message-ID: <20260105023254.1426488-6-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: 5-k_jYVNI2mHplRZ0b36QMx1__C6fFAj X-Proofpoint-GUID: 5-k_jYVNI2mHplRZ0b36QMx1__C6fFAj X-Authority-Analysis: v=2.4 cv=AMUfTh+a c=1 sm=1 tr=0 ts=695b2303 cx=c_pps a=gIfcoYsirJbf48DBMSPrZA==:117 a=gIfcoYsirJbf48DBMSPrZA==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=25DsG_EPHROMD9ZIbpgA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX8bm3hTDR3W7X TN2am1dEZJ4na2f1gjLsQJNUvQySGtjFuF2TWGuButWaRk9ipkdpVxPVTJFHTMKh1spLCM8G5Lq l4P0WQ8n1pKU+8ZfZ0rxp1qF92MFn1EXeLyBHlRgEyGmVXsr2qx3QtleI4x4yBsv9so+C4hrOlj pHGaLpcvCwox8zeaQXqLurQCQKoYGknHTIz/t6Viaefutn+OZ08zvLdFD7WNnaDcNuJrsxMsBna BFivGc45HiLPJO87TX15E50kctDcJ+crFXxGd229CD1d49RgLOGUolRywAcPS16Zrqe+PEu53WC tFrxqmuIqf4a55UtOcEXNv4isrOvcs2uruMk/kasnq8VpnZDjA1Sf/pLtV0V7MiXPXK8VyiL4ul j4Wy5W/e34l1YFi5ERqBFU9NirIbmTujM6QRV3aNb+4M5fi5z1wUuU105ffNeAD8CVE05WGvexU x0fVHjIfOn4iJJMO9PQ== 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" Reserving MCAM entries in the AF driver for installing default MCAM entries is not an efficient allocation method, as it results in significant wastage of entries. This patch allocates MCAM indexes for promiscuous, multicast, broadcast, and unicast traffic in descending order of indexes (from lower to higher priority) when the NIX LF is attached to the PF/VF. Signed-off-by: Ratheesh Kannoth --- .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 361 +++++++++++++++++- .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 16 + .../net/ethernet/marvell/octeontx2/af/mbox.h | 8 +- .../net/ethernet/marvell/octeontx2/af/rvu.c | 17 +- .../net/ethernet/marvell/octeontx2/af/rvu.h | 1 + .../ethernet/marvell/octeontx2/af/rvu_npc.c | 36 +- .../marvell/octeontx2/nic/otx2_flows.c | 2 +- 7 files changed, 421 insertions(+), 20 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 a3c4e2c1fcba..03fc27c544b9 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -25,10 +25,28 @@ static const char *npc_kw_name[NPC_MCAM_KEY_MAX] =3D { [NPC_MCAM_KEY_X4] =3D "X4", }; =20 +static const char *npc_dft_rule_name[NPC_DFT_RULE_MAX_ID] =3D { + [NPC_DFT_RULE_PROMISC_ID] =3D "Promisc", + [NPC_DFT_RULE_MCAST_ID] =3D "Mcast", + [NPC_DFT_RULE_BCAST_ID] =3D "Bcast", + [NPC_DFT_RULE_UCAST_ID] =3D "Ucast", +}; + #define KEX_EXTR_CFG(bytesm1, hdr_ofs, ena, key_ofs) \ (((bytesm1) << 16) | ((hdr_ofs) << 8) | ((ena) << 7) | \ ((key_ofs) & 0x3F)) =20 +#define NPC_DFT_RULE_ID_MK(pcifunc, id) \ + ((pcifunc) | FIELD_PREP(GENMASK_ULL(31, 16), id)) + +#define NPC_DFT_RULE_ID_2_PCIFUNC(rid) \ + FIELD_GET(GENMASK_ULL(15, 0), rid) + +#define NPC_DFT_RULE_ID_2_ID(rid) \ + FIELD_GET(GENMASK_ULL(31, 16), rid) + +#define NPC_DFT_RULE_PRIO 127 + static const char cn20k_def_pfl_name[] =3D "default"; =20 static struct npc_mcam_kex_extr npc_mkex_extr_default =3D { @@ -2167,9 +2185,10 @@ rvu_mbox_handler_npc_cn20k_get_free_count(struct rvu= *rvu, return 0; } =20 -int rvu_mbox_handler_npc_cn20k_get_kex_cfg(struct rvu *rvu, - struct msg_req *req, - struct npc_cn20k_get_kex_cfg_rsp *rsp) +int +rvu_mbox_handler_npc_cn20k_get_kex_cfg(struct rvu *rvu, + struct msg_req *req, + struct npc_cn20k_get_kex_cfg_rsp *rsp) { int extr, lt; =20 @@ -2382,6 +2401,340 @@ static int npc_pcifunc_map_create(struct rvu *rvu) return cnt; } =20 +int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast, + u16 *mcast, u16 *promisc, u16 *ucast) +{ + u16 *ptr[4] =3D {promisc, mcast, bcast, ucast}; + unsigned long idx; + bool set =3D false; + void *val; + int i, j; + + if (!npc_priv.init_done) + return 0; + + if (is_lbk_vf(rvu, pcifunc)) { + if (!ptr[0]) + return -ENOMEM; + + idx =3D NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID); + val =3D xa_load(&npc_priv.xa_pf2dfl_rmap, idx); + if (!val) { + pr_debug("%s:%d Failed to find %s index for pcifunc=3D%#x\n", + __func__, __LINE__, + npc_dft_rule_name[NPC_DFT_RULE_PROMISC_ID], + pcifunc); + + *ptr[0] =3D USHRT_MAX; + return -ESRCH; + } + + *ptr[0] =3D xa_to_value(val); + return 0; + } + + if (is_vf(pcifunc)) { + if (!ptr[3]) + return -ENOMEM; + + idx =3D NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID); + val =3D xa_load(&npc_priv.xa_pf2dfl_rmap, idx); + if (!val) { + pr_debug("%s:%d Failed to find %s index for pcifunc=3D%#x\n", + __func__, __LINE__, + npc_dft_rule_name[NPC_DFT_RULE_UCAST_ID], + pcifunc); + + *ptr[3] =3D USHRT_MAX; + return -ESRCH; + } + + *ptr[3] =3D xa_to_value(val); + return 0; + } + + for (i =3D NPC_DFT_RULE_START_ID, j =3D 0; i < NPC_DFT_RULE_MAX_ID; i++, + j++) { + if (!ptr[j]) + continue; + + idx =3D NPC_DFT_RULE_ID_MK(pcifunc, i); + val =3D xa_load(&npc_priv.xa_pf2dfl_rmap, idx); + if (!val) { + pr_debug("%s:%d Failed to find %s index for pcifunc=3D%#x\n", + __func__, __LINE__, + npc_dft_rule_name[i], pcifunc); + + *ptr[j] =3D USHRT_MAX; + continue; + } + + *ptr[j] =3D xa_to_value(val); + set =3D true; + } + + return set ? 0 : -ESRCH; +} + +static bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc) +{ + return is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc)) || + is_lbk_vf(rvu, pcifunc); +} + +void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc) +{ + struct npc_mcam_free_entry_req free_req =3D { 0 }; + unsigned long index; + struct msg_rsp rsp; + u16 ptr[4]; + int rc, i; + void *map; + + if (!npc_priv.init_done) + return; + + if (!npc_is_cgx_or_lbk(rvu, pcifunc)) { + dev_dbg(rvu->dev, + "%s:%d dft rule allocation is only for cgx mapped device, pcifunc=3D%#x= \n", + __func__, __LINE__, pcifunc); + return; + } + + rc =3D npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0], &ptr[1], + &ptr[2], &ptr[3]); + if (rc) + return; + + /* LBK */ + if (is_lbk_vf(rvu, pcifunc)) { + index =3D NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID); + map =3D xa_erase(&npc_priv.xa_pf2dfl_rmap, index); + if (!map) + dev_dbg(rvu->dev, + "%s:%d Err from delete %s mcam idx from xarray (pcifunc=3D%#x\n", + __func__, __LINE__, + npc_dft_rule_name[NPC_DFT_RULE_PROMISC_ID], + pcifunc); + + goto free_rules; + } + + /* VF */ + if (is_vf(pcifunc)) { + index =3D NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID); + map =3D xa_erase(&npc_priv.xa_pf2dfl_rmap, index); + if (!map) + dev_dbg(rvu->dev, + "%s:%d Err from delete %s mcam idx from xarray (pcifunc=3D%#x\n", + __func__, __LINE__, + npc_dft_rule_name[NPC_DFT_RULE_UCAST_ID], + pcifunc); + + goto free_rules; + } + + /* PF */ + for (i =3D NPC_DFT_RULE_START_ID; i < NPC_DFT_RULE_MAX_ID; i++) { + index =3D NPC_DFT_RULE_ID_MK(pcifunc, i); + map =3D xa_erase(&npc_priv.xa_pf2dfl_rmap, index); + if (!map) + dev_dbg(rvu->dev, + "%s:%d Err from delete %s mcam idx from xarray (pcifunc=3D%#x\n", + __func__, __LINE__, npc_dft_rule_name[i], + pcifunc); + } + +free_rules: + + free_req.hdr.pcifunc =3D pcifunc; + free_req.all =3D 1; + rc =3D rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp); + if (rc) + dev_err(rvu->dev, + "%s:%d Error deleting default entries (pcifunc=3D%#x\n", + __func__, __LINE__, pcifunc); +} + +int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc) +{ + u16 mcam_idx[4] =3D { 0 }, pf_ucast, pf_pcifunc; + struct npc_mcam_alloc_entry_req req =3D { 0 }; + struct npc_mcam_alloc_entry_rsp rsp =3D { 0 }; + int ret, eidx, i, k, pf, cnt; + struct rvu_pfvf *pfvf; + unsigned long index; + u16 b, m, p, u; + + if (!npc_priv.init_done) + return 0; + + if (!npc_is_cgx_or_lbk(rvu, pcifunc)) { + dev_dbg(rvu->dev, + "%s:%d dft rule allocation is only for cgx mapped device, pcifunc=3D%#x= \n", + __func__, __LINE__, pcifunc); + return 0; + } + + /* Check if default rules are already alloced for this pcifunc */ + ret =3D npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &b, &m, &p, &u); + if (!ret) { + dev_err(rvu->dev, + "%s:%d default rules are already installed (pcifunc=3D%#x)\n", + __func__, __LINE__, pcifunc); + dev_err(rvu->dev, + "%s:%d bcast(%u) mcast(%u) promisc(%u) ucast(%u)\n", + __func__, __LINE__, b, m, p, u); + return 0; + } + + /* Set ref index as lowest priority index */ + eidx =3D 2 * npc_priv.bank_depth - 1; + + /* Install only UCAST for VF */ + cnt =3D is_vf(pcifunc) ? 1 : ARRAY_SIZE(mcam_idx); + + /* For VF pcifunc, allocate default mcam indexes by taking + * ref as PF's ucast index. + */ + if (is_vf(pcifunc)) { + pf =3D rvu_get_pf(rvu->pdev, pcifunc); + pf_pcifunc =3D pf << RVU_CN20K_PFVF_PF_SHIFT; + + /* Get PF's ucast entry index */ + ret =3D npc_cn20k_dft_rules_idx_get(rvu, pf_pcifunc, NULL, + NULL, NULL, &pf_ucast); + + /* There is no PF rules installed; and VF installation comes + * first. PF may come later. + * TODO: Install PF rules before installing VF rules. + */ + + /* Set PF's ucast as ref entry */ + if (!ret) + eidx =3D pf_ucast; + } + + pfvf =3D rvu_get_pfvf(rvu, pcifunc); + pfvf->hw_prio =3D NPC_DFT_RULE_PRIO; + + req.contig =3D false; + req.ref_prio =3D NPC_MCAM_HIGHER_PRIO; + req.ref_entry =3D eidx; + req.kw_type =3D NPC_MCAM_KEY_X2; + req.count =3D cnt; + req.hdr.pcifunc =3D pcifunc; + + ret =3D rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &req, &rsp); + + /* successfully allocated index */ + if (!ret) { + /* Copy indexes to local array */ + for (i =3D 0; i < cnt; i++) + mcam_idx[i] =3D rsp.entry_list[i]; + + goto chk_sanity; + } + + /* If there is no slots available and request is for PF, + * return error. + */ + if (!is_vf(pcifunc)) { + dev_err(rvu->dev, + "%s:%d Default index allocation failed for pcifunc=3D%#x\n", + __func__, __LINE__, pcifunc); + return ret; + } + + /* We could not find an index with higher priority index for VF. + * Find rule with lower priority index and set hardware priority + * as NPC_DFT_RULE_PRIO - 1 (higher hw priority) + */ + req.contig =3D false; + req.kw_type =3D NPC_MCAM_KEY_X2; + req.count =3D cnt; + req.hdr.pcifunc =3D pcifunc; + req.ref_prio =3D NPC_MCAM_LOWER_PRIO; + req.ref_entry =3D eidx + 1; + ret =3D rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &req, &rsp); + if (ret) { + dev_err(rvu->dev, + "%s:%d Default index allocation failed for pcifunc=3D%#x\n", + __func__, __LINE__, pcifunc); + return ret; + } + + /* Copy indexes to local array */ + for (i =3D 0; i < cnt; i++) + mcam_idx[i] =3D rsp.entry_list[i]; + + pfvf->hw_prio =3D NPC_DFT_RULE_PRIO - 1; + +chk_sanity: + dev_dbg(rvu->dev, + "%s:%d Default index for pcifunc=3D%#x, bcast=3D%u mcast=3D%u promise=3D= %u ucast=3D%u cnt=3D%u\n", + __func__, __LINE__, pcifunc, mcam_idx[0], mcam_idx[1], + mcam_idx[2], mcam_idx[3], cnt); + + /* LBK */ + if (is_lbk_vf(rvu, pcifunc)) { + index =3D NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID); + ret =3D xa_insert(&npc_priv.xa_pf2dfl_rmap, index, + xa_mk_value(mcam_idx[0]), GFP_KERNEL); + if (ret) { + dev_err(rvu->dev, + "%s:%d Err to insert %s mcam idx to xarray pcifunc=3D%#x\n", + __func__, __LINE__, + npc_dft_rule_name[NPC_DFT_RULE_PROMISC_ID], + pcifunc); + ret =3D -EFAULT; + goto err; + } + + goto done; + } + + /* VF */ + if (is_vf(pcifunc)) { + index =3D NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID); + ret =3D xa_insert(&npc_priv.xa_pf2dfl_rmap, index, + xa_mk_value(mcam_idx[0]), GFP_KERNEL); + if (ret) { + dev_err(rvu->dev, + "%s:%d Err to insert %s mcam idx to xarray pcifunc=3D%#x\n", + __func__, __LINE__, + npc_dft_rule_name[NPC_DFT_RULE_UCAST_ID], + pcifunc); + ret =3D -EFAULT; + goto err; + } + + goto done; + } + + /* PF */ + for (i =3D NPC_DFT_RULE_START_ID, k =3D 0; i < NPC_DFT_RULE_MAX_ID && + k < cnt; i++, k++) { + index =3D NPC_DFT_RULE_ID_MK(pcifunc, i); + ret =3D xa_insert(&npc_priv.xa_pf2dfl_rmap, index, + xa_mk_value(mcam_idx[k]), GFP_KERNEL); + if (ret) { + dev_err(rvu->dev, + "%s:%d Err to insert %s mcam idx to xarray pcifunc=3D%#x\n", + __func__, __LINE__, npc_dft_rule_name[i], + pcifunc); + ret =3D -EFAULT; + goto err; + } + } + +done: + return 0; +err: + /* TODO: handle errors */ + return ret; +} + static int npc_priv_init(struct rvu *rvu) { struct npc_mcam *mcam =3D &rvu->hw->mcam; @@ -2432,6 +2785,7 @@ static int npc_priv_init(struct rvu *rvu) xa_init_flags(&npc_priv.xa_sb_free, XA_FLAGS_ALLOC); 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); =20 npc_create_srch_order(num_subbanks); npc_populate_restricted_idxs(num_subbanks); @@ -2461,6 +2815,7 @@ int npc_cn20k_deinit(struct rvu *rvu) xa_destroy(&npc_priv.xa_sb_free); xa_destroy(&npc_priv.xa_idx2pf_map); xa_destroy(&npc_priv.xa_pf_map); + xa_destroy(&npc_priv.xa_pf2dfl_rmap); =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 ad660a920abd..575474fd258c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h @@ -84,6 +84,15 @@ enum npc_subbank_flag { NPC_SUBBANK_FLAG_USED =3D BIT(1), // At least one slot allocated }; =20 +enum npc_dft_rule_id { + NPC_DFT_RULE_START_ID =3D 1, + NPC_DFT_RULE_PROMISC_ID =3D NPC_DFT_RULE_START_ID, + NPC_DFT_RULE_MCAST_ID, + NPC_DFT_RULE_BCAST_ID, + NPC_DFT_RULE_UCAST_ID, + NPC_DFT_RULE_MAX_ID, +}; + struct npc_subbank { u16 b0t, b0b, b1t, b1b; // mcam indexes of this subbank enum npc_subbank_flag flags; @@ -108,6 +117,7 @@ struct npc_priv_t { struct xarray *xa_pf2idx_map; // Each PF to map its mcam idxes 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 int pf_cnt; bool init_done; }; @@ -214,4 +224,10 @@ int npc_cn20k_apply_custom_kpu(struct rvu *rvu, struct= npc_kpu_profile_adapter * void npc_cn20k_update_action_entries_n_flags(struct rvu *rvu, struct npc_kpu_profile_adapter *profile); + +int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc); +void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc); + +int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast, + u16 *mcast, u16 *promisc, u16 *ucast); #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 2b413c99a841..49c9ee15c74f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1539,9 +1539,10 @@ struct npc_mcam_alloc_entry_req { #define NPC_MCAM_ANY_PRIO 0 #define NPC_MCAM_LOWER_PRIO 1 #define NPC_MCAM_HIGHER_PRIO 2 - u8 priority; /* Lower or higher w.r.t ref_entry */ + u8 ref_prio; /* Lower or higher w.r.t ref_entry */ u16 ref_entry; u16 count; /* Number of entries requested */ + u8 kw_type; /* entry key type, valid for cn20k */ }; =20 struct npc_mcam_alloc_entry_rsp { @@ -1634,10 +1635,12 @@ struct npc_mcam_alloc_and_write_entry_req { struct mbox_msghdr hdr; struct mcam_entry entry_data; u16 ref_entry; - u8 priority; /* Lower or higher w.r.t ref_entry */ + u8 ref_prio; /* Lower or higher w.r.t ref_entry */ u8 intf; /* Rx or Tx interface */ u8 enable_entry;/* Enable this MCAM entry ? */ u8 alloc_cntr; /* Allocate counter and map ? */ + /* hardware priority, supported for cn20k */ + u8 hw_prio; }; =20 struct npc_mcam_alloc_and_write_entry_rsp { @@ -1790,6 +1793,7 @@ struct npc_install_flow_req { u8 vtag1_op; /* old counter value */ u16 cntr_val; + u8 hw_prio; }; =20 struct npc_install_flow_rsp { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/= ethernet/marvell/octeontx2/af/rvu.c index 2d78e08f985f..df02caedc020 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -22,6 +22,7 @@ #include "rvu_npc_hash.h" #include "cn20k/reg.h" #include "cn20k/api.h" +#include "cn20k/npc.h" =20 #define DRV_NAME "rvu_af" #define DRV_STRING "Marvell OcteonTX2 RVU Admin Function Driver" @@ -1396,7 +1397,6 @@ static void rvu_detach_block(struct rvu *rvu, int pci= func, int blktype) if (blkaddr < 0) return; =20 - block =3D &hw->block[blkaddr]; =20 num_lfs =3D rvu_get_rsrc_mapcount(pfvf, block->addr); @@ -1467,6 +1467,13 @@ static int rvu_detach_rsrcs(struct rvu *rvu, struct = rsrc_detach *detach, else if ((blkid =3D=3D BLKADDR_CPT1) && !detach->cptlfs) continue; } + + if (detach_all || + (detach && (blkid =3D=3D BLKADDR_NIX0 || + blkid =3D=3D BLKADDR_NIX1) && + detach->nixlf)) + npc_cn20k_dft_rules_free(rvu, pcifunc); + rvu_detach_block(rvu, pcifunc, block->type); } =20 @@ -1738,8 +1745,14 @@ int rvu_mbox_handler_attach_resources(struct rvu *rv= u, if (attach->npalf) rvu_attach_block(rvu, pcifunc, BLKTYPE_NPA, 1, attach); =20 - if (attach->nixlf) + if (attach->nixlf) { rvu_attach_block(rvu, pcifunc, BLKTYPE_NIX, 1, attach); + if (is_cn20k(rvu->pdev)) { + err =3D npc_cn20k_dft_rules_alloc(rvu, pcifunc); + if (err) + goto exit; + } + } =20 if (attach->sso) { /* RVU func doesn't know which exact LF or slot is attached diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/= ethernet/marvell/octeontx2/af/rvu.h index dd930aa05582..d2a0f6821cf9 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -308,6 +308,7 @@ struct rvu_pfvf { u64 lmt_map_ent_w1; /* Preseving the word1 of lmtst map table entry*/ unsigned long flags; struct sdp_node_info *sdp_info; + u8 hw_prio; /* Hw priority of default rules */ }; =20 enum rvu_pfvf_flags { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.c index 8361d0aa4b6f..246f3568a795 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -653,6 +653,9 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 p= cifunc, req.match_id =3D action.match_id; req.flow_key_alg =3D action.flow_key_alg; =20 + if (is_cn20k(rvu->pdev)) + req.hw_prio =3D pfvf->hw_prio; + rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); } =20 @@ -741,6 +744,9 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16= pcifunc, req.match_id =3D action.match_id; req.flow_key_alg =3D flow_key_alg; =20 + if (is_cn20k(rvu->pdev)) + req.hw_prio =3D pfvf->hw_prio; + rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); } =20 @@ -821,6 +827,9 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu,= u16 pcifunc, req.hdr.pcifunc =3D 0; /* AF is requester */ req.vf =3D pcifunc; =20 + if (is_cn20k(rvu->pdev)) + req.hw_prio =3D pfvf->hw_prio; + rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); } =20 @@ -909,6 +918,9 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u1= 6 pcifunc, int nixlf, req.match_id =3D action.match_id; req.flow_key_alg =3D flow_key_alg; =20 + if (is_cn20k(rvu->pdev)) + req.hw_prio =3D pfvf->hw_prio; + rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); } =20 @@ -2484,7 +2496,7 @@ npc_get_mcam_search_range_priority(struct npc_mcam *m= cam, { u16 fcnt; =20 - if (req->priority =3D=3D NPC_MCAM_HIGHER_PRIO) + if (req->ref_prio =3D=3D NPC_MCAM_HIGHER_PRIO) goto hprio; =20 /* For a low priority entry allocation @@ -2584,7 +2596,7 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mc= am, u16 pcifunc, goto lprio_alloc; =20 /* Get the search range for priority allocation request */ - if (req->priority) { + if (req->ref_prio) { npc_get_mcam_search_range_priority(mcam, req, &start, &end, &reverse); goto alloc; @@ -2625,11 +2637,11 @@ static int npc_mcam_alloc_entries(struct npc_mcam *= mcam, u16 pcifunc, * and not in mid zone. */ if (!(pcifunc & RVU_PFVF_FUNC_MASK) && - req->priority =3D=3D NPC_MCAM_HIGHER_PRIO) + req->ref_prio =3D=3D NPC_MCAM_HIGHER_PRIO) end =3D req->ref_entry; =20 if (!(pcifunc & RVU_PFVF_FUNC_MASK) && - req->priority =3D=3D NPC_MCAM_LOWER_PRIO) + req->ref_prio =3D=3D NPC_MCAM_LOWER_PRIO) start =3D req->ref_entry; } =20 @@ -2678,7 +2690,7 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mc= am, u16 pcifunc, /* If allocating requested no of entries is unsucessful, * expand the search range to full bitmap length and retry. */ - if (!req->priority && (rsp->count < req->count) && + if (!req->ref_prio && rsp->count < req->count && ((end - start) !=3D mcam->bmap_entries)) { reverse =3D true; start =3D 0; @@ -2689,14 +2701,14 @@ static int npc_mcam_alloc_entries(struct npc_mcam *= mcam, u16 pcifunc, /* For priority entry allocation requests, if allocation is * failed then expand search to max possible range and retry. */ - if (req->priority && rsp->count < req->count) { - if (req->priority =3D=3D NPC_MCAM_LOWER_PRIO && + if (req->ref_prio && rsp->count < req->count) { + if (req->ref_prio =3D=3D NPC_MCAM_LOWER_PRIO && (start !=3D (req->ref_entry + 1))) { start =3D req->ref_entry + 1; end =3D mcam->bmap_entries; reverse =3D false; goto alloc; - } else if ((req->priority =3D=3D NPC_MCAM_HIGHER_PRIO) && + } else if ((req->ref_prio =3D=3D NPC_MCAM_HIGHER_PRIO) && ((end - start) !=3D req->ref_entry)) { start =3D 0; end =3D req->ref_entry; @@ -2810,9 +2822,9 @@ int rvu_mbox_handler_npc_mcam_alloc_entry(struct rvu = *rvu, /* ref_entry can't be '0' if requested priority is high. * Can't be last entry if requested priority is low. */ - if ((!req->ref_entry && req->priority =3D=3D NPC_MCAM_HIGHER_PRIO) || - ((req->ref_entry =3D=3D mcam->bmap_entries) && - req->priority =3D=3D NPC_MCAM_LOWER_PRIO)) + if ((!req->ref_entry && req->ref_prio =3D=3D NPC_MCAM_HIGHER_PRIO) || + (req->ref_entry =3D=3D mcam->bmap_entries && + req->ref_prio =3D=3D NPC_MCAM_LOWER_PRIO)) return NPC_MCAM_INVALID_REQ; =20 /* Since list of allocated indices needs to be sent to requester, @@ -3358,7 +3370,7 @@ int rvu_mbox_handler_npc_mcam_alloc_and_write_entry(s= truct rvu *rvu, /* Try to allocate a MCAM entry */ entry_req.hdr.pcifunc =3D req->hdr.pcifunc; entry_req.contig =3D true; - entry_req.priority =3D req->priority; + entry_req.ref_prio =3D req->ref_prio; entry_req.ref_entry =3D req->ref_entry; entry_req.count =3D 1; =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/driv= ers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c index 64c6d9162ef6..052d989f2d9a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c @@ -104,7 +104,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 = count) * will be on top of PF. */ if (!is_otx2_vf(pfvf->pcifunc)) { - req->priority =3D NPC_MCAM_HIGHER_PRIO; + req->ref_prio =3D NPC_MCAM_HIGHER_PRIO; req->ref_entry =3D flow_cfg->def_ent[0]; } =20 --=20 2.43.0 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (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 1DE9730DED5; Mon, 5 Jan 2026 02:33:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580435; cv=none; b=V4Skw/EspCbVFF94bA+UuZ7Jlph9pyYBRMA9SSF04DXtM3MRtJpu9uSEUf+GR9Wt5WFGcv1tIrfv0wxNEr4rYnRM1Ex0SjTJtK4pw9BuscTyKQkh8MJvu6F82ekJYw4HHCT1+UWgZEzANE+NHCRbLBsBcgNXelpSwwM4r3W4RMw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580435; c=relaxed/simple; bh=NaC1uwjbYILob5J/KxSaDlRz96iJaelU3p2DA9/rLDE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rZZro7r/SYEH9Ww97QGYfg9Wx+0FHkJlrPS9kz/2dSfTnzYzzUOKXAQZQuENd8CLnkLrHtH+Crwduxx8AzTHyXUtodSBBMqBlkPl6/daEqX0dTH46xhVZH0RI/LYH+nFyRncvORVpSSwFXn+rHK8onYG2jLYYXhFHjnnsWJyhgI= 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=dq1z6UJ5; arc=none smtp.client-ip=67.231.156.173 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="dq1z6UJ5" Received: from pps.filterd (m0431383.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604NH9Za2304596; Sun, 4 Jan 2026 18:33:41 -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=X 2NubngraBnn7xbJSZXS1dzhXhkt09k7wlphsySD9+w=; b=dq1z6UJ5+J5yOmlvO kEUCko/aHRzHyP8CGL6ic8UOL5/f+sxMd2Ln+XSxKXSuZcZ/lfxwN7Dfm5zAuQ79 dAhnTfpsvR0O8VQR2SFsSsjYxtFZtPwUDBZ+pB5yhhOWM6bfEE3W/PyBi5i060R0 NgT3bYJRvsyhIHiBgrQnUEYctnwc2J9r/G7co8uevP67oHdgG//+bVyOF1yPvtHa /7XeEQYPOzonsm5VXiH7IgZ1t84wfd6KTWMtoyG1wxkZOgMXPOBQcEYEqpMvpBFY vrNTQEnj034n+Sym5Uzmji/NT33Kz+vwmv0n2IWrVW9TLGGeTRnLezIDURg9Veln ewOjA== Received: from dc6wp-exch02.marvell.com ([4.21.29.225]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 4bfmrbs035-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:41 -0800 (PST) Received: from DC6WP-EXCH02.marvell.com (10.76.176.209) by DC6WP-EXCH02.marvell.com (10.76.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:33:41 -0800 Received: from maili.marvell.com (10.69.176.80) by DC6WP-EXCH02.marvell.com (10.76.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:33:41 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id E5F483F7094; Sun, 4 Jan 2026 18:33:37 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 06/13] octeontx2-af: npc: cn20k: Use common APIs Date: Mon, 5 Jan 2026 08:02:47 +0530 Message-ID: <20260105023254.1426488-7-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-Authority-Analysis: v=2.4 cv=bN0b4f+Z c=1 sm=1 tr=0 ts=695b2305 cx=c_pps a=gIfcoYsirJbf48DBMSPrZA==:117 a=gIfcoYsirJbf48DBMSPrZA==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=YiITfu5hDICovFRBzmQA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-ORIG-GUID: 3hdA8fu3VSH1vj93z2UK6joeXMP3g7S0 X-Proofpoint-GUID: 3hdA8fu3VSH1vj93z2UK6joeXMP3g7S0 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX+Mt0zw0rCee+ rxZj0VHU3B0ggobcyGCST3OW5lXflsRsLXguwBobnaWXVtSCiueQhR37pWBxj1WDO2M41ATc2Yc lxnj+TA6I1nUwYfwM+Vp0Qn7vJtDTByVpER4XEci24/qqBGNl4A64eiZOXirwZ+dIpvKByYusW9 QpQ/XMElTXWID0xVgvdv7WkYECjopk50rRRxRv7hJ6eIuJxKdym5HL9mT1NqdfNSlkqoc4mQONp jbBq475UFvkSjwgUvwiZP57yC3ozlPTWlXWjMJ7loydT7sK0roRUiXPYlA/N/g9+Oj2qW03Z7/d F+LWkd2ifUPKQTDAqCZ08mz/rv1icaUMHmi/Wc4VLYzjSzoEX9HeHfq0tFbzXR+tUCUoFaZFgcJ WkOgpGciPOZdK8Az1HJfV/9SL9f4aW3BmGVLMSPNrCYqyeTMiOIkvMa1/FvWp0XPIonTp5n25mA nmAdwu6JZzCx0nuae6g== 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" From: Suman Ghosh In cn20k silicon, the register definitions and the algorithms used to read, write, copy, and enable MCAM entries have changed. This patch updates the common APIs to support both cn20k and previous silicon variants. Additionally, cn20k introduces a new algorithm for MCAM index management. The common APIs are updated to invoke the cn20k-specific index management routines for allocating, freeing, and retrieving default MCAM entries. Signed-off-by: Suman Ghosh Signed-off-by: Ratheesh Kannoth --- .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 473 +++++++++++++++++- .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 15 + .../net/ethernet/marvell/octeontx2/af/mbox.h | 3 + .../net/ethernet/marvell/octeontx2/af/rvu.h | 4 +- .../ethernet/marvell/octeontx2/af/rvu_nix.c | 1 - .../ethernet/marvell/octeontx2/af/rvu_npc.c | 290 ++++++++--- .../marvell/octeontx2/af/rvu_npc_fs.c | 11 +- 7 files changed, 725 insertions(+), 72 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 03fc27c544b9..28e5fa6361a5 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -448,7 +448,8 @@ static void npc_program_mkex_rx(struct rvu *rvu, int bl= kaddr, =20 /* Program EXTRACTOR */ for (extr =3D 0; extr < num_extr; extr++) - rvu_write64(rvu, blkaddr, NPC_AF_INTFX_EXTRACTORX_CFG(intf, extr), + rvu_write64(rvu, blkaddr, + NPC_AF_INTFX_EXTRACTORX_CFG(intf, extr), mkex_extr->intf_extr_lid[intf][extr]); =20 /* Program EXTRACTOR_LTYPE */ @@ -519,10 +520,12 @@ void npc_cn20k_load_mkex_profile(struct rvu *rvu, int= blkaddr, =20 mcam_kex_extr =3D (struct npc_mcam_kex_extr __force *)mkex_prfl_addr; =20 - while (((s64)prfl_sz > 0) && (mcam_kex_extr->mkex_sign !=3D MKEX_END_SIGN= )) { + while (((s64)prfl_sz > 0) && (mcam_kex_extr->mkex_sign !=3D + MKEX_END_SIGN)) { /* Compare with mkex mod_param name string */ if (mcam_kex_extr->mkex_sign =3D=3D MKEX_CN20K_SIGN && - !strncmp(mcam_kex_extr->name, mkex_profile, MKEX_NAME_LEN)) { + !strncmp(mcam_kex_extr->name, mkex_profile, + MKEX_NAME_LEN)) { rvu->kpu.mcam_kex_prfl.mkex_extr =3D mcam_kex_extr; goto program_mkex_extr; } @@ -533,13 +536,433 @@ void npc_cn20k_load_mkex_profile(struct rvu *rvu, in= t blkaddr, dev_warn(dev, "Failed to load requested profile: %s\n", mkex_profile); =20 program_mkex_extr: - dev_info(rvu->dev, "Using %s mkex profile\n", rvu->kpu.mcam_kex_prfl.mkex= _extr->name); + dev_info(rvu->dev, "Using %s mkex profile\n", + rvu->kpu.mcam_kex_prfl.mkex_extr->name); /* Program selected mkex profile */ - npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mcam_kex_prfl.mkex_extr); + npc_program_mkex_profile(rvu, blkaddr, + rvu->kpu.mcam_kex_prfl.mkex_extr); if (mkex_prfl_addr) iounmap(mkex_prfl_addr); } =20 +void +npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr, + int index, bool enable) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + int mcam_idx =3D index % mcam->banksize; + int bank =3D index / mcam->banksize; + u64 cfg, hw_prio; + u8 kw_type; + + npc_mcam_idx_2_key_type(rvu, index, &kw_type); + if (kw_type =3D=3D NPC_MCAM_KEY_X2) { + cfg =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank)); + hw_prio =3D cfg & GENMASK_ULL(14, 8); + cfg =3D enable ? 1 : 0; + cfg |=3D hw_prio; + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank), + cfg); + return; + } + + /* For NPC_CN20K_MCAM_KEY_X4 keys, both the banks + * need to be programmed with the same value. + */ + for (bank =3D 0; bank < mcam->banks_per_entry; bank++) { + cfg =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank)); + hw_prio =3D cfg & GENMASK_ULL(14, 8); + cfg =3D enable ? 1 : 0; + cfg |=3D hw_prio; + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank), + cfg); + } +} + +void +npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr, int bank, int ind= ex) +{ + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 1), + 0); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 0), + 0); + + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 1), 0); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 0), 0); + + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 1), 0); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 0), 0); + + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 1), 0); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 0), 0); + + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 1), 0); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 0), 0); +} + +static void npc_cn20k_get_keyword(struct mcam_entry *entry, int idx, + u64 *cam0, u64 *cam1) +{ + u64 kw_mask; + + /* The two banks of every MCAM entry are used as a single double-wide ent= ry that + * is compared with the search key as follows: + * + * NPC_AF_MCAME()_BANK(0)_CAM(0..1)_W0_EXT[MD] corresponds to NPC_MCAM_KE= Y_X4_S[KW0] + * NPC_AF_MCAME()_BANK(0)_CAM(0..1)_W1_EXT[MD] corresponds to NPC_MCAM_KE= Y_X4_S[KW1] + * NPC_AF_MCAME()_BANK(0)_CAM(0..1)_W2_EXT[MD] corresponds to NPC_MCAM_KE= Y_X4_S[KW2] + * NPC_AF_MCAME()_BANK(0)_CAM(0..1)_W3_EXT[MD] corresponds to NPC_MCAM_KE= Y_X4_S[KW3] + * NPC_AF_MCAME()_BANK(1)_CAM(0..1)_W0_EXT[MD] corresponds to NPC_MCAM_KE= Y_X4_S[KW4] + * NPC_AF_MCAME()_BANK(1)_CAM(0..1)_W1_EXT[MD] corresponds to NPC_MCAM_KE= Y_X4_S[KW5] + * NPC_AF_MCAME()_BANK(1)_CAM(0..1)_W2_EXT[MD] corresponds to NPC_MCAM_KE= Y_X4_S[KW6] + * NPC_AF_MCAME()_BANK(1)_CAM(0..1)_W3_EXT[MD] corresponds to NPC_MCAM_KE= Y_X4_S[KW7] + */ + *cam1 =3D entry->kw[idx]; + kw_mask =3D entry->kw_mask[idx]; + *cam1 &=3D kw_mask; + *cam0 =3D ~*cam1 & kw_mask; +} + +static void npc_cn20k_config_kw_x2(struct rvu *rvu, struct npc_mcam *mcam, + int blkaddr, int index, u8 intf, + struct mcam_entry *entry, + int bank, u8 kw_type, int kw) +{ + u64 intf_ext =3D 0, intf_ext_mask =3D 0; + u8 tx_intf_mask =3D ~intf & 0x3; + u8 tx_intf =3D intf, kex_type; + u8 kw_type_mask =3D ~kw_type; + u64 cam0, cam1, kex_cfg; + + if (is_npc_intf_tx(intf)) { + /* Last bit must be set and rest don't care + * for TX interfaces + */ + tx_intf_mask =3D 0x1; + tx_intf =3D intf & tx_intf_mask; + tx_intf_mask =3D ~tx_intf & tx_intf_mask; + } + + kex_cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf)); + kex_type =3D (kex_cfg & GENMASK_ULL(34, 32)) >> 32; + /*-----------------------------------------------------------------------= --------------| + * Kex type | mcam entry | cam1 | cam 0 || <----- output ----> | + * in profile | len | (key type) | (key type) || len | type = | + *-----------------------------------------------------------------------= --------------| + * X2 | 256 (X2) | 001b | 110b || X2 | X2 | + *-----------------------------------------------------------------------= --------------| + * X4 | 256 (X2) | 000b | 000b || X2 | DYNAMIC | + *-----------------------------------------------------------------------= --------------| + * X4 | 512 (X4) | 010b | 101b || X4 | X4 | + *-----------------------------------------------------------------------= --------------| + * DYNAMIC | 256 (X2) | 000b | 000b || X2 | DYNAMIC | + *-----------------------------------------------------------------------= --------------| + * DYNAMIC | 512 (X4) | 010b | 101b || X4 | X4 | + *-----------------------------------------------------------------------= --------------| + */ + if ((kex_type =3D=3D NPC_MCAM_KEY_DYN || kex_type =3D=3D NPC_MCAM_KEY_X4)= && + kw_type =3D=3D NPC_MCAM_KEY_X2) { + kw_type =3D 0; + kw_type_mask =3D 0; + } + + intf_ext =3D ((u64)kw_type << 16) | tx_intf; + intf_ext_mask =3D (((u64)kw_type_mask << 16) & GENMASK_ULL(18, 16)) | + tx_intf_mask; + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 1), + intf_ext); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 0), + intf_ext_mask); + + /* Set the match key */ + npc_cn20k_get_keyword(entry, kw, &cam0, &cam1); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 1), + cam1); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 0), + cam0); + + npc_cn20k_get_keyword(entry, kw + 1, &cam0, &cam1); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 1), + cam1); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 0), + cam0); + + npc_cn20k_get_keyword(entry, kw + 2, &cam0, &cam1); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 1), + cam1); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 0), + cam0); + + npc_cn20k_get_keyword(entry, kw + 3, &cam0, &cam1); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 1), + cam1); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 0), + cam0); +} + +static void npc_cn20k_config_kw_x4(struct rvu *rvu, struct npc_mcam *mcam, + int blkaddr, int index, u8 intf, + struct mcam_entry *entry, u8 kw_type) +{ + int kw =3D 0, bank; + + for (bank =3D 0; bank < mcam->banks_per_entry; bank++, kw =3D kw + 4) + npc_cn20k_config_kw_x2(rvu, mcam, blkaddr, + index, intf, + entry, bank, kw_type, kw); +} + +static void +npc_cn20k_set_mcam_bank_cfg(struct rvu *rvu, int blkaddr, int mcam_idx, + int bank, u8 kw_type, bool enable, u8 hw_prio) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + u64 bank_cfg; + + bank_cfg =3D (u64)hw_prio << 8; + if (enable) + bank_cfg |=3D 0x1; + + if (kw_type =3D=3D NPC_MCAM_KEY_X2) { + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank), + bank_cfg); + return; + } + + /* For NPC_MCAM_KEY_X4 keys, both the banks + * need to be programmed with the same value. + */ + for (bank =3D 0; bank < mcam->banks_per_entry; bank++) { + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank), + bank_cfg); + } +} + +void +npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, u8 in= tf, + struct mcam_entry *entry, bool enable, u8 hw_prio) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + int mcam_idx =3D index % mcam->banksize; + int bank =3D index / mcam->banksize; + int kw =3D 0; + u8 kw_type; + + /* Disable before mcam entry update */ + npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, false); + + npc_mcam_idx_2_key_type(rvu, index, &kw_type); + /* CAM1 takes the comparison value and + * CAM0 specifies match for a bit in key being '0' or '1' or 'dontcare'. + * CAM1 =3D 0 & CAM0 =3D 1 =3D> match if key =3D 0 + * CAM1 =3D 1 & CAM0 =3D 0 =3D> match if key =3D 1 + * CAM1 =3D 0 & CAM0 =3D 0 =3D> always match i.e dontcare. + */ + if (kw_type =3D=3D NPC_MCAM_KEY_X2) { + /* Clear mcam entry to avoid writes being suppressed by NPC */ + npc_cn20k_clear_mcam_entry(rvu, blkaddr, bank, mcam_idx); + npc_cn20k_config_kw_x2(rvu, mcam, blkaddr, + mcam_idx, intf, entry, + bank, kw_type, kw); + /* Set 'action' */ + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, bank, 0), + entry->action); + + /* Set TAG 'action' */ + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, bank, 1), + entry->vtag_action); + } else { + /* Clear mcam entry to avoid writes being suppressed by NPC */ + npc_cn20k_clear_mcam_entry(rvu, blkaddr, 0, mcam_idx); + npc_cn20k_clear_mcam_entry(rvu, blkaddr, 1, mcam_idx); + + npc_cn20k_config_kw_x4(rvu, mcam, blkaddr, + mcam_idx, intf, entry, kw_type); + for (bank =3D 0; bank < mcam->banks_per_entry; bank++) { + /* Set 'action' */ + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, bank, 0), + entry->action); + + /* Set TAG 'action' */ + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, bank, 1), + entry->vtag_action); + } + } + + /* TODO: */ + /* PF installing VF rule */ + npc_cn20k_set_mcam_bank_cfg(rvu, blkaddr, mcam_idx, bank, + kw_type, enable, hw_prio); +} + +void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 = dest) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + u8 src_kwtype, dest_kwtype; + u64 cfg, sreg, dreg; + int dbank, sbank; + int bank, i; + + dbank =3D npc_get_bank(mcam, dest); + sbank =3D npc_get_bank(mcam, src); + npc_mcam_idx_2_key_type(rvu, src, &src_kwtype); + npc_mcam_idx_2_key_type(rvu, dest, &dest_kwtype); + if (src_kwtype !=3D dest_kwtype) + return; + + src &=3D (mcam->banksize - 1); + dest &=3D (mcam->banksize - 1); + + /* Copy INTF's, W0's, W1's, W2's, W3s CAM0 and CAM1 configuration */ + for (bank =3D 0; bank < mcam->banks_per_entry; bank++) { + sreg =3D NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(src, sbank + bank, 0); + dreg =3D NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(dest, dbank + bank, 0); + for (i =3D 0; i < 10; i++) { + cfg =3D rvu_read64(rvu, blkaddr, sreg + (i * 8)); + rvu_write64(rvu, blkaddr, dreg + (i * 8), cfg); + } + + /* Copy action */ + for (i =3D 0; i < 3; i++) { + cfg =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(src, + sbank + bank, + i)); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(dest, + dbank + bank, + i), cfg); + } + + /* Copy bank configuration */ + cfg =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(src, sbank + bank)); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(dest, dbank + bank), cfg); + if (src_kwtype =3D=3D NPC_MCAM_KEY_X2) + break; + } +} + +static void npc_cn20k_fill_entryword(struct mcam_entry *entry, int idx, + u64 cam0, u64 cam1) +{ + entry->kw[idx] =3D cam1; + entry->kw_mask[idx] =3D cam1 ^ cam0; +} + +void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index, + struct mcam_entry *entry, u8 *intf, u8 *ena, + u8 *hw_prio) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + int kw =3D 0, bank; + u64 cam0, cam1, bank_cfg; + u8 kw_type; + + npc_mcam_idx_2_key_type(rvu, index, &kw_type); + + bank =3D npc_get_bank(mcam, index); + index &=3D (mcam->banksize - 1); + *intf =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_INTF_EXT(index, bank, 1)) & 3; + bank_cfg =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(index, bank)); + *ena =3D bank_cfg & 0x1; + *hw_prio =3D (bank_cfg & GENMASK_ULL(14, 8)) >> 8; + if (kw_type =3D=3D NPC_MCAM_KEY_X2) { + cam1 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 1)); + cam0 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 0)); + npc_cn20k_fill_entryword(entry, kw, cam0, cam1); + + cam1 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 1)); + cam0 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 0)); + npc_cn20k_fill_entryword(entry, kw + 1, cam0, cam1); + + cam1 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 1)); + cam0 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 0)); + npc_cn20k_fill_entryword(entry, kw + 2, cam0, cam1); + + cam1 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 1)); + cam0 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 0)); + npc_cn20k_fill_entryword(entry, kw + 3, cam0, cam1); + goto read_action; + } + + for (bank =3D 0; bank < mcam->banks_per_entry; bank++, kw =3D kw + 4) { + cam1 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 1)); + cam0 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 0)); + npc_cn20k_fill_entryword(entry, kw, cam0, cam1); + + cam1 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 1)); + cam0 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W1_EXT(index, bank, 0)); + npc_cn20k_fill_entryword(entry, kw + 1, cam0, cam1); + + cam1 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 1)); + cam0 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W2_EXT(index, bank, 0)); + npc_cn20k_fill_entryword(entry, kw + 2, cam0, cam1); + + cam1 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 1)); + cam0 =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 0)); + npc_cn20k_fill_entryword(entry, kw + 3, cam0, cam1); + } + +read_action: + /* 'action' is set to same value for both bank '0' and '1'. + * Hence, reading bank '0' should be enough. + */ + entry->action =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, 0, 0)); + entry->vtag_action =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, 0, 1)); +} + static u8 npc_map2cn20k_flag(u8 flag) { switch (flag) { @@ -610,13 +1033,15 @@ npc_cn20k_update_action_entries_n_flags(struct rvu *= rvu, } } =20 -int npc_cn20k_apply_custom_kpu(struct rvu *rvu, struct npc_kpu_profile_ada= pter *profile) +int npc_cn20k_apply_custom_kpu(struct rvu *rvu, + struct npc_kpu_profile_adapter *profile) { - size_t hdr_sz =3D sizeof(struct npc_cn20k_kpu_profile_fwdata), offset =3D= 0; + size_t hdr_sz =3D sizeof(struct npc_cn20k_kpu_profile_fwdata); struct npc_cn20k_kpu_profile_fwdata *fw =3D rvu->kpu_fwdata; struct npc_kpu_profile_action *action; struct npc_kpu_profile_cam *cam; struct npc_kpu_fwdata *fw_kpu; + size_t offset =3D 0; u16 kpu, entry; int entries; =20 @@ -702,6 +1127,40 @@ int npc_cn20k_apply_custom_kpu(struct rvu *rvu, struc= t npc_kpu_profile_adapter * return 0; } =20 +int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type) +{ + struct npc_subbank *sb; + int bank_off, sb_id; + + /* mcam_idx should be less than (2 * bank depth) */ + if (mcam_idx >=3D npc_priv.bank_depth * 2) { + dev_err(rvu->dev, "%s:%d bad params\n", + __func__, __LINE__); + return -EINVAL; + } + + /* find mcam offset per bank */ + bank_off =3D mcam_idx & (npc_priv.bank_depth - 1); + + /* Find subbank id */ + sb_id =3D bank_off / npc_priv.subbank_depth; + + /* Check if subbank id is more than maximum + * number of subbanks available + */ + if (sb_id >=3D npc_priv.num_subbanks) { + dev_err(rvu->dev, "%s:%d invalid subbank %d\n", + __func__, __LINE__, sb_id); + return -EINVAL; + } + + sb =3D &npc_priv.sb[sb_id]; + + *key_type =3D sb->key_type; + + return 0; +} + static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank = *sb, u16 sub_off, u16 *mcam_idx) { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.h index 575474fd258c..7e86c879fe99 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h @@ -230,4 +230,19 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pci= func); =20 int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast, u16 *mcast, u16 *promisc, u16 *ucast); + +void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, + u8 intf, struct mcam_entry *entry, + bool enable, u8 hw_prio); +void npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr, + int index, bool enable); +void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, + u16 src, u16 dest); +void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index, + struct mcam_entry *entry, u8 *intf, u8 *ena, + u8 *hw_prio); +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); + #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 49c9ee15c74f..24df1b67bde3 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1577,6 +1577,8 @@ struct npc_mcam_write_entry_req { u8 intf; /* Rx or Tx interface */ u8 enable_entry;/* Enable this MCAM entry ? */ u8 set_cntr; /* Set counter for this entry ? */ + u8 hw_prio; /* hardware priority, valid for cn20k */ + u64 reserved; /* reserved for future use */ }; =20 /* Enable/Disable a given entry */ @@ -1824,6 +1826,7 @@ struct npc_mcam_read_entry_rsp { struct mcam_entry entry_data; u8 intf; u8 enable; + u8 hw_prio; /* valid for cn20k */ }; =20 /* Available entries to use */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/= ethernet/marvell/octeontx2/af/rvu.h index d2a0f6821cf9..a53bb5c924ef 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -1124,8 +1124,8 @@ int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifun= c, u8 tx_pause, u8 rx_pause void rvu_mac_reset(struct rvu *rvu, u16 pcifunc); u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac); void cgx_start_linkup(struct rvu *rvu); -int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf, - int type); +int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, + u16 pcifunc, int nixlf, int type); bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blk= addr, int index); int rvu_npc_init(struct rvu *rvu); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_nix.c index 2f485a930edd..810707d0e1f2 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -5283,7 +5283,6 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, = struct msg_req *req, /* Disable the interface if it is in any multicast list */ nix_mcast_update_mce_entry(rvu, pcifunc, 0); =20 - pfvf =3D rvu_get_pfvf(rvu, pcifunc); clear_bit(NIXLF_INITIALIZED, &pfvf->flags); =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.c index 246f3568a795..ea0368b32b01 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -18,6 +18,7 @@ #include "rvu_npc_hash.h" #include "cn20k/npc.h" #include "rvu_npc.h" +#include "cn20k/reg.h" =20 #define RSVD_MCAM_ENTRIES_PER_PF 3 /* Broadcast, Promisc and AllMulticast = */ #define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */ @@ -151,10 +152,33 @@ int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, { struct rvu_hwinfo *hw =3D container_of(mcam, struct rvu_hwinfo, mcam); struct rvu *rvu =3D hw->rvu; - int pf =3D rvu_get_pf(rvu->pdev, pcifunc); + u16 bcast, mcast, promisc, ucast; int index; + int rc; + int pf; + + if (is_cn20k(rvu->pdev)) { + rc =3D npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &bcast, &mcast, + &promisc, &ucast); + if (rc) + return -EFAULT; + + switch (type) { + case NIXLF_BCAST_ENTRY: + return bcast; + case NIXLF_ALLMULTI_ENTRY: + return mcast; + case NIXLF_PROMISC_ENTRY: + return promisc; + case NIXLF_UCAST_ENTRY: + return ucast; + default: + return -EINVAL; + } + } =20 /* Check if this is for a PF */ + pf =3D rvu_get_pf(rvu->pdev, pcifunc); if (pf && !(pcifunc & RVU_PFVF_FUNC_MASK)) { /* Reserved entries exclude PF0 */ pf--; @@ -175,7 +199,12 @@ int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, =20 int npc_get_bank(struct npc_mcam *mcam, int index) { + struct rvu_hwinfo *hw =3D container_of(mcam, struct rvu_hwinfo, mcam); int bank =3D index / mcam->banksize; + struct rvu *rvu =3D hw->rvu; + + if (is_cn20k(rvu->pdev)) + return bank; =20 /* 0,1 & 2,3 banks are combined for this keysize */ if (mcam->keysize =3D=3D NPC_MCAM_KEY_X2) @@ -191,7 +220,13 @@ bool is_mcam_entry_enabled(struct rvu *rvu, struct npc= _mcam *mcam, u64 cfg; =20 index &=3D (mcam->banksize - 1); - cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_CFG(index, bank)); + if (is_cn20k(rvu->pdev)) + cfg =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(index, bank)); + else + cfg =3D rvu_read64(rvu, blkaddr, + NPC_AF_MCAMEX_BANKX_CFG(index, bank)); + return (cfg & 1); } =20 @@ -201,6 +236,13 @@ void npc_enable_mcam_entry(struct rvu *rvu, struct npc= _mcam *mcam, int bank =3D npc_get_bank(mcam, index); int actbank =3D bank; =20 + if (is_cn20k(rvu->pdev)) { + if (index < 0 || index >=3D mcam->banksize * mcam->banks) + return; + + return npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable); + } + index &=3D (mcam->banksize - 1); for (; bank < (actbank + mcam->banks_per_entry); bank++) { rvu_write64(rvu, blkaddr, @@ -369,6 +411,7 @@ static u64 npc_get_default_entry_action(struct rvu *rvu= , struct npc_mcam *mcam, int blkaddr, u16 pf_func) { int bank, nixlf, index; + u64 reg; =20 /* get ucast entry rule entry index */ if (nix_get_nixlf(rvu, pf_func, &nixlf, NULL)) { @@ -383,8 +426,12 @@ static u64 npc_get_default_entry_action(struct rvu *rv= u, struct npc_mcam *mcam, bank =3D npc_get_bank(mcam, index); index &=3D (mcam->banksize - 1); =20 - return rvu_read64(rvu, blkaddr, - NPC_AF_MCAMEX_BANKX_ACTION(index, bank)); + if (is_cn20k(rvu->pdev)) + reg =3D NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 0); + else + reg =3D NPC_AF_MCAMEX_BANKX_ACTION(index, bank); + + return rvu_read64(rvu, blkaddr, reg); } =20 static void npc_fixup_vf_rule(struct rvu *rvu, struct npc_mcam *mcam, @@ -549,6 +596,9 @@ static void npc_copy_mcam_entry(struct rvu *rvu, struct= npc_mcam *mcam, u64 cfg, sreg, dreg; int bank, i; =20 + if (is_cn20k(rvu->pdev)) + return npc_cn20k_copy_mcam_entry(rvu, blkaddr, src, dest); + src &=3D (mcam->banksize - 1); dest &=3D (mcam->banksize - 1); =20 @@ -585,20 +635,31 @@ u64 npc_get_mcam_action(struct rvu *rvu, struct npc_m= cam *mcam, int blkaddr, int index) { int bank =3D npc_get_bank(mcam, index); + u64 reg; =20 index &=3D (mcam->banksize - 1); - return rvu_read64(rvu, blkaddr, - NPC_AF_MCAMEX_BANKX_ACTION(index, bank)); + + if (is_cn20k(rvu->pdev)) + reg =3D NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 0); + else + reg =3D NPC_AF_MCAMEX_BANKX_ACTION(index, bank); + return rvu_read64(rvu, blkaddr, reg); } =20 void npc_set_mcam_action(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, int index, u64 cfg) { int bank =3D npc_get_bank(mcam, index); + u64 reg; =20 index &=3D (mcam->banksize - 1); - return rvu_write64(rvu, blkaddr, - NPC_AF_MCAMEX_BANKX_ACTION(index, bank), cfg); + + if (is_cn20k(rvu->pdev)) + reg =3D NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 0); + else + reg =3D NPC_AF_MCAMEX_BANKX_ACTION(index, bank); + + return rvu_write64(rvu, blkaddr, reg, cfg); } =20 void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc, @@ -973,10 +1034,17 @@ static void npc_update_vf_flow_entry(struct rvu *rvu= , struct npc_mcam *mcam, /* disable before mcam entry update */ npc_enable_mcam_entry(rvu, mcam, blkaddr, actindex, false); + /* update 'action' */ - rvu_write64(rvu, blkaddr, - NPC_AF_MCAMEX_BANKX_ACTION(entry, bank), - rx_action); + if (is_cn20k(rvu->pdev)) + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(entry, bank, 0), + rx_action); + else + rvu_write64(rvu, blkaddr, + NPC_AF_MCAMEX_BANKX_ACTION(entry, bank), + rx_action); + if (enable) npc_enable_mcam_entry(rvu, mcam, blkaddr, actindex, true); @@ -993,6 +1061,7 @@ static void npc_update_rx_action_with_alg_idx(struct r= vu *rvu, struct nix_rx_act struct npc_mcam *mcam =3D &rvu->hw->mcam; struct rvu_hwinfo *hw =3D rvu->hw; int bank, op_rss; + u64 reg; =20 if (!is_mcam_entry_enabled(rvu, mcam, blkaddr, mcam_index)) return; @@ -1002,15 +1071,19 @@ static void npc_update_rx_action_with_alg_idx(struc= t rvu *rvu, struct nix_rx_act bank =3D npc_get_bank(mcam, mcam_index); mcam_index &=3D (mcam->banksize - 1); =20 + if (is_cn20k(rvu->pdev)) + reg =3D NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_index, + bank, 0); + else + reg =3D NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank); + /* If Rx action is MCAST update only RSS algorithm index */ if (!op_rss) { - *(u64 *)&action =3D rvu_read64(rvu, blkaddr, - NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank)); + *(u64 *)&action =3D rvu_read64(rvu, blkaddr, reg); =20 action.flow_key_alg =3D alg_idx; } - rvu_write64(rvu, blkaddr, - NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank), *(u64 *)&action); + rvu_write64(rvu, blkaddr, reg, *(u64 *)&action); } =20 void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixl= f, @@ -1020,6 +1093,7 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, = u16 pcifunc, int nixlf, struct nix_rx_action action; int blkaddr, index, bank; struct rvu_pfvf *pfvf; + u64 reg; =20 blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) @@ -1042,8 +1116,12 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu,= u16 pcifunc, int nixlf, bank =3D npc_get_bank(mcam, index); index &=3D (mcam->banksize - 1); =20 - *(u64 *)&action =3D rvu_read64(rvu, blkaddr, - NPC_AF_MCAMEX_BANKX_ACTION(index, bank)); + if (is_cn20k(rvu->pdev)) + reg =3D NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, bank, 0); + else + reg =3D NPC_AF_MCAMEX_BANKX_ACTION(index, bank); + + *(u64 *)&action =3D rvu_read64(rvu, blkaddr, reg); /* Ignore if no action was set earlier */ if (!*(u64 *)&action) return; @@ -1053,9 +1131,7 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, = u16 pcifunc, int nixlf, action.index =3D group; action.flow_key_alg =3D alg_idx; =20 - rvu_write64(rvu, blkaddr, - NPC_AF_MCAMEX_BANKX_ACTION(index, bank), *(u64 *)&action); - + rvu_write64(rvu, blkaddr, reg, *(u64 *)&action); /* update the VF flow rule action with the VF default entry action */ if (mcam_index < 0) npc_update_vf_flow_entry(rvu, mcam, blkaddr, pcifunc, @@ -1870,46 +1946,56 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkadd= r) int cntr; u64 cfg; =20 - /* Actual number of MCAM entries vary by entry size */ cfg =3D (rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(0)) >> 32) & 0x07; - mcam->total_entries =3D (mcam->banks / BIT_ULL(cfg)) * mcam->banksize; mcam->keysize =3D cfg; =20 /* Number of banks combined per MCAM entry */ if (is_cn20k(rvu->pdev)) { + /* In cn20k, x2 entries is allowed for x4 profile. + * set total_entries as 8192 * 2 and key size as x2. + */ + mcam->total_entries =3D mcam->banks * mcam->banksize; if (cfg =3D=3D NPC_MCAM_KEY_X2) mcam->banks_per_entry =3D 1; else mcam->banks_per_entry =3D 2; + + rsvd =3D 0; } else { + mcam->total_entries =3D (mcam->banks / BIT_ULL(cfg)) * + mcam->banksize; + if (cfg =3D=3D NPC_MCAM_KEY_X4) mcam->banks_per_entry =3D 4; else if (cfg =3D=3D NPC_MCAM_KEY_X2) mcam->banks_per_entry =3D 2; else mcam->banks_per_entry =3D 1; - } =20 - /* Reserve one MCAM entry for each of the NIX LF to - * guarantee space to install default matching DMAC rule. - * Also reserve 2 MCAM entries for each PF for default - * channel based matching or 'bcast & promisc' matching to - * support BCAST and PROMISC modes of operation for PFs. - * PF0 is excluded. - */ - rsvd =3D (nixlf_count * RSVD_MCAM_ENTRIES_PER_NIXLF) + - ((rvu->hw->total_pfs - 1) * RSVD_MCAM_ENTRIES_PER_PF); - if (mcam->total_entries <=3D rsvd) { - dev_warn(rvu->dev, - "Insufficient NPC MCAM size %d for pkt I/O, exiting\n", - mcam->total_entries); - return -ENOMEM; + /* Reserve one MCAM entry for each of the NIX LF to + * guarantee space to install default matching DMAC rule. + * Also reserve 2 MCAM entries for each PF for default + * channel based matching or 'bcast & promisc' matching to + * support BCAST and PROMISC modes of operation for PFs. + * PF0 is excluded. + */ + rsvd =3D (nixlf_count * RSVD_MCAM_ENTRIES_PER_NIXLF) + + ((rvu->hw->total_pfs - 1) * RSVD_MCAM_ENTRIES_PER_PF); + if (mcam->total_entries <=3D rsvd) { + dev_warn(rvu->dev, + "Insufficient NPC MCAM size %d for pkt I/O, exiting\n", + mcam->total_entries); + return -ENOMEM; + } } =20 mcam->bmap_entries =3D mcam->total_entries - rsvd; - mcam->nixlf_offset =3D mcam->bmap_entries; - mcam->pf_offset =3D mcam->nixlf_offset + nixlf_count; + /* cn20k does not need offsets to alloc mcam entries */ + if (!is_cn20k(rvu->pdev)) { + mcam->nixlf_offset =3D mcam->bmap_entries; + mcam->pf_offset =3D mcam->nixlf_offset + nixlf_count; + } =20 /* Allocate bitmaps for managing MCAM entries */ mcam->bmap =3D bitmap_zalloc(mcam->bmap_entries, GFP_KERNEL); @@ -1933,13 +2019,15 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkadd= r) * allocations and another 1/8th at the top for high priority * allocations. */ - mcam->lprio_count =3D mcam->bmap_entries / 8; - if (mcam->lprio_count > BITS_PER_LONG) - mcam->lprio_count =3D round_down(mcam->lprio_count, - BITS_PER_LONG); - mcam->lprio_start =3D mcam->bmap_entries - mcam->lprio_count; - mcam->hprio_count =3D mcam->lprio_count; - mcam->hprio_end =3D mcam->hprio_count; + if (!is_cn20k(rvu->pdev)) { + mcam->lprio_count =3D mcam->bmap_entries / 8; + if (mcam->lprio_count > BITS_PER_LONG) + mcam->lprio_count =3D round_down(mcam->lprio_count, + BITS_PER_LONG); + mcam->lprio_start =3D mcam->bmap_entries - mcam->lprio_count; + mcam->hprio_count =3D mcam->lprio_count; + mcam->hprio_end =3D mcam->hprio_count; + } =20 /* Allocate bitmap for managing MCAM counters and memory * for saving counter to RVU PFFUNC allocation mapping. @@ -2063,15 +2151,13 @@ static void rvu_npc_setup_interfaces(struct rvu *rv= u, int blkaddr) struct npc_mcam *mcam =3D &rvu->hw->mcam; struct rvu_hwinfo *hw =3D rvu->hw; u64 nibble_ena, rx_kex, tx_kex; - u64 *keyx_cfg; + u64 *keyx_cfg, reg; u8 intf; =20 - if (is_cn20k(rvu->pdev)) { + if (is_cn20k(rvu->pdev)) keyx_cfg =3D mkex_extr->keyx_cfg; - goto skip_miss_cntr; - } - - keyx_cfg =3D mkex->keyx_cfg; + else + keyx_cfg =3D mkex->keyx_cfg; =20 /* Reserve last counter for MCAM RX miss action which is set to * drop packet. This way we will know how many pkts didn't match @@ -2080,7 +2166,6 @@ static void rvu_npc_setup_interfaces(struct rvu *rvu,= int blkaddr) mcam->counters.max--; mcam->rx_miss_act_cntr =3D mcam->counters.max; =20 -skip_miss_cntr: rx_kex =3D keyx_cfg[NIX_INTF_RX]; tx_kex =3D keyx_cfg[NIX_INTF_TX]; =20 @@ -2103,14 +2188,18 @@ static void rvu_npc_setup_interfaces(struct rvu *rv= u, int blkaddr) rx_kex); =20 if (is_cn20k(rvu->pdev)) - continue; + reg =3D NPC_AF_INTFX_MISS_ACTX(intf, 0); + else + reg =3D NPC_AF_INTFX_MISS_ACT(intf); =20 /* If MCAM lookup doesn't result in a match, drop the received * packet. And map this action to a counter to count dropped * packets. */ - rvu_write64(rvu, blkaddr, - NPC_AF_INTFX_MISS_ACT(intf), NIX_RX_ACTIONOP_DROP); + rvu_write64(rvu, blkaddr, reg, NIX_RX_ACTIONOP_DROP); + + if (is_cn20k(rvu->pdev)) + continue; =20 /* NPC_AF_INTFX_MISS_STAT_ACT[14:12] - counter[11:9] * NPC_AF_INTFX_MISS_STAT_ACT[8:0] - counter[8:0] @@ -2130,12 +2219,15 @@ static void rvu_npc_setup_interfaces(struct rvu *rv= u, int blkaddr) rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf), tx_kex); =20 + if (is_cn20k(rvu->pdev)) + reg =3D NPC_AF_INTFX_MISS_ACTX(intf, 0); + else + reg =3D NPC_AF_INTFX_MISS_ACT(intf); + /* Set TX miss action to UCAST_DEFAULT i.e * transmit the packet on NIX LF SQ's default channel. */ - rvu_write64(rvu, blkaddr, - NPC_AF_INTFX_MISS_ACT(intf), - NIX_TX_ACTIONOP_UCAST_DEFAULT); + rvu_write64(rvu, blkaddr, reg, NIX_TX_ACTIONOP_UCAST_DEFAULT); } } =20 @@ -2333,6 +2425,10 @@ static void npc_map_mcam_entry_and_cntr(struct rvu *= rvu, struct npc_mcam *mcam, /* Set mapping and increment counter's refcnt */ mcam->entry2cntr_map[entry] =3D cntr; mcam->cntr_refcnt[cntr]++; + + if (is_cn20k(rvu->pdev)) + return; + /* Enable stats */ rvu_write64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank), @@ -2390,6 +2486,7 @@ static void npc_mcam_free_all_entries(struct rvu *rvu= , struct npc_mcam *mcam, int blkaddr, u16 pcifunc) { u16 index, cntr; + int rc; =20 /* Scan all MCAM entries and free the ones mapped to 'pcifunc' */ for (index =3D 0; index < mcam->bmap_entries; index++) { @@ -2407,6 +2504,13 @@ static void npc_mcam_free_all_entries(struct rvu *rv= u, struct npc_mcam *mcam, blkaddr, index, cntr); mcam->entry2target_pffunc[index] =3D 0x0; + if (is_cn20k(rvu->pdev)) { + rc =3D npc_cn20k_idx_free(rvu, &index, 1); + if (rc) + dev_err(rvu->dev, + "Failed to free mcam idx=3D%u pcifunc=3D%#x\n", + index, pcifunc); + } } } } @@ -2553,14 +2657,74 @@ static int npc_mcam_alloc_entries(struct npc_mcam *= mcam, u16 pcifunc, struct npc_mcam_alloc_entry_req *req, struct npc_mcam_alloc_entry_rsp *rsp) { + struct rvu_hwinfo *hw =3D container_of(mcam, struct rvu_hwinfo, mcam); u16 entry_list[NPC_MAX_NONCONTIG_ENTRIES]; u16 fcnt, hp_fcnt, lp_fcnt; + struct rvu *rvu =3D hw->rvu; u16 start, end, index; int entry, next_start; bool reverse =3D false; unsigned long *bmap; + int ret, limit =3D 0; u16 max_contig; =20 + if (!is_cn20k(rvu->pdev)) + goto not_cn20k; + + /* The below table is being followed during allocation, + * + * 1. ref_entry =3D=3D 0 && prio =3D=3D HIGH && count =3D=3D 1 =3D=3D> u= ser wants to allocate 0th index + * 2. ref_entry =3D=3D 0 && prio =3D=3D HIGH && count > 1 =3D=3D> Inval= id request + * 3. ref_entry =3D=3D 0 && prio =3D=3D LOW && count >=3D 1 =3D=3D> lim= it =3D 0 + * 4. ref_entry !=3D 0 && prio =3D=3D HIGH && count >=3D 1 =3D=3D> limit= =3D 0 + * 5. ref_entry !=3D 0 && prio =3D=3D LOW && count >=3D1 =3D=3D> limit= =3D Max (X2: 2*8192, X4: 8192) + */ + if (req->ref_entry && req->ref_prio =3D=3D NPC_MCAM_LOWER_PRIO) { + if (req->kw_type =3D=3D NPC_MCAM_KEY_X2) + limit =3D 2 * mcam->bmap_entries; + else + limit =3D mcam->bmap_entries; + } + + 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); + + if (ret) { + rsp->count =3D 0; + return NPC_MCAM_ALLOC_FAILED; + } + + rsp->count =3D req->count; + if (req->contig) + rsp->entry =3D rsp->entry_list[0]; + + /* cn20k, entries allocation algorithm is different. + * This common API updates some bitmap on usage etc, which + * will be used by other functions. So update those for + * cn20k as well. + */ + + 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]; + npc_mcam_set_bit(mcam, index); + mcam->entry2pfvf_map[index] =3D pcifunc; + mcam->entry2cntr_map[index] =3D NPC_MCAM_INVALID_MAP; + } + + /* cn20k, free count is provided thru different mbox message. + * one counter to indicate free x2 slots and free x4 slots + * does not provide any useful information to the user. + */ + rsp->free_count =3D -1; + mutex_unlock(&mcam->lock); + + return 0; + +not_cn20k: mutex_lock(&mcam->lock); =20 /* Check if there are any free entries */ @@ -2881,6 +3045,14 @@ int rvu_mbox_handler_npc_mcam_free_entry(struct rvu = *rvu, npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr, req->entry, cntr); =20 + if (is_cn20k(rvu->pdev)) { + rc =3D npc_cn20k_idx_free(rvu, &req->entry, 1); + if (rc) + dev_err(rvu->dev, + "Failed to free index=3D%u\n", + req->entry); + } + goto exit; =20 free_all: 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 02b6c7294bcb..03e079046601 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -1756,14 +1756,19 @@ static int npc_update_dmac_value(struct rvu *rvu, i= nt npcblkaddr, struct npc_mcam_write_entry_req write_req =3D { 0 }; struct mcam_entry *entry =3D &write_req.entry_data; struct npc_mcam *mcam =3D &rvu->hw->mcam; + u8 intf, enable, hw_prio; struct msg_rsp rsp; - u8 intf, enable; int err; =20 ether_addr_copy(rule->packet.dmac, pfvf->mac_addr); =20 - npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry, - entry, &intf, &enable); + if (is_cn20k(rvu->pdev)) + npc_cn20k_read_mcam_entry(rvu, npcblkaddr, rule->entry, + entry, &intf, + &enable, &hw_prio); + else + npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry, + entry, &intf, &enable); =20 npc_update_entry(rvu, NPC_DMAC, entry, ether_addr_to_u64(pfvf->mac_addr), 0, --=20 2.43.0 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0a-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 5F468314B94; Mon, 5 Jan 2026 02:33:54 +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=1767580437; cv=none; b=WPBoTy4xwZB45NHbGKksT/zsk7s7cRz6Gg0bvIZswW+Y1mS+4jEZaOFsByYQXadmWfy7EQEDB2B3ymn8IU2QxOa49MvrBQntp4edwfRafOkXBH26t75GIP5yyLBlH8Nj+zEn5b718i6bGLX6LIrUQm9uHkB+Cq/MDqxP83FB/BU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580437; c=relaxed/simple; bh=8UdscG7n+8w8yGvqXREUag+JSGQBlQWLaqRkPM2sgVU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ypt6ZsQ5q+phB1HPLUWYYYDTFnKoHtZsnzVO4CixIWd/Rq+K0c5rllDvylBRFbnvx7q/HRkxY5goV/acTXWmv9UIYDzfkyzaY+dui6L5/OHUModllhekJTYR3A2nYRXpTnmVpjACjh6Iq5zp9eKrrhApomouECZ6Uf74c44QUzI= 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=J+RhY3wt; 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="J+RhY3wt" Received: from pps.filterd (m0431384.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604MtNqT2644729; Sun, 4 Jan 2026 18:33:46 -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 FEPGnr9kl1L6k9aTcoQINL4asBvqBfAGZY8qYopu3U=; b=J+RhY3wtYaC4NvBYY 9z+NIilcTMtD8xpexReRzt7Yb+U1DCqtxV6zjMd7IwGJFIJekXsy9vL6qgRnNIFq oguppRUfdAdcVNTJyDqlALmAy4Nw4lKwsqcxR1bGYB8hnOnU7fyXFYCAQ4/GtDBq 8X2F1mAxS7j6cQwjHrLFNmwgG6n3MdLWo8R5EaUB9PpI5scX7moo3C/DXfURpYID LbPJQ1lNoDJHtw4LrIeNdVC4y5jlin38o3McufFqIs//0fI3L0Omw6N98J0F+Fjv Do2ywOzn7A+hjSc+ImcqfvsDtZQHUUH+FNr2A4Jq3sxs8fWNzCPTbm7cBklKFObG ARquw== Received: from dc6wp-exch02.marvell.com ([4.21.29.225]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 4bfr8bgtse-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:45 -0800 (PST) Received: from DC6WP-EXCH02.marvell.com (10.76.176.209) by DC6WP-EXCH02.marvell.com (10.76.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:33:44 -0800 Received: from maili.marvell.com (10.69.176.80) by DC6WP-EXCH02.marvell.com (10.76.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:33:44 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id 61C353F7094; Sun, 4 Jan 2026 18:33:41 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 07/13] octeontx2-af: npc: cn20k: Prepare for new SoC Date: Mon, 5 Jan 2026 08:02:48 +0530 Message-ID: <20260105023254.1426488-8-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: mzoFMA80zfXcTQwMsiGlx9fP3KFrNHL6 X-Proofpoint-GUID: mzoFMA80zfXcTQwMsiGlx9fP3KFrNHL6 X-Authority-Analysis: v=2.4 cv=P/I3RyAu c=1 sm=1 tr=0 ts=695b2309 cx=c_pps a=gIfcoYsirJbf48DBMSPrZA==:117 a=gIfcoYsirJbf48DBMSPrZA==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=2uKIO9XhH62ytmgeegMA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX03zMEKNlyIOo COkZeoFXWIhBuyhgwI8qTCVHQYNMT4svMB2Q54UDogiUbYAioCJMnrCb4mEh+l4Q6Yt/OIHKCvu zpAZBq26VsYyLmcu7B7Q6uFiOvYKkH4+wWhfyL3EC8XOte+1dibjxpOOjsj4ZH4tTAvfyiFU1nh oct4fJB/ZHJ7/HZEQ9aEnj/QMAR75ux1OxwmIDRCF6MMtih8p/BkLy8zczsfTp6n1ZISJiB6MZD XXEYNDQCl6jPS7GT5jOaPBcl4OfIkngABCjuW6dqOw5EXVz2BRUBHIA635lZp0UmNa8KEJOh7OR klyawcrLvPr/DuhVu9uTKRe0XNGgQS34pzLJfSkL00vUg90iw1DmxikMEbM1Lh7dzEsjYoENdv4 CxAe573lEd0+oKZhfxRVrTj2NkHIDtzz5sp1OW9Otw7YyWBaE6c+Ltv/USXK9lYF9t3GmMsJQkv kVx8k+c0SlypfjYvotQ== 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" Current code pass mcam_entry structure to all low level functions. This is not proper: 1) We need to modify all functions to support a new SoC 2) It does not look good to pass soc specific structure to all common functions. This patch adds a mcam meta data structure, which is populated and passed to low level functions. Signed-off-by: Ratheesh Kannoth --- .../net/ethernet/marvell/octeontx2/af/mbox.h | 8 + .../marvell/octeontx2/af/rvu_npc_fs.c | 140 +++++++++++------- .../marvell/octeontx2/af/rvu_npc_fs.h | 2 +- .../marvell/octeontx2/af/rvu_npc_hash.c | 6 +- .../marvell/octeontx2/af/rvu_npc_hash.h | 2 +- 5 files changed, 98 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net= /ethernet/marvell/octeontx2/af/mbox.h index 24df1b67bde3..7c58552435d2 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1561,6 +1561,14 @@ struct npc_mcam_free_entry_req { u8 all; /* If all entries allocated to this PFVF to be freed */ }; =20 +struct mcam_entry_mdata { + u64 *kw; + u64 *kw_mask; + u64 *action; + u64 *vtag_action; + u8 max_kw; +}; + struct mcam_entry { #define NPC_MAX_KWS_IN_KEY 8 /* Number of keywords in max keywidth */ u64 kw[NPC_MAX_KWS_IN_KEY]; 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 03e079046601..8b28dd88ad83 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -898,11 +898,12 @@ static int npc_check_unsupported_flows(struct rvu *rv= u, u64 features, u8 intf) * dont care. */ void npc_update_entry(struct rvu *rvu, enum key_fields type, - struct mcam_entry *entry, u64 val_lo, + struct mcam_entry_mdata *mdata, u64 val_lo, u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf) { struct npc_mcam *mcam =3D &rvu->hw->mcam; struct mcam_entry dummy =3D { {0} }; + u64 *kw, *kw_mask, *val, *mask; struct npc_key_field *field; u64 kw1, kw2, kw3; int i, max_kw; @@ -915,10 +916,9 @@ void npc_update_entry(struct rvu *rvu, enum key_fields= type, if (!field->nr_kws) return; =20 - if (is_cn20k(rvu->pdev)) - max_kw =3D NPC_MAX_KWS_IN_KEY; - else - max_kw =3D NPC_MAX_KWS_IN_KEY - 1; + max_kw =3D NPC_MAX_KWS_IN_KEY; + kw =3D dummy.kw; + kw_mask =3D dummy.kw_mask; =20 for (i =3D 0; i < max_kw; i++) { if (!field->kw_mask[i]) @@ -927,10 +927,10 @@ void npc_update_entry(struct rvu *rvu, enum key_field= s type, shift =3D __ffs64(field->kw_mask[i]); /* update entry value */ kw1 =3D (val_lo << shift) & field->kw_mask[i]; - dummy.kw[i] =3D kw1; + kw[i] =3D kw1; /* update entry mask */ kw1 =3D (mask_lo << shift) & field->kw_mask[i]; - dummy.kw_mask[i] =3D kw1; + kw_mask[i] =3D kw1; =20 if (field->nr_kws =3D=3D 1) break; @@ -940,12 +940,12 @@ void npc_update_entry(struct rvu *rvu, enum key_field= s type, kw2 =3D shift ? val_lo >> (64 - shift) : 0; kw2 |=3D (val_hi << shift); kw2 &=3D field->kw_mask[i + 1]; - dummy.kw[i + 1] =3D kw2; + kw[i + 1] =3D kw2; /* update entry mask */ kw2 =3D shift ? mask_lo >> (64 - shift) : 0; kw2 |=3D (mask_hi << shift); kw2 &=3D field->kw_mask[i + 1]; - dummy.kw_mask[i + 1] =3D kw2; + kw_mask[i + 1] =3D kw2; break; } /* place remaining bits of key value in kw[x + 1], kw[x + 2] */ @@ -956,34 +956,39 @@ void npc_update_entry(struct rvu *rvu, enum key_field= s type, kw2 &=3D field->kw_mask[i + 1]; kw3 =3D shift ? val_hi >> (64 - shift) : 0; kw3 &=3D field->kw_mask[i + 2]; - dummy.kw[i + 1] =3D kw2; - dummy.kw[i + 2] =3D kw3; + kw[i + 1] =3D kw2; + kw[i + 2] =3D kw3; /* update entry mask */ kw2 =3D shift ? mask_lo >> (64 - shift) : 0; kw2 |=3D (mask_hi << shift); kw2 &=3D field->kw_mask[i + 1]; kw3 =3D shift ? mask_hi >> (64 - shift) : 0; kw3 &=3D field->kw_mask[i + 2]; - dummy.kw_mask[i + 1] =3D kw2; - dummy.kw_mask[i + 2] =3D kw3; + kw_mask[i + 1] =3D kw2; + kw_mask[i + 2] =3D kw3; break; } } /* dummy is ready with values and masks for given key * field now clear and update input entry with those */ - for (i =3D 0; i < max_kw; i++) { + + val =3D mdata->kw; + mask =3D mdata->kw_mask; + + for (i =3D 0; i < max_kw; i++, val++, mask++) { if (!field->kw_mask[i]) continue; - entry->kw[i] &=3D ~field->kw_mask[i]; - entry->kw_mask[i] &=3D ~field->kw_mask[i]; =20 - entry->kw[i] |=3D dummy.kw[i]; - entry->kw_mask[i] |=3D dummy.kw_mask[i]; + *val &=3D ~field->kw_mask[i]; + *mask &=3D ~field->kw_mask[i]; + + *val |=3D kw[i]; + *mask |=3D kw_mask[i]; } } =20 -static void npc_update_ipv6_flow(struct rvu *rvu, struct mcam_entry *entry, +static void npc_update_ipv6_flow(struct rvu *rvu, struct mcam_entry_mdata = *mdata, u64 features, struct flow_msg *pkt, struct flow_msg *mask, struct rvu_npc_mcam_rule *output, u8 intf) @@ -1009,7 +1014,7 @@ static void npc_update_ipv6_flow(struct rvu *rvu, str= uct mcam_entry *entry, val_hi =3D (u64)src_ip[0] << 32 | src_ip[1]; val_lo =3D (u64)src_ip[2] << 32 | src_ip[3]; =20 - npc_update_entry(rvu, NPC_SIP_IPV6, entry, val_lo, val_hi, + npc_update_entry(rvu, NPC_SIP_IPV6, mdata, val_lo, val_hi, mask_lo, mask_hi, intf); memcpy(opkt->ip6src, pkt->ip6src, sizeof(opkt->ip6src)); memcpy(omask->ip6src, mask->ip6src, sizeof(omask->ip6src)); @@ -1023,14 +1028,14 @@ static void npc_update_ipv6_flow(struct rvu *rvu, s= truct mcam_entry *entry, val_hi =3D (u64)dst_ip[0] << 32 | dst_ip[1]; val_lo =3D (u64)dst_ip[2] << 32 | dst_ip[3]; =20 - npc_update_entry(rvu, NPC_DIP_IPV6, entry, val_lo, val_hi, + npc_update_entry(rvu, NPC_DIP_IPV6, mdata, val_lo, val_hi, mask_lo, mask_hi, intf); memcpy(opkt->ip6dst, pkt->ip6dst, sizeof(opkt->ip6dst)); memcpy(omask->ip6dst, mask->ip6dst, sizeof(omask->ip6dst)); } } =20 -static void npc_update_vlan_features(struct rvu *rvu, struct mcam_entry *e= ntry, +static void npc_update_vlan_features(struct rvu *rvu, struct mcam_entry_md= ata *mdata, u64 features, u8 intf) { bool ctag =3D !!(features & BIT_ULL(NPC_VLAN_ETYPE_CTAG)); @@ -1039,20 +1044,20 @@ static void npc_update_vlan_features(struct rvu *rv= u, struct mcam_entry *entry, =20 /* If only VLAN id is given then always match outer VLAN id */ if (vid && !ctag && !stag) { - npc_update_entry(rvu, NPC_LB, entry, + npc_update_entry(rvu, NPC_LB, mdata, NPC_LT_LB_STAG_QINQ | NPC_LT_LB_CTAG, 0, NPC_LT_LB_STAG_QINQ & NPC_LT_LB_CTAG, 0, intf); return; } if (ctag) - npc_update_entry(rvu, NPC_LB, entry, NPC_LT_LB_CTAG, 0, + npc_update_entry(rvu, NPC_LB, mdata, NPC_LT_LB_CTAG, 0, ~0ULL, 0, intf); if (stag) - npc_update_entry(rvu, NPC_LB, entry, NPC_LT_LB_STAG_QINQ, 0, + npc_update_entry(rvu, NPC_LB, mdata, NPC_LT_LB_STAG_QINQ, 0, ~0ULL, 0, intf); } =20 -static void npc_update_flow(struct rvu *rvu, struct mcam_entry *entry, +static void npc_update_flow(struct rvu *rvu, struct mcam_entry_mdata *mdat= a, u64 features, struct flow_msg *pkt, struct flow_msg *mask, struct rvu_npc_mcam_rule *output, u8 intf, @@ -1070,39 +1075,39 @@ static void npc_update_flow(struct rvu *rvu, struct= mcam_entry *entry, =20 /* For tcp/udp/sctp LTYPE should be present in entry */ if (features & BIT_ULL(NPC_IPPROTO_TCP)) - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_TCP, + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_TCP, 0, ~0ULL, 0, intf); if (features & BIT_ULL(NPC_IPPROTO_UDP)) - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_UDP, + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_UDP, 0, ~0ULL, 0, intf); if (features & BIT_ULL(NPC_IPPROTO_SCTP)) - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_SCTP, + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_SCTP, 0, ~0ULL, 0, intf); if (features & BIT_ULL(NPC_IPPROTO_ICMP)) - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP, + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_ICMP, 0, ~0ULL, 0, intf); if (features & BIT_ULL(NPC_IPPROTO_ICMP6)) - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP6, + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_ICMP6, 0, ~0ULL, 0, intf); =20 /* For AH, LTYPE should be present in entry */ if (features & BIT_ULL(NPC_IPPROTO_AH)) - npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_AH, + npc_update_entry(rvu, NPC_LD, mdata, NPC_LT_LD_AH, 0, ~0ULL, 0, intf); /* For ESP, LTYPE should be present in entry */ if (features & BIT_ULL(NPC_IPPROTO_ESP)) - npc_update_entry(rvu, NPC_LE, entry, NPC_LT_LE_ESP, + npc_update_entry(rvu, NPC_LE, mdata, NPC_LT_LE_ESP, 0, ~0ULL, 0, intf); =20 if (features & BIT_ULL(NPC_LXMB)) { output->lxmb =3D is_broadcast_ether_addr(pkt->dmac) ? 2 : 1; - npc_update_entry(rvu, NPC_LXMB, entry, output->lxmb, 0, + npc_update_entry(rvu, NPC_LXMB, mdata, output->lxmb, 0, output->lxmb, 0, intf); } #define NPC_WRITE_FLOW(field, member, val_lo, val_hi, mask_lo, mask_hi) = \ do { \ if (features & BIT_ULL((field))) { \ - npc_update_entry(rvu, (field), entry, (val_lo), (val_hi), \ + npc_update_entry(rvu, (field), mdata, (val_lo), (val_hi), \ (mask_lo), (mask_hi), intf); \ memcpy(&opkt->member, &pkt->member, sizeof(pkt->member)); \ memcpy(&omask->member, &mask->member, sizeof(mask->member)); \ @@ -1190,10 +1195,10 @@ do { \ =20 NPC_WRITE_FLOW(NPC_IPFRAG_IPV6, next_header, pkt->next_header, 0, mask->next_header, 0); - npc_update_ipv6_flow(rvu, entry, features, pkt, mask, output, intf); - npc_update_vlan_features(rvu, entry, features, intf); + npc_update_ipv6_flow(rvu, mdata, features, pkt, mask, output, intf); + npc_update_vlan_features(rvu, mdata, features, intf); =20 - npc_update_field_hash(rvu, intf, entry, blkaddr, features, + npc_update_field_hash(rvu, intf, mdata, blkaddr, features, pkt, mask, opkt, omask); } =20 @@ -1281,8 +1286,20 @@ static int npc_mcast_update_action_index(struct rvu = *rvu, struct npc_install_flo return 0; } =20 +static void +npc_populate_mcam_mdata(struct rvu *rvu, + struct mcam_entry_mdata *mdata, + struct mcam_entry *entry) +{ + mdata->kw =3D entry->kw; + mdata->kw_mask =3D entry->kw_mask; + mdata->action =3D &entry->action; + mdata->vtag_action =3D &entry->vtag_action; + mdata->max_kw =3D NPC_MAX_KWS_IN_KEY; +} + static int npc_update_rx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, - struct mcam_entry *entry, + struct mcam_entry_mdata *mdata, struct npc_install_flow_req *req, u16 target, bool pf_set_vfs_mac) { @@ -1293,7 +1310,7 @@ static int npc_update_rx_entry(struct rvu *rvu, struc= t rvu_pfvf *pfvf, if (rswitch->mode =3D=3D DEVLINK_ESWITCH_MODE_SWITCHDEV && pf_set_vfs_mac) req->chan_mask =3D 0x0; /* Do not care channel */ =20 - npc_update_entry(rvu, NPC_CHAN, entry, req->channel, 0, req->chan_mask, + npc_update_entry(rvu, NPC_CHAN, mdata, req->channel, 0, req->chan_mask, 0, NIX_INTF_RX); =20 *(u64 *)&action =3D 0x00; @@ -1325,12 +1342,12 @@ static int npc_update_rx_entry(struct rvu *rvu, str= uct rvu_pfvf *pfvf, action.match_id =3D req->match_id; } =20 - entry->action =3D *(u64 *)&action; + *mdata->action =3D *(u64 *)&action; =20 /* VTAG0 starts at 0th byte of LID_B. * VTAG1 starts at 4th byte of LID_B. */ - entry->vtag_action =3D FIELD_PREP(RX_VTAG0_VALID_BIT, req->vtag0_valid) | + *mdata->vtag_action =3D FIELD_PREP(RX_VTAG0_VALID_BIT, req->vtag0_valid) | FIELD_PREP(RX_VTAG0_TYPE_MASK, req->vtag0_type) | FIELD_PREP(RX_VTAG0_LID_MASK, NPC_LID_LB) | FIELD_PREP(RX_VTAG0_RELPTR_MASK, 0) | @@ -1343,7 +1360,7 @@ static int npc_update_rx_entry(struct rvu *rvu, struc= t rvu_pfvf *pfvf, } =20 static int npc_update_tx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, - struct mcam_entry *entry, + struct mcam_entry_mdata *mdata, struct npc_install_flow_req *req, u16 target) { struct nix_tx_action action; @@ -1356,7 +1373,7 @@ static int npc_update_tx_entry(struct rvu *rvu, struc= t rvu_pfvf *pfvf, if (is_pffunc_af(req->hdr.pcifunc)) mask =3D 0; =20 - npc_update_entry(rvu, NPC_PF_FUNC, entry, (__force u16)htons(target), + npc_update_entry(rvu, NPC_PF_FUNC, mdata, (__force u16)htons(target), 0, mask, 0, NIX_INTF_TX); =20 *(u64 *)&action =3D 0x00; @@ -1369,12 +1386,12 @@ static int npc_update_tx_entry(struct rvu *rvu, str= uct rvu_pfvf *pfvf, =20 action.match_id =3D req->match_id; =20 - entry->action =3D *(u64 *)&action; + *mdata->action =3D *(u64 *)&action; =20 /* VTAG0 starts at 0th byte of LID_B. * VTAG1 starts at 4th byte of LID_B. */ - entry->vtag_action =3D FIELD_PREP(TX_VTAG0_DEF_MASK, req->vtag0_def) | + *mdata->vtag_action =3D FIELD_PREP(TX_VTAG0_DEF_MASK, req->vtag0_def) | FIELD_PREP(TX_VTAG0_OP_MASK, req->vtag0_op) | FIELD_PREP(TX_VTAG0_LID_MASK, NPC_LID_LA) | FIELD_PREP(TX_VTAG0_RELPTR_MASK, 20) | @@ -1396,6 +1413,7 @@ static int npc_install_flow(struct rvu *rvu, int blka= ddr, u16 target, u64 features, installed_features, missing_features =3D 0; struct npc_mcam_write_entry_req write_req =3D { 0 }; struct npc_mcam *mcam =3D &rvu->hw->mcam; + struct mcam_entry_mdata mdata =3D { }; struct rvu_npc_mcam_rule dummy =3D { 0 }; struct rvu_npc_mcam_rule *rule; u16 owner =3D req->hdr.pcifunc; @@ -1410,15 +1428,18 @@ static int npc_install_flow(struct rvu *rvu, int bl= kaddr, u16 target, entry =3D &write_req.entry_data; entry_index =3D req->entry; =20 - npc_update_flow(rvu, entry, features, &req->packet, &req->mask, &dummy, + npc_populate_mcam_mdata(rvu, &mdata, + &write_req.entry_data); + + npc_update_flow(rvu, &mdata, features, &req->packet, &req->mask, &dummy, req->intf, blkaddr); =20 if (is_npc_intf_rx(req->intf)) { - err =3D npc_update_rx_entry(rvu, pfvf, entry, req, target, pf_set_vfs_ma= c); + err =3D npc_update_rx_entry(rvu, pfvf, &mdata, req, target, pf_set_vfs_m= ac); if (err) return err; } else { - err =3D npc_update_tx_entry(rvu, pfvf, entry, req, target); + err =3D npc_update_tx_entry(rvu, pfvf, &mdata, req, target); if (err) return err; } @@ -1438,7 +1459,7 @@ static int npc_install_flow(struct rvu *rvu, int blka= ddr, u16 target, missing_features =3D (def_ucast_rule->features ^ features) & def_ucast_rule->features; if (missing_features) - npc_update_flow(rvu, entry, missing_features, + npc_update_flow(rvu, &mdata, missing_features, &def_ucast_rule->packet, &def_ucast_rule->mask, &dummy, req->intf, @@ -1754,12 +1775,17 @@ static int npc_update_dmac_value(struct rvu *rvu, i= nt npcblkaddr, struct rvu_pfvf *pfvf) { struct npc_mcam_write_entry_req write_req =3D { 0 }; - struct mcam_entry *entry =3D &write_req.entry_data; struct npc_mcam *mcam =3D &rvu->hw->mcam; + struct mcam_entry_mdata mdata =3D { }; + struct mcam_entry *entry; u8 intf, enable, hw_prio; struct msg_rsp rsp; int err; =20 + entry =3D &write_req.entry_data; + + npc_populate_mcam_mdata(rvu, &mdata, entry); + ether_addr_copy(rule->packet.dmac, pfvf->mac_addr); =20 if (is_cn20k(rvu->pdev)) @@ -1770,7 +1796,7 @@ static int npc_update_dmac_value(struct rvu *rvu, int= npcblkaddr, npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry, entry, &intf, &enable); =20 - npc_update_entry(rvu, NPC_DMAC, entry, + npc_update_entry(rvu, NPC_DMAC, &mdata, ether_addr_to_u64(pfvf->mac_addr), 0, 0xffffffffffffull, 0, intf); =20 @@ -1871,6 +1897,7 @@ int npc_install_mcam_drop_rule(struct rvu *rvu, int m= cam_idx, u16 *counter_idx, struct npc_mcam_alloc_counter_rsp cntr_rsp =3D { 0 }; struct npc_mcam_write_entry_req req =3D { 0 }; struct npc_mcam *mcam =3D &rvu->hw->mcam; + struct mcam_entry_mdata mdata =3D { }; struct rvu_npc_mcam_rule *rule; struct msg_rsp rsp; bool enabled; @@ -1926,12 +1953,15 @@ int npc_install_mcam_drop_rule(struct rvu *rvu, int= mcam_idx, u16 *counter_idx, } *counter_idx =3D cntr_rsp.cntr; =20 + npc_populate_mcam_mdata(rvu, &mdata, + &req.entry_data); + /* Fill in fields for this mcam entry */ - npc_update_entry(rvu, NPC_EXACT_RESULT, &req.entry_data, exact_val, 0, + npc_update_entry(rvu, NPC_EXACT_RESULT, &mdata, exact_val, 0, exact_mask, 0, NIX_INTF_RX); - npc_update_entry(rvu, NPC_CHAN, &req.entry_data, chan_val, 0, + npc_update_entry(rvu, NPC_CHAN, &mdata, chan_val, 0, chan_mask, 0, NIX_INTF_RX); - npc_update_entry(rvu, NPC_LXMB, &req.entry_data, bcast_mcast_val, 0, + npc_update_entry(rvu, NPC_LXMB, &mdata, bcast_mcast_val, 0, bcast_mcast_mask, 0, NIX_INTF_RX); =20 req.intf =3D NIX_INTF_RX; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.h b/drive= rs/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.h index 3f5c9042d10e..442287ee7baa 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.h @@ -15,7 +15,7 @@ #define NPC_LDATA_EN BIT_ULL(7) =20 void npc_update_entry(struct rvu *rvu, enum key_fields type, - struct mcam_entry *entry, u64 val_lo, + struct mcam_entry_mdata *mdata, u64 val_lo, u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf); =20 #endif /* RVU_NPC_FS_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c b/dri= vers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c index 5ae046c93a82..0672bf0e6fe8 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c @@ -282,7 +282,7 @@ void npc_program_mkex_hash(struct rvu *rvu, int blkaddr) } =20 void npc_update_field_hash(struct rvu *rvu, u8 intf, - struct mcam_entry *entry, + struct mcam_entry_mdata *mdata, int blkaddr, u64 features, struct flow_msg *pkt, @@ -335,7 +335,7 @@ void npc_update_field_hash(struct rvu *rvu, u8 intf, rsp, intf, hash_idx); - npc_update_entry(rvu, NPC_SIP_IPV6, entry, + npc_update_entry(rvu, NPC_SIP_IPV6, mdata, field_hash, 0, GENMASK(31, 0), 0, intf); memcpy(&opkt->ip6src, &pkt->ip6src, @@ -352,7 +352,7 @@ void npc_update_field_hash(struct rvu *rvu, u8 intf, rsp, intf, hash_idx); - npc_update_entry(rvu, NPC_DIP_IPV6, entry, + npc_update_entry(rvu, NPC_DIP_IPV6, mdata, field_hash, 0, GENMASK(31, 0), 0, intf); memcpy(&opkt->ip6dst, &pkt->ip6dst, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h b/dri= vers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h index cb25cf478f1f..4cbcae69b6d3 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h @@ -53,7 +53,7 @@ struct npc_mcam_kex_hash { } __packed; =20 void npc_update_field_hash(struct rvu *rvu, u8 intf, - struct mcam_entry *entry, + struct mcam_entry_mdata *mdata, int blkaddr, u64 features, struct flow_msg *pkt, --=20 2.43.0 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (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 D02B231AAAB; Mon, 5 Jan 2026 02:33:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580441; cv=none; b=rkE+La3d/repxD54QuIVz5rdZhdTTBcwBeN3lavWs1k+0ugPOlkr2L1HATeQqrMVmdZyVCXr4s7TKmCUsXIQNLer+hgZvRhZcD08Rxv0xO7CMhw1XbR3TZ0/t7cAKRWjKSafaIW8MZS23QyhlHRLLYqz4uzAXKAWkJXRy9j1K1w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580441; c=relaxed/simple; bh=RhTe68b+VrB90edOIf3Ik8+BOLOHn01MyurinDNT/S8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=efr9OBRq/MTTbnT2HE2WZZXpTKcY2Fdks++X7Q51XGtL5hajduwz8rHc/be7B3yXqfkZRiEFe7+swnvBApt7P1hLqze5lCniMsL2aIyFVkWGQK/ZZ3OjOis+0oX4bFW+SLnloqFlcgl4NT7lzhdRPFw5avpYBm3Qjzr2fpQ1EFU= 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=hSAmDLrT; arc=none smtp.client-ip=67.231.156.173 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="hSAmDLrT" Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604MLgOi1047632; Sun, 4 Jan 2026 18:33:49 -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=p nSkBCLUmr13ac+Q95hTjWiiuraz5YFVI957WI4eovs=; b=hSAmDLrT2FeEltth1 h427mwlAFb8ffGoYtRC1axafyRf+tThxhH2P3uv+bk6WV29x4p6NHpUXxguazNmH cENyiYeEPZ3atHhNfYEDuIj8KQwuKTfP1u0C0nmka5cMsmT6sM4aK4mo6oxmcQ6N jvIkFh/sADxGfvaNUcCZBS7+2oXXFlgU3hw0/t/8lZVUEFVUaaPc0haJFtXHMp9A jWoNNOqo0vfDPl2mTubtjHmF/DdeH2/Aq6oi41toVezbEc0AQu4GgDkg2nuN0b72 fjJqIzsp+fpYN9kA2DZat1D600+7CMdxu/2awsnI0cnTw2WdZsgz2YtaLKM5OEtL yHCEg== Received: from dc5-exch05.marvell.com ([199.233.59.128]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 4bf3gmj00x-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:48 -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:01 -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:01 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id D32033F7094; Sun, 4 Jan 2026 18:33:44 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 08/13] octeontx2-af: npc: cn20k: Add new mailboxes for CN20K silicon Date: Mon, 5 Jan 2026 08:02:49 +0530 Message-ID: <20260105023254.1426488-9-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: WuGuy3Epdk4oe2v4lUSUTpjUzyipGV3p X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX50DzAwMGSb26 yx4O7GFy2aRSeCq0YehbtiBi0aPKENMngE1+vf7b3x7atNP6b5VPFaF54hi5q2nNF/jO5IwNQK8 QOI38zmBPTqXsxVaWurfrqKX7Xrtgcu8M8oeqSLKZBasq9qD1192sfyb+7zP3CLl/5KwxgUeg7W FSA8bemQ5jdASp6fCZgqSYnFXH4nyc2jkRbRCVM9AIquOzh7PeSaEwircABKumizp2M9SmFwnZk YqCB06NtCPIvf2j8zrSe6OoHp0smR8N32XAuyUYnJmufC1mTXqptBzcgwymtl3vAR2RCuTYLKLW Cx07WDVv3FtuRRZuBimFUDJOG98xVvDhPab3KEV0Fa9MfLLfezE4L5Putfw3p3UsMWQzkyfyZK9 UFj2W+AMutVmWK5sGBw+O+bU/WCxg8Tignmdl0ShnM0rA7Wx65fGhsESZ1GZBVmomzpZcTrApGr cUVodku9UXRRj7j4sJw== X-Authority-Analysis: v=2.4 cv=PcXyRyhd c=1 sm=1 tr=0 ts=695b230d cx=c_pps a=rEv8fa4AjpPjGxpoe8rlIQ==:117 a=rEv8fa4AjpPjGxpoe8rlIQ==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=-13oorr8sCoXC6saXsEA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-GUID: WuGuy3Epdk4oe2v4lUSUTpjUzyipGV3p 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" From: Suman Ghosh Due to new requirements in CN20K, the existing `struct mcam_entry` needed to be updated. Previously, it contained two arrays, `kw` and `kw_mask`, each of size 7 (keyword size). To support CN20K requirements, the size of these arrays has been increased from 7 to 8. However, this change breaks backward compatibility because it alters the structure layout. Therefore, we decided to use separate mailboxes that use the updated `struct mcam_entry`. This patch identifies such mailboxes and adds new ones specifically for CN20K. New mailboxes added: 1. `NPC_CN20K_MCAM_WRITE_ENTRY` 2. `NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY` 3. `NPC_CN20K_MCAM_READ_ENTRY` 4. `NPC_CN20K_MCAM_READ_BASE_RULE` Signed-off-by: Suman Ghosh Signed-off-by: Ratheesh Kannoth --- .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 188 ++++++++++++++++- .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 7 +- .../net/ethernet/marvell/octeontx2/af/mbox.h | 57 ++++- .../net/ethernet/marvell/octeontx2/af/npc.h | 1 + .../net/ethernet/marvell/octeontx2/af/rvu.h | 3 +- .../marvell/octeontx2/af/rvu_debugfs.c | 28 ++- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 54 ++++- .../marvell/octeontx2/af/rvu_npc_fs.c | 199 ++++++++++++------ 8 files changed, 446 insertions(+), 91 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 28e5fa6361a5..33c0047c1bcd 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -612,9 +612,13 @@ npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkadd= r, int bank, int index) NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 1), 0); rvu_write64(rvu, blkaddr, NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W3_EXT(index, bank, 0), 0); + + /* Clear corresponding stats register */ + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank), 0); } =20 -static void npc_cn20k_get_keyword(struct mcam_entry *entry, int idx, +static void npc_cn20k_get_keyword(struct cn20k_mcam_entry *entry, int idx, u64 *cam0, u64 *cam1) { u64 kw_mask; @@ -639,7 +643,7 @@ static void npc_cn20k_get_keyword(struct mcam_entry *en= try, int idx, =20 static void npc_cn20k_config_kw_x2(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, int index, u8 intf, - struct mcam_entry *entry, + struct cn20k_mcam_entry *entry, int bank, u8 kw_type, int kw) { u64 intf_ext =3D 0, intf_ext_mask =3D 0; @@ -726,7 +730,8 @@ static void npc_cn20k_config_kw_x2(struct rvu *rvu, str= uct npc_mcam *mcam, =20 static void npc_cn20k_config_kw_x4(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, int index, u8 intf, - struct mcam_entry *entry, u8 kw_type) + struct cn20k_mcam_entry *entry, + u8 kw_type) { int kw =3D 0, bank; =20 @@ -764,9 +769,9 @@ npc_cn20k_set_mcam_bank_cfg(struct rvu *rvu, int blkadd= r, int mcam_idx, } } =20 -void -npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, u8 in= tf, - struct mcam_entry *entry, bool enable, u8 hw_prio) +void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, + u8 intf, struct cn20k_mcam_entry *entry, + bool enable, u8 hw_prio) { struct npc_mcam *mcam =3D &rvu->hw->mcam; int mcam_idx =3D index % mcam->banksize; @@ -874,7 +879,7 @@ void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blk= addr, u16 src, u16 dest) } } =20 -static void npc_cn20k_fill_entryword(struct mcam_entry *entry, int idx, +static void npc_cn20k_fill_entryword(struct cn20k_mcam_entry *entry, int i= dx, u64 cam0, u64 cam1) { entry->kw[idx] =3D cam1; @@ -882,8 +887,8 @@ static void npc_cn20k_fill_entryword(struct mcam_entry = *entry, int idx, } =20 void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index, - struct mcam_entry *entry, u8 *intf, u8 *ena, - u8 *hw_prio) + struct cn20k_mcam_entry *entry, + u8 *intf, u8 *ena, u8 *hw_prio) { struct npc_mcam *mcam =3D &rvu->hw->mcam; int kw =3D 0, bank; @@ -963,6 +968,171 @@ void npc_cn20k_read_mcam_entry(struct rvu *rvu, int b= lkaddr, u16 index, NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, 0, 1)); } =20 +int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct rvu *rvu, + struct npc_cn20k_mcam_write_entry_req *req, + struct msg_rsp *rsp) +{ + struct rvu_pfvf *pfvf =3D rvu_get_pfvf(rvu, req->hdr.pcifunc); + struct npc_mcam *mcam =3D &rvu->hw->mcam; + u16 pcifunc =3D req->hdr.pcifunc; + int blkaddr, rc; + u8 nix_intf; + + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (blkaddr < 0) + return NPC_MCAM_INVALID_REQ; + + mutex_lock(&mcam->lock); + rc =3D npc_mcam_verify_entry(mcam, pcifunc, req->entry); + if (rc) + goto exit; + + if (!is_npc_interface_valid(rvu, req->intf)) { + rc =3D NPC_MCAM_INVALID_REQ; + goto exit; + } + + if (is_npc_intf_tx(req->intf)) + nix_intf =3D pfvf->nix_tx_intf; + else + nix_intf =3D pfvf->nix_rx_intf; + + /* For AF installed rules, the nix_intf should be set to target NIX */ + if (is_pffunc_af(req->hdr.pcifunc)) + nix_intf =3D req->intf; + + npc_cn20k_config_mcam_entry(rvu, blkaddr, req->entry, nix_intf, + &req->entry_data, req->enable_entry, + req->hw_prio); + + rc =3D 0; +exit: + mutex_unlock(&mcam->lock); + return rc; +} + +int rvu_mbox_handler_npc_cn20k_mcam_read_entry(struct rvu *rvu, + struct npc_mcam_read_entry_req *req, + struct npc_cn20k_mcam_read_entry_rsp *rsp) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + u16 pcifunc =3D req->hdr.pcifunc; + int blkaddr, rc; + + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (blkaddr < 0) + return NPC_MCAM_INVALID_REQ; + + mutex_lock(&mcam->lock); + rc =3D npc_mcam_verify_entry(mcam, pcifunc, req->entry); + if (!rc) + npc_cn20k_read_mcam_entry(rvu, blkaddr, req->entry, + &rsp->entry_data, &rsp->intf, + &rsp->enable, &rsp->hw_prio); + + mutex_unlock(&mcam->lock); + return rc; +} + +int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_entry(struct rvu *rvu, + struct npc_cn20k_mcam_alloc_and_write_entry_req *req, + struct npc_mcam_alloc_and_write_entry_rsp *rsp) +{ + struct rvu_pfvf *pfvf =3D rvu_get_pfvf(rvu, req->hdr.pcifunc); + struct npc_mcam_alloc_entry_req entry_req; + struct npc_mcam_alloc_entry_rsp entry_rsp; + struct npc_mcam *mcam =3D &rvu->hw->mcam; + u16 entry =3D NPC_MCAM_ENTRY_INVALID; + int blkaddr, rc; + u8 nix_intf; + + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (blkaddr < 0) + return NPC_MCAM_INVALID_REQ; + + if (!is_npc_interface_valid(rvu, req->intf)) + return NPC_MCAM_INVALID_REQ; + + /* Try to allocate a MCAM entry */ + entry_req.hdr.pcifunc =3D req->hdr.pcifunc; + entry_req.contig =3D true; + entry_req.ref_prio =3D req->ref_prio; + entry_req.ref_entry =3D req->ref_entry; + entry_req.count =3D 1; + + rc =3D rvu_mbox_handler_npc_mcam_alloc_entry(rvu, + &entry_req, &entry_rsp); + if (rc) + return rc; + + if (!entry_rsp.count) + return NPC_MCAM_ALLOC_FAILED; + + entry =3D entry_rsp.entry; + mutex_lock(&mcam->lock); + + if (is_npc_intf_tx(req->intf)) + nix_intf =3D pfvf->nix_tx_intf; + else + nix_intf =3D pfvf->nix_rx_intf; + + npc_cn20k_config_mcam_entry(rvu, blkaddr, entry, nix_intf, + &req->entry_data, req->enable_entry, + req->hw_prio); + + mutex_unlock(&mcam->lock); + + rsp->entry =3D entry; + return 0; +} + +int rvu_mbox_handler_npc_cn20k_read_base_steer_rule(struct rvu *rvu, + struct msg_req *req, + struct npc_cn20k_mcam_read_base_rule_rsp *rsp) +{ + struct npc_mcam *mcam =3D &rvu->hw->mcam; + int index, blkaddr, nixlf, rc =3D 0; + u16 pcifunc =3D req->hdr.pcifunc; + u8 intf, enable, hw_prio; + struct rvu_pfvf *pfvf; + + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (blkaddr < 0) + return NPC_MCAM_INVALID_REQ; + + /* Return the channel number in case of PF */ + if (!(pcifunc & RVU_PFVF_FUNC_MASK)) { + pfvf =3D rvu_get_pfvf(rvu, pcifunc); + rsp->entry.kw[0] =3D pfvf->rx_chan_base; + rsp->entry.kw_mask[0] =3D 0xFFFULL; + goto out; + } + + /* Find the pkt steering rule installed by PF to this VF */ + mutex_lock(&mcam->lock); + for (index =3D 0; index < mcam->bmap_entries; index++) { + if (mcam->entry2target_pffunc[index] =3D=3D pcifunc) + goto read_entry; + } + + rc =3D nix_get_nixlf(rvu, pcifunc, &nixlf, NULL); + if (rc < 0) { + mutex_unlock(&mcam->lock); + goto out; + } + /* Read the default ucast entry if there is no pkt steering rule */ + index =3D npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf, + NIXLF_UCAST_ENTRY); +read_entry: + /* Read the mcam entry */ + npc_cn20k_read_mcam_entry(rvu, blkaddr, index, + &rsp->entry, &intf, + &enable, &hw_prio); + mutex_unlock(&mcam->lock); +out: + return rc; +} + static u8 npc_map2cn20k_flag(u8 flag) { switch (flag) { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.h index 7e86c879fe99..f608ed286548 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h @@ -232,15 +232,16 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 = pcifunc, u16 *bcast, u16 *mcast, u16 *promisc, u16 *ucast); =20 void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, - u8 intf, struct mcam_entry *entry, + u8 intf, + struct cn20k_mcam_entry *entry, bool enable, u8 hw_prio); void npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr, int index, bool enable); void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest); void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index, - struct mcam_entry *entry, u8 *intf, u8 *ena, - u8 *hw_prio); + struct cn20k_mcam_entry *entry, u8 *intf, + u8 *ena, u8 *hw_prio); 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); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net= /ethernet/marvell/octeontx2/af/mbox.h index 7c58552435d2..34c960b84a65 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -287,6 +287,16 @@ M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6015, npc_cn20k_get= _free_count, \ msg_req, npc_cn20k_get_free_count_rsp) \ M(NPC_CN20K_GET_KEX_CFG, 0x6016, npc_cn20k_get_kex_cfg, \ msg_req, npc_cn20k_get_kex_cfg_rsp) \ +M(NPC_CN20K_MCAM_WRITE_ENTRY, 0x6017, npc_cn20k_mcam_write_entry, \ + npc_cn20k_mcam_write_entry_req, msg_rsp) \ +M(NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY, 0x6018, npc_cn20k_mcam_alloc_and_w= rite_entry, \ + npc_cn20k_mcam_alloc_and_write_entry_req, \ + npc_mcam_alloc_and_write_entry_rsp) \ +M(NPC_CN20K_MCAM_READ_ENTRY, 0x6019, npc_cn20k_mcam_read_entry, \ + npc_mcam_read_entry_req, \ + 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) \ /* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \ M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \ nix_lf_alloc_req, nix_lf_alloc_rsp) \ @@ -1570,13 +1580,32 @@ struct mcam_entry_mdata { }; =20 struct mcam_entry { -#define NPC_MAX_KWS_IN_KEY 8 /* Number of keywords in max keywidth */ +#define NPC_MAX_KWS_IN_KEY 7 /* Number of keywords in max keywidth */ u64 kw[NPC_MAX_KWS_IN_KEY]; u64 kw_mask[NPC_MAX_KWS_IN_KEY]; u64 action; u64 vtag_action; }; =20 +struct cn20k_mcam_entry { +#define NPC_CN20K_MAX_KWS_IN_KEY 8 /* Number of keywords in max keywidth */ + u64 kw[NPC_CN20K_MAX_KWS_IN_KEY]; + u64 kw_mask[NPC_CN20K_MAX_KWS_IN_KEY]; + u64 action; + u64 vtag_action; +}; + +struct npc_cn20k_mcam_write_entry_req { + struct mbox_msghdr hdr; + struct cn20k_mcam_entry entry_data; + u16 entry; /* MCAM entry to write this match key */ + u16 cntr; /* Counter for this MCAM entry */ + u8 intf; /* Rx or Tx interface */ + u8 enable_entry;/* Enable this MCAM entry ? */ + u8 hw_prio; /* hardware priority, valid for cn20k */ + u64 reserved; /* reserved for future use */ +}; + struct npc_mcam_write_entry_req { struct mbox_msghdr hdr; struct mcam_entry entry_data; @@ -1649,8 +1678,30 @@ struct npc_mcam_alloc_and_write_entry_req { u8 intf; /* Rx or Tx interface */ u8 enable_entry;/* Enable this MCAM entry ? */ u8 alloc_cntr; /* Allocate counter and map ? */ - /* hardware priority, supported for cn20k */ - u8 hw_prio; +}; + +struct npc_cn20k_mcam_alloc_and_write_entry_req { + struct mbox_msghdr hdr; + struct cn20k_mcam_entry entry_data; + u16 ref_entry; + u8 ref_prio; /* Lower or higher w.r.t ref_entry */ + u8 intf; /* Rx or Tx interface */ + u8 enable_entry;/* Enable this MCAM entry ? */ + u8 hw_prio; /* hardware priority, valid for cn20k */ + u16 reserved[4]; /* reserved for future use */ +}; + +struct npc_cn20k_mcam_read_entry_rsp { + struct mbox_msghdr hdr; + struct cn20k_mcam_entry entry_data; + u8 intf; + u8 enable; + u8 hw_prio; /* valid for cn20k */ +}; + +struct npc_cn20k_mcam_read_base_rule_rsp { + struct mbox_msghdr hdr; + struct cn20k_mcam_entry entry; }; =20 struct npc_mcam_alloc_and_write_entry_rsp { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/= ethernet/marvell/octeontx2/af/npc.h index cb05ec69e0b3..cefc5d70f3e4 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h @@ -644,6 +644,7 @@ struct rvu_npc_mcam_rule { u16 chan; u16 chan_mask; u8 lxmb; + u8 hw_prio; }; =20 #endif /* NPC_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/= ethernet/marvell/octeontx2/af/rvu.h index a53bb5c924ef..f811d6b5c545 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -197,7 +197,7 @@ struct npc_key_field { /* Masks where all set bits indicate position * of a field in the key */ - u64 kw_mask[NPC_MAX_KWS_IN_KEY]; + u64 kw_mask[NPC_CN20K_MAX_KWS_IN_KEY]; /* Number of words in the key a field spans. If a field is * of 16 bytes and key offset is 4 then the field will use * 4 bytes in KW0, 8 bytes in KW1 and 4 bytes in KW2 and @@ -1191,4 +1191,5 @@ int rvu_rep_pf_init(struct rvu *rvu); int rvu_rep_install_mcam_rules(struct rvu *rvu); void rvu_rep_update_rules(struct rvu *rvu, u16 pcifunc, bool ena); int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable); +int npc_mcam_verify_entry(struct npc_mcam *mcam, u16 pcifunc, int entry); #endif /* RVU_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/driv= ers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index 425d3a43c0b8..407f360feaf5 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -21,6 +21,7 @@ #include "rvu_npc_hash.h" #include "mcs.h" =20 +#include "cn20k/reg.h" #include "cn20k/debugfs.h" =20 #define DEBUGFS_DIR_NAME "octeontx2" @@ -3506,10 +3507,10 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_f= ile *s, void *unused) struct rvu_npc_mcam_rule *iter; struct rvu *rvu =3D s->private; struct npc_mcam *mcam; - int pf, vf =3D -1; + int pf, vf =3D -1, bank; + u16 target, index; bool enabled; int blkaddr; - u16 target; u64 hits; =20 blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); @@ -3554,6 +3555,15 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_fi= le *s, void *unused) =20 enabled =3D is_mcam_entry_enabled(rvu, mcam, blkaddr, iter->entry); seq_printf(s, "\tenabled: %s\n", enabled ? "yes" : "no"); + if (is_cn20k(rvu->pdev)) { + seq_printf(s, "\tpriority: %u\n", iter->hw_prio); + index =3D iter->entry & (mcam->banksize - 1); + bank =3D npc_get_bank(mcam, iter->entry); + hits =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank)); + seq_printf(s, "\thits: %lld\n", hits); + continue; + } =20 if (!iter->has_cntr) continue; @@ -3721,11 +3731,17 @@ static int rvu_dbg_npc_exact_drop_cnt(struct seq_fi= le *s, void *unused) chan =3D field->kw_mask[0] & cam1; =20 str =3D (cfg & 1) ? "enabled" : "disabled"; + if (is_cn20k(rvu->pdev)) + seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc, i, + rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(i, 0)), + chan, str); + else + seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc, i, + rvu_read64(rvu, blkaddr, + NPC_AF_MATCH_STATX(table->counter_idx[i])), + chan, str); =20 - seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc, i, - rvu_read64(rvu, blkaddr, - NPC_AF_MATCH_STATX(table->counter_idx[i])), - chan, str); } =20 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 ea0368b32b01..fdc6792df7bb 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -2382,8 +2382,8 @@ void rvu_npc_get_mcam_counter_alloc_info(struct rvu *= rvu, u16 pcifunc, } } =20 -static int npc_mcam_verify_entry(struct npc_mcam *mcam, - u16 pcifunc, int entry) +int npc_mcam_verify_entry(struct npc_mcam *mcam, + u16 pcifunc, int entry) { /* verify AF installed entries */ if (is_pffunc_af(pcifunc)) @@ -2926,6 +2926,10 @@ int npc_config_cntr_default_entries(struct rvu *rvu,= bool enable) struct rvu_npc_mcam_rule *rule; int blkaddr; =20 + /* Counter is set for each rule by default */ + if (is_cn20k(rvu->pdev)) + return -EINVAL; + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) return -EINVAL; @@ -3106,7 +3110,7 @@ int rvu_mbox_handler_npc_mcam_write_entry(struct rvu = *rvu, if (rc) goto exit; =20 - if (req->set_cntr && + if (!is_cn20k(rvu->pdev) && req->set_cntr && npc_mcam_verify_counter(mcam, pcifunc, req->cntr)) { rc =3D NPC_MCAM_INVALID_REQ; goto exit; @@ -3321,6 +3325,10 @@ int rvu_mbox_handler_npc_mcam_alloc_counter(struct r= vu *rvu, struct npc_mcam *mcam =3D &rvu->hw->mcam; int err; =20 + /* Counter is not supported for CN20K */ + if (is_cn20k(rvu->pdev)) + return NPC_MCAM_INVALID_REQ; + mutex_lock(&mcam->lock); =20 err =3D __npc_mcam_alloc_counter(rvu, req, rsp); @@ -3375,6 +3383,10 @@ int rvu_mbox_handler_npc_mcam_free_counter(struct rv= u *rvu, struct npc_mcam *mcam =3D &rvu->hw->mcam; int err; =20 + /* Counter is not supported for CN20K */ + if (is_cn20k(rvu->pdev)) + return NPC_MCAM_INVALID_REQ; + mutex_lock(&mcam->lock); =20 err =3D __npc_mcam_free_counter(rvu, req, rsp); @@ -3433,6 +3445,10 @@ int rvu_mbox_handler_npc_mcam_unmap_counter(struct r= vu *rvu, u16 index, entry =3D 0; int blkaddr, rc; =20 + /* Counter is not supported for CN20K */ + if (is_cn20k(rvu->pdev)) + return NPC_MCAM_INVALID_REQ; + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; @@ -3477,12 +3493,20 @@ int rvu_mbox_handler_npc_mcam_clear_counter(struct = rvu *rvu, struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp) { struct npc_mcam *mcam =3D &rvu->hw->mcam; - int blkaddr, err; + int blkaddr, err, index, bank; =20 blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; =20 + if (is_cn20k(rvu->pdev)) { + index =3D req->cntr & (mcam->banksize - 1); + bank =3D npc_get_bank(mcam, req->cntr); + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank), 0); + return 0; + } + mutex_lock(&mcam->lock); err =3D npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr); mutex_unlock(&mcam->lock); @@ -3499,12 +3523,20 @@ int rvu_mbox_handler_npc_mcam_counter_stats(struct = rvu *rvu, struct npc_mcam_oper_counter_rsp *rsp) { struct npc_mcam *mcam =3D &rvu->hw->mcam; - int blkaddr, err; + int blkaddr, err, index, bank; =20 blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; =20 + if (is_cn20k(rvu->pdev)) { + index =3D req->cntr & (mcam->banksize - 1); + bank =3D npc_get_bank(mcam, req->cntr); + rsp->stat =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank)); + return 0; + } + mutex_lock(&mcam->lock); err =3D npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr); mutex_unlock(&mcam->lock); @@ -3799,11 +3831,19 @@ int rvu_mbox_handler_npc_mcam_entry_stats(struct rv= u *rvu, if (blkaddr < 0) return NPC_MCAM_INVALID_REQ; =20 - mutex_lock(&mcam->lock); - index =3D req->entry & (mcam->banksize - 1); bank =3D npc_get_bank(mcam, req->entry); =20 + mutex_lock(&mcam->lock); + + if (is_cn20k(rvu->pdev)) { + rsp->stat_ena =3D 1; + rsp->stat =3D rvu_read64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(index, bank)); + mutex_unlock(&mcam->lock); + return 0; + } + /* read MCAM entry STAT_ACT register */ regval =3D rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_STAT_ACT(index, b= ank)); =20 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 8b28dd88ad83..20e98acad561 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -254,7 +254,7 @@ static bool npc_check_overlap(struct rvu *rvu, int blka= ddr, * other field bits. */ if (npc_check_overlap_fields(dummy, input, - NPC_MAX_KWS_IN_KEY - 1)) + NPC_MAX_KWS_IN_KEY)) return true; } } @@ -285,7 +285,7 @@ static bool npc_check_overlap(struct rvu *rvu, int blka= ddr, start_kwi, offset, intf); /* check any input field bits falls in any other field bits */ if (npc_check_overlap_fields(dummy, input, - NPC_MAX_KWS_IN_KEY)) + NPC_CN20K_MAX_KWS_IN_KEY)) return true; } } @@ -456,9 +456,9 @@ static void npc_handle_multi_layer_fields(struct rvu *r= vu, int blkaddr, u8 intf) u8 start_lid; =20 if (is_cn20k(rvu->pdev)) - max_kw =3D NPC_MAX_KWS_IN_KEY; + max_kw =3D NPC_CN20K_MAX_KWS_IN_KEY; else - max_kw =3D NPC_MAX_KWS_IN_KEY - 1; + max_kw =3D NPC_MAX_KWS_IN_KEY; =20 key_fields =3D mcam->rx_key_fields; features =3D &mcam->rx_features; @@ -901,6 +901,7 @@ void npc_update_entry(struct rvu *rvu, enum key_fields = type, struct mcam_entry_mdata *mdata, u64 val_lo, u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf) { + struct cn20k_mcam_entry cn20k_dummy =3D { {0} }; struct npc_mcam *mcam =3D &rvu->hw->mcam; struct mcam_entry dummy =3D { {0} }; u64 *kw, *kw_mask, *val, *mask; @@ -916,9 +917,15 @@ void npc_update_entry(struct rvu *rvu, enum key_fields= type, if (!field->nr_kws) return; =20 - max_kw =3D NPC_MAX_KWS_IN_KEY; - kw =3D dummy.kw; - kw_mask =3D dummy.kw_mask; + if (is_cn20k(rvu->pdev)) { + max_kw =3D NPC_CN20K_MAX_KWS_IN_KEY; + kw =3D cn20k_dummy.kw; + kw_mask =3D cn20k_dummy.kw_mask; + } else { + max_kw =3D NPC_MAX_KWS_IN_KEY; + kw =3D dummy.kw; + kw_mask =3D dummy.kw_mask; + } =20 for (i =3D 0; i < max_kw; i++) { if (!field->kw_mask[i]) @@ -1289,8 +1296,17 @@ static int npc_mcast_update_action_index(struct rvu = *rvu, struct npc_install_flo static void npc_populate_mcam_mdata(struct rvu *rvu, struct mcam_entry_mdata *mdata, + struct cn20k_mcam_entry *cn20k_entry, struct mcam_entry *entry) { + if (is_cn20k(rvu->pdev)) { + mdata->kw =3D cn20k_entry->kw; + mdata->kw_mask =3D cn20k_entry->kw_mask; + mdata->action =3D &cn20k_entry->action; + mdata->vtag_action =3D &cn20k_entry->vtag_action; + mdata->max_kw =3D NPC_CN20K_MAX_KWS_IN_KEY; + return; + } mdata->kw =3D entry->kw; mdata->kw_mask =3D entry->kw_mask; mdata->action =3D &entry->action; @@ -1410,9 +1426,11 @@ static int npc_install_flow(struct rvu *rvu, int blk= addr, u16 target, bool pf_set_vfs_mac) { struct rvu_npc_mcam_rule *def_ucast_rule =3D pfvf->def_ucast_rule; + struct npc_cn20k_mcam_write_entry_req cn20k_write_req =3D { 0 }; u64 features, installed_features, missing_features =3D 0; struct npc_mcam_write_entry_req write_req =3D { 0 }; struct npc_mcam *mcam =3D &rvu->hw->mcam; + struct cn20k_mcam_entry *cn20k_entry; struct mcam_entry_mdata mdata =3D { }; struct rvu_npc_mcam_rule dummy =3D { 0 }; struct rvu_npc_mcam_rule *rule; @@ -1425,11 +1443,12 @@ static int npc_install_flow(struct rvu *rvu, int bl= kaddr, u16 target, =20 installed_features =3D req->features; features =3D req->features; - entry =3D &write_req.entry_data; entry_index =3D req->entry; =20 - npc_populate_mcam_mdata(rvu, &mdata, - &write_req.entry_data); + cn20k_entry =3D &cn20k_write_req.entry_data; + entry =3D &write_req.entry_data; + + npc_populate_mcam_mdata(rvu, &mdata, cn20k_entry, entry); =20 npc_update_flow(rvu, &mdata, features, &req->packet, &req->mask, &dummy, req->intf, blkaddr); @@ -1476,49 +1495,79 @@ static int npc_install_flow(struct rvu *rvu, int bl= kaddr, u16 target, new =3D true; } =20 - /* allocate new counter if rule has no counter */ - if (!req->default_rule && req->set_cntr && !rule->has_cntr) - rvu_mcam_add_counter_to_rule(rvu, owner, rule, rsp); - - /* if user wants to delete an existing counter for a rule then - * free the counter - */ - if (!req->set_cntr && rule->has_cntr) - rvu_mcam_remove_counter_from_rule(rvu, owner, rule); + if (!is_cn20k(rvu->pdev)) { + write_req.hdr.pcifunc =3D owner; + + /* allocate new counter if rule has no counter */ + if (!req->default_rule && req->set_cntr && !rule->has_cntr) + rvu_mcam_add_counter_to_rule(rvu, owner, rule, rsp); + + /* if user wants to delete an existing counter for a rule then + * free the counter + */ + if (!req->set_cntr && rule->has_cntr) + rvu_mcam_remove_counter_from_rule(rvu, owner, rule); + + /* AF owns the default rules so change the owner just to relax + * the checks in rvu_mbox_handler_npc_mcam_write_entry + */ + if (req->default_rule) + write_req.hdr.pcifunc =3D 0; + + write_req.entry =3D entry_index; + write_req.intf =3D req->intf; + write_req.enable_entry =3D (u8)enable; + /* if counter is available then clear and use it */ + if (req->set_cntr && rule->has_cntr) { + rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(rule->cntr), req->cntr_val= ); + write_req.set_cntr =3D 1; + write_req.cntr =3D rule->cntr; + } + goto update_rule; + } =20 - write_req.hdr.pcifunc =3D owner; + cn20k_write_req.hdr.pcifunc =3D owner; =20 - /* AF owns the default rules so change the owner just to relax - * the checks in rvu_mbox_handler_npc_mcam_write_entry - */ if (req->default_rule) - write_req.hdr.pcifunc =3D 0; + cn20k_write_req.hdr.pcifunc =3D 0; =20 - write_req.entry =3D entry_index; - write_req.intf =3D req->intf; - write_req.enable_entry =3D (u8)enable; - /* if counter is available then clear and use it */ - if (req->set_cntr && rule->has_cntr) { - rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(rule->cntr), req->cntr_val); - write_req.set_cntr =3D 1; - write_req.cntr =3D rule->cntr; - } + cn20k_write_req.entry =3D entry_index; + cn20k_write_req.intf =3D req->intf; + cn20k_write_req.enable_entry =3D (u8)enable; + +update_rule: =20 /* update rule */ memcpy(&rule->packet, &dummy.packet, sizeof(rule->packet)); memcpy(&rule->mask, &dummy.mask, sizeof(rule->mask)); rule->entry =3D entry_index; - memcpy(&rule->rx_action, &entry->action, sizeof(struct nix_rx_action)); - if (is_npc_intf_tx(req->intf)) - memcpy(&rule->tx_action, &entry->action, - sizeof(struct nix_tx_action)); - rule->vtag_action =3D entry->vtag_action; + if (is_cn20k(rvu->pdev)) { + memcpy(&rule->rx_action, &cn20k_entry->action, sizeof(struct nix_rx_acti= on)); + if (is_npc_intf_tx(req->intf)) + memcpy(&rule->tx_action, &cn20k_entry->action, + sizeof(struct nix_tx_action)); + rule->vtag_action =3D cn20k_entry->vtag_action; + } else { + memcpy(&rule->rx_action, &entry->action, sizeof(struct nix_rx_action)); + if (is_npc_intf_tx(req->intf)) + memcpy(&rule->tx_action, &entry->action, + sizeof(struct nix_tx_action)); + rule->vtag_action =3D entry->vtag_action; + } + rule->features =3D installed_features; rule->default_rule =3D req->default_rule; rule->owner =3D owner; rule->enable =3D enable; - rule->chan_mask =3D write_req.entry_data.kw_mask[0] & NPC_KEX_CHAN_MASK; - rule->chan =3D write_req.entry_data.kw[0] & NPC_KEX_CHAN_MASK; + + if (is_cn20k(rvu->pdev)) { + rule->chan_mask =3D cn20k_write_req.entry_data.kw_mask[0] & NPC_KEX_CHAN= _MASK; + rule->chan =3D cn20k_write_req.entry_data.kw[0] & NPC_KEX_CHAN_MASK; + } else { + rule->chan_mask =3D write_req.entry_data.kw_mask[0] & NPC_KEX_CHAN_MASK; + rule->chan =3D write_req.entry_data.kw[0] & NPC_KEX_CHAN_MASK; + } + rule->chan &=3D rule->chan_mask; rule->lxmb =3D dummy.lxmb; if (is_npc_intf_tx(req->intf)) @@ -1532,15 +1581,20 @@ static int npc_install_flow(struct rvu *rvu, int bl= kaddr, u16 target, pfvf->def_ucast_rule =3D rule; =20 /* write to mcam entry registers */ - err =3D rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, - &write_rsp); - if (err) { - rvu_mcam_remove_counter_from_rule(rvu, owner, rule); - if (new) { - list_del(&rule->list); - kfree(rule); + if (is_cn20k(rvu->pdev)) { + err =3D rvu_mbox_handler_npc_cn20k_mcam_write_entry(rvu, &cn20k_write_re= q, + &write_rsp); + } else { + err =3D rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, + &write_rsp); + if (err) { + rvu_mcam_remove_counter_from_rule(rvu, owner, rule); + if (new) { + list_del(&rule->list); + kfree(rule); + } + return err; } - return err; } =20 /* VF's MAC address is being changed via PF */ @@ -1774,23 +1828,25 @@ static int npc_update_dmac_value(struct rvu *rvu, i= nt npcblkaddr, struct rvu_npc_mcam_rule *rule, struct rvu_pfvf *pfvf) { + struct npc_cn20k_mcam_write_entry_req cn20k_write_req =3D { 0 }; struct npc_mcam_write_entry_req write_req =3D { 0 }; - struct npc_mcam *mcam =3D &rvu->hw->mcam; struct mcam_entry_mdata mdata =3D { }; + struct npc_mcam *mcam =3D &rvu->hw->mcam; + struct cn20k_mcam_entry *cn20k_entry; struct mcam_entry *entry; u8 intf, enable, hw_prio; struct msg_rsp rsp; int err; =20 + cn20k_entry =3D &cn20k_write_req.entry_data; entry =3D &write_req.entry_data; - - npc_populate_mcam_mdata(rvu, &mdata, entry); + npc_populate_mcam_mdata(rvu, &mdata, cn20k_entry, entry); =20 ether_addr_copy(rule->packet.dmac, pfvf->mac_addr); =20 if (is_cn20k(rvu->pdev)) npc_cn20k_read_mcam_entry(rvu, npcblkaddr, rule->entry, - entry, &intf, + cn20k_entry, &intf, &enable, &hw_prio); else npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry, @@ -1893,6 +1949,7 @@ int npc_install_mcam_drop_rule(struct rvu *rvu, int m= cam_idx, u16 *counter_idx, u64 chan_val, u64 chan_mask, u64 exact_val, u64 exact_mask, u64 bcast_mcast_val, u64 bcast_mcast_mask) { + struct npc_cn20k_mcam_write_entry_req cn20k_req =3D { 0 }; struct npc_mcam_alloc_counter_req cntr_req =3D { 0 }; struct npc_mcam_alloc_counter_rsp cntr_rsp =3D { 0 }; struct npc_mcam_write_entry_req req =3D { 0 }; @@ -1941,19 +1998,22 @@ int npc_install_mcam_drop_rule(struct rvu *rvu, int= mcam_idx, u16 *counter_idx, /* Reserve slot 0 */ npc_mcam_rsrcs_reserve(rvu, blkaddr, mcam_idx); =20 - /* Allocate counter for this single drop on non hit rule */ - cntr_req.hdr.pcifunc =3D 0; /* AF request */ - cntr_req.contig =3D true; - cntr_req.count =3D 1; - err =3D rvu_mbox_handler_npc_mcam_alloc_counter(rvu, &cntr_req, &cntr_rsp= ); - if (err) { - dev_err(rvu->dev, "%s: Err to allocate cntr for drop rule (err=3D%d)\n", - __func__, err); - return -EFAULT; + if (!is_cn20k(rvu->pdev)) { + /* Allocate counter for this single drop on non hit rule */ + cntr_req.hdr.pcifunc =3D 0; /* AF request */ + cntr_req.contig =3D true; + cntr_req.count =3D 1; + err =3D rvu_mbox_handler_npc_mcam_alloc_counter(rvu, &cntr_req, &cntr_rs= p); + if (err) { + dev_err(rvu->dev, "%s: Err to allocate cntr for drop rule (err=3D%d)\n", + __func__, err); + return -EFAULT; + } + *counter_idx =3D cntr_rsp.cntr; } - *counter_idx =3D cntr_rsp.cntr; =20 npc_populate_mcam_mdata(rvu, &mdata, + &cn20k_req.entry_data, &req.entry_data); =20 /* Fill in fields for this mcam entry */ @@ -1964,11 +2024,26 @@ int npc_install_mcam_drop_rule(struct rvu *rvu, int= mcam_idx, u16 *counter_idx, npc_update_entry(rvu, NPC_LXMB, &mdata, bcast_mcast_val, 0, bcast_mcast_mask, 0, NIX_INTF_RX); =20 + if (is_cn20k(rvu->pdev)) { + cn20k_req.intf =3D NIX_INTF_RX; + cn20k_req.entry =3D mcam_idx; + + err =3D rvu_mbox_handler_npc_cn20k_mcam_write_entry(rvu, &cn20k_req, &rs= p); + if (err) { + dev_err(rvu->dev, "%s: Installation of single drop on non hit rule at %= d failed\n", + __func__, mcam_idx); + return err; + } + + goto enable_entry; + } + req.intf =3D NIX_INTF_RX; req.set_cntr =3D true; req.cntr =3D cntr_rsp.cntr; req.entry =3D mcam_idx; =20 +enable_entry: err =3D rvu_mbox_handler_npc_mcam_write_entry(rvu, &req, &rsp); if (err) { dev_err(rvu->dev, "%s: Installation of single drop on non hit rule at %d= failed\n", --=20 2.43.0 From nobody Wed Jan 7 22:50:11 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 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (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 EDBEB23184F; Mon, 5 Jan 2026 02:34:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580448; cv=none; b=dqLW5IUOr4jA3EIYIKtKv81NkenkLWO55RjElWG7wl/WfAGO8jDDmY0Ej2RhVqENYSe+hpfVsAvaVMrm+2QOlG8PIMoCGUDHwKw1vOs9cQCu1Kt5OloS6ra8lTTYJD+6x+n7YnoOqVt16e1+kFWarWU2PSnl2mGrwh7+2SmwMSc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580448; c=relaxed/simple; bh=RWLn9SEsiE388h+BaFarHd9MO6EMzLSi+TDsaIfD7FA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HF3Rgv9wFnSVIsh6Lg1dSPLstnL3bpwoUDAsLcyMAMdfCP6tiEf+HKiz11CzB1UcrJYXKUmCN/6VqEha8Q5gtS/s1jz1HuPqpQ07dsnlvkBX2AqVJFQm3RYg4Ie//PPBdMhmzeWPMzPoQNxrYRgqgj8HRqv72gEjFRy6RVGyQGM= 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=cElavZfa; arc=none smtp.client-ip=67.231.156.173 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="cElavZfa" Received: from pps.filterd (m0431383.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6050avQk2440677; Sun, 4 Jan 2026 18:33:55 -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=7 P8TBBRryf2saxKdHpYjlXl8zHoSUcuJz3FfsUWmjDc=; b=cElavZfap6yJmajK+ eMdSZXV0sg/zCDm86D6Kcrzqd75SAeW5hR5wTwtt4Mbi1Nz+NkI6IvllDsVAx/nh xa1n3wdbiQ8VMqXJ38QENGkqy11mvEpm7etltZV/kRWx5pC4G18/83p+Z2v40EHk qruuKgVoPPXGX2z2m3EO2iGfiH1A8WK3i+4fuRV2DmAEoXNV1kUS2vklY4s3ubGm OGN81Komro+2eurouDlOUDGTiTIJyN4OjoPh1fAE78Cocgabtk3oo2Nvq47EGEfF jPqnv8jwt4Ko4wy/KbVB6+21jTaTIu88h0AYrEidkDDzG2c6LFW6CObJG0fGuVqK BcU3w== Received: from dc6wp-exch02.marvell.com ([4.21.29.225]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 4bfmrbs03j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:55 -0800 (PST) Received: from DC6WP-EXCH02.marvell.com (10.76.176.209) by DC6WP-EXCH02.marvell.com (10.76.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:33:54 -0800 Received: from maili.marvell.com (10.69.176.80) by DC6WP-EXCH02.marvell.com (10.76.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:33:54 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id BF0EA3F7094; Sun, 4 Jan 2026 18:33:51 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 10/13] octeontx2-af: npc: cn20k: Allocate MCAM entry for flow installation Date: Mon, 5 Jan 2026 08:02:51 +0530 Message-ID: <20260105023254.1426488-11-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-Authority-Analysis: v=2.4 cv=bN0b4f+Z c=1 sm=1 tr=0 ts=695b2313 cx=c_pps a=gIfcoYsirJbf48DBMSPrZA==:117 a=gIfcoYsirJbf48DBMSPrZA==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=R86mbzlVWIuRp1_vrRQA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-ORIG-GUID: 93Tl5o9NReB3oLX93e479XKf01tEnofx X-Proofpoint-GUID: 93Tl5o9NReB3oLX93e479XKf01tEnofx X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfXxgt0lwY4u1a+ D5bnRZQ4P4K122tHhV/l9x66iCL5r0JPi+DlODbYKD6Uh/9DuCmN53elycSaIt4nhCUmWednRJM jviSoLjSeK2ksliaIBqbfwQaE80OcIIb4hD0/8JKHxKV8ErKIc1aVBFnhj7A28wX0jxxoINnN9a 7TriLZ7fKCuWaxwtac2epJhozMcQtz3DbdVXZ5DApRrzd6d9q+z9Q65Wdm3sStIM4bBUNsox3gy i/eM8jy+qJ0cC6nwUJsn4AnLWaj+Z7A6v/yvwWLKDfKMy0zMnUF+DJCz9iuIn572zocST+gQVVv Ff+WYSuLhMmaEkj/cdHEAgrCghcbtaw7Nr/hxFoht1UiLfsfYIqGTcgf2RAJutSgAtTS8bs1btN PV9JZTzPtU83t/Pc2RwzrNmf5wJxuFmKoEJJdWCLUmaWvcdDSKXKlhgOju2BUAZ2JLspQ6skNMs VLcl5UICYM6ij3qubjw== 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" In CN20K, the PF/VF driver is unaware of the NPC MCAM entry type (x2/x4) required for a particular TC rule when the user installs rules through the TC command. This forces the PF/VF driver to first query the AF driver for t= he rule size, then allocate an entry, and finally install the flow. This sequence requires three mailbox request/response exchanges from the PF. To speed up the installation, the `install_flow` mailbox request message is extended with additional fields that allow the AF driver to determine the required NPC MCAM entry type, allocate the MCAM entry, and complete the flow installation in a single step. Signed-off-by: Ratheesh Kannoth --- .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 180 ++++++++++-- .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 5 +- .../net/ethernet/marvell/octeontx2/af/mbox.h | 48 ++++ .../ethernet/marvell/octeontx2/af/rvu_npc.c | 4 + .../marvell/octeontx2/af/rvu_npc_fs.c | 130 ++++++++- .../marvell/octeontx2/af/rvu_npc_fs.h | 12 + .../marvell/octeontx2/nic/otx2_flows.c | 260 +++++++++++++++++- 7 files changed, 582 insertions(+), 57 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 75e492c2dfda..4c154cccbba1 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -14,6 +14,7 @@ #include "rvu_npc.h" #include "cn20k/npc.h" #include "cn20k/reg.h" +#include "rvu_npc_fs.h" =20 static struct npc_priv_t npc_priv =3D { .num_banks =3D MAX_NUM_BANKS, @@ -757,7 +758,7 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkadd= r, if (kw_type =3D=3D NPC_MCAM_KEY_X2) { cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank)); - hw_prio =3D cfg & GENMASK_ULL(14, 8); + hw_prio =3D cfg & GENMASK_ULL(30, 24); cfg =3D enable ? 1 : 0; cfg |=3D hw_prio; rvu_write64(rvu, blkaddr, @@ -772,7 +773,7 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkadd= r, for (bank =3D 0; bank < mcam->banks_per_entry; bank++) { cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank)); - hw_prio =3D cfg & GENMASK_ULL(14, 8); + hw_prio =3D cfg & GENMASK_ULL(30, 24); cfg =3D enable ? 1 : 0; cfg |=3D hw_prio; rvu_write64(rvu, blkaddr, @@ -842,7 +843,8 @@ static void npc_cn20k_get_keyword(struct cn20k_mcam_ent= ry *entry, int idx, static void npc_cn20k_config_kw_x2(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, int index, u8 intf, struct cn20k_mcam_entry *entry, - int bank, u8 kw_type, int kw) + int bank, u8 kw_type, int kw, + u8 req_kw_type) { u64 intf_ext =3D 0, intf_ext_mask =3D 0; u8 tx_intf_mask =3D ~intf & 0x3; @@ -861,27 +863,42 @@ static void npc_cn20k_config_kw_x2(struct rvu *rvu, s= truct npc_mcam *mcam, =20 kex_cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf)); kex_type =3D (kex_cfg & GENMASK_ULL(34, 32)) >> 32; - /*-----------------------------------------------------------------------= --------------| - * Kex type | mcam entry | cam1 | cam 0 || <----- output ----> | - * in profile | len | (key type) | (key type) || len | type = | - *-----------------------------------------------------------------------= --------------| - * X2 | 256 (X2) | 001b | 110b || X2 | X2 | - *-----------------------------------------------------------------------= --------------| - * X4 | 256 (X2) | 000b | 000b || X2 | DYNAMIC | - *-----------------------------------------------------------------------= --------------| - * X4 | 512 (X4) | 010b | 101b || X4 | X4 | - *-----------------------------------------------------------------------= --------------| - * DYNAMIC | 256 (X2) | 000b | 000b || X2 | DYNAMIC | - *-----------------------------------------------------------------------= --------------| - * DYNAMIC | 512 (X4) | 010b | 101b || X4 | X4 | - *-----------------------------------------------------------------------= --------------| + /*-----------------------------------------------------------------------= -------------------------------- + *Kex type | mcam entry | cam1 | cam 0| req_kw_type ||<----- output >= | + *in profile | len | (key type) | (key type) | ||len | type | + *-----------------------------------------------------------------------= ---------------------------------- + *X2 | 256 (X2) | 001b | 110b | 0 ||X2 | X2 | + *-----------------------------------------------------------------------= ---------------------------------| + *X4 | 256 (X2) | 000b | 000b | 0 ||X2 | DYN | + *-----------------------------------------------------------------------= ---------------------------------| + *X4 | 512 (X4) | 010b | 101b | 0 ||X4 | X4 | + *-----------------------------------------------------------------------= ---------------------------------| + *DYNAMIC | 256 (X2) | 000b | 000b | 0 ||X2 | DYN | + *-----------------------------------------------------------------------= ---------------------------------| + *DYNAMIC | 512 (X4) | 010b | 101b | 0 ||X4 | X4 | + *-----------------------------------------------------------------------= ---------------------------------| + *X4 | 256 (X2) | 000b | 000b | X2 ||DYN | DYN | + *-----------------------------------------------------------------------= ---------------------------------| + *DYNAMIC | 256 (X2) | 000b | 000b | X2 ||DYN | DYN | + *-----------------------------------------------------------------------= ---------------------------------| + * X2 | 512 (X4) | xxxb | xxxb | X4 ||INVAL | INVAL | + *-----------------------------------------------------------------------= ---------------------------------| */ + if ((kex_type =3D=3D NPC_MCAM_KEY_DYN || kex_type =3D=3D NPC_MCAM_KEY_X4)= && kw_type =3D=3D NPC_MCAM_KEY_X2) { kw_type =3D 0; kw_type_mask =3D 0; } =20 + /* Say, we need to write x2 keyword in an x4 subbank. req_kw_type will be= x2, + * and kw_type will be x4. So in the case ignore kw bits in mcam. + */ + if (kw_type =3D=3D NPC_MCAM_KEY_X4 && req_kw_type =3D=3D NPC_MCAM_KEY_X2)= { + kw_type =3D 0; + kw_type_mask =3D 0; + } + intf_ext =3D ((u64)kw_type << 16) | tx_intf; intf_ext_mask =3D (((u64)kw_type_mask << 16) & GENMASK_ULL(18, 16)) | tx_intf_mask; @@ -929,14 +946,15 @@ static void npc_cn20k_config_kw_x2(struct rvu *rvu, s= truct npc_mcam *mcam, static void npc_cn20k_config_kw_x4(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, int index, u8 intf, struct cn20k_mcam_entry *entry, - u8 kw_type) + u8 kw_type, u8 req_kw_type) { int kw =3D 0, bank; =20 for (bank =3D 0; bank < mcam->banks_per_entry; bank++, kw =3D kw + 4) npc_cn20k_config_kw_x2(rvu, mcam, blkaddr, index, intf, - entry, bank, kw_type, kw); + entry, bank, kw_type, + kw, req_kw_type); } =20 static void @@ -946,7 +964,7 @@ npc_cn20k_set_mcam_bank_cfg(struct rvu *rvu, int blkadd= r, int mcam_idx, struct npc_mcam *mcam =3D &rvu->hw->mcam; u64 bank_cfg; =20 - bank_cfg =3D (u64)hw_prio << 8; + bank_cfg =3D (u64)hw_prio << 24; if (enable) bank_cfg |=3D 0x1; =20 @@ -969,7 +987,7 @@ npc_cn20k_set_mcam_bank_cfg(struct rvu *rvu, int blkadd= r, int mcam_idx, =20 void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, u8 intf, struct cn20k_mcam_entry *entry, - bool enable, u8 hw_prio) + bool enable, u8 hw_prio, u8 req_kw_type) { struct npc_mcam *mcam =3D &rvu->hw->mcam; int mcam_idx =3D index % mcam->banksize; @@ -992,12 +1010,17 @@ void npc_cn20k_config_mcam_entry(struct rvu *rvu, in= t blkaddr, int index, npc_cn20k_clear_mcam_entry(rvu, blkaddr, bank, mcam_idx); npc_cn20k_config_kw_x2(rvu, mcam, blkaddr, mcam_idx, intf, entry, - bank, kw_type, kw); + bank, kw_type, kw, req_kw_type); /* Set 'action' */ rvu_write64(rvu, blkaddr, NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, bank, 0), entry->action); =20 + /* Set 'action2' for inline receive */ + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, bank, 2), + entry->action2); + /* Set TAG 'action' */ rvu_write64(rvu, blkaddr, NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, bank, 1), @@ -1008,7 +1031,8 @@ void npc_cn20k_config_mcam_entry(struct rvu *rvu, int= blkaddr, int index, npc_cn20k_clear_mcam_entry(rvu, blkaddr, 1, mcam_idx); =20 npc_cn20k_config_kw_x4(rvu, mcam, blkaddr, - mcam_idx, intf, entry, kw_type); + mcam_idx, intf, entry, + kw_type, req_kw_type); for (bank =3D 0; bank < mcam->banks_per_entry; bank++) { /* Set 'action' */ rvu_write64(rvu, blkaddr, @@ -1019,6 +1043,12 @@ void npc_cn20k_config_mcam_entry(struct rvu *rvu, in= t blkaddr, int index, rvu_write64(rvu, blkaddr, NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, bank, 1), entry->vtag_action); + + /* Set 'action2' for inline receive */ + rvu_write64(rvu, blkaddr, + NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(mcam_idx, bank, 2), + entry->action2); + } } =20 @@ -1102,7 +1132,7 @@ void npc_cn20k_read_mcam_entry(struct rvu *rvu, int b= lkaddr, u16 index, bank_cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(index, bank)); *ena =3D bank_cfg & 0x1; - *hw_prio =3D (bank_cfg & GENMASK_ULL(14, 8)) >> 8; + *hw_prio =3D (bank_cfg & GENMASK_ULL(30, 24)) >> 24; if (kw_type =3D=3D NPC_MCAM_KEY_X2) { cam1 =3D rvu_read64(rvu, blkaddr, NPC_AF_CN20K_MCAMEX_BANKX_CAMX_W0_EXT(index, bank, 1)); @@ -1203,7 +1233,7 @@ int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struc= t rvu *rvu, =20 npc_cn20k_config_mcam_entry(rvu, blkaddr, req->entry, nix_intf, &req->entry_data, req->enable_entry, - req->hw_prio); + req->hw_prio, req->req_kw_type); =20 rc =3D 0; exit: @@ -1281,7 +1311,7 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_e= ntry(struct rvu *rvu, =20 npc_cn20k_config_mcam_entry(rvu, blkaddr, entry, nix_intf, &req->entry_data, req->enable_entry, - req->hw_prio); + req->hw_prio, req->req_kw_type); =20 mutex_unlock(&mcam->lock); =20 @@ -1289,6 +1319,14 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_= entry(struct rvu *rvu, return 0; } =20 +static int rvu_npc_get_base_steer_rule_type(struct rvu *rvu, u16 pcifunc) +{ + if (is_lbk_vf(rvu, pcifunc)) + return NIXLF_PROMISC_ENTRY; + + return NIXLF_UCAST_ENTRY; +} + int rvu_mbox_handler_npc_cn20k_read_base_steer_rule(struct rvu *rvu, struct msg_req *req, struct npc_cn20k_mcam_read_base_rule_rsp *rsp) @@ -1298,6 +1336,7 @@ int rvu_mbox_handler_npc_cn20k_read_base_steer_rule(s= truct rvu *rvu, u16 pcifunc =3D req->hdr.pcifunc; u8 intf, enable, hw_prio; struct rvu_pfvf *pfvf; + int rl_type; =20 blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); if (blkaddr < 0) @@ -1323,9 +1362,11 @@ int rvu_mbox_handler_npc_cn20k_read_base_steer_rule(= struct rvu *rvu, mutex_unlock(&mcam->lock); goto out; } + + rl_type =3D rvu_npc_get_base_steer_rule_type(rvu, pcifunc); + /* Read the default ucast entry if there is no pkt steering rule */ - index =3D npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf, - NIXLF_UCAST_ENTRY); + index =3D npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf, rl_type); read_entry: /* Read the mcam entry */ npc_cn20k_read_mcam_entry(rvu, blkaddr, index, @@ -3845,6 +3886,89 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16= pcifunc, u16 *bcast, return set ? 0 : -ESRCH; } =20 +int rvu_mbox_handler_npc_get_pfl_info(struct rvu *rvu, struct msg_req *req, + struct npc_get_pfl_info_rsp *rsp) +{ + if (!is_cn20k(rvu->pdev)) { + dev_err(rvu->dev, "Mbox support is only for cn20k\n"); + return -EOPNOTSUPP; + } + + rsp->kw_type =3D npc_priv.kw; + rsp->x4_slots =3D npc_priv.bank_depth; + return 0; +} + +int rvu_mbox_handler_npc_get_num_kws(struct rvu *rvu, + struct npc_get_num_kws_req *req, + struct npc_get_num_kws_rsp *rsp) +{ + struct rvu_npc_mcam_rule dummy =3D { 0 }; + struct cn20k_mcam_entry cn20k_entry =3D { 0 }; + struct mcam_entry_mdata mdata =3D { }; + struct mcam_entry entry =3D { 0 }; + struct npc_install_flow_req *fl; + int i, cnt =3D 0, blkaddr; + + if (!is_cn20k(rvu->pdev)) { + dev_err(rvu->dev, "Mbox support is only for cn20k\n"); + return -EOPNOTSUPP; + } + + fl =3D &req->fl; + + blkaddr =3D rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (blkaddr < 0) { + dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__); + return NPC_MCAM_INVALID_REQ; + } + + npc_populate_mcam_mdata(rvu, &mdata, &cn20k_entry, &entry); + + npc_update_flow(rvu, &mdata, fl->features, &fl->packet, + &fl->mask, &dummy, fl->intf, blkaddr); + + /* Find the most significant word valid. Traverse from + * MSB to LSB, check if cam0 or cam1 is set + */ + for (i =3D NPC_CN20K_MAX_KWS_IN_KEY - 1; i >=3D 0; i--) { + if (cn20k_entry.kw[i] || cn20k_entry.kw_mask[i]) { + cnt =3D i + 1; + break; + } + } + + rsp->kws =3D cnt; + + return 0; +} + +int rvu_mbox_handler_npc_get_dft_rl_idxs(struct rvu *rvu, struct msg_req *= req, + struct npc_get_dft_rl_idxs_rsp *rsp) +{ + u16 bcast, mcast, promisc, ucast; + u16 pcifunc; + int rc; + + if (!is_cn20k(rvu->pdev)) { + dev_err(rvu->dev, "Mbox support is only for cn20k\n"); + return -EOPNOTSUPP; + } + + pcifunc =3D req->hdr.pcifunc; + + rc =3D npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &bcast, &mcast, + &promisc, &ucast); + if (rc) + return rc; + + rsp->bcast =3D bcast; + rsp->mcast =3D mcast; + rsp->promisc =3D promisc; + rsp->ucast =3D ucast; + return 0; +} + static bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc) { return is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc)) || diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/driver= s/net/ethernet/marvell/octeontx2/af/cn20k/npc.h index 9e04e0f8c618..61c3af133d39 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h @@ -243,9 +243,8 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pc= ifunc, u16 *bcast, u16 *mcast, u16 *promisc, u16 *ucast); =20 void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index, - u8 intf, - struct cn20k_mcam_entry *entry, - bool enable, u8 hw_prio); + u8 intf, struct cn20k_mcam_entry *entry, + bool enable, u8 hw_prio, u8 req_kw_type); void npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr, int index, bool enable); void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net= /ethernet/marvell/octeontx2/af/mbox.h index 05de319f5e51..49ffc6827276 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -300,6 +300,15 @@ M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601a, npc_cn20k_rea= d_base_steer_rule, M(NPC_MCAM_DEFRAG, 0x601b, npc_defrag, \ msg_req, \ msg_rsp) \ +M(NPC_MCAM_GET_NUM_KWS, 0x601c, npc_get_num_kws, \ + npc_get_num_kws_req, \ + npc_get_num_kws_rsp) \ +M(NPC_MCAM_GET_DFT_RL_IDXS, 0x601d, npc_get_dft_rl_idxs, \ + msg_req, \ + npc_get_dft_rl_idxs_rsp)\ +M(NPC_MCAM_GET_NPC_PFL_INFO, 0x601e, npc_get_pfl_info, \ + msg_req, \ + npc_get_pfl_info_rsp) \ /* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \ M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \ nix_lf_alloc_req, nix_lf_alloc_rsp) \ @@ -1597,6 +1606,7 @@ struct cn20k_mcam_entry { u64 kw_mask[NPC_CN20K_MAX_KWS_IN_KEY]; u64 action; u64 vtag_action; + u64 action2; }; =20 struct npc_cn20k_mcam_write_entry_req { @@ -1607,6 +1617,7 @@ struct npc_cn20k_mcam_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 req_kw_type; /* Type of kw which should be written */ u64 reserved; /* reserved for future use */ }; =20 @@ -1693,6 +1704,7 @@ struct npc_cn20k_mcam_alloc_and_write_entry_req { u8 enable_entry;/* Enable this MCAM entry ? */ u8 hw_prio; /* hardware priority, valid for cn20k */ u8 virt; /* Allocate virtual index */ + u8 req_kw_type; /* Key type to be written */ u16 reserved[4]; /* reserved for future use */ }; =20 @@ -1860,11 +1872,47 @@ struct npc_install_flow_req { /* old counter value */ u16 cntr_val; u8 hw_prio; + u8 req_kw_type; /* Key type to be written */ + u8 alloc_entry; /* only for cn20k */ + u16 ref_prio; + u16 ref_entry; }; =20 struct npc_install_flow_rsp { struct mbox_msghdr hdr; int counter; /* negative if no counter else counter number */ + u16 entry; + u8 kw_type; +}; + +struct npc_get_num_kws_req { + struct mbox_msghdr hdr; + struct npc_install_flow_req fl; + u32 rsvd[4]; +}; + +struct npc_get_num_kws_rsp { + struct mbox_msghdr hdr; + int kws; + u32 rsvd[4]; +}; + +struct npc_get_dft_rl_idxs_rsp { + struct mbox_msghdr hdr; + u16 bcast; + u16 mcast; + u16 promisc; + u16 ucast; + u16 vf_ucast; + u16 rsvd[7]; +}; + +struct npc_get_pfl_info_rsp { + struct mbox_msghdr hdr; + u16 x4_slots; + u8 kw_type; + u8 rsvd1[3]; + u32 rsvd2[4]; }; =20 struct npc_delete_flow_req { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/= net/ethernet/marvell/octeontx2/af/rvu_npc.c index d36291abcbc0..cd279b34684e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -2671,6 +2671,10 @@ static int npc_mcam_alloc_entries(struct npc_mcam *m= cam, u16 pcifunc, if (!is_cn20k(rvu->pdev)) goto not_cn20k; =20 + /* Only x2 or x4 key types are accepted */ + if (req->kw_type !=3D NPC_MCAM_KEY_X2 && req->kw_type !=3D NPC_MCAM_KEY_X= 4) + return NPC_MCAM_INVALID_REQ; + /* The below table is being followed during allocation, * * 1. ref_entry =3D=3D 0 && prio =3D=3D HIGH && count =3D=3D 1 =3D=3D> u= ser wants to allocate 0th index 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 b6d9ff67f05a..9107a19e1d3c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -1064,11 +1064,11 @@ static void npc_update_vlan_features(struct rvu *rv= u, struct mcam_entry_mdata *m ~0ULL, 0, intf); } =20 -static void npc_update_flow(struct rvu *rvu, struct mcam_entry_mdata *mdat= a, - u64 features, struct flow_msg *pkt, - struct flow_msg *mask, - struct rvu_npc_mcam_rule *output, u8 intf, - int blkaddr) +void npc_update_flow(struct rvu *rvu, struct mcam_entry_mdata *mdata, + u64 features, struct flow_msg *pkt, + struct flow_msg *mask, + struct rvu_npc_mcam_rule *output, u8 intf, + int blkaddr) { u64 dmac_mask =3D ether_addr_to_u64(mask->dmac); u64 smac_mask =3D ether_addr_to_u64(mask->smac); @@ -1293,7 +1293,7 @@ static int npc_mcast_update_action_index(struct rvu *= rvu, struct npc_install_flo return 0; } =20 -static void +void npc_populate_mcam_mdata(struct rvu *rvu, struct mcam_entry_mdata *mdata, struct cn20k_mcam_entry *cn20k_entry, @@ -1534,6 +1534,8 @@ static int npc_install_flow(struct rvu *rvu, int blka= ddr, u16 target, cn20k_write_req.entry =3D entry_index; cn20k_write_req.intf =3D req->intf; cn20k_write_req.enable_entry =3D (u8)enable; + cn20k_write_req.hw_prio =3D req->hw_prio; + cn20k_write_req.req_kw_type =3D req->req_kw_type; =20 update_rule: =20 @@ -1620,6 +1622,75 @@ static int npc_install_flow(struct rvu *rvu, int blk= addr, u16 target, return 0; } =20 +static int +rvu_npc_free_entry_for_flow_install(struct rvu *rvu, u16 pcifunc, + bool free_entry, int mcam_idx) +{ + struct npc_mcam_free_entry_req free_req; + struct msg_rsp rsp; + int rc; + + if (!free_entry) + return 0; + + free_req.hdr.pcifunc =3D pcifunc; + free_req.entry =3D mcam_idx; + rc =3D rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp); + return rc; +} + +static int +rvu_npc_alloc_entry_for_flow_install(struct rvu *rvu, + struct npc_install_flow_req *fl_req, + u16 *mcam_idx, u8 *kw_type, + bool *allocated) +{ + struct npc_mcam_alloc_entry_req entry_req; + struct npc_mcam_alloc_entry_rsp entry_rsp; + struct npc_get_num_kws_req kws_req; + struct npc_get_num_kws_rsp kws_rsp; + int off, kw_bits, rc; + u8 *src, *dst; + + if (!is_cn20k(rvu->pdev)) + return 0; + + if (!fl_req->alloc_entry) + return 0; + + off =3D offsetof(struct npc_install_flow_req, packet); + dst =3D (u8 *)&kws_req.fl + off; + src =3D (u8 *)fl_req + off; + memcpy(dst, src, sizeof(struct npc_install_flow_req) - off); + rc =3D rvu_mbox_handler_npc_get_num_kws(rvu, &kws_req, &kws_rsp); + if (rc) + return rc; + + kw_bits =3D kws_rsp.kws * 64; + + *kw_type =3D NPC_MCAM_KEY_X2; + if (kw_bits > 256) + *kw_type =3D NPC_MCAM_KEY_X4; + + memset(&entry_req, 0, sizeof(entry_req)); + memset(&entry_rsp, 0, sizeof(entry_rsp)); + + entry_req.hdr.pcifunc =3D fl_req->hdr.pcifunc; + entry_req.ref_prio =3D fl_req->ref_prio; + entry_req.ref_entry =3D fl_req->ref_entry; + entry_req.kw_type =3D *kw_type; + entry_req.count =3D 1; + rc =3D rvu_mbox_handler_npc_mcam_alloc_entry(rvu, + &entry_req, + &entry_rsp); + if (rc) + return rc; + + *mcam_idx =3D entry_rsp.entry_list[0]; + *allocated =3D true; + return 0; +} + int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, struct npc_install_flow_req *req, struct npc_install_flow_rsp *rsp) @@ -1630,11 +1701,11 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *r= vu, int blkaddr, nixlf, err; struct rvu_pfvf *pfvf; bool pf_set_vfs_mac =3D false; + bool allocated =3D false; bool enable =3D true; + u8 kw_type; 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__); @@ -1644,6 +1715,17 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rv= u, if (!is_npc_interface_valid(rvu, req->intf)) return NPC_FLOW_INTF_INVALID; =20 + err =3D rvu_npc_alloc_entry_for_flow_install(rvu, req, &req->entry, + &kw_type, &allocated); + if (err) { + dev_err(rvu->dev, + "%s: Error to alloc mcam entry for pcifunc=3D%#x\n", + __func__, req->hdr.pcifunc); + return err; + } + + req->entry =3D npc_cn20k_vidx2idx(req->entry); + /* If DMAC is not extracted in MKEX, rules installed by AF * can rely on L2MB bit set by hardware protocol checker for * broadcast and multicast addresses. @@ -1657,6 +1739,8 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, dev_warn(rvu->dev, "%s: mkex profile does not support ucast flow\n", __func__); + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, + allocated, req->entry); return NPC_FLOW_NOT_SUPPORTED; } =20 @@ -1664,6 +1748,8 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, dev_warn(rvu->dev, "%s: mkex profile does not support bcast/mcast flow", __func__); + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, + allocated, req->entry); return NPC_FLOW_NOT_SUPPORTED; } =20 @@ -1673,8 +1759,11 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rv= u, } =20 process_flow: - if (from_vf && req->default_rule) + if (from_vf && req->default_rule) { + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, + allocated, req->entry); return NPC_FLOW_VF_PERM_DENIED; + } =20 /* Each PF/VF info is maintained in struct rvu_pfvf. * rvu_pfvf for the target PF/VF needs to be retrieved @@ -1702,8 +1791,11 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rv= u, req->chan_mask =3D 0xFFF; =20 err =3D npc_check_unsupported_flows(rvu, req->features, req->intf); - if (err) + if (err) { + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, + allocated, req->entry); return NPC_FLOW_NOT_SUPPORTED; + } =20 pfvf =3D rvu_get_pfvf(rvu, target); =20 @@ -1722,8 +1814,11 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rv= u, =20 /* Proceed if NIXLF is attached or not for TX rules */ err =3D nix_get_nixlf(rvu, target, &nixlf, NULL); - if (err && is_npc_intf_rx(req->intf) && !pf_set_vfs_mac) + if (err && is_npc_intf_rx(req->intf) && !pf_set_vfs_mac) { + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, + allocated, req->entry); return NPC_FLOW_NO_NIXLF; + } =20 /* don't enable rule when nixlf not attached or initialized */ if (!(is_nixlf_attached(rvu, target) && @@ -1738,8 +1833,11 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rv= u, enable =3D true; =20 /* Do not allow requests from uninitialized VFs */ - if (from_vf && !enable) + if (from_vf && !enable) { + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, + allocated, req->entry); return NPC_FLOW_VF_NOT_INIT; + } =20 /* PF sets VF mac & VF NIXLF is not attached, update the mac addr */ if (pf_set_vfs_mac && !enable) { @@ -1752,6 +1850,12 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rv= u, mutex_lock(&rswitch->switch_lock); err =3D npc_install_flow(rvu, blkaddr, target, nixlf, pfvf, req, rsp, enable, pf_set_vfs_mac); + if (err) + rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, + allocated, req->entry); + + rsp->kw_type =3D kw_type; + rsp->entry =3D req->entry; mutex_unlock(&rswitch->switch_lock); =20 return err; @@ -2057,7 +2161,7 @@ int npc_install_mcam_drop_rule(struct rvu *rvu, int m= cam_idx, u16 *counter_idx, return err; } =20 - dev_err(rvu->dev, "%s: Installed single drop on non hit rule at %d, cntr= =3D%d\n", + dev_dbg(rvu->dev, "%s: Installed single drop on non hit rule at %d, cntr= =3D%d\n", __func__, mcam_idx, req.cntr); =20 /* disable entry at Bank 0, index 0 */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.h b/drive= rs/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.h index 442287ee7baa..d3ba86c23959 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.h @@ -18,4 +18,16 @@ void npc_update_entry(struct rvu *rvu, enum key_fields t= ype, struct mcam_entry_mdata *mdata, u64 val_lo, u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf); =20 +void npc_update_flow(struct rvu *rvu, struct mcam_entry_mdata *mdata, + u64 features, struct flow_msg *pkt, + struct flow_msg *mask, + struct rvu_npc_mcam_rule *output, u8 intf, + int blkaddr); + +void +npc_populate_mcam_mdata(struct rvu *rvu, + struct mcam_entry_mdata *mdata, + struct cn20k_mcam_entry *cn20k_entry, + struct mcam_entry *entry); + #endif /* RVU_NPC_FS_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/driv= ers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c index 052d989f2d9a..41621734d55e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c @@ -37,6 +37,98 @@ static void otx2_clear_ntuple_flow_info(struct otx2_nic = *pfvf, struct otx2_flow_ flow_cfg->max_flows =3D 0; } =20 +static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, bool *is_x2, + u16 *x4_slots) +{ + struct npc_get_pfl_info_rsp *rsp; + struct msg_req *req; + static struct { + bool is_set; + bool is_x2; + u16 x4_slots; + } pfl_info; + + /* Avoid sending mboxes for constant information + * like x4_slots + */ + if (pfl_info.is_set) { + *is_x2 =3D pfl_info.is_x2; + *x4_slots =3D pfl_info.x4_slots; + return 0; + } + + mutex_lock(&pfvf->mbox.lock); + + req =3D otx2_mbox_alloc_msg_npc_get_pfl_info(&pfvf->mbox); + if (!req) { + mutex_unlock(&pfvf->mbox.lock); + return -ENOMEM; + } + + /* Send message to AF */ + if (otx2_sync_mbox_msg(&pfvf->mbox)) { + mutex_unlock(&pfvf->mbox.lock); + return -EFAULT; + } + + rsp =3D (struct npc_get_pfl_info_rsp *)otx2_mbox_get_rsp + (&pfvf->mbox.mbox, 0, &req->hdr); + + if (IS_ERR(rsp)) { + mutex_unlock(&pfvf->mbox.lock); + return -EFAULT; + } + + *is_x2 =3D (rsp->kw_type =3D=3D NPC_MCAM_KEY_X2); + if (*is_x2) + *x4_slots =3D 0; + else + *x4_slots =3D rsp->x4_slots; + + pfl_info.is_x2 =3D *is_x2; + pfl_info.x4_slots =3D *x4_slots; + pfl_info.is_set =3D true; + + mutex_unlock(&pfvf->mbox.lock); + return 0; +} + +static int otx2_get_dft_rl_idx(struct otx2_nic *pfvf, u16 *mcam_idx) +{ + struct npc_get_dft_rl_idxs_rsp *rsp; + struct msg_req *req; + + mutex_lock(&pfvf->mbox.lock); + + req =3D otx2_mbox_alloc_msg_npc_get_dft_rl_idxs(&pfvf->mbox); + if (!req) { + mutex_unlock(&pfvf->mbox.lock); + return -ENOMEM; + } + + /* Send message to AF */ + if (otx2_sync_mbox_msg(&pfvf->mbox)) { + mutex_unlock(&pfvf->mbox.lock); + return -EINVAL; + } + + rsp =3D (struct npc_get_dft_rl_idxs_rsp *)otx2_mbox_get_rsp + (&pfvf->mbox.mbox, 0, &req->hdr); + + if (IS_ERR(rsp)) { + mutex_unlock(&pfvf->mbox.lock); + return -EFAULT; + } + + if (is_otx2_lbkvf(pfvf->pdev)) + *mcam_idx =3D rsp->promisc; + else + *mcam_idx =3D rsp->ucast; + + mutex_unlock(&pfvf->mbox.lock); + return 0; +} + static int otx2_free_ntuple_mcam_entries(struct otx2_nic *pfvf) { struct otx2_flow_config *flow_cfg =3D pfvf->flow_cfg; @@ -69,7 +161,10 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 = count) struct otx2_flow_config *flow_cfg =3D pfvf->flow_cfg; struct npc_mcam_alloc_entry_req *req; struct npc_mcam_alloc_entry_rsp *rsp; - int ent, allocated =3D 0; + u16 dft_idx =3D 0, x4_slots =3D 0; + int ent, allocated =3D 0, ref; + bool is_x2 =3D false; + int rc; =20 /* Free current ones and allocate new ones with requested count */ otx2_free_ntuple_mcam_entries(pfvf); @@ -86,6 +181,22 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 = count) return -ENOMEM; } =20 + if (is_cn20k(pfvf->pdev)) { + rc =3D otx2_mcam_pfl_info_get(pfvf, &is_x2, &x4_slots); + if (rc) { + netdev_err(pfvf->netdev, "Error to retrieve profile info\n"); + return rc; + } + + rc =3D otx2_get_dft_rl_idx(pfvf, &dft_idx); + if (rc) { + netdev_err(pfvf->netdev, + "Error to retrieve ucast mcam idx for pcifunc %#x\n", + pfvf->pcifunc); + return -EFAULT; + } + } + mutex_lock(&pfvf->mbox.lock); =20 /* In a single request a max of NPC_MAX_NONCONTIG_ENTRIES MCAM entries @@ -96,18 +207,31 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16= count) if (!req) goto exit; =20 + req->kw_type =3D is_x2 ? NPC_MCAM_KEY_X2 : NPC_MCAM_KEY_X4; req->contig =3D false; req->count =3D (count - allocated) > NPC_MAX_NONCONTIG_ENTRIES ? NPC_MAX_NONCONTIG_ENTRIES : count - allocated; =20 + ref =3D 0; + + if (is_cn20k(pfvf->pdev)) { + req->ref_prio =3D NPC_MCAM_HIGHER_PRIO; + ref =3D dft_idx; + } + /* Allocate higher priority entries for PFs, so that VF's entries * will be on top of PF. */ if (!is_otx2_vf(pfvf->pcifunc)) { req->ref_prio =3D NPC_MCAM_HIGHER_PRIO; - req->ref_entry =3D flow_cfg->def_ent[0]; + ref =3D flow_cfg->def_ent[0]; } =20 + if (is_cn20k(pfvf->pdev)) + ref =3D is_x2 ? ref : ref & (x4_slots - 1); + + req->ref_entry =3D ref; + /* Send message to AF */ if (otx2_sync_mbox_msg(&pfvf->mbox)) goto exit; @@ -163,8 +287,24 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf) struct npc_get_field_status_rsp *frsp; struct npc_mcam_alloc_entry_req *req; struct npc_mcam_alloc_entry_rsp *rsp; - int vf_vlan_max_flows; - int ent, count; + int vf_vlan_max_flows, count; + int rc, ref, prio, ent; + u16 dft_idx; + + ref =3D 0; + prio =3D 0; + if (is_cn20k(pfvf->pdev)) { + rc =3D otx2_get_dft_rl_idx(pfvf, &dft_idx); + if (rc) { + netdev_err(pfvf->netdev, + "Error to retrieve ucast mcam idx for pcifunc %#x\n", + pfvf->pcifunc); + return -EFAULT; + } + + ref =3D dft_idx; + prio =3D NPC_MCAM_HIGHER_PRIO; + } =20 vf_vlan_max_flows =3D pfvf->total_vfs * OTX2_PER_VF_VLAN_FLOWS; count =3D flow_cfg->ucast_flt_cnt + @@ -183,8 +323,11 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf) return -ENOMEM; } =20 + req->kw_type =3D NPC_MCAM_KEY_X2; req->contig =3D false; req->count =3D count; + req->ref_prio =3D prio; + req->ref_entry =3D ref; =20 /* Send message to AF */ if (otx2_sync_mbox_msg(&pfvf->mbox)) { @@ -819,7 +962,7 @@ static int otx2_prepare_ipv6_flow(struct ethtool_rx_flo= w_spec *fsp, } =20 static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp, - struct npc_install_flow_req *req) + struct npc_install_flow_req *req) { struct ethhdr *eth_mask =3D &fsp->m_u.ether_spec; struct ethhdr *eth_hdr =3D &fsp->h_u.ether_spec; @@ -945,6 +1088,54 @@ static int otx2_prepare_flow_request(struct ethtool_r= x_flow_spec *fsp, return 0; } =20 +static int otx2_get_kw_type(struct otx2_nic *pfvf, + struct npc_install_flow_req *fl_req, + u8 *kw_type) +{ + struct npc_get_num_kws_req *req; + struct npc_get_num_kws_rsp *rsp; + u8 *src, *dst; + int off, err; + int kw_bits; + + off =3D offsetof(struct npc_install_flow_req, packet); + + mutex_lock(&pfvf->mbox.lock); + + req =3D otx2_mbox_alloc_msg_npc_get_num_kws(&pfvf->mbox); + + dst =3D (u8 *)&req->fl + off; + src =3D (u8 *)fl_req + off; + + memcpy(dst, src, sizeof(struct npc_install_flow_req) - off); + + err =3D otx2_sync_mbox_msg(&pfvf->mbox); + if (err) { + mutex_unlock(&pfvf->mbox.lock); + netdev_err(pfvf->netdev, + "Error to get default number of keywords\n"); + return err; + } + + rsp =3D (struct npc_get_num_kws_rsp *)otx2_mbox_get_rsp + (&pfvf->mbox.mbox, 0, &req->hdr); + if (IS_ERR(rsp)) { + mutex_unlock(&pfvf->mbox.lock); + return -EFAULT; + } + + kw_bits =3D rsp->kws * 64; + + if (kw_bits <=3D 256) + *kw_type =3D NPC_MCAM_KEY_X2; + else + *kw_type =3D NPC_MCAM_KEY_X4; + + mutex_unlock(&pfvf->mbox.lock); + + return 0; +} + static int otx2_is_flow_rule_dmacfilter(struct otx2_nic *pfvf, struct ethtool_rx_flow_spec *fsp) { @@ -973,12 +1164,40 @@ static int otx2_is_flow_rule_dmacfilter(struct otx2_= nic *pfvf, =20 static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow) { + struct otx2_flow_config *flow_cfg =3D pfvf->flow_cfg; + struct npc_install_flow_req *req, treq =3D { 0 }; u64 ring_cookie =3D flow->flow_spec.ring_cookie; #ifdef CONFIG_DCB int vlan_prio, qidx, pfc_rule =3D 0; #endif - struct npc_install_flow_req *req; - int err, vf =3D 0; + int err, vf =3D 0, off, sz; + bool modify =3D false; + u8 *src, *dst; + u16 x4_slots; + bool is_x2; + u8 kw_type; + + if (is_cn20k(pfvf->pdev)) { + err =3D otx2_mcam_pfl_info_get(pfvf, &is_x2, &x4_slots); + if (err) { + netdev_err(pfvf->netdev, + "Error to retrieve ucast mcam idx for pcifunc %#x\n", + pfvf->pcifunc); + return -EFAULT; + } + + if (!is_x2) { + err =3D otx2_prepare_flow_request(&flow->flow_spec, &treq); + if (err) + return err; + + err =3D otx2_get_kw_type(pfvf, &treq, &kw_type); + if (err) + return err; + + modify =3D true; + } + } =20 mutex_lock(&pfvf->mbox.lock); req =3D otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox); @@ -987,14 +1206,29 @@ static int otx2_add_flow_msg(struct otx2_nic *pfvf, = struct otx2_flow *flow) return -ENOMEM; } =20 - err =3D otx2_prepare_flow_request(&flow->flow_spec, req); - if (err) { - /* free the allocated msg above */ - otx2_mbox_reset(&pfvf->mbox.mbox, 0); - mutex_unlock(&pfvf->mbox.lock); - return err; + if (modify) { + off =3D offsetof(struct npc_install_flow_req, packet); + sz =3D sizeof(struct npc_install_flow_req) - off; + dst =3D (u8 *)req + off; + src =3D (u8 *)&treq + off; + + memcpy(dst, src, sz); + req->req_kw_type =3D kw_type; + } else { + err =3D otx2_prepare_flow_request(&flow->flow_spec, req); + if (err) { + /* free the allocated msg above */ + otx2_mbox_reset(&pfvf->mbox.mbox, 0); + mutex_unlock(&pfvf->mbox.lock); + return err; + } } =20 + netdev_dbg(pfvf->netdev, + "flow entry (%u) installed at loc:%u kw_type=3D%u\n", + flow_cfg->flow_ent[flow->location], + flow->location, kw_type); + req->entry =3D flow->entry; req->intf =3D NIX_INTF_RX; req->set_cntr =3D 1; --=20 2.43.0 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (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 5B369315D2B; Mon, 5 Jan 2026 02:34:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580450; cv=none; b=UugSjH9YFJ//vJJgP7cSZLl2fvcydS8mgU6z5omkNX1dqTKcfHZ9T0GkPxy+2LaJSao+pz9K9+b08QZTa74F6PTT0jPgEqpPtZcCAFAQpG9FSUi6mfgY/UmDACgW/S3y6NyvNRTSxx1Miw1jVzCiJ7znR7TXm9iw5PvrzZDkNtQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580450; c=relaxed/simple; bh=yiHRdhTdfGrkD+EjI0d8u32P47AbRLlVUbHGJ/CSF6I=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ST6GDnE/vJbo7kAX4656nYLIEj/M60S6mICvaiPWiRHbZHVNocduM5RT957guCCyrvsJKjzDVcOX5QCeT06WSmKjbIL9WcRKLlsBIvVGUqPu/tC96IBYEVWw8JuR863cl5+lcd2qMAUZQmooQEL80MJN2+ck5kJYnuHjX3eK7N8= 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=aShKczf9; arc=none smtp.client-ip=67.231.156.173 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="aShKczf9" Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604MLgOj1047632; Sun, 4 Jan 2026 18:33:59 -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=J APySN50dfx99qoTuTWxT+sWjZa+SU+GeaLTagUyGFo=; b=aShKczf9x03AuxTCf lv3I1b7OAzduH7zuK6R4ZKlUcTaeTq+QHdj4RS45W6tvW2UjplYRTWQU5RSRTSsI BxthvQ7TmWdDKrJHbXeuDxqca8GzbO/IvtoU8k6ymApWXhIOLwWcHssZ2Cc5mM+J Kf51yUhXhMeFPp1u2zCuMuo0yyr90jVe++XHgB+Gmqp+LNTSuj3dp1SuUaaiWqdG wuhkPzL+eiFudDunNq4M+oKkwSpdmjDqRpIyXAKHAQWofDRxDLkJfrj1M64ROQlC QJTt18T5fWBBjNQXh6wiIee+RlvTSGn3qdUYyUOJYDRQKfUiopC/kkY19nk3C/DA pL9qg== Received: from dc5-exch05.marvell.com ([199.233.59.128]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 4bf3gmj01a-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:33:59 -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:12 -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:12 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id 3A1555C68E6; Sun, 4 Jan 2026 18:33:54 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Subbaraya Sundeep , "Ratheesh Kannoth" Subject: [PATCH net-next 11/13] octeontx2-pf: cn20k: Add TC rules support Date: Mon, 5 Jan 2026 08:02:52 +0530 Message-ID: <20260105023254.1426488-12-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: BjO0mtSgqubDiYMzeo1g1Dv1EFVSjG0A X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX64/K68gQUcoM 7f+udRvaaujyInhP5N9B8o86bcGnmRQkuCj8s/vJblN+wgiSSgP1AmW1f43hhKdi0/mW8dHqG1Y 6lXV+iYQIEzzSq8HJMDunD7b9TtnWn2OHp0GypikMTnrUXPv94A5bKwCk3MlUzqAl+apVIaNCiM 0qT4BkG5l9r4XTIvpXW3DLyqZaMk9CFVFXdawdMfct934giv8tbpvJYwDc+/NDzla9clX3yqlNp hP6BA1j5y9ce0afKz1Jk2+NhGF64oD0B7wJocCFwkLzSrPArT9tLLaGISP3jWUNJ1mFJ3MgOg0L hrwG+ZBCcIWx5d4QzlE9smH9MuBnAWEq+I/HjtSvjrt4cHxDccFAv6GcCynYD5tWjBwg5Bu8XGL /TYCvm80A2coEISIuYvDEGrwjDnsx0jcgxCckbqDB85gbkz13PFRVfNKFyWBN9UVBbGgy4+E+Pa pFqFVU/ut0WwllJBPbg== X-Authority-Analysis: v=2.4 cv=PcXyRyhd c=1 sm=1 tr=0 ts=695b2317 cx=c_pps a=rEv8fa4AjpPjGxpoe8rlIQ==:117 a=rEv8fa4AjpPjGxpoe8rlIQ==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=KaEl-UT5FusyG8Xfe_EA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-GUID: BjO0mtSgqubDiYMzeo1g1Dv1EFVSjG0A 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" From: Subbaraya Sundeep Unlike previous silicons, MCAM entries required for TC rules in CN20K are allocated dynamically. The key size can also be dynamic, i.e., X2 or X4. Based on the size of the TC rule match criteria, the AF driver allocates an X2 or X4 rule. This patch implements the required changes for CN20K TC by requesting an MCAM entry from the AF driver on the fly when the user installs a rule. Based on the TC rule priority added or deleted by the user, the PF driver shifts MCAM entries accordingly. If there is a mix of X2 and X4 rules and the user tries to install a rule in the middle of existing rules, the PF driver detects this and rejects the rule since X2 and X4 rules cannot be shifted in hardware. Signed-off-by: Subbaraya Sundeep Signed-off-by: Ratheesh Kannoth --- .../net/ethernet/marvell/octeontx2/af/mbox.h | 5 + .../marvell/octeontx2/af/rvu_npc_fs.c | 12 +- .../ethernet/marvell/octeontx2/nic/cn20k.c | 265 ++++++++++++++++++ .../ethernet/marvell/octeontx2/nic/cn20k.h | 13 + .../marvell/octeontx2/nic/otx2_common.h | 35 +++ .../marvell/octeontx2/nic/otx2_flows.c | 3 +- .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 77 ++--- 7 files changed, 367 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net= /ethernet/marvell/octeontx2/af/mbox.h index 49ffc6827276..6f26f7393709 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1874,6 +1874,11 @@ struct npc_install_flow_req { u8 hw_prio; u8 req_kw_type; /* Key type to be written */ u8 alloc_entry; /* only for cn20k */ +/* For now use any priority, once AF driver is changed to + * allocate least priority entry instead of mid zone then make + * NPC_MCAM_LEAST_PRIO as 3 + */ +#define NPC_MCAM_LEAST_PRIO NPC_MCAM_ANY_PRIO u16 ref_prio; u16 ref_entry; }; 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 9107a19e1d3c..57c50790e18b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -1739,8 +1739,10 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rv= u, dev_warn(rvu->dev, "%s: mkex profile does not support ucast flow\n", __func__); - rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, - allocated, req->entry); + rvu_npc_free_entry_for_flow_install(rvu, + req->hdr.pcifunc, + allocated, + req->entry); return NPC_FLOW_NOT_SUPPORTED; } =20 @@ -1748,8 +1750,10 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rv= u, dev_warn(rvu->dev, "%s: mkex profile does not support bcast/mcast flow", __func__); - rvu_npc_free_entry_for_flow_install(rvu, req->hdr.pcifunc, - allocated, req->entry); + rvu_npc_free_entry_for_flow_install(rvu, + req->hdr.pcifunc, + allocated, + req->entry); return NPC_FLOW_NOT_SUPPORTED; } =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c b/drivers/n= et/ethernet/marvell/octeontx2/nic/cn20k.c index a60f8cf53feb..cd2c9a95ee22 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c @@ -251,6 +251,271 @@ static u8 cn20k_aura_bpid_idx(struct otx2_nic *pfvf, = int aura_id) #endif } =20 +static int cn20k_tc_get_entry_index(struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node) +{ + struct otx2_tc_flow *tmp; + int index =3D 0; + + list_for_each_entry(tmp, &flow_cfg->flow_list_tc, list) { + if (tmp =3D=3D node) + return index; + + index++; + } + + return 0; +} + +static int cn20k_tc_free_mcam_entry(struct otx2_nic *nic, u16 entry) +{ + struct npc_mcam_free_entry_req *req; + int err; + + mutex_lock(&nic->mbox.lock); + req =3D otx2_mbox_alloc_msg_npc_mcam_free_entry(&nic->mbox); + if (!req) { + mutex_unlock(&nic->mbox.lock); + return -ENOMEM; + } + + req->entry =3D entry; + /* Send message to AF to free MCAM entries */ + err =3D otx2_sync_mbox_msg(&nic->mbox); + if (err) { + mutex_unlock(&nic->mbox.lock); + return err; + } + + mutex_unlock(&nic->mbox.lock); + + return 0; +} + +static bool cn20k_tc_check_entry_shiftable(struct otx2_nic *nic, + struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node, int index, + bool error) +{ + struct otx2_tc_flow *first, *tmp, *n; + u32 prio =3D 0; + int i =3D 0; + u8 type; + + first =3D list_first_entry(&flow_cfg->flow_list_tc, struct otx2_tc_flow, + list); + type =3D first->kw_type; + + /* Check all the nodes from start to given index (including index) has + * same type i.e, either X2 or X4 + */ + list_for_each_entry_safe(tmp, n, &flow_cfg->flow_list_tc, list) { + if (i > index) + break; + + if (type !=3D tmp->kw_type) { + /* List has both X2 and X4 entries so entries cannot be + * shifted to save MCAM space. + */ + if (error) + dev_err(nic->dev, "Rule %d cannot be shifted to %d\n", + tmp->prio, prio); + return false; + } + + type =3D tmp->kw_type; + prio =3D tmp->prio; + i++; + } + + return true; +} + +void cn20k_tc_update_mcam_table_del_req(struct otx2_nic *nic, + struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node) +{ + struct otx2_tc_flow *first, *tmp, *n; + int i =3D 0, index; + u16 cntr_val =3D 0; + u16 entry; + + index =3D cn20k_tc_get_entry_index(flow_cfg, node); + first =3D list_first_entry(&flow_cfg->flow_list_tc, struct otx2_tc_flow, + list); + entry =3D first->entry; + + /* If entries cannot be shifted then delete given entry + * and free it to AF too. + */ + if (!cn20k_tc_check_entry_shiftable(nic, flow_cfg, node, + index, false)) { + list_del(&node->list); + entry =3D node->entry; + goto free_mcam_entry; + } + + /* Find and delete the entry from the list and re-install + * all the entries from beginning to the index of the + * deleted entry to higher mcam indexes. + */ + list_for_each_entry_safe(tmp, n, &flow_cfg->flow_list_tc, list) { + if (node =3D=3D tmp) { + list_del(&tmp->list); + break; + } + + otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val); + tmp->entry =3D (list_next_entry(tmp, list))->entry; + tmp->req.entry =3D tmp->entry; + tmp->req.cntr_val =3D cntr_val; + } + + list_for_each_entry_safe(tmp, n, &flow_cfg->flow_list_tc, list) { + if (i =3D=3D index) + break; + + otx2_add_mcam_flow_entry(nic, &tmp->req); + i++; + } + +free_mcam_entry: + if (cn20k_tc_free_mcam_entry(nic, entry)) + netdev_err(nic->netdev, "Freeing entry %d to AF failed\n", + first->entry); +} + +int cn20k_tc_update_mcam_table_add_req(struct otx2_nic *nic, + struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node) +{ + struct otx2_tc_flow *tmp; + u16 cntr_val =3D 0; + int list_idx, i; + int entry, prev; + + /* Find the index of the entry(list_idx) whose priority + * is greater than the new entry and re-install all + * the entries from beginning to list_idx to higher + * mcam indexes. + */ + list_idx =3D otx2_tc_add_to_flow_list(flow_cfg, node); + entry =3D node->entry; + if (!cn20k_tc_check_entry_shiftable(nic, flow_cfg, node, + list_idx, true)) { + /* Due to mix of X2 and X4, entries cannot be shifted. + * In this case free the entry allocated for this rule. + */ + if (cn20k_tc_free_mcam_entry(nic, entry)) + netdev_err(nic->netdev, + "Freeing entry %d to AF failed\n", entry); + return -EINVAL; + } + + for (i =3D 0; i < list_idx; i++) { + tmp =3D otx2_tc_get_entry_by_index(flow_cfg, i); + if (!tmp) + return -ENOMEM; + + otx2_del_mcam_flow_entry(nic, tmp->entry, &cntr_val); + prev =3D tmp->entry; + tmp->entry =3D entry; + tmp->req.entry =3D tmp->entry; + tmp->req.cntr_val =3D cntr_val; + otx2_add_mcam_flow_entry(nic, &tmp->req); + entry =3D prev; + } + + return entry; +} + +#define MAX_TC_HW_PRIORITY 125 +#define MAX_TC_VF_PRIORITY 126 +#define MAX_TC_PF_PRIORITY 127 + +static int __cn20k_tc_alloc_entry(struct otx2_nic *nic, + struct npc_install_flow_req *flow_req, + u16 *entry, u8 *type, + u32 tc_priority, bool hw_priority) +{ + struct otx2_flow_config *flow_cfg =3D nic->flow_cfg; + struct npc_install_flow_req *req; + struct npc_install_flow_rsp *rsp; + struct otx2_tc_flow *tmp; + int ret =3D 0; + + req =3D otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox); + if (!req) + return -ENOMEM; + + memcpy(&flow_req->hdr, &req->hdr, sizeof(struct mbox_msghdr)); + memcpy(req, flow_req, sizeof(struct npc_install_flow_req)); + req->alloc_entry =3D 1; + + /* Allocate very least priority for first rule */ + if (hw_priority || list_empty(&flow_cfg->flow_list_tc)) { + req->ref_prio =3D NPC_MCAM_LEAST_PRIO; + } else { + req->ref_prio =3D NPC_MCAM_HIGHER_PRIO; + tmp =3D list_first_entry(&flow_cfg->flow_list_tc, + struct otx2_tc_flow, list); + req->ref_entry =3D tmp->entry; + } + + ret =3D otx2_sync_mbox_msg(&nic->mbox); + if (ret) + return ret; + + rsp =3D (struct npc_install_flow_rsp *)otx2_mbox_get_rsp(&nic->mbox.mbox, + 0, &req->hdr); + if (IS_ERR(rsp)) + return -EFAULT; + + if (entry) + *entry =3D rsp->entry; + if (type) + *type =3D rsp->kw_type; + + return ret; +} + +int cn20k_tc_alloc_entry(struct otx2_nic *nic, + struct flow_cls_offload *tc_flow_cmd, + struct otx2_tc_flow *new_node, + struct npc_install_flow_req *flow_req) +{ + bool hw_priority =3D false; + u16 entry_from_af; + u8 entry_type; + int ret; + + if (is_otx2_vf(nic->pcifunc)) + flow_req->hw_prio =3D MAX_TC_VF_PRIORITY; + else + flow_req->hw_prio =3D MAX_TC_PF_PRIORITY; + + if (new_node->prio <=3D MAX_TC_HW_PRIORITY) { + flow_req->hw_prio =3D new_node->prio; + hw_priority =3D true; + } + + mutex_lock(&nic->mbox.lock); + + ret =3D __cn20k_tc_alloc_entry(nic, flow_req, &entry_from_af, &entry_type, + new_node->prio, hw_priority); + if (ret) { + mutex_unlock(&nic->mbox.lock); + return ret; + } + + new_node->kw_type =3D entry_type; + new_node->entry =3D entry_from_af; + + mutex_unlock(&nic->mbox.lock); + + return 0; +} + static int cn20k_aura_aq_init(struct otx2_nic *pfvf, int aura_id, int pool_id, int numptrs) { diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h b/drivers/n= et/ethernet/marvell/octeontx2/nic/cn20k.h index 832adaf8c57f..3cc57886627d 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn20k.h @@ -10,8 +10,21 @@ =20 #include "otx2_common.h" =20 +struct otx2_flow_config; +struct otx2_tc_flow; + void cn20k_init(struct otx2_nic *pfvf); int cn20k_register_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs); void cn20k_disable_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs); void cn20k_enable_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs); +void cn20k_tc_update_mcam_table_del_req(struct otx2_nic *nic, + struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node); +int cn20k_tc_update_mcam_table_add_req(struct otx2_nic *nic, + struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node); +int cn20k_tc_alloc_entry(struct otx2_nic *nic, + struct flow_cls_offload *tc_flow_cmd, + struct otx2_tc_flow *new_node, + struct npc_install_flow_req *dummy); #endif /* CN20K_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/dri= vers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index e616a727a3a9..3cb86e584acb 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -366,6 +366,31 @@ struct otx2_flow_config { u16 ntuple_cnt; }; =20 +struct otx2_tc_flow_stats { + u64 bytes; + u64 pkts; + u64 used; +}; + +struct otx2_tc_flow { + struct list_head list; + unsigned long cookie; + struct rcu_head rcu; + struct otx2_tc_flow_stats stats; + spinlock_t lock; /* lock for stats */ + u16 rq; + u16 entry; + u16 leaf_profile; + bool is_act_police; + u32 prio; + struct npc_install_flow_req req; + u64 rate; + u32 burst; + u32 mcast_grp_idx; + bool is_pps; + u8 kw_type; /* X2/X4 */ +}; + struct dev_hw_ops { int (*sq_aq_init)(void *dev, u16 qidx, u8 chan_offset, u16 sqb_aura); @@ -1221,4 +1246,14 @@ void otx2_dma_unmap_skb_frags(struct otx2_nic *pfvf,= struct sg_list *sg); int otx2_read_free_sqe(struct otx2_nic *pfvf, u16 qidx); void otx2_queue_vf_work(struct mbox *mw, struct workqueue_struct *mbox_wq, int first, int mdevs, u64 intr); +int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, + u16 *cntr_val); +int otx2_add_mcam_flow_entry(struct otx2_nic *nic, + struct npc_install_flow_req *req); +int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node); + +struct otx2_tc_flow * +otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg, + int index); #endif /* OTX2_COMMON_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/driv= ers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c index 41621734d55e..3a3088a66469 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c @@ -1187,7 +1187,8 @@ static int otx2_add_flow_msg(struct otx2_nic *pfvf, s= truct otx2_flow *flow) } =20 if (!is_x2) { - err =3D otx2_prepare_flow_request(&flow->flow_spec, &treq); + err =3D otx2_prepare_flow_request(&flow->flow_spec, + &treq); if (err) return err; =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers= /net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 26a08d2cfbb1..866d9451f5d6 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -31,30 +31,6 @@ =20 #define MCAST_INVALID_GRP (-1U) =20 -struct otx2_tc_flow_stats { - u64 bytes; - u64 pkts; - u64 used; -}; - -struct otx2_tc_flow { - struct list_head list; - unsigned long cookie; - struct rcu_head rcu; - struct otx2_tc_flow_stats stats; - spinlock_t lock; /* lock for stats */ - u16 rq; - u16 entry; - u16 leaf_profile; - bool is_act_police; - u32 prio; - struct npc_install_flow_req req; - u32 mcast_grp_idx; - u64 rate; - u32 burst; - bool is_pps; -}; - static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, u32 *burst_exp, u32 *burst_mantissa) { @@ -971,8 +947,9 @@ static void otx2_destroy_tc_flow_list(struct otx2_nic *= pfvf) } } =20 -static struct otx2_tc_flow *otx2_tc_get_entry_by_cookie(struct otx2_flow_c= onfig *flow_cfg, - unsigned long cookie) +static struct otx2_tc_flow * +otx2_tc_get_entry_by_cookie(struct otx2_flow_config *flow_cfg, + unsigned long cookie) { struct otx2_tc_flow *tmp; =20 @@ -984,8 +961,8 @@ static struct otx2_tc_flow *otx2_tc_get_entry_by_cookie= (struct otx2_flow_config return NULL; } =20 -static struct otx2_tc_flow *otx2_tc_get_entry_by_index(struct otx2_flow_co= nfig *flow_cfg, - int index) +struct otx2_tc_flow * +otx2_tc_get_entry_by_index(struct otx2_flow_config *flow_cfg, int index) { struct otx2_tc_flow *tmp; int i =3D 0; @@ -1014,8 +991,8 @@ static void otx2_tc_del_from_flow_list(struct otx2_flo= w_config *flow_cfg, } } =20 -static int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg, - struct otx2_tc_flow *node) +int otx2_tc_add_to_flow_list(struct otx2_flow_config *flow_cfg, + struct otx2_tc_flow *node) { struct list_head *pos, *n; struct otx2_tc_flow *tmp; @@ -1038,7 +1015,8 @@ static int otx2_tc_add_to_flow_list(struct otx2_flow_= config *flow_cfg, return index; } =20 -static int otx2_add_mcam_flow_entry(struct otx2_nic *nic, struct npc_insta= ll_flow_req *req) +int otx2_add_mcam_flow_entry(struct otx2_nic *nic, + struct npc_install_flow_req *req) { struct npc_install_flow_req *tmp_req; int err; @@ -1064,7 +1042,7 @@ static int otx2_add_mcam_flow_entry(struct otx2_nic *= nic, struct npc_install_flo return 0; } =20 -static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, u16 *= cntr_val) +int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry, u16 *cntr_va= l) { struct npc_delete_flow_rsp *rsp; struct npc_delete_flow_req *req; @@ -1114,6 +1092,11 @@ static int otx2_tc_update_mcam_table_del_req(struct = otx2_nic *nic, int i =3D 0, index =3D 0; u16 cntr_val =3D 0; =20 + if (is_cn20k(nic->pdev)) { + cn20k_tc_update_mcam_table_del_req(nic, flow_cfg, node); + return 0; + } + /* Find and delete the entry from the list and re-install * all the entries from beginning to the index of the * deleted entry to higher mcam indexes. @@ -1153,6 +1136,9 @@ static int otx2_tc_update_mcam_table_add_req(struct o= tx2_nic *nic, int list_idx, i; u16 cntr_val =3D 0; =20 + if (is_cn20k(nic->pdev)) + return cn20k_tc_update_mcam_table_add_req(nic, flow_cfg, node); + /* Find the index of the entry(list_idx) whose priority * is greater than the new entry and re-install all * the entries from beginning to list_idx to higher @@ -1172,7 +1158,7 @@ static int otx2_tc_update_mcam_table_add_req(struct o= tx2_nic *nic, mcam_idx++; } =20 - return mcam_idx; + return flow_cfg->flow_ent[mcam_idx]; } =20 static int otx2_tc_update_mcam_table(struct otx2_nic *nic, @@ -1238,7 +1224,6 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, mutex_unlock(&nic->mbox.lock); } =20 - free_mcam_flow: otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL); otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false); @@ -1254,7 +1239,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, struct otx2_flow_config *flow_cfg =3D nic->flow_cfg; struct otx2_tc_flow *new_node, *old_node; struct npc_install_flow_req *req, dummy; - int rc, err, mcam_idx; + int rc, err, entry; =20 if (!(nic->flags & OTX2_FLAG_TC_FLOWER_SUPPORT)) return -ENOMEM; @@ -1264,7 +1249,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, return -EINVAL; } =20 - if (flow_cfg->nr_flows =3D=3D flow_cfg->max_flows) { + if (!is_cn20k(nic->pdev) && flow_cfg->nr_flows =3D=3D flow_cfg->max_flows= ) { NL_SET_ERR_MSG_MOD(extack, "Free MCAM entry not available to add the flow"); return -ENOMEM; @@ -1292,7 +1277,23 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, if (old_node) otx2_tc_del_flow(nic, tc_flow_cmd); =20 - mcam_idx =3D otx2_tc_update_mcam_table(nic, flow_cfg, new_node, true); + if (is_cn20k(nic->pdev)) { + rc =3D cn20k_tc_alloc_entry(nic, tc_flow_cmd, new_node, &dummy); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, + "MCAM rule allocation failed"); + kfree_rcu(new_node, rcu); + return rc; + } + } + + entry =3D otx2_tc_update_mcam_table(nic, flow_cfg, new_node, true); + if (entry < 0) { + NL_SET_ERR_MSG_MOD(extack, "Adding rule failed"); + rc =3D entry; + goto free_leaf; + } + mutex_lock(&nic->mbox.lock); req =3D otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox); if (!req) { @@ -1304,7 +1305,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, memcpy(&dummy.hdr, &req->hdr, sizeof(struct mbox_msghdr)); memcpy(req, &dummy, sizeof(struct npc_install_flow_req)); req->channel =3D nic->hw.rx_chan_base; - req->entry =3D flow_cfg->flow_ent[mcam_idx]; + req->entry =3D (u16)entry; req->intf =3D NIX_INTF_RX; req->vf =3D nic->pcifunc; req->set_cntr =3D 1; --=20 2.43.0 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0a-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 F313231D72B; Mon, 5 Jan 2026 02:34:10 +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=1767580453; cv=none; b=CKOCmRTaaxpWH5P8IYdWA42fCpiwVibGN1nPoTtB03BxtGRckFHRfvWg075Wh/w3Zh0GHnpeOOSHzBJyEAoMqz639dhcd0ccd+RQ0mJTOnAu+LhLB4m4JOOugjaVxtdaLCdb/nr6OEs+lyhUwb2rGbt9jazR6nT+EZde+9KZAG0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580453; c=relaxed/simple; bh=9DZMqprNmR/kr5fK093p3b8MHKmwKdRoLvFDTp8lKwE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=C9enxZTn9DOXlAnkp+2nitzjqffVyg1CtQ5cF0y24Z2xET7AlnaJ+Eqwp+YLBpszN+9phsBYHPjoCkqdpatJASWUSW8P9TGVWKQ98b5WpSZ5/z5cHmUgqvFt+uyzbq5ms4PlvicQTREWjuwSvLxg1NdDaY7l8PmTu5lOj2z5Nzc= 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=UOiYXGYu; 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="UOiYXGYu" Received: from pps.filterd (m0431384.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6050SmKJ2806564; Sun, 4 Jan 2026 18:34:02 -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=t KupvbCww24wlrszEQnIdaVXSPo+LKRcIyO6VSxh8l4=; b=UOiYXGYuYpm+RA8Jm wJLEJdLhBWGUuNxN9aw+i3xPAIkiyv4VLis10uIPeqm9YUIeZfXZdQO2j+uL/T33 NA2btQRw5nmYFv0M3FX1PBUhD7M6Ze+cZ+1PSmGWQ6gSq17eyHn0VGxrv4cDNKi2 Q+T+52rslSNNznhFynrtiv9srDyaH+MBRNU6tkYKFwjXjk+GvBGBD7b3otkd40GD fwbr4wNgj41UbCNHeGhZp3SEodG4mDRgm3zpDRs+v17ix2kDbt4FYt7Fzka3p/aj Pv4FsUzjJJ9s6hB8urwUOgxjp6lFcf9AnXf7wU6InlA8dMazuYwwf9LFuByThUow BI0bQ== Received: from dc5-exch05.marvell.com ([199.233.59.128]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 4bfr8bgtsx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:34:02 -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:15 -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:15 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id E774C3F7094; Sun, 4 Jan 2026 18:33:58 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 12/13] octeontx2-af: npc: cn20k: add debugfs support Date: Mon, 5 Jan 2026 08:02:53 +0530 Message-ID: <20260105023254.1426488-13-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: js6uMo_AzJBXPAOqh96YQbpIHxjWZ1ok X-Proofpoint-GUID: js6uMo_AzJBXPAOqh96YQbpIHxjWZ1ok X-Authority-Analysis: v=2.4 cv=P/I3RyAu c=1 sm=1 tr=0 ts=695b231a cx=c_pps a=rEv8fa4AjpPjGxpoe8rlIQ==:117 a=rEv8fa4AjpPjGxpoe8rlIQ==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=KJFtI6hBAxspoFtN7EMA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX69IIocoP3EHt xZIOj1GphBMnWbu7T+q9JGlZ7bWx+9GtCp6VLRiSff0Kjmy0oqsOvV8iVpRmVhx2Mo3FS43HHNx /7d3oXXb1GIRBtxNX/XQ6b41cTS7NBTq02GlEBSHt3RHQixV5rT1oFfDzskS1PqBzVI0qC6sI7p zR+/sOmk5AHsVKEiE8C6bLw+5uDUHA45M2vlQ+AdN8ljlyicRGT9vPvq+Ljs92Tn72IGx+OLelG 56IbuJsYrnt1QDT6djFEQO5ih5O98QII6pTpXYaAgg74Rk4cYYJGT5iKywEejqnbqTVEbFFfbEs DI66rCa2//QzEo3/2OPHcyO3ow0maSyuyll2anAOw+84LTHsmPnoAatmTgeHKCTtYthLcsMRLYg KKqhRW49/eESmHu3DcMrGGtNYCNNUQ4r++R7lPJXVI4DDBQOJmmvxw4Xl4dZjC7qp3cmd3wCmw7 5BW3UYE1L1xNKi8/nhA== 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" CN20K silicon divides the NPC MCAM into banks and subbanks, with each subbank configurable for x2 or x4 key widths. This patch adds debugfs entries to expose subbank usage details and their configured key type. A debugfs entry is also added to display the default MCAM indexes allocated for each pcifunc. Additionally, debugfs support is introduced to show the mapping between virtual indexes and real MCAM indexes, and vice versa. Signed-off-by: Ratheesh Kannoth --- .../marvell/octeontx2/af/cn20k/debugfs.c | 255 ++++++++++++++++++ .../marvell/octeontx2/af/rvu_debugfs.c | 37 ++- .../marvell/octeontx2/af/rvu_npc_fs.c | 1 + 3 files changed, 283 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c b/dr= ivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c index c7c59a98d969..a7a8a38f53e6 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c @@ -15,6 +15,233 @@ #include "debugfs.h" #include "cn20k/npc.h" =20 +static int npc_mcam_layout_show(struct seq_file *s, void *unused) +{ + int i, j, sbd, idx0, idx1, vidx0, vidx1; + struct npc_priv_t *npc_priv; + char buf0[32], buf1[32]; + struct npc_subbank *sb; + unsigned int bw0, bw1; + bool v0, v1; + int pf1, pf2; + bool e0, e1; + void *map; + + npc_priv =3D s->private; + + sbd =3D npc_priv->subbank_depth; + + for (i =3D npc_priv->num_subbanks - 1; i >=3D 0; i--) { + sb =3D &npc_priv->sb[i]; + mutex_lock(&sb->lock); + + if (sb->flags & NPC_SUBBANK_FLAG_FREE) + goto next; + + bw0 =3D bitmap_weight(sb->b0map, npc_priv->subbank_depth); + if (sb->key_type =3D=3D NPC_MCAM_KEY_X4) { + seq_printf(s, "\n\nsubbank:%u, x4, free=3D%u, used=3D%u\n", + sb->idx, sb->free_cnt, bw0); + + for (j =3D sbd - 1; j >=3D 0; j--) { + if (!test_bit(j, sb->b0map)) + continue; + + idx0 =3D sb->b0b + j; + map =3D xa_load(&npc_priv->xa_idx2pf_map, idx0); + pf1 =3D xa_to_value(map); + + map =3D xa_load(&npc_priv->xa_idx2vidx_map, idx0); + if (map) { + vidx0 =3D xa_to_value(map); + snprintf(buf0, sizeof(buf0), "v:%u", vidx0); + } + + seq_printf(s, "\t%u(%#x) %s\n", idx0, pf1, + map ? buf0 : " "); + } + goto next; + } + + bw1 =3D bitmap_weight(sb->b1map, npc_priv->subbank_depth); + seq_printf(s, "\n\nsubbank:%u, x2, free=3D%u, used=3D%u\n", + sb->idx, sb->free_cnt, bw0 + bw1); + seq_printf(s, "bank1(%u)\t\tbank0(%u)\n", bw1, bw0); + + for (j =3D sbd - 1; j >=3D 0; j--) { + e0 =3D test_bit(j, sb->b0map); + e1 =3D test_bit(j, sb->b1map); + + if (!e1 && !e0) + continue; + + if (e1 && e0) { + idx0 =3D sb->b0b + j; + map =3D xa_load(&npc_priv->xa_idx2pf_map, idx0); + pf1 =3D xa_to_value(map); + + map =3D xa_load(&npc_priv->xa_idx2vidx_map, idx0); + v0 =3D !!map; + if (v0) { + vidx0 =3D xa_to_value(map); + snprintf(buf0, sizeof(buf0), "v:%05u", vidx0); + } + + idx1 =3D sb->b1b + j; + map =3D xa_load(&npc_priv->xa_idx2pf_map, idx1); + pf2 =3D xa_to_value(map); + + map =3D xa_load(&npc_priv->xa_idx2vidx_map, idx1); + v1 =3D !!map; + if (v1) { + vidx1 =3D xa_to_value(map); + snprintf(buf1, sizeof(buf1), "v:%05u", vidx1); + } + + seq_printf(s, "%05u(%#x) %s\t\t%05u(%#x) %s\n", + idx1, pf2, v1 ? buf1 : " ", + idx0, pf1, v0 ? buf0 : " "); + + continue; + } + + if (e0) { + idx0 =3D sb->b0b + j; + map =3D xa_load(&npc_priv->xa_idx2pf_map, idx0); + pf1 =3D xa_to_value(map); + + map =3D xa_load(&npc_priv->xa_idx2vidx_map, idx0); + if (map) { + vidx0 =3D xa_to_value(map); + snprintf(buf0, sizeof(buf0), "v:%05u", vidx0); + } + + seq_printf(s, "\t\t \t\t%05u(%#x) %s\n", idx0, pf1, + map ? buf0 : " "); + continue; + } + + idx1 =3D sb->b1b + j; + map =3D xa_load(&npc_priv->xa_idx2pf_map, idx1); + pf1 =3D xa_to_value(map); + map =3D xa_load(&npc_priv->xa_idx2vidx_map, idx1); + if (map) { + vidx1 =3D xa_to_value(map); + snprintf(buf1, sizeof(buf1), "v:%05u", vidx1); + } + + seq_printf(s, "%05u(%#x) %s\n", idx1, pf1, + map ? buf1 : " "); + } +next: + mutex_unlock(&sb->lock); + } + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(npc_mcam_layout); + +static int npc_mcam_default_show(struct seq_file *s, void *unused) +{ + struct npc_priv_t *npc_priv; + unsigned long index; + u16 ptr[4], pcifunc; + struct rvu *rvu; + int rc, i; + void *map; + + npc_priv =3D npc_priv_get(); + rvu =3D s->private; + + seq_puts(s, "\npcifunc\tBcast\tmcast\tpromisc\tucast\n"); + + xa_for_each(&npc_priv->xa_pf_map, index, map) { + pcifunc =3D index; + + for (i =3D 0; i < ARRAY_SIZE(ptr); i++) + ptr[i] =3D USHRT_MAX; + + rc =3D npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0], + &ptr[1], &ptr[2], &ptr[3]); + if (rc) + continue; + + seq_printf(s, "%#x\t", pcifunc); + for (i =3D 0; i < ARRAY_SIZE(ptr); i++) { + if (ptr[i] !=3D USHRT_MAX) + seq_printf(s, "%u\t", ptr[i]); + else + seq_puts(s, "\t"); + } + seq_puts(s, "\n"); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(npc_mcam_default); + +static int npc_vidx2idx_map_show(struct seq_file *s, void *unused) +{ + struct npc_priv_t *npc_priv; + unsigned long index, start; + struct xarray *xa; + void *map; + + npc_priv =3D s->private; + start =3D npc_priv->bank_depth * 2; + xa =3D &npc_priv->xa_vidx2idx_map; + + seq_puts(s, "\nvidx\tmcam_idx\n"); + + xa_for_each_start(xa, index, map, start) + seq_printf(s, "%lu\t%lu\n", index, xa_to_value(map)); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(npc_vidx2idx_map); + +static int npc_idx2vidx_map_show(struct seq_file *s, void *unused) +{ + struct npc_priv_t *npc_priv; + unsigned long index; + struct xarray *xa; + void *map; + + npc_priv =3D s->private; + xa =3D &npc_priv->xa_idx2vidx_map; + + seq_puts(s, "\nmidx\tvidx\n"); + + xa_for_each(xa, index, map) + seq_printf(s, "%lu\t%lu\n", index, xa_to_value(map)); + return 0; +} +DEFINE_SHOW_ATTRIBUTE(npc_idx2vidx_map); + +static int npc_defrag_show(struct seq_file *s, void *unused) +{ + struct npc_defrag_show_node *node; + struct npc_priv_t *npc_priv; + u16 sbd, bdm; + + npc_priv =3D s->private; + bdm =3D npc_priv->bank_depth - 1; + sbd =3D npc_priv->subbank_depth; + + seq_puts(s, "\nold(sb) -> new(sb)\t\tvidx\n"); + + mutex_lock(&npc_priv->lock); + list_for_each_entry(node, &npc_priv->defrag_lh, list) + seq_printf(s, "%u(%u)\t%u(%u)\t%u\n", node->old_midx, + (node->old_midx & bdm) / sbd, + node->new_midx, + (node->new_midx & bdm) / sbd, + node->vidx); + mutex_unlock(&npc_priv->lock); + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(npc_defrag); + static void npc_subbank_srch_order_dbgfs_usage(void) { pr_err("Usage: echo \"[0]=3D[8],[1]=3D7,[2]=3D30,...[31]=3D0\" > /subbank_srch_order\n"); @@ -179,6 +406,7 @@ static const struct file_operations npc_subbank_srch_or= der_ops =3D { =20 int npc_cn20k_debugfs_init(struct rvu *rvu) { + struct npc_priv_t *npc_priv =3D npc_priv_get(); struct dentry *npc_dentry; =20 npc_dentry =3D debugfs_create_file("subbank_srch_order", 0644, @@ -187,6 +415,33 @@ int npc_cn20k_debugfs_init(struct rvu *rvu) if (!npc_dentry) return -EFAULT; =20 + npc_dentry =3D debugfs_create_file("mcam_layout", 0444, rvu->rvu_dbg.npc, + npc_priv, &npc_mcam_layout_fops); + + if (!npc_dentry) + return -EFAULT; + + npc_dentry =3D debugfs_create_file("mcam_default", 0444, rvu->rvu_dbg.npc, + rvu, &npc_mcam_default_fops); + + if (!npc_dentry) + return -EFAULT; + + npc_dentry =3D debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc, np= c_priv, + &npc_vidx2idx_map_fops); + if (!npc_dentry) + return -EFAULT; + + npc_dentry =3D debugfs_create_file("idx2vidx", 0444, rvu->rvu_dbg.npc, np= c_priv, + &npc_idx2vidx_map_fops); + if (!npc_dentry) + return -EFAULT; + + npc_dentry =3D debugfs_create_file("defrag", 0444, rvu->rvu_dbg.npc, npc_= priv, + &npc_defrag_fops); + if (!npc_dentry) + return -EFAULT; + return 0; } =20 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/driv= ers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c index 407f360feaf5..5b62550f73d0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c @@ -23,6 +23,7 @@ =20 #include "cn20k/reg.h" #include "cn20k/debugfs.h" +#include "cn20k/npc.h" =20 #define DEBUGFS_DIR_NAME "octeontx2" =20 @@ -3197,7 +3198,9 @@ static void rvu_print_npc_mcam_info(struct seq_file *= s, static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsu= ed) { struct rvu *rvu =3D filp->private; + int x4_free, x2_free, sb_free; int pf, vf, numvfs, blkaddr; + struct npc_priv_t *npc_priv; struct npc_mcam *mcam; u16 pcifunc, counters; u64 cfg; @@ -3211,16 +3214,30 @@ static int rvu_dbg_npc_mcam_info_display(struct seq= _file *filp, void *unsued) =20 seq_puts(filp, "\nNPC MCAM info:\n"); /* MCAM keywidth on receive and transmit sides */ - cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX)); - cfg =3D (cfg >> 32) & 0x07; - seq_printf(filp, "\t\t RX keywidth \t: %s\n", (cfg =3D=3D NPC_MCAM_KEY_X1= ) ? - "112bits" : ((cfg =3D=3D NPC_MCAM_KEY_X2) ? - "224bits" : "448bits")); - cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX)); - cfg =3D (cfg >> 32) & 0x07; - seq_printf(filp, "\t\t TX keywidth \t: %s\n", (cfg =3D=3D NPC_MCAM_KEY_X1= ) ? - "112bits" : ((cfg =3D=3D NPC_MCAM_KEY_X2) ? - "224bits" : "448bits")); + if (is_cn20k(rvu->pdev)) { + npc_priv =3D npc_priv_get(); + seq_printf(filp, "\t\t RX keywidth \t: %s\n", + (npc_priv->kw =3D=3D NPC_MCAM_KEY_X1) ? + "256bits" : "512bits"); + + npc_cn20k_subbank_calc_free(rvu, &x2_free, &x4_free, &sb_free); + seq_printf(filp, "\t\t free x4 slots\t: %d\n", x4_free); + + seq_printf(filp, "\t\t free x2 slots\t: %d\n", x2_free); + + seq_printf(filp, "\t\t free subbanks\t: %d\n", sb_free); + } else { + cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX)); + cfg =3D (cfg >> 32) & 0x07; + seq_printf(filp, "\t\t RX keywidth \t: %s\n", (cfg =3D=3D NPC_MCAM_KEY_X= 1) ? + "112bits" : ((cfg =3D=3D NPC_MCAM_KEY_X2) ? + "224bits" : "448bits")); + cfg =3D rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX)); + cfg =3D (cfg >> 32) & 0x07; + seq_printf(filp, "\t\t TX keywidth \t: %s\n", (cfg =3D=3D NPC_MCAM_KEY_X= 1) ? + "112bits" : ((cfg =3D=3D NPC_MCAM_KEY_X2) ? + "224bits" : "448bits")); + } =20 mutex_lock(&mcam->lock); /* MCAM entries */ 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 57c50790e18b..2d569236882f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -1572,6 +1572,7 @@ static int npc_install_flow(struct rvu *rvu, int blka= ddr, u16 target, =20 rule->chan &=3D rule->chan_mask; rule->lxmb =3D dummy.lxmb; + rule->hw_prio =3D req->hw_prio; if (is_npc_intf_tx(req->intf)) rule->intf =3D pfvf->nix_tx_intf; else --=20 2.43.0 From nobody Wed Jan 7 22:50:11 2026 Received: from mx0a-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 5AAF331A551; Mon, 5 Jan 2026 02:34:15 +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=1767580457; cv=none; b=LQOuOLb6xu0gn2jxarLxhoGY7bhrnhmzj5v5WlI1z373DxhwaVesFq9FR2DiQ3Cnq5TVhII5b1x0E63wOO+mJvS6s91w7b/lqvD1nE31HNERpBSmw+1BOX2b7eVWoOAwcxs9Vv8mKmMkRex7kmrqZgSRloFR0aXd0ZywXOHgp14= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767580457; c=relaxed/simple; bh=LpGdPJBskJ6Q3CbsHoSrDdMT7DJ0E3S8wMzaOslxSZM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MzBrkIiyxObnOFpNlpH7gAU1PmnTEkvs1RGf/G/bsIq9NQBnhTn5hxqVuWrpgDZBAE3ZI95dEjEpu0Zp81j8IkiH5cYrtbprT2+K/t5buQYXFCELkOQBxhSiHnKpr6O1Dh5cXfpD02ya/ElZSaNTsfB4LTJIDBNDjM6IjeWn7qw= 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=Gqua7Yba; 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="Gqua7Yba" Received: from pps.filterd (m0431384.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 604MAiek2569178; Sun, 4 Jan 2026 18:34:06 -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=k y8irWPRPlGwPiMLwlPsx6gYXJBA1tAI4K+thTjYd7U=; b=Gqua7YbacaODEa4Qf IeMNECP7XSyQRQO9w7+ECOQx8nEHUTkLVczEMXO4XjadZyY/X3I+dI33Qmi0ffBb 3c57GywKcYui1OaP1l6LEYOi2H5lr1Tc8Q7g+FS6WAD6D5srNb2934Xka9B4StYK CwSqYGflPprWPxfg7hVPKz7Oi4gw238o+gHBkvG6hkR0phtfU1fABUzgpjm64Qbi akwFJf820Pg2Mr2p7kwtCP9YNoUQlHiK8GvD2hR74ZG66GajPhg0j4xDE3GwhUfw /g9EchmMMjjNu3pRyQNv8GPECIBGB9bQNmJ/ZEtJtziXYOy99aAYP3T1dQwq+U65 IUpVQ== Received: from dc6wp-exch02.marvell.com ([4.21.29.225]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 4bfr8bgtt1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 04 Jan 2026 18:34:06 -0800 (PST) Received: from DC6WP-EXCH02.marvell.com (10.76.176.209) by DC6WP-EXCH02.marvell.com (10.76.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:05 -0800 Received: from maili.marvell.com (10.69.176.80) by DC6WP-EXCH02.marvell.com (10.76.176.209) with Microsoft SMTP Server id 15.2.1544.25 via Frontend Transport; Sun, 4 Jan 2026 18:34:05 -0800 Received: from rkannoth-OptiPlex-7090.. (unknown [10.28.36.165]) by maili.marvell.com (Postfix) with ESMTP id 61F573F7094; Sun, 4 Jan 2026 18:34:02 -0800 (PST) From: Ratheesh Kannoth To: , CC: , , , , , , , Ratheesh Kannoth Subject: [PATCH net-next 13/13] octeontx-af: npc: Use common structures Date: Mon, 5 Jan 2026 08:02:54 +0530 Message-ID: <20260105023254.1426488-14-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: RgZiJdSboktF0RfyZmrsDfgarP0CiekT X-Proofpoint-GUID: RgZiJdSboktF0RfyZmrsDfgarP0CiekT X-Authority-Analysis: v=2.4 cv=P/I3RyAu c=1 sm=1 tr=0 ts=695b231e cx=c_pps a=gIfcoYsirJbf48DBMSPrZA==:117 a=gIfcoYsirJbf48DBMSPrZA==:17 a=vUbySO9Y5rIA:10 a=VkNPw1HP01LnGYTKEx00:22 a=M5GUcnROAAAA:8 a=bNx57pydN-Y4TXDtlhsA:9 a=OBjm3rFKGHvpk9ecZwUJ:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMTA1MDAyMSBTYWx0ZWRfX6YOSh/e8Lvuw LKKGoxW2R8HcTBI6UG7i6IFL2/uyfLJRqZMA13QU+ZDUG8nHrhpgJ5MuQyXiSOGbeotZh4NnQao vJWuikrXmiytgls/qUQhP3O0ku6bKfbGqjW6Vvw2EXJMNYmjdpF5DjUeqJPAtf9dxcMyNVDaO41 K7CBTR7Hwb8YWTWCQqq151PkjEvqk7sYlsRTaoDen3UeXU9/TmE+wb1P35trsNysTD1ta1DgEz9 54J6pEpdaAGcE/3IU6g25S5a1LcL6kbkl8EF1FE5+aGc3Vh8FQvg7wUhLNAKaUjfN03lhegCzWv c39IhdmVdFz1Ud+oCzB3qeanR15E5qXD3qRtYIvK6IEtuQuY8wh5EypjQsSG72Ck76+09sh085M OjuxBcVbHAPOX5NOZ2Q46tuyzzYo9+csm2VREL05tAeU8eZgoAwOLeAsItf16taUd0b6BUynEEi 87C9sWBOtDDnrCuhr0g== 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" CN20K and legacy silicon differ in the size of key words used in NPC MCAM. However, SoC-specific structures are not required for low-level functions. Remove the SoC-specific structures and rename the macros to improve readability. Signed-off-by: Ratheesh Kannoth --- .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 11 ++++--- .../net/ethernet/marvell/octeontx2/af/mbox.h | 18 +++++++---- .../net/ethernet/marvell/octeontx2/af/rvu.h | 2 +- .../marvell/octeontx2/af/rvu_npc_fs.c | 31 ++++++++----------- 4 files changed, 32 insertions(+), 30 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 4c154cccbba1..593e319ae13e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c @@ -3903,10 +3903,10 @@ int rvu_mbox_handler_npc_get_num_kws(struct rvu *rv= u, struct npc_get_num_kws_req *req, struct npc_get_num_kws_rsp *rsp) { + u64 kw_mask[NPC_KWS_IN_KEY_SZ_MAX] =3D { 0 }; + u64 kw[NPC_KWS_IN_KEY_SZ_MAX] =3D { 0 }; struct rvu_npc_mcam_rule dummy =3D { 0 }; - struct cn20k_mcam_entry cn20k_entry =3D { 0 }; struct mcam_entry_mdata mdata =3D { }; - struct mcam_entry entry =3D { 0 }; struct npc_install_flow_req *fl; int i, cnt =3D 0, blkaddr; =20 @@ -3923,7 +3923,8 @@ int rvu_mbox_handler_npc_get_num_kws(struct rvu *rvu, return NPC_MCAM_INVALID_REQ; } =20 - npc_populate_mcam_mdata(rvu, &mdata, &cn20k_entry, &entry); + mdata.kw =3D kw; + mdata.kw_mask =3D kw_mask; =20 npc_update_flow(rvu, &mdata, fl->features, &fl->packet, &fl->mask, &dummy, fl->intf, blkaddr); @@ -3931,8 +3932,8 @@ int rvu_mbox_handler_npc_get_num_kws(struct rvu *rvu, /* Find the most significant word valid. Traverse from * MSB to LSB, check if cam0 or cam1 is set */ - for (i =3D NPC_CN20K_MAX_KWS_IN_KEY - 1; i >=3D 0; i--) { - if (cn20k_entry.kw[i] || cn20k_entry.kw_mask[i]) { + for (i =3D NPC_KWS_IN_KEY_SZ_MAX - 1; i >=3D 0; i--) { + if (kw[i] || kw_mask[i]) { cnt =3D i + 1; break; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net= /ethernet/marvell/octeontx2/af/mbox.h index 6f26f7393709..d65aaf4fae8b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1592,18 +1592,24 @@ struct mcam_entry_mdata { u8 max_kw; }; =20 +enum npc_kws_in_key_sz { + NPC_KWS_IN_KEY_SZ_7 =3D 7, + NPC_KWS_IN_KEY_SZ_8 =3D 8, + NPC_KWS_IN_KEY_SZ_9 =3D 9, + NPC_KWS_IN_KEY_SZ_10 =3D 10, + NPC_KWS_IN_KEY_SZ_MAX, +}; + struct mcam_entry { -#define NPC_MAX_KWS_IN_KEY 7 /* Number of keywords in max keywidth */ - u64 kw[NPC_MAX_KWS_IN_KEY]; - u64 kw_mask[NPC_MAX_KWS_IN_KEY]; + u64 kw[NPC_KWS_IN_KEY_SZ_7]; + u64 kw_mask[NPC_KWS_IN_KEY_SZ_7]; u64 action; u64 vtag_action; }; =20 struct cn20k_mcam_entry { -#define NPC_CN20K_MAX_KWS_IN_KEY 8 /* Number of keywords in max keywidth */ - u64 kw[NPC_CN20K_MAX_KWS_IN_KEY]; - u64 kw_mask[NPC_CN20K_MAX_KWS_IN_KEY]; + u64 kw[NPC_KWS_IN_KEY_SZ_8]; + u64 kw_mask[NPC_KWS_IN_KEY_SZ_8]; u64 action; u64 vtag_action; u64 action2; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/= ethernet/marvell/octeontx2/af/rvu.h index f811d6b5c545..a466181cf908 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -197,7 +197,7 @@ struct npc_key_field { /* Masks where all set bits indicate position * of a field in the key */ - u64 kw_mask[NPC_CN20K_MAX_KWS_IN_KEY]; + u64 kw_mask[NPC_KWS_IN_KEY_SZ_MAX]; /* Number of words in the key a field spans. If a field is * of 16 bytes and key offset is 4 then the field will use * 4 bytes in KW0, 8 bytes in KW1 and 4 bytes in KW2 and 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 2d569236882f..229f860d176d 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -254,7 +254,7 @@ static bool npc_check_overlap(struct rvu *rvu, int blka= ddr, * other field bits. */ if (npc_check_overlap_fields(dummy, input, - NPC_MAX_KWS_IN_KEY)) + NPC_KWS_IN_KEY_SZ_7)) return true; } } @@ -285,7 +285,7 @@ static bool npc_check_overlap(struct rvu *rvu, int blka= ddr, start_kwi, offset, intf); /* check any input field bits falls in any other field bits */ if (npc_check_overlap_fields(dummy, input, - NPC_CN20K_MAX_KWS_IN_KEY)) + NPC_KWS_IN_KEY_SZ_8)) return true; } } @@ -456,9 +456,9 @@ static void npc_handle_multi_layer_fields(struct rvu *r= vu, int blkaddr, u8 intf) u8 start_lid; =20 if (is_cn20k(rvu->pdev)) - max_kw =3D NPC_CN20K_MAX_KWS_IN_KEY; + max_kw =3D NPC_KWS_IN_KEY_SZ_8; else - max_kw =3D NPC_MAX_KWS_IN_KEY; + max_kw =3D NPC_KWS_IN_KEY_SZ_7; =20 key_fields =3D mcam->rx_key_fields; features =3D &mcam->rx_features; @@ -901,12 +901,12 @@ void npc_update_entry(struct rvu *rvu, enum key_field= s type, struct mcam_entry_mdata *mdata, u64 val_lo, u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf) { - struct cn20k_mcam_entry cn20k_dummy =3D { {0} }; + u64 kw_mask[NPC_KWS_IN_KEY_SZ_MAX] =3D { 0 }; + u64 kw[NPC_KWS_IN_KEY_SZ_MAX] =3D { 0 }; struct npc_mcam *mcam =3D &rvu->hw->mcam; - struct mcam_entry dummy =3D { {0} }; - u64 *kw, *kw_mask, *val, *mask; struct npc_key_field *field; u64 kw1, kw2, kw3; + u64 *val, *mask; int i, max_kw; u8 shift; =20 @@ -917,15 +917,10 @@ void npc_update_entry(struct rvu *rvu, enum key_field= s type, if (!field->nr_kws) return; =20 - if (is_cn20k(rvu->pdev)) { - max_kw =3D NPC_CN20K_MAX_KWS_IN_KEY; - kw =3D cn20k_dummy.kw; - kw_mask =3D cn20k_dummy.kw_mask; - } else { - max_kw =3D NPC_MAX_KWS_IN_KEY; - kw =3D dummy.kw; - kw_mask =3D dummy.kw_mask; - } + if (is_cn20k(rvu->pdev)) + max_kw =3D NPC_KWS_IN_KEY_SZ_8; + else + max_kw =3D NPC_KWS_IN_KEY_SZ_7; =20 for (i =3D 0; i < max_kw; i++) { if (!field->kw_mask[i]) @@ -1304,14 +1299,14 @@ npc_populate_mcam_mdata(struct rvu *rvu, mdata->kw_mask =3D cn20k_entry->kw_mask; mdata->action =3D &cn20k_entry->action; mdata->vtag_action =3D &cn20k_entry->vtag_action; - mdata->max_kw =3D NPC_CN20K_MAX_KWS_IN_KEY; + mdata->max_kw =3D NPC_KWS_IN_KEY_SZ_8; return; } mdata->kw =3D entry->kw; mdata->kw_mask =3D entry->kw_mask; mdata->action =3D &entry->action; mdata->vtag_action =3D &entry->vtag_action; - mdata->max_kw =3D NPC_MAX_KWS_IN_KEY; + mdata->max_kw =3D NPC_KWS_IN_KEY_SZ_7; } =20 static int npc_update_rx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, --=20 2.43.0