xref: /linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c (revision 207dd12bc195153fe6ca614d8add9ecb0b636270)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
3 
4 #include <linux/if_bridge.h>
5 #include <linux/list.h>
6 #include <linux/mutex.h>
7 #include <linux/refcount.h>
8 #include <linux/rtnetlink.h>
9 #include <linux/workqueue.h>
10 #include <net/arp.h>
11 #include <net/gre.h>
12 #include <net/lag.h>
13 #include <net/ndisc.h>
14 #include <net/ip6_tunnel.h>
15 
16 #include "spectrum.h"
17 #include "spectrum_ipip.h"
18 #include "spectrum_span.h"
19 #include "spectrum_switchdev.h"
20 
21 struct mlxsw_sp_span {
22 	struct work_struct work;
23 	struct mlxsw_sp *mlxsw_sp;
24 	const struct mlxsw_sp_span_trigger_ops **span_trigger_ops_arr;
25 	const struct mlxsw_sp_span_entry_ops **span_entry_ops_arr;
26 	size_t span_entry_ops_arr_size;
27 	struct list_head analyzed_ports_list;
28 	struct mutex analyzed_ports_lock; /* Protects analyzed_ports_list */
29 	struct list_head trigger_entries_list;
30 	u16 policer_id_base;
31 	refcount_t policer_id_base_ref_count;
32 	atomic_t active_entries_count;
33 	int entries_count;
34 	struct mlxsw_sp_span_entry entries[] __counted_by(entries_count);
35 };
36 
37 struct mlxsw_sp_span_analyzed_port {
38 	struct list_head list; /* Member of analyzed_ports_list */
39 	refcount_t ref_count;
40 	u16 local_port;
41 	bool ingress;
42 };
43 
44 struct mlxsw_sp_span_trigger_entry {
45 	struct list_head list; /* Member of trigger_entries_list */
46 	struct mlxsw_sp_span *span;
47 	const struct mlxsw_sp_span_trigger_ops *ops;
48 	refcount_t ref_count;
49 	u16 local_port;
50 	enum mlxsw_sp_span_trigger trigger;
51 	struct mlxsw_sp_span_trigger_parms parms;
52 };
53 
54 enum mlxsw_sp_span_trigger_type {
55 	MLXSW_SP_SPAN_TRIGGER_TYPE_PORT,
56 	MLXSW_SP_SPAN_TRIGGER_TYPE_GLOBAL,
57 };
58 
59 struct mlxsw_sp_span_trigger_ops {
60 	int (*bind)(struct mlxsw_sp_span_trigger_entry *trigger_entry);
61 	void (*unbind)(struct mlxsw_sp_span_trigger_entry *trigger_entry);
62 	bool (*matches)(struct mlxsw_sp_span_trigger_entry *trigger_entry,
63 			enum mlxsw_sp_span_trigger trigger,
64 			struct mlxsw_sp_port *mlxsw_sp_port);
65 	int (*enable)(struct mlxsw_sp_span_trigger_entry *trigger_entry,
66 		      struct mlxsw_sp_port *mlxsw_sp_port, u8 tc);
67 	void (*disable)(struct mlxsw_sp_span_trigger_entry *trigger_entry,
68 			struct mlxsw_sp_port *mlxsw_sp_port, u8 tc);
69 };
70 
71 static void mlxsw_sp_span_respin_work(struct work_struct *work);
72 
73 static u64 mlxsw_sp_span_occ_get(void *priv)
74 {
75 	const struct mlxsw_sp *mlxsw_sp = priv;
76 
77 	return atomic_read(&mlxsw_sp->span->active_entries_count);
78 }
79 
80 int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
81 {
82 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
83 	struct mlxsw_sp_span *span;
84 	int i, entries_count, err;
85 
86 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN))
87 		return -EIO;
88 
89 	entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_SPAN);
90 	span = kzalloc_flex(*span, entries, entries_count);
91 	if (!span)
92 		return -ENOMEM;
93 	refcount_set(&span->policer_id_base_ref_count, 0);
94 	span->entries_count = entries_count;
95 	atomic_set(&span->active_entries_count, 0);
96 	mutex_init(&span->analyzed_ports_lock);
97 	INIT_LIST_HEAD(&span->analyzed_ports_list);
98 	INIT_LIST_HEAD(&span->trigger_entries_list);
99 	span->mlxsw_sp = mlxsw_sp;
100 	mlxsw_sp->span = span;
101 
102 	for (i = 0; i < mlxsw_sp->span->entries_count; i++)
103 		mlxsw_sp->span->entries[i].id = i;
104 
105 	err = mlxsw_sp->span_ops->init(mlxsw_sp);
106 	if (err)
107 		goto err_init;
108 
109 	devl_resource_occ_get_register(devlink, MLXSW_SP_RESOURCE_SPAN,
110 				       mlxsw_sp_span_occ_get, mlxsw_sp);
111 	INIT_WORK(&span->work, mlxsw_sp_span_respin_work);
112 
113 	return 0;
114 
115 err_init:
116 	mutex_destroy(&mlxsw_sp->span->analyzed_ports_lock);
117 	kfree(mlxsw_sp->span);
118 	return err;
119 }
120 
121 void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
122 {
123 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
124 
125 	cancel_work_sync(&mlxsw_sp->span->work);
126 	devl_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_SPAN);
127 
128 	WARN_ON_ONCE(!list_empty(&mlxsw_sp->span->trigger_entries_list));
129 	WARN_ON_ONCE(!list_empty(&mlxsw_sp->span->analyzed_ports_list));
130 	mutex_destroy(&mlxsw_sp->span->analyzed_ports_lock);
131 	kfree(mlxsw_sp->span);
132 }
133 
134 static bool mlxsw_sp1_span_cpu_can_handle(const struct net_device *dev)
135 {
136 	return !dev;
137 }
138 
139 static int mlxsw_sp1_span_entry_cpu_parms(struct mlxsw_sp *mlxsw_sp,
140 					  const struct net_device *to_dev,
141 					  struct mlxsw_sp_span_parms *sparmsp)
142 {
143 	return -EOPNOTSUPP;
144 }
145 
146 static int
147 mlxsw_sp1_span_entry_cpu_configure(struct mlxsw_sp_span_entry *span_entry,
148 				   struct mlxsw_sp_span_parms sparms)
149 {
150 	return -EOPNOTSUPP;
151 }
152 
153 static void
154 mlxsw_sp1_span_entry_cpu_deconfigure(struct mlxsw_sp_span_entry *span_entry)
155 {
156 }
157 
158 static const
159 struct mlxsw_sp_span_entry_ops mlxsw_sp1_span_entry_ops_cpu = {
160 	.is_static = true,
161 	.can_handle = mlxsw_sp1_span_cpu_can_handle,
162 	.parms_set = mlxsw_sp1_span_entry_cpu_parms,
163 	.configure = mlxsw_sp1_span_entry_cpu_configure,
164 	.deconfigure = mlxsw_sp1_span_entry_cpu_deconfigure,
165 };
166 
167 static int
168 mlxsw_sp_span_entry_phys_parms(struct mlxsw_sp *mlxsw_sp,
169 			       const struct net_device *to_dev,
170 			       struct mlxsw_sp_span_parms *sparmsp)
171 {
172 	sparmsp->dest_port = netdev_priv(to_dev);
173 	return 0;
174 }
175 
176 static int
177 mlxsw_sp_span_entry_phys_configure(struct mlxsw_sp_span_entry *span_entry,
178 				   struct mlxsw_sp_span_parms sparms)
179 {
180 	struct mlxsw_sp_port *dest_port = sparms.dest_port;
181 	struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
182 	u16 local_port = dest_port->local_port;
183 	char mpat_pl[MLXSW_REG_MPAT_LEN];
184 	int pa_id = span_entry->id;
185 
186 	/* Create a new port analayzer entry for local_port. */
187 	mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
188 			    MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
189 	mlxsw_reg_mpat_session_id_set(mpat_pl, sparms.session_id);
190 	mlxsw_reg_mpat_pide_set(mpat_pl, sparms.policer_enable);
191 	mlxsw_reg_mpat_pid_set(mpat_pl, sparms.policer_id);
192 
193 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
194 }
195 
196 static void
197 mlxsw_sp_span_entry_deconfigure_common(struct mlxsw_sp_span_entry *span_entry,
198 				       enum mlxsw_reg_mpat_span_type span_type)
199 {
200 	struct mlxsw_sp_port *dest_port = span_entry->parms.dest_port;
201 	struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
202 	u16 local_port = dest_port->local_port;
203 	char mpat_pl[MLXSW_REG_MPAT_LEN];
204 	int pa_id = span_entry->id;
205 
206 	mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false, span_type);
207 	mlxsw_reg_mpat_session_id_set(mpat_pl, span_entry->parms.session_id);
208 	mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
209 }
210 
211 static void
212 mlxsw_sp_span_entry_phys_deconfigure(struct mlxsw_sp_span_entry *span_entry)
213 {
214 	mlxsw_sp_span_entry_deconfigure_common(span_entry,
215 					    MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
216 }
217 
218 static const
219 struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_phys = {
220 	.is_static = true,
221 	.can_handle = mlxsw_sp_port_dev_check,
222 	.parms_set = mlxsw_sp_span_entry_phys_parms,
223 	.configure = mlxsw_sp_span_entry_phys_configure,
224 	.deconfigure = mlxsw_sp_span_entry_phys_deconfigure,
225 };
226 
227 static int mlxsw_sp_span_dmac(int family,
228 			      const void *pkey,
229 			      struct net_device *dev,
230 			      unsigned char dmac[ETH_ALEN])
231 {
232 	struct neighbour *neigh;
233 	int err = 0;
234 
235 #if IS_ENABLED(CONFIG_IPV6_GRE)
236 	if (family == AF_INET6) {
237 		neigh = ipv6_neigh_lookup(dev, pkey);
238 		if (!neigh) {
239 			neigh = ipv6_neigh_create(dev, pkey);
240 			if (IS_ERR(neigh))
241 				return PTR_ERR(neigh);
242 		}
243 	} else
244 #endif
245 	{
246 		neigh = ipv4_neigh_lookup(dev, pkey);
247 		if (!neigh) {
248 			neigh = ipv4_neigh_create(dev, pkey);
249 			if (IS_ERR(neigh))
250 				return PTR_ERR(neigh);
251 		}
252 	}
253 
254 	neigh_event_send(neigh, NULL);
255 
256 	read_lock_bh(&neigh->lock);
257 	if ((neigh->nud_state & NUD_VALID) && !neigh->dead)
258 		memcpy(dmac, neigh->ha, ETH_ALEN);
259 	else
260 		err = -ENOENT;
261 	read_unlock_bh(&neigh->lock);
262 
263 	neigh_release(neigh);
264 	return err;
265 }
266 
267 static int
268 mlxsw_sp_span_entry_unoffloadable(struct mlxsw_sp_span_parms *sparmsp)
269 {
270 	sparmsp->dest_port = NULL;
271 	return 0;
272 }
273 
274 static struct net_device *
275 mlxsw_sp_span_entry_bridge_8021q(const struct net_device *br_dev,
276 				 unsigned char *dmac,
277 				 u16 *p_vid)
278 {
279 	struct bridge_vlan_info vinfo;
280 	struct net_device *edev;
281 	u16 vid = *p_vid;
282 
283 	if (!vid && WARN_ON(br_vlan_get_pvid(br_dev, &vid)))
284 		return NULL;
285 	if (!vid || br_vlan_get_info(br_dev, vid, &vinfo) ||
286 	    !(vinfo.flags & BRIDGE_VLAN_INFO_BRENTRY))
287 		return NULL;
288 
289 	edev = br_fdb_find_port(br_dev, dmac, vid);
290 	if (!edev)
291 		return NULL;
292 
293 	if (br_vlan_get_info(edev, vid, &vinfo))
294 		return NULL;
295 	if (vinfo.flags & BRIDGE_VLAN_INFO_UNTAGGED)
296 		*p_vid = 0;
297 	else
298 		*p_vid = vid;
299 	return edev;
300 }
301 
302 static struct net_device *
303 mlxsw_sp_span_entry_bridge_8021d(const struct net_device *br_dev,
304 				 unsigned char *dmac)
305 {
306 	return br_fdb_find_port(br_dev, dmac, 0);
307 }
308 
309 static struct net_device *
310 mlxsw_sp_span_entry_bridge(const struct net_device *br_dev,
311 			   unsigned char dmac[ETH_ALEN],
312 			   u16 *p_vid)
313 {
314 	struct mlxsw_sp_bridge_port *bridge_port;
315 	enum mlxsw_reg_spms_state spms_state;
316 	struct net_device *dev = NULL;
317 	struct mlxsw_sp_port *port;
318 	u8 stp_state;
319 
320 	if (br_vlan_enabled(br_dev))
321 		dev = mlxsw_sp_span_entry_bridge_8021q(br_dev, dmac, p_vid);
322 	else if (!*p_vid)
323 		dev = mlxsw_sp_span_entry_bridge_8021d(br_dev, dmac);
324 	if (!dev)
325 		return NULL;
326 
327 	port = mlxsw_sp_port_dev_lower_find(dev);
328 	if (!port)
329 		return NULL;
330 
331 	bridge_port = mlxsw_sp_bridge_port_find(port->mlxsw_sp->bridge, dev);
332 	if (!bridge_port)
333 		return NULL;
334 
335 	stp_state = mlxsw_sp_bridge_port_stp_state(bridge_port);
336 	spms_state = mlxsw_sp_stp_spms_state(stp_state);
337 	if (spms_state != MLXSW_REG_SPMS_STATE_FORWARDING)
338 		return NULL;
339 
340 	return dev;
341 }
342 
343 static struct net_device *
344 mlxsw_sp_span_entry_vlan(const struct net_device *vlan_dev,
345 			 u16 *p_vid)
346 {
347 	*p_vid = vlan_dev_vlan_id(vlan_dev);
348 	return vlan_dev_real_dev(vlan_dev);
349 }
350 
351 static struct net_device *
352 mlxsw_sp_span_entry_lag(struct net_device *lag_dev)
353 {
354 	struct net_device *dev;
355 	struct list_head *iter;
356 
357 	netdev_for_each_lower_dev(lag_dev, dev, iter)
358 		if (netif_carrier_ok(dev) &&
359 		    net_lag_port_dev_txable(dev) &&
360 		    mlxsw_sp_port_dev_check(dev))
361 			return dev;
362 
363 	return NULL;
364 }
365 
366 static __maybe_unused int
367 mlxsw_sp_span_entry_tunnel_parms_common(struct net_device *edev,
368 					union mlxsw_sp_l3addr saddr,
369 					union mlxsw_sp_l3addr daddr,
370 					union mlxsw_sp_l3addr gw,
371 					__u8 ttl, int family,
372 					struct mlxsw_sp_span_parms *sparmsp)
373 {
374 	unsigned char dmac[ETH_ALEN];
375 	u16 vid = 0;
376 
377 	if (mlxsw_sp_l3addr_is_zero(gw))
378 		gw = daddr;
379 
380 	if (!edev || mlxsw_sp_span_dmac(family, &gw, edev, dmac))
381 		goto unoffloadable;
382 
383 	if (is_vlan_dev(edev))
384 		edev = mlxsw_sp_span_entry_vlan(edev, &vid);
385 
386 	if (netif_is_bridge_master(edev)) {
387 		edev = mlxsw_sp_span_entry_bridge(edev, dmac, &vid);
388 		if (!edev)
389 			goto unoffloadable;
390 	}
391 
392 	if (is_vlan_dev(edev)) {
393 		if (vid || !(edev->flags & IFF_UP))
394 			goto unoffloadable;
395 		edev = mlxsw_sp_span_entry_vlan(edev, &vid);
396 	}
397 
398 	if (netif_is_lag_master(edev)) {
399 		if (!(edev->flags & IFF_UP))
400 			goto unoffloadable;
401 		edev = mlxsw_sp_span_entry_lag(edev);
402 		if (!edev)
403 			goto unoffloadable;
404 	}
405 
406 	if (!mlxsw_sp_port_dev_check(edev))
407 		goto unoffloadable;
408 
409 	sparmsp->dest_port = netdev_priv(edev);
410 	sparmsp->ttl = ttl;
411 	memcpy(sparmsp->dmac, dmac, ETH_ALEN);
412 	memcpy(sparmsp->smac, edev->dev_addr, ETH_ALEN);
413 	sparmsp->saddr = saddr;
414 	sparmsp->daddr = daddr;
415 	sparmsp->vid = vid;
416 	return 0;
417 
418 unoffloadable:
419 	return mlxsw_sp_span_entry_unoffloadable(sparmsp);
420 }
421 
422 #if IS_ENABLED(CONFIG_NET_IPGRE)
423 static struct net_device *
424 mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
425 			    __be32 *saddrp, __be32 *daddrp)
426 {
427 	struct ip_tunnel *tun = netdev_priv(to_dev);
428 	struct ip_tunnel_parm_kern parms;
429 	struct net_device *dev = NULL;
430 	struct rtable *rt = NULL;
431 	struct flowi4 fl4;
432 
433 	/* We assume "dev" stays valid after rt is put. */
434 	ASSERT_RTNL();
435 
436 	parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
437 	ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
438 			    0, 0, tun->net, parms.link, tun->fwmark, 0, 0);
439 
440 	rt = ip_route_output_key(tun->net, &fl4);
441 	if (IS_ERR(rt))
442 		return NULL;
443 
444 	if (rt->rt_type != RTN_UNICAST)
445 		goto out;
446 
447 	dev = rt->dst.dev;
448 	*saddrp = fl4.saddr;
449 	if (rt->rt_gw_family == AF_INET)
450 		*daddrp = rt->rt_gw4;
451 	/* can not offload if route has an IPv6 gateway */
452 	else if (rt->rt_gw_family == AF_INET6)
453 		dev = NULL;
454 
455 out:
456 	ip_rt_put(rt);
457 	return dev;
458 }
459 
460 static int
461 mlxsw_sp_span_entry_gretap4_parms(struct mlxsw_sp *mlxsw_sp,
462 				  const struct net_device *to_dev,
463 				  struct mlxsw_sp_span_parms *sparmsp)
464 {
465 	struct ip_tunnel_parm_kern tparm = mlxsw_sp_ipip_netdev_parms4(to_dev);
466 	union mlxsw_sp_l3addr saddr = { .addr4 = tparm.iph.saddr };
467 	union mlxsw_sp_l3addr daddr = { .addr4 = tparm.iph.daddr };
468 	bool inherit_tos = tparm.iph.tos & 0x1;
469 	bool inherit_ttl = !tparm.iph.ttl;
470 	union mlxsw_sp_l3addr gw = daddr;
471 	struct net_device *l3edev;
472 
473 	if (!(to_dev->flags & IFF_UP) ||
474 	    /* Reject tunnels with GRE keys, checksums, etc. */
475 	    !ip_tunnel_flags_empty(tparm.i_flags) ||
476 	    !ip_tunnel_flags_empty(tparm.o_flags) ||
477 	    /* Require a fixed TTL and a TOS copied from the mirrored packet. */
478 	    inherit_ttl || !inherit_tos ||
479 	    /* A destination address may not be "any". */
480 	    mlxsw_sp_l3addr_is_zero(daddr))
481 		return mlxsw_sp_span_entry_unoffloadable(sparmsp);
482 
483 	l3edev = mlxsw_sp_span_gretap4_route(to_dev, &saddr.addr4, &gw.addr4);
484 
485 	return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
486 						       tparm.iph.ttl,
487 						       AF_INET, sparmsp);
488 }
489 
490 static int
491 mlxsw_sp_span_entry_gretap4_configure(struct mlxsw_sp_span_entry *span_entry,
492 				      struct mlxsw_sp_span_parms sparms)
493 {
494 	struct mlxsw_sp_port *dest_port = sparms.dest_port;
495 	struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
496 	u16 local_port = dest_port->local_port;
497 	char mpat_pl[MLXSW_REG_MPAT_LEN];
498 	int pa_id = span_entry->id;
499 
500 	/* Create a new port analayzer entry for local_port. */
501 	mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
502 			    MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
503 	mlxsw_reg_mpat_pide_set(mpat_pl, sparms.policer_enable);
504 	mlxsw_reg_mpat_pid_set(mpat_pl, sparms.policer_id);
505 	mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
506 	mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
507 				    MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
508 				    sparms.dmac, !!sparms.vid);
509 	mlxsw_reg_mpat_eth_rspan_l3_ipv4_pack(mpat_pl,
510 					      sparms.ttl, sparms.smac,
511 					      be32_to_cpu(sparms.saddr.addr4),
512 					      be32_to_cpu(sparms.daddr.addr4));
513 
514 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
515 }
516 
517 static void
518 mlxsw_sp_span_entry_gretap4_deconfigure(struct mlxsw_sp_span_entry *span_entry)
519 {
520 	mlxsw_sp_span_entry_deconfigure_common(span_entry,
521 					MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
522 }
523 
524 static const struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_gretap4 = {
525 	.can_handle = netif_is_gretap,
526 	.parms_set = mlxsw_sp_span_entry_gretap4_parms,
527 	.configure = mlxsw_sp_span_entry_gretap4_configure,
528 	.deconfigure = mlxsw_sp_span_entry_gretap4_deconfigure,
529 };
530 #endif
531 
532 #if IS_ENABLED(CONFIG_IPV6_GRE)
533 static struct net_device *
534 mlxsw_sp_span_gretap6_route(const struct net_device *to_dev,
535 			    struct in6_addr *saddrp,
536 			    struct in6_addr *daddrp)
537 {
538 	struct ip6_tnl *t = netdev_priv(to_dev);
539 	struct flowi6 fl6 = t->fl.u.ip6;
540 	struct net_device *dev = NULL;
541 	struct dst_entry *dst;
542 	struct rt6_info *rt6;
543 
544 	/* We assume "dev" stays valid after dst is released. */
545 	ASSERT_RTNL();
546 
547 	fl6.flowi6_mark = t->parms.fwmark;
548 	if (!ip6_tnl_xmit_ctl(t, &fl6.saddr, &fl6.daddr))
549 		return NULL;
550 
551 	dst = ip6_route_output(t->net, NULL, &fl6);
552 	if (!dst || dst->error)
553 		goto out;
554 
555 	rt6 = dst_rt6_info(dst);
556 
557 	dev = dst->dev;
558 	*saddrp = fl6.saddr;
559 	*daddrp = rt6->rt6i_gateway;
560 
561 out:
562 	dst_release(dst);
563 	return dev;
564 }
565 
566 static int
567 mlxsw_sp_span_entry_gretap6_parms(struct mlxsw_sp *mlxsw_sp,
568 				  const struct net_device *to_dev,
569 				  struct mlxsw_sp_span_parms *sparmsp)
570 {
571 	struct __ip6_tnl_parm tparm = mlxsw_sp_ipip_netdev_parms6(to_dev);
572 	bool inherit_tos = tparm.flags & IP6_TNL_F_USE_ORIG_TCLASS;
573 	union mlxsw_sp_l3addr saddr = { .addr6 = tparm.laddr };
574 	union mlxsw_sp_l3addr daddr = { .addr6 = tparm.raddr };
575 	bool inherit_ttl = !tparm.hop_limit;
576 	union mlxsw_sp_l3addr gw = daddr;
577 	struct net_device *l3edev;
578 
579 	if (!(to_dev->flags & IFF_UP) ||
580 	    /* Reject tunnels with GRE keys, checksums, etc. */
581 	    !ip_tunnel_flags_empty(tparm.i_flags) ||
582 	    !ip_tunnel_flags_empty(tparm.o_flags) ||
583 	    /* Require a fixed TTL and a TOS copied from the mirrored packet. */
584 	    inherit_ttl || !inherit_tos ||
585 	    /* A destination address may not be "any". */
586 	    mlxsw_sp_l3addr_is_zero(daddr))
587 		return mlxsw_sp_span_entry_unoffloadable(sparmsp);
588 
589 	l3edev = mlxsw_sp_span_gretap6_route(to_dev, &saddr.addr6, &gw.addr6);
590 
591 	return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
592 						       tparm.hop_limit,
593 						       AF_INET6, sparmsp);
594 }
595 
596 static int
597 mlxsw_sp_span_entry_gretap6_configure(struct mlxsw_sp_span_entry *span_entry,
598 				      struct mlxsw_sp_span_parms sparms)
599 {
600 	struct mlxsw_sp_port *dest_port = sparms.dest_port;
601 	struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
602 	u16 local_port = dest_port->local_port;
603 	char mpat_pl[MLXSW_REG_MPAT_LEN];
604 	int pa_id = span_entry->id;
605 
606 	/* Create a new port analayzer entry for local_port. */
607 	mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
608 			    MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
609 	mlxsw_reg_mpat_pide_set(mpat_pl, sparms.policer_enable);
610 	mlxsw_reg_mpat_pid_set(mpat_pl, sparms.policer_id);
611 	mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
612 	mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
613 				    MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
614 				    sparms.dmac, !!sparms.vid);
615 	mlxsw_reg_mpat_eth_rspan_l3_ipv6_pack(mpat_pl, sparms.ttl, sparms.smac,
616 					      sparms.saddr.addr6,
617 					      sparms.daddr.addr6);
618 
619 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
620 }
621 
622 static void
623 mlxsw_sp_span_entry_gretap6_deconfigure(struct mlxsw_sp_span_entry *span_entry)
624 {
625 	mlxsw_sp_span_entry_deconfigure_common(span_entry,
626 					MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
627 }
628 
629 static const
630 struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_gretap6 = {
631 	.can_handle = netif_is_ip6gretap,
632 	.parms_set = mlxsw_sp_span_entry_gretap6_parms,
633 	.configure = mlxsw_sp_span_entry_gretap6_configure,
634 	.deconfigure = mlxsw_sp_span_entry_gretap6_deconfigure,
635 };
636 #endif
637 
638 static bool
639 mlxsw_sp_span_vlan_can_handle(const struct net_device *dev)
640 {
641 	return is_vlan_dev(dev) &&
642 	       mlxsw_sp_port_dev_check(vlan_dev_real_dev(dev));
643 }
644 
645 static int
646 mlxsw_sp_span_entry_vlan_parms(struct mlxsw_sp *mlxsw_sp,
647 			       const struct net_device *to_dev,
648 			       struct mlxsw_sp_span_parms *sparmsp)
649 {
650 	struct net_device *real_dev;
651 	u16 vid;
652 
653 	if (!(to_dev->flags & IFF_UP))
654 		return mlxsw_sp_span_entry_unoffloadable(sparmsp);
655 
656 	real_dev = mlxsw_sp_span_entry_vlan(to_dev, &vid);
657 	sparmsp->dest_port = netdev_priv(real_dev);
658 	sparmsp->vid = vid;
659 	return 0;
660 }
661 
662 static int
663 mlxsw_sp_span_entry_vlan_configure(struct mlxsw_sp_span_entry *span_entry,
664 				   struct mlxsw_sp_span_parms sparms)
665 {
666 	struct mlxsw_sp_port *dest_port = sparms.dest_port;
667 	struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
668 	u16 local_port = dest_port->local_port;
669 	char mpat_pl[MLXSW_REG_MPAT_LEN];
670 	int pa_id = span_entry->id;
671 
672 	mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
673 			    MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH);
674 	mlxsw_reg_mpat_pide_set(mpat_pl, sparms.policer_enable);
675 	mlxsw_reg_mpat_pid_set(mpat_pl, sparms.policer_id);
676 	mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
677 
678 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
679 }
680 
681 static void
682 mlxsw_sp_span_entry_vlan_deconfigure(struct mlxsw_sp_span_entry *span_entry)
683 {
684 	mlxsw_sp_span_entry_deconfigure_common(span_entry,
685 					MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH);
686 }
687 
688 static const
689 struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_vlan = {
690 	.can_handle = mlxsw_sp_span_vlan_can_handle,
691 	.parms_set = mlxsw_sp_span_entry_vlan_parms,
692 	.configure = mlxsw_sp_span_entry_vlan_configure,
693 	.deconfigure = mlxsw_sp_span_entry_vlan_deconfigure,
694 };
695 
696 static const
697 struct mlxsw_sp_span_entry_ops *mlxsw_sp1_span_entry_ops_arr[] = {
698 	&mlxsw_sp1_span_entry_ops_cpu,
699 	&mlxsw_sp_span_entry_ops_phys,
700 #if IS_ENABLED(CONFIG_NET_IPGRE)
701 	&mlxsw_sp_span_entry_ops_gretap4,
702 #endif
703 #if IS_ENABLED(CONFIG_IPV6_GRE)
704 	&mlxsw_sp_span_entry_ops_gretap6,
705 #endif
706 	&mlxsw_sp_span_entry_ops_vlan,
707 };
708 
709 static bool mlxsw_sp2_span_cpu_can_handle(const struct net_device *dev)
710 {
711 	return !dev;
712 }
713 
714 static int mlxsw_sp2_span_entry_cpu_parms(struct mlxsw_sp *mlxsw_sp,
715 					  const struct net_device *to_dev,
716 					  struct mlxsw_sp_span_parms *sparmsp)
717 {
718 	sparmsp->dest_port = mlxsw_sp->ports[MLXSW_PORT_CPU_PORT];
719 	return 0;
720 }
721 
722 static int
723 mlxsw_sp2_span_entry_cpu_configure(struct mlxsw_sp_span_entry *span_entry,
724 				   struct mlxsw_sp_span_parms sparms)
725 {
726 	/* Mirroring to the CPU port is like mirroring to any other physical
727 	 * port. Its local port is used instead of that of the physical port.
728 	 */
729 	return mlxsw_sp_span_entry_phys_configure(span_entry, sparms);
730 }
731 
732 static void
733 mlxsw_sp2_span_entry_cpu_deconfigure(struct mlxsw_sp_span_entry *span_entry)
734 {
735 	enum mlxsw_reg_mpat_span_type span_type;
736 
737 	span_type = MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH;
738 	mlxsw_sp_span_entry_deconfigure_common(span_entry, span_type);
739 }
740 
741 static const
742 struct mlxsw_sp_span_entry_ops mlxsw_sp2_span_entry_ops_cpu = {
743 	.is_static = true,
744 	.can_handle = mlxsw_sp2_span_cpu_can_handle,
745 	.parms_set = mlxsw_sp2_span_entry_cpu_parms,
746 	.configure = mlxsw_sp2_span_entry_cpu_configure,
747 	.deconfigure = mlxsw_sp2_span_entry_cpu_deconfigure,
748 };
749 
750 static const
751 struct mlxsw_sp_span_entry_ops *mlxsw_sp2_span_entry_ops_arr[] = {
752 	&mlxsw_sp2_span_entry_ops_cpu,
753 	&mlxsw_sp_span_entry_ops_phys,
754 #if IS_ENABLED(CONFIG_NET_IPGRE)
755 	&mlxsw_sp_span_entry_ops_gretap4,
756 #endif
757 #if IS_ENABLED(CONFIG_IPV6_GRE)
758 	&mlxsw_sp_span_entry_ops_gretap6,
759 #endif
760 	&mlxsw_sp_span_entry_ops_vlan,
761 };
762 
763 static int
764 mlxsw_sp_span_entry_nop_parms(struct mlxsw_sp *mlxsw_sp,
765 			      const struct net_device *to_dev,
766 			      struct mlxsw_sp_span_parms *sparmsp)
767 {
768 	return mlxsw_sp_span_entry_unoffloadable(sparmsp);
769 }
770 
771 static int
772 mlxsw_sp_span_entry_nop_configure(struct mlxsw_sp_span_entry *span_entry,
773 				  struct mlxsw_sp_span_parms sparms)
774 {
775 	return 0;
776 }
777 
778 static void
779 mlxsw_sp_span_entry_nop_deconfigure(struct mlxsw_sp_span_entry *span_entry)
780 {
781 }
782 
783 static const struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_nop = {
784 	.parms_set = mlxsw_sp_span_entry_nop_parms,
785 	.configure = mlxsw_sp_span_entry_nop_configure,
786 	.deconfigure = mlxsw_sp_span_entry_nop_deconfigure,
787 };
788 
789 static void
790 mlxsw_sp_span_entry_configure(struct mlxsw_sp *mlxsw_sp,
791 			      struct mlxsw_sp_span_entry *span_entry,
792 			      struct mlxsw_sp_span_parms sparms)
793 {
794 	int err;
795 
796 	if (!sparms.dest_port)
797 		goto set_parms;
798 
799 	if (sparms.dest_port->mlxsw_sp != mlxsw_sp) {
800 		dev_err(mlxsw_sp->bus_info->dev,
801 			"Cannot mirror to a port which belongs to a different mlxsw instance\n");
802 		sparms.dest_port = NULL;
803 		goto set_parms;
804 	}
805 
806 	err = span_entry->ops->configure(span_entry, sparms);
807 	if (err) {
808 		dev_err(mlxsw_sp->bus_info->dev, "Failed to offload mirror\n");
809 		sparms.dest_port = NULL;
810 		goto set_parms;
811 	}
812 
813 set_parms:
814 	span_entry->parms = sparms;
815 }
816 
817 static void
818 mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp_span_entry *span_entry)
819 {
820 	if (span_entry->parms.dest_port)
821 		span_entry->ops->deconfigure(span_entry);
822 }
823 
824 static int mlxsw_sp_span_policer_id_base_set(struct mlxsw_sp_span *span,
825 					     u16 policer_id)
826 {
827 	struct mlxsw_sp *mlxsw_sp = span->mlxsw_sp;
828 	u16 policer_id_base;
829 	int err;
830 
831 	/* Policers set on SPAN agents must be in the range of
832 	 * `policer_id_base .. policer_id_base + max_span_agents - 1`. If the
833 	 * base is set and the new policer is not within the range, then we
834 	 * must error out.
835 	 */
836 	if (refcount_read(&span->policer_id_base_ref_count)) {
837 		if (policer_id < span->policer_id_base ||
838 		    policer_id >= span->policer_id_base + span->entries_count)
839 			return -EINVAL;
840 
841 		refcount_inc(&span->policer_id_base_ref_count);
842 		return 0;
843 	}
844 
845 	/* Base must be even. */
846 	policer_id_base = policer_id % 2 == 0 ? policer_id : policer_id - 1;
847 	err = mlxsw_sp->span_ops->policer_id_base_set(mlxsw_sp,
848 						      policer_id_base);
849 	if (err)
850 		return err;
851 
852 	span->policer_id_base = policer_id_base;
853 	refcount_set(&span->policer_id_base_ref_count, 1);
854 
855 	return 0;
856 }
857 
858 static void mlxsw_sp_span_policer_id_base_unset(struct mlxsw_sp_span *span)
859 {
860 	if (refcount_dec_and_test(&span->policer_id_base_ref_count))
861 		span->policer_id_base = 0;
862 }
863 
864 static struct mlxsw_sp_span_entry *
865 mlxsw_sp_span_entry_create(struct mlxsw_sp *mlxsw_sp,
866 			   const struct net_device *to_dev,
867 			   const struct mlxsw_sp_span_entry_ops *ops,
868 			   struct mlxsw_sp_span_parms sparms)
869 {
870 	struct mlxsw_sp_span_entry *span_entry = NULL;
871 	int i;
872 
873 	/* find a free entry to use */
874 	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
875 		if (!refcount_read(&mlxsw_sp->span->entries[i].ref_count)) {
876 			span_entry = &mlxsw_sp->span->entries[i];
877 			break;
878 		}
879 	}
880 	if (!span_entry)
881 		return NULL;
882 
883 	if (sparms.policer_enable) {
884 		int err;
885 
886 		err = mlxsw_sp_span_policer_id_base_set(mlxsw_sp->span,
887 							sparms.policer_id);
888 		if (err)
889 			return NULL;
890 	}
891 
892 	atomic_inc(&mlxsw_sp->span->active_entries_count);
893 	span_entry->ops = ops;
894 	refcount_set(&span_entry->ref_count, 1);
895 	span_entry->to_dev = to_dev;
896 	mlxsw_sp_span_entry_configure(mlxsw_sp, span_entry, sparms);
897 
898 	return span_entry;
899 }
900 
901 static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
902 					struct mlxsw_sp_span_entry *span_entry)
903 {
904 	mlxsw_sp_span_entry_deconfigure(span_entry);
905 	atomic_dec(&mlxsw_sp->span->active_entries_count);
906 	if (span_entry->parms.policer_enable)
907 		mlxsw_sp_span_policer_id_base_unset(mlxsw_sp->span);
908 }
909 
910 struct mlxsw_sp_span_entry *
911 mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp,
912 				 const struct net_device *to_dev)
913 {
914 	int i;
915 
916 	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
917 		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
918 
919 		if (refcount_read(&curr->ref_count) && curr->to_dev == to_dev)
920 			return curr;
921 	}
922 	return NULL;
923 }
924 
925 void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp,
926 				    struct mlxsw_sp_span_entry *span_entry)
927 {
928 	mlxsw_sp_span_entry_deconfigure(span_entry);
929 	span_entry->ops = &mlxsw_sp_span_entry_ops_nop;
930 }
931 
932 static struct mlxsw_sp_span_entry *
933 mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id)
934 {
935 	int i;
936 
937 	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
938 		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
939 
940 		if (refcount_read(&curr->ref_count) && curr->id == span_id)
941 			return curr;
942 	}
943 	return NULL;
944 }
945 
946 static struct mlxsw_sp_span_entry *
947 mlxsw_sp_span_entry_find_by_parms(struct mlxsw_sp *mlxsw_sp,
948 				  const struct net_device *to_dev,
949 				  const struct mlxsw_sp_span_parms *sparms)
950 {
951 	int i;
952 
953 	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
954 		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
955 
956 		if (refcount_read(&curr->ref_count) && curr->to_dev == to_dev &&
957 		    curr->parms.policer_enable == sparms->policer_enable &&
958 		    curr->parms.policer_id == sparms->policer_id &&
959 		    curr->parms.session_id == sparms->session_id)
960 			return curr;
961 	}
962 	return NULL;
963 }
964 
965 static struct mlxsw_sp_span_entry *
966 mlxsw_sp_span_entry_get(struct mlxsw_sp *mlxsw_sp,
967 			const struct net_device *to_dev,
968 			const struct mlxsw_sp_span_entry_ops *ops,
969 			struct mlxsw_sp_span_parms sparms)
970 {
971 	struct mlxsw_sp_span_entry *span_entry;
972 
973 	span_entry = mlxsw_sp_span_entry_find_by_parms(mlxsw_sp, to_dev,
974 						       &sparms);
975 	if (span_entry) {
976 		/* Already exists, just take a reference */
977 		refcount_inc(&span_entry->ref_count);
978 		return span_entry;
979 	}
980 
981 	return mlxsw_sp_span_entry_create(mlxsw_sp, to_dev, ops, sparms);
982 }
983 
984 static int mlxsw_sp_span_entry_put(struct mlxsw_sp *mlxsw_sp,
985 				   struct mlxsw_sp_span_entry *span_entry)
986 {
987 	if (refcount_dec_and_test(&span_entry->ref_count))
988 		mlxsw_sp_span_entry_destroy(mlxsw_sp, span_entry);
989 	return 0;
990 }
991 
992 static int mlxsw_sp_span_port_buffer_update(struct mlxsw_sp_port *mlxsw_sp_port, bool enable)
993 {
994 	struct mlxsw_sp_hdroom hdroom;
995 
996 	hdroom = *mlxsw_sp_port->hdroom;
997 	hdroom.int_buf.enable = enable;
998 	mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port, &hdroom);
999 
1000 	return mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom);
1001 }
1002 
1003 static int
1004 mlxsw_sp_span_port_buffer_enable(struct mlxsw_sp_port *mlxsw_sp_port)
1005 {
1006 	return mlxsw_sp_span_port_buffer_update(mlxsw_sp_port, true);
1007 }
1008 
1009 static void mlxsw_sp_span_port_buffer_disable(struct mlxsw_sp_port *mlxsw_sp_port)
1010 {
1011 	mlxsw_sp_span_port_buffer_update(mlxsw_sp_port, false);
1012 }
1013 
1014 static struct mlxsw_sp_span_analyzed_port *
1015 mlxsw_sp_span_analyzed_port_find(struct mlxsw_sp_span *span, u16 local_port,
1016 				 bool ingress)
1017 {
1018 	struct mlxsw_sp_span_analyzed_port *analyzed_port;
1019 
1020 	list_for_each_entry(analyzed_port, &span->analyzed_ports_list, list) {
1021 		if (analyzed_port->local_port == local_port &&
1022 		    analyzed_port->ingress == ingress)
1023 			return analyzed_port;
1024 	}
1025 
1026 	return NULL;
1027 }
1028 
1029 static const struct mlxsw_sp_span_entry_ops *
1030 mlxsw_sp_span_entry_ops(struct mlxsw_sp *mlxsw_sp,
1031 			const struct net_device *to_dev)
1032 {
1033 	struct mlxsw_sp_span *span = mlxsw_sp->span;
1034 	size_t i;
1035 
1036 	for (i = 0; i < span->span_entry_ops_arr_size; ++i)
1037 		if (span->span_entry_ops_arr[i]->can_handle(to_dev))
1038 			return span->span_entry_ops_arr[i];
1039 
1040 	return NULL;
1041 }
1042 
1043 static void mlxsw_sp_span_respin_work(struct work_struct *work)
1044 {
1045 	struct mlxsw_sp_span *span;
1046 	struct mlxsw_sp *mlxsw_sp;
1047 	int i, err;
1048 
1049 	span = container_of(work, struct mlxsw_sp_span, work);
1050 	mlxsw_sp = span->mlxsw_sp;
1051 
1052 	rtnl_lock();
1053 	for (i = 0; i < mlxsw_sp->span->entries_count; i++) {
1054 		struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span->entries[i];
1055 		struct mlxsw_sp_span_parms sparms = {NULL};
1056 
1057 		if (!refcount_read(&curr->ref_count))
1058 			continue;
1059 
1060 		if (curr->ops->is_static)
1061 			continue;
1062 
1063 		err = curr->ops->parms_set(mlxsw_sp, curr->to_dev, &sparms);
1064 		if (err)
1065 			continue;
1066 
1067 		if (memcmp(&sparms, &curr->parms, sizeof(sparms))) {
1068 			mlxsw_sp_span_entry_deconfigure(curr);
1069 			mlxsw_sp_span_entry_configure(mlxsw_sp, curr, sparms);
1070 		}
1071 	}
1072 	rtnl_unlock();
1073 }
1074 
1075 void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp)
1076 {
1077 	if (atomic_read(&mlxsw_sp->span->active_entries_count) == 0)
1078 		return;
1079 	mlxsw_core_schedule_work(&mlxsw_sp->span->work);
1080 }
1081 
1082 int mlxsw_sp_span_agent_get(struct mlxsw_sp *mlxsw_sp, int *p_span_id,
1083 			    const struct mlxsw_sp_span_agent_parms *parms)
1084 {
1085 	const struct net_device *to_dev = parms->to_dev;
1086 	const struct mlxsw_sp_span_entry_ops *ops;
1087 	struct mlxsw_sp_span_entry *span_entry;
1088 	struct mlxsw_sp_span_parms sparms;
1089 	int err;
1090 
1091 	ASSERT_RTNL();
1092 
1093 	ops = mlxsw_sp_span_entry_ops(mlxsw_sp, to_dev);
1094 	if (!ops) {
1095 		dev_err(mlxsw_sp->bus_info->dev, "Cannot mirror to requested destination\n");
1096 		return -EOPNOTSUPP;
1097 	}
1098 
1099 	memset(&sparms, 0, sizeof(sparms));
1100 	err = ops->parms_set(mlxsw_sp, to_dev, &sparms);
1101 	if (err)
1102 		return err;
1103 
1104 	sparms.policer_id = parms->policer_id;
1105 	sparms.policer_enable = parms->policer_enable;
1106 	sparms.session_id = parms->session_id;
1107 	span_entry = mlxsw_sp_span_entry_get(mlxsw_sp, to_dev, ops, sparms);
1108 	if (!span_entry)
1109 		return -ENOBUFS;
1110 
1111 	*p_span_id = span_entry->id;
1112 
1113 	return 0;
1114 }
1115 
1116 void mlxsw_sp_span_agent_put(struct mlxsw_sp *mlxsw_sp, int span_id)
1117 {
1118 	struct mlxsw_sp_span_entry *span_entry;
1119 
1120 	ASSERT_RTNL();
1121 
1122 	span_entry = mlxsw_sp_span_entry_find_by_id(mlxsw_sp, span_id);
1123 	if (WARN_ON_ONCE(!span_entry))
1124 		return;
1125 
1126 	mlxsw_sp_span_entry_put(mlxsw_sp, span_entry);
1127 }
1128 
1129 static struct mlxsw_sp_span_analyzed_port *
1130 mlxsw_sp_span_analyzed_port_create(struct mlxsw_sp_span *span,
1131 				   struct mlxsw_sp_port *mlxsw_sp_port,
1132 				   bool ingress)
1133 {
1134 	struct mlxsw_sp_span_analyzed_port *analyzed_port;
1135 	int err;
1136 
1137 	analyzed_port = kzalloc_obj(*analyzed_port);
1138 	if (!analyzed_port)
1139 		return ERR_PTR(-ENOMEM);
1140 
1141 	refcount_set(&analyzed_port->ref_count, 1);
1142 	analyzed_port->local_port = mlxsw_sp_port->local_port;
1143 	analyzed_port->ingress = ingress;
1144 	list_add_tail(&analyzed_port->list, &span->analyzed_ports_list);
1145 
1146 	/* An egress mirror buffer should be allocated on the egress port which
1147 	 * does the mirroring.
1148 	 */
1149 	if (!ingress) {
1150 		err = mlxsw_sp_span_port_buffer_enable(mlxsw_sp_port);
1151 		if (err)
1152 			goto err_buffer_update;
1153 	}
1154 
1155 	return analyzed_port;
1156 
1157 err_buffer_update:
1158 	list_del(&analyzed_port->list);
1159 	kfree(analyzed_port);
1160 	return ERR_PTR(err);
1161 }
1162 
1163 static void
1164 mlxsw_sp_span_analyzed_port_destroy(struct mlxsw_sp_port *mlxsw_sp_port,
1165 				    struct mlxsw_sp_span_analyzed_port *
1166 				    analyzed_port)
1167 {
1168 	/* Remove egress mirror buffer now that port is no longer analyzed
1169 	 * at egress.
1170 	 */
1171 	if (!analyzed_port->ingress)
1172 		mlxsw_sp_span_port_buffer_disable(mlxsw_sp_port);
1173 
1174 	list_del(&analyzed_port->list);
1175 	kfree(analyzed_port);
1176 }
1177 
1178 int mlxsw_sp_span_analyzed_port_get(struct mlxsw_sp_port *mlxsw_sp_port,
1179 				    bool ingress)
1180 {
1181 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1182 	struct mlxsw_sp_span_analyzed_port *analyzed_port;
1183 	u16 local_port = mlxsw_sp_port->local_port;
1184 	int err = 0;
1185 
1186 	mutex_lock(&mlxsw_sp->span->analyzed_ports_lock);
1187 
1188 	analyzed_port = mlxsw_sp_span_analyzed_port_find(mlxsw_sp->span,
1189 							 local_port, ingress);
1190 	if (analyzed_port) {
1191 		refcount_inc(&analyzed_port->ref_count);
1192 		goto out_unlock;
1193 	}
1194 
1195 	analyzed_port = mlxsw_sp_span_analyzed_port_create(mlxsw_sp->span,
1196 							   mlxsw_sp_port,
1197 							   ingress);
1198 	if (IS_ERR(analyzed_port))
1199 		err = PTR_ERR(analyzed_port);
1200 
1201 out_unlock:
1202 	mutex_unlock(&mlxsw_sp->span->analyzed_ports_lock);
1203 	return err;
1204 }
1205 
1206 void mlxsw_sp_span_analyzed_port_put(struct mlxsw_sp_port *mlxsw_sp_port,
1207 				     bool ingress)
1208 {
1209 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1210 	struct mlxsw_sp_span_analyzed_port *analyzed_port;
1211 	u16 local_port = mlxsw_sp_port->local_port;
1212 
1213 	mutex_lock(&mlxsw_sp->span->analyzed_ports_lock);
1214 
1215 	analyzed_port = mlxsw_sp_span_analyzed_port_find(mlxsw_sp->span,
1216 							 local_port, ingress);
1217 	if (WARN_ON_ONCE(!analyzed_port))
1218 		goto out_unlock;
1219 
1220 	if (!refcount_dec_and_test(&analyzed_port->ref_count))
1221 		goto out_unlock;
1222 
1223 	mlxsw_sp_span_analyzed_port_destroy(mlxsw_sp_port, analyzed_port);
1224 
1225 out_unlock:
1226 	mutex_unlock(&mlxsw_sp->span->analyzed_ports_lock);
1227 }
1228 
1229 static int
1230 __mlxsw_sp_span_trigger_port_bind(struct mlxsw_sp_span *span,
1231 				  struct mlxsw_sp_span_trigger_entry *
1232 				  trigger_entry, bool enable)
1233 {
1234 	char mpar_pl[MLXSW_REG_MPAR_LEN];
1235 	enum mlxsw_reg_mpar_i_e i_e;
1236 
1237 	switch (trigger_entry->trigger) {
1238 	case MLXSW_SP_SPAN_TRIGGER_INGRESS:
1239 		i_e = MLXSW_REG_MPAR_TYPE_INGRESS;
1240 		break;
1241 	case MLXSW_SP_SPAN_TRIGGER_EGRESS:
1242 		i_e = MLXSW_REG_MPAR_TYPE_EGRESS;
1243 		break;
1244 	default:
1245 		WARN_ON_ONCE(1);
1246 		return -EINVAL;
1247 	}
1248 
1249 	if (trigger_entry->parms.probability_rate > MLXSW_REG_MPAR_RATE_MAX)
1250 		return -EINVAL;
1251 
1252 	mlxsw_reg_mpar_pack(mpar_pl, trigger_entry->local_port, i_e, enable,
1253 			    trigger_entry->parms.span_id,
1254 			    trigger_entry->parms.probability_rate);
1255 	return mlxsw_reg_write(span->mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
1256 }
1257 
1258 static int
1259 mlxsw_sp_span_trigger_port_bind(struct mlxsw_sp_span_trigger_entry *
1260 				trigger_entry)
1261 {
1262 	return __mlxsw_sp_span_trigger_port_bind(trigger_entry->span,
1263 						 trigger_entry, true);
1264 }
1265 
1266 static void
1267 mlxsw_sp_span_trigger_port_unbind(struct mlxsw_sp_span_trigger_entry *
1268 				  trigger_entry)
1269 {
1270 	__mlxsw_sp_span_trigger_port_bind(trigger_entry->span, trigger_entry,
1271 					  false);
1272 }
1273 
1274 static bool
1275 mlxsw_sp_span_trigger_port_matches(struct mlxsw_sp_span_trigger_entry *
1276 				   trigger_entry,
1277 				   enum mlxsw_sp_span_trigger trigger,
1278 				   struct mlxsw_sp_port *mlxsw_sp_port)
1279 {
1280 	return trigger_entry->trigger == trigger &&
1281 	       trigger_entry->local_port == mlxsw_sp_port->local_port;
1282 }
1283 
1284 static int
1285 mlxsw_sp_span_trigger_port_enable(struct mlxsw_sp_span_trigger_entry *
1286 				  trigger_entry,
1287 				  struct mlxsw_sp_port *mlxsw_sp_port, u8 tc)
1288 {
1289 	/* Port trigger are enabled during binding. */
1290 	return 0;
1291 }
1292 
1293 static void
1294 mlxsw_sp_span_trigger_port_disable(struct mlxsw_sp_span_trigger_entry *
1295 				   trigger_entry,
1296 				   struct mlxsw_sp_port *mlxsw_sp_port, u8 tc)
1297 {
1298 }
1299 
1300 static const struct mlxsw_sp_span_trigger_ops
1301 mlxsw_sp_span_trigger_port_ops = {
1302 	.bind = mlxsw_sp_span_trigger_port_bind,
1303 	.unbind = mlxsw_sp_span_trigger_port_unbind,
1304 	.matches = mlxsw_sp_span_trigger_port_matches,
1305 	.enable = mlxsw_sp_span_trigger_port_enable,
1306 	.disable = mlxsw_sp_span_trigger_port_disable,
1307 };
1308 
1309 static int
1310 mlxsw_sp1_span_trigger_global_bind(struct mlxsw_sp_span_trigger_entry *
1311 				   trigger_entry)
1312 {
1313 	return -EOPNOTSUPP;
1314 }
1315 
1316 static void
1317 mlxsw_sp1_span_trigger_global_unbind(struct mlxsw_sp_span_trigger_entry *
1318 				     trigger_entry)
1319 {
1320 }
1321 
1322 static bool
1323 mlxsw_sp1_span_trigger_global_matches(struct mlxsw_sp_span_trigger_entry *
1324 				      trigger_entry,
1325 				      enum mlxsw_sp_span_trigger trigger,
1326 				      struct mlxsw_sp_port *mlxsw_sp_port)
1327 {
1328 	WARN_ON_ONCE(1);
1329 	return false;
1330 }
1331 
1332 static int
1333 mlxsw_sp1_span_trigger_global_enable(struct mlxsw_sp_span_trigger_entry *
1334 				     trigger_entry,
1335 				     struct mlxsw_sp_port *mlxsw_sp_port,
1336 				     u8 tc)
1337 {
1338 	return -EOPNOTSUPP;
1339 }
1340 
1341 static void
1342 mlxsw_sp1_span_trigger_global_disable(struct mlxsw_sp_span_trigger_entry *
1343 				      trigger_entry,
1344 				      struct mlxsw_sp_port *mlxsw_sp_port,
1345 				      u8 tc)
1346 {
1347 }
1348 
1349 static const struct mlxsw_sp_span_trigger_ops
1350 mlxsw_sp1_span_trigger_global_ops = {
1351 	.bind = mlxsw_sp1_span_trigger_global_bind,
1352 	.unbind = mlxsw_sp1_span_trigger_global_unbind,
1353 	.matches = mlxsw_sp1_span_trigger_global_matches,
1354 	.enable = mlxsw_sp1_span_trigger_global_enable,
1355 	.disable = mlxsw_sp1_span_trigger_global_disable,
1356 };
1357 
1358 static const struct mlxsw_sp_span_trigger_ops *
1359 mlxsw_sp1_span_trigger_ops_arr[] = {
1360 	[MLXSW_SP_SPAN_TRIGGER_TYPE_PORT] = &mlxsw_sp_span_trigger_port_ops,
1361 	[MLXSW_SP_SPAN_TRIGGER_TYPE_GLOBAL] =
1362 		&mlxsw_sp1_span_trigger_global_ops,
1363 };
1364 
1365 static int
1366 mlxsw_sp2_span_trigger_global_bind(struct mlxsw_sp_span_trigger_entry *
1367 				   trigger_entry)
1368 {
1369 	struct mlxsw_sp *mlxsw_sp = trigger_entry->span->mlxsw_sp;
1370 	enum mlxsw_reg_mpagr_trigger trigger;
1371 	char mpagr_pl[MLXSW_REG_MPAGR_LEN];
1372 
1373 	switch (trigger_entry->trigger) {
1374 	case MLXSW_SP_SPAN_TRIGGER_TAIL_DROP:
1375 		trigger = MLXSW_REG_MPAGR_TRIGGER_INGRESS_SHARED_BUFFER;
1376 		break;
1377 	case MLXSW_SP_SPAN_TRIGGER_EARLY_DROP:
1378 		trigger = MLXSW_REG_MPAGR_TRIGGER_INGRESS_WRED;
1379 		break;
1380 	case MLXSW_SP_SPAN_TRIGGER_ECN:
1381 		trigger = MLXSW_REG_MPAGR_TRIGGER_EGRESS_ECN;
1382 		break;
1383 	default:
1384 		WARN_ON_ONCE(1);
1385 		return -EINVAL;
1386 	}
1387 
1388 	if (trigger_entry->parms.probability_rate > MLXSW_REG_MPAGR_RATE_MAX)
1389 		return -EINVAL;
1390 
1391 	mlxsw_reg_mpagr_pack(mpagr_pl, trigger, trigger_entry->parms.span_id,
1392 			     trigger_entry->parms.probability_rate);
1393 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpagr), mpagr_pl);
1394 }
1395 
1396 static void
1397 mlxsw_sp2_span_trigger_global_unbind(struct mlxsw_sp_span_trigger_entry *
1398 				     trigger_entry)
1399 {
1400 	/* There is no unbinding for global triggers. The trigger should be
1401 	 * disabled on all ports by now.
1402 	 */
1403 }
1404 
1405 static bool
1406 mlxsw_sp2_span_trigger_global_matches(struct mlxsw_sp_span_trigger_entry *
1407 				      trigger_entry,
1408 				      enum mlxsw_sp_span_trigger trigger,
1409 				      struct mlxsw_sp_port *mlxsw_sp_port)
1410 {
1411 	return trigger_entry->trigger == trigger;
1412 }
1413 
1414 static int
1415 __mlxsw_sp2_span_trigger_global_enable(struct mlxsw_sp_span_trigger_entry *
1416 				       trigger_entry,
1417 				       struct mlxsw_sp_port *mlxsw_sp_port,
1418 				       u8 tc, bool enable)
1419 {
1420 	struct mlxsw_sp *mlxsw_sp = trigger_entry->span->mlxsw_sp;
1421 	char momte_pl[MLXSW_REG_MOMTE_LEN];
1422 	enum mlxsw_reg_momte_type type;
1423 	int err;
1424 
1425 	switch (trigger_entry->trigger) {
1426 	case MLXSW_SP_SPAN_TRIGGER_TAIL_DROP:
1427 		type = MLXSW_REG_MOMTE_TYPE_SHARED_BUFFER_TCLASS;
1428 		break;
1429 	case MLXSW_SP_SPAN_TRIGGER_EARLY_DROP:
1430 		type = MLXSW_REG_MOMTE_TYPE_WRED;
1431 		break;
1432 	case MLXSW_SP_SPAN_TRIGGER_ECN:
1433 		type = MLXSW_REG_MOMTE_TYPE_ECN;
1434 		break;
1435 	default:
1436 		WARN_ON_ONCE(1);
1437 		return -EINVAL;
1438 	}
1439 
1440 	/* Query existing configuration in order to only change the state of
1441 	 * the specified traffic class.
1442 	 */
1443 	mlxsw_reg_momte_pack(momte_pl, mlxsw_sp_port->local_port, type);
1444 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(momte), momte_pl);
1445 	if (err)
1446 		return err;
1447 
1448 	mlxsw_reg_momte_tclass_en_set(momte_pl, tc, enable);
1449 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(momte), momte_pl);
1450 }
1451 
1452 static int
1453 mlxsw_sp2_span_trigger_global_enable(struct mlxsw_sp_span_trigger_entry *
1454 				     trigger_entry,
1455 				     struct mlxsw_sp_port *mlxsw_sp_port,
1456 				     u8 tc)
1457 {
1458 	return __mlxsw_sp2_span_trigger_global_enable(trigger_entry,
1459 						      mlxsw_sp_port, tc, true);
1460 }
1461 
1462 static void
1463 mlxsw_sp2_span_trigger_global_disable(struct mlxsw_sp_span_trigger_entry *
1464 				      trigger_entry,
1465 				      struct mlxsw_sp_port *mlxsw_sp_port,
1466 				      u8 tc)
1467 {
1468 	__mlxsw_sp2_span_trigger_global_enable(trigger_entry, mlxsw_sp_port, tc,
1469 					       false);
1470 }
1471 
1472 static const struct mlxsw_sp_span_trigger_ops
1473 mlxsw_sp2_span_trigger_global_ops = {
1474 	.bind = mlxsw_sp2_span_trigger_global_bind,
1475 	.unbind = mlxsw_sp2_span_trigger_global_unbind,
1476 	.matches = mlxsw_sp2_span_trigger_global_matches,
1477 	.enable = mlxsw_sp2_span_trigger_global_enable,
1478 	.disable = mlxsw_sp2_span_trigger_global_disable,
1479 };
1480 
1481 static const struct mlxsw_sp_span_trigger_ops *
1482 mlxsw_sp2_span_trigger_ops_arr[] = {
1483 	[MLXSW_SP_SPAN_TRIGGER_TYPE_PORT] = &mlxsw_sp_span_trigger_port_ops,
1484 	[MLXSW_SP_SPAN_TRIGGER_TYPE_GLOBAL] =
1485 		&mlxsw_sp2_span_trigger_global_ops,
1486 };
1487 
1488 static void
1489 mlxsw_sp_span_trigger_ops_set(struct mlxsw_sp_span_trigger_entry *trigger_entry)
1490 {
1491 	struct mlxsw_sp_span *span = trigger_entry->span;
1492 	enum mlxsw_sp_span_trigger_type type;
1493 
1494 	switch (trigger_entry->trigger) {
1495 	case MLXSW_SP_SPAN_TRIGGER_INGRESS:
1496 	case MLXSW_SP_SPAN_TRIGGER_EGRESS:
1497 		type = MLXSW_SP_SPAN_TRIGGER_TYPE_PORT;
1498 		break;
1499 	case MLXSW_SP_SPAN_TRIGGER_TAIL_DROP:
1500 	case MLXSW_SP_SPAN_TRIGGER_EARLY_DROP:
1501 	case MLXSW_SP_SPAN_TRIGGER_ECN:
1502 		type = MLXSW_SP_SPAN_TRIGGER_TYPE_GLOBAL;
1503 		break;
1504 	default:
1505 		WARN_ON_ONCE(1);
1506 		return;
1507 	}
1508 
1509 	trigger_entry->ops = span->span_trigger_ops_arr[type];
1510 }
1511 
1512 static struct mlxsw_sp_span_trigger_entry *
1513 mlxsw_sp_span_trigger_entry_create(struct mlxsw_sp_span *span,
1514 				   enum mlxsw_sp_span_trigger trigger,
1515 				   struct mlxsw_sp_port *mlxsw_sp_port,
1516 				   const struct mlxsw_sp_span_trigger_parms
1517 				   *parms)
1518 {
1519 	struct mlxsw_sp_span_trigger_entry *trigger_entry;
1520 	int err;
1521 
1522 	trigger_entry = kzalloc_obj(*trigger_entry);
1523 	if (!trigger_entry)
1524 		return ERR_PTR(-ENOMEM);
1525 
1526 	refcount_set(&trigger_entry->ref_count, 1);
1527 	trigger_entry->local_port = mlxsw_sp_port ? mlxsw_sp_port->local_port :
1528 						    0;
1529 	trigger_entry->trigger = trigger;
1530 	memcpy(&trigger_entry->parms, parms, sizeof(trigger_entry->parms));
1531 	trigger_entry->span = span;
1532 	mlxsw_sp_span_trigger_ops_set(trigger_entry);
1533 	list_add_tail(&trigger_entry->list, &span->trigger_entries_list);
1534 
1535 	err = trigger_entry->ops->bind(trigger_entry);
1536 	if (err)
1537 		goto err_trigger_entry_bind;
1538 
1539 	return trigger_entry;
1540 
1541 err_trigger_entry_bind:
1542 	list_del(&trigger_entry->list);
1543 	kfree(trigger_entry);
1544 	return ERR_PTR(err);
1545 }
1546 
1547 static void
1548 mlxsw_sp_span_trigger_entry_destroy(struct mlxsw_sp_span *span,
1549 				    struct mlxsw_sp_span_trigger_entry *
1550 				    trigger_entry)
1551 {
1552 	trigger_entry->ops->unbind(trigger_entry);
1553 	list_del(&trigger_entry->list);
1554 	kfree(trigger_entry);
1555 }
1556 
1557 static struct mlxsw_sp_span_trigger_entry *
1558 mlxsw_sp_span_trigger_entry_find(struct mlxsw_sp_span *span,
1559 				 enum mlxsw_sp_span_trigger trigger,
1560 				 struct mlxsw_sp_port *mlxsw_sp_port)
1561 {
1562 	struct mlxsw_sp_span_trigger_entry *trigger_entry;
1563 
1564 	list_for_each_entry(trigger_entry, &span->trigger_entries_list, list) {
1565 		if (trigger_entry->ops->matches(trigger_entry, trigger,
1566 						mlxsw_sp_port))
1567 			return trigger_entry;
1568 	}
1569 
1570 	return NULL;
1571 }
1572 
1573 int mlxsw_sp_span_agent_bind(struct mlxsw_sp *mlxsw_sp,
1574 			     enum mlxsw_sp_span_trigger trigger,
1575 			     struct mlxsw_sp_port *mlxsw_sp_port,
1576 			     const struct mlxsw_sp_span_trigger_parms *parms)
1577 {
1578 	struct mlxsw_sp_span_trigger_entry *trigger_entry;
1579 	int err = 0;
1580 
1581 	ASSERT_RTNL();
1582 
1583 	if (!mlxsw_sp_span_entry_find_by_id(mlxsw_sp, parms->span_id))
1584 		return -EINVAL;
1585 
1586 	trigger_entry = mlxsw_sp_span_trigger_entry_find(mlxsw_sp->span,
1587 							 trigger,
1588 							 mlxsw_sp_port);
1589 	if (trigger_entry) {
1590 		if (trigger_entry->parms.span_id != parms->span_id ||
1591 		    trigger_entry->parms.probability_rate !=
1592 		    parms->probability_rate)
1593 			return -EINVAL;
1594 		refcount_inc(&trigger_entry->ref_count);
1595 		goto out;
1596 	}
1597 
1598 	trigger_entry = mlxsw_sp_span_trigger_entry_create(mlxsw_sp->span,
1599 							   trigger,
1600 							   mlxsw_sp_port,
1601 							   parms);
1602 	if (IS_ERR(trigger_entry))
1603 		err = PTR_ERR(trigger_entry);
1604 
1605 out:
1606 	return err;
1607 }
1608 
1609 void mlxsw_sp_span_agent_unbind(struct mlxsw_sp *mlxsw_sp,
1610 				enum mlxsw_sp_span_trigger trigger,
1611 				struct mlxsw_sp_port *mlxsw_sp_port,
1612 				const struct mlxsw_sp_span_trigger_parms *parms)
1613 {
1614 	struct mlxsw_sp_span_trigger_entry *trigger_entry;
1615 
1616 	ASSERT_RTNL();
1617 
1618 	if (WARN_ON_ONCE(!mlxsw_sp_span_entry_find_by_id(mlxsw_sp,
1619 							 parms->span_id)))
1620 		return;
1621 
1622 	trigger_entry = mlxsw_sp_span_trigger_entry_find(mlxsw_sp->span,
1623 							 trigger,
1624 							 mlxsw_sp_port);
1625 	if (WARN_ON_ONCE(!trigger_entry))
1626 		return;
1627 
1628 	if (!refcount_dec_and_test(&trigger_entry->ref_count))
1629 		return;
1630 
1631 	mlxsw_sp_span_trigger_entry_destroy(mlxsw_sp->span, trigger_entry);
1632 }
1633 
1634 int mlxsw_sp_span_trigger_enable(struct mlxsw_sp_port *mlxsw_sp_port,
1635 				 enum mlxsw_sp_span_trigger trigger, u8 tc)
1636 {
1637 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1638 	struct mlxsw_sp_span_trigger_entry *trigger_entry;
1639 
1640 	ASSERT_RTNL();
1641 
1642 	trigger_entry = mlxsw_sp_span_trigger_entry_find(mlxsw_sp->span,
1643 							 trigger,
1644 							 mlxsw_sp_port);
1645 	if (WARN_ON_ONCE(!trigger_entry))
1646 		return -EINVAL;
1647 
1648 	return trigger_entry->ops->enable(trigger_entry, mlxsw_sp_port, tc);
1649 }
1650 
1651 void mlxsw_sp_span_trigger_disable(struct mlxsw_sp_port *mlxsw_sp_port,
1652 				   enum mlxsw_sp_span_trigger trigger, u8 tc)
1653 {
1654 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1655 	struct mlxsw_sp_span_trigger_entry *trigger_entry;
1656 
1657 	ASSERT_RTNL();
1658 
1659 	trigger_entry = mlxsw_sp_span_trigger_entry_find(mlxsw_sp->span,
1660 							 trigger,
1661 							 mlxsw_sp_port);
1662 	if (WARN_ON_ONCE(!trigger_entry))
1663 		return;
1664 
1665 	return trigger_entry->ops->disable(trigger_entry, mlxsw_sp_port, tc);
1666 }
1667 
1668 bool mlxsw_sp_span_trigger_is_ingress(enum mlxsw_sp_span_trigger trigger)
1669 {
1670 	switch (trigger) {
1671 	case MLXSW_SP_SPAN_TRIGGER_INGRESS:
1672 	case MLXSW_SP_SPAN_TRIGGER_EARLY_DROP:
1673 	case MLXSW_SP_SPAN_TRIGGER_TAIL_DROP:
1674 		return true;
1675 	case MLXSW_SP_SPAN_TRIGGER_EGRESS:
1676 	case MLXSW_SP_SPAN_TRIGGER_ECN:
1677 		return false;
1678 	}
1679 
1680 	WARN_ON_ONCE(1);
1681 	return false;
1682 }
1683 
1684 static int mlxsw_sp1_span_init(struct mlxsw_sp *mlxsw_sp)
1685 {
1686 	size_t arr_size = ARRAY_SIZE(mlxsw_sp1_span_entry_ops_arr);
1687 
1688 	/* Must be first to avoid NULL pointer dereference by subsequent
1689 	 * can_handle() callbacks.
1690 	 */
1691 	if (WARN_ON(mlxsw_sp1_span_entry_ops_arr[0] !=
1692 		    &mlxsw_sp1_span_entry_ops_cpu))
1693 		return -EINVAL;
1694 
1695 	mlxsw_sp->span->span_trigger_ops_arr = mlxsw_sp1_span_trigger_ops_arr;
1696 	mlxsw_sp->span->span_entry_ops_arr = mlxsw_sp1_span_entry_ops_arr;
1697 	mlxsw_sp->span->span_entry_ops_arr_size = arr_size;
1698 
1699 	return 0;
1700 }
1701 
1702 static int mlxsw_sp1_span_policer_id_base_set(struct mlxsw_sp *mlxsw_sp,
1703 					      u16 policer_id_base)
1704 {
1705 	return -EOPNOTSUPP;
1706 }
1707 
1708 const struct mlxsw_sp_span_ops mlxsw_sp1_span_ops = {
1709 	.init = mlxsw_sp1_span_init,
1710 	.policer_id_base_set = mlxsw_sp1_span_policer_id_base_set,
1711 };
1712 
1713 static int mlxsw_sp2_span_init(struct mlxsw_sp *mlxsw_sp)
1714 {
1715 	size_t arr_size = ARRAY_SIZE(mlxsw_sp2_span_entry_ops_arr);
1716 
1717 	/* Must be first to avoid NULL pointer dereference by subsequent
1718 	 * can_handle() callbacks.
1719 	 */
1720 	if (WARN_ON(mlxsw_sp2_span_entry_ops_arr[0] !=
1721 		    &mlxsw_sp2_span_entry_ops_cpu))
1722 		return -EINVAL;
1723 
1724 	mlxsw_sp->span->span_trigger_ops_arr = mlxsw_sp2_span_trigger_ops_arr;
1725 	mlxsw_sp->span->span_entry_ops_arr = mlxsw_sp2_span_entry_ops_arr;
1726 	mlxsw_sp->span->span_entry_ops_arr_size = arr_size;
1727 
1728 	return 0;
1729 }
1730 
1731 #define MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR 38
1732 #define MLXSW_SP3_SPAN_EG_MIRROR_BUFFER_FACTOR 50
1733 
1734 static int mlxsw_sp2_span_policer_id_base_set(struct mlxsw_sp *mlxsw_sp,
1735 					      u16 policer_id_base)
1736 {
1737 	char mogcr_pl[MLXSW_REG_MOGCR_LEN] = {0};
1738 	int err;
1739 
1740 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mogcr), mogcr_pl);
1741 	if (err)
1742 		return err;
1743 
1744 	mlxsw_reg_mogcr_mirroring_pid_base_set(mogcr_pl, policer_id_base);
1745 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mogcr), mogcr_pl);
1746 }
1747 
1748 const struct mlxsw_sp_span_ops mlxsw_sp2_span_ops = {
1749 	.init = mlxsw_sp2_span_init,
1750 	.policer_id_base_set = mlxsw_sp2_span_policer_id_base_set,
1751 };
1752 
1753 const struct mlxsw_sp_span_ops mlxsw_sp3_span_ops = {
1754 	.init = mlxsw_sp2_span_init,
1755 	.policer_id_base_set = mlxsw_sp2_span_policer_id_base_set,
1756 };
1757