xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /* Copyright (c) 2019 Mellanox Technologies. All rights reserved */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/bitops.h>
5*4882a593Smuzhiyun #include <linux/kernel.h>
6*4882a593Smuzhiyun #include <linux/netlink.h>
7*4882a593Smuzhiyun #include <net/devlink.h>
8*4882a593Smuzhiyun #include <uapi/linux/devlink.h>
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "core.h"
11*4882a593Smuzhiyun #include "reg.h"
12*4882a593Smuzhiyun #include "spectrum.h"
13*4882a593Smuzhiyun #include "spectrum_trap.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun struct mlxsw_sp_trap_policer_item {
16*4882a593Smuzhiyun 	struct devlink_trap_policer policer;
17*4882a593Smuzhiyun 	u16 hw_id;
18*4882a593Smuzhiyun };
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun struct mlxsw_sp_trap_group_item {
21*4882a593Smuzhiyun 	struct devlink_trap_group group;
22*4882a593Smuzhiyun 	u16 hw_group_id;
23*4882a593Smuzhiyun 	u8 priority;
24*4882a593Smuzhiyun 	u8 fixed_policer:1; /* Whether policer binding can change */
25*4882a593Smuzhiyun };
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define MLXSW_SP_TRAP_LISTENERS_MAX 3
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun struct mlxsw_sp_trap_item {
30*4882a593Smuzhiyun 	struct devlink_trap trap;
31*4882a593Smuzhiyun 	struct mlxsw_listener listeners_arr[MLXSW_SP_TRAP_LISTENERS_MAX];
32*4882a593Smuzhiyun 	u8 is_source:1;
33*4882a593Smuzhiyun };
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun /* All driver-specific traps must be documented in
36*4882a593Smuzhiyun  * Documentation/networking/devlink/mlxsw.rst
37*4882a593Smuzhiyun  */
38*4882a593Smuzhiyun enum {
39*4882a593Smuzhiyun 	DEVLINK_MLXSW_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX,
40*4882a593Smuzhiyun 	DEVLINK_MLXSW_TRAP_ID_IRIF_DISABLED,
41*4882a593Smuzhiyun 	DEVLINK_MLXSW_TRAP_ID_ERIF_DISABLED,
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #define DEVLINK_MLXSW_TRAP_NAME_IRIF_DISABLED \
45*4882a593Smuzhiyun 	"irif_disabled"
46*4882a593Smuzhiyun #define DEVLINK_MLXSW_TRAP_NAME_ERIF_DISABLED \
47*4882a593Smuzhiyun 	"erif_disabled"
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #define MLXSW_SP_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun enum {
52*4882a593Smuzhiyun 	/* Packet was early dropped. */
53*4882a593Smuzhiyun 	MLXSW_SP_MIRROR_REASON_INGRESS_WRED = 9,
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
mlxsw_sp_rx_listener(struct mlxsw_sp * mlxsw_sp,struct sk_buff * skb,u8 local_port,struct mlxsw_sp_port * mlxsw_sp_port)56*4882a593Smuzhiyun static int mlxsw_sp_rx_listener(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
57*4882a593Smuzhiyun 				u8 local_port,
58*4882a593Smuzhiyun 				struct mlxsw_sp_port *mlxsw_sp_port)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	if (unlikely(!mlxsw_sp_port)) {
63*4882a593Smuzhiyun 		dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: skb received for non-existent port\n",
64*4882a593Smuzhiyun 				     local_port);
65*4882a593Smuzhiyun 		kfree_skb(skb);
66*4882a593Smuzhiyun 		return -EINVAL;
67*4882a593Smuzhiyun 	}
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	skb->dev = mlxsw_sp_port->dev;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
72*4882a593Smuzhiyun 	u64_stats_update_begin(&pcpu_stats->syncp);
73*4882a593Smuzhiyun 	pcpu_stats->rx_packets++;
74*4882a593Smuzhiyun 	pcpu_stats->rx_bytes += skb->len;
75*4882a593Smuzhiyun 	u64_stats_update_end(&pcpu_stats->syncp);
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	skb->protocol = eth_type_trans(skb, skb->dev);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	return 0;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
mlxsw_sp_rx_drop_listener(struct sk_buff * skb,u8 local_port,void * trap_ctx)82*4882a593Smuzhiyun static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port,
83*4882a593Smuzhiyun 				      void *trap_ctx)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	struct devlink_port *in_devlink_port;
86*4882a593Smuzhiyun 	struct mlxsw_sp_port *mlxsw_sp_port;
87*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp;
88*4882a593Smuzhiyun 	struct devlink *devlink;
89*4882a593Smuzhiyun 	int err;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
92*4882a593Smuzhiyun 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	err = mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port);
95*4882a593Smuzhiyun 	if (err)
96*4882a593Smuzhiyun 		return;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	devlink = priv_to_devlink(mlxsw_sp->core);
99*4882a593Smuzhiyun 	in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
100*4882a593Smuzhiyun 							   local_port);
101*4882a593Smuzhiyun 	skb_push(skb, ETH_HLEN);
102*4882a593Smuzhiyun 	devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port, NULL);
103*4882a593Smuzhiyun 	consume_skb(skb);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
mlxsw_sp_rx_acl_drop_listener(struct sk_buff * skb,u8 local_port,void * trap_ctx)106*4882a593Smuzhiyun static void mlxsw_sp_rx_acl_drop_listener(struct sk_buff *skb, u8 local_port,
107*4882a593Smuzhiyun 					  void *trap_ctx)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	u32 cookie_index = mlxsw_skb_cb(skb)->cookie_index;
110*4882a593Smuzhiyun 	const struct flow_action_cookie *fa_cookie;
111*4882a593Smuzhiyun 	struct devlink_port *in_devlink_port;
112*4882a593Smuzhiyun 	struct mlxsw_sp_port *mlxsw_sp_port;
113*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp;
114*4882a593Smuzhiyun 	struct devlink *devlink;
115*4882a593Smuzhiyun 	int err;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
118*4882a593Smuzhiyun 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	err = mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port);
121*4882a593Smuzhiyun 	if (err)
122*4882a593Smuzhiyun 		return;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	devlink = priv_to_devlink(mlxsw_sp->core);
125*4882a593Smuzhiyun 	in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
126*4882a593Smuzhiyun 							   local_port);
127*4882a593Smuzhiyun 	skb_push(skb, ETH_HLEN);
128*4882a593Smuzhiyun 	rcu_read_lock();
129*4882a593Smuzhiyun 	fa_cookie = mlxsw_sp_acl_act_cookie_lookup(mlxsw_sp, cookie_index);
130*4882a593Smuzhiyun 	devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port, fa_cookie);
131*4882a593Smuzhiyun 	rcu_read_unlock();
132*4882a593Smuzhiyun 	consume_skb(skb);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
__mlxsw_sp_rx_no_mark_listener(struct sk_buff * skb,u8 local_port,void * trap_ctx)135*4882a593Smuzhiyun static int __mlxsw_sp_rx_no_mark_listener(struct sk_buff *skb, u8 local_port,
136*4882a593Smuzhiyun 					  void *trap_ctx)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun 	struct devlink_port *in_devlink_port;
139*4882a593Smuzhiyun 	struct mlxsw_sp_port *mlxsw_sp_port;
140*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp;
141*4882a593Smuzhiyun 	struct devlink *devlink;
142*4882a593Smuzhiyun 	int err;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
145*4882a593Smuzhiyun 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	err = mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port);
148*4882a593Smuzhiyun 	if (err)
149*4882a593Smuzhiyun 		return err;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	devlink = priv_to_devlink(mlxsw_sp->core);
152*4882a593Smuzhiyun 	in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
153*4882a593Smuzhiyun 							   local_port);
154*4882a593Smuzhiyun 	skb_push(skb, ETH_HLEN);
155*4882a593Smuzhiyun 	devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port, NULL);
156*4882a593Smuzhiyun 	skb_pull(skb, ETH_HLEN);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	return 0;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
mlxsw_sp_rx_no_mark_listener(struct sk_buff * skb,u8 local_port,void * trap_ctx)161*4882a593Smuzhiyun static void mlxsw_sp_rx_no_mark_listener(struct sk_buff *skb, u8 local_port,
162*4882a593Smuzhiyun 					 void *trap_ctx)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun 	int err;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	err = __mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
167*4882a593Smuzhiyun 	if (err)
168*4882a593Smuzhiyun 		return;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	netif_receive_skb(skb);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
mlxsw_sp_rx_mark_listener(struct sk_buff * skb,u8 local_port,void * trap_ctx)173*4882a593Smuzhiyun static void mlxsw_sp_rx_mark_listener(struct sk_buff *skb, u8 local_port,
174*4882a593Smuzhiyun 				      void *trap_ctx)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun 	skb->offload_fwd_mark = 1;
177*4882a593Smuzhiyun 	mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun 
mlxsw_sp_rx_l3_mark_listener(struct sk_buff * skb,u8 local_port,void * trap_ctx)180*4882a593Smuzhiyun static void mlxsw_sp_rx_l3_mark_listener(struct sk_buff *skb, u8 local_port,
181*4882a593Smuzhiyun 					 void *trap_ctx)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun 	skb->offload_l3_fwd_mark = 1;
184*4882a593Smuzhiyun 	skb->offload_fwd_mark = 1;
185*4882a593Smuzhiyun 	mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
mlxsw_sp_rx_ptp_listener(struct sk_buff * skb,u8 local_port,void * trap_ctx)188*4882a593Smuzhiyun static void mlxsw_sp_rx_ptp_listener(struct sk_buff *skb, u8 local_port,
189*4882a593Smuzhiyun 				     void *trap_ctx)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
192*4882a593Smuzhiyun 	int err;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	err = __mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
195*4882a593Smuzhiyun 	if (err)
196*4882a593Smuzhiyun 		return;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	/* The PTP handler expects skb->data to point to the start of the
199*4882a593Smuzhiyun 	 * Ethernet header.
200*4882a593Smuzhiyun 	 */
201*4882a593Smuzhiyun 	skb_push(skb, ETH_HLEN);
202*4882a593Smuzhiyun 	mlxsw_sp_ptp_receive(mlxsw_sp, skb, local_port);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
mlxsw_sp_rx_sample_listener(struct sk_buff * skb,u8 local_port,void * trap_ctx)205*4882a593Smuzhiyun static void mlxsw_sp_rx_sample_listener(struct sk_buff *skb, u8 local_port,
206*4882a593Smuzhiyun 					void *trap_ctx)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
209*4882a593Smuzhiyun 	int err;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	err = __mlxsw_sp_rx_no_mark_listener(skb, local_port, trap_ctx);
212*4882a593Smuzhiyun 	if (err)
213*4882a593Smuzhiyun 		return;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	/* The sample handler expects skb->data to point to the start of the
216*4882a593Smuzhiyun 	 * Ethernet header.
217*4882a593Smuzhiyun 	 */
218*4882a593Smuzhiyun 	skb_push(skb, ETH_HLEN);
219*4882a593Smuzhiyun 	mlxsw_sp_sample_receive(mlxsw_sp, skb, local_port);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun #define MLXSW_SP_TRAP_DROP(_id, _group_id)				      \
223*4882a593Smuzhiyun 	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				      \
224*4882a593Smuzhiyun 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
225*4882a593Smuzhiyun 			     MLXSW_SP_TRAP_METADATA)
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun #define MLXSW_SP_TRAP_DROP_EXT(_id, _group_id, _metadata)		      \
228*4882a593Smuzhiyun 	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				      \
229*4882a593Smuzhiyun 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
230*4882a593Smuzhiyun 			     MLXSW_SP_TRAP_METADATA | (_metadata))
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun #define MLXSW_SP_TRAP_BUFFER_DROP(_id)					      \
233*4882a593Smuzhiyun 	DEVLINK_TRAP_GENERIC(DROP, TRAP, _id,				      \
234*4882a593Smuzhiyun 			     DEVLINK_TRAP_GROUP_GENERIC_ID_BUFFER_DROPS,      \
235*4882a593Smuzhiyun 			     MLXSW_SP_TRAP_METADATA)
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun #define MLXSW_SP_TRAP_DRIVER_DROP(_id, _group_id)			      \
238*4882a593Smuzhiyun 	DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_MLXSW_TRAP_ID_##_id,	      \
239*4882a593Smuzhiyun 			    DEVLINK_MLXSW_TRAP_NAME_##_id,		      \
240*4882a593Smuzhiyun 			    DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
241*4882a593Smuzhiyun 			    MLXSW_SP_TRAP_METADATA)
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun #define MLXSW_SP_TRAP_EXCEPTION(_id, _group_id)		      \
244*4882a593Smuzhiyun 	DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id,			      \
245*4882a593Smuzhiyun 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
246*4882a593Smuzhiyun 			     MLXSW_SP_TRAP_METADATA)
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun #define MLXSW_SP_TRAP_CONTROL(_id, _group_id, _action)			      \
249*4882a593Smuzhiyun 	DEVLINK_TRAP_GENERIC(CONTROL, _action, _id,			      \
250*4882a593Smuzhiyun 			     DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id,	      \
251*4882a593Smuzhiyun 			     MLXSW_SP_TRAP_METADATA)
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun #define MLXSW_SP_RXL_DISCARD(_id, _group_id)				      \
254*4882a593Smuzhiyun 	MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, DISCARD_##_id,		      \
255*4882a593Smuzhiyun 		      TRAP_EXCEPTION_TO_CPU, false, SP_##_group_id,	      \
256*4882a593Smuzhiyun 		      SET_FW_DEFAULT, SP_##_group_id)
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun #define MLXSW_SP_RXL_ACL_DISCARD(_id, _en_group_id, _dis_group_id)	      \
259*4882a593Smuzhiyun 	MLXSW_RXL_DIS(mlxsw_sp_rx_acl_drop_listener, DISCARD_##_id,	      \
260*4882a593Smuzhiyun 		      TRAP_EXCEPTION_TO_CPU, false, SP_##_en_group_id,	      \
261*4882a593Smuzhiyun 		      SET_FW_DEFAULT, SP_##_dis_group_id)
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun #define MLXSW_SP_RXL_BUFFER_DISCARD(_mirror_reason)			      \
264*4882a593Smuzhiyun 	MLXSW_RXL_MIRROR(mlxsw_sp_rx_drop_listener, 0, SP_BUFFER_DISCARDS,    \
265*4882a593Smuzhiyun 			 MLXSW_SP_MIRROR_REASON_##_mirror_reason)
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun #define MLXSW_SP_RXL_EXCEPTION(_id, _group_id, _action)			      \
268*4882a593Smuzhiyun 	MLXSW_RXL(mlxsw_sp_rx_mark_listener, _id,			      \
269*4882a593Smuzhiyun 		   _action, false, SP_##_group_id, SET_FW_DEFAULT)
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun #define MLXSW_SP_RXL_NO_MARK(_id, _group_id, _action, _is_ctrl)		      \
272*4882a593Smuzhiyun 	MLXSW_RXL(mlxsw_sp_rx_no_mark_listener, _id, _action,		      \
273*4882a593Smuzhiyun 		  _is_ctrl, SP_##_group_id, DISCARD)
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun #define MLXSW_SP_RXL_MARK(_id, _group_id, _action, _is_ctrl)		      \
276*4882a593Smuzhiyun 	MLXSW_RXL(mlxsw_sp_rx_mark_listener, _id, _action, _is_ctrl,	      \
277*4882a593Smuzhiyun 		  SP_##_group_id, DISCARD)
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun #define MLXSW_SP_RXL_L3_MARK(_id, _group_id, _action, _is_ctrl)		      \
280*4882a593Smuzhiyun 	MLXSW_RXL(mlxsw_sp_rx_l3_mark_listener, _id, _action, _is_ctrl,	      \
281*4882a593Smuzhiyun 		  SP_##_group_id, DISCARD)
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun #define MLXSW_SP_TRAP_POLICER(_id, _rate, _burst)			      \
284*4882a593Smuzhiyun 	DEVLINK_TRAP_POLICER(_id, _rate, _burst,			      \
285*4882a593Smuzhiyun 			     MLXSW_REG_QPCR_HIGHEST_CIR,		      \
286*4882a593Smuzhiyun 			     MLXSW_REG_QPCR_LOWEST_CIR,			      \
287*4882a593Smuzhiyun 			     1 << MLXSW_REG_QPCR_HIGHEST_CBS,		      \
288*4882a593Smuzhiyun 			     1 << MLXSW_REG_QPCR_LOWEST_CBS)
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun /* Ordered by policer identifier */
291*4882a593Smuzhiyun static const struct mlxsw_sp_trap_policer_item
292*4882a593Smuzhiyun mlxsw_sp_trap_policer_items_arr[] = {
293*4882a593Smuzhiyun 	{
294*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(1, 10 * 1024, 4096),
295*4882a593Smuzhiyun 	},
296*4882a593Smuzhiyun 	{
297*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(2, 128, 128),
298*4882a593Smuzhiyun 	},
299*4882a593Smuzhiyun 	{
300*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(3, 128, 128),
301*4882a593Smuzhiyun 	},
302*4882a593Smuzhiyun 	{
303*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(4, 128, 128),
304*4882a593Smuzhiyun 	},
305*4882a593Smuzhiyun 	{
306*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(5, 16 * 1024, 8192),
307*4882a593Smuzhiyun 	},
308*4882a593Smuzhiyun 	{
309*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(6, 128, 128),
310*4882a593Smuzhiyun 	},
311*4882a593Smuzhiyun 	{
312*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(7, 1024, 512),
313*4882a593Smuzhiyun 	},
314*4882a593Smuzhiyun 	{
315*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(8, 20 * 1024, 8192),
316*4882a593Smuzhiyun 	},
317*4882a593Smuzhiyun 	{
318*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(9, 128, 128),
319*4882a593Smuzhiyun 	},
320*4882a593Smuzhiyun 	{
321*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(10, 1024, 512),
322*4882a593Smuzhiyun 	},
323*4882a593Smuzhiyun 	{
324*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(11, 256, 128),
325*4882a593Smuzhiyun 	},
326*4882a593Smuzhiyun 	{
327*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(12, 128, 128),
328*4882a593Smuzhiyun 	},
329*4882a593Smuzhiyun 	{
330*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(13, 128, 128),
331*4882a593Smuzhiyun 	},
332*4882a593Smuzhiyun 	{
333*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(14, 1024, 512),
334*4882a593Smuzhiyun 	},
335*4882a593Smuzhiyun 	{
336*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(15, 1024, 512),
337*4882a593Smuzhiyun 	},
338*4882a593Smuzhiyun 	{
339*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(16, 24 * 1024, 16384),
340*4882a593Smuzhiyun 	},
341*4882a593Smuzhiyun 	{
342*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(17, 19 * 1024, 8192),
343*4882a593Smuzhiyun 	},
344*4882a593Smuzhiyun 	{
345*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(18, 1024, 512),
346*4882a593Smuzhiyun 	},
347*4882a593Smuzhiyun 	{
348*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(19, 1024, 512),
349*4882a593Smuzhiyun 	},
350*4882a593Smuzhiyun 	{
351*4882a593Smuzhiyun 		.policer = MLXSW_SP_TRAP_POLICER(20, 10240, 4096),
352*4882a593Smuzhiyun 	},
353*4882a593Smuzhiyun };
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun static const struct mlxsw_sp_trap_group_item mlxsw_sp_trap_group_items_arr[] = {
356*4882a593Smuzhiyun 	{
357*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 1),
358*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS,
359*4882a593Smuzhiyun 		.priority = 0,
360*4882a593Smuzhiyun 	},
361*4882a593Smuzhiyun 	{
362*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 1),
363*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_DISCARDS,
364*4882a593Smuzhiyun 		.priority = 0,
365*4882a593Smuzhiyun 	},
366*4882a593Smuzhiyun 	{
367*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(L3_EXCEPTIONS, 1),
368*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_EXCEPTIONS,
369*4882a593Smuzhiyun 		.priority = 2,
370*4882a593Smuzhiyun 	},
371*4882a593Smuzhiyun 	{
372*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(TUNNEL_DROPS, 1),
373*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS,
374*4882a593Smuzhiyun 		.priority = 0,
375*4882a593Smuzhiyun 	},
376*4882a593Smuzhiyun 	{
377*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 1),
378*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS,
379*4882a593Smuzhiyun 		.priority = 0,
380*4882a593Smuzhiyun 	},
381*4882a593Smuzhiyun 	{
382*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(STP, 2),
383*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_STP,
384*4882a593Smuzhiyun 		.priority = 5,
385*4882a593Smuzhiyun 	},
386*4882a593Smuzhiyun 	{
387*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(LACP, 3),
388*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP,
389*4882a593Smuzhiyun 		.priority = 5,
390*4882a593Smuzhiyun 	},
391*4882a593Smuzhiyun 	{
392*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(LLDP, 4),
393*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP,
394*4882a593Smuzhiyun 		.priority = 5,
395*4882a593Smuzhiyun 	},
396*4882a593Smuzhiyun 	{
397*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(MC_SNOOPING, 5),
398*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_MC_SNOOPING,
399*4882a593Smuzhiyun 		.priority = 3,
400*4882a593Smuzhiyun 	},
401*4882a593Smuzhiyun 	{
402*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(DHCP, 6),
403*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP,
404*4882a593Smuzhiyun 		.priority = 2,
405*4882a593Smuzhiyun 	},
406*4882a593Smuzhiyun 	{
407*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(NEIGH_DISCOVERY, 7),
408*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_NEIGH_DISCOVERY,
409*4882a593Smuzhiyun 		.priority = 2,
410*4882a593Smuzhiyun 	},
411*4882a593Smuzhiyun 	{
412*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(BFD, 8),
413*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_BFD,
414*4882a593Smuzhiyun 		.priority = 5,
415*4882a593Smuzhiyun 	},
416*4882a593Smuzhiyun 	{
417*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(OSPF, 9),
418*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF,
419*4882a593Smuzhiyun 		.priority = 5,
420*4882a593Smuzhiyun 	},
421*4882a593Smuzhiyun 	{
422*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(BGP, 10),
423*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP,
424*4882a593Smuzhiyun 		.priority = 4,
425*4882a593Smuzhiyun 	},
426*4882a593Smuzhiyun 	{
427*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(VRRP, 11),
428*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP,
429*4882a593Smuzhiyun 		.priority = 5,
430*4882a593Smuzhiyun 	},
431*4882a593Smuzhiyun 	{
432*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(PIM, 12),
433*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM,
434*4882a593Smuzhiyun 		.priority = 5,
435*4882a593Smuzhiyun 	},
436*4882a593Smuzhiyun 	{
437*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(UC_LB, 13),
438*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR,
439*4882a593Smuzhiyun 		.priority = 0,
440*4882a593Smuzhiyun 	},
441*4882a593Smuzhiyun 	{
442*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(LOCAL_DELIVERY, 14),
443*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME,
444*4882a593Smuzhiyun 		.priority = 2,
445*4882a593Smuzhiyun 	},
446*4882a593Smuzhiyun 	{
447*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(EXTERNAL_DELIVERY, 19),
448*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_EXTERNAL_ROUTE,
449*4882a593Smuzhiyun 		.priority = 1,
450*4882a593Smuzhiyun 	},
451*4882a593Smuzhiyun 	{
452*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(IPV6, 15),
453*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_IPV6,
454*4882a593Smuzhiyun 		.priority = 2,
455*4882a593Smuzhiyun 	},
456*4882a593Smuzhiyun 	{
457*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(PTP_EVENT, 16),
458*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0,
459*4882a593Smuzhiyun 		.priority = 5,
460*4882a593Smuzhiyun 	},
461*4882a593Smuzhiyun 	{
462*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(PTP_GENERAL, 17),
463*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1,
464*4882a593Smuzhiyun 		.priority = 2,
465*4882a593Smuzhiyun 	},
466*4882a593Smuzhiyun 	{
467*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(ACL_SAMPLE, 0),
468*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_PKT_SAMPLE,
469*4882a593Smuzhiyun 		.priority = 0,
470*4882a593Smuzhiyun 	},
471*4882a593Smuzhiyun 	{
472*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(ACL_TRAP, 18),
473*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_FLOW_LOGGING,
474*4882a593Smuzhiyun 		.priority = 4,
475*4882a593Smuzhiyun 	},
476*4882a593Smuzhiyun };
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun static const struct mlxsw_sp_trap_item mlxsw_sp_trap_items_arr[] = {
479*4882a593Smuzhiyun 	{
480*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(SMAC_MC, L2_DROPS),
481*4882a593Smuzhiyun 		.listeners_arr = {
482*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_PACKET_SMAC_MC, L2_DISCARDS),
483*4882a593Smuzhiyun 		},
484*4882a593Smuzhiyun 	},
485*4882a593Smuzhiyun 	{
486*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(VLAN_TAG_MISMATCH, L2_DROPS),
487*4882a593Smuzhiyun 		.listeners_arr = {
488*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_SWITCH_VTAG_ALLOW,
489*4882a593Smuzhiyun 					     L2_DISCARDS),
490*4882a593Smuzhiyun 		},
491*4882a593Smuzhiyun 	},
492*4882a593Smuzhiyun 	{
493*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
494*4882a593Smuzhiyun 		.listeners_arr = {
495*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_SWITCH_VLAN, L2_DISCARDS),
496*4882a593Smuzhiyun 		},
497*4882a593Smuzhiyun 	},
498*4882a593Smuzhiyun 	{
499*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(INGRESS_STP_FILTER, L2_DROPS),
500*4882a593Smuzhiyun 		.listeners_arr = {
501*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_SWITCH_STP, L2_DISCARDS),
502*4882a593Smuzhiyun 		},
503*4882a593Smuzhiyun 	},
504*4882a593Smuzhiyun 	{
505*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(EMPTY_TX_LIST, L2_DROPS),
506*4882a593Smuzhiyun 		.listeners_arr = {
507*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_UC, L2_DISCARDS),
508*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_MC_NULL, L2_DISCARDS),
509*4882a593Smuzhiyun 		},
510*4882a593Smuzhiyun 	},
511*4882a593Smuzhiyun 	{
512*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(PORT_LOOPBACK_FILTER, L2_DROPS),
513*4882a593Smuzhiyun 		.listeners_arr = {
514*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_LB, L2_DISCARDS),
515*4882a593Smuzhiyun 		},
516*4882a593Smuzhiyun 	},
517*4882a593Smuzhiyun 	{
518*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(BLACKHOLE_ROUTE, L3_DROPS),
519*4882a593Smuzhiyun 		.listeners_arr = {
520*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ROUTER2, L3_DISCARDS),
521*4882a593Smuzhiyun 		},
522*4882a593Smuzhiyun 	},
523*4882a593Smuzhiyun 	{
524*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(NON_IP_PACKET, L3_DROPS),
525*4882a593Smuzhiyun 		.listeners_arr = {
526*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_NON_IP_PACKET,
527*4882a593Smuzhiyun 					     L3_DISCARDS),
528*4882a593Smuzhiyun 		},
529*4882a593Smuzhiyun 	},
530*4882a593Smuzhiyun 	{
531*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(UC_DIP_MC_DMAC, L3_DROPS),
532*4882a593Smuzhiyun 		.listeners_arr = {
533*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_UC_DIP_MC_DMAC,
534*4882a593Smuzhiyun 					     L3_DISCARDS),
535*4882a593Smuzhiyun 		},
536*4882a593Smuzhiyun 	},
537*4882a593Smuzhiyun 	{
538*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(DIP_LB, L3_DROPS),
539*4882a593Smuzhiyun 		.listeners_arr = {
540*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_DIP_LB, L3_DISCARDS),
541*4882a593Smuzhiyun 		},
542*4882a593Smuzhiyun 	},
543*4882a593Smuzhiyun 	{
544*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(SIP_MC, L3_DROPS),
545*4882a593Smuzhiyun 		.listeners_arr = {
546*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_SIP_MC, L3_DISCARDS),
547*4882a593Smuzhiyun 		},
548*4882a593Smuzhiyun 	},
549*4882a593Smuzhiyun 	{
550*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(SIP_LB, L3_DROPS),
551*4882a593Smuzhiyun 		.listeners_arr = {
552*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_SIP_LB, L3_DISCARDS),
553*4882a593Smuzhiyun 		},
554*4882a593Smuzhiyun 	},
555*4882a593Smuzhiyun 	{
556*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(CORRUPTED_IP_HDR, L3_DROPS),
557*4882a593Smuzhiyun 		.listeners_arr = {
558*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_CORRUPTED_IP_HDR,
559*4882a593Smuzhiyun 					     L3_DISCARDS),
560*4882a593Smuzhiyun 		},
561*4882a593Smuzhiyun 	},
562*4882a593Smuzhiyun 	{
563*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(IPV4_SIP_BC, L3_DROPS),
564*4882a593Smuzhiyun 		.listeners_arr = {
565*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ING_ROUTER_IPV4_SIP_BC,
566*4882a593Smuzhiyun 					     L3_DISCARDS),
567*4882a593Smuzhiyun 		},
568*4882a593Smuzhiyun 	},
569*4882a593Smuzhiyun 	{
570*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(IPV6_MC_DIP_RESERVED_SCOPE,
571*4882a593Smuzhiyun 					   L3_DROPS),
572*4882a593Smuzhiyun 		.listeners_arr = {
573*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_RESERVED_SCOPE,
574*4882a593Smuzhiyun 					     L3_DISCARDS),
575*4882a593Smuzhiyun 		},
576*4882a593Smuzhiyun 	},
577*4882a593Smuzhiyun 	{
578*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE,
579*4882a593Smuzhiyun 					   L3_DROPS),
580*4882a593Smuzhiyun 		.listeners_arr = {
581*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE,
582*4882a593Smuzhiyun 					     L3_DISCARDS),
583*4882a593Smuzhiyun 		},
584*4882a593Smuzhiyun 	},
585*4882a593Smuzhiyun 	{
586*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_EXCEPTION(MTU_ERROR, L3_EXCEPTIONS),
587*4882a593Smuzhiyun 		.listeners_arr = {
588*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(MTUERROR, L3_EXCEPTIONS,
589*4882a593Smuzhiyun 					       TRAP_TO_CPU),
590*4882a593Smuzhiyun 		},
591*4882a593Smuzhiyun 	},
592*4882a593Smuzhiyun 	{
593*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_EXCEPTION(TTL_ERROR, L3_EXCEPTIONS),
594*4882a593Smuzhiyun 		.listeners_arr = {
595*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(TTLERROR, L3_EXCEPTIONS,
596*4882a593Smuzhiyun 					       TRAP_TO_CPU),
597*4882a593Smuzhiyun 		},
598*4882a593Smuzhiyun 	},
599*4882a593Smuzhiyun 	{
600*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_EXCEPTION(RPF, L3_EXCEPTIONS),
601*4882a593Smuzhiyun 		.listeners_arr = {
602*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(RPF, L3_EXCEPTIONS, TRAP_TO_CPU),
603*4882a593Smuzhiyun 		},
604*4882a593Smuzhiyun 	},
605*4882a593Smuzhiyun 	{
606*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_EXCEPTION(REJECT_ROUTE, L3_EXCEPTIONS),
607*4882a593Smuzhiyun 		.listeners_arr = {
608*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(RTR_INGRESS1, L3_EXCEPTIONS,
609*4882a593Smuzhiyun 					       TRAP_TO_CPU),
610*4882a593Smuzhiyun 		},
611*4882a593Smuzhiyun 	},
612*4882a593Smuzhiyun 	{
613*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_EXCEPTION(UNRESOLVED_NEIGH,
614*4882a593Smuzhiyun 						L3_EXCEPTIONS),
615*4882a593Smuzhiyun 		.listeners_arr = {
616*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV4, L3_EXCEPTIONS,
617*4882a593Smuzhiyun 					       TRAP_TO_CPU),
618*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV6, L3_EXCEPTIONS,
619*4882a593Smuzhiyun 					       TRAP_TO_CPU),
620*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER3, L3_EXCEPTIONS,
621*4882a593Smuzhiyun 					       TRAP_EXCEPTION_TO_CPU),
622*4882a593Smuzhiyun 		},
623*4882a593Smuzhiyun 	},
624*4882a593Smuzhiyun 	{
625*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_EXCEPTION(IPV4_LPM_UNICAST_MISS,
626*4882a593Smuzhiyun 						L3_EXCEPTIONS),
627*4882a593Smuzhiyun 		.listeners_arr = {
628*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM4,
629*4882a593Smuzhiyun 					       L3_EXCEPTIONS,
630*4882a593Smuzhiyun 					       TRAP_EXCEPTION_TO_CPU),
631*4882a593Smuzhiyun 		},
632*4882a593Smuzhiyun 	},
633*4882a593Smuzhiyun 	{
634*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_EXCEPTION(IPV6_LPM_UNICAST_MISS,
635*4882a593Smuzhiyun 						L3_EXCEPTIONS),
636*4882a593Smuzhiyun 		.listeners_arr = {
637*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM6,
638*4882a593Smuzhiyun 					       L3_EXCEPTIONS,
639*4882a593Smuzhiyun 					       TRAP_EXCEPTION_TO_CPU),
640*4882a593Smuzhiyun 		},
641*4882a593Smuzhiyun 	},
642*4882a593Smuzhiyun 	{
643*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DRIVER_DROP(IRIF_DISABLED, L3_DROPS),
644*4882a593Smuzhiyun 		.listeners_arr = {
645*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ROUTER_IRIF_EN, L3_DISCARDS),
646*4882a593Smuzhiyun 		},
647*4882a593Smuzhiyun 	},
648*4882a593Smuzhiyun 	{
649*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DRIVER_DROP(ERIF_DISABLED, L3_DROPS),
650*4882a593Smuzhiyun 		.listeners_arr = {
651*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(ROUTER_ERIF_EN, L3_DISCARDS),
652*4882a593Smuzhiyun 		},
653*4882a593Smuzhiyun 	},
654*4882a593Smuzhiyun 	{
655*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(NON_ROUTABLE, L3_DROPS),
656*4882a593Smuzhiyun 		.listeners_arr = {
657*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(NON_ROUTABLE, L3_DISCARDS),
658*4882a593Smuzhiyun 		},
659*4882a593Smuzhiyun 	},
660*4882a593Smuzhiyun 	{
661*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_EXCEPTION(DECAP_ERROR, TUNNEL_DROPS),
662*4882a593Smuzhiyun 		.listeners_arr = {
663*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(DECAP_ECN0, TUNNEL_DISCARDS,
664*4882a593Smuzhiyun 					       TRAP_EXCEPTION_TO_CPU),
665*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(IPIP_DECAP_ERROR,
666*4882a593Smuzhiyun 					       TUNNEL_DISCARDS,
667*4882a593Smuzhiyun 					       TRAP_EXCEPTION_TO_CPU),
668*4882a593Smuzhiyun 			MLXSW_SP_RXL_EXCEPTION(DISCARD_DEC_PKT, TUNNEL_DISCARDS,
669*4882a593Smuzhiyun 					       TRAP_EXCEPTION_TO_CPU),
670*4882a593Smuzhiyun 		},
671*4882a593Smuzhiyun 	},
672*4882a593Smuzhiyun 	{
673*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP(OVERLAY_SMAC_MC, TUNNEL_DROPS),
674*4882a593Smuzhiyun 		.listeners_arr = {
675*4882a593Smuzhiyun 			MLXSW_SP_RXL_DISCARD(OVERLAY_SMAC_MC, TUNNEL_DISCARDS),
676*4882a593Smuzhiyun 		},
677*4882a593Smuzhiyun 	},
678*4882a593Smuzhiyun 	{
679*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP_EXT(INGRESS_FLOW_ACTION_DROP,
680*4882a593Smuzhiyun 					       ACL_DROPS,
681*4882a593Smuzhiyun 					       DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE),
682*4882a593Smuzhiyun 		.listeners_arr = {
683*4882a593Smuzhiyun 			MLXSW_SP_RXL_ACL_DISCARD(INGRESS_ACL, ACL_DISCARDS,
684*4882a593Smuzhiyun 						 DUMMY),
685*4882a593Smuzhiyun 		},
686*4882a593Smuzhiyun 	},
687*4882a593Smuzhiyun 	{
688*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_DROP_EXT(EGRESS_FLOW_ACTION_DROP,
689*4882a593Smuzhiyun 					       ACL_DROPS,
690*4882a593Smuzhiyun 					       DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE),
691*4882a593Smuzhiyun 		.listeners_arr = {
692*4882a593Smuzhiyun 			MLXSW_SP_RXL_ACL_DISCARD(EGRESS_ACL, ACL_DISCARDS,
693*4882a593Smuzhiyun 						 DUMMY),
694*4882a593Smuzhiyun 		},
695*4882a593Smuzhiyun 	},
696*4882a593Smuzhiyun 	{
697*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(STP, STP, TRAP),
698*4882a593Smuzhiyun 		.listeners_arr = {
699*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(STP, STP, TRAP_TO_CPU, true),
700*4882a593Smuzhiyun 		},
701*4882a593Smuzhiyun 	},
702*4882a593Smuzhiyun 	{
703*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(LACP, LACP, TRAP),
704*4882a593Smuzhiyun 		.listeners_arr = {
705*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(LACP, LACP, TRAP_TO_CPU, true),
706*4882a593Smuzhiyun 		},
707*4882a593Smuzhiyun 	},
708*4882a593Smuzhiyun 	{
709*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(LLDP, LLDP, TRAP),
710*4882a593Smuzhiyun 		.listeners_arr = {
711*4882a593Smuzhiyun 			MLXSW_RXL(mlxsw_sp_rx_ptp_listener, LLDP, TRAP_TO_CPU,
712*4882a593Smuzhiyun 				  true, SP_LLDP, DISCARD),
713*4882a593Smuzhiyun 		},
714*4882a593Smuzhiyun 	},
715*4882a593Smuzhiyun 	{
716*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_QUERY, MC_SNOOPING, MIRROR),
717*4882a593Smuzhiyun 		.listeners_arr = {
718*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IGMP_QUERY, MC_SNOOPING,
719*4882a593Smuzhiyun 					  MIRROR_TO_CPU, false),
720*4882a593Smuzhiyun 		},
721*4882a593Smuzhiyun 	},
722*4882a593Smuzhiyun 	{
723*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_V1_REPORT, MC_SNOOPING,
724*4882a593Smuzhiyun 					      TRAP),
725*4882a593Smuzhiyun 		.listeners_arr = {
726*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, MC_SNOOPING,
727*4882a593Smuzhiyun 					     TRAP_TO_CPU, false),
728*4882a593Smuzhiyun 		},
729*4882a593Smuzhiyun 	},
730*4882a593Smuzhiyun 	{
731*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_V2_REPORT, MC_SNOOPING,
732*4882a593Smuzhiyun 					      TRAP),
733*4882a593Smuzhiyun 		.listeners_arr = {
734*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, MC_SNOOPING,
735*4882a593Smuzhiyun 					     TRAP_TO_CPU, false),
736*4882a593Smuzhiyun 		},
737*4882a593Smuzhiyun 	},
738*4882a593Smuzhiyun 	{
739*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_V3_REPORT, MC_SNOOPING,
740*4882a593Smuzhiyun 					      TRAP),
741*4882a593Smuzhiyun 		.listeners_arr = {
742*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, MC_SNOOPING,
743*4882a593Smuzhiyun 					     TRAP_TO_CPU, false),
744*4882a593Smuzhiyun 		},
745*4882a593Smuzhiyun 	},
746*4882a593Smuzhiyun 	{
747*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IGMP_V2_LEAVE, MC_SNOOPING,
748*4882a593Smuzhiyun 					      TRAP),
749*4882a593Smuzhiyun 		.listeners_arr = {
750*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, MC_SNOOPING,
751*4882a593Smuzhiyun 					     TRAP_TO_CPU, false),
752*4882a593Smuzhiyun 		},
753*4882a593Smuzhiyun 	},
754*4882a593Smuzhiyun 	{
755*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(MLD_QUERY, MC_SNOOPING, MIRROR),
756*4882a593Smuzhiyun 		.listeners_arr = {
757*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_MLDV12_LISTENER_QUERY,
758*4882a593Smuzhiyun 					  MC_SNOOPING, MIRROR_TO_CPU, false),
759*4882a593Smuzhiyun 		},
760*4882a593Smuzhiyun 	},
761*4882a593Smuzhiyun 	{
762*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(MLD_V1_REPORT, MC_SNOOPING,
763*4882a593Smuzhiyun 					      TRAP),
764*4882a593Smuzhiyun 		.listeners_arr = {
765*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_REPORT,
766*4882a593Smuzhiyun 					     MC_SNOOPING, TRAP_TO_CPU, false),
767*4882a593Smuzhiyun 		},
768*4882a593Smuzhiyun 	},
769*4882a593Smuzhiyun 	{
770*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(MLD_V2_REPORT, MC_SNOOPING,
771*4882a593Smuzhiyun 					      TRAP),
772*4882a593Smuzhiyun 		.listeners_arr = {
773*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(IPV6_MLDV2_LISTENER_REPORT,
774*4882a593Smuzhiyun 					     MC_SNOOPING, TRAP_TO_CPU, false),
775*4882a593Smuzhiyun 		},
776*4882a593Smuzhiyun 	},
777*4882a593Smuzhiyun 	{
778*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(MLD_V1_DONE, MC_SNOOPING,
779*4882a593Smuzhiyun 					      TRAP),
780*4882a593Smuzhiyun 		.listeners_arr = {
781*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(IPV6_MLDV1_LISTENER_DONE,
782*4882a593Smuzhiyun 					     MC_SNOOPING, TRAP_TO_CPU, false),
783*4882a593Smuzhiyun 		},
784*4882a593Smuzhiyun 	},
785*4882a593Smuzhiyun 	{
786*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_DHCP, DHCP, TRAP),
787*4882a593Smuzhiyun 		.listeners_arr = {
788*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV4_DHCP, DHCP, TRAP_TO_CPU, false),
789*4882a593Smuzhiyun 		},
790*4882a593Smuzhiyun 	},
791*4882a593Smuzhiyun 	{
792*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_DHCP, DHCP, TRAP),
793*4882a593Smuzhiyun 		.listeners_arr = {
794*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_DHCP, DHCP, TRAP_TO_CPU, false),
795*4882a593Smuzhiyun 		},
796*4882a593Smuzhiyun 	},
797*4882a593Smuzhiyun 	{
798*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(ARP_REQUEST, NEIGH_DISCOVERY,
799*4882a593Smuzhiyun 					      MIRROR),
800*4882a593Smuzhiyun 		.listeners_arr = {
801*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(ARPBC, NEIGH_DISCOVERY, MIRROR_TO_CPU,
802*4882a593Smuzhiyun 					  false),
803*4882a593Smuzhiyun 		},
804*4882a593Smuzhiyun 	},
805*4882a593Smuzhiyun 	{
806*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(ARP_RESPONSE, NEIGH_DISCOVERY,
807*4882a593Smuzhiyun 					      MIRROR),
808*4882a593Smuzhiyun 		.listeners_arr = {
809*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(ARPUC, NEIGH_DISCOVERY, MIRROR_TO_CPU,
810*4882a593Smuzhiyun 					  false),
811*4882a593Smuzhiyun 		},
812*4882a593Smuzhiyun 	},
813*4882a593Smuzhiyun 	{
814*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(ARP_OVERLAY, NEIGH_DISCOVERY,
815*4882a593Smuzhiyun 					      TRAP),
816*4882a593Smuzhiyun 		.listeners_arr = {
817*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(NVE_DECAP_ARP, NEIGH_DISCOVERY,
818*4882a593Smuzhiyun 					     TRAP_TO_CPU, false),
819*4882a593Smuzhiyun 		},
820*4882a593Smuzhiyun 	},
821*4882a593Smuzhiyun 	{
822*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_NEIGH_SOLICIT,
823*4882a593Smuzhiyun 					      NEIGH_DISCOVERY, TRAP),
824*4882a593Smuzhiyun 		.listeners_arr = {
825*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(L3_IPV6_NEIGHBOR_SOLICITATION,
826*4882a593Smuzhiyun 					  NEIGH_DISCOVERY, TRAP_TO_CPU, false),
827*4882a593Smuzhiyun 		},
828*4882a593Smuzhiyun 	},
829*4882a593Smuzhiyun 	{
830*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_NEIGH_ADVERT,
831*4882a593Smuzhiyun 					      NEIGH_DISCOVERY, TRAP),
832*4882a593Smuzhiyun 		.listeners_arr = {
833*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(L3_IPV6_NEIGHBOR_ADVERTISEMENT,
834*4882a593Smuzhiyun 					  NEIGH_DISCOVERY, TRAP_TO_CPU, false),
835*4882a593Smuzhiyun 		},
836*4882a593Smuzhiyun 	},
837*4882a593Smuzhiyun 	{
838*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_BFD, BFD, TRAP),
839*4882a593Smuzhiyun 		.listeners_arr = {
840*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV4_BFD, BFD, TRAP_TO_CPU, false),
841*4882a593Smuzhiyun 		},
842*4882a593Smuzhiyun 	},
843*4882a593Smuzhiyun 	{
844*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_BFD, BFD, TRAP),
845*4882a593Smuzhiyun 		.listeners_arr = {
846*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_BFD, BFD, TRAP_TO_CPU, false),
847*4882a593Smuzhiyun 		},
848*4882a593Smuzhiyun 	},
849*4882a593Smuzhiyun 	{
850*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_OSPF, OSPF, TRAP),
851*4882a593Smuzhiyun 		.listeners_arr = {
852*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV4_OSPF, OSPF, TRAP_TO_CPU, false),
853*4882a593Smuzhiyun 		},
854*4882a593Smuzhiyun 	},
855*4882a593Smuzhiyun 	{
856*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_OSPF, OSPF, TRAP),
857*4882a593Smuzhiyun 		.listeners_arr = {
858*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_OSPF, OSPF, TRAP_TO_CPU, false),
859*4882a593Smuzhiyun 		},
860*4882a593Smuzhiyun 	},
861*4882a593Smuzhiyun 	{
862*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_BGP, BGP, TRAP),
863*4882a593Smuzhiyun 		.listeners_arr = {
864*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV4_BGP, BGP, TRAP_TO_CPU, false),
865*4882a593Smuzhiyun 		},
866*4882a593Smuzhiyun 	},
867*4882a593Smuzhiyun 	{
868*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_BGP, BGP, TRAP),
869*4882a593Smuzhiyun 		.listeners_arr = {
870*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_BGP, BGP, TRAP_TO_CPU, false),
871*4882a593Smuzhiyun 		},
872*4882a593Smuzhiyun 	},
873*4882a593Smuzhiyun 	{
874*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_VRRP, VRRP, TRAP),
875*4882a593Smuzhiyun 		.listeners_arr = {
876*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV4_VRRP, VRRP, TRAP_TO_CPU, false),
877*4882a593Smuzhiyun 		},
878*4882a593Smuzhiyun 	},
879*4882a593Smuzhiyun 	{
880*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_VRRP, VRRP, TRAP),
881*4882a593Smuzhiyun 		.listeners_arr = {
882*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_VRRP, VRRP, TRAP_TO_CPU, false),
883*4882a593Smuzhiyun 		},
884*4882a593Smuzhiyun 	},
885*4882a593Smuzhiyun 	{
886*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_PIM, PIM, TRAP),
887*4882a593Smuzhiyun 		.listeners_arr = {
888*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV4_PIM, PIM, TRAP_TO_CPU, false),
889*4882a593Smuzhiyun 		},
890*4882a593Smuzhiyun 	},
891*4882a593Smuzhiyun 	{
892*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_PIM, PIM, TRAP),
893*4882a593Smuzhiyun 		.listeners_arr = {
894*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_PIM, PIM, TRAP_TO_CPU, false),
895*4882a593Smuzhiyun 		},
896*4882a593Smuzhiyun 	},
897*4882a593Smuzhiyun 	{
898*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(UC_LB, UC_LB, MIRROR),
899*4882a593Smuzhiyun 		.listeners_arr = {
900*4882a593Smuzhiyun 			MLXSW_SP_RXL_L3_MARK(LBERROR, LBERROR, MIRROR_TO_CPU,
901*4882a593Smuzhiyun 					     false),
902*4882a593Smuzhiyun 		},
903*4882a593Smuzhiyun 	},
904*4882a593Smuzhiyun 	{
905*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(LOCAL_ROUTE, LOCAL_DELIVERY,
906*4882a593Smuzhiyun 					      TRAP),
907*4882a593Smuzhiyun 		.listeners_arr = {
908*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IP2ME, IP2ME, TRAP_TO_CPU, false),
909*4882a593Smuzhiyun 		},
910*4882a593Smuzhiyun 	},
911*4882a593Smuzhiyun 	{
912*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(EXTERNAL_ROUTE, EXTERNAL_DELIVERY,
913*4882a593Smuzhiyun 					      TRAP),
914*4882a593Smuzhiyun 		.listeners_arr = {
915*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(RTR_INGRESS0, EXTERNAL_ROUTE,
916*4882a593Smuzhiyun 					  TRAP_TO_CPU, false),
917*4882a593Smuzhiyun 		},
918*4882a593Smuzhiyun 	},
919*4882a593Smuzhiyun 	{
920*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_UC_DIP_LINK_LOCAL_SCOPE,
921*4882a593Smuzhiyun 					      LOCAL_DELIVERY, TRAP),
922*4882a593Smuzhiyun 		.listeners_arr = {
923*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_LINK_LOCAL_DEST, IP2ME,
924*4882a593Smuzhiyun 					  TRAP_TO_CPU, false),
925*4882a593Smuzhiyun 		},
926*4882a593Smuzhiyun 	},
927*4882a593Smuzhiyun 	{
928*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV4_ROUTER_ALERT, LOCAL_DELIVERY,
929*4882a593Smuzhiyun 					      TRAP),
930*4882a593Smuzhiyun 		.listeners_arr = {
931*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV4, IP2ME, TRAP_TO_CPU,
932*4882a593Smuzhiyun 					  false),
933*4882a593Smuzhiyun 		},
934*4882a593Smuzhiyun 	},
935*4882a593Smuzhiyun 	{
936*4882a593Smuzhiyun 		/* IPV6_ROUTER_ALERT is defined in uAPI as 22, but it is not
937*4882a593Smuzhiyun 		 * used in this file, so undefine it.
938*4882a593Smuzhiyun 		 */
939*4882a593Smuzhiyun 		#undef IPV6_ROUTER_ALERT
940*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_ROUTER_ALERT, LOCAL_DELIVERY,
941*4882a593Smuzhiyun 					      TRAP),
942*4882a593Smuzhiyun 		.listeners_arr = {
943*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV6, IP2ME, TRAP_TO_CPU,
944*4882a593Smuzhiyun 					  false),
945*4882a593Smuzhiyun 		},
946*4882a593Smuzhiyun 	},
947*4882a593Smuzhiyun 	{
948*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_DIP_ALL_NODES, IPV6, TRAP),
949*4882a593Smuzhiyun 		.listeners_arr = {
950*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_ALL_NODES_LINK, IPV6,
951*4882a593Smuzhiyun 					  TRAP_TO_CPU, false),
952*4882a593Smuzhiyun 		},
953*4882a593Smuzhiyun 	},
954*4882a593Smuzhiyun 	{
955*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_DIP_ALL_ROUTERS, IPV6, TRAP),
956*4882a593Smuzhiyun 		.listeners_arr = {
957*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(IPV6_ALL_ROUTERS_LINK, IPV6,
958*4882a593Smuzhiyun 					  TRAP_TO_CPU, false),
959*4882a593Smuzhiyun 		},
960*4882a593Smuzhiyun 	},
961*4882a593Smuzhiyun 	{
962*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_ROUTER_SOLICIT, IPV6, TRAP),
963*4882a593Smuzhiyun 		.listeners_arr = {
964*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(L3_IPV6_ROUTER_SOLICITATION, IPV6,
965*4882a593Smuzhiyun 					  TRAP_TO_CPU, false),
966*4882a593Smuzhiyun 		},
967*4882a593Smuzhiyun 	},
968*4882a593Smuzhiyun 	{
969*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_ROUTER_ADVERT, IPV6, TRAP),
970*4882a593Smuzhiyun 		.listeners_arr = {
971*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(L3_IPV6_ROUTER_ADVERTISEMENT, IPV6,
972*4882a593Smuzhiyun 					  TRAP_TO_CPU, false),
973*4882a593Smuzhiyun 		},
974*4882a593Smuzhiyun 	},
975*4882a593Smuzhiyun 	{
976*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(IPV6_REDIRECT, IPV6, TRAP),
977*4882a593Smuzhiyun 		.listeners_arr = {
978*4882a593Smuzhiyun 			MLXSW_SP_RXL_MARK(L3_IPV6_REDIRECTION, IPV6,
979*4882a593Smuzhiyun 					  TRAP_TO_CPU, false),
980*4882a593Smuzhiyun 		},
981*4882a593Smuzhiyun 	},
982*4882a593Smuzhiyun 	{
983*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(PTP_EVENT, PTP_EVENT, TRAP),
984*4882a593Smuzhiyun 		.listeners_arr = {
985*4882a593Smuzhiyun 			MLXSW_RXL(mlxsw_sp_rx_ptp_listener, PTP0, TRAP_TO_CPU,
986*4882a593Smuzhiyun 				  false, SP_PTP0, DISCARD),
987*4882a593Smuzhiyun 		},
988*4882a593Smuzhiyun 	},
989*4882a593Smuzhiyun 	{
990*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(PTP_GENERAL, PTP_GENERAL, TRAP),
991*4882a593Smuzhiyun 		.listeners_arr = {
992*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(PTP1, PTP1, TRAP_TO_CPU, false),
993*4882a593Smuzhiyun 		},
994*4882a593Smuzhiyun 	},
995*4882a593Smuzhiyun 	{
996*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(FLOW_ACTION_SAMPLE, ACL_SAMPLE,
997*4882a593Smuzhiyun 					      MIRROR),
998*4882a593Smuzhiyun 		.listeners_arr = {
999*4882a593Smuzhiyun 			MLXSW_RXL(mlxsw_sp_rx_sample_listener, PKT_SAMPLE,
1000*4882a593Smuzhiyun 				  MIRROR_TO_CPU, false, SP_PKT_SAMPLE, DISCARD),
1001*4882a593Smuzhiyun 		},
1002*4882a593Smuzhiyun 	},
1003*4882a593Smuzhiyun 	{
1004*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_CONTROL(FLOW_ACTION_TRAP, ACL_TRAP, TRAP),
1005*4882a593Smuzhiyun 		.listeners_arr = {
1006*4882a593Smuzhiyun 			MLXSW_SP_RXL_NO_MARK(ACL0, FLOW_LOGGING, TRAP_TO_CPU,
1007*4882a593Smuzhiyun 					     false),
1008*4882a593Smuzhiyun 		},
1009*4882a593Smuzhiyun 	},
1010*4882a593Smuzhiyun };
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun static struct mlxsw_sp_trap_policer_item *
mlxsw_sp_trap_policer_item_lookup(struct mlxsw_sp * mlxsw_sp,u32 id)1013*4882a593Smuzhiyun mlxsw_sp_trap_policer_item_lookup(struct mlxsw_sp *mlxsw_sp, u32 id)
1014*4882a593Smuzhiyun {
1015*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1016*4882a593Smuzhiyun 	int i;
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	for (i = 0; i < trap->policers_count; i++) {
1019*4882a593Smuzhiyun 		if (trap->policer_items_arr[i].policer.id == id)
1020*4882a593Smuzhiyun 			return &trap->policer_items_arr[i];
1021*4882a593Smuzhiyun 	}
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun 	return NULL;
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun static struct mlxsw_sp_trap_group_item *
mlxsw_sp_trap_group_item_lookup(struct mlxsw_sp * mlxsw_sp,u16 id)1027*4882a593Smuzhiyun mlxsw_sp_trap_group_item_lookup(struct mlxsw_sp *mlxsw_sp, u16 id)
1028*4882a593Smuzhiyun {
1029*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1030*4882a593Smuzhiyun 	int i;
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	for (i = 0; i < trap->groups_count; i++) {
1033*4882a593Smuzhiyun 		if (trap->group_items_arr[i].group.id == id)
1034*4882a593Smuzhiyun 			return &trap->group_items_arr[i];
1035*4882a593Smuzhiyun 	}
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun 	return NULL;
1038*4882a593Smuzhiyun }
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun static struct mlxsw_sp_trap_item *
mlxsw_sp_trap_item_lookup(struct mlxsw_sp * mlxsw_sp,u16 id)1041*4882a593Smuzhiyun mlxsw_sp_trap_item_lookup(struct mlxsw_sp *mlxsw_sp, u16 id)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1044*4882a593Smuzhiyun 	int i;
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun 	for (i = 0; i < trap->traps_count; i++) {
1047*4882a593Smuzhiyun 		if (trap->trap_items_arr[i].trap.id == id)
1048*4882a593Smuzhiyun 			return &trap->trap_items_arr[i];
1049*4882a593Smuzhiyun 	}
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun 	return NULL;
1052*4882a593Smuzhiyun }
1053*4882a593Smuzhiyun 
mlxsw_sp_trap_cpu_policers_set(struct mlxsw_sp * mlxsw_sp)1054*4882a593Smuzhiyun static int mlxsw_sp_trap_cpu_policers_set(struct mlxsw_sp *mlxsw_sp)
1055*4882a593Smuzhiyun {
1056*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1057*4882a593Smuzhiyun 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
1058*4882a593Smuzhiyun 	u16 hw_id;
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun 	/* The purpose of "thin" policer is to drop as many packets
1061*4882a593Smuzhiyun 	 * as possible. The dummy group is using it.
1062*4882a593Smuzhiyun 	 */
1063*4882a593Smuzhiyun 	hw_id = find_first_zero_bit(trap->policers_usage, trap->max_policers);
1064*4882a593Smuzhiyun 	if (WARN_ON(hw_id == trap->max_policers))
1065*4882a593Smuzhiyun 		return -ENOBUFS;
1066*4882a593Smuzhiyun 
1067*4882a593Smuzhiyun 	__set_bit(hw_id, trap->policers_usage);
1068*4882a593Smuzhiyun 	trap->thin_policer_hw_id = hw_id;
1069*4882a593Smuzhiyun 	mlxsw_reg_qpcr_pack(qpcr_pl, hw_id, MLXSW_REG_QPCR_IR_UNITS_M,
1070*4882a593Smuzhiyun 			    false, 1, 4);
1071*4882a593Smuzhiyun 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun 
mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp * mlxsw_sp)1074*4882a593Smuzhiyun static int mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp *mlxsw_sp)
1075*4882a593Smuzhiyun {
1076*4882a593Smuzhiyun 	char htgt_pl[MLXSW_REG_HTGT_LEN];
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun 	mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SP_DUMMY,
1079*4882a593Smuzhiyun 			    mlxsw_sp->trap->thin_policer_hw_id, 0, 1);
1080*4882a593Smuzhiyun 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun 
mlxsw_sp_trap_policer_items_arr_init(struct mlxsw_sp * mlxsw_sp)1083*4882a593Smuzhiyun static int mlxsw_sp_trap_policer_items_arr_init(struct mlxsw_sp *mlxsw_sp)
1084*4882a593Smuzhiyun {
1085*4882a593Smuzhiyun 	size_t arr_size = ARRAY_SIZE(mlxsw_sp_trap_policer_items_arr);
1086*4882a593Smuzhiyun 	size_t elem_size = sizeof(struct mlxsw_sp_trap_policer_item);
1087*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1088*4882a593Smuzhiyun 	size_t free_policers = 0;
1089*4882a593Smuzhiyun 	u32 last_id;
1090*4882a593Smuzhiyun 	int i;
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun 	for_each_clear_bit(i, trap->policers_usage, trap->max_policers)
1093*4882a593Smuzhiyun 		free_policers++;
1094*4882a593Smuzhiyun 
1095*4882a593Smuzhiyun 	if (arr_size > free_policers) {
1096*4882a593Smuzhiyun 		dev_err(mlxsw_sp->bus_info->dev, "Exceeded number of supported packet trap policers\n");
1097*4882a593Smuzhiyun 		return -ENOBUFS;
1098*4882a593Smuzhiyun 	}
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun 	trap->policer_items_arr = kcalloc(free_policers, elem_size, GFP_KERNEL);
1101*4882a593Smuzhiyun 	if (!trap->policer_items_arr)
1102*4882a593Smuzhiyun 		return -ENOMEM;
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun 	trap->policers_count = free_policers;
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun 	/* Initialize policer items array with pre-defined policers. */
1107*4882a593Smuzhiyun 	memcpy(trap->policer_items_arr, mlxsw_sp_trap_policer_items_arr,
1108*4882a593Smuzhiyun 	       elem_size * arr_size);
1109*4882a593Smuzhiyun 
1110*4882a593Smuzhiyun 	/* Initialize policer items array with the rest of the available
1111*4882a593Smuzhiyun 	 * policers.
1112*4882a593Smuzhiyun 	 */
1113*4882a593Smuzhiyun 	last_id = mlxsw_sp_trap_policer_items_arr[arr_size - 1].policer.id;
1114*4882a593Smuzhiyun 	for (i = arr_size; i < trap->policers_count; i++) {
1115*4882a593Smuzhiyun 		const struct mlxsw_sp_trap_policer_item *policer_item;
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun 		/* Use parameters set for first policer and override
1118*4882a593Smuzhiyun 		 * relevant ones.
1119*4882a593Smuzhiyun 		 */
1120*4882a593Smuzhiyun 		policer_item = &mlxsw_sp_trap_policer_items_arr[0];
1121*4882a593Smuzhiyun 		trap->policer_items_arr[i] = *policer_item;
1122*4882a593Smuzhiyun 		trap->policer_items_arr[i].policer.id = ++last_id;
1123*4882a593Smuzhiyun 		trap->policer_items_arr[i].policer.init_rate = 1;
1124*4882a593Smuzhiyun 		trap->policer_items_arr[i].policer.init_burst = 16;
1125*4882a593Smuzhiyun 	}
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun 	return 0;
1128*4882a593Smuzhiyun }
1129*4882a593Smuzhiyun 
mlxsw_sp_trap_policer_items_arr_fini(struct mlxsw_sp * mlxsw_sp)1130*4882a593Smuzhiyun static void mlxsw_sp_trap_policer_items_arr_fini(struct mlxsw_sp *mlxsw_sp)
1131*4882a593Smuzhiyun {
1132*4882a593Smuzhiyun 	kfree(mlxsw_sp->trap->policer_items_arr);
1133*4882a593Smuzhiyun }
1134*4882a593Smuzhiyun 
mlxsw_sp_trap_policers_init(struct mlxsw_sp * mlxsw_sp)1135*4882a593Smuzhiyun static int mlxsw_sp_trap_policers_init(struct mlxsw_sp *mlxsw_sp)
1136*4882a593Smuzhiyun {
1137*4882a593Smuzhiyun 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1138*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_policer_item *policer_item;
1139*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1140*4882a593Smuzhiyun 	int err, i;
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun 	err = mlxsw_sp_trap_policer_items_arr_init(mlxsw_sp);
1143*4882a593Smuzhiyun 	if (err)
1144*4882a593Smuzhiyun 		return err;
1145*4882a593Smuzhiyun 
1146*4882a593Smuzhiyun 	for (i = 0; i < trap->policers_count; i++) {
1147*4882a593Smuzhiyun 		policer_item = &trap->policer_items_arr[i];
1148*4882a593Smuzhiyun 		err = devlink_trap_policers_register(devlink,
1149*4882a593Smuzhiyun 						     &policer_item->policer, 1);
1150*4882a593Smuzhiyun 		if (err)
1151*4882a593Smuzhiyun 			goto err_trap_policer_register;
1152*4882a593Smuzhiyun 	}
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun 	return 0;
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun err_trap_policer_register:
1157*4882a593Smuzhiyun 	for (i--; i >= 0; i--) {
1158*4882a593Smuzhiyun 		policer_item = &trap->policer_items_arr[i];
1159*4882a593Smuzhiyun 		devlink_trap_policers_unregister(devlink,
1160*4882a593Smuzhiyun 						 &policer_item->policer, 1);
1161*4882a593Smuzhiyun 	}
1162*4882a593Smuzhiyun 	mlxsw_sp_trap_policer_items_arr_fini(mlxsw_sp);
1163*4882a593Smuzhiyun 	return err;
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun 
mlxsw_sp_trap_policers_fini(struct mlxsw_sp * mlxsw_sp)1166*4882a593Smuzhiyun static void mlxsw_sp_trap_policers_fini(struct mlxsw_sp *mlxsw_sp)
1167*4882a593Smuzhiyun {
1168*4882a593Smuzhiyun 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1169*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_policer_item *policer_item;
1170*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1171*4882a593Smuzhiyun 	int i;
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 	for (i = trap->policers_count - 1; i >= 0; i--) {
1174*4882a593Smuzhiyun 		policer_item = &trap->policer_items_arr[i];
1175*4882a593Smuzhiyun 		devlink_trap_policers_unregister(devlink,
1176*4882a593Smuzhiyun 						 &policer_item->policer, 1);
1177*4882a593Smuzhiyun 	}
1178*4882a593Smuzhiyun 	mlxsw_sp_trap_policer_items_arr_fini(mlxsw_sp);
1179*4882a593Smuzhiyun }
1180*4882a593Smuzhiyun 
mlxsw_sp_trap_group_items_arr_init(struct mlxsw_sp * mlxsw_sp)1181*4882a593Smuzhiyun static int mlxsw_sp_trap_group_items_arr_init(struct mlxsw_sp *mlxsw_sp)
1182*4882a593Smuzhiyun {
1183*4882a593Smuzhiyun 	size_t common_groups_count = ARRAY_SIZE(mlxsw_sp_trap_group_items_arr);
1184*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_group_item *spec_group_items_arr;
1185*4882a593Smuzhiyun 	size_t elem_size = sizeof(struct mlxsw_sp_trap_group_item);
1186*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1187*4882a593Smuzhiyun 	size_t groups_count, spec_groups_count;
1188*4882a593Smuzhiyun 	int err;
1189*4882a593Smuzhiyun 
1190*4882a593Smuzhiyun 	err = mlxsw_sp->trap_ops->groups_init(mlxsw_sp, &spec_group_items_arr,
1191*4882a593Smuzhiyun 					      &spec_groups_count);
1192*4882a593Smuzhiyun 	if (err)
1193*4882a593Smuzhiyun 		return err;
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun 	/* The group items array is created by concatenating the common trap
1196*4882a593Smuzhiyun 	 * group items and the ASIC-specific trap group items.
1197*4882a593Smuzhiyun 	 */
1198*4882a593Smuzhiyun 	groups_count = common_groups_count + spec_groups_count;
1199*4882a593Smuzhiyun 	trap->group_items_arr = kcalloc(groups_count, elem_size, GFP_KERNEL);
1200*4882a593Smuzhiyun 	if (!trap->group_items_arr)
1201*4882a593Smuzhiyun 		return -ENOMEM;
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	memcpy(trap->group_items_arr, mlxsw_sp_trap_group_items_arr,
1204*4882a593Smuzhiyun 	       elem_size * common_groups_count);
1205*4882a593Smuzhiyun 	memcpy(trap->group_items_arr + common_groups_count,
1206*4882a593Smuzhiyun 	       spec_group_items_arr, elem_size * spec_groups_count);
1207*4882a593Smuzhiyun 
1208*4882a593Smuzhiyun 	trap->groups_count = groups_count;
1209*4882a593Smuzhiyun 
1210*4882a593Smuzhiyun 	return 0;
1211*4882a593Smuzhiyun }
1212*4882a593Smuzhiyun 
mlxsw_sp_trap_group_items_arr_fini(struct mlxsw_sp * mlxsw_sp)1213*4882a593Smuzhiyun static void mlxsw_sp_trap_group_items_arr_fini(struct mlxsw_sp *mlxsw_sp)
1214*4882a593Smuzhiyun {
1215*4882a593Smuzhiyun 	kfree(mlxsw_sp->trap->group_items_arr);
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun 
mlxsw_sp_trap_groups_init(struct mlxsw_sp * mlxsw_sp)1218*4882a593Smuzhiyun static int mlxsw_sp_trap_groups_init(struct mlxsw_sp *mlxsw_sp)
1219*4882a593Smuzhiyun {
1220*4882a593Smuzhiyun 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1221*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_group_item *group_item;
1222*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1223*4882a593Smuzhiyun 	int err, i;
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun 	err = mlxsw_sp_trap_group_items_arr_init(mlxsw_sp);
1226*4882a593Smuzhiyun 	if (err)
1227*4882a593Smuzhiyun 		return err;
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun 	for (i = 0; i < trap->groups_count; i++) {
1230*4882a593Smuzhiyun 		group_item = &trap->group_items_arr[i];
1231*4882a593Smuzhiyun 		err = devlink_trap_groups_register(devlink, &group_item->group,
1232*4882a593Smuzhiyun 						   1);
1233*4882a593Smuzhiyun 		if (err)
1234*4882a593Smuzhiyun 			goto err_trap_group_register;
1235*4882a593Smuzhiyun 	}
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	return 0;
1238*4882a593Smuzhiyun 
1239*4882a593Smuzhiyun err_trap_group_register:
1240*4882a593Smuzhiyun 	for (i--; i >= 0; i--) {
1241*4882a593Smuzhiyun 		group_item = &trap->group_items_arr[i];
1242*4882a593Smuzhiyun 		devlink_trap_groups_unregister(devlink, &group_item->group, 1);
1243*4882a593Smuzhiyun 	}
1244*4882a593Smuzhiyun 	mlxsw_sp_trap_group_items_arr_fini(mlxsw_sp);
1245*4882a593Smuzhiyun 	return err;
1246*4882a593Smuzhiyun }
1247*4882a593Smuzhiyun 
mlxsw_sp_trap_groups_fini(struct mlxsw_sp * mlxsw_sp)1248*4882a593Smuzhiyun static void mlxsw_sp_trap_groups_fini(struct mlxsw_sp *mlxsw_sp)
1249*4882a593Smuzhiyun {
1250*4882a593Smuzhiyun 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1251*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1252*4882a593Smuzhiyun 	int i;
1253*4882a593Smuzhiyun 
1254*4882a593Smuzhiyun 	for (i = trap->groups_count - 1; i >= 0; i--) {
1255*4882a593Smuzhiyun 		const struct mlxsw_sp_trap_group_item *group_item;
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun 		group_item = &trap->group_items_arr[i];
1258*4882a593Smuzhiyun 		devlink_trap_groups_unregister(devlink, &group_item->group, 1);
1259*4882a593Smuzhiyun 	}
1260*4882a593Smuzhiyun 	mlxsw_sp_trap_group_items_arr_fini(mlxsw_sp);
1261*4882a593Smuzhiyun }
1262*4882a593Smuzhiyun 
1263*4882a593Smuzhiyun static bool
mlxsw_sp_trap_listener_is_valid(const struct mlxsw_listener * listener)1264*4882a593Smuzhiyun mlxsw_sp_trap_listener_is_valid(const struct mlxsw_listener *listener)
1265*4882a593Smuzhiyun {
1266*4882a593Smuzhiyun 	return listener->trap_id != 0;
1267*4882a593Smuzhiyun }
1268*4882a593Smuzhiyun 
mlxsw_sp_trap_items_arr_init(struct mlxsw_sp * mlxsw_sp)1269*4882a593Smuzhiyun static int mlxsw_sp_trap_items_arr_init(struct mlxsw_sp *mlxsw_sp)
1270*4882a593Smuzhiyun {
1271*4882a593Smuzhiyun 	size_t common_traps_count = ARRAY_SIZE(mlxsw_sp_trap_items_arr);
1272*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_item *spec_trap_items_arr;
1273*4882a593Smuzhiyun 	size_t elem_size = sizeof(struct mlxsw_sp_trap_item);
1274*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1275*4882a593Smuzhiyun 	size_t traps_count, spec_traps_count;
1276*4882a593Smuzhiyun 	int err;
1277*4882a593Smuzhiyun 
1278*4882a593Smuzhiyun 	err = mlxsw_sp->trap_ops->traps_init(mlxsw_sp, &spec_trap_items_arr,
1279*4882a593Smuzhiyun 					     &spec_traps_count);
1280*4882a593Smuzhiyun 	if (err)
1281*4882a593Smuzhiyun 		return err;
1282*4882a593Smuzhiyun 
1283*4882a593Smuzhiyun 	/* The trap items array is created by concatenating the common trap
1284*4882a593Smuzhiyun 	 * items and the ASIC-specific trap items.
1285*4882a593Smuzhiyun 	 */
1286*4882a593Smuzhiyun 	traps_count = common_traps_count + spec_traps_count;
1287*4882a593Smuzhiyun 	trap->trap_items_arr = kcalloc(traps_count, elem_size, GFP_KERNEL);
1288*4882a593Smuzhiyun 	if (!trap->trap_items_arr)
1289*4882a593Smuzhiyun 		return -ENOMEM;
1290*4882a593Smuzhiyun 
1291*4882a593Smuzhiyun 	memcpy(trap->trap_items_arr, mlxsw_sp_trap_items_arr,
1292*4882a593Smuzhiyun 	       elem_size * common_traps_count);
1293*4882a593Smuzhiyun 	memcpy(trap->trap_items_arr + common_traps_count,
1294*4882a593Smuzhiyun 	       spec_trap_items_arr, elem_size * spec_traps_count);
1295*4882a593Smuzhiyun 
1296*4882a593Smuzhiyun 	trap->traps_count = traps_count;
1297*4882a593Smuzhiyun 
1298*4882a593Smuzhiyun 	return 0;
1299*4882a593Smuzhiyun }
1300*4882a593Smuzhiyun 
mlxsw_sp_trap_items_arr_fini(struct mlxsw_sp * mlxsw_sp)1301*4882a593Smuzhiyun static void mlxsw_sp_trap_items_arr_fini(struct mlxsw_sp *mlxsw_sp)
1302*4882a593Smuzhiyun {
1303*4882a593Smuzhiyun 	kfree(mlxsw_sp->trap->trap_items_arr);
1304*4882a593Smuzhiyun }
1305*4882a593Smuzhiyun 
mlxsw_sp_traps_init(struct mlxsw_sp * mlxsw_sp)1306*4882a593Smuzhiyun static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
1307*4882a593Smuzhiyun {
1308*4882a593Smuzhiyun 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1309*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1310*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_item *trap_item;
1311*4882a593Smuzhiyun 	int err, i;
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun 	err = mlxsw_sp_trap_items_arr_init(mlxsw_sp);
1314*4882a593Smuzhiyun 	if (err)
1315*4882a593Smuzhiyun 		return err;
1316*4882a593Smuzhiyun 
1317*4882a593Smuzhiyun 	for (i = 0; i < trap->traps_count; i++) {
1318*4882a593Smuzhiyun 		trap_item = &trap->trap_items_arr[i];
1319*4882a593Smuzhiyun 		err = devlink_traps_register(devlink, &trap_item->trap, 1,
1320*4882a593Smuzhiyun 					     mlxsw_sp);
1321*4882a593Smuzhiyun 		if (err)
1322*4882a593Smuzhiyun 			goto err_trap_register;
1323*4882a593Smuzhiyun 	}
1324*4882a593Smuzhiyun 
1325*4882a593Smuzhiyun 	return 0;
1326*4882a593Smuzhiyun 
1327*4882a593Smuzhiyun err_trap_register:
1328*4882a593Smuzhiyun 	for (i--; i >= 0; i--) {
1329*4882a593Smuzhiyun 		trap_item = &trap->trap_items_arr[i];
1330*4882a593Smuzhiyun 		devlink_traps_unregister(devlink, &trap_item->trap, 1);
1331*4882a593Smuzhiyun 	}
1332*4882a593Smuzhiyun 	mlxsw_sp_trap_items_arr_fini(mlxsw_sp);
1333*4882a593Smuzhiyun 	return err;
1334*4882a593Smuzhiyun }
1335*4882a593Smuzhiyun 
mlxsw_sp_traps_fini(struct mlxsw_sp * mlxsw_sp)1336*4882a593Smuzhiyun static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
1337*4882a593Smuzhiyun {
1338*4882a593Smuzhiyun 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
1339*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1340*4882a593Smuzhiyun 	int i;
1341*4882a593Smuzhiyun 
1342*4882a593Smuzhiyun 	for (i = trap->traps_count - 1; i >= 0; i--) {
1343*4882a593Smuzhiyun 		const struct mlxsw_sp_trap_item *trap_item;
1344*4882a593Smuzhiyun 
1345*4882a593Smuzhiyun 		trap_item = &trap->trap_items_arr[i];
1346*4882a593Smuzhiyun 		devlink_traps_unregister(devlink, &trap_item->trap, 1);
1347*4882a593Smuzhiyun 	}
1348*4882a593Smuzhiyun 	mlxsw_sp_trap_items_arr_fini(mlxsw_sp);
1349*4882a593Smuzhiyun }
1350*4882a593Smuzhiyun 
mlxsw_sp_devlink_traps_init(struct mlxsw_sp * mlxsw_sp)1351*4882a593Smuzhiyun int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
1352*4882a593Smuzhiyun {
1353*4882a593Smuzhiyun 	int err;
1354*4882a593Smuzhiyun 
1355*4882a593Smuzhiyun 	err = mlxsw_sp_trap_cpu_policers_set(mlxsw_sp);
1356*4882a593Smuzhiyun 	if (err)
1357*4882a593Smuzhiyun 		return err;
1358*4882a593Smuzhiyun 
1359*4882a593Smuzhiyun 	err = mlxsw_sp_trap_dummy_group_init(mlxsw_sp);
1360*4882a593Smuzhiyun 	if (err)
1361*4882a593Smuzhiyun 		return err;
1362*4882a593Smuzhiyun 
1363*4882a593Smuzhiyun 	err = mlxsw_sp_trap_policers_init(mlxsw_sp);
1364*4882a593Smuzhiyun 	if (err)
1365*4882a593Smuzhiyun 		return err;
1366*4882a593Smuzhiyun 
1367*4882a593Smuzhiyun 	err = mlxsw_sp_trap_groups_init(mlxsw_sp);
1368*4882a593Smuzhiyun 	if (err)
1369*4882a593Smuzhiyun 		goto err_trap_groups_init;
1370*4882a593Smuzhiyun 
1371*4882a593Smuzhiyun 	err = mlxsw_sp_traps_init(mlxsw_sp);
1372*4882a593Smuzhiyun 	if (err)
1373*4882a593Smuzhiyun 		goto err_traps_init;
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun 	return 0;
1376*4882a593Smuzhiyun 
1377*4882a593Smuzhiyun err_traps_init:
1378*4882a593Smuzhiyun 	mlxsw_sp_trap_groups_fini(mlxsw_sp);
1379*4882a593Smuzhiyun err_trap_groups_init:
1380*4882a593Smuzhiyun 	mlxsw_sp_trap_policers_fini(mlxsw_sp);
1381*4882a593Smuzhiyun 	return err;
1382*4882a593Smuzhiyun }
1383*4882a593Smuzhiyun 
mlxsw_sp_devlink_traps_fini(struct mlxsw_sp * mlxsw_sp)1384*4882a593Smuzhiyun void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp)
1385*4882a593Smuzhiyun {
1386*4882a593Smuzhiyun 	mlxsw_sp_traps_fini(mlxsw_sp);
1387*4882a593Smuzhiyun 	mlxsw_sp_trap_groups_fini(mlxsw_sp);
1388*4882a593Smuzhiyun 	mlxsw_sp_trap_policers_fini(mlxsw_sp);
1389*4882a593Smuzhiyun }
1390*4882a593Smuzhiyun 
mlxsw_sp_trap_init(struct mlxsw_core * mlxsw_core,const struct devlink_trap * trap,void * trap_ctx)1391*4882a593Smuzhiyun int mlxsw_sp_trap_init(struct mlxsw_core *mlxsw_core,
1392*4882a593Smuzhiyun 		       const struct devlink_trap *trap, void *trap_ctx)
1393*4882a593Smuzhiyun {
1394*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1395*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_item *trap_item;
1396*4882a593Smuzhiyun 	int i;
1397*4882a593Smuzhiyun 
1398*4882a593Smuzhiyun 	trap_item = mlxsw_sp_trap_item_lookup(mlxsw_sp, trap->id);
1399*4882a593Smuzhiyun 	if (WARN_ON(!trap_item))
1400*4882a593Smuzhiyun 		return -EINVAL;
1401*4882a593Smuzhiyun 
1402*4882a593Smuzhiyun 	for (i = 0; i < MLXSW_SP_TRAP_LISTENERS_MAX; i++) {
1403*4882a593Smuzhiyun 		const struct mlxsw_listener *listener;
1404*4882a593Smuzhiyun 		int err;
1405*4882a593Smuzhiyun 
1406*4882a593Smuzhiyun 		listener = &trap_item->listeners_arr[i];
1407*4882a593Smuzhiyun 		if (!mlxsw_sp_trap_listener_is_valid(listener))
1408*4882a593Smuzhiyun 			continue;
1409*4882a593Smuzhiyun 		err = mlxsw_core_trap_register(mlxsw_core, listener, trap_ctx);
1410*4882a593Smuzhiyun 		if (err)
1411*4882a593Smuzhiyun 			return err;
1412*4882a593Smuzhiyun 	}
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun 	return 0;
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun 
mlxsw_sp_trap_fini(struct mlxsw_core * mlxsw_core,const struct devlink_trap * trap,void * trap_ctx)1417*4882a593Smuzhiyun void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core,
1418*4882a593Smuzhiyun 			const struct devlink_trap *trap, void *trap_ctx)
1419*4882a593Smuzhiyun {
1420*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1421*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_item *trap_item;
1422*4882a593Smuzhiyun 	int i;
1423*4882a593Smuzhiyun 
1424*4882a593Smuzhiyun 	trap_item = mlxsw_sp_trap_item_lookup(mlxsw_sp, trap->id);
1425*4882a593Smuzhiyun 	if (WARN_ON(!trap_item))
1426*4882a593Smuzhiyun 		return;
1427*4882a593Smuzhiyun 
1428*4882a593Smuzhiyun 	for (i = MLXSW_SP_TRAP_LISTENERS_MAX - 1; i >= 0; i--) {
1429*4882a593Smuzhiyun 		const struct mlxsw_listener *listener;
1430*4882a593Smuzhiyun 
1431*4882a593Smuzhiyun 		listener = &trap_item->listeners_arr[i];
1432*4882a593Smuzhiyun 		if (!mlxsw_sp_trap_listener_is_valid(listener))
1433*4882a593Smuzhiyun 			continue;
1434*4882a593Smuzhiyun 		mlxsw_core_trap_unregister(mlxsw_core, listener, trap_ctx);
1435*4882a593Smuzhiyun 	}
1436*4882a593Smuzhiyun }
1437*4882a593Smuzhiyun 
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)1438*4882a593Smuzhiyun int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
1439*4882a593Smuzhiyun 			     const struct devlink_trap *trap,
1440*4882a593Smuzhiyun 			     enum devlink_trap_action action,
1441*4882a593Smuzhiyun 			     struct netlink_ext_ack *extack)
1442*4882a593Smuzhiyun {
1443*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1444*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_item *trap_item;
1445*4882a593Smuzhiyun 	int i;
1446*4882a593Smuzhiyun 
1447*4882a593Smuzhiyun 	trap_item = mlxsw_sp_trap_item_lookup(mlxsw_sp, trap->id);
1448*4882a593Smuzhiyun 	if (WARN_ON(!trap_item))
1449*4882a593Smuzhiyun 		return -EINVAL;
1450*4882a593Smuzhiyun 
1451*4882a593Smuzhiyun 	if (trap_item->is_source) {
1452*4882a593Smuzhiyun 		NL_SET_ERR_MSG_MOD(extack, "Changing the action of source traps is not supported");
1453*4882a593Smuzhiyun 		return -EOPNOTSUPP;
1454*4882a593Smuzhiyun 	}
1455*4882a593Smuzhiyun 
1456*4882a593Smuzhiyun 	for (i = 0; i < MLXSW_SP_TRAP_LISTENERS_MAX; i++) {
1457*4882a593Smuzhiyun 		const struct mlxsw_listener *listener;
1458*4882a593Smuzhiyun 		bool enabled;
1459*4882a593Smuzhiyun 		int err;
1460*4882a593Smuzhiyun 
1461*4882a593Smuzhiyun 		listener = &trap_item->listeners_arr[i];
1462*4882a593Smuzhiyun 		if (!mlxsw_sp_trap_listener_is_valid(listener))
1463*4882a593Smuzhiyun 			continue;
1464*4882a593Smuzhiyun 
1465*4882a593Smuzhiyun 		switch (action) {
1466*4882a593Smuzhiyun 		case DEVLINK_TRAP_ACTION_DROP:
1467*4882a593Smuzhiyun 			enabled = false;
1468*4882a593Smuzhiyun 			break;
1469*4882a593Smuzhiyun 		case DEVLINK_TRAP_ACTION_TRAP:
1470*4882a593Smuzhiyun 			enabled = true;
1471*4882a593Smuzhiyun 			break;
1472*4882a593Smuzhiyun 		default:
1473*4882a593Smuzhiyun 			return -EINVAL;
1474*4882a593Smuzhiyun 		}
1475*4882a593Smuzhiyun 		err = mlxsw_core_trap_state_set(mlxsw_core, listener, enabled);
1476*4882a593Smuzhiyun 		if (err)
1477*4882a593Smuzhiyun 			return err;
1478*4882a593Smuzhiyun 	}
1479*4882a593Smuzhiyun 
1480*4882a593Smuzhiyun 	return 0;
1481*4882a593Smuzhiyun }
1482*4882a593Smuzhiyun 
1483*4882a593Smuzhiyun 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)1484*4882a593Smuzhiyun __mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
1485*4882a593Smuzhiyun 			   const struct devlink_trap_group *group,
1486*4882a593Smuzhiyun 			   u32 policer_id, struct netlink_ext_ack *extack)
1487*4882a593Smuzhiyun {
1488*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1489*4882a593Smuzhiyun 	u16 hw_policer_id = MLXSW_REG_HTGT_INVALID_POLICER;
1490*4882a593Smuzhiyun 	const struct mlxsw_sp_trap_group_item *group_item;
1491*4882a593Smuzhiyun 	char htgt_pl[MLXSW_REG_HTGT_LEN];
1492*4882a593Smuzhiyun 
1493*4882a593Smuzhiyun 	group_item = mlxsw_sp_trap_group_item_lookup(mlxsw_sp, group->id);
1494*4882a593Smuzhiyun 	if (WARN_ON(!group_item))
1495*4882a593Smuzhiyun 		return -EINVAL;
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun 	if (group_item->fixed_policer && policer_id != group->init_policer_id) {
1498*4882a593Smuzhiyun 		NL_SET_ERR_MSG_MOD(extack, "Changing the policer binding of this group is not supported");
1499*4882a593Smuzhiyun 		return -EOPNOTSUPP;
1500*4882a593Smuzhiyun 	}
1501*4882a593Smuzhiyun 
1502*4882a593Smuzhiyun 	if (policer_id) {
1503*4882a593Smuzhiyun 		struct mlxsw_sp_trap_policer_item *policer_item;
1504*4882a593Smuzhiyun 
1505*4882a593Smuzhiyun 		policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp,
1506*4882a593Smuzhiyun 								 policer_id);
1507*4882a593Smuzhiyun 		if (WARN_ON(!policer_item))
1508*4882a593Smuzhiyun 			return -EINVAL;
1509*4882a593Smuzhiyun 		hw_policer_id = policer_item->hw_id;
1510*4882a593Smuzhiyun 	}
1511*4882a593Smuzhiyun 
1512*4882a593Smuzhiyun 	mlxsw_reg_htgt_pack(htgt_pl, group_item->hw_group_id, hw_policer_id,
1513*4882a593Smuzhiyun 			    group_item->priority, group_item->priority);
1514*4882a593Smuzhiyun 	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
1515*4882a593Smuzhiyun }
1516*4882a593Smuzhiyun 
mlxsw_sp_trap_group_init(struct mlxsw_core * mlxsw_core,const struct devlink_trap_group * group)1517*4882a593Smuzhiyun int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
1518*4882a593Smuzhiyun 			     const struct devlink_trap_group *group)
1519*4882a593Smuzhiyun {
1520*4882a593Smuzhiyun 	return __mlxsw_sp_trap_group_init(mlxsw_core, group,
1521*4882a593Smuzhiyun 					  group->init_policer_id, NULL);
1522*4882a593Smuzhiyun }
1523*4882a593Smuzhiyun 
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)1524*4882a593Smuzhiyun int mlxsw_sp_trap_group_set(struct mlxsw_core *mlxsw_core,
1525*4882a593Smuzhiyun 			    const struct devlink_trap_group *group,
1526*4882a593Smuzhiyun 			    const struct devlink_trap_policer *policer,
1527*4882a593Smuzhiyun 			    struct netlink_ext_ack *extack)
1528*4882a593Smuzhiyun {
1529*4882a593Smuzhiyun 	u32 policer_id = policer ? policer->id : 0;
1530*4882a593Smuzhiyun 
1531*4882a593Smuzhiyun 	return __mlxsw_sp_trap_group_init(mlxsw_core, group, policer_id,
1532*4882a593Smuzhiyun 					  extack);
1533*4882a593Smuzhiyun }
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun static int
mlxsw_sp_trap_policer_item_init(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_trap_policer_item * policer_item)1536*4882a593Smuzhiyun mlxsw_sp_trap_policer_item_init(struct mlxsw_sp *mlxsw_sp,
1537*4882a593Smuzhiyun 				struct mlxsw_sp_trap_policer_item *policer_item)
1538*4882a593Smuzhiyun {
1539*4882a593Smuzhiyun 	struct mlxsw_sp_trap *trap = mlxsw_sp->trap;
1540*4882a593Smuzhiyun 	u16 hw_id;
1541*4882a593Smuzhiyun 
1542*4882a593Smuzhiyun 	/* We should be able to allocate a policer because the number of
1543*4882a593Smuzhiyun 	 * policers we registered with devlink is in according with the number
1544*4882a593Smuzhiyun 	 * of available policers.
1545*4882a593Smuzhiyun 	 */
1546*4882a593Smuzhiyun 	hw_id = find_first_zero_bit(trap->policers_usage, trap->max_policers);
1547*4882a593Smuzhiyun 	if (WARN_ON(hw_id == trap->max_policers))
1548*4882a593Smuzhiyun 		return -ENOBUFS;
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun 	__set_bit(hw_id, trap->policers_usage);
1551*4882a593Smuzhiyun 	policer_item->hw_id = hw_id;
1552*4882a593Smuzhiyun 
1553*4882a593Smuzhiyun 	return 0;
1554*4882a593Smuzhiyun }
1555*4882a593Smuzhiyun 
1556*4882a593Smuzhiyun static void
mlxsw_sp_trap_policer_item_fini(struct mlxsw_sp * mlxsw_sp,struct mlxsw_sp_trap_policer_item * policer_item)1557*4882a593Smuzhiyun mlxsw_sp_trap_policer_item_fini(struct mlxsw_sp *mlxsw_sp,
1558*4882a593Smuzhiyun 				struct mlxsw_sp_trap_policer_item *policer_item)
1559*4882a593Smuzhiyun {
1560*4882a593Smuzhiyun 	__clear_bit(policer_item->hw_id, mlxsw_sp->trap->policers_usage);
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun 
mlxsw_sp_trap_policer_bs(u64 burst,u8 * p_burst_size,struct netlink_ext_ack * extack)1563*4882a593Smuzhiyun static int mlxsw_sp_trap_policer_bs(u64 burst, u8 *p_burst_size,
1564*4882a593Smuzhiyun 				    struct netlink_ext_ack *extack)
1565*4882a593Smuzhiyun {
1566*4882a593Smuzhiyun 	int bs = fls64(burst) - 1;
1567*4882a593Smuzhiyun 
1568*4882a593Smuzhiyun 	if (burst != (BIT_ULL(bs))) {
1569*4882a593Smuzhiyun 		NL_SET_ERR_MSG_MOD(extack, "Policer burst size is not power of two");
1570*4882a593Smuzhiyun 		return -EINVAL;
1571*4882a593Smuzhiyun 	}
1572*4882a593Smuzhiyun 
1573*4882a593Smuzhiyun 	*p_burst_size = bs;
1574*4882a593Smuzhiyun 
1575*4882a593Smuzhiyun 	return 0;
1576*4882a593Smuzhiyun }
1577*4882a593Smuzhiyun 
__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)1578*4882a593Smuzhiyun static int __mlxsw_sp_trap_policer_set(struct mlxsw_sp *mlxsw_sp, u16 hw_id,
1579*4882a593Smuzhiyun 				       u64 rate, u64 burst, bool clear_counter,
1580*4882a593Smuzhiyun 				       struct netlink_ext_ack *extack)
1581*4882a593Smuzhiyun {
1582*4882a593Smuzhiyun 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
1583*4882a593Smuzhiyun 	u8 burst_size;
1584*4882a593Smuzhiyun 	int err;
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun 	err = mlxsw_sp_trap_policer_bs(burst, &burst_size, extack);
1587*4882a593Smuzhiyun 	if (err)
1588*4882a593Smuzhiyun 		return err;
1589*4882a593Smuzhiyun 
1590*4882a593Smuzhiyun 	mlxsw_reg_qpcr_pack(qpcr_pl, hw_id, MLXSW_REG_QPCR_IR_UNITS_M, false,
1591*4882a593Smuzhiyun 			    rate, burst_size);
1592*4882a593Smuzhiyun 	mlxsw_reg_qpcr_clear_counter_set(qpcr_pl, clear_counter);
1593*4882a593Smuzhiyun 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
1594*4882a593Smuzhiyun }
1595*4882a593Smuzhiyun 
mlxsw_sp_trap_policer_init(struct mlxsw_core * mlxsw_core,const struct devlink_trap_policer * policer)1596*4882a593Smuzhiyun int mlxsw_sp_trap_policer_init(struct mlxsw_core *mlxsw_core,
1597*4882a593Smuzhiyun 			       const struct devlink_trap_policer *policer)
1598*4882a593Smuzhiyun {
1599*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1600*4882a593Smuzhiyun 	struct mlxsw_sp_trap_policer_item *policer_item;
1601*4882a593Smuzhiyun 	int err;
1602*4882a593Smuzhiyun 
1603*4882a593Smuzhiyun 	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
1604*4882a593Smuzhiyun 	if (WARN_ON(!policer_item))
1605*4882a593Smuzhiyun 		return -EINVAL;
1606*4882a593Smuzhiyun 
1607*4882a593Smuzhiyun 	err = mlxsw_sp_trap_policer_item_init(mlxsw_sp, policer_item);
1608*4882a593Smuzhiyun 	if (err)
1609*4882a593Smuzhiyun 		return err;
1610*4882a593Smuzhiyun 
1611*4882a593Smuzhiyun 	err = __mlxsw_sp_trap_policer_set(mlxsw_sp, policer_item->hw_id,
1612*4882a593Smuzhiyun 					  policer->init_rate,
1613*4882a593Smuzhiyun 					  policer->init_burst, true, NULL);
1614*4882a593Smuzhiyun 	if (err)
1615*4882a593Smuzhiyun 		goto err_trap_policer_set;
1616*4882a593Smuzhiyun 
1617*4882a593Smuzhiyun 	return 0;
1618*4882a593Smuzhiyun 
1619*4882a593Smuzhiyun err_trap_policer_set:
1620*4882a593Smuzhiyun 	mlxsw_sp_trap_policer_item_fini(mlxsw_sp, policer_item);
1621*4882a593Smuzhiyun 	return err;
1622*4882a593Smuzhiyun }
1623*4882a593Smuzhiyun 
mlxsw_sp_trap_policer_fini(struct mlxsw_core * mlxsw_core,const struct devlink_trap_policer * policer)1624*4882a593Smuzhiyun void mlxsw_sp_trap_policer_fini(struct mlxsw_core *mlxsw_core,
1625*4882a593Smuzhiyun 				const struct devlink_trap_policer *policer)
1626*4882a593Smuzhiyun {
1627*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1628*4882a593Smuzhiyun 	struct mlxsw_sp_trap_policer_item *policer_item;
1629*4882a593Smuzhiyun 
1630*4882a593Smuzhiyun 	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
1631*4882a593Smuzhiyun 	if (WARN_ON(!policer_item))
1632*4882a593Smuzhiyun 		return;
1633*4882a593Smuzhiyun 
1634*4882a593Smuzhiyun 	mlxsw_sp_trap_policer_item_fini(mlxsw_sp, policer_item);
1635*4882a593Smuzhiyun }
1636*4882a593Smuzhiyun 
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)1637*4882a593Smuzhiyun int mlxsw_sp_trap_policer_set(struct mlxsw_core *mlxsw_core,
1638*4882a593Smuzhiyun 			      const struct devlink_trap_policer *policer,
1639*4882a593Smuzhiyun 			      u64 rate, u64 burst,
1640*4882a593Smuzhiyun 			      struct netlink_ext_ack *extack)
1641*4882a593Smuzhiyun {
1642*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1643*4882a593Smuzhiyun 	struct mlxsw_sp_trap_policer_item *policer_item;
1644*4882a593Smuzhiyun 
1645*4882a593Smuzhiyun 	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
1646*4882a593Smuzhiyun 	if (WARN_ON(!policer_item))
1647*4882a593Smuzhiyun 		return -EINVAL;
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun 	return __mlxsw_sp_trap_policer_set(mlxsw_sp, policer_item->hw_id,
1650*4882a593Smuzhiyun 					   rate, burst, false, extack);
1651*4882a593Smuzhiyun }
1652*4882a593Smuzhiyun 
1653*4882a593Smuzhiyun int
mlxsw_sp_trap_policer_counter_get(struct mlxsw_core * mlxsw_core,const struct devlink_trap_policer * policer,u64 * p_drops)1654*4882a593Smuzhiyun mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core,
1655*4882a593Smuzhiyun 				  const struct devlink_trap_policer *policer,
1656*4882a593Smuzhiyun 				  u64 *p_drops)
1657*4882a593Smuzhiyun {
1658*4882a593Smuzhiyun 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
1659*4882a593Smuzhiyun 	struct mlxsw_sp_trap_policer_item *policer_item;
1660*4882a593Smuzhiyun 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
1661*4882a593Smuzhiyun 	int err;
1662*4882a593Smuzhiyun 
1663*4882a593Smuzhiyun 	policer_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, policer->id);
1664*4882a593Smuzhiyun 	if (WARN_ON(!policer_item))
1665*4882a593Smuzhiyun 		return -EINVAL;
1666*4882a593Smuzhiyun 
1667*4882a593Smuzhiyun 	mlxsw_reg_qpcr_pack(qpcr_pl, policer_item->hw_id,
1668*4882a593Smuzhiyun 			    MLXSW_REG_QPCR_IR_UNITS_M, false, 0, 0);
1669*4882a593Smuzhiyun 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
1670*4882a593Smuzhiyun 	if (err)
1671*4882a593Smuzhiyun 		return err;
1672*4882a593Smuzhiyun 
1673*4882a593Smuzhiyun 	*p_drops = mlxsw_reg_qpcr_violate_count_get(qpcr_pl);
1674*4882a593Smuzhiyun 
1675*4882a593Smuzhiyun 	return 0;
1676*4882a593Smuzhiyun }
1677*4882a593Smuzhiyun 
mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp * mlxsw_sp,u16 id,bool * p_enabled,u16 * p_hw_id)1678*4882a593Smuzhiyun int mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp *mlxsw_sp, u16 id,
1679*4882a593Smuzhiyun 					  bool *p_enabled, u16 *p_hw_id)
1680*4882a593Smuzhiyun {
1681*4882a593Smuzhiyun 	struct mlxsw_sp_trap_policer_item *pol_item;
1682*4882a593Smuzhiyun 	struct mlxsw_sp_trap_group_item *gr_item;
1683*4882a593Smuzhiyun 	u32 pol_id;
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun 	gr_item = mlxsw_sp_trap_group_item_lookup(mlxsw_sp, id);
1686*4882a593Smuzhiyun 	if (!gr_item)
1687*4882a593Smuzhiyun 		return -ENOENT;
1688*4882a593Smuzhiyun 
1689*4882a593Smuzhiyun 	pol_id = gr_item->group.init_policer_id;
1690*4882a593Smuzhiyun 	if (!pol_id) {
1691*4882a593Smuzhiyun 		*p_enabled = false;
1692*4882a593Smuzhiyun 		return 0;
1693*4882a593Smuzhiyun 	}
1694*4882a593Smuzhiyun 
1695*4882a593Smuzhiyun 	pol_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, pol_id);
1696*4882a593Smuzhiyun 	if (WARN_ON(!pol_item))
1697*4882a593Smuzhiyun 		return -ENOENT;
1698*4882a593Smuzhiyun 
1699*4882a593Smuzhiyun 	*p_enabled = true;
1700*4882a593Smuzhiyun 	*p_hw_id = pol_item->hw_id;
1701*4882a593Smuzhiyun 	return 0;
1702*4882a593Smuzhiyun }
1703*4882a593Smuzhiyun 
1704*4882a593Smuzhiyun static const struct mlxsw_sp_trap_group_item
1705*4882a593Smuzhiyun mlxsw_sp1_trap_group_items_arr[] = {
1706*4882a593Smuzhiyun };
1707*4882a593Smuzhiyun 
1708*4882a593Smuzhiyun static const struct mlxsw_sp_trap_item
1709*4882a593Smuzhiyun mlxsw_sp1_trap_items_arr[] = {
1710*4882a593Smuzhiyun };
1711*4882a593Smuzhiyun 
1712*4882a593Smuzhiyun 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)1713*4882a593Smuzhiyun mlxsw_sp1_trap_groups_init(struct mlxsw_sp *mlxsw_sp,
1714*4882a593Smuzhiyun 			   const struct mlxsw_sp_trap_group_item **arr,
1715*4882a593Smuzhiyun 			   size_t *p_groups_count)
1716*4882a593Smuzhiyun {
1717*4882a593Smuzhiyun 	*arr = mlxsw_sp1_trap_group_items_arr;
1718*4882a593Smuzhiyun 	*p_groups_count = ARRAY_SIZE(mlxsw_sp1_trap_group_items_arr);
1719*4882a593Smuzhiyun 
1720*4882a593Smuzhiyun 	return 0;
1721*4882a593Smuzhiyun }
1722*4882a593Smuzhiyun 
mlxsw_sp1_traps_init(struct mlxsw_sp * mlxsw_sp,const struct mlxsw_sp_trap_item ** arr,size_t * p_traps_count)1723*4882a593Smuzhiyun static int mlxsw_sp1_traps_init(struct mlxsw_sp *mlxsw_sp,
1724*4882a593Smuzhiyun 				const struct mlxsw_sp_trap_item **arr,
1725*4882a593Smuzhiyun 				size_t *p_traps_count)
1726*4882a593Smuzhiyun {
1727*4882a593Smuzhiyun 	*arr = mlxsw_sp1_trap_items_arr;
1728*4882a593Smuzhiyun 	*p_traps_count = ARRAY_SIZE(mlxsw_sp1_trap_items_arr);
1729*4882a593Smuzhiyun 
1730*4882a593Smuzhiyun 	return 0;
1731*4882a593Smuzhiyun }
1732*4882a593Smuzhiyun 
1733*4882a593Smuzhiyun const struct mlxsw_sp_trap_ops mlxsw_sp1_trap_ops = {
1734*4882a593Smuzhiyun 	.groups_init = mlxsw_sp1_trap_groups_init,
1735*4882a593Smuzhiyun 	.traps_init = mlxsw_sp1_traps_init,
1736*4882a593Smuzhiyun };
1737*4882a593Smuzhiyun 
1738*4882a593Smuzhiyun static const struct mlxsw_sp_trap_group_item
1739*4882a593Smuzhiyun mlxsw_sp2_trap_group_items_arr[] = {
1740*4882a593Smuzhiyun 	{
1741*4882a593Smuzhiyun 		.group = DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 20),
1742*4882a593Smuzhiyun 		.hw_group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_BUFFER_DISCARDS,
1743*4882a593Smuzhiyun 		.priority = 0,
1744*4882a593Smuzhiyun 		.fixed_policer = true,
1745*4882a593Smuzhiyun 	},
1746*4882a593Smuzhiyun };
1747*4882a593Smuzhiyun 
1748*4882a593Smuzhiyun static const struct mlxsw_sp_trap_item
1749*4882a593Smuzhiyun mlxsw_sp2_trap_items_arr[] = {
1750*4882a593Smuzhiyun 	{
1751*4882a593Smuzhiyun 		.trap = MLXSW_SP_TRAP_BUFFER_DROP(EARLY_DROP),
1752*4882a593Smuzhiyun 		.listeners_arr = {
1753*4882a593Smuzhiyun 			MLXSW_SP_RXL_BUFFER_DISCARD(INGRESS_WRED),
1754*4882a593Smuzhiyun 		},
1755*4882a593Smuzhiyun 		.is_source = true,
1756*4882a593Smuzhiyun 	},
1757*4882a593Smuzhiyun };
1758*4882a593Smuzhiyun 
1759*4882a593Smuzhiyun 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)1760*4882a593Smuzhiyun mlxsw_sp2_trap_groups_init(struct mlxsw_sp *mlxsw_sp,
1761*4882a593Smuzhiyun 			   const struct mlxsw_sp_trap_group_item **arr,
1762*4882a593Smuzhiyun 			   size_t *p_groups_count)
1763*4882a593Smuzhiyun {
1764*4882a593Smuzhiyun 	*arr = mlxsw_sp2_trap_group_items_arr;
1765*4882a593Smuzhiyun 	*p_groups_count = ARRAY_SIZE(mlxsw_sp2_trap_group_items_arr);
1766*4882a593Smuzhiyun 
1767*4882a593Smuzhiyun 	return 0;
1768*4882a593Smuzhiyun }
1769*4882a593Smuzhiyun 
mlxsw_sp2_traps_init(struct mlxsw_sp * mlxsw_sp,const struct mlxsw_sp_trap_item ** arr,size_t * p_traps_count)1770*4882a593Smuzhiyun static int mlxsw_sp2_traps_init(struct mlxsw_sp *mlxsw_sp,
1771*4882a593Smuzhiyun 				const struct mlxsw_sp_trap_item **arr,
1772*4882a593Smuzhiyun 				size_t *p_traps_count)
1773*4882a593Smuzhiyun {
1774*4882a593Smuzhiyun 	*arr = mlxsw_sp2_trap_items_arr;
1775*4882a593Smuzhiyun 	*p_traps_count = ARRAY_SIZE(mlxsw_sp2_trap_items_arr);
1776*4882a593Smuzhiyun 
1777*4882a593Smuzhiyun 	return 0;
1778*4882a593Smuzhiyun }
1779*4882a593Smuzhiyun 
1780*4882a593Smuzhiyun const struct mlxsw_sp_trap_ops mlxsw_sp2_trap_ops = {
1781*4882a593Smuzhiyun 	.groups_init = mlxsw_sp2_trap_groups_init,
1782*4882a593Smuzhiyun 	.traps_init = mlxsw_sp2_traps_init,
1783*4882a593Smuzhiyun };
1784