Merge branch 'akpm' (patches from Andrew)
[linux-2.6-block.git] / net / dsa / switch.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
f515f192
VD
2/*
3 * Handling of a single switch chip, part of a switch fabric
4 *
4333d619
VD
5 * Copyright (c) 2017 Savoir-faire Linux Inc.
6 * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
f515f192
VD
7 */
8
d371b7c9 9#include <linux/if_bridge.h>
f515f192
VD
10#include <linux/netdevice.h>
11#include <linux/notifier.h>
061f6a50 12#include <linux/if_vlan.h>
1faabf74 13#include <net/switchdev.h>
ea5dd34b
VD
14
15#include "dsa_priv.h"
f515f192 16
1faabf74
VD
17static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds,
18 unsigned int ageing_time)
19{
d0004a02 20 struct dsa_port *dp;
1faabf74 21
d0004a02 22 dsa_switch_for_each_port(dp, ds)
1faabf74
VD
23 if (dp->ageing_time && dp->ageing_time < ageing_time)
24 ageing_time = dp->ageing_time;
1faabf74
VD
25
26 return ageing_time;
27}
28
29static 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;
77b61365
VO
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;
1faabf74
VD
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
fac6abd5
VO
49static bool dsa_port_mtu_match(struct dsa_port *dp,
50 struct dsa_notifier_mtu_info *info)
bfcb8132 51{
fac6abd5 52 if (dp->ds->index == info->sw_index && dp->index == info->port)
88faba20 53 return true;
bfcb8132 54
88faba20
VO
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)
bfcb8132
VO
59 return false;
60
fac6abd5 61 if (dsa_port_is_dsa(dp) || dsa_port_is_cpu(dp))
bfcb8132
VO
62 return true;
63
64 return false;
65}
66
67static int dsa_switch_mtu(struct dsa_switch *ds,
68 struct dsa_notifier_mtu_info *info)
69{
fac6abd5
VO
70 struct dsa_port *dp;
71 int ret;
bfcb8132
VO
72
73 if (!ds->ops->port_change_mtu)
74 return -EOPNOTSUPP;
75
fac6abd5
VO
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);
bfcb8132
VO
80 if (ret)
81 return ret;
82 }
83 }
84
85 return 0;
86}
87
04d3a4c6
VD
88static int dsa_switch_bridge_join(struct dsa_switch *ds,
89 struct dsa_notifier_bridge_info *info)
90{
f66a6a69 91 struct dsa_switch_tree *dst = ds->dst;
e19cc13c 92 int err;
f66a6a69 93
67b5fb5d
VO
94 if (dst->index == info->tree_index && ds->index == info->sw_index) {
95 if (!ds->ops->port_bridge_join)
96 return -EOPNOTSUPP;
97
e19cc13c
VO
98 err = ds->ops->port_bridge_join(ds, info->port, info->br);
99 if (err)
100 return err;
101 }
04d3a4c6 102
f66a6a69 103 if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
e19cc13c
VO
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 }
04d3a4c6 111
e19cc13c 112 return dsa_tag_8021q_bridge_join(ds, info);
04d3a4c6
VD
113}
114
115static int dsa_switch_bridge_leave(struct dsa_switch *ds,
116 struct dsa_notifier_bridge_info *info)
117{
f66a6a69 118 struct dsa_switch_tree *dst = ds->dst;
89153ed6 119 struct netlink_ext_ack extack = {0};
58adf9dc
VO
120 bool change_vlan_filtering = false;
121 bool vlan_filtering;
d0004a02
VO
122 struct dsa_port *dp;
123 int err;
d371b7c9 124
f66a6a69 125 if (dst->index == info->tree_index && ds->index == info->sw_index &&
bcb9928a 126 ds->ops->port_bridge_leave)
04d3a4c6
VD
127 ds->ops->port_bridge_leave(ds, info->port, info->br);
128
f66a6a69 129 if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
bcb9928a 130 ds->ops->crosschip_bridge_leave)
f66a6a69
VO
131 ds->ops->crosschip_bridge_leave(ds, info->tree_index,
132 info->sw_index, info->port,
40ef2c93 133 info->br);
04d3a4c6 134
58adf9dc
VO
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
d371b7c9
VO
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
479dc497
VO
149 * vlan_filtering callback is only when the last port leaves the last
150 * VLAN-aware bridge.
d371b7c9 151 */
58adf9dc 152 if (change_vlan_filtering && ds->vlan_filtering_is_global) {
d0004a02 153 dsa_switch_for_each_port(dp, ds) {
479dc497
VO
154 struct net_device *bridge_dev;
155
d0004a02 156 bridge_dev = dp->bridge_dev;
479dc497
VO
157
158 if (bridge_dev && br_vlan_enabled(bridge_dev)) {
58adf9dc 159 change_vlan_filtering = false;
d371b7c9
VO
160 break;
161 }
162 }
163 }
58adf9dc
VO
164
165 if (change_vlan_filtering) {
68bb8ea8 166 err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port),
58adf9dc 167 vlan_filtering, &extack);
89153ed6
VO
168 if (extack._msg)
169 dev_err(ds->dev, "port %d: %s\n", info->port,
170 extack._msg);
43a4b4db 171 if (err && err != -EOPNOTSUPP)
d371b7c9
VO
172 return err;
173 }
e19cc13c
VO
174
175 return dsa_tag_8021q_bridge_leave(ds, info);
04d3a4c6
VD
176}
177
b8e997c4
VO
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 */
fac6abd5
VO
182static bool dsa_port_host_address_match(struct dsa_port *dp,
183 int info_sw_index, int info_port)
b8e997c4
VO
184{
185 struct dsa_port *targeted_dp, *cpu_dp;
186 struct dsa_switch *targeted_ds;
187
fac6abd5 188 targeted_ds = dsa_switch_find(dp->ds->dst->index, info_sw_index);
b8e997c4
VO
189 targeted_dp = dsa_to_port(targeted_ds, info_port);
190 cpu_dp = targeted_dp->cpu_dp;
191
fac6abd5
VO
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);
b8e997c4
VO
195
196 return false;
197}
198
161ca59d
VO
199static 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
fac6abd5
VO
212static int dsa_port_do_mdb_add(struct dsa_port *dp,
213 const struct switchdev_obj_port_mdb *mdb)
161ca59d 214{
fac6abd5 215 struct dsa_switch *ds = dp->ds;
161ca59d 216 struct dsa_mac_addr *a;
fac6abd5 217 int port = dp->index;
338a3a47 218 int err = 0;
161ca59d
VO
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
338a3a47
VO
224 mutex_lock(&dp->addr_lists_lock);
225
161ca59d
VO
226 a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid);
227 if (a) {
228 refcount_inc(&a->refcount);
338a3a47 229 goto out;
161ca59d
VO
230 }
231
232 a = kzalloc(sizeof(*a), GFP_KERNEL);
338a3a47
VO
233 if (!a) {
234 err = -ENOMEM;
235 goto out;
236 }
161ca59d
VO
237
238 err = ds->ops->port_mdb_add(ds, port, mdb);
239 if (err) {
240 kfree(a);
338a3a47 241 goto out;
161ca59d
VO
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
338a3a47
VO
249out:
250 mutex_unlock(&dp->addr_lists_lock);
251
252 return err;
161ca59d
VO
253}
254
fac6abd5
VO
255static int dsa_port_do_mdb_del(struct dsa_port *dp,
256 const struct switchdev_obj_port_mdb *mdb)
161ca59d 257{
fac6abd5 258 struct dsa_switch *ds = dp->ds;
161ca59d 259 struct dsa_mac_addr *a;
fac6abd5 260 int port = dp->index;
338a3a47 261 int err = 0;
161ca59d
VO
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
338a3a47
VO
267 mutex_lock(&dp->addr_lists_lock);
268
161ca59d 269 a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid);
338a3a47
VO
270 if (!a) {
271 err = -ENOENT;
272 goto out;
273 }
161ca59d
VO
274
275 if (!refcount_dec_and_test(&a->refcount))
338a3a47 276 goto out;
161ca59d
VO
277
278 err = ds->ops->port_mdb_del(ds, port, mdb);
279 if (err) {
232deb3f 280 refcount_set(&a->refcount, 1);
338a3a47 281 goto out;
161ca59d
VO
282 }
283
284 list_del(&a->list);
285 kfree(a);
286
338a3a47
VO
287out:
288 mutex_unlock(&dp->addr_lists_lock);
289
290 return err;
161ca59d
VO
291}
292
fac6abd5
VO
293static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr,
294 u16 vid)
3f6e32f9 295{
fac6abd5 296 struct dsa_switch *ds = dp->ds;
3f6e32f9 297 struct dsa_mac_addr *a;
fac6abd5 298 int port = dp->index;
338a3a47 299 int err = 0;
3f6e32f9
VO
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
338a3a47
VO
305 mutex_lock(&dp->addr_lists_lock);
306
3f6e32f9
VO
307 a = dsa_mac_addr_find(&dp->fdbs, addr, vid);
308 if (a) {
309 refcount_inc(&a->refcount);
338a3a47 310 goto out;
3f6e32f9
VO
311 }
312
313 a = kzalloc(sizeof(*a), GFP_KERNEL);
338a3a47
VO
314 if (!a) {
315 err = -ENOMEM;
316 goto out;
317 }
3f6e32f9
VO
318
319 err = ds->ops->port_fdb_add(ds, port, addr, vid);
320 if (err) {
321 kfree(a);
338a3a47 322 goto out;
3f6e32f9
VO
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
338a3a47
VO
330out:
331 mutex_unlock(&dp->addr_lists_lock);
332
333 return err;
3f6e32f9
VO
334}
335
fac6abd5
VO
336static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr,
337 u16 vid)
3f6e32f9 338{
fac6abd5 339 struct dsa_switch *ds = dp->ds;
3f6e32f9 340 struct dsa_mac_addr *a;
fac6abd5 341 int port = dp->index;
338a3a47 342 int err = 0;
3f6e32f9
VO
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
338a3a47
VO
348 mutex_lock(&dp->addr_lists_lock);
349
3f6e32f9 350 a = dsa_mac_addr_find(&dp->fdbs, addr, vid);
338a3a47
VO
351 if (!a) {
352 err = -ENOENT;
353 goto out;
354 }
3f6e32f9
VO
355
356 if (!refcount_dec_and_test(&a->refcount))
338a3a47 357 goto out;
3f6e32f9
VO
358
359 err = ds->ops->port_fdb_del(ds, port, addr, vid);
360 if (err) {
232deb3f 361 refcount_set(&a->refcount, 1);
338a3a47 362 goto out;
3f6e32f9
VO
363 }
364
365 list_del(&a->list);
366 kfree(a);
367
338a3a47
VO
368out:
369 mutex_unlock(&dp->addr_lists_lock);
370
371 return err;
3f6e32f9
VO
372}
373
3dc80afc
VO
374static int dsa_switch_host_fdb_add(struct dsa_switch *ds,
375 struct dsa_notifier_fdb_info *info)
376{
fac6abd5 377 struct dsa_port *dp;
3dc80afc 378 int err = 0;
3dc80afc
VO
379
380 if (!ds->ops->port_fdb_add)
381 return -EOPNOTSUPP;
382
fac6abd5
VO
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);
3dc80afc
VO
387 if (err)
388 break;
389 }
390 }
391
392 return err;
393}
394
395static int dsa_switch_host_fdb_del(struct dsa_switch *ds,
396 struct dsa_notifier_fdb_info *info)
397{
fac6abd5 398 struct dsa_port *dp;
3f6e32f9 399 int err = 0;
3f6e32f9 400
3dc80afc
VO
401 if (!ds->ops->port_fdb_del)
402 return -EOPNOTSUPP;
403
fac6abd5
VO
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);
3f6e32f9
VO
408 if (err)
409 break;
410 }
411 }
3dc80afc 412
3f6e32f9 413 return err;
3dc80afc
VO
414}
415
685fb6a4
VD
416static int dsa_switch_fdb_add(struct dsa_switch *ds,
417 struct dsa_notifier_fdb_info *info)
418{
3169241f 419 int port = dsa_towards_port(ds, info->sw_index, info->port);
fac6abd5 420 struct dsa_port *dp = dsa_to_port(ds, port);
685fb6a4 421
1b6dd556
AS
422 if (!ds->ops->port_fdb_add)
423 return -EOPNOTSUPP;
685fb6a4 424
fac6abd5 425 return dsa_port_do_fdb_add(dp, info->addr, info->vid);
685fb6a4
VD
426}
427
428static int dsa_switch_fdb_del(struct dsa_switch *ds,
429 struct dsa_notifier_fdb_info *info)
430{
3169241f 431 int port = dsa_towards_port(ds, info->sw_index, info->port);
fac6abd5 432 struct dsa_port *dp = dsa_to_port(ds, port);
685fb6a4
VD
433
434 if (!ds->ops->port_fdb_del)
435 return -EOPNOTSUPP;
436
fac6abd5 437 return dsa_port_do_fdb_del(dp, info->addr, info->vid);
685fb6a4
VD
438}
439
18596f50
GM
440static 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
449static 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
058102a6
TW
458static 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
471static 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
b71d0987 483 return -EOPNOTSUPP;
058102a6
TW
484}
485
486static 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
b71d0987 496 return -EOPNOTSUPP;
058102a6
TW
497}
498
ffb68fc5
VO
499static int dsa_switch_mdb_add(struct dsa_switch *ds,
500 struct dsa_notifier_mdb_info *info)
e6db98db 501{
abd49535 502 int port = dsa_towards_port(ds, info->sw_index, info->port);
fac6abd5 503 struct dsa_port *dp = dsa_to_port(ds, port);
e6db98db 504
a52b2da7 505 if (!ds->ops->port_mdb_add)
e6db98db
VD
506 return -EOPNOTSUPP;
507
fac6abd5 508 return dsa_port_do_mdb_add(dp, info->mdb);
8ae5bcdc
VD
509}
510
511static int dsa_switch_mdb_del(struct dsa_switch *ds,
512 struct dsa_notifier_mdb_info *info)
513{
161ca59d 514 int port = dsa_towards_port(ds, info->sw_index, info->port);
fac6abd5 515 struct dsa_port *dp = dsa_to_port(ds, port);
161ca59d 516
8ae5bcdc
VD
517 if (!ds->ops->port_mdb_del)
518 return -EOPNOTSUPP;
519
fac6abd5 520 return dsa_port_do_mdb_del(dp, info->mdb);
8ae5bcdc
VD
521}
522
b8e997c4
VO
523static int dsa_switch_host_mdb_add(struct dsa_switch *ds,
524 struct dsa_notifier_mdb_info *info)
525{
fac6abd5 526 struct dsa_port *dp;
b8e997c4 527 int err = 0;
b8e997c4
VO
528
529 if (!ds->ops->port_mdb_add)
530 return -EOPNOTSUPP;
531
fac6abd5
VO
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);
b8e997c4
VO
536 if (err)
537 break;
538 }
539 }
540
541 return err;
542}
543
544static int dsa_switch_host_mdb_del(struct dsa_switch *ds,
545 struct dsa_notifier_mdb_info *info)
546{
fac6abd5 547 struct dsa_port *dp;
161ca59d 548 int err = 0;
161ca59d 549
b8e997c4
VO
550 if (!ds->ops->port_mdb_del)
551 return -EOPNOTSUPP;
552
fac6abd5
VO
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);
161ca59d
VO
557 if (err)
558 break;
559 }
560 }
b8e997c4 561
161ca59d 562 return err;
b8e997c4
VO
563}
564
fac6abd5
VO
565static bool dsa_port_vlan_match(struct dsa_port *dp,
566 struct dsa_notifier_vlan_info *info)
e65d45cc 567{
fac6abd5 568 if (dp->ds->index == info->sw_index && dp->index == info->port)
e65d45cc
VD
569 return true;
570
fac6abd5 571 if (dsa_port_is_dsa(dp))
e65d45cc
VD
572 return true;
573
574 return false;
575}
576
ffb68fc5
VO
577static int dsa_switch_vlan_add(struct dsa_switch *ds,
578 struct dsa_notifier_vlan_info *info)
9c428c59 579{
fac6abd5
VO
580 struct dsa_port *dp;
581 int err;
9c428c59 582
1958d581 583 if (!ds->ops->port_vlan_add)
9c428c59
VD
584 return -EOPNOTSUPP;
585
fac6abd5
VO
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,
31046a5f 589 info->extack);
e65d45cc
VD
590 if (err)
591 return err;
592 }
9c428c59
VD
593 }
594
d0c627b8
VD
595 return 0;
596}
597
598static int dsa_switch_vlan_del(struct dsa_switch *ds,
599 struct dsa_notifier_vlan_info *info)
600{
d0c627b8
VD
601 if (!ds->ops->port_vlan_del)
602 return -EOPNOTSUPP;
603
1ca4aa9c 604 if (ds->index == info->sw_index)
e65d45cc 605 return ds->ops->port_vlan_del(ds, info->port, info->vlan);
1ca4aa9c 606
7e1741b4
VD
607 /* Do not deprogram the DSA links as they may be used as conduit
608 * for other VLAN members in the fabric.
609 */
1ca4aa9c 610 return 0;
d0c627b8
VD
611}
612
53da0eba
VO
613static 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;
d0004a02
VO
617 struct dsa_port *dp, *cpu_dp;
618 int err;
53da0eba
VO
619
620 if (!ds->ops->change_tag_protocol)
621 return -EOPNOTSUPP;
622
623 ASSERT_RTNL();
624
d0004a02
VO
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);
21e0b508
TW
628 if (err)
629 return err;
630
d0004a02 631 dsa_port_set_tag_protocol(cpu_dp, tag_ops);
53da0eba
VO
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 */
d0004a02
VO
638 dsa_switch_for_each_user_port(dp, ds) {
639 struct net_device *slave = dp->slave;
53da0eba 640
d0004a02 641 dsa_slave_setup_tagger(slave);
53da0eba 642
d0004a02
VO
643 /* rtnl_mutex is held in dsa_tree_change_tag_proto */
644 dsa_slave_change_mtu(slave, slave->mtu);
53da0eba
VO
645 }
646
647 return 0;
648}
649
c595c433
HV
650static int dsa_switch_mrp_add(struct dsa_switch *ds,
651 struct dsa_notifier_mrp_info *info)
652{
c595c433
HV
653 if (!ds->ops->port_mrp_add)
654 return -EOPNOTSUPP;
655
f9bcdc36
VO
656 if (ds->index == info->sw_index)
657 return ds->ops->port_mrp_add(ds, info->port, info->mrp);
c595c433 658
f9bcdc36 659 return 0;
c595c433
HV
660}
661
662static 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
c595c433
HV
674static int
675dsa_switch_mrp_add_ring_role(struct dsa_switch *ds,
676 struct dsa_notifier_mrp_ring_role_info *info)
677{
c595c433
HV
678 if (!ds->ops->port_mrp_add)
679 return -EOPNOTSUPP;
680
f9bcdc36
VO
681 if (ds->index == info->sw_index)
682 return ds->ops->port_mrp_add_ring_role(ds, info->port,
683 info->mrp);
c595c433 684
f9bcdc36 685 return 0;
c595c433
HV
686}
687
688static int
689dsa_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
f515f192
VD
702static 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) {
1faabf74
VD
709 case DSA_NOTIFIER_AGEING_TIME:
710 err = dsa_switch_ageing_time(ds, info);
711 break;
04d3a4c6
VD
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;
685fb6a4
VD
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;
3dc80afc
VO
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;
18596f50
GM
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;
058102a6
TW
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;
8ae5bcdc
VD
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;
b8e997c4
VO
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;
d0c627b8
VD
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;
bfcb8132
VO
763 case DSA_NOTIFIER_MTU:
764 err = dsa_switch_mtu(ds, info);
765 break;
53da0eba
VO
766 case DSA_NOTIFIER_TAG_PROTO:
767 err = dsa_switch_change_tag_proto(ds, info);
768 break;
c595c433
HV
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;
c64b9c05
VO
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;
f515f192
VD
787 default:
788 err = -EOPNOTSUPP;
789 break;
790 }
791
f515f192
VD
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
799int 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
806void 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}