134dd1710SVadym Kochan // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
234dd1710SVadym Kochan /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
334dd1710SVadym Kochan
434dd1710SVadym Kochan #include <net/devlink.h>
534dd1710SVadym Kochan
634dd1710SVadym Kochan #include "prestera_devlink.h"
7a80cf955SOleksandr Mazur #include "prestera_hw.h"
834dd1710SVadym Kochan
90a9003f4SOleksandr Mazur /* All driver-specific traps must be documented in
100a9003f4SOleksandr Mazur * Documentation/networking/devlink/prestera.rst
110a9003f4SOleksandr Mazur */
120a9003f4SOleksandr Mazur enum {
130a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX,
140a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ARP_BC,
150a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IS_IS,
160a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_OSPF,
170a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_BC_MAC,
180a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ROUTER_MC,
190a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_VRRP,
200a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_DHCP,
210a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_MAC_TO_ME,
220a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IPV4_OPTIONS,
230a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_DEFAULT_ROUTE,
240a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_TO_ME,
250a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IPV4_ICMP_REDIRECT,
260a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_0,
270a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_1,
280a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_2,
290a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_3,
300a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_4,
310a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_5,
320a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_6,
330a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ACL_CODE_7,
340a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_BGP,
350a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_SSH,
360a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_TELNET,
370a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ICMP,
38a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_MET_RED,
39a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_SIP_IS_ZERO,
40a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_IP_UC_DIP_DA_MISMATCH,
41a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ILLEGAL_IPV4_HDR,
42a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_ILLEGAL_IP_ADDR,
43a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_INVALID_SA,
44a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_LOCAL_PORT,
45a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_PORT_NO_VLAN,
46a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_ID_RXDMA_DROP,
470a9003f4SOleksandr Mazur };
480a9003f4SOleksandr Mazur
490a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ARP_BC \
500a9003f4SOleksandr Mazur "arp_bc"
510a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IS_IS \
520a9003f4SOleksandr Mazur "is_is"
530a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_OSPF \
540a9003f4SOleksandr Mazur "ospf"
550a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_BC_MAC \
560a9003f4SOleksandr Mazur "ip_bc_mac"
570a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ROUTER_MC \
580a9003f4SOleksandr Mazur "router_mc"
590a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_VRRP \
600a9003f4SOleksandr Mazur "vrrp"
610a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_DHCP \
620a9003f4SOleksandr Mazur "dhcp"
630a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_MAC_TO_ME \
640a9003f4SOleksandr Mazur "mac_to_me"
650a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IPV4_OPTIONS \
660a9003f4SOleksandr Mazur "ipv4_options"
670a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_DEFAULT_ROUTE \
680a9003f4SOleksandr Mazur "ip_default_route"
690a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_TO_ME \
700a9003f4SOleksandr Mazur "ip_to_me"
710a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IPV4_ICMP_REDIRECT \
720a9003f4SOleksandr Mazur "ipv4_icmp_redirect"
730a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_0 \
740a9003f4SOleksandr Mazur "acl_code_0"
750a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_1 \
760a9003f4SOleksandr Mazur "acl_code_1"
770a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_2 \
780a9003f4SOleksandr Mazur "acl_code_2"
790a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_3 \
800a9003f4SOleksandr Mazur "acl_code_3"
810a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_4 \
820a9003f4SOleksandr Mazur "acl_code_4"
830a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_5 \
840a9003f4SOleksandr Mazur "acl_code_5"
850a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_6 \
860a9003f4SOleksandr Mazur "acl_code_6"
870a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ACL_CODE_7 \
880a9003f4SOleksandr Mazur "acl_code_7"
890a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_BGP \
900a9003f4SOleksandr Mazur "bgp"
910a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_SSH \
920a9003f4SOleksandr Mazur "ssh"
930a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_TELNET \
940a9003f4SOleksandr Mazur "telnet"
950a9003f4SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ICMP \
960a9003f4SOleksandr Mazur "icmp"
97a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_RXDMA_DROP \
98a80cf955SOleksandr Mazur "rxdma_drop"
99a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_PORT_NO_VLAN \
100a80cf955SOleksandr Mazur "port_no_vlan"
101a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_LOCAL_PORT \
102a80cf955SOleksandr Mazur "local_port"
103a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_INVALID_SA \
104a80cf955SOleksandr Mazur "invalid_sa"
105a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ILLEGAL_IP_ADDR \
106a80cf955SOleksandr Mazur "illegal_ip_addr"
107a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_ILLEGAL_IPV4_HDR \
108a80cf955SOleksandr Mazur "illegal_ipv4_hdr"
109a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_UC_DIP_DA_MISMATCH \
110a80cf955SOleksandr Mazur "ip_uc_dip_da_mismatch"
111a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_IP_SIP_IS_ZERO \
112a80cf955SOleksandr Mazur "ip_sip_is_zero"
113a80cf955SOleksandr Mazur #define DEVLINK_PRESTERA_TRAP_NAME_MET_RED \
114a80cf955SOleksandr Mazur "met_red"
1150a9003f4SOleksandr Mazur
1160a9003f4SOleksandr Mazur struct prestera_trap {
1170a9003f4SOleksandr Mazur struct devlink_trap trap;
1180a9003f4SOleksandr Mazur u8 cpu_code;
1190a9003f4SOleksandr Mazur };
1200a9003f4SOleksandr Mazur
1210a9003f4SOleksandr Mazur struct prestera_trap_item {
1220a9003f4SOleksandr Mazur enum devlink_trap_action action;
1230a9003f4SOleksandr Mazur void *trap_ctx;
1240a9003f4SOleksandr Mazur };
1250a9003f4SOleksandr Mazur
1260a9003f4SOleksandr Mazur struct prestera_trap_data {
1270a9003f4SOleksandr Mazur struct prestera_switch *sw;
1280a9003f4SOleksandr Mazur struct prestera_trap_item *trap_items_arr;
1290a9003f4SOleksandr Mazur u32 traps_count;
1300a9003f4SOleksandr Mazur };
1310a9003f4SOleksandr Mazur
1320a9003f4SOleksandr Mazur #define PRESTERA_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
1330a9003f4SOleksandr Mazur
1340a9003f4SOleksandr Mazur #define PRESTERA_TRAP_CONTROL(_id, _group_id, _action) \
1350a9003f4SOleksandr Mazur DEVLINK_TRAP_GENERIC(CONTROL, _action, _id, \
1360a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
1370a9003f4SOleksandr Mazur PRESTERA_TRAP_METADATA)
1380a9003f4SOleksandr Mazur
1390a9003f4SOleksandr Mazur #define PRESTERA_TRAP_DRIVER_CONTROL(_id, _group_id) \
1400a9003f4SOleksandr Mazur DEVLINK_TRAP_DRIVER(CONTROL, TRAP, DEVLINK_PRESTERA_TRAP_ID_##_id, \
1410a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_NAME_##_id, \
1420a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
1430a9003f4SOleksandr Mazur PRESTERA_TRAP_METADATA)
1440a9003f4SOleksandr Mazur
1450a9003f4SOleksandr Mazur #define PRESTERA_TRAP_EXCEPTION(_id, _group_id) \
1460a9003f4SOleksandr Mazur DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \
1470a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
1480a9003f4SOleksandr Mazur PRESTERA_TRAP_METADATA)
1490a9003f4SOleksandr Mazur
1500a9003f4SOleksandr Mazur #define PRESTERA_TRAP_DRIVER_EXCEPTION(_id, _group_id) \
1510a9003f4SOleksandr Mazur DEVLINK_TRAP_DRIVER(EXCEPTION, TRAP, DEVLINK_PRESTERA_TRAP_ID_##_id, \
1520a9003f4SOleksandr Mazur DEVLINK_PRESTERA_TRAP_NAME_##_id, \
1530a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
1540a9003f4SOleksandr Mazur PRESTERA_TRAP_METADATA)
1550a9003f4SOleksandr Mazur
156a80cf955SOleksandr Mazur #define PRESTERA_TRAP_DRIVER_DROP(_id, _group_id) \
157a80cf955SOleksandr Mazur DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_PRESTERA_TRAP_ID_##_id, \
158a80cf955SOleksandr Mazur DEVLINK_PRESTERA_TRAP_NAME_##_id, \
159a80cf955SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
160a80cf955SOleksandr Mazur PRESTERA_TRAP_METADATA)
161a80cf955SOleksandr Mazur
1620a9003f4SOleksandr Mazur static const struct devlink_trap_group prestera_trap_groups_arr[] = {
1630a9003f4SOleksandr Mazur /* No policer is associated with following groups (policerid == 0)*/
1640a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
1650a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 0),
1660a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(L3_EXCEPTIONS, 0),
1670a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(NEIGH_DISCOVERY, 0),
1680a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(ACL_TRAP, 0),
1690a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 0),
1700a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(ACL_SAMPLE, 0),
1710a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(OSPF, 0),
1720a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(STP, 0),
1730a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(LACP, 0),
1740a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(LLDP, 0),
1750a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(VRRP, 0),
1760a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(DHCP, 0),
1770a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(BGP, 0),
1780a9003f4SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(LOCAL_DELIVERY, 0),
179a80cf955SOleksandr Mazur DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 0),
1800a9003f4SOleksandr Mazur };
1810a9003f4SOleksandr Mazur
1820a9003f4SOleksandr Mazur /* Initialize trap list, as well as associate CPU code with them. */
1830a9003f4SOleksandr Mazur static struct prestera_trap prestera_trap_items_arr[] = {
1840a9003f4SOleksandr Mazur {
1850a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ARP_BC, NEIGH_DISCOVERY),
1860a9003f4SOleksandr Mazur .cpu_code = 5,
1870a9003f4SOleksandr Mazur },
1880a9003f4SOleksandr Mazur {
1890a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(IS_IS, LOCAL_DELIVERY),
1900a9003f4SOleksandr Mazur .cpu_code = 13,
1910a9003f4SOleksandr Mazur },
1920a9003f4SOleksandr Mazur {
1930a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(OSPF, OSPF),
1940a9003f4SOleksandr Mazur .cpu_code = 16,
1950a9003f4SOleksandr Mazur },
1960a9003f4SOleksandr Mazur {
1970a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(IP_BC_MAC, LOCAL_DELIVERY),
1980a9003f4SOleksandr Mazur .cpu_code = 19,
1990a9003f4SOleksandr Mazur },
2000a9003f4SOleksandr Mazur {
2010a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(STP, STP, TRAP),
2020a9003f4SOleksandr Mazur .cpu_code = 26,
2030a9003f4SOleksandr Mazur },
2040a9003f4SOleksandr Mazur {
2050a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(LACP, LACP, TRAP),
2060a9003f4SOleksandr Mazur .cpu_code = 27,
2070a9003f4SOleksandr Mazur },
2080a9003f4SOleksandr Mazur {
2090a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(LLDP, LLDP, TRAP),
2100a9003f4SOleksandr Mazur .cpu_code = 28,
2110a9003f4SOleksandr Mazur },
2120a9003f4SOleksandr Mazur {
2130a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ROUTER_MC, LOCAL_DELIVERY),
2140a9003f4SOleksandr Mazur .cpu_code = 29,
2150a9003f4SOleksandr Mazur },
2160a9003f4SOleksandr Mazur {
2170a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(VRRP, VRRP),
2180a9003f4SOleksandr Mazur .cpu_code = 30,
2190a9003f4SOleksandr Mazur },
2200a9003f4SOleksandr Mazur {
2210a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(DHCP, DHCP),
2220a9003f4SOleksandr Mazur .cpu_code = 33,
2230a9003f4SOleksandr Mazur },
2240a9003f4SOleksandr Mazur {
2250a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_EXCEPTION(MTU_ERROR, L3_EXCEPTIONS),
2260a9003f4SOleksandr Mazur .cpu_code = 63,
2270a9003f4SOleksandr Mazur },
2280a9003f4SOleksandr Mazur {
2290a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(MAC_TO_ME, LOCAL_DELIVERY),
2300a9003f4SOleksandr Mazur .cpu_code = 65,
2310a9003f4SOleksandr Mazur },
2320a9003f4SOleksandr Mazur {
2330a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_EXCEPTION(TTL_ERROR, L3_EXCEPTIONS),
2340a9003f4SOleksandr Mazur .cpu_code = 133,
2350a9003f4SOleksandr Mazur },
2360a9003f4SOleksandr Mazur {
2370a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_EXCEPTION(IPV4_OPTIONS,
2380a9003f4SOleksandr Mazur L3_EXCEPTIONS),
2390a9003f4SOleksandr Mazur .cpu_code = 141,
2400a9003f4SOleksandr Mazur },
2410a9003f4SOleksandr Mazur {
2420a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(IP_DEFAULT_ROUTE,
2430a9003f4SOleksandr Mazur LOCAL_DELIVERY),
2440a9003f4SOleksandr Mazur .cpu_code = 160,
2450a9003f4SOleksandr Mazur },
2460a9003f4SOleksandr Mazur {
2470a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(LOCAL_ROUTE, LOCAL_DELIVERY,
2480a9003f4SOleksandr Mazur TRAP),
2490a9003f4SOleksandr Mazur .cpu_code = 161,
2500a9003f4SOleksandr Mazur },
2510a9003f4SOleksandr Mazur {
2520a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_EXCEPTION(IPV4_ICMP_REDIRECT,
2530a9003f4SOleksandr Mazur L3_EXCEPTIONS),
2540a9003f4SOleksandr Mazur .cpu_code = 180,
2550a9003f4SOleksandr Mazur },
2560a9003f4SOleksandr Mazur {
2570a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_CONTROL(ARP_RESPONSE, NEIGH_DISCOVERY,
2580a9003f4SOleksandr Mazur TRAP),
2590a9003f4SOleksandr Mazur .cpu_code = 188,
2600a9003f4SOleksandr Mazur },
2610a9003f4SOleksandr Mazur {
2620a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_0, ACL_TRAP),
2630a9003f4SOleksandr Mazur .cpu_code = 192,
2640a9003f4SOleksandr Mazur },
2650a9003f4SOleksandr Mazur {
2660a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_1, ACL_TRAP),
2670a9003f4SOleksandr Mazur .cpu_code = 193,
2680a9003f4SOleksandr Mazur },
2690a9003f4SOleksandr Mazur {
2700a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_2, ACL_TRAP),
2710a9003f4SOleksandr Mazur .cpu_code = 194,
2720a9003f4SOleksandr Mazur },
2730a9003f4SOleksandr Mazur {
2740a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_3, ACL_TRAP),
2750a9003f4SOleksandr Mazur .cpu_code = 195,
2760a9003f4SOleksandr Mazur },
2770a9003f4SOleksandr Mazur {
2780a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_4, ACL_TRAP),
2790a9003f4SOleksandr Mazur .cpu_code = 196,
2800a9003f4SOleksandr Mazur },
2810a9003f4SOleksandr Mazur {
2820a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_5, ACL_TRAP),
2830a9003f4SOleksandr Mazur .cpu_code = 197,
2840a9003f4SOleksandr Mazur },
2850a9003f4SOleksandr Mazur {
2860a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_6, ACL_TRAP),
2870a9003f4SOleksandr Mazur .cpu_code = 198,
2880a9003f4SOleksandr Mazur },
2890a9003f4SOleksandr Mazur {
2900a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ACL_CODE_7, ACL_TRAP),
2910a9003f4SOleksandr Mazur .cpu_code = 199,
2920a9003f4SOleksandr Mazur },
2930a9003f4SOleksandr Mazur {
2940a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(BGP, BGP),
2950a9003f4SOleksandr Mazur .cpu_code = 206,
2960a9003f4SOleksandr Mazur },
2970a9003f4SOleksandr Mazur {
2980a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(SSH, LOCAL_DELIVERY),
2990a9003f4SOleksandr Mazur .cpu_code = 207,
3000a9003f4SOleksandr Mazur },
3010a9003f4SOleksandr Mazur {
3020a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(TELNET, LOCAL_DELIVERY),
3030a9003f4SOleksandr Mazur .cpu_code = 208,
3040a9003f4SOleksandr Mazur },
3050a9003f4SOleksandr Mazur {
3060a9003f4SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_CONTROL(ICMP, LOCAL_DELIVERY),
3070a9003f4SOleksandr Mazur .cpu_code = 209,
3080a9003f4SOleksandr Mazur },
309a80cf955SOleksandr Mazur {
310a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(RXDMA_DROP, BUFFER_DROPS),
311a80cf955SOleksandr Mazur .cpu_code = 37,
312a80cf955SOleksandr Mazur },
313a80cf955SOleksandr Mazur {
314a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(PORT_NO_VLAN, L2_DROPS),
315a80cf955SOleksandr Mazur .cpu_code = 39,
316a80cf955SOleksandr Mazur },
317a80cf955SOleksandr Mazur {
318a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(LOCAL_PORT, L2_DROPS),
319a80cf955SOleksandr Mazur .cpu_code = 56,
320a80cf955SOleksandr Mazur },
321a80cf955SOleksandr Mazur {
322a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(INVALID_SA, L2_DROPS),
323a80cf955SOleksandr Mazur .cpu_code = 60,
324a80cf955SOleksandr Mazur },
325a80cf955SOleksandr Mazur {
326a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(ILLEGAL_IP_ADDR, L3_DROPS),
327a80cf955SOleksandr Mazur .cpu_code = 136,
328a80cf955SOleksandr Mazur },
329a80cf955SOleksandr Mazur {
330a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(ILLEGAL_IPV4_HDR, L3_DROPS),
331a80cf955SOleksandr Mazur .cpu_code = 137,
332a80cf955SOleksandr Mazur },
333a80cf955SOleksandr Mazur {
334a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(IP_UC_DIP_DA_MISMATCH,
335a80cf955SOleksandr Mazur L3_DROPS),
336a80cf955SOleksandr Mazur .cpu_code = 138,
337a80cf955SOleksandr Mazur },
338a80cf955SOleksandr Mazur {
339a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(IP_SIP_IS_ZERO, L3_DROPS),
340a80cf955SOleksandr Mazur .cpu_code = 145,
341a80cf955SOleksandr Mazur },
342a80cf955SOleksandr Mazur {
343a80cf955SOleksandr Mazur .trap = PRESTERA_TRAP_DRIVER_DROP(MET_RED, BUFFER_DROPS),
344a80cf955SOleksandr Mazur .cpu_code = 185,
345a80cf955SOleksandr Mazur },
3460a9003f4SOleksandr Mazur };
3470a9003f4SOleksandr Mazur
348a80cf955SOleksandr Mazur static int prestera_drop_counter_get(struct devlink *devlink,
349a80cf955SOleksandr Mazur const struct devlink_trap *trap,
350a80cf955SOleksandr Mazur u64 *p_drops);
351a80cf955SOleksandr Mazur
prestera_dl_info_get(struct devlink * dl,struct devlink_info_req * req,struct netlink_ext_ack * extack)35234dd1710SVadym Kochan static int prestera_dl_info_get(struct devlink *dl,
35334dd1710SVadym Kochan struct devlink_info_req *req,
35434dd1710SVadym Kochan struct netlink_ext_ack *extack)
35534dd1710SVadym Kochan {
35634dd1710SVadym Kochan struct prestera_switch *sw = devlink_priv(dl);
35734dd1710SVadym Kochan char buf[16];
35834dd1710SVadym Kochan
35934dd1710SVadym Kochan snprintf(buf, sizeof(buf), "%d.%d.%d",
36034dd1710SVadym Kochan sw->dev->fw_rev.maj,
36134dd1710SVadym Kochan sw->dev->fw_rev.min,
36234dd1710SVadym Kochan sw->dev->fw_rev.sub);
36334dd1710SVadym Kochan
36434dd1710SVadym Kochan return devlink_info_version_running_put(req,
36534dd1710SVadym Kochan DEVLINK_INFO_VERSION_GENERIC_FW,
36634dd1710SVadym Kochan buf);
36734dd1710SVadym Kochan }
36834dd1710SVadym Kochan
3690a9003f4SOleksandr Mazur static int prestera_trap_init(struct devlink *devlink,
3700a9003f4SOleksandr Mazur const struct devlink_trap *trap, void *trap_ctx);
3710a9003f4SOleksandr Mazur
3720a9003f4SOleksandr Mazur static int prestera_trap_action_set(struct devlink *devlink,
3730a9003f4SOleksandr Mazur const struct devlink_trap *trap,
3740a9003f4SOleksandr Mazur enum devlink_trap_action action,
3750a9003f4SOleksandr Mazur struct netlink_ext_ack *extack);
3760a9003f4SOleksandr Mazur
37734dd1710SVadym Kochan static const struct devlink_ops prestera_dl_ops = {
37834dd1710SVadym Kochan .info_get = prestera_dl_info_get,
3790a9003f4SOleksandr Mazur .trap_init = prestera_trap_init,
3800a9003f4SOleksandr Mazur .trap_action_set = prestera_trap_action_set,
381a80cf955SOleksandr Mazur .trap_drop_counter_get = prestera_drop_counter_get,
38234dd1710SVadym Kochan };
38334dd1710SVadym Kochan
prestera_devlink_alloc(struct prestera_device * dev)384919d13a7SLeon Romanovsky struct prestera_switch *prestera_devlink_alloc(struct prestera_device *dev)
38534dd1710SVadym Kochan {
38634dd1710SVadym Kochan struct devlink *dl;
38734dd1710SVadym Kochan
388919d13a7SLeon Romanovsky dl = devlink_alloc(&prestera_dl_ops, sizeof(struct prestera_switch),
389919d13a7SLeon Romanovsky dev->dev);
39034dd1710SVadym Kochan
39134dd1710SVadym Kochan return devlink_priv(dl);
39234dd1710SVadym Kochan }
39334dd1710SVadym Kochan
prestera_devlink_free(struct prestera_switch * sw)39434dd1710SVadym Kochan void prestera_devlink_free(struct prestera_switch *sw)
39534dd1710SVadym Kochan {
39634dd1710SVadym Kochan struct devlink *dl = priv_to_devlink(sw);
39734dd1710SVadym Kochan
39834dd1710SVadym Kochan devlink_free(dl);
39934dd1710SVadym Kochan }
40034dd1710SVadym Kochan
prestera_devlink_register(struct prestera_switch * sw)401*4beb0c24SLeon Romanovsky void prestera_devlink_register(struct prestera_switch *sw)
40234dd1710SVadym Kochan {
40334dd1710SVadym Kochan struct devlink *dl = priv_to_devlink(sw);
40434dd1710SVadym Kochan
405db4278c5SLeon Romanovsky devlink_register(dl);
4060a9003f4SOleksandr Mazur }
4070a9003f4SOleksandr Mazur
prestera_devlink_unregister(struct prestera_switch * sw)40834dd1710SVadym Kochan void prestera_devlink_unregister(struct prestera_switch *sw)
40934dd1710SVadym Kochan {
41034dd1710SVadym Kochan struct devlink *dl = priv_to_devlink(sw);
41134dd1710SVadym Kochan
41234dd1710SVadym Kochan devlink_unregister(dl);
41334dd1710SVadym Kochan }
41434dd1710SVadym Kochan
prestera_devlink_port_register(struct prestera_port * port)41534dd1710SVadym Kochan int prestera_devlink_port_register(struct prestera_port *port)
41634dd1710SVadym Kochan {
41734dd1710SVadym Kochan struct prestera_switch *sw = port->sw;
41834dd1710SVadym Kochan struct devlink *dl = priv_to_devlink(sw);
41934dd1710SVadym Kochan struct devlink_port_attrs attrs = {};
42034dd1710SVadym Kochan int err;
42134dd1710SVadym Kochan
42234dd1710SVadym Kochan attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
42334dd1710SVadym Kochan attrs.phys.port_number = port->fp_id;
42434dd1710SVadym Kochan attrs.switch_id.id_len = sizeof(sw->id);
42534dd1710SVadym Kochan memcpy(attrs.switch_id.id, &sw->id, attrs.switch_id.id_len);
42634dd1710SVadym Kochan
42734dd1710SVadym Kochan devlink_port_attrs_set(&port->dl_port, &attrs);
42834dd1710SVadym Kochan
42934dd1710SVadym Kochan err = devlink_port_register(dl, &port->dl_port, port->fp_id);
43034dd1710SVadym Kochan if (err) {
43134dd1710SVadym Kochan dev_err(prestera_dev(sw), "devlink_port_register failed: %d\n", err);
43234dd1710SVadym Kochan return err;
43334dd1710SVadym Kochan }
43434dd1710SVadym Kochan
43534dd1710SVadym Kochan return 0;
43634dd1710SVadym Kochan }
43734dd1710SVadym Kochan
prestera_devlink_port_unregister(struct prestera_port * port)43834dd1710SVadym Kochan void prestera_devlink_port_unregister(struct prestera_port *port)
43934dd1710SVadym Kochan {
44034dd1710SVadym Kochan devlink_port_unregister(&port->dl_port);
44134dd1710SVadym Kochan }
44234dd1710SVadym Kochan
prestera_devlink_traps_register(struct prestera_switch * sw)443*4beb0c24SLeon Romanovsky int prestera_devlink_traps_register(struct prestera_switch *sw)
4440a9003f4SOleksandr Mazur {
4450a9003f4SOleksandr Mazur const u32 groups_count = ARRAY_SIZE(prestera_trap_groups_arr);
4460a9003f4SOleksandr Mazur const u32 traps_count = ARRAY_SIZE(prestera_trap_items_arr);
4470a9003f4SOleksandr Mazur struct devlink *devlink = priv_to_devlink(sw);
4480a9003f4SOleksandr Mazur struct prestera_trap_data *trap_data;
4490a9003f4SOleksandr Mazur struct prestera_trap *prestera_trap;
4500a9003f4SOleksandr Mazur int err, i;
4510a9003f4SOleksandr Mazur
4520a9003f4SOleksandr Mazur trap_data = kzalloc(sizeof(*trap_data), GFP_KERNEL);
4530a9003f4SOleksandr Mazur if (!trap_data)
4540a9003f4SOleksandr Mazur return -ENOMEM;
4550a9003f4SOleksandr Mazur
4560a9003f4SOleksandr Mazur trap_data->trap_items_arr = kcalloc(traps_count,
4570a9003f4SOleksandr Mazur sizeof(struct prestera_trap_item),
4580a9003f4SOleksandr Mazur GFP_KERNEL);
4590a9003f4SOleksandr Mazur if (!trap_data->trap_items_arr) {
4600a9003f4SOleksandr Mazur err = -ENOMEM;
4610a9003f4SOleksandr Mazur goto err_trap_items_alloc;
4620a9003f4SOleksandr Mazur }
4630a9003f4SOleksandr Mazur
4640a9003f4SOleksandr Mazur trap_data->sw = sw;
4650a9003f4SOleksandr Mazur trap_data->traps_count = traps_count;
4660a9003f4SOleksandr Mazur sw->trap_data = trap_data;
4670a9003f4SOleksandr Mazur
4680a9003f4SOleksandr Mazur err = devlink_trap_groups_register(devlink, prestera_trap_groups_arr,
4690a9003f4SOleksandr Mazur groups_count);
4700a9003f4SOleksandr Mazur if (err)
4710a9003f4SOleksandr Mazur goto err_groups_register;
4720a9003f4SOleksandr Mazur
4730a9003f4SOleksandr Mazur for (i = 0; i < traps_count; i++) {
4740a9003f4SOleksandr Mazur prestera_trap = &prestera_trap_items_arr[i];
4750a9003f4SOleksandr Mazur err = devlink_traps_register(devlink, &prestera_trap->trap, 1,
4760a9003f4SOleksandr Mazur sw);
4770a9003f4SOleksandr Mazur if (err)
4780a9003f4SOleksandr Mazur goto err_trap_register;
4790a9003f4SOleksandr Mazur }
4800a9003f4SOleksandr Mazur
4810a9003f4SOleksandr Mazur return 0;
4820a9003f4SOleksandr Mazur
4830a9003f4SOleksandr Mazur err_trap_register:
4840a9003f4SOleksandr Mazur for (i--; i >= 0; i--) {
4850a9003f4SOleksandr Mazur prestera_trap = &prestera_trap_items_arr[i];
4860a9003f4SOleksandr Mazur devlink_traps_unregister(devlink, &prestera_trap->trap, 1);
4870a9003f4SOleksandr Mazur }
48813a9c4acSLeon Romanovsky devlink_trap_groups_unregister(devlink, prestera_trap_groups_arr,
48913a9c4acSLeon Romanovsky groups_count);
4900a9003f4SOleksandr Mazur err_groups_register:
4910a9003f4SOleksandr Mazur kfree(trap_data->trap_items_arr);
4920a9003f4SOleksandr Mazur err_trap_items_alloc:
4930a9003f4SOleksandr Mazur kfree(trap_data);
4940a9003f4SOleksandr Mazur return err;
4950a9003f4SOleksandr Mazur }
4960a9003f4SOleksandr Mazur
4970a9003f4SOleksandr Mazur static struct prestera_trap_item *
prestera_get_trap_item_by_cpu_code(struct prestera_switch * sw,u8 cpu_code)4980a9003f4SOleksandr Mazur prestera_get_trap_item_by_cpu_code(struct prestera_switch *sw, u8 cpu_code)
4990a9003f4SOleksandr Mazur {
5000a9003f4SOleksandr Mazur struct prestera_trap_data *trap_data = sw->trap_data;
5010a9003f4SOleksandr Mazur struct prestera_trap *prestera_trap;
5020a9003f4SOleksandr Mazur int i;
5030a9003f4SOleksandr Mazur
5040a9003f4SOleksandr Mazur for (i = 0; i < trap_data->traps_count; i++) {
5050a9003f4SOleksandr Mazur prestera_trap = &prestera_trap_items_arr[i];
5060a9003f4SOleksandr Mazur if (cpu_code == prestera_trap->cpu_code)
5070a9003f4SOleksandr Mazur return &trap_data->trap_items_arr[i];
5080a9003f4SOleksandr Mazur }
5090a9003f4SOleksandr Mazur
5100a9003f4SOleksandr Mazur return NULL;
5110a9003f4SOleksandr Mazur }
5120a9003f4SOleksandr Mazur
prestera_devlink_trap_report(struct prestera_port * port,struct sk_buff * skb,u8 cpu_code)5130a9003f4SOleksandr Mazur void prestera_devlink_trap_report(struct prestera_port *port,
5140a9003f4SOleksandr Mazur struct sk_buff *skb, u8 cpu_code)
5150a9003f4SOleksandr Mazur {
5160a9003f4SOleksandr Mazur struct prestera_trap_item *trap_item;
5170a9003f4SOleksandr Mazur struct devlink *devlink;
5180a9003f4SOleksandr Mazur
5190a9003f4SOleksandr Mazur devlink = port->dl_port.devlink;
5200a9003f4SOleksandr Mazur
5210a9003f4SOleksandr Mazur trap_item = prestera_get_trap_item_by_cpu_code(port->sw, cpu_code);
5220a9003f4SOleksandr Mazur if (unlikely(!trap_item))
5230a9003f4SOleksandr Mazur return;
5240a9003f4SOleksandr Mazur
5250a9003f4SOleksandr Mazur devlink_trap_report(devlink, skb, trap_item->trap_ctx,
5260a9003f4SOleksandr Mazur &port->dl_port, NULL);
5270a9003f4SOleksandr Mazur }
5280a9003f4SOleksandr Mazur
5290a9003f4SOleksandr Mazur static struct prestera_trap_item *
prestera_devlink_trap_item_lookup(struct prestera_switch * sw,u16 trap_id)5300a9003f4SOleksandr Mazur prestera_devlink_trap_item_lookup(struct prestera_switch *sw, u16 trap_id)
5310a9003f4SOleksandr Mazur {
5320a9003f4SOleksandr Mazur struct prestera_trap_data *trap_data = sw->trap_data;
5330a9003f4SOleksandr Mazur int i;
5340a9003f4SOleksandr Mazur
5350a9003f4SOleksandr Mazur for (i = 0; i < ARRAY_SIZE(prestera_trap_items_arr); i++) {
5360a9003f4SOleksandr Mazur if (prestera_trap_items_arr[i].trap.id == trap_id)
5370a9003f4SOleksandr Mazur return &trap_data->trap_items_arr[i];
5380a9003f4SOleksandr Mazur }
5390a9003f4SOleksandr Mazur
5400a9003f4SOleksandr Mazur return NULL;
5410a9003f4SOleksandr Mazur }
5420a9003f4SOleksandr Mazur
prestera_trap_init(struct devlink * devlink,const struct devlink_trap * trap,void * trap_ctx)5430a9003f4SOleksandr Mazur static int prestera_trap_init(struct devlink *devlink,
5440a9003f4SOleksandr Mazur const struct devlink_trap *trap, void *trap_ctx)
5450a9003f4SOleksandr Mazur {
5460a9003f4SOleksandr Mazur struct prestera_switch *sw = devlink_priv(devlink);
5470a9003f4SOleksandr Mazur struct prestera_trap_item *trap_item;
5480a9003f4SOleksandr Mazur
5490a9003f4SOleksandr Mazur trap_item = prestera_devlink_trap_item_lookup(sw, trap->id);
5500a9003f4SOleksandr Mazur if (WARN_ON(!trap_item))
5510a9003f4SOleksandr Mazur return -EINVAL;
5520a9003f4SOleksandr Mazur
5530a9003f4SOleksandr Mazur trap_item->trap_ctx = trap_ctx;
5540a9003f4SOleksandr Mazur trap_item->action = trap->init_action;
5550a9003f4SOleksandr Mazur
5560a9003f4SOleksandr Mazur return 0;
5570a9003f4SOleksandr Mazur }
5580a9003f4SOleksandr Mazur
prestera_trap_action_set(struct devlink * devlink,const struct devlink_trap * trap,enum devlink_trap_action action,struct netlink_ext_ack * extack)5590a9003f4SOleksandr Mazur static int prestera_trap_action_set(struct devlink *devlink,
5600a9003f4SOleksandr Mazur const struct devlink_trap *trap,
5610a9003f4SOleksandr Mazur enum devlink_trap_action action,
5620a9003f4SOleksandr Mazur struct netlink_ext_ack *extack)
5630a9003f4SOleksandr Mazur {
5640a9003f4SOleksandr Mazur /* Currently, driver does not support trap action altering */
5650a9003f4SOleksandr Mazur return -EOPNOTSUPP;
5660a9003f4SOleksandr Mazur }
5670a9003f4SOleksandr Mazur
prestera_drop_counter_get(struct devlink * devlink,const struct devlink_trap * trap,u64 * p_drops)568a80cf955SOleksandr Mazur static int prestera_drop_counter_get(struct devlink *devlink,
569a80cf955SOleksandr Mazur const struct devlink_trap *trap,
570a80cf955SOleksandr Mazur u64 *p_drops)
571a80cf955SOleksandr Mazur {
572a80cf955SOleksandr Mazur struct prestera_switch *sw = devlink_priv(devlink);
573a80cf955SOleksandr Mazur enum prestera_hw_cpu_code_cnt_t cpu_code_type =
574a80cf955SOleksandr Mazur PRESTERA_HW_CPU_CODE_CNT_TYPE_DROP;
575a80cf955SOleksandr Mazur struct prestera_trap *prestera_trap =
576a80cf955SOleksandr Mazur container_of(trap, struct prestera_trap, trap);
577a80cf955SOleksandr Mazur
578a80cf955SOleksandr Mazur return prestera_hw_cpu_code_counters_get(sw, prestera_trap->cpu_code,
579a80cf955SOleksandr Mazur cpu_code_type, p_drops);
580a80cf955SOleksandr Mazur }
581a80cf955SOleksandr Mazur
prestera_devlink_traps_unregister(struct prestera_switch * sw)582*4beb0c24SLeon Romanovsky void prestera_devlink_traps_unregister(struct prestera_switch *sw)
5830a9003f4SOleksandr Mazur {
584*4beb0c24SLeon Romanovsky struct prestera_trap_data *trap_data = sw->trap_data;
5850a9003f4SOleksandr Mazur struct devlink *dl = priv_to_devlink(sw);
5860a9003f4SOleksandr Mazur const struct devlink_trap *trap;
5870a9003f4SOleksandr Mazur int i;
5880a9003f4SOleksandr Mazur
5890a9003f4SOleksandr Mazur for (i = 0; i < ARRAY_SIZE(prestera_trap_items_arr); ++i) {
5900a9003f4SOleksandr Mazur trap = &prestera_trap_items_arr[i].trap;
5910a9003f4SOleksandr Mazur devlink_traps_unregister(dl, trap, 1);
5920a9003f4SOleksandr Mazur }
5930a9003f4SOleksandr Mazur
5940a9003f4SOleksandr Mazur devlink_trap_groups_unregister(dl, prestera_trap_groups_arr,
5950a9003f4SOleksandr Mazur ARRAY_SIZE(prestera_trap_groups_arr));
596*4beb0c24SLeon Romanovsky kfree(trap_data->trap_items_arr);
597*4beb0c24SLeon Romanovsky kfree(trap_data);
5980a9003f4SOleksandr Mazur }
599