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