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);
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 
otx2_mcam_entry_init(struct otx2_nic * pfvf)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;
167674b3e16SSuman Ghosh 	struct npc_get_field_status_req *freq;
168674b3e16SSuman Ghosh 	struct npc_get_field_status_rsp *frsp;
169f0a1913fSSubbaraya Sundeep 	struct npc_mcam_alloc_entry_req *req;
170f0a1913fSSubbaraya Sundeep 	struct npc_mcam_alloc_entry_rsp *rsp;
171f0c2982aSNaveen Mamindlapalli 	int vf_vlan_max_flows;
1729917060fSSunil Goutham 	int ent, count;
1739917060fSSunil Goutham 
1749917060fSSunil Goutham 	vf_vlan_max_flows = pfvf->total_vfs * OTX2_PER_VF_VLAN_FLOWS;
1759917060fSSunil Goutham 	count = OTX2_MAX_UNICAST_FLOWS +
1769917060fSSunil Goutham 			OTX2_MAX_VLAN_FLOWS + vf_vlan_max_flows;
1779917060fSSunil Goutham 
1789917060fSSunil Goutham 	flow_cfg->def_ent = devm_kmalloc_array(pfvf->dev, count,
1799917060fSSunil Goutham 					       sizeof(u16), GFP_KERNEL);
1809917060fSSunil Goutham 	if (!flow_cfg->def_ent)
1819917060fSSunil Goutham 		return -ENOMEM;
182f0a1913fSSubbaraya Sundeep 
183f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
184f0a1913fSSubbaraya Sundeep 
185f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_mcam_alloc_entry(&pfvf->mbox);
186f0a1913fSSubbaraya Sundeep 	if (!req) {
187f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
188f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
189f0a1913fSSubbaraya Sundeep 	}
190f0a1913fSSubbaraya Sundeep 
191f0a1913fSSubbaraya Sundeep 	req->contig = false;
1929917060fSSunil Goutham 	req->count = count;
193f0a1913fSSubbaraya Sundeep 
194f0a1913fSSubbaraya Sundeep 	/* Send message to AF */
195f0a1913fSSubbaraya Sundeep 	if (otx2_sync_mbox_msg(&pfvf->mbox)) {
196f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
197f0a1913fSSubbaraya Sundeep 		return -EINVAL;
198f0a1913fSSubbaraya Sundeep 	}
199f0a1913fSSubbaraya Sundeep 
200f0a1913fSSubbaraya Sundeep 	rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
201f0a1913fSSubbaraya Sundeep 	       (&pfvf->mbox.mbox, 0, &req->hdr);
202f0a1913fSSubbaraya Sundeep 
20363ee5157SHariprasad Kelam 	if (rsp->count != req->count) {
204f0a1913fSSubbaraya Sundeep 		netdev_info(pfvf->netdev,
2059917060fSSunil Goutham 			    "Unable to allocate MCAM entries for ucast, vlan and vf_vlan\n");
2069917060fSSunil Goutham 		mutex_unlock(&pfvf->mbox.lock);
2079917060fSSunil Goutham 		devm_kfree(pfvf->dev, flow_cfg->def_ent);
2089917060fSSunil Goutham 		return 0;
2099917060fSSunil Goutham 	}
2109917060fSSunil Goutham 
2119917060fSSunil Goutham 	for (ent = 0; ent < rsp->count; ent++)
2129917060fSSunil Goutham 		flow_cfg->def_ent[ent] = rsp->entry_list[ent];
2139917060fSSunil Goutham 
214f0c2982aSNaveen Mamindlapalli 	flow_cfg->vf_vlan_offset = 0;
2159917060fSSunil Goutham 	flow_cfg->unicast_offset = vf_vlan_max_flows;
216fd9d7859SHariprasad Kelam 	flow_cfg->rx_vlan_offset = flow_cfg->unicast_offset +
217fd9d7859SHariprasad Kelam 					OTX2_MAX_UNICAST_FLOWS;
21863ee5157SHariprasad Kelam 	pfvf->flags |= OTX2_FLAG_UCAST_FLTR_SUPPORT;
219674b3e16SSuman Ghosh 
220674b3e16SSuman Ghosh 	/* Check if NPC_DMAC field is supported
221674b3e16SSuman Ghosh 	 * by the mkex profile before setting VLAN support flag.
222674b3e16SSuman Ghosh 	 */
223674b3e16SSuman Ghosh 	freq = otx2_mbox_alloc_msg_npc_get_field_status(&pfvf->mbox);
224674b3e16SSuman Ghosh 	if (!freq) {
225674b3e16SSuman Ghosh 		mutex_unlock(&pfvf->mbox.lock);
226674b3e16SSuman Ghosh 		return -ENOMEM;
227674b3e16SSuman Ghosh 	}
228674b3e16SSuman Ghosh 
229674b3e16SSuman Ghosh 	freq->field = NPC_DMAC;
230674b3e16SSuman Ghosh 	if (otx2_sync_mbox_msg(&pfvf->mbox)) {
231674b3e16SSuman Ghosh 		mutex_unlock(&pfvf->mbox.lock);
232674b3e16SSuman Ghosh 		return -EINVAL;
233674b3e16SSuman Ghosh 	}
234674b3e16SSuman Ghosh 
235674b3e16SSuman Ghosh 	frsp = (struct npc_get_field_status_rsp *)otx2_mbox_get_rsp
236674b3e16SSuman Ghosh 	       (&pfvf->mbox.mbox, 0, &freq->hdr);
237674b3e16SSuman Ghosh 
238674b3e16SSuman Ghosh 	if (frsp->enable) {
239fd9d7859SHariprasad Kelam 		pfvf->flags |= OTX2_FLAG_RX_VLAN_SUPPORT;
240f0c2982aSNaveen Mamindlapalli 		pfvf->flags |= OTX2_FLAG_VF_VLAN_SUPPORT;
241674b3e16SSuman Ghosh 	}
242f0a1913fSSubbaraya Sundeep 
243f0a1913fSSubbaraya Sundeep 	pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
244f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
245f0a1913fSSubbaraya Sundeep 
2469917060fSSunil Goutham 	/* Allocate entries for Ntuple filters */
2472da48943SSunil Goutham 	count = otx2_alloc_mcam_entries(pfvf, OTX2_DEFAULT_FLOWCOUNT);
2489917060fSSunil Goutham 	if (count <= 0) {
2499917060fSSunil Goutham 		otx2_clear_ntuple_flow_info(pfvf, flow_cfg);
2509917060fSSunil Goutham 		return 0;
2519917060fSSunil Goutham 	}
2529917060fSSunil Goutham 
2539917060fSSunil Goutham 	pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT;
2549917060fSSunil Goutham 
255f0a1913fSSubbaraya Sundeep 	return 0;
256f0a1913fSSubbaraya Sundeep }
257f0a1913fSSubbaraya Sundeep 
258fa5e0ccbSRatheesh Kannoth /* TODO : revisit on size */
259fa5e0ccbSRatheesh Kannoth #define OTX2_DMAC_FLTR_BITMAP_SZ (4 * 2048 + 32)
260fa5e0ccbSRatheesh Kannoth 
otx2vf_mcam_flow_init(struct otx2_nic * pfvf)2613cffaed2SRakesh Babu int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
2623cffaed2SRakesh Babu {
2633cffaed2SRakesh Babu 	struct otx2_flow_config *flow_cfg;
2643cffaed2SRakesh Babu 
2653cffaed2SRakesh Babu 	pfvf->flow_cfg = devm_kzalloc(pfvf->dev,
2663cffaed2SRakesh Babu 				      sizeof(struct otx2_flow_config),
2673cffaed2SRakesh Babu 				      GFP_KERNEL);
2683cffaed2SRakesh Babu 	if (!pfvf->flow_cfg)
2693cffaed2SRakesh Babu 		return -ENOMEM;
2703cffaed2SRakesh Babu 
271fa5e0ccbSRatheesh Kannoth 	pfvf->flow_cfg->dmacflt_bmap = devm_kcalloc(pfvf->dev,
272fa5e0ccbSRatheesh Kannoth 						    BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ),
273fa5e0ccbSRatheesh Kannoth 						    sizeof(long), GFP_KERNEL);
274fa5e0ccbSRatheesh Kannoth 	if (!pfvf->flow_cfg->dmacflt_bmap)
275fa5e0ccbSRatheesh Kannoth 		return -ENOMEM;
276fa5e0ccbSRatheesh Kannoth 
2773cffaed2SRakesh Babu 	flow_cfg = pfvf->flow_cfg;
2783cffaed2SRakesh Babu 	INIT_LIST_HEAD(&flow_cfg->flow_list);
279ec87f054SSuman Ghosh 	INIT_LIST_HEAD(&flow_cfg->flow_list_tc);
2802e2a8126SSunil Goutham 	flow_cfg->max_flows = 0;
2813cffaed2SRakesh Babu 
2823cffaed2SRakesh Babu 	return 0;
2833cffaed2SRakesh Babu }
2843cffaed2SRakesh Babu EXPORT_SYMBOL(otx2vf_mcam_flow_init);
2853cffaed2SRakesh Babu 
otx2_mcam_flow_init(struct otx2_nic * pf)286f0a1913fSSubbaraya Sundeep int otx2_mcam_flow_init(struct otx2_nic *pf)
287f0a1913fSSubbaraya Sundeep {
288f0a1913fSSubbaraya Sundeep 	int err;
289f0a1913fSSubbaraya Sundeep 
290f0a1913fSSubbaraya Sundeep 	pf->flow_cfg = devm_kzalloc(pf->dev, sizeof(struct otx2_flow_config),
291f0a1913fSSubbaraya Sundeep 				    GFP_KERNEL);
292f0a1913fSSubbaraya Sundeep 	if (!pf->flow_cfg)
293f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
294f0a1913fSSubbaraya Sundeep 
295fa5e0ccbSRatheesh Kannoth 	pf->flow_cfg->dmacflt_bmap = devm_kcalloc(pf->dev,
296fa5e0ccbSRatheesh Kannoth 						  BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ),
297fa5e0ccbSRatheesh Kannoth 						  sizeof(long), GFP_KERNEL);
298fa5e0ccbSRatheesh Kannoth 	if (!pf->flow_cfg->dmacflt_bmap)
299fa5e0ccbSRatheesh Kannoth 		return -ENOMEM;
300fa5e0ccbSRatheesh Kannoth 
301f0a1913fSSubbaraya Sundeep 	INIT_LIST_HEAD(&pf->flow_cfg->flow_list);
302ec87f054SSuman Ghosh 	INIT_LIST_HEAD(&pf->flow_cfg->flow_list_tc);
303f0a1913fSSubbaraya Sundeep 
3042da48943SSunil Goutham 	/* Allocate bare minimum number of MCAM entries needed for
3052da48943SSunil Goutham 	 * unicast and ntuple filters.
3062da48943SSunil Goutham 	 */
3072da48943SSunil Goutham 	err = otx2_mcam_entry_init(pf);
308f0a1913fSSubbaraya Sundeep 	if (err)
309f0a1913fSSubbaraya Sundeep 		return err;
310f0a1913fSSubbaraya Sundeep 
3119917060fSSunil Goutham 	/* Check if MCAM entries are allocate or not */
3129917060fSSunil Goutham 	if (!(pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT))
3139917060fSSunil Goutham 		return 0;
3149917060fSSunil Goutham 
31563ee5157SHariprasad Kelam 	pf->mac_table = devm_kzalloc(pf->dev, sizeof(struct otx2_mac_table)
31663ee5157SHariprasad Kelam 					* OTX2_MAX_UNICAST_FLOWS, GFP_KERNEL);
31763ee5157SHariprasad Kelam 	if (!pf->mac_table)
31863ee5157SHariprasad Kelam 		return -ENOMEM;
31963ee5157SHariprasad Kelam 
32079d2be38SHariprasad Kelam 	otx2_dmacflt_get_max_cnt(pf);
32179d2be38SHariprasad Kelam 
32279d2be38SHariprasad Kelam 	/* DMAC filters are not allocated */
32379d2be38SHariprasad Kelam 	if (!pf->flow_cfg->dmacflt_max_flows)
32479d2be38SHariprasad Kelam 		return 0;
32579d2be38SHariprasad Kelam 
32679d2be38SHariprasad Kelam 	pf->flow_cfg->bmap_to_dmacindex =
327fa5e0ccbSRatheesh Kannoth 			devm_kzalloc(pf->dev, sizeof(u32) *
32879d2be38SHariprasad Kelam 				     pf->flow_cfg->dmacflt_max_flows,
32979d2be38SHariprasad Kelam 				     GFP_KERNEL);
33079d2be38SHariprasad Kelam 
33179d2be38SHariprasad Kelam 	if (!pf->flow_cfg->bmap_to_dmacindex)
33279d2be38SHariprasad Kelam 		return -ENOMEM;
33379d2be38SHariprasad Kelam 
33479d2be38SHariprasad Kelam 	pf->flags |= OTX2_FLAG_DMACFLTR_SUPPORT;
33579d2be38SHariprasad Kelam 
336f0a1913fSSubbaraya Sundeep 	return 0;
337f0a1913fSSubbaraya Sundeep }
338f0a1913fSSubbaraya Sundeep 
otx2_mcam_flow_del(struct otx2_nic * pf)339f0a1913fSSubbaraya Sundeep void otx2_mcam_flow_del(struct otx2_nic *pf)
340f0a1913fSSubbaraya Sundeep {
341f0a1913fSSubbaraya Sundeep 	otx2_destroy_mcam_flows(pf);
342f0a1913fSSubbaraya Sundeep }
3433cffaed2SRakesh Babu EXPORT_SYMBOL(otx2_mcam_flow_del);
344f0a1913fSSubbaraya Sundeep 
34563ee5157SHariprasad Kelam /*  On success adds mcam entry
34663ee5157SHariprasad Kelam  *  On failure enable promisous mode
34763ee5157SHariprasad Kelam  */
otx2_do_add_macfilter(struct otx2_nic * pf,const u8 * mac)34863ee5157SHariprasad Kelam static int otx2_do_add_macfilter(struct otx2_nic *pf, const u8 *mac)
34963ee5157SHariprasad Kelam {
35063ee5157SHariprasad Kelam 	struct otx2_flow_config *flow_cfg = pf->flow_cfg;
35163ee5157SHariprasad Kelam 	struct npc_install_flow_req *req;
35263ee5157SHariprasad Kelam 	int err, i;
35363ee5157SHariprasad Kelam 
35463ee5157SHariprasad Kelam 	if (!(pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT))
35563ee5157SHariprasad Kelam 		return -ENOMEM;
35663ee5157SHariprasad Kelam 
35763ee5157SHariprasad Kelam 	/* dont have free mcam entries or uc list is greater than alloted */
35863ee5157SHariprasad Kelam 	if (netdev_uc_count(pf->netdev) > OTX2_MAX_UNICAST_FLOWS)
35963ee5157SHariprasad Kelam 		return -ENOMEM;
36063ee5157SHariprasad Kelam 
36163ee5157SHariprasad Kelam 	mutex_lock(&pf->mbox.lock);
36263ee5157SHariprasad Kelam 	req = otx2_mbox_alloc_msg_npc_install_flow(&pf->mbox);
36363ee5157SHariprasad Kelam 	if (!req) {
36463ee5157SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
36563ee5157SHariprasad Kelam 		return -ENOMEM;
36663ee5157SHariprasad Kelam 	}
36763ee5157SHariprasad Kelam 
36863ee5157SHariprasad Kelam 	/* unicast offset starts with 32 0..31 for ntuple */
36963ee5157SHariprasad Kelam 	for (i = 0; i <  OTX2_MAX_UNICAST_FLOWS; i++) {
37063ee5157SHariprasad Kelam 		if (pf->mac_table[i].inuse)
37163ee5157SHariprasad Kelam 			continue;
37263ee5157SHariprasad Kelam 		ether_addr_copy(pf->mac_table[i].addr, mac);
37363ee5157SHariprasad Kelam 		pf->mac_table[i].inuse = true;
37463ee5157SHariprasad Kelam 		pf->mac_table[i].mcam_entry =
3759917060fSSunil Goutham 			flow_cfg->def_ent[i + flow_cfg->unicast_offset];
37663ee5157SHariprasad Kelam 		req->entry =  pf->mac_table[i].mcam_entry;
37763ee5157SHariprasad Kelam 		break;
37863ee5157SHariprasad Kelam 	}
37963ee5157SHariprasad Kelam 
38063ee5157SHariprasad Kelam 	ether_addr_copy(req->packet.dmac, mac);
38163ee5157SHariprasad Kelam 	eth_broadcast_addr((u8 *)&req->mask.dmac);
38263ee5157SHariprasad Kelam 	req->features = BIT_ULL(NPC_DMAC);
38363ee5157SHariprasad Kelam 	req->channel = pf->hw.rx_chan_base;
38463ee5157SHariprasad Kelam 	req->intf = NIX_INTF_RX;
38563ee5157SHariprasad Kelam 	req->op = NIX_RX_ACTION_DEFAULT;
38663ee5157SHariprasad Kelam 	req->set_cntr = 1;
38763ee5157SHariprasad Kelam 
38863ee5157SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pf->mbox);
38963ee5157SHariprasad Kelam 	mutex_unlock(&pf->mbox.lock);
39063ee5157SHariprasad Kelam 
39163ee5157SHariprasad Kelam 	return err;
39263ee5157SHariprasad Kelam }
39363ee5157SHariprasad Kelam 
otx2_add_macfilter(struct net_device * netdev,const u8 * mac)39463ee5157SHariprasad Kelam int otx2_add_macfilter(struct net_device *netdev, const u8 *mac)
39563ee5157SHariprasad Kelam {
39663ee5157SHariprasad Kelam 	struct otx2_nic *pf = netdev_priv(netdev);
39763ee5157SHariprasad Kelam 
398fa5e0ccbSRatheesh Kannoth 	if (!bitmap_empty(pf->flow_cfg->dmacflt_bmap,
39979d2be38SHariprasad Kelam 			  pf->flow_cfg->dmacflt_max_flows))
40079d2be38SHariprasad Kelam 		netdev_warn(netdev,
40179d2be38SHariprasad Kelam 			    "Add %pM to CGX/RPM DMAC filters list as well\n",
40279d2be38SHariprasad Kelam 			    mac);
40379d2be38SHariprasad Kelam 
40463ee5157SHariprasad Kelam 	return otx2_do_add_macfilter(pf, mac);
40563ee5157SHariprasad Kelam }
40663ee5157SHariprasad Kelam 
otx2_get_mcamentry_for_mac(struct otx2_nic * pf,const u8 * mac,int * mcam_entry)40763ee5157SHariprasad Kelam static bool otx2_get_mcamentry_for_mac(struct otx2_nic *pf, const u8 *mac,
40863ee5157SHariprasad Kelam 				       int *mcam_entry)
40963ee5157SHariprasad Kelam {
41063ee5157SHariprasad Kelam 	int i;
41163ee5157SHariprasad Kelam 
41263ee5157SHariprasad Kelam 	for (i = 0; i < OTX2_MAX_UNICAST_FLOWS; i++) {
41363ee5157SHariprasad Kelam 		if (!pf->mac_table[i].inuse)
41463ee5157SHariprasad Kelam 			continue;
41563ee5157SHariprasad Kelam 
41663ee5157SHariprasad Kelam 		if (ether_addr_equal(pf->mac_table[i].addr, mac)) {
41763ee5157SHariprasad Kelam 			*mcam_entry = pf->mac_table[i].mcam_entry;
41863ee5157SHariprasad Kelam 			pf->mac_table[i].inuse = false;
41963ee5157SHariprasad Kelam 			return true;
42063ee5157SHariprasad Kelam 		}
42163ee5157SHariprasad Kelam 	}
42263ee5157SHariprasad Kelam 	return false;
42363ee5157SHariprasad Kelam }
42463ee5157SHariprasad Kelam 
otx2_del_macfilter(struct net_device * netdev,const u8 * mac)42563ee5157SHariprasad Kelam int otx2_del_macfilter(struct net_device *netdev, const u8 *mac)
42663ee5157SHariprasad Kelam {
42763ee5157SHariprasad Kelam 	struct otx2_nic *pf = netdev_priv(netdev);
42863ee5157SHariprasad Kelam 	struct npc_delete_flow_req *req;
42963ee5157SHariprasad Kelam 	int err, mcam_entry;
43063ee5157SHariprasad Kelam 
43163ee5157SHariprasad Kelam 	/* check does mcam entry exists for given mac */
43263ee5157SHariprasad Kelam 	if (!otx2_get_mcamentry_for_mac(pf, mac, &mcam_entry))
43363ee5157SHariprasad Kelam 		return 0;
43463ee5157SHariprasad Kelam 
43563ee5157SHariprasad Kelam 	mutex_lock(&pf->mbox.lock);
43663ee5157SHariprasad Kelam 	req = otx2_mbox_alloc_msg_npc_delete_flow(&pf->mbox);
43763ee5157SHariprasad Kelam 	if (!req) {
43863ee5157SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
43963ee5157SHariprasad Kelam 		return -ENOMEM;
44063ee5157SHariprasad Kelam 	}
44163ee5157SHariprasad Kelam 	req->entry = mcam_entry;
44263ee5157SHariprasad Kelam 	/* Send message to AF */
44363ee5157SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pf->mbox);
44463ee5157SHariprasad Kelam 	mutex_unlock(&pf->mbox.lock);
44563ee5157SHariprasad Kelam 
44663ee5157SHariprasad Kelam 	return err;
44763ee5157SHariprasad Kelam }
44863ee5157SHariprasad Kelam 
otx2_find_flow(struct otx2_nic * pfvf,u32 location)449f0a1913fSSubbaraya Sundeep static struct otx2_flow *otx2_find_flow(struct otx2_nic *pfvf, u32 location)
450f0a1913fSSubbaraya Sundeep {
451f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter;
452f0a1913fSSubbaraya Sundeep 
453f0a1913fSSubbaraya Sundeep 	list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
454f0a1913fSSubbaraya Sundeep 		if (iter->location == location)
455f0a1913fSSubbaraya Sundeep 			return iter;
456f0a1913fSSubbaraya Sundeep 	}
457f0a1913fSSubbaraya Sundeep 
458f0a1913fSSubbaraya Sundeep 	return NULL;
459f0a1913fSSubbaraya Sundeep }
460f0a1913fSSubbaraya Sundeep 
otx2_add_flow_to_list(struct otx2_nic * pfvf,struct otx2_flow * flow)461f0a1913fSSubbaraya Sundeep static void otx2_add_flow_to_list(struct otx2_nic *pfvf, struct otx2_flow *flow)
462f0a1913fSSubbaraya Sundeep {
463f0a1913fSSubbaraya Sundeep 	struct list_head *head = &pfvf->flow_cfg->flow_list;
464f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter;
465f0a1913fSSubbaraya Sundeep 
466f0a1913fSSubbaraya Sundeep 	list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
467f0a1913fSSubbaraya Sundeep 		if (iter->location > flow->location)
468f0a1913fSSubbaraya Sundeep 			break;
469f0a1913fSSubbaraya Sundeep 		head = &iter->list;
470f0a1913fSSubbaraya Sundeep 	}
471f0a1913fSSubbaraya Sundeep 
472f0a1913fSSubbaraya Sundeep 	list_add(&flow->list, head);
473f0a1913fSSubbaraya Sundeep }
474f0a1913fSSubbaraya Sundeep 
otx2_get_maxflows(struct otx2_flow_config * flow_cfg)4753cffaed2SRakesh Babu int otx2_get_maxflows(struct otx2_flow_config *flow_cfg)
47679d2be38SHariprasad Kelam {
4773cffaed2SRakesh Babu 	if (!flow_cfg)
4783cffaed2SRakesh Babu 		return 0;
4793cffaed2SRakesh Babu 
4802e2a8126SSunil Goutham 	if (flow_cfg->nr_flows == flow_cfg->max_flows ||
481fa5e0ccbSRatheesh Kannoth 	    !bitmap_empty(flow_cfg->dmacflt_bmap,
48279d2be38SHariprasad Kelam 			  flow_cfg->dmacflt_max_flows))
4832e2a8126SSunil Goutham 		return flow_cfg->max_flows + flow_cfg->dmacflt_max_flows;
48479d2be38SHariprasad Kelam 	else
4852e2a8126SSunil Goutham 		return flow_cfg->max_flows;
48679d2be38SHariprasad Kelam }
4873cffaed2SRakesh Babu EXPORT_SYMBOL(otx2_get_maxflows);
48879d2be38SHariprasad Kelam 
otx2_get_flow(struct otx2_nic * pfvf,struct ethtool_rxnfc * nfc,u32 location)489f0a1913fSSubbaraya Sundeep int otx2_get_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
490f0a1913fSSubbaraya Sundeep 		  u32 location)
491f0a1913fSSubbaraya Sundeep {
492f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter;
493f0a1913fSSubbaraya Sundeep 
49479d2be38SHariprasad Kelam 	if (location >= otx2_get_maxflows(pfvf->flow_cfg))
495f0a1913fSSubbaraya Sundeep 		return -EINVAL;
496f0a1913fSSubbaraya Sundeep 
497f0a1913fSSubbaraya Sundeep 	list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
498f0a1913fSSubbaraya Sundeep 		if (iter->location == location) {
499f0a1913fSSubbaraya Sundeep 			nfc->fs = iter->flow_spec;
50081a43620SGeetha sowjanya 			nfc->rss_context = iter->rss_ctx_id;
501f0a1913fSSubbaraya Sundeep 			return 0;
502f0a1913fSSubbaraya Sundeep 		}
503f0a1913fSSubbaraya Sundeep 	}
504f0a1913fSSubbaraya Sundeep 
505f0a1913fSSubbaraya Sundeep 	return -ENOENT;
506f0a1913fSSubbaraya Sundeep }
507f0a1913fSSubbaraya Sundeep 
otx2_get_all_flows(struct otx2_nic * pfvf,struct ethtool_rxnfc * nfc,u32 * rule_locs)508f0a1913fSSubbaraya Sundeep int otx2_get_all_flows(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
509f0a1913fSSubbaraya Sundeep 		       u32 *rule_locs)
510f0a1913fSSubbaraya Sundeep {
511f41b2d67SSubbaraya Sundeep 	u32 rule_cnt = nfc->rule_cnt;
512f0a1913fSSubbaraya Sundeep 	u32 location = 0;
513f0a1913fSSubbaraya Sundeep 	int idx = 0;
514f0a1913fSSubbaraya Sundeep 	int err = 0;
515f0a1913fSSubbaraya Sundeep 
51679d2be38SHariprasad Kelam 	nfc->data = otx2_get_maxflows(pfvf->flow_cfg);
517f41b2d67SSubbaraya Sundeep 	while ((!err || err == -ENOENT) && idx < rule_cnt) {
518f0a1913fSSubbaraya Sundeep 		err = otx2_get_flow(pfvf, nfc, location);
519f0a1913fSSubbaraya Sundeep 		if (!err)
520f0a1913fSSubbaraya Sundeep 			rule_locs[idx++] = location;
521f0a1913fSSubbaraya Sundeep 		location++;
522f0a1913fSSubbaraya Sundeep 	}
523f41b2d67SSubbaraya Sundeep 	nfc->rule_cnt = rule_cnt;
524f0a1913fSSubbaraya Sundeep 
525f0a1913fSSubbaraya Sundeep 	return err;
526f0a1913fSSubbaraya Sundeep }
527f0a1913fSSubbaraya Sundeep 
otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec * fsp,struct npc_install_flow_req * req,u32 flow_type)528b7cf9661SNaveen Mamindlapalli static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp,
529f0a1913fSSubbaraya Sundeep 				  struct npc_install_flow_req *req,
530f0a1913fSSubbaraya Sundeep 				  u32 flow_type)
531f0a1913fSSubbaraya Sundeep {
532f0a1913fSSubbaraya Sundeep 	struct ethtool_usrip4_spec *ipv4_usr_mask = &fsp->m_u.usr_ip4_spec;
533f0a1913fSSubbaraya Sundeep 	struct ethtool_usrip4_spec *ipv4_usr_hdr = &fsp->h_u.usr_ip4_spec;
534f0a1913fSSubbaraya Sundeep 	struct ethtool_tcpip4_spec *ipv4_l4_mask = &fsp->m_u.tcp_ip4_spec;
535f0a1913fSSubbaraya Sundeep 	struct ethtool_tcpip4_spec *ipv4_l4_hdr = &fsp->h_u.tcp_ip4_spec;
536b7cf9661SNaveen Mamindlapalli 	struct ethtool_ah_espip4_spec *ah_esp_hdr = &fsp->h_u.ah_ip4_spec;
537b7cf9661SNaveen Mamindlapalli 	struct ethtool_ah_espip4_spec *ah_esp_mask = &fsp->m_u.ah_ip4_spec;
538f0a1913fSSubbaraya Sundeep 	struct flow_msg *pmask = &req->mask;
539f0a1913fSSubbaraya Sundeep 	struct flow_msg *pkt = &req->packet;
540f0a1913fSSubbaraya Sundeep 
541f0a1913fSSubbaraya Sundeep 	switch (flow_type) {
542f0a1913fSSubbaraya Sundeep 	case IP_USER_FLOW:
543f0a1913fSSubbaraya Sundeep 		if (ipv4_usr_mask->ip4src) {
544f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip4src, &ipv4_usr_hdr->ip4src,
545f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip4src));
546f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip4src, &ipv4_usr_mask->ip4src,
547f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip4src));
548f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SIP_IPV4);
549f0a1913fSSubbaraya Sundeep 		}
550f0a1913fSSubbaraya Sundeep 		if (ipv4_usr_mask->ip4dst) {
551f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip4dst, &ipv4_usr_hdr->ip4dst,
552f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip4dst));
553f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip4dst, &ipv4_usr_mask->ip4dst,
554f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip4dst));
555f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DIP_IPV4);
556f0a1913fSSubbaraya Sundeep 		}
5572b9cef66SNaveen Mamindlapalli 		if (ipv4_usr_mask->tos) {
5582b9cef66SNaveen Mamindlapalli 			pkt->tos = ipv4_usr_hdr->tos;
5592b9cef66SNaveen Mamindlapalli 			pmask->tos = ipv4_usr_mask->tos;
5602b9cef66SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_TOS);
5612b9cef66SNaveen Mamindlapalli 		}
5622b9cef66SNaveen Mamindlapalli 		if (ipv4_usr_mask->proto) {
5632b9cef66SNaveen Mamindlapalli 			switch (ipv4_usr_hdr->proto) {
5642b9cef66SNaveen Mamindlapalli 			case IPPROTO_ICMP:
5652b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_ICMP);
5662b9cef66SNaveen Mamindlapalli 				break;
5672b9cef66SNaveen Mamindlapalli 			case IPPROTO_TCP:
5682b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_TCP);
5692b9cef66SNaveen Mamindlapalli 				break;
5702b9cef66SNaveen Mamindlapalli 			case IPPROTO_UDP:
5712b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_UDP);
5722b9cef66SNaveen Mamindlapalli 				break;
5732b9cef66SNaveen Mamindlapalli 			case IPPROTO_SCTP:
5742b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_SCTP);
5752b9cef66SNaveen Mamindlapalli 				break;
5762b9cef66SNaveen Mamindlapalli 			case IPPROTO_AH:
5772b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_AH);
5782b9cef66SNaveen Mamindlapalli 				break;
5792b9cef66SNaveen Mamindlapalli 			case IPPROTO_ESP:
5802b9cef66SNaveen Mamindlapalli 				req->features |= BIT_ULL(NPC_IPPROTO_ESP);
5812b9cef66SNaveen Mamindlapalli 				break;
5822b9cef66SNaveen Mamindlapalli 			default:
5832b9cef66SNaveen Mamindlapalli 				return -EOPNOTSUPP;
5842b9cef66SNaveen Mamindlapalli 			}
5852b9cef66SNaveen Mamindlapalli 		}
586b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IP);
587b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
588b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
589f0a1913fSSubbaraya Sundeep 		break;
590f0a1913fSSubbaraya Sundeep 	case TCP_V4_FLOW:
591f0a1913fSSubbaraya Sundeep 	case UDP_V4_FLOW:
592f0a1913fSSubbaraya Sundeep 	case SCTP_V4_FLOW:
593b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IP);
594b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
595b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
596f0a1913fSSubbaraya Sundeep 		if (ipv4_l4_mask->ip4src) {
597f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip4src, &ipv4_l4_hdr->ip4src,
598f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip4src));
599f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip4src, &ipv4_l4_mask->ip4src,
600f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip4src));
601f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SIP_IPV4);
602f0a1913fSSubbaraya Sundeep 		}
603f0a1913fSSubbaraya Sundeep 		if (ipv4_l4_mask->ip4dst) {
604f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip4dst, &ipv4_l4_hdr->ip4dst,
605f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip4dst));
606f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip4dst, &ipv4_l4_mask->ip4dst,
607f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip4dst));
608f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DIP_IPV4);
609f0a1913fSSubbaraya Sundeep 		}
6102b9cef66SNaveen Mamindlapalli 		if (ipv4_l4_mask->tos) {
6112b9cef66SNaveen Mamindlapalli 			pkt->tos = ipv4_l4_hdr->tos;
6122b9cef66SNaveen Mamindlapalli 			pmask->tos = ipv4_l4_mask->tos;
6132b9cef66SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_TOS);
6142b9cef66SNaveen Mamindlapalli 		}
615f0a1913fSSubbaraya Sundeep 		if (ipv4_l4_mask->psrc) {
616f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->sport, &ipv4_l4_hdr->psrc,
617f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->sport));
618f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->sport, &ipv4_l4_mask->psrc,
619f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->sport));
620f0a1913fSSubbaraya Sundeep 			if (flow_type == UDP_V4_FLOW)
621f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_UDP);
622f0a1913fSSubbaraya Sundeep 			else if (flow_type == TCP_V4_FLOW)
623f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_TCP);
624f0a1913fSSubbaraya Sundeep 			else
625f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_SCTP);
626f0a1913fSSubbaraya Sundeep 		}
627f0a1913fSSubbaraya Sundeep 		if (ipv4_l4_mask->pdst) {
628f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->dport, &ipv4_l4_hdr->pdst,
629f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->dport));
630f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->dport, &ipv4_l4_mask->pdst,
631f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->dport));
632f0a1913fSSubbaraya Sundeep 			if (flow_type == UDP_V4_FLOW)
633f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_UDP);
634f0a1913fSSubbaraya Sundeep 			else if (flow_type == TCP_V4_FLOW)
635f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_TCP);
636f0a1913fSSubbaraya Sundeep 			else
637f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_SCTP);
638f0a1913fSSubbaraya Sundeep 		}
639b7cf9661SNaveen Mamindlapalli 		if (flow_type == UDP_V4_FLOW)
640b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_UDP);
641b7cf9661SNaveen Mamindlapalli 		else if (flow_type == TCP_V4_FLOW)
642b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_TCP);
643b7cf9661SNaveen Mamindlapalli 		else
644b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_SCTP);
645b7cf9661SNaveen Mamindlapalli 		break;
646b7cf9661SNaveen Mamindlapalli 	case AH_V4_FLOW:
647b7cf9661SNaveen Mamindlapalli 	case ESP_V4_FLOW:
648b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IP);
649b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
650b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
651b7cf9661SNaveen Mamindlapalli 		if (ah_esp_mask->ip4src) {
652b7cf9661SNaveen Mamindlapalli 			memcpy(&pkt->ip4src, &ah_esp_hdr->ip4src,
653b7cf9661SNaveen Mamindlapalli 			       sizeof(pkt->ip4src));
654b7cf9661SNaveen Mamindlapalli 			memcpy(&pmask->ip4src, &ah_esp_mask->ip4src,
655b7cf9661SNaveen Mamindlapalli 			       sizeof(pmask->ip4src));
656b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_SIP_IPV4);
657b7cf9661SNaveen Mamindlapalli 		}
658b7cf9661SNaveen Mamindlapalli 		if (ah_esp_mask->ip4dst) {
659b7cf9661SNaveen Mamindlapalli 			memcpy(&pkt->ip4dst, &ah_esp_hdr->ip4dst,
660b7cf9661SNaveen Mamindlapalli 			       sizeof(pkt->ip4dst));
661b7cf9661SNaveen Mamindlapalli 			memcpy(&pmask->ip4dst, &ah_esp_mask->ip4dst,
662b7cf9661SNaveen Mamindlapalli 			       sizeof(pmask->ip4dst));
663b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_DIP_IPV4);
664b7cf9661SNaveen Mamindlapalli 		}
6652b9cef66SNaveen Mamindlapalli 		if (ah_esp_mask->tos) {
6662b9cef66SNaveen Mamindlapalli 			pkt->tos = ah_esp_hdr->tos;
6672b9cef66SNaveen Mamindlapalli 			pmask->tos = ah_esp_mask->tos;
6682b9cef66SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_TOS);
6692b9cef66SNaveen Mamindlapalli 		}
670b7cf9661SNaveen Mamindlapalli 
671b7cf9661SNaveen Mamindlapalli 		/* NPC profile doesn't extract AH/ESP header fields */
6722b9cef66SNaveen Mamindlapalli 		if (ah_esp_mask->spi & ah_esp_hdr->spi)
673b7cf9661SNaveen Mamindlapalli 			return -EOPNOTSUPP;
674b7cf9661SNaveen Mamindlapalli 
675b7cf9661SNaveen Mamindlapalli 		if (flow_type == AH_V4_FLOW)
676b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_AH);
677b7cf9661SNaveen Mamindlapalli 		else
678b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_ESP);
679f0a1913fSSubbaraya Sundeep 		break;
680f0a1913fSSubbaraya Sundeep 	default:
681f0a1913fSSubbaraya Sundeep 		break;
682f0a1913fSSubbaraya Sundeep 	}
683b7cf9661SNaveen Mamindlapalli 
684b7cf9661SNaveen Mamindlapalli 	return 0;
685f0a1913fSSubbaraya Sundeep }
686f0a1913fSSubbaraya Sundeep 
otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec * fsp,struct npc_install_flow_req * req,u32 flow_type)687b7cf9661SNaveen Mamindlapalli static int otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec *fsp,
688f0a1913fSSubbaraya Sundeep 				  struct npc_install_flow_req *req,
689f0a1913fSSubbaraya Sundeep 				  u32 flow_type)
690f0a1913fSSubbaraya Sundeep {
691f0a1913fSSubbaraya Sundeep 	struct ethtool_usrip6_spec *ipv6_usr_mask = &fsp->m_u.usr_ip6_spec;
692f0a1913fSSubbaraya Sundeep 	struct ethtool_usrip6_spec *ipv6_usr_hdr = &fsp->h_u.usr_ip6_spec;
693f0a1913fSSubbaraya Sundeep 	struct ethtool_tcpip6_spec *ipv6_l4_mask = &fsp->m_u.tcp_ip6_spec;
694f0a1913fSSubbaraya Sundeep 	struct ethtool_tcpip6_spec *ipv6_l4_hdr = &fsp->h_u.tcp_ip6_spec;
695b7cf9661SNaveen Mamindlapalli 	struct ethtool_ah_espip6_spec *ah_esp_hdr = &fsp->h_u.ah_ip6_spec;
696b7cf9661SNaveen Mamindlapalli 	struct ethtool_ah_espip6_spec *ah_esp_mask = &fsp->m_u.ah_ip6_spec;
697f0a1913fSSubbaraya Sundeep 	struct flow_msg *pmask = &req->mask;
698f0a1913fSSubbaraya Sundeep 	struct flow_msg *pkt = &req->packet;
699f0a1913fSSubbaraya Sundeep 
700f0a1913fSSubbaraya Sundeep 	switch (flow_type) {
701f0a1913fSSubbaraya Sundeep 	case IPV6_USER_FLOW:
702f0a1913fSSubbaraya Sundeep 		if (!ipv6_addr_any((struct in6_addr *)ipv6_usr_mask->ip6src)) {
703f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip6src, &ipv6_usr_hdr->ip6src,
704f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip6src));
705f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip6src, &ipv6_usr_mask->ip6src,
706f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip6src));
707f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SIP_IPV6);
708f0a1913fSSubbaraya Sundeep 		}
709f0a1913fSSubbaraya Sundeep 		if (!ipv6_addr_any((struct in6_addr *)ipv6_usr_mask->ip6dst)) {
710f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip6dst, &ipv6_usr_hdr->ip6dst,
711f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip6dst));
712f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip6dst, &ipv6_usr_mask->ip6dst,
713f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip6dst));
714f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DIP_IPV6);
715f0a1913fSSubbaraya Sundeep 		}
716c672e372SSuman Ghosh 		if (ipv6_usr_hdr->l4_proto == IPPROTO_FRAGMENT) {
717c672e372SSuman Ghosh 			pkt->next_header = ipv6_usr_hdr->l4_proto;
718c672e372SSuman Ghosh 			pmask->next_header = ipv6_usr_mask->l4_proto;
719c672e372SSuman Ghosh 			req->features |= BIT_ULL(NPC_IPFRAG_IPV6);
720c672e372SSuman Ghosh 		}
721b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IPV6);
722b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
723b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
724f0a1913fSSubbaraya Sundeep 		break;
725f0a1913fSSubbaraya Sundeep 	case TCP_V6_FLOW:
726f0a1913fSSubbaraya Sundeep 	case UDP_V6_FLOW:
727f0a1913fSSubbaraya Sundeep 	case SCTP_V6_FLOW:
728b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IPV6);
729b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
730b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
731f0a1913fSSubbaraya Sundeep 		if (!ipv6_addr_any((struct in6_addr *)ipv6_l4_mask->ip6src)) {
732f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip6src, &ipv6_l4_hdr->ip6src,
733f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip6src));
734f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip6src, &ipv6_l4_mask->ip6src,
735f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip6src));
736f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SIP_IPV6);
737f0a1913fSSubbaraya Sundeep 		}
738f0a1913fSSubbaraya Sundeep 		if (!ipv6_addr_any((struct in6_addr *)ipv6_l4_mask->ip6dst)) {
739f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->ip6dst, &ipv6_l4_hdr->ip6dst,
740f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->ip6dst));
741f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->ip6dst, &ipv6_l4_mask->ip6dst,
742f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->ip6dst));
743f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DIP_IPV6);
744f0a1913fSSubbaraya Sundeep 		}
745f0a1913fSSubbaraya Sundeep 		if (ipv6_l4_mask->psrc) {
746f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->sport, &ipv6_l4_hdr->psrc,
747f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->sport));
748f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->sport, &ipv6_l4_mask->psrc,
749f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->sport));
750f0a1913fSSubbaraya Sundeep 			if (flow_type == UDP_V6_FLOW)
751f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_UDP);
752f0a1913fSSubbaraya Sundeep 			else if (flow_type == TCP_V6_FLOW)
753f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_TCP);
754f0a1913fSSubbaraya Sundeep 			else
755f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_SPORT_SCTP);
756f0a1913fSSubbaraya Sundeep 		}
757f0a1913fSSubbaraya Sundeep 		if (ipv6_l4_mask->pdst) {
758f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->dport, &ipv6_l4_hdr->pdst,
759f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->dport));
760f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->dport, &ipv6_l4_mask->pdst,
761f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->dport));
762f0a1913fSSubbaraya Sundeep 			if (flow_type == UDP_V6_FLOW)
763f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_UDP);
764f0a1913fSSubbaraya Sundeep 			else if (flow_type == TCP_V6_FLOW)
765f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_TCP);
766f0a1913fSSubbaraya Sundeep 			else
767f0a1913fSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_DPORT_SCTP);
768f0a1913fSSubbaraya Sundeep 		}
769b7cf9661SNaveen Mamindlapalli 		if (flow_type == UDP_V6_FLOW)
770b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_UDP);
771b7cf9661SNaveen Mamindlapalli 		else if (flow_type == TCP_V6_FLOW)
772b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_TCP);
773b7cf9661SNaveen Mamindlapalli 		else
774b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_SCTP);
775f0a1913fSSubbaraya Sundeep 		break;
776b7cf9661SNaveen Mamindlapalli 	case AH_V6_FLOW:
777b7cf9661SNaveen Mamindlapalli 	case ESP_V6_FLOW:
778b7cf9661SNaveen Mamindlapalli 		pkt->etype = cpu_to_be16(ETH_P_IPV6);
779b7cf9661SNaveen Mamindlapalli 		pmask->etype = cpu_to_be16(0xFFFF);
780b7cf9661SNaveen Mamindlapalli 		req->features |= BIT_ULL(NPC_ETYPE);
781b7cf9661SNaveen Mamindlapalli 		if (!ipv6_addr_any((struct in6_addr *)ah_esp_hdr->ip6src)) {
782b7cf9661SNaveen Mamindlapalli 			memcpy(&pkt->ip6src, &ah_esp_hdr->ip6src,
783b7cf9661SNaveen Mamindlapalli 			       sizeof(pkt->ip6src));
784b7cf9661SNaveen Mamindlapalli 			memcpy(&pmask->ip6src, &ah_esp_mask->ip6src,
785b7cf9661SNaveen Mamindlapalli 			       sizeof(pmask->ip6src));
786b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_SIP_IPV6);
787b7cf9661SNaveen Mamindlapalli 		}
788b7cf9661SNaveen Mamindlapalli 		if (!ipv6_addr_any((struct in6_addr *)ah_esp_hdr->ip6dst)) {
789b7cf9661SNaveen Mamindlapalli 			memcpy(&pkt->ip6dst, &ah_esp_hdr->ip6dst,
790b7cf9661SNaveen Mamindlapalli 			       sizeof(pkt->ip6dst));
791b7cf9661SNaveen Mamindlapalli 			memcpy(&pmask->ip6dst, &ah_esp_mask->ip6dst,
792b7cf9661SNaveen Mamindlapalli 			       sizeof(pmask->ip6dst));
793b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_DIP_IPV6);
794b7cf9661SNaveen Mamindlapalli 		}
795b7cf9661SNaveen Mamindlapalli 
796b7cf9661SNaveen Mamindlapalli 		/* NPC profile doesn't extract AH/ESP header fields */
797b7cf9661SNaveen Mamindlapalli 		if ((ah_esp_mask->spi & ah_esp_hdr->spi) ||
7983acd9db9SDeepak R Varma 		    (ah_esp_mask->tclass & ah_esp_hdr->tclass))
799b7cf9661SNaveen Mamindlapalli 			return -EOPNOTSUPP;
800b7cf9661SNaveen Mamindlapalli 
801b7cf9661SNaveen Mamindlapalli 		if (flow_type == AH_V6_FLOW)
802b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_AH);
803b7cf9661SNaveen Mamindlapalli 		else
804b7cf9661SNaveen Mamindlapalli 			req->features |= BIT_ULL(NPC_IPPROTO_ESP);
805320daffdSGustavo A. R. Silva 		break;
806f0a1913fSSubbaraya Sundeep 	default:
807f0a1913fSSubbaraya Sundeep 		break;
808f0a1913fSSubbaraya Sundeep 	}
809b7cf9661SNaveen Mamindlapalli 
810b7cf9661SNaveen Mamindlapalli 	return 0;
811f0a1913fSSubbaraya Sundeep }
812f0a1913fSSubbaraya Sundeep 
otx2_prepare_flow_request(struct ethtool_rx_flow_spec * fsp,struct npc_install_flow_req * req)813dce677daSSubbaraya Sundeep static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
814f0a1913fSSubbaraya Sundeep 			      struct npc_install_flow_req *req)
815f0a1913fSSubbaraya Sundeep {
816f0a1913fSSubbaraya Sundeep 	struct ethhdr *eth_mask = &fsp->m_u.ether_spec;
817f0a1913fSSubbaraya Sundeep 	struct ethhdr *eth_hdr = &fsp->h_u.ether_spec;
818f0a1913fSSubbaraya Sundeep 	struct flow_msg *pmask = &req->mask;
819f0a1913fSSubbaraya Sundeep 	struct flow_msg *pkt = &req->packet;
820f0a1913fSSubbaraya Sundeep 	u32 flow_type;
821b7cf9661SNaveen Mamindlapalli 	int ret;
822f0a1913fSSubbaraya Sundeep 
82381a43620SGeetha sowjanya 	flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
824f0a1913fSSubbaraya Sundeep 	switch (flow_type) {
825f0a1913fSSubbaraya Sundeep 	/* bits not set in mask are don't care */
826f0a1913fSSubbaraya Sundeep 	case ETHER_FLOW:
827f0a1913fSSubbaraya Sundeep 		if (!is_zero_ether_addr(eth_mask->h_source)) {
828f0a1913fSSubbaraya Sundeep 			ether_addr_copy(pkt->smac, eth_hdr->h_source);
829f0a1913fSSubbaraya Sundeep 			ether_addr_copy(pmask->smac, eth_mask->h_source);
830f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_SMAC);
831f0a1913fSSubbaraya Sundeep 		}
832f0a1913fSSubbaraya Sundeep 		if (!is_zero_ether_addr(eth_mask->h_dest)) {
833f0a1913fSSubbaraya Sundeep 			ether_addr_copy(pkt->dmac, eth_hdr->h_dest);
834f0a1913fSSubbaraya Sundeep 			ether_addr_copy(pmask->dmac, eth_mask->h_dest);
835f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_DMAC);
836f0a1913fSSubbaraya Sundeep 		}
8373cffaed2SRakesh Babu 		if (eth_hdr->h_proto) {
838f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->etype, &eth_hdr->h_proto,
839f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->etype));
840f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->etype, &eth_mask->h_proto,
841f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->etype));
842f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_ETYPE);
843f0a1913fSSubbaraya Sundeep 		}
844f0a1913fSSubbaraya Sundeep 		break;
845f0a1913fSSubbaraya Sundeep 	case IP_USER_FLOW:
846f0a1913fSSubbaraya Sundeep 	case TCP_V4_FLOW:
847f0a1913fSSubbaraya Sundeep 	case UDP_V4_FLOW:
848f0a1913fSSubbaraya Sundeep 	case SCTP_V4_FLOW:
849b7cf9661SNaveen Mamindlapalli 	case AH_V4_FLOW:
850b7cf9661SNaveen Mamindlapalli 	case ESP_V4_FLOW:
851b7cf9661SNaveen Mamindlapalli 		ret = otx2_prepare_ipv4_flow(fsp, req, flow_type);
852b7cf9661SNaveen Mamindlapalli 		if (ret)
853b7cf9661SNaveen Mamindlapalli 			return ret;
854f0a1913fSSubbaraya Sundeep 		break;
855f0a1913fSSubbaraya Sundeep 	case IPV6_USER_FLOW:
856f0a1913fSSubbaraya Sundeep 	case TCP_V6_FLOW:
857f0a1913fSSubbaraya Sundeep 	case UDP_V6_FLOW:
858f0a1913fSSubbaraya Sundeep 	case SCTP_V6_FLOW:
859b7cf9661SNaveen Mamindlapalli 	case AH_V6_FLOW:
860b7cf9661SNaveen Mamindlapalli 	case ESP_V6_FLOW:
861b7cf9661SNaveen Mamindlapalli 		ret = otx2_prepare_ipv6_flow(fsp, req, flow_type);
862b7cf9661SNaveen Mamindlapalli 		if (ret)
863b7cf9661SNaveen Mamindlapalli 			return ret;
864f0a1913fSSubbaraya Sundeep 		break;
865f0a1913fSSubbaraya Sundeep 	default:
866f0a1913fSSubbaraya Sundeep 		return -EOPNOTSUPP;
867f0a1913fSSubbaraya Sundeep 	}
868f0a1913fSSubbaraya Sundeep 	if (fsp->flow_type & FLOW_EXT) {
869dce677daSSubbaraya Sundeep 		u16 vlan_etype;
870dce677daSSubbaraya Sundeep 
871dce677daSSubbaraya Sundeep 		if (fsp->m_ext.vlan_etype) {
872dce677daSSubbaraya Sundeep 			/* Partial masks not supported */
873dce677daSSubbaraya Sundeep 			if (be16_to_cpu(fsp->m_ext.vlan_etype) != 0xFFFF)
874f0a1913fSSubbaraya Sundeep 				return -EINVAL;
875dce677daSSubbaraya Sundeep 
876dce677daSSubbaraya Sundeep 			vlan_etype = be16_to_cpu(fsp->h_ext.vlan_etype);
8778278ee2aSSuman Ghosh 
8788278ee2aSSuman Ghosh 			/* Drop rule with vlan_etype == 802.1Q
8798278ee2aSSuman Ghosh 			 * and vlan_id == 0 is not supported
8808278ee2aSSuman Ghosh 			 */
8818278ee2aSSuman Ghosh 			if (vlan_etype == ETH_P_8021Q && !fsp->m_ext.vlan_tci &&
8828278ee2aSSuman Ghosh 			    fsp->ring_cookie == RX_CLS_FLOW_DISC)
8838278ee2aSSuman Ghosh 				return -EINVAL;
8848278ee2aSSuman Ghosh 
885dce677daSSubbaraya Sundeep 			/* Only ETH_P_8021Q and ETH_P_802AD types supported */
886dce677daSSubbaraya Sundeep 			if (vlan_etype != ETH_P_8021Q &&
887dce677daSSubbaraya Sundeep 			    vlan_etype != ETH_P_8021AD)
888dce677daSSubbaraya Sundeep 				return -EINVAL;
889dce677daSSubbaraya Sundeep 
890dce677daSSubbaraya Sundeep 			memcpy(&pkt->vlan_etype, &fsp->h_ext.vlan_etype,
891dce677daSSubbaraya Sundeep 			       sizeof(pkt->vlan_etype));
892dce677daSSubbaraya Sundeep 			memcpy(&pmask->vlan_etype, &fsp->m_ext.vlan_etype,
893dce677daSSubbaraya Sundeep 			       sizeof(pmask->vlan_etype));
894dce677daSSubbaraya Sundeep 
895dce677daSSubbaraya Sundeep 			if (vlan_etype == ETH_P_8021Q)
896dce677daSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_VLAN_ETYPE_CTAG);
897dce677daSSubbaraya Sundeep 			else
898dce677daSSubbaraya Sundeep 				req->features |= BIT_ULL(NPC_VLAN_ETYPE_STAG);
899dce677daSSubbaraya Sundeep 		}
900dce677daSSubbaraya Sundeep 
901f0a1913fSSubbaraya Sundeep 		if (fsp->m_ext.vlan_tci) {
902f0a1913fSSubbaraya Sundeep 			memcpy(&pkt->vlan_tci, &fsp->h_ext.vlan_tci,
903f0a1913fSSubbaraya Sundeep 			       sizeof(pkt->vlan_tci));
904f0a1913fSSubbaraya Sundeep 			memcpy(&pmask->vlan_tci, &fsp->m_ext.vlan_tci,
905f0a1913fSSubbaraya Sundeep 			       sizeof(pmask->vlan_tci));
906f0a1913fSSubbaraya Sundeep 			req->features |= BIT_ULL(NPC_OUTER_VID);
907f0a1913fSSubbaraya Sundeep 		}
908f0a1913fSSubbaraya Sundeep 
909c672e372SSuman Ghosh 		if (fsp->m_ext.data[1]) {
910c672e372SSuman Ghosh 			if (flow_type == IP_USER_FLOW) {
911c672e372SSuman Ghosh 				if (be32_to_cpu(fsp->h_ext.data[1]) != IPV4_FLAG_MORE)
912c672e372SSuman Ghosh 					return -EINVAL;
913c672e372SSuman Ghosh 
914c672e372SSuman Ghosh 				pkt->ip_flag = be32_to_cpu(fsp->h_ext.data[1]);
915c672e372SSuman Ghosh 				pmask->ip_flag = be32_to_cpu(fsp->m_ext.data[1]);
916c672e372SSuman Ghosh 				req->features |= BIT_ULL(NPC_IPFRAG_IPV4);
917c672e372SSuman Ghosh 			} else if (fsp->h_ext.data[1] ==
918c672e372SSuman Ghosh 					cpu_to_be32(OTX2_DEFAULT_ACTION)) {
919c672e372SSuman Ghosh 				/* Not Drop/Direct to queue but use action
920c672e372SSuman Ghosh 				 * in default entry
921c672e372SSuman Ghosh 				 */
922f0a1913fSSubbaraya Sundeep 				req->op = NIX_RX_ACTION_DEFAULT;
923f0a1913fSSubbaraya Sundeep 			}
924c672e372SSuman Ghosh 		}
925c672e372SSuman Ghosh 	}
926f0a1913fSSubbaraya Sundeep 
927f0a1913fSSubbaraya Sundeep 	if (fsp->flow_type & FLOW_MAC_EXT &&
928f0a1913fSSubbaraya Sundeep 	    !is_zero_ether_addr(fsp->m_ext.h_dest)) {
929f0a1913fSSubbaraya Sundeep 		ether_addr_copy(pkt->dmac, fsp->h_ext.h_dest);
930f0a1913fSSubbaraya Sundeep 		ether_addr_copy(pmask->dmac, fsp->m_ext.h_dest);
931f0a1913fSSubbaraya Sundeep 		req->features |= BIT_ULL(NPC_DMAC);
932f0a1913fSSubbaraya Sundeep 	}
933f0a1913fSSubbaraya Sundeep 
934f0a1913fSSubbaraya Sundeep 	if (!req->features)
935f0a1913fSSubbaraya Sundeep 		return -EOPNOTSUPP;
936f0a1913fSSubbaraya Sundeep 
937f0a1913fSSubbaraya Sundeep 	return 0;
938f0a1913fSSubbaraya Sundeep }
939f0a1913fSSubbaraya Sundeep 
otx2_is_flow_rule_dmacfilter(struct otx2_nic * pfvf,struct ethtool_rx_flow_spec * fsp)94079d2be38SHariprasad Kelam static int otx2_is_flow_rule_dmacfilter(struct otx2_nic *pfvf,
94179d2be38SHariprasad Kelam 					struct ethtool_rx_flow_spec *fsp)
94279d2be38SHariprasad Kelam {
94379d2be38SHariprasad Kelam 	struct ethhdr *eth_mask = &fsp->m_u.ether_spec;
94479d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr = &fsp->h_u.ether_spec;
94579d2be38SHariprasad Kelam 	u64 ring_cookie = fsp->ring_cookie;
94679d2be38SHariprasad Kelam 	u32 flow_type;
94779d2be38SHariprasad Kelam 
94879d2be38SHariprasad Kelam 	if (!(pfvf->flags & OTX2_FLAG_DMACFLTR_SUPPORT))
94979d2be38SHariprasad Kelam 		return false;
95079d2be38SHariprasad Kelam 
95179d2be38SHariprasad Kelam 	flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
95279d2be38SHariprasad Kelam 
95379d2be38SHariprasad Kelam 	/* CGX/RPM block dmac filtering configured for white listing
95479d2be38SHariprasad Kelam 	 * check for action other than DROP
95579d2be38SHariprasad Kelam 	 */
95679d2be38SHariprasad Kelam 	if (flow_type == ETHER_FLOW && ring_cookie != RX_CLS_FLOW_DISC &&
95779d2be38SHariprasad Kelam 	    !ethtool_get_flow_spec_ring_vf(ring_cookie)) {
95879d2be38SHariprasad Kelam 		if (is_zero_ether_addr(eth_mask->h_dest) &&
95979d2be38SHariprasad Kelam 		    is_valid_ether_addr(eth_hdr->h_dest))
96079d2be38SHariprasad Kelam 			return true;
96179d2be38SHariprasad Kelam 	}
96279d2be38SHariprasad Kelam 
96379d2be38SHariprasad Kelam 	return false;
96479d2be38SHariprasad Kelam }
96579d2be38SHariprasad Kelam 
otx2_add_flow_msg(struct otx2_nic * pfvf,struct otx2_flow * flow)966f0a1913fSSubbaraya Sundeep static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow)
967f0a1913fSSubbaraya Sundeep {
968f0a1913fSSubbaraya Sundeep 	u64 ring_cookie = flow->flow_spec.ring_cookie;
9698e675581SHariprasad Kelam #ifdef CONFIG_DCB
9708e675581SHariprasad Kelam 	int vlan_prio, qidx, pfc_rule = 0;
9718e675581SHariprasad Kelam #endif
972f0a1913fSSubbaraya Sundeep 	struct npc_install_flow_req *req;
973f0a1913fSSubbaraya Sundeep 	int err, vf = 0;
974f0a1913fSSubbaraya Sundeep 
975f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
976f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox);
977f0a1913fSSubbaraya Sundeep 	if (!req) {
978f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
979f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
980f0a1913fSSubbaraya Sundeep 	}
981f0a1913fSSubbaraya Sundeep 
982f0a1913fSSubbaraya Sundeep 	err = otx2_prepare_flow_request(&flow->flow_spec, req);
983f0a1913fSSubbaraya Sundeep 	if (err) {
984f0a1913fSSubbaraya Sundeep 		/* free the allocated msg above */
985f0a1913fSSubbaraya Sundeep 		otx2_mbox_reset(&pfvf->mbox.mbox, 0);
986f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
987f0a1913fSSubbaraya Sundeep 		return err;
988f0a1913fSSubbaraya Sundeep 	}
989f0a1913fSSubbaraya Sundeep 
990f0a1913fSSubbaraya Sundeep 	req->entry = flow->entry;
991f0a1913fSSubbaraya Sundeep 	req->intf = NIX_INTF_RX;
992f0a1913fSSubbaraya Sundeep 	req->set_cntr = 1;
993f0a1913fSSubbaraya Sundeep 	req->channel = pfvf->hw.rx_chan_base;
994f0a1913fSSubbaraya Sundeep 	if (ring_cookie == RX_CLS_FLOW_DISC) {
995f0a1913fSSubbaraya Sundeep 		req->op = NIX_RX_ACTIONOP_DROP;
996f0a1913fSSubbaraya Sundeep 	} else {
997f0a1913fSSubbaraya Sundeep 		/* change to unicast only if action of default entry is not
998f0a1913fSSubbaraya Sundeep 		 * requested by user
999f0a1913fSSubbaraya Sundeep 		 */
100081a43620SGeetha sowjanya 		if (flow->flow_spec.flow_type & FLOW_RSS) {
100181a43620SGeetha sowjanya 			req->op = NIX_RX_ACTIONOP_RSS;
100281a43620SGeetha sowjanya 			req->index = flow->rss_ctx_id;
1003e7938365SSunil Goutham 			req->flow_key_alg = pfvf->hw.flowkey_alg_idx;
100481a43620SGeetha sowjanya 		} else {
1005f0a1913fSSubbaraya Sundeep 			req->op = NIX_RX_ACTIONOP_UCAST;
1006f0a1913fSSubbaraya Sundeep 			req->index = ethtool_get_flow_spec_ring(ring_cookie);
100781a43620SGeetha sowjanya 		}
1008f0a1913fSSubbaraya Sundeep 		vf = ethtool_get_flow_spec_ring_vf(ring_cookie);
1009f0a1913fSSubbaraya Sundeep 		if (vf > pci_num_vf(pfvf->pdev)) {
1010f0a1913fSSubbaraya Sundeep 			mutex_unlock(&pfvf->mbox.lock);
1011f0a1913fSSubbaraya Sundeep 			return -EINVAL;
1012f0a1913fSSubbaraya Sundeep 		}
10138e675581SHariprasad Kelam 
10148e675581SHariprasad Kelam #ifdef CONFIG_DCB
10158e675581SHariprasad Kelam 		/* Identify PFC rule if PFC enabled and ntuple rule is vlan */
10168e675581SHariprasad Kelam 		if (!vf && (req->features & BIT_ULL(NPC_OUTER_VID)) &&
10178e675581SHariprasad Kelam 		    pfvf->pfc_en && req->op != NIX_RX_ACTIONOP_RSS) {
10188e675581SHariprasad Kelam 			vlan_prio = ntohs(req->packet.vlan_tci) &
10198e675581SHariprasad Kelam 				    ntohs(req->mask.vlan_tci);
10208e675581SHariprasad Kelam 
10218e675581SHariprasad Kelam 			/* Get the priority */
10228e675581SHariprasad Kelam 			vlan_prio >>= 13;
10238e675581SHariprasad Kelam 			flow->rule_type |= PFC_FLOWCTRL_RULE;
10248e675581SHariprasad Kelam 			/* Check if PFC enabled for this priority */
10258e675581SHariprasad Kelam 			if (pfvf->pfc_en & BIT(vlan_prio)) {
10268e675581SHariprasad Kelam 				pfc_rule = true;
10278e675581SHariprasad Kelam 				qidx = req->index;
10288e675581SHariprasad Kelam 			}
10298e675581SHariprasad Kelam 		}
10308e675581SHariprasad Kelam #endif
1031f0a1913fSSubbaraya Sundeep 	}
1032f0a1913fSSubbaraya Sundeep 
1033f0a1913fSSubbaraya Sundeep 	/* ethtool ring_cookie has (VF + 1) for VF */
1034f0a1913fSSubbaraya Sundeep 	if (vf) {
1035f0a1913fSSubbaraya Sundeep 		req->vf = vf;
1036f0a1913fSSubbaraya Sundeep 		flow->is_vf = true;
1037f0a1913fSSubbaraya Sundeep 		flow->vf = vf;
1038f0a1913fSSubbaraya Sundeep 	}
1039f0a1913fSSubbaraya Sundeep 
1040f0a1913fSSubbaraya Sundeep 	/* Send message to AF */
1041f0a1913fSSubbaraya Sundeep 	err = otx2_sync_mbox_msg(&pfvf->mbox);
10428e675581SHariprasad Kelam 
10438e675581SHariprasad Kelam #ifdef CONFIG_DCB
10448e675581SHariprasad Kelam 	if (!err && pfc_rule)
10458e675581SHariprasad Kelam 		otx2_update_bpid_in_rqctx(pfvf, vlan_prio, qidx, true);
10468e675581SHariprasad Kelam #endif
10478e675581SHariprasad Kelam 
1048f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
1049f0a1913fSSubbaraya Sundeep 	return err;
1050f0a1913fSSubbaraya Sundeep }
1051f0a1913fSSubbaraya Sundeep 
otx2_add_flow_with_pfmac(struct otx2_nic * pfvf,struct otx2_flow * flow)105279d2be38SHariprasad Kelam static int otx2_add_flow_with_pfmac(struct otx2_nic *pfvf,
105379d2be38SHariprasad Kelam 				    struct otx2_flow *flow)
105479d2be38SHariprasad Kelam {
105579d2be38SHariprasad Kelam 	struct otx2_flow *pf_mac;
105679d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr;
105779d2be38SHariprasad Kelam 
105879d2be38SHariprasad Kelam 	pf_mac = kzalloc(sizeof(*pf_mac), GFP_KERNEL);
105979d2be38SHariprasad Kelam 	if (!pf_mac)
106079d2be38SHariprasad Kelam 		return -ENOMEM;
106179d2be38SHariprasad Kelam 
106279d2be38SHariprasad Kelam 	pf_mac->entry = 0;
10638e675581SHariprasad Kelam 	pf_mac->rule_type |= DMAC_FILTER_RULE;
10642e2a8126SSunil Goutham 	pf_mac->location = pfvf->flow_cfg->max_flows;
106579d2be38SHariprasad Kelam 	memcpy(&pf_mac->flow_spec, &flow->flow_spec,
106679d2be38SHariprasad Kelam 	       sizeof(struct ethtool_rx_flow_spec));
106779d2be38SHariprasad Kelam 	pf_mac->flow_spec.location = pf_mac->location;
106879d2be38SHariprasad Kelam 
106979d2be38SHariprasad Kelam 	/* Copy PF mac address */
107079d2be38SHariprasad Kelam 	eth_hdr = &pf_mac->flow_spec.h_u.ether_spec;
107179d2be38SHariprasad Kelam 	ether_addr_copy(eth_hdr->h_dest, pfvf->netdev->dev_addr);
107279d2be38SHariprasad Kelam 
107379d2be38SHariprasad Kelam 	/* Install DMAC filter with PF mac address */
107479d2be38SHariprasad Kelam 	otx2_dmacflt_add(pfvf, eth_hdr->h_dest, 0);
107579d2be38SHariprasad Kelam 
107679d2be38SHariprasad Kelam 	otx2_add_flow_to_list(pfvf, pf_mac);
107779d2be38SHariprasad Kelam 	pfvf->flow_cfg->nr_flows++;
1078fa5e0ccbSRatheesh Kannoth 	set_bit(0, pfvf->flow_cfg->dmacflt_bmap);
107979d2be38SHariprasad Kelam 
108079d2be38SHariprasad Kelam 	return 0;
108179d2be38SHariprasad Kelam }
108279d2be38SHariprasad Kelam 
otx2_add_flow(struct otx2_nic * pfvf,struct ethtool_rxnfc * nfc)108381a43620SGeetha sowjanya int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
1084f0a1913fSSubbaraya Sundeep {
1085f0a1913fSSubbaraya Sundeep 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
108681a43620SGeetha sowjanya 	struct ethtool_rx_flow_spec *fsp = &nfc->fs;
1087f0a1913fSSubbaraya Sundeep 	struct otx2_flow *flow;
108879d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr;
1089f0a1913fSSubbaraya Sundeep 	bool new = false;
109079d2be38SHariprasad Kelam 	int err = 0;
1091*f174a0daSSuman Ghosh 	u64 vf_num;
109281a43620SGeetha sowjanya 	u32 ring;
1093f0a1913fSSubbaraya Sundeep 
1094a515e5b5SSunil Goutham 	if (!flow_cfg->max_flows) {
1095a515e5b5SSunil Goutham 		netdev_err(pfvf->netdev,
1096a515e5b5SSunil Goutham 			   "Ntuple rule count is 0, allocate and retry\n");
1097a515e5b5SSunil Goutham 		return -EINVAL;
1098a515e5b5SSunil Goutham 	}
1099a515e5b5SSunil Goutham 
110081a43620SGeetha sowjanya 	ring = ethtool_get_flow_spec_ring(fsp->ring_cookie);
1101f0a1913fSSubbaraya Sundeep 	if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT))
1102f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
1103f0a1913fSSubbaraya Sundeep 
1104*f174a0daSSuman Ghosh 	/* Number of queues on a VF can be greater or less than
1105*f174a0daSSuman Ghosh 	 * the PF's queue. Hence no need to check for the
1106*f174a0daSSuman Ghosh 	 * queue count. Hence no need to check queue count if PF
1107*f174a0daSSuman Ghosh 	 * is installing for its VF. Below is the expected vf_num value
1108*f174a0daSSuman Ghosh 	 * based on the ethtool commands.
1109*f174a0daSSuman Ghosh 	 *
1110*f174a0daSSuman Ghosh 	 * e.g.
1111*f174a0daSSuman Ghosh 	 * 1. ethtool -U <netdev> ... action -1  ==> vf_num:255
1112*f174a0daSSuman Ghosh 	 * 2. ethtool -U <netdev> ... action <queue_num>  ==> vf_num:0
1113*f174a0daSSuman Ghosh 	 * 3. ethtool -U <netdev> ... vf <vf_idx> queue <queue_num>  ==>
1114*f174a0daSSuman Ghosh 	 *    vf_num:vf_idx+1
1115*f174a0daSSuman Ghosh 	 */
1116*f174a0daSSuman Ghosh 	vf_num = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);
1117*f174a0daSSuman Ghosh 	if (!is_otx2_vf(pfvf->pcifunc) && !vf_num &&
1118*f174a0daSSuman Ghosh 	    ring >= pfvf->hw.rx_queues && fsp->ring_cookie != RX_CLS_FLOW_DISC)
1119f0a1913fSSubbaraya Sundeep 		return -EINVAL;
1120f0a1913fSSubbaraya Sundeep 
112179d2be38SHariprasad Kelam 	if (fsp->location >= otx2_get_maxflows(flow_cfg))
1122f0a1913fSSubbaraya Sundeep 		return -EINVAL;
1123f0a1913fSSubbaraya Sundeep 
1124f0a1913fSSubbaraya Sundeep 	flow = otx2_find_flow(pfvf, fsp->location);
1125f0a1913fSSubbaraya Sundeep 	if (!flow) {
112679d2be38SHariprasad Kelam 		flow = kzalloc(sizeof(*flow), GFP_KERNEL);
1127f0a1913fSSubbaraya Sundeep 		if (!flow)
1128f0a1913fSSubbaraya Sundeep 			return -ENOMEM;
1129f0a1913fSSubbaraya Sundeep 		flow->location = fsp->location;
1130dce677daSSubbaraya Sundeep 		flow->entry = flow_cfg->flow_ent[flow->location];
1131f0a1913fSSubbaraya Sundeep 		new = true;
1132f0a1913fSSubbaraya Sundeep 	}
1133f0a1913fSSubbaraya Sundeep 	/* struct copy */
1134f0a1913fSSubbaraya Sundeep 	flow->flow_spec = *fsp;
1135f0a1913fSSubbaraya Sundeep 
113681a43620SGeetha sowjanya 	if (fsp->flow_type & FLOW_RSS)
113781a43620SGeetha sowjanya 		flow->rss_ctx_id = nfc->rss_context;
113881a43620SGeetha sowjanya 
113979d2be38SHariprasad Kelam 	if (otx2_is_flow_rule_dmacfilter(pfvf, &flow->flow_spec)) {
114079d2be38SHariprasad Kelam 		eth_hdr = &flow->flow_spec.h_u.ether_spec;
114179d2be38SHariprasad Kelam 
114279d2be38SHariprasad Kelam 		/* Sync dmac filter table with updated fields */
11438e675581SHariprasad Kelam 		if (flow->rule_type & DMAC_FILTER_RULE)
114479d2be38SHariprasad Kelam 			return otx2_dmacflt_update(pfvf, eth_hdr->h_dest,
114579d2be38SHariprasad Kelam 						   flow->entry);
114679d2be38SHariprasad Kelam 
1147fa5e0ccbSRatheesh Kannoth 		if (bitmap_full(flow_cfg->dmacflt_bmap,
114879d2be38SHariprasad Kelam 				flow_cfg->dmacflt_max_flows)) {
114979d2be38SHariprasad Kelam 			netdev_warn(pfvf->netdev,
115079d2be38SHariprasad Kelam 				    "Can't insert the rule %d as max allowed dmac filters are %d\n",
115179d2be38SHariprasad Kelam 				    flow->location +
115279d2be38SHariprasad Kelam 				    flow_cfg->dmacflt_max_flows,
115379d2be38SHariprasad Kelam 				    flow_cfg->dmacflt_max_flows);
115479d2be38SHariprasad Kelam 			err = -EINVAL;
115579d2be38SHariprasad Kelam 			if (new)
115679d2be38SHariprasad Kelam 				kfree(flow);
115779d2be38SHariprasad Kelam 			return err;
115879d2be38SHariprasad Kelam 		}
115979d2be38SHariprasad Kelam 
116079d2be38SHariprasad Kelam 		/* Install PF mac address to DMAC filter list */
1161fa5e0ccbSRatheesh Kannoth 		if (!test_bit(0, flow_cfg->dmacflt_bmap))
116279d2be38SHariprasad Kelam 			otx2_add_flow_with_pfmac(pfvf, flow);
116379d2be38SHariprasad Kelam 
11648e675581SHariprasad Kelam 		flow->rule_type |= DMAC_FILTER_RULE;
1165fa5e0ccbSRatheesh Kannoth 		flow->entry = find_first_zero_bit(flow_cfg->dmacflt_bmap,
116679d2be38SHariprasad Kelam 						  flow_cfg->dmacflt_max_flows);
11672e2a8126SSunil Goutham 		fsp->location = flow_cfg->max_flows + flow->entry;
116879d2be38SHariprasad Kelam 		flow->flow_spec.location = fsp->location;
116979d2be38SHariprasad Kelam 		flow->location = fsp->location;
117079d2be38SHariprasad Kelam 
1171fa5e0ccbSRatheesh Kannoth 		set_bit(flow->entry, flow_cfg->dmacflt_bmap);
117279d2be38SHariprasad Kelam 		otx2_dmacflt_add(pfvf, eth_hdr->h_dest, flow->entry);
117379d2be38SHariprasad Kelam 
117479d2be38SHariprasad Kelam 	} else {
11752e2a8126SSunil Goutham 		if (flow->location >= pfvf->flow_cfg->max_flows) {
117679d2be38SHariprasad Kelam 			netdev_warn(pfvf->netdev,
117779d2be38SHariprasad Kelam 				    "Can't insert non dmac ntuple rule at %d, allowed range %d-0\n",
117879d2be38SHariprasad Kelam 				    flow->location,
11792e2a8126SSunil Goutham 				    flow_cfg->max_flows - 1);
118079d2be38SHariprasad Kelam 			err = -EINVAL;
118179d2be38SHariprasad Kelam 		} else {
1182f0a1913fSSubbaraya Sundeep 			err = otx2_add_flow_msg(pfvf, flow);
118379d2be38SHariprasad Kelam 		}
118479d2be38SHariprasad Kelam 	}
118579d2be38SHariprasad Kelam 
1186f0a1913fSSubbaraya Sundeep 	if (err) {
11873cffaed2SRakesh Babu 		if (err == MBOX_MSG_INVALID)
11883cffaed2SRakesh Babu 			err = -EINVAL;
1189f0a1913fSSubbaraya Sundeep 		if (new)
1190f0a1913fSSubbaraya Sundeep 			kfree(flow);
1191f0a1913fSSubbaraya Sundeep 		return err;
1192f0a1913fSSubbaraya Sundeep 	}
1193f0a1913fSSubbaraya Sundeep 
1194f0a1913fSSubbaraya Sundeep 	/* add the new flow installed to list */
1195f0a1913fSSubbaraya Sundeep 	if (new) {
1196f0a1913fSSubbaraya Sundeep 		otx2_add_flow_to_list(pfvf, flow);
1197f0a1913fSSubbaraya Sundeep 		flow_cfg->nr_flows++;
1198f0a1913fSSubbaraya Sundeep 	}
1199f0a1913fSSubbaraya Sundeep 
1200*f174a0daSSuman Ghosh 	if (flow->is_vf)
1201*f174a0daSSuman Ghosh 		netdev_info(pfvf->netdev,
1202*f174a0daSSuman Ghosh 			    "Make sure that VF's queue number is within its queue limit\n");
1203f0a1913fSSubbaraya Sundeep 	return 0;
1204f0a1913fSSubbaraya Sundeep }
1205f0a1913fSSubbaraya Sundeep 
otx2_remove_flow_msg(struct otx2_nic * pfvf,u16 entry,bool all)1206f0a1913fSSubbaraya Sundeep static int otx2_remove_flow_msg(struct otx2_nic *pfvf, u16 entry, bool all)
1207f0a1913fSSubbaraya Sundeep {
1208f0a1913fSSubbaraya Sundeep 	struct npc_delete_flow_req *req;
1209f0a1913fSSubbaraya Sundeep 	int err;
1210f0a1913fSSubbaraya Sundeep 
1211f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
1212f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
1213f0a1913fSSubbaraya Sundeep 	if (!req) {
1214f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
1215f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
1216f0a1913fSSubbaraya Sundeep 	}
1217f0a1913fSSubbaraya Sundeep 
1218f0a1913fSSubbaraya Sundeep 	req->entry = entry;
1219f0a1913fSSubbaraya Sundeep 	if (all)
1220f0a1913fSSubbaraya Sundeep 		req->all = 1;
1221f0a1913fSSubbaraya Sundeep 
1222f0a1913fSSubbaraya Sundeep 	/* Send message to AF */
1223f0a1913fSSubbaraya Sundeep 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1224f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
1225f0a1913fSSubbaraya Sundeep 	return err;
1226f0a1913fSSubbaraya Sundeep }
1227f0a1913fSSubbaraya Sundeep 
otx2_update_rem_pfmac(struct otx2_nic * pfvf,int req)122879d2be38SHariprasad Kelam static void otx2_update_rem_pfmac(struct otx2_nic *pfvf, int req)
122979d2be38SHariprasad Kelam {
123079d2be38SHariprasad Kelam 	struct otx2_flow *iter;
123179d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr;
123279d2be38SHariprasad Kelam 	bool found = false;
123379d2be38SHariprasad Kelam 
123479d2be38SHariprasad Kelam 	list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
12358e675581SHariprasad Kelam 		if ((iter->rule_type & DMAC_FILTER_RULE) && iter->entry == 0) {
123679d2be38SHariprasad Kelam 			eth_hdr = &iter->flow_spec.h_u.ether_spec;
123779d2be38SHariprasad Kelam 			if (req == DMAC_ADDR_DEL) {
123879d2be38SHariprasad Kelam 				otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
123979d2be38SHariprasad Kelam 						    0);
1240fa5e0ccbSRatheesh Kannoth 				clear_bit(0, pfvf->flow_cfg->dmacflt_bmap);
124179d2be38SHariprasad Kelam 				found = true;
124279d2be38SHariprasad Kelam 			} else {
124379d2be38SHariprasad Kelam 				ether_addr_copy(eth_hdr->h_dest,
124479d2be38SHariprasad Kelam 						pfvf->netdev->dev_addr);
1245fa5e0ccbSRatheesh Kannoth 
124679d2be38SHariprasad Kelam 				otx2_dmacflt_update(pfvf, eth_hdr->h_dest, 0);
124779d2be38SHariprasad Kelam 			}
124879d2be38SHariprasad Kelam 			break;
124979d2be38SHariprasad Kelam 		}
125079d2be38SHariprasad Kelam 	}
125179d2be38SHariprasad Kelam 
125279d2be38SHariprasad Kelam 	if (found) {
125379d2be38SHariprasad Kelam 		list_del(&iter->list);
125479d2be38SHariprasad Kelam 		kfree(iter);
125579d2be38SHariprasad Kelam 		pfvf->flow_cfg->nr_flows--;
125679d2be38SHariprasad Kelam 	}
125779d2be38SHariprasad Kelam }
125879d2be38SHariprasad Kelam 
otx2_remove_flow(struct otx2_nic * pfvf,u32 location)1259f0a1913fSSubbaraya Sundeep int otx2_remove_flow(struct otx2_nic *pfvf, u32 location)
1260f0a1913fSSubbaraya Sundeep {
1261f0a1913fSSubbaraya Sundeep 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1262f0a1913fSSubbaraya Sundeep 	struct otx2_flow *flow;
1263f0a1913fSSubbaraya Sundeep 	int err;
1264f0a1913fSSubbaraya Sundeep 
126579d2be38SHariprasad Kelam 	if (location >= otx2_get_maxflows(flow_cfg))
1266f0a1913fSSubbaraya Sundeep 		return -EINVAL;
1267f0a1913fSSubbaraya Sundeep 
1268f0a1913fSSubbaraya Sundeep 	flow = otx2_find_flow(pfvf, location);
1269f0a1913fSSubbaraya Sundeep 	if (!flow)
1270f0a1913fSSubbaraya Sundeep 		return -ENOENT;
1271f0a1913fSSubbaraya Sundeep 
12728e675581SHariprasad Kelam 	if (flow->rule_type & DMAC_FILTER_RULE) {
127379d2be38SHariprasad Kelam 		struct ethhdr *eth_hdr = &flow->flow_spec.h_u.ether_spec;
127479d2be38SHariprasad Kelam 
127579d2be38SHariprasad Kelam 		/* user not allowed to remove dmac filter with interface mac */
127679d2be38SHariprasad Kelam 		if (ether_addr_equal(pfvf->netdev->dev_addr, eth_hdr->h_dest))
127779d2be38SHariprasad Kelam 			return -EPERM;
127879d2be38SHariprasad Kelam 
127979d2be38SHariprasad Kelam 		err = otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
128079d2be38SHariprasad Kelam 					  flow->entry);
1281fa5e0ccbSRatheesh Kannoth 		clear_bit(flow->entry, flow_cfg->dmacflt_bmap);
128279d2be38SHariprasad Kelam 		/* If all dmac filters are removed delete macfilter with
128379d2be38SHariprasad Kelam 		 * interface mac address and configure CGX/RPM block in
128479d2be38SHariprasad Kelam 		 * promiscuous mode
128579d2be38SHariprasad Kelam 		 */
1286fa5e0ccbSRatheesh Kannoth 		if (bitmap_weight(flow_cfg->dmacflt_bmap,
128779d2be38SHariprasad Kelam 				  flow_cfg->dmacflt_max_flows) == 1)
128879d2be38SHariprasad Kelam 			otx2_update_rem_pfmac(pfvf, DMAC_ADDR_DEL);
128979d2be38SHariprasad Kelam 	} else {
12908e675581SHariprasad Kelam #ifdef CONFIG_DCB
12918e675581SHariprasad Kelam 		if (flow->rule_type & PFC_FLOWCTRL_RULE)
12928e675581SHariprasad Kelam 			otx2_update_bpid_in_rqctx(pfvf, 0,
12938e675581SHariprasad Kelam 						  flow->flow_spec.ring_cookie,
12948e675581SHariprasad Kelam 						  false);
12958e675581SHariprasad Kelam #endif
12968e675581SHariprasad Kelam 
1297f0a1913fSSubbaraya Sundeep 		err = otx2_remove_flow_msg(pfvf, flow->entry, false);
129879d2be38SHariprasad Kelam 	}
129979d2be38SHariprasad Kelam 
1300f0a1913fSSubbaraya Sundeep 	if (err)
1301f0a1913fSSubbaraya Sundeep 		return err;
1302f0a1913fSSubbaraya Sundeep 
1303f0a1913fSSubbaraya Sundeep 	list_del(&flow->list);
1304f0a1913fSSubbaraya Sundeep 	kfree(flow);
1305f0a1913fSSubbaraya Sundeep 	flow_cfg->nr_flows--;
1306f0a1913fSSubbaraya Sundeep 
1307f0a1913fSSubbaraya Sundeep 	return 0;
1308f0a1913fSSubbaraya Sundeep }
1309f0a1913fSSubbaraya Sundeep 
otx2_rss_ctx_flow_del(struct otx2_nic * pfvf,int ctx_id)131081a43620SGeetha sowjanya void otx2_rss_ctx_flow_del(struct otx2_nic *pfvf, int ctx_id)
131181a43620SGeetha sowjanya {
131281a43620SGeetha sowjanya 	struct otx2_flow *flow, *tmp;
131381a43620SGeetha sowjanya 	int err;
131481a43620SGeetha sowjanya 
131581a43620SGeetha sowjanya 	list_for_each_entry_safe(flow, tmp, &pfvf->flow_cfg->flow_list, list) {
131681a43620SGeetha sowjanya 		if (flow->rss_ctx_id != ctx_id)
131781a43620SGeetha sowjanya 			continue;
131881a43620SGeetha sowjanya 		err = otx2_remove_flow(pfvf, flow->location);
131981a43620SGeetha sowjanya 		if (err)
132081a43620SGeetha sowjanya 			netdev_warn(pfvf->netdev,
132181a43620SGeetha sowjanya 				    "Can't delete the rule %d associated with this rss group err:%d",
132281a43620SGeetha sowjanya 				    flow->location, err);
132381a43620SGeetha sowjanya 	}
132481a43620SGeetha sowjanya }
132581a43620SGeetha sowjanya 
otx2_destroy_ntuple_flows(struct otx2_nic * pfvf)1326f0a1913fSSubbaraya Sundeep int otx2_destroy_ntuple_flows(struct otx2_nic *pfvf)
1327f0a1913fSSubbaraya Sundeep {
1328f0a1913fSSubbaraya Sundeep 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1329f0a1913fSSubbaraya Sundeep 	struct npc_delete_flow_req *req;
1330f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter, *tmp;
1331f0a1913fSSubbaraya Sundeep 	int err;
1332f0a1913fSSubbaraya Sundeep 
1333f0a1913fSSubbaraya Sundeep 	if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT))
1334f0a1913fSSubbaraya Sundeep 		return 0;
1335f0a1913fSSubbaraya Sundeep 
1336a515e5b5SSunil Goutham 	if (!flow_cfg->max_flows)
1337a515e5b5SSunil Goutham 		return 0;
1338a515e5b5SSunil Goutham 
1339f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
1340f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
1341f0a1913fSSubbaraya Sundeep 	if (!req) {
1342f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
1343f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
1344f0a1913fSSubbaraya Sundeep 	}
1345f0a1913fSSubbaraya Sundeep 
13469917060fSSunil Goutham 	req->start = flow_cfg->flow_ent[0];
13472e2a8126SSunil Goutham 	req->end   = flow_cfg->flow_ent[flow_cfg->max_flows - 1];
1348f0a1913fSSubbaraya Sundeep 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1349f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
1350f0a1913fSSubbaraya Sundeep 
1351f0a1913fSSubbaraya Sundeep 	list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list, list) {
1352f0a1913fSSubbaraya Sundeep 		list_del(&iter->list);
1353f0a1913fSSubbaraya Sundeep 		kfree(iter);
1354f0a1913fSSubbaraya Sundeep 		flow_cfg->nr_flows--;
1355f0a1913fSSubbaraya Sundeep 	}
1356f0a1913fSSubbaraya Sundeep 	return err;
1357f0a1913fSSubbaraya Sundeep }
1358f0a1913fSSubbaraya Sundeep 
otx2_destroy_mcam_flows(struct otx2_nic * pfvf)1359f0a1913fSSubbaraya Sundeep int otx2_destroy_mcam_flows(struct otx2_nic *pfvf)
1360f0a1913fSSubbaraya Sundeep {
1361f0a1913fSSubbaraya Sundeep 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1362f0a1913fSSubbaraya Sundeep 	struct npc_mcam_free_entry_req *req;
1363f0a1913fSSubbaraya Sundeep 	struct otx2_flow *iter, *tmp;
1364f0a1913fSSubbaraya Sundeep 	int err;
1365f0a1913fSSubbaraya Sundeep 
1366f0a1913fSSubbaraya Sundeep 	if (!(pfvf->flags & OTX2_FLAG_MCAM_ENTRIES_ALLOC))
1367f0a1913fSSubbaraya Sundeep 		return 0;
1368f0a1913fSSubbaraya Sundeep 
1369f0a1913fSSubbaraya Sundeep 	/* remove all flows */
1370f0a1913fSSubbaraya Sundeep 	err = otx2_remove_flow_msg(pfvf, 0, true);
1371f0a1913fSSubbaraya Sundeep 	if (err)
1372f0a1913fSSubbaraya Sundeep 		return err;
1373f0a1913fSSubbaraya Sundeep 
1374f0a1913fSSubbaraya Sundeep 	list_for_each_entry_safe(iter, tmp, &flow_cfg->flow_list, list) {
1375f0a1913fSSubbaraya Sundeep 		list_del(&iter->list);
1376f0a1913fSSubbaraya Sundeep 		kfree(iter);
1377f0a1913fSSubbaraya Sundeep 		flow_cfg->nr_flows--;
1378f0a1913fSSubbaraya Sundeep 	}
1379f0a1913fSSubbaraya Sundeep 
1380f0a1913fSSubbaraya Sundeep 	mutex_lock(&pfvf->mbox.lock);
1381f0a1913fSSubbaraya Sundeep 	req = otx2_mbox_alloc_msg_npc_mcam_free_entry(&pfvf->mbox);
1382f0a1913fSSubbaraya Sundeep 	if (!req) {
1383f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
1384f0a1913fSSubbaraya Sundeep 		return -ENOMEM;
1385f0a1913fSSubbaraya Sundeep 	}
1386f0a1913fSSubbaraya Sundeep 
1387f0a1913fSSubbaraya Sundeep 	req->all = 1;
1388f0a1913fSSubbaraya Sundeep 	/* Send message to AF to free MCAM entries */
1389f0a1913fSSubbaraya Sundeep 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1390f0a1913fSSubbaraya Sundeep 	if (err) {
1391f0a1913fSSubbaraya Sundeep 		mutex_unlock(&pfvf->mbox.lock);
1392f0a1913fSSubbaraya Sundeep 		return err;
1393f0a1913fSSubbaraya Sundeep 	}
1394f0a1913fSSubbaraya Sundeep 
1395f0a1913fSSubbaraya Sundeep 	pfvf->flags &= ~OTX2_FLAG_MCAM_ENTRIES_ALLOC;
1396f0a1913fSSubbaraya Sundeep 	mutex_unlock(&pfvf->mbox.lock);
1397f0a1913fSSubbaraya Sundeep 
1398f0a1913fSSubbaraya Sundeep 	return 0;
1399f0a1913fSSubbaraya Sundeep }
1400fd9d7859SHariprasad Kelam 
otx2_install_rxvlan_offload_flow(struct otx2_nic * pfvf)1401fd9d7859SHariprasad Kelam int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf)
1402fd9d7859SHariprasad Kelam {
1403fd9d7859SHariprasad Kelam 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1404fd9d7859SHariprasad Kelam 	struct npc_install_flow_req *req;
1405fd9d7859SHariprasad Kelam 	int err;
1406fd9d7859SHariprasad Kelam 
1407fd9d7859SHariprasad Kelam 	mutex_lock(&pfvf->mbox.lock);
1408fd9d7859SHariprasad Kelam 	req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox);
1409fd9d7859SHariprasad Kelam 	if (!req) {
1410fd9d7859SHariprasad Kelam 		mutex_unlock(&pfvf->mbox.lock);
1411fd9d7859SHariprasad Kelam 		return -ENOMEM;
1412fd9d7859SHariprasad Kelam 	}
1413fd9d7859SHariprasad Kelam 
14149917060fSSunil Goutham 	req->entry = flow_cfg->def_ent[flow_cfg->rx_vlan_offset];
1415fd9d7859SHariprasad Kelam 	req->intf = NIX_INTF_RX;
1416fd9d7859SHariprasad Kelam 	ether_addr_copy(req->packet.dmac, pfvf->netdev->dev_addr);
1417fd9d7859SHariprasad Kelam 	eth_broadcast_addr((u8 *)&req->mask.dmac);
1418fd9d7859SHariprasad Kelam 	req->channel = pfvf->hw.rx_chan_base;
1419fd9d7859SHariprasad Kelam 	req->op = NIX_RX_ACTION_DEFAULT;
1420fd9d7859SHariprasad Kelam 	req->features = BIT_ULL(NPC_OUTER_VID) | BIT_ULL(NPC_DMAC);
1421fd9d7859SHariprasad Kelam 	req->vtag0_valid = true;
1422fd9d7859SHariprasad Kelam 	req->vtag0_type = NIX_AF_LFX_RX_VTAG_TYPE0;
1423fd9d7859SHariprasad Kelam 
1424fd9d7859SHariprasad Kelam 	/* Send message to AF */
1425fd9d7859SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1426fd9d7859SHariprasad Kelam 	mutex_unlock(&pfvf->mbox.lock);
1427fd9d7859SHariprasad Kelam 	return err;
1428fd9d7859SHariprasad Kelam }
1429fd9d7859SHariprasad Kelam 
otx2_delete_rxvlan_offload_flow(struct otx2_nic * pfvf)1430fd9d7859SHariprasad Kelam static int otx2_delete_rxvlan_offload_flow(struct otx2_nic *pfvf)
1431fd9d7859SHariprasad Kelam {
1432fd9d7859SHariprasad Kelam 	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
1433fd9d7859SHariprasad Kelam 	struct npc_delete_flow_req *req;
1434fd9d7859SHariprasad Kelam 	int err;
1435fd9d7859SHariprasad Kelam 
1436fd9d7859SHariprasad Kelam 	mutex_lock(&pfvf->mbox.lock);
1437fd9d7859SHariprasad Kelam 	req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
1438fd9d7859SHariprasad Kelam 	if (!req) {
1439fd9d7859SHariprasad Kelam 		mutex_unlock(&pfvf->mbox.lock);
1440fd9d7859SHariprasad Kelam 		return -ENOMEM;
1441fd9d7859SHariprasad Kelam 	}
1442fd9d7859SHariprasad Kelam 
14439917060fSSunil Goutham 	req->entry = flow_cfg->def_ent[flow_cfg->rx_vlan_offset];
1444fd9d7859SHariprasad Kelam 	/* Send message to AF */
1445fd9d7859SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pfvf->mbox);
1446fd9d7859SHariprasad Kelam 	mutex_unlock(&pfvf->mbox.lock);
1447fd9d7859SHariprasad Kelam 	return err;
1448fd9d7859SHariprasad Kelam }
1449fd9d7859SHariprasad Kelam 
otx2_enable_rxvlan(struct otx2_nic * pf,bool enable)1450fd9d7859SHariprasad Kelam int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable)
1451fd9d7859SHariprasad Kelam {
1452fd9d7859SHariprasad Kelam 	struct nix_vtag_config *req;
1453fd9d7859SHariprasad Kelam 	struct mbox_msghdr *rsp_hdr;
1454fd9d7859SHariprasad Kelam 	int err;
1455fd9d7859SHariprasad Kelam 
1456fd9d7859SHariprasad Kelam 	/* Dont have enough mcam entries */
1457fd9d7859SHariprasad Kelam 	if (!(pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT))
1458fd9d7859SHariprasad Kelam 		return -ENOMEM;
1459fd9d7859SHariprasad Kelam 
1460fd9d7859SHariprasad Kelam 	if (enable) {
1461fd9d7859SHariprasad Kelam 		err = otx2_install_rxvlan_offload_flow(pf);
1462fd9d7859SHariprasad Kelam 		if (err)
1463fd9d7859SHariprasad Kelam 			return err;
1464fd9d7859SHariprasad Kelam 	} else {
1465fd9d7859SHariprasad Kelam 		err = otx2_delete_rxvlan_offload_flow(pf);
1466fd9d7859SHariprasad Kelam 		if (err)
1467fd9d7859SHariprasad Kelam 			return err;
1468fd9d7859SHariprasad Kelam 	}
1469fd9d7859SHariprasad Kelam 
1470fd9d7859SHariprasad Kelam 	mutex_lock(&pf->mbox.lock);
1471fd9d7859SHariprasad Kelam 	req = otx2_mbox_alloc_msg_nix_vtag_cfg(&pf->mbox);
1472fd9d7859SHariprasad Kelam 	if (!req) {
1473fd9d7859SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
1474fd9d7859SHariprasad Kelam 		return -ENOMEM;
1475fd9d7859SHariprasad Kelam 	}
1476fd9d7859SHariprasad Kelam 
1477fd9d7859SHariprasad Kelam 	/* config strip, capture and size */
1478fd9d7859SHariprasad Kelam 	req->vtag_size = VTAGSIZE_T4;
1479fd9d7859SHariprasad Kelam 	req->cfg_type = 1; /* rx vlan cfg */
1480fd9d7859SHariprasad Kelam 	req->rx.vtag_type = NIX_AF_LFX_RX_VTAG_TYPE0;
1481fd9d7859SHariprasad Kelam 	req->rx.strip_vtag = enable;
1482fd9d7859SHariprasad Kelam 	req->rx.capture_vtag = enable;
1483fd9d7859SHariprasad Kelam 
1484fd9d7859SHariprasad Kelam 	err = otx2_sync_mbox_msg(&pf->mbox);
1485fd9d7859SHariprasad Kelam 	if (err) {
1486fd9d7859SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
1487fd9d7859SHariprasad Kelam 		return err;
1488fd9d7859SHariprasad Kelam 	}
1489fd9d7859SHariprasad Kelam 
1490fd9d7859SHariprasad Kelam 	rsp_hdr = otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
1491fd9d7859SHariprasad Kelam 	if (IS_ERR(rsp_hdr)) {
1492fd9d7859SHariprasad Kelam 		mutex_unlock(&pf->mbox.lock);
1493fd9d7859SHariprasad Kelam 		return PTR_ERR(rsp_hdr);
1494fd9d7859SHariprasad Kelam 	}
1495fd9d7859SHariprasad Kelam 
1496fd9d7859SHariprasad Kelam 	mutex_unlock(&pf->mbox.lock);
1497fd9d7859SHariprasad Kelam 	return rsp_hdr->rc;
1498fd9d7859SHariprasad Kelam }
149979d2be38SHariprasad Kelam 
otx2_dmacflt_reinstall_flows(struct otx2_nic * pf)150079d2be38SHariprasad Kelam void otx2_dmacflt_reinstall_flows(struct otx2_nic *pf)
150179d2be38SHariprasad Kelam {
150279d2be38SHariprasad Kelam 	struct otx2_flow *iter;
150379d2be38SHariprasad Kelam 	struct ethhdr *eth_hdr;
150479d2be38SHariprasad Kelam 
150579d2be38SHariprasad Kelam 	list_for_each_entry(iter, &pf->flow_cfg->flow_list, list) {
15068e675581SHariprasad Kelam 		if (iter->rule_type & DMAC_FILTER_RULE) {
150779d2be38SHariprasad Kelam 			eth_hdr = &iter->flow_spec.h_u.ether_spec;
150879d2be38SHariprasad Kelam 			otx2_dmacflt_add(pf, eth_hdr->h_dest,
150979d2be38SHariprasad Kelam 					 iter->entry);
151079d2be38SHariprasad Kelam 		}
151179d2be38SHariprasad Kelam 	}
151279d2be38SHariprasad Kelam }
151379d2be38SHariprasad Kelam 
otx2_dmacflt_update_pfmac_flow(struct otx2_nic * pfvf)151479d2be38SHariprasad Kelam void otx2_dmacflt_update_pfmac_flow(struct otx2_nic *pfvf)
151579d2be38SHariprasad Kelam {
151679d2be38SHariprasad Kelam 	otx2_update_rem_pfmac(pfvf, DMAC_ADDR_UPDATE);
151779d2be38SHariprasad Kelam }
1518