xref: /openbmc/linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1b5ce611fSIdo Schimmel // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2b5ce611fSIdo Schimmel /* Copyright (c) 2019 Mellanox Technologies. All rights reserved */
3b5ce611fSIdo Schimmel 
44561705bSIdo Schimmel #include <linux/bitops.h>
5b5ce611fSIdo Schimmel #include <linux/kernel.h>
613f2e64bSIdo Schimmel #include <linux/netlink.h>
7b5ce611fSIdo Schimmel #include <net/devlink.h>
8b5ce611fSIdo Schimmel #include <uapi/linux/devlink.h>
9b5ce611fSIdo Schimmel 
10b5ce611fSIdo Schimmel #include "core.h"
11b5ce611fSIdo Schimmel #include "reg.h"
12b5ce611fSIdo Schimmel #include "spectrum.h"
1303484e49SIdo Schimmel #include "spectrum_trap.h"
14b5ce611fSIdo Schimmel 
1585d4ec59SIdo Schimmel struct mlxsw_sp_trap_policer_item {
16cc678f4dSIdo Schimmel 	struct devlink_trap_policer policer;
1785d4ec59SIdo Schimmel 	u16 hw_id;
1885d4ec59SIdo Schimmel };
1985d4ec59SIdo Schimmel 
20b14a40dbSIdo Schimmel struct mlxsw_sp_trap_group_item {
21b14a40dbSIdo Schimmel 	struct devlink_trap_group group;
22b14a40dbSIdo Schimmel 	u16 hw_group_id;
23b14a40dbSIdo Schimmel 	u8 priority;
246687e953SIdo Schimmel 	u8 fixed_policer:1; /* Whether policer binding can change */
25b14a40dbSIdo Schimmel };
26b14a40dbSIdo Schimmel 
27200b7ccaSIdo Schimmel #define MLXSW_SP_TRAP_LISTENERS_MAX 3
28200b7ccaSIdo Schimmel 
29200b7ccaSIdo Schimmel struct mlxsw_sp_trap_item {
30200b7ccaSIdo Schimmel 	struct devlink_trap trap;
31200b7ccaSIdo Schimmel 	struct mlxsw_listener listeners_arr[MLXSW_SP_TRAP_LISTENERS_MAX];
326687e953SIdo Schimmel 	u8 is_source:1;
33200b7ccaSIdo Schimmel };
34200b7ccaSIdo Schimmel 
355b051621SAmit Cohen /* All driver-specific traps must be documented in
365b051621SAmit Cohen  * Documentation/networking/devlink/mlxsw.rst
375b051621SAmit Cohen  */
385b051621SAmit Cohen enum {
395b051621SAmit Cohen 	DEVLINK_MLXSW_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX,
405b051621SAmit Cohen 	DEVLINK_MLXSW_TRAP_ID_IRIF_DISABLED,
415b051621SAmit Cohen 	DEVLINK_MLXSW_TRAP_ID_ERIF_DISABLED,
425b051621SAmit Cohen };
435b051621SAmit Cohen 
445b051621SAmit Cohen #define DEVLINK_MLXSW_TRAP_NAME_IRIF_DISABLED \
455b051621SAmit Cohen 	"irif_disabled"
465b051621SAmit Cohen #define DEVLINK_MLXSW_TRAP_NAME_ERIF_DISABLED \
475b051621SAmit Cohen 	"erif_disabled"
485b051621SAmit Cohen 
49b5ce611fSIdo Schimmel #define MLXSW_SP_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
50b5ce611fSIdo Schimmel 
516687e953SIdo Schimmel enum {
52cf31190aSIdo Schimmel 	/* Packet was mirrored from ingress. */
53cf31190aSIdo Schimmel 	MLXSW_SP_MIRROR_REASON_INGRESS = 1,
5445aad0b7SIdo Schimmel 	/* Packet was mirrored from policy engine. */
5545aad0b7SIdo Schimmel 	MLXSW_SP_MIRROR_REASON_POLICY_ENGINE = 2,
566687e953SIdo Schimmel 	/* Packet was early dropped. */
576687e953SIdo Schimmel 	MLXSW_SP_MIRROR_REASON_INGRESS_WRED = 9,
5854d0e963SIdo Schimmel 	/* Packet was mirrored from egress. */
5954d0e963SIdo Schimmel 	MLXSW_SP_MIRROR_REASON_EGRESS = 14,
606687e953SIdo Schimmel };
616687e953SIdo Schimmel 
mlxsw_sp_rx_listener(struct mlxsw_sp * mlxsw_sp,struct sk_buff * skb,u16 local_port,struct mlxsw_sp_port * mlxsw_sp_port)62a5118ef1SJiri Pirko static int mlxsw_sp_rx_listener(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
63c934757dSAmit Cohen 				u16 local_port,
64a5118ef1SJiri Pirko 				struct mlxsw_sp_port *mlxsw_sp_port)
65a5118ef1SJiri Pirko {
66a5118ef1SJiri Pirko 	struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
67a5118ef1SJiri Pirko 
68a5118ef1SJiri Pirko 	if (unlikely(!mlxsw_sp_port)) {
69a5118ef1SJiri Pirko 		dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: skb received for non-existent port\n",
70a5118ef1SJiri Pirko 				     local_port);
71a5118ef1SJiri Pirko 		kfree_skb(skb);
72a5118ef1SJiri Pirko 		return -EINVAL;
73a5118ef1SJiri Pirko 	}
74a5118ef1SJiri Pirko 
75a5118ef1SJiri Pirko 	skb->dev = mlxsw_sp_port->dev;
76a5118ef1SJiri Pirko 
77a5118ef1SJiri Pirko 	pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
78a5118ef1SJiri Pirko 	u64_stats_update_begin(&pcpu_stats->syncp);
79a5118ef1SJiri Pirko 	pcpu_stats->rx_packets++;
80a5118ef1SJiri Pirko 	pcpu_stats->rx_bytes += skb->len;
81a5118ef1SJiri Pirko 	u64_stats_update_end(&pcpu_stats->syncp);
82a5118ef1SJiri Pirko 
83a5118ef1SJiri Pirko 	skb->protocol = eth_type_trans(skb, skb->dev);
84a5118ef1SJiri Pirko 
85a5118ef1SJiri Pirko 	return 0;
86a5118ef1SJiri Pirko }
87a5118ef1SJiri Pirko 
mlxsw_sp_rx_drop_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)88c934757dSAmit Cohen static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u16 local_port,
89a5118ef1SJiri Pirko 				      void *trap_ctx)
90a5118ef1SJiri Pirko {
91a5118ef1SJiri Pirko 	struct devlink_port *in_devlink_port;
92a5118ef1SJiri Pirko 	struct mlxsw_sp_port *mlxsw_sp_port;
93a5118ef1SJiri Pirko 	struct mlxsw_sp *mlxsw_sp;
94a5118ef1SJiri Pirko 	struct devlink *devlink;
95a5118ef1SJiri Pirko 	int err;
96a5118ef1SJiri Pirko 
97a5118ef1SJiri Pirko 	mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
98a5118ef1SJiri Pirko 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
99a5118ef1SJiri Pirko 
100a5118ef1SJiri Pirko 	err = mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port);
101a5118ef1SJiri Pirko 	if (err)
102a5118ef1SJiri Pirko 		return;
103a5118ef1SJiri Pirko 
104a5118ef1SJiri Pirko 	devlink = priv_to_devlink(mlxsw_sp->core);
105a5118ef1SJiri Pirko 	in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
106a5118ef1SJiri Pirko 							   local_port);
107a5118ef1SJiri Pirko 	skb_push(skb, ETH_HLEN);
1085a2e106cSJiri Pirko 	devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port, NULL);
109a5118ef1SJiri Pirko 	consume_skb(skb);
110a5118ef1SJiri Pirko }
111a5118ef1SJiri Pirko 
mlxsw_sp_rx_acl_drop_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)112c934757dSAmit Cohen static void mlxsw_sp_rx_acl_drop_listener(struct sk_buff *skb, u16 local_port,
1136de9fceeSJiri Pirko 					  void *trap_ctx)
1146de9fceeSJiri Pirko {
115d4cabaadSIdo Schimmel 	u32 cookie_index = mlxsw_skb_cb(skb)->rx_md_info.cookie_index;
1166de9fceeSJiri Pirko 	const struct flow_action_cookie *fa_cookie;
1176de9fceeSJiri Pirko 	struct devlink_port *in_devlink_port;
1186de9fceeSJiri Pirko 	struct mlxsw_sp_port *mlxsw_sp_port;
1196de9fceeSJiri Pirko 	struct mlxsw_sp *mlxsw_sp;
1206de9fceeSJiri Pirko 	struct devlink *devlink;
1216de9fceeSJiri Pirko 	int err;
1226de9fceeSJiri Pirko 
1236de9fceeSJiri Pirko 	mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
1246de9fceeSJiri Pirko 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
1256de9fceeSJiri Pirko 
1266de9fceeSJiri Pirko 	err = mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port);
1276de9fceeSJiri Pirko 	if (err)
1286de9fceeSJiri Pirko 		return;
1296de9fceeSJiri Pirko 
1306de9fceeSJiri Pirko 	devlink = priv_to_devlink(mlxsw_sp->core);
1316de9fceeSJiri Pirko 	in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
1326de9fceeSJiri Pirko 							   local_port);
1336de9fceeSJiri Pirko 	skb_push(skb, ETH_HLEN);
1346de9fceeSJiri Pirko 	rcu_read_lock();
1356de9fceeSJiri Pirko 	fa_cookie = mlxsw_sp_acl_act_cookie_lookup(mlxsw_sp, cookie_index);
1366de9fceeSJiri Pirko 	devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port, fa_cookie);
1376de9fceeSJiri Pirko 	rcu_read_unlock();
1386de9fceeSJiri Pirko 	consume_skb(skb);
1396de9fceeSJiri Pirko }
1406de9fceeSJiri Pirko 
__mlxsw_sp_rx_no_mark_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)141c934757dSAmit Cohen static int __mlxsw_sp_rx_no_mark_listener(struct sk_buff *skb, u16 local_port,
142a5118ef1SJiri Pirko 					  void *trap_ctx)
143a5118ef1SJiri Pirko {
144a5118ef1SJiri Pirko 	struct devlink_port *in_devlink_port;
145a5118ef1SJiri Pirko 	struct mlxsw_sp_port *mlxsw_sp_port;
146a5118ef1SJiri Pirko 	struct mlxsw_sp *mlxsw_sp;
147a5118ef1SJiri Pirko 	struct devlink *devlink;
148a5118ef1SJiri Pirko 	int err;
149a5118ef1SJiri Pirko 
150a5118ef1SJiri Pirko 	mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
151a5118ef1SJiri Pirko 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
152a5118ef1SJiri Pirko 
153a5118ef1SJiri Pirko 	err = mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port);
154a5118ef1SJiri Pirko 	if (err)
15545b1c873SIdo Schimmel 		return err;
156a5118ef1SJiri Pirko 
157a5118ef1SJiri Pirko 	devlink = priv_to_devlink(mlxsw_sp->core);
158a5118ef1SJiri Pirko 	in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
159a5118ef1SJiri Pirko 							   local_port);
160a5118ef1SJiri Pirko 	skb_push(skb, ETH_HLEN);
1615a2e106cSJiri Pirko 	devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port, NULL);
162a5118ef1SJiri Pirko 	skb_pull(skb, ETH_HLEN);
16345b1c873SIdo Schimmel 
16445b1c873SIdo Schimmel 	return 0;
16545b1c873SIdo Schimmel }
16645b1c873SIdo Schimmel 
mlxsw_sp_rx_no_mark_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)167c934757dSAmit Cohen static void mlxsw_sp_rx_no_mark_listener(struct sk_buff *skb, u16 local_port,
16845b1c873SIdo Schimmel 					 void *trap_ctx)
16945b1c873SIdo Schimmel {
17045b1c873SIdo Schimmel 	int err;
17145b1c873SIdo Schimmel 
17245b1c873SIdo Schimmel 	err = __mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
17345b1c873SIdo Schimmel 	if (err)
17445b1c873SIdo Schimmel 		return;
17545b1c873SIdo Schimmel 
176a5118ef1SJiri Pirko 	netif_receive_skb(skb);
177a5118ef1SJiri Pirko }
178b5ce611fSIdo Schimmel 
mlxsw_sp_rx_mark_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)179c934757dSAmit Cohen static void mlxsw_sp_rx_mark_listener(struct sk_buff *skb, u16 local_port,
18045b1c873SIdo Schimmel 				      void *trap_ctx)
18145b1c873SIdo Schimmel {
18245b1c873SIdo Schimmel 	skb->offload_fwd_mark = 1;
18345b1c873SIdo Schimmel 	mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
18445b1c873SIdo Schimmel }
18545b1c873SIdo Schimmel 
mlxsw_sp_rx_l3_mark_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)186c934757dSAmit Cohen static void mlxsw_sp_rx_l3_mark_listener(struct sk_buff *skb, u16 local_port,
1878110668eSIdo Schimmel 					 void *trap_ctx)
1888110668eSIdo Schimmel {
1898110668eSIdo Schimmel 	skb->offload_l3_fwd_mark = 1;
1908110668eSIdo Schimmel 	skb->offload_fwd_mark = 1;
1918110668eSIdo Schimmel 	mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
1928110668eSIdo Schimmel }
1938110668eSIdo Schimmel 
mlxsw_sp_rx_ptp_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)194c934757dSAmit Cohen static void mlxsw_sp_rx_ptp_listener(struct sk_buff *skb, u16 local_port,
19539c10350SIdo Schimmel 				     void *trap_ctx)
19639c10350SIdo Schimmel {
19739c10350SIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
19839c10350SIdo Schimmel 	int err;
19939c10350SIdo Schimmel 
20039c10350SIdo Schimmel 	err = __mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
20139c10350SIdo Schimmel 	if (err)
20239c10350SIdo Schimmel 		return;
20339c10350SIdo Schimmel 
20439c10350SIdo Schimmel 	/* The PTP handler expects skb->data to point to the start of the
20539c10350SIdo Schimmel 	 * Ethernet header.
20639c10350SIdo Schimmel 	 */
20739c10350SIdo Schimmel 	skb_push(skb, ETH_HLEN);
20839c10350SIdo Schimmel 	mlxsw_sp_ptp_receive(mlxsw_sp, skb, local_port);
20939c10350SIdo Schimmel }
21039c10350SIdo Schimmel 
2112073c600SIdo Schimmel static struct mlxsw_sp_port *
mlxsw_sp_sample_tx_port_get(struct mlxsw_sp * mlxsw_sp,const struct mlxsw_rx_md_info * rx_md_info)2122073c600SIdo Schimmel mlxsw_sp_sample_tx_port_get(struct mlxsw_sp *mlxsw_sp,
2132073c600SIdo Schimmel 			    const struct mlxsw_rx_md_info *rx_md_info)
2142073c600SIdo Schimmel {
215c934757dSAmit Cohen 	u16 local_port;
2162073c600SIdo Schimmel 
2172073c600SIdo Schimmel 	if (!rx_md_info->tx_port_valid)
2182073c600SIdo Schimmel 		return NULL;
2192073c600SIdo Schimmel 
2202073c600SIdo Schimmel 	if (rx_md_info->tx_port_is_lag)
2212073c600SIdo Schimmel 		local_port = mlxsw_core_lag_mapping_get(mlxsw_sp->core,
2222073c600SIdo Schimmel 							rx_md_info->tx_lag_id,
2232073c600SIdo Schimmel 							rx_md_info->tx_lag_port_index);
2242073c600SIdo Schimmel 	else
2252073c600SIdo Schimmel 		local_port = rx_md_info->tx_sys_port;
2262073c600SIdo Schimmel 
2272073c600SIdo Schimmel 	if (local_port >= mlxsw_core_max_ports(mlxsw_sp->core))
2282073c600SIdo Schimmel 		return NULL;
2292073c600SIdo Schimmel 
2302073c600SIdo Schimmel 	return mlxsw_sp->ports[local_port];
2312073c600SIdo Schimmel }
2322073c600SIdo Schimmel 
2332073c600SIdo Schimmel /* The latency units are determined according to MOGCR.mirror_latency_units. It
2342073c600SIdo Schimmel  * defaults to 64 nanoseconds.
2352073c600SIdo Schimmel  */
2362073c600SIdo Schimmel #define MLXSW_SP_MIRROR_LATENCY_SHIFT	6
2372073c600SIdo Schimmel 
mlxsw_sp_psample_md_init(struct mlxsw_sp * mlxsw_sp,struct psample_metadata * md,struct sk_buff * skb,int in_ifindex,bool truncate,u32 trunc_size)2382073c600SIdo Schimmel static void mlxsw_sp_psample_md_init(struct mlxsw_sp *mlxsw_sp,
2392073c600SIdo Schimmel 				     struct psample_metadata *md,
2402073c600SIdo Schimmel 				     struct sk_buff *skb, int in_ifindex,
2412073c600SIdo Schimmel 				     bool truncate, u32 trunc_size)
2422073c600SIdo Schimmel {
2432073c600SIdo Schimmel 	struct mlxsw_rx_md_info *rx_md_info = &mlxsw_skb_cb(skb)->rx_md_info;
2442073c600SIdo Schimmel 	struct mlxsw_sp_port *mlxsw_sp_port;
2452073c600SIdo Schimmel 
2462073c600SIdo Schimmel 	md->trunc_size = truncate ? trunc_size : skb->len;
2472073c600SIdo Schimmel 	md->in_ifindex = in_ifindex;
2482073c600SIdo Schimmel 	mlxsw_sp_port = mlxsw_sp_sample_tx_port_get(mlxsw_sp, rx_md_info);
2492073c600SIdo Schimmel 	md->out_ifindex = mlxsw_sp_port && mlxsw_sp_port->dev ?
2502073c600SIdo Schimmel 			  mlxsw_sp_port->dev->ifindex : 0;
2512073c600SIdo Schimmel 	md->out_tc_valid = rx_md_info->tx_tc_valid;
2522073c600SIdo Schimmel 	md->out_tc = rx_md_info->tx_tc;
2532073c600SIdo Schimmel 	md->out_tc_occ_valid = rx_md_info->tx_congestion_valid;
2542073c600SIdo Schimmel 	md->out_tc_occ = rx_md_info->tx_congestion;
2552073c600SIdo Schimmel 	md->latency_valid = rx_md_info->latency_valid;
2562073c600SIdo Schimmel 	md->latency = rx_md_info->latency;
2572073c600SIdo Schimmel 	md->latency <<= MLXSW_SP_MIRROR_LATENCY_SHIFT;
2582073c600SIdo Schimmel }
2592073c600SIdo Schimmel 
mlxsw_sp_rx_sample_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)260c934757dSAmit Cohen static void mlxsw_sp_rx_sample_listener(struct sk_buff *skb, u16 local_port,
26188e27749SIdo Schimmel 					void *trap_ctx)
26288e27749SIdo Schimmel {
26388e27749SIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
26490f53c53SIdo Schimmel 	struct mlxsw_sp_sample_trigger trigger;
26590f53c53SIdo Schimmel 	struct mlxsw_sp_sample_params *params;
26648990befSIdo Schimmel 	struct mlxsw_sp_port *mlxsw_sp_port;
26748990befSIdo Schimmel 	struct psample_metadata md = {};
26888e27749SIdo Schimmel 	int err;
26988e27749SIdo Schimmel 
27088e27749SIdo Schimmel 	err = __mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
27188e27749SIdo Schimmel 	if (err)
27288e27749SIdo Schimmel 		return;
27388e27749SIdo Schimmel 
27448990befSIdo Schimmel 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
27548990befSIdo Schimmel 	if (!mlxsw_sp_port)
27648990befSIdo Schimmel 		goto out;
27748990befSIdo Schimmel 
27890f53c53SIdo Schimmel 	trigger.type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_INGRESS;
27990f53c53SIdo Schimmel 	trigger.local_port = local_port;
28090f53c53SIdo Schimmel 	params = mlxsw_sp_sample_trigger_params_lookup(mlxsw_sp, &trigger);
28190f53c53SIdo Schimmel 	if (!params)
28248990befSIdo Schimmel 		goto out;
28348990befSIdo Schimmel 
28448990befSIdo Schimmel 	/* The psample module expects skb->data to point to the start of the
28588e27749SIdo Schimmel 	 * Ethernet header.
28688e27749SIdo Schimmel 	 */
28788e27749SIdo Schimmel 	skb_push(skb, ETH_HLEN);
2882073c600SIdo Schimmel 	mlxsw_sp_psample_md_init(mlxsw_sp, &md, skb,
28990f53c53SIdo Schimmel 				 mlxsw_sp_port->dev->ifindex, params->truncate,
29090f53c53SIdo Schimmel 				 params->trunc_size);
29190f53c53SIdo Schimmel 	psample_sample_packet(params->psample_group, skb, params->rate, &md);
29248990befSIdo Schimmel out:
29348990befSIdo Schimmel 	consume_skb(skb);
29488e27749SIdo Schimmel }
29588e27749SIdo Schimmel 
mlxsw_sp_rx_sample_tx_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)296c934757dSAmit Cohen static void mlxsw_sp_rx_sample_tx_listener(struct sk_buff *skb, u16 local_port,
29754d0e963SIdo Schimmel 					   void *trap_ctx)
29854d0e963SIdo Schimmel {
29954d0e963SIdo Schimmel 	struct mlxsw_rx_md_info *rx_md_info = &mlxsw_skb_cb(skb)->rx_md_info;
30054d0e963SIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
30154d0e963SIdo Schimmel 	struct mlxsw_sp_port *mlxsw_sp_port, *mlxsw_sp_port_tx;
30254d0e963SIdo Schimmel 	struct mlxsw_sp_sample_trigger trigger;
30354d0e963SIdo Schimmel 	struct mlxsw_sp_sample_params *params;
30454d0e963SIdo Schimmel 	struct psample_metadata md = {};
30554d0e963SIdo Schimmel 	int err;
30654d0e963SIdo Schimmel 
30754d0e963SIdo Schimmel 	/* Locally generated packets are not reported from the policy engine
30854d0e963SIdo Schimmel 	 * trigger, so do not report them from the egress trigger as well.
30954d0e963SIdo Schimmel 	 */
31054d0e963SIdo Schimmel 	if (local_port == MLXSW_PORT_CPU_PORT)
31154d0e963SIdo Schimmel 		goto out;
31254d0e963SIdo Schimmel 
31354d0e963SIdo Schimmel 	err = __mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
31454d0e963SIdo Schimmel 	if (err)
31554d0e963SIdo Schimmel 		return;
31654d0e963SIdo Schimmel 
31754d0e963SIdo Schimmel 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
31854d0e963SIdo Schimmel 	if (!mlxsw_sp_port)
31954d0e963SIdo Schimmel 		goto out;
32054d0e963SIdo Schimmel 
32154d0e963SIdo Schimmel 	/* Packet was sampled from Tx, so we need to retrieve the sample
32254d0e963SIdo Schimmel 	 * parameters based on the Tx port and not the Rx port.
32354d0e963SIdo Schimmel 	 */
32454d0e963SIdo Schimmel 	mlxsw_sp_port_tx = mlxsw_sp_sample_tx_port_get(mlxsw_sp, rx_md_info);
32554d0e963SIdo Schimmel 	if (!mlxsw_sp_port_tx)
32654d0e963SIdo Schimmel 		goto out;
32754d0e963SIdo Schimmel 
32854d0e963SIdo Schimmel 	trigger.type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_EGRESS;
32954d0e963SIdo Schimmel 	trigger.local_port = mlxsw_sp_port_tx->local_port;
33054d0e963SIdo Schimmel 	params = mlxsw_sp_sample_trigger_params_lookup(mlxsw_sp, &trigger);
33154d0e963SIdo Schimmel 	if (!params)
33254d0e963SIdo Schimmel 		goto out;
33354d0e963SIdo Schimmel 
33454d0e963SIdo Schimmel 	/* The psample module expects skb->data to point to the start of the
33554d0e963SIdo Schimmel 	 * Ethernet header.
33654d0e963SIdo Schimmel 	 */
33754d0e963SIdo Schimmel 	skb_push(skb, ETH_HLEN);
33854d0e963SIdo Schimmel 	mlxsw_sp_psample_md_init(mlxsw_sp, &md, skb,
33954d0e963SIdo Schimmel 				 mlxsw_sp_port->dev->ifindex, params->truncate,
34054d0e963SIdo Schimmel 				 params->trunc_size);
34154d0e963SIdo Schimmel 	psample_sample_packet(params->psample_group, skb, params->rate, &md);
34254d0e963SIdo Schimmel out:
34354d0e963SIdo Schimmel 	consume_skb(skb);
34454d0e963SIdo Schimmel }
34554d0e963SIdo Schimmel 
mlxsw_sp_rx_sample_acl_listener(struct sk_buff * skb,u16 local_port,void * trap_ctx)346c934757dSAmit Cohen static void mlxsw_sp_rx_sample_acl_listener(struct sk_buff *skb, u16 local_port,
34745aad0b7SIdo Schimmel 					    void *trap_ctx)
34845aad0b7SIdo Schimmel {
34945aad0b7SIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
35045aad0b7SIdo Schimmel 	struct mlxsw_sp_sample_trigger trigger = {
35145aad0b7SIdo Schimmel 		.type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_POLICY_ENGINE,
35245aad0b7SIdo Schimmel 	};
35345aad0b7SIdo Schimmel 	struct mlxsw_sp_sample_params *params;
35445aad0b7SIdo Schimmel 	struct mlxsw_sp_port *mlxsw_sp_port;
35545aad0b7SIdo Schimmel 	struct psample_metadata md = {};
35645aad0b7SIdo Schimmel 	int err;
35745aad0b7SIdo Schimmel 
35845aad0b7SIdo Schimmel 	err = __mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
35945aad0b7SIdo Schimmel 	if (err)
36045aad0b7SIdo Schimmel 		return;
36145aad0b7SIdo Schimmel 
36245aad0b7SIdo Schimmel 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
36345aad0b7SIdo Schimmel 	if (!mlxsw_sp_port)
36445aad0b7SIdo Schimmel 		goto out;
36545aad0b7SIdo Schimmel 
36645aad0b7SIdo Schimmel 	params = mlxsw_sp_sample_trigger_params_lookup(mlxsw_sp, &trigger);
36745aad0b7SIdo Schimmel 	if (!params)
36845aad0b7SIdo Schimmel 		goto out;
36945aad0b7SIdo Schimmel 
37045aad0b7SIdo Schimmel 	/* The psample module expects skb->data to point to the start of the
37145aad0b7SIdo Schimmel 	 * Ethernet header.
37245aad0b7SIdo Schimmel 	 */
37345aad0b7SIdo Schimmel 	skb_push(skb, ETH_HLEN);
37445aad0b7SIdo Schimmel 	mlxsw_sp_psample_md_init(mlxsw_sp, &md, skb,
37545aad0b7SIdo Schimmel 				 mlxsw_sp_port->dev->ifindex, params->truncate,
37645aad0b7SIdo Schimmel 				 params->trunc_size);
37745aad0b7SIdo Schimmel 	psample_sample_packet(params->psample_group, skb, params->rate, &md);
37845aad0b7SIdo Schimmel out:
37945aad0b7SIdo Schimmel 	consume_skb(skb);
38045aad0b7SIdo Schimmel }
38145aad0b7SIdo Schimmel 
382b5ce611fSIdo Schimmel #define MLXSW_SP_TRAP_DROP(_id, _group_id)				      \
383b5ce611fSIdo Schimmel 	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				      \
384107f1678SIdo Schimmel 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
385b5ce611fSIdo Schimmel 			     MLXSW_SP_TRAP_METADATA)
386b5ce611fSIdo Schimmel 
3876de9fceeSJiri Pirko #define MLXSW_SP_TRAP_DROP_EXT(_id, _group_id, _metadata)		      \
3886de9fceeSJiri Pirko 	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				      \
389107f1678SIdo Schimmel 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
3906de9fceeSJiri Pirko 			     MLXSW_SP_TRAP_METADATA | (_metadata))
3916de9fceeSJiri Pirko 
3926687e953SIdo Schimmel #define MLXSW_SP_TRAP_BUFFER_DROP(_id)					      \
3936687e953SIdo Schimmel 	DEVLINK_TRAP_GENERIC(DROP, TRAP, _id,				      \
3946687e953SIdo Schimmel 			     DEVLINK_TRAP_GROUP_GENERIC_ID_BUFFER_DROPS,      \
3956687e953SIdo Schimmel 			     MLXSW_SP_TRAP_METADATA)
3966687e953SIdo Schimmel 
3975b051621SAmit Cohen #define MLXSW_SP_TRAP_DRIVER_DROP(_id, _group_id)			      \
3985b051621SAmit Cohen 	DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_MLXSW_TRAP_ID_##_id,	      \
3995b051621SAmit Cohen 			    DEVLINK_MLXSW_TRAP_NAME_##_id,		      \
400107f1678SIdo Schimmel 			    DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
4015b051621SAmit Cohen 			    MLXSW_SP_TRAP_METADATA)
4025b051621SAmit Cohen 
403fd74feebSAmit Cohen #define MLXSW_SP_TRAP_EXCEPTION(_id, _group_id)		      \
404fd74feebSAmit Cohen 	DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id,			      \
405107f1678SIdo Schimmel 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
406fd74feebSAmit Cohen 			     MLXSW_SP_TRAP_METADATA)
407fd74feebSAmit Cohen 
40839c10350SIdo Schimmel #define MLXSW_SP_TRAP_CONTROL(_id, _group_id, _action)			      \
40939c10350SIdo Schimmel 	DEVLINK_TRAP_GENERIC(CONTROL, _action, _id,			      \
41039c10350SIdo Schimmel 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
41139c10350SIdo Schimmel 			     MLXSW_SP_TRAP_METADATA)
41239c10350SIdo Schimmel 
413b5ce611fSIdo Schimmel #define MLXSW_SP_RXL_DISCARD(_id, _group_id)				      \
41476d4067fSJiri Pirko 	MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, DISCARD_##_id,		      \
41576d4067fSJiri Pirko 		      TRAP_EXCEPTION_TO_CPU, false, SP_##_group_id,	      \
416dbd1ddadSJiri Pirko 		      SET_FW_DEFAULT, SP_##_group_id)
417b5ce611fSIdo Schimmel 
41845dbee09SJiri Pirko #define MLXSW_SP_RXL_ACL_DISCARD(_id, _en_group_id, _dis_group_id)	      \
4196de9fceeSJiri Pirko 	MLXSW_RXL_DIS(mlxsw_sp_rx_acl_drop_listener, DISCARD_##_id,	      \
42045dbee09SJiri Pirko 		      TRAP_EXCEPTION_TO_CPU, false, SP_##_en_group_id,	      \
42145dbee09SJiri Pirko 		      SET_FW_DEFAULT, SP_##_dis_group_id)
42245dbee09SJiri Pirko 
4236687e953SIdo Schimmel #define MLXSW_SP_RXL_BUFFER_DISCARD(_mirror_reason)			      \
4246687e953SIdo Schimmel 	MLXSW_RXL_MIRROR(mlxsw_sp_rx_drop_listener, 0, SP_BUFFER_DISCARDS,    \
4256687e953SIdo Schimmel 			 MLXSW_SP_MIRROR_REASON_##_mirror_reason)
4266687e953SIdo Schimmel 
427fd74feebSAmit Cohen #define MLXSW_SP_RXL_EXCEPTION(_id, _group_id, _action)			      \
42845b1c873SIdo Schimmel 	MLXSW_RXL(mlxsw_sp_rx_mark_listener, _id,			      \
4291ef658a3SJiri Pirko 		   _action, false, SP_##_group_id, SET_FW_DEFAULT)
430fd74feebSAmit Cohen 
43139c10350SIdo Schimmel #define MLXSW_SP_RXL_NO_MARK(_id, _group_id, _action, _is_ctrl)		      \
43239c10350SIdo Schimmel 	MLXSW_RXL(mlxsw_sp_rx_no_mark_listener, _id, _action,		      \
43339c10350SIdo Schimmel 		  _is_ctrl, SP_##_group_id, DISCARD)
43439c10350SIdo Schimmel 
43539c10350SIdo Schimmel #define MLXSW_SP_RXL_MARK(_id, _group_id, _action, _is_ctrl)		      \
43639c10350SIdo Schimmel 	MLXSW_RXL(mlxsw_sp_rx_mark_listener, _id, _action, _is_ctrl,	      \
43739c10350SIdo Schimmel 		  SP_##_group_id, DISCARD)
43839c10350SIdo Schimmel 
4398110668eSIdo Schimmel #define MLXSW_SP_RXL_L3_MARK(_id, _group_id, _action, _is_ctrl)		      \
4408110668eSIdo Schimmel 	MLXSW_RXL(mlxsw_sp_rx_l3_mark_listener, _id, _action, _is_ctrl,	      \
4418110668eSIdo Schimmel 		  SP_##_group_id, DISCARD)
4428110668eSIdo Schimmel 
4434561705bSIdo Schimmel #define MLXSW_SP_TRAP_POLICER(_id, _rate, _burst)			      \
4444561705bSIdo Schimmel 	DEVLINK_TRAP_POLICER(_id, _rate, _burst,			      \
4454561705bSIdo Schimmel 			     MLXSW_REG_QPCR_HIGHEST_CIR,		      \
4464561705bSIdo Schimmel 			     MLXSW_REG_QPCR_LOWEST_CIR,			      \
4474561705bSIdo Schimmel 			     1 << MLXSW_REG_QPCR_HIGHEST_CBS,		      \
4484561705bSIdo Schimmel 			     1 << MLXSW_REG_QPCR_LOWEST_CBS)
4494561705bSIdo Schimmel 
4504561705bSIdo Schimmel /* Ordered by policer identifier */
451cc678f4dSIdo Schimmel static const struct mlxsw_sp_trap_policer_item
452cc678f4dSIdo Schimmel mlxsw_sp_trap_policer_items_arr[] = {
453cc678f4dSIdo Schimmel 	{
4547ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(1, 10 * 1024, 4096),
455cc678f4dSIdo Schimmel 	},
45639c10350SIdo Schimmel 	{
45739c10350SIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(2, 128, 128),
45839c10350SIdo Schimmel 	},
45939c10350SIdo Schimmel 	{
46039c10350SIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(3, 128, 128),
46139c10350SIdo Schimmel 	},
46239c10350SIdo Schimmel 	{
46339c10350SIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(4, 128, 128),
46439c10350SIdo Schimmel 	},
46539c10350SIdo Schimmel 	{
4667ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(5, 16 * 1024, 8192),
46739c10350SIdo Schimmel 	},
4688110668eSIdo Schimmel 	{
4698110668eSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(6, 128, 128),
4708110668eSIdo Schimmel 	},
4718110668eSIdo Schimmel 	{
4727ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(7, 1024, 512),
4738110668eSIdo Schimmel 	},
4748110668eSIdo Schimmel 	{
4757ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(8, 20 * 1024, 8192),
4768110668eSIdo Schimmel 	},
4778110668eSIdo Schimmel 	{
4788110668eSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(9, 128, 128),
4798110668eSIdo Schimmel 	},
4808110668eSIdo Schimmel 	{
4817ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(10, 1024, 512),
4828110668eSIdo Schimmel 	},
4838110668eSIdo Schimmel 	{
4847ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(11, 256, 128),
4858110668eSIdo Schimmel 	},
4868110668eSIdo Schimmel 	{
4878110668eSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(12, 128, 128),
4888110668eSIdo Schimmel 	},
4898110668eSIdo Schimmel 	{
4908110668eSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(13, 128, 128),
4918110668eSIdo Schimmel 	},
4928110668eSIdo Schimmel 	{
4937ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(14, 1024, 512),
4948110668eSIdo Schimmel 	},
4958110668eSIdo Schimmel 	{
4967ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(15, 1024, 512),
4978110668eSIdo Schimmel 	},
4988110668eSIdo Schimmel 	{
4997ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(16, 24 * 1024, 16384),
5008110668eSIdo Schimmel 	},
5018110668eSIdo Schimmel 	{
5027ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(17, 19 * 1024, 8192),
5038110668eSIdo Schimmel 	},
50488e27749SIdo Schimmel 	{
5057ee0db9dSIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(18, 1024, 512),
50688e27749SIdo Schimmel 	},
507ec4f5b36SIdo Schimmel 	{
508ec4f5b36SIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(19, 1024, 512),
509ec4f5b36SIdo Schimmel 	},
5106687e953SIdo Schimmel 	{
5116687e953SIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(20, 10240, 4096),
5126687e953SIdo Schimmel 	},
513*d85be0f5SIdo Schimmel 	{
514*d85be0f5SIdo Schimmel 		.policer = MLXSW_SP_TRAP_POLICER(21, 128, 128),
515*d85be0f5SIdo Schimmel 	},
5164561705bSIdo Schimmel };
5174561705bSIdo Schimmel 
518b14a40dbSIdo Schimmel static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = {
519b14a40dbSIdo Schimmel 	{
520b14a40dbSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 1),
521b14a40dbSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS,
522b14a40dbSIdo Schimmel 		.priority = 0,
523b14a40dbSIdo Schimmel 	},
524b14a40dbSIdo Schimmel 	{
525b14a40dbSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 1),
526b14a40dbSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_DISCARDS,
527b14a40dbSIdo Schimmel 		.priority = 0,
528b14a40dbSIdo Schimmel 	},
529b14a40dbSIdo Schimmel 	{
5301e292f5cSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(L3_EXCEPTIONS, 1),
5311e292f5cSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_EXCEPTIONS,
5321e292f5cSIdo Schimmel 		.priority = 2,
5331e292f5cSIdo Schimmel 	},
5341e292f5cSIdo Schimmel 	{
535b14a40dbSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(TUNNEL_DROPS, 1),
536b14a40dbSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS,
537b14a40dbSIdo Schimmel 		.priority = 0,
538b14a40dbSIdo Schimmel 	},
539b14a40dbSIdo Schimmel 	{
540b14a40dbSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 1),
541b14a40dbSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS,
542b14a40dbSIdo Schimmel 		.priority = 0,
543b14a40dbSIdo Schimmel 	},
54439c10350SIdo Schimmel 	{
54539c10350SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(STP, 2),
54639c10350SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_STP,
54739c10350SIdo Schimmel 		.priority = 5,
54839c10350SIdo Schimmel 	},
54939c10350SIdo Schimmel 	{
55039c10350SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(LACP, 3),
55139c10350SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP,
55239c10350SIdo Schimmel 		.priority = 5,
55339c10350SIdo Schimmel 	},
55439c10350SIdo Schimmel 	{
55539c10350SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(LLDP, 4),
55639c10350SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP,
55739c10350SIdo Schimmel 		.priority = 5,
55839c10350SIdo Schimmel 	},
55939c10350SIdo Schimmel 	{
56039c10350SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(MC_SNOOPING, 5),
56139c10350SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_MC_SNOOPING,
56239c10350SIdo Schimmel 		.priority = 3,
56339c10350SIdo Schimmel 	},
5648110668eSIdo Schimmel 	{
5658110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(DHCP, 6),
5668110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP,
5678110668eSIdo Schimmel 		.priority = 2,
5688110668eSIdo Schimmel 	},
5698110668eSIdo Schimmel 	{
5708110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(NEIGH_DISCOVERY, 7),
5718110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_NEIGH_DISCOVERY,
5728110668eSIdo Schimmel 		.priority = 2,
5738110668eSIdo Schimmel 	},
5748110668eSIdo Schimmel 	{
5758110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(BFD, 8),
5768110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_BFD,
5778110668eSIdo Schimmel 		.priority = 5,
5788110668eSIdo Schimmel 	},
5798110668eSIdo Schimmel 	{
5808110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(OSPF, 9),
5818110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF,
5828110668eSIdo Schimmel 		.priority = 5,
5838110668eSIdo Schimmel 	},
5848110668eSIdo Schimmel 	{
5858110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(BGP, 10),
5868110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP,
5878110668eSIdo Schimmel 		.priority = 4,
5888110668eSIdo Schimmel 	},
5898110668eSIdo Schimmel 	{
5908110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(VRRP, 11),
5918110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP,
5928110668eSIdo Schimmel 		.priority = 5,
5938110668eSIdo Schimmel 	},
5948110668eSIdo Schimmel 	{
5958110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(PIM, 12),
5968110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM,
5978110668eSIdo Schimmel 		.priority = 5,
5988110668eSIdo Schimmel 	},
5998110668eSIdo Schimmel 	{
6008110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(UC_LB, 13),
6018110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR,
6028110668eSIdo Schimmel 		.priority = 0,
6038110668eSIdo Schimmel 	},
6048110668eSIdo Schimmel 	{
6058110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(LOCAL_DELIVERY, 14),
6068110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME,
6078110668eSIdo Schimmel 		.priority = 2,
6088110668eSIdo Schimmel 	},
6098110668eSIdo Schimmel 	{
610ec4f5b36SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(EXTERNAL_DELIVERY, 19),
611ec4f5b36SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_EXTERNAL_ROUTE,
612ec4f5b36SIdo Schimmel 		.priority = 1,
613ec4f5b36SIdo Schimmel 	},
614ec4f5b36SIdo Schimmel 	{
6158110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(IPV6, 15),
6168110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6,
6178110668eSIdo Schimmel 		.priority = 2,
6188110668eSIdo Schimmel 	},
6198110668eSIdo Schimmel 	{
6208110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(PTP_EVENT, 16),
6218110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0,
6228110668eSIdo Schimmel 		.priority = 5,
6238110668eSIdo Schimmel 	},
6248110668eSIdo Schimmel 	{
6258110668eSIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(PTP_GENERAL, 17),
6268110668eSIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1,
6278110668eSIdo Schimmel 		.priority = 2,
6288110668eSIdo Schimmel 	},
62988e27749SIdo Schimmel 	{
63088e27749SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(ACL_TRAP, 18),
63188e27749SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_FLOW_LOGGING,
63288e27749SIdo Schimmel 		.priority = 4,
63388e27749SIdo Schimmel 	},
634*d85be0f5SIdo Schimmel 	{
635*d85be0f5SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(EAPOL, 21),
636*d85be0f5SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_EAPOL,
637*d85be0f5SIdo Schimmel 		.priority = 5,
638*d85be0f5SIdo Schimmel 	},
6398cd999e4SIdo Schimmel };
6408cd999e4SIdo Schimmel 
641200b7ccaSIdo Schimmel static const struct mlxsw_sp_trap_item mlxsw_sp_trap_items_arr[] = {
642200b7ccaSIdo Schimmel 	{
643200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(SMAC_MC, L2_DROPS),
644200b7ccaSIdo Schimmel 		.listeners_arr = {
645b5ce611fSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(ING_PACKET_SMAC_MC, L2_DISCARDS),
646200b7ccaSIdo Schimmel 		},
647200b7ccaSIdo Schimmel 	},
648200b7ccaSIdo Schimmel 	{
649200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(VLAN_TAG_MISMATCH, L2_DROPS),
650200b7ccaSIdo Schimmel 		.listeners_arr = {
651200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(ING_SWITCH_VTAG_ALLOW,
652200b7ccaSIdo Schimmel 					     L2_DISCARDS),
653200b7ccaSIdo Schimmel 		},
654200b7ccaSIdo Schimmel 	},
655200b7ccaSIdo Schimmel 	{
656200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
657200b7ccaSIdo Schimmel 		.listeners_arr = {
658b5ce611fSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(ING_SWITCH_VLAN, L2_DISCARDS),
659200b7ccaSIdo Schimmel 		},
660200b7ccaSIdo Schimmel 	},
661200b7ccaSIdo Schimmel 	{
662200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(INGRESS_STP_FILTER, L2_DROPS),
663200b7ccaSIdo Schimmel 		.listeners_arr = {
664b5ce611fSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(ING_SWITCH_STP, L2_DISCARDS),
665200b7ccaSIdo Schimmel 		},
666200b7ccaSIdo Schimmel 	},
667200b7ccaSIdo Schimmel 	{
668200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(EMPTY_TX_LIST, L2_DROPS),
669200b7ccaSIdo Schimmel 		.listeners_arr = {
670b5ce611fSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_UC, L2_DISCARDS),
671b5ce611fSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_MC_NULL, L2_DISCARDS),
672200b7ccaSIdo Schimmel 		},
673200b7ccaSIdo Schimmel 	},
674200b7ccaSIdo Schimmel 	{
675200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(PORT_LOOPBACK_FILTER, L2_DROPS),
676200b7ccaSIdo Schimmel 		.listeners_arr = {
677b5ce611fSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_LB, L2_DISCARDS),
678200b7ccaSIdo Schimmel 		},
679200b7ccaSIdo Schimmel 	},
680200b7ccaSIdo Schimmel 	{
681200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(BLACKHOLE_ROUTE, L3_DROPS),
682200b7ccaSIdo Schimmel 		.listeners_arr = {
683dbc684f1SAmit Cohen 			MLXSW_SP_RXL_DISCARD(ROUTER2, L3_DISCARDS),
684200b7ccaSIdo Schimmel 		},
685200b7ccaSIdo Schimmel 	},
686200b7ccaSIdo Schimmel 	{
687200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(NON_IP_PACKET, L3_DROPS),
688200b7ccaSIdo Schimmel 		.listeners_arr = {
689200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_NON_IP_PACKET,
690200b7ccaSIdo Schimmel 					     L3_DISCARDS),
691200b7ccaSIdo Schimmel 		},
692200b7ccaSIdo Schimmel 	},
693200b7ccaSIdo Schimmel 	{
694200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(UC_DIP_MC_DMAC, L3_DROPS),
695200b7ccaSIdo Schimmel 		.listeners_arr = {
696200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_UC_DIP_MC_DMAC,
697200b7ccaSIdo Schimmel 					     L3_DISCARDS),
698200b7ccaSIdo Schimmel 		},
699200b7ccaSIdo Schimmel 	},
700200b7ccaSIdo Schimmel 	{
701200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(DIP_LB, L3_DROPS),
702200b7ccaSIdo Schimmel 		.listeners_arr = {
703dbc684f1SAmit Cohen 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_DIP_LB, L3_DISCARDS),
704200b7ccaSIdo Schimmel 		},
705200b7ccaSIdo Schimmel 	},
706200b7ccaSIdo Schimmel 	{
707200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(SIP_MC, L3_DROPS),
708200b7ccaSIdo Schimmel 		.listeners_arr = {
709dbc684f1SAmit Cohen 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_SIP_MC, L3_DISCARDS),
710200b7ccaSIdo Schimmel 		},
711200b7ccaSIdo Schimmel 	},
712200b7ccaSIdo Schimmel 	{
713200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(SIP_LB, L3_DROPS),
714200b7ccaSIdo Schimmel 		.listeners_arr = {
715dbc684f1SAmit Cohen 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_SIP_LB, L3_DISCARDS),
716200b7ccaSIdo Schimmel 		},
717200b7ccaSIdo Schimmel 	},
718200b7ccaSIdo Schimmel 	{
719200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(CORRUPTED_IP_HDR, L3_DROPS),
720200b7ccaSIdo Schimmel 		.listeners_arr = {
721200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_CORRUPTED_IP_HDR,
722200b7ccaSIdo Schimmel 					     L3_DISCARDS),
723200b7ccaSIdo Schimmel 		},
724200b7ccaSIdo Schimmel 	},
725200b7ccaSIdo Schimmel 	{
726200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(IPV4_SIP_BC, L3_DROPS),
727200b7ccaSIdo Schimmel 		.listeners_arr = {
728200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_IPV4_SIP_BC,
729200b7ccaSIdo Schimmel 					     L3_DISCARDS),
730200b7ccaSIdo Schimmel 		},
731200b7ccaSIdo Schimmel 	},
732200b7ccaSIdo Schimmel 	{
733200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(IPV6_MC_DIP_RESERVED_SCOPE,
734200b7ccaSIdo Schimmel 					   L3_DROPS),
735200b7ccaSIdo Schimmel 		.listeners_arr = {
736200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_RESERVED_SCOPE,
737200b7ccaSIdo Schimmel 					     L3_DISCARDS),
738200b7ccaSIdo Schimmel 		},
739200b7ccaSIdo Schimmel 	},
740200b7ccaSIdo Schimmel 	{
741200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE,
742200b7ccaSIdo Schimmel 					   L3_DROPS),
743200b7ccaSIdo Schimmel 		.listeners_arr = {
744200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE,
745200b7ccaSIdo Schimmel 					     L3_DISCARDS),
746200b7ccaSIdo Schimmel 		},
747200b7ccaSIdo Schimmel 	},
748200b7ccaSIdo Schimmel 	{
7491e292f5cSIdo Schimmel 		.trap = MLXSW_SP_TRAP_EXCEPTION(MTU_ERROR, L3_EXCEPTIONS),
750200b7ccaSIdo Schimmel 		.listeners_arr = {
7511e292f5cSIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(MTUERROR, L3_EXCEPTIONS,
752200b7ccaSIdo Schimmel 					       TRAP_TO_CPU),
753200b7ccaSIdo Schimmel 		},
754200b7ccaSIdo Schimmel 	},
755200b7ccaSIdo Schimmel 	{
7561e292f5cSIdo Schimmel 		.trap = MLXSW_SP_TRAP_EXCEPTION(TTL_ERROR, L3_EXCEPTIONS),
757200b7ccaSIdo Schimmel 		.listeners_arr = {
7581e292f5cSIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(TTLERROR, L3_EXCEPTIONS,
759200b7ccaSIdo Schimmel 					       TRAP_TO_CPU),
760200b7ccaSIdo Schimmel 		},
761200b7ccaSIdo Schimmel 	},
762200b7ccaSIdo Schimmel 	{
7631e292f5cSIdo Schimmel 		.trap = MLXSW_SP_TRAP_EXCEPTION(RPF, L3_EXCEPTIONS),
764200b7ccaSIdo Schimmel 		.listeners_arr = {
7651e292f5cSIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(RPF, L3_EXCEPTIONS, TRAP_TO_CPU),
766200b7ccaSIdo Schimmel 		},
767200b7ccaSIdo Schimmel 	},
768200b7ccaSIdo Schimmel 	{
7691e292f5cSIdo Schimmel 		.trap = MLXSW_SP_TRAP_EXCEPTION(REJECT_ROUTE, L3_EXCEPTIONS),
770200b7ccaSIdo Schimmel 		.listeners_arr = {
7711e292f5cSIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(RTR_INGRESS1, L3_EXCEPTIONS,
772200b7ccaSIdo Schimmel 					       TRAP_TO_CPU),
773200b7ccaSIdo Schimmel 		},
774200b7ccaSIdo Schimmel 	},
775200b7ccaSIdo Schimmel 	{
7761e292f5cSIdo Schimmel 		.trap = MLXSW_SP_TRAP_EXCEPTION(UNRESOLVED_NEIGH,
7771e292f5cSIdo Schimmel 						L3_EXCEPTIONS),
778200b7ccaSIdo Schimmel 		.listeners_arr = {
7791e292f5cSIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV4, L3_EXCEPTIONS,
780200b7ccaSIdo Schimmel 					       TRAP_TO_CPU),
7811e292f5cSIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV6, L3_EXCEPTIONS,
782200b7ccaSIdo Schimmel 					       TRAP_TO_CPU),
78352d45575SIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(RTR_EGRESS0, L3_EXCEPTIONS,
784fd74feebSAmit Cohen 					       TRAP_EXCEPTION_TO_CPU),
785200b7ccaSIdo Schimmel 		},
786200b7ccaSIdo Schimmel 	},
787200b7ccaSIdo Schimmel 	{
788200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_EXCEPTION(IPV4_LPM_UNICAST_MISS,
7891e292f5cSIdo Schimmel 						L3_EXCEPTIONS),
790200b7ccaSIdo Schimmel 		.listeners_arr = {
7911e292f5cSIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM4,
7921e292f5cSIdo Schimmel 					       L3_EXCEPTIONS,
793fd74feebSAmit Cohen 					       TRAP_EXCEPTION_TO_CPU),
794200b7ccaSIdo Schimmel 		},
795200b7ccaSIdo Schimmel 	},
796200b7ccaSIdo Schimmel 	{
797200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_EXCEPTION(IPV6_LPM_UNICAST_MISS,
7981e292f5cSIdo Schimmel 						L3_EXCEPTIONS),
799200b7ccaSIdo Schimmel 		.listeners_arr = {
8001e292f5cSIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM6,
8011e292f5cSIdo Schimmel 					       L3_EXCEPTIONS,
802fd74feebSAmit Cohen 					       TRAP_EXCEPTION_TO_CPU),
803200b7ccaSIdo Schimmel 		},
804200b7ccaSIdo Schimmel 	},
805200b7ccaSIdo Schimmel 	{
806200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DRIVER_DROP(IRIF_DISABLED, L3_DROPS),
807200b7ccaSIdo Schimmel 		.listeners_arr = {
8085b051621SAmit Cohen 			MLXSW_SP_RXL_DISCARD(ROUTER_IRIF_EN, L3_DISCARDS),
809200b7ccaSIdo Schimmel 		},
810200b7ccaSIdo Schimmel 	},
811200b7ccaSIdo Schimmel 	{
812200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DRIVER_DROP(ERIF_DISABLED, L3_DROPS),
813200b7ccaSIdo Schimmel 		.listeners_arr = {
8145b051621SAmit Cohen 			MLXSW_SP_RXL_DISCARD(ROUTER_ERIF_EN, L3_DISCARDS),
815200b7ccaSIdo Schimmel 		},
816200b7ccaSIdo Schimmel 	},
817200b7ccaSIdo Schimmel 	{
818200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(NON_ROUTABLE, L3_DROPS),
819200b7ccaSIdo Schimmel 		.listeners_arr = {
820196442ecSAmit Cohen 			MLXSW_SP_RXL_DISCARD(NON_ROUTABLE, L3_DISCARDS),
821200b7ccaSIdo Schimmel 		},
822200b7ccaSIdo Schimmel 	},
823200b7ccaSIdo Schimmel 	{
824200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_EXCEPTION(DECAP_ERROR, TUNNEL_DROPS),
825200b7ccaSIdo Schimmel 		.listeners_arr = {
826d12d8468SIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(DECAP_ECN0, TUNNEL_DISCARDS,
827d12d8468SIdo Schimmel 					       TRAP_EXCEPTION_TO_CPU),
828200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_EXCEPTION(IPIP_DECAP_ERROR,
829200b7ccaSIdo Schimmel 					       TUNNEL_DISCARDS,
830a318bf62SAmit Cohen 					       TRAP_EXCEPTION_TO_CPU),
831a318bf62SAmit Cohen 			MLXSW_SP_RXL_EXCEPTION(DISCARD_DEC_PKT, TUNNEL_DISCARDS,
832a318bf62SAmit Cohen 					       TRAP_EXCEPTION_TO_CPU),
833200b7ccaSIdo Schimmel 		},
834200b7ccaSIdo Schimmel 	},
835200b7ccaSIdo Schimmel 	{
836200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(OVERLAY_SMAC_MC, TUNNEL_DROPS),
837200b7ccaSIdo Schimmel 		.listeners_arr = {
8383aed0722SAmit Cohen 			MLXSW_SP_RXL_DISCARD(OVERLAY_SMAC_MC, TUNNEL_DISCARDS),
839200b7ccaSIdo Schimmel 		},
840200b7ccaSIdo Schimmel 	},
841200b7ccaSIdo Schimmel 	{
842200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP_EXT(INGRESS_FLOW_ACTION_DROP,
843200b7ccaSIdo Schimmel 					       ACL_DROPS,
844200b7ccaSIdo Schimmel 					       DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE),
845200b7ccaSIdo Schimmel 		.listeners_arr = {
846200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_ACL_DISCARD(INGRESS_ACL, ACL_DISCARDS,
847200b7ccaSIdo Schimmel 						 DUMMY),
848200b7ccaSIdo Schimmel 		},
849200b7ccaSIdo Schimmel 	},
850200b7ccaSIdo Schimmel 	{
851200b7ccaSIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP_EXT(EGRESS_FLOW_ACTION_DROP,
852200b7ccaSIdo Schimmel 					       ACL_DROPS,
853200b7ccaSIdo Schimmel 					       DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE),
854200b7ccaSIdo Schimmel 		.listeners_arr = {
855200b7ccaSIdo Schimmel 			MLXSW_SP_RXL_ACL_DISCARD(EGRESS_ACL, ACL_DISCARDS,
856200b7ccaSIdo Schimmel 						 DUMMY),
857200b7ccaSIdo Schimmel 		},
858200b7ccaSIdo Schimmel 	},
85939c10350SIdo Schimmel 	{
86039c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(STP, STP, TRAP),
86139c10350SIdo Schimmel 		.listeners_arr = {
86239c10350SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(STP, STP, TRAP_TO_CPU, true),
86339c10350SIdo Schimmel 		},
86439c10350SIdo Schimmel 	},
86539c10350SIdo Schimmel 	{
86639c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(LACP, LACP, TRAP),
86739c10350SIdo Schimmel 		.listeners_arr = {
86839c10350SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(LACP, LACP, TRAP_TO_CPU, true),
86939c10350SIdo Schimmel 		},
87039c10350SIdo Schimmel 	},
87139c10350SIdo Schimmel 	{
87239c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(LLDP, LLDP, TRAP),
87339c10350SIdo Schimmel 		.listeners_arr = {
87439c10350SIdo Schimmel 			MLXSW_RXL(mlxsw_sp_rx_ptp_listener, LLDP, TRAP_TO_CPU,
8750106668cSPetr Machata 				  true, SP_LLDP, DISCARD),
87639c10350SIdo Schimmel 		},
87739c10350SIdo Schimmel 	},
87839c10350SIdo Schimmel 	{
87939c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_QUERY, MC_SNOOPING, MIRROR),
88039c10350SIdo Schimmel 		.listeners_arr = {
88139c10350SIdo Schimmel 			MLXSW_SP_RXL_MARK(IGMP_QUERY, MC_SNOOPING,
88239c10350SIdo Schimmel 					  MIRROR_TO_CPU, false),
88339c10350SIdo Schimmel 		},
88439c10350SIdo Schimmel 	},
88539c10350SIdo Schimmel 	{
88639c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_V1_REPORT, MC_SNOOPING,
88739c10350SIdo Schimmel 					      TRAP),
88839c10350SIdo Schimmel 		.listeners_arr = {
88939c10350SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, MC_SNOOPING,
89039c10350SIdo Schimmel 					     TRAP_TO_CPU, false),
89139c10350SIdo Schimmel 		},
89239c10350SIdo Schimmel 	},
89339c10350SIdo Schimmel 	{
89439c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_V2_REPORT, MC_SNOOPING,
89539c10350SIdo Schimmel 					      TRAP),
89639c10350SIdo Schimmel 		.listeners_arr = {
89739c10350SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, MC_SNOOPING,
89839c10350SIdo Schimmel 					     TRAP_TO_CPU, false),
89939c10350SIdo Schimmel 		},
90039c10350SIdo Schimmel 	},
90139c10350SIdo Schimmel 	{
90239c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_V3_REPORT, MC_SNOOPING,
90339c10350SIdo Schimmel 					      TRAP),
90439c10350SIdo Schimmel 		.listeners_arr = {
90539c10350SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, MC_SNOOPING,
90639c10350SIdo Schimmel 					     TRAP_TO_CPU, false),
90739c10350SIdo Schimmel 		},
90839c10350SIdo Schimmel 	},
90939c10350SIdo Schimmel 	{
91039c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_V2_LEAVE, MC_SNOOPING,
91139c10350SIdo Schimmel 					      TRAP),
91239c10350SIdo Schimmel 		.listeners_arr = {
91339c10350SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, MC_SNOOPING,
91439c10350SIdo Schimmel 					     TRAP_TO_CPU, false),
91539c10350SIdo Schimmel 		},
91639c10350SIdo Schimmel 	},
91739c10350SIdo Schimmel 	{
91839c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(MLD_QUERY, MC_SNOOPING, MIRROR),
91939c10350SIdo Schimmel 		.listeners_arr = {
92039c10350SIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_MLDV12_LISTENER_QUERY,
92139c10350SIdo Schimmel 					  MC_SNOOPING, MIRROR_TO_CPU, false),
92239c10350SIdo Schimmel 		},
92339c10350SIdo Schimmel 	},
92439c10350SIdo Schimmel 	{
92539c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(MLD_V1_REPORT, MC_SNOOPING,
92639c10350SIdo Schimmel 					      TRAP),
92739c10350SIdo Schimmel 		.listeners_arr = {
92839c10350SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_REPORT,
92939c10350SIdo Schimmel 					     MC_SNOOPING, TRAP_TO_CPU, false),
93039c10350SIdo Schimmel 		},
93139c10350SIdo Schimmel 	},
93239c10350SIdo Schimmel 	{
93339c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(MLD_V2_REPORT, MC_SNOOPING,
93439c10350SIdo Schimmel 					      TRAP),
93539c10350SIdo Schimmel 		.listeners_arr = {
93639c10350SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(IPV6_MLDV2_LISTENER_REPORT,
93739c10350SIdo Schimmel 					     MC_SNOOPING, TRAP_TO_CPU, false),
93839c10350SIdo Schimmel 		},
93939c10350SIdo Schimmel 	},
94039c10350SIdo Schimmel 	{
94139c10350SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(MLD_V1_DONE, MC_SNOOPING,
94239c10350SIdo Schimmel 					      TRAP),
94339c10350SIdo Schimmel 		.listeners_arr = {
94439c10350SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_DONE,
94539c10350SIdo Schimmel 					     MC_SNOOPING, TRAP_TO_CPU, false),
94639c10350SIdo Schimmel 		},
94739c10350SIdo Schimmel 	},
9488110668eSIdo Schimmel 	{
9498110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_DHCP, DHCP, TRAP),
9508110668eSIdo Schimmel 		.listeners_arr = {
9518110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV4_DHCP, DHCP, TRAP_TO_CPU, false),
9528110668eSIdo Schimmel 		},
9538110668eSIdo Schimmel 	},
9548110668eSIdo Schimmel 	{
9558110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_DHCP, DHCP, TRAP),
9568110668eSIdo Schimmel 		.listeners_arr = {
9578110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_DHCP, DHCP, TRAP_TO_CPU, false),
9588110668eSIdo Schimmel 		},
9598110668eSIdo Schimmel 	},
9608110668eSIdo Schimmel 	{
9618110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(ARP_REQUEST, NEIGH_DISCOVERY,
9628110668eSIdo Schimmel 					      MIRROR),
9638110668eSIdo Schimmel 		.listeners_arr = {
9644b1cc357SAmit Cohen 			MLXSW_SP_RXL_MARK(ROUTER_ARPBC, NEIGH_DISCOVERY,
9654b1cc357SAmit Cohen 					  TRAP_TO_CPU, false),
9668110668eSIdo Schimmel 		},
9678110668eSIdo Schimmel 	},
9688110668eSIdo Schimmel 	{
9698110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(ARP_RESPONSE, NEIGH_DISCOVERY,
9708110668eSIdo Schimmel 					      MIRROR),
9718110668eSIdo Schimmel 		.listeners_arr = {
9724b1cc357SAmit Cohen 			MLXSW_SP_RXL_MARK(ROUTER_ARPUC, NEIGH_DISCOVERY,
9734b1cc357SAmit Cohen 					  TRAP_TO_CPU, false),
9748110668eSIdo Schimmel 		},
9758110668eSIdo Schimmel 	},
9768110668eSIdo Schimmel 	{
9778110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(ARP_OVERLAY, NEIGH_DISCOVERY,
9788110668eSIdo Schimmel 					      TRAP),
9798110668eSIdo Schimmel 		.listeners_arr = {
9808110668eSIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(NVE_DECAP_ARP, NEIGH_DISCOVERY,
9818110668eSIdo Schimmel 					     TRAP_TO_CPU, false),
9828110668eSIdo Schimmel 		},
9838110668eSIdo Schimmel 	},
9848110668eSIdo Schimmel 	{
9858110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_NEIGH_SOLICIT,
9868110668eSIdo Schimmel 					      NEIGH_DISCOVERY, TRAP),
9878110668eSIdo Schimmel 		.listeners_arr = {
9888110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(L3_IPV6_NEIGHBOR_SOLICITATION,
9898110668eSIdo Schimmel 					  NEIGH_DISCOVERY, TRAP_TO_CPU, false),
9908110668eSIdo Schimmel 		},
9918110668eSIdo Schimmel 	},
9928110668eSIdo Schimmel 	{
9938110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_NEIGH_ADVERT,
9948110668eSIdo Schimmel 					      NEIGH_DISCOVERY, TRAP),
9958110668eSIdo Schimmel 		.listeners_arr = {
9968110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(L3_IPV6_NEIGHBOR_ADVERTISEMENT,
9978110668eSIdo Schimmel 					  NEIGH_DISCOVERY, TRAP_TO_CPU, false),
9988110668eSIdo Schimmel 		},
9998110668eSIdo Schimmel 	},
10008110668eSIdo Schimmel 	{
10018110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_BFD, BFD, TRAP),
10028110668eSIdo Schimmel 		.listeners_arr = {
10038110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV4_BFD, BFD, TRAP_TO_CPU, false),
10048110668eSIdo Schimmel 		},
10058110668eSIdo Schimmel 	},
10068110668eSIdo Schimmel 	{
10078110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_BFD, BFD, TRAP),
10088110668eSIdo Schimmel 		.listeners_arr = {
10098110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_BFD, BFD, TRAP_TO_CPU, false),
10108110668eSIdo Schimmel 		},
10118110668eSIdo Schimmel 	},
10128110668eSIdo Schimmel 	{
10138110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_OSPF, OSPF, TRAP),
10148110668eSIdo Schimmel 		.listeners_arr = {
10158110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV4_OSPF, OSPF, TRAP_TO_CPU, false),
10168110668eSIdo Schimmel 		},
10178110668eSIdo Schimmel 	},
10188110668eSIdo Schimmel 	{
10198110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_OSPF, OSPF, TRAP),
10208110668eSIdo Schimmel 		.listeners_arr = {
10218110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_OSPF, OSPF, TRAP_TO_CPU, false),
10228110668eSIdo Schimmel 		},
10238110668eSIdo Schimmel 	},
10248110668eSIdo Schimmel 	{
10258110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_BGP, BGP, TRAP),
10268110668eSIdo Schimmel 		.listeners_arr = {
10278110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV4_BGP, BGP, TRAP_TO_CPU, false),
10288110668eSIdo Schimmel 		},
10298110668eSIdo Schimmel 	},
10308110668eSIdo Schimmel 	{
10318110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_BGP, BGP, TRAP),
10328110668eSIdo Schimmel 		.listeners_arr = {
10338110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_BGP, BGP, TRAP_TO_CPU, false),
10348110668eSIdo Schimmel 		},
10358110668eSIdo Schimmel 	},
10368110668eSIdo Schimmel 	{
10378110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_VRRP, VRRP, TRAP),
10388110668eSIdo Schimmel 		.listeners_arr = {
10398110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV4_VRRP, VRRP, TRAP_TO_CPU, false),
10408110668eSIdo Schimmel 		},
10418110668eSIdo Schimmel 	},
10428110668eSIdo Schimmel 	{
10438110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_VRRP, VRRP, TRAP),
10448110668eSIdo Schimmel 		.listeners_arr = {
10458110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_VRRP, VRRP, TRAP_TO_CPU, false),
10468110668eSIdo Schimmel 		},
10478110668eSIdo Schimmel 	},
10488110668eSIdo Schimmel 	{
10498110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_PIM, PIM, TRAP),
10508110668eSIdo Schimmel 		.listeners_arr = {
10518110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV4_PIM, PIM, TRAP_TO_CPU, false),
10528110668eSIdo Schimmel 		},
10538110668eSIdo Schimmel 	},
10548110668eSIdo Schimmel 	{
10558110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_PIM, PIM, TRAP),
10568110668eSIdo Schimmel 		.listeners_arr = {
10578110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_PIM, PIM, TRAP_TO_CPU, false),
10588110668eSIdo Schimmel 		},
10598110668eSIdo Schimmel 	},
10608110668eSIdo Schimmel 	{
10618110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(UC_LB, UC_LB, MIRROR),
10628110668eSIdo Schimmel 		.listeners_arr = {
10638110668eSIdo Schimmel 			MLXSW_SP_RXL_L3_MARK(LBERROR, LBERROR, MIRROR_TO_CPU,
10648110668eSIdo Schimmel 					     false),
10658110668eSIdo Schimmel 		},
10668110668eSIdo Schimmel 	},
10678110668eSIdo Schimmel 	{
10688110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(LOCAL_ROUTE, LOCAL_DELIVERY,
10698110668eSIdo Schimmel 					      TRAP),
10708110668eSIdo Schimmel 		.listeners_arr = {
10718110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IP2ME, IP2ME, TRAP_TO_CPU, false),
10728110668eSIdo Schimmel 		},
10738110668eSIdo Schimmel 	},
10748110668eSIdo Schimmel 	{
1075ec4f5b36SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(EXTERNAL_ROUTE, EXTERNAL_DELIVERY,
10768110668eSIdo Schimmel 					      TRAP),
10778110668eSIdo Schimmel 		.listeners_arr = {
1078ec4f5b36SIdo Schimmel 			MLXSW_SP_RXL_MARK(RTR_INGRESS0, EXTERNAL_ROUTE,
1079ec4f5b36SIdo Schimmel 					  TRAP_TO_CPU, false),
10808110668eSIdo Schimmel 		},
10818110668eSIdo Schimmel 	},
10828110668eSIdo Schimmel 	{
10838110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_UC_DIP_LINK_LOCAL_SCOPE,
10848110668eSIdo Schimmel 					      LOCAL_DELIVERY, TRAP),
10858110668eSIdo Schimmel 		.listeners_arr = {
10868110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_LINK_LOCAL_DEST, IP2ME,
10878110668eSIdo Schimmel 					  TRAP_TO_CPU, false),
10888110668eSIdo Schimmel 		},
10898110668eSIdo Schimmel 	},
10908110668eSIdo Schimmel 	{
10918110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_ROUTER_ALERT, LOCAL_DELIVERY,
10928110668eSIdo Schimmel 					      TRAP),
10938110668eSIdo Schimmel 		.listeners_arr = {
10948110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV4, IP2ME, TRAP_TO_CPU,
10958110668eSIdo Schimmel 					  false),
10968110668eSIdo Schimmel 		},
10978110668eSIdo Schimmel 	},
10988110668eSIdo Schimmel 	{
10998110668eSIdo Schimmel 		/* IPV6_ROUTER_ALERT is defined in uAPI as 22, but it is not
11008110668eSIdo Schimmel 		 * used in this file, so undefine it.
11018110668eSIdo Schimmel 		 */
11028110668eSIdo Schimmel 		#undef IPV6_ROUTER_ALERT
11038110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_ROUTER_ALERT, LOCAL_DELIVERY,
11048110668eSIdo Schimmel 					      TRAP),
11058110668eSIdo Schimmel 		.listeners_arr = {
11068110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV6, IP2ME, TRAP_TO_CPU,
11078110668eSIdo Schimmel 					  false),
11088110668eSIdo Schimmel 		},
11098110668eSIdo Schimmel 	},
11108110668eSIdo Schimmel 	{
11118110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_DIP_ALL_NODES, IPV6, TRAP),
11128110668eSIdo Schimmel 		.listeners_arr = {
11138110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_ALL_NODES_LINK, IPV6,
11148110668eSIdo Schimmel 					  TRAP_TO_CPU, false),
11158110668eSIdo Schimmel 		},
11168110668eSIdo Schimmel 	},
11178110668eSIdo Schimmel 	{
11188110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_DIP_ALL_ROUTERS, IPV6, TRAP),
11198110668eSIdo Schimmel 		.listeners_arr = {
11208110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(IPV6_ALL_ROUTERS_LINK, IPV6,
11218110668eSIdo Schimmel 					  TRAP_TO_CPU, false),
11228110668eSIdo Schimmel 		},
11238110668eSIdo Schimmel 	},
11248110668eSIdo Schimmel 	{
11258110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_ROUTER_SOLICIT, IPV6, TRAP),
11268110668eSIdo Schimmel 		.listeners_arr = {
11278110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(L3_IPV6_ROUTER_SOLICITATION, IPV6,
11288110668eSIdo Schimmel 					  TRAP_TO_CPU, false),
11298110668eSIdo Schimmel 		},
11308110668eSIdo Schimmel 	},
11318110668eSIdo Schimmel 	{
11328110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_ROUTER_ADVERT, IPV6, TRAP),
11338110668eSIdo Schimmel 		.listeners_arr = {
11348110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(L3_IPV6_ROUTER_ADVERTISEMENT, IPV6,
11358110668eSIdo Schimmel 					  TRAP_TO_CPU, false),
11368110668eSIdo Schimmel 		},
11378110668eSIdo Schimmel 	},
11388110668eSIdo Schimmel 	{
11398110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_REDIRECT, IPV6, TRAP),
11408110668eSIdo Schimmel 		.listeners_arr = {
11418110668eSIdo Schimmel 			MLXSW_SP_RXL_MARK(L3_IPV6_REDIRECTION, IPV6,
11428110668eSIdo Schimmel 					  TRAP_TO_CPU, false),
11438110668eSIdo Schimmel 		},
11448110668eSIdo Schimmel 	},
11458110668eSIdo Schimmel 	{
11468110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(PTP_EVENT, PTP_EVENT, TRAP),
11478110668eSIdo Schimmel 		.listeners_arr = {
11488110668eSIdo Schimmel 			MLXSW_RXL(mlxsw_sp_rx_ptp_listener, PTP0, TRAP_TO_CPU,
11498110668eSIdo Schimmel 				  false, SP_PTP0, DISCARD),
11508110668eSIdo Schimmel 		},
11518110668eSIdo Schimmel 	},
11528110668eSIdo Schimmel 	{
11538110668eSIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(PTP_GENERAL, PTP_GENERAL, TRAP),
11548110668eSIdo Schimmel 		.listeners_arr = {
11558110668eSIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(PTP1, PTP1, TRAP_TO_CPU, false),
11568110668eSIdo Schimmel 		},
11578110668eSIdo Schimmel 	},
115888e27749SIdo Schimmel 	{
115988e27749SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(FLOW_ACTION_TRAP, ACL_TRAP, TRAP),
116088e27749SIdo Schimmel 		.listeners_arr = {
116188e27749SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(ACL0, FLOW_LOGGING, TRAP_TO_CPU,
116288e27749SIdo Schimmel 					     false),
116388e27749SIdo Schimmel 		},
116488e27749SIdo Schimmel 	},
116537b50e55SIdo Schimmel 	{
116637b50e55SIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(BLACKHOLE_NEXTHOP, L3_DROPS),
116737b50e55SIdo Schimmel 		.listeners_arr = {
116837b50e55SIdo Schimmel 			MLXSW_SP_RXL_DISCARD(ROUTER3, L3_DISCARDS),
116937b50e55SIdo Schimmel 		},
117037b50e55SIdo Schimmel 	},
1171*d85be0f5SIdo Schimmel 	{
1172*d85be0f5SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(EAPOL, EAPOL, TRAP),
1173*d85be0f5SIdo Schimmel 		.listeners_arr = {
1174*d85be0f5SIdo Schimmel 			MLXSW_SP_RXL_NO_MARK(EAPOL, EAPOL, TRAP_TO_CPU, true),
1175*d85be0f5SIdo Schimmel 		},
1176*d85be0f5SIdo Schimmel 	},
1177*d85be0f5SIdo Schimmel 	{
1178*d85be0f5SIdo Schimmel 		.trap = MLXSW_SP_TRAP_DROP(LOCKED_PORT, L2_DROPS),
1179*d85be0f5SIdo Schimmel 		.listeners_arr = {
1180*d85be0f5SIdo Schimmel 			MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, FDB_MISS,
1181*d85be0f5SIdo Schimmel 				      TRAP_EXCEPTION_TO_CPU, false,
1182*d85be0f5SIdo Schimmel 				      SP_L2_DISCARDS, DISCARD, SP_L2_DISCARDS),
1183*d85be0f5SIdo Schimmel 			MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, FDB_MISMATCH,
1184*d85be0f5SIdo Schimmel 				      TRAP_EXCEPTION_TO_CPU, false,
1185*d85be0f5SIdo Schimmel 				      SP_L2_DISCARDS, DISCARD, SP_L2_DISCARDS),
1186*d85be0f5SIdo Schimmel 		},
1187*d85be0f5SIdo Schimmel 	},
1188b5ce611fSIdo Schimmel };
1189b5ce611fSIdo Schimmel 
119013f2e64bSIdo Schimmel static struct mlxsw_sp_trap_policer_item *
mlxsw_sp_trap_policer_item_lookup(struct mlxsw_sp * mlxsw_sp,u32 id)119113f2e64bSIdo Schimmel mlxsw_sp_trap_policer_item_lookup(struct mlxsw_sp *mlxsw_sp, u32 id)
119213f2e64bSIdo Schimmel {
119313f2e64bSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1194cc678f4dSIdo Schimmel 	int i;
119513f2e64bSIdo Schimmel 
1196cc678f4dSIdo Schimmel 	for (i = 0; i < trap->policers_count; i++) {
1197cc678f4dSIdo Schimmel 		if (trap->policer_items_arr[i].policer.id == id)
1198cc678f4dSIdo Schimmel 			return &trap->policer_items_arr[i];
119913f2e64bSIdo Schimmel 	}
120013f2e64bSIdo Schimmel 
120113f2e64bSIdo Schimmel 	return NULL;
120213f2e64bSIdo Schimmel }
120313f2e64bSIdo Schimmel 
1204b14a40dbSIdo Schimmel static struct mlxsw_sp_trap_group_item *
mlxsw_sp_trap_group_item_lookup(struct mlxsw_sp * mlxsw_sp,u16 id)1205b14a40dbSIdo Schimmel mlxsw_sp_trap_group_item_lookup(struct mlxsw_sp *mlxsw_sp, u16 id)
1206b14a40dbSIdo Schimmel {
1207b14a40dbSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1208b14a40dbSIdo Schimmel 	int i;
1209b14a40dbSIdo Schimmel 
1210b14a40dbSIdo Schimmel 	for (i = 0; i < trap->groups_count; i++) {
1211b14a40dbSIdo Schimmel 		if (trap->group_items_arr[i].group.id == id)
1212b14a40dbSIdo Schimmel 			return &trap->group_items_arr[i];
1213b14a40dbSIdo Schimmel 	}
1214b14a40dbSIdo Schimmel 
1215b14a40dbSIdo Schimmel 	return NULL;
1216b14a40dbSIdo Schimmel }
1217b14a40dbSIdo Schimmel 
1218200b7ccaSIdo Schimmel static struct mlxsw_sp_trap_item *
mlxsw_sp_trap_item_lookup(struct mlxsw_sp * mlxsw_sp,u16 id)1219200b7ccaSIdo Schimmel mlxsw_sp_trap_item_lookup(struct mlxsw_sp *mlxsw_sp, u16 id)
1220200b7ccaSIdo Schimmel {
1221200b7ccaSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1222200b7ccaSIdo Schimmel 	int i;
1223200b7ccaSIdo Schimmel 
1224200b7ccaSIdo Schimmel 	for (i = 0; i < trap->traps_count; i++) {
1225200b7ccaSIdo Schimmel 		if (trap->trap_items_arr[i].trap.id == id)
1226200b7ccaSIdo Schimmel 			return &trap->trap_items_arr[i];
1227200b7ccaSIdo Schimmel 	}
1228200b7ccaSIdo Schimmel 
1229200b7ccaSIdo Schimmel 	return NULL;
1230200b7ccaSIdo Schimmel }
1231200b7ccaSIdo Schimmel 
mlxsw_sp_trap_cpu_policers_set(struct mlxsw_sp * mlxsw_sp)12323cbc37e6SJiri Pirko static int mlxsw_sp_trap_cpu_policers_set(struct mlxsw_sp *mlxsw_sp)
12333cbc37e6SJiri Pirko {
1234b87bde80SIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
12353cbc37e6SJiri Pirko 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
1236b87bde80SIdo Schimmel 	u16 hw_id;
1237e6125230SJiri Pirko 
1238e6125230SJiri Pirko 	/* The purpose of "thin" policer is to drop as many packets
1239e6125230SJiri Pirko 	 * as possible. The dummy group is using it.
1240e6125230SJiri Pirko 	 */
1241b87bde80SIdo Schimmel 	hw_id = find_first_zero_bit(trap->policers_usage, trap->max_policers);
1242b87bde80SIdo Schimmel 	if (WARN_ON(hw_id == trap->max_policers))
1243b87bde80SIdo Schimmel 		return -ENOBUFS;
1244b87bde80SIdo Schimmel 
1245b87bde80SIdo Schimmel 	__set_bit(hw_id, trap->policers_usage);
1246b87bde80SIdo Schimmel 	trap->thin_policer_hw_id = hw_id;
1247b87bde80SIdo Schimmel 	mlxsw_reg_qpcr_pack(qpcr_pl, hw_id, MLXSW_REG_QPCR_IR_UNITS_M,
1248b87bde80SIdo Schimmel 			    false, 1, 4);
12493cbc37e6SJiri Pirko 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
12503cbc37e6SJiri Pirko }
12513cbc37e6SJiri Pirko 
mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp * mlxsw_sp)1252e6125230SJiri Pirko static int mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp *mlxsw_sp)
1253e6125230SJiri Pirko {
1254e6125230SJiri Pirko 	char htgt_pl[MLXSW_REG_HTGT_LEN];
1255e6125230SJiri Pirko 
1256e6125230SJiri Pirko 	mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SP_DUMMY,
1257b87bde80SIdo Schimmel 			    mlxsw_sp->trap->thin_policer_hw_id, 0, 1);
1258e6125230SJiri Pirko 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
1259e6125230SJiri Pirko }
1260e6125230SJiri Pirko 
mlxsw_sp_trap_policer_items_arr_init(struct mlxsw_sp * mlxsw_sp)1261cc678f4dSIdo Schimmel static int mlxsw_sp_trap_policer_items_arr_init(struct mlxsw_sp *mlxsw_sp)
12624561705bSIdo Schimmel {
126376ba292cSIdo Schimmel 	size_t arr_size = ARRAY_SIZE(mlxsw_sp_trap_policer_items_arr);
1264cc678f4dSIdo Schimmel 	size_t elem_size = sizeof(struct mlxsw_sp_trap_policer_item);
12654561705bSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
126676ba292cSIdo Schimmel 	size_t free_policers = 0;
1267cc678f4dSIdo Schimmel 	u32 last_id;
1268cc678f4dSIdo Schimmel 	int i;
12694561705bSIdo Schimmel 
12704561705bSIdo Schimmel 	for_each_clear_bit(i, trap->policers_usage, trap->max_policers)
12714561705bSIdo Schimmel 		free_policers++;
12724561705bSIdo Schimmel 
1273cc678f4dSIdo Schimmel 	if (arr_size > free_policers) {
12744561705bSIdo Schimmel 		dev_err(mlxsw_sp->bus_info->dev, "Exceeded number of supported packet trap policers\n");
12754561705bSIdo Schimmel 		return -ENOBUFS;
12764561705bSIdo Schimmel 	}
12774561705bSIdo Schimmel 
1278cc678f4dSIdo Schimmel 	trap->policer_items_arr = kcalloc(free_policers, elem_size, GFP_KERNEL);
1279cc678f4dSIdo Schimmel 	if (!trap->policer_items_arr)
12804561705bSIdo Schimmel 		return -ENOMEM;
12814561705bSIdo Schimmel 
12824561705bSIdo Schimmel 	trap->policers_count = free_policers;
12834561705bSIdo Schimmel 
1284cc678f4dSIdo Schimmel 	/* Initialize policer items array with pre-defined policers. */
1285cc678f4dSIdo Schimmel 	memcpy(trap->policer_items_arr, mlxsw_sp_trap_policer_items_arr,
1286cc678f4dSIdo Schimmel 	       elem_size * arr_size);
12874561705bSIdo Schimmel 
1288cc678f4dSIdo Schimmel 	/* Initialize policer items array with the rest of the available
1289cc678f4dSIdo Schimmel 	 * policers.
1290cc678f4dSIdo Schimmel 	 */
1291cc678f4dSIdo Schimmel 	last_id = mlxsw_sp_trap_policer_items_arr[arr_size - 1].policer.id;
1292cc678f4dSIdo Schimmel 	for (i = arr_size; i < trap->policers_count; i++) {
1293cc678f4dSIdo Schimmel 		const struct mlxsw_sp_trap_policer_item *policer_item;
1294cc678f4dSIdo Schimmel 
12954561705bSIdo Schimmel 		/* Use parameters set for first policer and override
12964561705bSIdo Schimmel 		 * relevant ones.
12974561705bSIdo Schimmel 		 */
1298cc678f4dSIdo Schimmel 		policer_item = &mlxsw_sp_trap_policer_items_arr[0];
1299cc678f4dSIdo Schimmel 		trap->policer_items_arr[i] = *policer_item;
1300cc678f4dSIdo Schimmel 		trap->policer_items_arr[i].policer.id = ++last_id;
1301cc678f4dSIdo Schimmel 		trap->policer_items_arr[i].policer.init_rate = 1;
1302cc678f4dSIdo Schimmel 		trap->policer_items_arr[i].policer.init_burst = 16;
13034561705bSIdo Schimmel 	}
13044561705bSIdo Schimmel 
1305cc678f4dSIdo Schimmel 	return 0;
1306cc678f4dSIdo Schimmel }
130713f2e64bSIdo Schimmel 
mlxsw_sp_trap_policer_items_arr_fini(struct mlxsw_sp * mlxsw_sp)1308cc678f4dSIdo Schimmel static void mlxsw_sp_trap_policer_items_arr_fini(struct mlxsw_sp *mlxsw_sp)
1309cc678f4dSIdo Schimmel {
1310cc678f4dSIdo Schimmel 	kfree(mlxsw_sp->trap->policer_items_arr);
1311cc678f4dSIdo Schimmel }
1312cc678f4dSIdo Schimmel 
mlxsw_sp_trap_policers_init(struct mlxsw_sp * mlxsw_sp)1313cc678f4dSIdo Schimmel static int mlxsw_sp_trap_policers_init(struct mlxsw_sp *mlxsw_sp)
1314cc678f4dSIdo Schimmel {
1315cc678f4dSIdo Schimmel 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1316cc678f4dSIdo Schimmel 	const struct mlxsw_sp_trap_policer_item *policer_item;
1317cc678f4dSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1318cc678f4dSIdo Schimmel 	int err, i;
1319cc678f4dSIdo Schimmel 
1320cc678f4dSIdo Schimmel 	err = mlxsw_sp_trap_policer_items_arr_init(mlxsw_sp);
132113f2e64bSIdo Schimmel 	if (err)
1322cc678f4dSIdo Schimmel 		return err;
1323cc678f4dSIdo Schimmel 
1324cc678f4dSIdo Schimmel 	for (i = 0; i < trap->policers_count; i++) {
1325cc678f4dSIdo Schimmel 		policer_item = &trap->policer_items_arr[i];
132672a4c8c9SJiri Pirko 		err = devl_trap_policers_register(devlink,
1327cc678f4dSIdo Schimmel 						  &policer_item->policer, 1);
1328cc678f4dSIdo Schimmel 		if (err)
1329cc678f4dSIdo Schimmel 			goto err_trap_policer_register;
1330cc678f4dSIdo Schimmel 	}
133113f2e64bSIdo Schimmel 
13324561705bSIdo Schimmel 	return 0;
133313f2e64bSIdo Schimmel 
1334cc678f4dSIdo Schimmel err_trap_policer_register:
1335cc678f4dSIdo Schimmel 	for (i--; i >= 0; i--) {
1336cc678f4dSIdo Schimmel 		policer_item = &trap->policer_items_arr[i];
133772a4c8c9SJiri Pirko 		devl_trap_policers_unregister(devlink,
1338cc678f4dSIdo Schimmel 					      &policer_item->policer, 1);
1339cc678f4dSIdo Schimmel 	}
1340cc678f4dSIdo Schimmel 	mlxsw_sp_trap_policer_items_arr_fini(mlxsw_sp);
134113f2e64bSIdo Schimmel 	return err;
13424561705bSIdo Schimmel }
13434561705bSIdo Schimmel 
mlxsw_sp_trap_policers_fini(struct mlxsw_sp * mlxsw_sp)13444561705bSIdo Schimmel static void mlxsw_sp_trap_policers_fini(struct mlxsw_sp *mlxsw_sp)
13454561705bSIdo Schimmel {
134613f2e64bSIdo Schimmel 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1347cc678f4dSIdo Schimmel 	const struct mlxsw_sp_trap_policer_item *policer_item;
13484561705bSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1349cc678f4dSIdo Schimmel 	int i;
13504561705bSIdo Schimmel 
1351cc678f4dSIdo Schimmel 	for (i = trap->policers_count - 1; i >= 0; i--) {
1352cc678f4dSIdo Schimmel 		policer_item = &trap->policer_items_arr[i];
135372a4c8c9SJiri Pirko 		devl_trap_policers_unregister(devlink,
1354cc678f4dSIdo Schimmel 					      &policer_item->policer, 1);
1355cc678f4dSIdo Schimmel 	}
1356cc678f4dSIdo Schimmel 	mlxsw_sp_trap_policer_items_arr_fini(mlxsw_sp);
13574561705bSIdo Schimmel }
13584561705bSIdo Schimmel 
mlxsw_sp_trap_group_items_arr_init(struct mlxsw_sp * mlxsw_sp)135936d1fd68SIdo Schimmel static int mlxsw_sp_trap_group_items_arr_init(struct mlxsw_sp *mlxsw_sp)
136036d1fd68SIdo Schimmel {
136136d1fd68SIdo Schimmel 	size_t common_groups_count = ARRAY_SIZE(mlxsw_sp_trap_group_items_arr);
136236d1fd68SIdo Schimmel 	const struct mlxsw_sp_trap_group_item *spec_group_items_arr;
136336d1fd68SIdo Schimmel 	size_t elem_size = sizeof(struct mlxsw_sp_trap_group_item);
136436d1fd68SIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
136536d1fd68SIdo Schimmel 	size_t groups_count, spec_groups_count;
136636d1fd68SIdo Schimmel 	int err;
136736d1fd68SIdo Schimmel 
136836d1fd68SIdo Schimmel 	err = mlxsw_sp->trap_ops->groups_init(mlxsw_sp, &spec_group_items_arr,
136936d1fd68SIdo Schimmel 					      &spec_groups_count);
137036d1fd68SIdo Schimmel 	if (err)
137136d1fd68SIdo Schimmel 		return err;
137236d1fd68SIdo Schimmel 
137336d1fd68SIdo Schimmel 	/* The group items array is created by concatenating the common trap
137436d1fd68SIdo Schimmel 	 * group items and the ASIC-specific trap group items.
137536d1fd68SIdo Schimmel 	 */
137636d1fd68SIdo Schimmel 	groups_count = common_groups_count + spec_groups_count;
137736d1fd68SIdo Schimmel 	trap->group_items_arr = kcalloc(groups_count, elem_size, GFP_KERNEL);
137836d1fd68SIdo Schimmel 	if (!trap->group_items_arr)
137936d1fd68SIdo Schimmel 		return -ENOMEM;
138036d1fd68SIdo Schimmel 
138136d1fd68SIdo Schimmel 	memcpy(trap->group_items_arr, mlxsw_sp_trap_group_items_arr,
138236d1fd68SIdo Schimmel 	       elem_size * common_groups_count);
138336d1fd68SIdo Schimmel 	memcpy(trap->group_items_arr + common_groups_count,
138436d1fd68SIdo Schimmel 	       spec_group_items_arr, elem_size * spec_groups_count);
138536d1fd68SIdo Schimmel 
138636d1fd68SIdo Schimmel 	trap->groups_count = groups_count;
138736d1fd68SIdo Schimmel 
138836d1fd68SIdo Schimmel 	return 0;
138936d1fd68SIdo Schimmel }
139036d1fd68SIdo Schimmel 
mlxsw_sp_trap_group_items_arr_fini(struct mlxsw_sp * mlxsw_sp)139136d1fd68SIdo Schimmel static void mlxsw_sp_trap_group_items_arr_fini(struct mlxsw_sp *mlxsw_sp)
139236d1fd68SIdo Schimmel {
139336d1fd68SIdo Schimmel 	kfree(mlxsw_sp->trap->group_items_arr);
139436d1fd68SIdo Schimmel }
139536d1fd68SIdo Schimmel 
mlxsw_sp_trap_groups_init(struct mlxsw_sp * mlxsw_sp)1396b14a40dbSIdo Schimmel static int mlxsw_sp_trap_groups_init(struct mlxsw_sp *mlxsw_sp)
1397b14a40dbSIdo Schimmel {
1398b14a40dbSIdo Schimmel 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1399b14a40dbSIdo Schimmel 	const struct mlxsw_sp_trap_group_item *group_item;
1400b14a40dbSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1401b14a40dbSIdo Schimmel 	int err, i;
1402b14a40dbSIdo Schimmel 
140336d1fd68SIdo Schimmel 	err = mlxsw_sp_trap_group_items_arr_init(mlxsw_sp);
140436d1fd68SIdo Schimmel 	if (err)
140536d1fd68SIdo Schimmel 		return err;
1406b14a40dbSIdo Schimmel 
1407b14a40dbSIdo Schimmel 	for (i = 0; i < trap->groups_count; i++) {
1408b14a40dbSIdo Schimmel 		group_item = &trap->group_items_arr[i];
140972a4c8c9SJiri Pirko 		err = devl_trap_groups_register(devlink, &group_item->group, 1);
1410b14a40dbSIdo Schimmel 		if (err)
1411b14a40dbSIdo Schimmel 			goto err_trap_group_register;
1412b14a40dbSIdo Schimmel 	}
1413b14a40dbSIdo Schimmel 
1414b14a40dbSIdo Schimmel 	return 0;
1415b14a40dbSIdo Schimmel 
1416b14a40dbSIdo Schimmel err_trap_group_register:
1417b14a40dbSIdo Schimmel 	for (i--; i >= 0; i--) {
1418b14a40dbSIdo Schimmel 		group_item = &trap->group_items_arr[i];
141972a4c8c9SJiri Pirko 		devl_trap_groups_unregister(devlink, &group_item->group, 1);
1420b14a40dbSIdo Schimmel 	}
142136d1fd68SIdo Schimmel 	mlxsw_sp_trap_group_items_arr_fini(mlxsw_sp);
1422b14a40dbSIdo Schimmel 	return err;
1423b14a40dbSIdo Schimmel }
1424b14a40dbSIdo Schimmel 
mlxsw_sp_trap_groups_fini(struct mlxsw_sp * mlxsw_sp)1425b14a40dbSIdo Schimmel static void mlxsw_sp_trap_groups_fini(struct mlxsw_sp *mlxsw_sp)
1426b14a40dbSIdo Schimmel {
1427b14a40dbSIdo Schimmel 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1428b14a40dbSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1429b14a40dbSIdo Schimmel 	int i;
1430b14a40dbSIdo Schimmel 
1431b14a40dbSIdo Schimmel 	for (i = trap->groups_count - 1; i >= 0; i--) {
1432b14a40dbSIdo Schimmel 		const struct mlxsw_sp_trap_group_item *group_item;
1433b14a40dbSIdo Schimmel 
1434b14a40dbSIdo Schimmel 		group_item = &trap->group_items_arr[i];
143572a4c8c9SJiri Pirko 		devl_trap_groups_unregister(devlink, &group_item->group, 1);
1436b14a40dbSIdo Schimmel 	}
143736d1fd68SIdo Schimmel 	mlxsw_sp_trap_group_items_arr_fini(mlxsw_sp);
1438b14a40dbSIdo Schimmel }
1439b14a40dbSIdo Schimmel 
1440200b7ccaSIdo Schimmel static bool
mlxsw_sp_trap_listener_is_valid(const struct mlxsw_listener * listener)1441200b7ccaSIdo Schimmel mlxsw_sp_trap_listener_is_valid(const struct mlxsw_listener *listener)
1442200b7ccaSIdo Schimmel {
1443200b7ccaSIdo Schimmel 	return listener->trap_id != 0;
1444200b7ccaSIdo Schimmel }
1445200b7ccaSIdo Schimmel 
mlxsw_sp_trap_items_arr_init(struct mlxsw_sp * mlxsw_sp)1446869c7be9SIdo Schimmel static int mlxsw_sp_trap_items_arr_init(struct mlxsw_sp *mlxsw_sp)
1447869c7be9SIdo Schimmel {
1448869c7be9SIdo Schimmel 	size_t common_traps_count = ARRAY_SIZE(mlxsw_sp_trap_items_arr);
1449869c7be9SIdo Schimmel 	const struct mlxsw_sp_trap_item *spec_trap_items_arr;
1450869c7be9SIdo Schimmel 	size_t elem_size = sizeof(struct mlxsw_sp_trap_item);
1451869c7be9SIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1452869c7be9SIdo Schimmel 	size_t traps_count, spec_traps_count;
1453869c7be9SIdo Schimmel 	int err;
1454869c7be9SIdo Schimmel 
1455869c7be9SIdo Schimmel 	err = mlxsw_sp->trap_ops->traps_init(mlxsw_sp, &spec_trap_items_arr,
1456869c7be9SIdo Schimmel 					     &spec_traps_count);
1457869c7be9SIdo Schimmel 	if (err)
1458869c7be9SIdo Schimmel 		return err;
1459869c7be9SIdo Schimmel 
1460869c7be9SIdo Schimmel 	/* The trap items array is created by concatenating the common trap
1461869c7be9SIdo Schimmel 	 * items and the ASIC-specific trap items.
1462869c7be9SIdo Schimmel 	 */
1463869c7be9SIdo Schimmel 	traps_count = common_traps_count + spec_traps_count;
1464869c7be9SIdo Schimmel 	trap->trap_items_arr = kcalloc(traps_count, elem_size, GFP_KERNEL);
1465869c7be9SIdo Schimmel 	if (!trap->trap_items_arr)
1466869c7be9SIdo Schimmel 		return -ENOMEM;
1467869c7be9SIdo Schimmel 
1468869c7be9SIdo Schimmel 	memcpy(trap->trap_items_arr, mlxsw_sp_trap_items_arr,
1469869c7be9SIdo Schimmel 	       elem_size * common_traps_count);
1470869c7be9SIdo Schimmel 	memcpy(trap->trap_items_arr + common_traps_count,
1471869c7be9SIdo Schimmel 	       spec_trap_items_arr, elem_size * spec_traps_count);
1472869c7be9SIdo Schimmel 
1473869c7be9SIdo Schimmel 	trap->traps_count = traps_count;
1474869c7be9SIdo Schimmel 
1475869c7be9SIdo Schimmel 	return 0;
1476869c7be9SIdo Schimmel }
1477869c7be9SIdo Schimmel 
mlxsw_sp_trap_items_arr_fini(struct mlxsw_sp * mlxsw_sp)1478869c7be9SIdo Schimmel static void mlxsw_sp_trap_items_arr_fini(struct mlxsw_sp *mlxsw_sp)
1479869c7be9SIdo Schimmel {
1480869c7be9SIdo Schimmel 	kfree(mlxsw_sp->trap->trap_items_arr);
1481869c7be9SIdo Schimmel }
1482869c7be9SIdo Schimmel 
mlxsw_sp_traps_init(struct mlxsw_sp * mlxsw_sp)1483200b7ccaSIdo Schimmel static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
1484b5ce611fSIdo Schimmel {
1485b5ce611fSIdo Schimmel 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1486200b7ccaSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1487200b7ccaSIdo Schimmel 	const struct mlxsw_sp_trap_item *trap_item;
1488200b7ccaSIdo Schimmel 	int err, i;
1489200b7ccaSIdo Schimmel 
1490869c7be9SIdo Schimmel 	err = mlxsw_sp_trap_items_arr_init(mlxsw_sp);
1491869c7be9SIdo Schimmel 	if (err)
1492869c7be9SIdo Schimmel 		return err;
1493200b7ccaSIdo Schimmel 
1494200b7ccaSIdo Schimmel 	for (i = 0; i < trap->traps_count; i++) {
1495200b7ccaSIdo Schimmel 		trap_item = &trap->trap_items_arr[i];
149672a4c8c9SJiri Pirko 		err = devl_traps_register(devlink, &trap_item->trap, 1,
1497200b7ccaSIdo Schimmel 					  mlxsw_sp);
1498200b7ccaSIdo Schimmel 		if (err)
1499200b7ccaSIdo Schimmel 			goto err_trap_register;
1500200b7ccaSIdo Schimmel 	}
1501200b7ccaSIdo Schimmel 
1502200b7ccaSIdo Schimmel 	return 0;
1503200b7ccaSIdo Schimmel 
1504200b7ccaSIdo Schimmel err_trap_register:
1505200b7ccaSIdo Schimmel 	for (i--; i >= 0; i--) {
1506200b7ccaSIdo Schimmel 		trap_item = &trap->trap_items_arr[i];
150772a4c8c9SJiri Pirko 		devl_traps_unregister(devlink, &trap_item->trap, 1);
1508200b7ccaSIdo Schimmel 	}
1509869c7be9SIdo Schimmel 	mlxsw_sp_trap_items_arr_fini(mlxsw_sp);
1510200b7ccaSIdo Schimmel 	return err;
1511200b7ccaSIdo Schimmel }
1512200b7ccaSIdo Schimmel 
mlxsw_sp_traps_fini(struct mlxsw_sp * mlxsw_sp)1513200b7ccaSIdo Schimmel static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
1514200b7ccaSIdo Schimmel {
1515200b7ccaSIdo Schimmel 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1516200b7ccaSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1517200b7ccaSIdo Schimmel 	int i;
1518200b7ccaSIdo Schimmel 
1519200b7ccaSIdo Schimmel 	for (i = trap->traps_count - 1; i >= 0; i--) {
1520200b7ccaSIdo Schimmel 		const struct mlxsw_sp_trap_item *trap_item;
1521200b7ccaSIdo Schimmel 
1522200b7ccaSIdo Schimmel 		trap_item = &trap->trap_items_arr[i];
152372a4c8c9SJiri Pirko 		devl_traps_unregister(devlink, &trap_item->trap, 1);
1524200b7ccaSIdo Schimmel 	}
1525869c7be9SIdo Schimmel 	mlxsw_sp_trap_items_arr_fini(mlxsw_sp);
1526200b7ccaSIdo Schimmel }
1527200b7ccaSIdo Schimmel 
mlxsw_sp_devlink_traps_init(struct mlxsw_sp * mlxsw_sp)1528200b7ccaSIdo Schimmel int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
1529200b7ccaSIdo Schimmel {
15303cbc37e6SJiri Pirko 	int err;
15313cbc37e6SJiri Pirko 
15323cbc37e6SJiri Pirko 	err = mlxsw_sp_trap_cpu_policers_set(mlxsw_sp);
15333cbc37e6SJiri Pirko 	if (err)
15343cbc37e6SJiri Pirko 		return err;
1535b5ce611fSIdo Schimmel 
1536e6125230SJiri Pirko 	err = mlxsw_sp_trap_dummy_group_init(mlxsw_sp);
1537e6125230SJiri Pirko 	if (err)
1538e6125230SJiri Pirko 		return err;
1539e6125230SJiri Pirko 
15404561705bSIdo Schimmel 	err = mlxsw_sp_trap_policers_init(mlxsw_sp);
15414561705bSIdo Schimmel 	if (err)
15424561705bSIdo Schimmel 		return err;
15434561705bSIdo Schimmel 
1544b14a40dbSIdo Schimmel 	err = mlxsw_sp_trap_groups_init(mlxsw_sp);
15458cd999e4SIdo Schimmel 	if (err)
1546b14a40dbSIdo Schimmel 		goto err_trap_groups_init;
15478cd999e4SIdo Schimmel 
1548200b7ccaSIdo Schimmel 	err = mlxsw_sp_traps_init(mlxsw_sp);
15498cd999e4SIdo Schimmel 	if (err)
1550200b7ccaSIdo Schimmel 		goto err_traps_init;
15518cd999e4SIdo Schimmel 
15528cd999e4SIdo Schimmel 	return 0;
15538cd999e4SIdo Schimmel 
1554200b7ccaSIdo Schimmel err_traps_init:
1555b14a40dbSIdo Schimmel 	mlxsw_sp_trap_groups_fini(mlxsw_sp);
1556b14a40dbSIdo Schimmel err_trap_groups_init:
15574561705bSIdo Schimmel 	mlxsw_sp_trap_policers_fini(mlxsw_sp);
15588cd999e4SIdo Schimmel 	return err;
1559b5ce611fSIdo Schimmel }
1560b5ce611fSIdo Schimmel 
mlxsw_sp_devlink_traps_fini(struct mlxsw_sp * mlxsw_sp)1561b5ce611fSIdo Schimmel void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp)
1562b5ce611fSIdo Schimmel {
1563200b7ccaSIdo Schimmel 	mlxsw_sp_traps_fini(mlxsw_sp);
1564b14a40dbSIdo Schimmel 	mlxsw_sp_trap_groups_fini(mlxsw_sp);
15654561705bSIdo Schimmel 	mlxsw_sp_trap_policers_fini(mlxsw_sp);
1566b5ce611fSIdo Schimmel }
1567b5ce611fSIdo Schimmel 
mlxsw_sp_trap_init(struct mlxsw_core * mlxsw_core,const struct devlink_trap * trap,void * trap_ctx)1568b5ce611fSIdo Schimmel int mlxsw_sp_trap_init(struct mlxsw_core *mlxsw_core,
1569b5ce611fSIdo Schimmel 		       const struct devlink_trap *trap, void *trap_ctx)
1570b5ce611fSIdo Schimmel {
1571200b7ccaSIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1572200b7ccaSIdo Schimmel 	const struct mlxsw_sp_trap_item *trap_item;
1573b5ce611fSIdo Schimmel 	int i;
1574b5ce611fSIdo Schimmel 
1575200b7ccaSIdo Schimmel 	trap_item = mlxsw_sp_trap_item_lookup(mlxsw_sp, trap->id);
1576200b7ccaSIdo Schimmel 	if (WARN_ON(!trap_item))
1577200b7ccaSIdo Schimmel 		return -EINVAL;
1578200b7ccaSIdo Schimmel 
1579200b7ccaSIdo Schimmel 	for (i = 0; i < MLXSW_SP_TRAP_LISTENERS_MAX; i++) {
158016adc56cSJiri Pirko 		const struct mlxsw_listener *listener;
1581b5ce611fSIdo Schimmel 		int err;
1582b5ce611fSIdo Schimmel 
1583200b7ccaSIdo Schimmel 		listener = &trap_item->listeners_arr[i];
1584200b7ccaSIdo Schimmel 		if (!mlxsw_sp_trap_listener_is_valid(listener))
1585b5ce611fSIdo Schimmel 			continue;
1586b5ce611fSIdo Schimmel 		err = mlxsw_core_trap_register(mlxsw_core, listener, trap_ctx);
1587b5ce611fSIdo Schimmel 		if (err)
1588b5ce611fSIdo Schimmel 			return err;
1589b5ce611fSIdo Schimmel 	}
1590b5ce611fSIdo Schimmel 
1591b5ce611fSIdo Schimmel 	return 0;
1592b5ce611fSIdo Schimmel }
1593b5ce611fSIdo Schimmel 
mlxsw_sp_trap_fini(struct mlxsw_core * mlxsw_core,const struct devlink_trap * trap,void * trap_ctx)1594b5ce611fSIdo Schimmel void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core,
1595b5ce611fSIdo Schimmel 			const struct devlink_trap *trap, void *trap_ctx)
1596b5ce611fSIdo Schimmel {
1597200b7ccaSIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1598200b7ccaSIdo Schimmel 	const struct mlxsw_sp_trap_item *trap_item;
1599b5ce611fSIdo Schimmel 	int i;
1600b5ce611fSIdo Schimmel 
1601200b7ccaSIdo Schimmel 	trap_item = mlxsw_sp_trap_item_lookup(mlxsw_sp, trap->id);
1602200b7ccaSIdo Schimmel 	if (WARN_ON(!trap_item))
1603200b7ccaSIdo Schimmel 		return;
1604200b7ccaSIdo Schimmel 
1605200b7ccaSIdo Schimmel 	for (i = MLXSW_SP_TRAP_LISTENERS_MAX - 1; i >= 0; i--) {
160616adc56cSJiri Pirko 		const struct mlxsw_listener *listener;
1607b5ce611fSIdo Schimmel 
1608200b7ccaSIdo Schimmel 		listener = &trap_item->listeners_arr[i];
1609200b7ccaSIdo Schimmel 		if (!mlxsw_sp_trap_listener_is_valid(listener))
1610b5ce611fSIdo Schimmel 			continue;
1611b5ce611fSIdo Schimmel 		mlxsw_core_trap_unregister(mlxsw_core, listener, trap_ctx);
1612b5ce611fSIdo Schimmel 	}
1613b5ce611fSIdo Schimmel }
1614b5ce611fSIdo Schimmel 
mlxsw_sp_trap_action_set(struct mlxsw_core * mlxsw_core,const struct devlink_trap * trap,enum devlink_trap_action action,struct netlink_ext_ack * extack)1615b5ce611fSIdo Schimmel int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
1616b5ce611fSIdo Schimmel 			     const struct devlink_trap *trap,
1617c88e11e0SIdo Schimmel 			     enum devlink_trap_action action,
1618c88e11e0SIdo Schimmel 			     struct netlink_ext_ack *extack)
1619b5ce611fSIdo Schimmel {
1620200b7ccaSIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1621200b7ccaSIdo Schimmel 	const struct mlxsw_sp_trap_item *trap_item;
1622b5ce611fSIdo Schimmel 	int i;
1623b5ce611fSIdo Schimmel 
1624200b7ccaSIdo Schimmel 	trap_item = mlxsw_sp_trap_item_lookup(mlxsw_sp, trap->id);
1625200b7ccaSIdo Schimmel 	if (WARN_ON(!trap_item))
1626200b7ccaSIdo Schimmel 		return -EINVAL;
1627200b7ccaSIdo Schimmel 
16286687e953SIdo Schimmel 	if (trap_item->is_source) {
16296687e953SIdo Schimmel 		NL_SET_ERR_MSG_MOD(extack, "Changing the action of source traps is not supported");
16306687e953SIdo Schimmel 		return -EOPNOTSUPP;
16316687e953SIdo Schimmel 	}
16326687e953SIdo Schimmel 
1633200b7ccaSIdo Schimmel 	for (i = 0; i < MLXSW_SP_TRAP_LISTENERS_MAX; i++) {
163416adc56cSJiri Pirko 		const struct mlxsw_listener *listener;
16354a23d45aSJiri Pirko 		bool enabled;
1636b5ce611fSIdo Schimmel 		int err;
1637b5ce611fSIdo Schimmel 
1638200b7ccaSIdo Schimmel 		listener = &trap_item->listeners_arr[i];
1639200b7ccaSIdo Schimmel 		if (!mlxsw_sp_trap_listener_is_valid(listener))
1640b5ce611fSIdo Schimmel 			continue;
1641200b7ccaSIdo Schimmel 
1642b5ce611fSIdo Schimmel 		switch (action) {
1643b5ce611fSIdo Schimmel 		case DEVLINK_TRAP_ACTION_DROP:
16444a23d45aSJiri Pirko 			enabled = false;
1645b5ce611fSIdo Schimmel 			break;
1646b5ce611fSIdo Schimmel 		case DEVLINK_TRAP_ACTION_TRAP:
16474a23d45aSJiri Pirko 			enabled = true;
1648b5ce611fSIdo Schimmel 			break;
1649b5ce611fSIdo Schimmel 		default:
1650b5ce611fSIdo Schimmel 			return -EINVAL;
1651b5ce611fSIdo Schimmel 		}
16524a23d45aSJiri Pirko 		err = mlxsw_core_trap_state_set(mlxsw_core, listener, enabled);
1653b5ce611fSIdo Schimmel 		if (err)
1654b5ce611fSIdo Schimmel 			return err;
1655b5ce611fSIdo Schimmel 	}
1656b5ce611fSIdo Schimmel 
1657b5ce611fSIdo Schimmel 	return 0;
1658b5ce611fSIdo Schimmel }
1659b5ce611fSIdo Schimmel 
166039defcbbSIdo Schimmel static int
__mlxsw_sp_trap_group_init(struct mlxsw_core * mlxsw_core,const struct devlink_trap_group * group,u32 policer_id,struct netlink_ext_ack * extack)166139defcbbSIdo Schimmel __mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
166239defcbbSIdo Schimmel 			   const struct devlink_trap_group *group,
1663c88e11e0SIdo Schimmel 			   u32 policer_id, struct netlink_ext_ack *extack)
1664b5ce611fSIdo Schimmel {
166513f2e64bSIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
166613f2e64bSIdo Schimmel 	u16 hw_policer_id = MLXSW_REG_HTGT_INVALID_POLICER;
1667b14a40dbSIdo Schimmel 	const struct mlxsw_sp_trap_group_item *group_item;
1668b5ce611fSIdo Schimmel 	char htgt_pl[MLXSW_REG_HTGT_LEN];
1669b5ce611fSIdo Schimmel 
1670b14a40dbSIdo Schimmel 	group_item = mlxsw_sp_trap_group_item_lookup(mlxsw_sp, group->id);
1671b14a40dbSIdo Schimmel 	if (WARN_ON(!group_item))
1672b5ce611fSIdo Schimmel 		return -EINVAL;
1673b5ce611fSIdo Schimmel 
16746687e953SIdo Schimmel 	if (group_item->fixed_policer && policer_id != group->init_policer_id) {
16756687e953SIdo Schimmel 		NL_SET_ERR_MSG_MOD(extack, "Changing the policer binding of this group is not supported");
16766687e953SIdo Schimmel 		return -EOPNOTSUPP;
16776687e953SIdo Schimmel 	}
16786687e953SIdo Schimmel 
167939defcbbSIdo Schimmel 	if (policer_id) {
168013f2e64bSIdo Schimmel 		struct mlxsw_sp_trap_policer_item *policer_item;
168113f2e64bSIdo Schimmel 
168239defcbbSIdo Schimmel 		policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp,
168339defcbbSIdo Schimmel 								 policer_id);
168413f2e64bSIdo Schimmel 		if (WARN_ON(!policer_item))
168513f2e64bSIdo Schimmel 			return -EINVAL;
168613f2e64bSIdo Schimmel 		hw_policer_id = policer_item->hw_id;
168713f2e64bSIdo Schimmel 	}
168813f2e64bSIdo Schimmel 
1689b14a40dbSIdo Schimmel 	mlxsw_reg_htgt_pack(htgt_pl, group_item->hw_group_id, hw_policer_id,
1690d88f8cc1SIdo Schimmel 			    group_item->priority, group_item->priority);
16913cbc37e6SJiri Pirko 	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
1692b5ce611fSIdo Schimmel }
169313f2e64bSIdo Schimmel 
mlxsw_sp_trap_group_init(struct mlxsw_core * mlxsw_core,const struct devlink_trap_group * group)169439defcbbSIdo Schimmel int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
169539defcbbSIdo Schimmel 			     const struct devlink_trap_group *group)
169639defcbbSIdo Schimmel {
169739defcbbSIdo Schimmel 	return __mlxsw_sp_trap_group_init(mlxsw_core, group,
1698c88e11e0SIdo Schimmel 					  group->init_policer_id, NULL);
169939defcbbSIdo Schimmel }
170039defcbbSIdo Schimmel 
mlxsw_sp_trap_group_set(struct mlxsw_core * mlxsw_core,const struct devlink_trap_group * group,const struct devlink_trap_policer * policer,struct netlink_ext_ack * extack)170139defcbbSIdo Schimmel int mlxsw_sp_trap_group_set(struct mlxsw_core *mlxsw_core,
170239defcbbSIdo Schimmel 			    const struct devlink_trap_group *group,
1703c88e11e0SIdo Schimmel 			    const struct devlink_trap_policer *policer,
1704c88e11e0SIdo Schimmel 			    struct netlink_ext_ack *extack)
170539defcbbSIdo Schimmel {
170639defcbbSIdo Schimmel 	u32 policer_id = policer ? policer->id : 0;
170739defcbbSIdo Schimmel 
1708c88e11e0SIdo Schimmel 	return __mlxsw_sp_trap_group_init(mlxsw_core, group, policer_id,
1709c88e11e0SIdo Schimmel 					  extack);
171039defcbbSIdo Schimmel }
171139defcbbSIdo Schimmel 
1712cc678f4dSIdo Schimmel static int
mlxsw_sp_trap_policer_item_init(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_trap_policer_item * policer_item)1713cc678f4dSIdo Schimmel mlxsw_sp_trap_policer_item_init(struct mlxsw_sp *mlxsw_sp,
1714cc678f4dSIdo Schimmel 				struct mlxsw_sp_trap_policer_item *policer_item)
171513f2e64bSIdo Schimmel {
171613f2e64bSIdo Schimmel 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
171713f2e64bSIdo Schimmel 	u16 hw_id;
171813f2e64bSIdo Schimmel 
171913f2e64bSIdo Schimmel 	/* We should be able to allocate a policer because the number of
172013f2e64bSIdo Schimmel 	 * policers we registered with devlink is in according with the number
172113f2e64bSIdo Schimmel 	 * of available policers.
172213f2e64bSIdo Schimmel 	 */
172313f2e64bSIdo Schimmel 	hw_id = find_first_zero_bit(trap->policers_usage, trap->max_policers);
172413f2e64bSIdo Schimmel 	if (WARN_ON(hw_id == trap->max_policers))
1725cc678f4dSIdo Schimmel 		return -ENOBUFS;
172613f2e64bSIdo Schimmel 
172713f2e64bSIdo Schimmel 	__set_bit(hw_id, trap->policers_usage);
172813f2e64bSIdo Schimmel 	policer_item->hw_id = hw_id;
172913f2e64bSIdo Schimmel 
1730cc678f4dSIdo Schimmel 	return 0;
173113f2e64bSIdo Schimmel }
173213f2e64bSIdo Schimmel 
173313f2e64bSIdo Schimmel static void
mlxsw_sp_trap_policer_item_fini(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_trap_policer_item * policer_item)173413f2e64bSIdo Schimmel mlxsw_sp_trap_policer_item_fini(struct mlxsw_sp *mlxsw_sp,
173513f2e64bSIdo Schimmel 				struct mlxsw_sp_trap_policer_item *policer_item)
173613f2e64bSIdo Schimmel {
173713f2e64bSIdo Schimmel 	__clear_bit(policer_item->hw_id, mlxsw_sp->trap->policers_usage);
173813f2e64bSIdo Schimmel }
173913f2e64bSIdo Schimmel 
mlxsw_sp_trap_policer_bs(u64 burst,u8 * p_burst_size,struct netlink_ext_ack * extack)174013f2e64bSIdo Schimmel static int mlxsw_sp_trap_policer_bs(u64 burst, u8 *p_burst_size,
174113f2e64bSIdo Schimmel 				    struct netlink_ext_ack *extack)
174213f2e64bSIdo Schimmel {
174313f2e64bSIdo Schimmel 	int bs = fls64(burst) - 1;
174413f2e64bSIdo Schimmel 
1745468c2a10SColin Ian King 	if (burst != (BIT_ULL(bs))) {
174613f2e64bSIdo Schimmel 		NL_SET_ERR_MSG_MOD(extack, "Policer burst size is not power of two");
174713f2e64bSIdo Schimmel 		return -EINVAL;
174813f2e64bSIdo Schimmel 	}
174913f2e64bSIdo Schimmel 
175013f2e64bSIdo Schimmel 	*p_burst_size = bs;
175113f2e64bSIdo Schimmel 
175213f2e64bSIdo Schimmel 	return 0;
175313f2e64bSIdo Schimmel }
175413f2e64bSIdo Schimmel 
__mlxsw_sp_trap_policer_set(struct mlxsw_sp * mlxsw_sp,u16 hw_id,u64 rate,u64 burst,bool clear_counter,struct netlink_ext_ack * extack)175513f2e64bSIdo Schimmel static int __mlxsw_sp_trap_policer_set(struct mlxsw_sp *mlxsw_sp, u16 hw_id,
175613f2e64bSIdo Schimmel 				       u64 rate, u64 burst, bool clear_counter,
175713f2e64bSIdo Schimmel 				       struct netlink_ext_ack *extack)
175813f2e64bSIdo Schimmel {
175913f2e64bSIdo Schimmel 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
176013f2e64bSIdo Schimmel 	u8 burst_size;
176113f2e64bSIdo Schimmel 	int err;
176213f2e64bSIdo Schimmel 
176313f2e64bSIdo Schimmel 	err = mlxsw_sp_trap_policer_bs(burst, &burst_size, extack);
176413f2e64bSIdo Schimmel 	if (err)
176513f2e64bSIdo Schimmel 		return err;
176613f2e64bSIdo Schimmel 
176713f2e64bSIdo Schimmel 	mlxsw_reg_qpcr_pack(qpcr_pl, hw_id, MLXSW_REG_QPCR_IR_UNITS_M, false,
176813f2e64bSIdo Schimmel 			    rate, burst_size);
176913f2e64bSIdo Schimmel 	mlxsw_reg_qpcr_clear_counter_set(qpcr_pl, clear_counter);
177013f2e64bSIdo Schimmel 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
177113f2e64bSIdo Schimmel }
177213f2e64bSIdo Schimmel 
mlxsw_sp_trap_policer_init(struct mlxsw_core * mlxsw_core,const struct devlink_trap_policer * policer)177313f2e64bSIdo Schimmel int mlxsw_sp_trap_policer_init(struct mlxsw_core *mlxsw_core,
177413f2e64bSIdo Schimmel 			       const struct devlink_trap_policer *policer)
177513f2e64bSIdo Schimmel {
177613f2e64bSIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
177713f2e64bSIdo Schimmel 	struct mlxsw_sp_trap_policer_item *policer_item;
177813f2e64bSIdo Schimmel 	int err;
177913f2e64bSIdo Schimmel 
1780cc678f4dSIdo Schimmel 	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
1781cc678f4dSIdo Schimmel 	if (WARN_ON(!policer_item))
1782cc678f4dSIdo Schimmel 		return -EINVAL;
1783cc678f4dSIdo Schimmel 
1784cc678f4dSIdo Schimmel 	err = mlxsw_sp_trap_policer_item_init(mlxsw_sp, policer_item);
1785cc678f4dSIdo Schimmel 	if (err)
1786cc678f4dSIdo Schimmel 		return err;
178713f2e64bSIdo Schimmel 
178813f2e64bSIdo Schimmel 	err = __mlxsw_sp_trap_policer_set(mlxsw_sp, policer_item->hw_id,
178913f2e64bSIdo Schimmel 					  policer->init_rate,
179013f2e64bSIdo Schimmel 					  policer->init_burst, true, NULL);
179113f2e64bSIdo Schimmel 	if (err)
179213f2e64bSIdo Schimmel 		goto err_trap_policer_set;
179313f2e64bSIdo Schimmel 
179413f2e64bSIdo Schimmel 	return 0;
179513f2e64bSIdo Schimmel 
179613f2e64bSIdo Schimmel err_trap_policer_set:
179713f2e64bSIdo Schimmel 	mlxsw_sp_trap_policer_item_fini(mlxsw_sp, policer_item);
179813f2e64bSIdo Schimmel 	return err;
179913f2e64bSIdo Schimmel }
180013f2e64bSIdo Schimmel 
mlxsw_sp_trap_policer_fini(struct mlxsw_core * mlxsw_core,const struct devlink_trap_policer * policer)180113f2e64bSIdo Schimmel void mlxsw_sp_trap_policer_fini(struct mlxsw_core *mlxsw_core,
180213f2e64bSIdo Schimmel 				const struct devlink_trap_policer *policer)
180313f2e64bSIdo Schimmel {
180413f2e64bSIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
180513f2e64bSIdo Schimmel 	struct mlxsw_sp_trap_policer_item *policer_item;
180613f2e64bSIdo Schimmel 
180713f2e64bSIdo Schimmel 	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
180813f2e64bSIdo Schimmel 	if (WARN_ON(!policer_item))
180913f2e64bSIdo Schimmel 		return;
181013f2e64bSIdo Schimmel 
181113f2e64bSIdo Schimmel 	mlxsw_sp_trap_policer_item_fini(mlxsw_sp, policer_item);
181213f2e64bSIdo Schimmel }
181313f2e64bSIdo Schimmel 
mlxsw_sp_trap_policer_set(struct mlxsw_core * mlxsw_core,const struct devlink_trap_policer * policer,u64 rate,u64 burst,struct netlink_ext_ack * extack)181413f2e64bSIdo Schimmel int mlxsw_sp_trap_policer_set(struct mlxsw_core *mlxsw_core,
181513f2e64bSIdo Schimmel 			      const struct devlink_trap_policer *policer,
181613f2e64bSIdo Schimmel 			      u64 rate, u64 burst,
181713f2e64bSIdo Schimmel 			      struct netlink_ext_ack *extack)
181813f2e64bSIdo Schimmel {
181913f2e64bSIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
182013f2e64bSIdo Schimmel 	struct mlxsw_sp_trap_policer_item *policer_item;
182113f2e64bSIdo Schimmel 
182213f2e64bSIdo Schimmel 	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
182313f2e64bSIdo Schimmel 	if (WARN_ON(!policer_item))
182413f2e64bSIdo Schimmel 		return -EINVAL;
182513f2e64bSIdo Schimmel 
182613f2e64bSIdo Schimmel 	return __mlxsw_sp_trap_policer_set(mlxsw_sp, policer_item->hw_id,
182713f2e64bSIdo Schimmel 					   rate, burst, false, extack);
182813f2e64bSIdo Schimmel }
182913f2e64bSIdo Schimmel 
183013f2e64bSIdo Schimmel int
mlxsw_sp_trap_policer_counter_get(struct mlxsw_core * mlxsw_core,const struct devlink_trap_policer * policer,u64 * p_drops)183113f2e64bSIdo Schimmel mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core,
183213f2e64bSIdo Schimmel 				  const struct devlink_trap_policer *policer,
183313f2e64bSIdo Schimmel 				  u64 *p_drops)
183413f2e64bSIdo Schimmel {
183513f2e64bSIdo Schimmel 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
183613f2e64bSIdo Schimmel 	struct mlxsw_sp_trap_policer_item *policer_item;
183713f2e64bSIdo Schimmel 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
183813f2e64bSIdo Schimmel 	int err;
183913f2e64bSIdo Schimmel 
184013f2e64bSIdo Schimmel 	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
184113f2e64bSIdo Schimmel 	if (WARN_ON(!policer_item))
184213f2e64bSIdo Schimmel 		return -EINVAL;
184313f2e64bSIdo Schimmel 
184413f2e64bSIdo Schimmel 	mlxsw_reg_qpcr_pack(qpcr_pl, policer_item->hw_id,
184513f2e64bSIdo Schimmel 			    MLXSW_REG_QPCR_IR_UNITS_M, false, 0, 0);
184613f2e64bSIdo Schimmel 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
184713f2e64bSIdo Schimmel 	if (err)
184813f2e64bSIdo Schimmel 		return err;
184913f2e64bSIdo Schimmel 
185013f2e64bSIdo Schimmel 	*p_drops = mlxsw_reg_qpcr_violate_count_get(qpcr_pl);
185113f2e64bSIdo Schimmel 
185213f2e64bSIdo Schimmel 	return 0;
185313f2e64bSIdo Schimmel }
185436d1fd68SIdo Schimmel 
mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp * mlxsw_sp,u16 id,bool * p_enabled,u16 * p_hw_id)185554a92385SPetr Machata int mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp *mlxsw_sp, u16 id,
185654a92385SPetr Machata 					  bool *p_enabled, u16 *p_hw_id)
185754a92385SPetr Machata {
185854a92385SPetr Machata 	struct mlxsw_sp_trap_policer_item *pol_item;
185954a92385SPetr Machata 	struct mlxsw_sp_trap_group_item *gr_item;
186054a92385SPetr Machata 	u32 pol_id;
186154a92385SPetr Machata 
186254a92385SPetr Machata 	gr_item = mlxsw_sp_trap_group_item_lookup(mlxsw_sp, id);
186354a92385SPetr Machata 	if (!gr_item)
186454a92385SPetr Machata 		return -ENOENT;
186554a92385SPetr Machata 
186654a92385SPetr Machata 	pol_id = gr_item->group.init_policer_id;
186754a92385SPetr Machata 	if (!pol_id) {
186854a92385SPetr Machata 		*p_enabled = false;
186954a92385SPetr Machata 		return 0;
187054a92385SPetr Machata 	}
187154a92385SPetr Machata 
187254a92385SPetr Machata 	pol_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, pol_id);
187354a92385SPetr Machata 	if (WARN_ON(!pol_item))
187454a92385SPetr Machata 		return -ENOENT;
187554a92385SPetr Machata 
187654a92385SPetr Machata 	*p_enabled = true;
187754a92385SPetr Machata 	*p_hw_id = pol_item->hw_id;
187854a92385SPetr Machata 	return 0;
187954a92385SPetr Machata }
188054a92385SPetr Machata 
188136d1fd68SIdo Schimmel static const struct mlxsw_sp_trap_group_item
188236d1fd68SIdo Schimmel mlxsw_sp1_trap_group_items_arr[] = {
188334a27721SIdo Schimmel 	{
188434a27721SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(ACL_SAMPLE, 0),
188534a27721SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PKT_SAMPLE,
188634a27721SIdo Schimmel 		.priority = 0,
188734a27721SIdo Schimmel 	},
188836d1fd68SIdo Schimmel };
188936d1fd68SIdo Schimmel 
1890869c7be9SIdo Schimmel static const struct mlxsw_sp_trap_item
1891869c7be9SIdo Schimmel mlxsw_sp1_trap_items_arr[] = {
189234a27721SIdo Schimmel 	{
189334a27721SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(FLOW_ACTION_SAMPLE, ACL_SAMPLE,
189434a27721SIdo Schimmel 					      MIRROR),
189534a27721SIdo Schimmel 		.listeners_arr = {
189634a27721SIdo Schimmel 			MLXSW_RXL(mlxsw_sp_rx_sample_listener, PKT_SAMPLE,
189734a27721SIdo Schimmel 				  MIRROR_TO_CPU, false, SP_PKT_SAMPLE, DISCARD),
189834a27721SIdo Schimmel 		},
189934a27721SIdo Schimmel 	},
1900869c7be9SIdo Schimmel };
1901869c7be9SIdo Schimmel 
190236d1fd68SIdo Schimmel static int
mlxsw_sp1_trap_groups_init(struct mlxsw_sp * mlxsw_sp,const struct mlxsw_sp_trap_group_item ** arr,size_t * p_groups_count)190336d1fd68SIdo Schimmel mlxsw_sp1_trap_groups_init(struct mlxsw_sp *mlxsw_sp,
190436d1fd68SIdo Schimmel 			   const struct mlxsw_sp_trap_group_item **arr,
190536d1fd68SIdo Schimmel 			   size_t *p_groups_count)
190636d1fd68SIdo Schimmel {
190736d1fd68SIdo Schimmel 	*arr = mlxsw_sp1_trap_group_items_arr;
190836d1fd68SIdo Schimmel 	*p_groups_count = ARRAY_SIZE(mlxsw_sp1_trap_group_items_arr);
190936d1fd68SIdo Schimmel 
191036d1fd68SIdo Schimmel 	return 0;
191136d1fd68SIdo Schimmel }
191236d1fd68SIdo Schimmel 
mlxsw_sp1_traps_init(struct mlxsw_sp * mlxsw_sp,const struct mlxsw_sp_trap_item ** arr,size_t * p_traps_count)1913869c7be9SIdo Schimmel static int mlxsw_sp1_traps_init(struct mlxsw_sp *mlxsw_sp,
1914869c7be9SIdo Schimmel 				const struct mlxsw_sp_trap_item **arr,
1915869c7be9SIdo Schimmel 				size_t *p_traps_count)
1916869c7be9SIdo Schimmel {
1917869c7be9SIdo Schimmel 	*arr = mlxsw_sp1_trap_items_arr;
1918869c7be9SIdo Schimmel 	*p_traps_count = ARRAY_SIZE(mlxsw_sp1_trap_items_arr);
1919869c7be9SIdo Schimmel 
1920869c7be9SIdo Schimmel 	return 0;
1921869c7be9SIdo Schimmel }
1922869c7be9SIdo Schimmel 
192336d1fd68SIdo Schimmel const struct mlxsw_sp_trap_ops mlxsw_sp1_trap_ops = {
192436d1fd68SIdo Schimmel 	.groups_init = mlxsw_sp1_trap_groups_init,
1925869c7be9SIdo Schimmel 	.traps_init = mlxsw_sp1_traps_init,
192636d1fd68SIdo Schimmel };
192736d1fd68SIdo Schimmel 
192836d1fd68SIdo Schimmel static const struct mlxsw_sp_trap_group_item
192936d1fd68SIdo Schimmel mlxsw_sp2_trap_group_items_arr[] = {
19306687e953SIdo Schimmel 	{
19316687e953SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 20),
19326687e953SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_BUFFER_DISCARDS,
19336687e953SIdo Schimmel 		.priority = 0,
19346687e953SIdo Schimmel 		.fixed_policer = true,
19356687e953SIdo Schimmel 	},
193634a27721SIdo Schimmel 	{
193734a27721SIdo Schimmel 		.group = DEVLINK_TRAP_GROUP_GENERIC(ACL_SAMPLE, 0),
193834a27721SIdo Schimmel 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PKT_SAMPLE,
193934a27721SIdo Schimmel 		.priority = 0,
1940cf31190aSIdo Schimmel 		.fixed_policer = true,
194134a27721SIdo Schimmel 	},
194236d1fd68SIdo Schimmel };
194336d1fd68SIdo Schimmel 
1944869c7be9SIdo Schimmel static const struct mlxsw_sp_trap_item
1945869c7be9SIdo Schimmel mlxsw_sp2_trap_items_arr[] = {
19466687e953SIdo Schimmel 	{
19476687e953SIdo Schimmel 		.trap = MLXSW_SP_TRAP_BUFFER_DROP(EARLY_DROP),
19486687e953SIdo Schimmel 		.listeners_arr = {
19496687e953SIdo Schimmel 			MLXSW_SP_RXL_BUFFER_DISCARD(INGRESS_WRED),
19506687e953SIdo Schimmel 		},
19516687e953SIdo Schimmel 		.is_source = true,
19526687e953SIdo Schimmel 	},
195334a27721SIdo Schimmel 	{
195434a27721SIdo Schimmel 		.trap = MLXSW_SP_TRAP_CONTROL(FLOW_ACTION_SAMPLE, ACL_SAMPLE,
195534a27721SIdo Schimmel 					      MIRROR),
195634a27721SIdo Schimmel 		.listeners_arr = {
1957cf31190aSIdo Schimmel 			MLXSW_RXL_MIRROR(mlxsw_sp_rx_sample_listener, 1,
1958cf31190aSIdo Schimmel 					 SP_PKT_SAMPLE,
1959cf31190aSIdo Schimmel 					 MLXSW_SP_MIRROR_REASON_INGRESS),
196054d0e963SIdo Schimmel 			MLXSW_RXL_MIRROR(mlxsw_sp_rx_sample_tx_listener, 1,
196154d0e963SIdo Schimmel 					 SP_PKT_SAMPLE,
196254d0e963SIdo Schimmel 					 MLXSW_SP_MIRROR_REASON_EGRESS),
196345aad0b7SIdo Schimmel 			MLXSW_RXL_MIRROR(mlxsw_sp_rx_sample_acl_listener, 1,
196445aad0b7SIdo Schimmel 					 SP_PKT_SAMPLE,
196545aad0b7SIdo Schimmel 					 MLXSW_SP_MIRROR_REASON_POLICY_ENGINE),
196634a27721SIdo Schimmel 		},
196734a27721SIdo Schimmel 	},
1968869c7be9SIdo Schimmel };
1969869c7be9SIdo Schimmel 
197036d1fd68SIdo Schimmel static int
mlxsw_sp2_trap_groups_init(struct mlxsw_sp * mlxsw_sp,const struct mlxsw_sp_trap_group_item ** arr,size_t * p_groups_count)197136d1fd68SIdo Schimmel mlxsw_sp2_trap_groups_init(struct mlxsw_sp *mlxsw_sp,
197236d1fd68SIdo Schimmel 			   const struct mlxsw_sp_trap_group_item **arr,
197336d1fd68SIdo Schimmel 			   size_t *p_groups_count)
197436d1fd68SIdo Schimmel {
197536d1fd68SIdo Schimmel 	*arr = mlxsw_sp2_trap_group_items_arr;
197636d1fd68SIdo Schimmel 	*p_groups_count = ARRAY_SIZE(mlxsw_sp2_trap_group_items_arr);
197736d1fd68SIdo Schimmel 
197836d1fd68SIdo Schimmel 	return 0;
197936d1fd68SIdo Schimmel }
198036d1fd68SIdo Schimmel 
mlxsw_sp2_traps_init(struct mlxsw_sp * mlxsw_sp,const struct mlxsw_sp_trap_item ** arr,size_t * p_traps_count)1981869c7be9SIdo Schimmel static int mlxsw_sp2_traps_init(struct mlxsw_sp *mlxsw_sp,
1982869c7be9SIdo Schimmel 				const struct mlxsw_sp_trap_item **arr,
1983869c7be9SIdo Schimmel 				size_t *p_traps_count)
1984869c7be9SIdo Schimmel {
1985869c7be9SIdo Schimmel 	*arr = mlxsw_sp2_trap_items_arr;
1986869c7be9SIdo Schimmel 	*p_traps_count = ARRAY_SIZE(mlxsw_sp2_trap_items_arr);
1987869c7be9SIdo Schimmel 
1988869c7be9SIdo Schimmel 	return 0;
1989869c7be9SIdo Schimmel }
1990869c7be9SIdo Schimmel 
199136d1fd68SIdo Schimmel const struct mlxsw_sp_trap_ops mlxsw_sp2_trap_ops = {
199236d1fd68SIdo Schimmel 	.groups_init = mlxsw_sp2_trap_groups_init,
1993869c7be9SIdo Schimmel 	.traps_init = mlxsw_sp2_traps_init,
199436d1fd68SIdo Schimmel };
1995