From nobody Fri Jan 9 00:45:24 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