18beef08fSSteen Hegelund // SPDX-License-Identifier: GPL-2.0+
28beef08fSSteen Hegelund /* Microchip Sparx5 Switch driver VCAP implementation
38beef08fSSteen Hegelund *
48beef08fSSteen Hegelund * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
58beef08fSSteen Hegelund *
68beef08fSSteen Hegelund * The Sparx5 Chip Register Model can be browsed at this location:
78beef08fSSteen Hegelund * https://github.com/microchip-ung/sparx-5_reginfo
88beef08fSSteen Hegelund */
98beef08fSSteen Hegelund
10e0305cc1SSteen Hegelund #include "vcap_api_debugfs.h"
118beef08fSSteen Hegelund #include "sparx5_main_regs.h"
128beef08fSSteen Hegelund #include "sparx5_main.h"
13c9da1ac1SSteen Hegelund #include "sparx5_vcap_impl.h"
14e8145e06SSteen Hegelund #include "sparx5_vcap_ag_api.h"
15e0305cc1SSteen Hegelund #include "sparx5_vcap_debugfs.h"
168beef08fSSteen Hegelund
17c9da1ac1SSteen Hegelund #define SUPER_VCAP_BLK_SIZE 3072 /* addresses per Super VCAP block */
18c9da1ac1SSteen Hegelund #define STREAMSIZE (64 * 4) /* bytes in the VCAP cache area */
19c9da1ac1SSteen Hegelund
20c9da1ac1SSteen Hegelund #define SPARX5_IS2_LOOKUPS 4
2130172a72SSteen Hegelund #define VCAP_IS2_KEYSEL(_ena, _noneth, _v4_mc, _v4_uc, _v6_mc, _v6_uc, _arp) \
2230172a72SSteen Hegelund (ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_SET(_ena) | \
2330172a72SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(_noneth) | \
2430172a72SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_SET(_v4_mc) | \
2530172a72SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_SET(_v4_uc) | \
2630172a72SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_SET(_v6_mc) | \
2730172a72SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(_v6_uc) | \
2830172a72SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(_arp))
29c9da1ac1SSteen Hegelund
30545609fdSSteen Hegelund #define SPARX5_IS0_LOOKUPS 6
31545609fdSSteen Hegelund #define VCAP_IS0_KEYSEL(_ena, _etype, _ipv4, _ipv6, _mpls_uc, _mpls_mc, _mlbs) \
32545609fdSSteen Hegelund (ANA_CL_ADV_CL_CFG_LOOKUP_ENA_SET(_ena) | \
33545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_SET(_etype) | \
34545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_SET(_ipv4) | \
35545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_SET(_ipv6) | \
36545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL_SET(_mpls_uc) | \
37545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL_SET(_mpls_mc) | \
38545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL_SET(_mlbs))
39545609fdSSteen Hegelund
403cbe7537SSteen Hegelund #define SPARX5_ES0_LOOKUPS 1
413cbe7537SSteen Hegelund #define VCAP_ES0_KEYSEL(_key) (REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA_SET(_key))
423cbe7537SSteen Hegelund #define SPARX5_STAT_ESDX_GRN_PKTS 0x300
433cbe7537SSteen Hegelund #define SPARX5_STAT_ESDX_YEL_PKTS 0x301
443cbe7537SSteen Hegelund
45b95d9e2cSSteen Hegelund #define SPARX5_ES2_LOOKUPS 2
46b95d9e2cSSteen Hegelund #define VCAP_ES2_KEYSEL(_ena, _arp, _ipv4, _ipv6) \
47b95d9e2cSSteen Hegelund (EACL_VCAP_ES2_KEY_SEL_KEY_ENA_SET(_ena) | \
48b95d9e2cSSteen Hegelund EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_SET(_arp) | \
49b95d9e2cSSteen Hegelund EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_SET(_ipv4) | \
50b95d9e2cSSteen Hegelund EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_SET(_ipv6))
51b95d9e2cSSteen Hegelund
52c9da1ac1SSteen Hegelund static struct sparx5_vcap_inst {
53c9da1ac1SSteen Hegelund enum vcap_type vtype; /* type of vcap */
54c9da1ac1SSteen Hegelund int vinst; /* instance number within the same type */
55c9da1ac1SSteen Hegelund int lookups; /* number of lookups in this vcap type */
56c9da1ac1SSteen Hegelund int lookups_per_instance; /* number of lookups in this instance */
57c9da1ac1SSteen Hegelund int first_cid; /* first chain id in this vcap */
58c9da1ac1SSteen Hegelund int last_cid; /* last chain id in this vcap */
59c9da1ac1SSteen Hegelund int count; /* number of available addresses, not in super vcap */
60c9da1ac1SSteen Hegelund int map_id; /* id in the super vcap block mapping (if applicable) */
61c9da1ac1SSteen Hegelund int blockno; /* starting block in super vcap (if applicable) */
62c9da1ac1SSteen Hegelund int blocks; /* number of blocks in super vcap (if applicable) */
63e7e3f514SSteen Hegelund bool ingress; /* is vcap in the ingress path */
64c9da1ac1SSteen Hegelund } sparx5_vcap_inst_cfg[] = {
65c9da1ac1SSteen Hegelund {
66545609fdSSteen Hegelund .vtype = VCAP_TYPE_IS0, /* CLM-0 */
67545609fdSSteen Hegelund .vinst = 0,
68545609fdSSteen Hegelund .map_id = 1,
69545609fdSSteen Hegelund .lookups = SPARX5_IS0_LOOKUPS,
70545609fdSSteen Hegelund .lookups_per_instance = SPARX5_IS0_LOOKUPS / 3,
71545609fdSSteen Hegelund .first_cid = SPARX5_VCAP_CID_IS0_L0,
72545609fdSSteen Hegelund .last_cid = SPARX5_VCAP_CID_IS0_L2 - 1,
73545609fdSSteen Hegelund .blockno = 8, /* Maps block 8-9 */
74545609fdSSteen Hegelund .blocks = 2,
75e7e3f514SSteen Hegelund .ingress = true,
76545609fdSSteen Hegelund },
77545609fdSSteen Hegelund {
78545609fdSSteen Hegelund .vtype = VCAP_TYPE_IS0, /* CLM-1 */
79545609fdSSteen Hegelund .vinst = 1,
80545609fdSSteen Hegelund .map_id = 2,
81545609fdSSteen Hegelund .lookups = SPARX5_IS0_LOOKUPS,
82545609fdSSteen Hegelund .lookups_per_instance = SPARX5_IS0_LOOKUPS / 3,
83545609fdSSteen Hegelund .first_cid = SPARX5_VCAP_CID_IS0_L2,
84545609fdSSteen Hegelund .last_cid = SPARX5_VCAP_CID_IS0_L4 - 1,
85545609fdSSteen Hegelund .blockno = 6, /* Maps block 6-7 */
86545609fdSSteen Hegelund .blocks = 2,
87e7e3f514SSteen Hegelund .ingress = true,
88545609fdSSteen Hegelund },
89545609fdSSteen Hegelund {
90545609fdSSteen Hegelund .vtype = VCAP_TYPE_IS0, /* CLM-2 */
91545609fdSSteen Hegelund .vinst = 2,
92545609fdSSteen Hegelund .map_id = 3,
93545609fdSSteen Hegelund .lookups = SPARX5_IS0_LOOKUPS,
94545609fdSSteen Hegelund .lookups_per_instance = SPARX5_IS0_LOOKUPS / 3,
95545609fdSSteen Hegelund .first_cid = SPARX5_VCAP_CID_IS0_L4,
96545609fdSSteen Hegelund .last_cid = SPARX5_VCAP_CID_IS0_MAX,
97545609fdSSteen Hegelund .blockno = 4, /* Maps block 4-5 */
98545609fdSSteen Hegelund .blocks = 2,
99e7e3f514SSteen Hegelund .ingress = true,
100545609fdSSteen Hegelund },
101545609fdSSteen Hegelund {
102c9da1ac1SSteen Hegelund .vtype = VCAP_TYPE_IS2, /* IS2-0 */
103c9da1ac1SSteen Hegelund .vinst = 0,
104c9da1ac1SSteen Hegelund .map_id = 4,
105c9da1ac1SSteen Hegelund .lookups = SPARX5_IS2_LOOKUPS,
106c9da1ac1SSteen Hegelund .lookups_per_instance = SPARX5_IS2_LOOKUPS / 2,
107c9da1ac1SSteen Hegelund .first_cid = SPARX5_VCAP_CID_IS2_L0,
108c9da1ac1SSteen Hegelund .last_cid = SPARX5_VCAP_CID_IS2_L2 - 1,
109c9da1ac1SSteen Hegelund .blockno = 0, /* Maps block 0-1 */
110c9da1ac1SSteen Hegelund .blocks = 2,
111e7e3f514SSteen Hegelund .ingress = true,
112c9da1ac1SSteen Hegelund },
113c9da1ac1SSteen Hegelund {
114c9da1ac1SSteen Hegelund .vtype = VCAP_TYPE_IS2, /* IS2-1 */
115c9da1ac1SSteen Hegelund .vinst = 1,
116c9da1ac1SSteen Hegelund .map_id = 5,
117c9da1ac1SSteen Hegelund .lookups = SPARX5_IS2_LOOKUPS,
118c9da1ac1SSteen Hegelund .lookups_per_instance = SPARX5_IS2_LOOKUPS / 2,
119c9da1ac1SSteen Hegelund .first_cid = SPARX5_VCAP_CID_IS2_L2,
120c9da1ac1SSteen Hegelund .last_cid = SPARX5_VCAP_CID_IS2_MAX,
121c9da1ac1SSteen Hegelund .blockno = 2, /* Maps block 2-3 */
122c9da1ac1SSteen Hegelund .blocks = 2,
123e7e3f514SSteen Hegelund .ingress = true,
124c9da1ac1SSteen Hegelund },
125b95d9e2cSSteen Hegelund {
1263cbe7537SSteen Hegelund .vtype = VCAP_TYPE_ES0,
1273cbe7537SSteen Hegelund .lookups = SPARX5_ES0_LOOKUPS,
1283cbe7537SSteen Hegelund .lookups_per_instance = SPARX5_ES0_LOOKUPS,
1293cbe7537SSteen Hegelund .first_cid = SPARX5_VCAP_CID_ES0_L0,
1303cbe7537SSteen Hegelund .last_cid = SPARX5_VCAP_CID_ES0_MAX,
1313cbe7537SSteen Hegelund .count = 4096, /* Addresses according to datasheet */
1323cbe7537SSteen Hegelund .ingress = false,
1333cbe7537SSteen Hegelund },
1343cbe7537SSteen Hegelund {
135b95d9e2cSSteen Hegelund .vtype = VCAP_TYPE_ES2,
136b95d9e2cSSteen Hegelund .lookups = SPARX5_ES2_LOOKUPS,
137b95d9e2cSSteen Hegelund .lookups_per_instance = SPARX5_ES2_LOOKUPS,
138b95d9e2cSSteen Hegelund .first_cid = SPARX5_VCAP_CID_ES2_L0,
139b95d9e2cSSteen Hegelund .last_cid = SPARX5_VCAP_CID_ES2_MAX,
140b95d9e2cSSteen Hegelund .count = 12288, /* Addresses according to datasheet */
141e7e3f514SSteen Hegelund .ingress = false,
142b95d9e2cSSteen Hegelund },
143c9da1ac1SSteen Hegelund };
144c9da1ac1SSteen Hegelund
14563e35645SSteen Hegelund /* These protocols have dedicated keysets in IS0 and a TC dissector */
14663e35645SSteen Hegelund static u16 sparx5_vcap_is0_known_etypes[] = {
14763e35645SSteen Hegelund ETH_P_ALL,
14863e35645SSteen Hegelund ETH_P_IP,
14963e35645SSteen Hegelund ETH_P_IPV6,
15063e35645SSteen Hegelund };
15163e35645SSteen Hegelund
15263e35645SSteen Hegelund /* These protocols have dedicated keysets in IS2 and a TC dissector */
15363e35645SSteen Hegelund static u16 sparx5_vcap_is2_known_etypes[] = {
15463e35645SSteen Hegelund ETH_P_ALL,
15563e35645SSteen Hegelund ETH_P_ARP,
15663e35645SSteen Hegelund ETH_P_IP,
15763e35645SSteen Hegelund ETH_P_IPV6,
15863e35645SSteen Hegelund };
15963e35645SSteen Hegelund
1607b911a53SSteen Hegelund /* These protocols have dedicated keysets in ES2 and a TC dissector */
1617b911a53SSteen Hegelund static u16 sparx5_vcap_es2_known_etypes[] = {
1627b911a53SSteen Hegelund ETH_P_ALL,
1637b911a53SSteen Hegelund ETH_P_ARP,
1647b911a53SSteen Hegelund ETH_P_IP,
1657b911a53SSteen Hegelund ETH_P_IPV6,
1667b911a53SSteen Hegelund };
1677b911a53SSteen Hegelund
sparx5_vcap_type_err(struct sparx5 * sparx5,struct vcap_admin * admin,const char * fname)168545609fdSSteen Hegelund static void sparx5_vcap_type_err(struct sparx5 *sparx5,
169545609fdSSteen Hegelund struct vcap_admin *admin,
170545609fdSSteen Hegelund const char *fname)
171545609fdSSteen Hegelund {
172545609fdSSteen Hegelund pr_err("%s: vcap type: %s not supported\n",
173545609fdSSteen Hegelund fname, sparx5_vcaps[admin->vtype].name);
174545609fdSSteen Hegelund }
175545609fdSSteen Hegelund
17646be056eSSteen Hegelund /* Await the super VCAP completion of the current operation */
sparx5_vcap_wait_super_update(struct sparx5 * sparx5)17746be056eSSteen Hegelund static void sparx5_vcap_wait_super_update(struct sparx5 *sparx5)
17846be056eSSteen Hegelund {
17946be056eSSteen Hegelund u32 value;
18046be056eSSteen Hegelund
18146be056eSSteen Hegelund read_poll_timeout(spx5_rd, value,
18246be056eSSteen Hegelund !VCAP_SUPER_CTRL_UPDATE_SHOT_GET(value), 500, 10000,
18346be056eSSteen Hegelund false, sparx5, VCAP_SUPER_CTRL);
18446be056eSSteen Hegelund }
18546be056eSSteen Hegelund
1863cbe7537SSteen Hegelund /* Await the ES0 VCAP completion of the current operation */
sparx5_vcap_wait_es0_update(struct sparx5 * sparx5)1873cbe7537SSteen Hegelund static void sparx5_vcap_wait_es0_update(struct sparx5 *sparx5)
1883cbe7537SSteen Hegelund {
1893cbe7537SSteen Hegelund u32 value;
1903cbe7537SSteen Hegelund
1913cbe7537SSteen Hegelund read_poll_timeout(spx5_rd, value,
1923cbe7537SSteen Hegelund !VCAP_ES0_CTRL_UPDATE_SHOT_GET(value), 500, 10000,
1933cbe7537SSteen Hegelund false, sparx5, VCAP_ES0_CTRL);
1943cbe7537SSteen Hegelund }
1953cbe7537SSteen Hegelund
196b95d9e2cSSteen Hegelund /* Await the ES2 VCAP completion of the current operation */
sparx5_vcap_wait_es2_update(struct sparx5 * sparx5)197b95d9e2cSSteen Hegelund static void sparx5_vcap_wait_es2_update(struct sparx5 *sparx5)
198b95d9e2cSSteen Hegelund {
199b95d9e2cSSteen Hegelund u32 value;
200b95d9e2cSSteen Hegelund
201b95d9e2cSSteen Hegelund read_poll_timeout(spx5_rd, value,
202b95d9e2cSSteen Hegelund !VCAP_ES2_CTRL_UPDATE_SHOT_GET(value), 500, 10000,
203b95d9e2cSSteen Hegelund false, sparx5, VCAP_ES2_CTRL);
204b95d9e2cSSteen Hegelund }
205b95d9e2cSSteen Hegelund
206b95d9e2cSSteen Hegelund /* Initializing a VCAP address range */
_sparx5_vcap_range_init(struct sparx5 * sparx5,struct vcap_admin * admin,u32 addr,u32 count)20746be056eSSteen Hegelund static void _sparx5_vcap_range_init(struct sparx5 *sparx5,
20846be056eSSteen Hegelund struct vcap_admin *admin,
20946be056eSSteen Hegelund u32 addr, u32 count)
21046be056eSSteen Hegelund {
21146be056eSSteen Hegelund u32 size = count - 1;
21246be056eSSteen Hegelund
213b95d9e2cSSteen Hegelund switch (admin->vtype) {
214b95d9e2cSSteen Hegelund case VCAP_TYPE_IS0:
215b95d9e2cSSteen Hegelund case VCAP_TYPE_IS2:
21646be056eSSteen Hegelund spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(0) |
21746be056eSSteen Hegelund VCAP_SUPER_CFG_MV_SIZE_SET(size),
21846be056eSSteen Hegelund sparx5, VCAP_SUPER_CFG);
21946be056eSSteen Hegelund spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) |
22046be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET(0) |
22146be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET(0) |
22246be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET(0) |
22346be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr) |
22446be056eSSteen Hegelund VCAP_SUPER_CTRL_CLEAR_CACHE_SET(true) |
22546be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true),
22646be056eSSteen Hegelund sparx5, VCAP_SUPER_CTRL);
22746be056eSSteen Hegelund sparx5_vcap_wait_super_update(sparx5);
228b95d9e2cSSteen Hegelund break;
2293cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
2303cbe7537SSteen Hegelund spx5_wr(VCAP_ES0_CFG_MV_NUM_POS_SET(0) |
2313cbe7537SSteen Hegelund VCAP_ES0_CFG_MV_SIZE_SET(size),
2323cbe7537SSteen Hegelund sparx5, VCAP_ES0_CFG);
2333cbe7537SSteen Hegelund spx5_wr(VCAP_ES0_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) |
2343cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_ENTRY_DIS_SET(0) |
2353cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_ACTION_DIS_SET(0) |
2363cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_CNT_DIS_SET(0) |
2373cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_ADDR_SET(addr) |
2383cbe7537SSteen Hegelund VCAP_ES0_CTRL_CLEAR_CACHE_SET(true) |
2393cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_SHOT_SET(true),
2403cbe7537SSteen Hegelund sparx5, VCAP_ES0_CTRL);
2413cbe7537SSteen Hegelund sparx5_vcap_wait_es0_update(sparx5);
2423cbe7537SSteen Hegelund break;
243b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
244b95d9e2cSSteen Hegelund spx5_wr(VCAP_ES2_CFG_MV_NUM_POS_SET(0) |
245b95d9e2cSSteen Hegelund VCAP_ES2_CFG_MV_SIZE_SET(size),
246b95d9e2cSSteen Hegelund sparx5, VCAP_ES2_CFG);
247b95d9e2cSSteen Hegelund spx5_wr(VCAP_ES2_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) |
248b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_ENTRY_DIS_SET(0) |
249b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_ACTION_DIS_SET(0) |
250b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_CNT_DIS_SET(0) |
251b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_ADDR_SET(addr) |
252b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_CLEAR_CACHE_SET(true) |
253b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_SHOT_SET(true),
254b95d9e2cSSteen Hegelund sparx5, VCAP_ES2_CTRL);
255b95d9e2cSSteen Hegelund sparx5_vcap_wait_es2_update(sparx5);
256b95d9e2cSSteen Hegelund break;
257b95d9e2cSSteen Hegelund default:
258b95d9e2cSSteen Hegelund sparx5_vcap_type_err(sparx5, admin, __func__);
259b95d9e2cSSteen Hegelund break;
260b95d9e2cSSteen Hegelund }
26146be056eSSteen Hegelund }
26246be056eSSteen Hegelund
26346be056eSSteen Hegelund /* Initializing VCAP rule data area */
sparx5_vcap_block_init(struct sparx5 * sparx5,struct vcap_admin * admin)26446be056eSSteen Hegelund static void sparx5_vcap_block_init(struct sparx5 *sparx5,
26546be056eSSteen Hegelund struct vcap_admin *admin)
26646be056eSSteen Hegelund {
26746be056eSSteen Hegelund _sparx5_vcap_range_init(sparx5, admin, admin->first_valid_addr,
26846be056eSSteen Hegelund admin->last_valid_addr -
26946be056eSSteen Hegelund admin->first_valid_addr);
27046be056eSSteen Hegelund }
27146be056eSSteen Hegelund
27246be056eSSteen Hegelund /* Get the keyset name from the sparx5 VCAP model */
sparx5_vcap_keyset_name(struct net_device * ndev,enum vcap_keyfield_set keyset)27346be056eSSteen Hegelund static const char *sparx5_vcap_keyset_name(struct net_device *ndev,
27446be056eSSteen Hegelund enum vcap_keyfield_set keyset)
27546be056eSSteen Hegelund {
27646be056eSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
27746be056eSSteen Hegelund
278abc4010dSSteen Hegelund return vcap_keyset_name(port->sparx5->vcap_ctrl, keyset);
27946be056eSSteen Hegelund }
28046be056eSSteen Hegelund
281545609fdSSteen Hegelund /* Check if this is the first lookup of IS0 */
sparx5_vcap_is0_is_first_chain(struct vcap_rule * rule)282545609fdSSteen Hegelund static bool sparx5_vcap_is0_is_first_chain(struct vcap_rule *rule)
283545609fdSSteen Hegelund {
284545609fdSSteen Hegelund return (rule->vcap_chain_id >= SPARX5_VCAP_CID_IS0_L0 &&
285545609fdSSteen Hegelund rule->vcap_chain_id < SPARX5_VCAP_CID_IS0_L1) ||
286545609fdSSteen Hegelund ((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS0_L2 &&
287545609fdSSteen Hegelund rule->vcap_chain_id < SPARX5_VCAP_CID_IS0_L3)) ||
288545609fdSSteen Hegelund ((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS0_L4 &&
289545609fdSSteen Hegelund rule->vcap_chain_id < SPARX5_VCAP_CID_IS0_L5));
290545609fdSSteen Hegelund }
291545609fdSSteen Hegelund
29246be056eSSteen Hegelund /* Check if this is the first lookup of IS2 */
sparx5_vcap_is2_is_first_chain(struct vcap_rule * rule)29346be056eSSteen Hegelund static bool sparx5_vcap_is2_is_first_chain(struct vcap_rule *rule)
29446be056eSSteen Hegelund {
29546be056eSSteen Hegelund return (rule->vcap_chain_id >= SPARX5_VCAP_CID_IS2_L0 &&
29646be056eSSteen Hegelund rule->vcap_chain_id < SPARX5_VCAP_CID_IS2_L1) ||
29746be056eSSteen Hegelund ((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS2_L2 &&
29846be056eSSteen Hegelund rule->vcap_chain_id < SPARX5_VCAP_CID_IS2_L3));
29946be056eSSteen Hegelund }
30046be056eSSteen Hegelund
sparx5_vcap_es2_is_first_chain(struct vcap_rule * rule)301b95d9e2cSSteen Hegelund static bool sparx5_vcap_es2_is_first_chain(struct vcap_rule *rule)
302b95d9e2cSSteen Hegelund {
303b95d9e2cSSteen Hegelund return (rule->vcap_chain_id >= SPARX5_VCAP_CID_ES2_L0 &&
304b95d9e2cSSteen Hegelund rule->vcap_chain_id < SPARX5_VCAP_CID_ES2_L1);
305b95d9e2cSSteen Hegelund }
306b95d9e2cSSteen Hegelund
30746be056eSSteen Hegelund /* Set the narrow range ingress port mask on a rule */
sparx5_vcap_add_ingress_range_port_mask(struct vcap_rule * rule,struct net_device * ndev)308b95d9e2cSSteen Hegelund static void sparx5_vcap_add_ingress_range_port_mask(struct vcap_rule *rule,
30946be056eSSteen Hegelund struct net_device *ndev)
31046be056eSSteen Hegelund {
31146be056eSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
31246be056eSSteen Hegelund u32 port_mask;
31346be056eSSteen Hegelund u32 range;
31446be056eSSteen Hegelund
31546be056eSSteen Hegelund range = port->portno / BITS_PER_TYPE(u32);
31646be056eSSteen Hegelund /* Port bit set to match-any */
31746be056eSSteen Hegelund port_mask = ~BIT(port->portno % BITS_PER_TYPE(u32));
31846be056eSSteen Hegelund vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_SEL, 0, 0xf);
31946be056eSSteen Hegelund vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_RNG, range, 0xf);
32046be056eSSteen Hegelund vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0, port_mask);
32146be056eSSteen Hegelund }
32246be056eSSteen Hegelund
32346be056eSSteen Hegelund /* Set the wide range ingress port mask on a rule */
sparx5_vcap_add_wide_port_mask(struct vcap_rule * rule,struct net_device * ndev)32446be056eSSteen Hegelund static void sparx5_vcap_add_wide_port_mask(struct vcap_rule *rule,
32546be056eSSteen Hegelund struct net_device *ndev)
32646be056eSSteen Hegelund {
32746be056eSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
32846be056eSSteen Hegelund struct vcap_u72_key port_mask;
32946be056eSSteen Hegelund u32 range;
33046be056eSSteen Hegelund
33146be056eSSteen Hegelund /* Port bit set to match-any */
33246be056eSSteen Hegelund memset(port_mask.value, 0, sizeof(port_mask.value));
33346be056eSSteen Hegelund memset(port_mask.mask, 0xff, sizeof(port_mask.mask));
33446be056eSSteen Hegelund range = port->portno / BITS_PER_BYTE;
33546be056eSSteen Hegelund port_mask.mask[range] = ~BIT(port->portno % BITS_PER_BYTE);
33646be056eSSteen Hegelund vcap_rule_add_key_u72(rule, VCAP_KF_IF_IGR_PORT_MASK, &port_mask);
33746be056eSSteen Hegelund }
33846be056eSSteen Hegelund
sparx5_vcap_add_egress_range_port_mask(struct vcap_rule * rule,struct net_device * ndev)339b95d9e2cSSteen Hegelund static void sparx5_vcap_add_egress_range_port_mask(struct vcap_rule *rule,
340b95d9e2cSSteen Hegelund struct net_device *ndev)
341b95d9e2cSSteen Hegelund {
342b95d9e2cSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
343b95d9e2cSSteen Hegelund u32 port_mask;
344b95d9e2cSSteen Hegelund u32 range;
345b95d9e2cSSteen Hegelund
346b95d9e2cSSteen Hegelund /* Mask range selects:
347b95d9e2cSSteen Hegelund * 0-2: Physical/Logical egress port number 0-31, 32–63, 64.
348b95d9e2cSSteen Hegelund * 3-5: Virtual Interface Number 0-31, 32-63, 64.
349b95d9e2cSSteen Hegelund * 6: CPU queue Number 0-7.
350b95d9e2cSSteen Hegelund *
351b95d9e2cSSteen Hegelund * Use physical/logical port ranges (0-2)
352b95d9e2cSSteen Hegelund */
353b95d9e2cSSteen Hegelund range = port->portno / BITS_PER_TYPE(u32);
354b95d9e2cSSteen Hegelund /* Port bit set to match-any */
355b95d9e2cSSteen Hegelund port_mask = ~BIT(port->portno % BITS_PER_TYPE(u32));
356b95d9e2cSSteen Hegelund vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_MASK_RNG, range, 0xf);
357b95d9e2cSSteen Hegelund vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_MASK, 0, port_mask);
358b95d9e2cSSteen Hegelund }
359b95d9e2cSSteen Hegelund
360545609fdSSteen Hegelund /* Convert IS0 chain id to vcap lookup id */
sparx5_vcap_is0_cid_to_lookup(int cid)361545609fdSSteen Hegelund static int sparx5_vcap_is0_cid_to_lookup(int cid)
362abc4010dSSteen Hegelund {
363abc4010dSSteen Hegelund int lookup = 0;
364abc4010dSSteen Hegelund
365545609fdSSteen Hegelund if (cid >= SPARX5_VCAP_CID_IS0_L1 && cid < SPARX5_VCAP_CID_IS0_L2)
366545609fdSSteen Hegelund lookup = 1;
367545609fdSSteen Hegelund else if (cid >= SPARX5_VCAP_CID_IS0_L2 && cid < SPARX5_VCAP_CID_IS0_L3)
368545609fdSSteen Hegelund lookup = 2;
369545609fdSSteen Hegelund else if (cid >= SPARX5_VCAP_CID_IS0_L3 && cid < SPARX5_VCAP_CID_IS0_L4)
370545609fdSSteen Hegelund lookup = 3;
371545609fdSSteen Hegelund else if (cid >= SPARX5_VCAP_CID_IS0_L4 && cid < SPARX5_VCAP_CID_IS0_L5)
372545609fdSSteen Hegelund lookup = 4;
373545609fdSSteen Hegelund else if (cid >= SPARX5_VCAP_CID_IS0_L5 && cid < SPARX5_VCAP_CID_IS0_MAX)
374545609fdSSteen Hegelund lookup = 5;
375545609fdSSteen Hegelund
376545609fdSSteen Hegelund return lookup;
377545609fdSSteen Hegelund }
378545609fdSSteen Hegelund
379545609fdSSteen Hegelund /* Convert IS2 chain id to vcap lookup id */
sparx5_vcap_is2_cid_to_lookup(int cid)380545609fdSSteen Hegelund static int sparx5_vcap_is2_cid_to_lookup(int cid)
381545609fdSSteen Hegelund {
382545609fdSSteen Hegelund int lookup = 0;
383545609fdSSteen Hegelund
384abc4010dSSteen Hegelund if (cid >= SPARX5_VCAP_CID_IS2_L1 && cid < SPARX5_VCAP_CID_IS2_L2)
385abc4010dSSteen Hegelund lookup = 1;
386abc4010dSSteen Hegelund else if (cid >= SPARX5_VCAP_CID_IS2_L2 && cid < SPARX5_VCAP_CID_IS2_L3)
387abc4010dSSteen Hegelund lookup = 2;
388abc4010dSSteen Hegelund else if (cid >= SPARX5_VCAP_CID_IS2_L3 && cid < SPARX5_VCAP_CID_IS2_MAX)
389abc4010dSSteen Hegelund lookup = 3;
390abc4010dSSteen Hegelund
391abc4010dSSteen Hegelund return lookup;
392abc4010dSSteen Hegelund }
393abc4010dSSteen Hegelund
394b95d9e2cSSteen Hegelund /* Convert ES2 chain id to vcap lookup id */
sparx5_vcap_es2_cid_to_lookup(int cid)395b95d9e2cSSteen Hegelund static int sparx5_vcap_es2_cid_to_lookup(int cid)
396b95d9e2cSSteen Hegelund {
397b95d9e2cSSteen Hegelund int lookup = 0;
398b95d9e2cSSteen Hegelund
399b95d9e2cSSteen Hegelund if (cid >= SPARX5_VCAP_CID_ES2_L1)
400b95d9e2cSSteen Hegelund lookup = 1;
401b95d9e2cSSteen Hegelund
402b95d9e2cSSteen Hegelund return lookup;
403b95d9e2cSSteen Hegelund }
404b95d9e2cSSteen Hegelund
405545609fdSSteen Hegelund /* Add ethernet type IS0 keyset to a list */
406545609fdSSteen Hegelund static void
sparx5_vcap_is0_get_port_etype_keysets(struct vcap_keyset_list * keysetlist,u32 value)407545609fdSSteen Hegelund sparx5_vcap_is0_get_port_etype_keysets(struct vcap_keyset_list *keysetlist,
408545609fdSSteen Hegelund u32 value)
409545609fdSSteen Hegelund {
410545609fdSSteen Hegelund switch (ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_GET(value)) {
411545609fdSSteen Hegelund case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE:
412545609fdSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_7TUPLE);
413545609fdSSteen Hegelund break;
414545609fdSSteen Hegelund case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4:
415545609fdSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_5TUPLE_IP4);
416545609fdSSteen Hegelund break;
417545609fdSSteen Hegelund }
418545609fdSSteen Hegelund }
419545609fdSSteen Hegelund
420545609fdSSteen Hegelund /* Return the list of keysets for the vcap port configuration */
sparx5_vcap_is0_get_port_keysets(struct net_device * ndev,int lookup,struct vcap_keyset_list * keysetlist,u16 l3_proto)421545609fdSSteen Hegelund static int sparx5_vcap_is0_get_port_keysets(struct net_device *ndev,
422545609fdSSteen Hegelund int lookup,
423545609fdSSteen Hegelund struct vcap_keyset_list *keysetlist,
424545609fdSSteen Hegelund u16 l3_proto)
425545609fdSSteen Hegelund {
426545609fdSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
427545609fdSSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
428545609fdSSteen Hegelund int portno = port->portno;
429545609fdSSteen Hegelund u32 value;
430545609fdSSteen Hegelund
431545609fdSSteen Hegelund value = spx5_rd(sparx5, ANA_CL_ADV_CL_CFG(portno, lookup));
432545609fdSSteen Hegelund
433545609fdSSteen Hegelund /* Collect all keysets for the port in a list */
434545609fdSSteen Hegelund if (l3_proto == ETH_P_ALL)
435545609fdSSteen Hegelund sparx5_vcap_is0_get_port_etype_keysets(keysetlist, value);
436545609fdSSteen Hegelund
437545609fdSSteen Hegelund if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP)
438545609fdSSteen Hegelund switch (ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_GET(value)) {
439545609fdSSteen Hegelund case VCAP_IS0_PS_ETYPE_DEFAULT:
440545609fdSSteen Hegelund sparx5_vcap_is0_get_port_etype_keysets(keysetlist,
441545609fdSSteen Hegelund value);
442545609fdSSteen Hegelund break;
443545609fdSSteen Hegelund case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE:
444545609fdSSteen Hegelund vcap_keyset_list_add(keysetlist,
445545609fdSSteen Hegelund VCAP_KFS_NORMAL_7TUPLE);
446545609fdSSteen Hegelund break;
447545609fdSSteen Hegelund case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4:
448545609fdSSteen Hegelund vcap_keyset_list_add(keysetlist,
449545609fdSSteen Hegelund VCAP_KFS_NORMAL_5TUPLE_IP4);
450545609fdSSteen Hegelund break;
451545609fdSSteen Hegelund }
452545609fdSSteen Hegelund
453545609fdSSteen Hegelund if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6)
454545609fdSSteen Hegelund switch (ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_GET(value)) {
455545609fdSSteen Hegelund case VCAP_IS0_PS_ETYPE_DEFAULT:
456545609fdSSteen Hegelund sparx5_vcap_is0_get_port_etype_keysets(keysetlist,
457545609fdSSteen Hegelund value);
458545609fdSSteen Hegelund break;
459545609fdSSteen Hegelund case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE:
460545609fdSSteen Hegelund vcap_keyset_list_add(keysetlist,
461545609fdSSteen Hegelund VCAP_KFS_NORMAL_7TUPLE);
462545609fdSSteen Hegelund break;
463545609fdSSteen Hegelund case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4:
464545609fdSSteen Hegelund vcap_keyset_list_add(keysetlist,
465545609fdSSteen Hegelund VCAP_KFS_NORMAL_5TUPLE_IP4);
466545609fdSSteen Hegelund break;
467545609fdSSteen Hegelund }
468545609fdSSteen Hegelund
469545609fdSSteen Hegelund if (l3_proto != ETH_P_IP && l3_proto != ETH_P_IPV6)
470545609fdSSteen Hegelund sparx5_vcap_is0_get_port_etype_keysets(keysetlist, value);
471545609fdSSteen Hegelund return 0;
472545609fdSSteen Hegelund }
473545609fdSSteen Hegelund
474abc4010dSSteen Hegelund /* Return the list of keysets for the vcap port configuration */
sparx5_vcap_is2_get_port_keysets(struct net_device * ndev,int lookup,struct vcap_keyset_list * keysetlist,u16 l3_proto)475abc4010dSSteen Hegelund static int sparx5_vcap_is2_get_port_keysets(struct net_device *ndev,
476abc4010dSSteen Hegelund int lookup,
477abc4010dSSteen Hegelund struct vcap_keyset_list *keysetlist,
478abc4010dSSteen Hegelund u16 l3_proto)
479abc4010dSSteen Hegelund {
480abc4010dSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
481abc4010dSSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
482abc4010dSSteen Hegelund int portno = port->portno;
483abc4010dSSteen Hegelund u32 value;
484abc4010dSSteen Hegelund
485abc4010dSSteen Hegelund value = spx5_rd(sparx5, ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
486abc4010dSSteen Hegelund
487abc4010dSSteen Hegelund /* Collect all keysets for the port in a list */
488abc4010dSSteen Hegelund if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) {
489abc4010dSSteen Hegelund switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value)) {
490abc4010dSSteen Hegelund case VCAP_IS2_PS_ARP_MAC_ETYPE:
491abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
492abc4010dSSteen Hegelund break;
493abc4010dSSteen Hegelund case VCAP_IS2_PS_ARP_ARP:
494abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP);
495abc4010dSSteen Hegelund break;
496abc4010dSSteen Hegelund }
497abc4010dSSteen Hegelund }
498abc4010dSSteen Hegelund
499abc4010dSSteen Hegelund if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
500abc4010dSSteen Hegelund switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value)) {
501abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV4_UC_MAC_ETYPE:
502abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
503abc4010dSSteen Hegelund break;
504abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER:
505abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
506abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
507abc4010dSSteen Hegelund break;
508abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE:
509abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
510abc4010dSSteen Hegelund break;
511abc4010dSSteen Hegelund }
512abc4010dSSteen Hegelund
513abc4010dSSteen Hegelund switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value)) {
514abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV4_MC_MAC_ETYPE:
515abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
516abc4010dSSteen Hegelund break;
517abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER:
518abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
519abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
520abc4010dSSteen Hegelund break;
521abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE:
522abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
523abc4010dSSteen Hegelund break;
524abc4010dSSteen Hegelund }
525abc4010dSSteen Hegelund }
526abc4010dSSteen Hegelund
527abc4010dSSteen Hegelund if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
528abc4010dSSteen Hegelund switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value)) {
529abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV6_UC_MAC_ETYPE:
530abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
531abc4010dSSteen Hegelund break;
532abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE:
533abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
534abc4010dSSteen Hegelund break;
535abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV6_UC_IP6_STD:
536abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
537abc4010dSSteen Hegelund break;
538abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER:
539abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
540abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
541abc4010dSSteen Hegelund break;
542abc4010dSSteen Hegelund }
543abc4010dSSteen Hegelund
544abc4010dSSteen Hegelund switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value)) {
545abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV6_MC_MAC_ETYPE:
546abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
547abc4010dSSteen Hegelund break;
548abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE:
549abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
550abc4010dSSteen Hegelund break;
551abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV6_MC_IP6_STD:
552abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
553abc4010dSSteen Hegelund break;
554abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER:
555abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
556abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
557abc4010dSSteen Hegelund break;
558abc4010dSSteen Hegelund case VCAP_IS2_PS_IPV6_MC_IP6_VID:
559abc4010dSSteen Hegelund /* Not used */
560abc4010dSSteen Hegelund break;
561abc4010dSSteen Hegelund }
562abc4010dSSteen Hegelund }
563abc4010dSSteen Hegelund
564abc4010dSSteen Hegelund if (l3_proto != ETH_P_ARP && l3_proto != ETH_P_IP &&
565abc4010dSSteen Hegelund l3_proto != ETH_P_IPV6) {
566abc4010dSSteen Hegelund switch (ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_GET(value)) {
567abc4010dSSteen Hegelund case VCAP_IS2_PS_NONETH_MAC_ETYPE:
568abc4010dSSteen Hegelund /* IS2 non-classified frames generate MAC_ETYPE */
569abc4010dSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
570abc4010dSSteen Hegelund break;
571abc4010dSSteen Hegelund }
572abc4010dSSteen Hegelund }
573abc4010dSSteen Hegelund return 0;
574abc4010dSSteen Hegelund }
575abc4010dSSteen Hegelund
576b95d9e2cSSteen Hegelund /* Return the keysets for the vcap port IP4 traffic class configuration */
577b95d9e2cSSteen Hegelund static void
sparx5_vcap_es2_get_port_ipv4_keysets(struct vcap_keyset_list * keysetlist,u32 value)578b95d9e2cSSteen Hegelund sparx5_vcap_es2_get_port_ipv4_keysets(struct vcap_keyset_list *keysetlist,
579b95d9e2cSSteen Hegelund u32 value)
580b95d9e2cSSteen Hegelund {
581b95d9e2cSSteen Hegelund switch (EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_GET(value)) {
582b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV4_MAC_ETYPE:
583b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
584b95d9e2cSSteen Hegelund break;
585b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV4_IP_7TUPLE:
586b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
587b95d9e2cSSteen Hegelund break;
588b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_VID:
589b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
590b95d9e2cSSteen Hegelund break;
591b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER:
592b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
593b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
594b95d9e2cSSteen Hegelund break;
595b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV4_IP4_VID:
596b95d9e2cSSteen Hegelund /* Not used */
597b95d9e2cSSteen Hegelund break;
598b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV4_IP4_OTHER:
599b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
600b95d9e2cSSteen Hegelund break;
601b95d9e2cSSteen Hegelund }
602b95d9e2cSSteen Hegelund }
603b95d9e2cSSteen Hegelund
604b95d9e2cSSteen Hegelund /* Return the list of keysets for the vcap port configuration */
sparx5_vcap_es0_get_port_keysets(struct net_device * ndev,struct vcap_keyset_list * keysetlist,u16 l3_proto)6053cbe7537SSteen Hegelund static int sparx5_vcap_es0_get_port_keysets(struct net_device *ndev,
6063cbe7537SSteen Hegelund struct vcap_keyset_list *keysetlist,
6073cbe7537SSteen Hegelund u16 l3_proto)
6083cbe7537SSteen Hegelund {
6093cbe7537SSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
6103cbe7537SSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
6113cbe7537SSteen Hegelund int portno = port->portno;
6123cbe7537SSteen Hegelund u32 value;
6133cbe7537SSteen Hegelund
6143cbe7537SSteen Hegelund value = spx5_rd(sparx5, REW_RTAG_ETAG_CTRL(portno));
6153cbe7537SSteen Hegelund
6163cbe7537SSteen Hegelund /* Collect all keysets for the port in a list */
6173cbe7537SSteen Hegelund switch (REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA_GET(value)) {
6183cbe7537SSteen Hegelund case VCAP_ES0_PS_NORMAL_SELECTION:
6193cbe7537SSteen Hegelund case VCAP_ES0_PS_FORCE_ISDX_LOOKUPS:
6203cbe7537SSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_ISDX);
6213cbe7537SSteen Hegelund break;
6223cbe7537SSteen Hegelund default:
6233cbe7537SSteen Hegelund break;
6243cbe7537SSteen Hegelund }
6253cbe7537SSteen Hegelund return 0;
6263cbe7537SSteen Hegelund }
6273cbe7537SSteen Hegelund
6283cbe7537SSteen Hegelund /* Return the list of keysets for the vcap port configuration */
sparx5_vcap_es2_get_port_keysets(struct net_device * ndev,int lookup,struct vcap_keyset_list * keysetlist,u16 l3_proto)629b95d9e2cSSteen Hegelund static int sparx5_vcap_es2_get_port_keysets(struct net_device *ndev,
630b95d9e2cSSteen Hegelund int lookup,
631b95d9e2cSSteen Hegelund struct vcap_keyset_list *keysetlist,
632b95d9e2cSSteen Hegelund u16 l3_proto)
633b95d9e2cSSteen Hegelund {
634b95d9e2cSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
635b95d9e2cSSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
636b95d9e2cSSteen Hegelund int portno = port->portno;
637b95d9e2cSSteen Hegelund u32 value;
638b95d9e2cSSteen Hegelund
639b95d9e2cSSteen Hegelund value = spx5_rd(sparx5, EACL_VCAP_ES2_KEY_SEL(portno, lookup));
640b95d9e2cSSteen Hegelund
641b95d9e2cSSteen Hegelund /* Collect all keysets for the port in a list */
642b95d9e2cSSteen Hegelund if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) {
643b95d9e2cSSteen Hegelund switch (EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_GET(value)) {
644b95d9e2cSSteen Hegelund case VCAP_ES2_PS_ARP_MAC_ETYPE:
645b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
646b95d9e2cSSteen Hegelund break;
647b95d9e2cSSteen Hegelund case VCAP_ES2_PS_ARP_ARP:
648b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP);
649b95d9e2cSSteen Hegelund break;
650b95d9e2cSSteen Hegelund }
651b95d9e2cSSteen Hegelund }
652b95d9e2cSSteen Hegelund
653b95d9e2cSSteen Hegelund if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP)
654b95d9e2cSSteen Hegelund sparx5_vcap_es2_get_port_ipv4_keysets(keysetlist, value);
655b95d9e2cSSteen Hegelund
656b95d9e2cSSteen Hegelund if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
657b95d9e2cSSteen Hegelund switch (EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_GET(value)) {
658b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV6_MAC_ETYPE:
659b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
660b95d9e2cSSteen Hegelund break;
661b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV6_IP_7TUPLE:
662b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
663b95d9e2cSSteen Hegelund break;
664b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV6_IP_7TUPLE_VID:
665b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
666b95d9e2cSSteen Hegelund break;
667b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV6_IP_7TUPLE_STD:
668b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
669b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
670b95d9e2cSSteen Hegelund break;
671b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV6_IP6_VID:
672b95d9e2cSSteen Hegelund /* Not used */
673b95d9e2cSSteen Hegelund break;
674b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV6_IP6_STD:
675b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
676b95d9e2cSSteen Hegelund break;
677b95d9e2cSSteen Hegelund case VCAP_ES2_PS_IPV6_IP4_DOWNGRADE:
678b95d9e2cSSteen Hegelund sparx5_vcap_es2_get_port_ipv4_keysets(keysetlist,
679b95d9e2cSSteen Hegelund value);
680b95d9e2cSSteen Hegelund break;
681b95d9e2cSSteen Hegelund }
682b95d9e2cSSteen Hegelund }
683b95d9e2cSSteen Hegelund
684b95d9e2cSSteen Hegelund if (l3_proto != ETH_P_ARP && l3_proto != ETH_P_IP &&
685b95d9e2cSSteen Hegelund l3_proto != ETH_P_IPV6) {
686b95d9e2cSSteen Hegelund vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
687b95d9e2cSSteen Hegelund }
688b95d9e2cSSteen Hegelund return 0;
689b95d9e2cSSteen Hegelund }
690b95d9e2cSSteen Hegelund
6910ca60948SSteen Hegelund /* Get the port keyset for the vcap lookup */
sparx5_vcap_get_port_keyset(struct net_device * ndev,struct vcap_admin * admin,int cid,u16 l3_proto,struct vcap_keyset_list * kslist)6920ca60948SSteen Hegelund int sparx5_vcap_get_port_keyset(struct net_device *ndev,
6930ca60948SSteen Hegelund struct vcap_admin *admin,
6940ca60948SSteen Hegelund int cid,
6950ca60948SSteen Hegelund u16 l3_proto,
6960ca60948SSteen Hegelund struct vcap_keyset_list *kslist)
6970ca60948SSteen Hegelund {
698545609fdSSteen Hegelund int lookup, err = -EINVAL;
699545609fdSSteen Hegelund struct sparx5_port *port;
7000ca60948SSteen Hegelund
701545609fdSSteen Hegelund switch (admin->vtype) {
702545609fdSSteen Hegelund case VCAP_TYPE_IS0:
703545609fdSSteen Hegelund lookup = sparx5_vcap_is0_cid_to_lookup(cid);
704545609fdSSteen Hegelund err = sparx5_vcap_is0_get_port_keysets(ndev, lookup, kslist,
705545609fdSSteen Hegelund l3_proto);
706545609fdSSteen Hegelund break;
707545609fdSSteen Hegelund case VCAP_TYPE_IS2:
708545609fdSSteen Hegelund lookup = sparx5_vcap_is2_cid_to_lookup(cid);
709545609fdSSteen Hegelund err = sparx5_vcap_is2_get_port_keysets(ndev, lookup, kslist,
710545609fdSSteen Hegelund l3_proto);
711545609fdSSteen Hegelund break;
7123cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
7133cbe7537SSteen Hegelund err = sparx5_vcap_es0_get_port_keysets(ndev, kslist, l3_proto);
7143cbe7537SSteen Hegelund break;
715b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
716b95d9e2cSSteen Hegelund lookup = sparx5_vcap_es2_cid_to_lookup(cid);
717b95d9e2cSSteen Hegelund err = sparx5_vcap_es2_get_port_keysets(ndev, lookup, kslist,
718b95d9e2cSSteen Hegelund l3_proto);
719b95d9e2cSSteen Hegelund break;
720545609fdSSteen Hegelund default:
721545609fdSSteen Hegelund port = netdev_priv(ndev);
722545609fdSSteen Hegelund sparx5_vcap_type_err(port->sparx5, admin, __func__);
723545609fdSSteen Hegelund break;
724545609fdSSteen Hegelund }
725545609fdSSteen Hegelund return err;
7260ca60948SSteen Hegelund }
7270ca60948SSteen Hegelund
72863e35645SSteen Hegelund /* Check if the ethertype is supported by the vcap port classification */
sparx5_vcap_is_known_etype(struct vcap_admin * admin,u16 etype)72963e35645SSteen Hegelund bool sparx5_vcap_is_known_etype(struct vcap_admin *admin, u16 etype)
73063e35645SSteen Hegelund {
73163e35645SSteen Hegelund const u16 *known_etypes;
73263e35645SSteen Hegelund int size, idx;
73363e35645SSteen Hegelund
73463e35645SSteen Hegelund switch (admin->vtype) {
73563e35645SSteen Hegelund case VCAP_TYPE_IS0:
73663e35645SSteen Hegelund known_etypes = sparx5_vcap_is0_known_etypes;
73763e35645SSteen Hegelund size = ARRAY_SIZE(sparx5_vcap_is0_known_etypes);
73863e35645SSteen Hegelund break;
73963e35645SSteen Hegelund case VCAP_TYPE_IS2:
74063e35645SSteen Hegelund known_etypes = sparx5_vcap_is2_known_etypes;
74163e35645SSteen Hegelund size = ARRAY_SIZE(sparx5_vcap_is2_known_etypes);
74263e35645SSteen Hegelund break;
74352b28a93SSteen Hegelund case VCAP_TYPE_ES0:
74452b28a93SSteen Hegelund return true;
7457b911a53SSteen Hegelund case VCAP_TYPE_ES2:
7467b911a53SSteen Hegelund known_etypes = sparx5_vcap_es2_known_etypes;
7477b911a53SSteen Hegelund size = ARRAY_SIZE(sparx5_vcap_es2_known_etypes);
7487b911a53SSteen Hegelund break;
74963e35645SSteen Hegelund default:
75063e35645SSteen Hegelund return false;
75163e35645SSteen Hegelund }
75263e35645SSteen Hegelund for (idx = 0; idx < size; ++idx)
75363e35645SSteen Hegelund if (known_etypes[idx] == etype)
75463e35645SSteen Hegelund return true;
75563e35645SSteen Hegelund return false;
75663e35645SSteen Hegelund }
75763e35645SSteen Hegelund
75846be056eSSteen Hegelund /* API callback used for validating a field keyset (check the port keysets) */
75946be056eSSteen Hegelund static enum vcap_keyfield_set
sparx5_vcap_validate_keyset(struct net_device * ndev,struct vcap_admin * admin,struct vcap_rule * rule,struct vcap_keyset_list * kslist,u16 l3_proto)76046be056eSSteen Hegelund sparx5_vcap_validate_keyset(struct net_device *ndev,
76146be056eSSteen Hegelund struct vcap_admin *admin,
76246be056eSSteen Hegelund struct vcap_rule *rule,
76346be056eSSteen Hegelund struct vcap_keyset_list *kslist,
76446be056eSSteen Hegelund u16 l3_proto)
76546be056eSSteen Hegelund {
766abc4010dSSteen Hegelund struct vcap_keyset_list keysetlist = {};
767abc4010dSSteen Hegelund enum vcap_keyfield_set keysets[10] = {};
768545609fdSSteen Hegelund struct sparx5_port *port;
769abc4010dSSteen Hegelund int idx, jdx, lookup;
770abc4010dSSteen Hegelund
77146be056eSSteen Hegelund if (!kslist || kslist->cnt == 0)
77246be056eSSteen Hegelund return VCAP_KFS_NO_VALUE;
773abc4010dSSteen Hegelund
774abc4010dSSteen Hegelund keysetlist.max = ARRAY_SIZE(keysets);
775abc4010dSSteen Hegelund keysetlist.keysets = keysets;
776545609fdSSteen Hegelund
777545609fdSSteen Hegelund /* Get a list of currently configured keysets in the lookups */
778545609fdSSteen Hegelund switch (admin->vtype) {
779545609fdSSteen Hegelund case VCAP_TYPE_IS0:
780545609fdSSteen Hegelund lookup = sparx5_vcap_is0_cid_to_lookup(rule->vcap_chain_id);
781545609fdSSteen Hegelund sparx5_vcap_is0_get_port_keysets(ndev, lookup, &keysetlist,
782545609fdSSteen Hegelund l3_proto);
783545609fdSSteen Hegelund break;
784545609fdSSteen Hegelund case VCAP_TYPE_IS2:
785545609fdSSteen Hegelund lookup = sparx5_vcap_is2_cid_to_lookup(rule->vcap_chain_id);
786545609fdSSteen Hegelund sparx5_vcap_is2_get_port_keysets(ndev, lookup, &keysetlist,
787545609fdSSteen Hegelund l3_proto);
788545609fdSSteen Hegelund break;
7893cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
7903cbe7537SSteen Hegelund sparx5_vcap_es0_get_port_keysets(ndev, &keysetlist, l3_proto);
7913cbe7537SSteen Hegelund break;
792b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
793b95d9e2cSSteen Hegelund lookup = sparx5_vcap_es2_cid_to_lookup(rule->vcap_chain_id);
794b95d9e2cSSteen Hegelund sparx5_vcap_es2_get_port_keysets(ndev, lookup, &keysetlist,
795b95d9e2cSSteen Hegelund l3_proto);
796b95d9e2cSSteen Hegelund break;
797545609fdSSteen Hegelund default:
798545609fdSSteen Hegelund port = netdev_priv(ndev);
799545609fdSSteen Hegelund sparx5_vcap_type_err(port->sparx5, admin, __func__);
800545609fdSSteen Hegelund break;
801545609fdSSteen Hegelund }
802abc4010dSSteen Hegelund
803abc4010dSSteen Hegelund /* Check if there is a match and return the match */
804abc4010dSSteen Hegelund for (idx = 0; idx < kslist->cnt; ++idx)
805abc4010dSSteen Hegelund for (jdx = 0; jdx < keysetlist.cnt; ++jdx)
806abc4010dSSteen Hegelund if (kslist->keysets[idx] == keysets[jdx])
807abc4010dSSteen Hegelund return kslist->keysets[idx];
808abc4010dSSteen Hegelund
809abc4010dSSteen Hegelund pr_err("%s:%d: %s not supported in port key selection\n",
810abc4010dSSteen Hegelund __func__, __LINE__,
811abc4010dSSteen Hegelund sparx5_vcap_keyset_name(ndev, kslist->keysets[0]));
812abc4010dSSteen Hegelund
813abc4010dSSteen Hegelund return -ENOENT;
81446be056eSSteen Hegelund }
81546be056eSSteen Hegelund
sparx5_vcap_ingress_add_default_fields(struct net_device * ndev,struct vcap_admin * admin,struct vcap_rule * rule)816b95d9e2cSSteen Hegelund static void sparx5_vcap_ingress_add_default_fields(struct net_device *ndev,
81746be056eSSteen Hegelund struct vcap_admin *admin,
81846be056eSSteen Hegelund struct vcap_rule *rule)
81946be056eSSteen Hegelund {
82046be056eSSteen Hegelund const struct vcap_field *field;
821b95d9e2cSSteen Hegelund bool is_first;
82246be056eSSteen Hegelund
823b95d9e2cSSteen Hegelund /* Add ingress port mask matching the net device */
82446be056eSSteen Hegelund field = vcap_lookup_keyfield(rule, VCAP_KF_IF_IGR_PORT_MASK);
82546be056eSSteen Hegelund if (field && field->width == SPX5_PORTS)
82646be056eSSteen Hegelund sparx5_vcap_add_wide_port_mask(rule, ndev);
82746be056eSSteen Hegelund else if (field && field->width == BITS_PER_TYPE(u32))
828b95d9e2cSSteen Hegelund sparx5_vcap_add_ingress_range_port_mask(rule, ndev);
82946be056eSSteen Hegelund else
83046be056eSSteen Hegelund pr_err("%s:%d: %s: could not add an ingress port mask for: %s\n",
83146be056eSSteen Hegelund __func__, __LINE__, netdev_name(ndev),
83246be056eSSteen Hegelund sparx5_vcap_keyset_name(ndev, rule->keyset));
833545609fdSSteen Hegelund
834b95d9e2cSSteen Hegelund if (admin->vtype == VCAP_TYPE_IS0)
835b95d9e2cSSteen Hegelund is_first = sparx5_vcap_is0_is_first_chain(rule);
836b95d9e2cSSteen Hegelund else
837b95d9e2cSSteen Hegelund is_first = sparx5_vcap_is2_is_first_chain(rule);
838b95d9e2cSSteen Hegelund
839b95d9e2cSSteen Hegelund /* Add key that selects the first/second lookup */
840b95d9e2cSSteen Hegelund if (is_first)
841b95d9e2cSSteen Hegelund vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
842b95d9e2cSSteen Hegelund VCAP_BIT_1);
843b95d9e2cSSteen Hegelund else
844b95d9e2cSSteen Hegelund vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
845b95d9e2cSSteen Hegelund VCAP_BIT_0);
846b95d9e2cSSteen Hegelund }
847b95d9e2cSSteen Hegelund
sparx5_vcap_es0_add_default_fields(struct net_device * ndev,struct vcap_admin * admin,struct vcap_rule * rule)8483cbe7537SSteen Hegelund static void sparx5_vcap_es0_add_default_fields(struct net_device *ndev,
8493cbe7537SSteen Hegelund struct vcap_admin *admin,
8503cbe7537SSteen Hegelund struct vcap_rule *rule)
8513cbe7537SSteen Hegelund {
8523cbe7537SSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
8533cbe7537SSteen Hegelund
8543cbe7537SSteen Hegelund vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_NO, port->portno, ~0);
855ebf44dedSSteen Hegelund /* Match untagged frames if there was no VLAN key */
856ebf44dedSSteen Hegelund vcap_rule_add_key_u32(rule, VCAP_KF_8021Q_TPID, SPX5_TPID_SEL_UNTAGGED,
857ebf44dedSSteen Hegelund ~0);
8583cbe7537SSteen Hegelund }
8593cbe7537SSteen Hegelund
sparx5_vcap_es2_add_default_fields(struct net_device * ndev,struct vcap_admin * admin,struct vcap_rule * rule)860b95d9e2cSSteen Hegelund static void sparx5_vcap_es2_add_default_fields(struct net_device *ndev,
861b95d9e2cSSteen Hegelund struct vcap_admin *admin,
862b95d9e2cSSteen Hegelund struct vcap_rule *rule)
863b95d9e2cSSteen Hegelund {
864b95d9e2cSSteen Hegelund const struct vcap_field *field;
865b95d9e2cSSteen Hegelund bool is_first;
866b95d9e2cSSteen Hegelund
867b95d9e2cSSteen Hegelund /* Add egress port mask matching the net device */
868b95d9e2cSSteen Hegelund field = vcap_lookup_keyfield(rule, VCAP_KF_IF_EGR_PORT_MASK);
869b95d9e2cSSteen Hegelund if (field)
870b95d9e2cSSteen Hegelund sparx5_vcap_add_egress_range_port_mask(rule, ndev);
871b95d9e2cSSteen Hegelund
872b95d9e2cSSteen Hegelund /* Add key that selects the first/second lookup */
873b95d9e2cSSteen Hegelund is_first = sparx5_vcap_es2_is_first_chain(rule);
874b95d9e2cSSteen Hegelund
875b95d9e2cSSteen Hegelund if (is_first)
876b95d9e2cSSteen Hegelund vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
877b95d9e2cSSteen Hegelund VCAP_BIT_1);
878b95d9e2cSSteen Hegelund else
879b95d9e2cSSteen Hegelund vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
880b95d9e2cSSteen Hegelund VCAP_BIT_0);
881b95d9e2cSSteen Hegelund }
882b95d9e2cSSteen Hegelund
883b95d9e2cSSteen Hegelund /* API callback used for adding default fields to a rule */
sparx5_vcap_add_default_fields(struct net_device * ndev,struct vcap_admin * admin,struct vcap_rule * rule)884b95d9e2cSSteen Hegelund static void sparx5_vcap_add_default_fields(struct net_device *ndev,
885b95d9e2cSSteen Hegelund struct vcap_admin *admin,
886b95d9e2cSSteen Hegelund struct vcap_rule *rule)
887b95d9e2cSSteen Hegelund {
888b95d9e2cSSteen Hegelund struct sparx5_port *port;
889b95d9e2cSSteen Hegelund
89046be056eSSteen Hegelund /* add the lookup bit */
891545609fdSSteen Hegelund switch (admin->vtype) {
892545609fdSSteen Hegelund case VCAP_TYPE_IS0:
893545609fdSSteen Hegelund case VCAP_TYPE_IS2:
894b95d9e2cSSteen Hegelund sparx5_vcap_ingress_add_default_fields(ndev, admin, rule);
895b95d9e2cSSteen Hegelund break;
8963cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
8973cbe7537SSteen Hegelund sparx5_vcap_es0_add_default_fields(ndev, admin, rule);
8983cbe7537SSteen Hegelund break;
899b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
900b95d9e2cSSteen Hegelund sparx5_vcap_es2_add_default_fields(ndev, admin, rule);
901545609fdSSteen Hegelund break;
902545609fdSSteen Hegelund default:
903545609fdSSteen Hegelund port = netdev_priv(ndev);
904545609fdSSteen Hegelund sparx5_vcap_type_err(port->sparx5, admin, __func__);
905545609fdSSteen Hegelund break;
906545609fdSSteen Hegelund }
90746be056eSSteen Hegelund }
90846be056eSSteen Hegelund
90946be056eSSteen Hegelund /* API callback used for erasing the vcap cache area (not the register area) */
sparx5_vcap_cache_erase(struct vcap_admin * admin)91046be056eSSteen Hegelund static void sparx5_vcap_cache_erase(struct vcap_admin *admin)
91146be056eSSteen Hegelund {
91246be056eSSteen Hegelund memset(admin->cache.keystream, 0, STREAMSIZE);
91346be056eSSteen Hegelund memset(admin->cache.maskstream, 0, STREAMSIZE);
91446be056eSSteen Hegelund memset(admin->cache.actionstream, 0, STREAMSIZE);
91546be056eSSteen Hegelund memset(&admin->cache.counter, 0, sizeof(admin->cache.counter));
91646be056eSSteen Hegelund }
91746be056eSSteen Hegelund
sparx5_vcap_is0_cache_write(struct sparx5 * sparx5,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)918b95d9e2cSSteen Hegelund static void sparx5_vcap_is0_cache_write(struct sparx5 *sparx5,
91946be056eSSteen Hegelund struct vcap_admin *admin,
92046be056eSSteen Hegelund enum vcap_selection sel,
92146be056eSSteen Hegelund u32 start,
92246be056eSSteen Hegelund u32 count)
92346be056eSSteen Hegelund {
92446be056eSSteen Hegelund u32 *keystr, *mskstr, *actstr;
92546be056eSSteen Hegelund int idx;
92646be056eSSteen Hegelund
92746be056eSSteen Hegelund keystr = &admin->cache.keystream[start];
92846be056eSSteen Hegelund mskstr = &admin->cache.maskstream[start];
92946be056eSSteen Hegelund actstr = &admin->cache.actionstream[start];
930b95d9e2cSSteen Hegelund
931b95d9e2cSSteen Hegelund switch (sel) {
932b95d9e2cSSteen Hegelund case VCAP_SEL_ENTRY:
933b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx) {
934b95d9e2cSSteen Hegelund /* Avoid 'match-off' by setting value & mask */
935b95d9e2cSSteen Hegelund spx5_wr(keystr[idx] & mskstr[idx], sparx5,
936b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_ENTRY_DAT(idx));
937b95d9e2cSSteen Hegelund spx5_wr(~mskstr[idx], sparx5,
938b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_MASK_DAT(idx));
939b95d9e2cSSteen Hegelund }
940b95d9e2cSSteen Hegelund break;
941b95d9e2cSSteen Hegelund case VCAP_SEL_ACTION:
942b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx)
943b95d9e2cSSteen Hegelund spx5_wr(actstr[idx], sparx5,
944b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_ACTION_DAT(idx));
945b95d9e2cSSteen Hegelund break;
946b95d9e2cSSteen Hegelund case VCAP_SEL_ALL:
947b95d9e2cSSteen Hegelund pr_err("%s:%d: cannot write all streams at once\n",
948b95d9e2cSSteen Hegelund __func__, __LINE__);
949b95d9e2cSSteen Hegelund break;
950b95d9e2cSSteen Hegelund default:
951b95d9e2cSSteen Hegelund break;
952b95d9e2cSSteen Hegelund }
953b95d9e2cSSteen Hegelund
954b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_COUNTER)
955b95d9e2cSSteen Hegelund spx5_wr(admin->cache.counter, sparx5,
956b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_CNT_DAT(0));
957b95d9e2cSSteen Hegelund }
958b95d9e2cSSteen Hegelund
sparx5_vcap_is2_cache_write(struct sparx5 * sparx5,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)959b95d9e2cSSteen Hegelund static void sparx5_vcap_is2_cache_write(struct sparx5 *sparx5,
960b95d9e2cSSteen Hegelund struct vcap_admin *admin,
961b95d9e2cSSteen Hegelund enum vcap_selection sel,
962b95d9e2cSSteen Hegelund u32 start,
963b95d9e2cSSteen Hegelund u32 count)
964b95d9e2cSSteen Hegelund {
965b95d9e2cSSteen Hegelund u32 *keystr, *mskstr, *actstr;
966b95d9e2cSSteen Hegelund int idx;
967b95d9e2cSSteen Hegelund
968b95d9e2cSSteen Hegelund keystr = &admin->cache.keystream[start];
969b95d9e2cSSteen Hegelund mskstr = &admin->cache.maskstream[start];
970b95d9e2cSSteen Hegelund actstr = &admin->cache.actionstream[start];
971b95d9e2cSSteen Hegelund
97246be056eSSteen Hegelund switch (sel) {
97346be056eSSteen Hegelund case VCAP_SEL_ENTRY:
97446be056eSSteen Hegelund for (idx = 0; idx < count; ++idx) {
97546be056eSSteen Hegelund /* Avoid 'match-off' by setting value & mask */
97646be056eSSteen Hegelund spx5_wr(keystr[idx] & mskstr[idx], sparx5,
97746be056eSSteen Hegelund VCAP_SUPER_VCAP_ENTRY_DAT(idx));
97846be056eSSteen Hegelund spx5_wr(~mskstr[idx], sparx5,
97946be056eSSteen Hegelund VCAP_SUPER_VCAP_MASK_DAT(idx));
98046be056eSSteen Hegelund }
98146be056eSSteen Hegelund break;
98246be056eSSteen Hegelund case VCAP_SEL_ACTION:
98346be056eSSteen Hegelund for (idx = 0; idx < count; ++idx)
98446be056eSSteen Hegelund spx5_wr(actstr[idx], sparx5,
98546be056eSSteen Hegelund VCAP_SUPER_VCAP_ACTION_DAT(idx));
98646be056eSSteen Hegelund break;
98746be056eSSteen Hegelund case VCAP_SEL_ALL:
98846be056eSSteen Hegelund pr_err("%s:%d: cannot write all streams at once\n",
98946be056eSSteen Hegelund __func__, __LINE__);
99046be056eSSteen Hegelund break;
99146be056eSSteen Hegelund default:
99246be056eSSteen Hegelund break;
99346be056eSSteen Hegelund }
994f13230a4SSteen Hegelund if (sel & VCAP_SEL_COUNTER) {
995f13230a4SSteen Hegelund start = start & 0xfff; /* counter limit */
996f13230a4SSteen Hegelund if (admin->vinst == 0)
997f13230a4SSteen Hegelund spx5_wr(admin->cache.counter, sparx5,
998f13230a4SSteen Hegelund ANA_ACL_CNT_A(start));
999f13230a4SSteen Hegelund else
1000f13230a4SSteen Hegelund spx5_wr(admin->cache.counter, sparx5,
1001f13230a4SSteen Hegelund ANA_ACL_CNT_B(start));
1002f13230a4SSteen Hegelund spx5_wr(admin->cache.sticky, sparx5,
1003f13230a4SSteen Hegelund VCAP_SUPER_VCAP_CNT_DAT(0));
1004b95d9e2cSSteen Hegelund }
1005b95d9e2cSSteen Hegelund }
1006b95d9e2cSSteen Hegelund
10073cbe7537SSteen Hegelund /* Use ESDX counters located in the XQS */
sparx5_es0_write_esdx_counter(struct sparx5 * sparx5,struct vcap_admin * admin,u32 id)10083cbe7537SSteen Hegelund static void sparx5_es0_write_esdx_counter(struct sparx5 *sparx5,
10093cbe7537SSteen Hegelund struct vcap_admin *admin, u32 id)
10103cbe7537SSteen Hegelund {
10113cbe7537SSteen Hegelund mutex_lock(&sparx5->queue_stats_lock);
10123cbe7537SSteen Hegelund spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(id), sparx5, XQS_STAT_CFG);
10133cbe7537SSteen Hegelund spx5_wr(admin->cache.counter, sparx5,
10143cbe7537SSteen Hegelund XQS_CNT(SPARX5_STAT_ESDX_GRN_PKTS));
10153cbe7537SSteen Hegelund spx5_wr(0, sparx5, XQS_CNT(SPARX5_STAT_ESDX_YEL_PKTS));
10163cbe7537SSteen Hegelund mutex_unlock(&sparx5->queue_stats_lock);
10173cbe7537SSteen Hegelund }
10183cbe7537SSteen Hegelund
sparx5_vcap_es0_cache_write(struct sparx5 * sparx5,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)10193cbe7537SSteen Hegelund static void sparx5_vcap_es0_cache_write(struct sparx5 *sparx5,
10203cbe7537SSteen Hegelund struct vcap_admin *admin,
10213cbe7537SSteen Hegelund enum vcap_selection sel,
10223cbe7537SSteen Hegelund u32 start,
10233cbe7537SSteen Hegelund u32 count)
10243cbe7537SSteen Hegelund {
10253cbe7537SSteen Hegelund u32 *keystr, *mskstr, *actstr;
10263cbe7537SSteen Hegelund int idx;
10273cbe7537SSteen Hegelund
10283cbe7537SSteen Hegelund keystr = &admin->cache.keystream[start];
10293cbe7537SSteen Hegelund mskstr = &admin->cache.maskstream[start];
10303cbe7537SSteen Hegelund actstr = &admin->cache.actionstream[start];
10313cbe7537SSteen Hegelund
10323cbe7537SSteen Hegelund switch (sel) {
10333cbe7537SSteen Hegelund case VCAP_SEL_ENTRY:
10343cbe7537SSteen Hegelund for (idx = 0; idx < count; ++idx) {
10353cbe7537SSteen Hegelund /* Avoid 'match-off' by setting value & mask */
10363cbe7537SSteen Hegelund spx5_wr(keystr[idx] & mskstr[idx], sparx5,
10373cbe7537SSteen Hegelund VCAP_ES0_VCAP_ENTRY_DAT(idx));
10383cbe7537SSteen Hegelund spx5_wr(~mskstr[idx], sparx5,
10393cbe7537SSteen Hegelund VCAP_ES0_VCAP_MASK_DAT(idx));
10403cbe7537SSteen Hegelund }
10413cbe7537SSteen Hegelund break;
10423cbe7537SSteen Hegelund case VCAP_SEL_ACTION:
10433cbe7537SSteen Hegelund for (idx = 0; idx < count; ++idx)
10443cbe7537SSteen Hegelund spx5_wr(actstr[idx], sparx5,
10453cbe7537SSteen Hegelund VCAP_ES0_VCAP_ACTION_DAT(idx));
10463cbe7537SSteen Hegelund break;
10473cbe7537SSteen Hegelund case VCAP_SEL_ALL:
10483cbe7537SSteen Hegelund pr_err("%s:%d: cannot write all streams at once\n",
10493cbe7537SSteen Hegelund __func__, __LINE__);
10503cbe7537SSteen Hegelund break;
10513cbe7537SSteen Hegelund default:
10523cbe7537SSteen Hegelund break;
10533cbe7537SSteen Hegelund }
10543cbe7537SSteen Hegelund if (sel & VCAP_SEL_COUNTER) {
10553cbe7537SSteen Hegelund spx5_wr(admin->cache.counter, sparx5, VCAP_ES0_VCAP_CNT_DAT(0));
10563cbe7537SSteen Hegelund sparx5_es0_write_esdx_counter(sparx5, admin, start);
10573cbe7537SSteen Hegelund }
10583cbe7537SSteen Hegelund }
10593cbe7537SSteen Hegelund
sparx5_vcap_es2_cache_write(struct sparx5 * sparx5,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)1060b95d9e2cSSteen Hegelund static void sparx5_vcap_es2_cache_write(struct sparx5 *sparx5,
1061b95d9e2cSSteen Hegelund struct vcap_admin *admin,
1062b95d9e2cSSteen Hegelund enum vcap_selection sel,
1063b95d9e2cSSteen Hegelund u32 start,
1064b95d9e2cSSteen Hegelund u32 count)
1065b95d9e2cSSteen Hegelund {
1066b95d9e2cSSteen Hegelund u32 *keystr, *mskstr, *actstr;
1067b95d9e2cSSteen Hegelund int idx;
1068b95d9e2cSSteen Hegelund
1069b95d9e2cSSteen Hegelund keystr = &admin->cache.keystream[start];
1070b95d9e2cSSteen Hegelund mskstr = &admin->cache.maskstream[start];
1071b95d9e2cSSteen Hegelund actstr = &admin->cache.actionstream[start];
1072b95d9e2cSSteen Hegelund
1073b95d9e2cSSteen Hegelund switch (sel) {
1074b95d9e2cSSteen Hegelund case VCAP_SEL_ENTRY:
1075b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx) {
1076b95d9e2cSSteen Hegelund /* Avoid 'match-off' by setting value & mask */
1077b95d9e2cSSteen Hegelund spx5_wr(keystr[idx] & mskstr[idx], sparx5,
1078b95d9e2cSSteen Hegelund VCAP_ES2_VCAP_ENTRY_DAT(idx));
1079b95d9e2cSSteen Hegelund spx5_wr(~mskstr[idx], sparx5,
1080b95d9e2cSSteen Hegelund VCAP_ES2_VCAP_MASK_DAT(idx));
1081b95d9e2cSSteen Hegelund }
1082b95d9e2cSSteen Hegelund break;
1083b95d9e2cSSteen Hegelund case VCAP_SEL_ACTION:
1084b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx)
1085b95d9e2cSSteen Hegelund spx5_wr(actstr[idx], sparx5,
1086b95d9e2cSSteen Hegelund VCAP_ES2_VCAP_ACTION_DAT(idx));
1087b95d9e2cSSteen Hegelund break;
1088b95d9e2cSSteen Hegelund case VCAP_SEL_ALL:
1089b95d9e2cSSteen Hegelund pr_err("%s:%d: cannot write all streams at once\n",
1090b95d9e2cSSteen Hegelund __func__, __LINE__);
1091b95d9e2cSSteen Hegelund break;
1092b95d9e2cSSteen Hegelund default:
1093b95d9e2cSSteen Hegelund break;
1094b95d9e2cSSteen Hegelund }
1095b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_COUNTER) {
1096b95d9e2cSSteen Hegelund start = start & 0x7ff; /* counter limit */
1097b95d9e2cSSteen Hegelund spx5_wr(admin->cache.counter, sparx5, EACL_ES2_CNT(start));
1098b95d9e2cSSteen Hegelund spx5_wr(admin->cache.sticky, sparx5, VCAP_ES2_VCAP_CNT_DAT(0));
1099b95d9e2cSSteen Hegelund }
1100b95d9e2cSSteen Hegelund }
1101b95d9e2cSSteen Hegelund
1102b95d9e2cSSteen Hegelund /* API callback used for writing to the VCAP cache */
sparx5_vcap_cache_write(struct net_device * ndev,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)1103b95d9e2cSSteen Hegelund static void sparx5_vcap_cache_write(struct net_device *ndev,
1104b95d9e2cSSteen Hegelund struct vcap_admin *admin,
1105b95d9e2cSSteen Hegelund enum vcap_selection sel,
1106b95d9e2cSSteen Hegelund u32 start,
1107b95d9e2cSSteen Hegelund u32 count)
1108b95d9e2cSSteen Hegelund {
1109b95d9e2cSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
1110b95d9e2cSSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
1111b95d9e2cSSteen Hegelund
1112b95d9e2cSSteen Hegelund switch (admin->vtype) {
1113b95d9e2cSSteen Hegelund case VCAP_TYPE_IS0:
1114b95d9e2cSSteen Hegelund sparx5_vcap_is0_cache_write(sparx5, admin, sel, start, count);
1115b95d9e2cSSteen Hegelund break;
1116b95d9e2cSSteen Hegelund case VCAP_TYPE_IS2:
1117b95d9e2cSSteen Hegelund sparx5_vcap_is2_cache_write(sparx5, admin, sel, start, count);
1118b95d9e2cSSteen Hegelund break;
11193cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
11203cbe7537SSteen Hegelund sparx5_vcap_es0_cache_write(sparx5, admin, sel, start, count);
11213cbe7537SSteen Hegelund break;
1122b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
1123b95d9e2cSSteen Hegelund sparx5_vcap_es2_cache_write(sparx5, admin, sel, start, count);
1124545609fdSSteen Hegelund break;
1125545609fdSSteen Hegelund default:
1126545609fdSSteen Hegelund sparx5_vcap_type_err(sparx5, admin, __func__);
1127545609fdSSteen Hegelund break;
1128545609fdSSteen Hegelund }
1129f13230a4SSteen Hegelund }
1130b95d9e2cSSteen Hegelund
sparx5_vcap_is0_cache_read(struct sparx5 * sparx5,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)1131b95d9e2cSSteen Hegelund static void sparx5_vcap_is0_cache_read(struct sparx5 *sparx5,
1132b95d9e2cSSteen Hegelund struct vcap_admin *admin,
1133b95d9e2cSSteen Hegelund enum vcap_selection sel,
1134b95d9e2cSSteen Hegelund u32 start,
1135b95d9e2cSSteen Hegelund u32 count)
1136b95d9e2cSSteen Hegelund {
1137b95d9e2cSSteen Hegelund u32 *keystr, *mskstr, *actstr;
1138b95d9e2cSSteen Hegelund int idx;
1139b95d9e2cSSteen Hegelund
1140b95d9e2cSSteen Hegelund keystr = &admin->cache.keystream[start];
1141b95d9e2cSSteen Hegelund mskstr = &admin->cache.maskstream[start];
1142b95d9e2cSSteen Hegelund actstr = &admin->cache.actionstream[start];
1143b95d9e2cSSteen Hegelund
1144b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_ENTRY) {
1145b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx) {
1146b95d9e2cSSteen Hegelund keystr[idx] = spx5_rd(sparx5,
1147b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_ENTRY_DAT(idx));
1148b95d9e2cSSteen Hegelund mskstr[idx] = ~spx5_rd(sparx5,
1149b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_MASK_DAT(idx));
1150b95d9e2cSSteen Hegelund }
1151b95d9e2cSSteen Hegelund }
1152b95d9e2cSSteen Hegelund
1153b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_ACTION)
1154b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx)
1155b95d9e2cSSteen Hegelund actstr[idx] = spx5_rd(sparx5,
1156b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_ACTION_DAT(idx));
1157b95d9e2cSSteen Hegelund
1158b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_COUNTER) {
1159b95d9e2cSSteen Hegelund admin->cache.counter =
1160b95d9e2cSSteen Hegelund spx5_rd(sparx5, VCAP_SUPER_VCAP_CNT_DAT(0));
1161b95d9e2cSSteen Hegelund admin->cache.sticky =
1162b95d9e2cSSteen Hegelund spx5_rd(sparx5, VCAP_SUPER_VCAP_CNT_DAT(0));
1163b95d9e2cSSteen Hegelund }
1164b95d9e2cSSteen Hegelund }
1165b95d9e2cSSteen Hegelund
sparx5_vcap_is2_cache_read(struct sparx5 * sparx5,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)1166b95d9e2cSSteen Hegelund static void sparx5_vcap_is2_cache_read(struct sparx5 *sparx5,
1167b95d9e2cSSteen Hegelund struct vcap_admin *admin,
1168b95d9e2cSSteen Hegelund enum vcap_selection sel,
1169b95d9e2cSSteen Hegelund u32 start,
1170b95d9e2cSSteen Hegelund u32 count)
1171b95d9e2cSSteen Hegelund {
1172b95d9e2cSSteen Hegelund u32 *keystr, *mskstr, *actstr;
1173b95d9e2cSSteen Hegelund int idx;
1174b95d9e2cSSteen Hegelund
1175b95d9e2cSSteen Hegelund keystr = &admin->cache.keystream[start];
1176b95d9e2cSSteen Hegelund mskstr = &admin->cache.maskstream[start];
1177b95d9e2cSSteen Hegelund actstr = &admin->cache.actionstream[start];
1178b95d9e2cSSteen Hegelund
1179b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_ENTRY) {
1180b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx) {
1181b95d9e2cSSteen Hegelund keystr[idx] = spx5_rd(sparx5,
1182b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_ENTRY_DAT(idx));
1183b95d9e2cSSteen Hegelund mskstr[idx] = ~spx5_rd(sparx5,
1184b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_MASK_DAT(idx));
1185b95d9e2cSSteen Hegelund }
1186b95d9e2cSSteen Hegelund }
1187b95d9e2cSSteen Hegelund
1188b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_ACTION)
1189b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx)
1190b95d9e2cSSteen Hegelund actstr[idx] = spx5_rd(sparx5,
1191b95d9e2cSSteen Hegelund VCAP_SUPER_VCAP_ACTION_DAT(idx));
1192b95d9e2cSSteen Hegelund
1193b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_COUNTER) {
1194b95d9e2cSSteen Hegelund start = start & 0xfff; /* counter limit */
1195b95d9e2cSSteen Hegelund if (admin->vinst == 0)
1196b95d9e2cSSteen Hegelund admin->cache.counter =
1197b95d9e2cSSteen Hegelund spx5_rd(sparx5, ANA_ACL_CNT_A(start));
1198b95d9e2cSSteen Hegelund else
1199b95d9e2cSSteen Hegelund admin->cache.counter =
1200b95d9e2cSSteen Hegelund spx5_rd(sparx5, ANA_ACL_CNT_B(start));
1201b95d9e2cSSteen Hegelund admin->cache.sticky =
1202b95d9e2cSSteen Hegelund spx5_rd(sparx5, VCAP_SUPER_VCAP_CNT_DAT(0));
1203b95d9e2cSSteen Hegelund }
1204b95d9e2cSSteen Hegelund }
1205b95d9e2cSSteen Hegelund
12063cbe7537SSteen Hegelund /* Use ESDX counters located in the XQS */
sparx5_es0_read_esdx_counter(struct sparx5 * sparx5,struct vcap_admin * admin,u32 id)12073cbe7537SSteen Hegelund static void sparx5_es0_read_esdx_counter(struct sparx5 *sparx5,
12083cbe7537SSteen Hegelund struct vcap_admin *admin, u32 id)
12093cbe7537SSteen Hegelund {
12103cbe7537SSteen Hegelund u32 counter;
12113cbe7537SSteen Hegelund
12123cbe7537SSteen Hegelund mutex_lock(&sparx5->queue_stats_lock);
12133cbe7537SSteen Hegelund spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(id), sparx5, XQS_STAT_CFG);
12143cbe7537SSteen Hegelund counter = spx5_rd(sparx5, XQS_CNT(SPARX5_STAT_ESDX_GRN_PKTS)) +
12153cbe7537SSteen Hegelund spx5_rd(sparx5, XQS_CNT(SPARX5_STAT_ESDX_YEL_PKTS));
12163cbe7537SSteen Hegelund mutex_unlock(&sparx5->queue_stats_lock);
12173cbe7537SSteen Hegelund if (counter)
12183cbe7537SSteen Hegelund admin->cache.counter = counter;
12193cbe7537SSteen Hegelund }
12203cbe7537SSteen Hegelund
sparx5_vcap_es0_cache_read(struct sparx5 * sparx5,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)12213cbe7537SSteen Hegelund static void sparx5_vcap_es0_cache_read(struct sparx5 *sparx5,
12223cbe7537SSteen Hegelund struct vcap_admin *admin,
12233cbe7537SSteen Hegelund enum vcap_selection sel,
12243cbe7537SSteen Hegelund u32 start,
12253cbe7537SSteen Hegelund u32 count)
12263cbe7537SSteen Hegelund {
12273cbe7537SSteen Hegelund u32 *keystr, *mskstr, *actstr;
12283cbe7537SSteen Hegelund int idx;
12293cbe7537SSteen Hegelund
12303cbe7537SSteen Hegelund keystr = &admin->cache.keystream[start];
12313cbe7537SSteen Hegelund mskstr = &admin->cache.maskstream[start];
12323cbe7537SSteen Hegelund actstr = &admin->cache.actionstream[start];
12333cbe7537SSteen Hegelund
12343cbe7537SSteen Hegelund if (sel & VCAP_SEL_ENTRY) {
12353cbe7537SSteen Hegelund for (idx = 0; idx < count; ++idx) {
12363cbe7537SSteen Hegelund keystr[idx] =
12373cbe7537SSteen Hegelund spx5_rd(sparx5, VCAP_ES0_VCAP_ENTRY_DAT(idx));
12383cbe7537SSteen Hegelund mskstr[idx] =
12393cbe7537SSteen Hegelund ~spx5_rd(sparx5, VCAP_ES0_VCAP_MASK_DAT(idx));
12403cbe7537SSteen Hegelund }
12413cbe7537SSteen Hegelund }
12423cbe7537SSteen Hegelund
12433cbe7537SSteen Hegelund if (sel & VCAP_SEL_ACTION)
12443cbe7537SSteen Hegelund for (idx = 0; idx < count; ++idx)
12453cbe7537SSteen Hegelund actstr[idx] =
12463cbe7537SSteen Hegelund spx5_rd(sparx5, VCAP_ES0_VCAP_ACTION_DAT(idx));
12473cbe7537SSteen Hegelund
12483cbe7537SSteen Hegelund if (sel & VCAP_SEL_COUNTER) {
12493cbe7537SSteen Hegelund admin->cache.counter =
12503cbe7537SSteen Hegelund spx5_rd(sparx5, VCAP_ES0_VCAP_CNT_DAT(0));
12513cbe7537SSteen Hegelund admin->cache.sticky = admin->cache.counter;
12523cbe7537SSteen Hegelund sparx5_es0_read_esdx_counter(sparx5, admin, start);
12533cbe7537SSteen Hegelund }
12543cbe7537SSteen Hegelund }
12553cbe7537SSteen Hegelund
sparx5_vcap_es2_cache_read(struct sparx5 * sparx5,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)1256b95d9e2cSSteen Hegelund static void sparx5_vcap_es2_cache_read(struct sparx5 *sparx5,
1257b95d9e2cSSteen Hegelund struct vcap_admin *admin,
1258b95d9e2cSSteen Hegelund enum vcap_selection sel,
1259b95d9e2cSSteen Hegelund u32 start,
1260b95d9e2cSSteen Hegelund u32 count)
1261b95d9e2cSSteen Hegelund {
1262b95d9e2cSSteen Hegelund u32 *keystr, *mskstr, *actstr;
1263b95d9e2cSSteen Hegelund int idx;
1264b95d9e2cSSteen Hegelund
1265b95d9e2cSSteen Hegelund keystr = &admin->cache.keystream[start];
1266b95d9e2cSSteen Hegelund mskstr = &admin->cache.maskstream[start];
1267b95d9e2cSSteen Hegelund actstr = &admin->cache.actionstream[start];
1268b95d9e2cSSteen Hegelund
1269b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_ENTRY) {
1270b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx) {
1271b95d9e2cSSteen Hegelund keystr[idx] =
1272b95d9e2cSSteen Hegelund spx5_rd(sparx5, VCAP_ES2_VCAP_ENTRY_DAT(idx));
1273b95d9e2cSSteen Hegelund mskstr[idx] =
1274b95d9e2cSSteen Hegelund ~spx5_rd(sparx5, VCAP_ES2_VCAP_MASK_DAT(idx));
1275b95d9e2cSSteen Hegelund }
1276b95d9e2cSSteen Hegelund }
1277b95d9e2cSSteen Hegelund
1278b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_ACTION)
1279b95d9e2cSSteen Hegelund for (idx = 0; idx < count; ++idx)
1280b95d9e2cSSteen Hegelund actstr[idx] =
1281b95d9e2cSSteen Hegelund spx5_rd(sparx5, VCAP_ES2_VCAP_ACTION_DAT(idx));
1282b95d9e2cSSteen Hegelund
1283b95d9e2cSSteen Hegelund if (sel & VCAP_SEL_COUNTER) {
1284b95d9e2cSSteen Hegelund start = start & 0x7ff; /* counter limit */
1285b95d9e2cSSteen Hegelund admin->cache.counter =
1286b95d9e2cSSteen Hegelund spx5_rd(sparx5, EACL_ES2_CNT(start));
1287b95d9e2cSSteen Hegelund admin->cache.sticky =
1288b95d9e2cSSteen Hegelund spx5_rd(sparx5, VCAP_ES2_VCAP_CNT_DAT(0));
1289b95d9e2cSSteen Hegelund }
129046be056eSSteen Hegelund }
129146be056eSSteen Hegelund
129246be056eSSteen Hegelund /* API callback used for reading from the VCAP into the VCAP cache */
sparx5_vcap_cache_read(struct net_device * ndev,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)129346be056eSSteen Hegelund static void sparx5_vcap_cache_read(struct net_device *ndev,
129446be056eSSteen Hegelund struct vcap_admin *admin,
1295f13230a4SSteen Hegelund enum vcap_selection sel,
1296f13230a4SSteen Hegelund u32 start,
129746be056eSSteen Hegelund u32 count)
129846be056eSSteen Hegelund {
1299f13230a4SSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
1300f13230a4SSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
1301f13230a4SSteen Hegelund
1302545609fdSSteen Hegelund switch (admin->vtype) {
1303545609fdSSteen Hegelund case VCAP_TYPE_IS0:
1304b95d9e2cSSteen Hegelund sparx5_vcap_is0_cache_read(sparx5, admin, sel, start, count);
1305545609fdSSteen Hegelund break;
1306545609fdSSteen Hegelund case VCAP_TYPE_IS2:
1307b95d9e2cSSteen Hegelund sparx5_vcap_is2_cache_read(sparx5, admin, sel, start, count);
1308b95d9e2cSSteen Hegelund break;
13093cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
13103cbe7537SSteen Hegelund sparx5_vcap_es0_cache_read(sparx5, admin, sel, start, count);
13113cbe7537SSteen Hegelund break;
1312b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
1313b95d9e2cSSteen Hegelund sparx5_vcap_es2_cache_read(sparx5, admin, sel, start, count);
1314545609fdSSteen Hegelund break;
1315545609fdSSteen Hegelund default:
1316545609fdSSteen Hegelund sparx5_vcap_type_err(sparx5, admin, __func__);
1317545609fdSSteen Hegelund break;
1318545609fdSSteen Hegelund }
1319f13230a4SSteen Hegelund }
132046be056eSSteen Hegelund
132146be056eSSteen Hegelund /* API callback used for initializing a VCAP address range */
sparx5_vcap_range_init(struct net_device * ndev,struct vcap_admin * admin,u32 addr,u32 count)132246be056eSSteen Hegelund static void sparx5_vcap_range_init(struct net_device *ndev,
132346be056eSSteen Hegelund struct vcap_admin *admin, u32 addr,
132446be056eSSteen Hegelund u32 count)
132546be056eSSteen Hegelund {
132646be056eSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
132746be056eSSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
132846be056eSSteen Hegelund
132946be056eSSteen Hegelund _sparx5_vcap_range_init(sparx5, admin, addr, count);
133046be056eSSteen Hegelund }
133146be056eSSteen Hegelund
sparx5_vcap_super_update(struct sparx5 * sparx5,enum vcap_command cmd,enum vcap_selection sel,u32 addr)1332b95d9e2cSSteen Hegelund static void sparx5_vcap_super_update(struct sparx5 *sparx5,
1333b95d9e2cSSteen Hegelund enum vcap_command cmd,
133446be056eSSteen Hegelund enum vcap_selection sel, u32 addr)
133546be056eSSteen Hegelund {
1336b95d9e2cSSteen Hegelund bool clear = (cmd == VCAP_CMD_INITIALIZE);
133746be056eSSteen Hegelund
133846be056eSSteen Hegelund spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(0) |
133946be056eSSteen Hegelund VCAP_SUPER_CFG_MV_SIZE_SET(0), sparx5, VCAP_SUPER_CFG);
134046be056eSSteen Hegelund spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(cmd) |
134146be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) |
134246be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) |
134346be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) |
134446be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr) |
134546be056eSSteen Hegelund VCAP_SUPER_CTRL_CLEAR_CACHE_SET(clear) |
134646be056eSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true),
134746be056eSSteen Hegelund sparx5, VCAP_SUPER_CTRL);
134846be056eSSteen Hegelund sparx5_vcap_wait_super_update(sparx5);
134946be056eSSteen Hegelund }
135046be056eSSteen Hegelund
sparx5_vcap_es0_update(struct sparx5 * sparx5,enum vcap_command cmd,enum vcap_selection sel,u32 addr)13513cbe7537SSteen Hegelund static void sparx5_vcap_es0_update(struct sparx5 *sparx5,
13523cbe7537SSteen Hegelund enum vcap_command cmd,
13533cbe7537SSteen Hegelund enum vcap_selection sel, u32 addr)
13543cbe7537SSteen Hegelund {
13553cbe7537SSteen Hegelund bool clear = (cmd == VCAP_CMD_INITIALIZE);
13563cbe7537SSteen Hegelund
13573cbe7537SSteen Hegelund spx5_wr(VCAP_ES0_CFG_MV_NUM_POS_SET(0) |
13583cbe7537SSteen Hegelund VCAP_ES0_CFG_MV_SIZE_SET(0), sparx5, VCAP_ES0_CFG);
13593cbe7537SSteen Hegelund spx5_wr(VCAP_ES0_CTRL_UPDATE_CMD_SET(cmd) |
13603cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) |
13613cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) |
13623cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) |
13633cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_ADDR_SET(addr) |
13643cbe7537SSteen Hegelund VCAP_ES0_CTRL_CLEAR_CACHE_SET(clear) |
13653cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_SHOT_SET(true),
13663cbe7537SSteen Hegelund sparx5, VCAP_ES0_CTRL);
13673cbe7537SSteen Hegelund sparx5_vcap_wait_es0_update(sparx5);
13683cbe7537SSteen Hegelund }
13693cbe7537SSteen Hegelund
sparx5_vcap_es2_update(struct sparx5 * sparx5,enum vcap_command cmd,enum vcap_selection sel,u32 addr)1370b95d9e2cSSteen Hegelund static void sparx5_vcap_es2_update(struct sparx5 *sparx5,
1371b95d9e2cSSteen Hegelund enum vcap_command cmd,
1372b95d9e2cSSteen Hegelund enum vcap_selection sel, u32 addr)
1373b95d9e2cSSteen Hegelund {
1374b95d9e2cSSteen Hegelund bool clear = (cmd == VCAP_CMD_INITIALIZE);
1375b95d9e2cSSteen Hegelund
1376b95d9e2cSSteen Hegelund spx5_wr(VCAP_ES2_CFG_MV_NUM_POS_SET(0) |
1377b95d9e2cSSteen Hegelund VCAP_ES2_CFG_MV_SIZE_SET(0), sparx5, VCAP_ES2_CFG);
1378b95d9e2cSSteen Hegelund spx5_wr(VCAP_ES2_CTRL_UPDATE_CMD_SET(cmd) |
1379b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) |
1380b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) |
1381b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) |
1382b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_ADDR_SET(addr) |
1383b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_CLEAR_CACHE_SET(clear) |
1384b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_SHOT_SET(true),
1385b95d9e2cSSteen Hegelund sparx5, VCAP_ES2_CTRL);
1386b95d9e2cSSteen Hegelund sparx5_vcap_wait_es2_update(sparx5);
1387b95d9e2cSSteen Hegelund }
1388b95d9e2cSSteen Hegelund
1389b95d9e2cSSteen Hegelund /* API callback used for updating the VCAP cache */
sparx5_vcap_update(struct net_device * ndev,struct vcap_admin * admin,enum vcap_command cmd,enum vcap_selection sel,u32 addr)1390b95d9e2cSSteen Hegelund static void sparx5_vcap_update(struct net_device *ndev,
1391b95d9e2cSSteen Hegelund struct vcap_admin *admin, enum vcap_command cmd,
1392b95d9e2cSSteen Hegelund enum vcap_selection sel, u32 addr)
1393b95d9e2cSSteen Hegelund {
1394b95d9e2cSSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
1395b95d9e2cSSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
1396b95d9e2cSSteen Hegelund
1397b95d9e2cSSteen Hegelund switch (admin->vtype) {
1398b95d9e2cSSteen Hegelund case VCAP_TYPE_IS0:
1399b95d9e2cSSteen Hegelund case VCAP_TYPE_IS2:
1400b95d9e2cSSteen Hegelund sparx5_vcap_super_update(sparx5, cmd, sel, addr);
1401b95d9e2cSSteen Hegelund break;
14023cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
14033cbe7537SSteen Hegelund sparx5_vcap_es0_update(sparx5, cmd, sel, addr);
14043cbe7537SSteen Hegelund break;
1405b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
1406b95d9e2cSSteen Hegelund sparx5_vcap_es2_update(sparx5, cmd, sel, addr);
1407b95d9e2cSSteen Hegelund break;
1408b95d9e2cSSteen Hegelund default:
1409b95d9e2cSSteen Hegelund sparx5_vcap_type_err(sparx5, admin, __func__);
1410b95d9e2cSSteen Hegelund break;
1411b95d9e2cSSteen Hegelund }
1412b95d9e2cSSteen Hegelund }
1413b95d9e2cSSteen Hegelund
sparx5_vcap_super_move(struct sparx5 * sparx5,u32 addr,enum vcap_command cmd,u16 mv_num_pos,u16 mv_size)1414b95d9e2cSSteen Hegelund static void sparx5_vcap_super_move(struct sparx5 *sparx5,
1415b95d9e2cSSteen Hegelund u32 addr,
1416b95d9e2cSSteen Hegelund enum vcap_command cmd,
1417b95d9e2cSSteen Hegelund u16 mv_num_pos,
1418b95d9e2cSSteen Hegelund u16 mv_size)
1419b95d9e2cSSteen Hegelund {
1420b95d9e2cSSteen Hegelund spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(mv_num_pos) |
1421b95d9e2cSSteen Hegelund VCAP_SUPER_CFG_MV_SIZE_SET(mv_size),
1422b95d9e2cSSteen Hegelund sparx5, VCAP_SUPER_CFG);
1423b95d9e2cSSteen Hegelund spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(cmd) |
1424b95d9e2cSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET(0) |
1425b95d9e2cSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET(0) |
1426b95d9e2cSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET(0) |
1427b95d9e2cSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr) |
1428b95d9e2cSSteen Hegelund VCAP_SUPER_CTRL_CLEAR_CACHE_SET(false) |
1429b95d9e2cSSteen Hegelund VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true),
1430b95d9e2cSSteen Hegelund sparx5, VCAP_SUPER_CTRL);
1431b95d9e2cSSteen Hegelund sparx5_vcap_wait_super_update(sparx5);
1432b95d9e2cSSteen Hegelund }
1433b95d9e2cSSteen Hegelund
sparx5_vcap_es0_move(struct sparx5 * sparx5,u32 addr,enum vcap_command cmd,u16 mv_num_pos,u16 mv_size)14343cbe7537SSteen Hegelund static void sparx5_vcap_es0_move(struct sparx5 *sparx5,
14353cbe7537SSteen Hegelund u32 addr,
14363cbe7537SSteen Hegelund enum vcap_command cmd,
14373cbe7537SSteen Hegelund u16 mv_num_pos,
14383cbe7537SSteen Hegelund u16 mv_size)
14393cbe7537SSteen Hegelund {
14403cbe7537SSteen Hegelund spx5_wr(VCAP_ES0_CFG_MV_NUM_POS_SET(mv_num_pos) |
14413cbe7537SSteen Hegelund VCAP_ES0_CFG_MV_SIZE_SET(mv_size),
14423cbe7537SSteen Hegelund sparx5, VCAP_ES0_CFG);
14433cbe7537SSteen Hegelund spx5_wr(VCAP_ES0_CTRL_UPDATE_CMD_SET(cmd) |
14443cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_ENTRY_DIS_SET(0) |
14453cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_ACTION_DIS_SET(0) |
14463cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_CNT_DIS_SET(0) |
14473cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_ADDR_SET(addr) |
14483cbe7537SSteen Hegelund VCAP_ES0_CTRL_CLEAR_CACHE_SET(false) |
14493cbe7537SSteen Hegelund VCAP_ES0_CTRL_UPDATE_SHOT_SET(true),
14503cbe7537SSteen Hegelund sparx5, VCAP_ES0_CTRL);
14513cbe7537SSteen Hegelund sparx5_vcap_wait_es0_update(sparx5);
14523cbe7537SSteen Hegelund }
14533cbe7537SSteen Hegelund
sparx5_vcap_es2_move(struct sparx5 * sparx5,u32 addr,enum vcap_command cmd,u16 mv_num_pos,u16 mv_size)1454b95d9e2cSSteen Hegelund static void sparx5_vcap_es2_move(struct sparx5 *sparx5,
1455b95d9e2cSSteen Hegelund u32 addr,
1456b95d9e2cSSteen Hegelund enum vcap_command cmd,
1457b95d9e2cSSteen Hegelund u16 mv_num_pos,
1458b95d9e2cSSteen Hegelund u16 mv_size)
1459b95d9e2cSSteen Hegelund {
1460b95d9e2cSSteen Hegelund spx5_wr(VCAP_ES2_CFG_MV_NUM_POS_SET(mv_num_pos) |
1461b95d9e2cSSteen Hegelund VCAP_ES2_CFG_MV_SIZE_SET(mv_size),
1462b95d9e2cSSteen Hegelund sparx5, VCAP_ES2_CFG);
1463b95d9e2cSSteen Hegelund spx5_wr(VCAP_ES2_CTRL_UPDATE_CMD_SET(cmd) |
1464b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_ENTRY_DIS_SET(0) |
1465b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_ACTION_DIS_SET(0) |
1466b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_CNT_DIS_SET(0) |
1467b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_ADDR_SET(addr) |
1468b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_CLEAR_CACHE_SET(false) |
1469b95d9e2cSSteen Hegelund VCAP_ES2_CTRL_UPDATE_SHOT_SET(true),
1470b95d9e2cSSteen Hegelund sparx5, VCAP_ES2_CTRL);
1471b95d9e2cSSteen Hegelund sparx5_vcap_wait_es2_update(sparx5);
1472b95d9e2cSSteen Hegelund }
1473b95d9e2cSSteen Hegelund
147446be056eSSteen Hegelund /* API callback used for moving a block of rules in the VCAP */
sparx5_vcap_move(struct net_device * ndev,struct vcap_admin * admin,u32 addr,int offset,int count)147546be056eSSteen Hegelund static void sparx5_vcap_move(struct net_device *ndev, struct vcap_admin *admin,
147646be056eSSteen Hegelund u32 addr, int offset, int count)
147746be056eSSteen Hegelund {
1478990e4839SSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
1479990e4839SSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
1480990e4839SSteen Hegelund enum vcap_command cmd;
1481990e4839SSteen Hegelund u16 mv_num_pos;
1482990e4839SSteen Hegelund u16 mv_size;
1483990e4839SSteen Hegelund
1484990e4839SSteen Hegelund mv_size = count - 1;
1485990e4839SSteen Hegelund if (offset > 0) {
1486990e4839SSteen Hegelund mv_num_pos = offset - 1;
1487990e4839SSteen Hegelund cmd = VCAP_CMD_MOVE_DOWN;
1488990e4839SSteen Hegelund } else {
1489990e4839SSteen Hegelund mv_num_pos = -offset - 1;
1490990e4839SSteen Hegelund cmd = VCAP_CMD_MOVE_UP;
1491990e4839SSteen Hegelund }
1492b95d9e2cSSteen Hegelund
1493b95d9e2cSSteen Hegelund switch (admin->vtype) {
1494b95d9e2cSSteen Hegelund case VCAP_TYPE_IS0:
1495b95d9e2cSSteen Hegelund case VCAP_TYPE_IS2:
1496b95d9e2cSSteen Hegelund sparx5_vcap_super_move(sparx5, addr, cmd, mv_num_pos, mv_size);
1497b95d9e2cSSteen Hegelund break;
14983cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
14993cbe7537SSteen Hegelund sparx5_vcap_es0_move(sparx5, addr, cmd, mv_num_pos, mv_size);
15003cbe7537SSteen Hegelund break;
1501b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
1502b95d9e2cSSteen Hegelund sparx5_vcap_es2_move(sparx5, addr, cmd, mv_num_pos, mv_size);
1503b95d9e2cSSteen Hegelund break;
1504b95d9e2cSSteen Hegelund default:
1505b95d9e2cSSteen Hegelund sparx5_vcap_type_err(sparx5, admin, __func__);
1506b95d9e2cSSteen Hegelund break;
1507b95d9e2cSSteen Hegelund }
150846be056eSSteen Hegelund }
150946be056eSSteen Hegelund
151046be056eSSteen Hegelund static struct vcap_operations sparx5_vcap_ops = {
151146be056eSSteen Hegelund .validate_keyset = sparx5_vcap_validate_keyset,
151246be056eSSteen Hegelund .add_default_fields = sparx5_vcap_add_default_fields,
151346be056eSSteen Hegelund .cache_erase = sparx5_vcap_cache_erase,
151446be056eSSteen Hegelund .cache_write = sparx5_vcap_cache_write,
151546be056eSSteen Hegelund .cache_read = sparx5_vcap_cache_read,
151646be056eSSteen Hegelund .init = sparx5_vcap_range_init,
151746be056eSSteen Hegelund .update = sparx5_vcap_update,
151846be056eSSteen Hegelund .move = sparx5_vcap_move,
151946be056eSSteen Hegelund .port_info = sparx5_port_info,
152046be056eSSteen Hegelund };
152146be056eSSteen Hegelund
sparx5_vcap_is0_keyset_to_etype_ps(enum vcap_keyfield_set keyset)1522*d9f175b0SSteen Hegelund static u32 sparx5_vcap_is0_keyset_to_etype_ps(enum vcap_keyfield_set keyset)
1523*d9f175b0SSteen Hegelund {
1524*d9f175b0SSteen Hegelund switch (keyset) {
1525*d9f175b0SSteen Hegelund case VCAP_KFS_NORMAL_7TUPLE:
1526*d9f175b0SSteen Hegelund return VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE;
1527*d9f175b0SSteen Hegelund case VCAP_KFS_NORMAL_5TUPLE_IP4:
1528*d9f175b0SSteen Hegelund return VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4;
1529*d9f175b0SSteen Hegelund default:
1530*d9f175b0SSteen Hegelund return VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE;
1531*d9f175b0SSteen Hegelund }
1532*d9f175b0SSteen Hegelund }
1533*d9f175b0SSteen Hegelund
sparx5_vcap_is0_set_port_keyset(struct net_device * ndev,int lookup,enum vcap_keyfield_set keyset,int l3_proto)1534*d9f175b0SSteen Hegelund static void sparx5_vcap_is0_set_port_keyset(struct net_device *ndev, int lookup,
1535*d9f175b0SSteen Hegelund enum vcap_keyfield_set keyset,
1536*d9f175b0SSteen Hegelund int l3_proto)
1537*d9f175b0SSteen Hegelund {
1538*d9f175b0SSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
1539*d9f175b0SSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
1540*d9f175b0SSteen Hegelund int portno = port->portno;
1541*d9f175b0SSteen Hegelund u32 value;
1542*d9f175b0SSteen Hegelund
1543*d9f175b0SSteen Hegelund switch (l3_proto) {
1544*d9f175b0SSteen Hegelund case ETH_P_IP:
1545*d9f175b0SSteen Hegelund value = sparx5_vcap_is0_keyset_to_etype_ps(keyset);
1546*d9f175b0SSteen Hegelund spx5_rmw(ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_SET(value),
1547*d9f175b0SSteen Hegelund ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL,
1548*d9f175b0SSteen Hegelund sparx5,
1549*d9f175b0SSteen Hegelund ANA_CL_ADV_CL_CFG(portno, lookup));
1550*d9f175b0SSteen Hegelund break;
1551*d9f175b0SSteen Hegelund case ETH_P_IPV6:
1552*d9f175b0SSteen Hegelund value = sparx5_vcap_is0_keyset_to_etype_ps(keyset);
1553*d9f175b0SSteen Hegelund spx5_rmw(ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_SET(value),
1554*d9f175b0SSteen Hegelund ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL,
1555*d9f175b0SSteen Hegelund sparx5,
1556*d9f175b0SSteen Hegelund ANA_CL_ADV_CL_CFG(portno, lookup));
1557*d9f175b0SSteen Hegelund break;
1558*d9f175b0SSteen Hegelund default:
1559*d9f175b0SSteen Hegelund value = sparx5_vcap_is0_keyset_to_etype_ps(keyset);
1560*d9f175b0SSteen Hegelund spx5_rmw(ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_SET(value),
1561*d9f175b0SSteen Hegelund ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL,
1562*d9f175b0SSteen Hegelund sparx5,
1563*d9f175b0SSteen Hegelund ANA_CL_ADV_CL_CFG(portno, lookup));
1564*d9f175b0SSteen Hegelund break;
1565*d9f175b0SSteen Hegelund }
1566*d9f175b0SSteen Hegelund }
1567*d9f175b0SSteen Hegelund
sparx5_vcap_is2_keyset_to_arp_ps(enum vcap_keyfield_set keyset)1568*d9f175b0SSteen Hegelund static u32 sparx5_vcap_is2_keyset_to_arp_ps(enum vcap_keyfield_set keyset)
1569*d9f175b0SSteen Hegelund {
1570*d9f175b0SSteen Hegelund switch (keyset) {
1571*d9f175b0SSteen Hegelund case VCAP_KFS_ARP:
1572*d9f175b0SSteen Hegelund return VCAP_IS2_PS_ARP_ARP;
1573*d9f175b0SSteen Hegelund default:
1574*d9f175b0SSteen Hegelund return VCAP_IS2_PS_ARP_MAC_ETYPE;
1575*d9f175b0SSteen Hegelund }
1576*d9f175b0SSteen Hegelund }
1577*d9f175b0SSteen Hegelund
sparx5_vcap_is2_keyset_to_ipv4_ps(enum vcap_keyfield_set keyset)1578*d9f175b0SSteen Hegelund static u32 sparx5_vcap_is2_keyset_to_ipv4_ps(enum vcap_keyfield_set keyset)
1579*d9f175b0SSteen Hegelund {
1580*d9f175b0SSteen Hegelund switch (keyset) {
1581*d9f175b0SSteen Hegelund case VCAP_KFS_MAC_ETYPE:
1582*d9f175b0SSteen Hegelund return VCAP_IS2_PS_IPV4_UC_MAC_ETYPE;
1583*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_OTHER:
1584*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_TCP_UDP:
1585*d9f175b0SSteen Hegelund return VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER;
1586*d9f175b0SSteen Hegelund case VCAP_KFS_IP_7TUPLE:
1587*d9f175b0SSteen Hegelund return VCAP_IS2_PS_IPV4_UC_IP_7TUPLE;
1588*d9f175b0SSteen Hegelund default:
1589*d9f175b0SSteen Hegelund return VCAP_KFS_NO_VALUE;
1590*d9f175b0SSteen Hegelund }
1591*d9f175b0SSteen Hegelund }
1592*d9f175b0SSteen Hegelund
sparx5_vcap_is2_keyset_to_ipv6_uc_ps(enum vcap_keyfield_set keyset)1593*d9f175b0SSteen Hegelund static u32 sparx5_vcap_is2_keyset_to_ipv6_uc_ps(enum vcap_keyfield_set keyset)
1594*d9f175b0SSteen Hegelund {
1595*d9f175b0SSteen Hegelund switch (keyset) {
1596*d9f175b0SSteen Hegelund case VCAP_KFS_MAC_ETYPE:
1597*d9f175b0SSteen Hegelund return VCAP_IS2_PS_IPV6_UC_MAC_ETYPE;
1598*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_OTHER:
1599*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_TCP_UDP:
1600*d9f175b0SSteen Hegelund return VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER;
1601*d9f175b0SSteen Hegelund case VCAP_KFS_IP_7TUPLE:
1602*d9f175b0SSteen Hegelund return VCAP_IS2_PS_IPV6_UC_IP_7TUPLE;
1603*d9f175b0SSteen Hegelund default:
1604*d9f175b0SSteen Hegelund return VCAP_KFS_NO_VALUE;
1605*d9f175b0SSteen Hegelund }
1606*d9f175b0SSteen Hegelund }
1607*d9f175b0SSteen Hegelund
sparx5_vcap_is2_keyset_to_ipv6_mc_ps(enum vcap_keyfield_set keyset)1608*d9f175b0SSteen Hegelund static u32 sparx5_vcap_is2_keyset_to_ipv6_mc_ps(enum vcap_keyfield_set keyset)
1609*d9f175b0SSteen Hegelund {
1610*d9f175b0SSteen Hegelund switch (keyset) {
1611*d9f175b0SSteen Hegelund case VCAP_KFS_MAC_ETYPE:
1612*d9f175b0SSteen Hegelund return VCAP_IS2_PS_IPV6_MC_MAC_ETYPE;
1613*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_OTHER:
1614*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_TCP_UDP:
1615*d9f175b0SSteen Hegelund return VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER;
1616*d9f175b0SSteen Hegelund case VCAP_KFS_IP_7TUPLE:
1617*d9f175b0SSteen Hegelund return VCAP_IS2_PS_IPV6_MC_IP_7TUPLE;
1618*d9f175b0SSteen Hegelund default:
1619*d9f175b0SSteen Hegelund return VCAP_KFS_NO_VALUE;
1620*d9f175b0SSteen Hegelund }
1621*d9f175b0SSteen Hegelund }
1622*d9f175b0SSteen Hegelund
sparx5_vcap_is2_set_port_keyset(struct net_device * ndev,int lookup,enum vcap_keyfield_set keyset,int l3_proto)1623*d9f175b0SSteen Hegelund static void sparx5_vcap_is2_set_port_keyset(struct net_device *ndev, int lookup,
1624*d9f175b0SSteen Hegelund enum vcap_keyfield_set keyset,
1625*d9f175b0SSteen Hegelund int l3_proto)
1626*d9f175b0SSteen Hegelund {
1627*d9f175b0SSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
1628*d9f175b0SSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
1629*d9f175b0SSteen Hegelund int portno = port->portno;
1630*d9f175b0SSteen Hegelund u32 value;
1631*d9f175b0SSteen Hegelund
1632*d9f175b0SSteen Hegelund switch (l3_proto) {
1633*d9f175b0SSteen Hegelund case ETH_P_ARP:
1634*d9f175b0SSteen Hegelund value = sparx5_vcap_is2_keyset_to_arp_ps(keyset);
1635*d9f175b0SSteen Hegelund spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(value),
1636*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL,
1637*d9f175b0SSteen Hegelund sparx5,
1638*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
1639*d9f175b0SSteen Hegelund break;
1640*d9f175b0SSteen Hegelund case ETH_P_IP:
1641*d9f175b0SSteen Hegelund value = sparx5_vcap_is2_keyset_to_ipv4_ps(keyset);
1642*d9f175b0SSteen Hegelund spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_SET(value),
1643*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL,
1644*d9f175b0SSteen Hegelund sparx5,
1645*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
1646*d9f175b0SSteen Hegelund spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_SET(value),
1647*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL,
1648*d9f175b0SSteen Hegelund sparx5,
1649*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
1650*d9f175b0SSteen Hegelund break;
1651*d9f175b0SSteen Hegelund case ETH_P_IPV6:
1652*d9f175b0SSteen Hegelund value = sparx5_vcap_is2_keyset_to_ipv6_uc_ps(keyset);
1653*d9f175b0SSteen Hegelund spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(value),
1654*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL,
1655*d9f175b0SSteen Hegelund sparx5,
1656*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
1657*d9f175b0SSteen Hegelund value = sparx5_vcap_is2_keyset_to_ipv6_mc_ps(keyset);
1658*d9f175b0SSteen Hegelund spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_SET(value),
1659*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL,
1660*d9f175b0SSteen Hegelund sparx5,
1661*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
1662*d9f175b0SSteen Hegelund break;
1663*d9f175b0SSteen Hegelund default:
1664*d9f175b0SSteen Hegelund value = VCAP_IS2_PS_NONETH_MAC_ETYPE;
1665*d9f175b0SSteen Hegelund spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(value),
1666*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL,
1667*d9f175b0SSteen Hegelund sparx5,
1668*d9f175b0SSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
1669*d9f175b0SSteen Hegelund break;
1670*d9f175b0SSteen Hegelund }
1671*d9f175b0SSteen Hegelund }
1672*d9f175b0SSteen Hegelund
sparx5_vcap_es2_keyset_to_arp_ps(enum vcap_keyfield_set keyset)1673*d9f175b0SSteen Hegelund static u32 sparx5_vcap_es2_keyset_to_arp_ps(enum vcap_keyfield_set keyset)
1674*d9f175b0SSteen Hegelund {
1675*d9f175b0SSteen Hegelund switch (keyset) {
1676*d9f175b0SSteen Hegelund case VCAP_KFS_ARP:
1677*d9f175b0SSteen Hegelund return VCAP_ES2_PS_ARP_ARP;
1678*d9f175b0SSteen Hegelund default:
1679*d9f175b0SSteen Hegelund return VCAP_ES2_PS_ARP_MAC_ETYPE;
1680*d9f175b0SSteen Hegelund }
1681*d9f175b0SSteen Hegelund }
1682*d9f175b0SSteen Hegelund
sparx5_vcap_es2_keyset_to_ipv4_ps(enum vcap_keyfield_set keyset)1683*d9f175b0SSteen Hegelund static u32 sparx5_vcap_es2_keyset_to_ipv4_ps(enum vcap_keyfield_set keyset)
1684*d9f175b0SSteen Hegelund {
1685*d9f175b0SSteen Hegelund switch (keyset) {
1686*d9f175b0SSteen Hegelund case VCAP_KFS_MAC_ETYPE:
1687*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV4_MAC_ETYPE;
1688*d9f175b0SSteen Hegelund case VCAP_KFS_IP_7TUPLE:
1689*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV4_IP_7TUPLE;
1690*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_TCP_UDP:
1691*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER;
1692*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_OTHER:
1693*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV4_IP4_OTHER;
1694*d9f175b0SSteen Hegelund default:
1695*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV4_MAC_ETYPE;
1696*d9f175b0SSteen Hegelund }
1697*d9f175b0SSteen Hegelund }
1698*d9f175b0SSteen Hegelund
sparx5_vcap_es2_keyset_to_ipv6_ps(enum vcap_keyfield_set keyset)1699*d9f175b0SSteen Hegelund static u32 sparx5_vcap_es2_keyset_to_ipv6_ps(enum vcap_keyfield_set keyset)
1700*d9f175b0SSteen Hegelund {
1701*d9f175b0SSteen Hegelund switch (keyset) {
1702*d9f175b0SSteen Hegelund case VCAP_KFS_MAC_ETYPE:
1703*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV6_MAC_ETYPE;
1704*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_TCP_UDP:
1705*d9f175b0SSteen Hegelund case VCAP_KFS_IP4_OTHER:
1706*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV6_IP4_DOWNGRADE;
1707*d9f175b0SSteen Hegelund case VCAP_KFS_IP_7TUPLE:
1708*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV6_IP_7TUPLE;
1709*d9f175b0SSteen Hegelund case VCAP_KFS_IP6_STD:
1710*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV6_IP6_STD;
1711*d9f175b0SSteen Hegelund default:
1712*d9f175b0SSteen Hegelund return VCAP_ES2_PS_IPV6_MAC_ETYPE;
1713*d9f175b0SSteen Hegelund }
1714*d9f175b0SSteen Hegelund }
1715*d9f175b0SSteen Hegelund
sparx5_vcap_es2_set_port_keyset(struct net_device * ndev,int lookup,enum vcap_keyfield_set keyset,int l3_proto)1716*d9f175b0SSteen Hegelund static void sparx5_vcap_es2_set_port_keyset(struct net_device *ndev, int lookup,
1717*d9f175b0SSteen Hegelund enum vcap_keyfield_set keyset,
1718*d9f175b0SSteen Hegelund int l3_proto)
1719*d9f175b0SSteen Hegelund {
1720*d9f175b0SSteen Hegelund struct sparx5_port *port = netdev_priv(ndev);
1721*d9f175b0SSteen Hegelund struct sparx5 *sparx5 = port->sparx5;
1722*d9f175b0SSteen Hegelund int portno = port->portno;
1723*d9f175b0SSteen Hegelund u32 value;
1724*d9f175b0SSteen Hegelund
1725*d9f175b0SSteen Hegelund switch (l3_proto) {
1726*d9f175b0SSteen Hegelund case ETH_P_IP:
1727*d9f175b0SSteen Hegelund value = sparx5_vcap_es2_keyset_to_ipv4_ps(keyset);
1728*d9f175b0SSteen Hegelund spx5_rmw(EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_SET(value),
1729*d9f175b0SSteen Hegelund EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL,
1730*d9f175b0SSteen Hegelund sparx5,
1731*d9f175b0SSteen Hegelund EACL_VCAP_ES2_KEY_SEL(portno, lookup));
1732*d9f175b0SSteen Hegelund break;
1733*d9f175b0SSteen Hegelund case ETH_P_IPV6:
1734*d9f175b0SSteen Hegelund value = sparx5_vcap_es2_keyset_to_ipv6_ps(keyset);
1735*d9f175b0SSteen Hegelund spx5_rmw(EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_SET(value),
1736*d9f175b0SSteen Hegelund EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL,
1737*d9f175b0SSteen Hegelund sparx5,
1738*d9f175b0SSteen Hegelund EACL_VCAP_ES2_KEY_SEL(portno, lookup));
1739*d9f175b0SSteen Hegelund break;
1740*d9f175b0SSteen Hegelund case ETH_P_ARP:
1741*d9f175b0SSteen Hegelund value = sparx5_vcap_es2_keyset_to_arp_ps(keyset);
1742*d9f175b0SSteen Hegelund spx5_rmw(EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_SET(value),
1743*d9f175b0SSteen Hegelund EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL,
1744*d9f175b0SSteen Hegelund sparx5,
1745*d9f175b0SSteen Hegelund EACL_VCAP_ES2_KEY_SEL(portno, lookup));
1746*d9f175b0SSteen Hegelund break;
1747*d9f175b0SSteen Hegelund }
1748*d9f175b0SSteen Hegelund }
1749*d9f175b0SSteen Hegelund
1750*d9f175b0SSteen Hegelund /* Change the port keyset for the lookup and protocol */
sparx5_vcap_set_port_keyset(struct net_device * ndev,struct vcap_admin * admin,int cid,u16 l3_proto,enum vcap_keyfield_set keyset,struct vcap_keyset_list * orig)1751*d9f175b0SSteen Hegelund void sparx5_vcap_set_port_keyset(struct net_device *ndev,
1752*d9f175b0SSteen Hegelund struct vcap_admin *admin,
1753*d9f175b0SSteen Hegelund int cid,
1754*d9f175b0SSteen Hegelund u16 l3_proto,
1755*d9f175b0SSteen Hegelund enum vcap_keyfield_set keyset,
1756*d9f175b0SSteen Hegelund struct vcap_keyset_list *orig)
1757*d9f175b0SSteen Hegelund {
1758*d9f175b0SSteen Hegelund struct sparx5_port *port;
1759*d9f175b0SSteen Hegelund int lookup;
1760*d9f175b0SSteen Hegelund
1761*d9f175b0SSteen Hegelund switch (admin->vtype) {
1762*d9f175b0SSteen Hegelund case VCAP_TYPE_IS0:
1763*d9f175b0SSteen Hegelund lookup = sparx5_vcap_is0_cid_to_lookup(cid);
1764*d9f175b0SSteen Hegelund if (orig)
1765*d9f175b0SSteen Hegelund sparx5_vcap_is0_get_port_keysets(ndev, lookup, orig,
1766*d9f175b0SSteen Hegelund l3_proto);
1767*d9f175b0SSteen Hegelund sparx5_vcap_is0_set_port_keyset(ndev, lookup, keyset, l3_proto);
1768*d9f175b0SSteen Hegelund break;
1769*d9f175b0SSteen Hegelund case VCAP_TYPE_IS2:
1770*d9f175b0SSteen Hegelund lookup = sparx5_vcap_is2_cid_to_lookup(cid);
1771*d9f175b0SSteen Hegelund if (orig)
1772*d9f175b0SSteen Hegelund sparx5_vcap_is2_get_port_keysets(ndev, lookup, orig,
1773*d9f175b0SSteen Hegelund l3_proto);
1774*d9f175b0SSteen Hegelund sparx5_vcap_is2_set_port_keyset(ndev, lookup, keyset, l3_proto);
1775*d9f175b0SSteen Hegelund break;
1776*d9f175b0SSteen Hegelund case VCAP_TYPE_ES0:
1777*d9f175b0SSteen Hegelund break;
1778*d9f175b0SSteen Hegelund case VCAP_TYPE_ES2:
1779*d9f175b0SSteen Hegelund lookup = sparx5_vcap_es2_cid_to_lookup(cid);
1780*d9f175b0SSteen Hegelund if (orig)
1781*d9f175b0SSteen Hegelund sparx5_vcap_es2_get_port_keysets(ndev, lookup, orig,
1782*d9f175b0SSteen Hegelund l3_proto);
1783*d9f175b0SSteen Hegelund sparx5_vcap_es2_set_port_keyset(ndev, lookup, keyset, l3_proto);
1784*d9f175b0SSteen Hegelund break;
1785*d9f175b0SSteen Hegelund default:
1786*d9f175b0SSteen Hegelund port = netdev_priv(ndev);
1787*d9f175b0SSteen Hegelund sparx5_vcap_type_err(port->sparx5, admin, __func__);
1788*d9f175b0SSteen Hegelund break;
1789*d9f175b0SSteen Hegelund }
1790*d9f175b0SSteen Hegelund }
1791*d9f175b0SSteen Hegelund
1792545609fdSSteen Hegelund /* Enable IS0 lookups per port and set the keyset generation */
sparx5_vcap_is0_port_key_selection(struct sparx5 * sparx5,struct vcap_admin * admin)1793545609fdSSteen Hegelund static void sparx5_vcap_is0_port_key_selection(struct sparx5 *sparx5,
179446be056eSSteen Hegelund struct vcap_admin *admin)
179546be056eSSteen Hegelund {
179646be056eSSteen Hegelund int portno, lookup;
179746be056eSSteen Hegelund u32 keysel;
179846be056eSSteen Hegelund
1799545609fdSSteen Hegelund keysel = VCAP_IS0_KEYSEL(false,
1800545609fdSSteen Hegelund VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE,
1801545609fdSSteen Hegelund VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4,
1802545609fdSSteen Hegelund VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE,
1803545609fdSSteen Hegelund VCAP_IS0_PS_MPLS_FOLLOW_ETYPE,
1804545609fdSSteen Hegelund VCAP_IS0_PS_MPLS_FOLLOW_ETYPE,
1805545609fdSSteen Hegelund VCAP_IS0_PS_MLBS_FOLLOW_ETYPE);
1806545609fdSSteen Hegelund for (lookup = 0; lookup < admin->lookups; ++lookup) {
1807545609fdSSteen Hegelund for (portno = 0; portno < SPX5_PORTS; ++portno) {
1808545609fdSSteen Hegelund spx5_wr(keysel, sparx5,
1809545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG(portno, lookup));
1810545609fdSSteen Hegelund spx5_rmw(ANA_CL_ADV_CL_CFG_LOOKUP_ENA,
1811545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG_LOOKUP_ENA,
1812545609fdSSteen Hegelund sparx5,
1813545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG(portno, lookup));
1814545609fdSSteen Hegelund }
1815545609fdSSteen Hegelund }
1816545609fdSSteen Hegelund }
1817545609fdSSteen Hegelund
1818545609fdSSteen Hegelund /* Enable IS2 lookups per port and set the keyset generation */
sparx5_vcap_is2_port_key_selection(struct sparx5 * sparx5,struct vcap_admin * admin)1819545609fdSSteen Hegelund static void sparx5_vcap_is2_port_key_selection(struct sparx5 *sparx5,
1820545609fdSSteen Hegelund struct vcap_admin *admin)
1821545609fdSSteen Hegelund {
1822545609fdSSteen Hegelund int portno, lookup;
1823545609fdSSteen Hegelund u32 keysel;
1824545609fdSSteen Hegelund
182530172a72SSteen Hegelund keysel = VCAP_IS2_KEYSEL(true, VCAP_IS2_PS_NONETH_MAC_ETYPE,
182630172a72SSteen Hegelund VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER,
182730172a72SSteen Hegelund VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
182830172a72SSteen Hegelund VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
182930172a72SSteen Hegelund VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
18303a344f99SSteen Hegelund VCAP_IS2_PS_ARP_ARP);
183146be056eSSteen Hegelund for (lookup = 0; lookup < admin->lookups; ++lookup) {
183246be056eSSteen Hegelund for (portno = 0; portno < SPX5_PORTS; ++portno) {
183346be056eSSteen Hegelund spx5_wr(keysel, sparx5,
183446be056eSSteen Hegelund ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
183546be056eSSteen Hegelund }
183646be056eSSteen Hegelund }
183701ef75a2SSteen Hegelund /* IS2 lookups are in bit 0:3 */
183801ef75a2SSteen Hegelund for (portno = 0; portno < SPX5_PORTS; ++portno)
183901ef75a2SSteen Hegelund spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0xf),
184001ef75a2SSteen Hegelund ANA_ACL_VCAP_S2_CFG_SEC_ENA,
184101ef75a2SSteen Hegelund sparx5,
184201ef75a2SSteen Hegelund ANA_ACL_VCAP_S2_CFG(portno));
184346be056eSSteen Hegelund }
184446be056eSSteen Hegelund
18453cbe7537SSteen Hegelund /* Enable ES0 lookups per port and set the keyset generation */
sparx5_vcap_es0_port_key_selection(struct sparx5 * sparx5,struct vcap_admin * admin)18463cbe7537SSteen Hegelund static void sparx5_vcap_es0_port_key_selection(struct sparx5 *sparx5,
18473cbe7537SSteen Hegelund struct vcap_admin *admin)
18483cbe7537SSteen Hegelund {
18493cbe7537SSteen Hegelund int portno;
18503cbe7537SSteen Hegelund u32 keysel;
18513cbe7537SSteen Hegelund
18523cbe7537SSteen Hegelund keysel = VCAP_ES0_KEYSEL(VCAP_ES0_PS_FORCE_ISDX_LOOKUPS);
18533cbe7537SSteen Hegelund for (portno = 0; portno < SPX5_PORTS; ++portno)
18543cbe7537SSteen Hegelund spx5_rmw(keysel, REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA,
18553cbe7537SSteen Hegelund sparx5, REW_RTAG_ETAG_CTRL(portno));
18563cbe7537SSteen Hegelund
18573cbe7537SSteen Hegelund spx5_rmw(REW_ES0_CTRL_ES0_LU_ENA_SET(1), REW_ES0_CTRL_ES0_LU_ENA,
18583cbe7537SSteen Hegelund sparx5, REW_ES0_CTRL);
18593cbe7537SSteen Hegelund }
18603cbe7537SSteen Hegelund
1861b95d9e2cSSteen Hegelund /* Enable ES2 lookups per port and set the keyset generation */
sparx5_vcap_es2_port_key_selection(struct sparx5 * sparx5,struct vcap_admin * admin)1862b95d9e2cSSteen Hegelund static void sparx5_vcap_es2_port_key_selection(struct sparx5 *sparx5,
1863b95d9e2cSSteen Hegelund struct vcap_admin *admin)
1864b95d9e2cSSteen Hegelund {
1865b95d9e2cSSteen Hegelund int portno, lookup;
1866b95d9e2cSSteen Hegelund u32 keysel;
1867b95d9e2cSSteen Hegelund
1868b95d9e2cSSteen Hegelund keysel = VCAP_ES2_KEYSEL(true, VCAP_ES2_PS_ARP_MAC_ETYPE,
1869b95d9e2cSSteen Hegelund VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER,
1870b95d9e2cSSteen Hegelund VCAP_ES2_PS_IPV6_IP_7TUPLE);
1871b95d9e2cSSteen Hegelund for (lookup = 0; lookup < admin->lookups; ++lookup)
1872b95d9e2cSSteen Hegelund for (portno = 0; portno < SPX5_PORTS; ++portno)
1873b95d9e2cSSteen Hegelund spx5_wr(keysel, sparx5,
1874b95d9e2cSSteen Hegelund EACL_VCAP_ES2_KEY_SEL(portno, lookup));
1875b95d9e2cSSteen Hegelund }
1876b95d9e2cSSteen Hegelund
1877545609fdSSteen Hegelund /* Enable lookups per port and set the keyset generation */
sparx5_vcap_port_key_selection(struct sparx5 * sparx5,struct vcap_admin * admin)1878545609fdSSteen Hegelund static void sparx5_vcap_port_key_selection(struct sparx5 *sparx5,
1879545609fdSSteen Hegelund struct vcap_admin *admin)
1880545609fdSSteen Hegelund {
1881545609fdSSteen Hegelund switch (admin->vtype) {
1882545609fdSSteen Hegelund case VCAP_TYPE_IS0:
1883545609fdSSteen Hegelund sparx5_vcap_is0_port_key_selection(sparx5, admin);
1884545609fdSSteen Hegelund break;
1885545609fdSSteen Hegelund case VCAP_TYPE_IS2:
1886545609fdSSteen Hegelund sparx5_vcap_is2_port_key_selection(sparx5, admin);
1887545609fdSSteen Hegelund break;
18883cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
18893cbe7537SSteen Hegelund sparx5_vcap_es0_port_key_selection(sparx5, admin);
18903cbe7537SSteen Hegelund break;
1891b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
1892b95d9e2cSSteen Hegelund sparx5_vcap_es2_port_key_selection(sparx5, admin);
1893b95d9e2cSSteen Hegelund break;
1894545609fdSSteen Hegelund default:
1895545609fdSSteen Hegelund sparx5_vcap_type_err(sparx5, admin, __func__);
1896545609fdSSteen Hegelund break;
1897545609fdSSteen Hegelund }
1898545609fdSSteen Hegelund }
1899545609fdSSteen Hegelund
1900545609fdSSteen Hegelund /* Disable lookups per port */
sparx5_vcap_port_key_deselection(struct sparx5 * sparx5,struct vcap_admin * admin)190146be056eSSteen Hegelund static void sparx5_vcap_port_key_deselection(struct sparx5 *sparx5,
190246be056eSSteen Hegelund struct vcap_admin *admin)
190346be056eSSteen Hegelund {
1904545609fdSSteen Hegelund int portno, lookup;
190546be056eSSteen Hegelund
1906545609fdSSteen Hegelund switch (admin->vtype) {
1907545609fdSSteen Hegelund case VCAP_TYPE_IS0:
1908545609fdSSteen Hegelund for (lookup = 0; lookup < admin->lookups; ++lookup)
1909545609fdSSteen Hegelund for (portno = 0; portno < SPX5_PORTS; ++portno)
1910545609fdSSteen Hegelund spx5_rmw(ANA_CL_ADV_CL_CFG_LOOKUP_ENA_SET(0),
1911545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG_LOOKUP_ENA,
1912545609fdSSteen Hegelund sparx5,
1913545609fdSSteen Hegelund ANA_CL_ADV_CL_CFG(portno, lookup));
1914545609fdSSteen Hegelund break;
1915545609fdSSteen Hegelund case VCAP_TYPE_IS2:
191646be056eSSteen Hegelund for (portno = 0; portno < SPX5_PORTS; ++portno)
191746be056eSSteen Hegelund spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0),
191846be056eSSteen Hegelund ANA_ACL_VCAP_S2_CFG_SEC_ENA,
191946be056eSSteen Hegelund sparx5,
192046be056eSSteen Hegelund ANA_ACL_VCAP_S2_CFG(portno));
1921545609fdSSteen Hegelund break;
19223cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
19233cbe7537SSteen Hegelund spx5_rmw(REW_ES0_CTRL_ES0_LU_ENA_SET(0),
19243cbe7537SSteen Hegelund REW_ES0_CTRL_ES0_LU_ENA, sparx5, REW_ES0_CTRL);
19253cbe7537SSteen Hegelund break;
1926b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
1927b95d9e2cSSteen Hegelund for (lookup = 0; lookup < admin->lookups; ++lookup)
1928b95d9e2cSSteen Hegelund for (portno = 0; portno < SPX5_PORTS; ++portno)
1929b95d9e2cSSteen Hegelund spx5_rmw(EACL_VCAP_ES2_KEY_SEL_KEY_ENA_SET(0),
1930b95d9e2cSSteen Hegelund EACL_VCAP_ES2_KEY_SEL_KEY_ENA,
1931b95d9e2cSSteen Hegelund sparx5,
1932b95d9e2cSSteen Hegelund EACL_VCAP_ES2_KEY_SEL(portno, lookup));
1933b95d9e2cSSteen Hegelund break;
1934545609fdSSteen Hegelund default:
1935545609fdSSteen Hegelund sparx5_vcap_type_err(sparx5, admin, __func__);
1936545609fdSSteen Hegelund break;
1937545609fdSSteen Hegelund }
193846be056eSSteen Hegelund }
193946be056eSSteen Hegelund
sparx5_vcap_admin_free(struct vcap_admin * admin)1940c9da1ac1SSteen Hegelund static void sparx5_vcap_admin_free(struct vcap_admin *admin)
1941c9da1ac1SSteen Hegelund {
1942c9da1ac1SSteen Hegelund if (!admin)
1943c9da1ac1SSteen Hegelund return;
194471c9de99SSteen Hegelund mutex_destroy(&admin->lock);
1945c9da1ac1SSteen Hegelund kfree(admin->cache.keystream);
1946c9da1ac1SSteen Hegelund kfree(admin->cache.maskstream);
1947c9da1ac1SSteen Hegelund kfree(admin->cache.actionstream);
1948c9da1ac1SSteen Hegelund kfree(admin);
1949c9da1ac1SSteen Hegelund }
1950c9da1ac1SSteen Hegelund
1951c9da1ac1SSteen Hegelund /* Allocate a vcap instance with a rule list and a cache area */
1952c9da1ac1SSteen Hegelund static struct vcap_admin *
sparx5_vcap_admin_alloc(struct sparx5 * sparx5,struct vcap_control * ctrl,const struct sparx5_vcap_inst * cfg)1953c9da1ac1SSteen Hegelund sparx5_vcap_admin_alloc(struct sparx5 *sparx5, struct vcap_control *ctrl,
1954c9da1ac1SSteen Hegelund const struct sparx5_vcap_inst *cfg)
1955c9da1ac1SSteen Hegelund {
1956c9da1ac1SSteen Hegelund struct vcap_admin *admin;
1957c9da1ac1SSteen Hegelund
1958c9da1ac1SSteen Hegelund admin = kzalloc(sizeof(*admin), GFP_KERNEL);
1959c9da1ac1SSteen Hegelund if (!admin)
1960c9da1ac1SSteen Hegelund return ERR_PTR(-ENOMEM);
1961c9da1ac1SSteen Hegelund INIT_LIST_HEAD(&admin->list);
1962c9da1ac1SSteen Hegelund INIT_LIST_HEAD(&admin->rules);
196367456717SSteen Hegelund INIT_LIST_HEAD(&admin->enabled);
196471c9de99SSteen Hegelund mutex_init(&admin->lock);
1965c9da1ac1SSteen Hegelund admin->vtype = cfg->vtype;
1966c9da1ac1SSteen Hegelund admin->vinst = cfg->vinst;
1967e7e3f514SSteen Hegelund admin->ingress = cfg->ingress;
1968c9da1ac1SSteen Hegelund admin->lookups = cfg->lookups;
1969c9da1ac1SSteen Hegelund admin->lookups_per_instance = cfg->lookups_per_instance;
1970c9da1ac1SSteen Hegelund admin->first_cid = cfg->first_cid;
1971c9da1ac1SSteen Hegelund admin->last_cid = cfg->last_cid;
1972c9da1ac1SSteen Hegelund admin->cache.keystream =
1973c9da1ac1SSteen Hegelund kzalloc(STREAMSIZE, GFP_KERNEL);
1974c9da1ac1SSteen Hegelund admin->cache.maskstream =
1975c9da1ac1SSteen Hegelund kzalloc(STREAMSIZE, GFP_KERNEL);
1976c9da1ac1SSteen Hegelund admin->cache.actionstream =
1977c9da1ac1SSteen Hegelund kzalloc(STREAMSIZE, GFP_KERNEL);
1978c9da1ac1SSteen Hegelund if (!admin->cache.keystream || !admin->cache.maskstream ||
1979c9da1ac1SSteen Hegelund !admin->cache.actionstream) {
1980c9da1ac1SSteen Hegelund sparx5_vcap_admin_free(admin);
1981c9da1ac1SSteen Hegelund return ERR_PTR(-ENOMEM);
1982c9da1ac1SSteen Hegelund }
1983c9da1ac1SSteen Hegelund return admin;
1984c9da1ac1SSteen Hegelund }
1985c9da1ac1SSteen Hegelund
1986c9da1ac1SSteen Hegelund /* Do block allocations and provide addresses for VCAP instances */
sparx5_vcap_block_alloc(struct sparx5 * sparx5,struct vcap_admin * admin,const struct sparx5_vcap_inst * cfg)1987c9da1ac1SSteen Hegelund static void sparx5_vcap_block_alloc(struct sparx5 *sparx5,
1988c9da1ac1SSteen Hegelund struct vcap_admin *admin,
1989c9da1ac1SSteen Hegelund const struct sparx5_vcap_inst *cfg)
1990c9da1ac1SSteen Hegelund {
1991b95d9e2cSSteen Hegelund int idx, cores;
1992c9da1ac1SSteen Hegelund
1993b95d9e2cSSteen Hegelund switch (admin->vtype) {
1994b95d9e2cSSteen Hegelund case VCAP_TYPE_IS0:
1995b95d9e2cSSteen Hegelund case VCAP_TYPE_IS2:
1996c9da1ac1SSteen Hegelund /* Super VCAP block mapping and address configuration. Block 0
1997c9da1ac1SSteen Hegelund * is assigned addresses 0 through 3071, block 1 is assigned
1998c9da1ac1SSteen Hegelund * addresses 3072 though 6143, and so on.
1999c9da1ac1SSteen Hegelund */
2000b95d9e2cSSteen Hegelund for (idx = cfg->blockno; idx < cfg->blockno + cfg->blocks;
2001b95d9e2cSSteen Hegelund ++idx) {
2002c9da1ac1SSteen Hegelund spx5_wr(VCAP_SUPER_IDX_CORE_IDX_SET(idx), sparx5,
2003c9da1ac1SSteen Hegelund VCAP_SUPER_IDX);
2004b95d9e2cSSteen Hegelund spx5_wr(VCAP_SUPER_MAP_CORE_MAP_SET(cfg->map_id),
2005b95d9e2cSSteen Hegelund sparx5, VCAP_SUPER_MAP);
2006c9da1ac1SSteen Hegelund }
2007c9da1ac1SSteen Hegelund admin->first_valid_addr = cfg->blockno * SUPER_VCAP_BLK_SIZE;
2008c9da1ac1SSteen Hegelund admin->last_used_addr = admin->first_valid_addr +
2009c9da1ac1SSteen Hegelund cfg->blocks * SUPER_VCAP_BLK_SIZE;
2010c9da1ac1SSteen Hegelund admin->last_valid_addr = admin->last_used_addr - 1;
2011b95d9e2cSSteen Hegelund break;
20123cbe7537SSteen Hegelund case VCAP_TYPE_ES0:
20133cbe7537SSteen Hegelund admin->first_valid_addr = 0;
20143cbe7537SSteen Hegelund admin->last_used_addr = cfg->count;
20153cbe7537SSteen Hegelund admin->last_valid_addr = cfg->count - 1;
20163cbe7537SSteen Hegelund cores = spx5_rd(sparx5, VCAP_ES0_CORE_CNT);
20173cbe7537SSteen Hegelund for (idx = 0; idx < cores; ++idx) {
20183cbe7537SSteen Hegelund spx5_wr(VCAP_ES0_IDX_CORE_IDX_SET(idx), sparx5,
20193cbe7537SSteen Hegelund VCAP_ES0_IDX);
20203cbe7537SSteen Hegelund spx5_wr(VCAP_ES0_MAP_CORE_MAP_SET(1), sparx5,
20213cbe7537SSteen Hegelund VCAP_ES0_MAP);
20223cbe7537SSteen Hegelund }
20233cbe7537SSteen Hegelund break;
2024b95d9e2cSSteen Hegelund case VCAP_TYPE_ES2:
2025b95d9e2cSSteen Hegelund admin->first_valid_addr = 0;
2026b95d9e2cSSteen Hegelund admin->last_used_addr = cfg->count;
2027b95d9e2cSSteen Hegelund admin->last_valid_addr = cfg->count - 1;
2028b95d9e2cSSteen Hegelund cores = spx5_rd(sparx5, VCAP_ES2_CORE_CNT);
2029b95d9e2cSSteen Hegelund for (idx = 0; idx < cores; ++idx) {
2030b95d9e2cSSteen Hegelund spx5_wr(VCAP_ES2_IDX_CORE_IDX_SET(idx), sparx5,
2031b95d9e2cSSteen Hegelund VCAP_ES2_IDX);
2032b95d9e2cSSteen Hegelund spx5_wr(VCAP_ES2_MAP_CORE_MAP_SET(1), sparx5,
2033b95d9e2cSSteen Hegelund VCAP_ES2_MAP);
2034b95d9e2cSSteen Hegelund }
2035b95d9e2cSSteen Hegelund break;
2036b95d9e2cSSteen Hegelund default:
2037b95d9e2cSSteen Hegelund sparx5_vcap_type_err(sparx5, admin, __func__);
2038b95d9e2cSSteen Hegelund break;
2039b95d9e2cSSteen Hegelund }
2040c9da1ac1SSteen Hegelund }
2041c9da1ac1SSteen Hegelund
20428beef08fSSteen Hegelund /* Allocate a vcap control and vcap instances and configure the system */
sparx5_vcap_init(struct sparx5 * sparx5)20438beef08fSSteen Hegelund int sparx5_vcap_init(struct sparx5 *sparx5)
20448beef08fSSteen Hegelund {
2045c9da1ac1SSteen Hegelund const struct sparx5_vcap_inst *cfg;
20468beef08fSSteen Hegelund struct vcap_control *ctrl;
2047c9da1ac1SSteen Hegelund struct vcap_admin *admin;
2048e0305cc1SSteen Hegelund struct dentry *dir;
2049c9da1ac1SSteen Hegelund int err = 0, idx;
20508beef08fSSteen Hegelund
20518beef08fSSteen Hegelund /* Create a VCAP control instance that owns the platform specific VCAP
20528beef08fSSteen Hegelund * model with VCAP instances and information about keysets, keys,
20538beef08fSSteen Hegelund * actionsets and actions
2054c9da1ac1SSteen Hegelund * - Create administrative state for each available VCAP
2055c9da1ac1SSteen Hegelund * - Lists of rules
2056c9da1ac1SSteen Hegelund * - Address information
2057c9da1ac1SSteen Hegelund * - Initialize VCAP blocks
205846be056eSSteen Hegelund * - Configure port keysets
20598beef08fSSteen Hegelund */
20608beef08fSSteen Hegelund ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
20618beef08fSSteen Hegelund if (!ctrl)
20628beef08fSSteen Hegelund return -ENOMEM;
20638beef08fSSteen Hegelund
20648beef08fSSteen Hegelund sparx5->vcap_ctrl = ctrl;
2065e8145e06SSteen Hegelund /* select the sparx5 VCAP model */
2066e8145e06SSteen Hegelund ctrl->vcaps = sparx5_vcaps;
2067e8145e06SSteen Hegelund ctrl->stats = &sparx5_vcap_stats;
206846be056eSSteen Hegelund /* Setup callbacks to allow the API to use the VCAP HW */
206946be056eSSteen Hegelund ctrl->ops = &sparx5_vcap_ops;
20708beef08fSSteen Hegelund
2071c9da1ac1SSteen Hegelund INIT_LIST_HEAD(&ctrl->list);
2072c9da1ac1SSteen Hegelund for (idx = 0; idx < ARRAY_SIZE(sparx5_vcap_inst_cfg); ++idx) {
2073c9da1ac1SSteen Hegelund cfg = &sparx5_vcap_inst_cfg[idx];
2074c9da1ac1SSteen Hegelund admin = sparx5_vcap_admin_alloc(sparx5, ctrl, cfg);
2075c9da1ac1SSteen Hegelund if (IS_ERR(admin)) {
2076c9da1ac1SSteen Hegelund err = PTR_ERR(admin);
2077c9da1ac1SSteen Hegelund pr_err("%s:%d: vcap allocation failed: %d\n",
2078c9da1ac1SSteen Hegelund __func__, __LINE__, err);
2079c9da1ac1SSteen Hegelund return err;
2080c9da1ac1SSteen Hegelund }
2081c9da1ac1SSteen Hegelund sparx5_vcap_block_alloc(sparx5, admin, cfg);
208246be056eSSteen Hegelund sparx5_vcap_block_init(sparx5, admin);
208346be056eSSteen Hegelund if (cfg->vinst == 0)
208446be056eSSteen Hegelund sparx5_vcap_port_key_selection(sparx5, admin);
2085c9da1ac1SSteen Hegelund list_add_tail(&admin->list, &ctrl->list);
2086c9da1ac1SSteen Hegelund }
2087e0305cc1SSteen Hegelund dir = vcap_debugfs(sparx5->dev, sparx5->debugfs_root, ctrl);
2088e0305cc1SSteen Hegelund for (idx = 0; idx < SPX5_PORTS; ++idx)
2089e0305cc1SSteen Hegelund if (sparx5->ports[idx])
2090e0305cc1SSteen Hegelund vcap_port_debugfs(sparx5->dev, dir, ctrl,
2091e0305cc1SSteen Hegelund sparx5->ports[idx]->ndev);
2092c9da1ac1SSteen Hegelund
2093c9da1ac1SSteen Hegelund return err;
20948beef08fSSteen Hegelund }
20958beef08fSSteen Hegelund
sparx5_vcap_destroy(struct sparx5 * sparx5)20968beef08fSSteen Hegelund void sparx5_vcap_destroy(struct sparx5 *sparx5)
20978beef08fSSteen Hegelund {
2098c9da1ac1SSteen Hegelund struct vcap_control *ctrl = sparx5->vcap_ctrl;
2099c9da1ac1SSteen Hegelund struct vcap_admin *admin, *admin_next;
2100c9da1ac1SSteen Hegelund
2101c9da1ac1SSteen Hegelund if (!ctrl)
21028beef08fSSteen Hegelund return;
21038beef08fSSteen Hegelund
2104c9da1ac1SSteen Hegelund list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) {
210546be056eSSteen Hegelund sparx5_vcap_port_key_deselection(sparx5, admin);
21068e10490bSSteen Hegelund vcap_del_rules(ctrl, admin);
2107c9da1ac1SSteen Hegelund list_del(&admin->list);
2108c9da1ac1SSteen Hegelund sparx5_vcap_admin_free(admin);
2109c9da1ac1SSteen Hegelund }
2110c9da1ac1SSteen Hegelund kfree(ctrl);
21118beef08fSSteen Hegelund }
2112