diff options
Diffstat (limited to 'drivers/net/ethernet/marvell/prestera/prestera_devlink.c')
-rw-r--r-- | drivers/net/ethernet/marvell/prestera/prestera_devlink.c | 620 |
1 files changed, 620 insertions, 0 deletions
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_devlink.c b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c new file mode 100644 index 000000000..06279cd6d --- /dev/null +++ b/drivers/net/ethernet/marvell/prestera/prestera_devlink.c @@ -0,0 +1,620 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */ + +#include <net/devlink.h> + +#include "prestera_devlink.h" +#include "prestera_hw.h" + +/* All driver-specific traps must be documented in + * Documentation/networking/devlink/prestera.rst + */ +enum { + DEVLINK_PRESTERA_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX, + DEVLINK_PRESTERA_TRAP_ID_ARP_BC, + DEVLINK_PRESTERA_TRAP_ID_IS_IS, + DEVLINK_PRESTERA_TRAP_ID_OSPF, + DEVLINK_PRESTERA_TRAP_ID_IP_BC_MAC, + DEVLINK_PRESTERA_TRAP_ID_ROUTER_MC, + DEVLINK_PRESTERA_TRAP_ID_VRRP, + DEVLINK_PRESTERA_TRAP_ID_DHCP, + DEVLINK_PRESTERA_TRAP_ID_MAC_TO_ME, + DEVLINK_PRESTERA_TRAP_ID_IPV4_OPTIONS, + DEVLINK_PRESTERA_TRAP_ID_IP_DEFAULT_ROUTE, + DEVLINK_PRESTERA_TRAP_ID_IP_TO_ME, + DEVLINK_PRESTERA_TRAP_ID_IPV4_ICMP_REDIRECT, + DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_0, + DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_1, + DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_2, + DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_3, + DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_4, + DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_5, + DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_6, + DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_7, + DEVLINK_PRESTERA_TRAP_ID_BGP, + DEVLINK_PRESTERA_TRAP_ID_SSH, + DEVLINK_PRESTERA_TRAP_ID_TELNET, + DEVLINK_PRESTERA_TRAP_ID_ICMP, + DEVLINK_PRESTERA_TRAP_ID_MET_RED, + DEVLINK_PRESTERA_TRAP_ID_IP_SIP_IS_ZERO, + DEVLINK_PRESTERA_TRAP_ID_IP_UC_DIP_DA_MISMATCH, + DEVLINK_PRESTERA_TRAP_ID_ILLEGAL_IPV4_HDR, + DEVLINK_PRESTERA_TRAP_ID_ILLEGAL_IP_ADDR, + DEVLINK_PRESTERA_TRAP_ID_INVALID_SA, + DEVLINK_PRESTERA_TRAP_ID_LOCAL_PORT, + DEVLINK_PRESTERA_TRAP_ID_PORT_NO_VLAN, + DEVLINK_PRESTERA_TRAP_ID_RXDMA_DROP, +}; + +#define DEVLINK_PRESTERA_TRAP_NAME_ARP_BC \ + "arp_bc" +#define DEVLINK_PRESTERA_TRAP_NAME_IS_IS \ + "is_is" +#define DEVLINK_PRESTERA_TRAP_NAME_OSPF \ + "ospf" +#define DEVLINK_PRESTERA_TRAP_NAME_IP_BC_MAC \ + "ip_bc_mac" +#define DEVLINK_PRESTERA_TRAP_NAME_ROUTER_MC \ + "router_mc" +#define DEVLINK_PRESTERA_TRAP_NAME_VRRP \ + "vrrp" +#define DEVLINK_PRESTERA_TRAP_NAME_DHCP \ + "dhcp" +#define DEVLINK_PRESTERA_TRAP_NAME_MAC_TO_ME \ + "mac_to_me" +#define DEVLINK_PRESTERA_TRAP_NAME_IPV4_OPTIONS \ + "ipv4_options" +#define DEVLINK_PRESTERA_TRAP_NAME_IP_DEFAULT_ROUTE \ + "ip_default_route" +#define DEVLINK_PRESTERA_TRAP_NAME_IP_TO_ME \ + "ip_to_me" +#define DEVLINK_PRESTERA_TRAP_NAME_IPV4_ICMP_REDIRECT \ + "ipv4_icmp_redirect" +#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_0 \ + "acl_code_0" +#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_1 \ + "acl_code_1" +#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_2 \ + "acl_code_2" +#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_3 \ + "acl_code_3" +#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_4 \ + "acl_code_4" +#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_5 \ + "acl_code_5" +#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_6 \ + "acl_code_6" +#define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_7 \ + "acl_code_7" +#define DEVLINK_PRESTERA_TRAP_NAME_BGP \ + "bgp" +#define DEVLINK_PRESTERA_TRAP_NAME_SSH \ + "ssh" +#define DEVLINK_PRESTERA_TRAP_NAME_TELNET \ + "telnet" +#define DEVLINK_PRESTERA_TRAP_NAME_ICMP \ + "icmp" +#define DEVLINK_PRESTERA_TRAP_NAME_RXDMA_DROP \ + "rxdma_drop" +#define DEVLINK_PRESTERA_TRAP_NAME_PORT_NO_VLAN \ + "port_no_vlan" +#define DEVLINK_PRESTERA_TRAP_NAME_LOCAL_PORT \ + "local_port" +#define DEVLINK_PRESTERA_TRAP_NAME_INVALID_SA \ + "invalid_sa" +#define DEVLINK_PRESTERA_TRAP_NAME_ILLEGAL_IP_ADDR \ + "illegal_ip_addr" +#define DEVLINK_PRESTERA_TRAP_NAME_ILLEGAL_IPV4_HDR \ + "illegal_ipv4_hdr" +#define DEVLINK_PRESTERA_TRAP_NAME_IP_UC_DIP_DA_MISMATCH \ + "ip_uc_dip_da_mismatch" +#define DEVLINK_PRESTERA_TRAP_NAME_IP_SIP_IS_ZERO \ + "ip_sip_is_zero" +#define DEVLINK_PRESTERA_TRAP_NAME_MET_RED \ + "met_red" + +struct prestera_trap { + struct devlink_trap trap; + u8 cpu_code; +}; + +struct prestera_trap_item { + enum devlink_trap_action action; + void *trap_ctx; +}; + +struct prestera_trap_data { + struct prestera_switch *sw; + struct prestera_trap_item *trap_items_arr; + u32 traps_count; +}; + +#define PRESTERA_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT + +#define PRESTERA_TRAP_CONTROL(_id, _group_id, _action) \ + DEVLINK_TRAP_GENERIC(CONTROL, _action, _id, \ + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ + PRESTERA_TRAP_METADATA) + +#define PRESTERA_TRAP_DRIVER_CONTROL(_id, _group_id) \ + DEVLINK_TRAP_DRIVER(CONTROL, TRAP, DEVLINK_PRESTERA_TRAP_ID_##_id, \ + DEVLINK_PRESTERA_TRAP_NAME_##_id, \ + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ + PRESTERA_TRAP_METADATA) + +#define PRESTERA_TRAP_EXCEPTION(_id, _group_id) \ + DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \ + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ + PRESTERA_TRAP_METADATA) + +#define PRESTERA_TRAP_DRIVER_EXCEPTION(_id, _group_id) \ + DEVLINK_TRAP_DRIVER(EXCEPTION, TRAP, DEVLINK_PRESTERA_TRAP_ID_##_id, \ + DEVLINK_PRESTERA_TRAP_NAME_##_id, \ + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ + PRESTERA_TRAP_METADATA) + +#define PRESTERA_TRAP_DRIVER_DROP(_id, _group_id) \ + DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_PRESTERA_TRAP_ID_##_id, \ + DEVLINK_PRESTERA_TRAP_NAME_##_id, \ + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ + PRESTERA_TRAP_METADATA) + +static const struct devlink_trap_group prestera_trap_groups_arr[] = { + /* No policer is associated with following groups (policerid == 0)*/ + DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0), + DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 0), + DEVLINK_TRAP_GROUP_GENERIC(L3_EXCEPTIONS, 0), + DEVLINK_TRAP_GROUP_GENERIC(NEIGH_DISCOVERY, 0), + DEVLINK_TRAP_GROUP_GENERIC(ACL_TRAP, 0), + DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 0), + DEVLINK_TRAP_GROUP_GENERIC(ACL_SAMPLE, 0), + DEVLINK_TRAP_GROUP_GENERIC(OSPF, 0), + DEVLINK_TRAP_GROUP_GENERIC(STP, 0), + DEVLINK_TRAP_GROUP_GENERIC(LACP, 0), + DEVLINK_TRAP_GROUP_GENERIC(LLDP, 0), + DEVLINK_TRAP_GROUP_GENERIC(VRRP, 0), + DEVLINK_TRAP_GROUP_GENERIC(DHCP, 0), + DEVLINK_TRAP_GROUP_GENERIC(BGP, 0), + DEVLINK_TRAP_GROUP_GENERIC(LOCAL_DELIVERY, 0), + DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 0), +}; + +/* Initialize trap list, as well as associate CPU code with them. */ +static struct prestera_trap prestera_trap_items_arr[] = { + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ARP_BC, NEIGH_DISCOVERY), + .cpu_code = 5, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(IS_IS, LOCAL_DELIVERY), + .cpu_code = 13, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(OSPF, OSPF), + .cpu_code = 16, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(IP_BC_MAC, LOCAL_DELIVERY), + .cpu_code = 19, + }, + { + .trap = PRESTERA_TRAP_CONTROL(STP, STP, TRAP), + .cpu_code = 26, + }, + { + .trap = PRESTERA_TRAP_CONTROL(LACP, LACP, TRAP), + .cpu_code = 27, + }, + { + .trap = PRESTERA_TRAP_CONTROL(LLDP, LLDP, TRAP), + .cpu_code = 28, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ROUTER_MC, LOCAL_DELIVERY), + .cpu_code = 29, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(VRRP, VRRP), + .cpu_code = 30, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(DHCP, DHCP), + .cpu_code = 33, + }, + { + .trap = PRESTERA_TRAP_EXCEPTION(MTU_ERROR, L3_EXCEPTIONS), + .cpu_code = 63, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(MAC_TO_ME, LOCAL_DELIVERY), + .cpu_code = 65, + }, + { + .trap = PRESTERA_TRAP_EXCEPTION(TTL_ERROR, L3_EXCEPTIONS), + .cpu_code = 133, + }, + { + .trap = PRESTERA_TRAP_DRIVER_EXCEPTION(IPV4_OPTIONS, + L3_EXCEPTIONS), + .cpu_code = 141, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(IP_DEFAULT_ROUTE, + LOCAL_DELIVERY), + .cpu_code = 160, + }, + { + .trap = PRESTERA_TRAP_CONTROL(LOCAL_ROUTE, LOCAL_DELIVERY, + TRAP), + .cpu_code = 161, + }, + { + .trap = PRESTERA_TRAP_DRIVER_EXCEPTION(IPV4_ICMP_REDIRECT, + L3_EXCEPTIONS), + .cpu_code = 180, + }, + { + .trap = PRESTERA_TRAP_CONTROL(ARP_RESPONSE, NEIGH_DISCOVERY, + TRAP), + .cpu_code = 188, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_0, ACL_TRAP), + .cpu_code = 192, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_1, ACL_TRAP), + .cpu_code = 193, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_2, ACL_TRAP), + .cpu_code = 194, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_3, ACL_TRAP), + .cpu_code = 195, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_4, ACL_TRAP), + .cpu_code = 196, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_5, ACL_TRAP), + .cpu_code = 197, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_6, ACL_TRAP), + .cpu_code = 198, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_7, ACL_TRAP), + .cpu_code = 199, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(BGP, BGP), + .cpu_code = 206, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(SSH, LOCAL_DELIVERY), + .cpu_code = 207, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(TELNET, LOCAL_DELIVERY), + .cpu_code = 208, + }, + { + .trap = PRESTERA_TRAP_DRIVER_CONTROL(ICMP, LOCAL_DELIVERY), + .cpu_code = 209, + }, + { + .trap = PRESTERA_TRAP_DRIVER_DROP(RXDMA_DROP, BUFFER_DROPS), + .cpu_code = 37, + }, + { + .trap = PRESTERA_TRAP_DRIVER_DROP(PORT_NO_VLAN, L2_DROPS), + .cpu_code = 39, + }, + { + .trap = PRESTERA_TRAP_DRIVER_DROP(LOCAL_PORT, L2_DROPS), + .cpu_code = 56, + }, + { + .trap = PRESTERA_TRAP_DRIVER_DROP(INVALID_SA, L2_DROPS), + .cpu_code = 60, + }, + { + .trap = PRESTERA_TRAP_DRIVER_DROP(ILLEGAL_IP_ADDR, L3_DROPS), + .cpu_code = 136, + }, + { + .trap = PRESTERA_TRAP_DRIVER_DROP(ILLEGAL_IPV4_HDR, L3_DROPS), + .cpu_code = 137, + }, + { + .trap = PRESTERA_TRAP_DRIVER_DROP(IP_UC_DIP_DA_MISMATCH, + L3_DROPS), + .cpu_code = 138, + }, + { + .trap = PRESTERA_TRAP_DRIVER_DROP(IP_SIP_IS_ZERO, L3_DROPS), + .cpu_code = 145, + }, + { + .trap = PRESTERA_TRAP_DRIVER_DROP(MET_RED, BUFFER_DROPS), + .cpu_code = 185, + }, +}; + +static int prestera_drop_counter_get(struct devlink *devlink, + const struct devlink_trap *trap, + u64 *p_drops); + +static int prestera_dl_info_get(struct devlink *dl, + struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + struct prestera_switch *sw = devlink_priv(dl); + char buf[16]; + int err; + + err = devlink_info_driver_name_put(req, PRESTERA_DRV_NAME); + if (err) + return err; + + snprintf(buf, sizeof(buf), "%d.%d.%d", + sw->dev->fw_rev.maj, + sw->dev->fw_rev.min, + sw->dev->fw_rev.sub); + + return devlink_info_version_running_put(req, + DEVLINK_INFO_VERSION_GENERIC_FW, + buf); +} + +static int prestera_trap_init(struct devlink *devlink, + const struct devlink_trap *trap, void *trap_ctx); + +static int prestera_trap_action_set(struct devlink *devlink, + const struct devlink_trap *trap, + enum devlink_trap_action action, + struct netlink_ext_ack *extack); + +static const struct devlink_ops prestera_dl_ops = { + .info_get = prestera_dl_info_get, + .trap_init = prestera_trap_init, + .trap_action_set = prestera_trap_action_set, + .trap_drop_counter_get = prestera_drop_counter_get, +}; + +struct prestera_switch *prestera_devlink_alloc(struct prestera_device *dev) +{ + struct devlink *dl; + + dl = devlink_alloc(&prestera_dl_ops, sizeof(struct prestera_switch), + dev->dev); + + return devlink_priv(dl); +} + +void prestera_devlink_free(struct prestera_switch *sw) +{ + struct devlink *dl = priv_to_devlink(sw); + + devlink_free(dl); +} + +void prestera_devlink_register(struct prestera_switch *sw) +{ + struct devlink *dl = priv_to_devlink(sw); + + devlink_register(dl); +} + +void prestera_devlink_unregister(struct prestera_switch *sw) +{ + struct devlink *dl = priv_to_devlink(sw); + + devlink_unregister(dl); +} + +int prestera_devlink_port_register(struct prestera_port *port) +{ + struct prestera_switch *sw = port->sw; + struct devlink *dl = priv_to_devlink(sw); + struct devlink_port_attrs attrs = {}; + int err; + + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; + attrs.phys.port_number = port->fp_id; + attrs.switch_id.id_len = sizeof(sw->id); + memcpy(attrs.switch_id.id, &sw->id, attrs.switch_id.id_len); + + devlink_port_attrs_set(&port->dl_port, &attrs); + + err = devlink_port_register(dl, &port->dl_port, port->fp_id); + if (err) { + dev_err(prestera_dev(sw), "devlink_port_register failed: %d\n", err); + return err; + } + + return 0; +} + +void prestera_devlink_port_unregister(struct prestera_port *port) +{ + devlink_port_unregister(&port->dl_port); +} + +void prestera_devlink_port_set(struct prestera_port *port) +{ + devlink_port_type_eth_set(&port->dl_port, port->dev); +} + +void prestera_devlink_port_clear(struct prestera_port *port) +{ + devlink_port_type_clear(&port->dl_port); +} + +struct devlink_port *prestera_devlink_get_port(struct net_device *dev) +{ + struct prestera_port *port = netdev_priv(dev); + + return &port->dl_port; +} + +int prestera_devlink_traps_register(struct prestera_switch *sw) +{ + const u32 groups_count = ARRAY_SIZE(prestera_trap_groups_arr); + const u32 traps_count = ARRAY_SIZE(prestera_trap_items_arr); + struct devlink *devlink = priv_to_devlink(sw); + struct prestera_trap_data *trap_data; + struct prestera_trap *prestera_trap; + int err, i; + + trap_data = kzalloc(sizeof(*trap_data), GFP_KERNEL); + if (!trap_data) + return -ENOMEM; + + trap_data->trap_items_arr = kcalloc(traps_count, + sizeof(struct prestera_trap_item), + GFP_KERNEL); + if (!trap_data->trap_items_arr) { + err = -ENOMEM; + goto err_trap_items_alloc; + } + + trap_data->sw = sw; + trap_data->traps_count = traps_count; + sw->trap_data = trap_data; + + err = devlink_trap_groups_register(devlink, prestera_trap_groups_arr, + groups_count); + if (err) + goto err_groups_register; + + for (i = 0; i < traps_count; i++) { + prestera_trap = &prestera_trap_items_arr[i]; + err = devlink_traps_register(devlink, &prestera_trap->trap, 1, + sw); + if (err) + goto err_trap_register; + } + + return 0; + +err_trap_register: + for (i--; i >= 0; i--) { + prestera_trap = &prestera_trap_items_arr[i]; + devlink_traps_unregister(devlink, &prestera_trap->trap, 1); + } + devlink_trap_groups_unregister(devlink, prestera_trap_groups_arr, + groups_count); +err_groups_register: + kfree(trap_data->trap_items_arr); +err_trap_items_alloc: + kfree(trap_data); + return err; +} + +static struct prestera_trap_item * +prestera_get_trap_item_by_cpu_code(struct prestera_switch *sw, u8 cpu_code) +{ + struct prestera_trap_data *trap_data = sw->trap_data; + struct prestera_trap *prestera_trap; + int i; + + for (i = 0; i < trap_data->traps_count; i++) { + prestera_trap = &prestera_trap_items_arr[i]; + if (cpu_code == prestera_trap->cpu_code) + return &trap_data->trap_items_arr[i]; + } + + return NULL; +} + +void prestera_devlink_trap_report(struct prestera_port *port, + struct sk_buff *skb, u8 cpu_code) +{ + struct prestera_trap_item *trap_item; + struct devlink *devlink; + + devlink = port->dl_port.devlink; + + trap_item = prestera_get_trap_item_by_cpu_code(port->sw, cpu_code); + if (unlikely(!trap_item)) + return; + + devlink_trap_report(devlink, skb, trap_item->trap_ctx, + &port->dl_port, NULL); +} + +static struct prestera_trap_item * +prestera_devlink_trap_item_lookup(struct prestera_switch *sw, u16 trap_id) +{ + struct prestera_trap_data *trap_data = sw->trap_data; + int i; + + for (i = 0; i < ARRAY_SIZE(prestera_trap_items_arr); i++) { + if (prestera_trap_items_arr[i].trap.id == trap_id) + return &trap_data->trap_items_arr[i]; + } + + return NULL; +} + +static int prestera_trap_init(struct devlink *devlink, + const struct devlink_trap *trap, void *trap_ctx) +{ + struct prestera_switch *sw = devlink_priv(devlink); + struct prestera_trap_item *trap_item; + + trap_item = prestera_devlink_trap_item_lookup(sw, trap->id); + if (WARN_ON(!trap_item)) + return -EINVAL; + + trap_item->trap_ctx = trap_ctx; + trap_item->action = trap->init_action; + + return 0; +} + +static int prestera_trap_action_set(struct devlink *devlink, + const struct devlink_trap *trap, + enum devlink_trap_action action, + struct netlink_ext_ack *extack) +{ + /* Currently, driver does not support trap action altering */ + return -EOPNOTSUPP; +} + +static int prestera_drop_counter_get(struct devlink *devlink, + const struct devlink_trap *trap, + u64 *p_drops) +{ + struct prestera_switch *sw = devlink_priv(devlink); + enum prestera_hw_cpu_code_cnt_t cpu_code_type = + PRESTERA_HW_CPU_CODE_CNT_TYPE_DROP; + struct prestera_trap *prestera_trap = + container_of(trap, struct prestera_trap, trap); + + return prestera_hw_cpu_code_counters_get(sw, prestera_trap->cpu_code, + cpu_code_type, p_drops); +} + +void prestera_devlink_traps_unregister(struct prestera_switch *sw) +{ + struct prestera_trap_data *trap_data = sw->trap_data; + struct devlink *dl = priv_to_devlink(sw); + const struct devlink_trap *trap; + int i; + + for (i = 0; i < ARRAY_SIZE(prestera_trap_items_arr); ++i) { + trap = &prestera_trap_items_arr[i].trap; + devlink_traps_unregister(dl, trap, 1); + } + + devlink_trap_groups_unregister(dl, prestera_trap_groups_arr, + ARRAY_SIZE(prestera_trap_groups_arr)); + kfree(trap_data->trap_items_arr); + kfree(trap_data); +} |