xref: /openbmc/linux/net/dsa/switch.c (revision d0004a020bb50263de0e3e775c7b7c7a003e0e0c)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Handling of a single switch chip, part of a switch fabric
4  *
5  * Copyright (c) 2017 Savoir-faire Linux Inc.
6  *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
7  */
8 
9 #include <linux/if_bridge.h>
10 #include <linux/netdevice.h>
11 #include <linux/notifier.h>
12 #include <linux/if_vlan.h>
13 #include <net/switchdev.h>
14 
15 #include "dsa_priv.h"
16 
17 static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds,
18 						   unsigned int ageing_time)
19 {
20 	struct dsa_port *dp;
21 
22 	dsa_switch_for_each_port(dp, ds)
23 		if (dp->ageing_time && dp->ageing_time < ageing_time)
24 			ageing_time = dp->ageing_time;
25 
26 	return ageing_time;
27 }
28 
29 static int dsa_switch_ageing_time(struct dsa_switch *ds,
30 				  struct dsa_notifier_ageing_time_info *info)
31 {
32 	unsigned int ageing_time = info->ageing_time;
33 
34 	if (ds->ageing_time_min && ageing_time < ds->ageing_time_min)
35 		return -ERANGE;
36 
37 	if (ds->ageing_time_max && ageing_time > ds->ageing_time_max)
38 		return -ERANGE;
39 
40 	/* Program the fastest ageing time in case of multiple bridges */
41 	ageing_time = dsa_switch_fastest_ageing_time(ds, ageing_time);
42 
43 	if (ds->ops->set_ageing_time)
44 		return ds->ops->set_ageing_time(ds, ageing_time);
45 
46 	return 0;
47 }
48 
49 static bool dsa_switch_mtu_match(struct dsa_switch *ds, int port,
50 				 struct dsa_notifier_mtu_info *info)
51 {
52 	if (ds->index == info->sw_index && port == info->port)
53 		return true;
54 
55 	/* Do not propagate to other switches in the tree if the notifier was
56 	 * targeted for a single switch.
57 	 */
58 	if (info->targeted_match)
59 		return false;
60 
61 	if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
62 		return true;
63 
64 	return false;
65 }
66 
67 static int dsa_switch_mtu(struct dsa_switch *ds,
68 			  struct dsa_notifier_mtu_info *info)
69 {
70 	int port, ret;
71 
72 	if (!ds->ops->port_change_mtu)
73 		return -EOPNOTSUPP;
74 
75 	for (port = 0; port < ds->num_ports; port++) {
76 		if (dsa_switch_mtu_match(ds, port, info)) {
77 			ret = ds->ops->port_change_mtu(ds, port, info->mtu);
78 			if (ret)
79 				return ret;
80 		}
81 	}
82 
83 	return 0;
84 }
85 
86 static int dsa_switch_bridge_join(struct dsa_switch *ds,
87 				  struct dsa_notifier_bridge_info *info)
88 {
89 	struct dsa_switch_tree *dst = ds->dst;
90 	int err;
91 
92 	if (dst->index == info->tree_index && ds->index == info->sw_index) {
93 		if (!ds->ops->port_bridge_join)
94 			return -EOPNOTSUPP;
95 
96 		err = ds->ops->port_bridge_join(ds, info->port, info->br);
97 		if (err)
98 			return err;
99 	}
100 
101 	if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
102 	    ds->ops->crosschip_bridge_join) {
103 		err = ds->ops->crosschip_bridge_join(ds, info->tree_index,
104 						     info->sw_index,
105 						     info->port, info->br);
106 		if (err)
107 			return err;
108 	}
109 
110 	return dsa_tag_8021q_bridge_join(ds, info);
111 }
112 
113 static int dsa_switch_bridge_leave(struct dsa_switch *ds,
114 				   struct dsa_notifier_bridge_info *info)
115 {
116 	struct dsa_switch_tree *dst = ds->dst;
117 	struct netlink_ext_ack extack = {0};
118 	bool change_vlan_filtering = false;
119 	bool vlan_filtering;
120 	struct dsa_port *dp;
121 	int err;
122 
123 	if (dst->index == info->tree_index && ds->index == info->sw_index &&
124 	    ds->ops->port_bridge_leave)
125 		ds->ops->port_bridge_leave(ds, info->port, info->br);
126 
127 	if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
128 	    ds->ops->crosschip_bridge_leave)
129 		ds->ops->crosschip_bridge_leave(ds, info->tree_index,
130 						info->sw_index, info->port,
131 						info->br);
132 
133 	if (ds->needs_standalone_vlan_filtering && !br_vlan_enabled(info->br)) {
134 		change_vlan_filtering = true;
135 		vlan_filtering = true;
136 	} else if (!ds->needs_standalone_vlan_filtering &&
137 		   br_vlan_enabled(info->br)) {
138 		change_vlan_filtering = true;
139 		vlan_filtering = false;
140 	}
141 
142 	/* If the bridge was vlan_filtering, the bridge core doesn't trigger an
143 	 * event for changing vlan_filtering setting upon slave ports leaving
144 	 * it. That is a good thing, because that lets us handle it and also
145 	 * handle the case where the switch's vlan_filtering setting is global
146 	 * (not per port). When that happens, the correct moment to trigger the
147 	 * vlan_filtering callback is only when the last port leaves the last
148 	 * VLAN-aware bridge.
149 	 */
150 	if (change_vlan_filtering && ds->vlan_filtering_is_global) {
151 		dsa_switch_for_each_port(dp, ds) {
152 			struct net_device *bridge_dev;
153 
154 			bridge_dev = dp->bridge_dev;
155 
156 			if (bridge_dev && br_vlan_enabled(bridge_dev)) {
157 				change_vlan_filtering = false;
158 				break;
159 			}
160 		}
161 	}
162 
163 	if (change_vlan_filtering) {
164 		err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port),
165 					      vlan_filtering, &extack);
166 		if (extack._msg)
167 			dev_err(ds->dev, "port %d: %s\n", info->port,
168 				extack._msg);
169 		if (err && err != -EOPNOTSUPP)
170 			return err;
171 	}
172 
173 	return dsa_tag_8021q_bridge_leave(ds, info);
174 }
175 
176 /* Matches for all upstream-facing ports (the CPU port and all upstream-facing
177  * DSA links) that sit between the targeted port on which the notifier was
178  * emitted and its dedicated CPU port.
179  */
180 static bool dsa_switch_host_address_match(struct dsa_switch *ds, int port,
181 					  int info_sw_index, int info_port)
182 {
183 	struct dsa_port *targeted_dp, *cpu_dp;
184 	struct dsa_switch *targeted_ds;
185 
186 	targeted_ds = dsa_switch_find(ds->dst->index, info_sw_index);
187 	targeted_dp = dsa_to_port(targeted_ds, info_port);
188 	cpu_dp = targeted_dp->cpu_dp;
189 
190 	if (dsa_switch_is_upstream_of(ds, targeted_ds))
191 		return port == dsa_towards_port(ds, cpu_dp->ds->index,
192 						cpu_dp->index);
193 
194 	return false;
195 }
196 
197 static struct dsa_mac_addr *dsa_mac_addr_find(struct list_head *addr_list,
198 					      const unsigned char *addr,
199 					      u16 vid)
200 {
201 	struct dsa_mac_addr *a;
202 
203 	list_for_each_entry(a, addr_list, list)
204 		if (ether_addr_equal(a->addr, addr) && a->vid == vid)
205 			return a;
206 
207 	return NULL;
208 }
209 
210 static int dsa_switch_do_mdb_add(struct dsa_switch *ds, int port,
211 				 const struct switchdev_obj_port_mdb *mdb)
212 {
213 	struct dsa_port *dp = dsa_to_port(ds, port);
214 	struct dsa_mac_addr *a;
215 	int err;
216 
217 	/* No need to bother with refcounting for user ports */
218 	if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
219 		return ds->ops->port_mdb_add(ds, port, mdb);
220 
221 	a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid);
222 	if (a) {
223 		refcount_inc(&a->refcount);
224 		return 0;
225 	}
226 
227 	a = kzalloc(sizeof(*a), GFP_KERNEL);
228 	if (!a)
229 		return -ENOMEM;
230 
231 	err = ds->ops->port_mdb_add(ds, port, mdb);
232 	if (err) {
233 		kfree(a);
234 		return err;
235 	}
236 
237 	ether_addr_copy(a->addr, mdb->addr);
238 	a->vid = mdb->vid;
239 	refcount_set(&a->refcount, 1);
240 	list_add_tail(&a->list, &dp->mdbs);
241 
242 	return 0;
243 }
244 
245 static int dsa_switch_do_mdb_del(struct dsa_switch *ds, int port,
246 				 const struct switchdev_obj_port_mdb *mdb)
247 {
248 	struct dsa_port *dp = dsa_to_port(ds, port);
249 	struct dsa_mac_addr *a;
250 	int err;
251 
252 	/* No need to bother with refcounting for user ports */
253 	if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
254 		return ds->ops->port_mdb_del(ds, port, mdb);
255 
256 	a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid);
257 	if (!a)
258 		return -ENOENT;
259 
260 	if (!refcount_dec_and_test(&a->refcount))
261 		return 0;
262 
263 	err = ds->ops->port_mdb_del(ds, port, mdb);
264 	if (err) {
265 		refcount_inc(&a->refcount);
266 		return err;
267 	}
268 
269 	list_del(&a->list);
270 	kfree(a);
271 
272 	return 0;
273 }
274 
275 static int dsa_switch_do_fdb_add(struct dsa_switch *ds, int port,
276 				 const unsigned char *addr, u16 vid)
277 {
278 	struct dsa_port *dp = dsa_to_port(ds, port);
279 	struct dsa_mac_addr *a;
280 	int err;
281 
282 	/* No need to bother with refcounting for user ports */
283 	if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
284 		return ds->ops->port_fdb_add(ds, port, addr, vid);
285 
286 	a = dsa_mac_addr_find(&dp->fdbs, addr, vid);
287 	if (a) {
288 		refcount_inc(&a->refcount);
289 		return 0;
290 	}
291 
292 	a = kzalloc(sizeof(*a), GFP_KERNEL);
293 	if (!a)
294 		return -ENOMEM;
295 
296 	err = ds->ops->port_fdb_add(ds, port, addr, vid);
297 	if (err) {
298 		kfree(a);
299 		return err;
300 	}
301 
302 	ether_addr_copy(a->addr, addr);
303 	a->vid = vid;
304 	refcount_set(&a->refcount, 1);
305 	list_add_tail(&a->list, &dp->fdbs);
306 
307 	return 0;
308 }
309 
310 static int dsa_switch_do_fdb_del(struct dsa_switch *ds, int port,
311 				 const unsigned char *addr, u16 vid)
312 {
313 	struct dsa_port *dp = dsa_to_port(ds, port);
314 	struct dsa_mac_addr *a;
315 	int err;
316 
317 	/* No need to bother with refcounting for user ports */
318 	if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp)))
319 		return ds->ops->port_fdb_del(ds, port, addr, vid);
320 
321 	a = dsa_mac_addr_find(&dp->fdbs, addr, vid);
322 	if (!a)
323 		return -ENOENT;
324 
325 	if (!refcount_dec_and_test(&a->refcount))
326 		return 0;
327 
328 	err = ds->ops->port_fdb_del(ds, port, addr, vid);
329 	if (err) {
330 		refcount_inc(&a->refcount);
331 		return err;
332 	}
333 
334 	list_del(&a->list);
335 	kfree(a);
336 
337 	return 0;
338 }
339 
340 static int dsa_switch_host_fdb_add(struct dsa_switch *ds,
341 				   struct dsa_notifier_fdb_info *info)
342 {
343 	int err = 0;
344 	int port;
345 
346 	if (!ds->ops->port_fdb_add)
347 		return -EOPNOTSUPP;
348 
349 	for (port = 0; port < ds->num_ports; port++) {
350 		if (dsa_switch_host_address_match(ds, port, info->sw_index,
351 						  info->port)) {
352 			err = dsa_switch_do_fdb_add(ds, port, info->addr,
353 						    info->vid);
354 			if (err)
355 				break;
356 		}
357 	}
358 
359 	return err;
360 }
361 
362 static int dsa_switch_host_fdb_del(struct dsa_switch *ds,
363 				   struct dsa_notifier_fdb_info *info)
364 {
365 	int err = 0;
366 	int port;
367 
368 	if (!ds->ops->port_fdb_del)
369 		return -EOPNOTSUPP;
370 
371 	for (port = 0; port < ds->num_ports; port++) {
372 		if (dsa_switch_host_address_match(ds, port, info->sw_index,
373 						  info->port)) {
374 			err = dsa_switch_do_fdb_del(ds, port, info->addr,
375 						    info->vid);
376 			if (err)
377 				break;
378 		}
379 	}
380 
381 	return err;
382 }
383 
384 static int dsa_switch_fdb_add(struct dsa_switch *ds,
385 			      struct dsa_notifier_fdb_info *info)
386 {
387 	int port = dsa_towards_port(ds, info->sw_index, info->port);
388 
389 	if (!ds->ops->port_fdb_add)
390 		return -EOPNOTSUPP;
391 
392 	return dsa_switch_do_fdb_add(ds, port, info->addr, info->vid);
393 }
394 
395 static int dsa_switch_fdb_del(struct dsa_switch *ds,
396 			      struct dsa_notifier_fdb_info *info)
397 {
398 	int port = dsa_towards_port(ds, info->sw_index, info->port);
399 
400 	if (!ds->ops->port_fdb_del)
401 		return -EOPNOTSUPP;
402 
403 	return dsa_switch_do_fdb_del(ds, port, info->addr, info->vid);
404 }
405 
406 static int dsa_switch_hsr_join(struct dsa_switch *ds,
407 			       struct dsa_notifier_hsr_info *info)
408 {
409 	if (ds->index == info->sw_index && ds->ops->port_hsr_join)
410 		return ds->ops->port_hsr_join(ds, info->port, info->hsr);
411 
412 	return -EOPNOTSUPP;
413 }
414 
415 static int dsa_switch_hsr_leave(struct dsa_switch *ds,
416 				struct dsa_notifier_hsr_info *info)
417 {
418 	if (ds->index == info->sw_index && ds->ops->port_hsr_leave)
419 		return ds->ops->port_hsr_leave(ds, info->port, info->hsr);
420 
421 	return -EOPNOTSUPP;
422 }
423 
424 static int dsa_switch_lag_change(struct dsa_switch *ds,
425 				 struct dsa_notifier_lag_info *info)
426 {
427 	if (ds->index == info->sw_index && ds->ops->port_lag_change)
428 		return ds->ops->port_lag_change(ds, info->port);
429 
430 	if (ds->index != info->sw_index && ds->ops->crosschip_lag_change)
431 		return ds->ops->crosschip_lag_change(ds, info->sw_index,
432 						     info->port);
433 
434 	return 0;
435 }
436 
437 static int dsa_switch_lag_join(struct dsa_switch *ds,
438 			       struct dsa_notifier_lag_info *info)
439 {
440 	if (ds->index == info->sw_index && ds->ops->port_lag_join)
441 		return ds->ops->port_lag_join(ds, info->port, info->lag,
442 					      info->info);
443 
444 	if (ds->index != info->sw_index && ds->ops->crosschip_lag_join)
445 		return ds->ops->crosschip_lag_join(ds, info->sw_index,
446 						   info->port, info->lag,
447 						   info->info);
448 
449 	return -EOPNOTSUPP;
450 }
451 
452 static int dsa_switch_lag_leave(struct dsa_switch *ds,
453 				struct dsa_notifier_lag_info *info)
454 {
455 	if (ds->index == info->sw_index && ds->ops->port_lag_leave)
456 		return ds->ops->port_lag_leave(ds, info->port, info->lag);
457 
458 	if (ds->index != info->sw_index && ds->ops->crosschip_lag_leave)
459 		return ds->ops->crosschip_lag_leave(ds, info->sw_index,
460 						    info->port, info->lag);
461 
462 	return -EOPNOTSUPP;
463 }
464 
465 static int dsa_switch_mdb_add(struct dsa_switch *ds,
466 			      struct dsa_notifier_mdb_info *info)
467 {
468 	int port = dsa_towards_port(ds, info->sw_index, info->port);
469 
470 	if (!ds->ops->port_mdb_add)
471 		return -EOPNOTSUPP;
472 
473 	return dsa_switch_do_mdb_add(ds, port, info->mdb);
474 }
475 
476 static int dsa_switch_mdb_del(struct dsa_switch *ds,
477 			      struct dsa_notifier_mdb_info *info)
478 {
479 	int port = dsa_towards_port(ds, info->sw_index, info->port);
480 
481 	if (!ds->ops->port_mdb_del)
482 		return -EOPNOTSUPP;
483 
484 	return dsa_switch_do_mdb_del(ds, port, info->mdb);
485 }
486 
487 static int dsa_switch_host_mdb_add(struct dsa_switch *ds,
488 				   struct dsa_notifier_mdb_info *info)
489 {
490 	int err = 0;
491 	int port;
492 
493 	if (!ds->ops->port_mdb_add)
494 		return -EOPNOTSUPP;
495 
496 	for (port = 0; port < ds->num_ports; port++) {
497 		if (dsa_switch_host_address_match(ds, port, info->sw_index,
498 						  info->port)) {
499 			err = dsa_switch_do_mdb_add(ds, port, info->mdb);
500 			if (err)
501 				break;
502 		}
503 	}
504 
505 	return err;
506 }
507 
508 static int dsa_switch_host_mdb_del(struct dsa_switch *ds,
509 				   struct dsa_notifier_mdb_info *info)
510 {
511 	int err = 0;
512 	int port;
513 
514 	if (!ds->ops->port_mdb_del)
515 		return -EOPNOTSUPP;
516 
517 	for (port = 0; port < ds->num_ports; port++) {
518 		if (dsa_switch_host_address_match(ds, port, info->sw_index,
519 						  info->port)) {
520 			err = dsa_switch_do_mdb_del(ds, port, info->mdb);
521 			if (err)
522 				break;
523 		}
524 	}
525 
526 	return err;
527 }
528 
529 static bool dsa_switch_vlan_match(struct dsa_switch *ds, int port,
530 				  struct dsa_notifier_vlan_info *info)
531 {
532 	if (ds->index == info->sw_index && port == info->port)
533 		return true;
534 
535 	if (dsa_is_dsa_port(ds, port))
536 		return true;
537 
538 	return false;
539 }
540 
541 static int dsa_switch_vlan_add(struct dsa_switch *ds,
542 			       struct dsa_notifier_vlan_info *info)
543 {
544 	int port, err;
545 
546 	if (!ds->ops->port_vlan_add)
547 		return -EOPNOTSUPP;
548 
549 	for (port = 0; port < ds->num_ports; port++) {
550 		if (dsa_switch_vlan_match(ds, port, info)) {
551 			err = ds->ops->port_vlan_add(ds, port, info->vlan,
552 						     info->extack);
553 			if (err)
554 				return err;
555 		}
556 	}
557 
558 	return 0;
559 }
560 
561 static int dsa_switch_vlan_del(struct dsa_switch *ds,
562 			       struct dsa_notifier_vlan_info *info)
563 {
564 	if (!ds->ops->port_vlan_del)
565 		return -EOPNOTSUPP;
566 
567 	if (ds->index == info->sw_index)
568 		return ds->ops->port_vlan_del(ds, info->port, info->vlan);
569 
570 	/* Do not deprogram the DSA links as they may be used as conduit
571 	 * for other VLAN members in the fabric.
572 	 */
573 	return 0;
574 }
575 
576 static int dsa_switch_change_tag_proto(struct dsa_switch *ds,
577 				       struct dsa_notifier_tag_proto_info *info)
578 {
579 	const struct dsa_device_ops *tag_ops = info->tag_ops;
580 	struct dsa_port *dp, *cpu_dp;
581 	int err;
582 
583 	if (!ds->ops->change_tag_protocol)
584 		return -EOPNOTSUPP;
585 
586 	ASSERT_RTNL();
587 
588 	dsa_switch_for_each_cpu_port(cpu_dp, ds) {
589 		err = ds->ops->change_tag_protocol(ds, cpu_dp->index,
590 						   tag_ops->proto);
591 		if (err)
592 			return err;
593 
594 		dsa_port_set_tag_protocol(cpu_dp, tag_ops);
595 	}
596 
597 	/* Now that changing the tag protocol can no longer fail, let's update
598 	 * the remaining bits which are "duplicated for faster access", and the
599 	 * bits that depend on the tagger, such as the MTU.
600 	 */
601 	dsa_switch_for_each_user_port(dp, ds) {
602 		struct net_device *slave = dp->slave;
603 
604 		dsa_slave_setup_tagger(slave);
605 
606 		/* rtnl_mutex is held in dsa_tree_change_tag_proto */
607 		dsa_slave_change_mtu(slave, slave->mtu);
608 	}
609 
610 	return 0;
611 }
612 
613 static int dsa_switch_mrp_add(struct dsa_switch *ds,
614 			      struct dsa_notifier_mrp_info *info)
615 {
616 	if (!ds->ops->port_mrp_add)
617 		return -EOPNOTSUPP;
618 
619 	if (ds->index == info->sw_index)
620 		return ds->ops->port_mrp_add(ds, info->port, info->mrp);
621 
622 	return 0;
623 }
624 
625 static int dsa_switch_mrp_del(struct dsa_switch *ds,
626 			      struct dsa_notifier_mrp_info *info)
627 {
628 	if (!ds->ops->port_mrp_del)
629 		return -EOPNOTSUPP;
630 
631 	if (ds->index == info->sw_index)
632 		return ds->ops->port_mrp_del(ds, info->port, info->mrp);
633 
634 	return 0;
635 }
636 
637 static int
638 dsa_switch_mrp_add_ring_role(struct dsa_switch *ds,
639 			     struct dsa_notifier_mrp_ring_role_info *info)
640 {
641 	if (!ds->ops->port_mrp_add)
642 		return -EOPNOTSUPP;
643 
644 	if (ds->index == info->sw_index)
645 		return ds->ops->port_mrp_add_ring_role(ds, info->port,
646 						       info->mrp);
647 
648 	return 0;
649 }
650 
651 static int
652 dsa_switch_mrp_del_ring_role(struct dsa_switch *ds,
653 			     struct dsa_notifier_mrp_ring_role_info *info)
654 {
655 	if (!ds->ops->port_mrp_del)
656 		return -EOPNOTSUPP;
657 
658 	if (ds->index == info->sw_index)
659 		return ds->ops->port_mrp_del_ring_role(ds, info->port,
660 						       info->mrp);
661 
662 	return 0;
663 }
664 
665 static int dsa_switch_event(struct notifier_block *nb,
666 			    unsigned long event, void *info)
667 {
668 	struct dsa_switch *ds = container_of(nb, struct dsa_switch, nb);
669 	int err;
670 
671 	switch (event) {
672 	case DSA_NOTIFIER_AGEING_TIME:
673 		err = dsa_switch_ageing_time(ds, info);
674 		break;
675 	case DSA_NOTIFIER_BRIDGE_JOIN:
676 		err = dsa_switch_bridge_join(ds, info);
677 		break;
678 	case DSA_NOTIFIER_BRIDGE_LEAVE:
679 		err = dsa_switch_bridge_leave(ds, info);
680 		break;
681 	case DSA_NOTIFIER_FDB_ADD:
682 		err = dsa_switch_fdb_add(ds, info);
683 		break;
684 	case DSA_NOTIFIER_FDB_DEL:
685 		err = dsa_switch_fdb_del(ds, info);
686 		break;
687 	case DSA_NOTIFIER_HOST_FDB_ADD:
688 		err = dsa_switch_host_fdb_add(ds, info);
689 		break;
690 	case DSA_NOTIFIER_HOST_FDB_DEL:
691 		err = dsa_switch_host_fdb_del(ds, info);
692 		break;
693 	case DSA_NOTIFIER_HSR_JOIN:
694 		err = dsa_switch_hsr_join(ds, info);
695 		break;
696 	case DSA_NOTIFIER_HSR_LEAVE:
697 		err = dsa_switch_hsr_leave(ds, info);
698 		break;
699 	case DSA_NOTIFIER_LAG_CHANGE:
700 		err = dsa_switch_lag_change(ds, info);
701 		break;
702 	case DSA_NOTIFIER_LAG_JOIN:
703 		err = dsa_switch_lag_join(ds, info);
704 		break;
705 	case DSA_NOTIFIER_LAG_LEAVE:
706 		err = dsa_switch_lag_leave(ds, info);
707 		break;
708 	case DSA_NOTIFIER_MDB_ADD:
709 		err = dsa_switch_mdb_add(ds, info);
710 		break;
711 	case DSA_NOTIFIER_MDB_DEL:
712 		err = dsa_switch_mdb_del(ds, info);
713 		break;
714 	case DSA_NOTIFIER_HOST_MDB_ADD:
715 		err = dsa_switch_host_mdb_add(ds, info);
716 		break;
717 	case DSA_NOTIFIER_HOST_MDB_DEL:
718 		err = dsa_switch_host_mdb_del(ds, info);
719 		break;
720 	case DSA_NOTIFIER_VLAN_ADD:
721 		err = dsa_switch_vlan_add(ds, info);
722 		break;
723 	case DSA_NOTIFIER_VLAN_DEL:
724 		err = dsa_switch_vlan_del(ds, info);
725 		break;
726 	case DSA_NOTIFIER_MTU:
727 		err = dsa_switch_mtu(ds, info);
728 		break;
729 	case DSA_NOTIFIER_TAG_PROTO:
730 		err = dsa_switch_change_tag_proto(ds, info);
731 		break;
732 	case DSA_NOTIFIER_MRP_ADD:
733 		err = dsa_switch_mrp_add(ds, info);
734 		break;
735 	case DSA_NOTIFIER_MRP_DEL:
736 		err = dsa_switch_mrp_del(ds, info);
737 		break;
738 	case DSA_NOTIFIER_MRP_ADD_RING_ROLE:
739 		err = dsa_switch_mrp_add_ring_role(ds, info);
740 		break;
741 	case DSA_NOTIFIER_MRP_DEL_RING_ROLE:
742 		err = dsa_switch_mrp_del_ring_role(ds, info);
743 		break;
744 	case DSA_NOTIFIER_TAG_8021Q_VLAN_ADD:
745 		err = dsa_switch_tag_8021q_vlan_add(ds, info);
746 		break;
747 	case DSA_NOTIFIER_TAG_8021Q_VLAN_DEL:
748 		err = dsa_switch_tag_8021q_vlan_del(ds, info);
749 		break;
750 	default:
751 		err = -EOPNOTSUPP;
752 		break;
753 	}
754 
755 	if (err)
756 		dev_dbg(ds->dev, "breaking chain for DSA event %lu (%d)\n",
757 			event, err);
758 
759 	return notifier_from_errno(err);
760 }
761 
762 int dsa_switch_register_notifier(struct dsa_switch *ds)
763 {
764 	ds->nb.notifier_call = dsa_switch_event;
765 
766 	return raw_notifier_chain_register(&ds->dst->nh, &ds->nb);
767 }
768 
769 void dsa_switch_unregister_notifier(struct dsa_switch *ds)
770 {
771 	int err;
772 
773 	err = raw_notifier_chain_unregister(&ds->dst->nh, &ds->nb);
774 	if (err)
775 		dev_err(ds->dev, "failed to unregister notifier (%d)\n", err);
776 }
777