From nobody Fri Jan 9 00:40:22 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