1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Microchip Sparx5 Switch driver 3 * 4 * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries. 5 */ 6 7 #include <linux/if_bridge.h> 8 #include <net/switchdev.h> 9 10 #include "sparx5_main_regs.h" 11 #include "sparx5_main.h" 12 13 static struct workqueue_struct *sparx5_owq; 14 15 struct sparx5_switchdev_event_work { 16 struct work_struct work; 17 struct switchdev_notifier_fdb_info fdb_info; 18 struct net_device *dev; 19 struct sparx5 *sparx5; 20 unsigned long event; 21 }; 22 23 static int sparx5_port_attr_pre_bridge_flags(struct sparx5_port *port, 24 struct switchdev_brport_flags flags) 25 { 26 if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD)) 27 return -EINVAL; 28 29 return 0; 30 } 31 32 static void sparx5_port_update_mcast_ip_flood(struct sparx5_port *port, bool flood_flag) 33 { 34 bool should_flood = flood_flag || port->is_mrouter; 35 int pgid; 36 37 for (pgid = PGID_IPV4_MC_DATA; pgid <= PGID_IPV6_MC_CTRL; pgid++) 38 sparx5_pgid_update_mask(port, pgid, should_flood); 39 } 40 41 static void sparx5_port_attr_bridge_flags(struct sparx5_port *port, 42 struct switchdev_brport_flags flags) 43 { 44 if (flags.mask & BR_MCAST_FLOOD) { 45 sparx5_pgid_update_mask(port, PGID_MC_FLOOD, !!(flags.val & BR_MCAST_FLOOD)); 46 sparx5_port_update_mcast_ip_flood(port, !!(flags.val & BR_MCAST_FLOOD)); 47 } 48 49 if (flags.mask & BR_FLOOD) 50 sparx5_pgid_update_mask(port, PGID_UC_FLOOD, !!(flags.val & BR_FLOOD)); 51 if (flags.mask & BR_BCAST_FLOOD) 52 sparx5_pgid_update_mask(port, PGID_BCAST, !!(flags.val & BR_BCAST_FLOOD)); 53 } 54 55 static void sparx5_attr_stp_state_set(struct sparx5_port *port, 56 u8 state) 57 { 58 struct sparx5 *sparx5 = port->sparx5; 59 60 if (!test_bit(port->portno, sparx5->bridge_mask)) { 61 netdev_err(port->ndev, 62 "Controlling non-bridged port %d?\n", port->portno); 63 return; 64 } 65 66 switch (state) { 67 case BR_STATE_FORWARDING: 68 set_bit(port->portno, sparx5->bridge_fwd_mask); 69 fallthrough; 70 case BR_STATE_LEARNING: 71 set_bit(port->portno, sparx5->bridge_lrn_mask); 72 break; 73 74 default: 75 /* All other states treated as blocking */ 76 clear_bit(port->portno, sparx5->bridge_fwd_mask); 77 clear_bit(port->portno, sparx5->bridge_lrn_mask); 78 break; 79 } 80 81 /* apply the bridge_fwd_mask to all the ports */ 82 sparx5_update_fwd(sparx5); 83 } 84 85 static void sparx5_port_attr_ageing_set(struct sparx5_port *port, 86 unsigned long ageing_clock_t) 87 { 88 unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t); 89 u32 ageing_time = jiffies_to_msecs(ageing_jiffies); 90 91 sparx5_set_ageing(port->sparx5, ageing_time); 92 } 93 94 static void sparx5_port_attr_mrouter_set(struct sparx5_port *port, 95 struct net_device *orig_dev, 96 bool enable) 97 { 98 struct sparx5 *sparx5 = port->sparx5; 99 struct sparx5_mdb_entry *e; 100 bool flood_flag; 101 102 if ((enable && port->is_mrouter) || (!enable && !port->is_mrouter)) 103 return; 104 105 /* Add/del mrouter port on all active mdb entries in HW. 106 * Don't change entry port mask, since that represents 107 * ports that actually joined that group. 108 */ 109 mutex_lock(&sparx5->mdb_lock); 110 list_for_each_entry(e, &sparx5->mdb_entries, list) { 111 if (!test_bit(port->portno, e->port_mask) && 112 ether_addr_is_ip_mcast(e->addr)) 113 sparx5_pgid_update_mask(port, e->pgid_idx, enable); 114 } 115 mutex_unlock(&sparx5->mdb_lock); 116 117 /* Enable/disable flooding depending on if port is mrouter port 118 * or if mcast flood is enabled. 119 */ 120 port->is_mrouter = enable; 121 flood_flag = br_port_flag_is_set(port->ndev, BR_MCAST_FLOOD); 122 sparx5_port_update_mcast_ip_flood(port, flood_flag); 123 } 124 125 static int sparx5_port_attr_set(struct net_device *dev, const void *ctx, 126 const struct switchdev_attr *attr, 127 struct netlink_ext_ack *extack) 128 { 129 struct sparx5_port *port = netdev_priv(dev); 130 131 switch (attr->id) { 132 case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: 133 return sparx5_port_attr_pre_bridge_flags(port, 134 attr->u.brport_flags); 135 case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: 136 sparx5_port_attr_bridge_flags(port, attr->u.brport_flags); 137 break; 138 case SWITCHDEV_ATTR_ID_PORT_STP_STATE: 139 sparx5_attr_stp_state_set(port, attr->u.stp_state); 140 break; 141 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: 142 sparx5_port_attr_ageing_set(port, attr->u.ageing_time); 143 break; 144 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: 145 /* Used PVID 1 when default_pvid is 0, to avoid 146 * collision with non-bridged ports. 147 */ 148 if (port->pvid == 0) 149 port->pvid = 1; 150 port->vlan_aware = attr->u.vlan_filtering; 151 sparx5_vlan_port_apply(port->sparx5, port); 152 break; 153 case SWITCHDEV_ATTR_ID_PORT_MROUTER: 154 sparx5_port_attr_mrouter_set(port, 155 attr->orig_dev, 156 attr->u.mrouter); 157 break; 158 default: 159 return -EOPNOTSUPP; 160 } 161 162 return 0; 163 } 164 165 static int sparx5_port_bridge_join(struct sparx5_port *port, 166 struct net_device *bridge, 167 struct netlink_ext_ack *extack) 168 { 169 struct sparx5 *sparx5 = port->sparx5; 170 struct net_device *ndev = port->ndev; 171 int err; 172 173 if (bitmap_empty(sparx5->bridge_mask, SPX5_PORTS)) 174 /* First bridged port */ 175 sparx5->hw_bridge_dev = bridge; 176 else 177 if (sparx5->hw_bridge_dev != bridge) 178 /* This is adding the port to a second bridge, this is 179 * unsupported 180 */ 181 return -ENODEV; 182 183 set_bit(port->portno, sparx5->bridge_mask); 184 185 err = switchdev_bridge_port_offload(ndev, ndev, NULL, NULL, NULL, 186 false, extack); 187 if (err) 188 goto err_switchdev_offload; 189 190 /* Remove standalone port entry */ 191 sparx5_mact_forget(sparx5, ndev->dev_addr, 0); 192 193 /* Port enters in bridge mode therefor don't need to copy to CPU 194 * frames for multicast in case the bridge is not requesting them 195 */ 196 __dev_mc_unsync(ndev, sparx5_mc_unsync); 197 198 return 0; 199 200 err_switchdev_offload: 201 clear_bit(port->portno, sparx5->bridge_mask); 202 return err; 203 } 204 205 static void sparx5_port_bridge_leave(struct sparx5_port *port, 206 struct net_device *bridge) 207 { 208 struct sparx5 *sparx5 = port->sparx5; 209 210 switchdev_bridge_port_unoffload(port->ndev, NULL, NULL, NULL); 211 212 clear_bit(port->portno, sparx5->bridge_mask); 213 if (bitmap_empty(sparx5->bridge_mask, SPX5_PORTS)) 214 sparx5->hw_bridge_dev = NULL; 215 216 /* Clear bridge vlan settings before updating the port settings */ 217 port->vlan_aware = 0; 218 port->pvid = NULL_VID; 219 port->vid = NULL_VID; 220 221 /* Forward frames to CPU */ 222 sparx5_mact_learn(sparx5, PGID_CPU, port->ndev->dev_addr, 0); 223 224 /* Port enters in host more therefore restore mc list */ 225 __dev_mc_sync(port->ndev, sparx5_mc_sync, sparx5_mc_unsync); 226 } 227 228 static int sparx5_port_changeupper(struct net_device *dev, 229 struct netdev_notifier_changeupper_info *info) 230 { 231 struct sparx5_port *port = netdev_priv(dev); 232 struct netlink_ext_ack *extack; 233 int err = 0; 234 235 extack = netdev_notifier_info_to_extack(&info->info); 236 237 if (netif_is_bridge_master(info->upper_dev)) { 238 if (info->linking) 239 err = sparx5_port_bridge_join(port, info->upper_dev, 240 extack); 241 else 242 sparx5_port_bridge_leave(port, info->upper_dev); 243 244 sparx5_vlan_port_apply(port->sparx5, port); 245 } 246 247 return err; 248 } 249 250 static int sparx5_port_add_addr(struct net_device *dev, bool up) 251 { 252 struct sparx5_port *port = netdev_priv(dev); 253 struct sparx5 *sparx5 = port->sparx5; 254 u16 vid = port->pvid; 255 256 if (up) 257 sparx5_mact_learn(sparx5, PGID_CPU, port->ndev->dev_addr, vid); 258 else 259 sparx5_mact_forget(sparx5, port->ndev->dev_addr, vid); 260 261 return 0; 262 } 263 264 static int sparx5_netdevice_port_event(struct net_device *dev, 265 struct notifier_block *nb, 266 unsigned long event, void *ptr) 267 { 268 int err = 0; 269 270 if (!sparx5_netdevice_check(dev)) 271 return 0; 272 273 switch (event) { 274 case NETDEV_CHANGEUPPER: 275 err = sparx5_port_changeupper(dev, ptr); 276 break; 277 case NETDEV_PRE_UP: 278 err = sparx5_port_add_addr(dev, true); 279 break; 280 case NETDEV_DOWN: 281 err = sparx5_port_add_addr(dev, false); 282 break; 283 } 284 285 return err; 286 } 287 288 static int sparx5_netdevice_event(struct notifier_block *nb, 289 unsigned long event, void *ptr) 290 { 291 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 292 int ret = 0; 293 294 ret = sparx5_netdevice_port_event(dev, nb, event, ptr); 295 296 return notifier_from_errno(ret); 297 } 298 299 static void sparx5_switchdev_bridge_fdb_event_work(struct work_struct *work) 300 { 301 struct sparx5_switchdev_event_work *switchdev_work = 302 container_of(work, struct sparx5_switchdev_event_work, work); 303 struct net_device *dev = switchdev_work->dev; 304 struct switchdev_notifier_fdb_info *fdb_info; 305 struct sparx5_port *port; 306 struct sparx5 *sparx5; 307 bool host_addr; 308 u16 vid; 309 310 rtnl_lock(); 311 if (!sparx5_netdevice_check(dev)) { 312 host_addr = true; 313 sparx5 = switchdev_work->sparx5; 314 } else { 315 host_addr = false; 316 sparx5 = switchdev_work->sparx5; 317 port = netdev_priv(dev); 318 } 319 320 fdb_info = &switchdev_work->fdb_info; 321 322 /* Used PVID 1 when default_pvid is 0, to avoid 323 * collision with non-bridged ports. 324 */ 325 if (fdb_info->vid == 0) 326 vid = 1; 327 else 328 vid = fdb_info->vid; 329 330 switch (switchdev_work->event) { 331 case SWITCHDEV_FDB_ADD_TO_DEVICE: 332 if (host_addr) 333 sparx5_add_mact_entry(sparx5, dev, PGID_CPU, 334 fdb_info->addr, vid); 335 else 336 sparx5_add_mact_entry(sparx5, port->ndev, port->portno, 337 fdb_info->addr, vid); 338 break; 339 case SWITCHDEV_FDB_DEL_TO_DEVICE: 340 sparx5_del_mact_entry(sparx5, fdb_info->addr, vid); 341 break; 342 } 343 344 rtnl_unlock(); 345 kfree(switchdev_work->fdb_info.addr); 346 kfree(switchdev_work); 347 dev_put(dev); 348 } 349 350 static void sparx5_schedule_work(struct work_struct *work) 351 { 352 queue_work(sparx5_owq, work); 353 } 354 355 static int sparx5_switchdev_event(struct notifier_block *nb, 356 unsigned long event, void *ptr) 357 { 358 struct net_device *dev = switchdev_notifier_info_to_dev(ptr); 359 struct sparx5_switchdev_event_work *switchdev_work; 360 struct switchdev_notifier_fdb_info *fdb_info; 361 struct switchdev_notifier_info *info = ptr; 362 struct sparx5 *spx5; 363 int err; 364 365 spx5 = container_of(nb, struct sparx5, switchdev_nb); 366 367 switch (event) { 368 case SWITCHDEV_PORT_ATTR_SET: 369 err = switchdev_handle_port_attr_set(dev, ptr, 370 sparx5_netdevice_check, 371 sparx5_port_attr_set); 372 return notifier_from_errno(err); 373 case SWITCHDEV_FDB_ADD_TO_DEVICE: 374 fallthrough; 375 case SWITCHDEV_FDB_DEL_TO_DEVICE: 376 switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); 377 if (!switchdev_work) 378 return NOTIFY_BAD; 379 380 switchdev_work->dev = dev; 381 switchdev_work->event = event; 382 switchdev_work->sparx5 = spx5; 383 384 fdb_info = container_of(info, 385 struct switchdev_notifier_fdb_info, 386 info); 387 INIT_WORK(&switchdev_work->work, 388 sparx5_switchdev_bridge_fdb_event_work); 389 memcpy(&switchdev_work->fdb_info, ptr, 390 sizeof(switchdev_work->fdb_info)); 391 switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC); 392 if (!switchdev_work->fdb_info.addr) 393 goto err_addr_alloc; 394 395 ether_addr_copy((u8 *)switchdev_work->fdb_info.addr, 396 fdb_info->addr); 397 dev_hold(dev); 398 399 sparx5_schedule_work(&switchdev_work->work); 400 break; 401 } 402 403 return NOTIFY_DONE; 404 err_addr_alloc: 405 kfree(switchdev_work); 406 return NOTIFY_BAD; 407 } 408 409 static int sparx5_handle_port_vlan_add(struct net_device *dev, 410 struct notifier_block *nb, 411 const struct switchdev_obj_port_vlan *v) 412 { 413 struct sparx5_port *port = netdev_priv(dev); 414 415 if (netif_is_bridge_master(dev)) { 416 struct sparx5 *sparx5 = 417 container_of(nb, struct sparx5, 418 switchdev_blocking_nb); 419 420 /* Flood broadcast to CPU */ 421 sparx5_mact_learn(sparx5, PGID_BCAST, dev->broadcast, 422 v->vid); 423 return 0; 424 } 425 426 if (!sparx5_netdevice_check(dev)) 427 return -EOPNOTSUPP; 428 429 return sparx5_vlan_vid_add(port, v->vid, 430 v->flags & BRIDGE_VLAN_INFO_PVID, 431 v->flags & BRIDGE_VLAN_INFO_UNTAGGED); 432 } 433 434 static int sparx5_alloc_mdb_entry(struct sparx5 *sparx5, 435 const unsigned char *addr, 436 u16 vid, 437 struct sparx5_mdb_entry **entry_out) 438 { 439 struct sparx5_mdb_entry *entry; 440 u16 pgid_idx; 441 int err; 442 443 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 444 if (!entry) 445 return -ENOMEM; 446 447 err = sparx5_pgid_alloc_mcast(sparx5, &pgid_idx); 448 if (err) { 449 kfree(entry); 450 return err; 451 } 452 453 memcpy(entry->addr, addr, ETH_ALEN); 454 entry->vid = vid; 455 entry->pgid_idx = pgid_idx; 456 457 mutex_lock(&sparx5->mdb_lock); 458 list_add_tail(&entry->list, &sparx5->mdb_entries); 459 mutex_unlock(&sparx5->mdb_lock); 460 461 *entry_out = entry; 462 return 0; 463 } 464 465 static void sparx5_free_mdb_entry(struct sparx5 *sparx5, 466 const unsigned char *addr, 467 u16 vid) 468 { 469 struct sparx5_mdb_entry *entry, *tmp; 470 471 mutex_lock(&sparx5->mdb_lock); 472 list_for_each_entry_safe(entry, tmp, &sparx5->mdb_entries, list) { 473 if ((vid == 0 || entry->vid == vid) && 474 ether_addr_equal(addr, entry->addr)) { 475 list_del(&entry->list); 476 477 sparx5_pgid_free(sparx5, entry->pgid_idx); 478 kfree(entry); 479 goto out; 480 } 481 } 482 483 out: 484 mutex_unlock(&sparx5->mdb_lock); 485 } 486 487 static struct sparx5_mdb_entry *sparx5_mdb_get_entry(struct sparx5 *sparx5, 488 const unsigned char *addr, 489 u16 vid) 490 { 491 struct sparx5_mdb_entry *e, *found = NULL; 492 493 mutex_lock(&sparx5->mdb_lock); 494 list_for_each_entry(e, &sparx5->mdb_entries, list) { 495 if (ether_addr_equal(e->addr, addr) && e->vid == vid) { 496 found = e; 497 goto out; 498 } 499 } 500 501 out: 502 mutex_unlock(&sparx5->mdb_lock); 503 return found; 504 } 505 506 static void sparx5_cpu_copy_ena(struct sparx5 *spx5, u16 pgid, bool enable) 507 { 508 spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(enable), 509 ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5, 510 ANA_AC_PGID_MISC_CFG(pgid)); 511 } 512 513 static int sparx5_handle_port_mdb_add(struct net_device *dev, 514 struct notifier_block *nb, 515 const struct switchdev_obj_port_mdb *v) 516 { 517 struct sparx5_port *port = netdev_priv(dev); 518 struct sparx5 *spx5 = port->sparx5; 519 struct sparx5_mdb_entry *entry; 520 bool is_host, is_new; 521 int err, i; 522 u16 vid; 523 524 if (!sparx5_netdevice_check(dev)) 525 return -EOPNOTSUPP; 526 527 is_host = netif_is_bridge_master(v->obj.orig_dev); 528 529 /* When VLAN unaware the vlan value is not parsed and we receive vid 0. 530 * Fall back to bridge vid 1. 531 */ 532 if (!br_vlan_enabled(spx5->hw_bridge_dev)) 533 vid = 1; 534 else 535 vid = v->vid; 536 537 is_new = false; 538 entry = sparx5_mdb_get_entry(spx5, v->addr, vid); 539 if (!entry) { 540 err = sparx5_alloc_mdb_entry(spx5, v->addr, vid, &entry); 541 is_new = true; 542 if (err) 543 return err; 544 } 545 546 mutex_lock(&spx5->mdb_lock); 547 548 /* Add any mrouter ports to the new entry */ 549 if (is_new && ether_addr_is_ip_mcast(v->addr)) 550 for (i = 0; i < SPX5_PORTS; i++) 551 if (spx5->ports[i] && spx5->ports[i]->is_mrouter) 552 sparx5_pgid_update_mask(spx5->ports[i], 553 entry->pgid_idx, 554 true); 555 556 if (is_host && !entry->cpu_copy) { 557 sparx5_cpu_copy_ena(spx5, entry->pgid_idx, true); 558 entry->cpu_copy = true; 559 } else if (!is_host) { 560 sparx5_pgid_update_mask(port, entry->pgid_idx, true); 561 set_bit(port->portno, entry->port_mask); 562 } 563 mutex_unlock(&spx5->mdb_lock); 564 565 sparx5_mact_learn(spx5, entry->pgid_idx, entry->addr, entry->vid); 566 567 return 0; 568 } 569 570 static int sparx5_handle_port_mdb_del(struct net_device *dev, 571 struct notifier_block *nb, 572 const struct switchdev_obj_port_mdb *v) 573 { 574 struct sparx5_port *port = netdev_priv(dev); 575 struct sparx5 *spx5 = port->sparx5; 576 struct sparx5_mdb_entry *entry; 577 bool is_host; 578 u16 vid; 579 580 if (!sparx5_netdevice_check(dev)) 581 return -EOPNOTSUPP; 582 583 is_host = netif_is_bridge_master(v->obj.orig_dev); 584 585 if (!br_vlan_enabled(spx5->hw_bridge_dev)) 586 vid = 1; 587 else 588 vid = v->vid; 589 590 entry = sparx5_mdb_get_entry(spx5, v->addr, vid); 591 if (!entry) 592 return 0; 593 594 mutex_lock(&spx5->mdb_lock); 595 if (is_host && entry->cpu_copy) { 596 sparx5_cpu_copy_ena(spx5, entry->pgid_idx, false); 597 entry->cpu_copy = false; 598 } else if (!is_host) { 599 clear_bit(port->portno, entry->port_mask); 600 601 /* Port not mrouter port or addr is L2 mcast, remove port from mask. */ 602 if (!port->is_mrouter || !ether_addr_is_ip_mcast(v->addr)) 603 sparx5_pgid_update_mask(port, entry->pgid_idx, false); 604 } 605 mutex_unlock(&spx5->mdb_lock); 606 607 if (bitmap_empty(entry->port_mask, SPX5_PORTS) && !entry->cpu_copy) { 608 /* Clear pgid in case mrouter ports exists 609 * that are not part of the group. 610 */ 611 sparx5_pgid_clear(spx5, entry->pgid_idx); 612 sparx5_mact_forget(spx5, entry->addr, entry->vid); 613 sparx5_free_mdb_entry(spx5, entry->addr, entry->vid); 614 } 615 return 0; 616 } 617 618 static int sparx5_handle_port_obj_add(struct net_device *dev, 619 struct notifier_block *nb, 620 struct switchdev_notifier_port_obj_info *info) 621 { 622 const struct switchdev_obj *obj = info->obj; 623 int err; 624 625 switch (obj->id) { 626 case SWITCHDEV_OBJ_ID_PORT_VLAN: 627 err = sparx5_handle_port_vlan_add(dev, nb, 628 SWITCHDEV_OBJ_PORT_VLAN(obj)); 629 break; 630 case SWITCHDEV_OBJ_ID_PORT_MDB: 631 case SWITCHDEV_OBJ_ID_HOST_MDB: 632 err = sparx5_handle_port_mdb_add(dev, nb, 633 SWITCHDEV_OBJ_PORT_MDB(obj)); 634 break; 635 default: 636 err = -EOPNOTSUPP; 637 break; 638 } 639 640 info->handled = true; 641 return err; 642 } 643 644 static int sparx5_handle_port_vlan_del(struct net_device *dev, 645 struct notifier_block *nb, 646 u16 vid) 647 { 648 struct sparx5_port *port = netdev_priv(dev); 649 int ret; 650 651 /* Master bridge? */ 652 if (netif_is_bridge_master(dev)) { 653 struct sparx5 *sparx5 = 654 container_of(nb, struct sparx5, 655 switchdev_blocking_nb); 656 657 sparx5_mact_forget(sparx5, dev->broadcast, vid); 658 return 0; 659 } 660 661 if (!sparx5_netdevice_check(dev)) 662 return -EOPNOTSUPP; 663 664 ret = sparx5_vlan_vid_del(port, vid); 665 if (ret) 666 return ret; 667 668 return 0; 669 } 670 671 static int sparx5_handle_port_obj_del(struct net_device *dev, 672 struct notifier_block *nb, 673 struct switchdev_notifier_port_obj_info *info) 674 { 675 const struct switchdev_obj *obj = info->obj; 676 int err; 677 678 switch (obj->id) { 679 case SWITCHDEV_OBJ_ID_PORT_VLAN: 680 err = sparx5_handle_port_vlan_del(dev, nb, 681 SWITCHDEV_OBJ_PORT_VLAN(obj)->vid); 682 break; 683 case SWITCHDEV_OBJ_ID_PORT_MDB: 684 case SWITCHDEV_OBJ_ID_HOST_MDB: 685 err = sparx5_handle_port_mdb_del(dev, nb, 686 SWITCHDEV_OBJ_PORT_MDB(obj)); 687 break; 688 default: 689 err = -EOPNOTSUPP; 690 break; 691 } 692 693 info->handled = true; 694 return err; 695 } 696 697 static int sparx5_switchdev_blocking_event(struct notifier_block *nb, 698 unsigned long event, 699 void *ptr) 700 { 701 struct net_device *dev = switchdev_notifier_info_to_dev(ptr); 702 int err; 703 704 switch (event) { 705 case SWITCHDEV_PORT_OBJ_ADD: 706 err = sparx5_handle_port_obj_add(dev, nb, ptr); 707 return notifier_from_errno(err); 708 case SWITCHDEV_PORT_OBJ_DEL: 709 err = sparx5_handle_port_obj_del(dev, nb, ptr); 710 return notifier_from_errno(err); 711 case SWITCHDEV_PORT_ATTR_SET: 712 err = switchdev_handle_port_attr_set(dev, ptr, 713 sparx5_netdevice_check, 714 sparx5_port_attr_set); 715 return notifier_from_errno(err); 716 } 717 718 return NOTIFY_DONE; 719 } 720 721 int sparx5_register_notifier_blocks(struct sparx5 *s5) 722 { 723 int err; 724 725 s5->netdevice_nb.notifier_call = sparx5_netdevice_event; 726 err = register_netdevice_notifier(&s5->netdevice_nb); 727 if (err) 728 return err; 729 730 s5->switchdev_nb.notifier_call = sparx5_switchdev_event; 731 err = register_switchdev_notifier(&s5->switchdev_nb); 732 if (err) 733 goto err_switchdev_nb; 734 735 s5->switchdev_blocking_nb.notifier_call = sparx5_switchdev_blocking_event; 736 err = register_switchdev_blocking_notifier(&s5->switchdev_blocking_nb); 737 if (err) 738 goto err_switchdev_blocking_nb; 739 740 sparx5_owq = alloc_ordered_workqueue("sparx5_order", 0); 741 if (!sparx5_owq) { 742 err = -ENOMEM; 743 goto err_switchdev_blocking_nb; 744 } 745 746 return 0; 747 748 err_switchdev_blocking_nb: 749 unregister_switchdev_notifier(&s5->switchdev_nb); 750 err_switchdev_nb: 751 unregister_netdevice_notifier(&s5->netdevice_nb); 752 753 return err; 754 } 755 756 void sparx5_unregister_notifier_blocks(struct sparx5 *s5) 757 { 758 destroy_workqueue(sparx5_owq); 759 760 unregister_switchdev_blocking_notifier(&s5->switchdev_blocking_nb); 761 unregister_switchdev_notifier(&s5->switchdev_nb); 762 unregister_netdevice_notifier(&s5->netdevice_nb); 763 } 764