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