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