1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver VCAP debugFS implementation
4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
7 #include <linux/types.h>
8 #include <linux/list.h>
10 #include "sparx5_vcap_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"
16 static const char *sparx5_vcap_is0_etype_str(u32 value
)
19 case VCAP_IS0_PS_ETYPE_DEFAULT
:
21 case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE
:
22 return "normal_7tuple";
23 case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4
:
24 return "normal_5tuple_ip4";
25 case VCAP_IS0_PS_ETYPE_MLL
:
27 case VCAP_IS0_PS_ETYPE_LL_FULL
:
29 case VCAP_IS0_PS_ETYPE_PURE_5TUPLE_IP4
:
30 return "pure_5tuple_ip4";
31 case VCAP_IS0_PS_ETYPE_ETAG
:
33 case VCAP_IS0_PS_ETYPE_NO_LOOKUP
:
40 static const char *sparx5_vcap_is0_mpls_str(u32 value
)
43 case VCAP_IS0_PS_MPLS_FOLLOW_ETYPE
:
44 return "follow_etype";
45 case VCAP_IS0_PS_MPLS_NORMAL_7TUPLE
:
46 return "normal_7tuple";
47 case VCAP_IS0_PS_MPLS_NORMAL_5TUPLE_IP4
:
48 return "normal_5tuple_ip4";
49 case VCAP_IS0_PS_MPLS_MLL
:
51 case VCAP_IS0_PS_MPLS_LL_FULL
:
53 case VCAP_IS0_PS_MPLS_PURE_5TUPLE_IP4
:
54 return "pure_5tuple_ip4";
55 case VCAP_IS0_PS_MPLS_ETAG
:
57 case VCAP_IS0_PS_MPLS_NO_LOOKUP
:
64 static const char *sparx5_vcap_is0_mlbs_str(u32 value
)
67 case VCAP_IS0_PS_MLBS_FOLLOW_ETYPE
:
68 return "follow_etype";
69 case VCAP_IS0_PS_MLBS_NO_LOOKUP
:
76 static void sparx5_vcap_is0_port_keys(struct sparx5
*sparx5
,
77 struct vcap_admin
*admin
,
78 struct sparx5_port
*port
,
79 struct vcap_output_print
*out
)
84 out
->prf(out
->dst
, " port[%02d] (%s): ", port
->portno
,
85 netdev_name(port
->ndev
));
86 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
) {
87 out
->prf(out
->dst
, "\n Lookup %d: ", lookup
);
89 /* Get lookup state */
90 value
= spx5_rd(sparx5
,
91 ANA_CL_ADV_CL_CFG(port
->portno
, lookup
));
92 out
->prf(out
->dst
, "\n state: ");
93 if (ANA_CL_ADV_CL_CFG_LOOKUP_ENA_GET(value
))
94 out
->prf(out
->dst
, "on");
96 out
->prf(out
->dst
, "off");
97 val
= ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_GET(value
);
98 out
->prf(out
->dst
, "\n etype: %s",
99 sparx5_vcap_is0_etype_str(val
));
100 val
= ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_GET(value
);
101 out
->prf(out
->dst
, "\n ipv4: %s",
102 sparx5_vcap_is0_etype_str(val
));
103 val
= ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_GET(value
);
104 out
->prf(out
->dst
, "\n ipv6: %s",
105 sparx5_vcap_is0_etype_str(val
));
106 val
= ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL_GET(value
);
107 out
->prf(out
->dst
, "\n mpls_uc: %s",
108 sparx5_vcap_is0_mpls_str(val
));
109 val
= ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL_GET(value
);
110 out
->prf(out
->dst
, "\n mpls_mc: %s",
111 sparx5_vcap_is0_mpls_str(val
));
112 val
= ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL_GET(value
);
113 out
->prf(out
->dst
, "\n mlbs: %s",
114 sparx5_vcap_is0_mlbs_str(val
));
116 out
->prf(out
->dst
, "\n");
119 static void sparx5_vcap_is2_port_keys(struct sparx5
*sparx5
,
120 struct vcap_admin
*admin
,
121 struct sparx5_port
*port
,
122 struct vcap_output_print
*out
)
127 out
->prf(out
->dst
, " port[%02d] (%s): ", port
->portno
,
128 netdev_name(port
->ndev
));
129 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
) {
130 out
->prf(out
->dst
, "\n Lookup %d: ", lookup
);
132 /* Get lookup state */
133 value
= spx5_rd(sparx5
, ANA_ACL_VCAP_S2_CFG(port
->portno
));
134 out
->prf(out
->dst
, "\n state: ");
135 if (ANA_ACL_VCAP_S2_CFG_SEC_ENA_GET(value
) & BIT(lookup
))
136 out
->prf(out
->dst
, "on");
138 out
->prf(out
->dst
, "off");
140 /* Get key selection state */
141 value
= spx5_rd(sparx5
,
142 ANA_ACL_VCAP_S2_KEY_SEL(port
->portno
, lookup
));
144 out
->prf(out
->dst
, "\n noneth: ");
145 switch (ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_GET(value
)) {
146 case VCAP_IS2_PS_NONETH_MAC_ETYPE
:
147 out
->prf(out
->dst
, "mac_etype");
149 case VCAP_IS2_PS_NONETH_CUSTOM_1
:
150 out
->prf(out
->dst
, "custom1");
152 case VCAP_IS2_PS_NONETH_CUSTOM_2
:
153 out
->prf(out
->dst
, "custom2");
155 case VCAP_IS2_PS_NONETH_NO_LOOKUP
:
156 out
->prf(out
->dst
, "none");
159 out
->prf(out
->dst
, "\n ipv4_mc: ");
160 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value
)) {
161 case VCAP_IS2_PS_IPV4_MC_MAC_ETYPE
:
162 out
->prf(out
->dst
, "mac_etype");
164 case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER
:
165 out
->prf(out
->dst
, "ip4_tcp_udp ip4_other");
167 case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE
:
168 out
->prf(out
->dst
, "ip_7tuple");
170 case VCAP_IS2_PS_IPV4_MC_IP4_VID
:
171 out
->prf(out
->dst
, "ip4_vid");
174 out
->prf(out
->dst
, "\n ipv4_uc: ");
175 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value
)) {
176 case VCAP_IS2_PS_IPV4_UC_MAC_ETYPE
:
177 out
->prf(out
->dst
, "mac_etype");
179 case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER
:
180 out
->prf(out
->dst
, "ip4_tcp_udp ip4_other");
182 case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE
:
183 out
->prf(out
->dst
, "ip_7tuple");
186 out
->prf(out
->dst
, "\n ipv6_mc: ");
187 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value
)) {
188 case VCAP_IS2_PS_IPV6_MC_MAC_ETYPE
:
189 out
->prf(out
->dst
, "mac_etype");
191 case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE
:
192 out
->prf(out
->dst
, "ip_7tuple");
194 case VCAP_IS2_PS_IPV6_MC_IP6_VID
:
195 out
->prf(out
->dst
, "ip6_vid");
197 case VCAP_IS2_PS_IPV6_MC_IP6_STD
:
198 out
->prf(out
->dst
, "ip6_std");
200 case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER
:
201 out
->prf(out
->dst
, "ip4_tcp_udp ip4_other");
204 out
->prf(out
->dst
, "\n ipv6_uc: ");
205 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value
)) {
206 case VCAP_IS2_PS_IPV6_UC_MAC_ETYPE
:
207 out
->prf(out
->dst
, "mac_etype");
209 case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE
:
210 out
->prf(out
->dst
, "ip_7tuple");
212 case VCAP_IS2_PS_IPV6_UC_IP6_STD
:
213 out
->prf(out
->dst
, "ip6_std");
215 case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER
:
216 out
->prf(out
->dst
, "ip4_tcp_udp ip4_other");
219 out
->prf(out
->dst
, "\n arp: ");
220 switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value
)) {
221 case VCAP_IS2_PS_ARP_MAC_ETYPE
:
222 out
->prf(out
->dst
, "mac_etype");
224 case VCAP_IS2_PS_ARP_ARP
:
225 out
->prf(out
->dst
, "arp");
229 out
->prf(out
->dst
, "\n");
232 static void sparx5_vcap_is2_port_stickies(struct sparx5
*sparx5
,
233 struct vcap_admin
*admin
,
234 struct vcap_output_print
*out
)
239 out
->prf(out
->dst
, " Sticky bits: ");
240 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
) {
241 out
->prf(out
->dst
, "\n Lookup %d: ", lookup
);
242 /* Get lookup sticky bits */
243 value
= spx5_rd(sparx5
, ANA_ACL_SEC_LOOKUP_STICKY(lookup
));
245 if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_CLM_STICKY_GET(value
))
246 out
->prf(out
->dst
, " sel_clm");
247 if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_IRLEG_STICKY_GET(value
))
248 out
->prf(out
->dst
, " sel_irleg");
249 if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_ERLEG_STICKY_GET(value
))
250 out
->prf(out
->dst
, " sel_erleg");
251 if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_PORT_STICKY_GET(value
))
252 out
->prf(out
->dst
, " sel_port");
253 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_CUSTOM2_STICKY_GET(value
))
254 out
->prf(out
->dst
, " custom2");
255 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_CUSTOM1_STICKY_GET(value
))
256 out
->prf(out
->dst
, " custom1");
257 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_OAM_STICKY_GET(value
))
258 out
->prf(out
->dst
, " oam");
259 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_VID_STICKY_GET(value
))
260 out
->prf(out
->dst
, " ip6_vid");
261 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_STD_STICKY_GET(value
))
262 out
->prf(out
->dst
, " ip6_std");
263 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_TCPUDP_STICKY_GET(value
))
264 out
->prf(out
->dst
, " ip6_tcpudp");
265 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP_7TUPLE_STICKY_GET(value
))
266 out
->prf(out
->dst
, " ip_7tuple");
267 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_VID_STICKY_GET(value
))
268 out
->prf(out
->dst
, " ip4_vid");
269 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_TCPUDP_STICKY_GET(value
))
270 out
->prf(out
->dst
, " ip4_tcpudp");
271 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_OTHER_STICKY_GET(value
))
272 out
->prf(out
->dst
, " ip4_other");
273 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_ARP_STICKY_GET(value
))
274 out
->prf(out
->dst
, " arp");
275 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_SNAP_STICKY_GET(value
))
276 out
->prf(out
->dst
, " mac_snap");
277 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_LLC_STICKY_GET(value
))
278 out
->prf(out
->dst
, " mac_llc");
279 if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_ETYPE_STICKY_GET(value
))
280 out
->prf(out
->dst
, " mac_etype");
282 spx5_wr(value
, sparx5
, ANA_ACL_SEC_LOOKUP_STICKY(lookup
));
284 out
->prf(out
->dst
, "\n");
287 static void sparx5_vcap_es0_port_keys(struct sparx5
*sparx5
,
288 struct vcap_admin
*admin
,
289 struct sparx5_port
*port
,
290 struct vcap_output_print
*out
)
294 out
->prf(out
->dst
, " port[%02d] (%s): ", port
->portno
,
295 netdev_name(port
->ndev
));
296 out
->prf(out
->dst
, "\n Lookup 0: ");
298 /* Get lookup state */
299 value
= spx5_rd(sparx5
, REW_ES0_CTRL
);
300 out
->prf(out
->dst
, "\n state: ");
301 if (REW_ES0_CTRL_ES0_LU_ENA_GET(value
))
302 out
->prf(out
->dst
, "on");
304 out
->prf(out
->dst
, "off");
306 out
->prf(out
->dst
, "\n keyset: ");
307 value
= spx5_rd(sparx5
, REW_RTAG_ETAG_CTRL(port
->portno
));
308 switch (REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA_GET(value
)) {
309 case VCAP_ES0_PS_NORMAL_SELECTION
:
310 out
->prf(out
->dst
, "normal");
312 case VCAP_ES0_PS_FORCE_ISDX_LOOKUPS
:
313 out
->prf(out
->dst
, "isdx");
315 case VCAP_ES0_PS_FORCE_VID_LOOKUPS
:
316 out
->prf(out
->dst
, "vid");
318 case VCAP_ES0_PS_RESERVED
:
319 out
->prf(out
->dst
, "reserved");
322 out
->prf(out
->dst
, "\n");
325 static void sparx5_vcap_es2_port_keys(struct sparx5
*sparx5
,
326 struct vcap_admin
*admin
,
327 struct sparx5_port
*port
,
328 struct vcap_output_print
*out
)
333 out
->prf(out
->dst
, " port[%02d] (%s): ", port
->portno
,
334 netdev_name(port
->ndev
));
335 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
) {
336 out
->prf(out
->dst
, "\n Lookup %d: ", lookup
);
338 /* Get lookup state */
339 value
= spx5_rd(sparx5
, EACL_VCAP_ES2_KEY_SEL(port
->portno
,
341 out
->prf(out
->dst
, "\n state: ");
342 if (EACL_VCAP_ES2_KEY_SEL_KEY_ENA_GET(value
))
343 out
->prf(out
->dst
, "on");
345 out
->prf(out
->dst
, "off");
347 out
->prf(out
->dst
, "\n arp: ");
348 switch (EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_GET(value
)) {
349 case VCAP_ES2_PS_ARP_MAC_ETYPE
:
350 out
->prf(out
->dst
, "mac_etype");
352 case VCAP_ES2_PS_ARP_ARP
:
353 out
->prf(out
->dst
, "arp");
356 out
->prf(out
->dst
, "\n ipv4: ");
357 switch (EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_GET(value
)) {
358 case VCAP_ES2_PS_IPV4_MAC_ETYPE
:
359 out
->prf(out
->dst
, "mac_etype");
361 case VCAP_ES2_PS_IPV4_IP_7TUPLE
:
362 out
->prf(out
->dst
, "ip_7tuple");
364 case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_VID
:
365 out
->prf(out
->dst
, "ip4_tcp_udp ip4_vid");
367 case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER
:
368 out
->prf(out
->dst
, "ip4_tcp_udp ip4_other");
370 case VCAP_ES2_PS_IPV4_IP4_VID
:
371 out
->prf(out
->dst
, "ip4_vid");
373 case VCAP_ES2_PS_IPV4_IP4_OTHER
:
374 out
->prf(out
->dst
, "ip4_other");
377 out
->prf(out
->dst
, "\n ipv6: ");
378 switch (EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_GET(value
)) {
379 case VCAP_ES2_PS_IPV6_MAC_ETYPE
:
380 out
->prf(out
->dst
, "mac_etype");
382 case VCAP_ES2_PS_IPV6_IP_7TUPLE
:
383 out
->prf(out
->dst
, "ip_7tuple");
385 case VCAP_ES2_PS_IPV6_IP_7TUPLE_VID
:
386 out
->prf(out
->dst
, "ip_7tuple ip6_vid");
388 case VCAP_ES2_PS_IPV6_IP_7TUPLE_STD
:
389 out
->prf(out
->dst
, "ip_7tuple ip6_std");
391 case VCAP_ES2_PS_IPV6_IP6_VID
:
392 out
->prf(out
->dst
, "ip6_vid");
394 case VCAP_ES2_PS_IPV6_IP6_STD
:
395 out
->prf(out
->dst
, "ip6_std");
397 case VCAP_ES2_PS_IPV6_IP4_DOWNGRADE
:
398 out
->prf(out
->dst
, "ip4_downgrade");
402 out
->prf(out
->dst
, "\n");
405 static void sparx5_vcap_es2_port_stickies(struct sparx5
*sparx5
,
406 struct vcap_admin
*admin
,
407 struct vcap_output_print
*out
)
412 out
->prf(out
->dst
, " Sticky bits: ");
413 for (lookup
= 0; lookup
< admin
->lookups
; ++lookup
) {
414 value
= spx5_rd(sparx5
, EACL_SEC_LOOKUP_STICKY(lookup
));
415 out
->prf(out
->dst
, "\n Lookup %d: ", lookup
);
416 if (EACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP_7TUPLE_STICKY_GET(value
))
417 out
->prf(out
->dst
, " ip_7tuple");
418 if (EACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_VID_STICKY_GET(value
))
419 out
->prf(out
->dst
, " ip6_vid");
420 if (EACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_STD_STICKY_GET(value
))
421 out
->prf(out
->dst
, " ip6_std");
422 if (EACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_TCPUDP_STICKY_GET(value
))
423 out
->prf(out
->dst
, " ip4_tcp_udp");
424 if (EACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_VID_STICKY_GET(value
))
425 out
->prf(out
->dst
, " ip4_vid");
426 if (EACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_OTHER_STICKY_GET(value
))
427 out
->prf(out
->dst
, " ip4_other");
428 if (EACL_SEC_LOOKUP_STICKY_SEC_TYPE_ARP_STICKY_GET(value
))
429 out
->prf(out
->dst
, " arp");
430 if (EACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_ETYPE_STICKY_GET(value
))
431 out
->prf(out
->dst
, " mac_etype");
433 spx5_wr(value
, sparx5
, EACL_SEC_LOOKUP_STICKY(lookup
));
435 out
->prf(out
->dst
, "\n");
438 /* Provide port information via a callback interface */
439 int sparx5_port_info(struct net_device
*ndev
,
440 struct vcap_admin
*admin
,
441 struct vcap_output_print
*out
)
443 struct sparx5_port
*port
= netdev_priv(ndev
);
444 struct sparx5
*sparx5
= port
->sparx5
;
445 const struct vcap_info
*vcap
;
446 struct vcap_control
*vctrl
;
448 vctrl
= sparx5
->vcap_ctrl
;
449 vcap
= &vctrl
->vcaps
[admin
->vtype
];
450 out
->prf(out
->dst
, "%s:\n", vcap
->name
);
451 switch (admin
->vtype
) {
453 sparx5_vcap_is0_port_keys(sparx5
, admin
, port
, out
);
456 sparx5_vcap_is2_port_keys(sparx5
, admin
, port
, out
);
457 sparx5_vcap_is2_port_stickies(sparx5
, admin
, out
);
460 sparx5_vcap_es0_port_keys(sparx5
, admin
, port
, out
);
463 sparx5_vcap_es2_port_keys(sparx5
, admin
, port
, out
);
464 sparx5_vcap_es2_port_stickies(sparx5
, admin
, out
);
467 out
->prf(out
->dst
, " no info\n");