// SPDX-License-Identifier: GPL-2.0+ /* Microchip Sparx5 Switch driver VCAP debugFS implementation * * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries. */ #include #include #include "sparx5_vcap_debugfs.h" #include "sparx5_main_regs.h" #include "sparx5_main.h" #include "sparx5_vcap_impl.h" #include "sparx5_vcap_ag_api.h" static void sparx5_vcap_port_keys(struct sparx5 *sparx5, struct vcap_admin *admin, struct sparx5_port *port, struct vcap_output_print *out) { int lookup; u32 value; out->prf(out->dst, " port[%02d] (%s): ", port->portno, netdev_name(port->ndev)); for (lookup = 0; lookup < admin->lookups; ++lookup) { out->prf(out->dst, "\n Lookup %d: ", lookup); /* Get lookup state */ value = spx5_rd(sparx5, ANA_ACL_VCAP_S2_CFG(port->portno)); out->prf(out->dst, "\n state: "); if (ANA_ACL_VCAP_S2_CFG_SEC_ENA_GET(value)) out->prf(out->dst, "on"); else out->prf(out->dst, "off"); /* Get key selection state */ value = spx5_rd(sparx5, ANA_ACL_VCAP_S2_KEY_SEL(port->portno, lookup)); out->prf(out->dst, "\n noneth: "); switch (ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_GET(value)) { case VCAP_IS2_PS_NONETH_MAC_ETYPE: out->prf(out->dst, "mac_etype"); break; case VCAP_IS2_PS_NONETH_CUSTOM_1: out->prf(out->dst, "custom1"); break; case VCAP_IS2_PS_NONETH_CUSTOM_2: out->prf(out->dst, "custom2"); break; case VCAP_IS2_PS_NONETH_NO_LOOKUP: out->prf(out->dst, "none"); break; } out->prf(out->dst, "\n ipv4_mc: "); switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value)) { case VCAP_IS2_PS_IPV4_MC_MAC_ETYPE: out->prf(out->dst, "mac_etype"); break; case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER: out->prf(out->dst, "ip4_tcp_udp ip4_other"); break; case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE: out->prf(out->dst, "ip_7tuple"); break; case VCAP_IS2_PS_IPV4_MC_IP4_VID: out->prf(out->dst, "ip4_vid"); break; } out->prf(out->dst, "\n ipv4_uc: "); switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value)) { case VCAP_IS2_PS_IPV4_UC_MAC_ETYPE: out->prf(out->dst, "mac_etype"); break; case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER: out->prf(out->dst, "ip4_tcp_udp ip4_other"); break; case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE: out->prf(out->dst, "ip_7tuple"); break; } out->prf(out->dst, "\n ipv6_mc: "); switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value)) { case VCAP_IS2_PS_IPV6_MC_MAC_ETYPE: out->prf(out->dst, "mac_etype"); break; case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE: out->prf(out->dst, "ip_7tuple"); break; case VCAP_IS2_PS_IPV6_MC_IP6_VID: out->prf(out->dst, "ip6_vid"); break; case VCAP_IS2_PS_IPV6_MC_IP6_STD: out->prf(out->dst, "ip6_std"); break; case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER: out->prf(out->dst, "ip4_tcp_udp ipv4_other"); break; } out->prf(out->dst, "\n ipv6_uc: "); switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value)) { case VCAP_IS2_PS_IPV6_UC_MAC_ETYPE: out->prf(out->dst, "mac_etype"); break; case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE: out->prf(out->dst, "ip_7tuple"); break; case VCAP_IS2_PS_IPV6_UC_IP6_STD: out->prf(out->dst, "ip6_std"); break; case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER: out->prf(out->dst, "ip4_tcp_udp ip4_other"); break; } out->prf(out->dst, "\n arp: "); switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value)) { case VCAP_IS2_PS_ARP_MAC_ETYPE: out->prf(out->dst, "mac_etype"); break; case VCAP_IS2_PS_ARP_ARP: out->prf(out->dst, "arp"); break; } } out->prf(out->dst, "\n"); } static void sparx5_vcap_port_stickies(struct sparx5 *sparx5, struct vcap_admin *admin, struct vcap_output_print *out) { int lookup; u32 value; out->prf(out->dst, " Sticky bits: "); for (lookup = 0; lookup < admin->lookups; ++lookup) { out->prf(out->dst, "\n Lookup %d: ", lookup); /* Get lookup sticky bits */ value = spx5_rd(sparx5, ANA_ACL_SEC_LOOKUP_STICKY(lookup)); if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_CLM_STICKY_GET(value)) out->prf(out->dst, " sel_clm"); if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_IRLEG_STICKY_GET(value)) out->prf(out->dst, " sel_irleg"); if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_ERLEG_STICKY_GET(value)) out->prf(out->dst, " sel_erleg"); if (ANA_ACL_SEC_LOOKUP_STICKY_KEY_SEL_PORT_STICKY_GET(value)) out->prf(out->dst, " sel_port"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_CUSTOM2_STICKY_GET(value)) out->prf(out->dst, " custom2"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_CUSTOM1_STICKY_GET(value)) out->prf(out->dst, " custom1"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_OAM_STICKY_GET(value)) out->prf(out->dst, " oam"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_VID_STICKY_GET(value)) out->prf(out->dst, " ip6_vid"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_STD_STICKY_GET(value)) out->prf(out->dst, " ip6_std"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP6_TCPUDP_STICKY_GET(value)) out->prf(out->dst, " ip6_tcpudp"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP_7TUPLE_STICKY_GET(value)) out->prf(out->dst, " ip_7tuple"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_VID_STICKY_GET(value)) out->prf(out->dst, " ip4_vid"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_TCPUDP_STICKY_GET(value)) out->prf(out->dst, " ip4_tcpudp"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_IP4_OTHER_STICKY_GET(value)) out->prf(out->dst, " ip4_other"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_ARP_STICKY_GET(value)) out->prf(out->dst, " arp"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_SNAP_STICKY_GET(value)) out->prf(out->dst, " mac_snap"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_LLC_STICKY_GET(value)) out->prf(out->dst, " mac_llc"); if (ANA_ACL_SEC_LOOKUP_STICKY_SEC_TYPE_MAC_ETYPE_STICKY_GET(value)) out->prf(out->dst, " mac_etype"); /* Clear stickies */ spx5_wr(value, sparx5, ANA_ACL_SEC_LOOKUP_STICKY(lookup)); } out->prf(out->dst, "\n"); } /* Provide port information via a callback interface */ int sparx5_port_info(struct net_device *ndev, struct vcap_admin *admin, struct vcap_output_print *out) { struct sparx5_port *port = netdev_priv(ndev); struct sparx5 *sparx5 = port->sparx5; const struct vcap_info *vcap; struct vcap_control *vctrl; vctrl = sparx5->vcap_ctrl; vcap = &vctrl->vcaps[admin->vtype]; out->prf(out->dst, "%s:\n", vcap->name); sparx5_vcap_port_keys(sparx5, admin, port, out); sparx5_vcap_port_stickies(sparx5, admin, out); return 0; }