brintos

brintos / linux-shallow public Read only

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