xref: /openbmc/linux/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c (revision ecc23d0a422a3118fcf6e4f0a46e17a6c2047b02)
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;
21fa5e0ccbSRatheesh 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 
otx2_clear_ntuple_flow_info(struct otx2_nic * pfvf,struct otx2_flow_config * flow_cfg)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 
otx2_free_ntuple_mcam_entries(struct otx2_nic * pfvf)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 
mcam_entry_cmp(const void * a,const void * b)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 
otx2_alloc_mcam_entries(struct otx2_nic * pfvf,u16 count)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);
124*c4eae7baSDipendra Khadka 		if (IS_ERR(rsp))
125*c4eae7baSDipendra Khadka 			goto exit;
1269917060fSSunil Goutham 
1279917060fSSunil Goutham 		for (ent = 0; ent < rsp->count; ent++)
1289917060fSSunil Goutham 			flow_cfg->flow_ent[ent + allocated] = rsp->entry_list[ent];
1299917060fSSunil Goutham 
1309917060fSSunil Goutham 		allocated += rsp->count;
1319917060fSSunil Goutham 
1329917060fSSunil Goutham 		/* If this request is not fulfilled, no need to send
1339917060fSSunil Goutham 		 * further requests.
1349917060fSSunil Goutham 		 */
1359917060fSSunil Goutham 		if (rsp->count != req->count)
1369917060fSSunil Goutham 			break;
1379917060fSSunil Goutham 	}
1389917060fSSunil Goutham 
139cc65fcabSSunil Goutham 	/* Multiple MCAM entry alloc requests could result in non-sequential
140cc65fcabSSunil Goutham 	 * MCAM entries in the flow_ent[] array. Sort them in an ascending order,
141cc65fcabSSunil Goutham 	 * otherwise user installed ntuple filter index and MCAM entry index will
142cc65fcabSSunil Goutham 	 * not be in sync.
143cc65fcabSSunil Goutham 	 */
144cc65fcabSSunil Goutham 	if (allocated)
145cc65fcabSSunil Goutham 		sort(&flow_cfg->flow_ent[0], allocated,
146cc65fcabSSunil Goutham 		     sizeof(flow_cfg->flow_ent[0]), mcam_entry_cmp, NULL);
147cc65fcabSSunil Goutham 
1489917060fSSunil Goutham exit:
1499917060fSSunil Goutham 	mutex_unlock(&pfvf->mbox.lock);
1509917060fSSunil Goutham 
1512e2a8126SSunil Goutham 	flow_cfg->max_flows = allocated;
1529917060fSSunil Goutham 
1532da48943SSunil Goutham 	if (allocated) {
1543cffaed2SRakesh Babu 		pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
1553cffaed2SRakesh Babu 		pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
1562da48943SSunil Goutham 	}
1573cffaed2SRakesh Babu 
1589917060fSSunil Goutham 	if (allocated != count)
1599917060fSSunil Goutham 		netdev_info(pfvf->netdev,
1603cffaed2SRakesh Babu 			    "Unable to allocate %d MCAM entries, got only %d\n",
1619917060fSSunil Goutham 			    count, allocated);
1629917060fSSunil Goutham 	return allocated;
1639917060fSSunil Goutham }
1642da48943SSunil Goutham EXPORT_SYMBOL(otx2_alloc_mcam_entries);
1659917060fSSunil Goutham 
otx2_mcam_entry_init(struct otx2_nic * pfvf)1662da48943SSunil Goutham static int otx2_mcam_entry_init(struct otx2_nic *pfvf)
167f0a1913fSSubbaraya Sundeep {
168f0a1913fSSubbaraya Sundeep 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
169674b3e16SSuman Ghosh 	struct npc_get_field_status_req *freq;
170674b3e16SSuman Ghosh 	struct npc_get_field_status_rsp *frsp;
171f0a1913fSSubbaraya Sundeep 	struct npc_mcam_alloc_entry_req *req;
172f0a1913fSSubbaraya Sundeep 	struct npc_mcam_alloc_entry_rsp *rsp;
173f0c2982aSNaveen Mamindlapalli 	int vf_vlan_max_flows;
1749917060fSSunil Goutham 	int ent, count;
1759917060fSSunil Goutham 
1769917060fSSunil Goutham 	vf_vlan_max_flows = pfvf->total_vfs * OTX2_PER_VF_VLAN_FLOWS;
1779917060fSSunil Goutham 	count = OTX2_MAX_UNICAST_FLOWS +
1789917060fSSunil Goutham 			OTX2_MAX_VLAN_FLOWS + vf_vlan_max_flows;
1799917060fSSunil Goutham 
1809917060fSSunil Goutham 	flow_cfg->def_ent = devm_kmalloc_array(pfvf->dev, count,
1819917060fSSunil Goutham 					       sizeof(u16), GFP_KERNEL);
1829917060fSSunil Goutham 	if (!flow_cfg->def_ent)
1839917060fSSunil Goutham 		return -ENOMEM;
184f0a1913fSSubbaraya Sundeep 
185f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
186f0a1913fSSubbaraya Sundeep 
187f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_mcam_alloc_entry(&pfvf->mbox);
188f0a1913fSSubbaraya Sundeep 	if (!req) {
189f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
190f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
191f0a1913fSSubbaraya Sundeep 	}
192f0a1913fSSubbaraya Sundeep 
193f0a1913fSSubbaraya Sundeep 	req->contig = false;
1949917060fSSunil Goutham 	req->count = count;
195f0a1913fSSubbaraya Sundeep 
196f0a1913fSSubbaraya Sundeep 	/* Send message to AF */
197f0a1913fSSubbaraya Sundeep 	if (otx2_sync_mbox_msg(&pfvf->mbox)) {
198f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
199f0a1913fSSubbaraya Sundeep 		return -EINVAL;
200f0a1913fSSubbaraya Sundeep 	}
201f0a1913fSSubbaraya Sundeep 
202f0a1913fSSubbaraya Sundeep 	rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
203f0a1913fSSubbaraya Sundeep 	       (&pfvf->mbox.mbox, 0, &req->hdr);
204*c4eae7baSDipendra Khadka 	if (IS_ERR(rsp)) {
205*c4eae7baSDipendra Khadka 		mutex_unlock(&pfvf->mbox.lock);
206*c4eae7baSDipendra Khadka 		return PTR_ERR(rsp);
207*c4eae7baSDipendra Khadka 	}
208f0a1913fSSubbaraya Sundeep 
20963ee5157SHariprasad Kelam 	if (rsp->count != req->count) {
210f0a1913fSSubbaraya Sundeep 		netdev_info(pfvf->netdev,
2119917060fSSunil Goutham 			    "Unable to allocate MCAM entries for ucast, vlan and vf_vlan\n");
2129917060fSSunil Goutham 		mutex_unlock(&pfvf->mbox.lock);
2139917060fSSunil Goutham 		devm_kfree(pfvf->dev, flow_cfg->def_ent);
2149917060fSSunil Goutham 		return 0;
2159917060fSSunil Goutham 	}
2169917060fSSunil Goutham 
2179917060fSSunil Goutham 	for (ent = 0; ent < rsp->count; ent++)
2189917060fSSunil Goutham 		flow_cfg->def_ent[ent] = rsp->entry_list[ent];
2199917060fSSunil Goutham 
220f0c2982aSNaveen Mamindlapalli 	flow_cfg->vf_vlan_offset = 0;
2219917060fSSunil Goutham 	flow_cfg->unicast_offset = vf_vlan_max_flows;
222fd9d7859SHariprasad Kelam 	flow_cfg->rx_vlan_offset = flow_cfg->unicast_offset +
223fd9d7859SHariprasad Kelam 					OTX2_MAX_UNICAST_FLOWS;
22463ee5157SHariprasad Kelam 	pfvf->flags |= OTX2_FLAG_UCAST_FLTR_SUPPORT;
225674b3e16SSuman Ghosh 
226674b3e16SSuman Ghosh 	/* Check if NPC_DMAC field is supported
227674b3e16SSuman Ghosh 	 * by the mkex profile before setting VLAN support flag.
228674b3e16SSuman Ghosh 	 */
229674b3e16SSuman Ghosh 	freq = otx2_mbox_alloc_msg_npc_get_field_status(&pfvf->mbox);
230674b3e16SSuman Ghosh 	if (!freq) {
231674b3e16SSuman Ghosh 		mutex_unlock(&pfvf->mbox.lock);
232674b3e16SSuman Ghosh 		return -ENOMEM;
233674b3e16SSuman Ghosh 	}
234674b3e16SSuman Ghosh 
235674b3e16SSuman Ghosh 	freq->field = NPC_DMAC;
236674b3e16SSuman Ghosh 	if (otx2_sync_mbox_msg(&pfvf->mbox)) {
237674b3e16SSuman Ghosh 		mutex_unlock(&pfvf->mbox.lock);
238674b3e16SSuman Ghosh 		return -EINVAL;
239674b3e16SSuman Ghosh 	}
240674b3e16SSuman Ghosh 
241674b3e16SSuman Ghosh 	frsp = (struct npc_get_field_status_rsp *)otx2_mbox_get_rsp
242674b3e16SSuman Ghosh 	       (&pfvf->mbox.mbox, 0, &freq->hdr);
243*c4eae7baSDipendra Khadka 	if (IS_ERR(frsp)) {
244*c4eae7baSDipendra Khadka 		mutex_unlock(&pfvf->mbox.lock);
245*c4eae7baSDipendra Khadka 		return PTR_ERR(frsp);
246*c4eae7baSDipendra Khadka 	}
247674b3e16SSuman Ghosh 
248674b3e16SSuman Ghosh 	if (frsp->enable) {
249fd9d7859SHariprasad Kelam 		pfvf->flags |= OTX2_FLAG_RX_VLAN_SUPPORT;
250f0c2982aSNaveen Mamindlapalli 		pfvf->flags |= OTX2_FLAG_VF_VLAN_SUPPORT;
251674b3e16SSuman Ghosh 	}
252f0a1913fSSubbaraya Sundeep 
253f0a1913fSSubbaraya Sundeep 	pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
254f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
255f0a1913fSSubbaraya Sundeep 
2569917060fSSunil Goutham 	/* Allocate entries for Ntuple filters */
2572da48943SSunil Goutham 	count = otx2_alloc_mcam_entries(pfvf, OTX2_DEFAULT_FLOWCOUNT);
2589917060fSSunil Goutham 	if (count <= 0) {
2599917060fSSunil Goutham 		otx2_clear_ntuple_flow_info(pfvf, flow_cfg);
2609917060fSSunil Goutham 		return 0;
2619917060fSSunil Goutham 	}
2629917060fSSunil Goutham 
2639917060fSSunil Goutham 	pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT;
2649917060fSSunil Goutham 
265f0a1913fSSubbaraya Sundeep 	return 0;
266f0a1913fSSubbaraya Sundeep }
267f0a1913fSSubbaraya Sundeep 
268fa5e0ccbSRatheesh Kannoth /* TODO : revisit on size */
269fa5e0ccbSRatheesh Kannoth #define OTX2_DMAC_FLTR_BITMAP_SZ (4 * 2048 + 32)
270fa5e0ccbSRatheesh Kannoth 
otx2vf_mcam_flow_init(struct otx2_nic * pfvf)2713cffaed2SRakesh Babu int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
2723cffaed2SRakesh Babu {
2733cffaed2SRakesh Babu 	struct otx2_flow_config *flow_cfg;
2743cffaed2SRakesh Babu 
2753cffaed2SRakesh Babu 	pfvf->flow_cfg = devm_kzalloc(pfvf->dev,
2763cffaed2SRakesh Babu 				      sizeof(struct otx2_flow_config),
2773cffaed2SRakesh Babu 				      GFP_KERNEL);
2783cffaed2SRakesh Babu 	if (!pfvf->flow_cfg)
2793cffaed2SRakesh Babu 		return -ENOMEM;
2803cffaed2SRakesh Babu 
281fa5e0ccbSRatheesh Kannoth 	pfvf->flow_cfg->dmacflt_bmap = devm_kcalloc(pfvf->dev,
282fa5e0ccbSRatheesh Kannoth 						    BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ),
283fa5e0ccbSRatheesh Kannoth 						    sizeof(long), GFP_KERNEL);
284fa5e0ccbSRatheesh Kannoth 	if (!pfvf->flow_cfg->dmacflt_bmap)
285fa5e0ccbSRatheesh Kannoth 		return -ENOMEM;
286fa5e0ccbSRatheesh Kannoth 
2873cffaed2SRakesh Babu 	flow_cfg = pfvf->flow_cfg;
2883cffaed2SRakesh Babu 	INIT_LIST_HEAD(&flow_cfg->flow_list);
289ec87f054SSuman Ghosh 	INIT_LIST_HEAD(&flow_cfg->flow_list_tc);
2902e2a8126SSunil Goutham 	flow_cfg->max_flows = 0;
2913cffaed2SRakesh Babu 
2923cffaed2SRakesh Babu 	return 0;
2933cffaed2SRakesh Babu }
2943cffaed2SRakesh Babu EXPORT_SYMBOL(otx2vf_mcam_flow_init);
2953cffaed2SRakesh Babu 
otx2_mcam_flow_init(struct otx2_nic * pf)296f0a1913fSSubbaraya Sundeep int otx2_mcam_flow_init(struct otx2_nic *pf)
297f0a1913fSSubbaraya Sundeep {
298f0a1913fSSubbaraya Sundeep 	int err;
299f0a1913fSSubbaraya Sundeep 
300f0a1913fSSubbaraya Sundeep 	pf->flow_cfg = devm_kzalloc(pf->dev, sizeof(struct otx2_flow_config),
301f0a1913fSSubbaraya Sundeep 				    GFP_KERNEL);
302f0a1913fSSubbaraya Sundeep 	if (!pf->flow_cfg)
303f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
304f0a1913fSSubbaraya Sundeep 
305fa5e0ccbSRatheesh Kannoth 	pf->flow_cfg->dmacflt_bmap = devm_kcalloc(pf->dev,
306fa5e0ccbSRatheesh Kannoth 						  BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ),
307fa5e0ccbSRatheesh Kannoth 						  sizeof(long), GFP_KERNEL);
308fa5e0ccbSRatheesh Kannoth 	if (!pf->flow_cfg->dmacflt_bmap)
309fa5e0ccbSRatheesh Kannoth 		return -ENOMEM;
310fa5e0ccbSRatheesh Kannoth 
311f0a1913fSSubbaraya Sundeep 	INIT_LIST_HEAD(&pf->flow_cfg->flow_list);
312ec87f054SSuman Ghosh 	INIT_LIST_HEAD(&pf->flow_cfg->flow_list_tc);
313f0a1913fSSubbaraya Sundeep 
3142da48943SSunil Goutham 	/* Allocate bare minimum number of MCAM entries needed for
3152da48943SSunil Goutham 	 * unicast and ntuple filters.
3162da48943SSunil Goutham 	 */
3172da48943SSunil Goutham 	err = otx2_mcam_entry_init(pf);
318f0a1913fSSubbaraya Sundeep 	if (err)
319f0a1913fSSubbaraya Sundeep 		return err;
320f0a1913fSSubbaraya Sundeep 
3219917060fSSunil Goutham 	/* Check if MCAM entries are allocate or not */
3229917060fSSunil Goutham 	if (!(pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT))
3239917060fSSunil Goutham 		return 0;
3249917060fSSunil Goutham 
32563ee5157SHariprasad Kelam 	pf->mac_table = devm_kzalloc(pf->dev, sizeof(struct otx2_mac_table)
32663ee5157SHariprasad Kelam 					* OTX2_MAX_UNICAST_FLOWS, GFP_KERNEL);
32763ee5157SHariprasad Kelam 	if (!pf->mac_table)
32863ee5157SHariprasad Kelam 		return -ENOMEM;
32963ee5157SHariprasad Kelam 
33079d2be38SHariprasad Kelam 	otx2_dmacflt_get_max_cnt(pf);
33179d2be38SHariprasad Kelam 
33279d2be38SHariprasad Kelam 	/* DMAC filters are not allocated */
33379d2be38SHariprasad Kelam 	if (!pf->flow_cfg->dmacflt_max_flows)
33479d2be38SHariprasad Kelam 		return 0;
33579d2be38SHariprasad Kelam 
33679d2be38SHariprasad Kelam 	pf->flow_cfg->bmap_to_dmacindex =
337fa5e0ccbSRatheesh Kannoth 			devm_kzalloc(pf->dev, sizeof(u32) *
33879d2be38SHariprasad Kelam 				     pf->flow_cfg->dmacflt_max_flows,
33979d2be38SHariprasad Kelam 				     GFP_KERNEL);
34079d2be38SHariprasad Kelam 
34179d2be38SHariprasad Kelam 	if (!pf->flow_cfg->bmap_to_dmacindex)
34279d2be38SHariprasad Kelam 		return -ENOMEM;
34379d2be38SHariprasad Kelam 
34479d2be38SHariprasad Kelam 	pf->flags |= OTX2_FLAG_DMACFLTR_SUPPORT;
34579d2be38SHariprasad Kelam 
346f0a1913fSSubbaraya Sundeep 	return 0;
347f0a1913fSSubbaraya Sundeep }
348f0a1913fSSubbaraya Sundeep 
otx2_mcam_flow_del(struct otx2_nic * pf)349f0a1913fSSubbaraya Sundeep void otx2_mcam_flow_del(struct otx2_nic *pf)
350f0a1913fSSubbaraya Sundeep {
351f0a1913fSSubbaraya Sundeep 	otx2_destroy_mcam_flows(pf);
352f0a1913fSSubbaraya Sundeep }
3533cffaed2SRakesh Babu EXPORT_SYMBOL(otx2_mcam_flow_del);
354f0a1913fSSubbaraya Sundeep 
35563ee5157SHariprasad Kelam /*  On success adds mcam entry
35663ee5157SHariprasad Kelam  *  On failure enable promisous mode
35763ee5157SHariprasad Kelam  */
otx2_do_add_macfilter(struct otx2_nic * pf,const u8 * mac)35863ee5157SHariprasad Kelam static int otx2_do_add_macfilter(struct otx2_nic *pf, const u8 *mac)
35963ee5157SHariprasad Kelam {
36063ee5157SHariprasad Kelam 	struct otx2_flow_config *flow_cfg = pf->flow_cfg;
36163ee5157SHariprasad Kelam 	struct npc_install_flow_req *req;
36263ee5157SHariprasad Kelam 	int err, i;
36363ee5157SHariprasad Kelam 
36463ee5157SHariprasad Kelam 	if (!(pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT))
36563ee5157SHariprasad Kelam 		return -ENOMEM;
36663ee5157SHariprasad Kelam 
36763ee5157SHariprasad Kelam 	/* dont have free mcam entries or uc list is greater than alloted */
36863ee5157SHariprasad Kelam 	if (netdev_uc_count(pf->netdev) > OTX2_MAX_UNICAST_FLOWS)
36963ee5157SHariprasad Kelam 		return -ENOMEM;
37063ee5157SHariprasad Kelam 
37163ee5157SHariprasad Kelam 	mutex_lock(&pf->mbox.lock);
37263ee5157SHariprasad Kelam 	req = otx2_mbox_alloc_msg_npc_install_flow(&pf->mbox);
37363ee5157SHariprasad Kelam 	if (!req) {
37463ee5157SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
37563ee5157SHariprasad Kelam 		return -ENOMEM;
37663ee5157SHariprasad Kelam 	}
37763ee5157SHariprasad Kelam 
37863ee5157SHariprasad Kelam 	/* unicast offset starts with 32 0..31 for ntuple */
37963ee5157SHariprasad Kelam 	for (i = 0; i <  OTX2_MAX_UNICAST_FLOWS; i++) {
38063ee5157SHariprasad Kelam 		if (pf->mac_table[i].inuse)
38163ee5157SHariprasad Kelam 			continue;
38263ee5157SHariprasad Kelam 		ether_addr_copy(pf->mac_table[i].addr, mac);
38363ee5157SHariprasad Kelam 		pf->mac_table[i].inuse = true;
38463ee5157SHariprasad Kelam 		pf->mac_table[i].mcam_entry =
3859917060fSSunil Goutham 			flow_cfg->def_ent[i + flow_cfg->unicast_offset];
38663ee5157SHariprasad Kelam 		req->entry =  pf->mac_table[i].mcam_entry;
38763ee5157SHariprasad Kelam 		break;
38863ee5157SHariprasad Kelam 	}
38963ee5157SHariprasad Kelam 
39063ee5157SHariprasad Kelam 	ether_addr_copy(req->packet.dmac, mac);
39163ee5157SHariprasad Kelam 	eth_broadcast_addr((u8 *)&req->mask.dmac);
39263ee5157SHariprasad Kelam 	req->features = BIT_ULL(NPC_DMAC);
39363ee5157SHariprasad Kelam 	req->channel = pf->hw.rx_chan_base;
39463ee5157SHariprasad Kelam 	req->intf = NIX_INTF_RX;
39563ee5157SHariprasad Kelam 	req->op = NIX_RX_ACTION_DEFAULT;
39663ee5157SHariprasad Kelam 	req->set_cntr = 1;
39763ee5157SHariprasad Kelam 
39863ee5157SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pf->mbox);
39963ee5157SHariprasad Kelam 	mutex_unlock(&pf->mbox.lock);
40063ee5157SHariprasad Kelam 
40163ee5157SHariprasad Kelam 	return err;
40263ee5157SHariprasad Kelam }
40363ee5157SHariprasad Kelam 
otx2_add_macfilter(struct net_device * netdev,const u8 * mac)40463ee5157SHariprasad Kelam int otx2_add_macfilter(struct net_device *netdev, const u8 *mac)
40563ee5157SHariprasad Kelam {
40663ee5157SHariprasad Kelam 	struct otx2_nic *pf = netdev_priv(netdev);
40763ee5157SHariprasad Kelam 
408fa5e0ccbSRatheesh Kannoth 	if (!bitmap_empty(pf->flow_cfg->dmacflt_bmap,
40979d2be38SHariprasad Kelam 			  pf->flow_cfg->dmacflt_max_flows))
41079d2be38SHariprasad Kelam 		netdev_warn(netdev,
41179d2be38SHariprasad Kelam 			    "Add %pM to CGX/RPM DMAC filters list as well\n",
41279d2be38SHariprasad Kelam 			    mac);
41379d2be38SHariprasad Kelam 
41463ee5157SHariprasad Kelam 	return otx2_do_add_macfilter(pf, mac);
41563ee5157SHariprasad Kelam }
41663ee5157SHariprasad Kelam 
otx2_get_mcamentry_for_mac(struct otx2_nic * pf,const u8 * mac,int * mcam_entry)41763ee5157SHariprasad Kelam static bool otx2_get_mcamentry_for_mac(struct otx2_nic *pf, const u8 *mac,
41863ee5157SHariprasad Kelam 				       int *mcam_entry)
41963ee5157SHariprasad Kelam {
42063ee5157SHariprasad Kelam 	int i;
42163ee5157SHariprasad Kelam 
42263ee5157SHariprasad Kelam 	for (i = 0; i < OTX2_MAX_UNICAST_FLOWS; i++) {
42363ee5157SHariprasad Kelam 		if (!pf->mac_table[i].inuse)
42463ee5157SHariprasad Kelam 			continue;
42563ee5157SHariprasad Kelam 
42663ee5157SHariprasad Kelam 		if (ether_addr_equal(pf->mac_table[i].addr, mac)) {
42763ee5157SHariprasad Kelam 			*mcam_entry = pf->mac_table[i].mcam_entry;
42863ee5157SHariprasad Kelam 			pf->mac_table[i].inuse = false;
42963ee5157SHariprasad Kelam 			return true;
43063ee5157SHariprasad Kelam 		}
43163ee5157SHariprasad Kelam 	}
43263ee5157SHariprasad Kelam 	return false;
43363ee5157SHariprasad Kelam }
43463ee5157SHariprasad Kelam 
otx2_del_macfilter(struct net_device * netdev,const u8 * mac)43563ee5157SHariprasad Kelam int otx2_del_macfilter(struct net_device *netdev, const u8 *mac)
43663ee5157SHariprasad Kelam {
43763ee5157SHariprasad Kelam 	struct otx2_nic *pf = netdev_priv(netdev);
43863ee5157SHariprasad Kelam 	struct npc_delete_flow_req *req;
43963ee5157SHariprasad Kelam 	int err, mcam_entry;
44063ee5157SHariprasad Kelam 
44163ee5157SHariprasad Kelam 	/* check does mcam entry exists for given mac */
44263ee5157SHariprasad Kelam 	if (!otx2_get_mcamentry_for_mac(pf, mac, &mcam_entry))
44363ee5157SHariprasad Kelam 		return 0;
44463ee5157SHariprasad Kelam 
44563ee5157SHariprasad Kelam 	mutex_lock(&pf->mbox.lock);
44663ee5157SHariprasad Kelam 	req = otx2_mbox_alloc_msg_npc_delete_flow(&pf->mbox);
44763ee5157SHariprasad Kelam 	if (!req) {
44863ee5157SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
44963ee5157SHariprasad Kelam 		return -ENOMEM;
45063ee5157SHariprasad Kelam 	}
45163ee5157SHariprasad Kelam 	req->entry = mcam_entry;
45263ee5157SHariprasad Kelam 	/* Send message to AF */
45363ee5157SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pf->mbox);
45463ee5157SHariprasad Kelam 	mutex_unlock(&pf->mbox.lock);
45563ee5157SHariprasad Kelam 
45663ee5157SHariprasad Kelam 	return err;
45763ee5157SHariprasad Kelam }
45863ee5157SHariprasad Kelam 
otx2_find_flow(struct otx2_nic * pfvf,u32 location)459f0a1913fSSubbaraya Sundeep static struct otx2_flow *otx2_find_flow(struct otx2_nic *pfvf, u32 location)
460f0a1913fSSubbaraya Sundeep {
461f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter;
462f0a1913fSSubbaraya Sundeep 
463f0a1913fSSubbaraya Sundeep 	list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
464f0a1913fSSubbaraya Sundeep 		if (iter->location == location)
465f0a1913fSSubbaraya Sundeep 			return iter;
466f0a1913fSSubbaraya Sundeep 	}
467f0a1913fSSubbaraya Sundeep 
468f0a1913fSSubbaraya Sundeep 	return NULL;
469f0a1913fSSubbaraya Sundeep }
470f0a1913fSSubbaraya Sundeep 
otx2_add_flow_to_list(struct otx2_nic * pfvf,struct otx2_flow * flow)471f0a1913fSSubbaraya Sundeep static void otx2_add_flow_to_list(struct otx2_nic *pfvf, struct otx2_flow *flow)
472f0a1913fSSubbaraya Sundeep {
473f0a1913fSSubbaraya Sundeep 	struct list_head *head = &pfvf->flow_cfg->flow_list;
474f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter;
475f0a1913fSSubbaraya Sundeep 
476f0a1913fSSubbaraya Sundeep 	list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
477f0a1913fSSubbaraya Sundeep 		if (iter->location > flow->location)
478f0a1913fSSubbaraya Sundeep 			break;
479f0a1913fSSubbaraya Sundeep 		head = &iter->list;
480f0a1913fSSubbaraya Sundeep 	}
481f0a1913fSSubbaraya Sundeep 
482f0a1913fSSubbaraya Sundeep 	list_add(&flow->list, head);
483f0a1913fSSubbaraya Sundeep }
484f0a1913fSSubbaraya Sundeep 
otx2_get_maxflows(struct otx2_flow_config * flow_cfg)4853cffaed2SRakesh Babu int otx2_get_maxflows(struct otx2_flow_config *flow_cfg)
48679d2be38SHariprasad Kelam {
4873cffaed2SRakesh Babu 	if (!flow_cfg)
4883cffaed2SRakesh Babu 		return 0;
4893cffaed2SRakesh Babu 
4902e2a8126SSunil Goutham 	if (flow_cfg->nr_flows == flow_cfg->max_flows ||
491fa5e0ccbSRatheesh Kannoth 	    !bitmap_empty(flow_cfg->dmacflt_bmap,
49279d2be38SHariprasad Kelam 			  flow_cfg->dmacflt_max_flows))
4932e2a8126SSunil Goutham 		return flow_cfg->max_flows + flow_cfg->dmacflt_max_flows;
49479d2be38SHariprasad Kelam 	else
4952e2a8126SSunil Goutham 		return flow_cfg->max_flows;
49679d2be38SHariprasad Kelam }
4973cffaed2SRakesh Babu EXPORT_SYMBOL(otx2_get_maxflows);
49879d2be38SHariprasad Kelam 
otx2_get_flow(struct otx2_nic * pfvf,struct ethtool_rxnfc * nfc,u32 location)499f0a1913fSSubbaraya Sundeep int otx2_get_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
500f0a1913fSSubbaraya Sundeep 		  u32 location)
501f0a1913fSSubbaraya Sundeep {
502f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter;
503f0a1913fSSubbaraya Sundeep 
50479d2be38SHariprasad Kelam 	if (location >= otx2_get_maxflows(pfvf->flow_cfg))
505f0a1913fSSubbaraya Sundeep 		return -EINVAL;
506f0a1913fSSubbaraya Sundeep 
507f0a1913fSSubbaraya Sundeep 	list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
508f0a1913fSSubbaraya Sundeep 		if (iter->location == location) {
509f0a1913fSSubbaraya Sundeep 			nfc->fs = iter->flow_spec;
51081a43620SGeetha sowjanya 			nfc->rss_context = iter->rss_ctx_id;
511f0a1913fSSubbaraya Sundeep 			return 0;
512f0a1913fSSubbaraya Sundeep 		}
513f0a1913fSSubbaraya Sundeep 	}
514f0a1913fSSubbaraya Sundeep 
515f0a1913fSSubbaraya Sundeep 	return -ENOENT;
516f0a1913fSSubbaraya Sundeep }
517f0a1913fSSubbaraya Sundeep 
otx2_get_all_flows(struct otx2_nic * pfvf,struct ethtool_rxnfc * nfc,u32 * rule_locs)518f0a1913fSSubbaraya Sundeep int otx2_get_all_flows(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
519f0a1913fSSubbaraya Sundeep 		       u32 *rule_locs)
520f0a1913fSSubbaraya Sundeep {
521f41b2d67SSubbaraya Sundeep 	u32 rule_cnt = nfc->rule_cnt;
522f0a1913fSSubbaraya Sundeep 	u32 location = 0;
523f0a1913fSSubbaraya Sundeep 	int idx = 0;
524f0a1913fSSubbaraya Sundeep 	int err = 0;
525f0a1913fSSubbaraya Sundeep 
52679d2be38SHariprasad Kelam 	nfc->data = otx2_get_maxflows(pfvf->flow_cfg);
527f41b2d67SSubbaraya Sundeep 	while ((!err || err == -ENOENT) && idx < rule_cnt) {
528f0a1913fSSubbaraya Sundeep 		err = otx2_get_flow(pfvf, nfc, location);
529f0a1913fSSubbaraya Sundeep 		if (!err)
530f0a1913fSSubbaraya Sundeep 			rule_locs[idx++] = location;
531f0a1913fSSubbaraya Sundeep 		location++;
532f0a1913fSSubbaraya Sundeep 	}
533f41b2d67SSubbaraya Sundeep 	nfc->rule_cnt = rule_cnt;
534f0a1913fSSubbaraya Sundeep 
535f0a1913fSSubbaraya Sundeep 	return err;
536f0a1913fSSubbaraya Sundeep }
537f0a1913fSSubbaraya Sundeep 
otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec * fsp,struct npc_install_flow_req * req,u32 flow_type)538b7cf9661SNaveen Mamindlapalli static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp,
539f0a1913fSSubbaraya Sundeep 				  struct npc_install_flow_req *req,
540f0a1913fSSubbaraya Sundeep 				  u32 flow_type)
541f0a1913fSSubbaraya Sundeep {
542f0a1913fSSubbaraya Sundeep 	struct ethtool_usrip4_spec *ipv4_usr_mask = &fsp->m_u.usr_ip4_spec;
543f0a1913fSSubbaraya Sundeep 	struct ethtool_usrip4_spec *ipv4_usr_hdr = &fsp->h_u.usr_ip4_spec;
544f0a1913fSSubbaraya Sundeep 	struct ethtool_tcpip4_spec *ipv4_l4_mask = &fsp->m_u.tcp_ip4_spec;
545f0a1913fSSubbaraya Sundeep 	struct ethtool_tcpip4_spec *ipv4_l4_hdr = &fsp->h_u.tcp_ip4_spec;
546b7cf9661SNaveen Mamindlapalli 	struct ethtool_ah_espip4_spec *ah_esp_hdr = &fsp->h_u.ah_ip4_spec;
547b7cf9661SNaveen Mamindlapalli 	struct ethtool_ah_espip4_spec *ah_esp_mask = &fsp->m_u.ah_ip4_spec;
548f0a1913fSSubbaraya Sundeep 	struct flow_msg *pmask = &req->mask;
549f0a1913fSSubbaraya Sundeep 	struct flow_msg *pkt = &req->packet;
550f0a1913fSSubbaraya Sundeep 
551f0a1913fSSubbaraya Sundeep 	switch (flow_type) {
552f0a1913fSSubbaraya Sundeep 	case IP_USER_FLOW:
553f0a1913fSSubbaraya Sundeep 		if (ipv4_usr_mask->ip4src) {
554f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip4src, &ipv4_usr_hdr->ip4src,
555f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip4src));
556f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip4src, &ipv4_usr_mask->ip4src,
557f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip4src));
558f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SIP_IPV4);
559f0a1913fSSubbaraya Sundeep 		}
560f0a1913fSSubbaraya Sundeep 		if (ipv4_usr_mask->ip4dst) {
561f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip4dst, &ipv4_usr_hdr->ip4dst,
562f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip4dst));
563f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip4dst, &ipv4_usr_mask->ip4dst,
564f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip4dst));
565f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DIP_IPV4);
566f0a1913fSSubbaraya Sundeep 		}
5672b9cef66SNaveen Mamindlapalli 		if (ipv4_usr_mask->tos) {
5682b9cef66SNaveen Mamindlapalli 			pkt->tos = ipv4_usr_hdr->tos;
5692b9cef66SNaveen Mamindlapalli 			pmask->tos = ipv4_usr_mask->tos;
5702b9cef66SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_TOS);
5712b9cef66SNaveen Mamindlapalli 		}
5722b9cef66SNaveen Mamindlapalli 		if (ipv4_usr_mask->proto) {
5732b9cef66SNaveen Mamindlapalli 			switch (ipv4_usr_hdr->proto) {
5742b9cef66SNaveen Mamindlapalli 			case IPPROTO_ICMP:
5752b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_ICMP);
5762b9cef66SNaveen Mamindlapalli 				break;
5772b9cef66SNaveen Mamindlapalli 			case IPPROTO_TCP:
5782b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_TCP);
5792b9cef66SNaveen Mamindlapalli 				break;
5802b9cef66SNaveen Mamindlapalli 			case IPPROTO_UDP:
5812b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_UDP);
5822b9cef66SNaveen Mamindlapalli 				break;
5832b9cef66SNaveen Mamindlapalli 			case IPPROTO_SCTP:
5842b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_SCTP);
5852b9cef66SNaveen Mamindlapalli 				break;
5862b9cef66SNaveen Mamindlapalli 			case IPPROTO_AH:
5872b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_AH);
5882b9cef66SNaveen Mamindlapalli 				break;
5892b9cef66SNaveen Mamindlapalli 			case IPPROTO_ESP:
5902b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_ESP);
5912b9cef66SNaveen Mamindlapalli 				break;
5922b9cef66SNaveen Mamindlapalli 			default:
5932b9cef66SNaveen Mamindlapalli 				return -EOPNOTSUPP;
5942b9cef66SNaveen Mamindlapalli 			}
5952b9cef66SNaveen Mamindlapalli 		}
596b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IP);
597b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
598b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
599f0a1913fSSubbaraya Sundeep 		break;
600f0a1913fSSubbaraya Sundeep 	case TCP_V4_FLOW:
601f0a1913fSSubbaraya Sundeep 	case UDP_V4_FLOW:
602f0a1913fSSubbaraya Sundeep 	case SCTP_V4_FLOW:
603b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IP);
604b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
605b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
606f0a1913fSSubbaraya Sundeep 		if (ipv4_l4_mask->ip4src) {
607f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip4src, &ipv4_l4_hdr->ip4src,
608f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip4src));
609f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip4src, &ipv4_l4_mask->ip4src,
610f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip4src));
611f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SIP_IPV4);
612f0a1913fSSubbaraya Sundeep 		}
613f0a1913fSSubbaraya Sundeep 		if (ipv4_l4_mask->ip4dst) {
614f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip4dst, &ipv4_l4_hdr->ip4dst,
615f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip4dst));
616f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip4dst, &ipv4_l4_mask->ip4dst,
617f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip4dst));
618f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DIP_IPV4);
619f0a1913fSSubbaraya Sundeep 		}
6202b9cef66SNaveen Mamindlapalli 		if (ipv4_l4_mask->tos) {
6212b9cef66SNaveen Mamindlapalli 			pkt->tos = ipv4_l4_hdr->tos;
6222b9cef66SNaveen Mamindlapalli 			pmask->tos = ipv4_l4_mask->tos;
6232b9cef66SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_TOS);
6242b9cef66SNaveen Mamindlapalli 		}
625f0a1913fSSubbaraya Sundeep 		if (ipv4_l4_mask->psrc) {
626f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->sport, &ipv4_l4_hdr->psrc,
627f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->sport));
628f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->sport, &ipv4_l4_mask->psrc,
629f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->sport));
630f0a1913fSSubbaraya Sundeep 			if (flow_type == UDP_V4_FLOW)
631f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_UDP);
632f0a1913fSSubbaraya Sundeep 			else if (flow_type == TCP_V4_FLOW)
633f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_TCP);
634f0a1913fSSubbaraya Sundeep 			else
635f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_SCTP);
636f0a1913fSSubbaraya Sundeep 		}
637f0a1913fSSubbaraya Sundeep 		if (ipv4_l4_mask->pdst) {
638f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->dport, &ipv4_l4_hdr->pdst,
639f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->dport));
640f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->dport, &ipv4_l4_mask->pdst,
641f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->dport));
642f0a1913fSSubbaraya Sundeep 			if (flow_type == UDP_V4_FLOW)
643f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_UDP);
644f0a1913fSSubbaraya Sundeep 			else if (flow_type == TCP_V4_FLOW)
645f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_TCP);
646f0a1913fSSubbaraya Sundeep 			else
647f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_SCTP);
648f0a1913fSSubbaraya Sundeep 		}
649b7cf9661SNaveen Mamindlapalli 		if (flow_type == UDP_V4_FLOW)
650b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_UDP);
651b7cf9661SNaveen Mamindlapalli 		else if (flow_type == TCP_V4_FLOW)
652b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_TCP);
653b7cf9661SNaveen Mamindlapalli 		else
654b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_SCTP);
655b7cf9661SNaveen Mamindlapalli 		break;
656b7cf9661SNaveen Mamindlapalli 	case AH_V4_FLOW:
657b7cf9661SNaveen Mamindlapalli 	case ESP_V4_FLOW:
658b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IP);
659b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
660b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
661b7cf9661SNaveen Mamindlapalli 		if (ah_esp_mask->ip4src) {
662b7cf9661SNaveen Mamindlapalli 			memcpy(&pkt->ip4src, &ah_esp_hdr->ip4src,
663b7cf9661SNaveen Mamindlapalli 			       sizeof(pkt->ip4src));
664b7cf9661SNaveen Mamindlapalli 			memcpy(&pmask->ip4src, &ah_esp_mask->ip4src,
665b7cf9661SNaveen Mamindlapalli 			       sizeof(pmask->ip4src));
666b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_SIP_IPV4);
667b7cf9661SNaveen Mamindlapalli 		}
668b7cf9661SNaveen Mamindlapalli 		if (ah_esp_mask->ip4dst) {
669b7cf9661SNaveen Mamindlapalli 			memcpy(&pkt->ip4dst, &ah_esp_hdr->ip4dst,
670b7cf9661SNaveen Mamindlapalli 			       sizeof(pkt->ip4dst));
671b7cf9661SNaveen Mamindlapalli 			memcpy(&pmask->ip4dst, &ah_esp_mask->ip4dst,
672b7cf9661SNaveen Mamindlapalli 			       sizeof(pmask->ip4dst));
673b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_DIP_IPV4);
674b7cf9661SNaveen Mamindlapalli 		}
6752b9cef66SNaveen Mamindlapalli 		if (ah_esp_mask->tos) {
6762b9cef66SNaveen Mamindlapalli 			pkt->tos = ah_esp_hdr->tos;
6772b9cef66SNaveen Mamindlapalli 			pmask->tos = ah_esp_mask->tos;
6782b9cef66SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_TOS);
6792b9cef66SNaveen Mamindlapalli 		}
680b7cf9661SNaveen Mamindlapalli 
681b7cf9661SNaveen Mamindlapalli 		/* NPC profile doesn't extract AH/ESP header fields */
6822b9cef66SNaveen Mamindlapalli 		if (ah_esp_mask->spi & ah_esp_hdr->spi)
683b7cf9661SNaveen Mamindlapalli 			return -EOPNOTSUPP;
684b7cf9661SNaveen Mamindlapalli 
685b7cf9661SNaveen Mamindlapalli 		if (flow_type == AH_V4_FLOW)
686b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_AH);
687b7cf9661SNaveen Mamindlapalli 		else
688b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_ESP);
689f0a1913fSSubbaraya Sundeep 		break;
690f0a1913fSSubbaraya Sundeep 	default:
691f0a1913fSSubbaraya Sundeep 		break;
692f0a1913fSSubbaraya Sundeep 	}
693b7cf9661SNaveen Mamindlapalli 
694b7cf9661SNaveen Mamindlapalli 	return 0;
695f0a1913fSSubbaraya Sundeep }
696f0a1913fSSubbaraya Sundeep 
otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec * fsp,struct npc_install_flow_req * req,u32 flow_type)697b7cf9661SNaveen Mamindlapalli static int otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec *fsp,
698f0a1913fSSubbaraya Sundeep 				  struct npc_install_flow_req *req,
699f0a1913fSSubbaraya Sundeep 				  u32 flow_type)
700f0a1913fSSubbaraya Sundeep {
701f0a1913fSSubbaraya Sundeep 	struct ethtool_usrip6_spec *ipv6_usr_mask = &fsp->m_u.usr_ip6_spec;
702f0a1913fSSubbaraya Sundeep 	struct ethtool_usrip6_spec *ipv6_usr_hdr = &fsp->h_u.usr_ip6_spec;
703f0a1913fSSubbaraya Sundeep 	struct ethtool_tcpip6_spec *ipv6_l4_mask = &fsp->m_u.tcp_ip6_spec;
704f0a1913fSSubbaraya Sundeep 	struct ethtool_tcpip6_spec *ipv6_l4_hdr = &fsp->h_u.tcp_ip6_spec;
705b7cf9661SNaveen Mamindlapalli 	struct ethtool_ah_espip6_spec *ah_esp_hdr = &fsp->h_u.ah_ip6_spec;
706b7cf9661SNaveen Mamindlapalli 	struct ethtool_ah_espip6_spec *ah_esp_mask = &fsp->m_u.ah_ip6_spec;
707f0a1913fSSubbaraya Sundeep 	struct flow_msg *pmask = &req->mask;
708f0a1913fSSubbaraya Sundeep 	struct flow_msg *pkt = &req->packet;
709f0a1913fSSubbaraya Sundeep 
710f0a1913fSSubbaraya Sundeep 	switch (flow_type) {
711f0a1913fSSubbaraya Sundeep 	case IPV6_USER_FLOW:
712f0a1913fSSubbaraya Sundeep 		if (!ipv6_addr_any((struct in6_addr *)ipv6_usr_mask->ip6src)) {
713f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip6src, &ipv6_usr_hdr->ip6src,
714f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip6src));
715f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip6src, &ipv6_usr_mask->ip6src,
716f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip6src));
717f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SIP_IPV6);
718f0a1913fSSubbaraya Sundeep 		}
719f0a1913fSSubbaraya Sundeep 		if (!ipv6_addr_any((struct in6_addr *)ipv6_usr_mask->ip6dst)) {
720f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip6dst, &ipv6_usr_hdr->ip6dst,
721f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip6dst));
722f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip6dst, &ipv6_usr_mask->ip6dst,
723f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip6dst));
724f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DIP_IPV6);
725f0a1913fSSubbaraya Sundeep 		}
726c672e372SSuman Ghosh 		if (ipv6_usr_hdr->l4_proto == IPPROTO_FRAGMENT) {
727c672e372SSuman Ghosh 			pkt->next_header = ipv6_usr_hdr->l4_proto;
728c672e372SSuman Ghosh 			pmask->next_header = ipv6_usr_mask->l4_proto;
729c672e372SSuman Ghosh 			req->features |= BIT_ULL(NPC_IPFRAG_IPV6);
730c672e372SSuman Ghosh 		}
731b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IPV6);
732b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
733b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
734f0a1913fSSubbaraya Sundeep 		break;
735f0a1913fSSubbaraya Sundeep 	case TCP_V6_FLOW:
736f0a1913fSSubbaraya Sundeep 	case UDP_V6_FLOW:
737f0a1913fSSubbaraya Sundeep 	case SCTP_V6_FLOW:
738b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IPV6);
739b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
740b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
741f0a1913fSSubbaraya Sundeep 		if (!ipv6_addr_any((struct in6_addr *)ipv6_l4_mask->ip6src)) {
742f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip6src, &ipv6_l4_hdr->ip6src,
743f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip6src));
744f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip6src, &ipv6_l4_mask->ip6src,
745f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip6src));
746f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SIP_IPV6);
747f0a1913fSSubbaraya Sundeep 		}
748f0a1913fSSubbaraya Sundeep 		if (!ipv6_addr_any((struct in6_addr *)ipv6_l4_mask->ip6dst)) {
749f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip6dst, &ipv6_l4_hdr->ip6dst,
750f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip6dst));
751f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip6dst, &ipv6_l4_mask->ip6dst,
752f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip6dst));
753f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DIP_IPV6);
754f0a1913fSSubbaraya Sundeep 		}
755f0a1913fSSubbaraya Sundeep 		if (ipv6_l4_mask->psrc) {
756f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->sport, &ipv6_l4_hdr->psrc,
757f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->sport));
758f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->sport, &ipv6_l4_mask->psrc,
759f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->sport));
760f0a1913fSSubbaraya Sundeep 			if (flow_type == UDP_V6_FLOW)
761f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_UDP);
762f0a1913fSSubbaraya Sundeep 			else if (flow_type == TCP_V6_FLOW)
763f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_TCP);
764f0a1913fSSubbaraya Sundeep 			else
765f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_SCTP);
766f0a1913fSSubbaraya Sundeep 		}
767f0a1913fSSubbaraya Sundeep 		if (ipv6_l4_mask->pdst) {
768f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->dport, &ipv6_l4_hdr->pdst,
769f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->dport));
770f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->dport, &ipv6_l4_mask->pdst,
771f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->dport));
772f0a1913fSSubbaraya Sundeep 			if (flow_type == UDP_V6_FLOW)
773f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_UDP);
774f0a1913fSSubbaraya Sundeep 			else if (flow_type == TCP_V6_FLOW)
775f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_TCP);
776f0a1913fSSubbaraya Sundeep 			else
777f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_SCTP);
778f0a1913fSSubbaraya Sundeep 		}
779b7cf9661SNaveen Mamindlapalli 		if (flow_type == UDP_V6_FLOW)
780b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_UDP);
781b7cf9661SNaveen Mamindlapalli 		else if (flow_type == TCP_V6_FLOW)
782b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_TCP);
783b7cf9661SNaveen Mamindlapalli 		else
784b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_SCTP);
785f0a1913fSSubbaraya Sundeep 		break;
786b7cf9661SNaveen Mamindlapalli 	case AH_V6_FLOW:
787b7cf9661SNaveen Mamindlapalli 	case ESP_V6_FLOW:
788b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IPV6);
789b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
790b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
791b7cf9661SNaveen Mamindlapalli 		if (!ipv6_addr_any((struct in6_addr *)ah_esp_hdr->ip6src)) {
792b7cf9661SNaveen Mamindlapalli 			memcpy(&pkt->ip6src, &ah_esp_hdr->ip6src,
793b7cf9661SNaveen Mamindlapalli 			       sizeof(pkt->ip6src));
794b7cf9661SNaveen Mamindlapalli 			memcpy(&pmask->ip6src, &ah_esp_mask->ip6src,
795b7cf9661SNaveen Mamindlapalli 			       sizeof(pmask->ip6src));
796b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_SIP_IPV6);
797b7cf9661SNaveen Mamindlapalli 		}
798b7cf9661SNaveen Mamindlapalli 		if (!ipv6_addr_any((struct in6_addr *)ah_esp_hdr->ip6dst)) {
799b7cf9661SNaveen Mamindlapalli 			memcpy(&pkt->ip6dst, &ah_esp_hdr->ip6dst,
800b7cf9661SNaveen Mamindlapalli 			       sizeof(pkt->ip6dst));
801b7cf9661SNaveen Mamindlapalli 			memcpy(&pmask->ip6dst, &ah_esp_mask->ip6dst,
802b7cf9661SNaveen Mamindlapalli 			       sizeof(pmask->ip6dst));
803b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_DIP_IPV6);
804b7cf9661SNaveen Mamindlapalli 		}
805b7cf9661SNaveen Mamindlapalli 
806b7cf9661SNaveen Mamindlapalli 		/* NPC profile doesn't extract AH/ESP header fields */
807b7cf9661SNaveen Mamindlapalli 		if ((ah_esp_mask->spi & ah_esp_hdr->spi) ||
8083acd9db9SDeepak R Varma 		    (ah_esp_mask->tclass & ah_esp_hdr->tclass))
809b7cf9661SNaveen Mamindlapalli 			return -EOPNOTSUPP;
810b7cf9661SNaveen Mamindlapalli 
811b7cf9661SNaveen Mamindlapalli 		if (flow_type == AH_V6_FLOW)
812b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_AH);
813b7cf9661SNaveen Mamindlapalli 		else
814b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_ESP);
815320daffdSGustavo A. R. Silva 		break;
816f0a1913fSSubbaraya Sundeep 	default:
817f0a1913fSSubbaraya Sundeep 		break;
818f0a1913fSSubbaraya Sundeep 	}
819b7cf9661SNaveen Mamindlapalli 
820b7cf9661SNaveen Mamindlapalli 	return 0;
821f0a1913fSSubbaraya Sundeep }
822f0a1913fSSubbaraya Sundeep 
otx2_prepare_flow_request(struct ethtool_rx_flow_spec * fsp,struct npc_install_flow_req * req)823dce677daSSubbaraya Sundeep static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
824f0a1913fSSubbaraya Sundeep 			      struct npc_install_flow_req *req)
825f0a1913fSSubbaraya Sundeep {
826f0a1913fSSubbaraya Sundeep 	struct ethhdr *eth_mask = &fsp->m_u.ether_spec;
827f0a1913fSSubbaraya Sundeep 	struct ethhdr *eth_hdr = &fsp->h_u.ether_spec;
828f0a1913fSSubbaraya Sundeep 	struct flow_msg *pmask = &req->mask;
829f0a1913fSSubbaraya Sundeep 	struct flow_msg *pkt = &req->packet;
830f0a1913fSSubbaraya Sundeep 	u32 flow_type;
831b7cf9661SNaveen Mamindlapalli 	int ret;
832f0a1913fSSubbaraya Sundeep 
83381a43620SGeetha sowjanya 	flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
834f0a1913fSSubbaraya Sundeep 	switch (flow_type) {
835f0a1913fSSubbaraya Sundeep 	/* bits not set in mask are don't care */
836f0a1913fSSubbaraya Sundeep 	case ETHER_FLOW:
837f0a1913fSSubbaraya Sundeep 		if (!is_zero_ether_addr(eth_mask->h_source)) {
838f0a1913fSSubbaraya Sundeep 			ether_addr_copy(pkt->smac, eth_hdr->h_source);
839f0a1913fSSubbaraya Sundeep 			ether_addr_copy(pmask->smac, eth_mask->h_source);
840f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SMAC);
841f0a1913fSSubbaraya Sundeep 		}
842f0a1913fSSubbaraya Sundeep 		if (!is_zero_ether_addr(eth_mask->h_dest)) {
843f0a1913fSSubbaraya Sundeep 			ether_addr_copy(pkt->dmac, eth_hdr->h_dest);
844f0a1913fSSubbaraya Sundeep 			ether_addr_copy(pmask->dmac, eth_mask->h_dest);
845f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DMAC);
846f0a1913fSSubbaraya Sundeep 		}
8473cffaed2SRakesh Babu 		if (eth_hdr->h_proto) {
848f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->etype, &eth_hdr->h_proto,
849f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->etype));
850f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->etype, &eth_mask->h_proto,
851f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->etype));
852f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_ETYPE);
853f0a1913fSSubbaraya Sundeep 		}
854f0a1913fSSubbaraya Sundeep 		break;
855f0a1913fSSubbaraya Sundeep 	case IP_USER_FLOW:
856f0a1913fSSubbaraya Sundeep 	case TCP_V4_FLOW:
857f0a1913fSSubbaraya Sundeep 	case UDP_V4_FLOW:
858f0a1913fSSubbaraya Sundeep 	case SCTP_V4_FLOW:
859b7cf9661SNaveen Mamindlapalli 	case AH_V4_FLOW:
860b7cf9661SNaveen Mamindlapalli 	case ESP_V4_FLOW:
861b7cf9661SNaveen Mamindlapalli 		ret = otx2_prepare_ipv4_flow(fsp, req, flow_type);
862b7cf9661SNaveen Mamindlapalli 		if (ret)
863b7cf9661SNaveen Mamindlapalli 			return ret;
864f0a1913fSSubbaraya Sundeep 		break;
865f0a1913fSSubbaraya Sundeep 	case IPV6_USER_FLOW:
866f0a1913fSSubbaraya Sundeep 	case TCP_V6_FLOW:
867f0a1913fSSubbaraya Sundeep 	case UDP_V6_FLOW:
868f0a1913fSSubbaraya Sundeep 	case SCTP_V6_FLOW:
869b7cf9661SNaveen Mamindlapalli 	case AH_V6_FLOW:
870b7cf9661SNaveen Mamindlapalli 	case ESP_V6_FLOW:
871b7cf9661SNaveen Mamindlapalli 		ret = otx2_prepare_ipv6_flow(fsp, req, flow_type);
872b7cf9661SNaveen Mamindlapalli 		if (ret)
873b7cf9661SNaveen Mamindlapalli 			return ret;
874f0a1913fSSubbaraya Sundeep 		break;
875f0a1913fSSubbaraya Sundeep 	default:
876f0a1913fSSubbaraya Sundeep 		return -EOPNOTSUPP;
877f0a1913fSSubbaraya Sundeep 	}
878f0a1913fSSubbaraya Sundeep 	if (fsp->flow_type & FLOW_EXT) {
879dce677daSSubbaraya Sundeep 		u16 vlan_etype;
880dce677daSSubbaraya Sundeep 
881dce677daSSubbaraya Sundeep 		if (fsp->m_ext.vlan_etype) {
882dce677daSSubbaraya Sundeep 			/* Partial masks not supported */
883dce677daSSubbaraya Sundeep 			if (be16_to_cpu(fsp->m_ext.vlan_etype) != 0xFFFF)
884f0a1913fSSubbaraya Sundeep 				return -EINVAL;
885dce677daSSubbaraya Sundeep 
886dce677daSSubbaraya Sundeep 			vlan_etype = be16_to_cpu(fsp->h_ext.vlan_etype);
8878278ee2aSSuman Ghosh 
8888278ee2aSSuman Ghosh 			/* Drop rule with vlan_etype == 802.1Q
8898278ee2aSSuman Ghosh 			 * and vlan_id == 0 is not supported
8908278ee2aSSuman Ghosh 			 */
8918278ee2aSSuman Ghosh 			if (vlan_etype == ETH_P_8021Q && !fsp->m_ext.vlan_tci &&
8928278ee2aSSuman Ghosh 			    fsp->ring_cookie == RX_CLS_FLOW_DISC)
8938278ee2aSSuman Ghosh 				return -EINVAL;
8948278ee2aSSuman Ghosh 
895dce677daSSubbaraya Sundeep 			/* Only ETH_P_8021Q and ETH_P_802AD types supported */
896dce677daSSubbaraya Sundeep 			if (vlan_etype != ETH_P_8021Q &&
897dce677daSSubbaraya Sundeep 			    vlan_etype != ETH_P_8021AD)
898dce677daSSubbaraya Sundeep 				return -EINVAL;
899dce677daSSubbaraya Sundeep 
900dce677daSSubbaraya Sundeep 			memcpy(&pkt->vlan_etype, &fsp->h_ext.vlan_etype,
901dce677daSSubbaraya Sundeep 			       sizeof(pkt->vlan_etype));
902dce677daSSubbaraya Sundeep 			memcpy(&pmask->vlan_etype, &fsp->m_ext.vlan_etype,
903dce677daSSubbaraya Sundeep 			       sizeof(pmask->vlan_etype));
904dce677daSSubbaraya Sundeep 
905dce677daSSubbaraya Sundeep 			if (vlan_etype == ETH_P_8021Q)
906dce677daSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_VLAN_ETYPE_CTAG);
907dce677daSSubbaraya Sundeep 			else
908dce677daSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_VLAN_ETYPE_STAG);
909dce677daSSubbaraya Sundeep 		}
910dce677daSSubbaraya Sundeep 
911f0a1913fSSubbaraya Sundeep 		if (fsp->m_ext.vlan_tci) {
912f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->vlan_tci, &fsp->h_ext.vlan_tci,
913f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->vlan_tci));
914f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->vlan_tci, &fsp->m_ext.vlan_tci,
915f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->vlan_tci));
916f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_OUTER_VID);
917f0a1913fSSubbaraya Sundeep 		}
918f0a1913fSSubbaraya Sundeep 
919c672e372SSuman Ghosh 		if (fsp->m_ext.data[1]) {
920c672e372SSuman Ghosh 			if (flow_type == IP_USER_FLOW) {
921c672e372SSuman Ghosh 				if (be32_to_cpu(fsp->h_ext.data[1]) != IPV4_FLAG_MORE)
922c672e372SSuman Ghosh 					return -EINVAL;
923c672e372SSuman Ghosh 
924c672e372SSuman Ghosh 				pkt->ip_flag = be32_to_cpu(fsp->h_ext.data[1]);
925c672e372SSuman Ghosh 				pmask->ip_flag = be32_to_cpu(fsp->m_ext.data[1]);
926c672e372SSuman Ghosh 				req->features |= BIT_ULL(NPC_IPFRAG_IPV4);
927c672e372SSuman Ghosh 			} else if (fsp->h_ext.data[1] ==
928c672e372SSuman Ghosh 					cpu_to_be32(OTX2_DEFAULT_ACTION)) {
929c672e372SSuman Ghosh 				/* Not Drop/Direct to queue but use action
930c672e372SSuman Ghosh 				 * in default entry
931c672e372SSuman Ghosh 				 */
932f0a1913fSSubbaraya Sundeep 				req->op = NIX_RX_ACTION_DEFAULT;
933f0a1913fSSubbaraya Sundeep 			}
934c672e372SSuman Ghosh 		}
935c672e372SSuman Ghosh 	}
936f0a1913fSSubbaraya Sundeep 
937f0a1913fSSubbaraya Sundeep 	if (fsp->flow_type & FLOW_MAC_EXT &&
938f0a1913fSSubbaraya Sundeep 	    !is_zero_ether_addr(fsp->m_ext.h_dest)) {
939f0a1913fSSubbaraya Sundeep 		ether_addr_copy(pkt->dmac, fsp->h_ext.h_dest);
940f0a1913fSSubbaraya Sundeep 		ether_addr_copy(pmask->dmac, fsp->m_ext.h_dest);
941f0a1913fSSubbaraya Sundeep 		req->features |= BIT_ULL(NPC_DMAC);
942f0a1913fSSubbaraya Sundeep 	}
943f0a1913fSSubbaraya Sundeep 
944f0a1913fSSubbaraya Sundeep 	if (!req->features)
945f0a1913fSSubbaraya Sundeep 		return -EOPNOTSUPP;
946f0a1913fSSubbaraya Sundeep 
947f0a1913fSSubbaraya Sundeep 	return 0;
948f0a1913fSSubbaraya Sundeep }
949f0a1913fSSubbaraya Sundeep 
otx2_is_flow_rule_dmacfilter(struct otx2_nic * pfvf,struct ethtool_rx_flow_spec * fsp)95079d2be38SHariprasad Kelam static int otx2_is_flow_rule_dmacfilter(struct otx2_nic *pfvf,
95179d2be38SHariprasad Kelam 					struct ethtool_rx_flow_spec *fsp)
95279d2be38SHariprasad Kelam {
95379d2be38SHariprasad Kelam 	struct ethhdr *eth_mask = &fsp->m_u.ether_spec;
95479d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr = &fsp->h_u.ether_spec;
95579d2be38SHariprasad Kelam 	u64 ring_cookie = fsp->ring_cookie;
95679d2be38SHariprasad Kelam 	u32 flow_type;
95779d2be38SHariprasad Kelam 
95879d2be38SHariprasad Kelam 	if (!(pfvf->flags & OTX2_FLAG_DMACFLTR_SUPPORT))
95979d2be38SHariprasad Kelam 		return false;
96079d2be38SHariprasad Kelam 
96179d2be38SHariprasad Kelam 	flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
96279d2be38SHariprasad Kelam 
96379d2be38SHariprasad Kelam 	/* CGX/RPM block dmac filtering configured for white listing
96479d2be38SHariprasad Kelam 	 * check for action other than DROP
96579d2be38SHariprasad Kelam 	 */
96679d2be38SHariprasad Kelam 	if (flow_type == ETHER_FLOW && ring_cookie != RX_CLS_FLOW_DISC &&
96779d2be38SHariprasad Kelam 	    !ethtool_get_flow_spec_ring_vf(ring_cookie)) {
96879d2be38SHariprasad Kelam 		if (is_zero_ether_addr(eth_mask->h_dest) &&
96979d2be38SHariprasad Kelam 		    is_valid_ether_addr(eth_hdr->h_dest))
97079d2be38SHariprasad Kelam 			return true;
97179d2be38SHariprasad Kelam 	}
97279d2be38SHariprasad Kelam 
97379d2be38SHariprasad Kelam 	return false;
97479d2be38SHariprasad Kelam }
97579d2be38SHariprasad Kelam 
otx2_add_flow_msg(struct otx2_nic * pfvf,struct otx2_flow * flow)976f0a1913fSSubbaraya Sundeep static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow)
977f0a1913fSSubbaraya Sundeep {
978f0a1913fSSubbaraya Sundeep 	u64 ring_cookie = flow->flow_spec.ring_cookie;
9798e675581SHariprasad Kelam #ifdef CONFIG_DCB
9808e675581SHariprasad Kelam 	int vlan_prio, qidx, pfc_rule = 0;
9818e675581SHariprasad Kelam #endif
982f0a1913fSSubbaraya Sundeep 	struct npc_install_flow_req *req;
983f0a1913fSSubbaraya Sundeep 	int err, vf = 0;
984f0a1913fSSubbaraya Sundeep 
985f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
986f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox);
987f0a1913fSSubbaraya Sundeep 	if (!req) {
988f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
989f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
990f0a1913fSSubbaraya Sundeep 	}
991f0a1913fSSubbaraya Sundeep 
992f0a1913fSSubbaraya Sundeep 	err = otx2_prepare_flow_request(&flow->flow_spec, req);
993f0a1913fSSubbaraya Sundeep 	if (err) {
994f0a1913fSSubbaraya Sundeep 		/* free the allocated msg above */
995f0a1913fSSubbaraya Sundeep 		otx2_mbox_reset(&pfvf->mbox.mbox, 0);
996f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
997f0a1913fSSubbaraya Sundeep 		return err;
998f0a1913fSSubbaraya Sundeep 	}
999f0a1913fSSubbaraya Sundeep 
1000f0a1913fSSubbaraya Sundeep 	req->entry = flow->entry;
1001f0a1913fSSubbaraya Sundeep 	req->intf = NIX_INTF_RX;
1002f0a1913fSSubbaraya Sundeep 	req->set_cntr = 1;
1003f0a1913fSSubbaraya Sundeep 	req->channel = pfvf->hw.rx_chan_base;
1004f0a1913fSSubbaraya Sundeep 	if (ring_cookie == RX_CLS_FLOW_DISC) {
1005f0a1913fSSubbaraya Sundeep 		req->op = NIX_RX_ACTIONOP_DROP;
1006f0a1913fSSubbaraya Sundeep 	} else {
1007f0a1913fSSubbaraya Sundeep 		/* change to unicast only if action of default entry is not
1008f0a1913fSSubbaraya Sundeep 		 * requested by user
1009f0a1913fSSubbaraya Sundeep 		 */
101081a43620SGeetha sowjanya 		if (flow->flow_spec.flow_type & FLOW_RSS) {
101181a43620SGeetha sowjanya 			req->op = NIX_RX_ACTIONOP_RSS;
101281a43620SGeetha sowjanya 			req->index = flow->rss_ctx_id;
1013e7938365SSunil Goutham 			req->flow_key_alg = pfvf->hw.flowkey_alg_idx;
101481a43620SGeetha sowjanya 		} else {
1015f0a1913fSSubbaraya Sundeep 			req->op = NIX_RX_ACTIONOP_UCAST;
1016f0a1913fSSubbaraya Sundeep 			req->index = ethtool_get_flow_spec_ring(ring_cookie);
101781a43620SGeetha sowjanya 		}
1018f0a1913fSSubbaraya Sundeep 		vf = ethtool_get_flow_spec_ring_vf(ring_cookie);
1019f0a1913fSSubbaraya Sundeep 		if (vf > pci_num_vf(pfvf->pdev)) {
1020f0a1913fSSubbaraya Sundeep 			mutex_unlock(&pfvf->mbox.lock);
1021f0a1913fSSubbaraya Sundeep 			return -EINVAL;
1022f0a1913fSSubbaraya Sundeep 		}
10238e675581SHariprasad Kelam 
10248e675581SHariprasad Kelam #ifdef CONFIG_DCB
10258e675581SHariprasad Kelam 		/* Identify PFC rule if PFC enabled and ntuple rule is vlan */
10268e675581SHariprasad Kelam 		if (!vf && (req->features & BIT_ULL(NPC_OUTER_VID)) &&
10278e675581SHariprasad Kelam 		    pfvf->pfc_en && req->op != NIX_RX_ACTIONOP_RSS) {
10288e675581SHariprasad Kelam 			vlan_prio = ntohs(req->packet.vlan_tci) &
10298e675581SHariprasad Kelam 				    ntohs(req->mask.vlan_tci);
10308e675581SHariprasad Kelam 
10318e675581SHariprasad Kelam 			/* Get the priority */
10328e675581SHariprasad Kelam 			vlan_prio >>= 13;
10338e675581SHariprasad Kelam 			flow->rule_type |= PFC_FLOWCTRL_RULE;
10348e675581SHariprasad Kelam 			/* Check if PFC enabled for this priority */
10358e675581SHariprasad Kelam 			if (pfvf->pfc_en & BIT(vlan_prio)) {
10368e675581SHariprasad Kelam 				pfc_rule = true;
10378e675581SHariprasad Kelam 				qidx = req->index;
10388e675581SHariprasad Kelam 			}
10398e675581SHariprasad Kelam 		}
10408e675581SHariprasad Kelam #endif
1041f0a1913fSSubbaraya Sundeep 	}
1042f0a1913fSSubbaraya Sundeep 
1043f0a1913fSSubbaraya Sundeep 	/* ethtool ring_cookie has (VF + 1) for VF */
1044f0a1913fSSubbaraya Sundeep 	if (vf) {
1045f0a1913fSSubbaraya Sundeep 		req->vf = vf;
1046f0a1913fSSubbaraya Sundeep 		flow->is_vf = true;
1047f0a1913fSSubbaraya Sundeep 		flow->vf = vf;
1048f0a1913fSSubbaraya Sundeep 	}
1049f0a1913fSSubbaraya Sundeep 
1050f0a1913fSSubbaraya Sundeep 	/* Send message to AF */
1051f0a1913fSSubbaraya Sundeep 	err = otx2_sync_mbox_msg(&pfvf->mbox);
10528e675581SHariprasad Kelam 
10538e675581SHariprasad Kelam #ifdef CONFIG_DCB
10548e675581SHariprasad Kelam 	if (!err && pfc_rule)
10558e675581SHariprasad Kelam 		otx2_update_bpid_in_rqctx(pfvf, vlan_prio, qidx, true);
10568e675581SHariprasad Kelam #endif
10578e675581SHariprasad Kelam 
1058f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
1059f0a1913fSSubbaraya Sundeep 	return err;
1060f0a1913fSSubbaraya Sundeep }
1061f0a1913fSSubbaraya Sundeep 
otx2_add_flow_with_pfmac(struct otx2_nic * pfvf,struct otx2_flow * flow)106279d2be38SHariprasad Kelam static int otx2_add_flow_with_pfmac(struct otx2_nic *pfvf,
106379d2be38SHariprasad Kelam 				    struct otx2_flow *flow)
106479d2be38SHariprasad Kelam {
106579d2be38SHariprasad Kelam 	struct otx2_flow *pf_mac;
106679d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr;
106779d2be38SHariprasad Kelam 
106879d2be38SHariprasad Kelam 	pf_mac = kzalloc(sizeof(*pf_mac), GFP_KERNEL);
106979d2be38SHariprasad Kelam 	if (!pf_mac)
107079d2be38SHariprasad Kelam 		return -ENOMEM;
107179d2be38SHariprasad Kelam 
107279d2be38SHariprasad Kelam 	pf_mac->entry = 0;
10738e675581SHariprasad Kelam 	pf_mac->rule_type |= DMAC_FILTER_RULE;
10742e2a8126SSunil Goutham 	pf_mac->location = pfvf->flow_cfg->max_flows;
107579d2be38SHariprasad Kelam 	memcpy(&pf_mac->flow_spec, &flow->flow_spec,
107679d2be38SHariprasad Kelam 	       sizeof(struct ethtool_rx_flow_spec));
107779d2be38SHariprasad Kelam 	pf_mac->flow_spec.location = pf_mac->location;
107879d2be38SHariprasad Kelam 
107979d2be38SHariprasad Kelam 	/* Copy PF mac address */
108079d2be38SHariprasad Kelam 	eth_hdr = &pf_mac->flow_spec.h_u.ether_spec;
108179d2be38SHariprasad Kelam 	ether_addr_copy(eth_hdr->h_dest, pfvf->netdev->dev_addr);
108279d2be38SHariprasad Kelam 
108379d2be38SHariprasad Kelam 	/* Install DMAC filter with PF mac address */
108479d2be38SHariprasad Kelam 	otx2_dmacflt_add(pfvf, eth_hdr->h_dest, 0);
108579d2be38SHariprasad Kelam 
108679d2be38SHariprasad Kelam 	otx2_add_flow_to_list(pfvf, pf_mac);
108779d2be38SHariprasad Kelam 	pfvf->flow_cfg->nr_flows++;
1088fa5e0ccbSRatheesh Kannoth 	set_bit(0, pfvf->flow_cfg->dmacflt_bmap);
108979d2be38SHariprasad Kelam 
109079d2be38SHariprasad Kelam 	return 0;
109179d2be38SHariprasad Kelam }
109279d2be38SHariprasad Kelam 
otx2_add_flow(struct otx2_nic * pfvf,struct ethtool_rxnfc * nfc)109381a43620SGeetha sowjanya int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
1094f0a1913fSSubbaraya Sundeep {
1095f0a1913fSSubbaraya Sundeep 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
109681a43620SGeetha sowjanya 	struct ethtool_rx_flow_spec *fsp = &nfc->fs;
1097f0a1913fSSubbaraya Sundeep 	struct otx2_flow *flow;
109879d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr;
1099f0a1913fSSubbaraya Sundeep 	bool new = false;
110079d2be38SHariprasad Kelam 	int err = 0;
1101f174a0daSSuman Ghosh 	u64 vf_num;
110281a43620SGeetha sowjanya 	u32 ring;
1103f0a1913fSSubbaraya Sundeep 
1104a515e5b5SSunil Goutham 	if (!flow_cfg->max_flows) {
1105a515e5b5SSunil Goutham 		netdev_err(pfvf->netdev,
1106a515e5b5SSunil Goutham 			   "Ntuple rule count is 0, allocate and retry\n");
1107a515e5b5SSunil Goutham 		return -EINVAL;
1108a515e5b5SSunil Goutham 	}
1109a515e5b5SSunil Goutham 
111081a43620SGeetha sowjanya 	ring = ethtool_get_flow_spec_ring(fsp->ring_cookie);
1111f0a1913fSSubbaraya Sundeep 	if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT))
1112f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
1113f0a1913fSSubbaraya Sundeep 
1114f174a0daSSuman Ghosh 	/* Number of queues on a VF can be greater or less than
1115f174a0daSSuman Ghosh 	 * the PF's queue. Hence no need to check for the
1116f174a0daSSuman Ghosh 	 * queue count. Hence no need to check queue count if PF
1117f174a0daSSuman Ghosh 	 * is installing for its VF. Below is the expected vf_num value
1118f174a0daSSuman Ghosh 	 * based on the ethtool commands.
1119f174a0daSSuman Ghosh 	 *
1120f174a0daSSuman Ghosh 	 * e.g.
1121f174a0daSSuman Ghosh 	 * 1. ethtool -U <netdev> ... action -1  ==> vf_num:255
1122f174a0daSSuman Ghosh 	 * 2. ethtool -U <netdev> ... action <queue_num>  ==> vf_num:0
1123f174a0daSSuman Ghosh 	 * 3. ethtool -U <netdev> ... vf <vf_idx> queue <queue_num>  ==>
1124f174a0daSSuman Ghosh 	 *    vf_num:vf_idx+1
1125f174a0daSSuman Ghosh 	 */
1126f174a0daSSuman Ghosh 	vf_num = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);
1127f174a0daSSuman Ghosh 	if (!is_otx2_vf(pfvf->pcifunc) && !vf_num &&
1128f174a0daSSuman Ghosh 	    ring >= pfvf->hw.rx_queues && fsp->ring_cookie != RX_CLS_FLOW_DISC)
1129f0a1913fSSubbaraya Sundeep 		return -EINVAL;
1130f0a1913fSSubbaraya Sundeep 
113179d2be38SHariprasad Kelam 	if (fsp->location >= otx2_get_maxflows(flow_cfg))
1132f0a1913fSSubbaraya Sundeep 		return -EINVAL;
1133f0a1913fSSubbaraya Sundeep 
1134f0a1913fSSubbaraya Sundeep 	flow = otx2_find_flow(pfvf, fsp->location);
1135f0a1913fSSubbaraya Sundeep 	if (!flow) {
113679d2be38SHariprasad Kelam 		flow = kzalloc(sizeof(*flow), GFP_KERNEL);
1137f0a1913fSSubbaraya Sundeep 		if (!flow)
1138f0a1913fSSubbaraya Sundeep 			return -ENOMEM;
1139f0a1913fSSubbaraya Sundeep 		flow->location = fsp->location;
1140dce677daSSubbaraya Sundeep 		flow->entry = flow_cfg->flow_ent[flow->location];
1141f0a1913fSSubbaraya Sundeep 		new = true;
1142f0a1913fSSubbaraya Sundeep 	}
1143f0a1913fSSubbaraya Sundeep 	/* struct copy */
1144f0a1913fSSubbaraya Sundeep 	flow->flow_spec = *fsp;
1145f0a1913fSSubbaraya Sundeep 
114681a43620SGeetha sowjanya 	if (fsp->flow_type & FLOW_RSS)
114781a43620SGeetha sowjanya 		flow->rss_ctx_id = nfc->rss_context;
114881a43620SGeetha sowjanya 
114979d2be38SHariprasad Kelam 	if (otx2_is_flow_rule_dmacfilter(pfvf, &flow->flow_spec)) {
115079d2be38SHariprasad Kelam 		eth_hdr = &flow->flow_spec.h_u.ether_spec;
115179d2be38SHariprasad Kelam 
115279d2be38SHariprasad Kelam 		/* Sync dmac filter table with updated fields */
11538e675581SHariprasad Kelam 		if (flow->rule_type & DMAC_FILTER_RULE)
115479d2be38SHariprasad Kelam 			return otx2_dmacflt_update(pfvf, eth_hdr->h_dest,
115579d2be38SHariprasad Kelam 						   flow->entry);
115679d2be38SHariprasad Kelam 
1157fa5e0ccbSRatheesh Kannoth 		if (bitmap_full(flow_cfg->dmacflt_bmap,
115879d2be38SHariprasad Kelam 				flow_cfg->dmacflt_max_flows)) {
115979d2be38SHariprasad Kelam 			netdev_warn(pfvf->netdev,
116079d2be38SHariprasad Kelam 				    "Can't insert the rule %d as max allowed dmac filters are %d\n",
116179d2be38SHariprasad Kelam 				    flow->location +
116279d2be38SHariprasad Kelam 				    flow_cfg->dmacflt_max_flows,
116379d2be38SHariprasad Kelam 				    flow_cfg->dmacflt_max_flows);
116479d2be38SHariprasad Kelam 			err = -EINVAL;
116579d2be38SHariprasad Kelam 			if (new)
116679d2be38SHariprasad Kelam 				kfree(flow);
116779d2be38SHariprasad Kelam 			return err;
116879d2be38SHariprasad Kelam 		}
116979d2be38SHariprasad Kelam 
117079d2be38SHariprasad Kelam 		/* Install PF mac address to DMAC filter list */
1171fa5e0ccbSRatheesh Kannoth 		if (!test_bit(0, flow_cfg->dmacflt_bmap))
117279d2be38SHariprasad Kelam 			otx2_add_flow_with_pfmac(pfvf, flow);
117379d2be38SHariprasad Kelam 
11748e675581SHariprasad Kelam 		flow->rule_type |= DMAC_FILTER_RULE;
1175fa5e0ccbSRatheesh Kannoth 		flow->entry = find_first_zero_bit(flow_cfg->dmacflt_bmap,
117679d2be38SHariprasad Kelam 						  flow_cfg->dmacflt_max_flows);
11772e2a8126SSunil Goutham 		fsp->location = flow_cfg->max_flows + flow->entry;
117879d2be38SHariprasad Kelam 		flow->flow_spec.location = fsp->location;
117979d2be38SHariprasad Kelam 		flow->location = fsp->location;
118079d2be38SHariprasad Kelam 
1181fa5e0ccbSRatheesh Kannoth 		set_bit(flow->entry, flow_cfg->dmacflt_bmap);
118279d2be38SHariprasad Kelam 		otx2_dmacflt_add(pfvf, eth_hdr->h_dest, flow->entry);
118379d2be38SHariprasad Kelam 
118479d2be38SHariprasad Kelam 	} else {
11852e2a8126SSunil Goutham 		if (flow->location >= pfvf->flow_cfg->max_flows) {
118679d2be38SHariprasad Kelam 			netdev_warn(pfvf->netdev,
118779d2be38SHariprasad Kelam 				    "Can't insert non dmac ntuple rule at %d, allowed range %d-0\n",
118879d2be38SHariprasad Kelam 				    flow->location,
11892e2a8126SSunil Goutham 				    flow_cfg->max_flows - 1);
119079d2be38SHariprasad Kelam 			err = -EINVAL;
119179d2be38SHariprasad Kelam 		} else {
1192f0a1913fSSubbaraya Sundeep 			err = otx2_add_flow_msg(pfvf, flow);
119379d2be38SHariprasad Kelam 		}
119479d2be38SHariprasad Kelam 	}
119579d2be38SHariprasad Kelam 
1196f0a1913fSSubbaraya Sundeep 	if (err) {
11973cffaed2SRakesh Babu 		if (err == MBOX_MSG_INVALID)
11983cffaed2SRakesh Babu 			err = -EINVAL;
1199f0a1913fSSubbaraya Sundeep 		if (new)
1200f0a1913fSSubbaraya Sundeep 			kfree(flow);
1201f0a1913fSSubbaraya Sundeep 		return err;
1202f0a1913fSSubbaraya Sundeep 	}
1203f0a1913fSSubbaraya Sundeep 
1204f0a1913fSSubbaraya Sundeep 	/* add the new flow installed to list */
1205f0a1913fSSubbaraya Sundeep 	if (new) {
1206f0a1913fSSubbaraya Sundeep 		otx2_add_flow_to_list(pfvf, flow);
1207f0a1913fSSubbaraya Sundeep 		flow_cfg->nr_flows++;
1208f0a1913fSSubbaraya Sundeep 	}
1209f0a1913fSSubbaraya Sundeep 
1210f174a0daSSuman Ghosh 	if (flow->is_vf)
1211f174a0daSSuman Ghosh 		netdev_info(pfvf->netdev,
1212f174a0daSSuman Ghosh 			    "Make sure that VF's queue number is within its queue limit\n");
1213f0a1913fSSubbaraya Sundeep 	return 0;
1214f0a1913fSSubbaraya Sundeep }
1215f0a1913fSSubbaraya Sundeep 
otx2_remove_flow_msg(struct otx2_nic * pfvf,u16 entry,bool all)1216f0a1913fSSubbaraya Sundeep static int otx2_remove_flow_msg(struct otx2_nic *pfvf, u16 entry, bool all)
1217f0a1913fSSubbaraya Sundeep {
1218f0a1913fSSubbaraya Sundeep 	struct npc_delete_flow_req *req;
1219f0a1913fSSubbaraya Sundeep 	int err;
1220f0a1913fSSubbaraya Sundeep 
1221f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
1222f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
1223f0a1913fSSubbaraya Sundeep 	if (!req) {
1224f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
1225f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
1226f0a1913fSSubbaraya Sundeep 	}
1227f0a1913fSSubbaraya Sundeep 
1228f0a1913fSSubbaraya Sundeep 	req->entry = entry;
1229f0a1913fSSubbaraya Sundeep 	if (all)
1230f0a1913fSSubbaraya Sundeep 		req->all = 1;
1231f0a1913fSSubbaraya Sundeep 
1232f0a1913fSSubbaraya Sundeep 	/* Send message to AF */
1233f0a1913fSSubbaraya Sundeep 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1234f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
1235f0a1913fSSubbaraya Sundeep 	return err;
1236f0a1913fSSubbaraya Sundeep }
1237f0a1913fSSubbaraya Sundeep 
otx2_update_rem_pfmac(struct otx2_nic * pfvf,int req)123879d2be38SHariprasad Kelam static void otx2_update_rem_pfmac(struct otx2_nic *pfvf, int req)
123979d2be38SHariprasad Kelam {
124079d2be38SHariprasad Kelam 	struct otx2_flow *iter;
124179d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr;
124279d2be38SHariprasad Kelam 	bool found = false;
124379d2be38SHariprasad Kelam 
124479d2be38SHariprasad Kelam 	list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
12458e675581SHariprasad Kelam 		if ((iter->rule_type & DMAC_FILTER_RULE) && iter->entry == 0) {
124679d2be38SHariprasad Kelam 			eth_hdr = &iter->flow_spec.h_u.ether_spec;
124779d2be38SHariprasad Kelam 			if (req == DMAC_ADDR_DEL) {
124879d2be38SHariprasad Kelam 				otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
124979d2be38SHariprasad Kelam 						    0);
1250fa5e0ccbSRatheesh Kannoth 				clear_bit(0, pfvf->flow_cfg->dmacflt_bmap);
125179d2be38SHariprasad Kelam 				found = true;
125279d2be38SHariprasad Kelam 			} else {
125379d2be38SHariprasad Kelam 				ether_addr_copy(eth_hdr->h_dest,
125479d2be38SHariprasad Kelam 						pfvf->netdev->dev_addr);
1255fa5e0ccbSRatheesh Kannoth 
125679d2be38SHariprasad Kelam 				otx2_dmacflt_update(pfvf, eth_hdr->h_dest, 0);
125779d2be38SHariprasad Kelam 			}
125879d2be38SHariprasad Kelam 			break;
125979d2be38SHariprasad Kelam 		}
126079d2be38SHariprasad Kelam 	}
126179d2be38SHariprasad Kelam 
126279d2be38SHariprasad Kelam 	if (found) {
126379d2be38SHariprasad Kelam 		list_del(&iter->list);
126479d2be38SHariprasad Kelam 		kfree(iter);
126579d2be38SHariprasad Kelam 		pfvf->flow_cfg->nr_flows--;
126679d2be38SHariprasad Kelam 	}
126779d2be38SHariprasad Kelam }
126879d2be38SHariprasad Kelam 
otx2_remove_flow(struct otx2_nic * pfvf,u32 location)1269f0a1913fSSubbaraya Sundeep int otx2_remove_flow(struct otx2_nic *pfvf, u32 location)
1270f0a1913fSSubbaraya Sundeep {
1271f0a1913fSSubbaraya Sundeep 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1272f0a1913fSSubbaraya Sundeep 	struct otx2_flow *flow;
1273f0a1913fSSubbaraya Sundeep 	int err;
1274f0a1913fSSubbaraya Sundeep 
127579d2be38SHariprasad Kelam 	if (location >= otx2_get_maxflows(flow_cfg))
1276f0a1913fSSubbaraya Sundeep 		return -EINVAL;
1277f0a1913fSSubbaraya Sundeep 
1278f0a1913fSSubbaraya Sundeep 	flow = otx2_find_flow(pfvf, location);
1279f0a1913fSSubbaraya Sundeep 	if (!flow)
1280f0a1913fSSubbaraya Sundeep 		return -ENOENT;
1281f0a1913fSSubbaraya Sundeep 
12828e675581SHariprasad Kelam 	if (flow->rule_type & DMAC_FILTER_RULE) {
128379d2be38SHariprasad Kelam 		struct ethhdr *eth_hdr = &flow->flow_spec.h_u.ether_spec;
128479d2be38SHariprasad Kelam 
128579d2be38SHariprasad Kelam 		/* user not allowed to remove dmac filter with interface mac */
128679d2be38SHariprasad Kelam 		if (ether_addr_equal(pfvf->netdev->dev_addr, eth_hdr->h_dest))
128779d2be38SHariprasad Kelam 			return -EPERM;
128879d2be38SHariprasad Kelam 
128979d2be38SHariprasad Kelam 		err = otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
129079d2be38SHariprasad Kelam 					  flow->entry);
1291fa5e0ccbSRatheesh Kannoth 		clear_bit(flow->entry, flow_cfg->dmacflt_bmap);
129279d2be38SHariprasad Kelam 		/* If all dmac filters are removed delete macfilter with
129379d2be38SHariprasad Kelam 		 * interface mac address and configure CGX/RPM block in
129479d2be38SHariprasad Kelam 		 * promiscuous mode
129579d2be38SHariprasad Kelam 		 */
1296fa5e0ccbSRatheesh Kannoth 		if (bitmap_weight(flow_cfg->dmacflt_bmap,
129779d2be38SHariprasad Kelam 				  flow_cfg->dmacflt_max_flows) == 1)
129879d2be38SHariprasad Kelam 			otx2_update_rem_pfmac(pfvf, DMAC_ADDR_DEL);
129979d2be38SHariprasad Kelam 	} else {
13008e675581SHariprasad Kelam #ifdef CONFIG_DCB
13018e675581SHariprasad Kelam 		if (flow->rule_type & PFC_FLOWCTRL_RULE)
13028e675581SHariprasad Kelam 			otx2_update_bpid_in_rqctx(pfvf, 0,
13038e675581SHariprasad Kelam 						  flow->flow_spec.ring_cookie,
13048e675581SHariprasad Kelam 						  false);
13058e675581SHariprasad Kelam #endif
13068e675581SHariprasad Kelam 
1307f0a1913fSSubbaraya Sundeep 		err = otx2_remove_flow_msg(pfvf, flow->entry, false);
130879d2be38SHariprasad Kelam 	}
130979d2be38SHariprasad Kelam 
1310f0a1913fSSubbaraya Sundeep 	if (err)
1311f0a1913fSSubbaraya Sundeep 		return err;
1312f0a1913fSSubbaraya Sundeep 
1313f0a1913fSSubbaraya Sundeep 	list_del(&flow->list);
1314f0a1913fSSubbaraya Sundeep 	kfree(flow);
1315f0a1913fSSubbaraya Sundeep 	flow_cfg->nr_flows--;
1316f0a1913fSSubbaraya Sundeep 
1317f0a1913fSSubbaraya Sundeep 	return 0;
1318f0a1913fSSubbaraya Sundeep }
1319f0a1913fSSubbaraya Sundeep 
otx2_rss_ctx_flow_del(struct otx2_nic * pfvf,int ctx_id)132081a43620SGeetha sowjanya void otx2_rss_ctx_flow_del(struct otx2_nic *pfvf, int ctx_id)
132181a43620SGeetha sowjanya {
132281a43620SGeetha sowjanya 	struct otx2_flow *flow, *tmp;
132381a43620SGeetha sowjanya 	int err;
132481a43620SGeetha sowjanya 
132581a43620SGeetha sowjanya 	list_for_each_entry_safe(flow, tmp, &pfvf->flow_cfg->flow_list, list) {
132681a43620SGeetha sowjanya 		if (flow->rss_ctx_id != ctx_id)
132781a43620SGeetha sowjanya 			continue;
132881a43620SGeetha sowjanya 		err = otx2_remove_flow(pfvf, flow->location);
132981a43620SGeetha sowjanya 		if (err)
133081a43620SGeetha sowjanya 			netdev_warn(pfvf->netdev,
133181a43620SGeetha sowjanya 				    "Can't delete the rule %d associated with this rss group err:%d",
133281a43620SGeetha sowjanya 				    flow->location, err);
133381a43620SGeetha sowjanya 	}
133481a43620SGeetha sowjanya }
133581a43620SGeetha sowjanya 
otx2_destroy_ntuple_flows(struct otx2_nic * pfvf)1336f0a1913fSSubbaraya Sundeep int otx2_destroy_ntuple_flows(struct otx2_nic *pfvf)
1337f0a1913fSSubbaraya Sundeep {
1338f0a1913fSSubbaraya Sundeep 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1339f0a1913fSSubbaraya Sundeep 	struct npc_delete_flow_req *req;
1340f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter, *tmp;
1341f0a1913fSSubbaraya Sundeep 	int err;
1342f0a1913fSSubbaraya Sundeep 
1343f0a1913fSSubbaraya Sundeep 	if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT))
1344f0a1913fSSubbaraya Sundeep 		return 0;
1345f0a1913fSSubbaraya Sundeep 
1346a515e5b5SSunil Goutham 	if (!flow_cfg->max_flows)
1347a515e5b5SSunil Goutham 		return 0;
1348a515e5b5SSunil Goutham 
1349f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
1350f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
1351f0a1913fSSubbaraya Sundeep 	if (!req) {
1352f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
1353f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
1354f0a1913fSSubbaraya Sundeep 	}
1355f0a1913fSSubbaraya Sundeep 
13569917060fSSunil Goutham 	req->start = flow_cfg->flow_ent[0];
13572e2a8126SSunil Goutham 	req->end   = flow_cfg->flow_ent[flow_cfg->max_flows - 1];
1358f0a1913fSSubbaraya Sundeep 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1359f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
1360f0a1913fSSubbaraya Sundeep 
1361f0a1913fSSubbaraya Sundeep 	list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list, list) {
1362f0a1913fSSubbaraya Sundeep 		list_del(&iter->list);
1363f0a1913fSSubbaraya Sundeep 		kfree(iter);
1364f0a1913fSSubbaraya Sundeep 		flow_cfg->nr_flows--;
1365f0a1913fSSubbaraya Sundeep 	}
1366f0a1913fSSubbaraya Sundeep 	return err;
1367f0a1913fSSubbaraya Sundeep }
1368f0a1913fSSubbaraya Sundeep 
otx2_destroy_mcam_flows(struct otx2_nic * pfvf)1369f0a1913fSSubbaraya Sundeep int otx2_destroy_mcam_flows(struct otx2_nic *pfvf)
1370f0a1913fSSubbaraya Sundeep {
1371f0a1913fSSubbaraya Sundeep 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1372f0a1913fSSubbaraya Sundeep 	struct npc_mcam_free_entry_req *req;
1373f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter, *tmp;
1374f0a1913fSSubbaraya Sundeep 	int err;
1375f0a1913fSSubbaraya Sundeep 
1376f0a1913fSSubbaraya Sundeep 	if (!(pfvf->flags & OTX2_FLAG_MCAM_ENTRIES_ALLOC))
1377f0a1913fSSubbaraya Sundeep 		return 0;
1378f0a1913fSSubbaraya Sundeep 
1379f0a1913fSSubbaraya Sundeep 	/* remove all flows */
1380f0a1913fSSubbaraya Sundeep 	err = otx2_remove_flow_msg(pfvf, 0, true);
1381f0a1913fSSubbaraya Sundeep 	if (err)
1382f0a1913fSSubbaraya Sundeep 		return err;
1383f0a1913fSSubbaraya Sundeep 
1384f0a1913fSSubbaraya Sundeep 	list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list, list) {
1385f0a1913fSSubbaraya Sundeep 		list_del(&iter->list);
1386f0a1913fSSubbaraya Sundeep 		kfree(iter);
1387f0a1913fSSubbaraya Sundeep 		flow_cfg->nr_flows--;
1388f0a1913fSSubbaraya Sundeep 	}
1389f0a1913fSSubbaraya Sundeep 
1390f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
1391f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_mcam_free_entry(&pfvf->mbox);
1392f0a1913fSSubbaraya Sundeep 	if (!req) {
1393f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
1394f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
1395f0a1913fSSubbaraya Sundeep 	}
1396f0a1913fSSubbaraya Sundeep 
1397f0a1913fSSubbaraya Sundeep 	req->all = 1;
1398f0a1913fSSubbaraya Sundeep 	/* Send message to AF to free MCAM entries */
1399f0a1913fSSubbaraya Sundeep 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1400f0a1913fSSubbaraya Sundeep 	if (err) {
1401f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
1402f0a1913fSSubbaraya Sundeep 		return err;
1403f0a1913fSSubbaraya Sundeep 	}
1404f0a1913fSSubbaraya Sundeep 
1405f0a1913fSSubbaraya Sundeep 	pfvf->flags &= ~OTX2_FLAG_MCAM_ENTRIES_ALLOC;
1406f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
1407f0a1913fSSubbaraya Sundeep 
1408f0a1913fSSubbaraya Sundeep 	return 0;
1409f0a1913fSSubbaraya Sundeep }
1410fd9d7859SHariprasad Kelam 
otx2_install_rxvlan_offload_flow(struct otx2_nic * pfvf)1411fd9d7859SHariprasad Kelam int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf)
1412fd9d7859SHariprasad Kelam {
1413fd9d7859SHariprasad Kelam 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1414fd9d7859SHariprasad Kelam 	struct npc_install_flow_req *req;
1415fd9d7859SHariprasad Kelam 	int err;
1416fd9d7859SHariprasad Kelam 
1417fd9d7859SHariprasad Kelam 	mutex_lock(&pfvf->mbox.lock);
1418fd9d7859SHariprasad Kelam 	req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox);
1419fd9d7859SHariprasad Kelam 	if (!req) {
1420fd9d7859SHariprasad Kelam 		mutex_unlock(&pfvf->mbox.lock);
1421fd9d7859SHariprasad Kelam 		return -ENOMEM;
1422fd9d7859SHariprasad Kelam 	}
1423fd9d7859SHariprasad Kelam 
14249917060fSSunil Goutham 	req->entry = flow_cfg->def_ent[flow_cfg->rx_vlan_offset];
1425fd9d7859SHariprasad Kelam 	req->intf = NIX_INTF_RX;
1426fd9d7859SHariprasad Kelam 	ether_addr_copy(req->packet.dmac, pfvf->netdev->dev_addr);
1427fd9d7859SHariprasad Kelam 	eth_broadcast_addr((u8 *)&req->mask.dmac);
1428fd9d7859SHariprasad Kelam 	req->channel = pfvf->hw.rx_chan_base;
1429fd9d7859SHariprasad Kelam 	req->op = NIX_RX_ACTION_DEFAULT;
1430fd9d7859SHariprasad Kelam 	req->features = BIT_ULL(NPC_OUTER_VID) | BIT_ULL(NPC_DMAC);
1431fd9d7859SHariprasad Kelam 	req->vtag0_valid = true;
1432fd9d7859SHariprasad Kelam 	req->vtag0_type = NIX_AF_LFX_RX_VTAG_TYPE0;
1433fd9d7859SHariprasad Kelam 
1434fd9d7859SHariprasad Kelam 	/* Send message to AF */
1435fd9d7859SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1436fd9d7859SHariprasad Kelam 	mutex_unlock(&pfvf->mbox.lock);
1437fd9d7859SHariprasad Kelam 	return err;
1438fd9d7859SHariprasad Kelam }
1439fd9d7859SHariprasad Kelam 
otx2_delete_rxvlan_offload_flow(struct otx2_nic * pfvf)1440fd9d7859SHariprasad Kelam static int otx2_delete_rxvlan_offload_flow(struct otx2_nic *pfvf)
1441fd9d7859SHariprasad Kelam {
1442fd9d7859SHariprasad Kelam 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1443fd9d7859SHariprasad Kelam 	struct npc_delete_flow_req *req;
1444fd9d7859SHariprasad Kelam 	int err;
1445fd9d7859SHariprasad Kelam 
1446fd9d7859SHariprasad Kelam 	mutex_lock(&pfvf->mbox.lock);
1447fd9d7859SHariprasad Kelam 	req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
1448fd9d7859SHariprasad Kelam 	if (!req) {
1449fd9d7859SHariprasad Kelam 		mutex_unlock(&pfvf->mbox.lock);
1450fd9d7859SHariprasad Kelam 		return -ENOMEM;
1451fd9d7859SHariprasad Kelam 	}
1452fd9d7859SHariprasad Kelam 
14539917060fSSunil Goutham 	req->entry = flow_cfg->def_ent[flow_cfg->rx_vlan_offset];
1454fd9d7859SHariprasad Kelam 	/* Send message to AF */
1455fd9d7859SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1456fd9d7859SHariprasad Kelam 	mutex_unlock(&pfvf->mbox.lock);
1457fd9d7859SHariprasad Kelam 	return err;
1458fd9d7859SHariprasad Kelam }
1459fd9d7859SHariprasad Kelam 
otx2_enable_rxvlan(struct otx2_nic * pf,bool enable)1460fd9d7859SHariprasad Kelam int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable)
1461fd9d7859SHariprasad Kelam {
1462fd9d7859SHariprasad Kelam 	struct nix_vtag_config *req;
1463fd9d7859SHariprasad Kelam 	struct mbox_msghdr *rsp_hdr;
1464fd9d7859SHariprasad Kelam 	int err;
1465fd9d7859SHariprasad Kelam 
1466fd9d7859SHariprasad Kelam 	/* Dont have enough mcam entries */
1467fd9d7859SHariprasad Kelam 	if (!(pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT))
1468fd9d7859SHariprasad Kelam 		return -ENOMEM;
1469fd9d7859SHariprasad Kelam 
1470fd9d7859SHariprasad Kelam 	if (enable) {
1471fd9d7859SHariprasad Kelam 		err = otx2_install_rxvlan_offload_flow(pf);
1472fd9d7859SHariprasad Kelam 		if (err)
1473fd9d7859SHariprasad Kelam 			return err;
1474fd9d7859SHariprasad Kelam 	} else {
1475fd9d7859SHariprasad Kelam 		err = otx2_delete_rxvlan_offload_flow(pf);
1476fd9d7859SHariprasad Kelam 		if (err)
1477fd9d7859SHariprasad Kelam 			return err;
1478fd9d7859SHariprasad Kelam 	}
1479fd9d7859SHariprasad Kelam 
1480fd9d7859SHariprasad Kelam 	mutex_lock(&pf->mbox.lock);
1481fd9d7859SHariprasad Kelam 	req = otx2_mbox_alloc_msg_nix_vtag_cfg(&pf->mbox);
1482fd9d7859SHariprasad Kelam 	if (!req) {
1483fd9d7859SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
1484fd9d7859SHariprasad Kelam 		return -ENOMEM;
1485fd9d7859SHariprasad Kelam 	}
1486fd9d7859SHariprasad Kelam 
1487fd9d7859SHariprasad Kelam 	/* config strip, capture and size */
1488fd9d7859SHariprasad Kelam 	req->vtag_size = VTAGSIZE_T4;
1489fd9d7859SHariprasad Kelam 	req->cfg_type = 1; /* rx vlan cfg */
1490fd9d7859SHariprasad Kelam 	req->rx.vtag_type = NIX_AF_LFX_RX_VTAG_TYPE0;
1491fd9d7859SHariprasad Kelam 	req->rx.strip_vtag = enable;
1492fd9d7859SHariprasad Kelam 	req->rx.capture_vtag = enable;
1493fd9d7859SHariprasad Kelam 
1494fd9d7859SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pf->mbox);
1495fd9d7859SHariprasad Kelam 	if (err) {
1496fd9d7859SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
1497fd9d7859SHariprasad Kelam 		return err;
1498fd9d7859SHariprasad Kelam 	}
1499fd9d7859SHariprasad Kelam 
1500fd9d7859SHariprasad Kelam 	rsp_hdr = otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
1501fd9d7859SHariprasad Kelam 	if (IS_ERR(rsp_hdr)) {
1502fd9d7859SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
1503fd9d7859SHariprasad Kelam 		return PTR_ERR(rsp_hdr);
1504fd9d7859SHariprasad Kelam 	}
1505fd9d7859SHariprasad Kelam 
1506fd9d7859SHariprasad Kelam 	mutex_unlock(&pf->mbox.lock);
1507fd9d7859SHariprasad Kelam 	return rsp_hdr->rc;
1508fd9d7859SHariprasad Kelam }
150979d2be38SHariprasad Kelam 
otx2_dmacflt_reinstall_flows(struct otx2_nic * pf)151079d2be38SHariprasad Kelam void otx2_dmacflt_reinstall_flows(struct otx2_nic *pf)
151179d2be38SHariprasad Kelam {
151279d2be38SHariprasad Kelam 	struct otx2_flow *iter;
151379d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr;
151479d2be38SHariprasad Kelam 
151579d2be38SHariprasad Kelam 	list_for_each_entry(iter, &pf->flow_cfg->flow_list, list) {
15168e675581SHariprasad Kelam 		if (iter->rule_type & DMAC_FILTER_RULE) {
151779d2be38SHariprasad Kelam 			eth_hdr = &iter->flow_spec.h_u.ether_spec;
151879d2be38SHariprasad Kelam 			otx2_dmacflt_add(pf, eth_hdr->h_dest,
151979d2be38SHariprasad Kelam 					 iter->entry);
152079d2be38SHariprasad Kelam 		}
152179d2be38SHariprasad Kelam 	}
152279d2be38SHariprasad Kelam }
152379d2be38SHariprasad Kelam 
otx2_dmacflt_update_pfmac_flow(struct otx2_nic * pfvf)152479d2be38SHariprasad Kelam void otx2_dmacflt_update_pfmac_flow(struct otx2_nic *pfvf)
152579d2be38SHariprasad Kelam {
152679d2be38SHariprasad Kelam 	otx2_update_rem_pfmac(pfvf, DMAC_ADDR_UPDATE);
152779d2be38SHariprasad Kelam }
1528