diff options
Diffstat (limited to 'net/dsa/slave.c')
| -rw-r--r-- | net/dsa/slave.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index aec78f5aca72..a3fcc1d01615 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
| @@ -1050,8 +1050,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = { | |||
| 1050 | static const struct switchdev_ops dsa_slave_switchdev_ops = { | 1050 | static const struct switchdev_ops dsa_slave_switchdev_ops = { |
| 1051 | .switchdev_port_attr_get = dsa_slave_port_attr_get, | 1051 | .switchdev_port_attr_get = dsa_slave_port_attr_get, |
| 1052 | .switchdev_port_attr_set = dsa_slave_port_attr_set, | 1052 | .switchdev_port_attr_set = dsa_slave_port_attr_set, |
| 1053 | .switchdev_port_obj_add = dsa_slave_port_obj_add, | ||
| 1054 | .switchdev_port_obj_del = dsa_slave_port_obj_del, | ||
| 1055 | }; | 1053 | }; |
| 1056 | 1054 | ||
| 1057 | static struct device_type dsa_type = { | 1055 | static struct device_type dsa_type = { |
| @@ -1529,6 +1527,44 @@ err_fdb_work_init: | |||
| 1529 | return NOTIFY_BAD; | 1527 | return NOTIFY_BAD; |
| 1530 | } | 1528 | } |
| 1531 | 1529 | ||
| 1530 | static int | ||
| 1531 | dsa_slave_switchdev_port_obj_event(unsigned long event, | ||
| 1532 | struct net_device *netdev, | ||
| 1533 | struct switchdev_notifier_port_obj_info *port_obj_info) | ||
| 1534 | { | ||
| 1535 | int err = -EOPNOTSUPP; | ||
| 1536 | |||
| 1537 | switch (event) { | ||
| 1538 | case SWITCHDEV_PORT_OBJ_ADD: | ||
| 1539 | err = dsa_slave_port_obj_add(netdev, port_obj_info->obj, | ||
| 1540 | port_obj_info->trans); | ||
| 1541 | break; | ||
| 1542 | case SWITCHDEV_PORT_OBJ_DEL: | ||
| 1543 | err = dsa_slave_port_obj_del(netdev, port_obj_info->obj); | ||
| 1544 | break; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | port_obj_info->handled = true; | ||
| 1548 | return notifier_from_errno(err); | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused, | ||
| 1552 | unsigned long event, void *ptr) | ||
| 1553 | { | ||
| 1554 | struct net_device *dev = switchdev_notifier_info_to_dev(ptr); | ||
| 1555 | |||
| 1556 | if (!dsa_slave_dev_check(dev)) | ||
| 1557 | return NOTIFY_DONE; | ||
| 1558 | |||
| 1559 | switch (event) { | ||
| 1560 | case SWITCHDEV_PORT_OBJ_ADD: /* fall through */ | ||
| 1561 | case SWITCHDEV_PORT_OBJ_DEL: | ||
| 1562 | return dsa_slave_switchdev_port_obj_event(event, dev, ptr); | ||
| 1563 | } | ||
| 1564 | |||
| 1565 | return NOTIFY_DONE; | ||
| 1566 | } | ||
| 1567 | |||
| 1532 | static struct notifier_block dsa_slave_nb __read_mostly = { | 1568 | static struct notifier_block dsa_slave_nb __read_mostly = { |
| 1533 | .notifier_call = dsa_slave_netdevice_event, | 1569 | .notifier_call = dsa_slave_netdevice_event, |
| 1534 | }; | 1570 | }; |
| @@ -1537,8 +1573,13 @@ static struct notifier_block dsa_slave_switchdev_notifier = { | |||
| 1537 | .notifier_call = dsa_slave_switchdev_event, | 1573 | .notifier_call = dsa_slave_switchdev_event, |
| 1538 | }; | 1574 | }; |
| 1539 | 1575 | ||
| 1576 | static struct notifier_block dsa_slave_switchdev_blocking_notifier = { | ||
| 1577 | .notifier_call = dsa_slave_switchdev_blocking_event, | ||
| 1578 | }; | ||
| 1579 | |||
| 1540 | int dsa_slave_register_notifier(void) | 1580 | int dsa_slave_register_notifier(void) |
| 1541 | { | 1581 | { |
| 1582 | struct notifier_block *nb; | ||
| 1542 | int err; | 1583 | int err; |
| 1543 | 1584 | ||
| 1544 | err = register_netdevice_notifier(&dsa_slave_nb); | 1585 | err = register_netdevice_notifier(&dsa_slave_nb); |
| @@ -1549,8 +1590,15 @@ int dsa_slave_register_notifier(void) | |||
| 1549 | if (err) | 1590 | if (err) |
| 1550 | goto err_switchdev_nb; | 1591 | goto err_switchdev_nb; |
| 1551 | 1592 | ||
| 1593 | nb = &dsa_slave_switchdev_blocking_notifier; | ||
| 1594 | err = register_switchdev_blocking_notifier(nb); | ||
| 1595 | if (err) | ||
| 1596 | goto err_switchdev_blocking_nb; | ||
| 1597 | |||
| 1552 | return 0; | 1598 | return 0; |
| 1553 | 1599 | ||
| 1600 | err_switchdev_blocking_nb: | ||
| 1601 | unregister_switchdev_notifier(&dsa_slave_switchdev_notifier); | ||
| 1554 | err_switchdev_nb: | 1602 | err_switchdev_nb: |
| 1555 | unregister_netdevice_notifier(&dsa_slave_nb); | 1603 | unregister_netdevice_notifier(&dsa_slave_nb); |
| 1556 | return err; | 1604 | return err; |
| @@ -1558,8 +1606,14 @@ err_switchdev_nb: | |||
| 1558 | 1606 | ||
| 1559 | void dsa_slave_unregister_notifier(void) | 1607 | void dsa_slave_unregister_notifier(void) |
| 1560 | { | 1608 | { |
| 1609 | struct notifier_block *nb; | ||
| 1561 | int err; | 1610 | int err; |
| 1562 | 1611 | ||
| 1612 | nb = &dsa_slave_switchdev_blocking_notifier; | ||
| 1613 | err = unregister_switchdev_blocking_notifier(nb); | ||
| 1614 | if (err) | ||
| 1615 | pr_err("DSA: failed to unregister switchdev blocking notifier (%d)\n", err); | ||
| 1616 | |||
| 1563 | err = unregister_switchdev_notifier(&dsa_slave_switchdev_notifier); | 1617 | err = unregister_switchdev_notifier(&dsa_slave_switchdev_notifier); |
| 1564 | if (err) | 1618 | if (err) |
| 1565 | pr_err("DSA: failed to unregister switchdev notifier (%d)\n", err); | 1619 | pr_err("DSA: failed to unregister switchdev notifier (%d)\n", err); |
