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 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