1// SPDX-License-Identifier: GPL-2.0+
2/* Microchip Sparx5 Switch driver
3 *
4 * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
5 */
6
7#include <linux/if_bridge.h>
8#include <net/switchdev.h>
9
10#include "sparx5_main_regs.h"
11#include "sparx5_main.h"
12
13static struct workqueue_struct *sparx5_owq;
14
15struct sparx5_switchdev_event_work {
16	struct work_struct work;
17	struct switchdev_notifier_fdb_info fdb_info;
18	struct net_device *dev;
19	struct sparx5 *sparx5;
20	unsigned long event;
21};
22
23static int sparx5_port_attr_pre_bridge_flags(struct sparx5_port *port,
24					     struct switchdev_brport_flags flags)
25{
26	if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD))
27		return -EINVAL;
28
29	return 0;
30}
31
32static void sparx5_port_update_mcast_ip_flood(struct sparx5_port *port, bool flood_flag)
33{
34	bool should_flood = flood_flag || port->is_mrouter;
35	int pgid;
36
37	for (pgid = PGID_IPV4_MC_DATA; pgid <= PGID_IPV6_MC_CTRL; pgid++)
38		sparx5_pgid_update_mask(port, pgid, should_flood);
39}
40
41static void sparx5_port_attr_bridge_flags(struct sparx5_port *port,
42					  struct switchdev_brport_flags flags)
43{
44	if (flags.mask & BR_MCAST_FLOOD) {
45		sparx5_pgid_update_mask(port, PGID_MC_FLOOD, !!(flags.val & BR_MCAST_FLOOD));
46		sparx5_port_update_mcast_ip_flood(port, !!(flags.val & BR_MCAST_FLOOD));
47	}
48
49	if (flags.mask & BR_FLOOD)
50		sparx5_pgid_update_mask(port, PGID_UC_FLOOD, !!(flags.val & BR_FLOOD));
51	if (flags.mask & BR_BCAST_FLOOD)
52		sparx5_pgid_update_mask(port, PGID_BCAST, !!(flags.val & BR_BCAST_FLOOD));
53}
54
55static void sparx5_attr_stp_state_set(struct sparx5_port *port,
56				      u8 state)
57{
58	struct sparx5 *sparx5 = port->sparx5;
59
60	if (!test_bit(port->portno, sparx5->bridge_mask)) {
61		netdev_err(port->ndev,
62			   "Controlling non-bridged port %d?\n", port->portno);
63		return;
64	}
65
66	switch (state) {
67	case BR_STATE_FORWARDING:
68		set_bit(port->portno, sparx5->bridge_fwd_mask);
69		fallthrough;
70	case BR_STATE_LEARNING:
71		set_bit(port->portno, sparx5->bridge_lrn_mask);
72		break;
73
74	default:
75		/* All other states treated as blocking */
76		clear_bit(port->portno, sparx5->bridge_fwd_mask);
77		clear_bit(port->portno, sparx5->bridge_lrn_mask);
78		break;
79	}
80
81	/* apply the bridge_fwd_mask to all the ports */
82	sparx5_update_fwd(sparx5);
83}
84
85static void sparx5_port_attr_ageing_set(struct sparx5_port *port,
86					unsigned long ageing_clock_t)
87{
88	unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t);
89	u32 ageing_time = jiffies_to_msecs(ageing_jiffies);
90
91	sparx5_set_ageing(port->sparx5, ageing_time);
92}
93
94static void sparx5_port_attr_mrouter_set(struct sparx5_port *port,
95					 struct net_device *orig_dev,
96					 bool enable)
97{
98	struct sparx5 *sparx5 = port->sparx5;
99	struct sparx5_mdb_entry *e;
100	bool flood_flag;
101
102	if ((enable && port->is_mrouter) || (!enable && !port->is_mrouter))
103		return;
104
105	/* Add/del mrouter port on all active mdb entries in HW.
106	 * Don't change entry port mask, since that represents
107	 * ports that actually joined that group.
108	 */
109	mutex_lock(&sparx5->mdb_lock);
110	list_for_each_entry(e, &sparx5->mdb_entries, list) {
111		if (!test_bit(port->portno, e->port_mask) &&
112		    ether_addr_is_ip_mcast(e->addr))
113			sparx5_pgid_update_mask(port, e->pgid_idx, enable);
114	}
115	mutex_unlock(&sparx5->mdb_lock);
116
117	/* Enable/disable flooding depending on if port is mrouter port
118	 * or if mcast flood is enabled.
119	 */
120	port->is_mrouter = enable;
121	flood_flag = br_port_flag_is_set(port->ndev, BR_MCAST_FLOOD);
122	sparx5_port_update_mcast_ip_flood(port, flood_flag);
123}
124
125static int sparx5_port_attr_set(struct net_device *dev, const void *ctx,
126				const struct switchdev_attr *attr,
127				struct netlink_ext_ack *extack)
128{
129	struct sparx5_port *port = netdev_priv(dev);
130
131	switch (attr->id) {
132	case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
133		return sparx5_port_attr_pre_bridge_flags(port,
134							 attr->u.brport_flags);
135	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
136		sparx5_port_attr_bridge_flags(port, attr->u.brport_flags);
137		break;
138	case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
139		sparx5_attr_stp_state_set(port, attr->u.stp_state);
140		break;
141	case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
142		sparx5_port_attr_ageing_set(port, attr->u.ageing_time);
143		break;
144	case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
145		/* Used PVID 1 when default_pvid is 0, to avoid
146		 * collision with non-bridged ports.
147		 */
148		if (port->pvid == 0)
149			port->pvid = 1;
150		port->vlan_aware = attr->u.vlan_filtering;
151		sparx5_vlan_port_apply(port->sparx5, port);
152		break;
153	case SWITCHDEV_ATTR_ID_PORT_MROUTER:
154		sparx5_port_attr_mrouter_set(port,
155					     attr->orig_dev,
156					     attr->u.mrouter);
157		break;
158	default:
159		return -EOPNOTSUPP;
160	}
161
162	return 0;
163}
164
165static int sparx5_port_bridge_join(struct sparx5_port *port,
166				   struct net_device *bridge,
167				   struct netlink_ext_ack *extack)
168{
169	struct sparx5 *sparx5 = port->sparx5;
170	struct net_device *ndev = port->ndev;
171	int err;
172
173	if (bitmap_empty(sparx5->bridge_mask, SPX5_PORTS))
174		/* First bridged port */
175		sparx5->hw_bridge_dev = bridge;
176	else
177		if (sparx5->hw_bridge_dev != bridge)
178			/* This is adding the port to a second bridge, this is
179			 * unsupported
180			 */
181			return -ENODEV;
182
183	set_bit(port->portno, sparx5->bridge_mask);
184
185	err = switchdev_bridge_port_offload(ndev, ndev, NULL, NULL, NULL,
186					    false, extack);
187	if (err)
188		goto err_switchdev_offload;
189
190	/* Remove standalone port entry */
191	sparx5_mact_forget(sparx5, ndev->dev_addr, 0);
192
193	/* Port enters in bridge mode therefor don't need to copy to CPU
194	 * frames for multicast in case the bridge is not requesting them
195	 */
196	__dev_mc_unsync(ndev, sparx5_mc_unsync);
197
198	return 0;
199
200err_switchdev_offload:
201	clear_bit(port->portno, sparx5->bridge_mask);
202	return err;
203}
204
205static void sparx5_port_bridge_leave(struct sparx5_port *port,
206				     struct net_device *bridge)
207{
208	struct sparx5 *sparx5 = port->sparx5;
209
210	switchdev_bridge_port_unoffload(port->ndev, NULL, NULL, NULL);
211
212	clear_bit(port->portno, sparx5->bridge_mask);
213	if (bitmap_empty(sparx5->bridge_mask, SPX5_PORTS))
214		sparx5->hw_bridge_dev = NULL;
215
216	/* Clear bridge vlan settings before updating the port settings */
217	port->vlan_aware = 0;
218	port->pvid = NULL_VID;
219	port->vid = NULL_VID;
220
221	/* Forward frames to CPU */
222	sparx5_mact_learn(sparx5, PGID_CPU, port->ndev->dev_addr, 0);
223
224	/* Port enters in host more therefore restore mc list */
225	__dev_mc_sync(port->ndev, sparx5_mc_sync, sparx5_mc_unsync);
226}
227
228static int sparx5_port_changeupper(struct net_device *dev,
229				   struct netdev_notifier_changeupper_info *info)
230{
231	struct sparx5_port *port = netdev_priv(dev);
232	struct netlink_ext_ack *extack;
233	int err = 0;
234
235	extack = netdev_notifier_info_to_extack(&info->info);
236
237	if (netif_is_bridge_master(info->upper_dev)) {
238		if (info->linking)
239			err = sparx5_port_bridge_join(port, info->upper_dev,
240						      extack);
241		else
242			sparx5_port_bridge_leave(port, info->upper_dev);
243
244		sparx5_vlan_port_apply(port->sparx5, port);
245	}
246
247	return err;
248}
249
250static int sparx5_port_add_addr(struct net_device *dev, bool up)
251{
252	struct sparx5_port *port = netdev_priv(dev);
253	struct sparx5 *sparx5 = port->sparx5;
254	u16 vid = port->pvid;
255
256	if (up)
257		sparx5_mact_learn(sparx5, PGID_CPU, port->ndev->dev_addr, vid);
258	else
259		sparx5_mact_forget(sparx5, port->ndev->dev_addr, vid);
260
261	return 0;
262}
263
264static int sparx5_netdevice_port_event(struct net_device *dev,
265				       struct notifier_block *nb,
266				       unsigned long event, void *ptr)
267{
268	int err = 0;
269
270	if (!sparx5_netdevice_check(dev))
271		return 0;
272
273	switch (event) {
274	case NETDEV_CHANGEUPPER:
275		err = sparx5_port_changeupper(dev, ptr);
276		break;
277	case NETDEV_PRE_UP:
278		err = sparx5_port_add_addr(dev, true);
279		break;
280	case NETDEV_DOWN:
281		err = sparx5_port_add_addr(dev, false);
282		break;
283	}
284
285	return err;
286}
287
288static int sparx5_netdevice_event(struct notifier_block *nb,
289				  unsigned long event, void *ptr)
290{
291	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
292	int ret = 0;
293
294	ret = sparx5_netdevice_port_event(dev, nb, event, ptr);
295
296	return notifier_from_errno(ret);
297}
298
299static void sparx5_switchdev_bridge_fdb_event_work(struct work_struct *work)
300{
301	struct sparx5_switchdev_event_work *switchdev_work =
302		container_of(work, struct sparx5_switchdev_event_work, work);
303	struct net_device *dev = switchdev_work->dev;
304	struct switchdev_notifier_fdb_info *fdb_info;
305	struct sparx5_port *port;
306	struct sparx5 *sparx5;
307	bool host_addr;
308	u16 vid;
309
310	rtnl_lock();
311	if (!sparx5_netdevice_check(dev)) {
312		host_addr = true;
313		sparx5 = switchdev_work->sparx5;
314	} else {
315		host_addr = false;
316		sparx5 = switchdev_work->sparx5;
317		port = netdev_priv(dev);
318	}
319
320	fdb_info = &switchdev_work->fdb_info;
321
322	/* Used PVID 1 when default_pvid is 0, to avoid
323	 * collision with non-bridged ports.
324	 */
325	if (fdb_info->vid == 0)
326		vid = 1;
327	else
328		vid = fdb_info->vid;
329
330	switch (switchdev_work->event) {
331	case SWITCHDEV_FDB_ADD_TO_DEVICE:
332		if (host_addr)
333			sparx5_add_mact_entry(sparx5, dev, PGID_CPU,
334					      fdb_info->addr, vid);
335		else
336			sparx5_add_mact_entry(sparx5, port->ndev, port->portno,
337					      fdb_info->addr, vid);
338		break;
339	case SWITCHDEV_FDB_DEL_TO_DEVICE:
340		sparx5_del_mact_entry(sparx5, fdb_info->addr, vid);
341		break;
342	}
343
344	rtnl_unlock();
345	kfree(switchdev_work->fdb_info.addr);
346	kfree(switchdev_work);
347	dev_put(dev);
348}
349
350static void sparx5_schedule_work(struct work_struct *work)
351{
352	queue_work(sparx5_owq, work);
353}
354
355static int sparx5_switchdev_event(struct notifier_block *nb,
356				  unsigned long event, void *ptr)
357{
358	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
359	struct sparx5_switchdev_event_work *switchdev_work;
360	struct switchdev_notifier_fdb_info *fdb_info;
361	struct switchdev_notifier_info *info = ptr;
362	struct sparx5 *spx5;
363	int err;
364
365	spx5 = container_of(nb, struct sparx5, switchdev_nb);
366
367	switch (event) {
368	case SWITCHDEV_PORT_ATTR_SET:
369		err = switchdev_handle_port_attr_set(dev, ptr,
370						     sparx5_netdevice_check,
371						     sparx5_port_attr_set);
372		return notifier_from_errno(err);
373	case SWITCHDEV_FDB_ADD_TO_DEVICE:
374		fallthrough;
375	case SWITCHDEV_FDB_DEL_TO_DEVICE:
376		switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
377		if (!switchdev_work)
378			return NOTIFY_BAD;
379
380		switchdev_work->dev = dev;
381		switchdev_work->event = event;
382		switchdev_work->sparx5 = spx5;
383
384		fdb_info = container_of(info,
385					struct switchdev_notifier_fdb_info,
386					info);
387		INIT_WORK(&switchdev_work->work,
388			  sparx5_switchdev_bridge_fdb_event_work);
389		memcpy(&switchdev_work->fdb_info, ptr,
390		       sizeof(switchdev_work->fdb_info));
391		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
392		if (!switchdev_work->fdb_info.addr)
393			goto err_addr_alloc;
394
395		ether_addr_copy((u8 *)switchdev_work->fdb_info.addr,
396				fdb_info->addr);
397		dev_hold(dev);
398
399		sparx5_schedule_work(&switchdev_work->work);
400		break;
401	}
402
403	return NOTIFY_DONE;
404err_addr_alloc:
405	kfree(switchdev_work);
406	return NOTIFY_BAD;
407}
408
409static int sparx5_handle_port_vlan_add(struct net_device *dev,
410				       struct notifier_block *nb,
411				       const struct switchdev_obj_port_vlan *v)
412{
413	struct sparx5_port *port = netdev_priv(dev);
414
415	if (netif_is_bridge_master(dev)) {
416		struct sparx5 *sparx5 =
417			container_of(nb, struct sparx5,
418				     switchdev_blocking_nb);
419
420		/* Flood broadcast to CPU */
421		sparx5_mact_learn(sparx5, PGID_BCAST, dev->broadcast,
422				  v->vid);
423		return 0;
424	}
425
426	if (!sparx5_netdevice_check(dev))
427		return -EOPNOTSUPP;
428
429	return sparx5_vlan_vid_add(port, v->vid,
430				  v->flags & BRIDGE_VLAN_INFO_PVID,
431				  v->flags & BRIDGE_VLAN_INFO_UNTAGGED);
432}
433
434static int sparx5_alloc_mdb_entry(struct sparx5 *sparx5,
435				  const unsigned char *addr,
436				  u16 vid,
437				  struct sparx5_mdb_entry **entry_out)
438{
439	struct sparx5_mdb_entry *entry;
440	u16 pgid_idx;
441	int err;
442
443	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
444	if (!entry)
445		return -ENOMEM;
446
447	err = sparx5_pgid_alloc_mcast(sparx5, &pgid_idx);
448	if (err) {
449		kfree(entry);
450		return err;
451	}
452
453	memcpy(entry->addr, addr, ETH_ALEN);
454	entry->vid = vid;
455	entry->pgid_idx = pgid_idx;
456
457	mutex_lock(&sparx5->mdb_lock);
458	list_add_tail(&entry->list, &sparx5->mdb_entries);
459	mutex_unlock(&sparx5->mdb_lock);
460
461	*entry_out = entry;
462	return 0;
463}
464
465static void sparx5_free_mdb_entry(struct sparx5 *sparx5,
466				  const unsigned char *addr,
467				  u16 vid)
468{
469	struct sparx5_mdb_entry *entry, *tmp;
470
471	mutex_lock(&sparx5->mdb_lock);
472	list_for_each_entry_safe(entry, tmp, &sparx5->mdb_entries, list) {
473		if ((vid == 0 || entry->vid == vid) &&
474		    ether_addr_equal(addr, entry->addr)) {
475			list_del(&entry->list);
476
477			sparx5_pgid_free(sparx5, entry->pgid_idx);
478			kfree(entry);
479			goto out;
480		}
481	}
482
483out:
484	mutex_unlock(&sparx5->mdb_lock);
485}
486
487static struct sparx5_mdb_entry *sparx5_mdb_get_entry(struct sparx5 *sparx5,
488						     const unsigned char *addr,
489						     u16 vid)
490{
491	struct sparx5_mdb_entry *e, *found = NULL;
492
493	mutex_lock(&sparx5->mdb_lock);
494	list_for_each_entry(e, &sparx5->mdb_entries, list) {
495		if (ether_addr_equal(e->addr, addr) && e->vid == vid) {
496			found = e;
497			goto out;
498		}
499	}
500
501out:
502	mutex_unlock(&sparx5->mdb_lock);
503	return found;
504}
505
506static void sparx5_cpu_copy_ena(struct sparx5 *spx5, u16 pgid, bool enable)
507{
508	spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(enable),
509		 ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5,
510		 ANA_AC_PGID_MISC_CFG(pgid));
511}
512
513static int sparx5_handle_port_mdb_add(struct net_device *dev,
514				      struct notifier_block *nb,
515				      const struct switchdev_obj_port_mdb *v)
516{
517	struct sparx5_port *port = netdev_priv(dev);
518	struct sparx5 *spx5 = port->sparx5;
519	struct sparx5_mdb_entry *entry;
520	bool is_host, is_new;
521	int err, i;
522	u16 vid;
523
524	if (!sparx5_netdevice_check(dev))
525		return -EOPNOTSUPP;
526
527	is_host = netif_is_bridge_master(v->obj.orig_dev);
528
529	/* When VLAN unaware the vlan value is not parsed and we receive vid 0.
530	 * Fall back to bridge vid 1.
531	 */
532	if (!br_vlan_enabled(spx5->hw_bridge_dev))
533		vid = 1;
534	else
535		vid = v->vid;
536
537	is_new = false;
538	entry = sparx5_mdb_get_entry(spx5, v->addr, vid);
539	if (!entry) {
540		err = sparx5_alloc_mdb_entry(spx5, v->addr, vid, &entry);
541		is_new = true;
542		if (err)
543			return err;
544	}
545
546	mutex_lock(&spx5->mdb_lock);
547
548	/* Add any mrouter ports to the new entry */
549	if (is_new && ether_addr_is_ip_mcast(v->addr))
550		for (i = 0; i < SPX5_PORTS; i++)
551			if (spx5->ports[i] && spx5->ports[i]->is_mrouter)
552				sparx5_pgid_update_mask(spx5->ports[i],
553							entry->pgid_idx,
554							true);
555
556	if (is_host && !entry->cpu_copy) {
557		sparx5_cpu_copy_ena(spx5, entry->pgid_idx, true);
558		entry->cpu_copy = true;
559	} else if (!is_host) {
560		sparx5_pgid_update_mask(port, entry->pgid_idx, true);
561		set_bit(port->portno, entry->port_mask);
562	}
563	mutex_unlock(&spx5->mdb_lock);
564
565	sparx5_mact_learn(spx5, entry->pgid_idx, entry->addr, entry->vid);
566
567	return 0;
568}
569
570static int sparx5_handle_port_mdb_del(struct net_device *dev,
571				      struct notifier_block *nb,
572				      const struct switchdev_obj_port_mdb *v)
573{
574	struct sparx5_port *port = netdev_priv(dev);
575	struct sparx5 *spx5 = port->sparx5;
576	struct sparx5_mdb_entry *entry;
577	bool is_host;
578	u16 vid;
579
580	if (!sparx5_netdevice_check(dev))
581		return -EOPNOTSUPP;
582
583	is_host = netif_is_bridge_master(v->obj.orig_dev);
584
585	if (!br_vlan_enabled(spx5->hw_bridge_dev))
586		vid = 1;
587	else
588		vid = v->vid;
589
590	entry = sparx5_mdb_get_entry(spx5, v->addr, vid);
591	if (!entry)
592		return 0;
593
594	mutex_lock(&spx5->mdb_lock);
595	if (is_host && entry->cpu_copy) {
596		sparx5_cpu_copy_ena(spx5, entry->pgid_idx, false);
597		entry->cpu_copy = false;
598	} else if (!is_host) {
599		clear_bit(port->portno, entry->port_mask);
600
601		/* Port not mrouter port or addr is L2 mcast, remove port from mask. */
602		if (!port->is_mrouter || !ether_addr_is_ip_mcast(v->addr))
603			sparx5_pgid_update_mask(port, entry->pgid_idx, false);
604	}
605	mutex_unlock(&spx5->mdb_lock);
606
607	if (bitmap_empty(entry->port_mask, SPX5_PORTS) && !entry->cpu_copy) {
608		 /* Clear pgid in case mrouter ports exists
609		  * that are not part of the group.
610		  */
611		sparx5_pgid_clear(spx5, entry->pgid_idx);
612		sparx5_mact_forget(spx5, entry->addr, entry->vid);
613		sparx5_free_mdb_entry(spx5, entry->addr, entry->vid);
614	}
615	return 0;
616}
617
618static int sparx5_handle_port_obj_add(struct net_device *dev,
619				      struct notifier_block *nb,
620				      struct switchdev_notifier_port_obj_info *info)
621{
622	const struct switchdev_obj *obj = info->obj;
623	int err;
624
625	switch (obj->id) {
626	case SWITCHDEV_OBJ_ID_PORT_VLAN:
627		err = sparx5_handle_port_vlan_add(dev, nb,
628						  SWITCHDEV_OBJ_PORT_VLAN(obj));
629		break;
630	case SWITCHDEV_OBJ_ID_PORT_MDB:
631	case SWITCHDEV_OBJ_ID_HOST_MDB:
632		err = sparx5_handle_port_mdb_add(dev, nb,
633						 SWITCHDEV_OBJ_PORT_MDB(obj));
634		break;
635	default:
636		err = -EOPNOTSUPP;
637		break;
638	}
639
640	info->handled = true;
641	return err;
642}
643
644static int sparx5_handle_port_vlan_del(struct net_device *dev,
645				       struct notifier_block *nb,
646				       u16 vid)
647{
648	struct sparx5_port *port = netdev_priv(dev);
649	int ret;
650
651	/* Master bridge? */
652	if (netif_is_bridge_master(dev)) {
653		struct sparx5 *sparx5 =
654			container_of(nb, struct sparx5,
655				     switchdev_blocking_nb);
656
657		sparx5_mact_forget(sparx5, dev->broadcast, vid);
658		return 0;
659	}
660
661	if (!sparx5_netdevice_check(dev))
662		return -EOPNOTSUPP;
663
664	ret = sparx5_vlan_vid_del(port, vid);
665	if (ret)
666		return ret;
667
668	return 0;
669}
670
671static int sparx5_handle_port_obj_del(struct net_device *dev,
672				      struct notifier_block *nb,
673				      struct switchdev_notifier_port_obj_info *info)
674{
675	const struct switchdev_obj *obj = info->obj;
676	int err;
677
678	switch (obj->id) {
679	case SWITCHDEV_OBJ_ID_PORT_VLAN:
680		err = sparx5_handle_port_vlan_del(dev, nb,
681						  SWITCHDEV_OBJ_PORT_VLAN(obj)->vid);
682		break;
683	case SWITCHDEV_OBJ_ID_PORT_MDB:
684	case SWITCHDEV_OBJ_ID_HOST_MDB:
685		err = sparx5_handle_port_mdb_del(dev, nb,
686						 SWITCHDEV_OBJ_PORT_MDB(obj));
687		break;
688	default:
689		err = -EOPNOTSUPP;
690		break;
691	}
692
693	info->handled = true;
694	return err;
695}
696
697static int sparx5_switchdev_blocking_event(struct notifier_block *nb,
698					   unsigned long event,
699					   void *ptr)
700{
701	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
702	int err;
703
704	switch (event) {
705	case SWITCHDEV_PORT_OBJ_ADD:
706		err = sparx5_handle_port_obj_add(dev, nb, ptr);
707		return notifier_from_errno(err);
708	case SWITCHDEV_PORT_OBJ_DEL:
709		err = sparx5_handle_port_obj_del(dev, nb, ptr);
710		return notifier_from_errno(err);
711	case SWITCHDEV_PORT_ATTR_SET:
712		err = switchdev_handle_port_attr_set(dev, ptr,
713						     sparx5_netdevice_check,
714						     sparx5_port_attr_set);
715		return notifier_from_errno(err);
716	}
717
718	return NOTIFY_DONE;
719}
720
721int sparx5_register_notifier_blocks(struct sparx5 *s5)
722{
723	int err;
724
725	s5->netdevice_nb.notifier_call = sparx5_netdevice_event;
726	err = register_netdevice_notifier(&s5->netdevice_nb);
727	if (err)
728		return err;
729
730	s5->switchdev_nb.notifier_call = sparx5_switchdev_event;
731	err = register_switchdev_notifier(&s5->switchdev_nb);
732	if (err)
733		goto err_switchdev_nb;
734
735	s5->switchdev_blocking_nb.notifier_call = sparx5_switchdev_blocking_event;
736	err = register_switchdev_blocking_notifier(&s5->switchdev_blocking_nb);
737	if (err)
738		goto err_switchdev_blocking_nb;
739
740	sparx5_owq = alloc_ordered_workqueue("sparx5_order", 0);
741	if (!sparx5_owq) {
742		err = -ENOMEM;
743		goto err_switchdev_blocking_nb;
744	}
745
746	return 0;
747
748err_switchdev_blocking_nb:
749	unregister_switchdev_notifier(&s5->switchdev_nb);
750err_switchdev_nb:
751	unregister_netdevice_notifier(&s5->netdevice_nb);
752
753	return err;
754}
755
756void sparx5_unregister_notifier_blocks(struct sparx5 *s5)
757{
758	destroy_workqueue(sparx5_owq);
759
760	unregister_switchdev_blocking_notifier(&s5->switchdev_blocking_nb);
761	unregister_switchdev_notifier(&s5->switchdev_nb);
762	unregister_netdevice_notifier(&s5->netdevice_nb);
763}
764