diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2019-02-27 14:44:25 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-02-27 15:39:55 -0500 |
commit | 1cb33af1f75099282a51c4cc0bcc0ad413730079 (patch) | |
tree | 5fba4afb6297475d26c9931c384df7f7a5ef4ee5 /net/switchdev/switchdev.c | |
parent | 1d9978757d387dc64ad5e9ee021d1e3cb5082e07 (diff) |
switchdev: Add SWITCHDEV_PORT_ATTR_SET
In preparation for allowing switchdev enabled drivers to veto specific
attribute settings from within the context of the caller, introduce a
new switchdev notifier type for port attributes.
Suggested-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/switchdev/switchdev.c')
-rw-r--r-- | net/switchdev/switchdev.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 362413c9b389..3560c19aa7e2 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -655,3 +655,54 @@ int switchdev_handle_port_obj_del(struct net_device *dev, | |||
655 | return err; | 655 | return err; |
656 | } | 656 | } |
657 | EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_del); | 657 | EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_del); |
658 | |||
659 | static int __switchdev_handle_port_attr_set(struct net_device *dev, | ||
660 | struct switchdev_notifier_port_attr_info *port_attr_info, | ||
661 | bool (*check_cb)(const struct net_device *dev), | ||
662 | int (*set_cb)(struct net_device *dev, | ||
663 | const struct switchdev_attr *attr, | ||
664 | struct switchdev_trans *trans)) | ||
665 | { | ||
666 | struct net_device *lower_dev; | ||
667 | struct list_head *iter; | ||
668 | int err = -EOPNOTSUPP; | ||
669 | |||
670 | if (check_cb(dev)) { | ||
671 | port_attr_info->handled = true; | ||
672 | return set_cb(dev, port_attr_info->attr, | ||
673 | port_attr_info->trans); | ||
674 | } | ||
675 | |||
676 | /* Switch ports might be stacked under e.g. a LAG. Ignore the | ||
677 | * unsupported devices, another driver might be able to handle them. But | ||
678 | * propagate to the callers any hard errors. | ||
679 | * | ||
680 | * If the driver does its own bookkeeping of stacked ports, it's not | ||
681 | * necessary to go through this helper. | ||
682 | */ | ||
683 | netdev_for_each_lower_dev(dev, lower_dev, iter) { | ||
684 | err = __switchdev_handle_port_attr_set(lower_dev, port_attr_info, | ||
685 | check_cb, set_cb); | ||
686 | if (err && err != -EOPNOTSUPP) | ||
687 | return err; | ||
688 | } | ||
689 | |||
690 | return err; | ||
691 | } | ||
692 | |||
693 | int switchdev_handle_port_attr_set(struct net_device *dev, | ||
694 | struct switchdev_notifier_port_attr_info *port_attr_info, | ||
695 | bool (*check_cb)(const struct net_device *dev), | ||
696 | int (*set_cb)(struct net_device *dev, | ||
697 | const struct switchdev_attr *attr, | ||
698 | struct switchdev_trans *trans)) | ||
699 | { | ||
700 | int err; | ||
701 | |||
702 | err = __switchdev_handle_port_attr_set(dev, port_attr_info, check_cb, | ||
703 | set_cb); | ||
704 | if (err == -EOPNOTSUPP) | ||
705 | err = 0; | ||
706 | return err; | ||
707 | } | ||
708 | EXPORT_SYMBOL_GPL(switchdev_handle_port_attr_set); | ||