1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver VCAP implementation
4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
6 * The Sparx5 Chip Register Model can be browsed at this location:
7 * https://github.com/microchip-ung/sparx-5_reginfo
10 #include "vcap_api_debugfs.h"
11 #include "sparx5_main_regs.h"
12 #include "sparx5_main.h"
13 #include "sparx5_vcap_impl.h"
14 #include "sparx5_vcap_ag_api.h"
15 #include "sparx5_vcap_debugfs.h"
17 #define SUPER_VCAP_BLK_SIZE 3072 /* addresses per Super VCAP block */
18 #define STREAMSIZE (64 * 4) /* bytes in the VCAP cache area */
20 #define VCAP_IS2_KEYSEL(_ena, _noneth, _v4_mc, _v4_uc, _v6_mc, _v6_uc, _arp) \
21 (ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_SET(_ena) | \
22 ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(_noneth) | \
23 ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_SET(_v4_mc) | \
24 ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_SET(_v4_uc) | \
25 ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_SET(_v6_mc) | \
26 ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(_v6_uc) | \
27 ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(_arp))
29 #define VCAP_IS0_KEYSEL(_ena, _etype, _ipv4, _ipv6, _mpls_uc, _mpls_mc, _mlbs) \
30 (ANA_CL_ADV_CL_CFG_LOOKUP_ENA_SET(_ena) | \
31 ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_SET(_etype) | \
32 ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_SET(_ipv4) | \
33 ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_SET(_ipv6) | \
34 ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL_SET(_mpls_uc) | \
35 ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL_SET(_mpls_mc) | \
36 ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL_SET(_mlbs))
38 #define VCAP_ES0_KEYSEL(_key) (REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA_SET(_key))
39 #define SPARX5_STAT_ESDX_GRN_PKTS 0x300
40 #define SPARX5_STAT_ESDX_YEL_PKTS 0x301
42 #define VCAP_ES2_KEYSEL(_ena, _arp, _ipv4, _ipv6) \
43 (EACL_VCAP_ES2_KEY_SEL_KEY_ENA_SET(_ena) | \
44 EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_SET(_arp) | \
45 EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_SET(_ipv4) | \
46 EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_SET(_ipv6))
48 const struct sparx5_vcap_inst sparx5_vcap_inst_cfg
[] = {
50 .vtype
= VCAP_TYPE_IS0
, /* CLM-0 */
53 .lookups
= SPARX5_IS0_LOOKUPS
,
54 .lookups_per_instance
= SPARX5_IS0_LOOKUPS
/ 3,
55 .first_cid
= SPARX5_VCAP_CID_IS0_L0
,
56 .last_cid
= SPARX5_VCAP_CID_IS0_L2
- 1,
57 .blockno
= 8, /* Maps block 8-9 */
62 .vtype
= VCAP_TYPE_IS0
, /* CLM-1 */
65 .lookups
= SPARX5_IS0_LOOKUPS
,
66 .lookups_per_instance
= SPARX5_IS0_LOOKUPS
/ 3,
67 .first_cid
= SPARX5_VCAP_CID_IS0_L2
,
68 .last_cid
= SPARX5_VCAP_CID_IS0_L4
- 1,
69 .blockno
= 6, /* Maps block 6-7 */
74 .vtype
= VCAP_TYPE_IS0
, /* CLM-2 */
77 .lookups
= SPARX5_IS0_LOOKUPS
,
78 .lookups_per_instance
= SPARX5_IS0_LOOKUPS
/ 3,
79 .first_cid
= SPARX5_VCAP_CID_IS0_L4
,
80 .last_cid
= SPARX5_VCAP_CID_IS0_MAX
,
81 .blockno
= 4, /* Maps block 4-5 */
86 .vtype
= VCAP_TYPE_IS2
, /* IS2-0 */
89 .lookups
= SPARX5_IS2_LOOKUPS
,
90 .lookups_per_instance
= SPARX5_IS2_LOOKUPS
/ 2,
91 .first_cid
= SPARX5_VCAP_CID_IS2_L0
,
92 .last_cid
= SPARX5_VCAP_CID_IS2_L2
- 1,
93 .blockno
= 0, /* Maps block 0-1 */
98 .vtype
= VCAP_TYPE_IS2
, /* IS2-1 */
101 .lookups
= SPARX5_IS2_LOOKUPS
,
102 .lookups_per_instance
= SPARX5_IS2_LOOKUPS
/ 2,
103 .first_cid
= SPARX5_VCAP_CID_IS2_L2
,
104 .last_cid
= SPARX5_VCAP_CID_IS2_MAX
,
105 .blockno
= 2, /* Maps block 2-3 */
110 .vtype
= VCAP_TYPE_ES0
,
111 .lookups
= SPARX5_ES0_LOOKUPS
,
112 .lookups_per_instance
= SPARX5_ES0_LOOKUPS
,
113 .first_cid
= SPARX5_VCAP_CID_ES0_L0
,
114 .last_cid
= SPARX5_VCAP_CID_ES0_MAX
,
115 .count
= 4096, /* Addresses according to datasheet */
119 .vtype
= VCAP_TYPE_ES2
,
120 .lookups
= SPARX5_ES2_LOOKUPS
,
121 .lookups_per_instance
= SPARX5_ES2_LOOKUPS
,
122 .first_cid
= SPARX5_VCAP_CID_ES2_L0
,
123 .last_cid
= SPARX5_VCAP_CID_ES2_MAX
,
124 .count
= 12288, /* Addresses according to datasheet */
129 /* These protocols have dedicated keysets in IS0 and a TC dissector */
130 static u16 sparx5_vcap_is0_known_etypes
[] = {
136 /* These protocols have dedicated keysets in IS2 and a TC dissector */
137 static u16 sparx5_vcap_is2_known_etypes
[] = {
144 /* These protocols have dedicated keysets in ES2 and a TC dissector */
145 static u16 sparx5_vcap_es2_known_etypes
[] = {
152 static void sparx5_vcap_type_err(struct sparx5
*sparx5
,
153 struct vcap_admin
*admin
,
156 pr_err("%s: vcap type: %s not supported\n",
157 fname
, sparx5_vcaps
[admin
->vtype
].name
);
160 /* Await the super VCAP completion of the current operation */
161 static void sparx5_vcap_wait_super_update(struct sparx5
*sparx5
)
165 read_poll_timeout(spx5_rd
, value
,
166 !VCAP_SUPER_CTRL_UPDATE_SHOT_GET(value
), 500, 10000,
167 false, sparx5
, VCAP_SUPER_CTRL
);
170 /* Await the ES0 VCAP completion of the current operation */
171 static void sparx5_vcap_wait_es0_update(struct sparx5
*sparx5
)
175 read_poll_timeout(spx5_rd
, value
,
176 !VCAP_ES0_CTRL_UPDATE_SHOT_GET(value
), 500, 10000,
177 false, sparx5
, VCAP_ES0_CTRL
);
180 /* Await the ES2 VCAP completion of the current operation */
181 static void sparx5_vcap_wait_es2_update(struct sparx5
*sparx5
)
185 read_poll_timeout(spx5_rd
, value
,
186 !VCAP_ES2_CTRL_UPDATE_SHOT_GET(value
), 500, 10000,
187 false, sparx5
, VCAP_ES2_CTRL
);
190 /* Initializing a VCAP address range */
191 static void _sparx5_vcap_range_init(struct sparx5
*sparx5
,
192 struct vcap_admin
*admin
,
195 u32 size
= count
- 1;
197 switch (admin
->vtype
) {
200 spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(0) |
201 VCAP_SUPER_CFG_MV_SIZE_SET(size
),
202 sparx5
, VCAP_SUPER_CFG
);
203 spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE
) |
204 VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET(0) |
205 VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET(0) |
206 VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET(0) |
207 VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr
) |
208 VCAP_SUPER_CTRL_CLEAR_CACHE_SET(true) |
209 VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true),
210 sparx5
, VCAP_SUPER_CTRL
);
211 sparx5_vcap_wait_super_update(sparx5
);
214 spx5_wr(VCAP_ES0_CFG_MV_NUM_POS_SET(0) |
215 VCAP_ES0_CFG_MV_SIZE_SET(size
),
216 sparx5
, VCAP_ES0_CFG
);
217 spx5_wr(VCAP_ES0_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE
) |
218 VCAP_ES0_CTRL_UPDATE_ENTRY_DIS_SET(0) |
219 VCAP_ES0_CTRL_UPDATE_ACTION_DIS_SET(0) |
220 VCAP_ES0_CTRL_UPDATE_CNT_DIS_SET(0) |
221 VCAP_ES0_CTRL_UPDATE_ADDR_SET(addr
) |
222 VCAP_ES0_CTRL_CLEAR_CACHE_SET(true) |
223 VCAP_ES0_CTRL_UPDATE_SHOT_SET(true),
224 sparx5
, VCAP_ES0_CTRL
);
225 sparx5_vcap_wait_es0_update(sparx5
);
228 spx5_wr(VCAP_ES2_CFG_MV_NUM_POS_SET(0) |
229 VCAP_ES2_CFG_MV_SIZE_SET(size
),
230 sparx5
, VCAP_ES2_CFG
);
231 spx5_wr(VCAP_ES2_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE
) |
232 VCAP_ES2_CTRL_UPDATE_ENTRY_DIS_SET(0) |
233 VCAP_ES2_CTRL_UPDATE_ACTION_DIS_SET(0) |
234 VCAP_ES2_CTRL_UPDATE_CNT_DIS_SET(0) |
235 VCAP_ES2_CTRL_UPDATE_ADDR_SET(addr
) |
236 VCAP_ES2_CTRL_CLEAR_CACHE_SET(true) |
237 VCAP_ES2_CTRL_UPDATE_SHOT_SET(true),
238 sparx5
, VCAP_ES2_CTRL
);
239 sparx5_vcap_wait_es2_update(sparx5
);
242 sparx5_vcap_type_err(sparx5
, admin
, __func__
);
247 /* Initializing VCAP rule data area */
248 static void sparx5_vcap_block_init(struct sparx5
*sparx5
,
249 struct vcap_admin
*admin
)
251 _sparx5_vcap_range_init(sparx5
, admin
, admin
->first_valid_addr
,
252 admin
->last_valid_addr
-
253 admin
->first_valid_addr
);
256 /* Get the keyset name from the sparx5 VCAP model */
257 static const char *sparx5_vcap_keyset_name(struct net_device
*ndev
,
258 enum vcap_keyfield_set keyset
)
260 struct sparx5_port
*port
= netdev_priv(ndev
);
262 return vcap_keyset_name(port
->sparx5
->vcap_ctrl
, keyset
);
265 /* Check if this is the first lookup of IS0 */
266 static bool sparx5_vcap_is0_is_first_chain(struct vcap_rule
*rule
)
268 return (rule
->vcap_chain_id
>= SPARX5_VCAP_CID_IS0_L0
&&
269 rule
->vcap_chain_id
< SPARX5_VCAP_CID_IS0_L1
) ||
270 ((rule
->vcap_chain_id
>= SPARX5_VCAP_CID_IS0_L2
&&
271 rule
->vcap_chain_id
< SPARX5_VCAP_CID_IS0_L3
)) ||
272 ((rule
->vcap_chain_id
>= SPARX5_VCAP_CID_IS0_L4
&&
273 rule
->vcap_chain_id
< SPARX5_VCAP_CID_IS0_L5
));
276 /* Check if this is the first lookup of IS2 */
277 static bool sparx5_vcap_is2_is_first_chain(struct vcap_rule
*rule
)
279 return (rule
->vcap_chain_id
>= SPARX5_VCAP_CID_IS2_L0
&&
280 rule
->vcap_chain_id
< SPARX5_VCAP_CID_IS2_L1
) ||
281 ((rule
->vcap_chain_id
>= SPARX5_VCAP_CID_IS2_L2
&&
282 rule
->vcap_chain_id
< SPARX5_VCAP_CID_IS2_L3
));
285 static bool sparx5_vcap_es2_is_first_chain(struct vcap_rule
*rule
)
287 return (rule
->vcap_chain_id
>= SPARX5_VCAP_CID_ES2_L0
&&
288 rule
->vcap_chain_id
< SPARX5_VCAP_CID_ES2_L1
);
291 /* Set the narrow range ingress port mask on a rule */
292 static void sparx5_vcap_add_ingress_range_port_mask(struct vcap_rule
*rule
,
293 struct net_device
*ndev
)
295 struct sparx5_port
*port
= netdev_priv(ndev
);
299 range
= port
->portno
/ BITS_PER_TYPE(u32
);
300 /* Port bit set to match-any */
301 port_mask
= ~BIT(port
->portno
% BITS_PER_TYPE(u32
));
302 vcap_rule_add_key_u32(rule
, VCAP_KF_IF_IGR_PORT_MASK_SEL
, 0, 0xf);
303 vcap_rule_add_key_u32(rule
, VCAP_KF_IF_IGR_PORT_MASK_RNG
, range
, 0xf);
304 vcap_rule_add_key_u32(rule
, VCAP_KF_IF_IGR_PORT_MASK
, 0, port_mask
);
307 /* Set the wide range ingress port mask on a rule */
308 static void sparx5_vcap_add_wide_port_mask(struct vcap_rule
*rule
,
309 struct net_device
*ndev
)
311 struct sparx5_port
*port
= netdev_priv(ndev
);
312 struct vcap_u72_key port_mask
;
315 /* Port bit set to match-any */
316 memset(port_mask
.value
, 0, sizeof(port_mask
.value
));
317 memset(port_mask
.mask
, 0xff, sizeof(port_mask
.mask
));
318 range
= port
->portno
/ BITS_PER_BYTE
;
319 port_mask
.mask
[range
] = ~BIT(port
->portno
% BITS_PER_BYTE
);
320 vcap_rule_add_key_u72(rule
, VCAP_KF_IF_IGR_PORT_MASK
, &port_mask
);
323 static void sparx5_vcap_add_egress_range_port_mask(struct vcap_rule
*rule
,
324 struct net_device
*ndev
)
326 struct sparx5_port
*port
= netdev_priv(ndev
);
330 /* Mask range selects:
331 * 0-2: Physical/Logical egress port number 0-31, 32–63, 64.
332 * 3-5: Virtual Interface Number 0-31, 32-63, 64.
333 * 6: CPU queue Number 0-7.
335 * Use physical/logical port ranges (0-2)
337 range
= port
->portno
/ BITS_PER_TYPE(u32
);
338 /* Port bit set to match-any */
339 port_mask
= ~BIT(port
->portno
% BITS_PER_TYPE(u32
));
340 vcap_rule_add_key_u32(rule
, VCAP_KF_IF_EGR_PORT_MASK_RNG
, range
, 0xf);
341 vcap_rule_add_key_u32(rule
, VCAP_KF_IF_EGR_PORT_MASK
, 0, port_mask
);
344 /* Convert IS0 chain id to vcap lookup id */
345 static int sparx5_vcap_is0_cid_to_lookup(int cid
)
349 if (cid
>= SPARX5_VCAP_CID_IS0_L1
&& cid
< SPARX5_VCAP_CID_IS0_L2
)
351 else if (cid
>= SPARX5_VCAP_CID_IS0_L2
&& cid
< SPARX5_VCAP_CID_IS0_L3
)
353 else if (cid
>= SPARX5_VCAP_CID_IS0_L3
&& cid
< SPARX5_VCAP_CID_IS0_L4
)
355 else if (cid
>= SPARX5_VCAP_CID_IS0_L4
&& cid
< SPARX5_VCAP_CID_IS0_L5
)
357 else if (cid
>= SPARX5_VCAP_CID_IS0_L5
&& cid
< SPARX5_VCAP_CID_IS0_MAX
)
363 /* Convert IS2 chain id to vcap lookup id */
364 static int sparx5_vcap_is2_cid_to_lookup(int cid
)
368 if (cid
>= SPARX5_VCAP_CID_IS2_L1
&& cid
< SPARX5_VCAP_CID_IS2_L2
)
370 else if (cid
>= SPARX5_VCAP_CID_IS2_L2
&& cid
< SPARX5_VCAP_CID_IS2_L3
)
372 else if (cid
>= SPARX5_VCAP_CID_IS2_L3
&& cid
< SPARX5_VCAP_CID_IS2_MAX
)
378 /* Convert ES2 chain id to vcap lookup id */
379 static int sparx5_vcap_es2_cid_to_lookup(int cid
)
383 if (cid
>= SPARX5_VCAP_CID_ES2_L1
)
389 /* Add ethernet type IS0 keyset to a list */
391 sparx5_vcap_is0_get_port_etype_keysets(struct vcap_keyset_list
*keysetlist
,
394 switch (ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_GET(value
)) {
395 case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE
:
396 vcap_keyset_list_add(keysetlist
, VCAP_KFS_NORMAL_7TUPLE
);
398 case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4
:
399 vcap_keyset_list_add(keysetlist
, VCAP_KFS_NORMAL_5TUPLE_IP4
);
404 /* Return the list of keysets for the vcap port configuration */
405 static int sparx5_vcap_is0_get_port_keysets(struct net_device
*ndev
,
407 struct vcap_keyset_list
*keysetlist
,
410 struct sparx5_port
*port
= netdev_priv(ndev
);
411 struct sparx5
*sparx5
= port
->sparx5
;
412 int portno
= port
->portno
;
415 value
= spx5_rd(sparx5
, ANA_CL_ADV_CL_CFG(portno
, lookup
));
417 /* Collect all keysets for the port in a list */
418 if (l3_proto
== ETH_P_ALL
)
419 sparx5_vcap_is0_get_port_etype_keysets(keysetlist
, value
);
421 if (l3_proto
== ETH_P_ALL
|| l3_proto
== ETH_P_IP
)
422 switch (ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_GET(value
)) {
423 case VCAP_IS0_PS_ETYPE_DEFAULT
:
424 sparx5_vcap_is0_get_port_etype_keysets(keysetlist
,
427 case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE
:
428 vcap_keyset_list_add(keysetlist
,
429 VCAP_KFS_NORMAL_7TUPLE
);
431 case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4
:
432 vcap_keyset_list_add(keysetlist
,
433 VCAP_KFS_NORMAL_5TUPLE_IP4
);
437 if (l3_proto
== ETH_P_ALL
|| l3_proto
== ETH_P_IPV6
)
438 switch (ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_GET(value
)) {
439 case VCAP_IS0_PS_ETYPE_DEFAULT
:
440 sparx5_vcap_is0_get_port_etype_keysets(keysetlist
,
443 case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE
:
444 vcap_keyset_list_add(keysetlist
,
445 VCAP_KFS_NORMAL_7TUPLE
);
447 case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4
:
448 vcap_keyset_list_add(keysetlist
,
449 VCAP_KFS_NORMAL_5TUPLE_IP4
);
453 if (l3_proto
!= ETH_P_IP
&& l3_proto
!= ETH_P_IPV6
)
454 sparx5_vcap_is0_get_port_etype_keysets(keysetlist
, value
);
458 /* Return the list of keysets for the vcap port configuration */
459 static int sparx5_vcap_is2_get_port_keysets(struct net_device
*ndev
,
461 struct vcap_keyset_list
*keysetlist
,
464 struct sparx5_port
*port
= netdev_priv(ndev
);
465 struct sparx5
*sparx5
= port
->sparx5
;
466 int portno
= port
->portno
;
469 value
= spx5_rd(sparx5
, ANA_ACL_VCAP_S2_KEY_SEL(portno
, lookup
));
471 /* Collect all keysets for the port in a list */
472 if (l3_proto
== ETH_P_ALL
|| l3_proto
== ETH_P_ARP
) {
473 switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value
)) {
474 case VCAP_IS2_PS_ARP_MAC_ETYPE
:
475 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
477 case VCAP_IS2_PS_ARP_ARP
:
478 vcap_keyset_list_add(keysetlist
, VCAP_KFS_ARP
);
483 if (l3_proto
== ETH_P_ALL
|| l3_proto
== ETH_P_IP
) {
484 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value
)) {
485 case VCAP_IS2_PS_IPV4_UC_MAC_ETYPE
:
486 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
488 case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER
:
489 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_TCP_UDP
);
490 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_OTHER
);
492 case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE
:
493 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP_7TUPLE
);
497 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value
)) {
498 case VCAP_IS2_PS_IPV4_MC_MAC_ETYPE
:
499 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
501 case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER
:
502 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_TCP_UDP
);
503 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_OTHER
);
505 case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE
:
506 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP_7TUPLE
);
511 if (l3_proto
== ETH_P_ALL
|| l3_proto
== ETH_P_IPV6
) {
512 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value
)) {
513 case VCAP_IS2_PS_IPV6_UC_MAC_ETYPE
:
514 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
516 case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE
:
517 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP_7TUPLE
);
519 case VCAP_IS2_PS_IPV6_UC_IP6_STD
:
520 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP6_STD
);
522 case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER
:
523 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_TCP_UDP
);
524 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_OTHER
);
528 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value
)) {
529 case VCAP_IS2_PS_IPV6_MC_MAC_ETYPE
:
530 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
532 case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE
:
533 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP_7TUPLE
);
535 case VCAP_IS2_PS_IPV6_MC_IP6_STD
:
536 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP6_STD
);
538 case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER
:
539 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_TCP_UDP
);
540 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_OTHER
);
542 case VCAP_IS2_PS_IPV6_MC_IP6_VID
:
548 if (l3_proto
!= ETH_P_ARP
&& l3_proto
!= ETH_P_IP
&&
549 l3_proto
!= ETH_P_IPV6
) {
550 switch (ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_GET(value
)) {
551 case VCAP_IS2_PS_NONETH_MAC_ETYPE
:
552 /* IS2 non-classified frames generate MAC_ETYPE */
553 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
560 /* Return the keysets for the vcap port IP4 traffic class configuration */
562 sparx5_vcap_es2_get_port_ipv4_keysets(struct vcap_keyset_list
*keysetlist
,
565 switch (EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_GET(value
)) {
566 case VCAP_ES2_PS_IPV4_MAC_ETYPE
:
567 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
569 case VCAP_ES2_PS_IPV4_IP_7TUPLE
:
570 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP_7TUPLE
);
572 case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_VID
:
573 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_TCP_UDP
);
575 case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER
:
576 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_TCP_UDP
);
577 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_OTHER
);
579 case VCAP_ES2_PS_IPV4_IP4_VID
:
582 case VCAP_ES2_PS_IPV4_IP4_OTHER
:
583 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP4_OTHER
);
588 /* Return the list of keysets for the vcap port configuration */
589 static int sparx5_vcap_es0_get_port_keysets(struct net_device
*ndev
,
590 struct vcap_keyset_list
*keysetlist
,
593 struct sparx5_port
*port
= netdev_priv(ndev
);
594 struct sparx5
*sparx5
= port
->sparx5
;
595 int portno
= port
->portno
;
598 value
= spx5_rd(sparx5
, REW_RTAG_ETAG_CTRL(portno
));
600 /* Collect all keysets for the port in a list */
601 switch (REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA_GET(value
)) {
602 case VCAP_ES0_PS_NORMAL_SELECTION
:
603 case VCAP_ES0_PS_FORCE_ISDX_LOOKUPS
:
604 vcap_keyset_list_add(keysetlist
, VCAP_KFS_ISDX
);
612 /* Return the list of keysets for the vcap port configuration */
613 static int sparx5_vcap_es2_get_port_keysets(struct net_device
*ndev
,
615 struct vcap_keyset_list
*keysetlist
,
618 struct sparx5_port
*port
= netdev_priv(ndev
);
619 struct sparx5
*sparx5
= port
->sparx5
;
620 int portno
= port
->portno
;
623 value
= spx5_rd(sparx5
, EACL_VCAP_ES2_KEY_SEL(portno
, lookup
));
625 /* Collect all keysets for the port in a list */
626 if (l3_proto
== ETH_P_ALL
|| l3_proto
== ETH_P_ARP
) {
627 switch (EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_GET(value
)) {
628 case VCAP_ES2_PS_ARP_MAC_ETYPE
:
629 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
631 case VCAP_ES2_PS_ARP_ARP
:
632 vcap_keyset_list_add(keysetlist
, VCAP_KFS_ARP
);
637 if (l3_proto
== ETH_P_ALL
|| l3_proto
== ETH_P_IP
)
638 sparx5_vcap_es2_get_port_ipv4_keysets(keysetlist
, value
);
640 if (l3_proto
== ETH_P_ALL
|| l3_proto
== ETH_P_IPV6
) {
641 switch (EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_GET(value
)) {
642 case VCAP_ES2_PS_IPV6_MAC_ETYPE
:
643 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
645 case VCAP_ES2_PS_IPV6_IP_7TUPLE
:
646 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP_7TUPLE
);
648 case VCAP_ES2_PS_IPV6_IP_7TUPLE_VID
:
649 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP_7TUPLE
);
651 case VCAP_ES2_PS_IPV6_IP_7TUPLE_STD
:
652 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP_7TUPLE
);
653 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP6_STD
);
655 case VCAP_ES2_PS_IPV6_IP6_VID
:
658 case VCAP_ES2_PS_IPV6_IP6_STD
:
659 vcap_keyset_list_add(keysetlist
, VCAP_KFS_IP6_STD
);
661 case VCAP_ES2_PS_IPV6_IP4_DOWNGRADE
:
662 sparx5_vcap_es2_get_port_ipv4_keysets(keysetlist
,
668 if (l3_proto
!= ETH_P_ARP
&& l3_proto
!= ETH_P_IP
&&
669 l3_proto
!= ETH_P_IPV6
) {
670 vcap_keyset_list_add(keysetlist
, VCAP_KFS_MAC_ETYPE
);
675 /* Get the port keyset for the vcap lookup */
676 int sparx5_vcap_get_port_keyset(struct net_device
*ndev
,
677 struct vcap_admin
*admin
,
680 struct vcap_keyset_list
*kslist
)
682 int lookup
, err
= -EINVAL
;
683 struct sparx5_port
*port
;
685 switch (admin
->vtype
) {
687 lookup
= sparx5_vcap_is0_cid_to_lookup(cid
);
688 err
= sparx5_vcap_is0_get_port_keysets(ndev
, lookup
, kslist
,
692 lookup
= sparx5_vcap_is2_cid_to_lookup(cid
);
693 err
= sparx5_vcap_is2_get_port_keysets(ndev
, lookup
, kslist
,
697 err
= sparx5_vcap_es0_get_port_keysets(ndev
, kslist
, l3_proto
);
700 lookup
= sparx5_vcap_es2_cid_to_lookup(cid
);
701 err
= sparx5_vcap_es2_get_port_keysets(ndev
, lookup
, kslist
,
705 port
= netdev_priv(ndev
);
706 sparx5_vcap_type_err(port
->sparx5
, admin
, __func__
);
712 /* Check if the ethertype is supported by the vcap port classification */
713 bool sparx5_vcap_is_known_etype(struct vcap_admin
*admin
, u16 etype
)
715 const u16
*known_etypes
;
718 switch (admin
->vtype
) {
720 known_etypes
= sparx5_vcap_is0_known_etypes
;
721 size
= ARRAY_SIZE(sparx5_vcap_is0_known_etypes
);
724 known_etypes
= sparx5_vcap_is2_known_etypes
;
725 size
= ARRAY_SIZE(sparx5_vcap_is2_known_etypes
);
730 known_etypes
= sparx5_vcap_es2_known_etypes
;
731 size
= ARRAY_SIZE(sparx5_vcap_es2_known_etypes
);
736 for (idx
= 0; idx
< size
; ++idx
)
737 if (known_etypes
[idx
] == etype
)
742 /* API callback used for validating a field keyset (check the port keysets) */
743 static enum vcap_keyfield_set
744 sparx5_vcap_validate_keyset(struct net_device
*ndev
,
745 struct vcap_admin
*admin
,
746 struct vcap_rule
*rule
,
747 struct vcap_keyset_list
*kslist
,
750 struct vcap_keyset_list keysetlist
= {};
751 enum vcap_keyfield_set keysets
[10] = {};
752 struct sparx5_port
*port
;
753 int idx
, jdx
, lookup
;
755 if (!kslist
|| kslist
->cnt
== 0)
756 return VCAP_KFS_NO_VALUE
;
758 keysetlist
.max
= ARRAY_SIZE(keysets
);
759 keysetlist
.keysets
= keysets
;
761 /* Get a list of currently configured keysets in the lookups */
762 switch (admin
->vtype
) {
764 lookup
= sparx5_vcap_is0_cid_to_lookup(rule
->vcap_chain_id
);
765 sparx5_vcap_is0_get_port_keysets(ndev
, lookup
, &keysetlist
,
769 lookup
= sparx5_vcap_is2_cid_to_lookup(rule
->vcap_chain_id
);
770 sparx5_vcap_is2_get_port_keysets(ndev
, lookup
, &keysetlist
,
774 sparx5_vcap_es0_get_port_keysets(ndev
, &keysetlist
, l3_proto
);
777 lookup
= sparx5_vcap_es2_cid_to_lookup(rule
->vcap_chain_id
);
778 sparx5_vcap_es2_get_port_keysets(ndev
, lookup
, &keysetlist
,
782 port
= netdev_priv(ndev
);
783 sparx5_vcap_type_err(port
->sparx5
, admin
, __func__
);
787 /* Check if there is a match and return the match */
788 for (idx
= 0; idx
< kslist
->cnt
; ++idx
)
789 for (jdx
= 0; jdx
< keysetlist
.cnt
; ++jdx
)
790 if (kslist
->keysets
[idx
] == keysets
[jdx
])
791 return kslist
->keysets
[idx
];
793 pr_err("%s:%d: %s not supported in port key selection\n",
795 sparx5_vcap_keyset_name(ndev
, kslist
->keysets
[0]));
800 static void sparx5_vcap_ingress_add_default_fields(struct net_device
*ndev
,
801 struct vcap_admin
*admin
,
802 struct vcap_rule
*rule
)
804 const struct vcap_field
*field
;
807 /* Add ingress port mask matching the net device */
808 field
= vcap_lookup_keyfield(rule
, VCAP_KF_IF_IGR_PORT_MASK
);
809 if (field
&& field
->width
== SPX5_PORTS
)
810 sparx5_vcap_add_wide_port_mask(rule
, ndev
);
811 else if (field
&& field
->width
== BITS_PER_TYPE(u32
))
812 sparx5_vcap_add_ingress_range_port_mask(rule
, ndev
);
814 pr_err("%s:%d: %s: could not add an ingress port mask for: %s\n",
815 __func__
, __LINE__
, netdev_name(ndev
),
816 sparx5_vcap_keyset_name(ndev
, rule
->keyset
));
818 if (admin
->vtype
== VCAP_TYPE_IS0
)
819 is_first
= sparx5_vcap_is0_is_first_chain(rule
);
821 is_first
= sparx5_vcap_is2_is_first_chain(rule
);
823 /* Add key that selects the first/second lookup */
825 vcap_rule_add_key_bit(rule
, VCAP_KF_LOOKUP_FIRST_IS
,
828 vcap_rule_add_key_bit(rule
, VCAP_KF_LOOKUP_FIRST_IS
,
832 static void sparx5_vcap_es0_add_default_fields(struct net_device
*ndev
,
833 struct vcap_admin
*admin
,
834 struct vcap_rule
*rule
)
836 struct sparx5_port
*port
= netdev_priv(ndev
);
838 vcap_rule_add_key_u32(rule
, VCAP_KF_IF_EGR_PORT_NO
, port
->portno
, ~0);
839 /* Match untagged frames if there was no VLAN key */
840 vcap_rule_add_key_u32(rule
, VCAP_KF_8021Q_TPID
, SPX5_TPID_SEL_UNTAGGED
,
844 static void sparx5_vcap_es2_add_default_fields(struct net_device
*ndev
,
845 struct vcap_admin
*admin
,
846 struct vcap_rule
*rule
)
848 const struct vcap_field
*field
;
851 /* Add egress port mask matching the net device */
852 field
= vcap_lookup_keyfield(rule
, VCAP_KF_IF_EGR_PORT_MASK
);
854 sparx5_vcap_add_egress_range_port_mask(rule
, ndev
);
856 /* Add key that selects the first/second lookup */
857 is_first
= sparx5_vcap_es2_is_first_chain(rule
);
860 vcap_rule_add_key_bit(rule
, VCAP_KF_LOOKUP_FIRST_IS
,
863 vcap_rule_add_key_bit(rule
, VCAP_KF_LOOKUP_FIRST_IS
,
867 /* API callback used for adding default fields to a rule */
868 static void sparx5_vcap_add_default_fields(struct net_device
*ndev
,
869 struct vcap_admin
*admin
,
870 struct vcap_rule
*rule
)
872 struct sparx5_port
*port
;
874 /* add the lookup bit */
875 switch (admin
->vtype
) {
878 sparx5_vcap_ingress_add_default_fields(ndev
, admin
, rule
);
881 sparx5_vcap_es0_add_default_fields(ndev
, admin
, rule
);
884 sparx5_vcap_es2_add_default_fields(ndev
, admin
, rule
);
887 port
= netdev_priv(ndev
);
888 sparx5_vcap_type_err(port
->sparx5
, admin
, __func__
);
893 /* API callback used for erasing the vcap cache area (not the register area) */
894 static void sparx5_vcap_cache_erase(struct vcap_admin
*admin
)
896 memset(admin
->cache
.keystream
, 0, STREAMSIZE
);
897 memset(admin
->cache
.maskstream
, 0, STREAMSIZE
);
898 memset(admin
->cache
.actionstream
, 0, STREAMSIZE
);
899 memset(&admin
->cache
.counter
, 0, sizeof(admin
->cache
.counter
));
902 static void sparx5_vcap_is0_cache_write(struct sparx5
*sparx5
,
903 struct vcap_admin
*admin
,
904 enum vcap_selection sel
,
908 u32
*keystr
, *mskstr
, *actstr
;
911 keystr
= &admin
->cache
.keystream
[start
];
912 mskstr
= &admin
->cache
.maskstream
[start
];
913 actstr
= &admin
->cache
.actionstream
[start
];
917 for (idx
= 0; idx
< count
; ++idx
) {
918 /* Avoid 'match-off' by setting value & mask */
919 spx5_wr(keystr
[idx
] & mskstr
[idx
], sparx5
,
920 VCAP_SUPER_VCAP_ENTRY_DAT(idx
));
921 spx5_wr(~mskstr
[idx
], sparx5
,
922 VCAP_SUPER_VCAP_MASK_DAT(idx
));
925 case VCAP_SEL_ACTION
:
926 for (idx
= 0; idx
< count
; ++idx
)
927 spx5_wr(actstr
[idx
], sparx5
,
928 VCAP_SUPER_VCAP_ACTION_DAT(idx
));
931 pr_err("%s:%d: cannot write all streams at once\n",
938 if (sel
& VCAP_SEL_COUNTER
)
939 spx5_wr(admin
->cache
.counter
, sparx5
,
940 VCAP_SUPER_VCAP_CNT_DAT(0));
943 static void sparx5_vcap_is2_cache_write(struct sparx5
*sparx5
,
944 struct vcap_admin
*admin
,
945 enum vcap_selection sel
,
949 u32
*keystr
, *mskstr
, *actstr
;
952 keystr
= &admin
->cache
.keystream
[start
];
953 mskstr
= &admin
->cache
.maskstream
[start
];
954 actstr
= &admin
->cache
.actionstream
[start
];
958 for (idx
= 0; idx
< count
; ++idx
) {
959 /* Avoid 'match-off' by setting value & mask */
960 spx5_wr(keystr
[idx
] & mskstr
[idx
], sparx5
,
961 VCAP_SUPER_VCAP_ENTRY_DAT(idx
));
962 spx5_wr(~mskstr
[idx
], sparx5
,
963 VCAP_SUPER_VCAP_MASK_DAT(idx
));
966 case VCAP_SEL_ACTION
:
967 for (idx
= 0; idx
< count
; ++idx
)
968 spx5_wr(actstr
[idx
], sparx5
,
969 VCAP_SUPER_VCAP_ACTION_DAT(idx
));
972 pr_err("%s:%d: cannot write all streams at once\n",
978 if (sel
& VCAP_SEL_COUNTER
) {
979 start
= start
& 0xfff; /* counter limit */
980 if (admin
->vinst
== 0)
981 spx5_wr(admin
->cache
.counter
, sparx5
,
982 ANA_ACL_CNT_A(start
));
984 spx5_wr(admin
->cache
.counter
, sparx5
,
985 ANA_ACL_CNT_B(start
));
986 spx5_wr(admin
->cache
.sticky
, sparx5
,
987 VCAP_SUPER_VCAP_CNT_DAT(0));
991 /* Use ESDX counters located in the XQS */
992 static void sparx5_es0_write_esdx_counter(struct sparx5
*sparx5
,
993 struct vcap_admin
*admin
, u32 id
)
995 mutex_lock(&sparx5
->queue_stats_lock
);
996 spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(id
), sparx5
, XQS_STAT_CFG
);
997 spx5_wr(admin
->cache
.counter
, sparx5
,
998 XQS_CNT(SPARX5_STAT_ESDX_GRN_PKTS
));
999 spx5_wr(0, sparx5
, XQS_CNT(SPARX5_STAT_ESDX_YEL_PKTS
));
1000 mutex_unlock(&sparx5
->queue_stats_lock
);
1003 static void sparx5_vcap_es0_cache_write(struct sparx5
*sparx5
,
1004 struct vcap_admin
*admin
,
1005 enum vcap_selection sel
,
1009 u32
*keystr
, *mskstr
, *actstr
;
1012 keystr
= &admin
->cache
.keystream
[start
];
1013 mskstr
= &admin
->cache
.maskstream
[start
];
1014 actstr
= &admin
->cache
.actionstream
[start
];
1017 case VCAP_SEL_ENTRY
:
1018 for (idx
= 0; idx
< count
; ++idx
) {
1019 /* Avoid 'match-off' by setting value & mask */
1020 spx5_wr(keystr
[idx
] & mskstr
[idx
], sparx5
,
1021 VCAP_ES0_VCAP_ENTRY_DAT(idx
));
1022 spx5_wr(~mskstr
[idx
], sparx5
,
1023 VCAP_ES0_VCAP_MASK_DAT(idx
));
1026 case VCAP_SEL_ACTION
:
1027 for (idx
= 0; idx
< count
; ++idx
)
1028 spx5_wr(actstr
[idx
], sparx5
,
1029 VCAP_ES0_VCAP_ACTION_DAT(idx
));
1032 pr_err("%s:%d: cannot write all streams at once\n",
1033 __func__
, __LINE__
);
1038 if (sel
& VCAP_SEL_COUNTER
) {
1039 spx5_wr(admin
->cache
.counter
, sparx5
, VCAP_ES0_VCAP_CNT_DAT(0));
1040 sparx5_es0_write_esdx_counter(sparx5
, admin
, start
);
1044 static void sparx5_vcap_es2_cache_write(struct sparx5
*sparx5
,
1045 struct vcap_admin
*admin
,
1046 enum vcap_selection sel
,
1050 u32
*keystr
, *mskstr
, *actstr
;
1053 keystr
= &admin
->cache
.keystream
[start
];
1054 mskstr
= &admin
->cache
.maskstream
[start
];
1055 actstr
= &admin
->cache
.actionstream
[start
];
1058 case VCAP_SEL_ENTRY
:
1059 for (idx
= 0; idx
< count
; ++idx
) {
1060 /* Avoid 'match-off' by setting value & mask */
1061 spx5_wr(keystr
[idx
] & mskstr
[idx
], sparx5
,
1062 VCAP_ES2_VCAP_ENTRY_DAT(idx
));
1063 spx5_wr(~mskstr
[idx
], sparx5
,
1064 VCAP_ES2_VCAP_MASK_DAT(idx
));
1067 case VCAP_SEL_ACTION
:
1068 for (idx
= 0; idx
< count
; ++idx
)
1069 spx5_wr(actstr
[idx
], sparx5
,
1070 VCAP_ES2_VCAP_ACTION_DAT(idx
));
1073 pr_err("%s:%d: cannot write all streams at once\n",
1074 __func__
, __LINE__
);
1079 if (sel
& VCAP_SEL_COUNTER
) {
1080 start
= start
& 0x7ff; /* counter limit */
1081 spx5_wr(admin
->cache
.counter
, sparx5
, EACL_ES2_CNT(start
));
1082 spx5_wr(admin
->cache
.sticky
, sparx5
, VCAP_ES2_VCAP_CNT_DAT(0));
1086 /* API callback used for writing to the VCAP cache */
1087 static void sparx5_vcap_cache_write(struct net_device
*ndev
,
1088 struct vcap_admin
*admin
,
1089 enum vcap_selection sel
,
1093 struct sparx5_port
*port
= netdev_priv(ndev
);
1094 struct sparx5
*sparx5
= port
->sparx5
;
1096 switch (admin
->vtype
) {
1098 sparx5_vcap_is0_cache_write(sparx5
, admin
, sel
, start
, count
);
1101 sparx5_vcap_is2_cache_write(sparx5
, admin
, sel
, start
, count
);
1104 sparx5_vcap_es0_cache_write(sparx5
, admin
, sel
, start
, count
);
1107 sparx5_vcap_es2_cache_write(sparx5
, admin
, sel
, start
, count
);
1110 sparx5_vcap_type_err(sparx5
, admin
, __func__
);
1115 static void sparx5_vcap_is0_cache_read(struct sparx5
*sparx5
,
1116 struct vcap_admin
*admin
,
1117 enum vcap_selection sel
,
1121 u32
*keystr
, *mskstr
, *actstr
;
1124 keystr
= &admin
->cache
.keystream
[start
];
1125 mskstr
= &admin
->cache
.maskstream
[start
];
1126 actstr
= &admin
->cache
.actionstream
[start
];
1128 if (sel
& VCAP_SEL_ENTRY
) {
1129 for (idx
= 0; idx
< count
; ++idx
) {
1130 keystr
[idx
] = spx5_rd(sparx5
,
1131 VCAP_SUPER_VCAP_ENTRY_DAT(idx
));
1132 mskstr
[idx
] = ~spx5_rd(sparx5
,
1133 VCAP_SUPER_VCAP_MASK_DAT(idx
));
1137 if (sel
& VCAP_SEL_ACTION
)
1138 for (idx
= 0; idx
< count
; ++idx
)
1139 actstr
[idx
] = spx5_rd(sparx5
,
1140 VCAP_SUPER_VCAP_ACTION_DAT(idx
));
1142 if (sel
& VCAP_SEL_COUNTER
) {
1143 admin
->cache
.counter
=
1144 spx5_rd(sparx5
, VCAP_SUPER_VCAP_CNT_DAT(0));
1145 admin
->cache
.sticky
=
1146 spx5_rd(sparx5
, VCAP_SUPER_VCAP_CNT_DAT(0));
1150 static void sparx5_vcap_is2_cache_read(struct sparx5
*sparx5
,
1151 struct vcap_admin
*admin
,
1152 enum vcap_selection sel
,
1156 u32
*keystr
, *mskstr
, *actstr
;
1159 keystr
= &admin
->cache
.keystream
[start
];
1160 mskstr
= &admin
->cache
.maskstream
[start
];
1161 actstr
= &admin
->cache
.actionstream
[start
];
1163 if (sel
& VCAP_SEL_ENTRY
) {
1164 for (idx
= 0; idx
< count
; ++idx
) {
1165 keystr
[idx
] = spx5_rd(sparx5
,
1166 VCAP_SUPER_VCAP_ENTRY_DAT(idx
));
1167 mskstr
[idx
] = ~spx5_rd(sparx5
,
1168 VCAP_SUPER_VCAP_MASK_DAT(idx
));
1172 if (sel
& VCAP_SEL_ACTION
)
1173 for (idx
= 0; idx
< count
; ++idx
)
1174 actstr
[idx
] = spx5_rd(sparx5
,
1175 VCAP_SUPER_VCAP_ACTION_DAT(idx
));
1177 if (sel
& VCAP_SEL_COUNTER
) {
1178 start
= start
& 0xfff; /* counter limit */
1179 if (admin
->vinst
== 0)
1180 admin
->cache
.counter
=
1181 spx5_rd(sparx5
, ANA_ACL_CNT_A(start
));
1183 admin
->cache
.counter
=
1184 spx5_rd(sparx5
, ANA_ACL_CNT_B(start
));
1185 admin
->cache
.sticky
=
1186 spx5_rd(sparx5
, VCAP_SUPER_VCAP_CNT_DAT(0));
1190 /* Use ESDX counters located in the XQS */
1191 static void sparx5_es0_read_esdx_counter(struct sparx5
*sparx5
,
1192 struct vcap_admin
*admin
, u32 id
)
1196 mutex_lock(&sparx5
->queue_stats_lock
);
1197 spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(id
), sparx5
, XQS_STAT_CFG
);
1198 counter
= spx5_rd(sparx5
, XQS_CNT(SPARX5_STAT_ESDX_GRN_PKTS
)) +
1199 spx5_rd(sparx5
, XQS_CNT(SPARX5_STAT_ESDX_YEL_PKTS
));
1200 mutex_unlock(&sparx5
->queue_stats_lock
);
1202 admin
->cache
.counter
= counter
;
1205 static void sparx5_vcap_es0_cache_read(struct sparx5
*sparx5
,
1206 struct vcap_admin
*admin
,
1207 enum vcap_selection sel
,
1211 u32
*keystr
, *mskstr
, *actstr
;
1214 keystr
= &admin
->cache
.keystream
[start
];
1215 mskstr
= &admin
->cache
.maskstream
[start
];
1216 actstr
= &admin
->cache
.actionstream
[start
];
1218 if (sel
& VCAP_SEL_ENTRY
) {
1219 for (idx
= 0; idx
< count
; ++idx
) {
1221 spx5_rd(sparx5
, VCAP_ES0_VCAP_ENTRY_DAT(idx
));
1223 ~spx5_rd(sparx5
, VCAP_ES0_VCAP_MASK_DAT(idx
));
1227 if (sel
& VCAP_SEL_ACTION
)
1228 for (idx
= 0; idx
< count
; ++idx
)
1230 spx5_rd(sparx5
, VCAP_ES0_VCAP_ACTION_DAT(idx
));
1232 if (sel
& VCAP_SEL_COUNTER
) {
1233 admin
->cache
.counter
=
1234 spx5_rd(sparx5
, VCAP_ES0_VCAP_CNT_DAT(0));
1235 admin
->cache
.sticky
= admin
->cache
.counter
;
1236 sparx5_es0_read_esdx_counter(sparx5
, admin
, start
);
1240 static void sparx5_vcap_es2_cache_read(struct sparx5
*sparx5
,
1241 struct vcap_admin
*admin
,
1242 enum vcap_selection sel
,
1246 u32
*keystr
, *mskstr
, *actstr
;
1249 keystr
= &admin
->cache
.keystream
[start
];
1250 mskstr
= &admin
->cache
.maskstream
[start
];
1251 actstr
= &admin
->cache
.actionstream
[start
];
1253 if (sel
& VCAP_SEL_ENTRY
) {
1254 for (idx
= 0; idx
< count
; ++idx
) {
1256 spx5_rd(sparx5
, VCAP_ES2_VCAP_ENTRY_DAT(idx
));
1258 ~spx5_rd(sparx5
, VCAP_ES2_VCAP_MASK_DAT(idx
));
1262 if (sel
& VCAP_SEL_ACTION
)
1263 for (idx
= 0; idx
< count
; ++idx
)
1265 spx5_rd(sparx5
, VCAP_ES2_VCAP_ACTION_DAT(idx
));
1267 if (sel
& VCAP_SEL_COUNTER
) {
1268 start
= start
& 0x7ff; /* counter limit */
1269 admin
->cache
.counter
=
1270 spx5_rd(sparx5
, EACL_ES2_CNT(start
));
1271 admin
->cache
.sticky
=
1272 spx5_rd(sparx5
, VCAP_ES2_VCAP_CNT_DAT(0));
1276 /* API callback used for reading from the VCAP into the VCAP cache */
1277 static void sparx5_vcap_cache_read(struct net_device
*ndev
,
1278 struct vcap_admin
*admin
,
1279 enum vcap_selection sel
,
1283 struct sparx5_port
*port
= netdev_priv(ndev
);
1284 struct sparx5
*sparx5
= port
->sparx5
;
1286 switch (admin
->vtype
) {
1288 sparx5_vcap_is0_cache_read(sparx5
, admin
, sel
, start
, count
);
1291 sparx5_vcap_is2_cache_read(sparx5
, admin
, sel
, start
, count
);
1294 sparx5_vcap_es0_cache_read(sparx5
, admin
, sel
, start
, count
);
1297 sparx5_vcap_es2_cache_read(sparx5
, admin
, sel
, start
, count
);
1300 sparx5_vcap_type_err(sparx5
, admin
, __func__
);
1305 /* API callback used for initializing a VCAP address range */
1306 static void sparx5_vcap_range_init(struct net_device
*ndev
,
1307 struct vcap_admin
*admin
, u32 addr
,
1310 struct sparx5_port
*port
= netdev_priv(ndev
);
1311 struct sparx5
*sparx5
= port
->sparx5
;
1313 _sparx5_vcap_range_init(sparx5
, admin
, addr
, count
);
1316 static void sparx5_vcap_super_update(struct sparx5
*sparx5
,
1317 enum vcap_command cmd
,
1318 enum vcap_selection sel
, u32 addr
)
1320 bool clear
= (cmd
== VCAP_CMD_INITIALIZE
);
1322 spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(0) |
1323 VCAP_SUPER_CFG_MV_SIZE_SET(0), sparx5
, VCAP_SUPER_CFG
);
1324 spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(cmd
) |
1325 VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY
& sel
) == 0) |
1326 VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION
& sel
) == 0) |
1327 VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER
& sel
) == 0) |
1328 VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr
) |
1329 VCAP_SUPER_CTRL_CLEAR_CACHE_SET(clear
) |
1330 VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true),
1331 sparx5
, VCAP_SUPER_CTRL
);
1332 sparx5_vcap_wait_super_update(sparx5
);
1335 static void sparx5_vcap_es0_update(struct sparx5
*sparx5
,
1336 enum vcap_command cmd
,
1337 enum vcap_selection sel
, u32 addr
)
1339 bool clear
= (cmd
== VCAP_CMD_INITIALIZE
);
1341 spx5_wr(VCAP_ES0_CFG_MV_NUM_POS_SET(0) |
1342 VCAP_ES0_CFG_MV_SIZE_SET(0), sparx5
, VCAP_ES0_CFG
);
1343 spx5_wr(VCAP_ES0_CTRL_UPDATE_CMD_SET(cmd
) |
1344 VCAP_ES0_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY
& sel
) == 0) |
1345 VCAP_ES0_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION
& sel
) == 0) |
1346 VCAP_ES0_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER
& sel
) == 0) |
1347 VCAP_ES0_CTRL_UPDATE_ADDR_SET(addr
) |
1348 VCAP_ES0_CTRL_CLEAR_CACHE_SET(clear
) |
1349 VCAP_ES0_CTRL_UPDATE_SHOT_SET(true),
1350 sparx5
, VCAP_ES0_CTRL
);
1351 sparx5_vcap_wait_es0_update(sparx5
);
1354 static void sparx5_vcap_es2_update(struct sparx5
*sparx5
,
1355 enum vcap_command cmd
,
1356 enum vcap_selection sel
, u32 addr
)
1358 bool clear
= (cmd
== VCAP_CMD_INITIALIZE
);
1360 spx5_wr(VCAP_ES2_CFG_MV_NUM_POS_SET(0) |
1361 VCAP_ES2_CFG_MV_SIZE_SET(0), sparx5
, VCAP_ES2_CFG
);
1362 spx5_wr(VCAP_ES2_CTRL_UPDATE_CMD_SET(cmd
) |
1363 VCAP_ES2_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY
& sel
) == 0) |
1364 VCAP_ES2_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION
& sel
) == 0) |
1365 VCAP_ES2_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER
& sel
) == 0) |
1366 VCAP_ES2_CTRL_UPDATE_ADDR_SET(addr
) |
1367 VCAP_ES2_CTRL_CLEAR_CACHE_SET(clear
) |
1368 VCAP_ES2_CTRL_UPDATE_SHOT_SET(true),
1369 sparx5
, VCAP_ES2_CTRL
);
1370 sparx5_vcap_wait_es2_update(sparx5
);
1373 /* API callback used for updating the VCAP cache */
1374 static void sparx5_vcap_update(struct net_device
*ndev
,
1375 struct vcap_admin
*admin
, enum vcap_command cmd
,
1376 enum vcap_selection sel
, u32 addr
)
1378 struct sparx5_port
*port
= netdev_priv(ndev
);
1379 struct sparx5
*sparx5
= port
->sparx5
;
1381 switch (admin
->vtype
) {
1384 sparx5_vcap_super_update(sparx5
, cmd
, sel
, addr
);
1387 sparx5_vcap_es0_update(sparx5
, cmd
, sel
, addr
);
1390 sparx5_vcap_es2_update(sparx5
, cmd
, sel
, addr
);
1393 sparx5_vcap_type_err(sparx5
, admin
, __func__
);
1398 static void sparx5_vcap_super_move(struct sparx5
*sparx5
,
1400 enum vcap_command cmd
,
1404 spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(mv_num_pos
) |
1405 VCAP_SUPER_CFG_MV_SIZE_SET(mv_size
),
1406 sparx5
, VCAP_SUPER_CFG
);
1407 spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(cmd
) |
1408 VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET(0) |
1409 VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET(0) |
1410 VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET(0) |
1411 VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr
) |
1412 VCAP_SUPER_CTRL_CLEAR_CACHE_SET(false) |
1413 VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true),
1414 sparx5
, VCAP_SUPER_CTRL
);
1415 sparx5_vcap_wait_super_update(sparx5
);
1418 static void sparx5_vcap_es0_move(struct sparx5
*sparx5
,
1420 enum vcap_command cmd
,
1424 spx5_wr(VCAP_ES0_CFG_MV_NUM_POS_SET(mv_num_pos
) |
1425 VCAP_ES0_CFG_MV_SIZE_SET(mv_size
),
1426 sparx5
, VCAP_ES0_CFG
);
1427 spx5_wr(VCAP_ES0_CTRL_UPDATE_CMD_SET(cmd
) |
1428 VCAP_ES0_CTRL_UPDATE_ENTRY_DIS_SET(0) |
1429 VCAP_ES0_CTRL_UPDATE_ACTION_DIS_SET(0) |
1430 VCAP_ES0_CTRL_UPDATE_CNT_DIS_SET(0) |
1431 VCAP_ES0_CTRL_UPDATE_ADDR_SET(addr
) |
1432 VCAP_ES0_CTRL_CLEAR_CACHE_SET(false) |
1433 VCAP_ES0_CTRL_UPDATE_SHOT_SET(true),
1434 sparx5
, VCAP_ES0_CTRL
);
1435 sparx5_vcap_wait_es0_update(sparx5
);
1438 static void sparx5_vcap_es2_move(struct sparx5
*sparx5
,
1440 enum vcap_command cmd
,
1444 spx5_wr(VCAP_ES2_CFG_MV_NUM_POS_SET(mv_num_pos
) |
1445 VCAP_ES2_CFG_MV_SIZE_SET(mv_size
),
1446 sparx5
, VCAP_ES2_CFG
);
1447 spx5_wr(VCAP_ES2_CTRL_UPDATE_CMD_SET(cmd
) |
1448 VCAP_ES2_CTRL_UPDATE_ENTRY_DIS_SET(0) |
1449 VCAP_ES2_CTRL_UPDATE_ACTION_DIS_SET(0) |
1450 VCAP_ES2_CTRL_UPDATE_CNT_DIS_SET(0) |
1451 VCAP_ES2_CTRL_UPDATE_ADDR_SET(addr
) |
1452 VCAP_ES2_CTRL_CLEAR_CACHE_SET(false) |
1453 VCAP_ES2_CTRL_UPDATE_SHOT_SET(true),
1454 sparx5
, VCAP_ES2_CTRL
);
1455 sparx5_vcap_wait_es2_update(sparx5
);
1458 /* API callback used for moving a block of rules in the VCAP */
1459 static void sparx5_vcap_move(struct net_device
*ndev
, struct vcap_admin
*admin
,
1460 u32 addr
, int offset
, int count
)
1462 struct sparx5_port
*port
= netdev_priv(ndev
);
1463 struct sparx5
*sparx5
= port
->sparx5
;
1464 enum vcap_command cmd
;
1468 mv_size
= count
- 1;
1470 mv_num_pos
= offset
- 1;
1471 cmd
= VCAP_CMD_MOVE_DOWN
;
1473 mv_num_pos
= -offset
- 1;
1474 cmd
= VCAP_CMD_MOVE_UP
;
1477 switch (admin
->vtype
) {
1480 sparx5_vcap_super_move(sparx5
, addr
, cmd
, mv_num_pos
, mv_size
);
1483 sparx5_vcap_es0_move(sparx5
, addr
, cmd
, mv_num_pos
, mv_size
);
1486 sparx5_vcap_es2_move(sparx5
, addr
, cmd
, mv_num_pos
, mv_size
);
1489 sparx5_vcap_type_err(sparx5
, admin
, __func__
);
1494 static const struct vcap_operations sparx5_vcap_ops
= {
1495 .validate_keyset
= sparx5_vcap_validate_keyset
,
1496 .add_default_fields
= sparx5_vcap_add_default_fields
,
1497 .cache_erase
= sparx5_vcap_cache_erase
,
1498 .cache_write
= sparx5_vcap_cache_write
,
1499 .cache_read
= sparx5_vcap_cache_read
,
1500 .init
= sparx5_vcap_range_init
,
1501 .update
= sparx5_vcap_update
,
1502 .move
= sparx5_vcap_move
,
1503 .port_info
= sparx5_port_info
,
1506 static u32
sparx5_vcap_is0_keyset_to_etype_ps(enum vcap_keyfield_set keyset
)
1509 case VCAP_KFS_NORMAL_7TUPLE
:
1510 return VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE
;
1511 case VCAP_KFS_NORMAL_5TUPLE_IP4
:
1512 return VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4
;
1514 return VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE
;
1518 static void sparx5_vcap_is0_set_port_keyset(struct net_device
*ndev
, int lookup
,
1519 enum vcap_keyfield_set keyset
,
1522 struct sparx5_port
*port
= netdev_priv(ndev
);
1523 struct sparx5
*sparx5
= port
->sparx5
;
1524 int portno
= port
->portno
;
1529 value
= sparx5_vcap_is0_keyset_to_etype_ps(keyset
);
1530 spx5_rmw(ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_SET(value
),
1531 ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL
,
1533 ANA_CL_ADV_CL_CFG(portno
, lookup
));
1536 value
= sparx5_vcap_is0_keyset_to_etype_ps(keyset
);
1537 spx5_rmw(ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_SET(value
),
1538 ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL
,
1540 ANA_CL_ADV_CL_CFG(portno
, lookup
));
1543 value
= sparx5_vcap_is0_keyset_to_etype_ps(keyset
);
1544 spx5_rmw(ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_SET(value
),
1545 ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL
,
1547 ANA_CL_ADV_CL_CFG(portno
, lookup
));
1552 static u32
sparx5_vcap_is2_keyset_to_arp_ps(enum vcap_keyfield_set keyset
)
1556 return VCAP_IS2_PS_ARP_ARP
;
1558 return VCAP_IS2_PS_ARP_MAC_ETYPE
;
1562 static u32
sparx5_vcap_is2_keyset_to_ipv4_ps(enum vcap_keyfield_set keyset
)
1565 case VCAP_KFS_MAC_ETYPE
:
1566 return VCAP_IS2_PS_IPV4_UC_MAC_ETYPE
;
1567 case VCAP_KFS_IP4_OTHER
:
1568 case VCAP_KFS_IP4_TCP_UDP
:
1569 return VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER
;
1570 case VCAP_KFS_IP_7TUPLE
:
1571 return VCAP_IS2_PS_IPV4_UC_IP_7TUPLE
;
1573 return VCAP_KFS_NO_VALUE
;
1577 static u32
sparx5_vcap_is2_keyset_to_ipv6_uc_ps(enum vcap_keyfield_set keyset
)
1580 case VCAP_KFS_MAC_ETYPE
:
1581 return VCAP_IS2_PS_IPV6_UC_MAC_ETYPE
;
1582 case VCAP_KFS_IP4_OTHER
:
1583 case VCAP_KFS_IP4_TCP_UDP
:
1584 return VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER
;
1585 case VCAP_KFS_IP_7TUPLE
:
1586 return VCAP_IS2_PS_IPV6_UC_IP_7TUPLE
;
1588 return VCAP_KFS_NO_VALUE
;
1592 static u32
sparx5_vcap_is2_keyset_to_ipv6_mc_ps(enum vcap_keyfield_set keyset
)
1595 case VCAP_KFS_MAC_ETYPE
:
1596 return VCAP_IS2_PS_IPV6_MC_MAC_ETYPE
;
1597 case VCAP_KFS_IP4_OTHER
:
1598 case VCAP_KFS_IP4_TCP_UDP
:
1599 return VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER
;
1600 case VCAP_KFS_IP_7TUPLE
:
1601 return VCAP_IS2_PS_IPV6_MC_IP_7TUPLE
;
1603 return VCAP_KFS_NO_VALUE
;
1607 static void sparx5_vcap_is2_set_port_keyset(struct net_device
*ndev
, int lookup
,
1608 enum vcap_keyfield_set keyset
,
1611 struct sparx5_port
*port
= netdev_priv(ndev
);
1612 struct sparx5
*sparx5
= port
->sparx5
;
1613 int portno
= port
->portno
;
1618 value
= sparx5_vcap_is2_keyset_to_arp_ps(keyset
);
1619 spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(value
),
1620 ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL
,
1622 ANA_ACL_VCAP_S2_KEY_SEL(portno
, lookup
));
1625 value
= sparx5_vcap_is2_keyset_to_ipv4_ps(keyset
);
1626 spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_SET(value
),
1627 ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL
,
1629 ANA_ACL_VCAP_S2_KEY_SEL(portno
, lookup
));
1630 spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_SET(value
),
1631 ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL
,
1633 ANA_ACL_VCAP_S2_KEY_SEL(portno
, lookup
));
1636 value
= sparx5_vcap_is2_keyset_to_ipv6_uc_ps(keyset
);
1637 spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(value
),
1638 ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL
,
1640 ANA_ACL_VCAP_S2_KEY_SEL(portno
, lookup
));
1641 value
= sparx5_vcap_is2_keyset_to_ipv6_mc_ps(keyset
);
1642 spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_SET(value
),
1643 ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL
,
1645 ANA_ACL_VCAP_S2_KEY_SEL(portno
, lookup
));
1648 value
= VCAP_IS2_PS_NONETH_MAC_ETYPE
;
1649 spx5_rmw(ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(value
),
1650 ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL
,
1652 ANA_ACL_VCAP_S2_KEY_SEL(portno
, lookup
));
1657 static u32
sparx5_vcap_es2_keyset_to_arp_ps(enum vcap_keyfield_set keyset
)
1661 return VCAP_ES2_PS_ARP_ARP
;
1663 return VCAP_ES2_PS_ARP_MAC_ETYPE
;
1667 static u32
sparx5_vcap_es2_keyset_to_ipv4_ps(enum vcap_keyfield_set keyset
)
1670 case VCAP_KFS_MAC_ETYPE
:
1671 return VCAP_ES2_PS_IPV4_MAC_ETYPE
;
1672 case VCAP_KFS_IP_7TUPLE
:
1673 return VCAP_ES2_PS_IPV4_IP_7TUPLE
;
1674 case VCAP_KFS_IP4_TCP_UDP
:
1675 return VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER
;
1676 case VCAP_KFS_IP4_OTHER
:
1677 return VCAP_ES2_PS_IPV4_IP4_OTHER
;
1679 return VCAP_ES2_PS_IPV4_MAC_ETYPE
;
1683 static u32
sparx5_vcap_es2_keyset_to_ipv6_ps(enum vcap_keyfield_set keyset
)
1686 case VCAP_KFS_MAC_ETYPE
:
1687 return VCAP_ES2_PS_IPV6_MAC_ETYPE
;
1688 case VCAP_KFS_IP4_TCP_UDP
:
1689 case VCAP_KFS_IP4_OTHER
:
1690 return VCAP_ES2_PS_IPV6_IP4_DOWNGRADE
;
1691 case VCAP_KFS_IP_7TUPLE
:
1692 return VCAP_ES2_PS_IPV6_IP_7TUPLE
;
1693 case VCAP_KFS_IP6_STD
:
1694 return VCAP_ES2_PS_IPV6_IP6_STD
;
1696 return VCAP_ES2_PS_IPV6_MAC_ETYPE
;
1700 static void sparx5_vcap_es2_set_port_keyset(struct net_device
*ndev
, int lookup
,
1701 enum vcap_keyfield_set keyset
,
1704 struct sparx5_port
*port
= netdev_priv(ndev
);
1705 struct sparx5
*sparx5
= port
->sparx5
;
1706 int portno
= port
->portno
;
1711 value
= sparx5_vcap_es2_keyset_to_ipv4_ps(keyset
);
1712 spx5_rmw(EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_SET(value
),
1713 EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL
,
1715 EACL_VCAP_ES2_KEY_SEL(portno
, lookup
));
1718 value
= sparx5_vcap_es2_keyset_to_ipv6_ps(keyset
);
1719 spx5_rmw(EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_SET(value
),
1720 EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL
,
1722 EACL_VCAP_ES2_KEY_SEL(portno
, lookup
));
1725 value
= sparx5_vcap_es2_keyset_to_arp_ps(keyset
);
1726 spx5_rmw(EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_SET(value
),
1727 EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL
,
1729 EACL_VCAP_ES2_KEY_SEL(portno
, lookup
));
1734 /* Change the port keyset for the lookup and protocol */
1735 void sparx5_vcap_set_port_keyset(struct net_device
*ndev
,
1736 struct vcap_admin
*admin
,
1739 enum vcap_keyfield_set keyset
,
1740 struct vcap_keyset_list
*orig
)
1742 struct sparx5_port
*port
;
1745 switch (admin
->vtype
) {
1747 lookup
= sparx5_vcap_is0_cid_to_lookup(cid
);
1749 sparx5_vcap_is0_get_port_keysets(ndev
, lookup
, orig
,
1751 sparx5_vcap_is0_set_port_keyset(ndev
, lookup
, keyset
, l3_proto
);
1754 lookup
= sparx5_vcap_is2_cid_to_lookup(cid
);
1756 sparx5_vcap_is2_get_port_keysets(ndev
, lookup
, orig
,
1758 sparx5_vcap_is2_set_port_keyset(ndev
, lookup
, keyset
, l3_proto
);
1763 lookup
= sparx5_vcap_es2_cid_to_lookup(cid
);
1765 sparx5_vcap_es2_get_port_keysets(ndev
, lookup
, orig
,
1767 sparx5_vcap_es2_set_port_keyset(ndev
, lookup
, keyset
, l3_proto
);
1770 port
= netdev_priv(ndev
);
1771 sparx5_vcap_type_err(port
->sparx5
, admin
, __func__
);
1776 /* Enable IS0 lookups per port and set the keyset generation */
1777 static void sparx5_vcap_is0_port_key_selection(struct sparx5
*sparx5
,
1778 struct vcap_admin
*admin
)
1780 const struct sparx5_consts
*consts
= sparx5
->data
->consts
;
1784 keysel
= VCAP_IS0_KEYSEL(false,
1785 VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE
,
1786 VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4
,
1787 VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE
,
1788 VCAP_IS0_PS_MPLS_FOLLOW_ETYPE
,
1789 VCAP_IS0_PS_MPLS_FOLLOW_ETYPE
,
1790 VCAP_IS0_PS_MLBS_FOLLOW_ETYPE
);
1791 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
) {
1792 for (portno
= 0; portno
< consts
->n_ports
; ++portno
) {
1793 spx5_wr(keysel
, sparx5
,
1794 ANA_CL_ADV_CL_CFG(portno
, lookup
));
1795 spx5_rmw(ANA_CL_ADV_CL_CFG_LOOKUP_ENA
,
1796 ANA_CL_ADV_CL_CFG_LOOKUP_ENA
,
1798 ANA_CL_ADV_CL_CFG(portno
, lookup
));
1803 /* Enable IS2 lookups per port and set the keyset generation */
1804 static void sparx5_vcap_is2_port_key_selection(struct sparx5
*sparx5
,
1805 struct vcap_admin
*admin
)
1807 const struct sparx5_consts
*consts
= sparx5
->data
->consts
;
1811 keysel
= VCAP_IS2_KEYSEL(true, VCAP_IS2_PS_NONETH_MAC_ETYPE
,
1812 VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER
,
1813 VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER
,
1814 VCAP_IS2_PS_IPV6_MC_IP_7TUPLE
,
1815 VCAP_IS2_PS_IPV6_UC_IP_7TUPLE
,
1816 VCAP_IS2_PS_ARP_ARP
);
1817 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
) {
1818 for (portno
= 0; portno
< consts
->n_ports
; ++portno
) {
1819 spx5_wr(keysel
, sparx5
,
1820 ANA_ACL_VCAP_S2_KEY_SEL(portno
, lookup
));
1823 /* IS2 lookups are in bit 0:3 */
1824 for (portno
= 0; portno
< consts
->n_ports
; ++portno
)
1825 spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0xf),
1826 ANA_ACL_VCAP_S2_CFG_SEC_ENA
,
1828 ANA_ACL_VCAP_S2_CFG(portno
));
1831 /* Enable ES0 lookups per port and set the keyset generation */
1832 static void sparx5_vcap_es0_port_key_selection(struct sparx5
*sparx5
,
1833 struct vcap_admin
*admin
)
1835 const struct sparx5_consts
*consts
= sparx5
->data
->consts
;
1839 keysel
= VCAP_ES0_KEYSEL(VCAP_ES0_PS_FORCE_ISDX_LOOKUPS
);
1840 for (portno
= 0; portno
< consts
->n_ports
; ++portno
)
1841 spx5_rmw(keysel
, REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA
,
1842 sparx5
, REW_RTAG_ETAG_CTRL(portno
));
1844 spx5_rmw(REW_ES0_CTRL_ES0_LU_ENA_SET(1), REW_ES0_CTRL_ES0_LU_ENA
,
1845 sparx5
, REW_ES0_CTRL
);
1848 /* Enable ES2 lookups per port and set the keyset generation */
1849 static void sparx5_vcap_es2_port_key_selection(struct sparx5
*sparx5
,
1850 struct vcap_admin
*admin
)
1852 const struct sparx5_consts
*consts
= sparx5
->data
->consts
;
1856 keysel
= VCAP_ES2_KEYSEL(true, VCAP_ES2_PS_ARP_MAC_ETYPE
,
1857 VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER
,
1858 VCAP_ES2_PS_IPV6_IP_7TUPLE
);
1859 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
)
1860 for (portno
= 0; portno
< consts
->n_ports
; ++portno
)
1861 spx5_wr(keysel
, sparx5
,
1862 EACL_VCAP_ES2_KEY_SEL(portno
, lookup
));
1865 /* Enable lookups per port and set the keyset generation */
1866 static void sparx5_vcap_port_key_selection(struct sparx5
*sparx5
,
1867 struct vcap_admin
*admin
)
1869 switch (admin
->vtype
) {
1871 sparx5_vcap_is0_port_key_selection(sparx5
, admin
);
1874 sparx5_vcap_is2_port_key_selection(sparx5
, admin
);
1877 sparx5_vcap_es0_port_key_selection(sparx5
, admin
);
1880 sparx5_vcap_es2_port_key_selection(sparx5
, admin
);
1883 sparx5_vcap_type_err(sparx5
, admin
, __func__
);
1888 /* Disable lookups per port */
1889 static void sparx5_vcap_port_key_deselection(struct sparx5
*sparx5
,
1890 struct vcap_admin
*admin
)
1892 const struct sparx5_consts
*consts
= sparx5
->data
->consts
;
1895 switch (admin
->vtype
) {
1897 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
)
1898 for (portno
= 0; portno
< consts
->n_ports
; ++portno
)
1899 spx5_rmw(ANA_CL_ADV_CL_CFG_LOOKUP_ENA_SET(0),
1900 ANA_CL_ADV_CL_CFG_LOOKUP_ENA
,
1902 ANA_CL_ADV_CL_CFG(portno
, lookup
));
1905 for (portno
= 0; portno
< consts
->n_ports
; ++portno
)
1906 spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0),
1907 ANA_ACL_VCAP_S2_CFG_SEC_ENA
,
1909 ANA_ACL_VCAP_S2_CFG(portno
));
1912 spx5_rmw(REW_ES0_CTRL_ES0_LU_ENA_SET(0),
1913 REW_ES0_CTRL_ES0_LU_ENA
, sparx5
, REW_ES0_CTRL
);
1916 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
)
1917 for (portno
= 0; portno
< consts
->n_ports
; ++portno
)
1918 spx5_rmw(EACL_VCAP_ES2_KEY_SEL_KEY_ENA_SET(0),
1919 EACL_VCAP_ES2_KEY_SEL_KEY_ENA
,
1921 EACL_VCAP_ES2_KEY_SEL(portno
, lookup
));
1924 sparx5_vcap_type_err(sparx5
, admin
, __func__
);
1929 static void sparx5_vcap_admin_free(struct vcap_admin
*admin
)
1933 mutex_destroy(&admin
->lock
);
1934 kfree(admin
->cache
.keystream
);
1935 kfree(admin
->cache
.maskstream
);
1936 kfree(admin
->cache
.actionstream
);
1940 /* Allocate a vcap instance with a rule list and a cache area */
1941 static struct vcap_admin
*
1942 sparx5_vcap_admin_alloc(struct sparx5
*sparx5
, struct vcap_control
*ctrl
,
1943 const struct sparx5_vcap_inst
*cfg
)
1945 struct vcap_admin
*admin
;
1947 admin
= kzalloc(sizeof(*admin
), GFP_KERNEL
);
1949 return ERR_PTR(-ENOMEM
);
1950 INIT_LIST_HEAD(&admin
->list
);
1951 INIT_LIST_HEAD(&admin
->rules
);
1952 INIT_LIST_HEAD(&admin
->enabled
);
1953 mutex_init(&admin
->lock
);
1954 admin
->vtype
= cfg
->vtype
;
1955 admin
->vinst
= cfg
->vinst
;
1956 admin
->ingress
= cfg
->ingress
;
1957 admin
->lookups
= cfg
->lookups
;
1958 admin
->lookups_per_instance
= cfg
->lookups_per_instance
;
1959 admin
->first_cid
= cfg
->first_cid
;
1960 admin
->last_cid
= cfg
->last_cid
;
1961 admin
->cache
.keystream
=
1962 kzalloc(STREAMSIZE
, GFP_KERNEL
);
1963 admin
->cache
.maskstream
=
1964 kzalloc(STREAMSIZE
, GFP_KERNEL
);
1965 admin
->cache
.actionstream
=
1966 kzalloc(STREAMSIZE
, GFP_KERNEL
);
1967 if (!admin
->cache
.keystream
|| !admin
->cache
.maskstream
||
1968 !admin
->cache
.actionstream
) {
1969 sparx5_vcap_admin_free(admin
);
1970 return ERR_PTR(-ENOMEM
);
1975 /* Do block allocations and provide addresses for VCAP instances */
1976 static void sparx5_vcap_block_alloc(struct sparx5
*sparx5
,
1977 struct vcap_admin
*admin
,
1978 const struct sparx5_vcap_inst
*cfg
)
1982 switch (admin
->vtype
) {
1985 /* Super VCAP block mapping and address configuration. Block 0
1986 * is assigned addresses 0 through 3071, block 1 is assigned
1987 * addresses 3072 though 6143, and so on.
1989 for (idx
= cfg
->blockno
; idx
< cfg
->blockno
+ cfg
->blocks
;
1991 spx5_wr(VCAP_SUPER_IDX_CORE_IDX_SET(idx
), sparx5
,
1993 spx5_wr(VCAP_SUPER_MAP_CORE_MAP_SET(cfg
->map_id
),
1994 sparx5
, VCAP_SUPER_MAP
);
1996 admin
->first_valid_addr
= cfg
->blockno
* SUPER_VCAP_BLK_SIZE
;
1997 admin
->last_used_addr
= admin
->first_valid_addr
+
1998 cfg
->blocks
* SUPER_VCAP_BLK_SIZE
;
1999 admin
->last_valid_addr
= admin
->last_used_addr
- 1;
2002 admin
->first_valid_addr
= 0;
2003 admin
->last_used_addr
= cfg
->count
;
2004 admin
->last_valid_addr
= cfg
->count
- 1;
2005 cores
= spx5_rd(sparx5
, VCAP_ES0_CORE_CNT
);
2006 for (idx
= 0; idx
< cores
; ++idx
) {
2007 spx5_wr(VCAP_ES0_IDX_CORE_IDX_SET(idx
), sparx5
,
2009 spx5_wr(VCAP_ES0_MAP_CORE_MAP_SET(1), sparx5
,
2014 admin
->first_valid_addr
= 0;
2015 admin
->last_used_addr
= cfg
->count
;
2016 admin
->last_valid_addr
= cfg
->count
- 1;
2017 cores
= spx5_rd(sparx5
, VCAP_ES2_CORE_CNT
);
2018 for (idx
= 0; idx
< cores
; ++idx
) {
2019 spx5_wr(VCAP_ES2_IDX_CORE_IDX_SET(idx
), sparx5
,
2021 spx5_wr(VCAP_ES2_MAP_CORE_MAP_SET(1), sparx5
,
2026 sparx5_vcap_type_err(sparx5
, admin
, __func__
);
2031 /* Allocate a vcap control and vcap instances and configure the system */
2032 int sparx5_vcap_init(struct sparx5
*sparx5
)
2034 const struct sparx5_consts
*consts
= sparx5
->data
->consts
;
2035 const struct sparx5_vcap_inst
*cfg
;
2036 struct vcap_control
*ctrl
;
2037 struct vcap_admin
*admin
;
2041 /* Create a VCAP control instance that owns the platform specific VCAP
2042 * model with VCAP instances and information about keysets, keys,
2043 * actionsets and actions
2044 * - Create administrative state for each available VCAP
2046 * - Address information
2047 * - Initialize VCAP blocks
2048 * - Configure port keysets
2050 ctrl
= kzalloc(sizeof(*ctrl
), GFP_KERNEL
);
2054 sparx5
->vcap_ctrl
= ctrl
;
2055 /* select the sparx5 VCAP model */
2056 ctrl
->vcaps
= consts
->vcaps
;
2057 ctrl
->stats
= consts
->vcap_stats
;
2058 /* Setup callbacks to allow the API to use the VCAP HW */
2059 ctrl
->ops
= &sparx5_vcap_ops
;
2061 INIT_LIST_HEAD(&ctrl
->list
);
2062 for (idx
= 0; idx
< ARRAY_SIZE(sparx5_vcap_inst_cfg
); ++idx
) {
2063 cfg
= &consts
->vcaps_cfg
[idx
];
2064 admin
= sparx5_vcap_admin_alloc(sparx5
, ctrl
, cfg
);
2065 if (IS_ERR(admin
)) {
2066 err
= PTR_ERR(admin
);
2067 pr_err("%s:%d: vcap allocation failed: %d\n",
2068 __func__
, __LINE__
, err
);
2071 sparx5_vcap_block_alloc(sparx5
, admin
, cfg
);
2072 sparx5_vcap_block_init(sparx5
, admin
);
2073 if (cfg
->vinst
== 0)
2074 sparx5_vcap_port_key_selection(sparx5
, admin
);
2075 list_add_tail(&admin
->list
, &ctrl
->list
);
2077 dir
= vcap_debugfs(sparx5
->dev
, sparx5
->debugfs_root
, ctrl
);
2078 for (idx
= 0; idx
< consts
->n_ports
; ++idx
)
2079 if (sparx5
->ports
[idx
])
2080 vcap_port_debugfs(sparx5
->dev
, dir
, ctrl
,
2081 sparx5
->ports
[idx
]->ndev
);
2086 void sparx5_vcap_destroy(struct sparx5
*sparx5
)
2088 struct vcap_control
*ctrl
= sparx5
->vcap_ctrl
;
2089 struct vcap_admin
*admin
, *admin_next
;
2094 list_for_each_entry_safe(admin
, admin_next
, &ctrl
->list
, list
) {
2095 sparx5_vcap_port_key_deselection(sparx5
, admin
);
2096 vcap_del_rules(ctrl
, admin
);
2097 list_del(&admin
->list
);
2098 sparx5_vcap_admin_free(admin
);