xref: /openbmc/linux/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c (revision 6c71a0574249f5e5a45fe055ab5f837023d5eeca)
123923ea4SSunil Goutham // SPDX-License-Identifier: GPL-2.0
2c7cd6c5aSSunil Goutham /* Marvell RVU Admin Function driver
323923ea4SSunil Goutham  *
4c7cd6c5aSSunil Goutham  * Copyright (C) 2018 Marvell.
523923ea4SSunil Goutham  *
623923ea4SSunil Goutham  */
723923ea4SSunil Goutham 
886cea61dSTomasz Duszynski #include <linux/bitfield.h>
923923ea4SSunil Goutham #include <linux/module.h>
1023923ea4SSunil Goutham #include <linux/pci.h>
1123923ea4SSunil Goutham 
1223923ea4SSunil Goutham #include "rvu_struct.h"
1323923ea4SSunil Goutham #include "rvu_reg.h"
1423923ea4SSunil Goutham #include "rvu.h"
1523923ea4SSunil Goutham #include "npc.h"
1623705adbSVamsi Attunuru #include "cgx.h"
1723923ea4SSunil Goutham #include "npc_profile.h"
1856d9f5fdSRatheesh Kannoth #include "rvu_npc_hash.h"
1923923ea4SSunil Goutham 
20967db352SNaveen Mamindlapalli #define RSVD_MCAM_ENTRIES_PER_PF	3 /* Broadcast, Promisc and AllMulticast */
21fefefd99SSunil Goutham #define RSVD_MCAM_ENTRIES_PER_NIXLF	1 /* Ucast for LFs */
22fefefd99SSunil Goutham 
23fefefd99SSunil Goutham #define NPC_PARSE_RESULT_DMAC_OFFSET	8
24698a82ebSSubbaraya Sundeep #define NPC_HW_TSTAMP_OFFSET		8ULL
25041a1c17SSubbaraya Sundeep #define NPC_KEX_CHAN_MASK		0xFFFULL
26041a1c17SSubbaraya Sundeep #define NPC_KEX_PF_FUNC_MASK		0xFFFFULL
27fefefd99SSunil Goutham 
2811c730bfSHarman Kalra #define ALIGN_8B_CEIL(__a)	(((__a) + 7) & (-8))
2911c730bfSHarman Kalra 
3042006910SStanislaw Kardach static const char def_pfl_name[] = "default";
3142006910SStanislaw Kardach 
32f9274958SSunil Goutham static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
33f9274958SSunil Goutham 				      int blkaddr, u16 pcifunc);
34a958dd59SSunil Goutham static void npc_mcam_free_all_counters(struct rvu *rvu, struct npc_mcam *mcam,
35a958dd59SSunil Goutham 				       u16 pcifunc);
36f9274958SSunil Goutham 
is_npc_intf_tx(u8 intf)371c1935c9SSubbaraya Sundeep bool is_npc_intf_tx(u8 intf)
381c1935c9SSubbaraya Sundeep {
391c1935c9SSubbaraya Sundeep 	return !!(intf & 0x1);
401c1935c9SSubbaraya Sundeep }
411c1935c9SSubbaraya Sundeep 
is_npc_intf_rx(u8 intf)421c1935c9SSubbaraya Sundeep bool is_npc_intf_rx(u8 intf)
431c1935c9SSubbaraya Sundeep {
441c1935c9SSubbaraya Sundeep 	return !(intf & 0x1);
451c1935c9SSubbaraya Sundeep }
461c1935c9SSubbaraya Sundeep 
is_npc_interface_valid(struct rvu * rvu,u8 intf)471c1935c9SSubbaraya Sundeep bool is_npc_interface_valid(struct rvu *rvu, u8 intf)
481c1935c9SSubbaraya Sundeep {
491c1935c9SSubbaraya Sundeep 	struct rvu_hwinfo *hw = rvu->hw;
501c1935c9SSubbaraya Sundeep 
511c1935c9SSubbaraya Sundeep 	return intf < hw->npc_intfs;
521c1935c9SSubbaraya Sundeep }
531c1935c9SSubbaraya Sundeep 
rvu_npc_get_tx_nibble_cfg(struct rvu * rvu,u64 nibble_ena)541c1935c9SSubbaraya Sundeep int rvu_npc_get_tx_nibble_cfg(struct rvu *rvu, u64 nibble_ena)
551c1935c9SSubbaraya Sundeep {
561c1935c9SSubbaraya Sundeep 	/* Due to a HW issue in these silicon versions, parse nibble enable
571c1935c9SSubbaraya Sundeep 	 * configuration has to be identical for both Rx and Tx interfaces.
581c1935c9SSubbaraya Sundeep 	 */
591c1935c9SSubbaraya Sundeep 	if (is_rvu_96xx_B0(rvu))
601c1935c9SSubbaraya Sundeep 		return nibble_ena;
611c1935c9SSubbaraya Sundeep 	return 0;
621c1935c9SSubbaraya Sundeep }
631c1935c9SSubbaraya Sundeep 
npc_mcam_verify_pf_func(struct rvu * rvu,struct mcam_entry * entry_data,u8 intf,u16 pcifunc)64041a1c17SSubbaraya Sundeep static int npc_mcam_verify_pf_func(struct rvu *rvu,
65041a1c17SSubbaraya Sundeep 				   struct mcam_entry *entry_data, u8 intf,
66041a1c17SSubbaraya Sundeep 				   u16 pcifunc)
67041a1c17SSubbaraya Sundeep {
68041a1c17SSubbaraya Sundeep 	u16 pf_func, pf_func_mask;
69041a1c17SSubbaraya Sundeep 
70041a1c17SSubbaraya Sundeep 	if (is_npc_intf_rx(intf))
71041a1c17SSubbaraya Sundeep 		return 0;
72041a1c17SSubbaraya Sundeep 
73041a1c17SSubbaraya Sundeep 	pf_func_mask = (entry_data->kw_mask[0] >> 32) &
74041a1c17SSubbaraya Sundeep 		NPC_KEX_PF_FUNC_MASK;
75041a1c17SSubbaraya Sundeep 	pf_func = (entry_data->kw[0] >> 32) & NPC_KEX_PF_FUNC_MASK;
76041a1c17SSubbaraya Sundeep 
77041a1c17SSubbaraya Sundeep 	pf_func = be16_to_cpu((__force __be16)pf_func);
78041a1c17SSubbaraya Sundeep 	if (pf_func_mask != NPC_KEX_PF_FUNC_MASK ||
79041a1c17SSubbaraya Sundeep 	    ((pf_func & ~RVU_PFVF_FUNC_MASK) !=
80041a1c17SSubbaraya Sundeep 	     (pcifunc & ~RVU_PFVF_FUNC_MASK)))
81041a1c17SSubbaraya Sundeep 		return -EINVAL;
82041a1c17SSubbaraya Sundeep 
83041a1c17SSubbaraya Sundeep 	return 0;
84041a1c17SSubbaraya Sundeep }
85041a1c17SSubbaraya Sundeep 
rvu_npc_set_pkind(struct rvu * rvu,int pkind,struct rvu_pfvf * pfvf)8694d942c5SGeetha sowjanya void rvu_npc_set_pkind(struct rvu *rvu, int pkind, struct rvu_pfvf *pfvf)
8794d942c5SGeetha sowjanya {
8894d942c5SGeetha sowjanya 	int blkaddr;
8994d942c5SGeetha sowjanya 	u64 val = 0;
9094d942c5SGeetha sowjanya 
9194d942c5SGeetha sowjanya 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
9294d942c5SGeetha sowjanya 	if (blkaddr < 0)
9394d942c5SGeetha sowjanya 		return;
9494d942c5SGeetha sowjanya 
9594d942c5SGeetha sowjanya 	/* Config CPI base for the PKIND */
9694d942c5SGeetha sowjanya 	val = pkind | 1ULL << 62;
9794d942c5SGeetha sowjanya 	rvu_write64(rvu, blkaddr, NPC_AF_PKINDX_CPI_DEFX(pkind, 0), val);
9894d942c5SGeetha sowjanya }
9994d942c5SGeetha sowjanya 
rvu_npc_get_pkind(struct rvu * rvu,u16 pf)10094d942c5SGeetha sowjanya int rvu_npc_get_pkind(struct rvu *rvu, u16 pf)
10194d942c5SGeetha sowjanya {
10294d942c5SGeetha sowjanya 	struct npc_pkind *pkind = &rvu->hw->pkind;
10394d942c5SGeetha sowjanya 	u32 map;
10494d942c5SGeetha sowjanya 	int i;
10594d942c5SGeetha sowjanya 
10694d942c5SGeetha sowjanya 	for (i = 0; i < pkind->rsrc.max; i++) {
10794d942c5SGeetha sowjanya 		map = pkind->pfchan_map[i];
10894d942c5SGeetha sowjanya 		if (((map >> 16) & 0x3F) == pf)
10994d942c5SGeetha sowjanya 			return i;
11094d942c5SGeetha sowjanya 	}
11194d942c5SGeetha sowjanya 	return -1;
11294d942c5SGeetha sowjanya }
11394d942c5SGeetha sowjanya 
11442157217SZyta Szpak #define NPC_AF_ACTION0_PTR_ADVANCE	GENMASK_ULL(27, 20)
11542157217SZyta Szpak 
npc_config_ts_kpuaction(struct rvu * rvu,int pf,u16 pcifunc,bool enable)11642157217SZyta Szpak int npc_config_ts_kpuaction(struct rvu *rvu, int pf, u16 pcifunc, bool enable)
11742157217SZyta Szpak {
11842157217SZyta Szpak 	int pkind, blkaddr;
11942157217SZyta Szpak 	u64 val;
12042157217SZyta Szpak 
12142157217SZyta Szpak 	pkind = rvu_npc_get_pkind(rvu, pf);
12242157217SZyta Szpak 	if (pkind < 0) {
12342157217SZyta Szpak 		dev_err(rvu->dev, "%s: pkind not mapped\n", __func__);
12442157217SZyta Szpak 		return -EINVAL;
12542157217SZyta Szpak 	}
12642157217SZyta Szpak 
12742157217SZyta Szpak 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, pcifunc);
12842157217SZyta Szpak 	if (blkaddr < 0) {
12942157217SZyta Szpak 		dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
13042157217SZyta Szpak 		return -EINVAL;
13142157217SZyta Szpak 	}
13242157217SZyta Szpak 
13342157217SZyta Szpak 	val = rvu_read64(rvu, blkaddr, NPC_AF_PKINDX_ACTION0(pkind));
13442157217SZyta Szpak 	val &= ~NPC_AF_ACTION0_PTR_ADVANCE;
13542157217SZyta Szpak 	/* If timestamp is enabled then configure NPC to shift 8 bytes */
13642157217SZyta Szpak 	if (enable)
13742157217SZyta Szpak 		val |= FIELD_PREP(NPC_AF_ACTION0_PTR_ADVANCE,
13842157217SZyta Szpak 				  NPC_HW_TSTAMP_OFFSET);
13942157217SZyta Szpak 	rvu_write64(rvu, blkaddr, NPC_AF_PKINDX_ACTION0(pkind), val);
14042157217SZyta Szpak 
14142157217SZyta Szpak 	return 0;
14242157217SZyta Szpak }
14342157217SZyta Szpak 
npc_get_ucast_mcam_index(struct npc_mcam * mcam,u16 pcifunc,int nixlf)1441c1935c9SSubbaraya Sundeep static int npc_get_ucast_mcam_index(struct npc_mcam *mcam, u16 pcifunc,
1451c1935c9SSubbaraya Sundeep 				    int nixlf)
1461c1935c9SSubbaraya Sundeep {
1471c1935c9SSubbaraya Sundeep 	struct rvu_hwinfo *hw = container_of(mcam, struct rvu_hwinfo, mcam);
1481c1935c9SSubbaraya Sundeep 	struct rvu *rvu = hw->rvu;
1491c1935c9SSubbaraya Sundeep 	int blkaddr = 0, max = 0;
1501c1935c9SSubbaraya Sundeep 	struct rvu_block *block;
1511c1935c9SSubbaraya Sundeep 	struct rvu_pfvf *pfvf;
1521c1935c9SSubbaraya Sundeep 
1531c1935c9SSubbaraya Sundeep 	pfvf = rvu_get_pfvf(rvu, pcifunc);
1541c1935c9SSubbaraya Sundeep 	/* Given a PF/VF and NIX LF number calculate the unicast mcam
1551c1935c9SSubbaraya Sundeep 	 * entry index based on the NIX block assigned to the PF/VF.
1561c1935c9SSubbaraya Sundeep 	 */
1571c1935c9SSubbaraya Sundeep 	blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
1581c1935c9SSubbaraya Sundeep 	while (blkaddr) {
1591c1935c9SSubbaraya Sundeep 		if (pfvf->nix_blkaddr == blkaddr)
1601c1935c9SSubbaraya Sundeep 			break;
1611c1935c9SSubbaraya Sundeep 		block = &rvu->hw->block[blkaddr];
1621c1935c9SSubbaraya Sundeep 		max += block->lf.max;
1631c1935c9SSubbaraya Sundeep 		blkaddr = rvu_get_next_nix_blkaddr(rvu, blkaddr);
1641c1935c9SSubbaraya Sundeep 	}
1651c1935c9SSubbaraya Sundeep 
1661c1935c9SSubbaraya Sundeep 	return mcam->nixlf_offset + (max + nixlf) * RSVD_MCAM_ENTRIES_PER_NIXLF;
1671c1935c9SSubbaraya Sundeep }
1681c1935c9SSubbaraya Sundeep 
npc_get_nixlf_mcam_index(struct npc_mcam * mcam,u16 pcifunc,int nixlf,int type)16963f925dcSNaveen Mamindlapalli int npc_get_nixlf_mcam_index(struct npc_mcam *mcam,
17075900140SSunil Goutham 			     u16 pcifunc, int nixlf, int type)
17175900140SSunil Goutham {
17275900140SSunil Goutham 	int pf = rvu_get_pf(pcifunc);
17375900140SSunil Goutham 	int index;
17475900140SSunil Goutham 
17575900140SSunil Goutham 	/* Check if this is for a PF */
17675900140SSunil Goutham 	if (pf && !(pcifunc & RVU_PFVF_FUNC_MASK)) {
17775900140SSunil Goutham 		/* Reserved entries exclude PF0 */
17875900140SSunil Goutham 		pf--;
17975900140SSunil Goutham 		index = mcam->pf_offset + (pf * RSVD_MCAM_ENTRIES_PER_PF);
18075900140SSunil Goutham 		/* Broadcast address matching entry should be first so
18175900140SSunil Goutham 		 * that the packet can be replicated to all VFs.
18275900140SSunil Goutham 		 */
18375900140SSunil Goutham 		if (type == NIXLF_BCAST_ENTRY)
18475900140SSunil Goutham 			return index;
185967db352SNaveen Mamindlapalli 		else if (type == NIXLF_ALLMULTI_ENTRY)
18675900140SSunil Goutham 			return index + 1;
187967db352SNaveen Mamindlapalli 		else if (type == NIXLF_PROMISC_ENTRY)
188967db352SNaveen Mamindlapalli 			return index + 2;
18975900140SSunil Goutham 	}
19075900140SSunil Goutham 
1911c1935c9SSubbaraya Sundeep 	return npc_get_ucast_mcam_index(mcam, pcifunc, nixlf);
19275900140SSunil Goutham }
19375900140SSunil Goutham 
npc_get_bank(struct npc_mcam * mcam,int index)19455307fcbSSubbaraya Sundeep int npc_get_bank(struct npc_mcam *mcam, int index)
19575900140SSunil Goutham {
19675900140SSunil Goutham 	int bank = index / mcam->banksize;
19775900140SSunil Goutham 
19875900140SSunil Goutham 	/* 0,1 & 2,3 banks are combined for this keysize */
19975900140SSunil Goutham 	if (mcam->keysize == NPC_MCAM_KEY_X2)
20075900140SSunil Goutham 		return bank ? 2 : 0;
20175900140SSunil Goutham 
20275900140SSunil Goutham 	return bank;
20375900140SSunil Goutham }
20475900140SSunil Goutham 
is_mcam_entry_enabled(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,int index)20563f925dcSNaveen Mamindlapalli bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam,
20675900140SSunil Goutham 			   int blkaddr, int index)
20775900140SSunil Goutham {
20875900140SSunil Goutham 	int bank = npc_get_bank(mcam, index);
20975900140SSunil Goutham 	u64 cfg;
21075900140SSunil Goutham 
21175900140SSunil Goutham 	index &= (mcam->banksize - 1);
21275900140SSunil Goutham 	cfg = rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_CFG(index, bank));
21375900140SSunil Goutham 	return (cfg & 1);
21475900140SSunil Goutham }
21575900140SSunil Goutham 
npc_enable_mcam_entry(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,int index,bool enable)21655307fcbSSubbaraya Sundeep void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
21775900140SSunil Goutham 			   int blkaddr, int index, bool enable)
21875900140SSunil Goutham {
21975900140SSunil Goutham 	int bank = npc_get_bank(mcam, index);
22075900140SSunil Goutham 	int actbank = bank;
22175900140SSunil Goutham 
22275900140SSunil Goutham 	index &= (mcam->banksize - 1);
22375900140SSunil Goutham 	for (; bank < (actbank + mcam->banks_per_entry); bank++) {
22475900140SSunil Goutham 		rvu_write64(rvu, blkaddr,
22575900140SSunil Goutham 			    NPC_AF_MCAMEX_BANKX_CFG(index, bank),
22675900140SSunil Goutham 			    enable ? 1 : 0);
22775900140SSunil Goutham 	}
22875900140SSunil Goutham }
22975900140SSunil Goutham 
npc_clear_mcam_entry(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,int index)2308cc89ae9SNithin Dabilpuram static void npc_clear_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
2318cc89ae9SNithin Dabilpuram 				 int blkaddr, int index)
2328cc89ae9SNithin Dabilpuram {
2338cc89ae9SNithin Dabilpuram 	int bank = npc_get_bank(mcam, index);
2348cc89ae9SNithin Dabilpuram 	int actbank = bank;
2358cc89ae9SNithin Dabilpuram 
2368cc89ae9SNithin Dabilpuram 	index &= (mcam->banksize - 1);
2378cc89ae9SNithin Dabilpuram 	for (; bank < (actbank + mcam->banks_per_entry); bank++) {
2388cc89ae9SNithin Dabilpuram 		rvu_write64(rvu, blkaddr,
2398cc89ae9SNithin Dabilpuram 			    NPC_AF_MCAMEX_BANKX_CAMX_INTF(index, bank, 1), 0);
2408cc89ae9SNithin Dabilpuram 		rvu_write64(rvu, blkaddr,
2418cc89ae9SNithin Dabilpuram 			    NPC_AF_MCAMEX_BANKX_CAMX_INTF(index, bank, 0), 0);
2428cc89ae9SNithin Dabilpuram 
2438cc89ae9SNithin Dabilpuram 		rvu_write64(rvu, blkaddr,
2448cc89ae9SNithin Dabilpuram 			    NPC_AF_MCAMEX_BANKX_CAMX_W0(index, bank, 1), 0);
2458cc89ae9SNithin Dabilpuram 		rvu_write64(rvu, blkaddr,
2468cc89ae9SNithin Dabilpuram 			    NPC_AF_MCAMEX_BANKX_CAMX_W0(index, bank, 0), 0);
2478cc89ae9SNithin Dabilpuram 
2488cc89ae9SNithin Dabilpuram 		rvu_write64(rvu, blkaddr,
2498cc89ae9SNithin Dabilpuram 			    NPC_AF_MCAMEX_BANKX_CAMX_W1(index, bank, 1), 0);
2508cc89ae9SNithin Dabilpuram 		rvu_write64(rvu, blkaddr,
2518cc89ae9SNithin Dabilpuram 			    NPC_AF_MCAMEX_BANKX_CAMX_W1(index, bank, 0), 0);
2528cc89ae9SNithin Dabilpuram 	}
2538cc89ae9SNithin Dabilpuram }
2548cc89ae9SNithin Dabilpuram 
npc_get_keyword(struct mcam_entry * entry,int idx,u64 * cam0,u64 * cam1)25575900140SSunil Goutham static void npc_get_keyword(struct mcam_entry *entry, int idx,
25675900140SSunil Goutham 			    u64 *cam0, u64 *cam1)
25775900140SSunil Goutham {
25875900140SSunil Goutham 	u64 kw_mask = 0x00;
25975900140SSunil Goutham 
26075900140SSunil Goutham #define CAM_MASK(n)	(BIT_ULL(n) - 1)
26175900140SSunil Goutham 
26275900140SSunil Goutham 	/* 0, 2, 4, 6 indices refer to BANKX_CAMX_W0 and
26375900140SSunil Goutham 	 * 1, 3, 5, 7 indices refer to BANKX_CAMX_W1.
26475900140SSunil Goutham 	 *
26575900140SSunil Goutham 	 * Also, only 48 bits of BANKX_CAMX_W1 are valid.
26675900140SSunil Goutham 	 */
26775900140SSunil Goutham 	switch (idx) {
26875900140SSunil Goutham 	case 0:
26975900140SSunil Goutham 		/* BANK(X)_CAM_W0<63:0> = MCAM_KEY[KW0]<63:0> */
27075900140SSunil Goutham 		*cam1 = entry->kw[0];
27175900140SSunil Goutham 		kw_mask = entry->kw_mask[0];
27275900140SSunil Goutham 		break;
27375900140SSunil Goutham 	case 1:
27475900140SSunil Goutham 		/* BANK(X)_CAM_W1<47:0> = MCAM_KEY[KW1]<47:0> */
27575900140SSunil Goutham 		*cam1 = entry->kw[1] & CAM_MASK(48);
27675900140SSunil Goutham 		kw_mask = entry->kw_mask[1] & CAM_MASK(48);
27775900140SSunil Goutham 		break;
27875900140SSunil Goutham 	case 2:
27975900140SSunil Goutham 		/* BANK(X + 1)_CAM_W0<15:0> = MCAM_KEY[KW1]<63:48>
28075900140SSunil Goutham 		 * BANK(X + 1)_CAM_W0<63:16> = MCAM_KEY[KW2]<47:0>
28175900140SSunil Goutham 		 */
28275900140SSunil Goutham 		*cam1 = (entry->kw[1] >> 48) & CAM_MASK(16);
28375900140SSunil Goutham 		*cam1 |= ((entry->kw[2] & CAM_MASK(48)) << 16);
28475900140SSunil Goutham 		kw_mask = (entry->kw_mask[1] >> 48) & CAM_MASK(16);
28575900140SSunil Goutham 		kw_mask |= ((entry->kw_mask[2] & CAM_MASK(48)) << 16);
28675900140SSunil Goutham 		break;
28775900140SSunil Goutham 	case 3:
28875900140SSunil Goutham 		/* BANK(X + 1)_CAM_W1<15:0> = MCAM_KEY[KW2]<63:48>
28975900140SSunil Goutham 		 * BANK(X + 1)_CAM_W1<47:16> = MCAM_KEY[KW3]<31:0>
29075900140SSunil Goutham 		 */
29175900140SSunil Goutham 		*cam1 = (entry->kw[2] >> 48) & CAM_MASK(16);
29275900140SSunil Goutham 		*cam1 |= ((entry->kw[3] & CAM_MASK(32)) << 16);
29375900140SSunil Goutham 		kw_mask = (entry->kw_mask[2] >> 48) & CAM_MASK(16);
29475900140SSunil Goutham 		kw_mask |= ((entry->kw_mask[3] & CAM_MASK(32)) << 16);
29575900140SSunil Goutham 		break;
29675900140SSunil Goutham 	case 4:
29775900140SSunil Goutham 		/* BANK(X + 2)_CAM_W0<31:0> = MCAM_KEY[KW3]<63:32>
29875900140SSunil Goutham 		 * BANK(X + 2)_CAM_W0<63:32> = MCAM_KEY[KW4]<31:0>
29975900140SSunil Goutham 		 */
30075900140SSunil Goutham 		*cam1 = (entry->kw[3] >> 32) & CAM_MASK(32);
30175900140SSunil Goutham 		*cam1 |= ((entry->kw[4] & CAM_MASK(32)) << 32);
30275900140SSunil Goutham 		kw_mask = (entry->kw_mask[3] >> 32) & CAM_MASK(32);
30375900140SSunil Goutham 		kw_mask |= ((entry->kw_mask[4] & CAM_MASK(32)) << 32);
30475900140SSunil Goutham 		break;
30575900140SSunil Goutham 	case 5:
30675900140SSunil Goutham 		/* BANK(X + 2)_CAM_W1<31:0> = MCAM_KEY[KW4]<63:32>
30775900140SSunil Goutham 		 * BANK(X + 2)_CAM_W1<47:32> = MCAM_KEY[KW5]<15:0>
30875900140SSunil Goutham 		 */
30975900140SSunil Goutham 		*cam1 = (entry->kw[4] >> 32) & CAM_MASK(32);
31075900140SSunil Goutham 		*cam1 |= ((entry->kw[5] & CAM_MASK(16)) << 32);
31175900140SSunil Goutham 		kw_mask = (entry->kw_mask[4] >> 32) & CAM_MASK(32);
31275900140SSunil Goutham 		kw_mask |= ((entry->kw_mask[5] & CAM_MASK(16)) << 32);
31375900140SSunil Goutham 		break;
31475900140SSunil Goutham 	case 6:
31575900140SSunil Goutham 		/* BANK(X + 3)_CAM_W0<47:0> = MCAM_KEY[KW5]<63:16>
31675900140SSunil Goutham 		 * BANK(X + 3)_CAM_W0<63:48> = MCAM_KEY[KW6]<15:0>
31775900140SSunil Goutham 		 */
31875900140SSunil Goutham 		*cam1 = (entry->kw[5] >> 16) & CAM_MASK(48);
31975900140SSunil Goutham 		*cam1 |= ((entry->kw[6] & CAM_MASK(16)) << 48);
32075900140SSunil Goutham 		kw_mask = (entry->kw_mask[5] >> 16) & CAM_MASK(48);
32175900140SSunil Goutham 		kw_mask |= ((entry->kw_mask[6] & CAM_MASK(16)) << 48);
32275900140SSunil Goutham 		break;
32375900140SSunil Goutham 	case 7:
32475900140SSunil Goutham 		/* BANK(X + 3)_CAM_W1<47:0> = MCAM_KEY[KW6]<63:16> */
32575900140SSunil Goutham 		*cam1 = (entry->kw[6] >> 16) & CAM_MASK(48);
32675900140SSunil Goutham 		kw_mask = (entry->kw_mask[6] >> 16) & CAM_MASK(48);
32775900140SSunil Goutham 		break;
32875900140SSunil Goutham 	}
32975900140SSunil Goutham 
33075900140SSunil Goutham 	*cam1 &= kw_mask;
33175900140SSunil Goutham 	*cam0 = ~*cam1 & kw_mask;
33275900140SSunil Goutham }
33375900140SSunil Goutham 
npc_fill_entryword(struct mcam_entry * entry,int idx,u64 cam0,u64 cam1)334f0c2982aSNaveen Mamindlapalli static void npc_fill_entryword(struct mcam_entry *entry, int idx,
335f0c2982aSNaveen Mamindlapalli 			       u64 cam0, u64 cam1)
336f0c2982aSNaveen Mamindlapalli {
337f0c2982aSNaveen Mamindlapalli 	/* Similar to npc_get_keyword, but fills mcam_entry structure from
338f0c2982aSNaveen Mamindlapalli 	 * CAM registers.
339f0c2982aSNaveen Mamindlapalli 	 */
340f0c2982aSNaveen Mamindlapalli 	switch (idx) {
341f0c2982aSNaveen Mamindlapalli 	case 0:
342f0c2982aSNaveen Mamindlapalli 		entry->kw[0] = cam1;
343f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[0] = cam1 ^ cam0;
344f0c2982aSNaveen Mamindlapalli 		break;
345f0c2982aSNaveen Mamindlapalli 	case 1:
346f0c2982aSNaveen Mamindlapalli 		entry->kw[1] = cam1;
347f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[1] = cam1 ^ cam0;
348f0c2982aSNaveen Mamindlapalli 		break;
349f0c2982aSNaveen Mamindlapalli 	case 2:
350f0c2982aSNaveen Mamindlapalli 		entry->kw[1] |= (cam1 & CAM_MASK(16)) << 48;
351f0c2982aSNaveen Mamindlapalli 		entry->kw[2] = (cam1 >> 16) & CAM_MASK(48);
352f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[1] |= ((cam1 ^ cam0) & CAM_MASK(16)) << 48;
353f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[2] = ((cam1 ^ cam0) >> 16) & CAM_MASK(48);
354f0c2982aSNaveen Mamindlapalli 		break;
355f0c2982aSNaveen Mamindlapalli 	case 3:
356f0c2982aSNaveen Mamindlapalli 		entry->kw[2] |= (cam1 & CAM_MASK(16)) << 48;
357f0c2982aSNaveen Mamindlapalli 		entry->kw[3] = (cam1 >> 16) & CAM_MASK(32);
358f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[2] |= ((cam1 ^ cam0) & CAM_MASK(16)) << 48;
359f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[3] = ((cam1 ^ cam0) >> 16) & CAM_MASK(32);
360f0c2982aSNaveen Mamindlapalli 		break;
361f0c2982aSNaveen Mamindlapalli 	case 4:
362f0c2982aSNaveen Mamindlapalli 		entry->kw[3] |= (cam1 & CAM_MASK(32)) << 32;
363f0c2982aSNaveen Mamindlapalli 		entry->kw[4] = (cam1 >> 32) & CAM_MASK(32);
364f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[3] |= ((cam1 ^ cam0) & CAM_MASK(32)) << 32;
365f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[4] = ((cam1 ^ cam0) >> 32) & CAM_MASK(32);
366f0c2982aSNaveen Mamindlapalli 		break;
367f0c2982aSNaveen Mamindlapalli 	case 5:
368f0c2982aSNaveen Mamindlapalli 		entry->kw[4] |= (cam1 & CAM_MASK(32)) << 32;
369f0c2982aSNaveen Mamindlapalli 		entry->kw[5] = (cam1 >> 32) & CAM_MASK(16);
370f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[4] |= ((cam1 ^ cam0) & CAM_MASK(32)) << 32;
371f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[5] = ((cam1 ^ cam0) >> 32) & CAM_MASK(16);
372f0c2982aSNaveen Mamindlapalli 		break;
373f0c2982aSNaveen Mamindlapalli 	case 6:
374f0c2982aSNaveen Mamindlapalli 		entry->kw[5] |= (cam1 & CAM_MASK(48)) << 16;
375f0c2982aSNaveen Mamindlapalli 		entry->kw[6] = (cam1 >> 48) & CAM_MASK(16);
376f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[5] |= ((cam1 ^ cam0) & CAM_MASK(48)) << 16;
377f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[6] = ((cam1 ^ cam0) >> 48) & CAM_MASK(16);
378f0c2982aSNaveen Mamindlapalli 		break;
379f0c2982aSNaveen Mamindlapalli 	case 7:
380f0c2982aSNaveen Mamindlapalli 		entry->kw[6] |= (cam1 & CAM_MASK(48)) << 16;
381f0c2982aSNaveen Mamindlapalli 		entry->kw_mask[6] |= ((cam1 ^ cam0) & CAM_MASK(48)) << 16;
382f0c2982aSNaveen Mamindlapalli 		break;
383f0c2982aSNaveen Mamindlapalli 	}
384f0c2982aSNaveen Mamindlapalli }
385f0c2982aSNaveen Mamindlapalli 
npc_get_default_entry_action(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,u16 pf_func)386967db352SNaveen Mamindlapalli static u64 npc_get_default_entry_action(struct rvu *rvu, struct npc_mcam *mcam,
387967db352SNaveen Mamindlapalli 					int blkaddr, u16 pf_func)
388967db352SNaveen Mamindlapalli {
389967db352SNaveen Mamindlapalli 	int bank, nixlf, index;
390967db352SNaveen Mamindlapalli 
391967db352SNaveen Mamindlapalli 	/* get ucast entry rule entry index */
392c3287140SSubbaraya Sundeep 	if (nix_get_nixlf(rvu, pf_func, &nixlf, NULL)) {
393c3287140SSubbaraya Sundeep 		dev_err(rvu->dev, "%s: nixlf not attached to pcifunc:0x%x\n",
394c3287140SSubbaraya Sundeep 			__func__, pf_func);
395c3287140SSubbaraya Sundeep 		/* Action 0 is drop */
396c3287140SSubbaraya Sundeep 		return 0;
397c3287140SSubbaraya Sundeep 	}
398c3287140SSubbaraya Sundeep 
399967db352SNaveen Mamindlapalli 	index = npc_get_nixlf_mcam_index(mcam, pf_func, nixlf,
400967db352SNaveen Mamindlapalli 					 NIXLF_UCAST_ENTRY);
401967db352SNaveen Mamindlapalli 	bank = npc_get_bank(mcam, index);
402967db352SNaveen Mamindlapalli 	index &= (mcam->banksize - 1);
403967db352SNaveen Mamindlapalli 
404967db352SNaveen Mamindlapalli 	return rvu_read64(rvu, blkaddr,
405967db352SNaveen Mamindlapalli 			  NPC_AF_MCAMEX_BANKX_ACTION(index, bank));
406967db352SNaveen Mamindlapalli }
407967db352SNaveen Mamindlapalli 
npc_fixup_vf_rule(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,int index,struct mcam_entry * entry,bool * enable)408967db352SNaveen Mamindlapalli static void npc_fixup_vf_rule(struct rvu *rvu, struct npc_mcam *mcam,
409967db352SNaveen Mamindlapalli 			      int blkaddr, int index, struct mcam_entry *entry,
410967db352SNaveen Mamindlapalli 			      bool *enable)
41155307fcbSSubbaraya Sundeep {
412d225c449SSubbaraya Sundeep 	struct rvu_npc_mcam_rule *rule;
41355307fcbSSubbaraya Sundeep 	u16 owner, target_func;
41455307fcbSSubbaraya Sundeep 	struct rvu_pfvf *pfvf;
41555307fcbSSubbaraya Sundeep 	u64 rx_action;
41655307fcbSSubbaraya Sundeep 
41755307fcbSSubbaraya Sundeep 	owner = mcam->entry2pfvf_map[index];
41855307fcbSSubbaraya Sundeep 	target_func = (entry->action >> 4) & 0xffff;
419967db352SNaveen Mamindlapalli 	/* do nothing when target is LBK/PF or owner is not PF */
420cb7a6b3bSSubbaraya Sundeep 	if (is_pffunc_af(owner) || is_afvf(target_func) ||
421cb7a6b3bSSubbaraya Sundeep 	    (owner & RVU_PFVF_FUNC_MASK) ||
42255307fcbSSubbaraya Sundeep 	    !(target_func & RVU_PFVF_FUNC_MASK))
42355307fcbSSubbaraya Sundeep 		return;
42455307fcbSSubbaraya Sundeep 
425967db352SNaveen Mamindlapalli 	/* save entry2target_pffunc */
42655307fcbSSubbaraya Sundeep 	pfvf = rvu_get_pfvf(rvu, target_func);
42755307fcbSSubbaraya Sundeep 	mcam->entry2target_pffunc[index] = target_func;
42855307fcbSSubbaraya Sundeep 
429967db352SNaveen Mamindlapalli 	/* don't enable rule when nixlf not attached or initialized */
430967db352SNaveen Mamindlapalli 	if (!(is_nixlf_attached(rvu, target_func) &&
431967db352SNaveen Mamindlapalli 	      test_bit(NIXLF_INITIALIZED, &pfvf->flags)))
432967db352SNaveen Mamindlapalli 		*enable = false;
43355307fcbSSubbaraya Sundeep 
434d225c449SSubbaraya Sundeep 	/* fix up not needed for the rules added by user(ntuple filters) */
435d225c449SSubbaraya Sundeep 	list_for_each_entry(rule, &mcam->mcam_rules, list) {
436d225c449SSubbaraya Sundeep 		if (rule->entry == index)
437d225c449SSubbaraya Sundeep 			return;
438d225c449SSubbaraya Sundeep 	}
439d225c449SSubbaraya Sundeep 
440734b494eSSubbaraya Sundeep 	/* AF modifies given action iff PF/VF has requested for it */
441734b494eSSubbaraya Sundeep 	if ((entry->action & 0xFULL) != NIX_RX_ACTION_DEFAULT)
442734b494eSSubbaraya Sundeep 		return;
443734b494eSSubbaraya Sundeep 
444967db352SNaveen Mamindlapalli 	/* copy VF default entry action to the VF mcam entry */
445967db352SNaveen Mamindlapalli 	rx_action = npc_get_default_entry_action(rvu, mcam, blkaddr,
446967db352SNaveen Mamindlapalli 						 target_func);
44755307fcbSSubbaraya Sundeep 	if (rx_action)
44855307fcbSSubbaraya Sundeep 		entry->action = rx_action;
44955307fcbSSubbaraya Sundeep }
45055307fcbSSubbaraya Sundeep 
npc_config_mcam_entry(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,int index,u8 intf,struct mcam_entry * entry,bool enable)45175900140SSunil Goutham static void npc_config_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
45275900140SSunil Goutham 				  int blkaddr, int index, u8 intf,
45375900140SSunil Goutham 				  struct mcam_entry *entry, bool enable)
45475900140SSunil Goutham {
45575900140SSunil Goutham 	int bank = npc_get_bank(mcam, index);
45675900140SSunil Goutham 	int kw = 0, actbank, actindex;
457fa2bf6baSSubbaraya Sundeep 	u8 tx_intf_mask = ~intf & 0x3;
458fa2bf6baSSubbaraya Sundeep 	u8 tx_intf = intf;
45975900140SSunil Goutham 	u64 cam0, cam1;
46075900140SSunil Goutham 
46175900140SSunil Goutham 	actbank = bank; /* Save bank id, to set action later on */
46275900140SSunil Goutham 	actindex = index;
46375900140SSunil Goutham 	index &= (mcam->banksize - 1);
46475900140SSunil Goutham 
4658cc89ae9SNithin Dabilpuram 	/* Disable before mcam entry update */
4668cc89ae9SNithin Dabilpuram 	npc_enable_mcam_entry(rvu, mcam, blkaddr, actindex, false);
4678cc89ae9SNithin Dabilpuram 
4688cc89ae9SNithin Dabilpuram 	/* Clear mcam entry to avoid writes being suppressed by NPC */
4698cc89ae9SNithin Dabilpuram 	npc_clear_mcam_entry(rvu, mcam, blkaddr, actindex);
4708cc89ae9SNithin Dabilpuram 
47175900140SSunil Goutham 	/* CAM1 takes the comparison value and
47275900140SSunil Goutham 	 * CAM0 specifies match for a bit in key being '0' or '1' or 'dontcare'.
47375900140SSunil Goutham 	 * CAM1<n> = 0 & CAM0<n> = 1 => match if key<n> = 0
47475900140SSunil Goutham 	 * CAM1<n> = 1 & CAM0<n> = 0 => match if key<n> = 1
47575900140SSunil Goutham 	 * CAM1<n> = 0 & CAM0<n> = 0 => always match i.e dontcare.
47675900140SSunil Goutham 	 */
47775900140SSunil Goutham 	for (; bank < (actbank + mcam->banks_per_entry); bank++, kw = kw + 2) {
47875900140SSunil Goutham 		/* Interface should be set in all banks */
479fa2bf6baSSubbaraya Sundeep 		if (is_npc_intf_tx(intf)) {
480fa2bf6baSSubbaraya Sundeep 			/* Last bit must be set and rest don't care
481fa2bf6baSSubbaraya Sundeep 			 * for TX interfaces
482fa2bf6baSSubbaraya Sundeep 			 */
483fa2bf6baSSubbaraya Sundeep 			tx_intf_mask = 0x1;
484fa2bf6baSSubbaraya Sundeep 			tx_intf = intf & tx_intf_mask;
485fa2bf6baSSubbaraya Sundeep 			tx_intf_mask = ~tx_intf & tx_intf_mask;
486fa2bf6baSSubbaraya Sundeep 		}
487fa2bf6baSSubbaraya Sundeep 
48875900140SSunil Goutham 		rvu_write64(rvu, blkaddr,
48975900140SSunil Goutham 			    NPC_AF_MCAMEX_BANKX_CAMX_INTF(index, bank, 1),
490fa2bf6baSSubbaraya Sundeep 			    tx_intf);
49175900140SSunil Goutham 		rvu_write64(rvu, blkaddr,
49275900140SSunil Goutham 			    NPC_AF_MCAMEX_BANKX_CAMX_INTF(index, bank, 0),
493fa2bf6baSSubbaraya Sundeep 			    tx_intf_mask);
49475900140SSunil Goutham 
49575900140SSunil Goutham 		/* Set the match key */
49675900140SSunil Goutham 		npc_get_keyword(entry, kw, &cam0, &cam1);
49775900140SSunil Goutham 		rvu_write64(rvu, blkaddr,
49875900140SSunil Goutham 			    NPC_AF_MCAMEX_BANKX_CAMX_W0(index, bank, 1), cam1);
49975900140SSunil Goutham 		rvu_write64(rvu, blkaddr,
50075900140SSunil Goutham 			    NPC_AF_MCAMEX_BANKX_CAMX_W0(index, bank, 0), cam0);
50175900140SSunil Goutham 
50275900140SSunil Goutham 		npc_get_keyword(entry, kw + 1, &cam0, &cam1);
50375900140SSunil Goutham 		rvu_write64(rvu, blkaddr,
50475900140SSunil Goutham 			    NPC_AF_MCAMEX_BANKX_CAMX_W1(index, bank, 1), cam1);
50575900140SSunil Goutham 		rvu_write64(rvu, blkaddr,
50675900140SSunil Goutham 			    NPC_AF_MCAMEX_BANKX_CAMX_W1(index, bank, 0), cam0);
50775900140SSunil Goutham 	}
50875900140SSunil Goutham 
509967db352SNaveen Mamindlapalli 	/* PF installing VF rule */
510d225c449SSubbaraya Sundeep 	if (is_npc_intf_rx(intf) && actindex < mcam->bmap_entries)
511d225c449SSubbaraya Sundeep 		npc_fixup_vf_rule(rvu, mcam, blkaddr, actindex, entry, &enable);
51255307fcbSSubbaraya Sundeep 
51375900140SSunil Goutham 	/* Set 'action' */
51475900140SSunil Goutham 	rvu_write64(rvu, blkaddr,
51575900140SSunil Goutham 		    NPC_AF_MCAMEX_BANKX_ACTION(index, actbank), entry->action);
51675900140SSunil Goutham 
51775900140SSunil Goutham 	/* Set TAG 'action' */
51875900140SSunil Goutham 	rvu_write64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_TAG_ACT(index, actbank),
51975900140SSunil Goutham 		    entry->vtag_action);
52075900140SSunil Goutham 
52175900140SSunil Goutham 	/* Enable the entry */
52275900140SSunil Goutham 	if (enable)
52375900140SSunil Goutham 		npc_enable_mcam_entry(rvu, mcam, blkaddr, actindex, true);
52475900140SSunil Goutham }
52575900140SSunil Goutham 
npc_read_mcam_entry(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,u16 src,struct mcam_entry * entry,u8 * intf,u8 * ena)526f0c2982aSNaveen Mamindlapalli void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
527f0c2982aSNaveen Mamindlapalli 			 int blkaddr, u16 src,
528f0c2982aSNaveen Mamindlapalli 			 struct mcam_entry *entry, u8 *intf, u8 *ena)
529f0c2982aSNaveen Mamindlapalli {
530f0c2982aSNaveen Mamindlapalli 	int sbank = npc_get_bank(mcam, src);
531f0c2982aSNaveen Mamindlapalli 	int bank, kw = 0;
532f0c2982aSNaveen Mamindlapalli 	u64 cam0, cam1;
533f0c2982aSNaveen Mamindlapalli 
534f0c2982aSNaveen Mamindlapalli 	src &= (mcam->banksize - 1);
535f0c2982aSNaveen Mamindlapalli 	bank = sbank;
536f0c2982aSNaveen Mamindlapalli 
537f0c2982aSNaveen Mamindlapalli 	for (; bank < (sbank + mcam->banks_per_entry); bank++, kw = kw + 2) {
538f0c2982aSNaveen Mamindlapalli 		cam1 = rvu_read64(rvu, blkaddr,
539f0c2982aSNaveen Mamindlapalli 				  NPC_AF_MCAMEX_BANKX_CAMX_W0(src, bank, 1));
540f0c2982aSNaveen Mamindlapalli 		cam0 = rvu_read64(rvu, blkaddr,
541f0c2982aSNaveen Mamindlapalli 				  NPC_AF_MCAMEX_BANKX_CAMX_W0(src, bank, 0));
542f0c2982aSNaveen Mamindlapalli 		npc_fill_entryword(entry, kw, cam0, cam1);
543f0c2982aSNaveen Mamindlapalli 
544f0c2982aSNaveen Mamindlapalli 		cam1 = rvu_read64(rvu, blkaddr,
545f0c2982aSNaveen Mamindlapalli 				  NPC_AF_MCAMEX_BANKX_CAMX_W1(src, bank, 1));
546f0c2982aSNaveen Mamindlapalli 		cam0 = rvu_read64(rvu, blkaddr,
547f0c2982aSNaveen Mamindlapalli 				  NPC_AF_MCAMEX_BANKX_CAMX_W1(src, bank, 0));
548f0c2982aSNaveen Mamindlapalli 		npc_fill_entryword(entry, kw + 1, cam0, cam1);
549f0c2982aSNaveen Mamindlapalli 	}
550f0c2982aSNaveen Mamindlapalli 
551f0c2982aSNaveen Mamindlapalli 	entry->action = rvu_read64(rvu, blkaddr,
552f0c2982aSNaveen Mamindlapalli 				   NPC_AF_MCAMEX_BANKX_ACTION(src, sbank));
553f0c2982aSNaveen Mamindlapalli 	entry->vtag_action =
554f0c2982aSNaveen Mamindlapalli 		rvu_read64(rvu, blkaddr,
555f0c2982aSNaveen Mamindlapalli 			   NPC_AF_MCAMEX_BANKX_TAG_ACT(src, sbank));
556f0c2982aSNaveen Mamindlapalli 	*intf = rvu_read64(rvu, blkaddr,
557f0c2982aSNaveen Mamindlapalli 			   NPC_AF_MCAMEX_BANKX_CAMX_INTF(src, sbank, 1)) & 3;
558f0c2982aSNaveen Mamindlapalli 	*ena = rvu_read64(rvu, blkaddr,
559f0c2982aSNaveen Mamindlapalli 			  NPC_AF_MCAMEX_BANKX_CFG(src, sbank)) & 1;
560f0c2982aSNaveen Mamindlapalli }
561f0c2982aSNaveen Mamindlapalli 
npc_copy_mcam_entry(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,u16 src,u16 dest)562651cd265SSunil Goutham static void npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
563651cd265SSunil Goutham 				int blkaddr, u16 src, u16 dest)
564651cd265SSunil Goutham {
565651cd265SSunil Goutham 	int dbank = npc_get_bank(mcam, dest);
566651cd265SSunil Goutham 	int sbank = npc_get_bank(mcam, src);
567651cd265SSunil Goutham 	u64 cfg, sreg, dreg;
568651cd265SSunil Goutham 	int bank, i;
569651cd265SSunil Goutham 
570651cd265SSunil Goutham 	src &= (mcam->banksize - 1);
571651cd265SSunil Goutham 	dest &= (mcam->banksize - 1);
572651cd265SSunil Goutham 
573651cd265SSunil Goutham 	/* Copy INTF's, W0's, W1's CAM0 and CAM1 configuration */
574651cd265SSunil Goutham 	for (bank = 0; bank < mcam->banks_per_entry; bank++) {
575651cd265SSunil Goutham 		sreg = NPC_AF_MCAMEX_BANKX_CAMX_INTF(src, sbank + bank, 0);
576651cd265SSunil Goutham 		dreg = NPC_AF_MCAMEX_BANKX_CAMX_INTF(dest, dbank + bank, 0);
577651cd265SSunil Goutham 		for (i = 0; i < 6; i++) {
578651cd265SSunil Goutham 			cfg = rvu_read64(rvu, blkaddr, sreg + (i * 8));
579651cd265SSunil Goutham 			rvu_write64(rvu, blkaddr, dreg + (i * 8), cfg);
580651cd265SSunil Goutham 		}
581651cd265SSunil Goutham 	}
582651cd265SSunil Goutham 
583651cd265SSunil Goutham 	/* Copy action */
584651cd265SSunil Goutham 	cfg = rvu_read64(rvu, blkaddr,
585651cd265SSunil Goutham 			 NPC_AF_MCAMEX_BANKX_ACTION(src, sbank));
586651cd265SSunil Goutham 	rvu_write64(rvu, blkaddr,
587651cd265SSunil Goutham 		    NPC_AF_MCAMEX_BANKX_ACTION(dest, dbank), cfg);
588651cd265SSunil Goutham 
589651cd265SSunil Goutham 	/* Copy TAG action */
590651cd265SSunil Goutham 	cfg = rvu_read64(rvu, blkaddr,
591651cd265SSunil Goutham 			 NPC_AF_MCAMEX_BANKX_TAG_ACT(src, sbank));
592651cd265SSunil Goutham 	rvu_write64(rvu, blkaddr,
593651cd265SSunil Goutham 		    NPC_AF_MCAMEX_BANKX_TAG_ACT(dest, dbank), cfg);
594651cd265SSunil Goutham 
595651cd265SSunil Goutham 	/* Enable or disable */
596651cd265SSunil Goutham 	cfg = rvu_read64(rvu, blkaddr,
597651cd265SSunil Goutham 			 NPC_AF_MCAMEX_BANKX_CFG(src, sbank));
598651cd265SSunil Goutham 	rvu_write64(rvu, blkaddr,
599651cd265SSunil Goutham 		    NPC_AF_MCAMEX_BANKX_CFG(dest, dbank), cfg);
600651cd265SSunil Goutham }
601651cd265SSunil Goutham 
npc_get_mcam_action(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,int index)60275900140SSunil Goutham static u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
60375900140SSunil Goutham 			       int blkaddr, int index)
60475900140SSunil Goutham {
60575900140SSunil Goutham 	int bank = npc_get_bank(mcam, index);
60675900140SSunil Goutham 
60775900140SSunil Goutham 	index &= (mcam->banksize - 1);
60875900140SSunil Goutham 	return rvu_read64(rvu, blkaddr,
60975900140SSunil Goutham 			  NPC_AF_MCAMEX_BANKX_ACTION(index, bank));
61075900140SSunil Goutham }
61175900140SSunil Goutham 
rvu_npc_install_ucast_entry(struct rvu * rvu,u16 pcifunc,int nixlf,u64 chan,u8 * mac_addr)61275900140SSunil Goutham void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
61375900140SSunil Goutham 				 int nixlf, u64 chan, u8 *mac_addr)
61475900140SSunil Goutham {
61586cea61dSTomasz Duszynski 	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
61655307fcbSSubbaraya Sundeep 	struct npc_install_flow_req req = { 0 };
61755307fcbSSubbaraya Sundeep 	struct npc_install_flow_rsp rsp = { 0 };
61875900140SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
61933b5bc9eSTom Rix 	struct nix_rx_action action = { 0 };
62055307fcbSSubbaraya Sundeep 	int blkaddr, index;
62175900140SSunil Goutham 
622fe1939bbSRadha Mohan Chintakuntla 	/* AF's and SDP VFs work in promiscuous mode */
623fe1939bbSRadha Mohan Chintakuntla 	if (is_afvf(pcifunc) || is_sdp_vf(pcifunc))
6248bb991c5STomasz Duszynski 		return;
6258bb991c5STomasz Duszynski 
62675900140SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
62775900140SSunil Goutham 	if (blkaddr < 0)
62875900140SSunil Goutham 		return;
62975900140SSunil Goutham 
630674b3e16SSuman Ghosh 	/* Ucast rule should not be installed if DMAC
631674b3e16SSuman Ghosh 	 * extraction is not supported by the profile.
632674b3e16SSuman Ghosh 	 */
633674b3e16SSuman Ghosh 	if (!npc_is_feature_supported(rvu, BIT_ULL(NPC_DMAC), pfvf->nix_rx_intf))
634674b3e16SSuman Ghosh 		return;
635674b3e16SSuman Ghosh 
63675900140SSunil Goutham 	index = npc_get_nixlf_mcam_index(mcam, pcifunc,
63775900140SSunil Goutham 					 nixlf, NIXLF_UCAST_ENTRY);
63875900140SSunil Goutham 
63975900140SSunil Goutham 	/* Don't change the action if entry is already enabled
64075900140SSunil Goutham 	 * Otherwise RSS action may get overwritten.
64175900140SSunil Goutham 	 */
64275900140SSunil Goutham 	if (is_mcam_entry_enabled(rvu, mcam, blkaddr, index)) {
64375900140SSunil Goutham 		*(u64 *)&action = npc_get_mcam_action(rvu, mcam,
64475900140SSunil Goutham 						      blkaddr, index);
64575900140SSunil Goutham 	} else {
64675900140SSunil Goutham 		action.op = NIX_RX_ACTIONOP_UCAST;
64775900140SSunil Goutham 		action.pf_func = pcifunc;
64875900140SSunil Goutham 	}
64975900140SSunil Goutham 
65055307fcbSSubbaraya Sundeep 	req.default_rule = 1;
65155307fcbSSubbaraya Sundeep 	ether_addr_copy(req.packet.dmac, mac_addr);
65255307fcbSSubbaraya Sundeep 	eth_broadcast_addr((u8 *)&req.mask.dmac);
65355307fcbSSubbaraya Sundeep 	req.features = BIT_ULL(NPC_DMAC);
65455307fcbSSubbaraya Sundeep 	req.channel = chan;
655cb7a6b3bSSubbaraya Sundeep 	req.chan_mask = 0xFFFU;
65655307fcbSSubbaraya Sundeep 	req.intf = pfvf->nix_rx_intf;
65755307fcbSSubbaraya Sundeep 	req.op = action.op;
65855307fcbSSubbaraya Sundeep 	req.hdr.pcifunc = 0; /* AF is requester */
65955307fcbSSubbaraya Sundeep 	req.vf = action.pf_func;
66055307fcbSSubbaraya Sundeep 	req.index = action.index;
66155307fcbSSubbaraya Sundeep 	req.match_id = action.match_id;
66255307fcbSSubbaraya Sundeep 	req.flow_key_alg = action.flow_key_alg;
66386cea61dSTomasz Duszynski 
66455307fcbSSubbaraya Sundeep 	rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
66575900140SSunil Goutham }
66675900140SSunil Goutham 
rvu_npc_install_promisc_entry(struct rvu * rvu,u16 pcifunc,int nixlf,u64 chan,u8 chan_cnt)667d6f092caSSunil Goutham void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
668967db352SNaveen Mamindlapalli 				   int nixlf, u64 chan, u8 chan_cnt)
669d6f092caSSunil Goutham {
6701c1935c9SSubbaraya Sundeep 	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
67156bcef52SNaveen Mamindlapalli 	struct npc_install_flow_req req = { 0 };
67256bcef52SNaveen Mamindlapalli 	struct npc_install_flow_rsp rsp = { 0 };
673d6f092caSSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
674967db352SNaveen Mamindlapalli 	struct rvu_hwinfo *hw = rvu->hw;
67556bcef52SNaveen Mamindlapalli 	int blkaddr, ucast_idx, index;
67633b5bc9eSTom Rix 	struct nix_rx_action action = { 0 };
677d450a235SNalla, Pradeep 	u64 relaxed_mask;
6786b5de31eSHariprasad Kelam 	u8 flow_key_alg;
679d6f092caSSunil Goutham 
680967db352SNaveen Mamindlapalli 	if (!hw->cap.nix_rx_multicast && is_cgx_vf(rvu, pcifunc))
681d6f092caSSunil Goutham 		return;
682d6f092caSSunil Goutham 
6838bb991c5STomasz Duszynski 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
6848bb991c5STomasz Duszynski 	if (blkaddr < 0)
685d6f092caSSunil Goutham 		return;
686d6f092caSSunil Goutham 
687d6f092caSSunil Goutham 	index = npc_get_nixlf_mcam_index(mcam, pcifunc,
688d6f092caSSunil Goutham 					 nixlf, NIXLF_PROMISC_ENTRY);
689d6f092caSSunil Goutham 
690967db352SNaveen Mamindlapalli 	if (is_cgx_vf(rvu, pcifunc))
691967db352SNaveen Mamindlapalli 		index = npc_get_nixlf_mcam_index(mcam,
692967db352SNaveen Mamindlapalli 						 pcifunc & ~RVU_PFVF_FUNC_MASK,
693967db352SNaveen Mamindlapalli 						 nixlf, NIXLF_PROMISC_ENTRY);
694967db352SNaveen Mamindlapalli 
695f9f2da46SVamsi Attunuru 	/* If the corresponding PF's ucast action is RSS,
696f9f2da46SVamsi Attunuru 	 * use the same action for promisc also
697f9f2da46SVamsi Attunuru 	 */
69856bcef52SNaveen Mamindlapalli 	ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
69956bcef52SNaveen Mamindlapalli 					     nixlf, NIXLF_UCAST_ENTRY);
700f9f2da46SVamsi Attunuru 	if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx))
701f9f2da46SVamsi Attunuru 		*(u64 *)&action = npc_get_mcam_action(rvu, mcam,
702f9f2da46SVamsi Attunuru 						      blkaddr, ucast_idx);
703f9f2da46SVamsi Attunuru 
704f9f2da46SVamsi Attunuru 	if (action.op != NIX_RX_ACTIONOP_RSS) {
70533b5bc9eSTom Rix 		*(u64 *)&action = 0;
706d6f092caSSunil Goutham 		action.op = NIX_RX_ACTIONOP_UCAST;
707f9f2da46SVamsi Attunuru 	}
708d6f092caSSunil Goutham 
7096b5de31eSHariprasad Kelam 	flow_key_alg = action.flow_key_alg;
7106b5de31eSHariprasad Kelam 
711967db352SNaveen Mamindlapalli 	/* RX_ACTION set to MCAST for CGX PF's */
712967db352SNaveen Mamindlapalli 	if (hw->cap.nix_rx_multicast && pfvf->use_mce_list &&
713967db352SNaveen Mamindlapalli 	    is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) {
71433b5bc9eSTom Rix 		*(u64 *)&action = 0;
715967db352SNaveen Mamindlapalli 		action.op = NIX_RX_ACTIONOP_MCAST;
716967db352SNaveen Mamindlapalli 		pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK);
717967db352SNaveen Mamindlapalli 		action.index = pfvf->promisc_mce_idx;
71856bcef52SNaveen Mamindlapalli 	}
71956bcef52SNaveen Mamindlapalli 
720aee51224SVidya 	/* For cn10k the upper two bits of the channel number are
721aee51224SVidya 	 * cpt channel number. with masking out these bits in the
722aee51224SVidya 	 * mcam entry, same entry used for NIX will allow packets
723aee51224SVidya 	 * received from cpt for parsing.
724aee51224SVidya 	 */
725aee51224SVidya 	if (!is_rvu_otx2(rvu)) {
726aee51224SVidya 		req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
727aee51224SVidya 	} else {
72856bcef52SNaveen Mamindlapalli 		req.chan_mask = 0xFFFU;
729aee51224SVidya 	}
730aee51224SVidya 
73156bcef52SNaveen Mamindlapalli 	if (chan_cnt > 1) {
73256bcef52SNaveen Mamindlapalli 		if (!is_power_of_2(chan_cnt)) {
73356bcef52SNaveen Mamindlapalli 			dev_err(rvu->dev,
73456bcef52SNaveen Mamindlapalli 				"%s: channel count more than 1, must be power of 2\n", __func__);
73556bcef52SNaveen Mamindlapalli 			return;
73656bcef52SNaveen Mamindlapalli 		}
73756bcef52SNaveen Mamindlapalli 		relaxed_mask = GENMASK_ULL(BITS_PER_LONG_LONG - 1,
73856bcef52SNaveen Mamindlapalli 					   ilog2(chan_cnt));
73956bcef52SNaveen Mamindlapalli 		req.chan_mask &= relaxed_mask;
74056bcef52SNaveen Mamindlapalli 	}
74156bcef52SNaveen Mamindlapalli 
74256bcef52SNaveen Mamindlapalli 	req.channel = chan;
74356bcef52SNaveen Mamindlapalli 	req.intf = pfvf->nix_rx_intf;
74456bcef52SNaveen Mamindlapalli 	req.entry = index;
74556bcef52SNaveen Mamindlapalli 	req.op = action.op;
74656bcef52SNaveen Mamindlapalli 	req.hdr.pcifunc = 0; /* AF is requester */
74756bcef52SNaveen Mamindlapalli 	req.vf = pcifunc;
74856bcef52SNaveen Mamindlapalli 	req.index = action.index;
74956bcef52SNaveen Mamindlapalli 	req.match_id = action.match_id;
7506b5de31eSHariprasad Kelam 	req.flow_key_alg = flow_key_alg;
75156bcef52SNaveen Mamindlapalli 
75256bcef52SNaveen Mamindlapalli 	rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
753d6f092caSSunil Goutham }
754d6f092caSSunil Goutham 
rvu_npc_enable_promisc_entry(struct rvu * rvu,u16 pcifunc,int nixlf,bool enable)755967db352SNaveen Mamindlapalli void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc,
75640df309eSSunil Goutham 				  int nixlf, bool enable)
757d6f092caSSunil Goutham {
758d6f092caSSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
759d6f092caSSunil Goutham 	int blkaddr, index;
760d6f092caSSunil Goutham 
761d6f092caSSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
762d6f092caSSunil Goutham 	if (blkaddr < 0)
763d6f092caSSunil Goutham 		return;
764d6f092caSSunil Goutham 
765967db352SNaveen Mamindlapalli 	/* Get 'pcifunc' of PF device */
766967db352SNaveen Mamindlapalli 	pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
767d6f092caSSunil Goutham 
768d6f092caSSunil Goutham 	index = npc_get_nixlf_mcam_index(mcam, pcifunc,
769d6f092caSSunil Goutham 					 nixlf, NIXLF_PROMISC_ENTRY);
77040df309eSSunil Goutham 	npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
77140df309eSSunil Goutham }
77240df309eSSunil Goutham 
rvu_npc_install_bcast_match_entry(struct rvu * rvu,u16 pcifunc,int nixlf,u64 chan)77375900140SSunil Goutham void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
77475900140SSunil Goutham 				       int nixlf, u64 chan)
77575900140SSunil Goutham {
7760f9651bbSColin Ian King 	struct rvu_pfvf *pfvf;
77756bcef52SNaveen Mamindlapalli 	struct npc_install_flow_req req = { 0 };
77856bcef52SNaveen Mamindlapalli 	struct npc_install_flow_rsp rsp = { 0 };
77975900140SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
780561e8752SSunil Goutham 	struct rvu_hwinfo *hw = rvu->hw;
78175900140SSunil Goutham 	int blkaddr, index;
78275900140SSunil Goutham 
78375900140SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
78475900140SSunil Goutham 	if (blkaddr < 0)
78575900140SSunil Goutham 		return;
78675900140SSunil Goutham 
787561e8752SSunil Goutham 	/* Skip LBK VFs */
788561e8752SSunil Goutham 	if (is_afvf(pcifunc))
78975900140SSunil Goutham 		return;
79075900140SSunil Goutham 
791561e8752SSunil Goutham 	/* If pkt replication is not supported,
792561e8752SSunil Goutham 	 * then only PF is allowed to add a bcast match entry.
793561e8752SSunil Goutham 	 */
794967db352SNaveen Mamindlapalli 	if (!hw->cap.nix_rx_multicast && is_vf(pcifunc))
795561e8752SSunil Goutham 		return;
796561e8752SSunil Goutham 
797561e8752SSunil Goutham 	/* Get 'pcifunc' of PF device */
798561e8752SSunil Goutham 	pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
7991c1935c9SSubbaraya Sundeep 	pfvf = rvu_get_pfvf(rvu, pcifunc);
800674b3e16SSuman Ghosh 
801674b3e16SSuman Ghosh 	/* Bcast rule should not be installed if both DMAC
802674b3e16SSuman Ghosh 	 * and LXMB extraction is not supported by the profile.
803674b3e16SSuman Ghosh 	 */
804674b3e16SSuman Ghosh 	if (!npc_is_feature_supported(rvu, BIT_ULL(NPC_DMAC), pfvf->nix_rx_intf) &&
805674b3e16SSuman Ghosh 	    !npc_is_feature_supported(rvu, BIT_ULL(NPC_LXMB), pfvf->nix_rx_intf))
806674b3e16SSuman Ghosh 		return;
807674b3e16SSuman Ghosh 
80875900140SSunil Goutham 	index = npc_get_nixlf_mcam_index(mcam, pcifunc,
80975900140SSunil Goutham 					 nixlf, NIXLF_BCAST_ENTRY);
81075900140SSunil Goutham 
811561e8752SSunil Goutham 	if (!hw->cap.nix_rx_multicast) {
81275900140SSunil Goutham 		/* Early silicon doesn't support pkt replication,
81375900140SSunil Goutham 		 * so install entry with UCAST action, so that PF
81475900140SSunil Goutham 		 * receives all broadcast packets.
81575900140SSunil Goutham 		 */
816967db352SNaveen Mamindlapalli 		req.op = NIX_RX_ACTIONOP_UCAST;
817561e8752SSunil Goutham 	} else {
818967db352SNaveen Mamindlapalli 		req.op = NIX_RX_ACTIONOP_MCAST;
819967db352SNaveen Mamindlapalli 		req.index = pfvf->bcast_mce_idx;
820561e8752SSunil Goutham 	}
82175900140SSunil Goutham 
82256bcef52SNaveen Mamindlapalli 	eth_broadcast_addr((u8 *)&req.packet.dmac);
82356bcef52SNaveen Mamindlapalli 	eth_broadcast_addr((u8 *)&req.mask.dmac);
82456bcef52SNaveen Mamindlapalli 	req.features = BIT_ULL(NPC_DMAC);
82556bcef52SNaveen Mamindlapalli 	req.channel = chan;
826cb7a6b3bSSubbaraya Sundeep 	req.chan_mask = 0xFFFU;
82756bcef52SNaveen Mamindlapalli 	req.intf = pfvf->nix_rx_intf;
82856bcef52SNaveen Mamindlapalli 	req.entry = index;
82956bcef52SNaveen Mamindlapalli 	req.hdr.pcifunc = 0; /* AF is requester */
83056bcef52SNaveen Mamindlapalli 	req.vf = pcifunc;
83156bcef52SNaveen Mamindlapalli 
83256bcef52SNaveen Mamindlapalli 	rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
83375900140SSunil Goutham }
83475900140SSunil Goutham 
rvu_npc_enable_bcast_entry(struct rvu * rvu,u16 pcifunc,int nixlf,bool enable)835967db352SNaveen Mamindlapalli void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
836967db352SNaveen Mamindlapalli 				bool enable)
837561e8752SSunil Goutham {
838561e8752SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
839561e8752SSunil Goutham 	int blkaddr, index;
840561e8752SSunil Goutham 
841561e8752SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
842561e8752SSunil Goutham 	if (blkaddr < 0)
843561e8752SSunil Goutham 		return;
844561e8752SSunil Goutham 
845561e8752SSunil Goutham 	/* Get 'pcifunc' of PF device */
846561e8752SSunil Goutham 	pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
847561e8752SSunil Goutham 
848967db352SNaveen Mamindlapalli 	index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
849967db352SNaveen Mamindlapalli 					 NIXLF_BCAST_ENTRY);
850967db352SNaveen Mamindlapalli 	npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
851967db352SNaveen Mamindlapalli }
852967db352SNaveen Mamindlapalli 
rvu_npc_install_allmulti_entry(struct rvu * rvu,u16 pcifunc,int nixlf,u64 chan)853967db352SNaveen Mamindlapalli void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
854967db352SNaveen Mamindlapalli 				    u64 chan)
855967db352SNaveen Mamindlapalli {
856967db352SNaveen Mamindlapalli 	struct npc_install_flow_req req = { 0 };
857967db352SNaveen Mamindlapalli 	struct npc_install_flow_rsp rsp = { 0 };
858967db352SNaveen Mamindlapalli 	struct npc_mcam *mcam = &rvu->hw->mcam;
859967db352SNaveen Mamindlapalli 	struct rvu_hwinfo *hw = rvu->hw;
860967db352SNaveen Mamindlapalli 	int blkaddr, ucast_idx, index;
861967db352SNaveen Mamindlapalli 	u8 mac_addr[ETH_ALEN] = { 0 };
86233b5bc9eSTom Rix 	struct nix_rx_action action = { 0 };
863967db352SNaveen Mamindlapalli 	struct rvu_pfvf *pfvf;
8646b5de31eSHariprasad Kelam 	u8 flow_key_alg;
865967db352SNaveen Mamindlapalli 	u16 vf_func;
866967db352SNaveen Mamindlapalli 
867967db352SNaveen Mamindlapalli 	/* Only CGX PF/VF can add allmulticast entry */
868fe1939bbSRadha Mohan Chintakuntla 	if (is_afvf(pcifunc) && is_sdp_vf(pcifunc))
869967db352SNaveen Mamindlapalli 		return;
870967db352SNaveen Mamindlapalli 
871967db352SNaveen Mamindlapalli 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
872967db352SNaveen Mamindlapalli 	if (blkaddr < 0)
873967db352SNaveen Mamindlapalli 		return;
874967db352SNaveen Mamindlapalli 
875967db352SNaveen Mamindlapalli 	/* Get 'pcifunc' of PF device */
876967db352SNaveen Mamindlapalli 	vf_func = pcifunc & RVU_PFVF_FUNC_MASK;
877967db352SNaveen Mamindlapalli 	pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
878967db352SNaveen Mamindlapalli 	pfvf = rvu_get_pfvf(rvu, pcifunc);
879674b3e16SSuman Ghosh 
880674b3e16SSuman Ghosh 	/* Mcast rule should not be installed if both DMAC
881674b3e16SSuman Ghosh 	 * and LXMB extraction is not supported by the profile.
882674b3e16SSuman Ghosh 	 */
883674b3e16SSuman Ghosh 	if (!npc_is_feature_supported(rvu, BIT_ULL(NPC_DMAC), pfvf->nix_rx_intf) &&
884674b3e16SSuman Ghosh 	    !npc_is_feature_supported(rvu, BIT_ULL(NPC_LXMB), pfvf->nix_rx_intf))
885674b3e16SSuman Ghosh 		return;
886674b3e16SSuman Ghosh 
887967db352SNaveen Mamindlapalli 	index = npc_get_nixlf_mcam_index(mcam, pcifunc,
888967db352SNaveen Mamindlapalli 					 nixlf, NIXLF_ALLMULTI_ENTRY);
889967db352SNaveen Mamindlapalli 
890967db352SNaveen Mamindlapalli 	/* If the corresponding PF's ucast action is RSS,
891967db352SNaveen Mamindlapalli 	 * use the same action for multicast entry also
892967db352SNaveen Mamindlapalli 	 */
893967db352SNaveen Mamindlapalli 	ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
894967db352SNaveen Mamindlapalli 					     nixlf, NIXLF_UCAST_ENTRY);
895967db352SNaveen Mamindlapalli 	if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx))
896967db352SNaveen Mamindlapalli 		*(u64 *)&action = npc_get_mcam_action(rvu, mcam,
897967db352SNaveen Mamindlapalli 							blkaddr, ucast_idx);
898967db352SNaveen Mamindlapalli 
8996b5de31eSHariprasad Kelam 	flow_key_alg = action.flow_key_alg;
900967db352SNaveen Mamindlapalli 	if (action.op != NIX_RX_ACTIONOP_RSS) {
90133b5bc9eSTom Rix 		*(u64 *)&action = 0;
902967db352SNaveen Mamindlapalli 		action.op = NIX_RX_ACTIONOP_UCAST;
903967db352SNaveen Mamindlapalli 		action.pf_func = pcifunc;
904967db352SNaveen Mamindlapalli 	}
905967db352SNaveen Mamindlapalli 
906967db352SNaveen Mamindlapalli 	/* RX_ACTION set to MCAST for CGX PF's */
907967db352SNaveen Mamindlapalli 	if (hw->cap.nix_rx_multicast && pfvf->use_mce_list) {
90833b5bc9eSTom Rix 		*(u64 *)&action = 0;
909967db352SNaveen Mamindlapalli 		action.op = NIX_RX_ACTIONOP_MCAST;
910967db352SNaveen Mamindlapalli 		action.index = pfvf->mcast_mce_idx;
911967db352SNaveen Mamindlapalli 	}
912967db352SNaveen Mamindlapalli 
913967db352SNaveen Mamindlapalli 	mac_addr[0] = 0x01;	/* LSB bit of 1st byte in DMAC */
914967db352SNaveen Mamindlapalli 	ether_addr_copy(req.packet.dmac, mac_addr);
915967db352SNaveen Mamindlapalli 	ether_addr_copy(req.mask.dmac, mac_addr);
916967db352SNaveen Mamindlapalli 	req.features = BIT_ULL(NPC_DMAC);
917967db352SNaveen Mamindlapalli 
918967db352SNaveen Mamindlapalli 	/* For cn10k the upper two bits of the channel number are
919967db352SNaveen Mamindlapalli 	 * cpt channel number. with masking out these bits in the
920967db352SNaveen Mamindlapalli 	 * mcam entry, same entry used for NIX will allow packets
921967db352SNaveen Mamindlapalli 	 * received from cpt for parsing.
922967db352SNaveen Mamindlapalli 	 */
923967db352SNaveen Mamindlapalli 	if (!is_rvu_otx2(rvu))
924967db352SNaveen Mamindlapalli 		req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
925967db352SNaveen Mamindlapalli 	else
926967db352SNaveen Mamindlapalli 		req.chan_mask = 0xFFFU;
927967db352SNaveen Mamindlapalli 
928967db352SNaveen Mamindlapalli 	req.channel = chan;
929967db352SNaveen Mamindlapalli 	req.intf = pfvf->nix_rx_intf;
930967db352SNaveen Mamindlapalli 	req.entry = index;
931967db352SNaveen Mamindlapalli 	req.op = action.op;
932967db352SNaveen Mamindlapalli 	req.hdr.pcifunc = 0; /* AF is requester */
933967db352SNaveen Mamindlapalli 	req.vf = pcifunc | vf_func;
934967db352SNaveen Mamindlapalli 	req.index = action.index;
935967db352SNaveen Mamindlapalli 	req.match_id = action.match_id;
9366b5de31eSHariprasad Kelam 	req.flow_key_alg = flow_key_alg;
937967db352SNaveen Mamindlapalli 
938967db352SNaveen Mamindlapalli 	rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
939967db352SNaveen Mamindlapalli }
940967db352SNaveen Mamindlapalli 
rvu_npc_enable_allmulti_entry(struct rvu * rvu,u16 pcifunc,int nixlf,bool enable)941967db352SNaveen Mamindlapalli void rvu_npc_enable_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
942967db352SNaveen Mamindlapalli 				   bool enable)
943967db352SNaveen Mamindlapalli {
944967db352SNaveen Mamindlapalli 	struct npc_mcam *mcam = &rvu->hw->mcam;
945967db352SNaveen Mamindlapalli 	int blkaddr, index;
946967db352SNaveen Mamindlapalli 
947967db352SNaveen Mamindlapalli 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
948967db352SNaveen Mamindlapalli 	if (blkaddr < 0)
949967db352SNaveen Mamindlapalli 		return;
950967db352SNaveen Mamindlapalli 
951967db352SNaveen Mamindlapalli 	/* Get 'pcifunc' of PF device */
952967db352SNaveen Mamindlapalli 	pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
953967db352SNaveen Mamindlapalli 
954967db352SNaveen Mamindlapalli 	index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
955967db352SNaveen Mamindlapalli 					 NIXLF_ALLMULTI_ENTRY);
956e154b5b7SSubbaraya Sundeep 	npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
957561e8752SSunil Goutham }
958561e8752SSunil Goutham 
npc_update_vf_flow_entry(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,u16 pcifunc,u64 rx_action)95955307fcbSSubbaraya Sundeep static void npc_update_vf_flow_entry(struct rvu *rvu, struct npc_mcam *mcam,
96055307fcbSSubbaraya Sundeep 				     int blkaddr, u16 pcifunc, u64 rx_action)
96155307fcbSSubbaraya Sundeep {
962f2e4568eSSubbaraya Sundeep 	int actindex, index, bank, entry;
963d225c449SSubbaraya Sundeep 	struct rvu_npc_mcam_rule *rule;
964d225c449SSubbaraya Sundeep 	bool enable, update;
96555307fcbSSubbaraya Sundeep 
96655307fcbSSubbaraya Sundeep 	if (!(pcifunc & RVU_PFVF_FUNC_MASK))
96755307fcbSSubbaraya Sundeep 		return;
96855307fcbSSubbaraya Sundeep 
96955307fcbSSubbaraya Sundeep 	mutex_lock(&mcam->lock);
97055307fcbSSubbaraya Sundeep 	for (index = 0; index < mcam->bmap_entries; index++) {
97155307fcbSSubbaraya Sundeep 		if (mcam->entry2target_pffunc[index] == pcifunc) {
972d225c449SSubbaraya Sundeep 			update = true;
973d225c449SSubbaraya Sundeep 			/* update not needed for the rules added via ntuple filters */
974d225c449SSubbaraya Sundeep 			list_for_each_entry(rule, &mcam->mcam_rules, list) {
975d225c449SSubbaraya Sundeep 				if (rule->entry == index)
976d225c449SSubbaraya Sundeep 					update = false;
977d225c449SSubbaraya Sundeep 			}
978d225c449SSubbaraya Sundeep 			if (!update)
979d225c449SSubbaraya Sundeep 				continue;
98055307fcbSSubbaraya Sundeep 			bank = npc_get_bank(mcam, index);
98155307fcbSSubbaraya Sundeep 			actindex = index;
982f2e4568eSSubbaraya Sundeep 			entry = index & (mcam->banksize - 1);
98355307fcbSSubbaraya Sundeep 
98455307fcbSSubbaraya Sundeep 			/* read vf flow entry enable status */
98555307fcbSSubbaraya Sundeep 			enable = is_mcam_entry_enabled(rvu, mcam, blkaddr,
98655307fcbSSubbaraya Sundeep 						       actindex);
98755307fcbSSubbaraya Sundeep 			/* disable before mcam entry update */
98855307fcbSSubbaraya Sundeep 			npc_enable_mcam_entry(rvu, mcam, blkaddr, actindex,
98955307fcbSSubbaraya Sundeep 					      false);
99055307fcbSSubbaraya Sundeep 			/* update 'action' */
99155307fcbSSubbaraya Sundeep 			rvu_write64(rvu, blkaddr,
992f2e4568eSSubbaraya Sundeep 				    NPC_AF_MCAMEX_BANKX_ACTION(entry, bank),
99355307fcbSSubbaraya Sundeep 				    rx_action);
99455307fcbSSubbaraya Sundeep 			if (enable)
99555307fcbSSubbaraya Sundeep 				npc_enable_mcam_entry(rvu, mcam, blkaddr,
99655307fcbSSubbaraya Sundeep 						      actindex, true);
99755307fcbSSubbaraya Sundeep 		}
99855307fcbSSubbaraya Sundeep 	}
99955307fcbSSubbaraya Sundeep 	mutex_unlock(&mcam->lock);
100055307fcbSSubbaraya Sundeep }
100155307fcbSSubbaraya Sundeep 
npc_update_rx_action_with_alg_idx(struct rvu * rvu,struct nix_rx_action action,struct rvu_pfvf * pfvf,int mcam_index,int blkaddr,int alg_idx)10026b5de31eSHariprasad Kelam static void npc_update_rx_action_with_alg_idx(struct rvu *rvu, struct nix_rx_action action,
10036b5de31eSHariprasad Kelam 					      struct rvu_pfvf *pfvf, int mcam_index, int blkaddr,
10046b5de31eSHariprasad Kelam 					      int alg_idx)
10056b5de31eSHariprasad Kelam 
10066b5de31eSHariprasad Kelam {
10076b5de31eSHariprasad Kelam 	struct npc_mcam *mcam = &rvu->hw->mcam;
10086b5de31eSHariprasad Kelam 	struct rvu_hwinfo *hw = rvu->hw;
10096b5de31eSHariprasad Kelam 	int bank, op_rss;
10106b5de31eSHariprasad Kelam 
10116b5de31eSHariprasad Kelam 	if (!is_mcam_entry_enabled(rvu, mcam, blkaddr, mcam_index))
10126b5de31eSHariprasad Kelam 		return;
10136b5de31eSHariprasad Kelam 
10146b5de31eSHariprasad Kelam 	op_rss = (!hw->cap.nix_rx_multicast || !pfvf->use_mce_list);
10156b5de31eSHariprasad Kelam 
10166b5de31eSHariprasad Kelam 	bank = npc_get_bank(mcam, mcam_index);
10176b5de31eSHariprasad Kelam 	mcam_index &= (mcam->banksize - 1);
10186b5de31eSHariprasad Kelam 
10196b5de31eSHariprasad Kelam 	/* If Rx action is MCAST update only RSS algorithm index */
10206b5de31eSHariprasad Kelam 	if (!op_rss) {
10216b5de31eSHariprasad Kelam 		*(u64 *)&action = rvu_read64(rvu, blkaddr,
10226b5de31eSHariprasad Kelam 				NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank));
10236b5de31eSHariprasad Kelam 
10246b5de31eSHariprasad Kelam 		action.flow_key_alg = alg_idx;
10256b5de31eSHariprasad Kelam 	}
10266b5de31eSHariprasad Kelam 	rvu_write64(rvu, blkaddr,
10276b5de31eSHariprasad Kelam 		    NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank), *(u64 *)&action);
10286b5de31eSHariprasad Kelam }
10296b5de31eSHariprasad Kelam 
rvu_npc_update_flowkey_alg_idx(struct rvu * rvu,u16 pcifunc,int nixlf,int group,int alg_idx,int mcam_index)1030cc96b0e9SSunil Goutham void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
1031cc96b0e9SSunil Goutham 				    int group, int alg_idx, int mcam_index)
1032cc96b0e9SSunil Goutham {
1033cc96b0e9SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
1034cc96b0e9SSunil Goutham 	struct nix_rx_action action;
1035cc96b0e9SSunil Goutham 	int blkaddr, index, bank;
103655307fcbSSubbaraya Sundeep 	struct rvu_pfvf *pfvf;
1037cc96b0e9SSunil Goutham 
1038cc96b0e9SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
1039cc96b0e9SSunil Goutham 	if (blkaddr < 0)
1040cc96b0e9SSunil Goutham 		return;
1041cc96b0e9SSunil Goutham 
1042cc96b0e9SSunil Goutham 	/* Check if this is for reserved default entry */
1043cc96b0e9SSunil Goutham 	if (mcam_index < 0) {
1044cc96b0e9SSunil Goutham 		if (group != DEFAULT_RSS_CONTEXT_GROUP)
1045cc96b0e9SSunil Goutham 			return;
1046cc96b0e9SSunil Goutham 		index = npc_get_nixlf_mcam_index(mcam, pcifunc,
1047cc96b0e9SSunil Goutham 						 nixlf, NIXLF_UCAST_ENTRY);
1048cc96b0e9SSunil Goutham 	} else {
1049cc96b0e9SSunil Goutham 		/* TODO: validate this mcam index */
1050cc96b0e9SSunil Goutham 		index = mcam_index;
1051cc96b0e9SSunil Goutham 	}
1052cc96b0e9SSunil Goutham 
1053cc96b0e9SSunil Goutham 	if (index >= mcam->total_entries)
1054cc96b0e9SSunil Goutham 		return;
1055cc96b0e9SSunil Goutham 
1056cc96b0e9SSunil Goutham 	bank = npc_get_bank(mcam, index);
1057cc96b0e9SSunil Goutham 	index &= (mcam->banksize - 1);
1058cc96b0e9SSunil Goutham 
1059cc96b0e9SSunil Goutham 	*(u64 *)&action = rvu_read64(rvu, blkaddr,
1060cc96b0e9SSunil Goutham 				     NPC_AF_MCAMEX_BANKX_ACTION(index, bank));
1061cc96b0e9SSunil Goutham 	/* Ignore if no action was set earlier */
1062cc96b0e9SSunil Goutham 	if (!*(u64 *)&action)
1063cc96b0e9SSunil Goutham 		return;
1064cc96b0e9SSunil Goutham 
1065cc96b0e9SSunil Goutham 	action.op = NIX_RX_ACTIONOP_RSS;
1066cc96b0e9SSunil Goutham 	action.pf_func = pcifunc;
1067cc96b0e9SSunil Goutham 	action.index = group;
1068cc96b0e9SSunil Goutham 	action.flow_key_alg = alg_idx;
1069cc96b0e9SSunil Goutham 
1070cc96b0e9SSunil Goutham 	rvu_write64(rvu, blkaddr,
1071cc96b0e9SSunil Goutham 		    NPC_AF_MCAMEX_BANKX_ACTION(index, bank), *(u64 *)&action);
107286cea61dSTomasz Duszynski 
107355307fcbSSubbaraya Sundeep 	/* update the VF flow rule action with the VF default entry action */
107455307fcbSSubbaraya Sundeep 	if (mcam_index < 0)
107555307fcbSSubbaraya Sundeep 		npc_update_vf_flow_entry(rvu, mcam, blkaddr, pcifunc,
107655307fcbSSubbaraya Sundeep 					 *(u64 *)&action);
107755307fcbSSubbaraya Sundeep 
107855307fcbSSubbaraya Sundeep 	/* update the action change in default rule */
107955307fcbSSubbaraya Sundeep 	pfvf = rvu_get_pfvf(rvu, pcifunc);
108055307fcbSSubbaraya Sundeep 	if (pfvf->def_ucast_rule)
108155307fcbSSubbaraya Sundeep 		pfvf->def_ucast_rule->rx_action = action;
108255307fcbSSubbaraya Sundeep 
1083f9f2da46SVamsi Attunuru 	index = npc_get_nixlf_mcam_index(mcam, pcifunc,
1084f9f2da46SVamsi Attunuru 					 nixlf, NIXLF_PROMISC_ENTRY);
1085f9f2da46SVamsi Attunuru 
1086f9f2da46SVamsi Attunuru 	/* If PF's promiscuous entry is enabled,
1087f9f2da46SVamsi Attunuru 	 * Set RSS action for that entry as well
1088f9f2da46SVamsi Attunuru 	 */
10896b5de31eSHariprasad Kelam 	npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, blkaddr,
10906b5de31eSHariprasad Kelam 					  alg_idx);
1091f9f2da46SVamsi Attunuru 
10926b5de31eSHariprasad Kelam 	index = npc_get_nixlf_mcam_index(mcam, pcifunc,
10936b5de31eSHariprasad Kelam 					 nixlf, NIXLF_ALLMULTI_ENTRY);
10946b5de31eSHariprasad Kelam 	/* If PF's allmulti  entry is enabled,
10956b5de31eSHariprasad Kelam 	 * Set RSS action for that entry as well
10966b5de31eSHariprasad Kelam 	 */
10976b5de31eSHariprasad Kelam 	npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, blkaddr,
10986b5de31eSHariprasad Kelam 					  alg_idx);
1099cc96b0e9SSunil Goutham }
1100cc96b0e9SSunil Goutham 
npc_enadis_default_mce_entry(struct rvu * rvu,u16 pcifunc,int nixlf,int type,bool enable)1101967db352SNaveen Mamindlapalli void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
1102967db352SNaveen Mamindlapalli 				  int nixlf, int type, bool enable)
1103967db352SNaveen Mamindlapalli {
1104967db352SNaveen Mamindlapalli 	struct npc_mcam *mcam = &rvu->hw->mcam;
1105967db352SNaveen Mamindlapalli 	struct rvu_hwinfo *hw = rvu->hw;
1106967db352SNaveen Mamindlapalli 	struct nix_mce_list *mce_list;
1107967db352SNaveen Mamindlapalli 	int index, blkaddr, mce_idx;
1108967db352SNaveen Mamindlapalli 	struct rvu_pfvf *pfvf;
1109967db352SNaveen Mamindlapalli 
1110967db352SNaveen Mamindlapalli 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
1111967db352SNaveen Mamindlapalli 	if (blkaddr < 0)
1112967db352SNaveen Mamindlapalli 		return;
1113967db352SNaveen Mamindlapalli 
1114967db352SNaveen Mamindlapalli 	index = npc_get_nixlf_mcam_index(mcam, pcifunc & ~RVU_PFVF_FUNC_MASK,
1115967db352SNaveen Mamindlapalli 					 nixlf, type);
1116967db352SNaveen Mamindlapalli 
1117967db352SNaveen Mamindlapalli 	/* disable MCAM entry when packet replication is not supported by hw */
1118967db352SNaveen Mamindlapalli 	if (!hw->cap.nix_rx_multicast && !is_vf(pcifunc)) {
1119967db352SNaveen Mamindlapalli 		npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
1120967db352SNaveen Mamindlapalli 		return;
1121967db352SNaveen Mamindlapalli 	}
1122967db352SNaveen Mamindlapalli 
1123967db352SNaveen Mamindlapalli 	/* return incase mce list is not enabled */
1124967db352SNaveen Mamindlapalli 	pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK);
1125967db352SNaveen Mamindlapalli 	if (hw->cap.nix_rx_multicast && is_vf(pcifunc) &&
1126967db352SNaveen Mamindlapalli 	    type != NIXLF_BCAST_ENTRY && !pfvf->use_mce_list)
1127967db352SNaveen Mamindlapalli 		return;
1128967db352SNaveen Mamindlapalli 
1129967db352SNaveen Mamindlapalli 	nix_get_mce_list(rvu, pcifunc, type, &mce_list, &mce_idx);
1130967db352SNaveen Mamindlapalli 
1131967db352SNaveen Mamindlapalli 	nix_update_mce_list(rvu, pcifunc, mce_list,
1132967db352SNaveen Mamindlapalli 			    mce_idx, index, enable);
1133967db352SNaveen Mamindlapalli 	if (enable)
1134967db352SNaveen Mamindlapalli 		npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
1135967db352SNaveen Mamindlapalli }
1136967db352SNaveen Mamindlapalli 
npc_enadis_default_entries(struct rvu * rvu,u16 pcifunc,int nixlf,bool enable)113740df309eSSunil Goutham static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
113840df309eSSunil Goutham 				       int nixlf, bool enable)
113975900140SSunil Goutham {
114075900140SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
1141967db352SNaveen Mamindlapalli 	int index, blkaddr;
114240df309eSSunil Goutham 
114340df309eSSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
114440df309eSSunil Goutham 	if (blkaddr < 0)
114540df309eSSunil Goutham 		return;
114640df309eSSunil Goutham 
114740df309eSSunil Goutham 	/* Ucast MCAM match entry of this PF/VF */
114840df309eSSunil Goutham 	index = npc_get_nixlf_mcam_index(mcam, pcifunc,
114940df309eSSunil Goutham 					 nixlf, NIXLF_UCAST_ENTRY);
115040df309eSSunil Goutham 	npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
115140df309eSSunil Goutham 
1152967db352SNaveen Mamindlapalli 	/* Nothing to do for VFs, on platforms where pkt replication
1153967db352SNaveen Mamindlapalli 	 * is not supported
1154e154b5b7SSubbaraya Sundeep 	 */
1155967db352SNaveen Mamindlapalli 	if ((pcifunc & RVU_PFVF_FUNC_MASK) && !rvu->hw->cap.nix_rx_multicast)
115640df309eSSunil Goutham 		return;
115740df309eSSunil Goutham 
1158967db352SNaveen Mamindlapalli 	/* add/delete pf_func to broadcast MCE list */
1159967db352SNaveen Mamindlapalli 	npc_enadis_default_mce_entry(rvu, pcifunc, nixlf,
1160967db352SNaveen Mamindlapalli 				     NIXLF_BCAST_ENTRY, enable);
116140df309eSSunil Goutham }
116240df309eSSunil Goutham 
rvu_npc_disable_default_entries(struct rvu * rvu,u16 pcifunc,int nixlf)116340df309eSSunil Goutham void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
116440df309eSSunil Goutham {
11653f8fe40aSSubbaraya Sundeep 	if (nixlf < 0)
11663f8fe40aSSubbaraya Sundeep 		return;
11673f8fe40aSSubbaraya Sundeep 
116840df309eSSunil Goutham 	npc_enadis_default_entries(rvu, pcifunc, nixlf, false);
1169967db352SNaveen Mamindlapalli 
1170967db352SNaveen Mamindlapalli 	/* Delete multicast and promisc MCAM entries */
1171967db352SNaveen Mamindlapalli 	npc_enadis_default_mce_entry(rvu, pcifunc, nixlf,
1172967db352SNaveen Mamindlapalli 				     NIXLF_ALLMULTI_ENTRY, false);
1173967db352SNaveen Mamindlapalli 	npc_enadis_default_mce_entry(rvu, pcifunc, nixlf,
1174967db352SNaveen Mamindlapalli 				     NIXLF_PROMISC_ENTRY, false);
117540df309eSSunil Goutham }
117640df309eSSunil Goutham 
rvu_npc_enable_mcam_by_entry_index(struct rvu * rvu,int entry,int intf,bool enable)11773571fe07SRatheesh Kannoth bool rvu_npc_enable_mcam_by_entry_index(struct rvu *rvu, int entry, int intf, bool enable)
11783571fe07SRatheesh Kannoth {
11793571fe07SRatheesh Kannoth 	int blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
11803571fe07SRatheesh Kannoth 	struct npc_mcam *mcam = &rvu->hw->mcam;
11813571fe07SRatheesh Kannoth 	struct rvu_npc_mcam_rule *rule, *tmp;
11823571fe07SRatheesh Kannoth 
11833571fe07SRatheesh Kannoth 	mutex_lock(&mcam->lock);
11843571fe07SRatheesh Kannoth 
11853571fe07SRatheesh Kannoth 	list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) {
11863571fe07SRatheesh Kannoth 		if (rule->intf != intf)
11873571fe07SRatheesh Kannoth 			continue;
11883571fe07SRatheesh Kannoth 
11893571fe07SRatheesh Kannoth 		if (rule->entry != entry)
11903571fe07SRatheesh Kannoth 			continue;
11913571fe07SRatheesh Kannoth 
11923571fe07SRatheesh Kannoth 		rule->enable = enable;
11933571fe07SRatheesh Kannoth 		mutex_unlock(&mcam->lock);
11943571fe07SRatheesh Kannoth 
11953571fe07SRatheesh Kannoth 		npc_enable_mcam_entry(rvu, mcam, blkaddr,
11963571fe07SRatheesh Kannoth 				      entry, enable);
11973571fe07SRatheesh Kannoth 
11983571fe07SRatheesh Kannoth 		return true;
11993571fe07SRatheesh Kannoth 	}
12003571fe07SRatheesh Kannoth 
12013571fe07SRatheesh Kannoth 	mutex_unlock(&mcam->lock);
12023571fe07SRatheesh Kannoth 	return false;
12033571fe07SRatheesh Kannoth }
12043571fe07SRatheesh Kannoth 
rvu_npc_enable_default_entries(struct rvu * rvu,u16 pcifunc,int nixlf)120540df309eSSunil Goutham void rvu_npc_enable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
120640df309eSSunil Goutham {
12073f8fe40aSSubbaraya Sundeep 	if (nixlf < 0)
12083f8fe40aSSubbaraya Sundeep 		return;
12093f8fe40aSSubbaraya Sundeep 
1210967db352SNaveen Mamindlapalli 	/* Enables only broadcast match entry. Promisc/Allmulti are enabled
1211967db352SNaveen Mamindlapalli 	 * in set_rx_mode mbox handler.
1212967db352SNaveen Mamindlapalli 	 */
121340df309eSSunil Goutham 	npc_enadis_default_entries(rvu, pcifunc, nixlf, true);
121440df309eSSunil Goutham }
121540df309eSSunil Goutham 
rvu_npc_disable_mcam_entries(struct rvu * rvu,u16 pcifunc,int nixlf)121640df309eSSunil Goutham void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
121740df309eSSunil Goutham {
121855307fcbSSubbaraya Sundeep 	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
121940df309eSSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
1220b6b0e366SSubbaraya Sundeep 	struct rvu_npc_mcam_rule *rule, *tmp;
122140df309eSSunil Goutham 	int blkaddr;
122275900140SSunil Goutham 
122375900140SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
122475900140SSunil Goutham 	if (blkaddr < 0)
122575900140SSunil Goutham 		return;
122675900140SSunil Goutham 
1227f9274958SSunil Goutham 	mutex_lock(&mcam->lock);
1228f9274958SSunil Goutham 
122955307fcbSSubbaraya Sundeep 	/* Disable MCAM entries directing traffic to this 'pcifunc' */
1230b6b0e366SSubbaraya Sundeep 	list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) {
123155307fcbSSubbaraya Sundeep 		if (is_npc_intf_rx(rule->intf) &&
1232967db352SNaveen Mamindlapalli 		    rule->rx_action.pf_func == pcifunc &&
1233967db352SNaveen Mamindlapalli 		    rule->rx_action.op != NIX_RX_ACTIONOP_MCAST) {
123455307fcbSSubbaraya Sundeep 			npc_enable_mcam_entry(rvu, mcam, blkaddr,
123555307fcbSSubbaraya Sundeep 					      rule->entry, false);
123655307fcbSSubbaraya Sundeep 			rule->enable = false;
123755307fcbSSubbaraya Sundeep 			/* Indicate that default rule is disabled */
1238b6b0e366SSubbaraya Sundeep 			if (rule->default_rule) {
123955307fcbSSubbaraya Sundeep 				pfvf->def_ucast_rule = NULL;
1240b6b0e366SSubbaraya Sundeep 				list_del(&rule->list);
1241b6b0e366SSubbaraya Sundeep 				kfree(rule);
1242b6b0e366SSubbaraya Sundeep 			}
124355307fcbSSubbaraya Sundeep 		}
124455307fcbSSubbaraya Sundeep 	}
124555307fcbSSubbaraya Sundeep 
124655307fcbSSubbaraya Sundeep 	mutex_unlock(&mcam->lock);
124755307fcbSSubbaraya Sundeep 
124855307fcbSSubbaraya Sundeep 	npc_mcam_disable_flows(rvu, pcifunc);
124955307fcbSSubbaraya Sundeep 
125055307fcbSSubbaraya Sundeep 	rvu_npc_disable_default_entries(rvu, pcifunc, nixlf);
125155307fcbSSubbaraya Sundeep }
125255307fcbSSubbaraya Sundeep 
rvu_npc_free_mcam_entries(struct rvu * rvu,u16 pcifunc,int nixlf)125355307fcbSSubbaraya Sundeep void rvu_npc_free_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
125455307fcbSSubbaraya Sundeep {
125555307fcbSSubbaraya Sundeep 	struct npc_mcam *mcam = &rvu->hw->mcam;
125655307fcbSSubbaraya Sundeep 	struct rvu_npc_mcam_rule *rule, *tmp;
125755307fcbSSubbaraya Sundeep 	int blkaddr;
125855307fcbSSubbaraya Sundeep 
125955307fcbSSubbaraya Sundeep 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
126055307fcbSSubbaraya Sundeep 	if (blkaddr < 0)
126155307fcbSSubbaraya Sundeep 		return;
126255307fcbSSubbaraya Sundeep 
126355307fcbSSubbaraya Sundeep 	mutex_lock(&mcam->lock);
126455307fcbSSubbaraya Sundeep 
126555307fcbSSubbaraya Sundeep 	/* Free all MCAM entries owned by this 'pcifunc' */
1266f9274958SSunil Goutham 	npc_mcam_free_all_entries(rvu, mcam, blkaddr, pcifunc);
1267f9274958SSunil Goutham 
126855307fcbSSubbaraya Sundeep 	/* Free all MCAM counters owned by this 'pcifunc' */
1269a958dd59SSunil Goutham 	npc_mcam_free_all_counters(rvu, mcam, pcifunc);
1270a958dd59SSunil Goutham 
127155307fcbSSubbaraya Sundeep 	/* Delete MCAM entries owned by this 'pcifunc' */
127255307fcbSSubbaraya Sundeep 	list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) {
127355307fcbSSubbaraya Sundeep 		if (rule->owner == pcifunc && !rule->default_rule) {
127455307fcbSSubbaraya Sundeep 			list_del(&rule->list);
127555307fcbSSubbaraya Sundeep 			kfree(rule);
127655307fcbSSubbaraya Sundeep 		}
127755307fcbSSubbaraya Sundeep 	}
127855307fcbSSubbaraya Sundeep 
1279f9274958SSunil Goutham 	mutex_unlock(&mcam->lock);
1280f9274958SSunil Goutham 
128140df309eSSunil Goutham 	rvu_npc_disable_default_entries(rvu, pcifunc, nixlf);
128275900140SSunil Goutham }
128375900140SSunil Goutham 
npc_program_mkex_rx(struct rvu * rvu,int blkaddr,struct npc_mcam_kex * mkex,u8 intf)12841c1935c9SSubbaraya Sundeep static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr,
12851c1935c9SSubbaraya Sundeep 				struct npc_mcam_kex *mkex, u8 intf)
128623705adbSVamsi Attunuru {
128723705adbSVamsi Attunuru 	int lid, lt, ld, fl;
128823705adbSVamsi Attunuru 
12891c1935c9SSubbaraya Sundeep 	if (is_npc_intf_tx(intf))
12901c1935c9SSubbaraya Sundeep 		return;
12911c1935c9SSubbaraya Sundeep 
12921c1935c9SSubbaraya Sundeep 	rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf),
129323705adbSVamsi Attunuru 		    mkex->keyx_cfg[NIX_INTF_RX]);
12941c1935c9SSubbaraya Sundeep 
12951c1935c9SSubbaraya Sundeep 	/* Program LDATA */
12961c1935c9SSubbaraya Sundeep 	for (lid = 0; lid < NPC_MAX_LID; lid++) {
12971c1935c9SSubbaraya Sundeep 		for (lt = 0; lt < NPC_MAX_LT; lt++) {
12981c1935c9SSubbaraya Sundeep 			for (ld = 0; ld < NPC_MAX_LD; ld++)
12991c1935c9SSubbaraya Sundeep 				SET_KEX_LD(intf, lid, lt, ld,
13001c1935c9SSubbaraya Sundeep 					   mkex->intf_lid_lt_ld[NIX_INTF_RX]
13011c1935c9SSubbaraya Sundeep 					   [lid][lt][ld]);
13021c1935c9SSubbaraya Sundeep 		}
13031c1935c9SSubbaraya Sundeep 	}
13041c1935c9SSubbaraya Sundeep 	/* Program LFLAGS */
13051c1935c9SSubbaraya Sundeep 	for (ld = 0; ld < NPC_MAX_LD; ld++) {
13061c1935c9SSubbaraya Sundeep 		for (fl = 0; fl < NPC_MAX_LFL; fl++)
13071c1935c9SSubbaraya Sundeep 			SET_KEX_LDFLAGS(intf, ld, fl,
13081c1935c9SSubbaraya Sundeep 					mkex->intf_ld_flags[NIX_INTF_RX]
13091c1935c9SSubbaraya Sundeep 					[ld][fl]);
13101c1935c9SSubbaraya Sundeep 	}
13111c1935c9SSubbaraya Sundeep }
13121c1935c9SSubbaraya Sundeep 
npc_program_mkex_tx(struct rvu * rvu,int blkaddr,struct npc_mcam_kex * mkex,u8 intf)13131c1935c9SSubbaraya Sundeep static void npc_program_mkex_tx(struct rvu *rvu, int blkaddr,
13141c1935c9SSubbaraya Sundeep 				struct npc_mcam_kex *mkex, u8 intf)
13151c1935c9SSubbaraya Sundeep {
13161c1935c9SSubbaraya Sundeep 	int lid, lt, ld, fl;
13171c1935c9SSubbaraya Sundeep 
13181c1935c9SSubbaraya Sundeep 	if (is_npc_intf_rx(intf))
13191c1935c9SSubbaraya Sundeep 		return;
13201c1935c9SSubbaraya Sundeep 
13211c1935c9SSubbaraya Sundeep 	rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf),
132223705adbSVamsi Attunuru 		    mkex->keyx_cfg[NIX_INTF_TX]);
132323705adbSVamsi Attunuru 
13241c1935c9SSubbaraya Sundeep 	/* Program LDATA */
13251c1935c9SSubbaraya Sundeep 	for (lid = 0; lid < NPC_MAX_LID; lid++) {
13261c1935c9SSubbaraya Sundeep 		for (lt = 0; lt < NPC_MAX_LT; lt++) {
13271c1935c9SSubbaraya Sundeep 			for (ld = 0; ld < NPC_MAX_LD; ld++)
13281c1935c9SSubbaraya Sundeep 				SET_KEX_LD(intf, lid, lt, ld,
13291c1935c9SSubbaraya Sundeep 					   mkex->intf_lid_lt_ld[NIX_INTF_TX]
13301c1935c9SSubbaraya Sundeep 					   [lid][lt][ld]);
13311c1935c9SSubbaraya Sundeep 		}
13321c1935c9SSubbaraya Sundeep 	}
13331c1935c9SSubbaraya Sundeep 	/* Program LFLAGS */
13341c1935c9SSubbaraya Sundeep 	for (ld = 0; ld < NPC_MAX_LD; ld++) {
13351c1935c9SSubbaraya Sundeep 		for (fl = 0; fl < NPC_MAX_LFL; fl++)
13361c1935c9SSubbaraya Sundeep 			SET_KEX_LDFLAGS(intf, ld, fl,
13371c1935c9SSubbaraya Sundeep 					mkex->intf_ld_flags[NIX_INTF_TX]
13381c1935c9SSubbaraya Sundeep 					[ld][fl]);
13391c1935c9SSubbaraya Sundeep 	}
13401c1935c9SSubbaraya Sundeep }
13411c1935c9SSubbaraya Sundeep 
npc_program_mkex_profile(struct rvu * rvu,int blkaddr,struct npc_mcam_kex * mkex)13421c1935c9SSubbaraya Sundeep static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr,
13431c1935c9SSubbaraya Sundeep 				     struct npc_mcam_kex *mkex)
13441c1935c9SSubbaraya Sundeep {
13451c1935c9SSubbaraya Sundeep 	struct rvu_hwinfo *hw = rvu->hw;
13461c1935c9SSubbaraya Sundeep 	u8 intf;
13471c1935c9SSubbaraya Sundeep 	int ld;
13481c1935c9SSubbaraya Sundeep 
134923705adbSVamsi Attunuru 	for (ld = 0; ld < NPC_MAX_LD; ld++)
135023705adbSVamsi Attunuru 		rvu_write64(rvu, blkaddr, NPC_AF_KEX_LDATAX_FLAGS_CFG(ld),
135123705adbSVamsi Attunuru 			    mkex->kex_ld_flags[ld]);
135223705adbSVamsi Attunuru 
13531c1935c9SSubbaraya Sundeep 	for (intf = 0; intf < hw->npc_intfs; intf++) {
13541c1935c9SSubbaraya Sundeep 		npc_program_mkex_rx(rvu, blkaddr, mkex, intf);
13551c1935c9SSubbaraya Sundeep 		npc_program_mkex_tx(rvu, blkaddr, mkex, intf);
135623705adbSVamsi Attunuru 	}
135756d9f5fdSRatheesh Kannoth 
135856d9f5fdSRatheesh Kannoth 	/* Programme mkex hash profile */
135956d9f5fdSRatheesh Kannoth 	npc_program_mkex_hash(rvu, blkaddr);
136023705adbSVamsi Attunuru }
136123705adbSVamsi Attunuru 
npc_fwdb_prfl_img_map(struct rvu * rvu,void __iomem ** prfl_img_addr,u64 * size)13625d16250bSHarman Kalra static int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr,
13635d16250bSHarman Kalra 				 u64 *size)
13645d16250bSHarman Kalra {
13655d16250bSHarman Kalra 	u64 prfl_addr, prfl_sz;
13665d16250bSHarman Kalra 
13675d16250bSHarman Kalra 	if (!rvu->fwdata)
13685d16250bSHarman Kalra 		return -EINVAL;
13695d16250bSHarman Kalra 
13705d16250bSHarman Kalra 	prfl_addr = rvu->fwdata->mcam_addr;
13715d16250bSHarman Kalra 	prfl_sz = rvu->fwdata->mcam_sz;
13725d16250bSHarman Kalra 
13735d16250bSHarman Kalra 	if (!prfl_addr || !prfl_sz)
13745d16250bSHarman Kalra 		return -EINVAL;
13755d16250bSHarman Kalra 
13765d16250bSHarman Kalra 	*prfl_img_addr = ioremap_wc(prfl_addr, prfl_sz);
13775d16250bSHarman Kalra 	if (!(*prfl_img_addr))
13785d16250bSHarman Kalra 		return -ENOMEM;
13795d16250bSHarman Kalra 
13805d16250bSHarman Kalra 	*size = prfl_sz;
13815d16250bSHarman Kalra 
13825d16250bSHarman Kalra 	return 0;
13835d16250bSHarman Kalra }
13845d16250bSHarman Kalra 
13855d16250bSHarman Kalra /* strtoull of "mkexprof" with base:36 */
138623705adbSVamsi Attunuru #define MKEX_END_SIGN  0xdeadbeef
138723705adbSVamsi Attunuru 
npc_load_mkex_profile(struct rvu * rvu,int blkaddr,const char * mkex_profile)138842006910SStanislaw Kardach static void npc_load_mkex_profile(struct rvu *rvu, int blkaddr,
138942006910SStanislaw Kardach 				  const char *mkex_profile)
139023705adbSVamsi Attunuru {
139123705adbSVamsi Attunuru 	struct device *dev = &rvu->pdev->dev;
139223705adbSVamsi Attunuru 	struct npc_mcam_kex *mcam_kex;
13935d16250bSHarman Kalra 	void __iomem *mkex_prfl_addr = NULL;
13945d16250bSHarman Kalra 	u64 prfl_sz;
13955d16250bSHarman Kalra 	int ret;
139623705adbSVamsi Attunuru 
139723705adbSVamsi Attunuru 	/* If user not selected mkex profile */
13983a724415SStanislaw Kardach 	if (rvu->kpu_fwdata_sz ||
13993a724415SStanislaw Kardach 	    !strncmp(mkex_profile, def_pfl_name, MKEX_NAME_LEN))
140042006910SStanislaw Kardach 		goto program_mkex;
140123705adbSVamsi Attunuru 
14025d16250bSHarman Kalra 	/* Setting up the mapping for mkex profile image */
14035d16250bSHarman Kalra 	ret = npc_fwdb_prfl_img_map(rvu, &mkex_prfl_addr, &prfl_sz);
14045d16250bSHarman Kalra 	if (ret < 0)
140542006910SStanislaw Kardach 		goto program_mkex;
140623705adbSVamsi Attunuru 
14075d16250bSHarman Kalra 	mcam_kex = (struct npc_mcam_kex __force *)mkex_prfl_addr;
140823705adbSVamsi Attunuru 
140923705adbSVamsi Attunuru 	while (((s64)prfl_sz > 0) && (mcam_kex->mkex_sign != MKEX_END_SIGN)) {
141023705adbSVamsi Attunuru 		/* Compare with mkex mod_param name string */
141123705adbSVamsi Attunuru 		if (mcam_kex->mkex_sign == MKEX_SIGN &&
141223705adbSVamsi Attunuru 		    !strncmp(mcam_kex->name, mkex_profile, MKEX_NAME_LEN)) {
14135d9b976dSSunil Goutham 			/* Due to an errata (35786) in A0/B0 pass silicon,
141423705adbSVamsi Attunuru 			 * parse nibble enable configuration has to be
141523705adbSVamsi Attunuru 			 * identical for both Rx and Tx interfaces.
141623705adbSVamsi Attunuru 			 */
141742006910SStanislaw Kardach 			if (!is_rvu_96xx_B0(rvu) ||
141842006910SStanislaw Kardach 			    mcam_kex->keyx_cfg[NIX_INTF_RX] == mcam_kex->keyx_cfg[NIX_INTF_TX])
141942006910SStanislaw Kardach 				rvu->kpu.mkex = mcam_kex;
142042006910SStanislaw Kardach 			goto program_mkex;
142123705adbSVamsi Attunuru 		}
142223705adbSVamsi Attunuru 
142323705adbSVamsi Attunuru 		mcam_kex++;
142423705adbSVamsi Attunuru 		prfl_sz -= sizeof(struct npc_mcam_kex);
142523705adbSVamsi Attunuru 	}
142642006910SStanislaw Kardach 	dev_warn(dev, "Failed to load requested profile: %s\n", mkex_profile);
142723705adbSVamsi Attunuru 
142842006910SStanislaw Kardach program_mkex:
142942006910SStanislaw Kardach 	dev_info(rvu->dev, "Using %s mkex profile\n", rvu->kpu.mkex->name);
143042006910SStanislaw Kardach 	/* Program selected mkex profile */
143142006910SStanislaw Kardach 	npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mkex);
143223705adbSVamsi Attunuru 	if (mkex_prfl_addr)
14335d16250bSHarman Kalra 		iounmap(mkex_prfl_addr);
143423705adbSVamsi Attunuru }
143523705adbSVamsi Attunuru 
npc_config_kpuaction(struct rvu * rvu,int blkaddr,const struct npc_kpu_profile_action * kpuaction,int kpu,int entry,bool pkind)143623923ea4SSunil Goutham static void npc_config_kpuaction(struct rvu *rvu, int blkaddr,
14374a681bf3SRikard Falkeborn 				 const struct npc_kpu_profile_action *kpuaction,
143823923ea4SSunil Goutham 				 int kpu, int entry, bool pkind)
143923923ea4SSunil Goutham {
144023923ea4SSunil Goutham 	struct npc_kpu_action0 action0 = {0};
144123923ea4SSunil Goutham 	struct npc_kpu_action1 action1 = {0};
144223923ea4SSunil Goutham 	u64 reg;
144323923ea4SSunil Goutham 
144423923ea4SSunil Goutham 	action1.errlev = kpuaction->errlev;
144523923ea4SSunil Goutham 	action1.errcode = kpuaction->errcode;
144623923ea4SSunil Goutham 	action1.dp0_offset = kpuaction->dp0_offset;
144723923ea4SSunil Goutham 	action1.dp1_offset = kpuaction->dp1_offset;
144823923ea4SSunil Goutham 	action1.dp2_offset = kpuaction->dp2_offset;
144923923ea4SSunil Goutham 
145023923ea4SSunil Goutham 	if (pkind)
145123923ea4SSunil Goutham 		reg = NPC_AF_PKINDX_ACTION1(entry);
145223923ea4SSunil Goutham 	else
145323923ea4SSunil Goutham 		reg = NPC_AF_KPUX_ENTRYX_ACTION1(kpu, entry);
145423923ea4SSunil Goutham 
145523923ea4SSunil Goutham 	rvu_write64(rvu, blkaddr, reg, *(u64 *)&action1);
145623923ea4SSunil Goutham 
145723923ea4SSunil Goutham 	action0.byp_count = kpuaction->bypass_count;
145823923ea4SSunil Goutham 	action0.capture_ena = kpuaction->cap_ena;
145923923ea4SSunil Goutham 	action0.parse_done = kpuaction->parse_done;
146023923ea4SSunil Goutham 	action0.next_state = kpuaction->next_state;
146123923ea4SSunil Goutham 	action0.capture_lid = kpuaction->lid;
146223923ea4SSunil Goutham 	action0.capture_ltype = kpuaction->ltype;
146323923ea4SSunil Goutham 	action0.capture_flags = kpuaction->flags;
146423923ea4SSunil Goutham 	action0.ptr_advance = kpuaction->ptr_advance;
146523923ea4SSunil Goutham 	action0.var_len_offset = kpuaction->offset;
146623923ea4SSunil Goutham 	action0.var_len_mask = kpuaction->mask;
146723923ea4SSunil Goutham 	action0.var_len_right = kpuaction->right;
146823923ea4SSunil Goutham 	action0.var_len_shift = kpuaction->shift;
146923923ea4SSunil Goutham 
147023923ea4SSunil Goutham 	if (pkind)
147123923ea4SSunil Goutham 		reg = NPC_AF_PKINDX_ACTION0(entry);
147223923ea4SSunil Goutham 	else
147323923ea4SSunil Goutham 		reg = NPC_AF_KPUX_ENTRYX_ACTION0(kpu, entry);
147423923ea4SSunil Goutham 
147523923ea4SSunil Goutham 	rvu_write64(rvu, blkaddr, reg, *(u64 *)&action0);
147623923ea4SSunil Goutham }
147723923ea4SSunil Goutham 
npc_config_kpucam(struct rvu * rvu,int blkaddr,const struct npc_kpu_profile_cam * kpucam,int kpu,int entry)147823923ea4SSunil Goutham static void npc_config_kpucam(struct rvu *rvu, int blkaddr,
14794a681bf3SRikard Falkeborn 			      const struct npc_kpu_profile_cam *kpucam,
148023923ea4SSunil Goutham 			      int kpu, int entry)
148123923ea4SSunil Goutham {
148223923ea4SSunil Goutham 	struct npc_kpu_cam cam0 = {0};
148323923ea4SSunil Goutham 	struct npc_kpu_cam cam1 = {0};
148423923ea4SSunil Goutham 
148523923ea4SSunil Goutham 	cam1.state = kpucam->state & kpucam->state_mask;
148623923ea4SSunil Goutham 	cam1.dp0_data = kpucam->dp0 & kpucam->dp0_mask;
148723923ea4SSunil Goutham 	cam1.dp1_data = kpucam->dp1 & kpucam->dp1_mask;
148823923ea4SSunil Goutham 	cam1.dp2_data = kpucam->dp2 & kpucam->dp2_mask;
148923923ea4SSunil Goutham 
149023923ea4SSunil Goutham 	cam0.state = ~kpucam->state & kpucam->state_mask;
149123923ea4SSunil Goutham 	cam0.dp0_data = ~kpucam->dp0 & kpucam->dp0_mask;
149223923ea4SSunil Goutham 	cam0.dp1_data = ~kpucam->dp1 & kpucam->dp1_mask;
149323923ea4SSunil Goutham 	cam0.dp2_data = ~kpucam->dp2 & kpucam->dp2_mask;
149423923ea4SSunil Goutham 
149523923ea4SSunil Goutham 	rvu_write64(rvu, blkaddr,
149623923ea4SSunil Goutham 		    NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 0), *(u64 *)&cam0);
149723923ea4SSunil Goutham 	rvu_write64(rvu, blkaddr,
149823923ea4SSunil Goutham 		    NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 1), *(u64 *)&cam1);
149923923ea4SSunil Goutham }
150023923ea4SSunil Goutham 
enable_mask(int count)150123923ea4SSunil Goutham static inline u64 enable_mask(int count)
150223923ea4SSunil Goutham {
150323923ea4SSunil Goutham 	return (((count) < 64) ? ~(BIT_ULL(count) - 1) : (0x00ULL));
150423923ea4SSunil Goutham }
150523923ea4SSunil Goutham 
npc_program_kpu_profile(struct rvu * rvu,int blkaddr,int kpu,const struct npc_kpu_profile * profile)150623923ea4SSunil Goutham static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
15074a681bf3SRikard Falkeborn 				    const struct npc_kpu_profile *profile)
150823923ea4SSunil Goutham {
150923923ea4SSunil Goutham 	int entry, num_entries, max_entries;
15103a724415SStanislaw Kardach 	u64 entry_mask;
151123923ea4SSunil Goutham 
151223923ea4SSunil Goutham 	if (profile->cam_entries != profile->action_entries) {
151323923ea4SSunil Goutham 		dev_err(rvu->dev,
151423923ea4SSunil Goutham 			"KPU%d: CAM and action entries [%d != %d] not equal\n",
151523923ea4SSunil Goutham 			kpu, profile->cam_entries, profile->action_entries);
151623923ea4SSunil Goutham 	}
151723923ea4SSunil Goutham 
15181c1935c9SSubbaraya Sundeep 	max_entries = rvu->hw->npc_kpu_entries;
151923923ea4SSunil Goutham 
152023923ea4SSunil Goutham 	/* Program CAM match entries for previous KPU extracted data */
152123923ea4SSunil Goutham 	num_entries = min_t(int, profile->cam_entries, max_entries);
152223923ea4SSunil Goutham 	for (entry = 0; entry < num_entries; entry++)
152323923ea4SSunil Goutham 		npc_config_kpucam(rvu, blkaddr,
152423923ea4SSunil Goutham 				  &profile->cam[entry], kpu, entry);
152523923ea4SSunil Goutham 
152623923ea4SSunil Goutham 	/* Program this KPU's actions */
152723923ea4SSunil Goutham 	num_entries = min_t(int, profile->action_entries, max_entries);
152823923ea4SSunil Goutham 	for (entry = 0; entry < num_entries; entry++)
152923923ea4SSunil Goutham 		npc_config_kpuaction(rvu, blkaddr, &profile->action[entry],
153023923ea4SSunil Goutham 				     kpu, entry, false);
153123923ea4SSunil Goutham 
153223923ea4SSunil Goutham 	/* Enable all programmed entries */
153323923ea4SSunil Goutham 	num_entries = min_t(int, profile->action_entries, profile->cam_entries);
15343a724415SStanislaw Kardach 	entry_mask = enable_mask(num_entries);
15353a724415SStanislaw Kardach 	/* Disable first KPU_MAX_CST_ENT entries for built-in profile */
15363a724415SStanislaw Kardach 	if (!rvu->kpu.custom)
15373a724415SStanislaw Kardach 		entry_mask |= GENMASK_ULL(KPU_MAX_CST_ENT - 1, 0);
153823923ea4SSunil Goutham 	rvu_write64(rvu, blkaddr,
15393a724415SStanislaw Kardach 		    NPC_AF_KPUX_ENTRY_DISX(kpu, 0), entry_mask);
154023923ea4SSunil Goutham 	if (num_entries > 64) {
154123923ea4SSunil Goutham 		rvu_write64(rvu, blkaddr,
154223923ea4SSunil Goutham 			    NPC_AF_KPUX_ENTRY_DISX(kpu, 1),
154323923ea4SSunil Goutham 			    enable_mask(num_entries - 64));
154423923ea4SSunil Goutham 	}
154523923ea4SSunil Goutham 
154623923ea4SSunil Goutham 	/* Enable this KPU */
154723923ea4SSunil Goutham 	rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(kpu), 0x01);
154823923ea4SSunil Goutham }
154923923ea4SSunil Goutham 
npc_prepare_default_kpu(struct npc_kpu_profile_adapter * profile)155042006910SStanislaw Kardach static int npc_prepare_default_kpu(struct npc_kpu_profile_adapter *profile)
155142006910SStanislaw Kardach {
15523a724415SStanislaw Kardach 	profile->custom = 0;
155342006910SStanislaw Kardach 	profile->name = def_pfl_name;
155442006910SStanislaw Kardach 	profile->version = NPC_KPU_PROFILE_VER;
155542006910SStanislaw Kardach 	profile->ikpu = ikpu_action_entries;
155642006910SStanislaw Kardach 	profile->pkinds = ARRAY_SIZE(ikpu_action_entries);
155742006910SStanislaw Kardach 	profile->kpu = npc_kpu_profiles;
155842006910SStanislaw Kardach 	profile->kpus = ARRAY_SIZE(npc_kpu_profiles);
155942006910SStanislaw Kardach 	profile->lt_def = &npc_lt_defaults;
156042006910SStanislaw Kardach 	profile->mkex = &npc_mkex_default;
156156d9f5fdSRatheesh Kannoth 	profile->mkex_hash = &npc_mkex_hash_default;
156242006910SStanislaw Kardach 
156342006910SStanislaw Kardach 	return 0;
156442006910SStanislaw Kardach }
156542006910SStanislaw Kardach 
npc_apply_custom_kpu(struct rvu * rvu,struct npc_kpu_profile_adapter * profile)15663a724415SStanislaw Kardach static int npc_apply_custom_kpu(struct rvu *rvu,
15673a724415SStanislaw Kardach 				struct npc_kpu_profile_adapter *profile)
15683a724415SStanislaw Kardach {
15693a724415SStanislaw Kardach 	size_t hdr_sz = sizeof(struct npc_kpu_profile_fwdata), offset = 0;
15703a724415SStanislaw Kardach 	struct npc_kpu_profile_fwdata *fw = rvu->kpu_fwdata;
15713a724415SStanislaw Kardach 	struct npc_kpu_profile_action *action;
15723a724415SStanislaw Kardach 	struct npc_kpu_profile_cam *cam;
15733a724415SStanislaw Kardach 	struct npc_kpu_fwdata *fw_kpu;
15743a724415SStanislaw Kardach 	int entries;
15753a724415SStanislaw Kardach 	u16 kpu, entry;
15763a724415SStanislaw Kardach 
15773a724415SStanislaw Kardach 	if (rvu->kpu_fwdata_sz < hdr_sz) {
15783a724415SStanislaw Kardach 		dev_warn(rvu->dev, "Invalid KPU profile size\n");
15793a724415SStanislaw Kardach 		return -EINVAL;
15803a724415SStanislaw Kardach 	}
15813a724415SStanislaw Kardach 	if (le64_to_cpu(fw->signature) != KPU_SIGN) {
15823a724415SStanislaw Kardach 		dev_warn(rvu->dev, "Invalid KPU profile signature %llx\n",
15833a724415SStanislaw Kardach 			 fw->signature);
15843a724415SStanislaw Kardach 		return -EINVAL;
15853a724415SStanislaw Kardach 	}
15863a724415SStanislaw Kardach 	/* Verify if the using known profile structure */
15873a724415SStanislaw Kardach 	if (NPC_KPU_VER_MAJ(profile->version) >
15883a724415SStanislaw Kardach 	    NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER)) {
15893a724415SStanislaw Kardach 		dev_warn(rvu->dev, "Not supported Major version: %d > %d\n",
15903a724415SStanislaw Kardach 			 NPC_KPU_VER_MAJ(profile->version),
15913a724415SStanislaw Kardach 			 NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER));
15923a724415SStanislaw Kardach 		return -EINVAL;
15933a724415SStanislaw Kardach 	}
1594c87e6b13SHarman Kalra 	/* Verify if profile is aligned with the required kernel changes */
1595c87e6b13SHarman Kalra 	if (NPC_KPU_VER_MIN(profile->version) <
1596c87e6b13SHarman Kalra 	    NPC_KPU_VER_MIN(NPC_KPU_PROFILE_VER)) {
1597c87e6b13SHarman Kalra 		dev_warn(rvu->dev,
1598b934b6d1SColin Ian King 			 "Invalid KPU profile version: %d.%d.%d expected version <= %d.%d.%d\n",
1599c87e6b13SHarman Kalra 			 NPC_KPU_VER_MAJ(profile->version),
1600c87e6b13SHarman Kalra 			 NPC_KPU_VER_MIN(profile->version),
1601c87e6b13SHarman Kalra 			 NPC_KPU_VER_PATCH(profile->version),
1602c87e6b13SHarman Kalra 			 NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER),
1603c87e6b13SHarman Kalra 			 NPC_KPU_VER_MIN(NPC_KPU_PROFILE_VER),
1604c87e6b13SHarman Kalra 			 NPC_KPU_VER_PATCH(NPC_KPU_PROFILE_VER));
1605c87e6b13SHarman Kalra 		return -EINVAL;
1606c87e6b13SHarman Kalra 	}
16073a724415SStanislaw Kardach 	/* Verify if profile fits the HW */
16083a724415SStanislaw Kardach 	if (fw->kpus > profile->kpus) {
16093a724415SStanislaw Kardach 		dev_warn(rvu->dev, "Not enough KPUs: %d > %ld\n", fw->kpus,
16103a724415SStanislaw Kardach 			 profile->kpus);
16113a724415SStanislaw Kardach 		return -EINVAL;
16123a724415SStanislaw Kardach 	}
16133a724415SStanislaw Kardach 
16143a724415SStanislaw Kardach 	profile->custom = 1;
16153a724415SStanislaw Kardach 	profile->name = fw->name;
16163a724415SStanislaw Kardach 	profile->version = le64_to_cpu(fw->version);
16173a724415SStanislaw Kardach 	profile->mkex = &fw->mkex;
16183a724415SStanislaw Kardach 	profile->lt_def = &fw->lt_def;
16193a724415SStanislaw Kardach 
16203a724415SStanislaw Kardach 	for (kpu = 0; kpu < fw->kpus; kpu++) {
16213a724415SStanislaw Kardach 		fw_kpu = (struct npc_kpu_fwdata *)(fw->data + offset);
16223a724415SStanislaw Kardach 		if (fw_kpu->entries > KPU_MAX_CST_ENT)
16233a724415SStanislaw Kardach 			dev_warn(rvu->dev,
16243a724415SStanislaw Kardach 				 "Too many custom entries on KPU%d: %d > %d\n",
16253a724415SStanislaw Kardach 				 kpu, fw_kpu->entries, KPU_MAX_CST_ENT);
16263a724415SStanislaw Kardach 		entries = min(fw_kpu->entries, KPU_MAX_CST_ENT);
16273a724415SStanislaw Kardach 		cam = (struct npc_kpu_profile_cam *)fw_kpu->data;
16283a724415SStanislaw Kardach 		offset += sizeof(*fw_kpu) + fw_kpu->entries * sizeof(*cam);
16293a724415SStanislaw Kardach 		action = (struct npc_kpu_profile_action *)(fw->data + offset);
16303a724415SStanislaw Kardach 		offset += fw_kpu->entries * sizeof(*action);
16313a724415SStanislaw Kardach 		if (rvu->kpu_fwdata_sz < hdr_sz + offset) {
16323a724415SStanislaw Kardach 			dev_warn(rvu->dev,
16333a724415SStanislaw Kardach 				 "Profile size mismatch on KPU%i parsing.\n",
16343a724415SStanislaw Kardach 				 kpu + 1);
16353a724415SStanislaw Kardach 			return -EINVAL;
16363a724415SStanislaw Kardach 		}
16373a724415SStanislaw Kardach 		for (entry = 0; entry < entries; entry++) {
16383a724415SStanislaw Kardach 			profile->kpu[kpu].cam[entry] = cam[entry];
16393a724415SStanislaw Kardach 			profile->kpu[kpu].action[entry] = action[entry];
16403a724415SStanislaw Kardach 		}
16413a724415SStanislaw Kardach 	}
16423a724415SStanislaw Kardach 
16433a724415SStanislaw Kardach 	return 0;
16443a724415SStanislaw Kardach }
16453a724415SStanislaw Kardach 
npc_load_kpu_prfl_img(struct rvu * rvu,void __iomem * prfl_addr,u64 prfl_sz,const char * kpu_profile)164611c730bfSHarman Kalra static int npc_load_kpu_prfl_img(struct rvu *rvu, void __iomem *prfl_addr,
164711c730bfSHarman Kalra 				 u64 prfl_sz, const char *kpu_profile)
164811c730bfSHarman Kalra {
164911c730bfSHarman Kalra 	struct npc_kpu_profile_fwdata *kpu_data = NULL;
165011c730bfSHarman Kalra 	int rc = -EINVAL;
165111c730bfSHarman Kalra 
165211c730bfSHarman Kalra 	kpu_data = (struct npc_kpu_profile_fwdata __force *)prfl_addr;
165311c730bfSHarman Kalra 	if (le64_to_cpu(kpu_data->signature) == KPU_SIGN &&
165411c730bfSHarman Kalra 	    !strncmp(kpu_data->name, kpu_profile, KPU_NAME_LEN)) {
165511c730bfSHarman Kalra 		dev_info(rvu->dev, "Loading KPU profile from firmware db: %s\n",
165611c730bfSHarman Kalra 			 kpu_profile);
165711c730bfSHarman Kalra 		rvu->kpu_fwdata = kpu_data;
165811c730bfSHarman Kalra 		rvu->kpu_fwdata_sz = prfl_sz;
165911c730bfSHarman Kalra 		rvu->kpu_prfl_addr = prfl_addr;
166011c730bfSHarman Kalra 		rc = 0;
166111c730bfSHarman Kalra 	}
166211c730bfSHarman Kalra 
166311c730bfSHarman Kalra 	return rc;
166411c730bfSHarman Kalra }
166511c730bfSHarman Kalra 
npc_fwdb_detect_load_prfl_img(struct rvu * rvu,uint64_t prfl_sz,const char * kpu_profile)166611c730bfSHarman Kalra static int npc_fwdb_detect_load_prfl_img(struct rvu *rvu, uint64_t prfl_sz,
166711c730bfSHarman Kalra 					 const char *kpu_profile)
166811c730bfSHarman Kalra {
166911c730bfSHarman Kalra 	struct npc_coalesced_kpu_prfl *img_data = NULL;
167011c730bfSHarman Kalra 	int i = 0, rc = -EINVAL;
167111c730bfSHarman Kalra 	void __iomem *kpu_prfl_addr;
1672b08b0c7aSHariprasad Kelam 	u32 offset;
167311c730bfSHarman Kalra 
167411c730bfSHarman Kalra 	img_data = (struct npc_coalesced_kpu_prfl __force *)rvu->kpu_prfl_addr;
167511c730bfSHarman Kalra 	if (le64_to_cpu(img_data->signature) == KPU_SIGN &&
167611c730bfSHarman Kalra 	    !strncmp(img_data->name, kpu_profile, KPU_NAME_LEN)) {
167711c730bfSHarman Kalra 		/* Loaded profile is a single KPU profile. */
167811c730bfSHarman Kalra 		rc = npc_load_kpu_prfl_img(rvu, rvu->kpu_prfl_addr,
167911c730bfSHarman Kalra 					   prfl_sz, kpu_profile);
168011c730bfSHarman Kalra 		goto done;
168111c730bfSHarman Kalra 	}
168211c730bfSHarman Kalra 
168311c730bfSHarman Kalra 	/* Loaded profile is coalesced image, offset of first KPU profile.*/
168411c730bfSHarman Kalra 	offset = offsetof(struct npc_coalesced_kpu_prfl, prfl_sz) +
168511c730bfSHarman Kalra 		(img_data->num_prfl * sizeof(uint16_t));
168611c730bfSHarman Kalra 	/* Check if mapped image is coalesced image. */
168711c730bfSHarman Kalra 	while (i < img_data->num_prfl) {
168811c730bfSHarman Kalra 		/* Profile image offsets are rounded up to next 8 multiple.*/
168911c730bfSHarman Kalra 		offset = ALIGN_8B_CEIL(offset);
169011c730bfSHarman Kalra 		kpu_prfl_addr = (void __iomem *)((uintptr_t)rvu->kpu_prfl_addr +
169111c730bfSHarman Kalra 					 offset);
169211c730bfSHarman Kalra 		rc = npc_load_kpu_prfl_img(rvu, kpu_prfl_addr,
169311c730bfSHarman Kalra 					   img_data->prfl_sz[i], kpu_profile);
169411c730bfSHarman Kalra 		if (!rc)
169511c730bfSHarman Kalra 			break;
169611c730bfSHarman Kalra 		/* Calculating offset of profile image based on profile size.*/
169711c730bfSHarman Kalra 		offset += img_data->prfl_sz[i];
169811c730bfSHarman Kalra 		i++;
169911c730bfSHarman Kalra 	}
170011c730bfSHarman Kalra done:
170111c730bfSHarman Kalra 	return rc;
170211c730bfSHarman Kalra }
170311c730bfSHarman Kalra 
npc_load_kpu_profile_fwdb(struct rvu * rvu,const char * kpu_profile)17045d16250bSHarman Kalra static int npc_load_kpu_profile_fwdb(struct rvu *rvu, const char *kpu_profile)
17055d16250bSHarman Kalra {
170611c730bfSHarman Kalra 	int ret = -EINVAL;
17075d16250bSHarman Kalra 	u64 prfl_sz;
17085d16250bSHarman Kalra 
17095d16250bSHarman Kalra 	/* Setting up the mapping for NPC profile image */
17105d16250bSHarman Kalra 	ret = npc_fwdb_prfl_img_map(rvu, &rvu->kpu_prfl_addr, &prfl_sz);
17115d16250bSHarman Kalra 	if (ret < 0)
171211c730bfSHarman Kalra 		goto done;
17135d16250bSHarman Kalra 
171411c730bfSHarman Kalra 	/* Detect if profile is coalesced or single KPU profile and load */
171511c730bfSHarman Kalra 	ret = npc_fwdb_detect_load_prfl_img(rvu, prfl_sz, kpu_profile);
171611c730bfSHarman Kalra 	if (ret == 0)
171711c730bfSHarman Kalra 		goto done;
17185d16250bSHarman Kalra 
17195d16250bSHarman Kalra 	/* Cleaning up if KPU profile image from fwdata is not valid. */
17205d16250bSHarman Kalra 	if (rvu->kpu_prfl_addr) {
17215d16250bSHarman Kalra 		iounmap(rvu->kpu_prfl_addr);
17225d16250bSHarman Kalra 		rvu->kpu_prfl_addr = NULL;
17235d16250bSHarman Kalra 		rvu->kpu_fwdata_sz = 0;
17245d16250bSHarman Kalra 		rvu->kpu_fwdata = NULL;
17255d16250bSHarman Kalra 	}
17265d16250bSHarman Kalra 
172711c730bfSHarman Kalra done:
172811c730bfSHarman Kalra 	return ret;
17295d16250bSHarman Kalra }
17305d16250bSHarman Kalra 
npc_load_kpu_profile(struct rvu * rvu)173142006910SStanislaw Kardach static void npc_load_kpu_profile(struct rvu *rvu)
173242006910SStanislaw Kardach {
173342006910SStanislaw Kardach 	struct npc_kpu_profile_adapter *profile = &rvu->kpu;
17343a724415SStanislaw Kardach 	const char *kpu_profile = rvu->kpu_pfl_name;
17353a724415SStanislaw Kardach 	const struct firmware *fw = NULL;
1736c87e6b13SHarman Kalra 	bool retry_fwdb = false;
173742006910SStanislaw Kardach 
17383a724415SStanislaw Kardach 	/* If user not specified profile customization */
17393a724415SStanislaw Kardach 	if (!strncmp(kpu_profile, def_pfl_name, KPU_NAME_LEN))
17403a724415SStanislaw Kardach 		goto revert_to_default;
17413a724415SStanislaw Kardach 	/* First prepare default KPU, then we'll customize top entries. */
17423a724415SStanislaw Kardach 	npc_prepare_default_kpu(profile);
17433a724415SStanislaw Kardach 
17445d16250bSHarman Kalra 	/* Order of preceedence for load loading NPC profile (high to low)
17455d16250bSHarman Kalra 	 * Firmware binary in filesystem.
17465d16250bSHarman Kalra 	 * Firmware database method.
17475d16250bSHarman Kalra 	 * Default KPU profile.
17485d16250bSHarman Kalra 	 */
1749cf243762SHarman Kalra 	if (!request_firmware_direct(&fw, kpu_profile, rvu->dev)) {
17503a724415SStanislaw Kardach 		dev_info(rvu->dev, "Loading KPU profile from firmware: %s\n",
17513a724415SStanislaw Kardach 			 kpu_profile);
17523a724415SStanislaw Kardach 		rvu->kpu_fwdata = kzalloc(fw->size, GFP_KERNEL);
17533a724415SStanislaw Kardach 		if (rvu->kpu_fwdata) {
17543a724415SStanislaw Kardach 			memcpy(rvu->kpu_fwdata, fw->data, fw->size);
17553a724415SStanislaw Kardach 			rvu->kpu_fwdata_sz = fw->size;
17563a724415SStanislaw Kardach 		}
17573a724415SStanislaw Kardach 		release_firmware(fw);
1758c87e6b13SHarman Kalra 		retry_fwdb = true;
17595d16250bSHarman Kalra 		goto program_kpu;
17603a724415SStanislaw Kardach 	}
17613a724415SStanislaw Kardach 
17625d16250bSHarman Kalra load_image_fwdb:
17635d16250bSHarman Kalra 	/* Loading the KPU profile using firmware database */
17645d16250bSHarman Kalra 	if (npc_load_kpu_profile_fwdb(rvu, kpu_profile))
17655d16250bSHarman Kalra 		goto revert_to_default;
17665d16250bSHarman Kalra 
17675d16250bSHarman Kalra program_kpu:
17683a724415SStanislaw Kardach 	/* Apply profile customization if firmware was loaded. */
17693a724415SStanislaw Kardach 	if (!rvu->kpu_fwdata_sz || npc_apply_custom_kpu(rvu, profile)) {
17705d16250bSHarman Kalra 		/* If image from firmware filesystem fails to load or invalid
17715d16250bSHarman Kalra 		 * retry with firmware database method.
17725d16250bSHarman Kalra 		 */
17735d16250bSHarman Kalra 		if (rvu->kpu_fwdata || rvu->kpu_fwdata_sz) {
17745d16250bSHarman Kalra 			/* Loading image from firmware database failed. */
17755d16250bSHarman Kalra 			if (rvu->kpu_prfl_addr) {
17765d16250bSHarman Kalra 				iounmap(rvu->kpu_prfl_addr);
17775d16250bSHarman Kalra 				rvu->kpu_prfl_addr = NULL;
17785d16250bSHarman Kalra 			} else {
17795d16250bSHarman Kalra 				kfree(rvu->kpu_fwdata);
17805d16250bSHarman Kalra 			}
17815d16250bSHarman Kalra 			rvu->kpu_fwdata = NULL;
17825d16250bSHarman Kalra 			rvu->kpu_fwdata_sz = 0;
1783c87e6b13SHarman Kalra 			if (retry_fwdb) {
1784c87e6b13SHarman Kalra 				retry_fwdb = false;
17855d16250bSHarman Kalra 				goto load_image_fwdb;
17865d16250bSHarman Kalra 			}
1787c87e6b13SHarman Kalra 		}
17885d16250bSHarman Kalra 
17893a724415SStanislaw Kardach 		dev_warn(rvu->dev,
17903a724415SStanislaw Kardach 			 "Can't load KPU profile %s. Using default.\n",
17913a724415SStanislaw Kardach 			 kpu_profile);
17923a724415SStanislaw Kardach 		kfree(rvu->kpu_fwdata);
17933a724415SStanislaw Kardach 		rvu->kpu_fwdata = NULL;
17943a724415SStanislaw Kardach 		goto revert_to_default;
17953a724415SStanislaw Kardach 	}
17963a724415SStanislaw Kardach 
17973a724415SStanislaw Kardach 	dev_info(rvu->dev, "Using custom profile '%s', version %d.%d.%d\n",
17983a724415SStanislaw Kardach 		 profile->name, NPC_KPU_VER_MAJ(profile->version),
17993a724415SStanislaw Kardach 		 NPC_KPU_VER_MIN(profile->version),
18003a724415SStanislaw Kardach 		 NPC_KPU_VER_PATCH(profile->version));
18013a724415SStanislaw Kardach 
18023a724415SStanislaw Kardach 	return;
18033a724415SStanislaw Kardach 
18043a724415SStanislaw Kardach revert_to_default:
180542006910SStanislaw Kardach 	npc_prepare_default_kpu(profile);
180642006910SStanislaw Kardach }
180742006910SStanislaw Kardach 
npc_parser_profile_init(struct rvu * rvu,int blkaddr)180823923ea4SSunil Goutham static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
180923923ea4SSunil Goutham {
181023923ea4SSunil Goutham 	struct rvu_hwinfo *hw = rvu->hw;
181123923ea4SSunil Goutham 	int num_pkinds, num_kpus, idx;
181223923ea4SSunil Goutham 
181323923ea4SSunil Goutham 	/* Disable all KPUs and their entries */
181423923ea4SSunil Goutham 	for (idx = 0; idx < hw->npc_kpus; idx++) {
181523923ea4SSunil Goutham 		rvu_write64(rvu, blkaddr,
181623923ea4SSunil Goutham 			    NPC_AF_KPUX_ENTRY_DISX(idx, 0), ~0ULL);
181723923ea4SSunil Goutham 		rvu_write64(rvu, blkaddr,
181823923ea4SSunil Goutham 			    NPC_AF_KPUX_ENTRY_DISX(idx, 1), ~0ULL);
181923923ea4SSunil Goutham 		rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx), 0x00);
182023923ea4SSunil Goutham 	}
182123923ea4SSunil Goutham 
182242006910SStanislaw Kardach 	/* Load and customize KPU profile. */
182342006910SStanislaw Kardach 	npc_load_kpu_profile(rvu);
182442006910SStanislaw Kardach 
182523923ea4SSunil Goutham 	/* First program IKPU profile i.e PKIND configs.
182623923ea4SSunil Goutham 	 * Check HW max count to avoid configuring junk or
182723923ea4SSunil Goutham 	 * writing to unsupported CSR addresses.
182823923ea4SSunil Goutham 	 */
182942006910SStanislaw Kardach 	num_pkinds = rvu->kpu.pkinds;
1830ac059d16SGeetha sowjanya 	num_pkinds = min_t(int, hw->npc_pkinds, num_pkinds);
183123923ea4SSunil Goutham 
183223923ea4SSunil Goutham 	for (idx = 0; idx < num_pkinds; idx++)
183342006910SStanislaw Kardach 		npc_config_kpuaction(rvu, blkaddr, &rvu->kpu.ikpu[idx], 0, idx, true);
183423923ea4SSunil Goutham 
183523923ea4SSunil Goutham 	/* Program KPU CAM and Action profiles */
183642006910SStanislaw Kardach 	num_kpus = rvu->kpu.kpus;
183723923ea4SSunil Goutham 	num_kpus = min_t(int, hw->npc_kpus, num_kpus);
183823923ea4SSunil Goutham 
183923923ea4SSunil Goutham 	for (idx = 0; idx < num_kpus; idx++)
184042006910SStanislaw Kardach 		npc_program_kpu_profile(rvu, blkaddr, idx, &rvu->kpu.kpu[idx]);
184123923ea4SSunil Goutham }
184223923ea4SSunil Goutham 
npc_mcam_rsrcs_init(struct rvu * rvu,int blkaddr)1843fefefd99SSunil Goutham static int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
1844fefefd99SSunil Goutham {
1845fefefd99SSunil Goutham 	int nixlf_count = rvu_get_nixlf_count(rvu);
1846fefefd99SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
1847f9274958SSunil Goutham 	int rsvd, err;
1848cb7a6b3bSSubbaraya Sundeep 	u16 index;
1849cb7a6b3bSSubbaraya Sundeep 	int cntr;
1850fefefd99SSunil Goutham 	u64 cfg;
1851fefefd99SSunil Goutham 
1852fefefd99SSunil Goutham 	/* Actual number of MCAM entries vary by entry size */
1853fefefd99SSunil Goutham 	cfg = (rvu_read64(rvu, blkaddr,
1854fefefd99SSunil Goutham 			  NPC_AF_INTFX_KEX_CFG(0)) >> 32) & 0x07;
1855fefefd99SSunil Goutham 	mcam->total_entries = (mcam->banks / BIT_ULL(cfg)) * mcam->banksize;
1856fefefd99SSunil Goutham 	mcam->keysize = cfg;
1857fefefd99SSunil Goutham 
1858fefefd99SSunil Goutham 	/* Number of banks combined per MCAM entry */
1859fefefd99SSunil Goutham 	if (cfg == NPC_MCAM_KEY_X4)
1860fefefd99SSunil Goutham 		mcam->banks_per_entry = 4;
1861fefefd99SSunil Goutham 	else if (cfg == NPC_MCAM_KEY_X2)
1862fefefd99SSunil Goutham 		mcam->banks_per_entry = 2;
1863fefefd99SSunil Goutham 	else
1864fefefd99SSunil Goutham 		mcam->banks_per_entry = 1;
1865fefefd99SSunil Goutham 
1866fefefd99SSunil Goutham 	/* Reserve one MCAM entry for each of the NIX LF to
1867fefefd99SSunil Goutham 	 * guarantee space to install default matching DMAC rule.
1868fefefd99SSunil Goutham 	 * Also reserve 2 MCAM entries for each PF for default
1869fefefd99SSunil Goutham 	 * channel based matching or 'bcast & promisc' matching to
1870fefefd99SSunil Goutham 	 * support BCAST and PROMISC modes of operation for PFs.
1871fefefd99SSunil Goutham 	 * PF0 is excluded.
1872fefefd99SSunil Goutham 	 */
1873fefefd99SSunil Goutham 	rsvd = (nixlf_count * RSVD_MCAM_ENTRIES_PER_NIXLF) +
1874fefefd99SSunil Goutham 		((rvu->hw->total_pfs - 1) * RSVD_MCAM_ENTRIES_PER_PF);
1875fefefd99SSunil Goutham 	if (mcam->total_entries <= rsvd) {
1876fefefd99SSunil Goutham 		dev_warn(rvu->dev,
1877fefefd99SSunil Goutham 			 "Insufficient NPC MCAM size %d for pkt I/O, exiting\n",
1878fefefd99SSunil Goutham 			 mcam->total_entries);
1879fefefd99SSunil Goutham 		return -ENOMEM;
1880fefefd99SSunil Goutham 	}
1881fefefd99SSunil Goutham 
1882f9274958SSunil Goutham 	mcam->bmap_entries = mcam->total_entries - rsvd;
1883f9274958SSunil Goutham 	mcam->nixlf_offset = mcam->bmap_entries;
1884fefefd99SSunil Goutham 	mcam->pf_offset = mcam->nixlf_offset + nixlf_count;
1885fefefd99SSunil Goutham 
1886f9274958SSunil Goutham 	/* Allocate bitmaps for managing MCAM entries */
1887f9274958SSunil Goutham 	mcam->bmap = devm_kcalloc(rvu->dev, BITS_TO_LONGS(mcam->bmap_entries),
1888f9274958SSunil Goutham 				  sizeof(long), GFP_KERNEL);
1889f9274958SSunil Goutham 	if (!mcam->bmap)
1890f9274958SSunil Goutham 		return -ENOMEM;
1891f9274958SSunil Goutham 
1892f9274958SSunil Goutham 	mcam->bmap_reverse = devm_kcalloc(rvu->dev,
1893f9274958SSunil Goutham 					  BITS_TO_LONGS(mcam->bmap_entries),
1894f9274958SSunil Goutham 					  sizeof(long), GFP_KERNEL);
1895f9274958SSunil Goutham 	if (!mcam->bmap_reverse)
1896f9274958SSunil Goutham 		return -ENOMEM;
1897f9274958SSunil Goutham 
1898f9274958SSunil Goutham 	mcam->bmap_fcnt = mcam->bmap_entries;
1899f9274958SSunil Goutham 
1900f9274958SSunil Goutham 	/* Alloc memory for saving entry to RVU PFFUNC allocation mapping */
1901f9274958SSunil Goutham 	mcam->entry2pfvf_map = devm_kcalloc(rvu->dev, mcam->bmap_entries,
1902f9274958SSunil Goutham 					    sizeof(u16), GFP_KERNEL);
1903f9274958SSunil Goutham 	if (!mcam->entry2pfvf_map)
1904f9274958SSunil Goutham 		return -ENOMEM;
1905f9274958SSunil Goutham 
1906f9274958SSunil Goutham 	/* Reserve 1/8th of MCAM entries at the bottom for low priority
1907f9274958SSunil Goutham 	 * allocations and another 1/8th at the top for high priority
1908f9274958SSunil Goutham 	 * allocations.
1909f9274958SSunil Goutham 	 */
1910f9274958SSunil Goutham 	mcam->lprio_count = mcam->bmap_entries / 8;
1911f9274958SSunil Goutham 	if (mcam->lprio_count > BITS_PER_LONG)
1912f9274958SSunil Goutham 		mcam->lprio_count = round_down(mcam->lprio_count,
1913f9274958SSunil Goutham 					       BITS_PER_LONG);
1914f9274958SSunil Goutham 	mcam->lprio_start = mcam->bmap_entries - mcam->lprio_count;
1915f9274958SSunil Goutham 	mcam->hprio_count = mcam->lprio_count;
1916f9274958SSunil Goutham 	mcam->hprio_end = mcam->hprio_count;
1917f9274958SSunil Goutham 
1918f9274958SSunil Goutham 	/* Allocate bitmap for managing MCAM counters and memory
1919f9274958SSunil Goutham 	 * for saving counter to RVU PFFUNC allocation mapping.
1920f9274958SSunil Goutham 	 */
1921f9274958SSunil Goutham 	err = rvu_alloc_bitmap(&mcam->counters);
1922f9274958SSunil Goutham 	if (err)
1923f9274958SSunil Goutham 		return err;
1924f9274958SSunil Goutham 
1925f9274958SSunil Goutham 	mcam->cntr2pfvf_map = devm_kcalloc(rvu->dev, mcam->counters.max,
1926f9274958SSunil Goutham 					   sizeof(u16), GFP_KERNEL);
1927f9274958SSunil Goutham 	if (!mcam->cntr2pfvf_map)
1928f9274958SSunil Goutham 		goto free_mem;
1929f9274958SSunil Goutham 
1930a958dd59SSunil Goutham 	/* Alloc memory for MCAM entry to counter mapping and for tracking
1931a958dd59SSunil Goutham 	 * counter's reference count.
1932a958dd59SSunil Goutham 	 */
1933a958dd59SSunil Goutham 	mcam->entry2cntr_map = devm_kcalloc(rvu->dev, mcam->bmap_entries,
1934a958dd59SSunil Goutham 					    sizeof(u16), GFP_KERNEL);
1935a958dd59SSunil Goutham 	if (!mcam->entry2cntr_map)
1936a958dd59SSunil Goutham 		goto free_mem;
1937a958dd59SSunil Goutham 
1938a958dd59SSunil Goutham 	mcam->cntr_refcnt = devm_kcalloc(rvu->dev, mcam->counters.max,
1939a958dd59SSunil Goutham 					 sizeof(u16), GFP_KERNEL);
1940a958dd59SSunil Goutham 	if (!mcam->cntr_refcnt)
1941a958dd59SSunil Goutham 		goto free_mem;
1942a958dd59SSunil Goutham 
194355307fcbSSubbaraya Sundeep 	/* Alloc memory for saving target device of mcam rule */
194455307fcbSSubbaraya Sundeep 	mcam->entry2target_pffunc = devm_kcalloc(rvu->dev, mcam->total_entries,
194555307fcbSSubbaraya Sundeep 						 sizeof(u16), GFP_KERNEL);
194655307fcbSSubbaraya Sundeep 	if (!mcam->entry2target_pffunc)
194755307fcbSSubbaraya Sundeep 		goto free_mem;
194855307fcbSSubbaraya Sundeep 
1949cb7a6b3bSSubbaraya Sundeep 	for (index = 0; index < mcam->bmap_entries; index++) {
1950cb7a6b3bSSubbaraya Sundeep 		mcam->entry2pfvf_map[index] = NPC_MCAM_INVALID_MAP;
1951cb7a6b3bSSubbaraya Sundeep 		mcam->entry2cntr_map[index] = NPC_MCAM_INVALID_MAP;
1952cb7a6b3bSSubbaraya Sundeep 	}
1953cb7a6b3bSSubbaraya Sundeep 
1954cb7a6b3bSSubbaraya Sundeep 	for (cntr = 0; cntr < mcam->counters.max; cntr++)
1955cb7a6b3bSSubbaraya Sundeep 		mcam->cntr2pfvf_map[cntr] = NPC_MCAM_INVALID_MAP;
1956cb7a6b3bSSubbaraya Sundeep 
19570964fc8fSStanislaw Kardach 	mutex_init(&mcam->lock);
1958fefefd99SSunil Goutham 
1959fefefd99SSunil Goutham 	return 0;
1960f9274958SSunil Goutham 
1961f9274958SSunil Goutham free_mem:
1962f9274958SSunil Goutham 	kfree(mcam->counters.bmap);
1963f9274958SSunil Goutham 	return -ENOMEM;
1964fefefd99SSunil Goutham }
1965fefefd99SSunil Goutham 
rvu_npc_hw_init(struct rvu * rvu,int blkaddr)19661c1935c9SSubbaraya Sundeep static void rvu_npc_hw_init(struct rvu *rvu, int blkaddr)
19671c1935c9SSubbaraya Sundeep {
19681c1935c9SSubbaraya Sundeep 	struct npc_pkind *pkind = &rvu->hw->pkind;
19691c1935c9SSubbaraya Sundeep 	struct npc_mcam *mcam = &rvu->hw->mcam;
19701c1935c9SSubbaraya Sundeep 	struct rvu_hwinfo *hw = rvu->hw;
19711c1935c9SSubbaraya Sundeep 	u64 npc_const, npc_const1;
19721c1935c9SSubbaraya Sundeep 	u64 npc_const2 = 0;
19731c1935c9SSubbaraya Sundeep 
19741c1935c9SSubbaraya Sundeep 	npc_const = rvu_read64(rvu, blkaddr, NPC_AF_CONST);
19751c1935c9SSubbaraya Sundeep 	npc_const1 = rvu_read64(rvu, blkaddr, NPC_AF_CONST1);
19761c1935c9SSubbaraya Sundeep 	if (npc_const1 & BIT_ULL(63))
19771c1935c9SSubbaraya Sundeep 		npc_const2 = rvu_read64(rvu, blkaddr, NPC_AF_CONST2);
19781c1935c9SSubbaraya Sundeep 
1979ac059d16SGeetha sowjanya 	pkind->rsrc.max = NPC_UNRESERVED_PKIND_COUNT;
1980ac059d16SGeetha sowjanya 	hw->npc_pkinds = (npc_const1 >> 12) & 0xFFULL;
19811c1935c9SSubbaraya Sundeep 	hw->npc_kpu_entries = npc_const1 & 0xFFFULL;
19821c1935c9SSubbaraya Sundeep 	hw->npc_kpus = (npc_const >> 8) & 0x1FULL;
19831c1935c9SSubbaraya Sundeep 	hw->npc_intfs = npc_const & 0xFULL;
19841c1935c9SSubbaraya Sundeep 	hw->npc_counters = (npc_const >> 48) & 0xFFFFULL;
19851c1935c9SSubbaraya Sundeep 
19861c1935c9SSubbaraya Sundeep 	mcam->banks = (npc_const >> 44) & 0xFULL;
19871c1935c9SSubbaraya Sundeep 	mcam->banksize = (npc_const >> 28) & 0xFFFFULL;
198899b8e547SHariprasad Kelam 	hw->npc_stat_ena = BIT_ULL(9);
19891c1935c9SSubbaraya Sundeep 	/* Extended set */
19901c1935c9SSubbaraya Sundeep 	if (npc_const2) {
19911c1935c9SSubbaraya Sundeep 		hw->npc_ext_set = true;
199299b8e547SHariprasad Kelam 		/* 96xx supports only match_stats and npc_counters
199399b8e547SHariprasad Kelam 		 * reflected in NPC_AF_CONST reg.
199499b8e547SHariprasad Kelam 		 * STAT_SEL and ENA are at [0:8] and 9 bit positions.
199599b8e547SHariprasad Kelam 		 * 98xx has both match_stat and ext and npc_counter
199699b8e547SHariprasad Kelam 		 * reflected in NPC_AF_CONST2
199799b8e547SHariprasad Kelam 		 * STAT_SEL_EXT added at [12:14] bit position.
199899b8e547SHariprasad Kelam 		 * cn10k supports only ext and hence npc_counters in
199999b8e547SHariprasad Kelam 		 * NPC_AF_CONST is 0 and npc_counters reflected in NPC_AF_CONST2.
200099b8e547SHariprasad Kelam 		 * STAT_SEL bitpos incremented from [0:8] to [0:11] and ENA bit moved to 63
200199b8e547SHariprasad Kelam 		 */
200299b8e547SHariprasad Kelam 		if (!hw->npc_counters)
200399b8e547SHariprasad Kelam 			hw->npc_stat_ena = BIT_ULL(63);
20041c1935c9SSubbaraya Sundeep 		hw->npc_counters = (npc_const2 >> 16) & 0xFFFFULL;
20051c1935c9SSubbaraya Sundeep 		mcam->banksize = npc_const2 & 0xFFFFULL;
20061c1935c9SSubbaraya Sundeep 	}
20071c1935c9SSubbaraya Sundeep 
20081c1935c9SSubbaraya Sundeep 	mcam->counters.max = hw->npc_counters;
20091c1935c9SSubbaraya Sundeep }
20101c1935c9SSubbaraya Sundeep 
rvu_npc_setup_interfaces(struct rvu * rvu,int blkaddr)20111c1935c9SSubbaraya Sundeep static void rvu_npc_setup_interfaces(struct rvu *rvu, int blkaddr)
20121c1935c9SSubbaraya Sundeep {
2013dd1d1a8aSStanislaw Kardach 	struct npc_mcam_kex *mkex = rvu->kpu.mkex;
20141c1935c9SSubbaraya Sundeep 	struct npc_mcam *mcam = &rvu->hw->mcam;
20151c1935c9SSubbaraya Sundeep 	struct rvu_hwinfo *hw = rvu->hw;
20161c1935c9SSubbaraya Sundeep 	u64 nibble_ena, rx_kex, tx_kex;
20171c1935c9SSubbaraya Sundeep 	u8 intf;
20181c1935c9SSubbaraya Sundeep 
20191c1935c9SSubbaraya Sundeep 	/* Reserve last counter for MCAM RX miss action which is set to
20201c1935c9SSubbaraya Sundeep 	 * drop packet. This way we will know how many pkts didn't match
20211c1935c9SSubbaraya Sundeep 	 * any MCAM entry.
20221c1935c9SSubbaraya Sundeep 	 */
20231c1935c9SSubbaraya Sundeep 	mcam->counters.max--;
20241c1935c9SSubbaraya Sundeep 	mcam->rx_miss_act_cntr = mcam->counters.max;
20251c1935c9SSubbaraya Sundeep 
2026dd1d1a8aSStanislaw Kardach 	rx_kex = mkex->keyx_cfg[NIX_INTF_RX];
2027dd1d1a8aSStanislaw Kardach 	tx_kex = mkex->keyx_cfg[NIX_INTF_TX];
20281c1935c9SSubbaraya Sundeep 	nibble_ena = FIELD_GET(NPC_PARSE_NIBBLE, rx_kex);
20291c1935c9SSubbaraya Sundeep 
20301c1935c9SSubbaraya Sundeep 	nibble_ena = rvu_npc_get_tx_nibble_cfg(rvu, nibble_ena);
20311c1935c9SSubbaraya Sundeep 	if (nibble_ena) {
20321c1935c9SSubbaraya Sundeep 		tx_kex &= ~NPC_PARSE_NIBBLE;
20331c1935c9SSubbaraya Sundeep 		tx_kex |= FIELD_PREP(NPC_PARSE_NIBBLE, nibble_ena);
2034dd1d1a8aSStanislaw Kardach 		mkex->keyx_cfg[NIX_INTF_TX] = tx_kex;
20351c1935c9SSubbaraya Sundeep 	}
20361c1935c9SSubbaraya Sundeep 
20371c1935c9SSubbaraya Sundeep 	/* Configure RX interfaces */
20381c1935c9SSubbaraya Sundeep 	for (intf = 0; intf < hw->npc_intfs; intf++) {
20391c1935c9SSubbaraya Sundeep 		if (is_npc_intf_tx(intf))
20401c1935c9SSubbaraya Sundeep 			continue;
20411c1935c9SSubbaraya Sundeep 
20421c1935c9SSubbaraya Sundeep 		/* Set RX MCAM search key size. LA..LE (ltype only) + Channel */
20431c1935c9SSubbaraya Sundeep 		rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf),
20441c1935c9SSubbaraya Sundeep 			    rx_kex);
20451c1935c9SSubbaraya Sundeep 
20461c1935c9SSubbaraya Sundeep 		/* If MCAM lookup doesn't result in a match, drop the received
20471c1935c9SSubbaraya Sundeep 		 * packet. And map this action to a counter to count dropped
20481c1935c9SSubbaraya Sundeep 		 * packets.
20491c1935c9SSubbaraya Sundeep 		 */
20501c1935c9SSubbaraya Sundeep 		rvu_write64(rvu, blkaddr,
20511c1935c9SSubbaraya Sundeep 			    NPC_AF_INTFX_MISS_ACT(intf), NIX_RX_ACTIONOP_DROP);
20521c1935c9SSubbaraya Sundeep 
20531c1935c9SSubbaraya Sundeep 		/* NPC_AF_INTFX_MISS_STAT_ACT[14:12] - counter[11:9]
20541c1935c9SSubbaraya Sundeep 		 * NPC_AF_INTFX_MISS_STAT_ACT[8:0] - counter[8:0]
20551c1935c9SSubbaraya Sundeep 		 */
20561c1935c9SSubbaraya Sundeep 		rvu_write64(rvu, blkaddr,
20571c1935c9SSubbaraya Sundeep 			    NPC_AF_INTFX_MISS_STAT_ACT(intf),
20581c1935c9SSubbaraya Sundeep 			    ((mcam->rx_miss_act_cntr >> 9) << 12) |
205999b8e547SHariprasad Kelam 			    hw->npc_stat_ena | mcam->rx_miss_act_cntr);
20601c1935c9SSubbaraya Sundeep 	}
20611c1935c9SSubbaraya Sundeep 
20621c1935c9SSubbaraya Sundeep 	/* Configure TX interfaces */
20631c1935c9SSubbaraya Sundeep 	for (intf = 0; intf < hw->npc_intfs; intf++) {
20641c1935c9SSubbaraya Sundeep 		if (is_npc_intf_rx(intf))
20651c1935c9SSubbaraya Sundeep 			continue;
20661c1935c9SSubbaraya Sundeep 
20671c1935c9SSubbaraya Sundeep 		/* Extract Ltypes LID_LA to LID_LE */
20681c1935c9SSubbaraya Sundeep 		rvu_write64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf),
20691c1935c9SSubbaraya Sundeep 			    tx_kex);
20701c1935c9SSubbaraya Sundeep 
20711c1935c9SSubbaraya Sundeep 		/* Set TX miss action to UCAST_DEFAULT i.e
20721c1935c9SSubbaraya Sundeep 		 * transmit the packet on NIX LF SQ's default channel.
20731c1935c9SSubbaraya Sundeep 		 */
20741c1935c9SSubbaraya Sundeep 		rvu_write64(rvu, blkaddr,
20751c1935c9SSubbaraya Sundeep 			    NPC_AF_INTFX_MISS_ACT(intf),
20761c1935c9SSubbaraya Sundeep 			    NIX_TX_ACTIONOP_UCAST_DEFAULT);
20771c1935c9SSubbaraya Sundeep 	}
20781c1935c9SSubbaraya Sundeep }
20791c1935c9SSubbaraya Sundeep 
rvu_npc_init(struct rvu * rvu)208023923ea4SSunil Goutham int rvu_npc_init(struct rvu *rvu)
208123923ea4SSunil Goutham {
208242006910SStanislaw Kardach 	struct npc_kpu_profile_adapter *kpu = &rvu->kpu;
208323923ea4SSunil Goutham 	struct npc_pkind *pkind = &rvu->hw->pkind;
2084e07fb507SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
2085f9274958SSunil Goutham 	int blkaddr, entry, bank, err;
208623923ea4SSunil Goutham 
208723923ea4SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
208823923ea4SSunil Goutham 	if (blkaddr < 0) {
208923923ea4SSunil Goutham 		dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
209023923ea4SSunil Goutham 		return -ENODEV;
209123923ea4SSunil Goutham 	}
209223923ea4SSunil Goutham 
20931c1935c9SSubbaraya Sundeep 	rvu_npc_hw_init(rvu, blkaddr);
20941c1935c9SSubbaraya Sundeep 
2095f9274958SSunil Goutham 	/* First disable all MCAM entries, to stop traffic towards NIXLFs */
20961c1935c9SSubbaraya Sundeep 	for (bank = 0; bank < mcam->banks; bank++) {
20971c1935c9SSubbaraya Sundeep 		for (entry = 0; entry < mcam->banksize; entry++)
2098f9274958SSunil Goutham 			rvu_write64(rvu, blkaddr,
2099f9274958SSunil Goutham 				    NPC_AF_MCAMEX_BANKX_CFG(entry, bank), 0);
2100f9274958SSunil Goutham 	}
2101f9274958SSunil Goutham 
210223923ea4SSunil Goutham 	err = rvu_alloc_bitmap(&pkind->rsrc);
210323923ea4SSunil Goutham 	if (err)
210423923ea4SSunil Goutham 		return err;
2105ac059d16SGeetha sowjanya 	/* Reserve PKIND#0 for LBKs. Power reset value of LBK_CH_PKIND is '0',
2106ac059d16SGeetha sowjanya 	 * no need to configure PKIND for all LBKs separately.
2107ac059d16SGeetha sowjanya 	 */
2108ac059d16SGeetha sowjanya 	rvu_alloc_rsrc(&pkind->rsrc);
210923923ea4SSunil Goutham 
211023923ea4SSunil Goutham 	/* Allocate mem for pkind to PF and channel mapping info */
211123923ea4SSunil Goutham 	pkind->pfchan_map = devm_kcalloc(rvu->dev, pkind->rsrc.max,
211223923ea4SSunil Goutham 					 sizeof(u32), GFP_KERNEL);
211323923ea4SSunil Goutham 	if (!pkind->pfchan_map)
211423923ea4SSunil Goutham 		return -ENOMEM;
211523923ea4SSunil Goutham 
211623923ea4SSunil Goutham 	/* Configure KPU profile */
211723923ea4SSunil Goutham 	npc_parser_profile_init(rvu, blkaddr);
211823923ea4SSunil Goutham 
21196b3321baSSunil Goutham 	/* Config Outer L2, IPv4's NPC layer info */
21206b3321baSSunil Goutham 	rvu_write64(rvu, blkaddr, NPC_AF_PCK_DEF_OL2,
212142006910SStanislaw Kardach 		    (kpu->lt_def->pck_ol2.lid << 8) | (kpu->lt_def->pck_ol2.ltype_match << 4) |
212242006910SStanislaw Kardach 		    kpu->lt_def->pck_ol2.ltype_mask);
21236b3321baSSunil Goutham 	rvu_write64(rvu, blkaddr, NPC_AF_PCK_DEF_OIP4,
212442006910SStanislaw Kardach 		    (kpu->lt_def->pck_oip4.lid << 8) | (kpu->lt_def->pck_oip4.ltype_match << 4) |
212542006910SStanislaw Kardach 		    kpu->lt_def->pck_oip4.ltype_mask);
21266b3321baSSunil Goutham 
2127962e1bd6SJerin Jacob 	/* Config Inner IPV4 NPC layer info */
2128962e1bd6SJerin Jacob 	rvu_write64(rvu, blkaddr, NPC_AF_PCK_DEF_IIP4,
212942006910SStanislaw Kardach 		    (kpu->lt_def->pck_iip4.lid << 8) | (kpu->lt_def->pck_iip4.ltype_match << 4) |
213042006910SStanislaw Kardach 		    kpu->lt_def->pck_iip4.ltype_mask);
2131962e1bd6SJerin Jacob 
21326b3321baSSunil Goutham 	/* Enable below for Rx pkts.
21336b3321baSSunil Goutham 	 * - Outer IPv4 header checksum validation.
21341e4428b6SSunil Goutham 	 * - Detect outer L2 broadcast address and set NPC_RESULT_S[L2B].
21351e4428b6SSunil Goutham 	 * - Detect outer L2 multicast address and set NPC_RESULT_S[L2M].
2136962e1bd6SJerin Jacob 	 * - Inner IPv4 header checksum validation.
2137962e1bd6SJerin Jacob 	 * - Set non zero checksum error code value
21386b3321baSSunil Goutham 	 */
21396b3321baSSunil Goutham 	rvu_write64(rvu, blkaddr, NPC_AF_PCK_CFG,
21406b3321baSSunil Goutham 		    rvu_read64(rvu, blkaddr, NPC_AF_PCK_CFG) |
21411e4428b6SSunil Goutham 		    ((u64)NPC_EC_OIP4_CSUM << 32) | (NPC_EC_IIP4_CSUM << 24) |
21421e4428b6SSunil Goutham 		    BIT_ULL(7) | BIT_ULL(6) | BIT_ULL(2) | BIT_ULL(1));
21436b3321baSSunil Goutham 
21441c1935c9SSubbaraya Sundeep 	rvu_npc_setup_interfaces(rvu, blkaddr);
2145fefefd99SSunil Goutham 
214656d9f5fdSRatheesh Kannoth 	npc_config_secret_key(rvu, blkaddr);
21479b179a96SSubbaraya Sundeep 	/* Configure MKEX profile */
21489b179a96SSubbaraya Sundeep 	npc_load_mkex_profile(rvu, blkaddr, rvu->mkex_pfl_name);
21499b179a96SSubbaraya Sundeep 
2150fefefd99SSunil Goutham 	err = npc_mcam_rsrcs_init(rvu, blkaddr);
2151fefefd99SSunil Goutham 	if (err)
2152fefefd99SSunil Goutham 		return err;
2153fefefd99SSunil Goutham 
21549b179a96SSubbaraya Sundeep 	err = npc_flow_steering_init(rvu, blkaddr);
21559b179a96SSubbaraya Sundeep 	if (err) {
21569b179a96SSubbaraya Sundeep 		dev_err(rvu->dev,
21579b179a96SSubbaraya Sundeep 			"Incorrect mkex profile loaded using default mkex\n");
21589b179a96SSubbaraya Sundeep 		npc_load_mkex_profile(rvu, blkaddr, def_pfl_name);
21599b179a96SSubbaraya Sundeep 	}
2160fefefd99SSunil Goutham 
216123923ea4SSunil Goutham 	return 0;
216223923ea4SSunil Goutham }
216323923ea4SSunil Goutham 
rvu_npc_freemem(struct rvu * rvu)216423923ea4SSunil Goutham void rvu_npc_freemem(struct rvu *rvu)
216523923ea4SSunil Goutham {
216623923ea4SSunil Goutham 	struct npc_pkind *pkind = &rvu->hw->pkind;
21670964fc8fSStanislaw Kardach 	struct npc_mcam *mcam = &rvu->hw->mcam;
216823923ea4SSunil Goutham 
216923923ea4SSunil Goutham 	kfree(pkind->rsrc.bmap);
2170f9274958SSunil Goutham 	kfree(mcam->counters.bmap);
21715d16250bSHarman Kalra 	if (rvu->kpu_prfl_addr)
21725d16250bSHarman Kalra 		iounmap(rvu->kpu_prfl_addr);
21735d16250bSHarman Kalra 	else
21743a724415SStanislaw Kardach 		kfree(rvu->kpu_fwdata);
21750964fc8fSStanislaw Kardach 	mutex_destroy(&mcam->lock);
217623923ea4SSunil Goutham }
2177f9274958SSunil Goutham 
rvu_npc_get_mcam_entry_alloc_info(struct rvu * rvu,u16 pcifunc,int blkaddr,int * alloc_cnt,int * enable_cnt)2178e07fb507SSunil Goutham void rvu_npc_get_mcam_entry_alloc_info(struct rvu *rvu, u16 pcifunc,
2179e07fb507SSunil Goutham 				       int blkaddr, int *alloc_cnt,
2180e07fb507SSunil Goutham 				       int *enable_cnt)
2181e07fb507SSunil Goutham {
2182e07fb507SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
2183e07fb507SSunil Goutham 	int entry;
2184e07fb507SSunil Goutham 
2185e07fb507SSunil Goutham 	*alloc_cnt = 0;
2186e07fb507SSunil Goutham 	*enable_cnt = 0;
2187e07fb507SSunil Goutham 
2188e07fb507SSunil Goutham 	for (entry = 0; entry < mcam->bmap_entries; entry++) {
2189e07fb507SSunil Goutham 		if (mcam->entry2pfvf_map[entry] == pcifunc) {
2190e07fb507SSunil Goutham 			(*alloc_cnt)++;
2191e07fb507SSunil Goutham 			if (is_mcam_entry_enabled(rvu, mcam, blkaddr, entry))
2192e07fb507SSunil Goutham 				(*enable_cnt)++;
2193e07fb507SSunil Goutham 		}
2194e07fb507SSunil Goutham 	}
2195e07fb507SSunil Goutham }
2196e07fb507SSunil Goutham 
rvu_npc_get_mcam_counter_alloc_info(struct rvu * rvu,u16 pcifunc,int blkaddr,int * alloc_cnt,int * enable_cnt)2197e07fb507SSunil Goutham void rvu_npc_get_mcam_counter_alloc_info(struct rvu *rvu, u16 pcifunc,
2198e07fb507SSunil Goutham 					 int blkaddr, int *alloc_cnt,
2199e07fb507SSunil Goutham 					 int *enable_cnt)
2200e07fb507SSunil Goutham {
2201e07fb507SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
2202e07fb507SSunil Goutham 	int cntr;
2203e07fb507SSunil Goutham 
2204e07fb507SSunil Goutham 	*alloc_cnt = 0;
2205e07fb507SSunil Goutham 	*enable_cnt = 0;
2206e07fb507SSunil Goutham 
2207e07fb507SSunil Goutham 	for (cntr = 0; cntr < mcam->counters.max; cntr++) {
2208e07fb507SSunil Goutham 		if (mcam->cntr2pfvf_map[cntr] == pcifunc) {
2209e07fb507SSunil Goutham 			(*alloc_cnt)++;
2210e07fb507SSunil Goutham 			if (mcam->cntr_refcnt[cntr])
2211e07fb507SSunil Goutham 				(*enable_cnt)++;
2212e07fb507SSunil Goutham 		}
2213e07fb507SSunil Goutham 	}
2214e07fb507SSunil Goutham }
2215e07fb507SSunil Goutham 
npc_mcam_verify_entry(struct npc_mcam * mcam,u16 pcifunc,int entry)2216f9274958SSunil Goutham static int npc_mcam_verify_entry(struct npc_mcam *mcam,
2217f9274958SSunil Goutham 				 u16 pcifunc, int entry)
2218f9274958SSunil Goutham {
221963f925dcSNaveen Mamindlapalli 	/* verify AF installed entries */
222063f925dcSNaveen Mamindlapalli 	if (is_pffunc_af(pcifunc))
222163f925dcSNaveen Mamindlapalli 		return 0;
2222f9274958SSunil Goutham 	/* Verify if entry is valid and if it is indeed
2223f9274958SSunil Goutham 	 * allocated to the requesting PFFUNC.
2224f9274958SSunil Goutham 	 */
2225f9274958SSunil Goutham 	if (entry >= mcam->bmap_entries)
2226f9274958SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2227f9274958SSunil Goutham 
2228f9274958SSunil Goutham 	if (pcifunc != mcam->entry2pfvf_map[entry])
2229f9274958SSunil Goutham 		return NPC_MCAM_PERM_DENIED;
2230f9274958SSunil Goutham 
2231f9274958SSunil Goutham 	return 0;
2232f9274958SSunil Goutham }
2233f9274958SSunil Goutham 
npc_mcam_verify_counter(struct npc_mcam * mcam,u16 pcifunc,int cntr)22347fbb3f23SSunil Goutham static int npc_mcam_verify_counter(struct npc_mcam *mcam,
22357fbb3f23SSunil Goutham 				   u16 pcifunc, int cntr)
22367fbb3f23SSunil Goutham {
22377fbb3f23SSunil Goutham 	/* Verify if counter is valid and if it is indeed
22387fbb3f23SSunil Goutham 	 * allocated to the requesting PFFUNC.
22397fbb3f23SSunil Goutham 	 */
22407fbb3f23SSunil Goutham 	if (cntr >= mcam->counters.max)
22417fbb3f23SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
22427fbb3f23SSunil Goutham 
22437fbb3f23SSunil Goutham 	if (pcifunc != mcam->cntr2pfvf_map[cntr])
22447fbb3f23SSunil Goutham 		return NPC_MCAM_PERM_DENIED;
22457fbb3f23SSunil Goutham 
22467fbb3f23SSunil Goutham 	return 0;
22477fbb3f23SSunil Goutham }
22487fbb3f23SSunil Goutham 
npc_map_mcam_entry_and_cntr(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,u16 entry,u16 cntr)2249a958dd59SSunil Goutham static void npc_map_mcam_entry_and_cntr(struct rvu *rvu, struct npc_mcam *mcam,
2250a958dd59SSunil Goutham 					int blkaddr, u16 entry, u16 cntr)
2251a958dd59SSunil Goutham {
2252a958dd59SSunil Goutham 	u16 index = entry & (mcam->banksize - 1);
225399b8e547SHariprasad Kelam 	u32 bank = npc_get_bank(mcam, entry);
225499b8e547SHariprasad Kelam 	struct rvu_hwinfo *hw = rvu->hw;
2255a958dd59SSunil Goutham 
2256a958dd59SSunil Goutham 	/* Set mapping and increment counter's refcnt */
2257a958dd59SSunil Goutham 	mcam->entry2cntr_map[entry] = cntr;
2258a958dd59SSunil Goutham 	mcam->cntr_refcnt[cntr]++;
225999b8e547SHariprasad Kelam 	/* Enable stats */
2260a958dd59SSunil Goutham 	rvu_write64(rvu, blkaddr,
2261a958dd59SSunil Goutham 		    NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank),
226299b8e547SHariprasad Kelam 		    ((cntr >> 9) << 12) | hw->npc_stat_ena | cntr);
2263a958dd59SSunil Goutham }
2264a958dd59SSunil Goutham 
npc_unmap_mcam_entry_and_cntr(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,u16 entry,u16 cntr)2265a958dd59SSunil Goutham static void npc_unmap_mcam_entry_and_cntr(struct rvu *rvu,
2266a958dd59SSunil Goutham 					  struct npc_mcam *mcam,
2267a958dd59SSunil Goutham 					  int blkaddr, u16 entry, u16 cntr)
2268a958dd59SSunil Goutham {
2269a958dd59SSunil Goutham 	u16 index = entry & (mcam->banksize - 1);
2270698a82ebSSubbaraya Sundeep 	u32 bank = npc_get_bank(mcam, entry);
2271a958dd59SSunil Goutham 
2272a958dd59SSunil Goutham 	/* Remove mapping and reduce counter's refcnt */
2273a958dd59SSunil Goutham 	mcam->entry2cntr_map[entry] = NPC_MCAM_INVALID_MAP;
2274a958dd59SSunil Goutham 	mcam->cntr_refcnt[cntr]--;
2275a958dd59SSunil Goutham 	/* Disable stats */
2276a958dd59SSunil Goutham 	rvu_write64(rvu, blkaddr,
2277a958dd59SSunil Goutham 		    NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank), 0x00);
2278a958dd59SSunil Goutham }
2279a958dd59SSunil Goutham 
2280f9274958SSunil Goutham /* Sets MCAM entry in bitmap as used. Update
2281f9274958SSunil Goutham  * reverse bitmap too. Should be called with
2282f9274958SSunil Goutham  * 'mcam->lock' held.
2283f9274958SSunil Goutham  */
npc_mcam_set_bit(struct npc_mcam * mcam,u16 index)2284f9274958SSunil Goutham static void npc_mcam_set_bit(struct npc_mcam *mcam, u16 index)
2285f9274958SSunil Goutham {
2286f9274958SSunil Goutham 	u16 entry, rentry;
2287f9274958SSunil Goutham 
2288f9274958SSunil Goutham 	entry = index;
2289f9274958SSunil Goutham 	rentry = mcam->bmap_entries - index - 1;
2290f9274958SSunil Goutham 
2291f9274958SSunil Goutham 	__set_bit(entry, mcam->bmap);
2292f9274958SSunil Goutham 	__set_bit(rentry, mcam->bmap_reverse);
2293f9274958SSunil Goutham 	mcam->bmap_fcnt--;
2294f9274958SSunil Goutham }
2295f9274958SSunil Goutham 
2296f9274958SSunil Goutham /* Sets MCAM entry in bitmap as free. Update
2297f9274958SSunil Goutham  * reverse bitmap too. Should be called with
2298f9274958SSunil Goutham  * 'mcam->lock' held.
2299f9274958SSunil Goutham  */
npc_mcam_clear_bit(struct npc_mcam * mcam,u16 index)2300f9274958SSunil Goutham static void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index)
2301f9274958SSunil Goutham {
2302f9274958SSunil Goutham 	u16 entry, rentry;
2303f9274958SSunil Goutham 
2304f9274958SSunil Goutham 	entry = index;
2305f9274958SSunil Goutham 	rentry = mcam->bmap_entries - index - 1;
2306f9274958SSunil Goutham 
2307f9274958SSunil Goutham 	__clear_bit(entry, mcam->bmap);
2308f9274958SSunil Goutham 	__clear_bit(rentry, mcam->bmap_reverse);
2309f9274958SSunil Goutham 	mcam->bmap_fcnt++;
2310f9274958SSunil Goutham }
2311f9274958SSunil Goutham 
npc_mcam_free_all_entries(struct rvu * rvu,struct npc_mcam * mcam,int blkaddr,u16 pcifunc)2312f9274958SSunil Goutham static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
2313f9274958SSunil Goutham 				      int blkaddr, u16 pcifunc)
2314f9274958SSunil Goutham {
2315a958dd59SSunil Goutham 	u16 index, cntr;
2316f9274958SSunil Goutham 
2317f9274958SSunil Goutham 	/* Scan all MCAM entries and free the ones mapped to 'pcifunc' */
2318f9274958SSunil Goutham 	for (index = 0; index < mcam->bmap_entries; index++) {
2319f9274958SSunil Goutham 		if (mcam->entry2pfvf_map[index] == pcifunc) {
2320f9274958SSunil Goutham 			mcam->entry2pfvf_map[index] = NPC_MCAM_INVALID_MAP;
2321f9274958SSunil Goutham 			/* Free the entry in bitmap */
2322f9274958SSunil Goutham 			npc_mcam_clear_bit(mcam, index);
2323f9274958SSunil Goutham 			/* Disable the entry */
2324f9274958SSunil Goutham 			npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
2325a958dd59SSunil Goutham 
2326a958dd59SSunil Goutham 			/* Update entry2counter mapping */
2327a958dd59SSunil Goutham 			cntr = mcam->entry2cntr_map[index];
2328a958dd59SSunil Goutham 			if (cntr != NPC_MCAM_INVALID_MAP)
2329a958dd59SSunil Goutham 				npc_unmap_mcam_entry_and_cntr(rvu, mcam,
2330a958dd59SSunil Goutham 							      blkaddr, index,
2331a958dd59SSunil Goutham 							      cntr);
233255307fcbSSubbaraya Sundeep 			mcam->entry2target_pffunc[index] = 0x0;
2333a958dd59SSunil Goutham 		}
2334a958dd59SSunil Goutham 	}
2335a958dd59SSunil Goutham }
2336a958dd59SSunil Goutham 
npc_mcam_free_all_counters(struct rvu * rvu,struct npc_mcam * mcam,u16 pcifunc)2337a958dd59SSunil Goutham static void npc_mcam_free_all_counters(struct rvu *rvu, struct npc_mcam *mcam,
2338a958dd59SSunil Goutham 				       u16 pcifunc)
2339a958dd59SSunil Goutham {
2340a958dd59SSunil Goutham 	u16 cntr;
2341a958dd59SSunil Goutham 
2342a958dd59SSunil Goutham 	/* Scan all MCAM counters and free the ones mapped to 'pcifunc' */
2343a958dd59SSunil Goutham 	for (cntr = 0; cntr < mcam->counters.max; cntr++) {
2344a958dd59SSunil Goutham 		if (mcam->cntr2pfvf_map[cntr] == pcifunc) {
2345a958dd59SSunil Goutham 			mcam->cntr2pfvf_map[cntr] = NPC_MCAM_INVALID_MAP;
2346a958dd59SSunil Goutham 			mcam->cntr_refcnt[cntr] = 0;
2347a958dd59SSunil Goutham 			rvu_free_rsrc(&mcam->counters, cntr);
2348a958dd59SSunil Goutham 			/* This API is expected to be called after freeing
2349a958dd59SSunil Goutham 			 * MCAM entries, which inturn will remove
2350a958dd59SSunil Goutham 			 * 'entry to counter' mapping.
2351a958dd59SSunil Goutham 			 * No need to do it again.
2352a958dd59SSunil Goutham 			 */
2353f9274958SSunil Goutham 		}
2354f9274958SSunil Goutham 	}
2355f9274958SSunil Goutham }
2356f9274958SSunil Goutham 
2357f9274958SSunil Goutham /* Find area of contiguous free entries of size 'nr'.
2358f9274958SSunil Goutham  * If not found return max contiguous free entries available.
2359f9274958SSunil Goutham  */
npc_mcam_find_zero_area(unsigned long * map,u16 size,u16 start,u16 nr,u16 * max_area)2360f9274958SSunil Goutham static u16 npc_mcam_find_zero_area(unsigned long *map, u16 size, u16 start,
2361f9274958SSunil Goutham 				   u16 nr, u16 *max_area)
2362f9274958SSunil Goutham {
2363f9274958SSunil Goutham 	u16 max_area_start = 0;
2364f9274958SSunil Goutham 	u16 index, next, end;
2365f9274958SSunil Goutham 
2366f9274958SSunil Goutham 	*max_area = 0;
2367f9274958SSunil Goutham 
2368f9274958SSunil Goutham again:
2369f9274958SSunil Goutham 	index = find_next_zero_bit(map, size, start);
2370f9274958SSunil Goutham 	if (index >= size)
2371f9274958SSunil Goutham 		return max_area_start;
2372f9274958SSunil Goutham 
2373f9274958SSunil Goutham 	end = ((index + nr) >= size) ? size : index + nr;
2374f9274958SSunil Goutham 	next = find_next_bit(map, end, index);
2375f9274958SSunil Goutham 	if (*max_area < (next - index)) {
2376f9274958SSunil Goutham 		*max_area = next - index;
2377f9274958SSunil Goutham 		max_area_start = index;
2378f9274958SSunil Goutham 	}
2379f9274958SSunil Goutham 
2380f9274958SSunil Goutham 	if (next < end) {
2381f9274958SSunil Goutham 		start = next + 1;
2382f9274958SSunil Goutham 		goto again;
2383f9274958SSunil Goutham 	}
2384f9274958SSunil Goutham 
2385f9274958SSunil Goutham 	return max_area_start;
2386f9274958SSunil Goutham }
2387f9274958SSunil Goutham 
2388f9274958SSunil Goutham /* Find number of free MCAM entries available
2389f9274958SSunil Goutham  * within range i.e in between 'start' and 'end'.
2390f9274958SSunil Goutham  */
npc_mcam_get_free_count(unsigned long * map,u16 start,u16 end)2391f9274958SSunil Goutham static u16 npc_mcam_get_free_count(unsigned long *map, u16 start, u16 end)
2392f9274958SSunil Goutham {
2393f9274958SSunil Goutham 	u16 index, next;
2394f9274958SSunil Goutham 	u16 fcnt = 0;
2395f9274958SSunil Goutham 
2396f9274958SSunil Goutham again:
2397f9274958SSunil Goutham 	if (start >= end)
2398f9274958SSunil Goutham 		return fcnt;
2399f9274958SSunil Goutham 
2400f9274958SSunil Goutham 	index = find_next_zero_bit(map, end, start);
2401f9274958SSunil Goutham 	if (index >= end)
2402f9274958SSunil Goutham 		return fcnt;
2403f9274958SSunil Goutham 
2404f9274958SSunil Goutham 	next = find_next_bit(map, end, index);
2405f9274958SSunil Goutham 	if (next <= end) {
2406f9274958SSunil Goutham 		fcnt += next - index;
2407f9274958SSunil Goutham 		start = next + 1;
2408f9274958SSunil Goutham 		goto again;
2409f9274958SSunil Goutham 	}
2410f9274958SSunil Goutham 
2411f9274958SSunil Goutham 	fcnt += end - index;
2412f9274958SSunil Goutham 	return fcnt;
2413f9274958SSunil Goutham }
2414f9274958SSunil Goutham 
2415f9274958SSunil Goutham static void
npc_get_mcam_search_range_priority(struct npc_mcam * mcam,struct npc_mcam_alloc_entry_req * req,u16 * start,u16 * end,bool * reverse)2416f9274958SSunil Goutham npc_get_mcam_search_range_priority(struct npc_mcam *mcam,
2417f9274958SSunil Goutham 				   struct npc_mcam_alloc_entry_req *req,
2418f9274958SSunil Goutham 				   u16 *start, u16 *end, bool *reverse)
2419f9274958SSunil Goutham {
2420f9274958SSunil Goutham 	u16 fcnt;
2421f9274958SSunil Goutham 
2422f9274958SSunil Goutham 	if (req->priority == NPC_MCAM_HIGHER_PRIO)
2423f9274958SSunil Goutham 		goto hprio;
2424f9274958SSunil Goutham 
2425f9274958SSunil Goutham 	/* For a low priority entry allocation
2426f9274958SSunil Goutham 	 * - If reference entry is not in hprio zone then
2427f9274958SSunil Goutham 	 *      search range: ref_entry to end.
2428f9274958SSunil Goutham 	 * - If reference entry is in hprio zone and if
2429f9274958SSunil Goutham 	 *   request can be accomodated in non-hprio zone then
2430f9274958SSunil Goutham 	 *      search range: 'start of middle zone' to 'end'
2431f9274958SSunil Goutham 	 * - else search in reverse, so that less number of hprio
2432f9274958SSunil Goutham 	 *   zone entries are allocated.
2433f9274958SSunil Goutham 	 */
2434f9274958SSunil Goutham 
2435f9274958SSunil Goutham 	*reverse = false;
2436f9274958SSunil Goutham 	*start = req->ref_entry + 1;
2437f9274958SSunil Goutham 	*end = mcam->bmap_entries;
2438f9274958SSunil Goutham 
2439f9274958SSunil Goutham 	if (req->ref_entry >= mcam->hprio_end)
2440f9274958SSunil Goutham 		return;
2441f9274958SSunil Goutham 
2442f9274958SSunil Goutham 	fcnt = npc_mcam_get_free_count(mcam->bmap,
2443f9274958SSunil Goutham 				       mcam->hprio_end, mcam->bmap_entries);
2444f9274958SSunil Goutham 	if (fcnt > req->count)
2445f9274958SSunil Goutham 		*start = mcam->hprio_end;
2446f9274958SSunil Goutham 	else
2447f9274958SSunil Goutham 		*reverse = true;
2448f9274958SSunil Goutham 	return;
2449f9274958SSunil Goutham 
2450f9274958SSunil Goutham hprio:
2451f9274958SSunil Goutham 	/* For a high priority entry allocation, search is always
2452f9274958SSunil Goutham 	 * in reverse to preserve hprio zone entries.
2453f9274958SSunil Goutham 	 * - If reference entry is not in lprio zone then
2454f9274958SSunil Goutham 	 *      search range: 0 to ref_entry.
2455f9274958SSunil Goutham 	 * - If reference entry is in lprio zone and if
2456f9274958SSunil Goutham 	 *   request can be accomodated in middle zone then
2457f9274958SSunil Goutham 	 *      search range: 'hprio_end' to 'lprio_start'
2458f9274958SSunil Goutham 	 */
2459f9274958SSunil Goutham 
2460f9274958SSunil Goutham 	*reverse = true;
2461f9274958SSunil Goutham 	*start = 0;
2462f9274958SSunil Goutham 	*end = req->ref_entry;
2463f9274958SSunil Goutham 
2464f9274958SSunil Goutham 	if (req->ref_entry <= mcam->lprio_start)
2465f9274958SSunil Goutham 		return;
2466f9274958SSunil Goutham 
2467f9274958SSunil Goutham 	fcnt = npc_mcam_get_free_count(mcam->bmap,
2468f9274958SSunil Goutham 				       mcam->hprio_end, mcam->lprio_start);
2469f9274958SSunil Goutham 	if (fcnt < req->count)
2470f9274958SSunil Goutham 		return;
2471f9274958SSunil Goutham 	*start = mcam->hprio_end;
2472f9274958SSunil Goutham 	*end = mcam->lprio_start;
2473f9274958SSunil Goutham }
2474f9274958SSunil Goutham 
npc_mcam_alloc_entries(struct npc_mcam * mcam,u16 pcifunc,struct npc_mcam_alloc_entry_req * req,struct npc_mcam_alloc_entry_rsp * rsp)2475f9274958SSunil Goutham static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc,
2476f9274958SSunil Goutham 				  struct npc_mcam_alloc_entry_req *req,
2477f9274958SSunil Goutham 				  struct npc_mcam_alloc_entry_rsp *rsp)
2478f9274958SSunil Goutham {
2479f9274958SSunil Goutham 	u16 entry_list[NPC_MAX_NONCONTIG_ENTRIES];
2480f9274958SSunil Goutham 	u16 fcnt, hp_fcnt, lp_fcnt;
2481f9274958SSunil Goutham 	u16 start, end, index;
2482f9274958SSunil Goutham 	int entry, next_start;
2483f9274958SSunil Goutham 	bool reverse = false;
2484f9274958SSunil Goutham 	unsigned long *bmap;
2485f9274958SSunil Goutham 	u16 max_contig;
2486f9274958SSunil Goutham 
2487f9274958SSunil Goutham 	mutex_lock(&mcam->lock);
2488f9274958SSunil Goutham 
2489f9274958SSunil Goutham 	/* Check if there are any free entries */
2490f9274958SSunil Goutham 	if (!mcam->bmap_fcnt) {
2491f9274958SSunil Goutham 		mutex_unlock(&mcam->lock);
2492f9274958SSunil Goutham 		return NPC_MCAM_ALLOC_FAILED;
2493f9274958SSunil Goutham 	}
2494f9274958SSunil Goutham 
2495f9274958SSunil Goutham 	/* MCAM entries are divided into high priority, middle and
2496f9274958SSunil Goutham 	 * low priority zones. Idea is to not allocate top and lower
2497f9274958SSunil Goutham 	 * most entries as much as possible, this is to increase
2498f9274958SSunil Goutham 	 * probability of honouring priority allocation requests.
2499f9274958SSunil Goutham 	 *
2500f9274958SSunil Goutham 	 * Two bitmaps are used for mcam entry management,
2501f9274958SSunil Goutham 	 * mcam->bmap for forward search i.e '0 to mcam->bmap_entries'.
2502f9274958SSunil Goutham 	 * mcam->bmap_reverse for reverse search i.e 'mcam->bmap_entries to 0'.
2503f9274958SSunil Goutham 	 *
2504f9274958SSunil Goutham 	 * Reverse bitmap is used to allocate entries
2505f9274958SSunil Goutham 	 * - when a higher priority entry is requested
2506f9274958SSunil Goutham 	 * - when available free entries are less.
2507f9274958SSunil Goutham 	 * Lower priority ones out of avaialble free entries are always
2508f9274958SSunil Goutham 	 * chosen when 'high vs low' question arises.
2509*2d7912f3SSubbaraya Sundeep 	 *
2510*2d7912f3SSubbaraya Sundeep 	 * For a VF base MCAM match rule is set by its PF. And all the
2511*2d7912f3SSubbaraya Sundeep 	 * further MCAM rules installed by VF on its own are
2512*2d7912f3SSubbaraya Sundeep 	 * concatenated with the base rule set by its PF. Hence PF entries
2513*2d7912f3SSubbaraya Sundeep 	 * should be at lower priority compared to VF entries. Otherwise
2514*2d7912f3SSubbaraya Sundeep 	 * base rule is hit always and rules installed by VF will be of
2515*2d7912f3SSubbaraya Sundeep 	 * no use. Hence if the request is from PF then allocate low
2516*2d7912f3SSubbaraya Sundeep 	 * priority entries.
2517f9274958SSunil Goutham 	 */
2518*2d7912f3SSubbaraya Sundeep 	if (!(pcifunc & RVU_PFVF_FUNC_MASK))
2519*2d7912f3SSubbaraya Sundeep 		goto lprio_alloc;
2520f9274958SSunil Goutham 
2521f9274958SSunil Goutham 	/* Get the search range for priority allocation request */
2522f9274958SSunil Goutham 	if (req->priority) {
2523f9274958SSunil Goutham 		npc_get_mcam_search_range_priority(mcam, req,
2524f9274958SSunil Goutham 						   &start, &end, &reverse);
2525f9274958SSunil Goutham 		goto alloc;
2526f9274958SSunil Goutham 	}
2527f9274958SSunil Goutham 
2528f9274958SSunil Goutham 	/* Find out the search range for non-priority allocation request
2529f9274958SSunil Goutham 	 *
2530f9274958SSunil Goutham 	 * Get MCAM free entry count in middle zone.
2531f9274958SSunil Goutham 	 */
2532f9274958SSunil Goutham 	lp_fcnt = npc_mcam_get_free_count(mcam->bmap,
2533f9274958SSunil Goutham 					  mcam->lprio_start,
2534f9274958SSunil Goutham 					  mcam->bmap_entries);
2535f9274958SSunil Goutham 	hp_fcnt = npc_mcam_get_free_count(mcam->bmap, 0, mcam->hprio_end);
2536f9274958SSunil Goutham 	fcnt = mcam->bmap_fcnt - lp_fcnt - hp_fcnt;
2537f9274958SSunil Goutham 
2538f9274958SSunil Goutham 	/* Check if request can be accomodated in the middle zone */
2539f9274958SSunil Goutham 	if (fcnt > req->count) {
2540f9274958SSunil Goutham 		start = mcam->hprio_end;
2541f9274958SSunil Goutham 		end = mcam->lprio_start;
2542f9274958SSunil Goutham 	} else if ((fcnt + (hp_fcnt / 2) + (lp_fcnt / 2)) > req->count) {
2543f9274958SSunil Goutham 		/* Expand search zone from half of hprio zone to
2544f9274958SSunil Goutham 		 * half of lprio zone.
2545f9274958SSunil Goutham 		 */
2546f9274958SSunil Goutham 		start = mcam->hprio_end / 2;
2547f9274958SSunil Goutham 		end = mcam->bmap_entries - (mcam->lprio_count / 2);
2548f9274958SSunil Goutham 		reverse = true;
2549f9274958SSunil Goutham 	} else {
2550f9274958SSunil Goutham 		/* Not enough free entries, search all entries in reverse,
2551f9274958SSunil Goutham 		 * so that low priority ones will get used up.
2552f9274958SSunil Goutham 		 */
25537df5b4b2SSubbaraya Sundeep lprio_alloc:
2554f9274958SSunil Goutham 		reverse = true;
2555f9274958SSunil Goutham 		start = 0;
2556f9274958SSunil Goutham 		end = mcam->bmap_entries;
2557*2d7912f3SSubbaraya Sundeep 		/* Ensure PF requests are always at bottom and if PF requests
2558*2d7912f3SSubbaraya Sundeep 		 * for higher/lower priority entry wrt reference entry then
2559*2d7912f3SSubbaraya Sundeep 		 * honour that criteria and start search for entries from bottom
2560*2d7912f3SSubbaraya Sundeep 		 * and not in mid zone.
2561*2d7912f3SSubbaraya Sundeep 		 */
2562*2d7912f3SSubbaraya Sundeep 		if (!(pcifunc & RVU_PFVF_FUNC_MASK) &&
2563*2d7912f3SSubbaraya Sundeep 		    req->priority == NPC_MCAM_HIGHER_PRIO)
2564*2d7912f3SSubbaraya Sundeep 			end = req->ref_entry;
2565*2d7912f3SSubbaraya Sundeep 
2566*2d7912f3SSubbaraya Sundeep 		if (!(pcifunc & RVU_PFVF_FUNC_MASK) &&
2567*2d7912f3SSubbaraya Sundeep 		    req->priority == NPC_MCAM_LOWER_PRIO)
2568*2d7912f3SSubbaraya Sundeep 			start = req->ref_entry;
2569f9274958SSunil Goutham 	}
2570f9274958SSunil Goutham 
2571f9274958SSunil Goutham alloc:
2572f9274958SSunil Goutham 	if (reverse) {
2573f9274958SSunil Goutham 		bmap = mcam->bmap_reverse;
2574f9274958SSunil Goutham 		start = mcam->bmap_entries - start;
2575f9274958SSunil Goutham 		end = mcam->bmap_entries - end;
2576d7be1d1cSYang Guang 		swap(start, end);
2577f9274958SSunil Goutham 	} else {
2578f9274958SSunil Goutham 		bmap = mcam->bmap;
2579f9274958SSunil Goutham 	}
2580f9274958SSunil Goutham 
2581f9274958SSunil Goutham 	if (req->contig) {
2582f9274958SSunil Goutham 		/* Allocate requested number of contiguous entries, if
2583f9274958SSunil Goutham 		 * unsuccessful find max contiguous entries available.
2584f9274958SSunil Goutham 		 */
2585f9274958SSunil Goutham 		index = npc_mcam_find_zero_area(bmap, end, start,
2586f9274958SSunil Goutham 						req->count, &max_contig);
2587f9274958SSunil Goutham 		rsp->count = max_contig;
2588f9274958SSunil Goutham 		if (reverse)
2589f9274958SSunil Goutham 			rsp->entry = mcam->bmap_entries - index - max_contig;
2590f9274958SSunil Goutham 		else
2591f9274958SSunil Goutham 			rsp->entry = index;
2592f9274958SSunil Goutham 	} else {
2593f9274958SSunil Goutham 		/* Allocate requested number of non-contiguous entries,
2594f9274958SSunil Goutham 		 * if unsuccessful allocate as many as possible.
2595f9274958SSunil Goutham 		 */
2596f9274958SSunil Goutham 		rsp->count = 0;
2597f9274958SSunil Goutham 		next_start = start;
2598f9274958SSunil Goutham 		for (entry = 0; entry < req->count; entry++) {
2599f9274958SSunil Goutham 			index = find_next_zero_bit(bmap, end, next_start);
2600f9274958SSunil Goutham 			if (index >= end)
2601f9274958SSunil Goutham 				break;
2602f9274958SSunil Goutham 
2603f9274958SSunil Goutham 			next_start = start + (index - start) + 1;
2604f9274958SSunil Goutham 
2605f9274958SSunil Goutham 			/* Save the entry's index */
2606f9274958SSunil Goutham 			if (reverse)
2607f9274958SSunil Goutham 				index = mcam->bmap_entries - index - 1;
2608f9274958SSunil Goutham 			entry_list[entry] = index;
2609f9274958SSunil Goutham 			rsp->count++;
2610f9274958SSunil Goutham 		}
2611f9274958SSunil Goutham 	}
2612f9274958SSunil Goutham 
2613f9274958SSunil Goutham 	/* If allocating requested no of entries is unsucessful,
2614f9274958SSunil Goutham 	 * expand the search range to full bitmap length and retry.
2615f9274958SSunil Goutham 	 */
2616f9274958SSunil Goutham 	if (!req->priority && (rsp->count < req->count) &&
2617f9274958SSunil Goutham 	    ((end - start) != mcam->bmap_entries)) {
2618f9274958SSunil Goutham 		reverse = true;
2619f9274958SSunil Goutham 		start = 0;
2620f9274958SSunil Goutham 		end = mcam->bmap_entries;
2621f9274958SSunil Goutham 		goto alloc;
2622f9274958SSunil Goutham 	}
2623f9274958SSunil Goutham 
2624f9274958SSunil Goutham 	/* For priority entry allocation requests, if allocation is
2625f9274958SSunil Goutham 	 * failed then expand search to max possible range and retry.
2626f9274958SSunil Goutham 	 */
2627f9274958SSunil Goutham 	if (req->priority && rsp->count < req->count) {
2628f9274958SSunil Goutham 		if (req->priority == NPC_MCAM_LOWER_PRIO &&
2629f9274958SSunil Goutham 		    (start != (req->ref_entry + 1))) {
2630f9274958SSunil Goutham 			start = req->ref_entry + 1;
2631f9274958SSunil Goutham 			end = mcam->bmap_entries;
2632f9274958SSunil Goutham 			reverse = false;
2633f9274958SSunil Goutham 			goto alloc;
2634f9274958SSunil Goutham 		} else if ((req->priority == NPC_MCAM_HIGHER_PRIO) &&
2635f9274958SSunil Goutham 			   ((end - start) != req->ref_entry)) {
2636f9274958SSunil Goutham 			start = 0;
2637f9274958SSunil Goutham 			end = req->ref_entry;
2638f9274958SSunil Goutham 			reverse = true;
2639f9274958SSunil Goutham 			goto alloc;
2640f9274958SSunil Goutham 		}
2641f9274958SSunil Goutham 	}
2642f9274958SSunil Goutham 
2643f9274958SSunil Goutham 	/* Copy MCAM entry indices into mbox response entry_list.
2644f9274958SSunil Goutham 	 * Requester always expects indices in ascending order, so
264536704239SJilin Yuan 	 * reverse the list if reverse bitmap is used for allocation.
2646f9274958SSunil Goutham 	 */
2647f9274958SSunil Goutham 	if (!req->contig && rsp->count) {
2648f9274958SSunil Goutham 		index = 0;
2649f9274958SSunil Goutham 		for (entry = rsp->count - 1; entry >= 0; entry--) {
2650f9274958SSunil Goutham 			if (reverse)
2651f9274958SSunil Goutham 				rsp->entry_list[index++] = entry_list[entry];
2652f9274958SSunil Goutham 			else
2653f9274958SSunil Goutham 				rsp->entry_list[entry] = entry_list[entry];
2654f9274958SSunil Goutham 		}
2655f9274958SSunil Goutham 	}
2656f9274958SSunil Goutham 
2657f9274958SSunil Goutham 	/* Mark the allocated entries as used and set nixlf mapping */
2658f9274958SSunil Goutham 	for (entry = 0; entry < rsp->count; entry++) {
2659f9274958SSunil Goutham 		index = req->contig ?
2660f9274958SSunil Goutham 			(rsp->entry + entry) : rsp->entry_list[entry];
2661f9274958SSunil Goutham 		npc_mcam_set_bit(mcam, index);
2662f9274958SSunil Goutham 		mcam->entry2pfvf_map[index] = pcifunc;
2663a958dd59SSunil Goutham 		mcam->entry2cntr_map[index] = NPC_MCAM_INVALID_MAP;
2664f9274958SSunil Goutham 	}
2665f9274958SSunil Goutham 
2666f9274958SSunil Goutham 	/* Update available free count in mbox response */
2667f9274958SSunil Goutham 	rsp->free_count = mcam->bmap_fcnt;
2668f9274958SSunil Goutham 
2669f9274958SSunil Goutham 	mutex_unlock(&mcam->lock);
2670f9274958SSunil Goutham 	return 0;
2671f9274958SSunil Goutham }
2672f9274958SSunil Goutham 
26733571fe07SRatheesh Kannoth /* Marks bitmaps to reserved the mcam slot */
npc_mcam_rsrcs_reserve(struct rvu * rvu,int blkaddr,int entry_idx)26743571fe07SRatheesh Kannoth void npc_mcam_rsrcs_reserve(struct rvu *rvu, int blkaddr, int entry_idx)
26753571fe07SRatheesh Kannoth {
26763571fe07SRatheesh Kannoth 	struct npc_mcam *mcam = &rvu->hw->mcam;
26773571fe07SRatheesh Kannoth 
26783571fe07SRatheesh Kannoth 	npc_mcam_set_bit(mcam, entry_idx);
26793571fe07SRatheesh Kannoth }
26803571fe07SRatheesh Kannoth 
rvu_mbox_handler_npc_mcam_alloc_entry(struct rvu * rvu,struct npc_mcam_alloc_entry_req * req,struct npc_mcam_alloc_entry_rsp * rsp)2681f9274958SSunil Goutham int rvu_mbox_handler_npc_mcam_alloc_entry(struct rvu *rvu,
2682f9274958SSunil Goutham 					  struct npc_mcam_alloc_entry_req *req,
2683f9274958SSunil Goutham 					  struct npc_mcam_alloc_entry_rsp *rsp)
2684f9274958SSunil Goutham {
2685f9274958SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
2686f9274958SSunil Goutham 	u16 pcifunc = req->hdr.pcifunc;
2687f9274958SSunil Goutham 	int blkaddr;
2688f9274958SSunil Goutham 
2689f9274958SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
2690f9274958SSunil Goutham 	if (blkaddr < 0)
2691f9274958SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2692f9274958SSunil Goutham 
2693f9274958SSunil Goutham 	rsp->entry = NPC_MCAM_ENTRY_INVALID;
2694f9274958SSunil Goutham 	rsp->free_count = 0;
2695f9274958SSunil Goutham 
2696225b2549SSuman Ghosh 	/* Check if ref_entry is greater that the range
2697225b2549SSuman Ghosh 	 * then set it to max value.
2698225b2549SSuman Ghosh 	 */
2699225b2549SSuman Ghosh 	if (req->ref_entry > mcam->bmap_entries)
2700225b2549SSuman Ghosh 		req->ref_entry = mcam->bmap_entries;
2701f9274958SSunil Goutham 
2702f9274958SSunil Goutham 	/* ref_entry can't be '0' if requested priority is high.
2703f9274958SSunil Goutham 	 * Can't be last entry if requested priority is low.
2704f9274958SSunil Goutham 	 */
2705f9274958SSunil Goutham 	if ((!req->ref_entry && req->priority == NPC_MCAM_HIGHER_PRIO) ||
2706225b2549SSuman Ghosh 	    ((req->ref_entry == mcam->bmap_entries) &&
2707f9274958SSunil Goutham 	     req->priority == NPC_MCAM_LOWER_PRIO))
2708f9274958SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2709f9274958SSunil Goutham 
2710f9274958SSunil Goutham 	/* Since list of allocated indices needs to be sent to requester,
2711f9274958SSunil Goutham 	 * max number of non-contiguous entries per mbox msg is limited.
2712f9274958SSunil Goutham 	 */
27139917060fSSunil Goutham 	if (!req->contig && req->count > NPC_MAX_NONCONTIG_ENTRIES) {
27149917060fSSunil Goutham 		dev_err(rvu->dev,
27159917060fSSunil Goutham 			"%s: %d Non-contiguous MCAM entries requested is more than max (%d) allowed\n",
27169917060fSSunil Goutham 			__func__, req->count, NPC_MAX_NONCONTIG_ENTRIES);
2717f9274958SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
27189917060fSSunil Goutham 	}
2719f9274958SSunil Goutham 
2720f9274958SSunil Goutham 	/* Alloc request from PFFUNC with no NIXLF attached should be denied */
2721cb7a6b3bSSubbaraya Sundeep 	if (!is_pffunc_af(pcifunc) && !is_nixlf_attached(rvu, pcifunc))
2722f9274958SSunil Goutham 		return NPC_MCAM_ALLOC_DENIED;
2723f9274958SSunil Goutham 
2724f9274958SSunil Goutham 	return npc_mcam_alloc_entries(mcam, pcifunc, req, rsp);
2725f9274958SSunil Goutham }
2726f9274958SSunil Goutham 
rvu_mbox_handler_npc_mcam_free_entry(struct rvu * rvu,struct npc_mcam_free_entry_req * req,struct msg_rsp * rsp)2727f9274958SSunil Goutham int rvu_mbox_handler_npc_mcam_free_entry(struct rvu *rvu,
2728f9274958SSunil Goutham 					 struct npc_mcam_free_entry_req *req,
2729f9274958SSunil Goutham 					 struct msg_rsp *rsp)
2730f9274958SSunil Goutham {
2731f9274958SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
2732f9274958SSunil Goutham 	u16 pcifunc = req->hdr.pcifunc;
2733f9274958SSunil Goutham 	int blkaddr, rc = 0;
2734a958dd59SSunil Goutham 	u16 cntr;
2735f9274958SSunil Goutham 
2736f9274958SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
2737f9274958SSunil Goutham 	if (blkaddr < 0)
2738f9274958SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2739f9274958SSunil Goutham 
2740f9274958SSunil Goutham 	/* Free request from PFFUNC with no NIXLF attached, ignore */
2741cb7a6b3bSSubbaraya Sundeep 	if (!is_pffunc_af(pcifunc) && !is_nixlf_attached(rvu, pcifunc))
2742f9274958SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2743f9274958SSunil Goutham 
2744f9274958SSunil Goutham 	mutex_lock(&mcam->lock);
2745f9274958SSunil Goutham 
2746f9274958SSunil Goutham 	if (req->all)
2747f9274958SSunil Goutham 		goto free_all;
2748f9274958SSunil Goutham 
2749f9274958SSunil Goutham 	rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry);
2750f9274958SSunil Goutham 	if (rc)
2751f9274958SSunil Goutham 		goto exit;
2752f9274958SSunil Goutham 
2753cb7a6b3bSSubbaraya Sundeep 	mcam->entry2pfvf_map[req->entry] = NPC_MCAM_INVALID_MAP;
275455307fcbSSubbaraya Sundeep 	mcam->entry2target_pffunc[req->entry] = 0x0;
2755f9274958SSunil Goutham 	npc_mcam_clear_bit(mcam, req->entry);
2756f9274958SSunil Goutham 	npc_enable_mcam_entry(rvu, mcam, blkaddr, req->entry, false);
2757f9274958SSunil Goutham 
2758a958dd59SSunil Goutham 	/* Update entry2counter mapping */
2759a958dd59SSunil Goutham 	cntr = mcam->entry2cntr_map[req->entry];
2760a958dd59SSunil Goutham 	if (cntr != NPC_MCAM_INVALID_MAP)
2761a958dd59SSunil Goutham 		npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
2762a958dd59SSunil Goutham 					      req->entry, cntr);
2763a958dd59SSunil Goutham 
2764f9274958SSunil Goutham 	goto exit;
2765f9274958SSunil Goutham 
2766f9274958SSunil Goutham free_all:
2767f9274958SSunil Goutham 	/* Free up all entries allocated to requesting PFFUNC */
2768f9274958SSunil Goutham 	npc_mcam_free_all_entries(rvu, mcam, blkaddr, pcifunc);
2769f9274958SSunil Goutham exit:
2770f9274958SSunil Goutham 	mutex_unlock(&mcam->lock);
2771f9274958SSunil Goutham 	return rc;
2772f9274958SSunil Goutham }
2773651cd265SSunil Goutham 
rvu_mbox_handler_npc_mcam_read_entry(struct rvu * rvu,struct npc_mcam_read_entry_req * req,struct npc_mcam_read_entry_rsp * rsp)2774dbab48ceSNaveen Mamindlapalli int rvu_mbox_handler_npc_mcam_read_entry(struct rvu *rvu,
2775dbab48ceSNaveen Mamindlapalli 					 struct npc_mcam_read_entry_req *req,
2776dbab48ceSNaveen Mamindlapalli 					 struct npc_mcam_read_entry_rsp *rsp)
2777dbab48ceSNaveen Mamindlapalli {
2778dbab48ceSNaveen Mamindlapalli 	struct npc_mcam *mcam = &rvu->hw->mcam;
2779dbab48ceSNaveen Mamindlapalli 	u16 pcifunc = req->hdr.pcifunc;
2780dbab48ceSNaveen Mamindlapalli 	int blkaddr, rc;
2781dbab48ceSNaveen Mamindlapalli 
2782dbab48ceSNaveen Mamindlapalli 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
2783dbab48ceSNaveen Mamindlapalli 	if (blkaddr < 0)
2784dbab48ceSNaveen Mamindlapalli 		return NPC_MCAM_INVALID_REQ;
2785dbab48ceSNaveen Mamindlapalli 
2786dbab48ceSNaveen Mamindlapalli 	mutex_lock(&mcam->lock);
2787dbab48ceSNaveen Mamindlapalli 	rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry);
2788dbab48ceSNaveen Mamindlapalli 	if (!rc) {
2789dbab48ceSNaveen Mamindlapalli 		npc_read_mcam_entry(rvu, mcam, blkaddr, req->entry,
2790dbab48ceSNaveen Mamindlapalli 				    &rsp->entry_data,
2791dbab48ceSNaveen Mamindlapalli 				    &rsp->intf, &rsp->enable);
2792dbab48ceSNaveen Mamindlapalli 	}
2793dbab48ceSNaveen Mamindlapalli 
2794dbab48ceSNaveen Mamindlapalli 	mutex_unlock(&mcam->lock);
2795dbab48ceSNaveen Mamindlapalli 	return rc;
2796dbab48ceSNaveen Mamindlapalli }
2797dbab48ceSNaveen Mamindlapalli 
rvu_mbox_handler_npc_mcam_write_entry(struct rvu * rvu,struct npc_mcam_write_entry_req * req,struct msg_rsp * rsp)2798651cd265SSunil Goutham int rvu_mbox_handler_npc_mcam_write_entry(struct rvu *rvu,
2799651cd265SSunil Goutham 					  struct npc_mcam_write_entry_req *req,
2800651cd265SSunil Goutham 					  struct msg_rsp *rsp)
2801651cd265SSunil Goutham {
28021c1935c9SSubbaraya Sundeep 	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
2803651cd265SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
2804651cd265SSunil Goutham 	u16 pcifunc = req->hdr.pcifunc;
2805651cd265SSunil Goutham 	int blkaddr, rc;
28061c1935c9SSubbaraya Sundeep 	u8 nix_intf;
2807651cd265SSunil Goutham 
2808651cd265SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
2809651cd265SSunil Goutham 	if (blkaddr < 0)
2810651cd265SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2811651cd265SSunil Goutham 
2812651cd265SSunil Goutham 	mutex_lock(&mcam->lock);
2813651cd265SSunil Goutham 	rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry);
2814651cd265SSunil Goutham 	if (rc)
2815651cd265SSunil Goutham 		goto exit;
2816651cd265SSunil Goutham 
2817a958dd59SSunil Goutham 	if (req->set_cntr &&
2818a958dd59SSunil Goutham 	    npc_mcam_verify_counter(mcam, pcifunc, req->cntr)) {
2819a958dd59SSunil Goutham 		rc = NPC_MCAM_INVALID_REQ;
2820a958dd59SSunil Goutham 		goto exit;
2821a958dd59SSunil Goutham 	}
2822a958dd59SSunil Goutham 
28231c1935c9SSubbaraya Sundeep 	if (!is_npc_interface_valid(rvu, req->intf)) {
2824651cd265SSunil Goutham 		rc = NPC_MCAM_INVALID_REQ;
2825651cd265SSunil Goutham 		goto exit;
2826651cd265SSunil Goutham 	}
2827651cd265SSunil Goutham 
28281c1935c9SSubbaraya Sundeep 	if (is_npc_intf_tx(req->intf))
28291c1935c9SSubbaraya Sundeep 		nix_intf = pfvf->nix_tx_intf;
28301c1935c9SSubbaraya Sundeep 	else
28311c1935c9SSubbaraya Sundeep 		nix_intf = pfvf->nix_rx_intf;
28321c1935c9SSubbaraya Sundeep 
2833cb7a6b3bSSubbaraya Sundeep 	if (!is_pffunc_af(pcifunc) &&
2834cb7a6b3bSSubbaraya Sundeep 	    npc_mcam_verify_pf_func(rvu, &req->entry_data, req->intf, pcifunc)) {
2835041a1c17SSubbaraya Sundeep 		rc = NPC_MCAM_INVALID_REQ;
2836041a1c17SSubbaraya Sundeep 		goto exit;
2837041a1c17SSubbaraya Sundeep 	}
2838041a1c17SSubbaraya Sundeep 
283963f925dcSNaveen Mamindlapalli 	/* For AF installed rules, the nix_intf should be set to target NIX */
284063f925dcSNaveen Mamindlapalli 	if (is_pffunc_af(req->hdr.pcifunc))
284163f925dcSNaveen Mamindlapalli 		nix_intf = req->intf;
284263f925dcSNaveen Mamindlapalli 
28431c1935c9SSubbaraya Sundeep 	npc_config_mcam_entry(rvu, mcam, blkaddr, req->entry, nix_intf,
2844651cd265SSunil Goutham 			      &req->entry_data, req->enable_entry);
2845651cd265SSunil Goutham 
2846a958dd59SSunil Goutham 	if (req->set_cntr)
2847a958dd59SSunil Goutham 		npc_map_mcam_entry_and_cntr(rvu, mcam, blkaddr,
2848a958dd59SSunil Goutham 					    req->entry, req->cntr);
2849a958dd59SSunil Goutham 
2850651cd265SSunil Goutham 	rc = 0;
2851651cd265SSunil Goutham exit:
2852651cd265SSunil Goutham 	mutex_unlock(&mcam->lock);
2853651cd265SSunil Goutham 	return rc;
2854651cd265SSunil Goutham }
2855651cd265SSunil Goutham 
rvu_mbox_handler_npc_mcam_ena_entry(struct rvu * rvu,struct npc_mcam_ena_dis_entry_req * req,struct msg_rsp * rsp)2856651cd265SSunil Goutham int rvu_mbox_handler_npc_mcam_ena_entry(struct rvu *rvu,
2857651cd265SSunil Goutham 					struct npc_mcam_ena_dis_entry_req *req,
2858651cd265SSunil Goutham 					struct msg_rsp *rsp)
2859651cd265SSunil Goutham {
2860651cd265SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
2861651cd265SSunil Goutham 	u16 pcifunc = req->hdr.pcifunc;
2862651cd265SSunil Goutham 	int blkaddr, rc;
2863651cd265SSunil Goutham 
2864651cd265SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
2865651cd265SSunil Goutham 	if (blkaddr < 0)
2866651cd265SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2867651cd265SSunil Goutham 
2868651cd265SSunil Goutham 	mutex_lock(&mcam->lock);
2869651cd265SSunil Goutham 	rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry);
2870651cd265SSunil Goutham 	mutex_unlock(&mcam->lock);
2871651cd265SSunil Goutham 	if (rc)
2872651cd265SSunil Goutham 		return rc;
2873651cd265SSunil Goutham 
2874651cd265SSunil Goutham 	npc_enable_mcam_entry(rvu, mcam, blkaddr, req->entry, true);
2875651cd265SSunil Goutham 
2876651cd265SSunil Goutham 	return 0;
2877651cd265SSunil Goutham }
2878651cd265SSunil Goutham 
rvu_mbox_handler_npc_mcam_dis_entry(struct rvu * rvu,struct npc_mcam_ena_dis_entry_req * req,struct msg_rsp * rsp)2879651cd265SSunil Goutham int rvu_mbox_handler_npc_mcam_dis_entry(struct rvu *rvu,
2880651cd265SSunil Goutham 					struct npc_mcam_ena_dis_entry_req *req,
2881651cd265SSunil Goutham 					struct msg_rsp *rsp)
2882651cd265SSunil Goutham {
2883651cd265SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
2884651cd265SSunil Goutham 	u16 pcifunc = req->hdr.pcifunc;
2885651cd265SSunil Goutham 	int blkaddr, rc;
2886651cd265SSunil Goutham 
2887651cd265SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
2888651cd265SSunil Goutham 	if (blkaddr < 0)
2889651cd265SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2890651cd265SSunil Goutham 
2891651cd265SSunil Goutham 	mutex_lock(&mcam->lock);
2892651cd265SSunil Goutham 	rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry);
2893651cd265SSunil Goutham 	mutex_unlock(&mcam->lock);
2894651cd265SSunil Goutham 	if (rc)
2895651cd265SSunil Goutham 		return rc;
2896651cd265SSunil Goutham 
2897651cd265SSunil Goutham 	npc_enable_mcam_entry(rvu, mcam, blkaddr, req->entry, false);
2898651cd265SSunil Goutham 
2899651cd265SSunil Goutham 	return 0;
2900651cd265SSunil Goutham }
2901651cd265SSunil Goutham 
rvu_mbox_handler_npc_mcam_shift_entry(struct rvu * rvu,struct npc_mcam_shift_entry_req * req,struct npc_mcam_shift_entry_rsp * rsp)2902651cd265SSunil Goutham int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
2903651cd265SSunil Goutham 					  struct npc_mcam_shift_entry_req *req,
2904651cd265SSunil Goutham 					  struct npc_mcam_shift_entry_rsp *rsp)
2905651cd265SSunil Goutham {
2906651cd265SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
2907651cd265SSunil Goutham 	u16 pcifunc = req->hdr.pcifunc;
2908651cd265SSunil Goutham 	u16 old_entry, new_entry;
2909698a82ebSSubbaraya Sundeep 	int blkaddr, rc = 0;
2910a958dd59SSunil Goutham 	u16 index, cntr;
2911651cd265SSunil Goutham 
2912651cd265SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
2913651cd265SSunil Goutham 	if (blkaddr < 0)
2914651cd265SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2915651cd265SSunil Goutham 
2916651cd265SSunil Goutham 	if (req->shift_count > NPC_MCAM_MAX_SHIFTS)
2917651cd265SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
2918651cd265SSunil Goutham 
2919651cd265SSunil Goutham 	mutex_lock(&mcam->lock);
2920651cd265SSunil Goutham 	for (index = 0; index < req->shift_count; index++) {
2921651cd265SSunil Goutham 		old_entry = req->curr_entry[index];
2922651cd265SSunil Goutham 		new_entry = req->new_entry[index];
2923651cd265SSunil Goutham 
2924651cd265SSunil Goutham 		/* Check if both old and new entries are valid and
2925651cd265SSunil Goutham 		 * does belong to this PFFUNC or not.
2926651cd265SSunil Goutham 		 */
2927651cd265SSunil Goutham 		rc = npc_mcam_verify_entry(mcam, pcifunc, old_entry);
2928651cd265SSunil Goutham 		if (rc)
2929651cd265SSunil Goutham 			break;
2930651cd265SSunil Goutham 
2931651cd265SSunil Goutham 		rc = npc_mcam_verify_entry(mcam, pcifunc, new_entry);
2932651cd265SSunil Goutham 		if (rc)
2933651cd265SSunil Goutham 			break;
2934651cd265SSunil Goutham 
2935a958dd59SSunil Goutham 		/* new_entry should not have a counter mapped */
2936a958dd59SSunil Goutham 		if (mcam->entry2cntr_map[new_entry] != NPC_MCAM_INVALID_MAP) {
2937a958dd59SSunil Goutham 			rc = NPC_MCAM_PERM_DENIED;
2938a958dd59SSunil Goutham 			break;
2939a958dd59SSunil Goutham 		}
2940a958dd59SSunil Goutham 
2941651cd265SSunil Goutham 		/* Disable the new_entry */
2942651cd265SSunil Goutham 		npc_enable_mcam_entry(rvu, mcam, blkaddr, new_entry, false);
2943651cd265SSunil Goutham 
2944651cd265SSunil Goutham 		/* Copy rule from old entry to new entry */
2945651cd265SSunil Goutham 		npc_copy_mcam_entry(rvu, mcam, blkaddr, old_entry, new_entry);
2946651cd265SSunil Goutham 
2947a958dd59SSunil Goutham 		/* Copy counter mapping, if any */
2948a958dd59SSunil Goutham 		cntr = mcam->entry2cntr_map[old_entry];
2949a958dd59SSunil Goutham 		if (cntr != NPC_MCAM_INVALID_MAP) {
2950a958dd59SSunil Goutham 			npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
2951a958dd59SSunil Goutham 						      old_entry, cntr);
2952a958dd59SSunil Goutham 			npc_map_mcam_entry_and_cntr(rvu, mcam, blkaddr,
2953a958dd59SSunil Goutham 						    new_entry, cntr);
2954a958dd59SSunil Goutham 		}
2955a958dd59SSunil Goutham 
2956651cd265SSunil Goutham 		/* Enable new_entry and disable old_entry */
2957651cd265SSunil Goutham 		npc_enable_mcam_entry(rvu, mcam, blkaddr, new_entry, true);
2958651cd265SSunil Goutham 		npc_enable_mcam_entry(rvu, mcam, blkaddr, old_entry, false);
2959651cd265SSunil Goutham 	}
2960651cd265SSunil Goutham 
2961651cd265SSunil Goutham 	/* If shift has failed then report the failed index */
2962651cd265SSunil Goutham 	if (index != req->shift_count) {
2963651cd265SSunil Goutham 		rc = NPC_MCAM_PERM_DENIED;
2964651cd265SSunil Goutham 		rsp->failed_entry_idx = index;
2965651cd265SSunil Goutham 	}
2966651cd265SSunil Goutham 
2967651cd265SSunil Goutham 	mutex_unlock(&mcam->lock);
2968651cd265SSunil Goutham 	return rc;
2969651cd265SSunil Goutham }
29707fbb3f23SSunil Goutham 
rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu * rvu,struct npc_mcam_alloc_counter_req * req,struct npc_mcam_alloc_counter_rsp * rsp)29717fbb3f23SSunil Goutham int rvu_mbox_handler_npc_mcam_alloc_counter(struct rvu *rvu,
29727fbb3f23SSunil Goutham 			struct npc_mcam_alloc_counter_req *req,
29737fbb3f23SSunil Goutham 			struct npc_mcam_alloc_counter_rsp *rsp)
29747fbb3f23SSunil Goutham {
29757fbb3f23SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
29767fbb3f23SSunil Goutham 	u16 pcifunc = req->hdr.pcifunc;
29777fbb3f23SSunil Goutham 	u16 max_contig, cntr;
29787fbb3f23SSunil Goutham 	int blkaddr, index;
29797fbb3f23SSunil Goutham 
29807fbb3f23SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
29817fbb3f23SSunil Goutham 	if (blkaddr < 0)
29827fbb3f23SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
29837fbb3f23SSunil Goutham 
29847fbb3f23SSunil Goutham 	/* If the request is from a PFFUNC with no NIXLF attached, ignore */
2985cb7a6b3bSSubbaraya Sundeep 	if (!is_pffunc_af(pcifunc) && !is_nixlf_attached(rvu, pcifunc))
29867fbb3f23SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
29877fbb3f23SSunil Goutham 
29887fbb3f23SSunil Goutham 	/* Since list of allocated counter IDs needs to be sent to requester,
29897fbb3f23SSunil Goutham 	 * max number of non-contiguous counters per mbox msg is limited.
29907fbb3f23SSunil Goutham 	 */
29917fbb3f23SSunil Goutham 	if (!req->contig && req->count > NPC_MAX_NONCONTIG_COUNTERS)
29927fbb3f23SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
29937fbb3f23SSunil Goutham 
29947fbb3f23SSunil Goutham 	mutex_lock(&mcam->lock);
29957fbb3f23SSunil Goutham 
29967fbb3f23SSunil Goutham 	/* Check if unused counters are available or not */
29977fbb3f23SSunil Goutham 	if (!rvu_rsrc_free_count(&mcam->counters)) {
29987fbb3f23SSunil Goutham 		mutex_unlock(&mcam->lock);
29997fbb3f23SSunil Goutham 		return NPC_MCAM_ALLOC_FAILED;
30007fbb3f23SSunil Goutham 	}
30017fbb3f23SSunil Goutham 
30027fbb3f23SSunil Goutham 	rsp->count = 0;
30037fbb3f23SSunil Goutham 
30047fbb3f23SSunil Goutham 	if (req->contig) {
30057fbb3f23SSunil Goutham 		/* Allocate requested number of contiguous counters, if
30067fbb3f23SSunil Goutham 		 * unsuccessful find max contiguous entries available.
30077fbb3f23SSunil Goutham 		 */
30087fbb3f23SSunil Goutham 		index = npc_mcam_find_zero_area(mcam->counters.bmap,
30097fbb3f23SSunil Goutham 						mcam->counters.max, 0,
30107fbb3f23SSunil Goutham 						req->count, &max_contig);
30117fbb3f23SSunil Goutham 		rsp->count = max_contig;
30127fbb3f23SSunil Goutham 		rsp->cntr = index;
30137fbb3f23SSunil Goutham 		for (cntr = index; cntr < (index + max_contig); cntr++) {
30147fbb3f23SSunil Goutham 			__set_bit(cntr, mcam->counters.bmap);
30157fbb3f23SSunil Goutham 			mcam->cntr2pfvf_map[cntr] = pcifunc;
30167fbb3f23SSunil Goutham 		}
30177fbb3f23SSunil Goutham 	} else {
30187fbb3f23SSunil Goutham 		/* Allocate requested number of non-contiguous counters,
30197fbb3f23SSunil Goutham 		 * if unsuccessful allocate as many as possible.
30207fbb3f23SSunil Goutham 		 */
30217fbb3f23SSunil Goutham 		for (cntr = 0; cntr < req->count; cntr++) {
30227fbb3f23SSunil Goutham 			index = rvu_alloc_rsrc(&mcam->counters);
30237fbb3f23SSunil Goutham 			if (index < 0)
30247fbb3f23SSunil Goutham 				break;
30257fbb3f23SSunil Goutham 			rsp->cntr_list[cntr] = index;
30267fbb3f23SSunil Goutham 			rsp->count++;
30277fbb3f23SSunil Goutham 			mcam->cntr2pfvf_map[index] = pcifunc;
30287fbb3f23SSunil Goutham 		}
30297fbb3f23SSunil Goutham 	}
30307fbb3f23SSunil Goutham 
30317fbb3f23SSunil Goutham 	mutex_unlock(&mcam->lock);
30327fbb3f23SSunil Goutham 	return 0;
30337fbb3f23SSunil Goutham }
30347fbb3f23SSunil Goutham 
rvu_mbox_handler_npc_mcam_free_counter(struct rvu * rvu,struct npc_mcam_oper_counter_req * req,struct msg_rsp * rsp)30357fbb3f23SSunil Goutham int rvu_mbox_handler_npc_mcam_free_counter(struct rvu *rvu,
30367fbb3f23SSunil Goutham 		struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp)
30377fbb3f23SSunil Goutham {
30387fbb3f23SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
3039a958dd59SSunil Goutham 	u16 index, entry = 0;
3040a958dd59SSunil Goutham 	int blkaddr, err;
3041a958dd59SSunil Goutham 
3042a958dd59SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
3043a958dd59SSunil Goutham 	if (blkaddr < 0)
3044a958dd59SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
30457fbb3f23SSunil Goutham 
30467fbb3f23SSunil Goutham 	mutex_lock(&mcam->lock);
30477fbb3f23SSunil Goutham 	err = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr);
30487fbb3f23SSunil Goutham 	if (err) {
30497fbb3f23SSunil Goutham 		mutex_unlock(&mcam->lock);
30507fbb3f23SSunil Goutham 		return err;
30517fbb3f23SSunil Goutham 	}
30527fbb3f23SSunil Goutham 
30537fbb3f23SSunil Goutham 	/* Mark counter as free/unused */
30547fbb3f23SSunil Goutham 	mcam->cntr2pfvf_map[req->cntr] = NPC_MCAM_INVALID_MAP;
30557fbb3f23SSunil Goutham 	rvu_free_rsrc(&mcam->counters, req->cntr);
30567fbb3f23SSunil Goutham 
3057a958dd59SSunil Goutham 	/* Disable all MCAM entry's stats which are using this counter */
3058a958dd59SSunil Goutham 	while (entry < mcam->bmap_entries) {
3059a958dd59SSunil Goutham 		if (!mcam->cntr_refcnt[req->cntr])
3060a958dd59SSunil Goutham 			break;
3061a958dd59SSunil Goutham 
3062a958dd59SSunil Goutham 		index = find_next_bit(mcam->bmap, mcam->bmap_entries, entry);
3063a958dd59SSunil Goutham 		if (index >= mcam->bmap_entries)
3064a958dd59SSunil Goutham 			break;
306564451b98SHariprasad Kelam 		entry = index + 1;
3066a958dd59SSunil Goutham 		if (mcam->entry2cntr_map[index] != req->cntr)
3067a958dd59SSunil Goutham 			continue;
3068a958dd59SSunil Goutham 
3069a958dd59SSunil Goutham 		npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
3070a958dd59SSunil Goutham 					      index, req->cntr);
3071a958dd59SSunil Goutham 	}
3072a958dd59SSunil Goutham 
3073a958dd59SSunil Goutham 	mutex_unlock(&mcam->lock);
30747fbb3f23SSunil Goutham 	return 0;
30757fbb3f23SSunil Goutham }
30767fbb3f23SSunil Goutham 
rvu_mbox_handler_npc_mcam_unmap_counter(struct rvu * rvu,struct npc_mcam_unmap_counter_req * req,struct msg_rsp * rsp)3077a958dd59SSunil Goutham int rvu_mbox_handler_npc_mcam_unmap_counter(struct rvu *rvu,
3078a958dd59SSunil Goutham 		struct npc_mcam_unmap_counter_req *req, struct msg_rsp *rsp)
3079a958dd59SSunil Goutham {
3080a958dd59SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
3081a958dd59SSunil Goutham 	u16 index, entry = 0;
3082a958dd59SSunil Goutham 	int blkaddr, rc;
3083a958dd59SSunil Goutham 
3084a958dd59SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
3085a958dd59SSunil Goutham 	if (blkaddr < 0)
3086a958dd59SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
3087a958dd59SSunil Goutham 
3088a958dd59SSunil Goutham 	mutex_lock(&mcam->lock);
3089a958dd59SSunil Goutham 	rc = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr);
3090a958dd59SSunil Goutham 	if (rc)
3091a958dd59SSunil Goutham 		goto exit;
3092a958dd59SSunil Goutham 
3093a958dd59SSunil Goutham 	/* Unmap the MCAM entry and counter */
3094a958dd59SSunil Goutham 	if (!req->all) {
3095a958dd59SSunil Goutham 		rc = npc_mcam_verify_entry(mcam, req->hdr.pcifunc, req->entry);
3096a958dd59SSunil Goutham 		if (rc)
3097a958dd59SSunil Goutham 			goto exit;
3098a958dd59SSunil Goutham 		npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
3099a958dd59SSunil Goutham 					      req->entry, req->cntr);
3100a958dd59SSunil Goutham 		goto exit;
3101a958dd59SSunil Goutham 	}
3102a958dd59SSunil Goutham 
3103a958dd59SSunil Goutham 	/* Disable all MCAM entry's stats which are using this counter */
3104a958dd59SSunil Goutham 	while (entry < mcam->bmap_entries) {
3105a958dd59SSunil Goutham 		if (!mcam->cntr_refcnt[req->cntr])
3106a958dd59SSunil Goutham 			break;
3107a958dd59SSunil Goutham 
3108a958dd59SSunil Goutham 		index = find_next_bit(mcam->bmap, mcam->bmap_entries, entry);
3109a958dd59SSunil Goutham 		if (index >= mcam->bmap_entries)
3110a958dd59SSunil Goutham 			break;
31116537e96dSSubbaraya Sundeep 		entry = index + 1;
31126537e96dSSubbaraya Sundeep 
3113a958dd59SSunil Goutham 		if (mcam->entry2cntr_map[index] != req->cntr)
3114a958dd59SSunil Goutham 			continue;
3115a958dd59SSunil Goutham 
3116a958dd59SSunil Goutham 		npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
3117a958dd59SSunil Goutham 					      index, req->cntr);
3118a958dd59SSunil Goutham 	}
3119a958dd59SSunil Goutham exit:
3120a958dd59SSunil Goutham 	mutex_unlock(&mcam->lock);
3121a958dd59SSunil Goutham 	return rc;
3122a958dd59SSunil Goutham }
3123a958dd59SSunil Goutham 
rvu_mbox_handler_npc_mcam_clear_counter(struct rvu * rvu,struct npc_mcam_oper_counter_req * req,struct msg_rsp * rsp)31247fbb3f23SSunil Goutham int rvu_mbox_handler_npc_mcam_clear_counter(struct rvu *rvu,
31257fbb3f23SSunil Goutham 		struct npc_mcam_oper_counter_req *req, struct msg_rsp *rsp)
31267fbb3f23SSunil Goutham {
31277fbb3f23SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
31287fbb3f23SSunil Goutham 	int blkaddr, err;
31297fbb3f23SSunil Goutham 
31307fbb3f23SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
31317fbb3f23SSunil Goutham 	if (blkaddr < 0)
31327fbb3f23SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
31337fbb3f23SSunil Goutham 
31347fbb3f23SSunil Goutham 	mutex_lock(&mcam->lock);
31357fbb3f23SSunil Goutham 	err = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr);
31367fbb3f23SSunil Goutham 	mutex_unlock(&mcam->lock);
31377fbb3f23SSunil Goutham 	if (err)
31387fbb3f23SSunil Goutham 		return err;
31397fbb3f23SSunil Goutham 
31407fbb3f23SSunil Goutham 	rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(req->cntr), 0x00);
31417fbb3f23SSunil Goutham 
31427fbb3f23SSunil Goutham 	return 0;
31437fbb3f23SSunil Goutham }
31447fbb3f23SSunil Goutham 
rvu_mbox_handler_npc_mcam_counter_stats(struct rvu * rvu,struct npc_mcam_oper_counter_req * req,struct npc_mcam_oper_counter_rsp * rsp)31457fbb3f23SSunil Goutham int rvu_mbox_handler_npc_mcam_counter_stats(struct rvu *rvu,
31467fbb3f23SSunil Goutham 			struct npc_mcam_oper_counter_req *req,
31477fbb3f23SSunil Goutham 			struct npc_mcam_oper_counter_rsp *rsp)
31487fbb3f23SSunil Goutham {
31497fbb3f23SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
31507fbb3f23SSunil Goutham 	int blkaddr, err;
31517fbb3f23SSunil Goutham 
31527fbb3f23SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
31537fbb3f23SSunil Goutham 	if (blkaddr < 0)
31547fbb3f23SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
31557fbb3f23SSunil Goutham 
31567fbb3f23SSunil Goutham 	mutex_lock(&mcam->lock);
31577fbb3f23SSunil Goutham 	err = npc_mcam_verify_counter(mcam, req->hdr.pcifunc, req->cntr);
31587fbb3f23SSunil Goutham 	mutex_unlock(&mcam->lock);
31597fbb3f23SSunil Goutham 	if (err)
31607fbb3f23SSunil Goutham 		return err;
31617fbb3f23SSunil Goutham 
31627fbb3f23SSunil Goutham 	rsp->stat = rvu_read64(rvu, blkaddr, NPC_AF_MATCH_STATX(req->cntr));
31637fbb3f23SSunil Goutham 	rsp->stat &= BIT_ULL(48) - 1;
31647fbb3f23SSunil Goutham 
31657fbb3f23SSunil Goutham 	return 0;
31667fbb3f23SSunil Goutham }
316763be91c8SSunil Goutham 
rvu_mbox_handler_npc_mcam_alloc_and_write_entry(struct rvu * rvu,struct npc_mcam_alloc_and_write_entry_req * req,struct npc_mcam_alloc_and_write_entry_rsp * rsp)316863be91c8SSunil Goutham int rvu_mbox_handler_npc_mcam_alloc_and_write_entry(struct rvu *rvu,
316963be91c8SSunil Goutham 			  struct npc_mcam_alloc_and_write_entry_req *req,
317063be91c8SSunil Goutham 			  struct npc_mcam_alloc_and_write_entry_rsp *rsp)
317163be91c8SSunil Goutham {
31721c1935c9SSubbaraya Sundeep 	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
317363be91c8SSunil Goutham 	struct npc_mcam_alloc_counter_req cntr_req;
317463be91c8SSunil Goutham 	struct npc_mcam_alloc_counter_rsp cntr_rsp;
317563be91c8SSunil Goutham 	struct npc_mcam_alloc_entry_req entry_req;
317663be91c8SSunil Goutham 	struct npc_mcam_alloc_entry_rsp entry_rsp;
317763be91c8SSunil Goutham 	struct npc_mcam *mcam = &rvu->hw->mcam;
317863be91c8SSunil Goutham 	u16 entry = NPC_MCAM_ENTRY_INVALID;
317963be91c8SSunil Goutham 	u16 cntr = NPC_MCAM_ENTRY_INVALID;
318063be91c8SSunil Goutham 	int blkaddr, rc;
31811c1935c9SSubbaraya Sundeep 	u8 nix_intf;
318263be91c8SSunil Goutham 
318363be91c8SSunil Goutham 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
318463be91c8SSunil Goutham 	if (blkaddr < 0)
318563be91c8SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
318663be91c8SSunil Goutham 
31871c1935c9SSubbaraya Sundeep 	if (!is_npc_interface_valid(rvu, req->intf))
318863be91c8SSunil Goutham 		return NPC_MCAM_INVALID_REQ;
318963be91c8SSunil Goutham 
3190041a1c17SSubbaraya Sundeep 	if (npc_mcam_verify_pf_func(rvu, &req->entry_data, req->intf,
3191041a1c17SSubbaraya Sundeep 				    req->hdr.pcifunc))
3192041a1c17SSubbaraya Sundeep 		return NPC_MCAM_INVALID_REQ;
3193041a1c17SSubbaraya Sundeep 
319463be91c8SSunil Goutham 	/* Try to allocate a MCAM entry */
319563be91c8SSunil Goutham 	entry_req.hdr.pcifunc = req->hdr.pcifunc;
319663be91c8SSunil Goutham 	entry_req.contig = true;
319763be91c8SSunil Goutham 	entry_req.priority = req->priority;
319863be91c8SSunil Goutham 	entry_req.ref_entry = req->ref_entry;
319963be91c8SSunil Goutham 	entry_req.count = 1;
320063be91c8SSunil Goutham 
320163be91c8SSunil Goutham 	rc = rvu_mbox_handler_npc_mcam_alloc_entry(rvu,
320263be91c8SSunil Goutham 						   &entry_req, &entry_rsp);
320363be91c8SSunil Goutham 	if (rc)
320463be91c8SSunil Goutham 		return rc;
320563be91c8SSunil Goutham 
320663be91c8SSunil Goutham 	if (!entry_rsp.count)
320763be91c8SSunil Goutham 		return NPC_MCAM_ALLOC_FAILED;
320863be91c8SSunil Goutham 
320963be91c8SSunil Goutham 	entry = entry_rsp.entry;
321063be91c8SSunil Goutham 
321163be91c8SSunil Goutham 	if (!req->alloc_cntr)
321263be91c8SSunil Goutham 		goto write_entry;
321363be91c8SSunil Goutham 
321463be91c8SSunil Goutham 	/* Now allocate counter */
321563be91c8SSunil Goutham 	cntr_req.hdr.pcifunc = req->hdr.pcifunc;
321663be91c8SSunil Goutham 	cntr_req.contig = true;
321763be91c8SSunil Goutham 	cntr_req.count = 1;
321863be91c8SSunil Goutham 
321963be91c8SSunil Goutham 	rc = rvu_mbox_handler_npc_mcam_alloc_counter(rvu, &cntr_req, &cntr_rsp);
322063be91c8SSunil Goutham 	if (rc) {
322163be91c8SSunil Goutham 		/* Free allocated MCAM entry */
322263be91c8SSunil Goutham 		mutex_lock(&mcam->lock);
3223cb7a6b3bSSubbaraya Sundeep 		mcam->entry2pfvf_map[entry] = NPC_MCAM_INVALID_MAP;
322463be91c8SSunil Goutham 		npc_mcam_clear_bit(mcam, entry);
322563be91c8SSunil Goutham 		mutex_unlock(&mcam->lock);
322663be91c8SSunil Goutham 		return rc;
322763be91c8SSunil Goutham 	}
322863be91c8SSunil Goutham 
322963be91c8SSunil Goutham 	cntr = cntr_rsp.cntr;
323063be91c8SSunil Goutham 
323163be91c8SSunil Goutham write_entry:
323263be91c8SSunil Goutham 	mutex_lock(&mcam->lock);
32331c1935c9SSubbaraya Sundeep 
32341c1935c9SSubbaraya Sundeep 	if (is_npc_intf_tx(req->intf))
32351c1935c9SSubbaraya Sundeep 		nix_intf = pfvf->nix_tx_intf;
32361c1935c9SSubbaraya Sundeep 	else
32371c1935c9SSubbaraya Sundeep 		nix_intf = pfvf->nix_rx_intf;
32381c1935c9SSubbaraya Sundeep 
32391c1935c9SSubbaraya Sundeep 	npc_config_mcam_entry(rvu, mcam, blkaddr, entry, nix_intf,
324063be91c8SSunil Goutham 			      &req->entry_data, req->enable_entry);
324163be91c8SSunil Goutham 
324263be91c8SSunil Goutham 	if (req->alloc_cntr)
324363be91c8SSunil Goutham 		npc_map_mcam_entry_and_cntr(rvu, mcam, blkaddr, entry, cntr);
324463be91c8SSunil Goutham 	mutex_unlock(&mcam->lock);
324563be91c8SSunil Goutham 
324663be91c8SSunil Goutham 	rsp->entry = entry;
324763be91c8SSunil Goutham 	rsp->cntr = cntr;
324863be91c8SSunil Goutham 
324963be91c8SSunil Goutham 	return 0;
325063be91c8SSunil Goutham }
3251631e70bbSSantosh Shukla 
3252631e70bbSSantosh Shukla #define GET_KEX_CFG(intf) \
3253631e70bbSSantosh Shukla 	rvu_read64(rvu, BLKADDR_NPC, NPC_AF_INTFX_KEX_CFG(intf))
3254631e70bbSSantosh Shukla 
3255631e70bbSSantosh Shukla #define GET_KEX_FLAGS(ld) \
3256631e70bbSSantosh Shukla 	rvu_read64(rvu, BLKADDR_NPC, NPC_AF_KEX_LDATAX_FLAGS_CFG(ld))
3257631e70bbSSantosh Shukla 
3258631e70bbSSantosh Shukla #define GET_KEX_LD(intf, lid, lt, ld)	\
3259631e70bbSSantosh Shukla 	rvu_read64(rvu, BLKADDR_NPC,	\
3260631e70bbSSantosh Shukla 		NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf, lid, lt, ld))
3261631e70bbSSantosh Shukla 
3262631e70bbSSantosh Shukla #define GET_KEX_LDFLAGS(intf, ld, fl)	\
3263631e70bbSSantosh Shukla 	rvu_read64(rvu, BLKADDR_NPC,	\
3264631e70bbSSantosh Shukla 		NPC_AF_INTFX_LDATAX_FLAGSX_CFG(intf, ld, fl))
3265631e70bbSSantosh Shukla 
rvu_mbox_handler_npc_get_kex_cfg(struct rvu * rvu,struct msg_req * req,struct npc_get_kex_cfg_rsp * rsp)3266631e70bbSSantosh Shukla int rvu_mbox_handler_npc_get_kex_cfg(struct rvu *rvu, struct msg_req *req,
3267631e70bbSSantosh Shukla 				     struct npc_get_kex_cfg_rsp *rsp)
3268631e70bbSSantosh Shukla {
3269631e70bbSSantosh Shukla 	int lid, lt, ld, fl;
3270631e70bbSSantosh Shukla 
3271631e70bbSSantosh Shukla 	rsp->rx_keyx_cfg = GET_KEX_CFG(NIX_INTF_RX);
3272631e70bbSSantosh Shukla 	rsp->tx_keyx_cfg = GET_KEX_CFG(NIX_INTF_TX);
3273631e70bbSSantosh Shukla 	for (lid = 0; lid < NPC_MAX_LID; lid++) {
3274631e70bbSSantosh Shukla 		for (lt = 0; lt < NPC_MAX_LT; lt++) {
3275631e70bbSSantosh Shukla 			for (ld = 0; ld < NPC_MAX_LD; ld++) {
3276631e70bbSSantosh Shukla 				rsp->intf_lid_lt_ld[NIX_INTF_RX][lid][lt][ld] =
3277631e70bbSSantosh Shukla 					GET_KEX_LD(NIX_INTF_RX, lid, lt, ld);
3278631e70bbSSantosh Shukla 				rsp->intf_lid_lt_ld[NIX_INTF_TX][lid][lt][ld] =
3279631e70bbSSantosh Shukla 					GET_KEX_LD(NIX_INTF_TX, lid, lt, ld);
3280631e70bbSSantosh Shukla 			}
3281631e70bbSSantosh Shukla 		}
3282631e70bbSSantosh Shukla 	}
3283631e70bbSSantosh Shukla 	for (ld = 0; ld < NPC_MAX_LD; ld++)
3284631e70bbSSantosh Shukla 		rsp->kex_ld_flags[ld] = GET_KEX_FLAGS(ld);
3285631e70bbSSantosh Shukla 
3286631e70bbSSantosh Shukla 	for (ld = 0; ld < NPC_MAX_LD; ld++) {
3287631e70bbSSantosh Shukla 		for (fl = 0; fl < NPC_MAX_LFL; fl++) {
3288631e70bbSSantosh Shukla 			rsp->intf_ld_flags[NIX_INTF_RX][ld][fl] =
3289631e70bbSSantosh Shukla 					GET_KEX_LDFLAGS(NIX_INTF_RX, ld, fl);
3290631e70bbSSantosh Shukla 			rsp->intf_ld_flags[NIX_INTF_TX][ld][fl] =
3291631e70bbSSantosh Shukla 					GET_KEX_LDFLAGS(NIX_INTF_TX, ld, fl);
3292631e70bbSSantosh Shukla 		}
3293631e70bbSSantosh Shukla 	}
329423705adbSVamsi Attunuru 	memcpy(rsp->mkex_pfl_name, rvu->mkex_pfl_name, MKEX_NAME_LEN);
3295631e70bbSSantosh Shukla 	return 0;
3296631e70bbSSantosh Shukla }
329786cea61dSTomasz Duszynski 
329885212a12SKiran Kumar K static int
npc_set_var_len_offset_pkind(struct rvu * rvu,u16 pcifunc,u64 pkind,u8 var_len_off,u8 var_len_off_mask,u8 shift_dir)3299edadeb38SKiran Kumar K npc_set_var_len_offset_pkind(struct rvu *rvu, u16 pcifunc, u64 pkind,
3300edadeb38SKiran Kumar K 			     u8 var_len_off, u8 var_len_off_mask, u8 shift_dir)
3301edadeb38SKiran Kumar K {
3302edadeb38SKiran Kumar K 	struct npc_kpu_action0 *act0;
3303edadeb38SKiran Kumar K 	u8 shift_count = 0;
3304edadeb38SKiran Kumar K 	int blkaddr;
3305edadeb38SKiran Kumar K 	u64 val;
3306edadeb38SKiran Kumar K 
3307edadeb38SKiran Kumar K 	if (!var_len_off_mask)
3308edadeb38SKiran Kumar K 		return -EINVAL;
3309edadeb38SKiran Kumar K 
3310edadeb38SKiran Kumar K 	if (var_len_off_mask != 0xff) {
3311edadeb38SKiran Kumar K 		if (shift_dir)
3312edadeb38SKiran Kumar K 			shift_count = __ffs(var_len_off_mask);
3313edadeb38SKiran Kumar K 		else
3314edadeb38SKiran Kumar K 			shift_count = (8 - __fls(var_len_off_mask));
3315edadeb38SKiran Kumar K 	}
3316edadeb38SKiran Kumar K 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, pcifunc);
3317edadeb38SKiran Kumar K 	if (blkaddr < 0) {
3318edadeb38SKiran Kumar K 		dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
3319edadeb38SKiran Kumar K 		return -EINVAL;
3320edadeb38SKiran Kumar K 	}
3321edadeb38SKiran Kumar K 	val = rvu_read64(rvu, blkaddr, NPC_AF_PKINDX_ACTION0(pkind));
3322edadeb38SKiran Kumar K 	act0 = (struct npc_kpu_action0 *)&val;
3323edadeb38SKiran Kumar K 	act0->var_len_shift = shift_count;
3324edadeb38SKiran Kumar K 	act0->var_len_right = shift_dir;
3325edadeb38SKiran Kumar K 	act0->var_len_mask = var_len_off_mask;
3326edadeb38SKiran Kumar K 	act0->var_len_offset = var_len_off;
3327edadeb38SKiran Kumar K 	rvu_write64(rvu, blkaddr, NPC_AF_PKINDX_ACTION0(pkind), val);
3328edadeb38SKiran Kumar K 	return 0;
3329edadeb38SKiran Kumar K }
3330edadeb38SKiran Kumar K 
rvu_npc_set_parse_mode(struct rvu * rvu,u16 pcifunc,u64 mode,u8 dir,u64 pkind,u8 var_len_off,u8 var_len_off_mask,u8 shift_dir)3331edadeb38SKiran Kumar K int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
3332edadeb38SKiran Kumar K 			   u64 pkind, u8 var_len_off, u8 var_len_off_mask,
3333edadeb38SKiran Kumar K 			   u8 shift_dir)
3334edadeb38SKiran Kumar K 
3335edadeb38SKiran Kumar K {
3336edadeb38SKiran Kumar K 	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
3337edadeb38SKiran Kumar K 	int blkaddr, nixlf, rc, intf_mode;
3338edadeb38SKiran Kumar K 	int pf = rvu_get_pf(pcifunc);
3339edadeb38SKiran Kumar K 	u64 rxpkind, txpkind;
3340edadeb38SKiran Kumar K 	u8 cgx_id, lmac_id;
3341edadeb38SKiran Kumar K 
3342edadeb38SKiran Kumar K 	/* use default pkind to disable edsa/higig */
3343edadeb38SKiran Kumar K 	rxpkind = rvu_npc_get_pkind(rvu, pf);
3344edadeb38SKiran Kumar K 	txpkind = NPC_TX_DEF_PKIND;
3345edadeb38SKiran Kumar K 	intf_mode = NPC_INTF_MODE_DEF;
3346edadeb38SKiran Kumar K 
3347edadeb38SKiran Kumar K 	if (mode & OTX2_PRIV_FLAGS_CUSTOM) {
3348edadeb38SKiran Kumar K 		if (pkind == NPC_RX_CUSTOM_PRE_L2_PKIND) {
3349edadeb38SKiran Kumar K 			rc = npc_set_var_len_offset_pkind(rvu, pcifunc, pkind,
3350edadeb38SKiran Kumar K 							  var_len_off,
3351edadeb38SKiran Kumar K 							  var_len_off_mask,
3352edadeb38SKiran Kumar K 							  shift_dir);
3353edadeb38SKiran Kumar K 			if (rc)
3354edadeb38SKiran Kumar K 				return rc;
3355edadeb38SKiran Kumar K 		}
3356edadeb38SKiran Kumar K 		rxpkind = pkind;
3357edadeb38SKiran Kumar K 		txpkind = pkind;
3358edadeb38SKiran Kumar K 	}
3359edadeb38SKiran Kumar K 
3360edadeb38SKiran Kumar K 	if (dir & PKIND_RX) {
3361edadeb38SKiran Kumar K 		/* rx pkind set req valid only for cgx mapped PFs */
3362edadeb38SKiran Kumar K 		if (!is_cgx_config_permitted(rvu, pcifunc))
3363edadeb38SKiran Kumar K 			return 0;
3364edadeb38SKiran Kumar K 		rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
3365edadeb38SKiran Kumar K 
3366edadeb38SKiran Kumar K 		rc = cgx_set_pkind(rvu_cgx_pdata(cgx_id, rvu), lmac_id,
3367edadeb38SKiran Kumar K 				   rxpkind);
3368edadeb38SKiran Kumar K 		if (rc)
3369edadeb38SKiran Kumar K 			return rc;
3370edadeb38SKiran Kumar K 	}
3371edadeb38SKiran Kumar K 
3372edadeb38SKiran Kumar K 	if (dir & PKIND_TX) {
3373edadeb38SKiran Kumar K 		/* Tx pkind set request valid if PCIFUNC has NIXLF attached */
3374edadeb38SKiran Kumar K 		rc = nix_get_nixlf(rvu, pcifunc, &nixlf, &blkaddr);
3375edadeb38SKiran Kumar K 		if (rc)
3376edadeb38SKiran Kumar K 			return rc;
3377edadeb38SKiran Kumar K 
3378edadeb38SKiran Kumar K 		rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf),
3379edadeb38SKiran Kumar K 			    txpkind);
3380edadeb38SKiran Kumar K 	}
3381edadeb38SKiran Kumar K 
3382edadeb38SKiran Kumar K 	pfvf->intf_mode = intf_mode;
3383edadeb38SKiran Kumar K 	return 0;
3384edadeb38SKiran Kumar K }
3385edadeb38SKiran Kumar K 
rvu_mbox_handler_npc_set_pkind(struct rvu * rvu,struct npc_set_pkind * req,struct msg_rsp * rsp)3386edadeb38SKiran Kumar K int rvu_mbox_handler_npc_set_pkind(struct rvu *rvu, struct npc_set_pkind *req,
3387edadeb38SKiran Kumar K 				   struct msg_rsp *rsp)
3388edadeb38SKiran Kumar K {
3389edadeb38SKiran Kumar K 	return rvu_npc_set_parse_mode(rvu, req->hdr.pcifunc, req->mode,
3390edadeb38SKiran Kumar K 				      req->dir, req->pkind, req->var_len_off,
3391edadeb38SKiran Kumar K 				      req->var_len_off_mask, req->shift_dir);
3392edadeb38SKiran Kumar K }
3393edadeb38SKiran Kumar K 
rvu_mbox_handler_npc_read_base_steer_rule(struct rvu * rvu,struct msg_req * req,struct npc_mcam_read_base_rule_rsp * rsp)3394dbab48ceSNaveen Mamindlapalli int rvu_mbox_handler_npc_read_base_steer_rule(struct rvu *rvu,
3395dbab48ceSNaveen Mamindlapalli 					      struct msg_req *req,
3396dbab48ceSNaveen Mamindlapalli 					      struct npc_mcam_read_base_rule_rsp *rsp)
3397dbab48ceSNaveen Mamindlapalli {
3398dbab48ceSNaveen Mamindlapalli 	struct npc_mcam *mcam = &rvu->hw->mcam;
3399dbab48ceSNaveen Mamindlapalli 	int index, blkaddr, nixlf, rc = 0;
3400dbab48ceSNaveen Mamindlapalli 	u16 pcifunc = req->hdr.pcifunc;
3401dbab48ceSNaveen Mamindlapalli 	struct rvu_pfvf *pfvf;
3402dbab48ceSNaveen Mamindlapalli 	u8 intf, enable;
3403dbab48ceSNaveen Mamindlapalli 
3404dbab48ceSNaveen Mamindlapalli 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
3405dbab48ceSNaveen Mamindlapalli 	if (blkaddr < 0)
3406dbab48ceSNaveen Mamindlapalli 		return NPC_MCAM_INVALID_REQ;
3407dbab48ceSNaveen Mamindlapalli 
3408dbab48ceSNaveen Mamindlapalli 	/* Return the channel number in case of PF */
3409dbab48ceSNaveen Mamindlapalli 	if (!(pcifunc & RVU_PFVF_FUNC_MASK)) {
3410dbab48ceSNaveen Mamindlapalli 		pfvf = rvu_get_pfvf(rvu, pcifunc);
3411dbab48ceSNaveen Mamindlapalli 		rsp->entry.kw[0] = pfvf->rx_chan_base;
3412dbab48ceSNaveen Mamindlapalli 		rsp->entry.kw_mask[0] = 0xFFFULL;
3413dbab48ceSNaveen Mamindlapalli 		goto out;
3414dbab48ceSNaveen Mamindlapalli 	}
3415dbab48ceSNaveen Mamindlapalli 
3416dbab48ceSNaveen Mamindlapalli 	/* Find the pkt steering rule installed by PF to this VF */
3417dbab48ceSNaveen Mamindlapalli 	mutex_lock(&mcam->lock);
3418dbab48ceSNaveen Mamindlapalli 	for (index = 0; index < mcam->bmap_entries; index++) {
3419dbab48ceSNaveen Mamindlapalli 		if (mcam->entry2target_pffunc[index] == pcifunc)
3420dbab48ceSNaveen Mamindlapalli 			goto read_entry;
3421dbab48ceSNaveen Mamindlapalli 	}
3422dbab48ceSNaveen Mamindlapalli 
3423dbab48ceSNaveen Mamindlapalli 	rc = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
3424dbab48ceSNaveen Mamindlapalli 	if (rc < 0) {
3425dbab48ceSNaveen Mamindlapalli 		mutex_unlock(&mcam->lock);
3426dbab48ceSNaveen Mamindlapalli 		goto out;
3427dbab48ceSNaveen Mamindlapalli 	}
3428dbab48ceSNaveen Mamindlapalli 	/* Read the default ucast entry if there is no pkt steering rule */
3429dbab48ceSNaveen Mamindlapalli 	index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
3430dbab48ceSNaveen Mamindlapalli 					 NIXLF_UCAST_ENTRY);
3431dbab48ceSNaveen Mamindlapalli read_entry:
3432dbab48ceSNaveen Mamindlapalli 	/* Read the mcam entry */
3433dbab48ceSNaveen Mamindlapalli 	npc_read_mcam_entry(rvu, mcam, blkaddr, index, &rsp->entry, &intf,
3434dbab48ceSNaveen Mamindlapalli 			    &enable);
3435dbab48ceSNaveen Mamindlapalli 	mutex_unlock(&mcam->lock);
3436dbab48ceSNaveen Mamindlapalli out:
3437dbab48ceSNaveen Mamindlapalli 	return rc;
3438dbab48ceSNaveen Mamindlapalli }
3439d8ce30e0SNaveen Mamindlapalli 
rvu_mbox_handler_npc_mcam_entry_stats(struct rvu * rvu,struct npc_mcam_get_stats_req * req,struct npc_mcam_get_stats_rsp * rsp)3440d8ce30e0SNaveen Mamindlapalli int rvu_mbox_handler_npc_mcam_entry_stats(struct rvu *rvu,
3441d8ce30e0SNaveen Mamindlapalli 					  struct npc_mcam_get_stats_req *req,
3442d8ce30e0SNaveen Mamindlapalli 					  struct npc_mcam_get_stats_rsp *rsp)
3443d8ce30e0SNaveen Mamindlapalli {
3444d8ce30e0SNaveen Mamindlapalli 	struct npc_mcam *mcam = &rvu->hw->mcam;
3445d8ce30e0SNaveen Mamindlapalli 	u16 index, cntr;
3446d8ce30e0SNaveen Mamindlapalli 	int blkaddr;
3447d8ce30e0SNaveen Mamindlapalli 	u64 regval;
3448d8ce30e0SNaveen Mamindlapalli 	u32 bank;
3449d8ce30e0SNaveen Mamindlapalli 
3450d8ce30e0SNaveen Mamindlapalli 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
3451d8ce30e0SNaveen Mamindlapalli 	if (blkaddr < 0)
3452d8ce30e0SNaveen Mamindlapalli 		return NPC_MCAM_INVALID_REQ;
3453d8ce30e0SNaveen Mamindlapalli 
3454d8ce30e0SNaveen Mamindlapalli 	mutex_lock(&mcam->lock);
3455d8ce30e0SNaveen Mamindlapalli 
3456d8ce30e0SNaveen Mamindlapalli 	index = req->entry & (mcam->banksize - 1);
3457d8ce30e0SNaveen Mamindlapalli 	bank = npc_get_bank(mcam, req->entry);
3458d8ce30e0SNaveen Mamindlapalli 
3459d8ce30e0SNaveen Mamindlapalli 	/* read MCAM entry STAT_ACT register */
3460d8ce30e0SNaveen Mamindlapalli 	regval = rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_STAT_ACT(index, bank));
3461d8ce30e0SNaveen Mamindlapalli 
346299b8e547SHariprasad Kelam 	if (!(regval & rvu->hw->npc_stat_ena)) {
3463d8ce30e0SNaveen Mamindlapalli 		rsp->stat_ena = 0;
3464d8ce30e0SNaveen Mamindlapalli 		mutex_unlock(&mcam->lock);
3465d8ce30e0SNaveen Mamindlapalli 		return 0;
3466d8ce30e0SNaveen Mamindlapalli 	}
3467d8ce30e0SNaveen Mamindlapalli 
3468d8ce30e0SNaveen Mamindlapalli 	cntr = regval & 0x1FF;
3469d8ce30e0SNaveen Mamindlapalli 
3470d8ce30e0SNaveen Mamindlapalli 	rsp->stat_ena = 1;
3471d8ce30e0SNaveen Mamindlapalli 	rsp->stat = rvu_read64(rvu, blkaddr, NPC_AF_MATCH_STATX(cntr));
3472d8ce30e0SNaveen Mamindlapalli 	rsp->stat &= BIT_ULL(48) - 1;
3473d8ce30e0SNaveen Mamindlapalli 
3474d8ce30e0SNaveen Mamindlapalli 	mutex_unlock(&mcam->lock);
3475d8ce30e0SNaveen Mamindlapalli 
3476d8ce30e0SNaveen Mamindlapalli 	return 0;
3477d8ce30e0SNaveen Mamindlapalli }
3478