156d9f5fdSRatheesh Kannoth // SPDX-License-Identifier: GPL-2.0
256d9f5fdSRatheesh Kannoth /* Marvell RVU Admin Function driver
356d9f5fdSRatheesh Kannoth  *
456d9f5fdSRatheesh Kannoth  * Copyright (C) 2022 Marvell.
556d9f5fdSRatheesh Kannoth  *
656d9f5fdSRatheesh Kannoth  */
756d9f5fdSRatheesh Kannoth 
856d9f5fdSRatheesh Kannoth #include <linux/bitfield.h>
956d9f5fdSRatheesh Kannoth #include <linux/module.h>
1056d9f5fdSRatheesh Kannoth #include <linux/pci.h>
1156d9f5fdSRatheesh Kannoth #include <linux/firmware.h>
1256d9f5fdSRatheesh Kannoth #include <linux/stddef.h>
1356d9f5fdSRatheesh Kannoth #include <linux/debugfs.h>
1456d9f5fdSRatheesh Kannoth 
1556d9f5fdSRatheesh Kannoth #include "rvu_struct.h"
1656d9f5fdSRatheesh Kannoth #include "rvu_reg.h"
1756d9f5fdSRatheesh Kannoth #include "rvu.h"
1856d9f5fdSRatheesh Kannoth #include "npc.h"
1956d9f5fdSRatheesh Kannoth #include "cgx.h"
2056d9f5fdSRatheesh Kannoth #include "rvu_npc_fs.h"
21b747923aSRatheesh Kannoth #include "rvu_npc_hash.h"
2256d9f5fdSRatheesh Kannoth 
rvu_npc_wide_extract(const u64 input[],size_t start_bit,size_t width_bits)2356d9f5fdSRatheesh Kannoth static u64 rvu_npc_wide_extract(const u64 input[], size_t start_bit,
2456d9f5fdSRatheesh Kannoth 				size_t width_bits)
2556d9f5fdSRatheesh Kannoth {
2656d9f5fdSRatheesh Kannoth 	const u64 mask = ~(u64)((~(__uint128_t)0) << width_bits);
2756d9f5fdSRatheesh Kannoth 	const size_t msb = start_bit + width_bits - 1;
2856d9f5fdSRatheesh Kannoth 	const size_t lword = start_bit >> 6;
2956d9f5fdSRatheesh Kannoth 	const size_t uword = msb >> 6;
3056d9f5fdSRatheesh Kannoth 	size_t lbits;
3156d9f5fdSRatheesh Kannoth 	u64 hi, lo;
3256d9f5fdSRatheesh Kannoth 
3356d9f5fdSRatheesh Kannoth 	if (lword == uword)
3456d9f5fdSRatheesh Kannoth 		return (input[lword] >> (start_bit & 63)) & mask;
3556d9f5fdSRatheesh Kannoth 
3656d9f5fdSRatheesh Kannoth 	lbits = 64 - (start_bit & 63);
3756d9f5fdSRatheesh Kannoth 	hi = input[uword];
3856d9f5fdSRatheesh Kannoth 	lo = (input[lword] >> (start_bit & 63));
3956d9f5fdSRatheesh Kannoth 	return ((hi << lbits) | lo) & mask;
4056d9f5fdSRatheesh Kannoth }
4156d9f5fdSRatheesh Kannoth 
rvu_npc_lshift_key(u64 * key,size_t key_bit_len)4256d9f5fdSRatheesh Kannoth static void rvu_npc_lshift_key(u64 *key, size_t key_bit_len)
4356d9f5fdSRatheesh Kannoth {
4456d9f5fdSRatheesh Kannoth 	u64 prev_orig_word = 0;
4556d9f5fdSRatheesh Kannoth 	u64 cur_orig_word = 0;
4656d9f5fdSRatheesh Kannoth 	size_t extra = key_bit_len % 64;
4756d9f5fdSRatheesh Kannoth 	size_t max_idx = key_bit_len / 64;
4856d9f5fdSRatheesh Kannoth 	size_t i;
4956d9f5fdSRatheesh Kannoth 
5056d9f5fdSRatheesh Kannoth 	if (extra)
5156d9f5fdSRatheesh Kannoth 		max_idx++;
5256d9f5fdSRatheesh Kannoth 
5356d9f5fdSRatheesh Kannoth 	for (i = 0; i < max_idx; i++) {
5456d9f5fdSRatheesh Kannoth 		cur_orig_word = key[i];
5556d9f5fdSRatheesh Kannoth 		key[i] = key[i] << 1;
5656d9f5fdSRatheesh Kannoth 		key[i] |= ((prev_orig_word >> 63) & 0x1);
5756d9f5fdSRatheesh Kannoth 		prev_orig_word = cur_orig_word;
5856d9f5fdSRatheesh Kannoth 	}
5956d9f5fdSRatheesh Kannoth }
6056d9f5fdSRatheesh Kannoth 
rvu_npc_toeplitz_hash(const u64 * data,u64 * key,size_t data_bit_len,size_t key_bit_len)6156d9f5fdSRatheesh Kannoth static u32 rvu_npc_toeplitz_hash(const u64 *data, u64 *key, size_t data_bit_len,
6256d9f5fdSRatheesh Kannoth 				 size_t key_bit_len)
6356d9f5fdSRatheesh Kannoth {
6456d9f5fdSRatheesh Kannoth 	u32 hash_out = 0;
6556d9f5fdSRatheesh Kannoth 	u64 temp_data = 0;
6656d9f5fdSRatheesh Kannoth 	int i;
6756d9f5fdSRatheesh Kannoth 
6856d9f5fdSRatheesh Kannoth 	for (i = data_bit_len - 1; i >= 0; i--) {
6956d9f5fdSRatheesh Kannoth 		temp_data = (data[i / 64]);
7056d9f5fdSRatheesh Kannoth 		temp_data = temp_data >> (i % 64);
7156d9f5fdSRatheesh Kannoth 		temp_data &= 0x1;
7256d9f5fdSRatheesh Kannoth 		if (temp_data)
7356d9f5fdSRatheesh Kannoth 			hash_out ^= (u32)(rvu_npc_wide_extract(key, key_bit_len - 32, 32));
7456d9f5fdSRatheesh Kannoth 
7556d9f5fdSRatheesh Kannoth 		rvu_npc_lshift_key(key, key_bit_len);
7656d9f5fdSRatheesh Kannoth 	}
7756d9f5fdSRatheesh Kannoth 
7856d9f5fdSRatheesh Kannoth 	return hash_out;
7956d9f5fdSRatheesh Kannoth }
8056d9f5fdSRatheesh Kannoth 
npc_field_hash_calc(u64 * ldata,struct npc_get_field_hash_info_rsp rsp,u8 intf,u8 hash_idx)81f6615590SRatheesh Kannoth u32 npc_field_hash_calc(u64 *ldata, struct npc_get_field_hash_info_rsp rsp,
82f6615590SRatheesh Kannoth 			u8 intf, u8 hash_idx)
8356d9f5fdSRatheesh Kannoth {
8456d9f5fdSRatheesh Kannoth 	u64 hash_key[3];
8556d9f5fdSRatheesh Kannoth 	u64 data_padded[2];
8656d9f5fdSRatheesh Kannoth 	u32 field_hash;
8756d9f5fdSRatheesh Kannoth 
88f6615590SRatheesh Kannoth 	hash_key[0] = rsp.secret_key[1] << 31;
89f6615590SRatheesh Kannoth 	hash_key[0] |= rsp.secret_key[2];
90f6615590SRatheesh Kannoth 	hash_key[1] = rsp.secret_key[1] >> 33;
91f6615590SRatheesh Kannoth 	hash_key[1] |= rsp.secret_key[0] << 31;
92f6615590SRatheesh Kannoth 	hash_key[2] = rsp.secret_key[0] >> 33;
9356d9f5fdSRatheesh Kannoth 
94f6615590SRatheesh Kannoth 	data_padded[0] = rsp.hash_mask[intf][hash_idx][0] & ldata[0];
95f6615590SRatheesh Kannoth 	data_padded[1] = rsp.hash_mask[intf][hash_idx][1] & ldata[1];
9656d9f5fdSRatheesh Kannoth 	field_hash = rvu_npc_toeplitz_hash(data_padded, hash_key, 128, 159);
9756d9f5fdSRatheesh Kannoth 
98f6615590SRatheesh Kannoth 	field_hash &= FIELD_GET(GENMASK(63, 32), rsp.hash_ctrl[intf][hash_idx]);
99f6615590SRatheesh Kannoth 	field_hash += FIELD_GET(GENMASK(31, 0), rsp.hash_ctrl[intf][hash_idx]);
10056d9f5fdSRatheesh Kannoth 	return field_hash;
10156d9f5fdSRatheesh Kannoth }
10256d9f5fdSRatheesh Kannoth 
npc_update_use_hash(struct rvu * rvu,int blkaddr,u8 intf,int lid,int lt,int ld)103f6615590SRatheesh Kannoth static u64 npc_update_use_hash(struct rvu *rvu, int blkaddr,
104f6615590SRatheesh Kannoth 			       u8 intf, int lid, int lt, int ld)
10556d9f5fdSRatheesh Kannoth {
106f6615590SRatheesh Kannoth 	u8 hdr, key;
107f6615590SRatheesh Kannoth 	u64 cfg;
10856d9f5fdSRatheesh Kannoth 
109f6615590SRatheesh Kannoth 	cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf, lid, lt, ld));
110f6615590SRatheesh Kannoth 	hdr = FIELD_GET(NPC_HDR_OFFSET, cfg);
111f6615590SRatheesh Kannoth 	key = FIELD_GET(NPC_KEY_OFFSET, cfg);
112f6615590SRatheesh Kannoth 
113f6615590SRatheesh Kannoth 	/* Update use_hash(bit-20) to 'true' and
114f6615590SRatheesh Kannoth 	 * bytesm1(bit-16:19) to '0x3' in KEX_LD_CFG
11556d9f5fdSRatheesh Kannoth 	 */
11656d9f5fdSRatheesh Kannoth 	cfg = KEX_LD_CFG_USE_HASH(0x1, 0x03,
117f6615590SRatheesh Kannoth 				  hdr, 0x1, 0x0, key);
11856d9f5fdSRatheesh Kannoth 
11956d9f5fdSRatheesh Kannoth 	return cfg;
12056d9f5fdSRatheesh Kannoth }
12156d9f5fdSRatheesh Kannoth 
npc_program_mkex_hash_rx(struct rvu * rvu,int blkaddr,u8 intf)12256d9f5fdSRatheesh Kannoth static void npc_program_mkex_hash_rx(struct rvu *rvu, int blkaddr,
12356d9f5fdSRatheesh Kannoth 				     u8 intf)
12456d9f5fdSRatheesh Kannoth {
12556d9f5fdSRatheesh Kannoth 	struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash;
12656d9f5fdSRatheesh Kannoth 	int lid, lt, ld, hash_cnt = 0;
12756d9f5fdSRatheesh Kannoth 
12856d9f5fdSRatheesh Kannoth 	if (is_npc_intf_tx(intf))
12956d9f5fdSRatheesh Kannoth 		return;
13056d9f5fdSRatheesh Kannoth 
13156d9f5fdSRatheesh Kannoth 	/* Program HASH_CFG */
13256d9f5fdSRatheesh Kannoth 	for (lid = 0; lid < NPC_MAX_LID; lid++) {
13356d9f5fdSRatheesh Kannoth 		for (lt = 0; lt < NPC_MAX_LT; lt++) {
13456d9f5fdSRatheesh Kannoth 			for (ld = 0; ld < NPC_MAX_LD; ld++) {
13556d9f5fdSRatheesh Kannoth 				if (mkex_hash->lid_lt_ld_hash_en[intf][lid][lt][ld]) {
136f6615590SRatheesh Kannoth 					u64 cfg;
13756d9f5fdSRatheesh Kannoth 
13856d9f5fdSRatheesh Kannoth 					if (hash_cnt == NPC_MAX_HASH)
13956d9f5fdSRatheesh Kannoth 						return;
14056d9f5fdSRatheesh Kannoth 
141f6615590SRatheesh Kannoth 					cfg = npc_update_use_hash(rvu, blkaddr,
142f6615590SRatheesh Kannoth 								  intf, lid, lt, ld);
14356d9f5fdSRatheesh Kannoth 					/* Set updated KEX configuration */
14456d9f5fdSRatheesh Kannoth 					SET_KEX_LD(intf, lid, lt, ld, cfg);
14556d9f5fdSRatheesh Kannoth 					/* Set HASH configuration */
14656d9f5fdSRatheesh Kannoth 					SET_KEX_LD_HASH(intf, ld,
14756d9f5fdSRatheesh Kannoth 							mkex_hash->hash[intf][ld]);
14856d9f5fdSRatheesh Kannoth 					SET_KEX_LD_HASH_MASK(intf, ld, 0,
14956d9f5fdSRatheesh Kannoth 							     mkex_hash->hash_mask[intf][ld][0]);
15056d9f5fdSRatheesh Kannoth 					SET_KEX_LD_HASH_MASK(intf, ld, 1,
15156d9f5fdSRatheesh Kannoth 							     mkex_hash->hash_mask[intf][ld][1]);
15256d9f5fdSRatheesh Kannoth 					SET_KEX_LD_HASH_CTRL(intf, ld,
15356d9f5fdSRatheesh Kannoth 							     mkex_hash->hash_ctrl[intf][ld]);
154406bed11SRatheesh Kannoth 
155406bed11SRatheesh Kannoth 					hash_cnt++;
15656d9f5fdSRatheesh Kannoth 				}
15756d9f5fdSRatheesh Kannoth 			}
15856d9f5fdSRatheesh Kannoth 		}
15956d9f5fdSRatheesh Kannoth 	}
16056d9f5fdSRatheesh Kannoth }
16156d9f5fdSRatheesh Kannoth 
npc_program_mkex_hash_tx(struct rvu * rvu,int blkaddr,u8 intf)16256d9f5fdSRatheesh Kannoth static void npc_program_mkex_hash_tx(struct rvu *rvu, int blkaddr,
16356d9f5fdSRatheesh Kannoth 				     u8 intf)
16456d9f5fdSRatheesh Kannoth {
16556d9f5fdSRatheesh Kannoth 	struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash;
16656d9f5fdSRatheesh Kannoth 	int lid, lt, ld, hash_cnt = 0;
16756d9f5fdSRatheesh Kannoth 
16856d9f5fdSRatheesh Kannoth 	if (is_npc_intf_rx(intf))
16956d9f5fdSRatheesh Kannoth 		return;
17056d9f5fdSRatheesh Kannoth 
17156d9f5fdSRatheesh Kannoth 	/* Program HASH_CFG */
17256d9f5fdSRatheesh Kannoth 	for (lid = 0; lid < NPC_MAX_LID; lid++) {
17356d9f5fdSRatheesh Kannoth 		for (lt = 0; lt < NPC_MAX_LT; lt++) {
17456d9f5fdSRatheesh Kannoth 			for (ld = 0; ld < NPC_MAX_LD; ld++)
17556d9f5fdSRatheesh Kannoth 				if (mkex_hash->lid_lt_ld_hash_en[intf][lid][lt][ld]) {
176f6615590SRatheesh Kannoth 					u64 cfg;
17756d9f5fdSRatheesh Kannoth 
17856d9f5fdSRatheesh Kannoth 					if (hash_cnt == NPC_MAX_HASH)
17956d9f5fdSRatheesh Kannoth 						return;
18056d9f5fdSRatheesh Kannoth 
181f6615590SRatheesh Kannoth 					cfg = npc_update_use_hash(rvu, blkaddr,
182f6615590SRatheesh Kannoth 								  intf, lid, lt, ld);
18356d9f5fdSRatheesh Kannoth 					/* Set updated KEX configuration */
18456d9f5fdSRatheesh Kannoth 					SET_KEX_LD(intf, lid, lt, ld, cfg);
18556d9f5fdSRatheesh Kannoth 					/* Set HASH configuration */
18656d9f5fdSRatheesh Kannoth 					SET_KEX_LD_HASH(intf, ld,
18756d9f5fdSRatheesh Kannoth 							mkex_hash->hash[intf][ld]);
18856d9f5fdSRatheesh Kannoth 					SET_KEX_LD_HASH_MASK(intf, ld, 0,
18956d9f5fdSRatheesh Kannoth 							     mkex_hash->hash_mask[intf][ld][0]);
19056d9f5fdSRatheesh Kannoth 					SET_KEX_LD_HASH_MASK(intf, ld, 1,
19156d9f5fdSRatheesh Kannoth 							     mkex_hash->hash_mask[intf][ld][1]);
19256d9f5fdSRatheesh Kannoth 					SET_KEX_LD_HASH_CTRL(intf, ld,
19356d9f5fdSRatheesh Kannoth 							     mkex_hash->hash_ctrl[intf][ld]);
19456d9f5fdSRatheesh Kannoth 					hash_cnt++;
19556d9f5fdSRatheesh Kannoth 				}
19656d9f5fdSRatheesh Kannoth 		}
19756d9f5fdSRatheesh Kannoth 	}
19856d9f5fdSRatheesh Kannoth }
19956d9f5fdSRatheesh Kannoth 
npc_config_secret_key(struct rvu * rvu,int blkaddr)20056d9f5fdSRatheesh Kannoth void npc_config_secret_key(struct rvu *rvu, int blkaddr)
20156d9f5fdSRatheesh Kannoth {
20256d9f5fdSRatheesh Kannoth 	struct hw_cap *hwcap = &rvu->hw->cap;
20356d9f5fdSRatheesh Kannoth 	struct rvu_hwinfo *hw = rvu->hw;
20456d9f5fdSRatheesh Kannoth 	u8 intf;
20556d9f5fdSRatheesh Kannoth 
206609aa68dSSunil Goutham 	if (!hwcap->npc_hash_extract)
20756d9f5fdSRatheesh Kannoth 		return;
20856d9f5fdSRatheesh Kannoth 
20956d9f5fdSRatheesh Kannoth 	for (intf = 0; intf < hw->npc_intfs; intf++) {
21056d9f5fdSRatheesh Kannoth 		rvu_write64(rvu, blkaddr, NPC_AF_INTFX_SECRET_KEY0(intf),
21156d9f5fdSRatheesh Kannoth 			    RVU_NPC_HASH_SECRET_KEY0);
21256d9f5fdSRatheesh Kannoth 		rvu_write64(rvu, blkaddr, NPC_AF_INTFX_SECRET_KEY1(intf),
21356d9f5fdSRatheesh Kannoth 			    RVU_NPC_HASH_SECRET_KEY1);
21456d9f5fdSRatheesh Kannoth 		rvu_write64(rvu, blkaddr, NPC_AF_INTFX_SECRET_KEY2(intf),
21556d9f5fdSRatheesh Kannoth 			    RVU_NPC_HASH_SECRET_KEY2);
21656d9f5fdSRatheesh Kannoth 	}
21756d9f5fdSRatheesh Kannoth }
21856d9f5fdSRatheesh Kannoth 
npc_program_mkex_hash(struct rvu * rvu,int blkaddr)21956d9f5fdSRatheesh Kannoth void npc_program_mkex_hash(struct rvu *rvu, int blkaddr)
22056d9f5fdSRatheesh Kannoth {
2214e62c99dSSuman Ghosh 	struct npc_mcam_kex_hash *mh = rvu->kpu.mkex_hash;
22256d9f5fdSRatheesh Kannoth 	struct hw_cap *hwcap = &rvu->hw->cap;
2234e62c99dSSuman Ghosh 	u8 intf, ld, hdr_offset, byte_len;
22456d9f5fdSRatheesh Kannoth 	struct rvu_hwinfo *hw = rvu->hw;
2254e62c99dSSuman Ghosh 	u64 cfg;
22656d9f5fdSRatheesh Kannoth 
2274e62c99dSSuman Ghosh 	/* Check if hardware supports hash extraction */
228609aa68dSSunil Goutham 	if (!hwcap->npc_hash_extract)
22956d9f5fdSRatheesh Kannoth 		return;
23056d9f5fdSRatheesh Kannoth 
2314e62c99dSSuman Ghosh 	/* Check if IPv6 source/destination address
2324e62c99dSSuman Ghosh 	 * should be hash enabled.
2334e62c99dSSuman Ghosh 	 * Hashing reduces 128bit SIP/DIP fields to 32bit
2344e62c99dSSuman Ghosh 	 * so that 224 bit X2 key can be used for IPv6 based filters as well,
2354e62c99dSSuman Ghosh 	 * which in turn results in more number of MCAM entries available for
2364e62c99dSSuman Ghosh 	 * use.
2374e62c99dSSuman Ghosh 	 *
2384e62c99dSSuman Ghosh 	 * Hashing of IPV6 SIP/DIP is enabled in below scenarios
2394e62c99dSSuman Ghosh 	 * 1. If the silicon variant supports hashing feature
2404e62c99dSSuman Ghosh 	 * 2. If the number of bytes of IP addr being extracted is 4 bytes ie
2414e62c99dSSuman Ghosh 	 *    32bit. The assumption here is that if user wants 8bytes of LSB of
2424e62c99dSSuman Ghosh 	 *    IP addr or full 16 bytes then his intention is not to use 32bit
2434e62c99dSSuman Ghosh 	 *    hash.
2444e62c99dSSuman Ghosh 	 */
2454e62c99dSSuman Ghosh 	for (intf = 0; intf < hw->npc_intfs; intf++) {
2464e62c99dSSuman Ghosh 		for (ld = 0; ld < NPC_MAX_LD; ld++) {
2474e62c99dSSuman Ghosh 			cfg = rvu_read64(rvu, blkaddr,
2484e62c99dSSuman Ghosh 					 NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf,
2494e62c99dSSuman Ghosh 								       NPC_LID_LC,
2504e62c99dSSuman Ghosh 								       NPC_LT_LC_IP6,
2514e62c99dSSuman Ghosh 								       ld));
2524e62c99dSSuman Ghosh 			hdr_offset = FIELD_GET(NPC_HDR_OFFSET, cfg);
2534e62c99dSSuman Ghosh 			byte_len = FIELD_GET(NPC_BYTESM, cfg);
2544e62c99dSSuman Ghosh 			/* Hashing of IPv6 source/destination address should be
2554e62c99dSSuman Ghosh 			 * enabled if,
2564e62c99dSSuman Ghosh 			 * hdr_offset == 8 (offset of source IPv6 address) or
2574e62c99dSSuman Ghosh 			 * hdr_offset == 24 (offset of destination IPv6)
2584e62c99dSSuman Ghosh 			 * address) and the number of byte to be
2594e62c99dSSuman Ghosh 			 * extracted is 4. As per hardware configuration
2604e62c99dSSuman Ghosh 			 * byte_len should be == actual byte_len - 1.
2614e62c99dSSuman Ghosh 			 * Hence byte_len is checked against 3 but nor 4.
2624e62c99dSSuman Ghosh 			 */
2634e62c99dSSuman Ghosh 			if ((hdr_offset == 8 || hdr_offset == 24) && byte_len == 3)
2644e62c99dSSuman Ghosh 				mh->lid_lt_ld_hash_en[intf][NPC_LID_LC][NPC_LT_LC_IP6][ld] = true;
2654e62c99dSSuman Ghosh 		}
2664e62c99dSSuman Ghosh 	}
2674e62c99dSSuman Ghosh 
2684e62c99dSSuman Ghosh 	/* Update hash configuration if the field is hash enabled */
26956d9f5fdSRatheesh Kannoth 	for (intf = 0; intf < hw->npc_intfs; intf++) {
27056d9f5fdSRatheesh Kannoth 		npc_program_mkex_hash_rx(rvu, blkaddr, intf);
27156d9f5fdSRatheesh Kannoth 		npc_program_mkex_hash_tx(rvu, blkaddr, intf);
27256d9f5fdSRatheesh Kannoth 	}
27356d9f5fdSRatheesh Kannoth }
27456d9f5fdSRatheesh Kannoth 
npc_update_field_hash(struct rvu * rvu,u8 intf,struct mcam_entry * entry,int blkaddr,u64 features,struct flow_msg * pkt,struct flow_msg * mask,struct flow_msg * opkt,struct flow_msg * omask)27556d9f5fdSRatheesh Kannoth void npc_update_field_hash(struct rvu *rvu, u8 intf,
27656d9f5fdSRatheesh Kannoth 			   struct mcam_entry *entry,
27756d9f5fdSRatheesh Kannoth 			   int blkaddr,
27856d9f5fdSRatheesh Kannoth 			   u64 features,
27956d9f5fdSRatheesh Kannoth 			   struct flow_msg *pkt,
28056d9f5fdSRatheesh Kannoth 			   struct flow_msg *mask,
28156d9f5fdSRatheesh Kannoth 			   struct flow_msg *opkt,
28256d9f5fdSRatheesh Kannoth 			   struct flow_msg *omask)
28356d9f5fdSRatheesh Kannoth {
28456d9f5fdSRatheesh Kannoth 	struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash;
285406bed11SRatheesh Kannoth 	struct npc_get_field_hash_info_req req;
286406bed11SRatheesh Kannoth 	struct npc_get_field_hash_info_rsp rsp;
28756d9f5fdSRatheesh Kannoth 	u64 ldata[2], cfg;
28856d9f5fdSRatheesh Kannoth 	u32 field_hash;
28956d9f5fdSRatheesh Kannoth 	u8 hash_idx;
29056d9f5fdSRatheesh Kannoth 
29156d9f5fdSRatheesh Kannoth 	if (!rvu->hw->cap.npc_hash_extract) {
29256d9f5fdSRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: Field hash extract feature is not supported\n", __func__);
29356d9f5fdSRatheesh Kannoth 		return;
29456d9f5fdSRatheesh Kannoth 	}
29556d9f5fdSRatheesh Kannoth 
29656d9f5fdSRatheesh Kannoth 	req.intf = intf;
297406bed11SRatheesh Kannoth 	rvu_mbox_handler_npc_get_field_hash_info(rvu, &req, &rsp);
29856d9f5fdSRatheesh Kannoth 
29956d9f5fdSRatheesh Kannoth 	for (hash_idx = 0; hash_idx < NPC_MAX_HASH; hash_idx++) {
30056d9f5fdSRatheesh Kannoth 		cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_HASHX_CFG(intf, hash_idx));
30156d9f5fdSRatheesh Kannoth 		if ((cfg & BIT_ULL(11)) && (cfg & BIT_ULL(12))) {
30256d9f5fdSRatheesh Kannoth 			u8 lid = (cfg & GENMASK_ULL(10, 8)) >> 8;
30356d9f5fdSRatheesh Kannoth 			u8 ltype = (cfg & GENMASK_ULL(7, 4)) >> 4;
30456d9f5fdSRatheesh Kannoth 			u8 ltype_mask = cfg & GENMASK_ULL(3, 0);
30556d9f5fdSRatheesh Kannoth 
30656d9f5fdSRatheesh Kannoth 			if (mkex_hash->lid_lt_ld_hash_en[intf][lid][ltype][hash_idx]) {
30756d9f5fdSRatheesh Kannoth 				switch (ltype & ltype_mask) {
30856d9f5fdSRatheesh Kannoth 				/* If hash extract enabled is supported for IPv6 then
30956d9f5fdSRatheesh Kannoth 				 * 128 bit IPv6 source and destination addressed
31056d9f5fdSRatheesh Kannoth 				 * is hashed to 32 bit value.
31156d9f5fdSRatheesh Kannoth 				 */
31256d9f5fdSRatheesh Kannoth 				case NPC_LT_LC_IP6:
313f6615590SRatheesh Kannoth 					/* ld[0] == hash_idx[0] == Source IPv6
314f6615590SRatheesh Kannoth 					 * ld[1] == hash_idx[1] == Destination IPv6
315f6615590SRatheesh Kannoth 					 */
316f6615590SRatheesh Kannoth 					if ((features & BIT_ULL(NPC_SIP_IPV6)) && !hash_idx) {
31756d9f5fdSRatheesh Kannoth 						u32 src_ip[IPV6_WORDS];
31856d9f5fdSRatheesh Kannoth 
31956d9f5fdSRatheesh Kannoth 						be32_to_cpu_array(src_ip, pkt->ip6src, IPV6_WORDS);
320f6615590SRatheesh Kannoth 						ldata[1] = (u64)src_ip[0] << 32 | src_ip[1];
321f6615590SRatheesh Kannoth 						ldata[0] = (u64)src_ip[2] << 32 | src_ip[3];
32256d9f5fdSRatheesh Kannoth 						field_hash = npc_field_hash_calc(ldata,
323f6615590SRatheesh Kannoth 										 rsp,
32456d9f5fdSRatheesh Kannoth 										 intf,
32556d9f5fdSRatheesh Kannoth 										 hash_idx);
32656d9f5fdSRatheesh Kannoth 						npc_update_entry(rvu, NPC_SIP_IPV6, entry,
327f6615590SRatheesh Kannoth 								 field_hash, 0,
328f6615590SRatheesh Kannoth 								 GENMASK(31, 0), 0, intf);
32956d9f5fdSRatheesh Kannoth 						memcpy(&opkt->ip6src, &pkt->ip6src,
33056d9f5fdSRatheesh Kannoth 						       sizeof(pkt->ip6src));
33156d9f5fdSRatheesh Kannoth 						memcpy(&omask->ip6src, &mask->ip6src,
33256d9f5fdSRatheesh Kannoth 						       sizeof(mask->ip6src));
333f6615590SRatheesh Kannoth 					} else if ((features & BIT_ULL(NPC_DIP_IPV6)) && hash_idx) {
33456d9f5fdSRatheesh Kannoth 						u32 dst_ip[IPV6_WORDS];
33556d9f5fdSRatheesh Kannoth 
33656d9f5fdSRatheesh Kannoth 						be32_to_cpu_array(dst_ip, pkt->ip6dst, IPV6_WORDS);
337f6615590SRatheesh Kannoth 						ldata[1] = (u64)dst_ip[0] << 32 | dst_ip[1];
338f6615590SRatheesh Kannoth 						ldata[0] = (u64)dst_ip[2] << 32 | dst_ip[3];
33956d9f5fdSRatheesh Kannoth 						field_hash = npc_field_hash_calc(ldata,
340f6615590SRatheesh Kannoth 										 rsp,
34156d9f5fdSRatheesh Kannoth 										 intf,
34256d9f5fdSRatheesh Kannoth 										 hash_idx);
34356d9f5fdSRatheesh Kannoth 						npc_update_entry(rvu, NPC_DIP_IPV6, entry,
344f6615590SRatheesh Kannoth 								 field_hash, 0,
345f6615590SRatheesh Kannoth 								 GENMASK(31, 0), 0, intf);
34656d9f5fdSRatheesh Kannoth 						memcpy(&opkt->ip6dst, &pkt->ip6dst,
34756d9f5fdSRatheesh Kannoth 						       sizeof(pkt->ip6dst));
34856d9f5fdSRatheesh Kannoth 						memcpy(&omask->ip6dst, &mask->ip6dst,
34956d9f5fdSRatheesh Kannoth 						       sizeof(mask->ip6dst));
35056d9f5fdSRatheesh Kannoth 					}
351f6615590SRatheesh Kannoth 
35256d9f5fdSRatheesh Kannoth 					break;
35356d9f5fdSRatheesh Kannoth 				}
35456d9f5fdSRatheesh Kannoth 			}
35556d9f5fdSRatheesh Kannoth 		}
35656d9f5fdSRatheesh Kannoth 	}
35756d9f5fdSRatheesh Kannoth }
35856d9f5fdSRatheesh Kannoth 
rvu_mbox_handler_npc_get_field_hash_info(struct rvu * rvu,struct npc_get_field_hash_info_req * req,struct npc_get_field_hash_info_rsp * rsp)359406bed11SRatheesh Kannoth int rvu_mbox_handler_npc_get_field_hash_info(struct rvu *rvu,
360406bed11SRatheesh Kannoth 					     struct npc_get_field_hash_info_req *req,
361406bed11SRatheesh Kannoth 					     struct npc_get_field_hash_info_rsp *rsp)
36256d9f5fdSRatheesh Kannoth {
36356d9f5fdSRatheesh Kannoth 	u64 *secret_key = rsp->secret_key;
36456d9f5fdSRatheesh Kannoth 	u8 intf = req->intf;
365406bed11SRatheesh Kannoth 	int i, j, blkaddr;
36656d9f5fdSRatheesh Kannoth 
36756d9f5fdSRatheesh Kannoth 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
36856d9f5fdSRatheesh Kannoth 	if (blkaddr < 0) {
36956d9f5fdSRatheesh Kannoth 		dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
37056d9f5fdSRatheesh Kannoth 		return -EINVAL;
37156d9f5fdSRatheesh Kannoth 	}
37256d9f5fdSRatheesh Kannoth 
37356d9f5fdSRatheesh Kannoth 	secret_key[0] = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_SECRET_KEY0(intf));
37456d9f5fdSRatheesh Kannoth 	secret_key[1] = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_SECRET_KEY1(intf));
37556d9f5fdSRatheesh Kannoth 	secret_key[2] = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_SECRET_KEY2(intf));
37656d9f5fdSRatheesh Kannoth 
377406bed11SRatheesh Kannoth 	for (i = 0; i < NPC_MAX_HASH; i++) {
378406bed11SRatheesh Kannoth 		for (j = 0; j < NPC_MAX_HASH_MASK; j++) {
379406bed11SRatheesh Kannoth 			rsp->hash_mask[NIX_INTF_RX][i][j] =
380406bed11SRatheesh Kannoth 				GET_KEX_LD_HASH_MASK(NIX_INTF_RX, i, j);
381406bed11SRatheesh Kannoth 			rsp->hash_mask[NIX_INTF_TX][i][j] =
382406bed11SRatheesh Kannoth 				GET_KEX_LD_HASH_MASK(NIX_INTF_TX, i, j);
383406bed11SRatheesh Kannoth 		}
384406bed11SRatheesh Kannoth 	}
385406bed11SRatheesh Kannoth 
386406bed11SRatheesh Kannoth 	for (i = 0; i < NPC_MAX_INTF; i++)
387406bed11SRatheesh Kannoth 		for (j = 0; j < NPC_MAX_HASH; j++)
388406bed11SRatheesh Kannoth 			rsp->hash_ctrl[i][j] = GET_KEX_LD_HASH_CTRL(i, j);
389406bed11SRatheesh Kannoth 
39056d9f5fdSRatheesh Kannoth 	return 0;
39156d9f5fdSRatheesh Kannoth }
392b747923aSRatheesh Kannoth 
393b747923aSRatheesh Kannoth /**
394b747923aSRatheesh Kannoth  *	rvu_exact_prepare_mdata - Make mdata for mcam entry
395b747923aSRatheesh Kannoth  *	@mac: MAC address
396b747923aSRatheesh Kannoth  *	@chan: Channel number.
397b747923aSRatheesh Kannoth  *	@ctype: Channel Type.
398b747923aSRatheesh Kannoth  *	@mask: LDATA mask.
399b747923aSRatheesh Kannoth  *	Return: Meta data
400b747923aSRatheesh Kannoth  */
rvu_exact_prepare_mdata(u8 * mac,u16 chan,u16 ctype,u64 mask)401b747923aSRatheesh Kannoth static u64 rvu_exact_prepare_mdata(u8 *mac, u16 chan, u16 ctype, u64 mask)
402b747923aSRatheesh Kannoth {
403*47f8dc09SLi Zetao 	u64 ldata = ether_addr_to_u64(mac);
404b747923aSRatheesh Kannoth 
405b747923aSRatheesh Kannoth 	/* Please note that mask is 48bit which excludes chan and ctype.
406b747923aSRatheesh Kannoth 	 * Increase mask bits if we need to include them as well.
407b747923aSRatheesh Kannoth 	 */
408b747923aSRatheesh Kannoth 	ldata |= ((u64)chan << 48);
409b747923aSRatheesh Kannoth 	ldata |= ((u64)ctype  << 60);
410b747923aSRatheesh Kannoth 	ldata &= mask;
411b747923aSRatheesh Kannoth 	ldata = ldata << 2;
412b747923aSRatheesh Kannoth 
413b747923aSRatheesh Kannoth 	return ldata;
414b747923aSRatheesh Kannoth }
415b747923aSRatheesh Kannoth 
416b747923aSRatheesh Kannoth /**
417b747923aSRatheesh Kannoth  *      rvu_exact_calculate_hash - calculate hash index to mem table.
418b747923aSRatheesh Kannoth  *	@rvu: resource virtualization unit.
419b747923aSRatheesh Kannoth  *	@chan: Channel number
420b747923aSRatheesh Kannoth  *	@ctype: Channel type.
421b747923aSRatheesh Kannoth  *	@mac: MAC address
422b747923aSRatheesh Kannoth  *	@mask: HASH mask.
423b747923aSRatheesh Kannoth  *	@table_depth: Depth of table.
424b747923aSRatheesh Kannoth  *	Return: Hash value
425b747923aSRatheesh Kannoth  */
rvu_exact_calculate_hash(struct rvu * rvu,u16 chan,u16 ctype,u8 * mac,u64 mask,u32 table_depth)426b747923aSRatheesh Kannoth static u32 rvu_exact_calculate_hash(struct rvu *rvu, u16 chan, u16 ctype, u8 *mac,
427b747923aSRatheesh Kannoth 				    u64 mask, u32 table_depth)
428b747923aSRatheesh Kannoth {
429b747923aSRatheesh Kannoth 	struct npc_exact_table *table = rvu->hw->table;
430b747923aSRatheesh Kannoth 	u64 hash_key[2];
431b747923aSRatheesh Kannoth 	u64 key_in[2];
432b747923aSRatheesh Kannoth 	u64 ldata;
433b747923aSRatheesh Kannoth 	u32 hash;
434b747923aSRatheesh Kannoth 
435b747923aSRatheesh Kannoth 	key_in[0] = RVU_NPC_HASH_SECRET_KEY0;
436b747923aSRatheesh Kannoth 	key_in[1] = RVU_NPC_HASH_SECRET_KEY2;
437b747923aSRatheesh Kannoth 
438b747923aSRatheesh Kannoth 	hash_key[0] = key_in[0] << 31;
439b747923aSRatheesh Kannoth 	hash_key[0] |= key_in[1];
440b747923aSRatheesh Kannoth 	hash_key[1] = key_in[0] >> 33;
441b747923aSRatheesh Kannoth 
442b747923aSRatheesh Kannoth 	ldata = rvu_exact_prepare_mdata(mac, chan, ctype, mask);
443b747923aSRatheesh Kannoth 
444b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: ldata=0x%llx hash_key0=0x%llx hash_key2=0x%llx\n", __func__,
445b747923aSRatheesh Kannoth 		ldata, hash_key[1], hash_key[0]);
446b747923aSRatheesh Kannoth 	hash = rvu_npc_toeplitz_hash(&ldata, (u64 *)hash_key, 64, 95);
447b747923aSRatheesh Kannoth 
448b747923aSRatheesh Kannoth 	hash &= table->mem_table.hash_mask;
449b747923aSRatheesh Kannoth 	hash += table->mem_table.hash_offset;
450b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: hash=%x\n", __func__,  hash);
451b747923aSRatheesh Kannoth 
452b747923aSRatheesh Kannoth 	return hash;
453b747923aSRatheesh Kannoth }
454b747923aSRatheesh Kannoth 
455b747923aSRatheesh Kannoth /**
456b747923aSRatheesh Kannoth  *      rvu_npc_exact_alloc_mem_table_entry - find free entry in 4 way table.
457b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
458b747923aSRatheesh Kannoth  *	@way: Indicate way to table.
459b747923aSRatheesh Kannoth  *	@index: Hash index to 4 way table.
460b747923aSRatheesh Kannoth  *	@hash: Hash value.
461b747923aSRatheesh Kannoth  *
462b747923aSRatheesh Kannoth  *	Searches 4 way table using hash index. Returns 0 on success.
463b747923aSRatheesh Kannoth  *	Return: 0 upon success.
464b747923aSRatheesh Kannoth  */
rvu_npc_exact_alloc_mem_table_entry(struct rvu * rvu,u8 * way,u32 * index,unsigned int hash)465b747923aSRatheesh Kannoth static int rvu_npc_exact_alloc_mem_table_entry(struct rvu *rvu, u8 *way,
466b747923aSRatheesh Kannoth 					       u32 *index, unsigned int hash)
467b747923aSRatheesh Kannoth {
468b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
469b747923aSRatheesh Kannoth 	int depth, i;
470b747923aSRatheesh Kannoth 
471b747923aSRatheesh Kannoth 	table = rvu->hw->table;
472b747923aSRatheesh Kannoth 	depth = table->mem_table.depth;
473b747923aSRatheesh Kannoth 
474b747923aSRatheesh Kannoth 	/* Check all the 4 ways for a free slot. */
475b747923aSRatheesh Kannoth 	mutex_lock(&table->lock);
476b747923aSRatheesh Kannoth 	for (i = 0; i <  table->mem_table.ways; i++) {
477b747923aSRatheesh Kannoth 		if (test_bit(hash + i * depth, table->mem_table.bmap))
478b747923aSRatheesh Kannoth 			continue;
479b747923aSRatheesh Kannoth 
480b747923aSRatheesh Kannoth 		set_bit(hash + i * depth, table->mem_table.bmap);
481b747923aSRatheesh Kannoth 		mutex_unlock(&table->lock);
482b747923aSRatheesh Kannoth 
483b747923aSRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: mem table entry alloc success (way=%d index=%d)\n",
484b747923aSRatheesh Kannoth 			__func__, i, hash);
485b747923aSRatheesh Kannoth 
486b747923aSRatheesh Kannoth 		*way = i;
487b747923aSRatheesh Kannoth 		*index = hash;
488b747923aSRatheesh Kannoth 		return 0;
489b747923aSRatheesh Kannoth 	}
490b747923aSRatheesh Kannoth 	mutex_unlock(&table->lock);
491b747923aSRatheesh Kannoth 
492b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: No space in 4 way exact way, weight=%u\n", __func__,
493b747923aSRatheesh Kannoth 		bitmap_weight(table->mem_table.bmap, table->mem_table.depth));
494b747923aSRatheesh Kannoth 	return -ENOSPC;
495b747923aSRatheesh Kannoth }
496b747923aSRatheesh Kannoth 
497b747923aSRatheesh Kannoth /**
498b747923aSRatheesh Kannoth  *	rvu_npc_exact_free_id - Free seq id from bitmat.
499b747923aSRatheesh Kannoth  *	@rvu: Resource virtualization unit.
500b747923aSRatheesh Kannoth  *	@seq_id: Sequence identifier to be freed.
501b747923aSRatheesh Kannoth  */
rvu_npc_exact_free_id(struct rvu * rvu,u32 seq_id)502b747923aSRatheesh Kannoth static void rvu_npc_exact_free_id(struct rvu *rvu, u32 seq_id)
503b747923aSRatheesh Kannoth {
504b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
505b747923aSRatheesh Kannoth 
506b747923aSRatheesh Kannoth 	table = rvu->hw->table;
507b747923aSRatheesh Kannoth 	mutex_lock(&table->lock);
508b747923aSRatheesh Kannoth 	clear_bit(seq_id, table->id_bmap);
509b747923aSRatheesh Kannoth 	mutex_unlock(&table->lock);
510b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: freed id %d\n", __func__, seq_id);
511b747923aSRatheesh Kannoth }
512b747923aSRatheesh Kannoth 
513b747923aSRatheesh Kannoth /**
514b747923aSRatheesh Kannoth  *	rvu_npc_exact_alloc_id - Alloc seq id from bitmap.
515b747923aSRatheesh Kannoth  *	@rvu: Resource virtualization unit.
516b747923aSRatheesh Kannoth  *	@seq_id: Sequence identifier.
517b747923aSRatheesh Kannoth  *	Return: True or false.
518b747923aSRatheesh Kannoth  */
rvu_npc_exact_alloc_id(struct rvu * rvu,u32 * seq_id)519b747923aSRatheesh Kannoth static bool rvu_npc_exact_alloc_id(struct rvu *rvu, u32 *seq_id)
520b747923aSRatheesh Kannoth {
521b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
522b747923aSRatheesh Kannoth 	u32 idx;
523b747923aSRatheesh Kannoth 
524b747923aSRatheesh Kannoth 	table = rvu->hw->table;
525b747923aSRatheesh Kannoth 
526b747923aSRatheesh Kannoth 	mutex_lock(&table->lock);
527b747923aSRatheesh Kannoth 	idx = find_first_zero_bit(table->id_bmap, table->tot_ids);
528b747923aSRatheesh Kannoth 	if (idx == table->tot_ids) {
529b747923aSRatheesh Kannoth 		mutex_unlock(&table->lock);
530b747923aSRatheesh Kannoth 		dev_err(rvu->dev, "%s: No space in id bitmap (%d)\n",
5312450d7d9SChristophe JAILLET 			__func__, table->tot_ids);
532b747923aSRatheesh Kannoth 
533b747923aSRatheesh Kannoth 		return false;
534b747923aSRatheesh Kannoth 	}
535b747923aSRatheesh Kannoth 
536b747923aSRatheesh Kannoth 	/* Mark bit map to indicate that slot is used.*/
537b747923aSRatheesh Kannoth 	set_bit(idx, table->id_bmap);
538b747923aSRatheesh Kannoth 	mutex_unlock(&table->lock);
539b747923aSRatheesh Kannoth 
540b747923aSRatheesh Kannoth 	*seq_id = idx;
541b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: Allocated id (%d)\n", __func__, *seq_id);
542b747923aSRatheesh Kannoth 
543b747923aSRatheesh Kannoth 	return true;
544b747923aSRatheesh Kannoth }
545b747923aSRatheesh Kannoth 
546b747923aSRatheesh Kannoth /**
547b747923aSRatheesh Kannoth  *      rvu_npc_exact_alloc_cam_table_entry - find free slot in fully associative table.
548b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
549b747923aSRatheesh Kannoth  *	@index: Index to exact CAM table.
550b747923aSRatheesh Kannoth  *	Return: 0 upon success; else error number.
551b747923aSRatheesh Kannoth  */
rvu_npc_exact_alloc_cam_table_entry(struct rvu * rvu,int * index)552b747923aSRatheesh Kannoth static int rvu_npc_exact_alloc_cam_table_entry(struct rvu *rvu, int *index)
553b747923aSRatheesh Kannoth {
554b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
555b747923aSRatheesh Kannoth 	u32 idx;
556b747923aSRatheesh Kannoth 
557b747923aSRatheesh Kannoth 	table = rvu->hw->table;
558b747923aSRatheesh Kannoth 
559b747923aSRatheesh Kannoth 	mutex_lock(&table->lock);
560b747923aSRatheesh Kannoth 	idx = find_first_zero_bit(table->cam_table.bmap, table->cam_table.depth);
561b747923aSRatheesh Kannoth 	if (idx == table->cam_table.depth) {
562b747923aSRatheesh Kannoth 		mutex_unlock(&table->lock);
563b747923aSRatheesh Kannoth 		dev_info(rvu->dev, "%s: No space in exact cam table, weight=%u\n", __func__,
564b747923aSRatheesh Kannoth 			 bitmap_weight(table->cam_table.bmap, table->cam_table.depth));
565b747923aSRatheesh Kannoth 		return -ENOSPC;
566b747923aSRatheesh Kannoth 	}
567b747923aSRatheesh Kannoth 
568b747923aSRatheesh Kannoth 	/* Mark bit map to indicate that slot is used.*/
569b747923aSRatheesh Kannoth 	set_bit(idx, table->cam_table.bmap);
570b747923aSRatheesh Kannoth 	mutex_unlock(&table->lock);
571b747923aSRatheesh Kannoth 
572b747923aSRatheesh Kannoth 	*index = idx;
573b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: cam table entry alloc success (index=%d)\n",
574b747923aSRatheesh Kannoth 		__func__, idx);
575b747923aSRatheesh Kannoth 	return 0;
576b747923aSRatheesh Kannoth }
577b747923aSRatheesh Kannoth 
578b747923aSRatheesh Kannoth /**
579b747923aSRatheesh Kannoth  *	rvu_exact_prepare_table_entry - Data for exact match table entry.
580b747923aSRatheesh Kannoth  *	@rvu: Resource virtualization unit.
581b747923aSRatheesh Kannoth  *	@enable: Enable/Disable entry
582b747923aSRatheesh Kannoth  *	@ctype: Software defined channel type. Currently set as 0.
583b747923aSRatheesh Kannoth  *	@chan: Channel number.
584b747923aSRatheesh Kannoth  *	@mac_addr: Destination mac address.
585b747923aSRatheesh Kannoth  *	Return: mdata for exact match table.
586b747923aSRatheesh Kannoth  */
rvu_exact_prepare_table_entry(struct rvu * rvu,bool enable,u8 ctype,u16 chan,u8 * mac_addr)587b747923aSRatheesh Kannoth static u64 rvu_exact_prepare_table_entry(struct rvu *rvu, bool enable,
588b747923aSRatheesh Kannoth 					 u8 ctype, u16 chan, u8 *mac_addr)
589b747923aSRatheesh Kannoth 
590b747923aSRatheesh Kannoth {
591*47f8dc09SLi Zetao 	u64 ldata = ether_addr_to_u64(mac_addr);
592b747923aSRatheesh Kannoth 
593b747923aSRatheesh Kannoth 	/* Enable or disable */
594b747923aSRatheesh Kannoth 	u64 mdata = FIELD_PREP(GENMASK_ULL(63, 63), enable ? 1 : 0);
595b747923aSRatheesh Kannoth 
596b747923aSRatheesh Kannoth 	/* Set Ctype */
597b747923aSRatheesh Kannoth 	mdata |= FIELD_PREP(GENMASK_ULL(61, 60), ctype);
598b747923aSRatheesh Kannoth 
599b747923aSRatheesh Kannoth 	/* Set chan */
600b747923aSRatheesh Kannoth 	mdata |= FIELD_PREP(GENMASK_ULL(59, 48), chan);
601b747923aSRatheesh Kannoth 
602b747923aSRatheesh Kannoth 	/* MAC address */
603b747923aSRatheesh Kannoth 	mdata |= FIELD_PREP(GENMASK_ULL(47, 0), ldata);
604b747923aSRatheesh Kannoth 
605b747923aSRatheesh Kannoth 	return mdata;
606b747923aSRatheesh Kannoth }
607b747923aSRatheesh Kannoth 
608b747923aSRatheesh Kannoth /**
609b747923aSRatheesh Kannoth  *	rvu_exact_config_secret_key - Configure secret key.
610b747923aSRatheesh Kannoth  *	@rvu: Resource virtualization unit.
611b747923aSRatheesh Kannoth  */
rvu_exact_config_secret_key(struct rvu * rvu)612b747923aSRatheesh Kannoth static void rvu_exact_config_secret_key(struct rvu *rvu)
613b747923aSRatheesh Kannoth {
614b747923aSRatheesh Kannoth 	int blkaddr;
615b747923aSRatheesh Kannoth 
616b747923aSRatheesh Kannoth 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
617b747923aSRatheesh Kannoth 	rvu_write64(rvu, blkaddr, NPC_AF_INTFX_EXACT_SECRET0(NIX_INTF_RX),
618b747923aSRatheesh Kannoth 		    RVU_NPC_HASH_SECRET_KEY0);
619b747923aSRatheesh Kannoth 
620b747923aSRatheesh Kannoth 	rvu_write64(rvu, blkaddr, NPC_AF_INTFX_EXACT_SECRET1(NIX_INTF_RX),
621b747923aSRatheesh Kannoth 		    RVU_NPC_HASH_SECRET_KEY1);
622b747923aSRatheesh Kannoth 
623b747923aSRatheesh Kannoth 	rvu_write64(rvu, blkaddr, NPC_AF_INTFX_EXACT_SECRET2(NIX_INTF_RX),
624b747923aSRatheesh Kannoth 		    RVU_NPC_HASH_SECRET_KEY2);
625b747923aSRatheesh Kannoth }
626b747923aSRatheesh Kannoth 
627b747923aSRatheesh Kannoth /**
628b747923aSRatheesh Kannoth  *	rvu_exact_config_search_key - Configure search key
629b747923aSRatheesh Kannoth  *	@rvu: Resource virtualization unit.
630b747923aSRatheesh Kannoth  */
rvu_exact_config_search_key(struct rvu * rvu)631b747923aSRatheesh Kannoth static void rvu_exact_config_search_key(struct rvu *rvu)
632b747923aSRatheesh Kannoth {
633b747923aSRatheesh Kannoth 	int blkaddr;
634b747923aSRatheesh Kannoth 	u64 reg_val;
635b747923aSRatheesh Kannoth 
636b747923aSRatheesh Kannoth 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
637b747923aSRatheesh Kannoth 
638b747923aSRatheesh Kannoth 	/* HDR offset */
639b747923aSRatheesh Kannoth 	reg_val = FIELD_PREP(GENMASK_ULL(39, 32), 0);
640b747923aSRatheesh Kannoth 
641b747923aSRatheesh Kannoth 	/* BYTESM1, number of bytes - 1 */
642b747923aSRatheesh Kannoth 	reg_val |= FIELD_PREP(GENMASK_ULL(18, 16), ETH_ALEN - 1);
643b747923aSRatheesh Kannoth 
644b747923aSRatheesh Kannoth 	/* Enable LID and set LID to  NPC_LID_LA */
645b747923aSRatheesh Kannoth 	reg_val |= FIELD_PREP(GENMASK_ULL(11, 11), 1);
646b747923aSRatheesh Kannoth 	reg_val |= FIELD_PREP(GENMASK_ULL(10, 8),  NPC_LID_LA);
647b747923aSRatheesh Kannoth 
648b747923aSRatheesh Kannoth 	/* Clear layer type based extraction */
649b747923aSRatheesh Kannoth 
650b747923aSRatheesh Kannoth 	/* Disable LT_EN */
651b747923aSRatheesh Kannoth 	reg_val |= FIELD_PREP(GENMASK_ULL(12, 12), 0);
652b747923aSRatheesh Kannoth 
653b747923aSRatheesh Kannoth 	/* Set LTYPE_MATCH to 0 */
654b747923aSRatheesh Kannoth 	reg_val |= FIELD_PREP(GENMASK_ULL(7, 4), 0);
655b747923aSRatheesh Kannoth 
656b747923aSRatheesh Kannoth 	/* Set LTYPE_MASK to 0 */
657b747923aSRatheesh Kannoth 	reg_val |= FIELD_PREP(GENMASK_ULL(3, 0), 0);
658b747923aSRatheesh Kannoth 
659b747923aSRatheesh Kannoth 	rvu_write64(rvu, blkaddr, NPC_AF_INTFX_EXACT_CFG(NIX_INTF_RX), reg_val);
660b747923aSRatheesh Kannoth }
661b747923aSRatheesh Kannoth 
662b747923aSRatheesh Kannoth /**
663b747923aSRatheesh Kannoth  *	rvu_exact_config_result_ctrl - Set exact table hash control
664b747923aSRatheesh Kannoth  *	@rvu: Resource virtualization unit.
665b747923aSRatheesh Kannoth  *	@depth: Depth of Exact match table.
666b747923aSRatheesh Kannoth  *
667b747923aSRatheesh Kannoth  *	Sets mask and offset for hash for mem table.
668b747923aSRatheesh Kannoth  */
rvu_exact_config_result_ctrl(struct rvu * rvu,uint32_t depth)669b747923aSRatheesh Kannoth static void rvu_exact_config_result_ctrl(struct rvu *rvu, uint32_t depth)
670b747923aSRatheesh Kannoth {
671b747923aSRatheesh Kannoth 	int blkaddr;
672b747923aSRatheesh Kannoth 	u64 reg = 0;
673b747923aSRatheesh Kannoth 
674b747923aSRatheesh Kannoth 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
675b747923aSRatheesh Kannoth 
676b747923aSRatheesh Kannoth 	/* Set mask. Note that depth is a power of 2 */
677b747923aSRatheesh Kannoth 	rvu->hw->table->mem_table.hash_mask = (depth - 1);
678b747923aSRatheesh Kannoth 	reg |= FIELD_PREP(GENMASK_ULL(42, 32), (depth - 1));
679b747923aSRatheesh Kannoth 
680b747923aSRatheesh Kannoth 	/* Set offset as 0 */
681b747923aSRatheesh Kannoth 	rvu->hw->table->mem_table.hash_offset = 0;
682b747923aSRatheesh Kannoth 	reg |= FIELD_PREP(GENMASK_ULL(10, 0), 0);
683b747923aSRatheesh Kannoth 
684b747923aSRatheesh Kannoth 	/* Set reg for RX */
685b747923aSRatheesh Kannoth 	rvu_write64(rvu, blkaddr, NPC_AF_INTFX_EXACT_RESULT_CTL(NIX_INTF_RX), reg);
686b747923aSRatheesh Kannoth 	/* Store hash mask and offset for s/w algorithm */
687b747923aSRatheesh Kannoth }
688b747923aSRatheesh Kannoth 
689b747923aSRatheesh Kannoth /**
690b747923aSRatheesh Kannoth  *	rvu_exact_config_table_mask - Set exact table mask.
691b747923aSRatheesh Kannoth  *	@rvu: Resource virtualization unit.
692b747923aSRatheesh Kannoth  */
rvu_exact_config_table_mask(struct rvu * rvu)693b747923aSRatheesh Kannoth static void rvu_exact_config_table_mask(struct rvu *rvu)
694b747923aSRatheesh Kannoth {
695b747923aSRatheesh Kannoth 	int blkaddr;
696b747923aSRatheesh Kannoth 	u64 mask = 0;
697b747923aSRatheesh Kannoth 
698b747923aSRatheesh Kannoth 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
699b747923aSRatheesh Kannoth 
700b747923aSRatheesh Kannoth 	/* Don't use Ctype */
701b747923aSRatheesh Kannoth 	mask |= FIELD_PREP(GENMASK_ULL(61, 60), 0);
702b747923aSRatheesh Kannoth 
703b747923aSRatheesh Kannoth 	/* Set chan */
704b747923aSRatheesh Kannoth 	mask |= GENMASK_ULL(59, 48);
705b747923aSRatheesh Kannoth 
706b747923aSRatheesh Kannoth 	/* Full ldata */
707b747923aSRatheesh Kannoth 	mask |= GENMASK_ULL(47, 0);
708b747923aSRatheesh Kannoth 
709b747923aSRatheesh Kannoth 	/* Store mask for s/w hash calcualtion */
710b747923aSRatheesh Kannoth 	rvu->hw->table->mem_table.mask = mask;
711b747923aSRatheesh Kannoth 
712b747923aSRatheesh Kannoth 	/* Set mask for RX.*/
713b747923aSRatheesh Kannoth 	rvu_write64(rvu, blkaddr, NPC_AF_INTFX_EXACT_MASK(NIX_INTF_RX), mask);
714b747923aSRatheesh Kannoth }
715b747923aSRatheesh Kannoth 
716b747923aSRatheesh Kannoth /**
717b747923aSRatheesh Kannoth  *      rvu_npc_exact_get_max_entries - Get total number of entries in table.
718b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
719b747923aSRatheesh Kannoth  *	Return: Maximum table entries possible.
720b747923aSRatheesh Kannoth  */
rvu_npc_exact_get_max_entries(struct rvu * rvu)721b747923aSRatheesh Kannoth u32 rvu_npc_exact_get_max_entries(struct rvu *rvu)
722b747923aSRatheesh Kannoth {
723b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
724b747923aSRatheesh Kannoth 
725b747923aSRatheesh Kannoth 	table = rvu->hw->table;
726b747923aSRatheesh Kannoth 	return table->tot_ids;
727b747923aSRatheesh Kannoth }
728b747923aSRatheesh Kannoth 
729b747923aSRatheesh Kannoth /**
730b747923aSRatheesh Kannoth  *      rvu_npc_exact_has_match_table - Checks support for exact match.
731b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
732b747923aSRatheesh Kannoth  *	Return: True if exact match table is supported/enabled.
733b747923aSRatheesh Kannoth  */
rvu_npc_exact_has_match_table(struct rvu * rvu)734b747923aSRatheesh Kannoth bool rvu_npc_exact_has_match_table(struct rvu *rvu)
735b747923aSRatheesh Kannoth {
736b747923aSRatheesh Kannoth 	return  rvu->hw->cap.npc_exact_match_enabled;
737b747923aSRatheesh Kannoth }
738b747923aSRatheesh Kannoth 
739b747923aSRatheesh Kannoth /**
740b747923aSRatheesh Kannoth  *      __rvu_npc_exact_find_entry_by_seq_id - find entry by id
741b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
742b747923aSRatheesh Kannoth  *	@seq_id: Sequence identifier.
743b747923aSRatheesh Kannoth  *
744b747923aSRatheesh Kannoth  *	Caller should acquire the lock.
745b747923aSRatheesh Kannoth  *	Return: Pointer to table entry.
746b747923aSRatheesh Kannoth  */
747b747923aSRatheesh Kannoth static struct npc_exact_table_entry *
__rvu_npc_exact_find_entry_by_seq_id(struct rvu * rvu,u32 seq_id)748b747923aSRatheesh Kannoth __rvu_npc_exact_find_entry_by_seq_id(struct rvu *rvu, u32 seq_id)
749b747923aSRatheesh Kannoth {
750b747923aSRatheesh Kannoth 	struct npc_exact_table *table = rvu->hw->table;
751b747923aSRatheesh Kannoth 	struct npc_exact_table_entry *entry = NULL;
752b747923aSRatheesh Kannoth 	struct list_head *lhead;
753b747923aSRatheesh Kannoth 
754b747923aSRatheesh Kannoth 	lhead = &table->lhead_gbl;
755b747923aSRatheesh Kannoth 
756b747923aSRatheesh Kannoth 	/* traverse to find the matching entry */
757b747923aSRatheesh Kannoth 	list_for_each_entry(entry, lhead, glist) {
758b747923aSRatheesh Kannoth 		if (entry->seq_id != seq_id)
759b747923aSRatheesh Kannoth 			continue;
760b747923aSRatheesh Kannoth 
761b747923aSRatheesh Kannoth 		return entry;
762b747923aSRatheesh Kannoth 	}
763b747923aSRatheesh Kannoth 
764b747923aSRatheesh Kannoth 	return NULL;
765b747923aSRatheesh Kannoth }
766b747923aSRatheesh Kannoth 
767b747923aSRatheesh Kannoth /**
768b747923aSRatheesh Kannoth  *      rvu_npc_exact_add_to_list - Add entry to list
769b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
770b747923aSRatheesh Kannoth  *	@opc_type: OPCODE to select MEM/CAM table.
771b747923aSRatheesh Kannoth  *	@ways: MEM table ways.
772b747923aSRatheesh Kannoth  *	@index: Index in MEM/CAM table.
773b747923aSRatheesh Kannoth  *	@cgx_id: CGX identifier.
774b747923aSRatheesh Kannoth  *	@lmac_id: LMAC identifier.
775b747923aSRatheesh Kannoth  *	@mac_addr: MAC address.
776b747923aSRatheesh Kannoth  *	@chan: Channel number.
777b747923aSRatheesh Kannoth  *	@ctype: Channel Type.
778b747923aSRatheesh Kannoth  *	@seq_id: Sequence identifier
779b747923aSRatheesh Kannoth  *	@cmd: True if function is called by ethtool cmd
780b747923aSRatheesh Kannoth  *	@mcam_idx: NPC mcam index of DMAC entry in NPC mcam.
781b747923aSRatheesh Kannoth  *	@pcifunc: pci function
782b747923aSRatheesh Kannoth  *	Return: 0 upon success.
783b747923aSRatheesh Kannoth  */
rvu_npc_exact_add_to_list(struct rvu * rvu,enum npc_exact_opc_type opc_type,u8 ways,u32 index,u8 cgx_id,u8 lmac_id,u8 * mac_addr,u16 chan,u8 ctype,u32 * seq_id,bool cmd,u32 mcam_idx,u16 pcifunc)784b747923aSRatheesh Kannoth static int rvu_npc_exact_add_to_list(struct rvu *rvu, enum npc_exact_opc_type opc_type, u8 ways,
785b747923aSRatheesh Kannoth 				     u32 index, u8 cgx_id, u8 lmac_id, u8 *mac_addr, u16 chan,
786b747923aSRatheesh Kannoth 				     u8 ctype, u32 *seq_id, bool cmd, u32 mcam_idx, u16 pcifunc)
787b747923aSRatheesh Kannoth {
788b747923aSRatheesh Kannoth 	struct npc_exact_table_entry *entry, *tmp, *iter;
789b747923aSRatheesh Kannoth 	struct npc_exact_table *table = rvu->hw->table;
790b747923aSRatheesh Kannoth 	struct list_head *lhead, *pprev;
791b747923aSRatheesh Kannoth 
792b747923aSRatheesh Kannoth 	WARN_ON(ways >= NPC_EXACT_TBL_MAX_WAYS);
793b747923aSRatheesh Kannoth 
794b747923aSRatheesh Kannoth 	if (!rvu_npc_exact_alloc_id(rvu, seq_id)) {
795b747923aSRatheesh Kannoth 		dev_err(rvu->dev, "%s: Generate seq id failed\n", __func__);
796b747923aSRatheesh Kannoth 		return -EFAULT;
797b747923aSRatheesh Kannoth 	}
798b747923aSRatheesh Kannoth 
799b747923aSRatheesh Kannoth 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
800b747923aSRatheesh Kannoth 	if (!entry) {
801b747923aSRatheesh Kannoth 		rvu_npc_exact_free_id(rvu, *seq_id);
802b747923aSRatheesh Kannoth 		dev_err(rvu->dev, "%s: Memory allocation failed\n", __func__);
803b747923aSRatheesh Kannoth 		return -ENOMEM;
804b747923aSRatheesh Kannoth 	}
805b747923aSRatheesh Kannoth 
806b747923aSRatheesh Kannoth 	mutex_lock(&table->lock);
807b747923aSRatheesh Kannoth 	switch (opc_type) {
808b747923aSRatheesh Kannoth 	case NPC_EXACT_OPC_CAM:
809b747923aSRatheesh Kannoth 		lhead = &table->lhead_cam_tbl_entry;
810b747923aSRatheesh Kannoth 		table->cam_tbl_entry_cnt++;
811b747923aSRatheesh Kannoth 		break;
812b747923aSRatheesh Kannoth 
813b747923aSRatheesh Kannoth 	case NPC_EXACT_OPC_MEM:
814b747923aSRatheesh Kannoth 		lhead = &table->lhead_mem_tbl_entry[ways];
815b747923aSRatheesh Kannoth 		table->mem_tbl_entry_cnt++;
816b747923aSRatheesh Kannoth 		break;
817b747923aSRatheesh Kannoth 
818b747923aSRatheesh Kannoth 	default:
819b747923aSRatheesh Kannoth 		mutex_unlock(&table->lock);
820b747923aSRatheesh Kannoth 		kfree(entry);
821b747923aSRatheesh Kannoth 		rvu_npc_exact_free_id(rvu, *seq_id);
822b747923aSRatheesh Kannoth 
823b747923aSRatheesh Kannoth 		dev_err(rvu->dev, "%s: Unknown opc type%d\n", __func__, opc_type);
824b747923aSRatheesh Kannoth 		return  -EINVAL;
825b747923aSRatheesh Kannoth 	}
826b747923aSRatheesh Kannoth 
827b747923aSRatheesh Kannoth 	/* Add to global list */
828b747923aSRatheesh Kannoth 	INIT_LIST_HEAD(&entry->glist);
829b747923aSRatheesh Kannoth 	list_add_tail(&entry->glist, &table->lhead_gbl);
830b747923aSRatheesh Kannoth 	INIT_LIST_HEAD(&entry->list);
831b747923aSRatheesh Kannoth 	entry->index = index;
832b747923aSRatheesh Kannoth 	entry->ways = ways;
833b747923aSRatheesh Kannoth 	entry->opc_type = opc_type;
834b747923aSRatheesh Kannoth 
835b747923aSRatheesh Kannoth 	entry->pcifunc = pcifunc;
836b747923aSRatheesh Kannoth 
837b747923aSRatheesh Kannoth 	ether_addr_copy(entry->mac, mac_addr);
838b747923aSRatheesh Kannoth 	entry->chan = chan;
839b747923aSRatheesh Kannoth 	entry->ctype = ctype;
840b747923aSRatheesh Kannoth 	entry->cgx_id = cgx_id;
841b747923aSRatheesh Kannoth 	entry->lmac_id = lmac_id;
842b747923aSRatheesh Kannoth 
843b747923aSRatheesh Kannoth 	entry->seq_id = *seq_id;
844b747923aSRatheesh Kannoth 
845b747923aSRatheesh Kannoth 	entry->mcam_idx = mcam_idx;
846b747923aSRatheesh Kannoth 	entry->cmd = cmd;
847b747923aSRatheesh Kannoth 
848b747923aSRatheesh Kannoth 	pprev = lhead;
849b747923aSRatheesh Kannoth 
850b747923aSRatheesh Kannoth 	/* Insert entry in ascending order of index */
851b747923aSRatheesh Kannoth 	list_for_each_entry_safe(iter, tmp, lhead, list) {
852b747923aSRatheesh Kannoth 		if (index < iter->index)
853b747923aSRatheesh Kannoth 			break;
854b747923aSRatheesh Kannoth 
855b747923aSRatheesh Kannoth 		pprev = &iter->list;
856b747923aSRatheesh Kannoth 	}
857b747923aSRatheesh Kannoth 
858b747923aSRatheesh Kannoth 	/* Add to each table list */
859b747923aSRatheesh Kannoth 	list_add(&entry->list, pprev);
860b747923aSRatheesh Kannoth 	mutex_unlock(&table->lock);
861b747923aSRatheesh Kannoth 	return 0;
862b747923aSRatheesh Kannoth }
863b747923aSRatheesh Kannoth 
864b747923aSRatheesh Kannoth /**
865b747923aSRatheesh Kannoth  *	rvu_npc_exact_mem_table_write - Wrapper for register write
866b747923aSRatheesh Kannoth  *	@rvu: resource virtualization unit.
867b747923aSRatheesh Kannoth  *	@blkaddr: Block address
868b747923aSRatheesh Kannoth  *	@ways: ways for MEM table.
869b747923aSRatheesh Kannoth  *	@index: Index in MEM
870b747923aSRatheesh Kannoth  *	@mdata: Meta data to be written to register.
871b747923aSRatheesh Kannoth  */
rvu_npc_exact_mem_table_write(struct rvu * rvu,int blkaddr,u8 ways,u32 index,u64 mdata)872b747923aSRatheesh Kannoth static void rvu_npc_exact_mem_table_write(struct rvu *rvu, int blkaddr, u8 ways,
873b747923aSRatheesh Kannoth 					  u32 index, u64 mdata)
874b747923aSRatheesh Kannoth {
875b747923aSRatheesh Kannoth 	rvu_write64(rvu, blkaddr, NPC_AF_EXACT_MEM_ENTRY(ways, index), mdata);
876b747923aSRatheesh Kannoth }
877b747923aSRatheesh Kannoth 
878b747923aSRatheesh Kannoth /**
879b747923aSRatheesh Kannoth  *	rvu_npc_exact_cam_table_write - Wrapper for register write
880b747923aSRatheesh Kannoth  *	@rvu: resource virtualization unit.
881b747923aSRatheesh Kannoth  *	@blkaddr: Block address
882b747923aSRatheesh Kannoth  *	@index: Index in MEM
883b747923aSRatheesh Kannoth  *	@mdata: Meta data to be written to register.
884b747923aSRatheesh Kannoth  */
rvu_npc_exact_cam_table_write(struct rvu * rvu,int blkaddr,u32 index,u64 mdata)885b747923aSRatheesh Kannoth static void rvu_npc_exact_cam_table_write(struct rvu *rvu, int blkaddr,
886b747923aSRatheesh Kannoth 					  u32 index, u64 mdata)
887b747923aSRatheesh Kannoth {
888b747923aSRatheesh Kannoth 	rvu_write64(rvu, blkaddr, NPC_AF_EXACT_CAM_ENTRY(index), mdata);
889b747923aSRatheesh Kannoth }
890b747923aSRatheesh Kannoth 
891b747923aSRatheesh Kannoth /**
892b747923aSRatheesh Kannoth  *      rvu_npc_exact_dealloc_table_entry - dealloc table entry
893b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
894b747923aSRatheesh Kannoth  *	@opc_type: OPCODE for selection of table(MEM or CAM)
895b747923aSRatheesh Kannoth  *	@ways: ways if opc_type is MEM table.
896b747923aSRatheesh Kannoth  *	@index: Index of MEM or CAM table.
897b747923aSRatheesh Kannoth  *	Return: 0 upon success.
898b747923aSRatheesh Kannoth  */
rvu_npc_exact_dealloc_table_entry(struct rvu * rvu,enum npc_exact_opc_type opc_type,u8 ways,u32 index)899b747923aSRatheesh Kannoth static int rvu_npc_exact_dealloc_table_entry(struct rvu *rvu, enum npc_exact_opc_type opc_type,
900b747923aSRatheesh Kannoth 					     u8 ways, u32 index)
901b747923aSRatheesh Kannoth {
902b747923aSRatheesh Kannoth 	int blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
903b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
904b747923aSRatheesh Kannoth 	u8 null_dmac[6] = { 0 };
905b747923aSRatheesh Kannoth 	int depth;
906b747923aSRatheesh Kannoth 
907b747923aSRatheesh Kannoth 	/* Prepare entry with all fields set to zero */
908b747923aSRatheesh Kannoth 	u64 null_mdata = rvu_exact_prepare_table_entry(rvu, false, 0, 0, null_dmac);
909b747923aSRatheesh Kannoth 
910b747923aSRatheesh Kannoth 	table = rvu->hw->table;
911b747923aSRatheesh Kannoth 	depth = table->mem_table.depth;
912b747923aSRatheesh Kannoth 
913b747923aSRatheesh Kannoth 	mutex_lock(&table->lock);
914b747923aSRatheesh Kannoth 
915b747923aSRatheesh Kannoth 	switch (opc_type) {
916b747923aSRatheesh Kannoth 	case NPC_EXACT_OPC_CAM:
917b747923aSRatheesh Kannoth 
918b747923aSRatheesh Kannoth 		/* Check whether entry is used already */
919b747923aSRatheesh Kannoth 		if (!test_bit(index, table->cam_table.bmap)) {
920b747923aSRatheesh Kannoth 			mutex_unlock(&table->lock);
921b747923aSRatheesh Kannoth 			dev_err(rvu->dev, "%s: Trying to free an unused entry ways=%d index=%d\n",
922b747923aSRatheesh Kannoth 				__func__, ways, index);
923b747923aSRatheesh Kannoth 			return -EINVAL;
924b747923aSRatheesh Kannoth 		}
925b747923aSRatheesh Kannoth 
926b747923aSRatheesh Kannoth 		rvu_npc_exact_cam_table_write(rvu, blkaddr, index, null_mdata);
927b747923aSRatheesh Kannoth 		clear_bit(index, table->cam_table.bmap);
928b747923aSRatheesh Kannoth 		break;
929b747923aSRatheesh Kannoth 
930b747923aSRatheesh Kannoth 	case NPC_EXACT_OPC_MEM:
931b747923aSRatheesh Kannoth 
932b747923aSRatheesh Kannoth 		/* Check whether entry is used already */
933b747923aSRatheesh Kannoth 		if (!test_bit(index + ways * depth, table->mem_table.bmap)) {
934b747923aSRatheesh Kannoth 			mutex_unlock(&table->lock);
935b747923aSRatheesh Kannoth 			dev_err(rvu->dev, "%s: Trying to free an unused entry index=%d\n",
936b747923aSRatheesh Kannoth 				__func__, index);
937b747923aSRatheesh Kannoth 			return -EINVAL;
938b747923aSRatheesh Kannoth 		}
939b747923aSRatheesh Kannoth 
940b747923aSRatheesh Kannoth 		rvu_npc_exact_mem_table_write(rvu, blkaddr, ways, index, null_mdata);
941b747923aSRatheesh Kannoth 		clear_bit(index + ways * depth, table->mem_table.bmap);
942b747923aSRatheesh Kannoth 		break;
943b747923aSRatheesh Kannoth 
944b747923aSRatheesh Kannoth 	default:
945b747923aSRatheesh Kannoth 		mutex_unlock(&table->lock);
946b747923aSRatheesh Kannoth 		dev_err(rvu->dev, "%s: invalid opc type %d", __func__, opc_type);
947b747923aSRatheesh Kannoth 		return -ENOSPC;
948b747923aSRatheesh Kannoth 	}
949b747923aSRatheesh Kannoth 
950b747923aSRatheesh Kannoth 	mutex_unlock(&table->lock);
951b747923aSRatheesh Kannoth 
952b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: Successfully deleted entry (index=%d, ways=%d opc_type=%d\n",
953b747923aSRatheesh Kannoth 		__func__, index,  ways, opc_type);
954b747923aSRatheesh Kannoth 
955b747923aSRatheesh Kannoth 	return 0;
956b747923aSRatheesh Kannoth }
957b747923aSRatheesh Kannoth 
958b747923aSRatheesh Kannoth /**
959b747923aSRatheesh Kannoth  *	rvu_npc_exact_alloc_table_entry - Allociate an entry
960b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
961b747923aSRatheesh Kannoth  *	@mac: MAC address.
962b747923aSRatheesh Kannoth  *	@chan: Channel number.
963b747923aSRatheesh Kannoth  *	@ctype: Channel Type.
964b747923aSRatheesh Kannoth  *	@index: Index of MEM table or CAM table.
965b747923aSRatheesh Kannoth  *	@ways: Ways. Only valid for MEM table.
966b747923aSRatheesh Kannoth  *	@opc_type: OPCODE to select table (MEM or CAM)
967b747923aSRatheesh Kannoth  *
968b747923aSRatheesh Kannoth  *	Try allocating a slot from MEM table. If all 4 ways
969b747923aSRatheesh Kannoth  *	slot are full for a hash index, check availability in
970b747923aSRatheesh Kannoth  *	32-entry CAM table for allocation.
971b747923aSRatheesh Kannoth  *	Return: 0 upon success.
972b747923aSRatheesh Kannoth  */
rvu_npc_exact_alloc_table_entry(struct rvu * rvu,char * mac,u16 chan,u8 ctype,u32 * index,u8 * ways,enum npc_exact_opc_type * opc_type)973b747923aSRatheesh Kannoth static int rvu_npc_exact_alloc_table_entry(struct rvu *rvu,  char *mac, u16 chan, u8 ctype,
974b747923aSRatheesh Kannoth 					   u32 *index, u8 *ways, enum npc_exact_opc_type *opc_type)
975b747923aSRatheesh Kannoth {
976b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
977b747923aSRatheesh Kannoth 	unsigned int hash;
978b747923aSRatheesh Kannoth 	int err;
979b747923aSRatheesh Kannoth 
980b747923aSRatheesh Kannoth 	table = rvu->hw->table;
981b747923aSRatheesh Kannoth 
982b747923aSRatheesh Kannoth 	/* Check in 4-ways mem entry for free slote */
983b747923aSRatheesh Kannoth 	hash =  rvu_exact_calculate_hash(rvu, chan, ctype, mac, table->mem_table.mask,
984b747923aSRatheesh Kannoth 					 table->mem_table.depth);
985b747923aSRatheesh Kannoth 	err = rvu_npc_exact_alloc_mem_table_entry(rvu, ways, index, hash);
986b747923aSRatheesh Kannoth 	if (!err) {
987b747923aSRatheesh Kannoth 		*opc_type = NPC_EXACT_OPC_MEM;
988b747923aSRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: inserted in 4 ways hash table ways=%d, index=%d\n",
989b747923aSRatheesh Kannoth 			__func__, *ways, *index);
990b747923aSRatheesh Kannoth 		return 0;
991b747923aSRatheesh Kannoth 	}
992b747923aSRatheesh Kannoth 
993b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: failed to insert in 4 ways hash table\n", __func__);
994b747923aSRatheesh Kannoth 
995b747923aSRatheesh Kannoth 	/* wayss is 0 for cam table */
996b747923aSRatheesh Kannoth 	*ways = 0;
997b747923aSRatheesh Kannoth 	err = rvu_npc_exact_alloc_cam_table_entry(rvu, index);
998b747923aSRatheesh Kannoth 	if (!err) {
999b747923aSRatheesh Kannoth 		*opc_type = NPC_EXACT_OPC_CAM;
1000b747923aSRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: inserted in fully associative hash table index=%u\n",
1001b747923aSRatheesh Kannoth 			__func__, *index);
1002b747923aSRatheesh Kannoth 		return 0;
1003b747923aSRatheesh Kannoth 	}
1004b747923aSRatheesh Kannoth 
1005b747923aSRatheesh Kannoth 	dev_err(rvu->dev, "%s: failed to insert in fully associative hash table\n", __func__);
1006b747923aSRatheesh Kannoth 	return -ENOSPC;
1007b747923aSRatheesh Kannoth }
1008b747923aSRatheesh Kannoth 
1009b747923aSRatheesh Kannoth /**
10103571fe07SRatheesh Kannoth  *	rvu_npc_exact_save_drop_rule_chan_and_mask - Save drop rules info in data base.
10113571fe07SRatheesh Kannoth  *      @rvu: resource virtualization unit.
10123571fe07SRatheesh Kannoth  *	@drop_mcam_idx: Drop rule index in NPC mcam.
10133571fe07SRatheesh Kannoth  *	@chan_val: Channel value.
10143571fe07SRatheesh Kannoth  *	@chan_mask: Channel Mask.
10153571fe07SRatheesh Kannoth  *	@pcifunc: pcifunc of interface.
10163571fe07SRatheesh Kannoth  *	Return: True upon success.
10173571fe07SRatheesh Kannoth  */
rvu_npc_exact_save_drop_rule_chan_and_mask(struct rvu * rvu,int drop_mcam_idx,u64 chan_val,u64 chan_mask,u16 pcifunc)10183571fe07SRatheesh Kannoth static bool rvu_npc_exact_save_drop_rule_chan_and_mask(struct rvu *rvu, int drop_mcam_idx,
10193571fe07SRatheesh Kannoth 						       u64 chan_val, u64 chan_mask, u16 pcifunc)
10203571fe07SRatheesh Kannoth {
10213571fe07SRatheesh Kannoth 	struct npc_exact_table *table;
10223571fe07SRatheesh Kannoth 	int i;
10233571fe07SRatheesh Kannoth 
10243571fe07SRatheesh Kannoth 	table = rvu->hw->table;
10253571fe07SRatheesh Kannoth 
10263571fe07SRatheesh Kannoth 	for (i = 0; i < NPC_MCAM_DROP_RULE_MAX; i++) {
10273571fe07SRatheesh Kannoth 		if (!table->drop_rule_map[i].valid)
10283571fe07SRatheesh Kannoth 			break;
10293571fe07SRatheesh Kannoth 
10303571fe07SRatheesh Kannoth 		if (table->drop_rule_map[i].chan_val != (u16)chan_val)
10313571fe07SRatheesh Kannoth 			continue;
10323571fe07SRatheesh Kannoth 
10333571fe07SRatheesh Kannoth 		if (table->drop_rule_map[i].chan_mask != (u16)chan_mask)
10343571fe07SRatheesh Kannoth 			continue;
10353571fe07SRatheesh Kannoth 
10363571fe07SRatheesh Kannoth 		return false;
10373571fe07SRatheesh Kannoth 	}
10383571fe07SRatheesh Kannoth 
10393571fe07SRatheesh Kannoth 	if (i == NPC_MCAM_DROP_RULE_MAX)
10403571fe07SRatheesh Kannoth 		return false;
10413571fe07SRatheesh Kannoth 
10423571fe07SRatheesh Kannoth 	table->drop_rule_map[i].drop_rule_idx = drop_mcam_idx;
10433571fe07SRatheesh Kannoth 	table->drop_rule_map[i].chan_val = (u16)chan_val;
10443571fe07SRatheesh Kannoth 	table->drop_rule_map[i].chan_mask = (u16)chan_mask;
10453571fe07SRatheesh Kannoth 	table->drop_rule_map[i].pcifunc = pcifunc;
10463571fe07SRatheesh Kannoth 	table->drop_rule_map[i].valid = true;
10473571fe07SRatheesh Kannoth 	return true;
10483571fe07SRatheesh Kannoth }
10493571fe07SRatheesh Kannoth 
10503571fe07SRatheesh Kannoth /**
10513571fe07SRatheesh Kannoth  *	rvu_npc_exact_calc_drop_rule_chan_and_mask - Calculate Channel number and mask.
10523571fe07SRatheesh Kannoth  *      @rvu: resource virtualization unit.
10533571fe07SRatheesh Kannoth  *	@intf_type: Interface type (SDK, LBK or CGX)
10543571fe07SRatheesh Kannoth  *	@cgx_id: CGX identifier.
10553571fe07SRatheesh Kannoth  *	@lmac_id: LAMC identifier.
10563571fe07SRatheesh Kannoth  *	@val: Channel number.
10573571fe07SRatheesh Kannoth  *	@mask: Channel mask.
10583571fe07SRatheesh Kannoth  *	Return: True upon success.
10593571fe07SRatheesh Kannoth  */
rvu_npc_exact_calc_drop_rule_chan_and_mask(struct rvu * rvu,u8 intf_type,u8 cgx_id,u8 lmac_id,u64 * val,u64 * mask)10603571fe07SRatheesh Kannoth static bool rvu_npc_exact_calc_drop_rule_chan_and_mask(struct rvu *rvu, u8 intf_type,
10613571fe07SRatheesh Kannoth 						       u8 cgx_id, u8 lmac_id,
10623571fe07SRatheesh Kannoth 						       u64 *val, u64 *mask)
10633571fe07SRatheesh Kannoth {
10643571fe07SRatheesh Kannoth 	u16 chan_val, chan_mask;
10653571fe07SRatheesh Kannoth 
10663571fe07SRatheesh Kannoth 	/* No support for SDP and LBK */
10673571fe07SRatheesh Kannoth 	if (intf_type != NIX_INTF_TYPE_CGX)
10683571fe07SRatheesh Kannoth 		return false;
10693571fe07SRatheesh Kannoth 
10703571fe07SRatheesh Kannoth 	chan_val = rvu_nix_chan_cgx(rvu, cgx_id, lmac_id, 0);
10713571fe07SRatheesh Kannoth 	chan_mask = 0xfff;
10723571fe07SRatheesh Kannoth 
10733571fe07SRatheesh Kannoth 	if (val)
10743571fe07SRatheesh Kannoth 		*val = chan_val;
10753571fe07SRatheesh Kannoth 
10763571fe07SRatheesh Kannoth 	if (mask)
10773571fe07SRatheesh Kannoth 		*mask = chan_mask;
10783571fe07SRatheesh Kannoth 
10793571fe07SRatheesh Kannoth 	return true;
10803571fe07SRatheesh Kannoth }
10813571fe07SRatheesh Kannoth 
10823571fe07SRatheesh Kannoth /**
10833571fe07SRatheesh Kannoth  *	rvu_npc_exact_drop_rule_to_pcifunc - Retrieve pcifunc
10843571fe07SRatheesh Kannoth  *      @rvu: resource virtualization unit.
10853571fe07SRatheesh Kannoth  *	@drop_rule_idx: Drop rule index in NPC mcam.
10863571fe07SRatheesh Kannoth  *
10873571fe07SRatheesh Kannoth  *	Debugfs (exact_drop_cnt) entry displays pcifunc for interface
10883571fe07SRatheesh Kannoth  *	by retrieving the pcifunc value from data base.
10893571fe07SRatheesh Kannoth  *	Return: Drop rule index.
10903571fe07SRatheesh Kannoth  */
rvu_npc_exact_drop_rule_to_pcifunc(struct rvu * rvu,u32 drop_rule_idx)10913571fe07SRatheesh Kannoth u16 rvu_npc_exact_drop_rule_to_pcifunc(struct rvu *rvu, u32 drop_rule_idx)
10923571fe07SRatheesh Kannoth {
10933571fe07SRatheesh Kannoth 	struct npc_exact_table *table;
10943571fe07SRatheesh Kannoth 	int i;
10953571fe07SRatheesh Kannoth 
10963571fe07SRatheesh Kannoth 	table = rvu->hw->table;
10973571fe07SRatheesh Kannoth 
10983571fe07SRatheesh Kannoth 	for (i = 0; i < NPC_MCAM_DROP_RULE_MAX; i++) {
10993571fe07SRatheesh Kannoth 		if (!table->drop_rule_map[i].valid)
11003571fe07SRatheesh Kannoth 			break;
11013571fe07SRatheesh Kannoth 
11023571fe07SRatheesh Kannoth 		if (table->drop_rule_map[i].drop_rule_idx != drop_rule_idx)
11033571fe07SRatheesh Kannoth 			continue;
11043571fe07SRatheesh Kannoth 
11053571fe07SRatheesh Kannoth 		return table->drop_rule_map[i].pcifunc;
11063571fe07SRatheesh Kannoth 	}
11073571fe07SRatheesh Kannoth 
11083571fe07SRatheesh Kannoth 	dev_err(rvu->dev, "%s: drop mcam rule index (%d) >= NPC_MCAM_DROP_RULE_MAX\n",
11093571fe07SRatheesh Kannoth 		__func__, drop_rule_idx);
11103571fe07SRatheesh Kannoth 	return -1;
11113571fe07SRatheesh Kannoth }
11123571fe07SRatheesh Kannoth 
11133571fe07SRatheesh Kannoth /**
11143571fe07SRatheesh Kannoth  *	rvu_npc_exact_get_drop_rule_info - Get drop rule information.
11153571fe07SRatheesh Kannoth  *      @rvu: resource virtualization unit.
11163571fe07SRatheesh Kannoth  *	@intf_type: Interface type (CGX, SDP or LBK)
11173571fe07SRatheesh Kannoth  *	@cgx_id: CGX identifier.
11183571fe07SRatheesh Kannoth  *	@lmac_id: LMAC identifier.
11193571fe07SRatheesh Kannoth  *	@drop_mcam_idx: NPC mcam drop rule index.
11203571fe07SRatheesh Kannoth  *	@val: Channel value.
11213571fe07SRatheesh Kannoth  *	@mask: Channel mask.
11223571fe07SRatheesh Kannoth  *	@pcifunc: pcifunc of interface corresponding to the drop rule.
11233571fe07SRatheesh Kannoth  *	Return: True upon success.
11243571fe07SRatheesh Kannoth  */
rvu_npc_exact_get_drop_rule_info(struct rvu * rvu,u8 intf_type,u8 cgx_id,u8 lmac_id,u32 * drop_mcam_idx,u64 * val,u64 * mask,u16 * pcifunc)11253571fe07SRatheesh Kannoth static bool rvu_npc_exact_get_drop_rule_info(struct rvu *rvu, u8 intf_type, u8 cgx_id,
11263571fe07SRatheesh Kannoth 					     u8 lmac_id, u32 *drop_mcam_idx, u64 *val,
11273571fe07SRatheesh Kannoth 					     u64 *mask, u16 *pcifunc)
11283571fe07SRatheesh Kannoth {
11293571fe07SRatheesh Kannoth 	struct npc_exact_table *table;
11303571fe07SRatheesh Kannoth 	u64 chan_val, chan_mask;
11313571fe07SRatheesh Kannoth 	bool rc;
11323571fe07SRatheesh Kannoth 	int i;
11333571fe07SRatheesh Kannoth 
11343571fe07SRatheesh Kannoth 	table = rvu->hw->table;
11353571fe07SRatheesh Kannoth 
11363571fe07SRatheesh Kannoth 	if (intf_type != NIX_INTF_TYPE_CGX) {
11373571fe07SRatheesh Kannoth 		dev_err(rvu->dev, "%s: No drop rule for LBK/SDP mode\n", __func__);
11383571fe07SRatheesh Kannoth 		return false;
11393571fe07SRatheesh Kannoth 	}
11403571fe07SRatheesh Kannoth 
11413571fe07SRatheesh Kannoth 	rc = rvu_npc_exact_calc_drop_rule_chan_and_mask(rvu, intf_type, cgx_id,
11423571fe07SRatheesh Kannoth 							lmac_id, &chan_val, &chan_mask);
11433571fe07SRatheesh Kannoth 	if (!rc)
11443571fe07SRatheesh Kannoth 		return false;
11453571fe07SRatheesh Kannoth 
11463571fe07SRatheesh Kannoth 	for (i = 0; i < NPC_MCAM_DROP_RULE_MAX; i++) {
11473571fe07SRatheesh Kannoth 		if (!table->drop_rule_map[i].valid)
11483571fe07SRatheesh Kannoth 			break;
11493571fe07SRatheesh Kannoth 
11503571fe07SRatheesh Kannoth 		if (table->drop_rule_map[i].chan_val != (u16)chan_val)
11513571fe07SRatheesh Kannoth 			continue;
11523571fe07SRatheesh Kannoth 
11533571fe07SRatheesh Kannoth 		if (val)
11543571fe07SRatheesh Kannoth 			*val = table->drop_rule_map[i].chan_val;
11553571fe07SRatheesh Kannoth 		if (mask)
11563571fe07SRatheesh Kannoth 			*mask = table->drop_rule_map[i].chan_mask;
11573571fe07SRatheesh Kannoth 		if (pcifunc)
11583571fe07SRatheesh Kannoth 			*pcifunc = table->drop_rule_map[i].pcifunc;
11593571fe07SRatheesh Kannoth 
11603571fe07SRatheesh Kannoth 		*drop_mcam_idx = i;
11613571fe07SRatheesh Kannoth 		return true;
11623571fe07SRatheesh Kannoth 	}
11633571fe07SRatheesh Kannoth 
11643571fe07SRatheesh Kannoth 	if (i == NPC_MCAM_DROP_RULE_MAX) {
11653571fe07SRatheesh Kannoth 		dev_err(rvu->dev, "%s: drop mcam rule index (%d) >= NPC_MCAM_DROP_RULE_MAX\n",
11663571fe07SRatheesh Kannoth 			__func__, *drop_mcam_idx);
11673571fe07SRatheesh Kannoth 		return false;
11683571fe07SRatheesh Kannoth 	}
11693571fe07SRatheesh Kannoth 
11703571fe07SRatheesh Kannoth 	dev_err(rvu->dev, "%s: Could not retrieve for cgx=%d, lmac=%d\n",
11713571fe07SRatheesh Kannoth 		__func__, cgx_id, lmac_id);
11723571fe07SRatheesh Kannoth 	return false;
11733571fe07SRatheesh Kannoth }
11743571fe07SRatheesh Kannoth 
11753571fe07SRatheesh Kannoth /**
11763571fe07SRatheesh Kannoth  *	__rvu_npc_exact_cmd_rules_cnt_update - Update number dmac rules against a drop rule.
11773571fe07SRatheesh Kannoth  *      @rvu: resource virtualization unit.
11783571fe07SRatheesh Kannoth  *	@drop_mcam_idx: NPC mcam drop rule index.
11793571fe07SRatheesh Kannoth  *	@val: +1 or -1.
11803571fe07SRatheesh Kannoth  *	@enable_or_disable_cam: If no exact match rules against a drop rule, disable it.
11813571fe07SRatheesh Kannoth  *
11823571fe07SRatheesh Kannoth  *	when first exact match entry against a drop rule is added, enable_or_disable_cam
11833571fe07SRatheesh Kannoth  *	is set to true. When last exact match entry against a drop rule is deleted,
11843571fe07SRatheesh Kannoth  *	enable_or_disable_cam is set to true.
11853571fe07SRatheesh Kannoth  *	Return: Number of rules
11863571fe07SRatheesh Kannoth  */
__rvu_npc_exact_cmd_rules_cnt_update(struct rvu * rvu,int drop_mcam_idx,int val,bool * enable_or_disable_cam)11873571fe07SRatheesh Kannoth static u16 __rvu_npc_exact_cmd_rules_cnt_update(struct rvu *rvu, int drop_mcam_idx,
11883571fe07SRatheesh Kannoth 						int val, bool *enable_or_disable_cam)
11893571fe07SRatheesh Kannoth {
11903571fe07SRatheesh Kannoth 	struct npc_exact_table *table;
11913571fe07SRatheesh Kannoth 	u16 *cnt, old_cnt;
1192af42088bSRatheesh Kannoth 	bool promisc;
11933571fe07SRatheesh Kannoth 
11943571fe07SRatheesh Kannoth 	table = rvu->hw->table;
1195af42088bSRatheesh Kannoth 	promisc = table->promisc_mode[drop_mcam_idx];
11963571fe07SRatheesh Kannoth 
11973571fe07SRatheesh Kannoth 	cnt = &table->cnt_cmd_rules[drop_mcam_idx];
11983571fe07SRatheesh Kannoth 	old_cnt = *cnt;
11993571fe07SRatheesh Kannoth 
12003571fe07SRatheesh Kannoth 	*cnt += val;
12013571fe07SRatheesh Kannoth 
12023571fe07SRatheesh Kannoth 	if (!enable_or_disable_cam)
12033571fe07SRatheesh Kannoth 		goto done;
12043571fe07SRatheesh Kannoth 
12053571fe07SRatheesh Kannoth 	*enable_or_disable_cam = false;
12063571fe07SRatheesh Kannoth 
1207af42088bSRatheesh Kannoth 	if (promisc)
1208af42088bSRatheesh Kannoth 		goto done;
1209af42088bSRatheesh Kannoth 
1210af42088bSRatheesh Kannoth 	/* If all rules are deleted and not already in promisc mode;
1211af42088bSRatheesh Kannoth 	 * disable cam
1212af42088bSRatheesh Kannoth 	 */
12132dba9459SRatheesh Kannoth 	if (!*cnt && val < 0) {
12143571fe07SRatheesh Kannoth 		*enable_or_disable_cam = true;
12153571fe07SRatheesh Kannoth 		goto done;
12163571fe07SRatheesh Kannoth 	}
12173571fe07SRatheesh Kannoth 
1218af42088bSRatheesh Kannoth 	/* If rule got added and not already in promisc mode; enable cam */
12192dba9459SRatheesh Kannoth 	if (!old_cnt && val > 0) {
12203571fe07SRatheesh Kannoth 		*enable_or_disable_cam = true;
12213571fe07SRatheesh Kannoth 		goto done;
12223571fe07SRatheesh Kannoth 	}
12233571fe07SRatheesh Kannoth 
12243571fe07SRatheesh Kannoth done:
12253571fe07SRatheesh Kannoth 	return *cnt;
12263571fe07SRatheesh Kannoth }
12273571fe07SRatheesh Kannoth 
12283571fe07SRatheesh Kannoth /**
1229b747923aSRatheesh Kannoth  *      rvu_npc_exact_del_table_entry_by_id - Delete and free table entry.
1230b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
1231b747923aSRatheesh Kannoth  *	@seq_id: Sequence identifier of the entry.
1232b747923aSRatheesh Kannoth  *
1233b747923aSRatheesh Kannoth  *	Deletes entry from linked lists and free up slot in HW MEM or CAM
1234b747923aSRatheesh Kannoth  *	table.
1235b747923aSRatheesh Kannoth  *	Return: 0 upon success.
1236b747923aSRatheesh Kannoth  */
rvu_npc_exact_del_table_entry_by_id(struct rvu * rvu,u32 seq_id)12372dba9459SRatheesh Kannoth static int rvu_npc_exact_del_table_entry_by_id(struct rvu *rvu, u32 seq_id)
1238b747923aSRatheesh Kannoth {
1239b747923aSRatheesh Kannoth 	struct npc_exact_table_entry *entry = NULL;
1240b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
12413571fe07SRatheesh Kannoth 	bool disable_cam = false;
1242da92e03cSRatheesh Kannoth 	u32 drop_mcam_idx = -1;
1243b747923aSRatheesh Kannoth 	int *cnt;
1244da92e03cSRatheesh Kannoth 	bool rc;
1245b747923aSRatheesh Kannoth 
1246b747923aSRatheesh Kannoth 	table = rvu->hw->table;
1247b747923aSRatheesh Kannoth 
1248b747923aSRatheesh Kannoth 	mutex_lock(&table->lock);
1249b747923aSRatheesh Kannoth 
1250b747923aSRatheesh Kannoth 	/* Lookup for entry which needs to be updated */
1251b747923aSRatheesh Kannoth 	entry = __rvu_npc_exact_find_entry_by_seq_id(rvu, seq_id);
1252b747923aSRatheesh Kannoth 	if (!entry) {
1253da92e03cSRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: failed to find entry for id=%d\n", __func__, seq_id);
1254b747923aSRatheesh Kannoth 		mutex_unlock(&table->lock);
1255b747923aSRatheesh Kannoth 		return -ENODATA;
1256b747923aSRatheesh Kannoth 	}
1257b747923aSRatheesh Kannoth 
1258b747923aSRatheesh Kannoth 	cnt = (entry->opc_type == NPC_EXACT_OPC_CAM) ? &table->cam_tbl_entry_cnt :
1259b747923aSRatheesh Kannoth 				&table->mem_tbl_entry_cnt;
1260b747923aSRatheesh Kannoth 
1261b747923aSRatheesh Kannoth 	/* delete from lists */
1262b747923aSRatheesh Kannoth 	list_del_init(&entry->list);
1263b747923aSRatheesh Kannoth 	list_del_init(&entry->glist);
1264b747923aSRatheesh Kannoth 
1265b747923aSRatheesh Kannoth 	(*cnt)--;
1266b747923aSRatheesh Kannoth 
1267da92e03cSRatheesh Kannoth 	rc = rvu_npc_exact_get_drop_rule_info(rvu, NIX_INTF_TYPE_CGX, entry->cgx_id,
1268da92e03cSRatheesh Kannoth 					      entry->lmac_id, &drop_mcam_idx, NULL, NULL, NULL);
1269da92e03cSRatheesh Kannoth 	if (!rc) {
1270da92e03cSRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: failed to retrieve drop info for id=0x%x\n",
1271da92e03cSRatheesh Kannoth 			__func__, seq_id);
1272da92e03cSRatheesh Kannoth 		mutex_unlock(&table->lock);
1273da92e03cSRatheesh Kannoth 		return -ENODATA;
1274da92e03cSRatheesh Kannoth 	}
12753571fe07SRatheesh Kannoth 
12763571fe07SRatheesh Kannoth 	if (entry->cmd)
12773571fe07SRatheesh Kannoth 		__rvu_npc_exact_cmd_rules_cnt_update(rvu, drop_mcam_idx, -1, &disable_cam);
12783571fe07SRatheesh Kannoth 
12793571fe07SRatheesh Kannoth 	/* No dmac filter rules; disable drop on hit rule */
12803571fe07SRatheesh Kannoth 	if (disable_cam) {
12813571fe07SRatheesh Kannoth 		rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX, false);
12823571fe07SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: Disabling mcam idx %d\n",
12833571fe07SRatheesh Kannoth 			__func__, drop_mcam_idx);
12843571fe07SRatheesh Kannoth 	}
12853571fe07SRatheesh Kannoth 
1286b747923aSRatheesh Kannoth 	mutex_unlock(&table->lock);
1287b747923aSRatheesh Kannoth 
1288b747923aSRatheesh Kannoth 	rvu_npc_exact_dealloc_table_entry(rvu, entry->opc_type, entry->ways, entry->index);
1289b747923aSRatheesh Kannoth 
1290b747923aSRatheesh Kannoth 	rvu_npc_exact_free_id(rvu, seq_id);
1291b747923aSRatheesh Kannoth 
1292b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: delete entry success for id=0x%x, mca=%pM\n",
1293b747923aSRatheesh Kannoth 		__func__, seq_id, entry->mac);
1294b747923aSRatheesh Kannoth 	kfree(entry);
1295b747923aSRatheesh Kannoth 
1296b747923aSRatheesh Kannoth 	return 0;
1297b747923aSRatheesh Kannoth }
1298b747923aSRatheesh Kannoth 
1299b747923aSRatheesh Kannoth /**
1300b747923aSRatheesh Kannoth  *      rvu_npc_exact_add_table_entry - Adds a table entry
1301b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
1302b747923aSRatheesh Kannoth  *	@cgx_id: cgx identifier.
1303b747923aSRatheesh Kannoth  *	@lmac_id: lmac identifier.
1304b747923aSRatheesh Kannoth  *	@mac: MAC address.
1305b747923aSRatheesh Kannoth  *	@chan: Channel number.
1306b747923aSRatheesh Kannoth  *	@ctype: Channel Type.
1307b747923aSRatheesh Kannoth  *	@seq_id: Sequence number.
1308b747923aSRatheesh Kannoth  *	@cmd: Whether it is invoked by ethtool cmd.
1309b747923aSRatheesh Kannoth  *	@mcam_idx: NPC mcam index corresponding to MAC
1310b747923aSRatheesh Kannoth  *	@pcifunc: PCI func.
1311b747923aSRatheesh Kannoth  *
1312b747923aSRatheesh Kannoth  *	Creates a new exact match table entry in either CAM or
1313b747923aSRatheesh Kannoth  *	MEM table.
1314b747923aSRatheesh Kannoth  *	Return: 0 upon success.
1315b747923aSRatheesh Kannoth  */
rvu_npc_exact_add_table_entry(struct rvu * rvu,u8 cgx_id,u8 lmac_id,u8 * mac,u16 chan,u8 ctype,u32 * seq_id,bool cmd,u32 mcam_idx,u16 pcifunc)13162dba9459SRatheesh Kannoth static int rvu_npc_exact_add_table_entry(struct rvu *rvu, u8 cgx_id, u8 lmac_id, u8 *mac,
13172dba9459SRatheesh Kannoth 					 u16 chan, u8 ctype, u32 *seq_id, bool cmd,
13182dba9459SRatheesh Kannoth 					 u32 mcam_idx, u16 pcifunc)
1319b747923aSRatheesh Kannoth {
1320b747923aSRatheesh Kannoth 	int blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
1321b747923aSRatheesh Kannoth 	enum npc_exact_opc_type opc_type;
13223571fe07SRatheesh Kannoth 	bool enable_cam = false;
13233571fe07SRatheesh Kannoth 	u32 drop_mcam_idx;
1324b747923aSRatheesh Kannoth 	u32 index;
1325b747923aSRatheesh Kannoth 	u64 mdata;
1326da92e03cSRatheesh Kannoth 	bool rc;
1327b747923aSRatheesh Kannoth 	int err;
1328b747923aSRatheesh Kannoth 	u8 ways;
1329b747923aSRatheesh Kannoth 
1330b747923aSRatheesh Kannoth 	ctype = 0;
1331b747923aSRatheesh Kannoth 
1332b747923aSRatheesh Kannoth 	err = rvu_npc_exact_alloc_table_entry(rvu, mac, chan, ctype, &index, &ways, &opc_type);
1333b747923aSRatheesh Kannoth 	if (err) {
1334b747923aSRatheesh Kannoth 		dev_err(rvu->dev, "%s: Could not alloc in exact match table\n", __func__);
1335b747923aSRatheesh Kannoth 		return err;
1336b747923aSRatheesh Kannoth 	}
1337b747923aSRatheesh Kannoth 
1338b747923aSRatheesh Kannoth 	/* Write mdata to table */
1339b747923aSRatheesh Kannoth 	mdata = rvu_exact_prepare_table_entry(rvu, true, ctype, chan, mac);
1340b747923aSRatheesh Kannoth 
1341b747923aSRatheesh Kannoth 	if (opc_type == NPC_EXACT_OPC_CAM)
1342b747923aSRatheesh Kannoth 		rvu_npc_exact_cam_table_write(rvu, blkaddr, index, mdata);
1343b747923aSRatheesh Kannoth 	else
1344b747923aSRatheesh Kannoth 		rvu_npc_exact_mem_table_write(rvu, blkaddr, ways, index,  mdata);
1345b747923aSRatheesh Kannoth 
1346b747923aSRatheesh Kannoth 	/* Insert entry to linked list */
1347b747923aSRatheesh Kannoth 	err = rvu_npc_exact_add_to_list(rvu, opc_type, ways, index, cgx_id, lmac_id,
1348b747923aSRatheesh Kannoth 					mac, chan, ctype, seq_id, cmd, mcam_idx, pcifunc);
1349b747923aSRatheesh Kannoth 	if (err) {
1350b747923aSRatheesh Kannoth 		rvu_npc_exact_dealloc_table_entry(rvu, opc_type, ways, index);
1351b747923aSRatheesh Kannoth 		dev_err(rvu->dev, "%s: could not add to exact match table\n", __func__);
1352b747923aSRatheesh Kannoth 		return err;
1353b747923aSRatheesh Kannoth 	}
1354b747923aSRatheesh Kannoth 
1355da92e03cSRatheesh Kannoth 	rc = rvu_npc_exact_get_drop_rule_info(rvu, NIX_INTF_TYPE_CGX, cgx_id, lmac_id,
13563571fe07SRatheesh Kannoth 					      &drop_mcam_idx, NULL, NULL, NULL);
1357da92e03cSRatheesh Kannoth 	if (!rc) {
1358da92e03cSRatheesh Kannoth 		rvu_npc_exact_dealloc_table_entry(rvu, opc_type, ways, index);
1359da92e03cSRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: failed to get drop rule info cgx=%d lmac=%d\n",
1360da92e03cSRatheesh Kannoth 			__func__, cgx_id, lmac_id);
1361da92e03cSRatheesh Kannoth 		return -EINVAL;
1362da92e03cSRatheesh Kannoth 	}
1363da92e03cSRatheesh Kannoth 
13643571fe07SRatheesh Kannoth 	if (cmd)
13653571fe07SRatheesh Kannoth 		__rvu_npc_exact_cmd_rules_cnt_update(rvu, drop_mcam_idx, 1, &enable_cam);
13663571fe07SRatheesh Kannoth 
13673571fe07SRatheesh Kannoth 	/* First command rule; enable drop on hit rule */
13683571fe07SRatheesh Kannoth 	if (enable_cam) {
13693571fe07SRatheesh Kannoth 		rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX, true);
13703571fe07SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: Enabling mcam idx %d\n",
13713571fe07SRatheesh Kannoth 			__func__, drop_mcam_idx);
13723571fe07SRatheesh Kannoth 	}
13733571fe07SRatheesh Kannoth 
1374b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev,
1375b747923aSRatheesh Kannoth 		"%s: Successfully added entry (index=%d, dmac=%pM, ways=%d opc_type=%d\n",
1376b747923aSRatheesh Kannoth 		__func__, index, mac, ways, opc_type);
1377b747923aSRatheesh Kannoth 
1378b747923aSRatheesh Kannoth 	return 0;
1379b747923aSRatheesh Kannoth }
1380b747923aSRatheesh Kannoth 
1381b747923aSRatheesh Kannoth /**
1382b747923aSRatheesh Kannoth  *      rvu_npc_exact_update_table_entry - Update exact match table.
1383b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
1384b747923aSRatheesh Kannoth  *	@cgx_id: CGX identifier.
1385b747923aSRatheesh Kannoth  *	@lmac_id: LMAC identifier.
1386b747923aSRatheesh Kannoth  *	@old_mac: Existing MAC address entry.
1387b747923aSRatheesh Kannoth  *	@new_mac: New MAC address entry.
1388b747923aSRatheesh Kannoth  *	@seq_id: Sequence identifier of the entry.
1389b747923aSRatheesh Kannoth  *
1390b747923aSRatheesh Kannoth  *	Updates MAC address of an entry. If entry is in MEM table, new
1391b747923aSRatheesh Kannoth  *	hash value may not match with old one.
1392b747923aSRatheesh Kannoth  *	Return: 0 upon success.
1393b747923aSRatheesh Kannoth  */
rvu_npc_exact_update_table_entry(struct rvu * rvu,u8 cgx_id,u8 lmac_id,u8 * old_mac,u8 * new_mac,u32 * seq_id)13942dba9459SRatheesh Kannoth static int rvu_npc_exact_update_table_entry(struct rvu *rvu, u8 cgx_id, u8 lmac_id,
13952dba9459SRatheesh Kannoth 					    u8 *old_mac, u8 *new_mac, u32 *seq_id)
1396b747923aSRatheesh Kannoth {
1397b747923aSRatheesh Kannoth 	int blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
1398b747923aSRatheesh Kannoth 	struct npc_exact_table_entry *entry;
1399b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
1400b747923aSRatheesh Kannoth 	u32 hash_index;
1401b747923aSRatheesh Kannoth 	u64 mdata;
1402b747923aSRatheesh Kannoth 
1403b747923aSRatheesh Kannoth 	table = rvu->hw->table;
1404b747923aSRatheesh Kannoth 
1405b747923aSRatheesh Kannoth 	mutex_lock(&table->lock);
1406b747923aSRatheesh Kannoth 
1407b747923aSRatheesh Kannoth 	/* Lookup for entry which needs to be updated */
1408b747923aSRatheesh Kannoth 	entry = __rvu_npc_exact_find_entry_by_seq_id(rvu, *seq_id);
1409b747923aSRatheesh Kannoth 	if (!entry) {
1410b747923aSRatheesh Kannoth 		mutex_unlock(&table->lock);
1411b747923aSRatheesh Kannoth 		dev_dbg(rvu->dev,
1412b747923aSRatheesh Kannoth 			"%s: failed to find entry for cgx_id=%d lmac_id=%d old_mac=%pM\n",
1413b747923aSRatheesh Kannoth 			__func__, cgx_id, lmac_id, old_mac);
1414b747923aSRatheesh Kannoth 		return -ENODATA;
1415b747923aSRatheesh Kannoth 	}
1416b747923aSRatheesh Kannoth 
1417b747923aSRatheesh Kannoth 	/* If entry is in mem table and new hash index is different than old
1418b747923aSRatheesh Kannoth 	 * hash index, we cannot update the entry. Fail in these scenarios.
1419b747923aSRatheesh Kannoth 	 */
1420b747923aSRatheesh Kannoth 	if (entry->opc_type == NPC_EXACT_OPC_MEM) {
1421b747923aSRatheesh Kannoth 		hash_index =  rvu_exact_calculate_hash(rvu, entry->chan, entry->ctype,
1422b747923aSRatheesh Kannoth 						       new_mac, table->mem_table.mask,
1423b747923aSRatheesh Kannoth 						       table->mem_table.depth);
1424b747923aSRatheesh Kannoth 		if (hash_index != entry->index) {
14252dba9459SRatheesh Kannoth 			dev_dbg(rvu->dev,
1426b747923aSRatheesh Kannoth 				"%s: Update failed due to index mismatch(new=0x%x, old=%x)\n",
1427b747923aSRatheesh Kannoth 				__func__, hash_index, entry->index);
1428b747923aSRatheesh Kannoth 			mutex_unlock(&table->lock);
1429b747923aSRatheesh Kannoth 			return -EINVAL;
1430b747923aSRatheesh Kannoth 		}
1431b747923aSRatheesh Kannoth 	}
1432b747923aSRatheesh Kannoth 
1433b747923aSRatheesh Kannoth 	mdata = rvu_exact_prepare_table_entry(rvu, true, entry->ctype, entry->chan, new_mac);
1434b747923aSRatheesh Kannoth 
1435b747923aSRatheesh Kannoth 	if (entry->opc_type == NPC_EXACT_OPC_MEM)
1436b747923aSRatheesh Kannoth 		rvu_npc_exact_mem_table_write(rvu, blkaddr, entry->ways, entry->index, mdata);
1437b747923aSRatheesh Kannoth 	else
1438b747923aSRatheesh Kannoth 		rvu_npc_exact_cam_table_write(rvu, blkaddr, entry->index, mdata);
1439b747923aSRatheesh Kannoth 
1440b747923aSRatheesh Kannoth 	/* Update entry fields */
1441b747923aSRatheesh Kannoth 	ether_addr_copy(entry->mac, new_mac);
1442b747923aSRatheesh Kannoth 	*seq_id = entry->seq_id;
1443b747923aSRatheesh Kannoth 
1444b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev,
1445b747923aSRatheesh Kannoth 		"%s: Successfully updated entry (index=%d, dmac=%pM, ways=%d opc_type=%d\n",
1446da92e03cSRatheesh Kannoth 		__func__, entry->index, entry->mac, entry->ways, entry->opc_type);
1447b747923aSRatheesh Kannoth 
1448b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: Successfully updated entry (old mac=%pM new_mac=%pM\n",
1449b747923aSRatheesh Kannoth 		__func__, old_mac, new_mac);
1450b747923aSRatheesh Kannoth 
1451b747923aSRatheesh Kannoth 	mutex_unlock(&table->lock);
1452b747923aSRatheesh Kannoth 	return 0;
1453b747923aSRatheesh Kannoth }
1454b747923aSRatheesh Kannoth 
1455b747923aSRatheesh Kannoth /**
14562dba9459SRatheesh Kannoth  *	rvu_npc_exact_promisc_disable - Disable promiscuous mode.
14572dba9459SRatheesh Kannoth  *      @rvu: resource virtualization unit.
14582dba9459SRatheesh Kannoth  *	@pcifunc: pcifunc
14592dba9459SRatheesh Kannoth  *
14602dba9459SRatheesh Kannoth  *	Drop rule is against each PF. We dont support DMAC filter for
14612dba9459SRatheesh Kannoth  *	VF.
14622dba9459SRatheesh Kannoth  *	Return: 0 upon success
14632dba9459SRatheesh Kannoth  */
14642dba9459SRatheesh Kannoth 
rvu_npc_exact_promisc_disable(struct rvu * rvu,u16 pcifunc)14652dba9459SRatheesh Kannoth int rvu_npc_exact_promisc_disable(struct rvu *rvu, u16 pcifunc)
14662dba9459SRatheesh Kannoth {
14672dba9459SRatheesh Kannoth 	struct npc_exact_table *table;
14682dba9459SRatheesh Kannoth 	int pf = rvu_get_pf(pcifunc);
14692dba9459SRatheesh Kannoth 	u8 cgx_id, lmac_id;
14702dba9459SRatheesh Kannoth 	u32 drop_mcam_idx;
14712dba9459SRatheesh Kannoth 	bool *promisc;
1472da92e03cSRatheesh Kannoth 	bool rc;
14732dba9459SRatheesh Kannoth 
14742dba9459SRatheesh Kannoth 	table = rvu->hw->table;
14752dba9459SRatheesh Kannoth 
14762dba9459SRatheesh Kannoth 	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
1477da92e03cSRatheesh Kannoth 	rc = rvu_npc_exact_get_drop_rule_info(rvu, NIX_INTF_TYPE_CGX, cgx_id, lmac_id,
14782dba9459SRatheesh Kannoth 					      &drop_mcam_idx, NULL, NULL, NULL);
1479da92e03cSRatheesh Kannoth 	if (!rc) {
1480da92e03cSRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: failed to get drop rule info cgx=%d lmac=%d\n",
1481da92e03cSRatheesh Kannoth 			__func__, cgx_id, lmac_id);
1482da92e03cSRatheesh Kannoth 		return -EINVAL;
1483da92e03cSRatheesh Kannoth 	}
14842dba9459SRatheesh Kannoth 
14852dba9459SRatheesh Kannoth 	mutex_lock(&table->lock);
14862dba9459SRatheesh Kannoth 	promisc = &table->promisc_mode[drop_mcam_idx];
14872dba9459SRatheesh Kannoth 
14882dba9459SRatheesh Kannoth 	if (!*promisc) {
14892dba9459SRatheesh Kannoth 		mutex_unlock(&table->lock);
14902dba9459SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: Err Already promisc mode disabled (cgx=%d lmac=%d)\n",
14912dba9459SRatheesh Kannoth 			__func__, cgx_id, lmac_id);
14922dba9459SRatheesh Kannoth 		return LMAC_AF_ERR_INVALID_PARAM;
14932dba9459SRatheesh Kannoth 	}
14942dba9459SRatheesh Kannoth 	*promisc = false;
14952dba9459SRatheesh Kannoth 	mutex_unlock(&table->lock);
14962dba9459SRatheesh Kannoth 
1497af42088bSRatheesh Kannoth 	/* Enable drop rule */
1498af42088bSRatheesh Kannoth 	rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX,
1499af42088bSRatheesh Kannoth 					   true);
1500af42088bSRatheesh Kannoth 
1501af42088bSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: disabled  promisc mode (cgx=%d lmac=%d)\n",
1502af42088bSRatheesh Kannoth 		__func__, cgx_id, lmac_id);
15032dba9459SRatheesh Kannoth 	return 0;
15042dba9459SRatheesh Kannoth }
15052dba9459SRatheesh Kannoth 
15062dba9459SRatheesh Kannoth /**
15072dba9459SRatheesh Kannoth  *	rvu_npc_exact_promisc_enable - Enable promiscuous mode.
15082dba9459SRatheesh Kannoth  *      @rvu: resource virtualization unit.
15092dba9459SRatheesh Kannoth  *	@pcifunc: pcifunc.
15102dba9459SRatheesh Kannoth  *	Return: 0 upon success
15112dba9459SRatheesh Kannoth  */
rvu_npc_exact_promisc_enable(struct rvu * rvu,u16 pcifunc)15122dba9459SRatheesh Kannoth int rvu_npc_exact_promisc_enable(struct rvu *rvu, u16 pcifunc)
15132dba9459SRatheesh Kannoth {
15142dba9459SRatheesh Kannoth 	struct npc_exact_table *table;
15152dba9459SRatheesh Kannoth 	int pf = rvu_get_pf(pcifunc);
15162dba9459SRatheesh Kannoth 	u8 cgx_id, lmac_id;
15172dba9459SRatheesh Kannoth 	u32 drop_mcam_idx;
15182dba9459SRatheesh Kannoth 	bool *promisc;
1519da92e03cSRatheesh Kannoth 	bool rc;
15202dba9459SRatheesh Kannoth 
15212dba9459SRatheesh Kannoth 	table = rvu->hw->table;
15222dba9459SRatheesh Kannoth 
15232dba9459SRatheesh Kannoth 	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
1524da92e03cSRatheesh Kannoth 	rc = rvu_npc_exact_get_drop_rule_info(rvu, NIX_INTF_TYPE_CGX, cgx_id, lmac_id,
15252dba9459SRatheesh Kannoth 					      &drop_mcam_idx, NULL, NULL, NULL);
1526da92e03cSRatheesh Kannoth 	if (!rc) {
1527da92e03cSRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: failed to get drop rule info cgx=%d lmac=%d\n",
1528da92e03cSRatheesh Kannoth 			__func__, cgx_id, lmac_id);
1529da92e03cSRatheesh Kannoth 		return -EINVAL;
1530da92e03cSRatheesh Kannoth 	}
15312dba9459SRatheesh Kannoth 
15322dba9459SRatheesh Kannoth 	mutex_lock(&table->lock);
15332dba9459SRatheesh Kannoth 	promisc = &table->promisc_mode[drop_mcam_idx];
15342dba9459SRatheesh Kannoth 
15352dba9459SRatheesh Kannoth 	if (*promisc) {
15362dba9459SRatheesh Kannoth 		mutex_unlock(&table->lock);
15372dba9459SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: Already in promisc mode (cgx=%d lmac=%d)\n",
15382dba9459SRatheesh Kannoth 			__func__, cgx_id, lmac_id);
15392dba9459SRatheesh Kannoth 		return LMAC_AF_ERR_INVALID_PARAM;
15402dba9459SRatheesh Kannoth 	}
15412dba9459SRatheesh Kannoth 	*promisc = true;
15422dba9459SRatheesh Kannoth 	mutex_unlock(&table->lock);
15432dba9459SRatheesh Kannoth 
1544af42088bSRatheesh Kannoth 	/*  disable drop rule */
1545af42088bSRatheesh Kannoth 	rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX,
1546af42088bSRatheesh Kannoth 					   false);
1547af42088bSRatheesh Kannoth 
1548af42088bSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: Enabled promisc mode (cgx=%d lmac=%d)\n",
1549af42088bSRatheesh Kannoth 		__func__, cgx_id, lmac_id);
15502dba9459SRatheesh Kannoth 	return 0;
15512dba9459SRatheesh Kannoth }
15522dba9459SRatheesh Kannoth 
15532dba9459SRatheesh Kannoth /**
15542dba9459SRatheesh Kannoth  *	rvu_npc_exact_mac_addr_reset - Delete PF mac address.
15552dba9459SRatheesh Kannoth  *      @rvu: resource virtualization unit.
15562dba9459SRatheesh Kannoth  *	@req: Reset request
15572dba9459SRatheesh Kannoth  *	@rsp: Reset response.
15582dba9459SRatheesh Kannoth  *	Return: 0 upon success
15592dba9459SRatheesh Kannoth  */
rvu_npc_exact_mac_addr_reset(struct rvu * rvu,struct cgx_mac_addr_reset_req * req,struct msg_rsp * rsp)15602dba9459SRatheesh Kannoth int rvu_npc_exact_mac_addr_reset(struct rvu *rvu, struct cgx_mac_addr_reset_req *req,
15612dba9459SRatheesh Kannoth 				 struct msg_rsp *rsp)
15622dba9459SRatheesh Kannoth {
15632dba9459SRatheesh Kannoth 	int pf = rvu_get_pf(req->hdr.pcifunc);
15642dba9459SRatheesh Kannoth 	u32 seq_id = req->index;
15652dba9459SRatheesh Kannoth 	struct rvu_pfvf *pfvf;
15662dba9459SRatheesh Kannoth 	u8 cgx_id, lmac_id;
15672dba9459SRatheesh Kannoth 	int rc;
15682dba9459SRatheesh Kannoth 
15692dba9459SRatheesh Kannoth 	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
15702dba9459SRatheesh Kannoth 
15712dba9459SRatheesh Kannoth 	pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
15722dba9459SRatheesh Kannoth 
15732dba9459SRatheesh Kannoth 	rc = rvu_npc_exact_del_table_entry_by_id(rvu, seq_id);
15742dba9459SRatheesh Kannoth 	if (rc) {
15752dba9459SRatheesh Kannoth 		/* TODO: how to handle this error case ? */
15762dba9459SRatheesh Kannoth 		dev_err(rvu->dev, "%s MAC (%pM) del PF=%d failed\n", __func__, pfvf->mac_addr, pf);
15772dba9459SRatheesh Kannoth 		return 0;
15782dba9459SRatheesh Kannoth 	}
15792dba9459SRatheesh Kannoth 
15802dba9459SRatheesh Kannoth 	dev_dbg(rvu->dev, "%s MAC (%pM) del PF=%d success (seq_id=%u)\n",
15812dba9459SRatheesh Kannoth 		__func__, pfvf->mac_addr, pf, seq_id);
15822dba9459SRatheesh Kannoth 	return 0;
15832dba9459SRatheesh Kannoth }
15842dba9459SRatheesh Kannoth 
15852dba9459SRatheesh Kannoth /**
15862dba9459SRatheesh Kannoth  *	rvu_npc_exact_mac_addr_update - Update mac address field with new value.
15872dba9459SRatheesh Kannoth  *      @rvu: resource virtualization unit.
15882dba9459SRatheesh Kannoth  *	@req: Update request.
15892dba9459SRatheesh Kannoth  *	@rsp: Update response.
15902dba9459SRatheesh Kannoth  *	Return: 0 upon success
15912dba9459SRatheesh Kannoth  */
rvu_npc_exact_mac_addr_update(struct rvu * rvu,struct cgx_mac_addr_update_req * req,struct cgx_mac_addr_update_rsp * rsp)15922dba9459SRatheesh Kannoth int rvu_npc_exact_mac_addr_update(struct rvu *rvu,
15932dba9459SRatheesh Kannoth 				  struct cgx_mac_addr_update_req *req,
15942dba9459SRatheesh Kannoth 				  struct cgx_mac_addr_update_rsp *rsp)
15952dba9459SRatheesh Kannoth {
15962dba9459SRatheesh Kannoth 	int pf = rvu_get_pf(req->hdr.pcifunc);
15972dba9459SRatheesh Kannoth 	struct npc_exact_table_entry *entry;
15982dba9459SRatheesh Kannoth 	struct npc_exact_table *table;
15992dba9459SRatheesh Kannoth 	struct rvu_pfvf *pfvf;
16002dba9459SRatheesh Kannoth 	u32 seq_id, mcam_idx;
16012dba9459SRatheesh Kannoth 	u8 old_mac[ETH_ALEN];
16022dba9459SRatheesh Kannoth 	u8 cgx_id, lmac_id;
16032dba9459SRatheesh Kannoth 	int rc;
16042dba9459SRatheesh Kannoth 
16052dba9459SRatheesh Kannoth 	if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
16062dba9459SRatheesh Kannoth 		return LMAC_AF_ERR_PERM_DENIED;
16072dba9459SRatheesh Kannoth 
16082dba9459SRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: Update request for seq_id=%d, mac=%pM\n",
16092dba9459SRatheesh Kannoth 		__func__, req->index, req->mac_addr);
16102dba9459SRatheesh Kannoth 
16112dba9459SRatheesh Kannoth 	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
16122dba9459SRatheesh Kannoth 
16132dba9459SRatheesh Kannoth 	pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
16142dba9459SRatheesh Kannoth 
16152dba9459SRatheesh Kannoth 	table = rvu->hw->table;
16162dba9459SRatheesh Kannoth 
16172dba9459SRatheesh Kannoth 	mutex_lock(&table->lock);
16182dba9459SRatheesh Kannoth 
16192dba9459SRatheesh Kannoth 	/* Lookup for entry which needs to be updated */
16202dba9459SRatheesh Kannoth 	entry = __rvu_npc_exact_find_entry_by_seq_id(rvu, req->index);
16212dba9459SRatheesh Kannoth 	if (!entry) {
16222dba9459SRatheesh Kannoth 		dev_err(rvu->dev, "%s: failed to find entry for id=0x%x\n", __func__, req->index);
16232dba9459SRatheesh Kannoth 		mutex_unlock(&table->lock);
16242dba9459SRatheesh Kannoth 		return LMAC_AF_ERR_EXACT_MATCH_TBL_LOOK_UP_FAILED;
16252dba9459SRatheesh Kannoth 	}
16262dba9459SRatheesh Kannoth 	ether_addr_copy(old_mac, entry->mac);
16272dba9459SRatheesh Kannoth 	seq_id = entry->seq_id;
16282dba9459SRatheesh Kannoth 	mcam_idx = entry->mcam_idx;
16292dba9459SRatheesh Kannoth 	mutex_unlock(&table->lock);
16302dba9459SRatheesh Kannoth 
16312dba9459SRatheesh Kannoth 	rc = rvu_npc_exact_update_table_entry(rvu, cgx_id, lmac_id,  old_mac,
16322dba9459SRatheesh Kannoth 					      req->mac_addr, &seq_id);
16332dba9459SRatheesh Kannoth 	if (!rc) {
16342dba9459SRatheesh Kannoth 		rsp->index = seq_id;
16352dba9459SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s  mac:%pM (pfvf:%pM default:%pM) update to PF=%d success\n",
16362dba9459SRatheesh Kannoth 			__func__, req->mac_addr, pfvf->mac_addr, pfvf->default_mac, pf);
16372dba9459SRatheesh Kannoth 		ether_addr_copy(pfvf->mac_addr, req->mac_addr);
16382dba9459SRatheesh Kannoth 		return 0;
16392dba9459SRatheesh Kannoth 	}
16402dba9459SRatheesh Kannoth 
16412dba9459SRatheesh Kannoth 	/* Try deleting and adding it again */
16422dba9459SRatheesh Kannoth 	rc = rvu_npc_exact_del_table_entry_by_id(rvu, req->index);
16432dba9459SRatheesh Kannoth 	if (rc) {
16442dba9459SRatheesh Kannoth 		/* This could be a new entry */
16452dba9459SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s MAC (%pM) del PF=%d failed\n", __func__,
16462dba9459SRatheesh Kannoth 			pfvf->mac_addr, pf);
16472dba9459SRatheesh Kannoth 	}
16482dba9459SRatheesh Kannoth 
16492dba9459SRatheesh Kannoth 	rc = rvu_npc_exact_add_table_entry(rvu, cgx_id, lmac_id, req->mac_addr,
16502dba9459SRatheesh Kannoth 					   pfvf->rx_chan_base, 0, &seq_id, true,
16512dba9459SRatheesh Kannoth 					   mcam_idx, req->hdr.pcifunc);
16522dba9459SRatheesh Kannoth 	if (rc) {
16532dba9459SRatheesh Kannoth 		dev_err(rvu->dev, "%s MAC (%pM) add PF=%d failed\n", __func__,
16542dba9459SRatheesh Kannoth 			req->mac_addr, pf);
16552dba9459SRatheesh Kannoth 		return LMAC_AF_ERR_EXACT_MATCH_TBL_ADD_FAILED;
16562dba9459SRatheesh Kannoth 	}
16572dba9459SRatheesh Kannoth 
16582dba9459SRatheesh Kannoth 	rsp->index = seq_id;
16592dba9459SRatheesh Kannoth 	dev_dbg(rvu->dev,
16602dba9459SRatheesh Kannoth 		"%s MAC (new:%pM, old=%pM default:%pM) del and add to PF=%d success (seq_id=%u)\n",
16612dba9459SRatheesh Kannoth 		__func__, req->mac_addr, pfvf->mac_addr, pfvf->default_mac, pf, seq_id);
16622dba9459SRatheesh Kannoth 
16632dba9459SRatheesh Kannoth 	ether_addr_copy(pfvf->mac_addr, req->mac_addr);
16642dba9459SRatheesh Kannoth 	return 0;
16652dba9459SRatheesh Kannoth }
16662dba9459SRatheesh Kannoth 
16672dba9459SRatheesh Kannoth /**
16682dba9459SRatheesh Kannoth  *	rvu_npc_exact_mac_addr_add - Adds MAC address to exact match table.
16692dba9459SRatheesh Kannoth  *      @rvu: resource virtualization unit.
16702dba9459SRatheesh Kannoth  *	@req: Add request.
16712dba9459SRatheesh Kannoth  *	@rsp: Add response.
16722dba9459SRatheesh Kannoth  *	Return: 0 upon success
16732dba9459SRatheesh Kannoth  */
rvu_npc_exact_mac_addr_add(struct rvu * rvu,struct cgx_mac_addr_add_req * req,struct cgx_mac_addr_add_rsp * rsp)16742dba9459SRatheesh Kannoth int rvu_npc_exact_mac_addr_add(struct rvu *rvu,
16752dba9459SRatheesh Kannoth 			       struct cgx_mac_addr_add_req *req,
16762dba9459SRatheesh Kannoth 			       struct cgx_mac_addr_add_rsp *rsp)
16772dba9459SRatheesh Kannoth {
16782dba9459SRatheesh Kannoth 	int pf = rvu_get_pf(req->hdr.pcifunc);
16792dba9459SRatheesh Kannoth 	struct rvu_pfvf *pfvf;
16802dba9459SRatheesh Kannoth 	u8 cgx_id, lmac_id;
16812dba9459SRatheesh Kannoth 	int rc = 0;
16822dba9459SRatheesh Kannoth 	u32 seq_id;
16832dba9459SRatheesh Kannoth 
16842dba9459SRatheesh Kannoth 	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
16852dba9459SRatheesh Kannoth 	pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
16862dba9459SRatheesh Kannoth 
16872dba9459SRatheesh Kannoth 	rc = rvu_npc_exact_add_table_entry(rvu, cgx_id, lmac_id, req->mac_addr,
16882dba9459SRatheesh Kannoth 					   pfvf->rx_chan_base, 0, &seq_id,
16892dba9459SRatheesh Kannoth 					   true, -1, req->hdr.pcifunc);
16902dba9459SRatheesh Kannoth 
16912dba9459SRatheesh Kannoth 	if (!rc) {
16922dba9459SRatheesh Kannoth 		rsp->index = seq_id;
16932dba9459SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s MAC (%pM) add to PF=%d success (seq_id=%u)\n",
16942dba9459SRatheesh Kannoth 			__func__, req->mac_addr, pf, seq_id);
16952dba9459SRatheesh Kannoth 		return 0;
16962dba9459SRatheesh Kannoth 	}
16972dba9459SRatheesh Kannoth 
16982dba9459SRatheesh Kannoth 	dev_err(rvu->dev, "%s MAC (%pM) add to PF=%d failed\n", __func__,
16992dba9459SRatheesh Kannoth 		req->mac_addr, pf);
17002dba9459SRatheesh Kannoth 	return LMAC_AF_ERR_EXACT_MATCH_TBL_ADD_FAILED;
17012dba9459SRatheesh Kannoth }
17022dba9459SRatheesh Kannoth 
17032dba9459SRatheesh Kannoth /**
17042dba9459SRatheesh Kannoth  *	rvu_npc_exact_mac_addr_del - Delete DMAC filter
17052dba9459SRatheesh Kannoth  *      @rvu: resource virtualization unit.
17062dba9459SRatheesh Kannoth  *	@req: Delete request.
17072dba9459SRatheesh Kannoth  *	@rsp: Delete response.
17082dba9459SRatheesh Kannoth  *	Return: 0 upon success
17092dba9459SRatheesh Kannoth  */
rvu_npc_exact_mac_addr_del(struct rvu * rvu,struct cgx_mac_addr_del_req * req,struct msg_rsp * rsp)17102dba9459SRatheesh Kannoth int rvu_npc_exact_mac_addr_del(struct rvu *rvu,
17112dba9459SRatheesh Kannoth 			       struct cgx_mac_addr_del_req *req,
17122dba9459SRatheesh Kannoth 			       struct msg_rsp *rsp)
17132dba9459SRatheesh Kannoth {
17142dba9459SRatheesh Kannoth 	int pf = rvu_get_pf(req->hdr.pcifunc);
17152dba9459SRatheesh Kannoth 	int rc;
17162dba9459SRatheesh Kannoth 
17172dba9459SRatheesh Kannoth 	rc = rvu_npc_exact_del_table_entry_by_id(rvu, req->index);
17182dba9459SRatheesh Kannoth 	if (!rc) {
17192dba9459SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s del to PF=%d success (seq_id=%u)\n",
17202dba9459SRatheesh Kannoth 			__func__, pf, req->index);
17212dba9459SRatheesh Kannoth 		return 0;
17222dba9459SRatheesh Kannoth 	}
17232dba9459SRatheesh Kannoth 
17242dba9459SRatheesh Kannoth 	dev_err(rvu->dev, "%s del to PF=%d failed (seq_id=%u)\n",
17252dba9459SRatheesh Kannoth 		__func__,  pf, req->index);
17262dba9459SRatheesh Kannoth 	return LMAC_AF_ERR_EXACT_MATCH_TBL_DEL_FAILED;
17272dba9459SRatheesh Kannoth }
17282dba9459SRatheesh Kannoth 
17292dba9459SRatheesh Kannoth /**
17302dba9459SRatheesh Kannoth  *	rvu_npc_exact_mac_addr_set - Add PF mac address to dmac filter.
17312dba9459SRatheesh Kannoth  *      @rvu: resource virtualization unit.
17322dba9459SRatheesh Kannoth  *	@req: Set request.
17332dba9459SRatheesh Kannoth  *	@rsp: Set response.
17342dba9459SRatheesh Kannoth  *	Return: 0 upon success
17352dba9459SRatheesh Kannoth  */
rvu_npc_exact_mac_addr_set(struct rvu * rvu,struct cgx_mac_addr_set_or_get * req,struct cgx_mac_addr_set_or_get * rsp)17362dba9459SRatheesh Kannoth int rvu_npc_exact_mac_addr_set(struct rvu *rvu, struct cgx_mac_addr_set_or_get *req,
17372dba9459SRatheesh Kannoth 			       struct cgx_mac_addr_set_or_get *rsp)
17382dba9459SRatheesh Kannoth {
17392dba9459SRatheesh Kannoth 	int pf = rvu_get_pf(req->hdr.pcifunc);
17402dba9459SRatheesh Kannoth 	u32 seq_id = req->index;
17412dba9459SRatheesh Kannoth 	struct rvu_pfvf *pfvf;
17422dba9459SRatheesh Kannoth 	u8 cgx_id, lmac_id;
17432dba9459SRatheesh Kannoth 	u32 mcam_idx = -1;
17442dba9459SRatheesh Kannoth 	int rc, nixlf;
17452dba9459SRatheesh Kannoth 
17462dba9459SRatheesh Kannoth 	rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
17472dba9459SRatheesh Kannoth 
17482dba9459SRatheesh Kannoth 	pfvf = &rvu->pf[pf];
17492dba9459SRatheesh Kannoth 
17502dba9459SRatheesh Kannoth 	/* If table does not have an entry; both update entry and del table entry API
17512dba9459SRatheesh Kannoth 	 * below fails. Those are not failure conditions.
17522dba9459SRatheesh Kannoth 	 */
17532dba9459SRatheesh Kannoth 	rc = rvu_npc_exact_update_table_entry(rvu, cgx_id, lmac_id, pfvf->mac_addr,
17542dba9459SRatheesh Kannoth 					      req->mac_addr, &seq_id);
17552dba9459SRatheesh Kannoth 	if (!rc) {
17562dba9459SRatheesh Kannoth 		rsp->index = seq_id;
17572dba9459SRatheesh Kannoth 		ether_addr_copy(pfvf->mac_addr, req->mac_addr);
17582dba9459SRatheesh Kannoth 		ether_addr_copy(rsp->mac_addr, req->mac_addr);
17592dba9459SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s MAC (%pM) update to PF=%d success\n",
17602dba9459SRatheesh Kannoth 			__func__, req->mac_addr, pf);
17612dba9459SRatheesh Kannoth 		return 0;
17622dba9459SRatheesh Kannoth 	}
17632dba9459SRatheesh Kannoth 
17642dba9459SRatheesh Kannoth 	/* Try deleting and adding it again */
17652dba9459SRatheesh Kannoth 	rc = rvu_npc_exact_del_table_entry_by_id(rvu, req->index);
17662dba9459SRatheesh Kannoth 	if (rc) {
17672dba9459SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s MAC (%pM) del PF=%d failed\n",
17682dba9459SRatheesh Kannoth 			__func__, pfvf->mac_addr, pf);
17692dba9459SRatheesh Kannoth 	}
17702dba9459SRatheesh Kannoth 
17712dba9459SRatheesh Kannoth 	/* find mcam entry if exist */
17722dba9459SRatheesh Kannoth 	rc = nix_get_nixlf(rvu, req->hdr.pcifunc, &nixlf, NULL);
17732dba9459SRatheesh Kannoth 	if (!rc) {
17742dba9459SRatheesh Kannoth 		mcam_idx = npc_get_nixlf_mcam_index(&rvu->hw->mcam, req->hdr.pcifunc,
17752dba9459SRatheesh Kannoth 						    nixlf, NIXLF_UCAST_ENTRY);
17762dba9459SRatheesh Kannoth 	}
17772dba9459SRatheesh Kannoth 
17782dba9459SRatheesh Kannoth 	rc = rvu_npc_exact_add_table_entry(rvu, cgx_id, lmac_id, req->mac_addr,
17792dba9459SRatheesh Kannoth 					   pfvf->rx_chan_base, 0, &seq_id,
17802dba9459SRatheesh Kannoth 					   true, mcam_idx, req->hdr.pcifunc);
17812dba9459SRatheesh Kannoth 	if (rc) {
17822dba9459SRatheesh Kannoth 		dev_err(rvu->dev, "%s MAC (%pM) add PF=%d failed\n",
17832dba9459SRatheesh Kannoth 			__func__, req->mac_addr, pf);
17842dba9459SRatheesh Kannoth 		return LMAC_AF_ERR_EXACT_MATCH_TBL_ADD_FAILED;
17852dba9459SRatheesh Kannoth 	}
17862dba9459SRatheesh Kannoth 
17872dba9459SRatheesh Kannoth 	rsp->index = seq_id;
17882dba9459SRatheesh Kannoth 	ether_addr_copy(rsp->mac_addr, req->mac_addr);
17892dba9459SRatheesh Kannoth 	ether_addr_copy(pfvf->mac_addr, req->mac_addr);
17902dba9459SRatheesh Kannoth 	dev_dbg(rvu->dev,
17912dba9459SRatheesh Kannoth 		"%s MAC (%pM) del and add to PF=%d success (seq_id=%u)\n",
17922dba9459SRatheesh Kannoth 		__func__, req->mac_addr, pf, seq_id);
17932dba9459SRatheesh Kannoth 	return 0;
17942dba9459SRatheesh Kannoth }
17952dba9459SRatheesh Kannoth 
17962dba9459SRatheesh Kannoth /**
1797ef83e186SRatheesh Kannoth  *	rvu_npc_exact_can_disable_feature - Check if feature can be disabled.
1798ef83e186SRatheesh Kannoth  *      @rvu: resource virtualization unit.
1799ef83e186SRatheesh Kannoth  *	Return: True if exact match feature is supported.
1800ef83e186SRatheesh Kannoth  */
rvu_npc_exact_can_disable_feature(struct rvu * rvu)1801ef83e186SRatheesh Kannoth bool rvu_npc_exact_can_disable_feature(struct rvu *rvu)
1802ef83e186SRatheesh Kannoth {
1803ef83e186SRatheesh Kannoth 	struct npc_exact_table *table = rvu->hw->table;
1804ef83e186SRatheesh Kannoth 	bool empty;
1805ef83e186SRatheesh Kannoth 
1806ef83e186SRatheesh Kannoth 	if (!rvu->hw->cap.npc_exact_match_enabled)
1807ef83e186SRatheesh Kannoth 		return false;
1808ef83e186SRatheesh Kannoth 
1809ef83e186SRatheesh Kannoth 	mutex_lock(&table->lock);
1810ef83e186SRatheesh Kannoth 	empty = list_empty(&table->lhead_gbl);
1811ef83e186SRatheesh Kannoth 	mutex_unlock(&table->lock);
1812ef83e186SRatheesh Kannoth 
1813ef83e186SRatheesh Kannoth 	return empty;
1814ef83e186SRatheesh Kannoth }
1815ef83e186SRatheesh Kannoth 
1816ef83e186SRatheesh Kannoth /**
1817ef83e186SRatheesh Kannoth  *	rvu_npc_exact_disable_feature - Disable feature.
1818ef83e186SRatheesh Kannoth  *      @rvu: resource virtualization unit.
1819ef83e186SRatheesh Kannoth  */
rvu_npc_exact_disable_feature(struct rvu * rvu)1820ef83e186SRatheesh Kannoth void rvu_npc_exact_disable_feature(struct rvu *rvu)
1821ef83e186SRatheesh Kannoth {
1822ef83e186SRatheesh Kannoth 	rvu->hw->cap.npc_exact_match_enabled = false;
1823ef83e186SRatheesh Kannoth }
1824ef83e186SRatheesh Kannoth 
1825ef83e186SRatheesh Kannoth /**
1826bab9eed5SRatheesh Kannoth  *	rvu_npc_exact_reset - Delete and free all entry which match pcifunc.
1827bab9eed5SRatheesh Kannoth  *      @rvu: resource virtualization unit.
1828bab9eed5SRatheesh Kannoth  *	@pcifunc: PCI func to match.
1829bab9eed5SRatheesh Kannoth  */
rvu_npc_exact_reset(struct rvu * rvu,u16 pcifunc)1830bab9eed5SRatheesh Kannoth void rvu_npc_exact_reset(struct rvu *rvu, u16 pcifunc)
1831bab9eed5SRatheesh Kannoth {
1832bab9eed5SRatheesh Kannoth 	struct npc_exact_table *table = rvu->hw->table;
1833bab9eed5SRatheesh Kannoth 	struct npc_exact_table_entry *tmp, *iter;
1834bab9eed5SRatheesh Kannoth 	u32 seq_id;
1835bab9eed5SRatheesh Kannoth 
1836bab9eed5SRatheesh Kannoth 	mutex_lock(&table->lock);
1837bab9eed5SRatheesh Kannoth 	list_for_each_entry_safe(iter, tmp, &table->lhead_gbl, glist) {
1838bab9eed5SRatheesh Kannoth 		if (pcifunc != iter->pcifunc)
1839bab9eed5SRatheesh Kannoth 			continue;
1840bab9eed5SRatheesh Kannoth 
1841bab9eed5SRatheesh Kannoth 		seq_id = iter->seq_id;
1842bab9eed5SRatheesh Kannoth 		dev_dbg(rvu->dev, "%s: resetting pcifun=%d seq_id=%u\n", __func__,
1843bab9eed5SRatheesh Kannoth 			pcifunc, seq_id);
1844bab9eed5SRatheesh Kannoth 
1845bab9eed5SRatheesh Kannoth 		mutex_unlock(&table->lock);
1846bab9eed5SRatheesh Kannoth 		rvu_npc_exact_del_table_entry_by_id(rvu, seq_id);
1847bab9eed5SRatheesh Kannoth 		mutex_lock(&table->lock);
1848bab9eed5SRatheesh Kannoth 	}
1849bab9eed5SRatheesh Kannoth 	mutex_unlock(&table->lock);
1850bab9eed5SRatheesh Kannoth }
1851bab9eed5SRatheesh Kannoth 
1852bab9eed5SRatheesh Kannoth /**
1853b747923aSRatheesh Kannoth  *      rvu_npc_exact_init - initialize exact match table
1854b747923aSRatheesh Kannoth  *      @rvu: resource virtualization unit.
1855b747923aSRatheesh Kannoth  *
1856b747923aSRatheesh Kannoth  *	Initialize HW and SW resources to manage 4way-2K table and fully
1857b747923aSRatheesh Kannoth  *	associative 32-entry mcam table.
1858b747923aSRatheesh Kannoth  *	Return: 0 upon success.
1859b747923aSRatheesh Kannoth  */
rvu_npc_exact_init(struct rvu * rvu)1860b747923aSRatheesh Kannoth int rvu_npc_exact_init(struct rvu *rvu)
1861b747923aSRatheesh Kannoth {
18623571fe07SRatheesh Kannoth 	u64 bcast_mcast_val, bcast_mcast_mask;
1863b747923aSRatheesh Kannoth 	struct npc_exact_table *table;
18643571fe07SRatheesh Kannoth 	u64 exact_val, exact_mask;
18653571fe07SRatheesh Kannoth 	u64 chan_val, chan_mask;
18663571fe07SRatheesh Kannoth 	u8 cgx_id, lmac_id;
18673571fe07SRatheesh Kannoth 	u32 *drop_mcam_idx;
18683571fe07SRatheesh Kannoth 	u16 max_lmac_cnt;
1869b747923aSRatheesh Kannoth 	u64 npc_const3;
1870b747923aSRatheesh Kannoth 	int table_size;
1871b747923aSRatheesh Kannoth 	int blkaddr;
18723571fe07SRatheesh Kannoth 	u16 pcifunc;
18733571fe07SRatheesh Kannoth 	int err, i;
1874b747923aSRatheesh Kannoth 	u64 cfg;
18753571fe07SRatheesh Kannoth 	bool rc;
1876b747923aSRatheesh Kannoth 
1877b747923aSRatheesh Kannoth 	/* Read NPC_AF_CONST3 and check for have exact
1878b747923aSRatheesh Kannoth 	 * match functionality is present
1879b747923aSRatheesh Kannoth 	 */
1880b747923aSRatheesh Kannoth 	blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
1881b747923aSRatheesh Kannoth 	if (blkaddr < 0) {
1882b747923aSRatheesh Kannoth 		dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
1883b747923aSRatheesh Kannoth 		return -EINVAL;
1884b747923aSRatheesh Kannoth 	}
1885b747923aSRatheesh Kannoth 
1886b747923aSRatheesh Kannoth 	/* Check exact match feature is supported */
1887b747923aSRatheesh Kannoth 	npc_const3 = rvu_read64(rvu, blkaddr, NPC_AF_CONST3);
1888609aa68dSSunil Goutham 	if (!(npc_const3 & BIT_ULL(62)))
1889b747923aSRatheesh Kannoth 		return 0;
1890b747923aSRatheesh Kannoth 
1891b747923aSRatheesh Kannoth 	/* Check if kex profile has enabled EXACT match nibble */
1892b747923aSRatheesh Kannoth 	cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX));
1893609aa68dSSunil Goutham 	if (!(cfg & NPC_EXACT_NIBBLE_HIT))
1894b747923aSRatheesh Kannoth 		return 0;
1895b747923aSRatheesh Kannoth 
1896b747923aSRatheesh Kannoth 	/* Set capability to true */
1897b747923aSRatheesh Kannoth 	rvu->hw->cap.npc_exact_match_enabled = true;
1898b747923aSRatheesh Kannoth 
1899b6a0ecaeSChristophe JAILLET 	table = kzalloc(sizeof(*table), GFP_KERNEL);
1900b747923aSRatheesh Kannoth 	if (!table)
1901b747923aSRatheesh Kannoth 		return -ENOMEM;
1902b747923aSRatheesh Kannoth 
1903b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: Memory allocation for table success\n", __func__);
1904b747923aSRatheesh Kannoth 	rvu->hw->table = table;
1905b747923aSRatheesh Kannoth 
1906b747923aSRatheesh Kannoth 	/* Read table size, ways and depth */
1907b747923aSRatheesh Kannoth 	table->mem_table.ways = FIELD_GET(GENMASK_ULL(19, 16), npc_const3);
190860999cb8SRatheesh Kannoth 	table->mem_table.depth = FIELD_GET(GENMASK_ULL(15, 0), npc_const3);
190960999cb8SRatheesh Kannoth 	table->cam_table.depth = FIELD_GET(GENMASK_ULL(31, 24), npc_const3);
1910b747923aSRatheesh Kannoth 
1911b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: NPC exact match 4way_2k table(ways=%d, depth=%d)\n",
1912b747923aSRatheesh Kannoth 		__func__,  table->mem_table.ways, table->cam_table.depth);
1913b747923aSRatheesh Kannoth 
1914b747923aSRatheesh Kannoth 	/* Check if depth of table is not a sequre of 2
1915b747923aSRatheesh Kannoth 	 * TODO: why _builtin_popcount() is not working ?
1916b747923aSRatheesh Kannoth 	 */
1917b747923aSRatheesh Kannoth 	if ((table->mem_table.depth & (table->mem_table.depth - 1)) != 0) {
1918b747923aSRatheesh Kannoth 		dev_err(rvu->dev,
1919b747923aSRatheesh Kannoth 			"%s: NPC exact match 4way_2k table depth(%d) is not square of 2\n",
1920b747923aSRatheesh Kannoth 			__func__,  table->mem_table.depth);
1921b747923aSRatheesh Kannoth 		return -EINVAL;
1922b747923aSRatheesh Kannoth 	}
1923b747923aSRatheesh Kannoth 
1924b747923aSRatheesh Kannoth 	table_size = table->mem_table.depth * table->mem_table.ways;
1925b747923aSRatheesh Kannoth 
1926b747923aSRatheesh Kannoth 	/* Allocate bitmap for 4way 2K table */
192705a7b52eSChristophe JAILLET 	table->mem_table.bmap = devm_bitmap_zalloc(rvu->dev, table_size,
192805a7b52eSChristophe JAILLET 						   GFP_KERNEL);
1929b747923aSRatheesh Kannoth 	if (!table->mem_table.bmap)
1930b747923aSRatheesh Kannoth 		return -ENOMEM;
1931b747923aSRatheesh Kannoth 
1932b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: Allocated bitmap for 4way 2K entry table\n", __func__);
1933b747923aSRatheesh Kannoth 
1934b747923aSRatheesh Kannoth 	/* Allocate bitmap for 32 entry mcam */
193505a7b52eSChristophe JAILLET 	table->cam_table.bmap = devm_bitmap_zalloc(rvu->dev, 32, GFP_KERNEL);
1936b747923aSRatheesh Kannoth 
1937b747923aSRatheesh Kannoth 	if (!table->cam_table.bmap)
1938b747923aSRatheesh Kannoth 		return -ENOMEM;
1939b747923aSRatheesh Kannoth 
1940b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: Allocated bitmap for 32 entry cam\n", __func__);
1941b747923aSRatheesh Kannoth 
1942450f0650SChristophe JAILLET 	table->tot_ids = table_size + table->cam_table.depth;
19436d135d9eSChristophe JAILLET 	table->id_bmap = devm_bitmap_zalloc(rvu->dev, table->tot_ids,
19446d135d9eSChristophe JAILLET 					    GFP_KERNEL);
1945b747923aSRatheesh Kannoth 
1946b747923aSRatheesh Kannoth 	if (!table->id_bmap)
1947b747923aSRatheesh Kannoth 		return -ENOMEM;
1948b747923aSRatheesh Kannoth 
1949b747923aSRatheesh Kannoth 	dev_dbg(rvu->dev, "%s: Allocated bitmap for id map (total=%d)\n",
1950b747923aSRatheesh Kannoth 		__func__, table->tot_ids);
1951b747923aSRatheesh Kannoth 
1952b747923aSRatheesh Kannoth 	/* Initialize list heads for npc_exact_table entries.
1953b747923aSRatheesh Kannoth 	 * This entry is used by debugfs to show entries in
1954b747923aSRatheesh Kannoth 	 * exact match table.
1955b747923aSRatheesh Kannoth 	 */
1956b747923aSRatheesh Kannoth 	for (i = 0; i < NPC_EXACT_TBL_MAX_WAYS; i++)
1957b747923aSRatheesh Kannoth 		INIT_LIST_HEAD(&table->lhead_mem_tbl_entry[i]);
1958b747923aSRatheesh Kannoth 
1959b747923aSRatheesh Kannoth 	INIT_LIST_HEAD(&table->lhead_cam_tbl_entry);
1960b747923aSRatheesh Kannoth 	INIT_LIST_HEAD(&table->lhead_gbl);
1961b747923aSRatheesh Kannoth 
1962b747923aSRatheesh Kannoth 	mutex_init(&table->lock);
1963b747923aSRatheesh Kannoth 
1964b747923aSRatheesh Kannoth 	rvu_exact_config_secret_key(rvu);
1965b747923aSRatheesh Kannoth 	rvu_exact_config_search_key(rvu);
1966b747923aSRatheesh Kannoth 
1967b747923aSRatheesh Kannoth 	rvu_exact_config_table_mask(rvu);
1968b747923aSRatheesh Kannoth 	rvu_exact_config_result_ctrl(rvu, table->mem_table.depth);
1969b747923aSRatheesh Kannoth 
19703571fe07SRatheesh Kannoth 	/* - No drop rule for LBK
19713571fe07SRatheesh Kannoth 	 * - Drop rules for SDP and each LMAC.
19723571fe07SRatheesh Kannoth 	 */
19733571fe07SRatheesh Kannoth 	exact_val = !NPC_EXACT_RESULT_HIT;
19743571fe07SRatheesh Kannoth 	exact_mask = NPC_EXACT_RESULT_HIT;
19753571fe07SRatheesh Kannoth 
19763571fe07SRatheesh Kannoth 	/* nibble - 3	2  1   0
19773571fe07SRatheesh Kannoth 	 *	   L3B L3M L2B L2M
19783571fe07SRatheesh Kannoth 	 */
19793571fe07SRatheesh Kannoth 	bcast_mcast_val = 0b0000;
19803571fe07SRatheesh Kannoth 	bcast_mcast_mask = 0b0011;
19813571fe07SRatheesh Kannoth 
19823571fe07SRatheesh Kannoth 	/* Install SDP drop rule */
19833571fe07SRatheesh Kannoth 	drop_mcam_idx = &table->num_drop_rules;
19843571fe07SRatheesh Kannoth 
1985f2e664adSRakesh Babu Saladi 	max_lmac_cnt = rvu->cgx_cnt_max * rvu->hw->lmac_per_cgx +
1986f2e664adSRakesh Babu Saladi 		       PF_CGXMAP_BASE;
1987f2e664adSRakesh Babu Saladi 
19883571fe07SRatheesh Kannoth 	for (i = PF_CGXMAP_BASE; i < max_lmac_cnt; i++) {
19893571fe07SRatheesh Kannoth 		if (rvu->pf2cgxlmac_map[i] == 0xFF)
19903571fe07SRatheesh Kannoth 			continue;
19913571fe07SRatheesh Kannoth 
19923571fe07SRatheesh Kannoth 		rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[i], &cgx_id, &lmac_id);
19933571fe07SRatheesh Kannoth 
19943571fe07SRatheesh Kannoth 		rc = rvu_npc_exact_calc_drop_rule_chan_and_mask(rvu, NIX_INTF_TYPE_CGX, cgx_id,
19953571fe07SRatheesh Kannoth 								lmac_id, &chan_val, &chan_mask);
19963571fe07SRatheesh Kannoth 		if (!rc) {
19973571fe07SRatheesh Kannoth 			dev_err(rvu->dev,
19983571fe07SRatheesh Kannoth 				"%s: failed, info chan_val=0x%llx chan_mask=0x%llx rule_id=%d\n",
19993571fe07SRatheesh Kannoth 				__func__, chan_val, chan_mask, *drop_mcam_idx);
20003571fe07SRatheesh Kannoth 			return -EINVAL;
20013571fe07SRatheesh Kannoth 		}
20023571fe07SRatheesh Kannoth 
20033571fe07SRatheesh Kannoth 		/* Filter rules are only for PF */
20043571fe07SRatheesh Kannoth 		pcifunc = RVU_PFFUNC(i, 0);
20053571fe07SRatheesh Kannoth 
20063571fe07SRatheesh Kannoth 		dev_dbg(rvu->dev,
20073571fe07SRatheesh Kannoth 			"%s:Drop rule cgx=%d lmac=%d chan(val=0x%llx, mask=0x%llx\n",
20083571fe07SRatheesh Kannoth 			__func__, cgx_id, lmac_id, chan_val, chan_mask);
20093571fe07SRatheesh Kannoth 
20103571fe07SRatheesh Kannoth 		rc = rvu_npc_exact_save_drop_rule_chan_and_mask(rvu, table->num_drop_rules,
20113571fe07SRatheesh Kannoth 								chan_val, chan_mask, pcifunc);
20123571fe07SRatheesh Kannoth 		if (!rc) {
20133571fe07SRatheesh Kannoth 			dev_err(rvu->dev,
20143571fe07SRatheesh Kannoth 				"%s: failed to set drop info for cgx=%d, lmac=%d, chan=%llx\n",
20153571fe07SRatheesh Kannoth 				__func__, cgx_id, lmac_id, chan_val);
20166a605eb1SSebin Sebastian 			return -EINVAL;
20173571fe07SRatheesh Kannoth 		}
20183571fe07SRatheesh Kannoth 
20193571fe07SRatheesh Kannoth 		err = npc_install_mcam_drop_rule(rvu, *drop_mcam_idx,
20203571fe07SRatheesh Kannoth 						 &table->counter_idx[*drop_mcam_idx],
20213571fe07SRatheesh Kannoth 						 chan_val, chan_mask,
20223571fe07SRatheesh Kannoth 						 exact_val, exact_mask,
20233571fe07SRatheesh Kannoth 						 bcast_mcast_val, bcast_mcast_mask);
20243571fe07SRatheesh Kannoth 		if (err) {
20253571fe07SRatheesh Kannoth 			dev_err(rvu->dev,
20263571fe07SRatheesh Kannoth 				"failed to configure drop rule (cgx=%d lmac=%d)\n",
20273571fe07SRatheesh Kannoth 				cgx_id, lmac_id);
20283571fe07SRatheesh Kannoth 			return err;
20293571fe07SRatheesh Kannoth 		}
20303571fe07SRatheesh Kannoth 
20313571fe07SRatheesh Kannoth 		(*drop_mcam_idx)++;
20323571fe07SRatheesh Kannoth 	}
20333571fe07SRatheesh Kannoth 
2034b747923aSRatheesh Kannoth 	dev_info(rvu->dev, "initialized exact match table successfully\n");
2035b747923aSRatheesh Kannoth 	return 0;
2036b747923aSRatheesh Kannoth }
2037