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