472 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/* Microchip Sparx5 Switch driver VCAP debugFS implementation3 *4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.5 */6 7#include <linux/types.h>8#include <linux/list.h>9 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"15 16static const char *sparx5_vcap_is0_etype_str(u32 value)17{18 switch (value) {19 case VCAP_IS0_PS_ETYPE_DEFAULT:20 return "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:26 return "mll";27 case VCAP_IS0_PS_ETYPE_LL_FULL:28 return "ll_full";29 case VCAP_IS0_PS_ETYPE_PURE_5TUPLE_IP4:30 return "pure_5tuple_ip4";31 case VCAP_IS0_PS_ETYPE_ETAG:32 return "etag";33 case VCAP_IS0_PS_ETYPE_NO_LOOKUP:34 return "no lookup";35 default:36 return "unknown";37 }38}39 40static const char *sparx5_vcap_is0_mpls_str(u32 value)41{42 switch (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:50 return "mll";51 case VCAP_IS0_PS_MPLS_LL_FULL:52 return "ll_full";53 case VCAP_IS0_PS_MPLS_PURE_5TUPLE_IP4:54 return "pure_5tuple_ip4";55 case VCAP_IS0_PS_MPLS_ETAG:56 return "etag";57 case VCAP_IS0_PS_MPLS_NO_LOOKUP:58 return "no lookup";59 default:60 return "unknown";61 }62}63 64static const char *sparx5_vcap_is0_mlbs_str(u32 value)65{66 switch (value) {67 case VCAP_IS0_PS_MLBS_FOLLOW_ETYPE:68 return "follow_etype";69 case VCAP_IS0_PS_MLBS_NO_LOOKUP:70 return "no lookup";71 default:72 return "unknown";73 }74}75 76static 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)80{81 int lookup;82 u32 value, val;83 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);88 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");95 else96 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));115 }116 out->prf(out->dst, "\n");117}118 119static 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)123{124 int lookup;125 u32 value;126 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);131 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");137 else138 out->prf(out->dst, "off");139 140 /* Get key selection state */141 value = spx5_rd(sparx5,142 ANA_ACL_VCAP_S2_KEY_SEL(port->portno, lookup));143 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");148 break;149 case VCAP_IS2_PS_NONETH_CUSTOM_1:150 out->prf(out->dst, "custom1");151 break;152 case VCAP_IS2_PS_NONETH_CUSTOM_2:153 out->prf(out->dst, "custom2");154 break;155 case VCAP_IS2_PS_NONETH_NO_LOOKUP:156 out->prf(out->dst, "none");157 break;158 }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");163 break;164 case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER:165 out->prf(out->dst, "ip4_tcp_udp ip4_other");166 break;167 case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE:168 out->prf(out->dst, "ip_7tuple");169 break;170 case VCAP_IS2_PS_IPV4_MC_IP4_VID:171 out->prf(out->dst, "ip4_vid");172 break;173 }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");178 break;179 case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER:180 out->prf(out->dst, "ip4_tcp_udp ip4_other");181 break;182 case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE:183 out->prf(out->dst, "ip_7tuple");184 break;185 }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");190 break;191 case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE:192 out->prf(out->dst, "ip_7tuple");193 break;194 case VCAP_IS2_PS_IPV6_MC_IP6_VID:195 out->prf(out->dst, "ip6_vid");196 break;197 case VCAP_IS2_PS_IPV6_MC_IP6_STD:198 out->prf(out->dst, "ip6_std");199 break;200 case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER:201 out->prf(out->dst, "ip4_tcp_udp ip4_other");202 break;203 }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");208 break;209 case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE:210 out->prf(out->dst, "ip_7tuple");211 break;212 case VCAP_IS2_PS_IPV6_UC_IP6_STD:213 out->prf(out->dst, "ip6_std");214 break;215 case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER:216 out->prf(out->dst, "ip4_tcp_udp ip4_other");217 break;218 }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");223 break;224 case VCAP_IS2_PS_ARP_ARP:225 out->prf(out->dst, "arp");226 break;227 }228 }229 out->prf(out->dst, "\n");230}231 232static void sparx5_vcap_is2_port_stickies(struct sparx5 *sparx5,233 struct vcap_admin *admin,234 struct vcap_output_print *out)235{236 int lookup;237 u32 value;238 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));244 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");281 /* Clear stickies */282 spx5_wr(value, sparx5, ANA_ACL_SEC_LOOKUP_STICKY(lookup));283 }284 out->prf(out->dst, "\n");285}286 287static 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)291{292 u32 value;293 294 out->prf(out->dst, " port[%02d] (%s): ", port->portno,295 netdev_name(port->ndev));296 out->prf(out->dst, "\n Lookup 0: ");297 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");303 else304 out->prf(out->dst, "off");305 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");311 break;312 case VCAP_ES0_PS_FORCE_ISDX_LOOKUPS:313 out->prf(out->dst, "isdx");314 break;315 case VCAP_ES0_PS_FORCE_VID_LOOKUPS:316 out->prf(out->dst, "vid");317 break;318 case VCAP_ES0_PS_RESERVED:319 out->prf(out->dst, "reserved");320 break;321 }322 out->prf(out->dst, "\n");323}324 325static 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)329{330 int lookup;331 u32 value;332 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);337 338 /* Get lookup state */339 value = spx5_rd(sparx5, EACL_VCAP_ES2_KEY_SEL(port->portno,340 lookup));341 out->prf(out->dst, "\n state: ");342 if (EACL_VCAP_ES2_KEY_SEL_KEY_ENA_GET(value))343 out->prf(out->dst, "on");344 else345 out->prf(out->dst, "off");346 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");351 break;352 case VCAP_ES2_PS_ARP_ARP:353 out->prf(out->dst, "arp");354 break;355 }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");360 break;361 case VCAP_ES2_PS_IPV4_IP_7TUPLE:362 out->prf(out->dst, "ip_7tuple");363 break;364 case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_VID:365 out->prf(out->dst, "ip4_tcp_udp ip4_vid");366 break;367 case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER:368 out->prf(out->dst, "ip4_tcp_udp ip4_other");369 break;370 case VCAP_ES2_PS_IPV4_IP4_VID:371 out->prf(out->dst, "ip4_vid");372 break;373 case VCAP_ES2_PS_IPV4_IP4_OTHER:374 out->prf(out->dst, "ip4_other");375 break;376 }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");381 break;382 case VCAP_ES2_PS_IPV6_IP_7TUPLE:383 out->prf(out->dst, "ip_7tuple");384 break;385 case VCAP_ES2_PS_IPV6_IP_7TUPLE_VID:386 out->prf(out->dst, "ip_7tuple ip6_vid");387 break;388 case VCAP_ES2_PS_IPV6_IP_7TUPLE_STD:389 out->prf(out->dst, "ip_7tuple ip6_std");390 break;391 case VCAP_ES2_PS_IPV6_IP6_VID:392 out->prf(out->dst, "ip6_vid");393 break;394 case VCAP_ES2_PS_IPV6_IP6_STD:395 out->prf(out->dst, "ip6_std");396 break;397 case VCAP_ES2_PS_IPV6_IP4_DOWNGRADE:398 out->prf(out->dst, "ip4_downgrade");399 break;400 }401 }402 out->prf(out->dst, "\n");403}404 405static void sparx5_vcap_es2_port_stickies(struct sparx5 *sparx5,406 struct vcap_admin *admin,407 struct vcap_output_print *out)408{409 int lookup;410 u32 value;411 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");432 /* Clear stickies */433 spx5_wr(value, sparx5, EACL_SEC_LOOKUP_STICKY(lookup));434 }435 out->prf(out->dst, "\n");436}437 438/* Provide port information via a callback interface */439int sparx5_port_info(struct net_device *ndev,440 struct vcap_admin *admin,441 struct vcap_output_print *out)442{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;447 448 vctrl = sparx5->vcap_ctrl;449 vcap = &vctrl->vcaps[admin->vtype];450 out->prf(out->dst, "%s:\n", vcap->name);451 switch (admin->vtype) {452 case VCAP_TYPE_IS0:453 sparx5_vcap_is0_port_keys(sparx5, admin, port, out);454 break;455 case VCAP_TYPE_IS2:456 sparx5_vcap_is2_port_keys(sparx5, admin, port, out);457 sparx5_vcap_is2_port_stickies(sparx5, admin, out);458 break;459 case VCAP_TYPE_ES0:460 sparx5_vcap_es0_port_keys(sparx5, admin, port, out);461 break;462 case VCAP_TYPE_ES2:463 sparx5_vcap_es2_port_keys(sparx5, admin, port, out);464 sparx5_vcap_es2_port_stickies(sparx5, admin, out);465 break;466 default:467 out->prf(out->dst, " no info\n");468 break;469 }470 return 0;471}472