From 2e554a7a5d8a8092ecb20c547734bb33fddd5046 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 3 Oct 2020 01:06:46 +0300 Subject: net: dsa: propagate switchdev vlan_filtering prepare phase to drivers A driver may refuse to enable VLAN filtering for any reason beyond what the DSA framework cares about, such as: - having tc-flower rules that rely on the switch being VLAN-aware - the particular switch does not support VLAN, even if the driver does (the DSA framework just checks for the presence of the .port_vlan_add and .port_vlan_del pointers) - simply not supporting this configuration to be toggled at runtime Currently, when a driver rejects a configuration it cannot support, it does this from the commit phase, which triggers various warnings in switchdev. So propagate the prepare phase to drivers, to give them the ability to refuse invalid configurations cleanly and avoid the warnings. Since we need to modify all function prototypes and check for the prepare phase from within the drivers, take that opportunity and move the existing driver restrictions within the prepare phase where that is possible and easy. Cc: Florian Fainelli Cc: Martin Blumenstingl Cc: Hauke Mehrtens Cc: Woojung Huh Cc: Microchip Linux Driver Support Cc: Sean Wang Cc: Landen Chao Cc: Andrew Lunn Cc: Vivien Didelot Cc: Jonathan McDowell Cc: Linus Walleij Cc: Alexandre Belloni Cc: Claudiu Manoil Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot.c | 23 ++++++++++++++++++++--- drivers/net/ethernet/mscc/ocelot_net.c | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'drivers/net/ethernet/mscc') diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index e026617d6133..a965a554ff8b 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -199,12 +199,15 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port, return 0; } -void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, - bool vlan_aware) +int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, + bool vlan_aware, struct switchdev_trans *trans) { struct ocelot_port *ocelot_port = ocelot->ports[port]; u32 val; + if (switchdev_trans_ph_prepare(trans)) + return 0; + ocelot_port->vlan_aware = vlan_aware; if (vlan_aware) @@ -218,6 +221,8 @@ void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, ANA_PORT_VLAN_CFG, port); ocelot_port_set_native_vlan(ocelot, port, ocelot_port->vid); + + return 0; } EXPORT_SYMBOL(ocelot_port_vlan_filtering); @@ -1102,12 +1107,24 @@ EXPORT_SYMBOL(ocelot_port_bridge_join); int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, struct net_device *bridge) { + struct switchdev_trans trans; + int ret; + ocelot->bridge_mask &= ~BIT(port); if (!ocelot->bridge_mask) ocelot->hw_bridge_dev = NULL; - ocelot_port_vlan_filtering(ocelot, port, 0); + trans.ph_prepare = true; + ret = ocelot_port_vlan_filtering(ocelot, port, false, &trans); + if (ret) + return ret; + + trans.ph_prepare = false; + ret = ocelot_port_vlan_filtering(ocelot, port, false, &trans); + if (ret) + return ret; + ocelot_port_set_pvid(ocelot, port, 0); return ocelot_port_set_native_vlan(ocelot, port, 0); } diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 64e619f0f5b2..d3c03942546d 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -790,7 +790,7 @@ static int ocelot_port_attr_set(struct net_device *dev, break; case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: ocelot_port_vlan_filtering(ocelot, port, - attr->u.vlan_filtering); + attr->u.vlan_filtering, trans); break; case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED: ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled); -- cgit v1.2.3