Hi all,
This patch series finishes by the removal of switchdev_ops. To get there
we convert the existing switchdev_port_attr_{set,get} switchdev_ops to
use a blocking notifier, thus making it consistent with how the objects
are pushed to the switchdev enabled devices.
Please review and let me know what you think!
David, I would like to get Ido's feedback on this to make sure I did not
miss something, thank you!
Changes in v4:
- removed double space in Documentation/networking/switchdev.txt
- added Jiri's Acked-by tags
- added fall through annotations where appropriate
Changes in v3:
- dropped patches removing te need to get the attribute since we
still need that in order to support different sleeping vs.
non-sleeping contexts
Changes in v2:
- fixed bisectability issues in patch #15
- added Acked-by from Jiri where necessary
- fixed a few minor issues according to Jiri's feedback:
- rename port_attr_event -> port_attr_set_event
- moved SWITCHDEV_PORT_ATTR_SET closer to other blocking events
Florian Fainelli (9):
Documentation: networking: switchdev: Update port parent ID section
switchdev: Add SWITCHDEV_PORT_ATTR_SET, SWITCHDEV_PORT_ATTR_GET
rocker: Handle SWITCHDEV_PORT_ATTR_GET/SET
mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_ATTR_GET/SET
net: mscc: ocelot: Handle SWITCHDEV_PORT_ATTR_GET/SET
staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_ATTR_GET/SET
net: dsa: Handle SWITCHDEV_PORT_ATTR_GET/SET
net: switchdev: Replace port attr get/set SDO with a notification
net: Remove switchdev_ops
Documentation/networking/switchdev.txt | 10 +-
.../net/ethernet/mellanox/mlxsw/spectrum.c | 12 --
.../net/ethernet/mellanox/mlxsw/spectrum.h | 2 -
.../mellanox/mlxsw/spectrum_switchdev.c | 36 +++---
drivers/net/ethernet/mscc/ocelot.c | 26 ++++-
drivers/net/ethernet/rocker/rocker_main.c | 30 ++++-
drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 30 ++++-
include/linux/netdevice.h | 3 -
include/net/switchdev.h | 28 ++---
net/dsa/slave.c | 30 ++++-
net/switchdev/switchdev.c | 107 ++++++------------
11 files changed, 168 insertions(+), 146 deletions(-)
--
2.17.1
Update the section about switchdev drivers having to implement a
switchdev_port_attr_get() function to return
SWITCHDEV_ATTR_ID_PORT_PARENT_ID since that is no longer valid after
commit bccb30254a4a ("net: Get rid of
SWITCHDEV_ATTR_ID_PORT_PARENT_ID").
Fixes: bccb30254a4a ("net: Get rid of SWITCHDEV_ATTR_ID_PORT_PARENT_ID")
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: Florian Fainelli <[email protected]>
---
Documentation/networking/switchdev.txt | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt
index f3244d87512a..ea90243340a9 100644
--- a/Documentation/networking/switchdev.txt
+++ b/Documentation/networking/switchdev.txt
@@ -92,11 +92,11 @@ device.
Switch ID
^^^^^^^^^
-The switchdev driver must implement the switchdev op switchdev_port_attr_get
-for SWITCHDEV_ATTR_ID_PORT_PARENT_ID for each port netdev, returning the same
-physical ID for each port of a switch. The ID must be unique between switches
-on the same system. The ID does not need to be unique between switches on
-different systems.
+The switchdev driver must implement the net_device operation
+ndo_get_port_parent_id for each port netdev, returning the same physical ID for
+each port of a switch. The ID must be unique between switches on the same
+system. The ID does not need to be unique between switches on different
+systems.
The switch ID is used to locate ports on a switch and to know if aggregated
ports belong to the same switch.
--
2.17.1
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare rocker to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
rocker_port_attr_{set,get} calls.
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: Florian Fainelli <[email protected]>
---
drivers/net/ethernet/rocker/rocker_main.c | 24 +++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 66f72f8c46e5..9a8fe49e32b6 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2835,6 +2835,27 @@ rocker_switchdev_port_obj_event(unsigned long event, struct net_device *netdev,
return notifier_from_errno(err);
}
+static int
+rocker_switchdev_port_attr_event(unsigned long event, struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info
+ *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = rocker_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ case SWITCHDEV_PORT_ATTR_GET:
+ err = rocker_port_attr_get(netdev, port_attr_info->attr);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int rocker_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -2847,6 +2868,9 @@ static int rocker_switchdev_blocking_event(struct notifier_block *unused,
case SWITCHDEV_PORT_OBJ_ADD:
case SWITCHDEV_PORT_OBJ_DEL:
return rocker_switchdev_port_obj_event(event, dev, ptr);
+ case SWITCHDEV_PORT_ATTR_SET: /* fall through */
+ case SWITCHDEV_PORT_ATTR_GET:
+ return rocker_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare mlxsw to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
mlxsw_sp_port_attr_{set,get} calls.
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: Florian Fainelli <[email protected]>
---
.../mellanox/mlxsw/spectrum_switchdev.c | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 95e37de3e48f..88d4994309a7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -3443,6 +3443,26 @@ mlxsw_sp_switchdev_handle_vxlan_obj_del(struct net_device *vxlan_dev,
}
}
+static int
+mlxsw_sp_switchdev_port_attr_event(unsigned long event, struct net_device *dev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = mlxsw_sp_port_attr_set(dev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ case SWITCHDEV_PORT_ATTR_GET:
+ err = mlxsw_sp_port_attr_get(dev, port_attr_info->attr);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -3466,6 +3486,9 @@ static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
mlxsw_sp_port_dev_check,
mlxsw_sp_port_obj_del);
return notifier_from_errno(err);
+ case SWITCHDEV_PORT_ATTR_SET: /* fall through */
+ case SWITCHDEV_PORT_ATTR_GET:
+ return mlxsw_sp_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare DSA to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
dsa_slave_port_attr_{set,get} calls.
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: Florian Fainelli <[email protected]>
---
net/dsa/slave.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 2e5e7c04821b..66c6c353f4f7 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1558,6 +1558,27 @@ dsa_slave_switchdev_port_obj_event(unsigned long event,
return notifier_from_errno(err);
}
+static int
+dsa_slave_switchdev_port_attr_event(unsigned long event,
+ struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = dsa_slave_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ case SWITCHDEV_PORT_ATTR_GET:
+ err = dsa_slave_port_attr_get(netdev, port_attr_info->attr);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -1570,6 +1591,9 @@ static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused,
case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
case SWITCHDEV_PORT_OBJ_DEL:
return dsa_slave_switchdev_port_obj_event(event, dev, ptr);
+ case SWITCHDEV_PORT_ATTR_SET: /* fall through */
+ case SWITCHDEV_PORT_ATTR_GET:
+ return dsa_slave_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
Drop switchdev_ops.switchdev_port_attr_get and _set. 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_attr_notify() that sends the switchdev
notifications SWITCHDEV_PORT_ATTR_GET and _SET.
Update switchdev_port_attr_get() to dispatch to this new function. Drop
__switchdev_port_attr_set() and update switchdev_port_attr_set()
likewise.
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: Florian Fainelli <[email protected]>
---
net/switchdev/switchdev.c | 107 +++++++++++++-------------------------
1 file changed, 37 insertions(+), 70 deletions(-)
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 7e1357db33d7..8fc3db2179f5 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -174,81 +174,31 @@ 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)
+static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
+ struct net_device *dev,
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
{
- 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;
+ int err;
+ int rc;
- if (ops && ops->switchdev_port_attr_get)
- return ops->switchdev_port_attr_get(dev, attr);
+ struct switchdev_notifier_port_attr_info attr_info = {
+ .attr = attr,
+ .trans = trans,
+ .handled = false,
+ };
- if (attr->flags & SWITCHDEV_F_NO_RECURSE)
+ rc = call_switchdev_blocking_notifiers(nt, dev, &attr_info.info, NULL);
+ err = notifier_to_errno(rc);
+ if (err) {
+ WARN_ON(!attr_info.handled);
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)
-{
- 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_attr_set) {
- err = ops->switchdev_port_attr_set(dev, attr, trans);
- goto done;
- }
-
- if (attr->flags & SWITCHDEV_F_NO_RECURSE)
- goto done;
-
- /* Switch device port(s) may be stacked under
- * bond/team/vlan dev, so recurse down to set attr on
- * each port.
- */
-
- netdev_for_each_lower_dev(dev, lower_dev, iter) {
- err = __switchdev_port_attr_set(lower_dev, attr, trans);
- if (err)
- break;
}
-done:
- if (err == -EOPNOTSUPP && attr->flags & SWITCHDEV_F_SKIP_EOPNOTSUPP)
- err = 0;
+ if (!attr_info.handled)
+ return -EOPNOTSUPP;
- return err;
+ return 0;
}
static int switchdev_port_attr_set_now(struct net_device *dev,
@@ -267,7 +217,9 @@ static int switchdev_port_attr_set_now(struct net_device *dev,
*/
trans.ph_prepare = true;
- err = __switchdev_port_attr_set(dev, attr, &trans);
+ err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET,
+ dev, (struct switchdev_attr *)attr,
+ &trans);
if (err) {
/* Prepare phase failed: abort the transaction. Any
* resources reserved in the prepare phase are
@@ -286,7 +238,9 @@ static int switchdev_port_attr_set_now(struct net_device *dev,
*/
trans.ph_prepare = false;
- err = __switchdev_port_attr_set(dev, attr, &trans);
+ err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET,
+ dev, (struct switchdev_attr *)attr,
+ &trans);
WARN(err, "%s: Commit of attribute (id=%d) failed.\n",
dev->name, attr->id);
switchdev_trans_items_warn_destroy(dev, &trans);
@@ -338,6 +292,19 @@ int switchdev_port_attr_set(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(switchdev_port_attr_set);
+/**
+ * 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)
+{
+ return switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_GET, dev,
+ attr, NULL);
+}
+EXPORT_SYMBOL_GPL(switchdev_port_attr_get);
+
static size_t switchdev_obj_size(const struct switchdev_obj *obj)
{
switch (obj->id) {
--
2.17.1
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 <[email protected]>
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: Florian Fainelli <[email protected]>
---
include/net/switchdev.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 5e87b54c5dc5..b8becabbef38 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -143,6 +143,9 @@ enum switchdev_notifier_type {
SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE,
SWITCHDEV_VXLAN_FDB_OFFLOADED,
+
+ SWITCHDEV_PORT_ATTR_SET, /* Blocking. */
+ SWITCHDEV_PORT_ATTR_GET, /* Blocking. */
};
struct switchdev_notifier_info {
@@ -165,6 +168,13 @@ struct switchdev_notifier_port_obj_info {
bool handled;
};
+struct switchdev_notifier_port_attr_info {
+ struct switchdev_notifier_info info; /* must be first */
+ 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)
{
--
2.17.1
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare ocelot to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
ocelot_port_attr_{set,get} calls.
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: Florian Fainelli <[email protected]>
---
drivers/net/ethernet/mscc/ocelot.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 195306d05bcd..2708809713ed 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1582,6 +1582,24 @@ struct notifier_block ocelot_netdevice_nb __read_mostly = {
};
EXPORT_SYMBOL(ocelot_netdevice_nb);
+static int
+ocelot_switchdev_port_attr_event(unsigned long event,
+ struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = ocelot_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -1600,6 +1618,9 @@ static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
ocelot_netdevice_dev_check,
ocelot_port_obj_del);
return notifier_from_errno(err);
+ case SWITCHDEV_PORT_ATTR_SET: /* fall through */
+ case SWITCHDEV_PORT_ATTR_GET:
+ return ocelot_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare ethsw to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
swdev_port_attr_{set,get} calls.
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: Florian Fainelli <[email protected]>
---
drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index e559f4c25cf7..7c77fb43233e 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -1111,6 +1111,27 @@ ethsw_switchdev_port_obj_event(unsigned long event, struct net_device *netdev,
return notifier_from_errno(err);
}
+static int
+ethsw_switchdev_port_attr_event(unsigned long event,
+ struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = swdev_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ case SWITCHDEV_PORT_ATTR_GET:
+ err = swdev_port_attr_get(netdev, port_attr_info->attr);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int port_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -1123,6 +1144,9 @@ static int port_switchdev_blocking_event(struct notifier_block *unused,
case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
case SWITCHDEV_PORT_OBJ_DEL:
return ethsw_switchdev_port_obj_event(event, dev, ptr);
+ case SWITCHDEV_PORT_ATTR_SET: /* fall through */
+ case SWITCHDEV_PORT_ATTR_GET:
+ return ethsw_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
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.
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: Florian Fainelli <[email protected]>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 12 ------------
drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 --
.../mellanox/mlxsw/spectrum_switchdev.c | 13 -------------
drivers/net/ethernet/mscc/ocelot.c | 5 -----
drivers/net/ethernet/rocker/rocker_main.c | 6 ------
drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 6 ------
include/linux/netdevice.h | 3 ---
include/net/switchdev.h | 18 ------------------
net/dsa/slave.c | 6 ------
9 files changed, 71 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 7c9745cecbbd..619965abab43 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3220,7 +3220,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) {
@@ -3237,7 +3236,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:
@@ -3280,7 +3278,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);
@@ -4001,12 +3998,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_span_init;
}
- err = mlxsw_sp_switchdev_init(mlxsw_sp);
- if (err) {
- dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize switchdev\n");
- goto err_switchdev_init;
- }
-
err = mlxsw_sp_counter_pool_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to init counter pool\n");
@@ -4077,8 +4068,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
err_afa_init:
mlxsw_sp_counter_pool_fini(mlxsw_sp);
err_counter_pool_init:
- mlxsw_sp_switchdev_fini(mlxsw_sp);
-err_switchdev_init:
mlxsw_sp_span_fini(mlxsw_sp);
err_span_init:
mlxsw_sp_lag_fini(mlxsw_sp);
@@ -4141,7 +4130,6 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_nve_fini(mlxsw_sp);
mlxsw_sp_afa_fini(mlxsw_sp);
mlxsw_sp_counter_pool_fini(mlxsw_sp);
- mlxsw_sp_switchdev_fini(mlxsw_sp);
mlxsw_sp_span_fini(mlxsw_sp);
mlxsw_sp_lag_fini(mlxsw_sp);
mlxsw_sp_buffers_fini(mlxsw_sp);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index ceebc91f4f1d..82e3e6dc81a1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -375,8 +375,6 @@ u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes);
/* 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 88d4994309a7..3e2ef69a1d22 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1957,11 +1957,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_get = mlxsw_sp_port_attr_get,
- .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,
@@ -3576,11 +3571,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 2708809713ed..374636e8fcbe 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)
{
@@ -1654,7 +1650,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 9a8fe49e32b6..b017543fd196 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2147,11 +2147,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_get = rocker_port_attr_get,
- .switchdev_port_attr_set = rocker_port_attr_set,
-};
-
struct rocker_fib_event_work {
struct work_struct work;
union {
@@ -2605,7 +2600,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 7c77fb43233e..f4489976a9ac 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -932,11 +932,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_get = swdev_port_attr_get,
- .switchdev_port_attr_set = swdev_port_attr_set,
-};
-
/* For the moment, only flood setting needs to be updated */
static int port_bridge_join(struct net_device *netdev,
struct net_device *upper_dev)
@@ -1466,7 +1461,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 1fb733f38a47..a747456b9d23 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1836,9 +1836,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 b8becabbef38..e9aa920aba57 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -113,21 +113,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_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);
-};
-
enum switchdev_notifier_type {
SWITCHDEV_FDB_ADD_TO_BRIDGE = 1,
SWITCHDEV_FDB_DEL_TO_BRIDGE,
@@ -229,7 +214,6 @@ int switchdev_handle_port_obj_del(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
static inline void switchdev_deferred_process(void)
@@ -322,8 +306,6 @@ switchdev_handle_port_obj_del(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 66c6c353f4f7..3deab965dad9 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1057,11 +1057,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
.ndo_get_port_parent_id = dsa_slave_get_port_parent_id,
};
-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,
-};
-
static struct device_type dsa_type = {
.name = "dsa",
};
@@ -1321,7 +1316,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);
--
2.17.1
From: Florian Fainelli <[email protected]>
Date: Mon, 11 Feb 2019 11:09:52 -0800
> David, I would like to get Ido's feedback on this to make sure I did not
> miss something, thank you!
Ok, Ido please look at this when you can.
On Mon, Feb 11, 2019 at 12:16:57PM -0800, David Miller wrote:
> From: Florian Fainelli <[email protected]>
> Date: Mon, 11 Feb 2019 11:09:52 -0800
>
> > David, I would like to get Ido's feedback on this to make sure I did not
> > miss something, thank you!
>
> Ok, Ido please look at this when you can.
Will review tomorrow. I was occupied with other stuff last couple of
days. Sorry
On Mon, Feb 11, 2019 at 11:09:53AM -0800, Florian Fainelli wrote:
> Update the section about switchdev drivers having to implement a
> switchdev_port_attr_get() function to return
> SWITCHDEV_ATTR_ID_PORT_PARENT_ID since that is no longer valid after
> commit bccb30254a4a ("net: Get rid of
> SWITCHDEV_ATTR_ID_PORT_PARENT_ID").
>
> Fixes: bccb30254a4a ("net: Get rid of SWITCHDEV_ATTR_ID_PORT_PARENT_ID")
> Acked-by: Jiri Pirko <[email protected]>
> Signed-off-by: Florian Fainelli <[email protected]>
Reviewed-by: Ido Schimmel <[email protected]>
On Mon, Feb 11, 2019 at 11:09:52AM -0800, Florian Fainelli wrote:
> Hi all,
>
> This patch series finishes by the removal of switchdev_ops. To get there
> we convert the existing switchdev_port_attr_{set,get} switchdev_ops to
> use a blocking notifier, thus making it consistent with how the objects
> are pushed to the switchdev enabled devices.
>
> Please review and let me know what you think!
>
> David, I would like to get Ido's feedback on this to make sure I did not
> miss something, thank you!
Hi Florian,
Why do you still keep switchdev_port_attr_get()? I believe we can remove
it and simplify things.
After your recent patchset to remove 'PORT_BRIDGE_FLAGS', the only
remaining user of get() is 'PORT_BRIDGE_FLAGS_SUPPORT'. It can be
converted to a blocking set() with 'PORT_PRE_BRIDGE_FLAGS' (or a similar
name).
I would like to make sure we're in sync with regards to future changes.
After this patchset to get rid of switchdev_ops we can continue to
completely removing switchdev (I believe Jiri approves). The
prepare-commit model is not really needed and the two switchdev
notification chains can be split into bridge and vxlan specific chains.
Notifications sent in an atomic context can be handled by drivers
directly in this context. Similar to how FDB/route/neighbour are
handled. It will really simplify things. No need for the defer flag
anymore and tricks like 'PORT_BRIDGE_FLAGS_SUPPORT' and
'PORT_PRE_BRIDGE_FLAGS'. In the atomic context the driver can veto the
requested bridge flags, but program the device from a blocking context
(using a workqueue).
On Mon, Feb 11, 2019 at 11:09:54AM -0800, Florian Fainelli wrote:
> 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 <[email protected]>
> Acked-by: Jiri Pirko <[email protected]>
> Signed-off-by: Florian Fainelli <[email protected]>
> ---
> include/net/switchdev.h | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/include/net/switchdev.h b/include/net/switchdev.h
> index 5e87b54c5dc5..b8becabbef38 100644
> --- a/include/net/switchdev.h
> +++ b/include/net/switchdev.h
> @@ -143,6 +143,9 @@ enum switchdev_notifier_type {
> SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
> SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE,
> SWITCHDEV_VXLAN_FDB_OFFLOADED,
> +
> + SWITCHDEV_PORT_ATTR_SET, /* Blocking. */
> + SWITCHDEV_PORT_ATTR_GET, /* Blocking. */
As I wrote in the cover letter, I don't believe GET is needed.
> };
>
> struct switchdev_notifier_info {
> @@ -165,6 +168,13 @@ struct switchdev_notifier_port_obj_info {
> bool handled;
> };
>
> +struct switchdev_notifier_port_attr_info {
> + struct switchdev_notifier_info info; /* must be first */
> + 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)
> {
> --
> 2.17.1
>
Tue, Feb 12, 2019 at 02:14:47PM CET, [email protected] wrote:
>On Mon, Feb 11, 2019 at 11:09:52AM -0800, Florian Fainelli wrote:
>> Hi all,
>>
>> This patch series finishes by the removal of switchdev_ops. To get there
>> we convert the existing switchdev_port_attr_{set,get} switchdev_ops to
>> use a blocking notifier, thus making it consistent with how the objects
>> are pushed to the switchdev enabled devices.
>>
>> Please review and let me know what you think!
>>
>> David, I would like to get Ido's feedback on this to make sure I did not
>> miss something, thank you!
>
>Hi Florian,
>
>Why do you still keep switchdev_port_attr_get()? I believe we can remove
>it and simplify things.
>
>After your recent patchset to remove 'PORT_BRIDGE_FLAGS', the only
>remaining user of get() is 'PORT_BRIDGE_FLAGS_SUPPORT'. It can be
>converted to a blocking set() with 'PORT_PRE_BRIDGE_FLAGS' (or a similar
>name).
Let's do that in a follow-up.
>
>I would like to make sure we're in sync with regards to future changes.
>After this patchset to get rid of switchdev_ops we can continue to
>completely removing switchdev (I believe Jiri approves). The
Yes.
>prepare-commit model is not really needed and the two switchdev
>notification chains can be split into bridge and vxlan specific chains.
>
>Notifications sent in an atomic context can be handled by drivers
>directly in this context. Similar to how FDB/route/neighbour are
>handled. It will really simplify things. No need for the defer flag
>anymore and tricks like 'PORT_BRIDGE_FLAGS_SUPPORT' and
>'PORT_PRE_BRIDGE_FLAGS'. In the atomic context the driver can veto the
>requested bridge flags, but program the device from a blocking context
>(using a workqueue).
Sounds good to me.
On Mon, Feb 11, 2019 at 11:09:56AM -0800, Florian Fainelli wrote:
> Following patches will change the way we communicate getting or setting
> a port's attribute and use a blocking notifier to perform those tasks.
>
> Prepare mlxsw to support receiving notifier events targeting
> SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
> mlxsw_sp_port_attr_{set,get} calls.
>
> Acked-by: Jiri Pirko <[email protected]>
> Signed-off-by: Florian Fainelli <[email protected]>
> ---
> .../mellanox/mlxsw/spectrum_switchdev.c | 23 +++++++++++++++++++
> 1 file changed, 23 insertions(+)
>
> diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> index 95e37de3e48f..88d4994309a7 100644
> --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> @@ -3443,6 +3443,26 @@ mlxsw_sp_switchdev_handle_vxlan_obj_del(struct net_device *vxlan_dev,
> }
> }
>
> +static int
> +mlxsw_sp_switchdev_port_attr_event(unsigned long event, struct net_device *dev,
> + struct switchdev_notifier_port_attr_info *port_attr_info)
> +{
> + int err = -EOPNOTSUPP;
> +
> + switch (event) {
> + case SWITCHDEV_PORT_ATTR_SET:
> + err = mlxsw_sp_port_attr_set(dev, port_attr_info->attr,
> + port_attr_info->trans);
It is not that simple. These functions expect 'dev' to be an mlxsw
netdev since the operation is propagated using the device chain. This is
not the case with notification chains. 'dev' can be any netdev in the
system and then this line in mlxsw_sp_port_attr_set() is not correct:
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
You can check commit f30f0601eb93 ("switchdev: Add helpers to aid
traversal through lower devices") for reference.
> + break;
> + case SWITCHDEV_PORT_ATTR_GET:
> + err = mlxsw_sp_port_attr_get(dev, port_attr_info->attr);
> + break;
> + }
> +
> + port_attr_info->handled = true;
I believe this should only be set in case the driver actually handled
the notification. That's how it works for objects.
I suggest looking at the series merged in commit 06d212900ea9 ("Merge
branch 'switchdev-blocking-notifiers'").
> + return notifier_from_errno(err);
> +}
> +
> static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
> unsigned long event, void *ptr)
> {
> @@ -3466,6 +3486,9 @@ static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
> mlxsw_sp_port_dev_check,
> mlxsw_sp_port_obj_del);
> return notifier_from_errno(err);
> + case SWITCHDEV_PORT_ATTR_SET: /* fall through */
> + case SWITCHDEV_PORT_ATTR_GET:
> + return mlxsw_sp_switchdev_port_attr_event(event, dev, ptr);
> }
>
> return NOTIFY_DONE;
> --
> 2.17.1
>
On Mon, Feb 11, 2019 at 11:10:01AM -0800, Florian Fainelli wrote:
> 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.
>
> Acked-by: Jiri Pirko <[email protected]>
> Signed-off-by: Florian Fainelli <[email protected]>
> ---
> drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 12 ------------
> drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 --
> .../mellanox/mlxsw/spectrum_switchdev.c | 13 -------------
> drivers/net/ethernet/mscc/ocelot.c | 5 -----
> drivers/net/ethernet/rocker/rocker_main.c | 6 ------
> drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 6 ------
> include/linux/netdevice.h | 3 ---
> include/net/switchdev.h | 18 ------------------
> net/dsa/slave.c | 6 ------
There's also this line that can be removed from the 8021q driver:
net/8021q/vlan_dev.c:34:#include <net/switchdev.h>