From 5728ae0d17d27e14b7e5034f73a38b562cfcd5c5 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 21 Nov 2018 08:02:39 +0000 Subject: vxlan: Add hardware FDB learning In order to allow devices to signal learning events to VXLAN, introduce two new switchdev messages: SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE and SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE. Listen to these notifications in the vxlan driver. The FDB entries learned this way have an NTF_EXT_LEARNED flag, and only entries marked as such can be unlearned by the _DEL_ event. They are also immediately marked as offloaded. This is the same behavior that the bridge driver observes. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- include/net/switchdev.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 881ecb1555bf..7b371e7c4bc6 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -146,6 +146,8 @@ enum switchdev_notifier_type { SWITCHDEV_FDB_DEL_TO_DEVICE, SWITCHDEV_FDB_OFFLOADED, + SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE, + SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE, SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE, SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE, SWITCHDEV_VXLAN_FDB_OFFLOADED, -- cgit v1.2.3-71-gd317 From ec394af5ea1d8ee62681815d167115ac618bcb42 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 22 Nov 2018 23:28:07 +0000 Subject: switchdev: SWITCHDEV_OBJ_PORT_{VLAN, MDB}(): Sanitize The two macros SWITCHDEV_OBJ_PORT_VLAN() and SWITCHDEV_OBJ_PORT_MDB() expand to a container_of() call, yielding an appropriate container of their sole argument. However, due to a name collision, the first argument, i.e. the contained object pointer, is not the only one to get expanded. The third argument, which is a structure member name, and should be kept literal, gets expanded as well. The only safe way to use these two macros is therefore to name the local variable passed to them "obj". To fix this, rename the sole argument of the two macros from "obj" (which collides with the member name) to "OBJ". Additionally, instead of passing "OBJ" to container_of() verbatim, parenthesize it, so that a comma in the passed-in expression doesn't pollute the container_of() invocation. Signed-off-by: Petr Machata Acked-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- include/net/switchdev.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 7b371e7c4bc6..dd969224a9b9 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -95,8 +95,8 @@ struct switchdev_obj_port_vlan { u16 vid_end; }; -#define SWITCHDEV_OBJ_PORT_VLAN(obj) \ - container_of(obj, struct switchdev_obj_port_vlan, obj) +#define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \ + container_of((OBJ), struct switchdev_obj_port_vlan, obj) /* SWITCHDEV_OBJ_ID_PORT_MDB */ struct switchdev_obj_port_mdb { @@ -105,8 +105,8 @@ struct switchdev_obj_port_mdb { u16 vid; }; -#define SWITCHDEV_OBJ_PORT_MDB(obj) \ - container_of(obj, struct switchdev_obj_port_mdb, obj) +#define SWITCHDEV_OBJ_PORT_MDB(OBJ) \ + container_of((OBJ), struct switchdev_obj_port_mdb, obj) void switchdev_trans_item_enqueue(struct switchdev_trans *trans, void *data, void (*destructor)(void const *), -- cgit v1.2.3-71-gd317 From a93e3b17227ed8b0db7e44d0302b4da7d07f9a35 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 22 Nov 2018 23:28:25 +0000 Subject: switchdev: Add a blocking notifier chain In general one can't assume that a switchdev notifier is called in a non-atomic context, and correspondingly, the switchdev notifier chain is an atomic one. However, port object addition and deletion messages are delivered from a process context. Even the MDB addition messages, whose delivery is scheduled from atomic context, are queued and the delivery itself takes place in blocking context. For VLAN messages in particular, keeping the blocking nature is important for error reporting. Therefore introduce a blocking notifier chain and related service functions to distribute the notifications for which a blocking context can be assumed. Signed-off-by: Petr Machata Reviewed-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- include/net/switchdev.h | 27 +++++++++++++++++++++++++++ net/switchdev/switchdev.c | 26 ++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index dd969224a9b9..e021b67b9b32 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -182,10 +182,17 @@ int switchdev_port_obj_add(struct net_device *dev, const struct switchdev_obj *obj); int switchdev_port_obj_del(struct net_device *dev, const struct switchdev_obj *obj); + int register_switchdev_notifier(struct notifier_block *nb); int unregister_switchdev_notifier(struct notifier_block *nb); int call_switchdev_notifiers(unsigned long val, struct net_device *dev, struct switchdev_notifier_info *info); + +int register_switchdev_blocking_notifier(struct notifier_block *nb); +int unregister_switchdev_blocking_notifier(struct notifier_block *nb); +int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, + struct switchdev_notifier_info *info); + void switchdev_port_fwd_mark_set(struct net_device *dev, struct net_device *group_dev, bool joining); @@ -241,6 +248,26 @@ static inline int call_switchdev_notifiers(unsigned long val, return NOTIFY_DONE; } +static inline int +register_switchdev_blocking_notifier(struct notifier_block *nb) +{ + return 0; +} + +static inline int +unregister_switchdev_blocking_notifier(struct notifier_block *nb) +{ + return 0; +} + +static inline int +call_switchdev_blocking_notifiers(unsigned long val, + struct net_device *dev, + struct switchdev_notifier_info *info) +{ + return NOTIFY_DONE; +} + static inline bool switchdev_port_same_parent_id(struct net_device *a, struct net_device *b) { diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 74b9d916a58b..e109bb97ce3f 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -535,6 +535,7 @@ int switchdev_port_obj_del(struct net_device *dev, EXPORT_SYMBOL_GPL(switchdev_port_obj_del); static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain); +static BLOCKING_NOTIFIER_HEAD(switchdev_blocking_notif_chain); /** * register_switchdev_notifier - Register notifier @@ -576,6 +577,31 @@ int call_switchdev_notifiers(unsigned long val, struct net_device *dev, } EXPORT_SYMBOL_GPL(call_switchdev_notifiers); +int register_switchdev_blocking_notifier(struct notifier_block *nb) +{ + struct blocking_notifier_head *chain = &switchdev_blocking_notif_chain; + + return blocking_notifier_chain_register(chain, nb); +} +EXPORT_SYMBOL_GPL(register_switchdev_blocking_notifier); + +int unregister_switchdev_blocking_notifier(struct notifier_block *nb) +{ + struct blocking_notifier_head *chain = &switchdev_blocking_notif_chain; + + return blocking_notifier_chain_unregister(chain, nb); +} +EXPORT_SYMBOL_GPL(unregister_switchdev_blocking_notifier); + +int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, + struct switchdev_notifier_info *info) +{ + info->dev = dev; + return blocking_notifier_call_chain(&switchdev_blocking_notif_chain, + val, info); +} +EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers); + bool switchdev_port_same_parent_id(struct net_device *a, struct net_device *b) { -- cgit v1.2.3-71-gd317 From aa4efe21393f5c39a72c132d6e0d777d7405b885 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 22 Nov 2018 23:28:38 +0000 Subject: switchdev: Add SWITCHDEV_PORT_OBJ_ADD, SWITCHDEV_PORT_OBJ_DEL An offloading driver may need to have access to switchdev events on ports that aren't directly under its control. An example is a VXLAN port attached to a bridge offloaded by a driver. The driver needs to know about VLANs configured on the VXLAN device. However the VXLAN device isn't stashed between the bridge and a front-panel-port device (such as is the case e.g. for LAG devices), so the usual switchdev ops don't reach the driver. VXLAN is likely not the only device type like this: in theory any L2 tunnel device that needs offloading will prompt requirement of this sort. This falsifies the assumption that only the lower devices of a front panel port need to be notified to achieve flawless offloading. A way to fix this is to give up the notion of port object addition / deletion as a switchdev operation, which assumes somewhat tight coupling between the message producer and consumer. And instead send the message over a notifier chain. To that end, introduce two new switchdev notifier types, SWITCHDEV_PORT_OBJ_ADD and SWITCHDEV_PORT_OBJ_DEL. These notifier types communicate the same event as the corresponding switchdev op, except in a form of a notification. struct switchdev_notifier_port_obj_info was added to carry the fields that the switchdev op carries. An additional field, handled, will be used to communicate back to switchdev that the event has reached an interested party, which will be important for the two-phase commit. The two switchdev operations themselves are kept in place. Following patches first convert individual clients to the notifier protocol, and only then are the operations removed. Signed-off-by: Petr Machata Acked-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- include/net/switchdev.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index e021b67b9b32..a2f3ebf39301 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -146,6 +146,9 @@ enum switchdev_notifier_type { SWITCHDEV_FDB_DEL_TO_DEVICE, SWITCHDEV_FDB_OFFLOADED, + SWITCHDEV_PORT_OBJ_ADD, /* Blocking. */ + SWITCHDEV_PORT_OBJ_DEL, /* Blocking. */ + SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE, SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE, SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE, @@ -165,6 +168,13 @@ struct switchdev_notifier_fdb_info { offloaded:1; }; +struct switchdev_notifier_port_obj_info { + struct switchdev_notifier_info info; /* must be first */ + const struct switchdev_obj *obj; + struct switchdev_trans *trans; + bool handled; +}; + static inline struct net_device * switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info) { -- cgit v1.2.3-71-gd317 From f30f0601eb934dda107decd2e57b37168096fd74 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 22 Nov 2018 23:29:44 +0000 Subject: switchdev: Add helpers to aid traversal through lower devices After the transition from switchdev operations to notifier chain (which will take place in following patches), the onus is on the driver to find its own devices below possible layer of LAG or other uppers. The logic to do so is fairly repetitive: each driver is looking for its own devices among the lowers of the notified device. For those that it finds, it calls a handler. To indicate that the event was handled, struct switchdev_notifier_port_obj_info.handled is set. The differences lie only in what constitutes an "own" device and what handler to call. Therefore abstract this logic into two helpers, switchdev_handle_port_obj_add() and switchdev_handle_port_obj_del(). If a driver only supports physical ports under a bridge device, it will simply avoid this layer of indirection. One area where this helper diverges from the current switchdev behavior is the case of mixed lowers, some of which are switchdev ports and some of which are not. Previously, such scenario would fail with -EOPNOTSUPP. The helper could do that for lowers for which the passed-in predicate doesn't hold. That would however break the case that switchdev ports from several different drivers are stashed under one master, a scenario that switchdev currently happily supports. Therefore tolerate any and all unknown netdevices, whether they are backed by a switchdev driver or not. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- include/net/switchdev.h | 33 +++++++++++++++ net/switchdev/switchdev.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index a2f3ebf39301..6dc7de576167 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -210,6 +210,18 @@ void switchdev_port_fwd_mark_set(struct net_device *dev, bool switchdev_port_same_parent_id(struct net_device *a, struct net_device *b); +int switchdev_handle_port_obj_add(struct net_device *dev, + struct switchdev_notifier_port_obj_info *port_obj_info, + bool (*check_cb)(const struct net_device *dev), + int (*add_cb)(struct net_device *dev, + const struct switchdev_obj *obj, + struct switchdev_trans *trans)); +int switchdev_handle_port_obj_del(struct net_device *dev, + struct switchdev_notifier_port_obj_info *port_obj_info, + bool (*check_cb)(const struct net_device *dev), + int (*del_cb)(struct net_device *dev, + const struct switchdev_obj *obj)); + #define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops)) #else @@ -284,6 +296,27 @@ static inline bool switchdev_port_same_parent_id(struct net_device *a, return false; } +static inline int +switchdev_handle_port_obj_add(struct net_device *dev, + struct switchdev_notifier_port_obj_info *port_obj_info, + bool (*check_cb)(const struct net_device *dev), + int (*add_cb)(struct net_device *dev, + const struct switchdev_obj *obj, + struct switchdev_trans *trans)) +{ + return 0; +} + +static inline int +switchdev_handle_port_obj_del(struct net_device *dev, + struct switchdev_notifier_port_obj_info *port_obj_info, + bool (*check_cb)(const struct net_device *dev), + int (*del_cb)(struct net_device *dev, + const struct switchdev_obj *obj)) +{ + return 0; +} + #define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0) #endif diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index e109bb97ce3f..099434ec7996 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -621,3 +621,103 @@ bool switchdev_port_same_parent_id(struct net_device *a, return netdev_phys_item_id_same(&a_attr.u.ppid, &b_attr.u.ppid); } EXPORT_SYMBOL_GPL(switchdev_port_same_parent_id); + +static int __switchdev_handle_port_obj_add(struct net_device *dev, + struct switchdev_notifier_port_obj_info *port_obj_info, + bool (*check_cb)(const struct net_device *dev), + int (*add_cb)(struct net_device *dev, + const struct switchdev_obj *obj, + struct switchdev_trans *trans)) +{ + struct net_device *lower_dev; + struct list_head *iter; + int err = -EOPNOTSUPP; + + if (check_cb(dev)) { + /* This flag is only checked if the return value is success. */ + port_obj_info->handled = true; + return add_cb(dev, port_obj_info->obj, port_obj_info->trans); + } + + /* Switch ports might be stacked under e.g. a LAG. Ignore the + * unsupported devices, another driver might be able to handle them. But + * propagate to the callers any hard errors. + * + * If the driver does its own bookkeeping of stacked ports, it's not + * necessary to go through this helper. + */ + netdev_for_each_lower_dev(dev, lower_dev, iter) { + err = __switchdev_handle_port_obj_add(lower_dev, port_obj_info, + check_cb, add_cb); + if (err && err != -EOPNOTSUPP) + return err; + } + + return err; +} + +int switchdev_handle_port_obj_add(struct net_device *dev, + struct switchdev_notifier_port_obj_info *port_obj_info, + bool (*check_cb)(const struct net_device *dev), + int (*add_cb)(struct net_device *dev, + const struct switchdev_obj *obj, + struct switchdev_trans *trans)) +{ + int err; + + err = __switchdev_handle_port_obj_add(dev, port_obj_info, check_cb, + add_cb); + if (err == -EOPNOTSUPP) + err = 0; + return err; +} +EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_add); + +static int __switchdev_handle_port_obj_del(struct net_device *dev, + struct switchdev_notifier_port_obj_info *port_obj_info, + bool (*check_cb)(const struct net_device *dev), + int (*del_cb)(struct net_device *dev, + const struct switchdev_obj *obj)) +{ + struct net_device *lower_dev; + struct list_head *iter; + int err = -EOPNOTSUPP; + + if (check_cb(dev)) { + /* This flag is only checked if the return value is success. */ + port_obj_info->handled = true; + return del_cb(dev, port_obj_info->obj); + } + + /* Switch ports might be stacked under e.g. a LAG. Ignore the + * unsupported devices, another driver might be able to handle them. But + * propagate to the callers any hard errors. + * + * If the driver does its own bookkeeping of stacked ports, it's not + * necessary to go through this helper. + */ + netdev_for_each_lower_dev(dev, lower_dev, iter) { + err = __switchdev_handle_port_obj_del(lower_dev, port_obj_info, + check_cb, del_cb); + if (err && err != -EOPNOTSUPP) + return err; + } + + return err; +} + +int switchdev_handle_port_obj_del(struct net_device *dev, + struct switchdev_notifier_port_obj_info *port_obj_info, + bool (*check_cb)(const struct net_device *dev), + int (*del_cb)(struct net_device *dev, + const struct switchdev_obj *obj)) +{ + int err; + + err = __switchdev_handle_port_obj_del(dev, port_obj_info, check_cb, + del_cb); + if (err == -EOPNOTSUPP) + err = 0; + return err; +} +EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_del); -- cgit v1.2.3-71-gd317 From d17d9f5e5143125f9274194d8f7368f76b9d141f Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 22 Nov 2018 23:32:57 +0000 Subject: switchdev: Replace port obj add/del SDO with a notification Drop switchdev_ops.switchdev_port_obj_add and _del. Drop the uses of this field from all clients, which were migrated to use switchdev notification in the previous patches. Add a new function switchdev_port_obj_notify() that sends the switchdev notifications SWITCHDEV_PORT_OBJ_ADD and _DEL. Update switchdev_port_obj_del_now() to dispatch to this new function. Drop __switchdev_port_obj_add() and update switchdev_port_obj_add() likewise. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 - drivers/net/ethernet/mscc/ocelot.c | 2 - drivers/net/ethernet/rocker/rocker_main.c | 2 - drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 2 - include/net/switchdev.h | 9 --- net/dsa/slave.c | 2 - net/switchdev/switchdev.c | 67 ++++++++-------------- 7 files changed, 25 insertions(+), 61 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 3756aaecd39c..73e5db176d7e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1968,8 +1968,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { .switchdev_port_attr_get = mlxsw_sp_port_attr_get, .switchdev_port_attr_set = mlxsw_sp_port_attr_set, - .switchdev_port_obj_add = mlxsw_sp_port_obj_add, - .switchdev_port_obj_del = mlxsw_sp_port_obj_del, }; static int diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 01403b530522..7f8da8873a96 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1337,8 +1337,6 @@ static int ocelot_port_obj_del(struct net_device *dev, static const struct switchdev_ops ocelot_port_switchdev_ops = { .switchdev_port_attr_get = ocelot_port_attr_get, .switchdev_port_attr_set = ocelot_port_attr_set, - .switchdev_port_obj_add = ocelot_port_obj_add, - .switchdev_port_obj_del = ocelot_port_obj_del, }; static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port, diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 806ffe1d906e..f05d5c1341b6 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2145,8 +2145,6 @@ static int rocker_port_obj_del(struct net_device *dev, static const struct switchdev_ops rocker_port_switchdev_ops = { .switchdev_port_attr_get = rocker_port_attr_get, .switchdev_port_attr_set = rocker_port_attr_set, - .switchdev_port_obj_add = rocker_port_obj_add, - .switchdev_port_obj_del = rocker_port_obj_del, }; struct rocker_fib_event_work { diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 83e1d92dc7f3..06a233c7cdd3 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -930,8 +930,6 @@ static int swdev_port_obj_del(struct net_device *netdev, static const struct switchdev_ops ethsw_port_switchdev_ops = { .switchdev_port_attr_get = swdev_port_attr_get, .switchdev_port_attr_set = swdev_port_attr_set, - .switchdev_port_obj_add = swdev_port_obj_add, - .switchdev_port_obj_del = swdev_port_obj_del, }; /* For the moment, only flood setting needs to be updated */ diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 6dc7de576167..866b6d148b77 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -121,10 +121,6 @@ typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj); * @switchdev_port_attr_get: Get a port attribute (see switchdev_attr). * * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr). - * - * @switchdev_port_obj_add: Add an object to port (see switchdev_obj_*). - * - * @switchdev_port_obj_del: Delete an object from port (see switchdev_obj_*). */ struct switchdev_ops { int (*switchdev_port_attr_get)(struct net_device *dev, @@ -132,11 +128,6 @@ struct switchdev_ops { int (*switchdev_port_attr_set)(struct net_device *dev, const struct switchdev_attr *attr, struct switchdev_trans *trans); - int (*switchdev_port_obj_add)(struct net_device *dev, - const struct switchdev_obj *obj, - struct switchdev_trans *trans); - int (*switchdev_port_obj_del)(struct net_device *dev, - const struct switchdev_obj *obj); }; enum switchdev_notifier_type { diff --git a/net/dsa/slave.c b/net/dsa/slave.c index d00a0b6d4ce0..268119cf7117 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 = { static const struct switchdev_ops dsa_slave_switchdev_ops = { .switchdev_port_attr_get = dsa_slave_port_attr_get, .switchdev_port_attr_set = dsa_slave_port_attr_set, - .switchdev_port_obj_add = dsa_slave_port_obj_add, - .switchdev_port_obj_del = dsa_slave_port_obj_del, }; static struct device_type dsa_type = { diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 099434ec7996..fe23fac4dc4b 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -353,30 +353,29 @@ static size_t switchdev_obj_size(const struct switchdev_obj *obj) return 0; } -static int __switchdev_port_obj_add(struct net_device *dev, - const struct switchdev_obj *obj, - struct switchdev_trans *trans) +static int switchdev_port_obj_notify(enum switchdev_notifier_type nt, + struct net_device *dev, + const struct switchdev_obj *obj, + struct switchdev_trans *trans) { - const struct switchdev_ops *ops = dev->switchdev_ops; - struct net_device *lower_dev; - struct list_head *iter; - int err = -EOPNOTSUPP; - - if (ops && ops->switchdev_port_obj_add) - return ops->switchdev_port_obj_add(dev, obj, trans); + int rc; + int err; - /* Switch device port(s) may be stacked under - * bond/team/vlan dev, so recurse down to add object on - * each port. - */ + struct switchdev_notifier_port_obj_info obj_info = { + .obj = obj, + .trans = trans, + .handled = false, + }; - netdev_for_each_lower_dev(dev, lower_dev, iter) { - err = __switchdev_port_obj_add(lower_dev, obj, trans); - if (err) - break; + rc = call_switchdev_blocking_notifiers(nt, dev, &obj_info.info); + err = notifier_to_errno(rc); + if (err) { + WARN_ON(!obj_info.handled); + return err; } - - return err; + if (!obj_info.handled) + return -EOPNOTSUPP; + return 0; } static int switchdev_port_obj_add_now(struct net_device *dev, @@ -397,7 +396,8 @@ static int switchdev_port_obj_add_now(struct net_device *dev, */ trans.ph_prepare = true; - err = __switchdev_port_obj_add(dev, obj, &trans); + err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, + dev, obj, &trans); if (err) { /* Prepare phase failed: abort the transaction. Any * resources reserved in the prepare phase are @@ -416,7 +416,8 @@ static int switchdev_port_obj_add_now(struct net_device *dev, */ trans.ph_prepare = false; - err = __switchdev_port_obj_add(dev, obj, &trans); + err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, + dev, obj, &trans); WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); switchdev_trans_items_warn_destroy(dev, &trans); @@ -471,26 +472,8 @@ EXPORT_SYMBOL_GPL(switchdev_port_obj_add); static int switchdev_port_obj_del_now(struct net_device *dev, const struct switchdev_obj *obj) { - const struct switchdev_ops *ops = dev->switchdev_ops; - struct net_device *lower_dev; - struct list_head *iter; - int err = -EOPNOTSUPP; - - if (ops && ops->switchdev_port_obj_del) - return ops->switchdev_port_obj_del(dev, obj); - - /* Switch device port(s) may be stacked under - * bond/team/vlan dev, so recurse down to delete object on - * each port. - */ - - netdev_for_each_lower_dev(dev, lower_dev, iter) { - err = switchdev_port_obj_del_now(lower_dev, obj); - if (err) - break; - } - - return err; + return switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_DEL, + dev, obj, NULL); } static void switchdev_port_obj_del_deferred(struct net_device *dev, -- cgit v1.2.3-71-gd317 From 69b7320e14e6e8c7a77fa5803cecc86434a1162d Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 12 Dec 2018 17:02:52 +0000 Subject: net: switchdev: Add extack argument to switchdev_port_obj_add() After the previous patch, bridge driver has extack argument available to pass to switchdev. Therefore extend switchdev_port_obj_add() with this argument, updating all callers, and passing the argument through to switchdev_port_obj_notify(). Signed-off-by: Petr Machata Acked-by: Jiri Pirko Acked-by: Ivan Vecera Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- include/net/switchdev.h | 6 ++++-- net/bridge/br_mdb.c | 4 ++-- net/bridge/br_switchdev.c | 2 +- net/switchdev/switchdev.c | 19 +++++++++++-------- 4 files changed, 18 insertions(+), 13 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 866b6d148b77..69016305ad58 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -180,7 +180,8 @@ int switchdev_port_attr_get(struct net_device *dev, int switchdev_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr); int switchdev_port_obj_add(struct net_device *dev, - const struct switchdev_obj *obj); + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack); int switchdev_port_obj_del(struct net_device *dev, const struct switchdev_obj *obj); @@ -233,7 +234,8 @@ static inline int switchdev_port_attr_set(struct net_device *dev, } static inline int switchdev_port_obj_add(struct net_device *dev, - const struct switchdev_obj *obj) + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack) { return -EOPNOTSUPP; } diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 79d4c9d253e0..f69c8d91dc81 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -331,7 +331,7 @@ static void br_mdb_switchdev_host_port(struct net_device *dev, mdb.obj.orig_dev = dev; switch (type) { case RTM_NEWMDB: - switchdev_port_obj_add(lower_dev, &mdb.obj); + switchdev_port_obj_add(lower_dev, &mdb.obj, NULL); break; case RTM_DELMDB: switchdev_port_obj_del(lower_dev, &mdb.obj); @@ -381,7 +381,7 @@ static void __br_mdb_notify(struct net_device *dev, struct net_bridge_port *p, __mdb_entry_to_br_ip(entry, &complete_info->ip); mdb.obj.complete_priv = complete_info; mdb.obj.complete = br_mdb_complete; - if (switchdev_port_obj_add(port_dev, &mdb.obj)) + if (switchdev_port_obj_add(port_dev, &mdb.obj, NULL)) kfree(complete_info); } } else if (p && port_dev && type == RTM_DELMDB) { diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index 99ba32177b31..035ff59d9cbd 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -151,7 +151,7 @@ int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, .vid_end = vid, }; - return switchdev_port_obj_add(dev, &v.obj); + return switchdev_port_obj_add(dev, &v.obj, extack); } int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid) diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index fe23fac4dc4b..cb20669bf6ce 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -356,7 +356,8 @@ static size_t switchdev_obj_size(const struct switchdev_obj *obj) static int switchdev_port_obj_notify(enum switchdev_notifier_type nt, struct net_device *dev, const struct switchdev_obj *obj, - struct switchdev_trans *trans) + struct switchdev_trans *trans, + struct netlink_ext_ack *extack) { int rc; int err; @@ -379,7 +380,8 @@ static int switchdev_port_obj_notify(enum switchdev_notifier_type nt, } static int switchdev_port_obj_add_now(struct net_device *dev, - const struct switchdev_obj *obj) + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack) { struct switchdev_trans trans; int err; @@ -397,7 +399,7 @@ static int switchdev_port_obj_add_now(struct net_device *dev, trans.ph_prepare = true; err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, - dev, obj, &trans); + dev, obj, &trans, extack); if (err) { /* Prepare phase failed: abort the transaction. Any * resources reserved in the prepare phase are @@ -417,7 +419,7 @@ static int switchdev_port_obj_add_now(struct net_device *dev, trans.ph_prepare = false; err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, - dev, obj, &trans); + dev, obj, &trans, extack); WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); switchdev_trans_items_warn_destroy(dev, &trans); @@ -430,7 +432,7 @@ static void switchdev_port_obj_add_deferred(struct net_device *dev, const struct switchdev_obj *obj = data; int err; - err = switchdev_port_obj_add_now(dev, obj); + err = switchdev_port_obj_add_now(dev, obj, NULL); if (err && err != -EOPNOTSUPP) netdev_err(dev, "failed (err=%d) to add object (id=%d)\n", err, obj->id); @@ -460,12 +462,13 @@ static int switchdev_port_obj_add_defer(struct net_device *dev, * in case SWITCHDEV_F_DEFER flag is not set. */ int switchdev_port_obj_add(struct net_device *dev, - const struct switchdev_obj *obj) + const struct switchdev_obj *obj, + struct netlink_ext_ack *extack) { if (obj->flags & SWITCHDEV_F_DEFER) return switchdev_port_obj_add_defer(dev, obj); ASSERT_RTNL(); - return switchdev_port_obj_add_now(dev, obj); + return switchdev_port_obj_add_now(dev, obj, extack); } EXPORT_SYMBOL_GPL(switchdev_port_obj_add); @@ -473,7 +476,7 @@ static int switchdev_port_obj_del_now(struct net_device *dev, const struct switchdev_obj *obj) { return switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_DEL, - dev, obj, NULL); + dev, obj, NULL, NULL); } static void switchdev_port_obj_del_deferred(struct net_device *dev, -- cgit v1.2.3-71-gd317 From 479c86dc551c9720765ed19433990eae6a1f899f Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 12 Dec 2018 17:02:54 +0000 Subject: net: switchdev: Add extack to struct switchdev_notifier_info In order to pass extack to the drivers that need it, add an extack field to struct switchdev_notifier_info, and an extack argument to the function call_switchdev_blocking_notifiers(). Also add a helper function switchdev_notifier_info_to_extack(). Signed-off-by: Petr Machata Acked-by: Jiri Pirko Acked-by: Ivan Vecera Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 1 + include/net/switchdev.h | 13 +++++++++++-- net/switchdev/switchdev.c | 7 +++++-- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index b56ef684ecac..49d4b5854c62 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -364,6 +364,7 @@ static void vxlan_fdb_switchdev_notifier_info(const struct vxlan_dev *vxlan, struct switchdev_notifier_vxlan_fdb_info *fdb_info) { fdb_info->info.dev = vxlan->dev; + fdb_info->info.extack = NULL; fdb_info->remote_ip = rd->remote_ip; fdb_info->remote_port = rd->remote_port; fdb_info->remote_vni = rd->remote_vni; diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 69016305ad58..4facfa6775e8 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -149,6 +149,7 @@ enum switchdev_notifier_type { struct switchdev_notifier_info { struct net_device *dev; + struct netlink_ext_ack *extack; }; struct switchdev_notifier_fdb_info { @@ -172,6 +173,12 @@ switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info) return info->dev; } +static inline struct netlink_ext_ack * +switchdev_notifier_info_to_extack(const struct switchdev_notifier_info *info) +{ + return info->extack; +} + #ifdef CONFIG_NET_SWITCHDEV void switchdev_deferred_process(void); @@ -193,7 +200,8 @@ int call_switchdev_notifiers(unsigned long val, struct net_device *dev, int register_switchdev_blocking_notifier(struct notifier_block *nb); int unregister_switchdev_blocking_notifier(struct notifier_block *nb); int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, - struct switchdev_notifier_info *info); + struct switchdev_notifier_info *info, + struct netlink_ext_ack *extack); void switchdev_port_fwd_mark_set(struct net_device *dev, struct net_device *group_dev, @@ -278,7 +286,8 @@ unregister_switchdev_blocking_notifier(struct notifier_block *nb) static inline int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, - struct switchdev_notifier_info *info) + struct switchdev_notifier_info *info, + struct netlink_ext_ack *extack) { return NOTIFY_DONE; } diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index cb20669bf6ce..aa84acfb6632 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -368,7 +368,7 @@ static int switchdev_port_obj_notify(enum switchdev_notifier_type nt, .handled = false, }; - rc = call_switchdev_blocking_notifiers(nt, dev, &obj_info.info); + rc = call_switchdev_blocking_notifiers(nt, dev, &obj_info.info, extack); err = notifier_to_errno(rc); if (err) { WARN_ON(!obj_info.handled); @@ -559,6 +559,7 @@ int call_switchdev_notifiers(unsigned long val, struct net_device *dev, struct switchdev_notifier_info *info) { info->dev = dev; + info->extack = NULL; return atomic_notifier_call_chain(&switchdev_notif_chain, val, info); } EXPORT_SYMBOL_GPL(call_switchdev_notifiers); @@ -580,9 +581,11 @@ int unregister_switchdev_blocking_notifier(struct notifier_block *nb) EXPORT_SYMBOL_GPL(unregister_switchdev_blocking_notifier); int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, - struct switchdev_notifier_info *info) + struct switchdev_notifier_info *info, + struct netlink_ext_ack *extack) { info->dev = dev; + info->extack = extack; return blocking_notifier_call_chain(&switchdev_blocking_notif_chain, val, info); } -- cgit v1.2.3-71-gd317 From 6921351359395a6c6ac72cd275a8393f399cecc7 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 12 Dec 2018 17:02:56 +0000 Subject: net: switchdev: Add extack to switchdev_handle_port_obj_add() callback Drivers use switchdev_handle_port_obj_add() to handle recursive descent through lower devices. Change this function prototype to take add_cb that itself takes an extack argument. Decode extack from switchdev_notifier_port_obj_info and pass it to add_cb. Update mlxsw and ocelot drivers which use this helper. Signed-off-by: Petr Machata Acked-by: Jiri Pirko Acked-by: Ivan Vecera Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 3 ++- drivers/net/ethernet/mscc/ocelot.c | 3 ++- include/net/switchdev.h | 6 ++++-- net/switchdev/switchdev.c | 12 +++++++++--- 4 files changed, 17 insertions(+), 7 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 5ad1fcebf788..4b9292289256 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1777,7 +1777,8 @@ static void mlxsw_sp_span_respin_schedule(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_port_obj_add(struct net_device *dev, const struct switchdev_obj *obj, - struct switchdev_trans *trans) + struct switchdev_trans *trans, + struct netlink_ext_ack *extack) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); const struct switchdev_obj_port_vlan *vlan; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 7f8da8873a96..ea3eec263875 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1293,7 +1293,8 @@ static int ocelot_port_obj_del_mdb(struct net_device *dev, static int ocelot_port_obj_add(struct net_device *dev, const struct switchdev_obj *obj, - struct switchdev_trans *trans) + struct switchdev_trans *trans, + struct netlink_ext_ack *extack) { int ret = 0; diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 4facfa6775e8..a7fdab5ee6c3 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -215,7 +215,8 @@ int switchdev_handle_port_obj_add(struct net_device *dev, bool (*check_cb)(const struct net_device *dev), int (*add_cb)(struct net_device *dev, const struct switchdev_obj *obj, - struct switchdev_trans *trans)); + struct switchdev_trans *trans, + struct netlink_ext_ack *extack)); int switchdev_handle_port_obj_del(struct net_device *dev, struct switchdev_notifier_port_obj_info *port_obj_info, bool (*check_cb)(const struct net_device *dev), @@ -304,7 +305,8 @@ switchdev_handle_port_obj_add(struct net_device *dev, bool (*check_cb)(const struct net_device *dev), int (*add_cb)(struct net_device *dev, const struct switchdev_obj *obj, - struct switchdev_trans *trans)) + struct switchdev_trans *trans, + struct netlink_ext_ack *extack)) { return 0; } diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index aa84acfb6632..5df9d1138ac9 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -616,16 +616,21 @@ static int __switchdev_handle_port_obj_add(struct net_device *dev, bool (*check_cb)(const struct net_device *dev), int (*add_cb)(struct net_device *dev, const struct switchdev_obj *obj, - struct switchdev_trans *trans)) + struct switchdev_trans *trans, + struct netlink_ext_ack *extack)) { + struct netlink_ext_ack *extack; struct net_device *lower_dev; struct list_head *iter; int err = -EOPNOTSUPP; + extack = switchdev_notifier_info_to_extack(&port_obj_info->info); + if (check_cb(dev)) { /* This flag is only checked if the return value is success. */ port_obj_info->handled = true; - return add_cb(dev, port_obj_info->obj, port_obj_info->trans); + return add_cb(dev, port_obj_info->obj, port_obj_info->trans, + extack); } /* Switch ports might be stacked under e.g. a LAG. Ignore the @@ -650,7 +655,8 @@ int switchdev_handle_port_obj_add(struct net_device *dev, bool (*check_cb)(const struct net_device *dev), int (*add_cb)(struct net_device *dev, const struct switchdev_obj *obj, - struct switchdev_trans *trans)) + struct switchdev_trans *trans, + struct netlink_ext_ack *extack)) { int err; -- cgit v1.2.3-71-gd317 From 6685987c29582afc79b7fa3998dfbf36b4295791 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:56 +0000 Subject: switchdev: Add extack argument to call_switchdev_notifiers() A follow-up patch will enable vetoing of FDB entries. Make it possible to communicate details of why an FDB entry is not acceptable back to the user. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- Documentation/networking/switchdev.txt | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 6 ++++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 12 ++++++------ drivers/net/ethernet/rocker/rocker_main.c | 2 +- drivers/net/ethernet/rocker/rocker_ofdpa.c | 4 ++-- drivers/net/vxlan.c | 2 +- include/net/switchdev.h | 6 ++++-- net/bridge/br_switchdev.c | 2 +- net/dsa/slave.c | 2 +- net/switchdev/switchdev.c | 5 +++-- 10 files changed, 24 insertions(+), 19 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index 82236a17b5e6..f3244d87512a 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -196,7 +196,7 @@ The switch device will learn/forget source MAC address/VLAN on ingress packets and notify the switch driver of the mac/vlan/port tuples. The switch driver, in turn, will notify the bridge driver using the switchdev notifier call: - err = call_switchdev_notifiers(val, dev, info); + err = call_switchdev_notifiers(val, dev, info, extack); Where val is SWITCHDEV_FDB_ADD when learning and SWITCHDEV_FDB_DEL when forgetting, and info points to a struct switchdev_notifier_fdb_info. On diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 98e5ffd71b91..042341c7f6b9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -7294,7 +7294,8 @@ static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) info.addr = mac; info.vid = vid; - call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info); + call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info, + NULL); } static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops = { @@ -7381,7 +7382,8 @@ static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) info.addr = mac; info.vid = 0; - call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info); + call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info, + NULL); } static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 0abbaa0fbf14..71aad9d4e160 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -2443,7 +2443,7 @@ static void mlxsw_sp_fdb_vxlan_call_notifiers(struct net_device *dev, ether_addr_copy(info.eth_addr, mac); info.vni = vni; info.offloaded = adding; - call_switchdev_notifiers(type, dev, &info.info); + call_switchdev_notifiers(type, dev, &info.info, NULL); } static void mlxsw_sp_fdb_nve_call_notifiers(struct net_device *dev, @@ -2468,7 +2468,7 @@ mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type, info.addr = mac; info.vid = vid; info.offloaded = offloaded; - call_switchdev_notifiers(type, dev, &info.info); + call_switchdev_notifiers(type, dev, &info.info, NULL); } static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp, @@ -2819,7 +2819,7 @@ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp, return; vxlan_fdb_info.offloaded = true; call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev, - &vxlan_fdb_info.info); + &vxlan_fdb_info.info, NULL); mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, vxlan_fdb_info.eth_addr, fdb_info->vid, dev, true); @@ -2832,7 +2832,7 @@ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp, false); vxlan_fdb_info.offloaded = false; call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev, - &vxlan_fdb_info.info); + &vxlan_fdb_info.info, NULL); break; } } @@ -2977,7 +2977,7 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp, } vxlan_fdb_info->offloaded = true; call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev, - &vxlan_fdb_info->info); + &vxlan_fdb_info->info, NULL); mlxsw_sp_fid_put(fid); return; } @@ -2998,7 +2998,7 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp, goto err_fdb_tunnel_uc_op; vxlan_fdb_info->offloaded = true; call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev, - &vxlan_fdb_info->info); + &vxlan_fdb_info->info, NULL); mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, vxlan_fdb_info->eth_addr, vid, dev, true); diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 6213827e3956..62a205eba9f7 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2725,7 +2725,7 @@ rocker_fdb_offload_notify(struct rocker_port *rocker_port, info.vid = recv_info->vid; info.offloaded = true; call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, - rocker_port->dev, &info.info); + rocker_port->dev, &info.info, NULL); } static void rocker_switchdev_event_work(struct work_struct *work) diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c index 6473cc68c2d5..bea7895930f6 100644 --- a/drivers/net/ethernet/rocker/rocker_ofdpa.c +++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c @@ -1833,10 +1833,10 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work) rtnl_lock(); if (learned && removing) call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, - lw->ofdpa_port->dev, &info.info); + lw->ofdpa_port->dev, &info.info, NULL); else if (learned && !removing) call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, - lw->ofdpa_port->dev, &info.info); + lw->ofdpa_port->dev, &info.info, NULL); rtnl_unlock(); kfree(work); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a9e90159bb61..ef45c3c925be 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -393,7 +393,7 @@ static int vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan, : SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE; vxlan_fdb_switchdev_notifier_info(vxlan, fdb, rd, NULL, &info); ret = call_switchdev_notifiers(notifier_type, vxlan->dev, - &info.info); + &info.info, extack); return notifier_to_errno(ret); } diff --git a/include/net/switchdev.h b/include/net/switchdev.h index a7fdab5ee6c3..63843ae5dc81 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -195,7 +195,8 @@ int switchdev_port_obj_del(struct net_device *dev, int register_switchdev_notifier(struct notifier_block *nb); int unregister_switchdev_notifier(struct notifier_block *nb); int call_switchdev_notifiers(unsigned long val, struct net_device *dev, - struct switchdev_notifier_info *info); + struct switchdev_notifier_info *info, + struct netlink_ext_ack *extack); int register_switchdev_blocking_notifier(struct notifier_block *nb); int unregister_switchdev_blocking_notifier(struct notifier_block *nb); @@ -267,7 +268,8 @@ static inline int unregister_switchdev_notifier(struct notifier_block *nb) static inline int call_switchdev_notifiers(unsigned long val, struct net_device *dev, - struct switchdev_notifier_info *info) + struct switchdev_notifier_info *info, + struct netlink_ext_ack *extack) { return NOTIFY_DONE; } diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index 035ff59d9cbd..4d2b9eb7604a 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -113,7 +113,7 @@ br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac, info.added_by_user = added_by_user; info.offloaded = offloaded; notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE; - call_switchdev_notifiers(notifier_type, dev, &info.info); + call_switchdev_notifiers(notifier_type, dev, &info.info, NULL); } void diff --git a/net/dsa/slave.c b/net/dsa/slave.c index d5680a98a7f0..91de3a663226 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1451,7 +1451,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) } fdb_info->offloaded = true; call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, dev, - &fdb_info->info); + &fdb_info->info, NULL); break; case SWITCHDEV_FDB_DEL_TO_DEVICE: diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 5df9d1138ac9..cd78253de31d 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -556,10 +556,11 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier); * Call all network notifier blocks. */ int call_switchdev_notifiers(unsigned long val, struct net_device *dev, - struct switchdev_notifier_info *info) + struct switchdev_notifier_info *info, + struct netlink_ext_ack *extack) { info->dev = dev; - info->extack = NULL; + info->extack = extack; return atomic_notifier_call_chain(&switchdev_notif_chain, val, info); } EXPORT_SYMBOL_GPL(call_switchdev_notifiers); -- cgit v1.2.3-71-gd317 From bccb30254a4a02ee370dd23b2afbd25d7a78bc34 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:46 -0800 Subject: net: Get rid of SWITCHDEV_ATTR_ID_PORT_PARENT_ID Now that we have a dedicated NDO for getting a port's parent ID, get rid of SWITCHDEV_ATTR_ID_PORT_PARENT_ID and convert all callers to use the NDO exclusively. This is a preliminary change to getting rid of switchdev_ops eventually. Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- include/net/switchdev.h | 11 ----------- net/bridge/br_switchdev.c | 14 +++----------- net/core/net-sysfs.c | 19 ++++--------------- net/core/rtnetlink.c | 16 +++------------- net/ipv4/ipmr.c | 19 +++++-------------- net/switchdev/switchdev.c | 20 -------------------- 6 files changed, 15 insertions(+), 84 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 63843ae5dc81..5e87b54c5dc5 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -43,7 +43,6 @@ static inline bool switchdev_trans_ph_commit(struct switchdev_trans *trans) enum switchdev_attr_id { SWITCHDEV_ATTR_ID_UNDEFINED, - SWITCHDEV_ATTR_ID_PORT_PARENT_ID, SWITCHDEV_ATTR_ID_PORT_STP_STATE, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, @@ -61,7 +60,6 @@ struct switchdev_attr { void *complete_priv; void (*complete)(struct net_device *dev, int err, void *priv); union { - struct netdev_phys_item_id ppid; /* PORT_PARENT_ID */ u8 stp_state; /* PORT_STP_STATE */ unsigned long brport_flags; /* PORT_BRIDGE_FLAGS */ unsigned long brport_flags_support; /* PORT_BRIDGE_FLAGS_SUPPORT */ @@ -208,9 +206,6 @@ void switchdev_port_fwd_mark_set(struct net_device *dev, struct net_device *group_dev, bool joining); -bool switchdev_port_same_parent_id(struct net_device *a, - struct net_device *b); - int switchdev_handle_port_obj_add(struct net_device *dev, struct switchdev_notifier_port_obj_info *port_obj_info, bool (*check_cb)(const struct net_device *dev), @@ -295,12 +290,6 @@ call_switchdev_blocking_notifiers(unsigned long val, return NOTIFY_DONE; } -static inline bool switchdev_port_same_parent_id(struct net_device *a, - struct net_device *b) -{ - return false; -} - static inline int switchdev_handle_port_obj_add(struct net_device *dev, struct switchdev_notifier_port_obj_info *port_obj_info, diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index 06b0ae44585f..db9e8ab96d48 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -14,8 +14,7 @@ static int br_switchdev_mark_get(struct net_bridge *br, struct net_device *dev) /* dev is yet to be added to the port list. */ list_for_each_entry(p, &br->port_list, list) { - if (netdev_port_same_parent_id(dev, p->dev) || - switchdev_port_same_parent_id(dev, p->dev)) + if (netdev_port_same_parent_id(dev, p->dev)) return p->offload_fwd_mark; } @@ -24,19 +23,12 @@ static int br_switchdev_mark_get(struct net_bridge *br, struct net_device *dev) int nbp_switchdev_mark_set(struct net_bridge_port *p) { - const struct net_device_ops *ops = p->dev->netdev_ops; - struct switchdev_attr attr = { - .orig_dev = p->dev, - .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, - }; + struct netdev_phys_item_id ppid = { }; int err; ASSERT_RTNL(); - if (ops->ndo_get_port_parent_id) - err = dev_get_port_parent_id(p->dev, &attr.u.ppid, true); - else - err = switchdev_port_attr_get(p->dev, &attr); + err = dev_get_port_parent_id(p->dev, &ppid, true); if (err) { if (err == -EOPNOTSUPP) return 0; diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 4eace9f1dcf9..7c5061123ead 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -495,27 +494,17 @@ static ssize_t phys_switch_id_show(struct device *dev, struct device_attribute *attr, char *buf) { struct net_device *netdev = to_net_dev(dev); - const struct net_device_ops *ops = netdev->netdev_ops; ssize_t ret = -EINVAL; if (!rtnl_trylock()) return restart_syscall(); if (dev_isalive(netdev)) { - struct switchdev_attr attr = { - .orig_dev = netdev, - .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, - .flags = SWITCHDEV_F_NO_RECURSE, - }; - - if (ops->ndo_get_port_parent_id) - ret = dev_get_port_parent_id(netdev, &attr.u.ppid, - false); - else - ret = switchdev_port_attr_get(netdev, &attr); + struct netdev_phys_item_id ppid = { }; + + ret = dev_get_port_parent_id(netdev, &ppid, false); if (!ret) - ret = sprintf(buf, "%*phN\n", attr.u.ppid.id_len, - attr.u.ppid.id); + ret = sprintf(buf, "%*phN\n", ppid.id_len, ppid.id); } rtnl_unlock(); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 90dd02c1f561..a51cab95ba64 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include @@ -1146,26 +1145,17 @@ static int rtnl_phys_port_name_fill(struct sk_buff *skb, struct net_device *dev) static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev) { - const struct net_device_ops *ops = dev->netdev_ops; + struct netdev_phys_item_id ppid = { }; int err; - struct switchdev_attr attr = { - .orig_dev = dev, - .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, - .flags = SWITCHDEV_F_NO_RECURSE, - }; - if (ops->ndo_get_port_parent_id) - err = dev_get_port_parent_id(dev, &attr.u.ppid, false); - else - err = switchdev_port_attr_get(dev, &attr); + err = dev_get_port_parent_id(dev, &ppid, false); if (err) { if (err == -EOPNOTSUPP) return 0; return err; } - if (nla_put(skb, IFLA_PHYS_SWITCH_ID, attr.u.ppid.id_len, - attr.u.ppid.id)) + if (nla_put(skb, IFLA_PHYS_SWITCH_ID, ppid.id_len, ppid.id)) return -EMSGSIZE; return 0; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index c71bcc42d66d..e536970557dd 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -67,7 +67,6 @@ #include #include #include -#include #include @@ -837,11 +836,8 @@ static void ipmr_update_thresholds(struct mr_table *mrt, struct mr_mfc *cache, static int vif_add(struct net *net, struct mr_table *mrt, struct vifctl *vifc, int mrtsock) { - const struct net_device_ops *ops; + struct netdev_phys_item_id ppid = { }; int vifi = vifc->vifc_vifi; - struct switchdev_attr attr = { - .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, - }; struct vif_device *v = &mrt->vif_table[vifi]; struct net_device *dev; struct in_device *in_dev; @@ -920,15 +916,10 @@ static int vif_add(struct net *net, struct mr_table *mrt, vifc->vifc_flags | (!mrtsock ? VIFF_STATIC : 0), (VIFF_TUNNEL | VIFF_REGISTER)); - attr.orig_dev = dev; - ops = dev->netdev_ops; - if (ops->ndo_get_port_parent_id && - !dev_get_port_parent_id(dev, &attr.u.ppid, true)) { - memcpy(v->dev_parent_id.id, attr.u.ppid.id, attr.u.ppid.id_len); - v->dev_parent_id.id_len = attr.u.ppid.id_len; - } else if (!switchdev_port_attr_get(dev, &attr)) { - memcpy(v->dev_parent_id.id, attr.u.ppid.id, attr.u.ppid.id_len); - v->dev_parent_id.id_len = attr.u.ppid.id_len; + err = dev_get_port_parent_id(dev, &ppid, true); + if (err == 0) { + memcpy(v->dev_parent_id.id, ppid.id, ppid.id_len); + v->dev_parent_id.id_len = ppid.id_len; } else { v->dev_parent_id.id_len = 0; } diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index cd78253de31d..7e1357db33d7 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -592,26 +592,6 @@ int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, } EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers); -bool switchdev_port_same_parent_id(struct net_device *a, - struct net_device *b) -{ - struct switchdev_attr a_attr = { - .orig_dev = a, - .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, - }; - struct switchdev_attr b_attr = { - .orig_dev = b, - .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, - }; - - if (switchdev_port_attr_get(a, &a_attr) || - switchdev_port_attr_get(b, &b_attr)) - return false; - - return netdev_phys_item_id_same(&a_attr.u.ppid, &b_attr.u.ppid); -} -EXPORT_SYMBOL_GPL(switchdev_port_same_parent_id); - static int __switchdev_handle_port_obj_add(struct net_device *dev, struct switchdev_notifier_port_obj_info *port_obj_info, bool (*check_cb)(const struct net_device *dev), -- cgit v1.2.3-71-gd317 From 746dc184ba59aa2c843b9e888be3f1302d227b74 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Feb 2019 16:58:19 -0800 Subject: net: switchdev: Add PORT_PRE_BRIDGE_FLAGS In preparation for removing switchdev_port_attr_get(), introduce PORT_PRE_BRIDGE_FLAGS which will be called through switchdev_port_attr_set(), in the caller's context (possibly atomic) and which must be checked by the switchdev driver in order to return whether the operation is supported or not. This is entirely analoguous to how the BRIDGE_FLAGS_SUPPORT works, except it goes through a set() instead of get(). Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- include/net/switchdev.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 5e87b54c5dc5..de72b0a3867f 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -46,6 +46,7 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_PORT_STP_STATE, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, + SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_MROUTER, SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, @@ -61,7 +62,7 @@ struct switchdev_attr { void (*complete)(struct net_device *dev, int err, void *priv); union { u8 stp_state; /* PORT_STP_STATE */ - unsigned long brport_flags; /* PORT_BRIDGE_FLAGS */ + unsigned long brport_flags; /* PORT_{PRE}_BRIDGE_FLAGS */ unsigned long brport_flags_support; /* PORT_BRIDGE_FLAGS_SUPPORT */ bool mrouter; /* PORT_MROUTER */ clock_t ageing_time; /* BRIDGE_AGEING_TIME */ -- cgit v1.2.3-71-gd317 From cc0c207a5d18333fbfecc964a47ddb182fbcb720 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Feb 2019 16:58:25 -0800 Subject: net: Remove SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT Now that we have converted the bridge code and the drivers to check for bridge port(s) flags at the time we try to set them, there is no need for a get() -> set() sequence anymore and SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT therefore becomes unused. Reviewed-by: Ido Schimmel Signed-off-by: Florian Fainelli Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- Documentation/networking/switchdev.txt | 6 ++---- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 11 +---------- drivers/net/ethernet/rocker/rocker_main.c | 14 +------------- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 10 +--------- include/net/switchdev.h | 2 -- net/dsa/slave.c | 16 +--------------- 6 files changed, 6 insertions(+), 53 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index f3244d87512a..79c8b0f16aee 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -232,10 +232,8 @@ Learning_sync attribute enables syncing of the learned/forgotten FDB entry to the bridge's FDB. It's possible, but not optimal, to enable learning on the device port and on the bridge port, and disable learning_sync. -To support learning and learning_sync port attributes, the driver implements -switchdev op switchdev_port_attr_get/set for -SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS. The driver should initialize the attributes -to the hardware defaults. +To support learning, the driver implements switchdev op +switchdev_port_attr_get/set for SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS. FDB Ageing ^^^^^^^^^^ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 9a8798f74d2b..bbb5a406232e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -434,16 +434,7 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan) static int mlxsw_sp_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD | - BR_MCAST_FLOOD; - break; - default: - return -EOPNOTSUPP; - } - - return 0; + return -EOPNOTSUPP; } static int diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 25129f7b5583..6b8273e2057d 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2069,19 +2069,7 @@ static const struct net_device_ops rocker_port_netdev_ops = { static int rocker_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { - const struct rocker_port *rocker_port = netdev_priv(dev); - int err = 0; - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - err = rocker_world_port_attr_bridge_flags_support_get(rocker_port, - &attr->u.brport_flags_support); - break; - default: - return -EOPNOTSUPP; - } - - return err; + return -EOPNOTSUPP; } static int rocker_port_attr_set(struct net_device *dev, diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 331625137717..de4dcabbc29a 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -643,15 +643,7 @@ static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev) static int swdev_port_attr_get(struct net_device *netdev, struct switchdev_attr *attr) { - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD; - break; - default: - return -EOPNOTSUPP; - } - - return 0; + return -EOPNOTSUPP; } static int port_attr_stp_state_set(struct net_device *netdev, diff --git a/include/net/switchdev.h b/include/net/switchdev.h index de72b0a3867f..0f352019ef99 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -45,7 +45,6 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_UNDEFINED, SWITCHDEV_ATTR_ID_PORT_STP_STATE, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, - SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_MROUTER, SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, @@ -63,7 +62,6 @@ struct switchdev_attr { union { u8 stp_state; /* PORT_STP_STATE */ unsigned long brport_flags; /* PORT_{PRE}_BRIDGE_FLAGS */ - unsigned long brport_flags_support; /* PORT_BRIDGE_FLAGS_SUPPORT */ bool mrouter; /* PORT_MROUTER */ clock_t ageing_time; /* BRIDGE_AGEING_TIME */ bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */ diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 44cc4e50dd5a..db0a2651070f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -388,21 +388,7 @@ static int dsa_slave_get_port_parent_id(struct net_device *dev, static int dsa_slave_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { - struct dsa_port *dp = dsa_slave_to_port(dev); - struct dsa_switch *ds = dp->ds; - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - attr->u.brport_flags_support = 0; - if (ds->ops->port_egress_floods) - attr->u.brport_flags_support |= BR_FLOOD | - BR_MCAST_FLOOD; - break; - default: - return -EOPNOTSUPP; - } - - return 0; + return -EOPNOTSUPP; } static inline netdev_tx_t dsa_slave_netpoll_send_skb(struct net_device *dev, -- cgit v1.2.3-71-gd317 From 010c8f01aa7fe18ea97d302e1c7e9ca83bc27433 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Feb 2019 16:58:26 -0800 Subject: net: Get rid of switchdev_port_attr_get() With the bridge no longer calling switchdev_port_attr_get() to obtain the supported bridge port flags from a driver but instead trying to set the bridge port flags directly and relying on driver to reject unsupported configurations, we can effectively get rid of switchdev_port_attr_get() entirely since this was the only place where it was called. Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- Documentation/networking/switchdev.txt | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 7 ------- drivers/net/ethernet/rocker/rocker_main.c | 7 ------- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 7 ------- include/net/switchdev.h | 8 -------- net/dsa/slave.c | 7 ------- 6 files changed, 1 insertion(+), 37 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index 79c8b0f16aee..413abbae952f 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -233,7 +233,7 @@ the bridge's FDB. It's possible, but not optimal, to enable learning on the device port and on the bridge port, and disable learning_sync. To support learning, the driver implements switchdev op -switchdev_port_attr_get/set for SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS. +switchdev_port_attr_set for SWITCHDEV_ATTR_PORT_ID_{PRE}_BRIDGE_FLAGS. FDB Ageing ^^^^^^^^^^ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index bbb5a406232e..766f5b5f1cf5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -431,12 +431,6 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan) mlxsw_sp_bridge_vlan_destroy(bridge_vlan); } -static int mlxsw_sp_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static int mlxsw_sp_port_bridge_vlan_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_bridge_vlan *bridge_vlan, @@ -1945,7 +1939,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, } static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { - .switchdev_port_attr_get = mlxsw_sp_port_attr_get, .switchdev_port_attr_set = mlxsw_sp_port_attr_set, }; diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 6b8273e2057d..8200fbf91306 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2066,12 +2066,6 @@ static const struct net_device_ops rocker_port_netdev_ops = { * swdev interface ********************/ -static int rocker_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static int rocker_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr, struct switchdev_trans *trans) @@ -2148,7 +2142,6 @@ static int rocker_port_obj_del(struct net_device *dev, } static const struct switchdev_ops rocker_port_switchdev_ops = { - .switchdev_port_attr_get = rocker_port_attr_get, .switchdev_port_attr_set = rocker_port_attr_set, }; diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index de4dcabbc29a..018399ee8731 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -640,12 +640,6 @@ static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev) fsl_mc_free_irqs(sw_dev); } -static int swdev_port_attr_get(struct net_device *netdev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static int port_attr_stp_state_set(struct net_device *netdev, struct switchdev_trans *trans, u8 state) @@ -932,7 +926,6 @@ static int swdev_port_obj_del(struct net_device *netdev, } static const struct switchdev_ops ethsw_port_switchdev_ops = { - .switchdev_port_attr_get = swdev_port_attr_get, .switchdev_port_attr_set = swdev_port_attr_set, }; diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 0f352019ef99..45310ddf2d7e 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -179,8 +179,6 @@ switchdev_notifier_info_to_extack(const struct switchdev_notifier_info *info) #ifdef CONFIG_NET_SWITCHDEV void switchdev_deferred_process(void); -int switchdev_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr); int switchdev_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr); int switchdev_port_obj_add(struct net_device *dev, @@ -225,12 +223,6 @@ static inline void switchdev_deferred_process(void) { } -static inline int switchdev_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static inline int switchdev_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr) { diff --git a/net/dsa/slave.c b/net/dsa/slave.c index db0a2651070f..a78b2bba0332 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -385,12 +385,6 @@ static int dsa_slave_get_port_parent_id(struct net_device *dev, return 0; } -static int dsa_slave_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static inline netdev_tx_t dsa_slave_netpoll_send_skb(struct net_device *dev, struct sk_buff *skb) { @@ -1057,7 +1051,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = { }; static const struct switchdev_ops dsa_slave_switchdev_ops = { - .switchdev_port_attr_get = dsa_slave_port_attr_get, .switchdev_port_attr_set = dsa_slave_port_attr_set, }; -- cgit v1.2.3-71-gd317 From 72636db5ba7bb0520bf39ea56dc87c90580ec6fd Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sun, 24 Feb 2019 18:39:02 -0800 Subject: switchdev: Complete removal of switchdev_port_attr_get() We have no more in tree users of switchdev_port_attr_get() after d0e698d57a94 ("Merge branch 'net-Get-rid-of-switchdev_port_attr_get'") so completely remove the function signature and body. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- include/net/switchdev.h | 4 ---- net/switchdev/switchdev.c | 42 ------------------------------------------ 2 files changed, 46 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 45310ddf2d7e..be4b13e66668 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -115,13 +115,9 @@ typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj); /** * struct switchdev_ops - switchdev operations * - * @switchdev_port_attr_get: Get a port attribute (see switchdev_attr). - * * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr). */ struct switchdev_ops { - int (*switchdev_port_attr_get)(struct net_device *dev, - struct switchdev_attr *attr); int (*switchdev_port_attr_set)(struct net_device *dev, const struct switchdev_attr *attr, struct switchdev_trans *trans); diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 7e1357db33d7..362413c9b389 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -174,48 +174,6 @@ static int switchdev_deferred_enqueue(struct net_device *dev, return 0; } -/** - * switchdev_port_attr_get - Get port attribute - * - * @dev: port device - * @attr: attribute to get - */ -int switchdev_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) -{ - const struct switchdev_ops *ops = dev->switchdev_ops; - struct net_device *lower_dev; - struct list_head *iter; - struct switchdev_attr first = { - .id = SWITCHDEV_ATTR_ID_UNDEFINED - }; - int err = -EOPNOTSUPP; - - if (ops && ops->switchdev_port_attr_get) - return ops->switchdev_port_attr_get(dev, attr); - - if (attr->flags & SWITCHDEV_F_NO_RECURSE) - return err; - - /* Switch device port(s) may be stacked under - * bond/team/vlan dev, so recurse down to get attr on - * each port. Return -ENODATA if attr values don't - * compare across ports. - */ - - netdev_for_each_lower_dev(dev, lower_dev, iter) { - err = switchdev_port_attr_get(lower_dev, attr); - if (err) - break; - if (first.id == SWITCHDEV_ATTR_ID_UNDEFINED) - first = *attr; - else if (memcmp(&first, attr, sizeof(*attr))) - return -ENODATA; - } - - return err; -} -EXPORT_SYMBOL_GPL(switchdev_port_attr_get); - static int __switchdev_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr, struct switchdev_trans *trans) -- cgit v1.2.3-71-gd317 From 1cb33af1f75099282a51c4cc0bcc0ad413730079 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Feb 2019 11:44:25 -0800 Subject: 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 Reviewed-by: Ido Schimmel Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- include/net/switchdev.h | 27 +++++++++++++++++++++++++ net/switchdev/switchdev.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) (limited to 'include/net/switchdev.h') diff --git a/include/net/switchdev.h b/include/net/switchdev.h index be4b13e66668..5087c06ceb4b 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -132,6 +132,7 @@ enum switchdev_notifier_type { SWITCHDEV_PORT_OBJ_ADD, /* Blocking. */ SWITCHDEV_PORT_OBJ_DEL, /* Blocking. */ + SWITCHDEV_PORT_ATTR_SET, /* May be blocking . */ SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE, SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE, @@ -160,6 +161,13 @@ struct switchdev_notifier_port_obj_info { bool handled; }; +struct switchdev_notifier_port_attr_info { + struct switchdev_notifier_info info; /* must be first */ + const struct switchdev_attr *attr; + struct switchdev_trans *trans; + bool handled; +}; + static inline struct net_device * switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info) { @@ -212,7 +220,15 @@ int switchdev_handle_port_obj_del(struct net_device *dev, int (*del_cb)(struct net_device *dev, const struct switchdev_obj *obj)); +int switchdev_handle_port_attr_set(struct net_device *dev, + struct switchdev_notifier_port_attr_info *port_attr_info, + bool (*check_cb)(const struct net_device *dev), + int (*set_cb)(struct net_device *dev, + const struct switchdev_attr *attr, + struct switchdev_trans *trans)); + #define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops)) + #else static inline void switchdev_deferred_process(void) @@ -299,6 +315,17 @@ switchdev_handle_port_obj_del(struct net_device *dev, return 0; } +static inline int +switchdev_handle_port_attr_set(struct net_device *dev, + struct switchdev_notifier_port_attr_info *port_attr_info, + bool (*check_cb)(const struct net_device *dev), + int (*set_cb)(struct net_device *dev, + const struct switchdev_attr *attr, + struct switchdev_trans *trans)) +{ + return 0; +} + #define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0) #endif 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, return err; } EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_del); + +static int __switchdev_handle_port_attr_set(struct net_device *dev, + struct switchdev_notifier_port_attr_info *port_attr_info, + bool (*check_cb)(const struct net_device *dev), + int (*set_cb)(struct net_device *dev, + const struct switchdev_attr *attr, + struct switchdev_trans *trans)) +{ + struct net_device *lower_dev; + struct list_head *iter; + int err = -EOPNOTSUPP; + + if (check_cb(dev)) { + port_attr_info->handled = true; + return set_cb(dev, port_attr_info->attr, + port_attr_info->trans); + } + + /* Switch ports might be stacked under e.g. a LAG. Ignore the + * unsupported devices, another driver might be able to handle them. But + * propagate to the callers any hard errors. + * + * If the driver does its own bookkeeping of stacked ports, it's not + * necessary to go through this helper. + */ + netdev_for_each_lower_dev(dev, lower_dev, iter) { + err = __switchdev_handle_port_attr_set(lower_dev, port_attr_info, + check_cb, set_cb); + if (err && err != -EOPNOTSUPP) + return err; + } + + return err; +} + +int switchdev_handle_port_attr_set(struct net_device *dev, + struct switchdev_notifier_port_attr_info *port_attr_info, + bool (*check_cb)(const struct net_device *dev), + int (*set_cb)(struct net_device *dev, + const struct switchdev_attr *attr, + struct switchdev_trans *trans)) +{ + int err; + + err = __switchdev_handle_port_attr_set(dev, port_attr_info, check_cb, + set_cb); + if (err == -EOPNOTSUPP) + err = 0; + return err; +} +EXPORT_SYMBOL_GPL(switchdev_handle_port_attr_set); -- cgit v1.2.3-71-gd317 From 3d705f07d16b1d872c556b4ebf44deabeca0e9c1 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Feb 2019 11:44:32 -0800 Subject: net: Remove switchdev_ops Now that we have converted all possible callers to using a switchdev notifier for attributes we do not have a need for implementing switchdev_ops anymore, and this can be removed from all drivers the net_device structure. Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 3 --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 -- .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 12 ------------ drivers/net/ethernet/mscc/ocelot.c | 5 ----- drivers/net/ethernet/rocker/rocker_main.c | 5 ----- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 5 ----- include/linux/netdevice.h | 3 --- include/net/switchdev.h | 17 ----------------- net/dsa/slave.c | 5 ----- 9 files changed, 57 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index b00f6f74f91a..6c797e322be8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3660,7 +3660,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, } mlxsw_sp_port->default_vlan = mlxsw_sp_port_vlan; - mlxsw_sp_port_switchdev_init(mlxsw_sp_port); mlxsw_sp->ports[local_port] = mlxsw_sp_port; err = register_netdev(dev); if (err) { @@ -3677,7 +3676,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, err_register_netdev: mlxsw_sp->ports[local_port] = NULL; - mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan); err_port_vlan_create: err_port_pvid_set: @@ -3720,7 +3718,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp); unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ mlxsw_sp->ports[local_port] = NULL; - mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); mlxsw_sp_port_vlan_flush(mlxsw_sp_port, true); mlxsw_sp_port_nve_fini(mlxsw_sp_port); mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index a61c1130d9e3..da6278b0caa4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -407,8 +407,6 @@ extern const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals; /* spectrum_switchdev.c */ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp); -void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port); -void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port); int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid, bool adding); void diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index c1aedfea3a31..f6ce386c3036 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1938,10 +1938,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, return NULL; } -static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { - .switchdev_port_attr_set = mlxsw_sp_port_attr_set, -}; - static int mlxsw_sp_bridge_8021q_port_join(struct mlxsw_sp_bridge_device *bridge_device, struct mlxsw_sp_bridge_port *bridge_port, @@ -3545,11 +3541,3 @@ void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp) kfree(mlxsw_sp->bridge); } -void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port) -{ - mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops; -} - -void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port) -{ -} diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 83a678b11757..a1d0d6e42533 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1324,10 +1324,6 @@ static int ocelot_port_obj_del(struct net_device *dev, return ret; } -static const struct switchdev_ops ocelot_port_switchdev_ops = { - .switchdev_port_attr_set = ocelot_port_attr_set, -}; - static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port, struct net_device *bridge) { @@ -1660,7 +1656,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port, dev->netdev_ops = &ocelot_port_netdev_ops; dev->ethtool_ops = &ocelot_ethtool_ops; - dev->switchdev_ops = &ocelot_port_switchdev_ops; dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXFCS; dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index fc772cf079cc..c883aa89b7ca 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2142,10 +2142,6 @@ static int rocker_port_obj_del(struct net_device *dev, return err; } -static const struct switchdev_ops rocker_port_switchdev_ops = { - .switchdev_port_attr_set = rocker_port_attr_set, -}; - struct rocker_fib_event_work { struct work_struct work; union { @@ -2599,7 +2595,6 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) rocker_port_dev_addr_init(rocker_port); dev->netdev_ops = &rocker_port_netdev_ops; dev->ethtool_ops = &rocker_port_ethtool_ops; - dev->switchdev_ops = &rocker_port_switchdev_ops; netif_tx_napi_add(dev, &rocker_port->napi_tx, rocker_port_poll_tx, NAPI_POLL_WEIGHT); netif_napi_add(dev, &rocker_port->napi_rx, rocker_port_poll_rx, diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index b0d2d9bf2532..ad577beeb052 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -925,10 +925,6 @@ static int swdev_port_obj_del(struct net_device *netdev, return err; } -static const struct switchdev_ops ethsw_port_switchdev_ops = { - .switchdev_port_attr_set = swdev_port_attr_set, -}; - static int ethsw_switchdev_port_attr_set_event(struct net_device *netdev, struct switchdev_notifier_port_attr_info *port_attr_info) @@ -1455,7 +1451,6 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx) SET_NETDEV_DEV(port_netdev, dev); port_netdev->netdev_ops = ðsw_port_ops; port_netdev->ethtool_ops = ðsw_port_ethtool_ops; - port_netdev->switchdev_ops = ðsw_port_switchdev_ops; /* Set MTU limits */ port_netdev->min_mtu = ETH_MIN_MTU; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 58e83bd7a861..c10b60297d28 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1843,9 +1843,6 @@ struct net_device { #endif const struct net_device_ops *netdev_ops; const struct ethtool_ops *ethtool_ops; -#ifdef CONFIG_NET_SWITCHDEV - const struct switchdev_ops *switchdev_ops; -#endif #ifdef CONFIG_NET_L3_MASTER_DEV const struct l3mdev_ops *l3mdev_ops; #endif diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 5087c06ceb4b..e4f751e19ecf 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -112,17 +112,6 @@ void *switchdev_trans_item_dequeue(struct switchdev_trans *trans); typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj); -/** - * struct switchdev_ops - switchdev operations - * - * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr). - */ -struct switchdev_ops { - int (*switchdev_port_attr_set)(struct net_device *dev, - const struct switchdev_attr *attr, - struct switchdev_trans *trans); -}; - enum switchdev_notifier_type { SWITCHDEV_FDB_ADD_TO_BRIDGE = 1, SWITCHDEV_FDB_DEL_TO_BRIDGE, @@ -226,9 +215,6 @@ int switchdev_handle_port_attr_set(struct net_device *dev, int (*set_cb)(struct net_device *dev, const struct switchdev_attr *attr, struct switchdev_trans *trans)); - -#define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops)) - #else static inline void switchdev_deferred_process(void) @@ -325,9 +311,6 @@ switchdev_handle_port_attr_set(struct net_device *dev, { return 0; } - -#define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0) - #endif #endif /* _LINUX_SWITCHDEV_H_ */ diff --git a/net/dsa/slave.c b/net/dsa/slave.c index b089b43120e1..1808a2cd6872 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1118,10 +1118,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = { .ndo_vlan_rx_kill_vid = dsa_slave_vlan_rx_kill_vid, }; -static const struct switchdev_ops dsa_slave_switchdev_ops = { - .switchdev_port_attr_set = dsa_slave_port_attr_set, -}; - static struct device_type dsa_type = { .name = "dsa", }; @@ -1382,7 +1378,6 @@ int dsa_slave_create(struct dsa_port *port) eth_hw_addr_inherit(slave_dev, master); slave_dev->priv_flags |= IFF_NO_QUEUE; slave_dev->netdev_ops = &dsa_slave_netdev_ops; - slave_dev->switchdev_ops = &dsa_slave_switchdev_ops; slave_dev->min_mtu = 0; slave_dev->max_mtu = ETH_MAX_MTU; SET_NETDEV_DEVTYPE(slave_dev, &dsa_type); -- cgit v1.2.3-71-gd317 From 91cf8eceffc131d41f098351e1b290bdaab45ea7 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Feb 2019 16:29:16 -0800 Subject: switchdev: Remove unused transaction item queue There are no more in tree users of the switchdev_trans_item_{dequeue,enqueue} or switchdev_trans_item structure in the kernel since commit 00fc0c51e35b ("rocker: Change world_ops API and implementation to be switchdev independant"). Remove this unused code and update the documentation accordingly since. Signed-off-by: Florian Fainelli Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- Documentation/networking/switchdev.txt | 19 ------- include/net/switchdev.h | 12 ---- net/switchdev/switchdev.c | 100 +-------------------------------- 3 files changed, 2 insertions(+), 129 deletions(-) (limited to 'include/net/switchdev.h') diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index 633dd1fd81b7..86174ce8cd13 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -371,22 +371,3 @@ The driver can monitor for updates to arp_tbl using the netevent notifier NETEVENT_NEIGH_UPDATE. The device can be programmed with resolved nexthops for the routes as arp_tbl updates. The driver implements ndo_neigh_destroy to know when arp_tbl neighbor entries are purged from the port. - -Transaction item queue -^^^^^^^^^^^^^^^^^^^^^^ - -For switchdev ops attr_set and obj_add, there is a 2 phase transaction model -used. First phase is to "prepare" anything needed, including various checks, -memory allocation, etc. The goal is to handle the stuff that is not unlikely -to fail here. The second phase is to "commit" the actual changes. - -Switchdev provides an infrastructure for sharing items (for example memory -allocations) between the two phases. - -The object created by a driver in "prepare" phase and it is queued up by: -switchdev_trans_item_enqueue() -During the "commit" phase, the driver gets the object by: -switchdev_trans_item_dequeue() - -If a transaction is aborted during "prepare" phase, switchdev code will handle -cleanup of the queued-up objects. diff --git a/include/net/switchdev.h b/include/net/switchdev.h index e4f751e19ecf..0ebd67ae7012 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -20,14 +20,7 @@ #define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1) #define SWITCHDEV_F_DEFER BIT(2) -struct switchdev_trans_item { - struct list_head list; - void *data; - void (*destructor)(const void *data); -}; - struct switchdev_trans { - struct list_head item_list; bool ph_prepare; }; @@ -105,11 +98,6 @@ struct switchdev_obj_port_mdb { #define SWITCHDEV_OBJ_PORT_MDB(OBJ) \ container_of((OBJ), struct switchdev_obj_port_mdb, obj) -void switchdev_trans_item_enqueue(struct switchdev_trans *trans, - void *data, void (*destructor)(void const *), - struct switchdev_trans_item *tritem); -void *switchdev_trans_item_dequeue(struct switchdev_trans *trans); - typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj); enum switchdev_notifier_type { diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index d81cfcee9ad9..90ba4a1f0a6d 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -23,78 +23,6 @@ #include #include -/** - * switchdev_trans_item_enqueue - Enqueue data item to transaction queue - * - * @trans: transaction - * @data: pointer to data being queued - * @destructor: data destructor - * @tritem: transaction item being queued - * - * Enqeueue data item to transaction queue. tritem is typically placed in - * cointainter pointed at by data pointer. Destructor is called on - * transaction abort and after successful commit phase in case - * the caller did not dequeue the item before. - */ -void switchdev_trans_item_enqueue(struct switchdev_trans *trans, - void *data, void (*destructor)(void const *), - struct switchdev_trans_item *tritem) -{ - tritem->data = data; - tritem->destructor = destructor; - list_add_tail(&tritem->list, &trans->item_list); -} -EXPORT_SYMBOL_GPL(switchdev_trans_item_enqueue); - -static struct switchdev_trans_item * -__switchdev_trans_item_dequeue(struct switchdev_trans *trans) -{ - struct switchdev_trans_item *tritem; - - if (list_empty(&trans->item_list)) - return NULL; - tritem = list_first_entry(&trans->item_list, - struct switchdev_trans_item, list); - list_del(&tritem->list); - return tritem; -} - -/** - * switchdev_trans_item_dequeue - Dequeue data item from transaction queue - * - * @trans: transaction - */ -void *switchdev_trans_item_dequeue(struct switchdev_trans *trans) -{ - struct switchdev_trans_item *tritem; - - tritem = __switchdev_trans_item_dequeue(trans); - BUG_ON(!tritem); - return tritem->data; -} -EXPORT_SYMBOL_GPL(switchdev_trans_item_dequeue); - -static void switchdev_trans_init(struct switchdev_trans *trans) -{ - INIT_LIST_HEAD(&trans->item_list); -} - -static void switchdev_trans_items_destroy(struct switchdev_trans *trans) -{ - struct switchdev_trans_item *tritem; - - while ((tritem = __switchdev_trans_item_dequeue(trans))) - tritem->destructor(tritem->data); -} - -static void switchdev_trans_items_warn_destroy(struct net_device *dev, - struct switchdev_trans *trans) -{ - WARN(!list_empty(&trans->item_list), "%s: transaction item queue is not empty.\n", - dev->name); - switchdev_trans_items_destroy(trans); -} - static LIST_HEAD(deferred); static DEFINE_SPINLOCK(deferred_lock); @@ -208,8 +136,6 @@ static int switchdev_port_attr_set_now(struct net_device *dev, struct switchdev_trans trans; int err; - switchdev_trans_init(&trans); - /* Phase I: prepare for attr set. Driver/device should fail * here if there are going to be issues in the commit phase, * such as lack of resources or support. The driver/device @@ -220,17 +146,8 @@ static int switchdev_port_attr_set_now(struct net_device *dev, trans.ph_prepare = true; err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr, &trans); - if (err) { - /* Prepare phase failed: abort the transaction. Any - * resources reserved in the prepare phase are - * released. - */ - - if (err != -EOPNOTSUPP) - switchdev_trans_items_destroy(&trans); - + if (err) return err; - } /* Phase II: commit attr set. This cannot fail as a fault * of driver/device. If it does, it's a bug in the driver/device @@ -242,7 +159,6 @@ static int switchdev_port_attr_set_now(struct net_device *dev, &trans); WARN(err, "%s: Commit of attribute (id=%d) failed.\n", dev->name, attr->id); - switchdev_trans_items_warn_destroy(dev, &trans); return err; } @@ -341,8 +257,6 @@ static int switchdev_port_obj_add_now(struct net_device *dev, ASSERT_RTNL(); - switchdev_trans_init(&trans); - /* Phase I: prepare for obj add. Driver/device should fail * here if there are going to be issues in the commit phase, * such as lack of resources or support. The driver/device @@ -353,17 +267,8 @@ static int switchdev_port_obj_add_now(struct net_device *dev, trans.ph_prepare = true; err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, dev, obj, &trans, extack); - if (err) { - /* Prepare phase failed: abort the transaction. Any - * resources reserved in the prepare phase are - * released. - */ - - if (err != -EOPNOTSUPP) - switchdev_trans_items_destroy(&trans); - + if (err) return err; - } /* Phase II: commit obj add. This cannot fail as a fault * of driver/device. If it does, it's a bug in the driver/device @@ -374,7 +279,6 @@ static int switchdev_port_obj_add_now(struct net_device *dev, err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, dev, obj, &trans, extack); WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); - switchdev_trans_items_warn_destroy(dev, &trans); return err; } -- cgit v1.2.3-71-gd317