1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2019 Mellanox Technologies. All rights reserved */
3 
4 #include <linux/kernel.h>
5 #include <net/devlink.h>
6 #include <uapi/linux/devlink.h>
7 
8 #include "core.h"
9 #include "reg.h"
10 #include "spectrum.h"
11 
12 /* All driver-specific traps must be documented in
13  * Documentation/networking/devlink/mlxsw.rst
14  */
15 enum {
16 	DEVLINK_MLXSW_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX,
17 	DEVLINK_MLXSW_TRAP_ID_IRIF_DISABLED,
18 	DEVLINK_MLXSW_TRAP_ID_ERIF_DISABLED,
19 };
20 
21 #define DEVLINK_MLXSW_TRAP_NAME_IRIF_DISABLED \
22 	"irif_disabled"
23 #define DEVLINK_MLXSW_TRAP_NAME_ERIF_DISABLED \
24 	"erif_disabled"
25 
26 #define MLXSW_SP_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT
27 
28 static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port,
29 				      void *priv);
30 static void mlxsw_sp_rx_exception_listener(struct sk_buff *skb, u8 local_port,
31 					   void *trap_ctx);
32 
33 #define MLXSW_SP_TRAP_DROP(_id, _group_id)				      \
34 	DEVLINK_TRAP_GENERIC(DROP, DROP, _id,				      \
35 			     DEVLINK_TRAP_GROUP_GENERIC(_group_id),	      \
36 			     MLXSW_SP_TRAP_METADATA)
37 
38 #define MLXSW_SP_TRAP_DRIVER_DROP(_id, _group_id)			      \
39 	DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_MLXSW_TRAP_ID_##_id,	      \
40 			    DEVLINK_MLXSW_TRAP_NAME_##_id,		      \
41 			    DEVLINK_TRAP_GROUP_GENERIC(_group_id),	      \
42 			    MLXSW_SP_TRAP_METADATA)
43 
44 #define MLXSW_SP_TRAP_EXCEPTION(_id, _group_id)		      \
45 	DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id,			      \
46 			     DEVLINK_TRAP_GROUP_GENERIC(_group_id),	      \
47 			     MLXSW_SP_TRAP_METADATA)
48 
49 #define MLXSW_SP_RXL_DISCARD(_id, _group_id)				      \
50 	MLXSW_RXL(mlxsw_sp_rx_drop_listener, DISCARD_##_id, SET_FW_DEFAULT,   \
51 		  false, SP_##_group_id, DISCARD)
52 
53 #define MLXSW_SP_RXL_EXCEPTION(_id, _group_id, _action)			      \
54 	MLXSW_RXL(mlxsw_sp_rx_exception_listener, _id,			      \
55 		   _action, false, SP_##_group_id, DISCARD)
56 
57 static struct devlink_trap mlxsw_sp_traps_arr[] = {
58 	MLXSW_SP_TRAP_DROP(SMAC_MC, L2_DROPS),
59 	MLXSW_SP_TRAP_DROP(VLAN_TAG_MISMATCH, L2_DROPS),
60 	MLXSW_SP_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
61 	MLXSW_SP_TRAP_DROP(INGRESS_STP_FILTER, L2_DROPS),
62 	MLXSW_SP_TRAP_DROP(EMPTY_TX_LIST, L2_DROPS),
63 	MLXSW_SP_TRAP_DROP(PORT_LOOPBACK_FILTER, L2_DROPS),
64 	MLXSW_SP_TRAP_DROP(BLACKHOLE_ROUTE, L3_DROPS),
65 	MLXSW_SP_TRAP_DROP(NON_IP_PACKET, L3_DROPS),
66 	MLXSW_SP_TRAP_DROP(UC_DIP_MC_DMAC, L3_DROPS),
67 	MLXSW_SP_TRAP_DROP(DIP_LB, L3_DROPS),
68 	MLXSW_SP_TRAP_DROP(SIP_MC, L3_DROPS),
69 	MLXSW_SP_TRAP_DROP(SIP_LB, L3_DROPS),
70 	MLXSW_SP_TRAP_DROP(CORRUPTED_IP_HDR, L3_DROPS),
71 	MLXSW_SP_TRAP_DROP(IPV4_SIP_BC, L3_DROPS),
72 	MLXSW_SP_TRAP_DROP(IPV6_MC_DIP_RESERVED_SCOPE, L3_DROPS),
73 	MLXSW_SP_TRAP_DROP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, L3_DROPS),
74 	MLXSW_SP_TRAP_EXCEPTION(MTU_ERROR, L3_DROPS),
75 	MLXSW_SP_TRAP_EXCEPTION(TTL_ERROR, L3_DROPS),
76 	MLXSW_SP_TRAP_EXCEPTION(RPF, L3_DROPS),
77 	MLXSW_SP_TRAP_EXCEPTION(REJECT_ROUTE, L3_DROPS),
78 	MLXSW_SP_TRAP_EXCEPTION(UNRESOLVED_NEIGH, L3_DROPS),
79 	MLXSW_SP_TRAP_EXCEPTION(IPV4_LPM_UNICAST_MISS, L3_DROPS),
80 	MLXSW_SP_TRAP_EXCEPTION(IPV6_LPM_UNICAST_MISS, L3_DROPS),
81 	MLXSW_SP_TRAP_DRIVER_DROP(IRIF_DISABLED, L3_DROPS),
82 	MLXSW_SP_TRAP_DRIVER_DROP(ERIF_DISABLED, L3_DROPS),
83 	MLXSW_SP_TRAP_DROP(NON_ROUTABLE, L3_DROPS),
84 	MLXSW_SP_TRAP_EXCEPTION(DECAP_ERROR, TUNNEL_DROPS),
85 	MLXSW_SP_TRAP_DROP(OVERLAY_SMAC_MC, TUNNEL_DROPS),
86 };
87 
88 static struct mlxsw_listener mlxsw_sp_listeners_arr[] = {
89 	MLXSW_SP_RXL_DISCARD(ING_PACKET_SMAC_MC, L2_DISCARDS),
90 	MLXSW_SP_RXL_DISCARD(ING_SWITCH_VTAG_ALLOW, L2_DISCARDS),
91 	MLXSW_SP_RXL_DISCARD(ING_SWITCH_VLAN, L2_DISCARDS),
92 	MLXSW_SP_RXL_DISCARD(ING_SWITCH_STP, L2_DISCARDS),
93 	MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_UC, L2_DISCARDS),
94 	MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_MC_NULL, L2_DISCARDS),
95 	MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_LB, L2_DISCARDS),
96 	MLXSW_SP_RXL_DISCARD(ROUTER2, L3_DISCARDS),
97 	MLXSW_SP_RXL_DISCARD(ING_ROUTER_NON_IP_PACKET, L3_DISCARDS),
98 	MLXSW_SP_RXL_DISCARD(ING_ROUTER_UC_DIP_MC_DMAC, L3_DISCARDS),
99 	MLXSW_SP_RXL_DISCARD(ING_ROUTER_DIP_LB, L3_DISCARDS),
100 	MLXSW_SP_RXL_DISCARD(ING_ROUTER_SIP_MC, L3_DISCARDS),
101 	MLXSW_SP_RXL_DISCARD(ING_ROUTER_SIP_LB, L3_DISCARDS),
102 	MLXSW_SP_RXL_DISCARD(ING_ROUTER_CORRUPTED_IP_HDR, L3_DISCARDS),
103 	MLXSW_SP_RXL_DISCARD(ING_ROUTER_IPV4_SIP_BC, L3_DISCARDS),
104 	MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_RESERVED_SCOPE, L3_DISCARDS),
105 	MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, L3_DISCARDS),
106 	MLXSW_SP_RXL_EXCEPTION(MTUERROR, ROUTER_EXP, TRAP_TO_CPU),
107 	MLXSW_SP_RXL_EXCEPTION(TTLERROR, ROUTER_EXP, TRAP_TO_CPU),
108 	MLXSW_SP_RXL_EXCEPTION(RPF, RPF, TRAP_TO_CPU),
109 	MLXSW_SP_RXL_EXCEPTION(RTR_INGRESS1, REMOTE_ROUTE, TRAP_TO_CPU),
110 	MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV4, HOST_MISS, TRAP_TO_CPU),
111 	MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV6, HOST_MISS, TRAP_TO_CPU),
112 	MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER3, REMOTE_ROUTE,
113 			       TRAP_EXCEPTION_TO_CPU),
114 	MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM4, ROUTER_EXP,
115 			       TRAP_EXCEPTION_TO_CPU),
116 	MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM6, ROUTER_EXP,
117 			       TRAP_EXCEPTION_TO_CPU),
118 	MLXSW_SP_RXL_DISCARD(ROUTER_IRIF_EN, L3_DISCARDS),
119 	MLXSW_SP_RXL_DISCARD(ROUTER_ERIF_EN, L3_DISCARDS),
120 	MLXSW_SP_RXL_DISCARD(NON_ROUTABLE, L3_DISCARDS),
121 	MLXSW_SP_RXL_EXCEPTION(DECAP_ECN0, ROUTER_EXP, TRAP_EXCEPTION_TO_CPU),
122 	MLXSW_SP_RXL_EXCEPTION(IPIP_DECAP_ERROR, ROUTER_EXP,
123 			       TRAP_EXCEPTION_TO_CPU),
124 	MLXSW_SP_RXL_EXCEPTION(DISCARD_DEC_PKT, TUNNEL_DISCARDS,
125 			       TRAP_EXCEPTION_TO_CPU),
126 	MLXSW_SP_RXL_DISCARD(OVERLAY_SMAC_MC, TUNNEL_DISCARDS),
127 };
128 
129 /* Mapping between hardware trap and devlink trap. Multiple hardware traps can
130  * be mapped to the same devlink trap. Order is according to
131  * 'mlxsw_sp_listeners_arr'.
132  */
133 static u16 mlxsw_sp_listener_devlink_map[] = {
134 	DEVLINK_TRAP_GENERIC_ID_SMAC_MC,
135 	DEVLINK_TRAP_GENERIC_ID_VLAN_TAG_MISMATCH,
136 	DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER,
137 	DEVLINK_TRAP_GENERIC_ID_INGRESS_STP_FILTER,
138 	DEVLINK_TRAP_GENERIC_ID_EMPTY_TX_LIST,
139 	DEVLINK_TRAP_GENERIC_ID_EMPTY_TX_LIST,
140 	DEVLINK_TRAP_GENERIC_ID_PORT_LOOPBACK_FILTER,
141 	DEVLINK_TRAP_GENERIC_ID_BLACKHOLE_ROUTE,
142 	DEVLINK_TRAP_GENERIC_ID_NON_IP_PACKET,
143 	DEVLINK_TRAP_GENERIC_ID_UC_DIP_MC_DMAC,
144 	DEVLINK_TRAP_GENERIC_ID_DIP_LB,
145 	DEVLINK_TRAP_GENERIC_ID_SIP_MC,
146 	DEVLINK_TRAP_GENERIC_ID_SIP_LB,
147 	DEVLINK_TRAP_GENERIC_ID_CORRUPTED_IP_HDR,
148 	DEVLINK_TRAP_GENERIC_ID_IPV4_SIP_BC,
149 	DEVLINK_TRAP_GENERIC_ID_IPV6_MC_DIP_RESERVED_SCOPE,
150 	DEVLINK_TRAP_GENERIC_ID_IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE,
151 	DEVLINK_TRAP_GENERIC_ID_MTU_ERROR,
152 	DEVLINK_TRAP_GENERIC_ID_TTL_ERROR,
153 	DEVLINK_TRAP_GENERIC_ID_RPF,
154 	DEVLINK_TRAP_GENERIC_ID_REJECT_ROUTE,
155 	DEVLINK_TRAP_GENERIC_ID_UNRESOLVED_NEIGH,
156 	DEVLINK_TRAP_GENERIC_ID_UNRESOLVED_NEIGH,
157 	DEVLINK_TRAP_GENERIC_ID_UNRESOLVED_NEIGH,
158 	DEVLINK_TRAP_GENERIC_ID_IPV4_LPM_UNICAST_MISS,
159 	DEVLINK_TRAP_GENERIC_ID_IPV6_LPM_UNICAST_MISS,
160 	DEVLINK_MLXSW_TRAP_ID_IRIF_DISABLED,
161 	DEVLINK_MLXSW_TRAP_ID_ERIF_DISABLED,
162 	DEVLINK_TRAP_GENERIC_ID_NON_ROUTABLE,
163 	DEVLINK_TRAP_GENERIC_ID_DECAP_ERROR,
164 	DEVLINK_TRAP_GENERIC_ID_DECAP_ERROR,
165 	DEVLINK_TRAP_GENERIC_ID_DECAP_ERROR,
166 	DEVLINK_TRAP_GENERIC_ID_OVERLAY_SMAC_MC,
167 };
168 
169 static int mlxsw_sp_rx_listener(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
170 				u8 local_port,
171 				struct mlxsw_sp_port *mlxsw_sp_port)
172 {
173 	struct mlxsw_sp_port_pcpu_stats *pcpu_stats;
174 
175 	if (unlikely(!mlxsw_sp_port)) {
176 		dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: skb received for non-existent port\n",
177 				     local_port);
178 		kfree_skb(skb);
179 		return -EINVAL;
180 	}
181 
182 	skb->dev = mlxsw_sp_port->dev;
183 
184 	pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats);
185 	u64_stats_update_begin(&pcpu_stats->syncp);
186 	pcpu_stats->rx_packets++;
187 	pcpu_stats->rx_bytes += skb->len;
188 	u64_stats_update_end(&pcpu_stats->syncp);
189 
190 	skb->protocol = eth_type_trans(skb, skb->dev);
191 
192 	return 0;
193 }
194 
195 static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port,
196 				      void *trap_ctx)
197 {
198 	struct devlink_port *in_devlink_port;
199 	struct mlxsw_sp_port *mlxsw_sp_port;
200 	struct mlxsw_sp *mlxsw_sp;
201 	struct devlink *devlink;
202 
203 	mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
204 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
205 
206 	if (mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port))
207 		return;
208 
209 	devlink = priv_to_devlink(mlxsw_sp->core);
210 	in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
211 							   local_port);
212 	skb_push(skb, ETH_HLEN);
213 	devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port);
214 	consume_skb(skb);
215 }
216 
217 static void mlxsw_sp_rx_exception_listener(struct sk_buff *skb, u8 local_port,
218 					   void *trap_ctx)
219 {
220 	struct devlink_port *in_devlink_port;
221 	struct mlxsw_sp_port *mlxsw_sp_port;
222 	struct mlxsw_sp *mlxsw_sp;
223 	struct devlink *devlink;
224 
225 	mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
226 	mlxsw_sp_port = mlxsw_sp->ports[local_port];
227 
228 	if (mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port))
229 		return;
230 
231 	devlink = priv_to_devlink(mlxsw_sp->core);
232 	in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
233 							   local_port);
234 	skb_push(skb, ETH_HLEN);
235 	devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port);
236 	skb_pull(skb, ETH_HLEN);
237 	skb->offload_fwd_mark = 1;
238 	netif_receive_skb(skb);
239 }
240 
241 int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
242 {
243 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
244 
245 	if (WARN_ON(ARRAY_SIZE(mlxsw_sp_listener_devlink_map) !=
246 		    ARRAY_SIZE(mlxsw_sp_listeners_arr)))
247 		return -EINVAL;
248 
249 	return devlink_traps_register(devlink, mlxsw_sp_traps_arr,
250 				      ARRAY_SIZE(mlxsw_sp_traps_arr),
251 				      mlxsw_sp);
252 }
253 
254 void mlxsw_sp_devlink_traps_fini(struct mlxsw_sp *mlxsw_sp)
255 {
256 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
257 
258 	devlink_traps_unregister(devlink, mlxsw_sp_traps_arr,
259 				 ARRAY_SIZE(mlxsw_sp_traps_arr));
260 }
261 
262 int mlxsw_sp_trap_init(struct mlxsw_core *mlxsw_core,
263 		       const struct devlink_trap *trap, void *trap_ctx)
264 {
265 	int i;
266 
267 	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) {
268 		struct mlxsw_listener *listener;
269 		int err;
270 
271 		if (mlxsw_sp_listener_devlink_map[i] != trap->id)
272 			continue;
273 		listener = &mlxsw_sp_listeners_arr[i];
274 
275 		err = mlxsw_core_trap_register(mlxsw_core, listener, trap_ctx);
276 		if (err)
277 			return err;
278 	}
279 
280 	return 0;
281 }
282 
283 void mlxsw_sp_trap_fini(struct mlxsw_core *mlxsw_core,
284 			const struct devlink_trap *trap, void *trap_ctx)
285 {
286 	int i;
287 
288 	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) {
289 		struct mlxsw_listener *listener;
290 
291 		if (mlxsw_sp_listener_devlink_map[i] != trap->id)
292 			continue;
293 		listener = &mlxsw_sp_listeners_arr[i];
294 
295 		mlxsw_core_trap_unregister(mlxsw_core, listener, trap_ctx);
296 	}
297 }
298 
299 int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
300 			     const struct devlink_trap *trap,
301 			     enum devlink_trap_action action)
302 {
303 	int i;
304 
305 	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) {
306 		enum mlxsw_reg_hpkt_action hw_action;
307 		struct mlxsw_listener *listener;
308 		int err;
309 
310 		if (mlxsw_sp_listener_devlink_map[i] != trap->id)
311 			continue;
312 		listener = &mlxsw_sp_listeners_arr[i];
313 
314 		switch (action) {
315 		case DEVLINK_TRAP_ACTION_DROP:
316 			hw_action = MLXSW_REG_HPKT_ACTION_SET_FW_DEFAULT;
317 			break;
318 		case DEVLINK_TRAP_ACTION_TRAP:
319 			hw_action = MLXSW_REG_HPKT_ACTION_TRAP_EXCEPTION_TO_CPU;
320 			break;
321 		default:
322 			return -EINVAL;
323 		}
324 
325 		err = mlxsw_core_trap_action_set(mlxsw_core, listener,
326 						 hw_action);
327 		if (err)
328 			return err;
329 	}
330 
331 	return 0;
332 }
333 
334 #define MLXSW_SP_DISCARD_POLICER_ID	(MLXSW_REG_HTGT_TRAP_GROUP_MAX + 1)
335 
336 static int
337 mlxsw_sp_trap_group_policer_init(struct mlxsw_sp *mlxsw_sp,
338 				 const struct devlink_trap_group *group)
339 {
340 	enum mlxsw_reg_qpcr_ir_units ir_units;
341 	char qpcr_pl[MLXSW_REG_QPCR_LEN];
342 	u16 policer_id;
343 	u8 burst_size;
344 	bool is_bytes;
345 	u32 rate;
346 
347 	switch (group->id) {
348 	case DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS: /* fall through */
349 	case DEVLINK_TRAP_GROUP_GENERIC_ID_L3_DROPS: /* fall through */
350 	case DEVLINK_TRAP_GROUP_GENERIC_ID_TUNNEL_DROPS:
351 		policer_id = MLXSW_SP_DISCARD_POLICER_ID;
352 		ir_units = MLXSW_REG_QPCR_IR_UNITS_M;
353 		is_bytes = false;
354 		rate = 10 * 1024; /* 10Kpps */
355 		burst_size = 7;
356 		break;
357 	default:
358 		return -EINVAL;
359 	}
360 
361 	mlxsw_reg_qpcr_pack(qpcr_pl, policer_id, ir_units, is_bytes, rate,
362 			    burst_size);
363 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
364 }
365 
366 static int
367 __mlxsw_sp_trap_group_init(struct mlxsw_sp *mlxsw_sp,
368 			   const struct devlink_trap_group *group)
369 {
370 	char htgt_pl[MLXSW_REG_HTGT_LEN];
371 	u8 priority, tc, group_id;
372 	u16 policer_id;
373 
374 	switch (group->id) {
375 	case DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS:
376 		group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS;
377 		policer_id = MLXSW_SP_DISCARD_POLICER_ID;
378 		priority = 0;
379 		tc = 1;
380 		break;
381 	case DEVLINK_TRAP_GROUP_GENERIC_ID_L3_DROPS:
382 		group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_DISCARDS;
383 		policer_id = MLXSW_SP_DISCARD_POLICER_ID;
384 		priority = 0;
385 		tc = 1;
386 		break;
387 	case DEVLINK_TRAP_GROUP_GENERIC_ID_TUNNEL_DROPS:
388 		group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS;
389 		policer_id = MLXSW_SP_DISCARD_POLICER_ID;
390 		priority = 0;
391 		tc = 1;
392 		break;
393 	default:
394 		return -EINVAL;
395 	}
396 
397 	mlxsw_reg_htgt_pack(htgt_pl, group_id, policer_id, priority, tc);
398 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
399 }
400 
401 int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
402 			     const struct devlink_trap_group *group)
403 {
404 	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
405 	int err;
406 
407 	err = mlxsw_sp_trap_group_policer_init(mlxsw_sp, group);
408 	if (err)
409 		return err;
410 
411 	err = __mlxsw_sp_trap_group_init(mlxsw_sp, group);
412 	if (err)
413 		return err;
414 
415 	return 0;
416 }
417