1f0a1913fSSubbaraya Sundeep // SPDX-License-Identifier: GPL-2.0 2cb0e3ec4SSunil Goutham /* Marvell RVU Ethernet driver 3f0a1913fSSubbaraya Sundeep * 4f0a1913fSSubbaraya Sundeep * Copyright (C) 2020 Marvell. 5cb0e3ec4SSunil Goutham * 6f0a1913fSSubbaraya Sundeep */ 7f0a1913fSSubbaraya Sundeep 8f0a1913fSSubbaraya Sundeep #include <net/ipv6.h> 9cc65fcabSSunil Goutham #include <linux/sort.h> 10f0a1913fSSubbaraya Sundeep 11f0a1913fSSubbaraya Sundeep #include "otx2_common.h" 12f0a1913fSSubbaraya Sundeep 13f0a1913fSSubbaraya Sundeep #define OTX2_DEFAULT_ACTION 0x1 14f0a1913fSSubbaraya Sundeep 152da48943SSunil Goutham static int otx2_mcam_entry_init(struct otx2_nic *pfvf); 162da48943SSunil Goutham 17f0a1913fSSubbaraya Sundeep struct otx2_flow { 18f0a1913fSSubbaraya Sundeep struct ethtool_rx_flow_spec flow_spec; 19f0a1913fSSubbaraya Sundeep struct list_head list; 20f0a1913fSSubbaraya Sundeep u32 location; 21*fa5e0ccbSRatheesh Kannoth u32 entry; 22f0a1913fSSubbaraya Sundeep bool is_vf; 2381a43620SGeetha sowjanya u8 rss_ctx_id; 248e675581SHariprasad Kelam #define DMAC_FILTER_RULE BIT(0) 258e675581SHariprasad Kelam #define PFC_FLOWCTRL_RULE BIT(1) 268e675581SHariprasad Kelam u16 rule_type; 27f0a1913fSSubbaraya Sundeep int vf; 2879d2be38SHariprasad Kelam }; 2979d2be38SHariprasad Kelam 3079d2be38SHariprasad Kelam enum dmac_req { 3179d2be38SHariprasad Kelam DMAC_ADDR_UPDATE, 3279d2be38SHariprasad Kelam DMAC_ADDR_DEL 33f0a1913fSSubbaraya Sundeep }; 34f0a1913fSSubbaraya Sundeep 359917060fSSunil Goutham static void otx2_clear_ntuple_flow_info(struct otx2_nic *pfvf, struct otx2_flow_config *flow_cfg) 369917060fSSunil Goutham { 379917060fSSunil Goutham devm_kfree(pfvf->dev, flow_cfg->flow_ent); 389917060fSSunil Goutham flow_cfg->flow_ent = NULL; 392e2a8126SSunil Goutham flow_cfg->max_flows = 0; 409917060fSSunil Goutham } 419917060fSSunil Goutham 429917060fSSunil Goutham static int otx2_free_ntuple_mcam_entries(struct otx2_nic *pfvf) 439917060fSSunil Goutham { 449917060fSSunil Goutham struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 459917060fSSunil Goutham struct npc_mcam_free_entry_req *req; 469917060fSSunil Goutham int ent, err; 479917060fSSunil Goutham 482e2a8126SSunil Goutham if (!flow_cfg->max_flows) 499917060fSSunil Goutham return 0; 509917060fSSunil Goutham 519917060fSSunil Goutham mutex_lock(&pfvf->mbox.lock); 522e2a8126SSunil Goutham for (ent = 0; ent < flow_cfg->max_flows; ent++) { 539917060fSSunil Goutham req = otx2_mbox_alloc_msg_npc_mcam_free_entry(&pfvf->mbox); 549917060fSSunil Goutham if (!req) 559917060fSSunil Goutham break; 569917060fSSunil Goutham 579917060fSSunil Goutham req->entry = flow_cfg->flow_ent[ent]; 589917060fSSunil Goutham 599917060fSSunil Goutham /* Send message to AF to free MCAM entries */ 609917060fSSunil Goutham err = otx2_sync_mbox_msg(&pfvf->mbox); 619917060fSSunil Goutham if (err) 629917060fSSunil Goutham break; 639917060fSSunil Goutham } 649917060fSSunil Goutham mutex_unlock(&pfvf->mbox.lock); 659917060fSSunil Goutham otx2_clear_ntuple_flow_info(pfvf, flow_cfg); 669917060fSSunil Goutham return 0; 679917060fSSunil Goutham } 689917060fSSunil Goutham 69cc65fcabSSunil Goutham static int mcam_entry_cmp(const void *a, const void *b) 70cc65fcabSSunil Goutham { 71cc65fcabSSunil Goutham return *(u16 *)a - *(u16 *)b; 72cc65fcabSSunil Goutham } 73cc65fcabSSunil Goutham 742da48943SSunil Goutham int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count) 759917060fSSunil Goutham { 769917060fSSunil Goutham struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 779917060fSSunil Goutham struct npc_mcam_alloc_entry_req *req; 789917060fSSunil Goutham struct npc_mcam_alloc_entry_rsp *rsp; 799917060fSSunil Goutham int ent, allocated = 0; 809917060fSSunil Goutham 819917060fSSunil Goutham /* Free current ones and allocate new ones with requested count */ 829917060fSSunil Goutham otx2_free_ntuple_mcam_entries(pfvf); 839917060fSSunil Goutham 849917060fSSunil Goutham if (!count) 859917060fSSunil Goutham return 0; 869917060fSSunil Goutham 879917060fSSunil Goutham flow_cfg->flow_ent = devm_kmalloc_array(pfvf->dev, count, 889917060fSSunil Goutham sizeof(u16), GFP_KERNEL); 892da48943SSunil Goutham if (!flow_cfg->flow_ent) { 902da48943SSunil Goutham netdev_err(pfvf->netdev, 912da48943SSunil Goutham "%s: Unable to allocate memory for flow entries\n", 922da48943SSunil Goutham __func__); 939917060fSSunil Goutham return -ENOMEM; 942da48943SSunil Goutham } 959917060fSSunil Goutham 969917060fSSunil Goutham mutex_lock(&pfvf->mbox.lock); 979917060fSSunil Goutham 989917060fSSunil Goutham /* In a single request a max of NPC_MAX_NONCONTIG_ENTRIES MCAM entries 999917060fSSunil Goutham * can only be allocated. 1009917060fSSunil Goutham */ 1019917060fSSunil Goutham while (allocated < count) { 1029917060fSSunil Goutham req = otx2_mbox_alloc_msg_npc_mcam_alloc_entry(&pfvf->mbox); 1039917060fSSunil Goutham if (!req) 1049917060fSSunil Goutham goto exit; 1059917060fSSunil Goutham 1069917060fSSunil Goutham req->contig = false; 1079917060fSSunil Goutham req->count = (count - allocated) > NPC_MAX_NONCONTIG_ENTRIES ? 1089917060fSSunil Goutham NPC_MAX_NONCONTIG_ENTRIES : count - allocated; 1093cffaed2SRakesh Babu 1103cffaed2SRakesh Babu /* Allocate higher priority entries for PFs, so that VF's entries 1113cffaed2SRakesh Babu * will be on top of PF. 1123cffaed2SRakesh Babu */ 1133cffaed2SRakesh Babu if (!is_otx2_vf(pfvf->pcifunc)) { 1149917060fSSunil Goutham req->priority = NPC_MCAM_HIGHER_PRIO; 1159917060fSSunil Goutham req->ref_entry = flow_cfg->def_ent[0]; 1163cffaed2SRakesh Babu } 1179917060fSSunil Goutham 1189917060fSSunil Goutham /* Send message to AF */ 1199917060fSSunil Goutham if (otx2_sync_mbox_msg(&pfvf->mbox)) 1209917060fSSunil Goutham goto exit; 1219917060fSSunil Goutham 1229917060fSSunil Goutham rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp 1239917060fSSunil Goutham (&pfvf->mbox.mbox, 0, &req->hdr); 1249917060fSSunil Goutham 1259917060fSSunil Goutham for (ent = 0; ent < rsp->count; ent++) 1269917060fSSunil Goutham flow_cfg->flow_ent[ent + allocated] = rsp->entry_list[ent]; 1279917060fSSunil Goutham 1289917060fSSunil Goutham allocated += rsp->count; 1299917060fSSunil Goutham 1309917060fSSunil Goutham /* If this request is not fulfilled, no need to send 1319917060fSSunil Goutham * further requests. 1329917060fSSunil Goutham */ 1339917060fSSunil Goutham if (rsp->count != req->count) 1349917060fSSunil Goutham break; 1359917060fSSunil Goutham } 1369917060fSSunil Goutham 137cc65fcabSSunil Goutham /* Multiple MCAM entry alloc requests could result in non-sequential 138cc65fcabSSunil Goutham * MCAM entries in the flow_ent[] array. Sort them in an ascending order, 139cc65fcabSSunil Goutham * otherwise user installed ntuple filter index and MCAM entry index will 140cc65fcabSSunil Goutham * not be in sync. 141cc65fcabSSunil Goutham */ 142cc65fcabSSunil Goutham if (allocated) 143cc65fcabSSunil Goutham sort(&flow_cfg->flow_ent[0], allocated, 144cc65fcabSSunil Goutham sizeof(flow_cfg->flow_ent[0]), mcam_entry_cmp, NULL); 145cc65fcabSSunil Goutham 1469917060fSSunil Goutham exit: 1479917060fSSunil Goutham mutex_unlock(&pfvf->mbox.lock); 1489917060fSSunil Goutham 1492e2a8126SSunil Goutham flow_cfg->max_flows = allocated; 1509917060fSSunil Goutham 1512da48943SSunil Goutham if (allocated) { 1523cffaed2SRakesh Babu pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC; 1533cffaed2SRakesh Babu pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT; 1542da48943SSunil Goutham } 1553cffaed2SRakesh Babu 1569917060fSSunil Goutham if (allocated != count) 1579917060fSSunil Goutham netdev_info(pfvf->netdev, 1583cffaed2SRakesh Babu "Unable to allocate %d MCAM entries, got only %d\n", 1599917060fSSunil Goutham count, allocated); 1609917060fSSunil Goutham return allocated; 1619917060fSSunil Goutham } 1622da48943SSunil Goutham EXPORT_SYMBOL(otx2_alloc_mcam_entries); 1639917060fSSunil Goutham 1642da48943SSunil Goutham static int otx2_mcam_entry_init(struct otx2_nic *pfvf) 165f0a1913fSSubbaraya Sundeep { 166f0a1913fSSubbaraya Sundeep struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 167f0a1913fSSubbaraya Sundeep struct npc_mcam_alloc_entry_req *req; 168f0a1913fSSubbaraya Sundeep struct npc_mcam_alloc_entry_rsp *rsp; 169f0c2982aSNaveen Mamindlapalli int vf_vlan_max_flows; 1709917060fSSunil Goutham int ent, count; 1719917060fSSunil Goutham 1729917060fSSunil Goutham vf_vlan_max_flows = pfvf->total_vfs * OTX2_PER_VF_VLAN_FLOWS; 1739917060fSSunil Goutham count = OTX2_MAX_UNICAST_FLOWS + 1749917060fSSunil Goutham OTX2_MAX_VLAN_FLOWS + vf_vlan_max_flows; 1759917060fSSunil Goutham 1769917060fSSunil Goutham flow_cfg->def_ent = devm_kmalloc_array(pfvf->dev, count, 1779917060fSSunil Goutham sizeof(u16), GFP_KERNEL); 1789917060fSSunil Goutham if (!flow_cfg->def_ent) 1799917060fSSunil Goutham return -ENOMEM; 180f0a1913fSSubbaraya Sundeep 181f0a1913fSSubbaraya Sundeep mutex_lock(&pfvf->mbox.lock); 182f0a1913fSSubbaraya Sundeep 183f0a1913fSSubbaraya Sundeep req = otx2_mbox_alloc_msg_npc_mcam_alloc_entry(&pfvf->mbox); 184f0a1913fSSubbaraya Sundeep if (!req) { 185f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 186f0a1913fSSubbaraya Sundeep return -ENOMEM; 187f0a1913fSSubbaraya Sundeep } 188f0a1913fSSubbaraya Sundeep 189f0a1913fSSubbaraya Sundeep req->contig = false; 1909917060fSSunil Goutham req->count = count; 191f0a1913fSSubbaraya Sundeep 192f0a1913fSSubbaraya Sundeep /* Send message to AF */ 193f0a1913fSSubbaraya Sundeep if (otx2_sync_mbox_msg(&pfvf->mbox)) { 194f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 195f0a1913fSSubbaraya Sundeep return -EINVAL; 196f0a1913fSSubbaraya Sundeep } 197f0a1913fSSubbaraya Sundeep 198f0a1913fSSubbaraya Sundeep rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp 199f0a1913fSSubbaraya Sundeep (&pfvf->mbox.mbox, 0, &req->hdr); 200f0a1913fSSubbaraya Sundeep 20163ee5157SHariprasad Kelam if (rsp->count != req->count) { 202f0a1913fSSubbaraya Sundeep netdev_info(pfvf->netdev, 2039917060fSSunil Goutham "Unable to allocate MCAM entries for ucast, vlan and vf_vlan\n"); 2049917060fSSunil Goutham mutex_unlock(&pfvf->mbox.lock); 2059917060fSSunil Goutham devm_kfree(pfvf->dev, flow_cfg->def_ent); 2069917060fSSunil Goutham return 0; 2079917060fSSunil Goutham } 2089917060fSSunil Goutham 2099917060fSSunil Goutham for (ent = 0; ent < rsp->count; ent++) 2109917060fSSunil Goutham flow_cfg->def_ent[ent] = rsp->entry_list[ent]; 2119917060fSSunil Goutham 212f0c2982aSNaveen Mamindlapalli flow_cfg->vf_vlan_offset = 0; 2139917060fSSunil Goutham flow_cfg->unicast_offset = vf_vlan_max_flows; 214fd9d7859SHariprasad Kelam flow_cfg->rx_vlan_offset = flow_cfg->unicast_offset + 215fd9d7859SHariprasad Kelam OTX2_MAX_UNICAST_FLOWS; 21663ee5157SHariprasad Kelam pfvf->flags |= OTX2_FLAG_UCAST_FLTR_SUPPORT; 217fd9d7859SHariprasad Kelam pfvf->flags |= OTX2_FLAG_RX_VLAN_SUPPORT; 218f0c2982aSNaveen Mamindlapalli pfvf->flags |= OTX2_FLAG_VF_VLAN_SUPPORT; 219f0a1913fSSubbaraya Sundeep 220f0a1913fSSubbaraya Sundeep pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC; 221f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 222f0a1913fSSubbaraya Sundeep 2239917060fSSunil Goutham /* Allocate entries for Ntuple filters */ 2242da48943SSunil Goutham count = otx2_alloc_mcam_entries(pfvf, OTX2_DEFAULT_FLOWCOUNT); 2259917060fSSunil Goutham if (count <= 0) { 2269917060fSSunil Goutham otx2_clear_ntuple_flow_info(pfvf, flow_cfg); 2279917060fSSunil Goutham return 0; 2289917060fSSunil Goutham } 2299917060fSSunil Goutham 2309917060fSSunil Goutham pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT; 2319917060fSSunil Goutham 232f0a1913fSSubbaraya Sundeep return 0; 233f0a1913fSSubbaraya Sundeep } 234f0a1913fSSubbaraya Sundeep 235*fa5e0ccbSRatheesh Kannoth /* TODO : revisit on size */ 236*fa5e0ccbSRatheesh Kannoth #define OTX2_DMAC_FLTR_BITMAP_SZ (4 * 2048 + 32) 237*fa5e0ccbSRatheesh Kannoth 2383cffaed2SRakesh Babu int otx2vf_mcam_flow_init(struct otx2_nic *pfvf) 2393cffaed2SRakesh Babu { 2403cffaed2SRakesh Babu struct otx2_flow_config *flow_cfg; 2413cffaed2SRakesh Babu 2423cffaed2SRakesh Babu pfvf->flow_cfg = devm_kzalloc(pfvf->dev, 2433cffaed2SRakesh Babu sizeof(struct otx2_flow_config), 2443cffaed2SRakesh Babu GFP_KERNEL); 2453cffaed2SRakesh Babu if (!pfvf->flow_cfg) 2463cffaed2SRakesh Babu return -ENOMEM; 2473cffaed2SRakesh Babu 248*fa5e0ccbSRatheesh Kannoth pfvf->flow_cfg->dmacflt_bmap = devm_kcalloc(pfvf->dev, 249*fa5e0ccbSRatheesh Kannoth BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ), 250*fa5e0ccbSRatheesh Kannoth sizeof(long), GFP_KERNEL); 251*fa5e0ccbSRatheesh Kannoth if (!pfvf->flow_cfg->dmacflt_bmap) 252*fa5e0ccbSRatheesh Kannoth return -ENOMEM; 253*fa5e0ccbSRatheesh Kannoth 2543cffaed2SRakesh Babu flow_cfg = pfvf->flow_cfg; 2553cffaed2SRakesh Babu INIT_LIST_HEAD(&flow_cfg->flow_list); 2562e2a8126SSunil Goutham flow_cfg->max_flows = 0; 2573cffaed2SRakesh Babu 2583cffaed2SRakesh Babu return 0; 2593cffaed2SRakesh Babu } 2603cffaed2SRakesh Babu EXPORT_SYMBOL(otx2vf_mcam_flow_init); 2613cffaed2SRakesh Babu 262f0a1913fSSubbaraya Sundeep int otx2_mcam_flow_init(struct otx2_nic *pf) 263f0a1913fSSubbaraya Sundeep { 264f0a1913fSSubbaraya Sundeep int err; 265f0a1913fSSubbaraya Sundeep 266f0a1913fSSubbaraya Sundeep pf->flow_cfg = devm_kzalloc(pf->dev, sizeof(struct otx2_flow_config), 267f0a1913fSSubbaraya Sundeep GFP_KERNEL); 268f0a1913fSSubbaraya Sundeep if (!pf->flow_cfg) 269f0a1913fSSubbaraya Sundeep return -ENOMEM; 270f0a1913fSSubbaraya Sundeep 271*fa5e0ccbSRatheesh Kannoth pf->flow_cfg->dmacflt_bmap = devm_kcalloc(pf->dev, 272*fa5e0ccbSRatheesh Kannoth BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ), 273*fa5e0ccbSRatheesh Kannoth sizeof(long), GFP_KERNEL); 274*fa5e0ccbSRatheesh Kannoth if (!pf->flow_cfg->dmacflt_bmap) 275*fa5e0ccbSRatheesh Kannoth return -ENOMEM; 276*fa5e0ccbSRatheesh Kannoth 277f0a1913fSSubbaraya Sundeep INIT_LIST_HEAD(&pf->flow_cfg->flow_list); 278f0a1913fSSubbaraya Sundeep 2792da48943SSunil Goutham /* Allocate bare minimum number of MCAM entries needed for 2802da48943SSunil Goutham * unicast and ntuple filters. 2812da48943SSunil Goutham */ 2822da48943SSunil Goutham err = otx2_mcam_entry_init(pf); 283f0a1913fSSubbaraya Sundeep if (err) 284f0a1913fSSubbaraya Sundeep return err; 285f0a1913fSSubbaraya Sundeep 2869917060fSSunil Goutham /* Check if MCAM entries are allocate or not */ 2879917060fSSunil Goutham if (!(pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT)) 2889917060fSSunil Goutham return 0; 2899917060fSSunil Goutham 29063ee5157SHariprasad Kelam pf->mac_table = devm_kzalloc(pf->dev, sizeof(struct otx2_mac_table) 29163ee5157SHariprasad Kelam * OTX2_MAX_UNICAST_FLOWS, GFP_KERNEL); 29263ee5157SHariprasad Kelam if (!pf->mac_table) 29363ee5157SHariprasad Kelam return -ENOMEM; 29463ee5157SHariprasad Kelam 29579d2be38SHariprasad Kelam otx2_dmacflt_get_max_cnt(pf); 29679d2be38SHariprasad Kelam 29779d2be38SHariprasad Kelam /* DMAC filters are not allocated */ 29879d2be38SHariprasad Kelam if (!pf->flow_cfg->dmacflt_max_flows) 29979d2be38SHariprasad Kelam return 0; 30079d2be38SHariprasad Kelam 30179d2be38SHariprasad Kelam pf->flow_cfg->bmap_to_dmacindex = 302*fa5e0ccbSRatheesh Kannoth devm_kzalloc(pf->dev, sizeof(u32) * 30379d2be38SHariprasad Kelam pf->flow_cfg->dmacflt_max_flows, 30479d2be38SHariprasad Kelam GFP_KERNEL); 30579d2be38SHariprasad Kelam 30679d2be38SHariprasad Kelam if (!pf->flow_cfg->bmap_to_dmacindex) 30779d2be38SHariprasad Kelam return -ENOMEM; 30879d2be38SHariprasad Kelam 30979d2be38SHariprasad Kelam pf->flags |= OTX2_FLAG_DMACFLTR_SUPPORT; 31079d2be38SHariprasad Kelam 311f0a1913fSSubbaraya Sundeep return 0; 312f0a1913fSSubbaraya Sundeep } 313f0a1913fSSubbaraya Sundeep 314f0a1913fSSubbaraya Sundeep void otx2_mcam_flow_del(struct otx2_nic *pf) 315f0a1913fSSubbaraya Sundeep { 316f0a1913fSSubbaraya Sundeep otx2_destroy_mcam_flows(pf); 317f0a1913fSSubbaraya Sundeep } 3183cffaed2SRakesh Babu EXPORT_SYMBOL(otx2_mcam_flow_del); 319f0a1913fSSubbaraya Sundeep 32063ee5157SHariprasad Kelam /* On success adds mcam entry 32163ee5157SHariprasad Kelam * On failure enable promisous mode 32263ee5157SHariprasad Kelam */ 32363ee5157SHariprasad Kelam static int otx2_do_add_macfilter(struct otx2_nic *pf, const u8 *mac) 32463ee5157SHariprasad Kelam { 32563ee5157SHariprasad Kelam struct otx2_flow_config *flow_cfg = pf->flow_cfg; 32663ee5157SHariprasad Kelam struct npc_install_flow_req *req; 32763ee5157SHariprasad Kelam int err, i; 32863ee5157SHariprasad Kelam 32963ee5157SHariprasad Kelam if (!(pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT)) 33063ee5157SHariprasad Kelam return -ENOMEM; 33163ee5157SHariprasad Kelam 33263ee5157SHariprasad Kelam /* dont have free mcam entries or uc list is greater than alloted */ 33363ee5157SHariprasad Kelam if (netdev_uc_count(pf->netdev) > OTX2_MAX_UNICAST_FLOWS) 33463ee5157SHariprasad Kelam return -ENOMEM; 33563ee5157SHariprasad Kelam 33663ee5157SHariprasad Kelam mutex_lock(&pf->mbox.lock); 33763ee5157SHariprasad Kelam req = otx2_mbox_alloc_msg_npc_install_flow(&pf->mbox); 33863ee5157SHariprasad Kelam if (!req) { 33963ee5157SHariprasad Kelam mutex_unlock(&pf->mbox.lock); 34063ee5157SHariprasad Kelam return -ENOMEM; 34163ee5157SHariprasad Kelam } 34263ee5157SHariprasad Kelam 34363ee5157SHariprasad Kelam /* unicast offset starts with 32 0..31 for ntuple */ 34463ee5157SHariprasad Kelam for (i = 0; i < OTX2_MAX_UNICAST_FLOWS; i++) { 34563ee5157SHariprasad Kelam if (pf->mac_table[i].inuse) 34663ee5157SHariprasad Kelam continue; 34763ee5157SHariprasad Kelam ether_addr_copy(pf->mac_table[i].addr, mac); 34863ee5157SHariprasad Kelam pf->mac_table[i].inuse = true; 34963ee5157SHariprasad Kelam pf->mac_table[i].mcam_entry = 3509917060fSSunil Goutham flow_cfg->def_ent[i + flow_cfg->unicast_offset]; 35163ee5157SHariprasad Kelam req->entry = pf->mac_table[i].mcam_entry; 35263ee5157SHariprasad Kelam break; 35363ee5157SHariprasad Kelam } 35463ee5157SHariprasad Kelam 35563ee5157SHariprasad Kelam ether_addr_copy(req->packet.dmac, mac); 35663ee5157SHariprasad Kelam eth_broadcast_addr((u8 *)&req->mask.dmac); 35763ee5157SHariprasad Kelam req->features = BIT_ULL(NPC_DMAC); 35863ee5157SHariprasad Kelam req->channel = pf->hw.rx_chan_base; 35963ee5157SHariprasad Kelam req->intf = NIX_INTF_RX; 36063ee5157SHariprasad Kelam req->op = NIX_RX_ACTION_DEFAULT; 36163ee5157SHariprasad Kelam req->set_cntr = 1; 36263ee5157SHariprasad Kelam 36363ee5157SHariprasad Kelam err = otx2_sync_mbox_msg(&pf->mbox); 36463ee5157SHariprasad Kelam mutex_unlock(&pf->mbox.lock); 36563ee5157SHariprasad Kelam 36663ee5157SHariprasad Kelam return err; 36763ee5157SHariprasad Kelam } 36863ee5157SHariprasad Kelam 36963ee5157SHariprasad Kelam int otx2_add_macfilter(struct net_device *netdev, const u8 *mac) 37063ee5157SHariprasad Kelam { 37163ee5157SHariprasad Kelam struct otx2_nic *pf = netdev_priv(netdev); 37263ee5157SHariprasad Kelam 373*fa5e0ccbSRatheesh Kannoth if (!bitmap_empty(pf->flow_cfg->dmacflt_bmap, 37479d2be38SHariprasad Kelam pf->flow_cfg->dmacflt_max_flows)) 37579d2be38SHariprasad Kelam netdev_warn(netdev, 37679d2be38SHariprasad Kelam "Add %pM to CGX/RPM DMAC filters list as well\n", 37779d2be38SHariprasad Kelam mac); 37879d2be38SHariprasad Kelam 37963ee5157SHariprasad Kelam return otx2_do_add_macfilter(pf, mac); 38063ee5157SHariprasad Kelam } 38163ee5157SHariprasad Kelam 38263ee5157SHariprasad Kelam static bool otx2_get_mcamentry_for_mac(struct otx2_nic *pf, const u8 *mac, 38363ee5157SHariprasad Kelam int *mcam_entry) 38463ee5157SHariprasad Kelam { 38563ee5157SHariprasad Kelam int i; 38663ee5157SHariprasad Kelam 38763ee5157SHariprasad Kelam for (i = 0; i < OTX2_MAX_UNICAST_FLOWS; i++) { 38863ee5157SHariprasad Kelam if (!pf->mac_table[i].inuse) 38963ee5157SHariprasad Kelam continue; 39063ee5157SHariprasad Kelam 39163ee5157SHariprasad Kelam if (ether_addr_equal(pf->mac_table[i].addr, mac)) { 39263ee5157SHariprasad Kelam *mcam_entry = pf->mac_table[i].mcam_entry; 39363ee5157SHariprasad Kelam pf->mac_table[i].inuse = false; 39463ee5157SHariprasad Kelam return true; 39563ee5157SHariprasad Kelam } 39663ee5157SHariprasad Kelam } 39763ee5157SHariprasad Kelam return false; 39863ee5157SHariprasad Kelam } 39963ee5157SHariprasad Kelam 40063ee5157SHariprasad Kelam int otx2_del_macfilter(struct net_device *netdev, const u8 *mac) 40163ee5157SHariprasad Kelam { 40263ee5157SHariprasad Kelam struct otx2_nic *pf = netdev_priv(netdev); 40363ee5157SHariprasad Kelam struct npc_delete_flow_req *req; 40463ee5157SHariprasad Kelam int err, mcam_entry; 40563ee5157SHariprasad Kelam 40663ee5157SHariprasad Kelam /* check does mcam entry exists for given mac */ 40763ee5157SHariprasad Kelam if (!otx2_get_mcamentry_for_mac(pf, mac, &mcam_entry)) 40863ee5157SHariprasad Kelam return 0; 40963ee5157SHariprasad Kelam 41063ee5157SHariprasad Kelam mutex_lock(&pf->mbox.lock); 41163ee5157SHariprasad Kelam req = otx2_mbox_alloc_msg_npc_delete_flow(&pf->mbox); 41263ee5157SHariprasad Kelam if (!req) { 41363ee5157SHariprasad Kelam mutex_unlock(&pf->mbox.lock); 41463ee5157SHariprasad Kelam return -ENOMEM; 41563ee5157SHariprasad Kelam } 41663ee5157SHariprasad Kelam req->entry = mcam_entry; 41763ee5157SHariprasad Kelam /* Send message to AF */ 41863ee5157SHariprasad Kelam err = otx2_sync_mbox_msg(&pf->mbox); 41963ee5157SHariprasad Kelam mutex_unlock(&pf->mbox.lock); 42063ee5157SHariprasad Kelam 42163ee5157SHariprasad Kelam return err; 42263ee5157SHariprasad Kelam } 42363ee5157SHariprasad Kelam 424f0a1913fSSubbaraya Sundeep static struct otx2_flow *otx2_find_flow(struct otx2_nic *pfvf, u32 location) 425f0a1913fSSubbaraya Sundeep { 426f0a1913fSSubbaraya Sundeep struct otx2_flow *iter; 427f0a1913fSSubbaraya Sundeep 428f0a1913fSSubbaraya Sundeep list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) { 429f0a1913fSSubbaraya Sundeep if (iter->location == location) 430f0a1913fSSubbaraya Sundeep return iter; 431f0a1913fSSubbaraya Sundeep } 432f0a1913fSSubbaraya Sundeep 433f0a1913fSSubbaraya Sundeep return NULL; 434f0a1913fSSubbaraya Sundeep } 435f0a1913fSSubbaraya Sundeep 436f0a1913fSSubbaraya Sundeep static void otx2_add_flow_to_list(struct otx2_nic *pfvf, struct otx2_flow *flow) 437f0a1913fSSubbaraya Sundeep { 438f0a1913fSSubbaraya Sundeep struct list_head *head = &pfvf->flow_cfg->flow_list; 439f0a1913fSSubbaraya Sundeep struct otx2_flow *iter; 440f0a1913fSSubbaraya Sundeep 441f0a1913fSSubbaraya Sundeep list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) { 442f0a1913fSSubbaraya Sundeep if (iter->location > flow->location) 443f0a1913fSSubbaraya Sundeep break; 444f0a1913fSSubbaraya Sundeep head = &iter->list; 445f0a1913fSSubbaraya Sundeep } 446f0a1913fSSubbaraya Sundeep 447f0a1913fSSubbaraya Sundeep list_add(&flow->list, head); 448f0a1913fSSubbaraya Sundeep } 449f0a1913fSSubbaraya Sundeep 4503cffaed2SRakesh Babu int otx2_get_maxflows(struct otx2_flow_config *flow_cfg) 45179d2be38SHariprasad Kelam { 4523cffaed2SRakesh Babu if (!flow_cfg) 4533cffaed2SRakesh Babu return 0; 4543cffaed2SRakesh Babu 4552e2a8126SSunil Goutham if (flow_cfg->nr_flows == flow_cfg->max_flows || 456*fa5e0ccbSRatheesh Kannoth !bitmap_empty(flow_cfg->dmacflt_bmap, 45779d2be38SHariprasad Kelam flow_cfg->dmacflt_max_flows)) 4582e2a8126SSunil Goutham return flow_cfg->max_flows + flow_cfg->dmacflt_max_flows; 45979d2be38SHariprasad Kelam else 4602e2a8126SSunil Goutham return flow_cfg->max_flows; 46179d2be38SHariprasad Kelam } 4623cffaed2SRakesh Babu EXPORT_SYMBOL(otx2_get_maxflows); 46379d2be38SHariprasad Kelam 464f0a1913fSSubbaraya Sundeep int otx2_get_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc, 465f0a1913fSSubbaraya Sundeep u32 location) 466f0a1913fSSubbaraya Sundeep { 467f0a1913fSSubbaraya Sundeep struct otx2_flow *iter; 468f0a1913fSSubbaraya Sundeep 46979d2be38SHariprasad Kelam if (location >= otx2_get_maxflows(pfvf->flow_cfg)) 470f0a1913fSSubbaraya Sundeep return -EINVAL; 471f0a1913fSSubbaraya Sundeep 472f0a1913fSSubbaraya Sundeep list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) { 473f0a1913fSSubbaraya Sundeep if (iter->location == location) { 474f0a1913fSSubbaraya Sundeep nfc->fs = iter->flow_spec; 47581a43620SGeetha sowjanya nfc->rss_context = iter->rss_ctx_id; 476f0a1913fSSubbaraya Sundeep return 0; 477f0a1913fSSubbaraya Sundeep } 478f0a1913fSSubbaraya Sundeep } 479f0a1913fSSubbaraya Sundeep 480f0a1913fSSubbaraya Sundeep return -ENOENT; 481f0a1913fSSubbaraya Sundeep } 482f0a1913fSSubbaraya Sundeep 483f0a1913fSSubbaraya Sundeep int otx2_get_all_flows(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc, 484f0a1913fSSubbaraya Sundeep u32 *rule_locs) 485f0a1913fSSubbaraya Sundeep { 486f41b2d67SSubbaraya Sundeep u32 rule_cnt = nfc->rule_cnt; 487f0a1913fSSubbaraya Sundeep u32 location = 0; 488f0a1913fSSubbaraya Sundeep int idx = 0; 489f0a1913fSSubbaraya Sundeep int err = 0; 490f0a1913fSSubbaraya Sundeep 49179d2be38SHariprasad Kelam nfc->data = otx2_get_maxflows(pfvf->flow_cfg); 492f41b2d67SSubbaraya Sundeep while ((!err || err == -ENOENT) && idx < rule_cnt) { 493f0a1913fSSubbaraya Sundeep err = otx2_get_flow(pfvf, nfc, location); 494f0a1913fSSubbaraya Sundeep if (!err) 495f0a1913fSSubbaraya Sundeep rule_locs[idx++] = location; 496f0a1913fSSubbaraya Sundeep location++; 497f0a1913fSSubbaraya Sundeep } 498f41b2d67SSubbaraya Sundeep nfc->rule_cnt = rule_cnt; 499f0a1913fSSubbaraya Sundeep 500f0a1913fSSubbaraya Sundeep return err; 501f0a1913fSSubbaraya Sundeep } 502f0a1913fSSubbaraya Sundeep 503b7cf9661SNaveen Mamindlapalli static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp, 504f0a1913fSSubbaraya Sundeep struct npc_install_flow_req *req, 505f0a1913fSSubbaraya Sundeep u32 flow_type) 506f0a1913fSSubbaraya Sundeep { 507f0a1913fSSubbaraya Sundeep struct ethtool_usrip4_spec *ipv4_usr_mask = &fsp->m_u.usr_ip4_spec; 508f0a1913fSSubbaraya Sundeep struct ethtool_usrip4_spec *ipv4_usr_hdr = &fsp->h_u.usr_ip4_spec; 509f0a1913fSSubbaraya Sundeep struct ethtool_tcpip4_spec *ipv4_l4_mask = &fsp->m_u.tcp_ip4_spec; 510f0a1913fSSubbaraya Sundeep struct ethtool_tcpip4_spec *ipv4_l4_hdr = &fsp->h_u.tcp_ip4_spec; 511b7cf9661SNaveen Mamindlapalli struct ethtool_ah_espip4_spec *ah_esp_hdr = &fsp->h_u.ah_ip4_spec; 512b7cf9661SNaveen Mamindlapalli struct ethtool_ah_espip4_spec *ah_esp_mask = &fsp->m_u.ah_ip4_spec; 513f0a1913fSSubbaraya Sundeep struct flow_msg *pmask = &req->mask; 514f0a1913fSSubbaraya Sundeep struct flow_msg *pkt = &req->packet; 515f0a1913fSSubbaraya Sundeep 516f0a1913fSSubbaraya Sundeep switch (flow_type) { 517f0a1913fSSubbaraya Sundeep case IP_USER_FLOW: 518f0a1913fSSubbaraya Sundeep if (ipv4_usr_mask->ip4src) { 519f0a1913fSSubbaraya Sundeep memcpy(&pkt->ip4src, &ipv4_usr_hdr->ip4src, 520f0a1913fSSubbaraya Sundeep sizeof(pkt->ip4src)); 521f0a1913fSSubbaraya Sundeep memcpy(&pmask->ip4src, &ipv4_usr_mask->ip4src, 522f0a1913fSSubbaraya Sundeep sizeof(pmask->ip4src)); 523f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SIP_IPV4); 524f0a1913fSSubbaraya Sundeep } 525f0a1913fSSubbaraya Sundeep if (ipv4_usr_mask->ip4dst) { 526f0a1913fSSubbaraya Sundeep memcpy(&pkt->ip4dst, &ipv4_usr_hdr->ip4dst, 527f0a1913fSSubbaraya Sundeep sizeof(pkt->ip4dst)); 528f0a1913fSSubbaraya Sundeep memcpy(&pmask->ip4dst, &ipv4_usr_mask->ip4dst, 529f0a1913fSSubbaraya Sundeep sizeof(pmask->ip4dst)); 530f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DIP_IPV4); 531f0a1913fSSubbaraya Sundeep } 5322b9cef66SNaveen Mamindlapalli if (ipv4_usr_mask->tos) { 5332b9cef66SNaveen Mamindlapalli pkt->tos = ipv4_usr_hdr->tos; 5342b9cef66SNaveen Mamindlapalli pmask->tos = ipv4_usr_mask->tos; 5352b9cef66SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_TOS); 5362b9cef66SNaveen Mamindlapalli } 5372b9cef66SNaveen Mamindlapalli if (ipv4_usr_mask->proto) { 5382b9cef66SNaveen Mamindlapalli switch (ipv4_usr_hdr->proto) { 5392b9cef66SNaveen Mamindlapalli case IPPROTO_ICMP: 5402b9cef66SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_ICMP); 5412b9cef66SNaveen Mamindlapalli break; 5422b9cef66SNaveen Mamindlapalli case IPPROTO_TCP: 5432b9cef66SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_TCP); 5442b9cef66SNaveen Mamindlapalli break; 5452b9cef66SNaveen Mamindlapalli case IPPROTO_UDP: 5462b9cef66SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_UDP); 5472b9cef66SNaveen Mamindlapalli break; 5482b9cef66SNaveen Mamindlapalli case IPPROTO_SCTP: 5492b9cef66SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_SCTP); 5502b9cef66SNaveen Mamindlapalli break; 5512b9cef66SNaveen Mamindlapalli case IPPROTO_AH: 5522b9cef66SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_AH); 5532b9cef66SNaveen Mamindlapalli break; 5542b9cef66SNaveen Mamindlapalli case IPPROTO_ESP: 5552b9cef66SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_ESP); 5562b9cef66SNaveen Mamindlapalli break; 5572b9cef66SNaveen Mamindlapalli default: 5582b9cef66SNaveen Mamindlapalli return -EOPNOTSUPP; 5592b9cef66SNaveen Mamindlapalli } 5602b9cef66SNaveen Mamindlapalli } 561b7cf9661SNaveen Mamindlapalli pkt->etype = cpu_to_be16(ETH_P_IP); 562b7cf9661SNaveen Mamindlapalli pmask->etype = cpu_to_be16(0xFFFF); 563b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_ETYPE); 564f0a1913fSSubbaraya Sundeep break; 565f0a1913fSSubbaraya Sundeep case TCP_V4_FLOW: 566f0a1913fSSubbaraya Sundeep case UDP_V4_FLOW: 567f0a1913fSSubbaraya Sundeep case SCTP_V4_FLOW: 568b7cf9661SNaveen Mamindlapalli pkt->etype = cpu_to_be16(ETH_P_IP); 569b7cf9661SNaveen Mamindlapalli pmask->etype = cpu_to_be16(0xFFFF); 570b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_ETYPE); 571f0a1913fSSubbaraya Sundeep if (ipv4_l4_mask->ip4src) { 572f0a1913fSSubbaraya Sundeep memcpy(&pkt->ip4src, &ipv4_l4_hdr->ip4src, 573f0a1913fSSubbaraya Sundeep sizeof(pkt->ip4src)); 574f0a1913fSSubbaraya Sundeep memcpy(&pmask->ip4src, &ipv4_l4_mask->ip4src, 575f0a1913fSSubbaraya Sundeep sizeof(pmask->ip4src)); 576f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SIP_IPV4); 577f0a1913fSSubbaraya Sundeep } 578f0a1913fSSubbaraya Sundeep if (ipv4_l4_mask->ip4dst) { 579f0a1913fSSubbaraya Sundeep memcpy(&pkt->ip4dst, &ipv4_l4_hdr->ip4dst, 580f0a1913fSSubbaraya Sundeep sizeof(pkt->ip4dst)); 581f0a1913fSSubbaraya Sundeep memcpy(&pmask->ip4dst, &ipv4_l4_mask->ip4dst, 582f0a1913fSSubbaraya Sundeep sizeof(pmask->ip4dst)); 583f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DIP_IPV4); 584f0a1913fSSubbaraya Sundeep } 5852b9cef66SNaveen Mamindlapalli if (ipv4_l4_mask->tos) { 5862b9cef66SNaveen Mamindlapalli pkt->tos = ipv4_l4_hdr->tos; 5872b9cef66SNaveen Mamindlapalli pmask->tos = ipv4_l4_mask->tos; 5882b9cef66SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_TOS); 5892b9cef66SNaveen Mamindlapalli } 590f0a1913fSSubbaraya Sundeep if (ipv4_l4_mask->psrc) { 591f0a1913fSSubbaraya Sundeep memcpy(&pkt->sport, &ipv4_l4_hdr->psrc, 592f0a1913fSSubbaraya Sundeep sizeof(pkt->sport)); 593f0a1913fSSubbaraya Sundeep memcpy(&pmask->sport, &ipv4_l4_mask->psrc, 594f0a1913fSSubbaraya Sundeep sizeof(pmask->sport)); 595f0a1913fSSubbaraya Sundeep if (flow_type == UDP_V4_FLOW) 596f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SPORT_UDP); 597f0a1913fSSubbaraya Sundeep else if (flow_type == TCP_V4_FLOW) 598f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SPORT_TCP); 599f0a1913fSSubbaraya Sundeep else 600f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SPORT_SCTP); 601f0a1913fSSubbaraya Sundeep } 602f0a1913fSSubbaraya Sundeep if (ipv4_l4_mask->pdst) { 603f0a1913fSSubbaraya Sundeep memcpy(&pkt->dport, &ipv4_l4_hdr->pdst, 604f0a1913fSSubbaraya Sundeep sizeof(pkt->dport)); 605f0a1913fSSubbaraya Sundeep memcpy(&pmask->dport, &ipv4_l4_mask->pdst, 606f0a1913fSSubbaraya Sundeep sizeof(pmask->dport)); 607f0a1913fSSubbaraya Sundeep if (flow_type == UDP_V4_FLOW) 608f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DPORT_UDP); 609f0a1913fSSubbaraya Sundeep else if (flow_type == TCP_V4_FLOW) 610f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DPORT_TCP); 611f0a1913fSSubbaraya Sundeep else 612f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DPORT_SCTP); 613f0a1913fSSubbaraya Sundeep } 614b7cf9661SNaveen Mamindlapalli if (flow_type == UDP_V4_FLOW) 615b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_UDP); 616b7cf9661SNaveen Mamindlapalli else if (flow_type == TCP_V4_FLOW) 617b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_TCP); 618b7cf9661SNaveen Mamindlapalli else 619b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_SCTP); 620b7cf9661SNaveen Mamindlapalli break; 621b7cf9661SNaveen Mamindlapalli case AH_V4_FLOW: 622b7cf9661SNaveen Mamindlapalli case ESP_V4_FLOW: 623b7cf9661SNaveen Mamindlapalli pkt->etype = cpu_to_be16(ETH_P_IP); 624b7cf9661SNaveen Mamindlapalli pmask->etype = cpu_to_be16(0xFFFF); 625b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_ETYPE); 626b7cf9661SNaveen Mamindlapalli if (ah_esp_mask->ip4src) { 627b7cf9661SNaveen Mamindlapalli memcpy(&pkt->ip4src, &ah_esp_hdr->ip4src, 628b7cf9661SNaveen Mamindlapalli sizeof(pkt->ip4src)); 629b7cf9661SNaveen Mamindlapalli memcpy(&pmask->ip4src, &ah_esp_mask->ip4src, 630b7cf9661SNaveen Mamindlapalli sizeof(pmask->ip4src)); 631b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_SIP_IPV4); 632b7cf9661SNaveen Mamindlapalli } 633b7cf9661SNaveen Mamindlapalli if (ah_esp_mask->ip4dst) { 634b7cf9661SNaveen Mamindlapalli memcpy(&pkt->ip4dst, &ah_esp_hdr->ip4dst, 635b7cf9661SNaveen Mamindlapalli sizeof(pkt->ip4dst)); 636b7cf9661SNaveen Mamindlapalli memcpy(&pmask->ip4dst, &ah_esp_mask->ip4dst, 637b7cf9661SNaveen Mamindlapalli sizeof(pmask->ip4dst)); 638b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_DIP_IPV4); 639b7cf9661SNaveen Mamindlapalli } 6402b9cef66SNaveen Mamindlapalli if (ah_esp_mask->tos) { 6412b9cef66SNaveen Mamindlapalli pkt->tos = ah_esp_hdr->tos; 6422b9cef66SNaveen Mamindlapalli pmask->tos = ah_esp_mask->tos; 6432b9cef66SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_TOS); 6442b9cef66SNaveen Mamindlapalli } 645b7cf9661SNaveen Mamindlapalli 646b7cf9661SNaveen Mamindlapalli /* NPC profile doesn't extract AH/ESP header fields */ 6472b9cef66SNaveen Mamindlapalli if (ah_esp_mask->spi & ah_esp_hdr->spi) 648b7cf9661SNaveen Mamindlapalli return -EOPNOTSUPP; 649b7cf9661SNaveen Mamindlapalli 650b7cf9661SNaveen Mamindlapalli if (flow_type == AH_V4_FLOW) 651b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_AH); 652b7cf9661SNaveen Mamindlapalli else 653b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_ESP); 654f0a1913fSSubbaraya Sundeep break; 655f0a1913fSSubbaraya Sundeep default: 656f0a1913fSSubbaraya Sundeep break; 657f0a1913fSSubbaraya Sundeep } 658b7cf9661SNaveen Mamindlapalli 659b7cf9661SNaveen Mamindlapalli return 0; 660f0a1913fSSubbaraya Sundeep } 661f0a1913fSSubbaraya Sundeep 662b7cf9661SNaveen Mamindlapalli static int otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec *fsp, 663f0a1913fSSubbaraya Sundeep struct npc_install_flow_req *req, 664f0a1913fSSubbaraya Sundeep u32 flow_type) 665f0a1913fSSubbaraya Sundeep { 666f0a1913fSSubbaraya Sundeep struct ethtool_usrip6_spec *ipv6_usr_mask = &fsp->m_u.usr_ip6_spec; 667f0a1913fSSubbaraya Sundeep struct ethtool_usrip6_spec *ipv6_usr_hdr = &fsp->h_u.usr_ip6_spec; 668f0a1913fSSubbaraya Sundeep struct ethtool_tcpip6_spec *ipv6_l4_mask = &fsp->m_u.tcp_ip6_spec; 669f0a1913fSSubbaraya Sundeep struct ethtool_tcpip6_spec *ipv6_l4_hdr = &fsp->h_u.tcp_ip6_spec; 670b7cf9661SNaveen Mamindlapalli struct ethtool_ah_espip6_spec *ah_esp_hdr = &fsp->h_u.ah_ip6_spec; 671b7cf9661SNaveen Mamindlapalli struct ethtool_ah_espip6_spec *ah_esp_mask = &fsp->m_u.ah_ip6_spec; 672f0a1913fSSubbaraya Sundeep struct flow_msg *pmask = &req->mask; 673f0a1913fSSubbaraya Sundeep struct flow_msg *pkt = &req->packet; 674f0a1913fSSubbaraya Sundeep 675f0a1913fSSubbaraya Sundeep switch (flow_type) { 676f0a1913fSSubbaraya Sundeep case IPV6_USER_FLOW: 677f0a1913fSSubbaraya Sundeep if (!ipv6_addr_any((struct in6_addr *)ipv6_usr_mask->ip6src)) { 678f0a1913fSSubbaraya Sundeep memcpy(&pkt->ip6src, &ipv6_usr_hdr->ip6src, 679f0a1913fSSubbaraya Sundeep sizeof(pkt->ip6src)); 680f0a1913fSSubbaraya Sundeep memcpy(&pmask->ip6src, &ipv6_usr_mask->ip6src, 681f0a1913fSSubbaraya Sundeep sizeof(pmask->ip6src)); 682f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SIP_IPV6); 683f0a1913fSSubbaraya Sundeep } 684f0a1913fSSubbaraya Sundeep if (!ipv6_addr_any((struct in6_addr *)ipv6_usr_mask->ip6dst)) { 685f0a1913fSSubbaraya Sundeep memcpy(&pkt->ip6dst, &ipv6_usr_hdr->ip6dst, 686f0a1913fSSubbaraya Sundeep sizeof(pkt->ip6dst)); 687f0a1913fSSubbaraya Sundeep memcpy(&pmask->ip6dst, &ipv6_usr_mask->ip6dst, 688f0a1913fSSubbaraya Sundeep sizeof(pmask->ip6dst)); 689f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DIP_IPV6); 690f0a1913fSSubbaraya Sundeep } 691b7cf9661SNaveen Mamindlapalli pkt->etype = cpu_to_be16(ETH_P_IPV6); 692b7cf9661SNaveen Mamindlapalli pmask->etype = cpu_to_be16(0xFFFF); 693b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_ETYPE); 694f0a1913fSSubbaraya Sundeep break; 695f0a1913fSSubbaraya Sundeep case TCP_V6_FLOW: 696f0a1913fSSubbaraya Sundeep case UDP_V6_FLOW: 697f0a1913fSSubbaraya Sundeep case SCTP_V6_FLOW: 698b7cf9661SNaveen Mamindlapalli pkt->etype = cpu_to_be16(ETH_P_IPV6); 699b7cf9661SNaveen Mamindlapalli pmask->etype = cpu_to_be16(0xFFFF); 700b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_ETYPE); 701f0a1913fSSubbaraya Sundeep if (!ipv6_addr_any((struct in6_addr *)ipv6_l4_mask->ip6src)) { 702f0a1913fSSubbaraya Sundeep memcpy(&pkt->ip6src, &ipv6_l4_hdr->ip6src, 703f0a1913fSSubbaraya Sundeep sizeof(pkt->ip6src)); 704f0a1913fSSubbaraya Sundeep memcpy(&pmask->ip6src, &ipv6_l4_mask->ip6src, 705f0a1913fSSubbaraya Sundeep sizeof(pmask->ip6src)); 706f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SIP_IPV6); 707f0a1913fSSubbaraya Sundeep } 708f0a1913fSSubbaraya Sundeep if (!ipv6_addr_any((struct in6_addr *)ipv6_l4_mask->ip6dst)) { 709f0a1913fSSubbaraya Sundeep memcpy(&pkt->ip6dst, &ipv6_l4_hdr->ip6dst, 710f0a1913fSSubbaraya Sundeep sizeof(pkt->ip6dst)); 711f0a1913fSSubbaraya Sundeep memcpy(&pmask->ip6dst, &ipv6_l4_mask->ip6dst, 712f0a1913fSSubbaraya Sundeep sizeof(pmask->ip6dst)); 713f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DIP_IPV6); 714f0a1913fSSubbaraya Sundeep } 715f0a1913fSSubbaraya Sundeep if (ipv6_l4_mask->psrc) { 716f0a1913fSSubbaraya Sundeep memcpy(&pkt->sport, &ipv6_l4_hdr->psrc, 717f0a1913fSSubbaraya Sundeep sizeof(pkt->sport)); 718f0a1913fSSubbaraya Sundeep memcpy(&pmask->sport, &ipv6_l4_mask->psrc, 719f0a1913fSSubbaraya Sundeep sizeof(pmask->sport)); 720f0a1913fSSubbaraya Sundeep if (flow_type == UDP_V6_FLOW) 721f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SPORT_UDP); 722f0a1913fSSubbaraya Sundeep else if (flow_type == TCP_V6_FLOW) 723f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SPORT_TCP); 724f0a1913fSSubbaraya Sundeep else 725f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SPORT_SCTP); 726f0a1913fSSubbaraya Sundeep } 727f0a1913fSSubbaraya Sundeep if (ipv6_l4_mask->pdst) { 728f0a1913fSSubbaraya Sundeep memcpy(&pkt->dport, &ipv6_l4_hdr->pdst, 729f0a1913fSSubbaraya Sundeep sizeof(pkt->dport)); 730f0a1913fSSubbaraya Sundeep memcpy(&pmask->dport, &ipv6_l4_mask->pdst, 731f0a1913fSSubbaraya Sundeep sizeof(pmask->dport)); 732f0a1913fSSubbaraya Sundeep if (flow_type == UDP_V6_FLOW) 733f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DPORT_UDP); 734f0a1913fSSubbaraya Sundeep else if (flow_type == TCP_V6_FLOW) 735f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DPORT_TCP); 736f0a1913fSSubbaraya Sundeep else 737f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DPORT_SCTP); 738f0a1913fSSubbaraya Sundeep } 739b7cf9661SNaveen Mamindlapalli if (flow_type == UDP_V6_FLOW) 740b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_UDP); 741b7cf9661SNaveen Mamindlapalli else if (flow_type == TCP_V6_FLOW) 742b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_TCP); 743b7cf9661SNaveen Mamindlapalli else 744b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_SCTP); 745f0a1913fSSubbaraya Sundeep break; 746b7cf9661SNaveen Mamindlapalli case AH_V6_FLOW: 747b7cf9661SNaveen Mamindlapalli case ESP_V6_FLOW: 748b7cf9661SNaveen Mamindlapalli pkt->etype = cpu_to_be16(ETH_P_IPV6); 749b7cf9661SNaveen Mamindlapalli pmask->etype = cpu_to_be16(0xFFFF); 750b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_ETYPE); 751b7cf9661SNaveen Mamindlapalli if (!ipv6_addr_any((struct in6_addr *)ah_esp_hdr->ip6src)) { 752b7cf9661SNaveen Mamindlapalli memcpy(&pkt->ip6src, &ah_esp_hdr->ip6src, 753b7cf9661SNaveen Mamindlapalli sizeof(pkt->ip6src)); 754b7cf9661SNaveen Mamindlapalli memcpy(&pmask->ip6src, &ah_esp_mask->ip6src, 755b7cf9661SNaveen Mamindlapalli sizeof(pmask->ip6src)); 756b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_SIP_IPV6); 757b7cf9661SNaveen Mamindlapalli } 758b7cf9661SNaveen Mamindlapalli if (!ipv6_addr_any((struct in6_addr *)ah_esp_hdr->ip6dst)) { 759b7cf9661SNaveen Mamindlapalli memcpy(&pkt->ip6dst, &ah_esp_hdr->ip6dst, 760b7cf9661SNaveen Mamindlapalli sizeof(pkt->ip6dst)); 761b7cf9661SNaveen Mamindlapalli memcpy(&pmask->ip6dst, &ah_esp_mask->ip6dst, 762b7cf9661SNaveen Mamindlapalli sizeof(pmask->ip6dst)); 763b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_DIP_IPV6); 764b7cf9661SNaveen Mamindlapalli } 765b7cf9661SNaveen Mamindlapalli 766b7cf9661SNaveen Mamindlapalli /* NPC profile doesn't extract AH/ESP header fields */ 767b7cf9661SNaveen Mamindlapalli if ((ah_esp_mask->spi & ah_esp_hdr->spi) || 768b7cf9661SNaveen Mamindlapalli (ah_esp_mask->tclass & ah_esp_mask->tclass)) 769b7cf9661SNaveen Mamindlapalli return -EOPNOTSUPP; 770b7cf9661SNaveen Mamindlapalli 771b7cf9661SNaveen Mamindlapalli if (flow_type == AH_V6_FLOW) 772b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_AH); 773b7cf9661SNaveen Mamindlapalli else 774b7cf9661SNaveen Mamindlapalli req->features |= BIT_ULL(NPC_IPPROTO_ESP); 775320daffdSGustavo A. R. Silva break; 776f0a1913fSSubbaraya Sundeep default: 777f0a1913fSSubbaraya Sundeep break; 778f0a1913fSSubbaraya Sundeep } 779b7cf9661SNaveen Mamindlapalli 780b7cf9661SNaveen Mamindlapalli return 0; 781f0a1913fSSubbaraya Sundeep } 782f0a1913fSSubbaraya Sundeep 783dce677daSSubbaraya Sundeep static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp, 784f0a1913fSSubbaraya Sundeep struct npc_install_flow_req *req) 785f0a1913fSSubbaraya Sundeep { 786f0a1913fSSubbaraya Sundeep struct ethhdr *eth_mask = &fsp->m_u.ether_spec; 787f0a1913fSSubbaraya Sundeep struct ethhdr *eth_hdr = &fsp->h_u.ether_spec; 788f0a1913fSSubbaraya Sundeep struct flow_msg *pmask = &req->mask; 789f0a1913fSSubbaraya Sundeep struct flow_msg *pkt = &req->packet; 790f0a1913fSSubbaraya Sundeep u32 flow_type; 791b7cf9661SNaveen Mamindlapalli int ret; 792f0a1913fSSubbaraya Sundeep 79381a43620SGeetha sowjanya flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS); 794f0a1913fSSubbaraya Sundeep switch (flow_type) { 795f0a1913fSSubbaraya Sundeep /* bits not set in mask are don't care */ 796f0a1913fSSubbaraya Sundeep case ETHER_FLOW: 797f0a1913fSSubbaraya Sundeep if (!is_zero_ether_addr(eth_mask->h_source)) { 798f0a1913fSSubbaraya Sundeep ether_addr_copy(pkt->smac, eth_hdr->h_source); 799f0a1913fSSubbaraya Sundeep ether_addr_copy(pmask->smac, eth_mask->h_source); 800f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_SMAC); 801f0a1913fSSubbaraya Sundeep } 802f0a1913fSSubbaraya Sundeep if (!is_zero_ether_addr(eth_mask->h_dest)) { 803f0a1913fSSubbaraya Sundeep ether_addr_copy(pkt->dmac, eth_hdr->h_dest); 804f0a1913fSSubbaraya Sundeep ether_addr_copy(pmask->dmac, eth_mask->h_dest); 805f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DMAC); 806f0a1913fSSubbaraya Sundeep } 8073cffaed2SRakesh Babu if (eth_hdr->h_proto) { 808f0a1913fSSubbaraya Sundeep memcpy(&pkt->etype, ð_hdr->h_proto, 809f0a1913fSSubbaraya Sundeep sizeof(pkt->etype)); 810f0a1913fSSubbaraya Sundeep memcpy(&pmask->etype, ð_mask->h_proto, 811f0a1913fSSubbaraya Sundeep sizeof(pmask->etype)); 812f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_ETYPE); 813f0a1913fSSubbaraya Sundeep } 814f0a1913fSSubbaraya Sundeep break; 815f0a1913fSSubbaraya Sundeep case IP_USER_FLOW: 816f0a1913fSSubbaraya Sundeep case TCP_V4_FLOW: 817f0a1913fSSubbaraya Sundeep case UDP_V4_FLOW: 818f0a1913fSSubbaraya Sundeep case SCTP_V4_FLOW: 819b7cf9661SNaveen Mamindlapalli case AH_V4_FLOW: 820b7cf9661SNaveen Mamindlapalli case ESP_V4_FLOW: 821b7cf9661SNaveen Mamindlapalli ret = otx2_prepare_ipv4_flow(fsp, req, flow_type); 822b7cf9661SNaveen Mamindlapalli if (ret) 823b7cf9661SNaveen Mamindlapalli return ret; 824f0a1913fSSubbaraya Sundeep break; 825f0a1913fSSubbaraya Sundeep case IPV6_USER_FLOW: 826f0a1913fSSubbaraya Sundeep case TCP_V6_FLOW: 827f0a1913fSSubbaraya Sundeep case UDP_V6_FLOW: 828f0a1913fSSubbaraya Sundeep case SCTP_V6_FLOW: 829b7cf9661SNaveen Mamindlapalli case AH_V6_FLOW: 830b7cf9661SNaveen Mamindlapalli case ESP_V6_FLOW: 831b7cf9661SNaveen Mamindlapalli ret = otx2_prepare_ipv6_flow(fsp, req, flow_type); 832b7cf9661SNaveen Mamindlapalli if (ret) 833b7cf9661SNaveen Mamindlapalli return ret; 834f0a1913fSSubbaraya Sundeep break; 835f0a1913fSSubbaraya Sundeep default: 836f0a1913fSSubbaraya Sundeep return -EOPNOTSUPP; 837f0a1913fSSubbaraya Sundeep } 838f0a1913fSSubbaraya Sundeep if (fsp->flow_type & FLOW_EXT) { 839dce677daSSubbaraya Sundeep u16 vlan_etype; 840dce677daSSubbaraya Sundeep 841dce677daSSubbaraya Sundeep if (fsp->m_ext.vlan_etype) { 842dce677daSSubbaraya Sundeep /* Partial masks not supported */ 843dce677daSSubbaraya Sundeep if (be16_to_cpu(fsp->m_ext.vlan_etype) != 0xFFFF) 844f0a1913fSSubbaraya Sundeep return -EINVAL; 845dce677daSSubbaraya Sundeep 846dce677daSSubbaraya Sundeep vlan_etype = be16_to_cpu(fsp->h_ext.vlan_etype); 847dce677daSSubbaraya Sundeep /* Only ETH_P_8021Q and ETH_P_802AD types supported */ 848dce677daSSubbaraya Sundeep if (vlan_etype != ETH_P_8021Q && 849dce677daSSubbaraya Sundeep vlan_etype != ETH_P_8021AD) 850dce677daSSubbaraya Sundeep return -EINVAL; 851dce677daSSubbaraya Sundeep 852dce677daSSubbaraya Sundeep memcpy(&pkt->vlan_etype, &fsp->h_ext.vlan_etype, 853dce677daSSubbaraya Sundeep sizeof(pkt->vlan_etype)); 854dce677daSSubbaraya Sundeep memcpy(&pmask->vlan_etype, &fsp->m_ext.vlan_etype, 855dce677daSSubbaraya Sundeep sizeof(pmask->vlan_etype)); 856dce677daSSubbaraya Sundeep 857dce677daSSubbaraya Sundeep if (vlan_etype == ETH_P_8021Q) 858dce677daSSubbaraya Sundeep req->features |= BIT_ULL(NPC_VLAN_ETYPE_CTAG); 859dce677daSSubbaraya Sundeep else 860dce677daSSubbaraya Sundeep req->features |= BIT_ULL(NPC_VLAN_ETYPE_STAG); 861dce677daSSubbaraya Sundeep } 862dce677daSSubbaraya Sundeep 863f0a1913fSSubbaraya Sundeep if (fsp->m_ext.vlan_tci) { 864f0a1913fSSubbaraya Sundeep memcpy(&pkt->vlan_tci, &fsp->h_ext.vlan_tci, 865f0a1913fSSubbaraya Sundeep sizeof(pkt->vlan_tci)); 866f0a1913fSSubbaraya Sundeep memcpy(&pmask->vlan_tci, &fsp->m_ext.vlan_tci, 867f0a1913fSSubbaraya Sundeep sizeof(pmask->vlan_tci)); 868f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_OUTER_VID); 869f0a1913fSSubbaraya Sundeep } 870f0a1913fSSubbaraya Sundeep 871f0a1913fSSubbaraya Sundeep /* Not Drop/Direct to queue but use action in default entry */ 872f0a1913fSSubbaraya Sundeep if (fsp->m_ext.data[1] && 873f0a1913fSSubbaraya Sundeep fsp->h_ext.data[1] == cpu_to_be32(OTX2_DEFAULT_ACTION)) 874f0a1913fSSubbaraya Sundeep req->op = NIX_RX_ACTION_DEFAULT; 875f0a1913fSSubbaraya Sundeep } 876f0a1913fSSubbaraya Sundeep 877f0a1913fSSubbaraya Sundeep if (fsp->flow_type & FLOW_MAC_EXT && 878f0a1913fSSubbaraya Sundeep !is_zero_ether_addr(fsp->m_ext.h_dest)) { 879f0a1913fSSubbaraya Sundeep ether_addr_copy(pkt->dmac, fsp->h_ext.h_dest); 880f0a1913fSSubbaraya Sundeep ether_addr_copy(pmask->dmac, fsp->m_ext.h_dest); 881f0a1913fSSubbaraya Sundeep req->features |= BIT_ULL(NPC_DMAC); 882f0a1913fSSubbaraya Sundeep } 883f0a1913fSSubbaraya Sundeep 884f0a1913fSSubbaraya Sundeep if (!req->features) 885f0a1913fSSubbaraya Sundeep return -EOPNOTSUPP; 886f0a1913fSSubbaraya Sundeep 887f0a1913fSSubbaraya Sundeep return 0; 888f0a1913fSSubbaraya Sundeep } 889f0a1913fSSubbaraya Sundeep 89079d2be38SHariprasad Kelam static int otx2_is_flow_rule_dmacfilter(struct otx2_nic *pfvf, 89179d2be38SHariprasad Kelam struct ethtool_rx_flow_spec *fsp) 89279d2be38SHariprasad Kelam { 89379d2be38SHariprasad Kelam struct ethhdr *eth_mask = &fsp->m_u.ether_spec; 89479d2be38SHariprasad Kelam struct ethhdr *eth_hdr = &fsp->h_u.ether_spec; 89579d2be38SHariprasad Kelam u64 ring_cookie = fsp->ring_cookie; 89679d2be38SHariprasad Kelam u32 flow_type; 89779d2be38SHariprasad Kelam 89879d2be38SHariprasad Kelam if (!(pfvf->flags & OTX2_FLAG_DMACFLTR_SUPPORT)) 89979d2be38SHariprasad Kelam return false; 90079d2be38SHariprasad Kelam 90179d2be38SHariprasad Kelam flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS); 90279d2be38SHariprasad Kelam 90379d2be38SHariprasad Kelam /* CGX/RPM block dmac filtering configured for white listing 90479d2be38SHariprasad Kelam * check for action other than DROP 90579d2be38SHariprasad Kelam */ 90679d2be38SHariprasad Kelam if (flow_type == ETHER_FLOW && ring_cookie != RX_CLS_FLOW_DISC && 90779d2be38SHariprasad Kelam !ethtool_get_flow_spec_ring_vf(ring_cookie)) { 90879d2be38SHariprasad Kelam if (is_zero_ether_addr(eth_mask->h_dest) && 90979d2be38SHariprasad Kelam is_valid_ether_addr(eth_hdr->h_dest)) 91079d2be38SHariprasad Kelam return true; 91179d2be38SHariprasad Kelam } 91279d2be38SHariprasad Kelam 91379d2be38SHariprasad Kelam return false; 91479d2be38SHariprasad Kelam } 91579d2be38SHariprasad Kelam 916f0a1913fSSubbaraya Sundeep static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow) 917f0a1913fSSubbaraya Sundeep { 918f0a1913fSSubbaraya Sundeep u64 ring_cookie = flow->flow_spec.ring_cookie; 9198e675581SHariprasad Kelam #ifdef CONFIG_DCB 9208e675581SHariprasad Kelam int vlan_prio, qidx, pfc_rule = 0; 9218e675581SHariprasad Kelam #endif 922f0a1913fSSubbaraya Sundeep struct npc_install_flow_req *req; 923f0a1913fSSubbaraya Sundeep int err, vf = 0; 924f0a1913fSSubbaraya Sundeep 925f0a1913fSSubbaraya Sundeep mutex_lock(&pfvf->mbox.lock); 926f0a1913fSSubbaraya Sundeep req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox); 927f0a1913fSSubbaraya Sundeep if (!req) { 928f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 929f0a1913fSSubbaraya Sundeep return -ENOMEM; 930f0a1913fSSubbaraya Sundeep } 931f0a1913fSSubbaraya Sundeep 932f0a1913fSSubbaraya Sundeep err = otx2_prepare_flow_request(&flow->flow_spec, req); 933f0a1913fSSubbaraya Sundeep if (err) { 934f0a1913fSSubbaraya Sundeep /* free the allocated msg above */ 935f0a1913fSSubbaraya Sundeep otx2_mbox_reset(&pfvf->mbox.mbox, 0); 936f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 937f0a1913fSSubbaraya Sundeep return err; 938f0a1913fSSubbaraya Sundeep } 939f0a1913fSSubbaraya Sundeep 940f0a1913fSSubbaraya Sundeep req->entry = flow->entry; 941f0a1913fSSubbaraya Sundeep req->intf = NIX_INTF_RX; 942f0a1913fSSubbaraya Sundeep req->set_cntr = 1; 943f0a1913fSSubbaraya Sundeep req->channel = pfvf->hw.rx_chan_base; 944f0a1913fSSubbaraya Sundeep if (ring_cookie == RX_CLS_FLOW_DISC) { 945f0a1913fSSubbaraya Sundeep req->op = NIX_RX_ACTIONOP_DROP; 946f0a1913fSSubbaraya Sundeep } else { 947f0a1913fSSubbaraya Sundeep /* change to unicast only if action of default entry is not 948f0a1913fSSubbaraya Sundeep * requested by user 949f0a1913fSSubbaraya Sundeep */ 95081a43620SGeetha sowjanya if (flow->flow_spec.flow_type & FLOW_RSS) { 95181a43620SGeetha sowjanya req->op = NIX_RX_ACTIONOP_RSS; 95281a43620SGeetha sowjanya req->index = flow->rss_ctx_id; 953e7938365SSunil Goutham req->flow_key_alg = pfvf->hw.flowkey_alg_idx; 95481a43620SGeetha sowjanya } else { 955f0a1913fSSubbaraya Sundeep req->op = NIX_RX_ACTIONOP_UCAST; 956f0a1913fSSubbaraya Sundeep req->index = ethtool_get_flow_spec_ring(ring_cookie); 95781a43620SGeetha sowjanya } 958f0a1913fSSubbaraya Sundeep vf = ethtool_get_flow_spec_ring_vf(ring_cookie); 959f0a1913fSSubbaraya Sundeep if (vf > pci_num_vf(pfvf->pdev)) { 960f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 961f0a1913fSSubbaraya Sundeep return -EINVAL; 962f0a1913fSSubbaraya Sundeep } 9638e675581SHariprasad Kelam 9648e675581SHariprasad Kelam #ifdef CONFIG_DCB 9658e675581SHariprasad Kelam /* Identify PFC rule if PFC enabled and ntuple rule is vlan */ 9668e675581SHariprasad Kelam if (!vf && (req->features & BIT_ULL(NPC_OUTER_VID)) && 9678e675581SHariprasad Kelam pfvf->pfc_en && req->op != NIX_RX_ACTIONOP_RSS) { 9688e675581SHariprasad Kelam vlan_prio = ntohs(req->packet.vlan_tci) & 9698e675581SHariprasad Kelam ntohs(req->mask.vlan_tci); 9708e675581SHariprasad Kelam 9718e675581SHariprasad Kelam /* Get the priority */ 9728e675581SHariprasad Kelam vlan_prio >>= 13; 9738e675581SHariprasad Kelam flow->rule_type |= PFC_FLOWCTRL_RULE; 9748e675581SHariprasad Kelam /* Check if PFC enabled for this priority */ 9758e675581SHariprasad Kelam if (pfvf->pfc_en & BIT(vlan_prio)) { 9768e675581SHariprasad Kelam pfc_rule = true; 9778e675581SHariprasad Kelam qidx = req->index; 9788e675581SHariprasad Kelam } 9798e675581SHariprasad Kelam } 9808e675581SHariprasad Kelam #endif 981f0a1913fSSubbaraya Sundeep } 982f0a1913fSSubbaraya Sundeep 983f0a1913fSSubbaraya Sundeep /* ethtool ring_cookie has (VF + 1) for VF */ 984f0a1913fSSubbaraya Sundeep if (vf) { 985f0a1913fSSubbaraya Sundeep req->vf = vf; 986f0a1913fSSubbaraya Sundeep flow->is_vf = true; 987f0a1913fSSubbaraya Sundeep flow->vf = vf; 988f0a1913fSSubbaraya Sundeep } 989f0a1913fSSubbaraya Sundeep 990f0a1913fSSubbaraya Sundeep /* Send message to AF */ 991f0a1913fSSubbaraya Sundeep err = otx2_sync_mbox_msg(&pfvf->mbox); 9928e675581SHariprasad Kelam 9938e675581SHariprasad Kelam #ifdef CONFIG_DCB 9948e675581SHariprasad Kelam if (!err && pfc_rule) 9958e675581SHariprasad Kelam otx2_update_bpid_in_rqctx(pfvf, vlan_prio, qidx, true); 9968e675581SHariprasad Kelam #endif 9978e675581SHariprasad Kelam 998f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 999f0a1913fSSubbaraya Sundeep return err; 1000f0a1913fSSubbaraya Sundeep } 1001f0a1913fSSubbaraya Sundeep 100279d2be38SHariprasad Kelam static int otx2_add_flow_with_pfmac(struct otx2_nic *pfvf, 100379d2be38SHariprasad Kelam struct otx2_flow *flow) 100479d2be38SHariprasad Kelam { 100579d2be38SHariprasad Kelam struct otx2_flow *pf_mac; 100679d2be38SHariprasad Kelam struct ethhdr *eth_hdr; 100779d2be38SHariprasad Kelam 100879d2be38SHariprasad Kelam pf_mac = kzalloc(sizeof(*pf_mac), GFP_KERNEL); 100979d2be38SHariprasad Kelam if (!pf_mac) 101079d2be38SHariprasad Kelam return -ENOMEM; 101179d2be38SHariprasad Kelam 101279d2be38SHariprasad Kelam pf_mac->entry = 0; 10138e675581SHariprasad Kelam pf_mac->rule_type |= DMAC_FILTER_RULE; 10142e2a8126SSunil Goutham pf_mac->location = pfvf->flow_cfg->max_flows; 101579d2be38SHariprasad Kelam memcpy(&pf_mac->flow_spec, &flow->flow_spec, 101679d2be38SHariprasad Kelam sizeof(struct ethtool_rx_flow_spec)); 101779d2be38SHariprasad Kelam pf_mac->flow_spec.location = pf_mac->location; 101879d2be38SHariprasad Kelam 101979d2be38SHariprasad Kelam /* Copy PF mac address */ 102079d2be38SHariprasad Kelam eth_hdr = &pf_mac->flow_spec.h_u.ether_spec; 102179d2be38SHariprasad Kelam ether_addr_copy(eth_hdr->h_dest, pfvf->netdev->dev_addr); 102279d2be38SHariprasad Kelam 102379d2be38SHariprasad Kelam /* Install DMAC filter with PF mac address */ 102479d2be38SHariprasad Kelam otx2_dmacflt_add(pfvf, eth_hdr->h_dest, 0); 102579d2be38SHariprasad Kelam 102679d2be38SHariprasad Kelam otx2_add_flow_to_list(pfvf, pf_mac); 102779d2be38SHariprasad Kelam pfvf->flow_cfg->nr_flows++; 1028*fa5e0ccbSRatheesh Kannoth set_bit(0, pfvf->flow_cfg->dmacflt_bmap); 102979d2be38SHariprasad Kelam 103079d2be38SHariprasad Kelam return 0; 103179d2be38SHariprasad Kelam } 103279d2be38SHariprasad Kelam 103381a43620SGeetha sowjanya int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc) 1034f0a1913fSSubbaraya Sundeep { 1035f0a1913fSSubbaraya Sundeep struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 103681a43620SGeetha sowjanya struct ethtool_rx_flow_spec *fsp = &nfc->fs; 1037f0a1913fSSubbaraya Sundeep struct otx2_flow *flow; 103879d2be38SHariprasad Kelam struct ethhdr *eth_hdr; 1039f0a1913fSSubbaraya Sundeep bool new = false; 104079d2be38SHariprasad Kelam int err = 0; 104181a43620SGeetha sowjanya u32 ring; 1042f0a1913fSSubbaraya Sundeep 1043a515e5b5SSunil Goutham if (!flow_cfg->max_flows) { 1044a515e5b5SSunil Goutham netdev_err(pfvf->netdev, 1045a515e5b5SSunil Goutham "Ntuple rule count is 0, allocate and retry\n"); 1046a515e5b5SSunil Goutham return -EINVAL; 1047a515e5b5SSunil Goutham } 1048a515e5b5SSunil Goutham 104981a43620SGeetha sowjanya ring = ethtool_get_flow_spec_ring(fsp->ring_cookie); 1050f0a1913fSSubbaraya Sundeep if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT)) 1051f0a1913fSSubbaraya Sundeep return -ENOMEM; 1052f0a1913fSSubbaraya Sundeep 1053f0a1913fSSubbaraya Sundeep if (ring >= pfvf->hw.rx_queues && fsp->ring_cookie != RX_CLS_FLOW_DISC) 1054f0a1913fSSubbaraya Sundeep return -EINVAL; 1055f0a1913fSSubbaraya Sundeep 105679d2be38SHariprasad Kelam if (fsp->location >= otx2_get_maxflows(flow_cfg)) 1057f0a1913fSSubbaraya Sundeep return -EINVAL; 1058f0a1913fSSubbaraya Sundeep 1059f0a1913fSSubbaraya Sundeep flow = otx2_find_flow(pfvf, fsp->location); 1060f0a1913fSSubbaraya Sundeep if (!flow) { 106179d2be38SHariprasad Kelam flow = kzalloc(sizeof(*flow), GFP_KERNEL); 1062f0a1913fSSubbaraya Sundeep if (!flow) 1063f0a1913fSSubbaraya Sundeep return -ENOMEM; 1064f0a1913fSSubbaraya Sundeep flow->location = fsp->location; 1065dce677daSSubbaraya Sundeep flow->entry = flow_cfg->flow_ent[flow->location]; 1066f0a1913fSSubbaraya Sundeep new = true; 1067f0a1913fSSubbaraya Sundeep } 1068f0a1913fSSubbaraya Sundeep /* struct copy */ 1069f0a1913fSSubbaraya Sundeep flow->flow_spec = *fsp; 1070f0a1913fSSubbaraya Sundeep 107181a43620SGeetha sowjanya if (fsp->flow_type & FLOW_RSS) 107281a43620SGeetha sowjanya flow->rss_ctx_id = nfc->rss_context; 107381a43620SGeetha sowjanya 107479d2be38SHariprasad Kelam if (otx2_is_flow_rule_dmacfilter(pfvf, &flow->flow_spec)) { 107579d2be38SHariprasad Kelam eth_hdr = &flow->flow_spec.h_u.ether_spec; 107679d2be38SHariprasad Kelam 107779d2be38SHariprasad Kelam /* Sync dmac filter table with updated fields */ 10788e675581SHariprasad Kelam if (flow->rule_type & DMAC_FILTER_RULE) 107979d2be38SHariprasad Kelam return otx2_dmacflt_update(pfvf, eth_hdr->h_dest, 108079d2be38SHariprasad Kelam flow->entry); 108179d2be38SHariprasad Kelam 1082*fa5e0ccbSRatheesh Kannoth if (bitmap_full(flow_cfg->dmacflt_bmap, 108379d2be38SHariprasad Kelam flow_cfg->dmacflt_max_flows)) { 108479d2be38SHariprasad Kelam netdev_warn(pfvf->netdev, 108579d2be38SHariprasad Kelam "Can't insert the rule %d as max allowed dmac filters are %d\n", 108679d2be38SHariprasad Kelam flow->location + 108779d2be38SHariprasad Kelam flow_cfg->dmacflt_max_flows, 108879d2be38SHariprasad Kelam flow_cfg->dmacflt_max_flows); 108979d2be38SHariprasad Kelam err = -EINVAL; 109079d2be38SHariprasad Kelam if (new) 109179d2be38SHariprasad Kelam kfree(flow); 109279d2be38SHariprasad Kelam return err; 109379d2be38SHariprasad Kelam } 109479d2be38SHariprasad Kelam 109579d2be38SHariprasad Kelam /* Install PF mac address to DMAC filter list */ 1096*fa5e0ccbSRatheesh Kannoth if (!test_bit(0, flow_cfg->dmacflt_bmap)) 109779d2be38SHariprasad Kelam otx2_add_flow_with_pfmac(pfvf, flow); 109879d2be38SHariprasad Kelam 10998e675581SHariprasad Kelam flow->rule_type |= DMAC_FILTER_RULE; 1100*fa5e0ccbSRatheesh Kannoth flow->entry = find_first_zero_bit(flow_cfg->dmacflt_bmap, 110179d2be38SHariprasad Kelam flow_cfg->dmacflt_max_flows); 11022e2a8126SSunil Goutham fsp->location = flow_cfg->max_flows + flow->entry; 110379d2be38SHariprasad Kelam flow->flow_spec.location = fsp->location; 110479d2be38SHariprasad Kelam flow->location = fsp->location; 110579d2be38SHariprasad Kelam 1106*fa5e0ccbSRatheesh Kannoth set_bit(flow->entry, flow_cfg->dmacflt_bmap); 110779d2be38SHariprasad Kelam otx2_dmacflt_add(pfvf, eth_hdr->h_dest, flow->entry); 110879d2be38SHariprasad Kelam 110979d2be38SHariprasad Kelam } else { 11102e2a8126SSunil Goutham if (flow->location >= pfvf->flow_cfg->max_flows) { 111179d2be38SHariprasad Kelam netdev_warn(pfvf->netdev, 111279d2be38SHariprasad Kelam "Can't insert non dmac ntuple rule at %d, allowed range %d-0\n", 111379d2be38SHariprasad Kelam flow->location, 11142e2a8126SSunil Goutham flow_cfg->max_flows - 1); 111579d2be38SHariprasad Kelam err = -EINVAL; 111679d2be38SHariprasad Kelam } else { 1117f0a1913fSSubbaraya Sundeep err = otx2_add_flow_msg(pfvf, flow); 111879d2be38SHariprasad Kelam } 111979d2be38SHariprasad Kelam } 112079d2be38SHariprasad Kelam 1121f0a1913fSSubbaraya Sundeep if (err) { 11223cffaed2SRakesh Babu if (err == MBOX_MSG_INVALID) 11233cffaed2SRakesh Babu err = -EINVAL; 1124f0a1913fSSubbaraya Sundeep if (new) 1125f0a1913fSSubbaraya Sundeep kfree(flow); 1126f0a1913fSSubbaraya Sundeep return err; 1127f0a1913fSSubbaraya Sundeep } 1128f0a1913fSSubbaraya Sundeep 1129f0a1913fSSubbaraya Sundeep /* add the new flow installed to list */ 1130f0a1913fSSubbaraya Sundeep if (new) { 1131f0a1913fSSubbaraya Sundeep otx2_add_flow_to_list(pfvf, flow); 1132f0a1913fSSubbaraya Sundeep flow_cfg->nr_flows++; 1133f0a1913fSSubbaraya Sundeep } 1134f0a1913fSSubbaraya Sundeep 1135f0a1913fSSubbaraya Sundeep return 0; 1136f0a1913fSSubbaraya Sundeep } 1137f0a1913fSSubbaraya Sundeep 1138f0a1913fSSubbaraya Sundeep static int otx2_remove_flow_msg(struct otx2_nic *pfvf, u16 entry, bool all) 1139f0a1913fSSubbaraya Sundeep { 1140f0a1913fSSubbaraya Sundeep struct npc_delete_flow_req *req; 1141f0a1913fSSubbaraya Sundeep int err; 1142f0a1913fSSubbaraya Sundeep 1143f0a1913fSSubbaraya Sundeep mutex_lock(&pfvf->mbox.lock); 1144f0a1913fSSubbaraya Sundeep req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox); 1145f0a1913fSSubbaraya Sundeep if (!req) { 1146f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 1147f0a1913fSSubbaraya Sundeep return -ENOMEM; 1148f0a1913fSSubbaraya Sundeep } 1149f0a1913fSSubbaraya Sundeep 1150f0a1913fSSubbaraya Sundeep req->entry = entry; 1151f0a1913fSSubbaraya Sundeep if (all) 1152f0a1913fSSubbaraya Sundeep req->all = 1; 1153f0a1913fSSubbaraya Sundeep 1154f0a1913fSSubbaraya Sundeep /* Send message to AF */ 1155f0a1913fSSubbaraya Sundeep err = otx2_sync_mbox_msg(&pfvf->mbox); 1156f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 1157f0a1913fSSubbaraya Sundeep return err; 1158f0a1913fSSubbaraya Sundeep } 1159f0a1913fSSubbaraya Sundeep 116079d2be38SHariprasad Kelam static void otx2_update_rem_pfmac(struct otx2_nic *pfvf, int req) 116179d2be38SHariprasad Kelam { 116279d2be38SHariprasad Kelam struct otx2_flow *iter; 116379d2be38SHariprasad Kelam struct ethhdr *eth_hdr; 116479d2be38SHariprasad Kelam bool found = false; 116579d2be38SHariprasad Kelam 116679d2be38SHariprasad Kelam list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) { 11678e675581SHariprasad Kelam if ((iter->rule_type & DMAC_FILTER_RULE) && iter->entry == 0) { 116879d2be38SHariprasad Kelam eth_hdr = &iter->flow_spec.h_u.ether_spec; 116979d2be38SHariprasad Kelam if (req == DMAC_ADDR_DEL) { 117079d2be38SHariprasad Kelam otx2_dmacflt_remove(pfvf, eth_hdr->h_dest, 117179d2be38SHariprasad Kelam 0); 1172*fa5e0ccbSRatheesh Kannoth clear_bit(0, pfvf->flow_cfg->dmacflt_bmap); 117379d2be38SHariprasad Kelam found = true; 117479d2be38SHariprasad Kelam } else { 117579d2be38SHariprasad Kelam ether_addr_copy(eth_hdr->h_dest, 117679d2be38SHariprasad Kelam pfvf->netdev->dev_addr); 1177*fa5e0ccbSRatheesh Kannoth 117879d2be38SHariprasad Kelam otx2_dmacflt_update(pfvf, eth_hdr->h_dest, 0); 117979d2be38SHariprasad Kelam } 118079d2be38SHariprasad Kelam break; 118179d2be38SHariprasad Kelam } 118279d2be38SHariprasad Kelam } 118379d2be38SHariprasad Kelam 118479d2be38SHariprasad Kelam if (found) { 118579d2be38SHariprasad Kelam list_del(&iter->list); 118679d2be38SHariprasad Kelam kfree(iter); 118779d2be38SHariprasad Kelam pfvf->flow_cfg->nr_flows--; 118879d2be38SHariprasad Kelam } 118979d2be38SHariprasad Kelam } 119079d2be38SHariprasad Kelam 1191f0a1913fSSubbaraya Sundeep int otx2_remove_flow(struct otx2_nic *pfvf, u32 location) 1192f0a1913fSSubbaraya Sundeep { 1193f0a1913fSSubbaraya Sundeep struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 1194f0a1913fSSubbaraya Sundeep struct otx2_flow *flow; 1195f0a1913fSSubbaraya Sundeep int err; 1196f0a1913fSSubbaraya Sundeep 119779d2be38SHariprasad Kelam if (location >= otx2_get_maxflows(flow_cfg)) 1198f0a1913fSSubbaraya Sundeep return -EINVAL; 1199f0a1913fSSubbaraya Sundeep 1200f0a1913fSSubbaraya Sundeep flow = otx2_find_flow(pfvf, location); 1201f0a1913fSSubbaraya Sundeep if (!flow) 1202f0a1913fSSubbaraya Sundeep return -ENOENT; 1203f0a1913fSSubbaraya Sundeep 12048e675581SHariprasad Kelam if (flow->rule_type & DMAC_FILTER_RULE) { 120579d2be38SHariprasad Kelam struct ethhdr *eth_hdr = &flow->flow_spec.h_u.ether_spec; 120679d2be38SHariprasad Kelam 120779d2be38SHariprasad Kelam /* user not allowed to remove dmac filter with interface mac */ 120879d2be38SHariprasad Kelam if (ether_addr_equal(pfvf->netdev->dev_addr, eth_hdr->h_dest)) 120979d2be38SHariprasad Kelam return -EPERM; 121079d2be38SHariprasad Kelam 121179d2be38SHariprasad Kelam err = otx2_dmacflt_remove(pfvf, eth_hdr->h_dest, 121279d2be38SHariprasad Kelam flow->entry); 1213*fa5e0ccbSRatheesh Kannoth clear_bit(flow->entry, flow_cfg->dmacflt_bmap); 121479d2be38SHariprasad Kelam /* If all dmac filters are removed delete macfilter with 121579d2be38SHariprasad Kelam * interface mac address and configure CGX/RPM block in 121679d2be38SHariprasad Kelam * promiscuous mode 121779d2be38SHariprasad Kelam */ 1218*fa5e0ccbSRatheesh Kannoth if (bitmap_weight(flow_cfg->dmacflt_bmap, 121979d2be38SHariprasad Kelam flow_cfg->dmacflt_max_flows) == 1) 122079d2be38SHariprasad Kelam otx2_update_rem_pfmac(pfvf, DMAC_ADDR_DEL); 122179d2be38SHariprasad Kelam } else { 12228e675581SHariprasad Kelam #ifdef CONFIG_DCB 12238e675581SHariprasad Kelam if (flow->rule_type & PFC_FLOWCTRL_RULE) 12248e675581SHariprasad Kelam otx2_update_bpid_in_rqctx(pfvf, 0, 12258e675581SHariprasad Kelam flow->flow_spec.ring_cookie, 12268e675581SHariprasad Kelam false); 12278e675581SHariprasad Kelam #endif 12288e675581SHariprasad Kelam 1229f0a1913fSSubbaraya Sundeep err = otx2_remove_flow_msg(pfvf, flow->entry, false); 123079d2be38SHariprasad Kelam } 123179d2be38SHariprasad Kelam 1232f0a1913fSSubbaraya Sundeep if (err) 1233f0a1913fSSubbaraya Sundeep return err; 1234f0a1913fSSubbaraya Sundeep 1235f0a1913fSSubbaraya Sundeep list_del(&flow->list); 1236f0a1913fSSubbaraya Sundeep kfree(flow); 1237f0a1913fSSubbaraya Sundeep flow_cfg->nr_flows--; 1238f0a1913fSSubbaraya Sundeep 1239f0a1913fSSubbaraya Sundeep return 0; 1240f0a1913fSSubbaraya Sundeep } 1241f0a1913fSSubbaraya Sundeep 124281a43620SGeetha sowjanya void otx2_rss_ctx_flow_del(struct otx2_nic *pfvf, int ctx_id) 124381a43620SGeetha sowjanya { 124481a43620SGeetha sowjanya struct otx2_flow *flow, *tmp; 124581a43620SGeetha sowjanya int err; 124681a43620SGeetha sowjanya 124781a43620SGeetha sowjanya list_for_each_entry_safe(flow, tmp, &pfvf->flow_cfg->flow_list, list) { 124881a43620SGeetha sowjanya if (flow->rss_ctx_id != ctx_id) 124981a43620SGeetha sowjanya continue; 125081a43620SGeetha sowjanya err = otx2_remove_flow(pfvf, flow->location); 125181a43620SGeetha sowjanya if (err) 125281a43620SGeetha sowjanya netdev_warn(pfvf->netdev, 125381a43620SGeetha sowjanya "Can't delete the rule %d associated with this rss group err:%d", 125481a43620SGeetha sowjanya flow->location, err); 125581a43620SGeetha sowjanya } 125681a43620SGeetha sowjanya } 125781a43620SGeetha sowjanya 1258f0a1913fSSubbaraya Sundeep int otx2_destroy_ntuple_flows(struct otx2_nic *pfvf) 1259f0a1913fSSubbaraya Sundeep { 1260f0a1913fSSubbaraya Sundeep struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 1261f0a1913fSSubbaraya Sundeep struct npc_delete_flow_req *req; 1262f0a1913fSSubbaraya Sundeep struct otx2_flow *iter, *tmp; 1263f0a1913fSSubbaraya Sundeep int err; 1264f0a1913fSSubbaraya Sundeep 1265f0a1913fSSubbaraya Sundeep if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT)) 1266f0a1913fSSubbaraya Sundeep return 0; 1267f0a1913fSSubbaraya Sundeep 1268a515e5b5SSunil Goutham if (!flow_cfg->max_flows) 1269a515e5b5SSunil Goutham return 0; 1270a515e5b5SSunil Goutham 1271f0a1913fSSubbaraya Sundeep mutex_lock(&pfvf->mbox.lock); 1272f0a1913fSSubbaraya Sundeep req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox); 1273f0a1913fSSubbaraya Sundeep if (!req) { 1274f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 1275f0a1913fSSubbaraya Sundeep return -ENOMEM; 1276f0a1913fSSubbaraya Sundeep } 1277f0a1913fSSubbaraya Sundeep 12789917060fSSunil Goutham req->start = flow_cfg->flow_ent[0]; 12792e2a8126SSunil Goutham req->end = flow_cfg->flow_ent[flow_cfg->max_flows - 1]; 1280f0a1913fSSubbaraya Sundeep err = otx2_sync_mbox_msg(&pfvf->mbox); 1281f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 1282f0a1913fSSubbaraya Sundeep 1283f0a1913fSSubbaraya Sundeep list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list, list) { 1284f0a1913fSSubbaraya Sundeep list_del(&iter->list); 1285f0a1913fSSubbaraya Sundeep kfree(iter); 1286f0a1913fSSubbaraya Sundeep flow_cfg->nr_flows--; 1287f0a1913fSSubbaraya Sundeep } 1288f0a1913fSSubbaraya Sundeep return err; 1289f0a1913fSSubbaraya Sundeep } 1290f0a1913fSSubbaraya Sundeep 1291f0a1913fSSubbaraya Sundeep int otx2_destroy_mcam_flows(struct otx2_nic *pfvf) 1292f0a1913fSSubbaraya Sundeep { 1293f0a1913fSSubbaraya Sundeep struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 1294f0a1913fSSubbaraya Sundeep struct npc_mcam_free_entry_req *req; 1295f0a1913fSSubbaraya Sundeep struct otx2_flow *iter, *tmp; 1296f0a1913fSSubbaraya Sundeep int err; 1297f0a1913fSSubbaraya Sundeep 1298f0a1913fSSubbaraya Sundeep if (!(pfvf->flags & OTX2_FLAG_MCAM_ENTRIES_ALLOC)) 1299f0a1913fSSubbaraya Sundeep return 0; 1300f0a1913fSSubbaraya Sundeep 1301f0a1913fSSubbaraya Sundeep /* remove all flows */ 1302f0a1913fSSubbaraya Sundeep err = otx2_remove_flow_msg(pfvf, 0, true); 1303f0a1913fSSubbaraya Sundeep if (err) 1304f0a1913fSSubbaraya Sundeep return err; 1305f0a1913fSSubbaraya Sundeep 1306f0a1913fSSubbaraya Sundeep list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list, list) { 1307f0a1913fSSubbaraya Sundeep list_del(&iter->list); 1308f0a1913fSSubbaraya Sundeep kfree(iter); 1309f0a1913fSSubbaraya Sundeep flow_cfg->nr_flows--; 1310f0a1913fSSubbaraya Sundeep } 1311f0a1913fSSubbaraya Sundeep 1312f0a1913fSSubbaraya Sundeep mutex_lock(&pfvf->mbox.lock); 1313f0a1913fSSubbaraya Sundeep req = otx2_mbox_alloc_msg_npc_mcam_free_entry(&pfvf->mbox); 1314f0a1913fSSubbaraya Sundeep if (!req) { 1315f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 1316f0a1913fSSubbaraya Sundeep return -ENOMEM; 1317f0a1913fSSubbaraya Sundeep } 1318f0a1913fSSubbaraya Sundeep 1319f0a1913fSSubbaraya Sundeep req->all = 1; 1320f0a1913fSSubbaraya Sundeep /* Send message to AF to free MCAM entries */ 1321f0a1913fSSubbaraya Sundeep err = otx2_sync_mbox_msg(&pfvf->mbox); 1322f0a1913fSSubbaraya Sundeep if (err) { 1323f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 1324f0a1913fSSubbaraya Sundeep return err; 1325f0a1913fSSubbaraya Sundeep } 1326f0a1913fSSubbaraya Sundeep 1327f0a1913fSSubbaraya Sundeep pfvf->flags &= ~OTX2_FLAG_MCAM_ENTRIES_ALLOC; 1328f0a1913fSSubbaraya Sundeep mutex_unlock(&pfvf->mbox.lock); 1329f0a1913fSSubbaraya Sundeep 1330f0a1913fSSubbaraya Sundeep return 0; 1331f0a1913fSSubbaraya Sundeep } 1332fd9d7859SHariprasad Kelam 1333fd9d7859SHariprasad Kelam int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf) 1334fd9d7859SHariprasad Kelam { 1335fd9d7859SHariprasad Kelam struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 1336fd9d7859SHariprasad Kelam struct npc_install_flow_req *req; 1337fd9d7859SHariprasad Kelam int err; 1338fd9d7859SHariprasad Kelam 1339fd9d7859SHariprasad Kelam mutex_lock(&pfvf->mbox.lock); 1340fd9d7859SHariprasad Kelam req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox); 1341fd9d7859SHariprasad Kelam if (!req) { 1342fd9d7859SHariprasad Kelam mutex_unlock(&pfvf->mbox.lock); 1343fd9d7859SHariprasad Kelam return -ENOMEM; 1344fd9d7859SHariprasad Kelam } 1345fd9d7859SHariprasad Kelam 13469917060fSSunil Goutham req->entry = flow_cfg->def_ent[flow_cfg->rx_vlan_offset]; 1347fd9d7859SHariprasad Kelam req->intf = NIX_INTF_RX; 1348fd9d7859SHariprasad Kelam ether_addr_copy(req->packet.dmac, pfvf->netdev->dev_addr); 1349fd9d7859SHariprasad Kelam eth_broadcast_addr((u8 *)&req->mask.dmac); 1350fd9d7859SHariprasad Kelam req->channel = pfvf->hw.rx_chan_base; 1351fd9d7859SHariprasad Kelam req->op = NIX_RX_ACTION_DEFAULT; 1352fd9d7859SHariprasad Kelam req->features = BIT_ULL(NPC_OUTER_VID) | BIT_ULL(NPC_DMAC); 1353fd9d7859SHariprasad Kelam req->vtag0_valid = true; 1354fd9d7859SHariprasad Kelam req->vtag0_type = NIX_AF_LFX_RX_VTAG_TYPE0; 1355fd9d7859SHariprasad Kelam 1356fd9d7859SHariprasad Kelam /* Send message to AF */ 1357fd9d7859SHariprasad Kelam err = otx2_sync_mbox_msg(&pfvf->mbox); 1358fd9d7859SHariprasad Kelam mutex_unlock(&pfvf->mbox.lock); 1359fd9d7859SHariprasad Kelam return err; 1360fd9d7859SHariprasad Kelam } 1361fd9d7859SHariprasad Kelam 1362fd9d7859SHariprasad Kelam static int otx2_delete_rxvlan_offload_flow(struct otx2_nic *pfvf) 1363fd9d7859SHariprasad Kelam { 1364fd9d7859SHariprasad Kelam struct otx2_flow_config *flow_cfg = pfvf->flow_cfg; 1365fd9d7859SHariprasad Kelam struct npc_delete_flow_req *req; 1366fd9d7859SHariprasad Kelam int err; 1367fd9d7859SHariprasad Kelam 1368fd9d7859SHariprasad Kelam mutex_lock(&pfvf->mbox.lock); 1369fd9d7859SHariprasad Kelam req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox); 1370fd9d7859SHariprasad Kelam if (!req) { 1371fd9d7859SHariprasad Kelam mutex_unlock(&pfvf->mbox.lock); 1372fd9d7859SHariprasad Kelam return -ENOMEM; 1373fd9d7859SHariprasad Kelam } 1374fd9d7859SHariprasad Kelam 13759917060fSSunil Goutham req->entry = flow_cfg->def_ent[flow_cfg->rx_vlan_offset]; 1376fd9d7859SHariprasad Kelam /* Send message to AF */ 1377fd9d7859SHariprasad Kelam err = otx2_sync_mbox_msg(&pfvf->mbox); 1378fd9d7859SHariprasad Kelam mutex_unlock(&pfvf->mbox.lock); 1379fd9d7859SHariprasad Kelam return err; 1380fd9d7859SHariprasad Kelam } 1381fd9d7859SHariprasad Kelam 1382fd9d7859SHariprasad Kelam int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable) 1383fd9d7859SHariprasad Kelam { 1384fd9d7859SHariprasad Kelam struct nix_vtag_config *req; 1385fd9d7859SHariprasad Kelam struct mbox_msghdr *rsp_hdr; 1386fd9d7859SHariprasad Kelam int err; 1387fd9d7859SHariprasad Kelam 1388fd9d7859SHariprasad Kelam /* Dont have enough mcam entries */ 1389fd9d7859SHariprasad Kelam if (!(pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT)) 1390fd9d7859SHariprasad Kelam return -ENOMEM; 1391fd9d7859SHariprasad Kelam 1392fd9d7859SHariprasad Kelam if (enable) { 1393fd9d7859SHariprasad Kelam err = otx2_install_rxvlan_offload_flow(pf); 1394fd9d7859SHariprasad Kelam if (err) 1395fd9d7859SHariprasad Kelam return err; 1396fd9d7859SHariprasad Kelam } else { 1397fd9d7859SHariprasad Kelam err = otx2_delete_rxvlan_offload_flow(pf); 1398fd9d7859SHariprasad Kelam if (err) 1399fd9d7859SHariprasad Kelam return err; 1400fd9d7859SHariprasad Kelam } 1401fd9d7859SHariprasad Kelam 1402fd9d7859SHariprasad Kelam mutex_lock(&pf->mbox.lock); 1403fd9d7859SHariprasad Kelam req = otx2_mbox_alloc_msg_nix_vtag_cfg(&pf->mbox); 1404fd9d7859SHariprasad Kelam if (!req) { 1405fd9d7859SHariprasad Kelam mutex_unlock(&pf->mbox.lock); 1406fd9d7859SHariprasad Kelam return -ENOMEM; 1407fd9d7859SHariprasad Kelam } 1408fd9d7859SHariprasad Kelam 1409fd9d7859SHariprasad Kelam /* config strip, capture and size */ 1410fd9d7859SHariprasad Kelam req->vtag_size = VTAGSIZE_T4; 1411fd9d7859SHariprasad Kelam req->cfg_type = 1; /* rx vlan cfg */ 1412fd9d7859SHariprasad Kelam req->rx.vtag_type = NIX_AF_LFX_RX_VTAG_TYPE0; 1413fd9d7859SHariprasad Kelam req->rx.strip_vtag = enable; 1414fd9d7859SHariprasad Kelam req->rx.capture_vtag = enable; 1415fd9d7859SHariprasad Kelam 1416fd9d7859SHariprasad Kelam err = otx2_sync_mbox_msg(&pf->mbox); 1417fd9d7859SHariprasad Kelam if (err) { 1418fd9d7859SHariprasad Kelam mutex_unlock(&pf->mbox.lock); 1419fd9d7859SHariprasad Kelam return err; 1420fd9d7859SHariprasad Kelam } 1421fd9d7859SHariprasad Kelam 1422fd9d7859SHariprasad Kelam rsp_hdr = otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr); 1423fd9d7859SHariprasad Kelam if (IS_ERR(rsp_hdr)) { 1424fd9d7859SHariprasad Kelam mutex_unlock(&pf->mbox.lock); 1425fd9d7859SHariprasad Kelam return PTR_ERR(rsp_hdr); 1426fd9d7859SHariprasad Kelam } 1427fd9d7859SHariprasad Kelam 1428fd9d7859SHariprasad Kelam mutex_unlock(&pf->mbox.lock); 1429fd9d7859SHariprasad Kelam return rsp_hdr->rc; 1430fd9d7859SHariprasad Kelam } 143179d2be38SHariprasad Kelam 143279d2be38SHariprasad Kelam void otx2_dmacflt_reinstall_flows(struct otx2_nic *pf) 143379d2be38SHariprasad Kelam { 143479d2be38SHariprasad Kelam struct otx2_flow *iter; 143579d2be38SHariprasad Kelam struct ethhdr *eth_hdr; 143679d2be38SHariprasad Kelam 143779d2be38SHariprasad Kelam list_for_each_entry(iter, &pf->flow_cfg->flow_list, list) { 14388e675581SHariprasad Kelam if (iter->rule_type & DMAC_FILTER_RULE) { 143979d2be38SHariprasad Kelam eth_hdr = &iter->flow_spec.h_u.ether_spec; 144079d2be38SHariprasad Kelam otx2_dmacflt_add(pf, eth_hdr->h_dest, 144179d2be38SHariprasad Kelam iter->entry); 144279d2be38SHariprasad Kelam } 144379d2be38SHariprasad Kelam } 144479d2be38SHariprasad Kelam } 144579d2be38SHariprasad Kelam 144679d2be38SHariprasad Kelam void otx2_dmacflt_update_pfmac_flow(struct otx2_nic *pfvf) 144779d2be38SHariprasad Kelam { 144879d2be38SHariprasad Kelam otx2_update_rem_pfmac(pfvf, DMAC_ADDR_UPDATE); 144979d2be38SHariprasad Kelam } 1450