Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <f.fainelli@gmail.com>
Cc: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: Hauke Mehrtens <hauke@hauke-m.de>
Cc: Woojung Huh <woojung.huh@microchip.com>
Cc: Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
Cc: Sean Wang <sean.wang@mediatek.com>
Cc: Landen Chao <Landen.Chao@mediatek.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Vivien Didelot <vivien.didelot@gmail.com>
Cc: Jonathan McDowell <noodles@earth.li>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Claudiu Manoil <claudiu.manoil@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vladimir Oltean and committed by
David S. Miller
2e554a7a c2568c8c

+130 -47
+5 -1
drivers/net/dsa/b53/b53_common.c
··· 1374 1374 } 1375 1375 EXPORT_SYMBOL(b53_phylink_mac_link_up); 1376 1376 1377 - int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) 1377 + int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, 1378 + struct switchdev_trans *trans) 1378 1379 { 1379 1380 struct b53_device *dev = ds->priv; 1381 + 1382 + if (switchdev_trans_ph_prepare(trans)) 1383 + return 0; 1380 1384 1381 1385 b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering); 1382 1386
+2 -1
drivers/net/dsa/b53/b53_priv.h
··· 347 347 struct phy_device *phydev, 348 348 int speed, int duplex, 349 349 bool tx_pause, bool rx_pause); 350 - int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering); 350 + int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, 351 + struct switchdev_trans *trans); 351 352 int b53_vlan_prepare(struct dsa_switch *ds, int port, 352 353 const struct switchdev_obj_port_vlan *vlan); 353 354 void b53_vlan_add(struct dsa_switch *ds, int port,
+2 -1
drivers/net/dsa/dsa_loop.c
··· 190 190 } 191 191 192 192 static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port, 193 - bool vlan_filtering) 193 + bool vlan_filtering, 194 + struct switchdev_trans *trans) 194 195 { 195 196 dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n", 196 197 __func__, port, vlan_filtering);
+21 -5
drivers/net/dsa/lantiq_gswip.c
··· 736 736 } 737 737 738 738 static int gswip_port_vlan_filtering(struct dsa_switch *ds, int port, 739 - bool vlan_filtering) 739 + bool vlan_filtering, 740 + struct switchdev_trans *trans) 740 741 { 741 742 struct gswip_priv *priv = ds->priv; 742 - struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev; 743 743 744 744 /* Do not allow changing the VLAN filtering options while in bridge */ 745 - if (!!(priv->port_vlan_filter & BIT(port)) != vlan_filtering && bridge) 746 - return -EIO; 745 + if (switchdev_trans_ph_prepare(trans)) { 746 + struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev; 747 + 748 + if (!bridge) 749 + return 0; 750 + 751 + if (!!(priv->port_vlan_filter & BIT(port)) != vlan_filtering) 752 + return -EIO; 753 + 754 + return 0; 755 + } 747 756 748 757 if (vlan_filtering) { 749 758 /* Use port based VLAN tag */ ··· 790 781 791 782 /* disable port fetch/store dma on all ports */ 792 783 for (i = 0; i < priv->hw_info->max_ports; i++) { 784 + struct switchdev_trans trans; 785 + 786 + /* Skip the prepare phase, this shouldn't return an error 787 + * during setup. 788 + */ 789 + trans.ph_prepare = false; 790 + 793 791 gswip_port_disable(ds, i); 794 - gswip_port_vlan_filtering(ds, i, false); 792 + gswip_port_vlan_filtering(ds, i, false, &trans); 795 793 } 796 794 797 795 /* enable Switch */
+5 -1
drivers/net/dsa/microchip/ksz8795.c
··· 782 782 } 783 783 784 784 static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port, 785 - bool flag) 785 + bool flag, 786 + struct switchdev_trans *trans) 786 787 { 787 788 struct ksz_device *dev = ds->priv; 789 + 790 + if (switchdev_trans_ph_prepare(trans)) 791 + return 0; 788 792 789 793 ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag); 790 794
+5 -1
drivers/net/dsa/microchip/ksz9477.c
··· 493 493 } 494 494 495 495 static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port, 496 - bool flag) 496 + bool flag, 497 + struct switchdev_trans *trans) 497 498 { 498 499 struct ksz_device *dev = ds->priv; 500 + 501 + if (switchdev_trans_ph_prepare(trans)) 502 + return 0; 499 503 500 504 if (flag) { 501 505 ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL,
+5 -1
drivers/net/dsa/mt7530.c
··· 1289 1289 1290 1290 static int 1291 1291 mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, 1292 - bool vlan_filtering) 1292 + bool vlan_filtering, 1293 + struct switchdev_trans *trans) 1293 1294 { 1295 + if (switchdev_trans_ph_prepare(trans)) 1296 + return 0; 1297 + 1294 1298 if (vlan_filtering) { 1295 1299 /* The port is being kept as VLAN-unaware port when bridge is 1296 1300 * set up with vlan_filtering not being set, Otherwise, the
+4 -3
drivers/net/dsa/mv88e6xxx/chip.c
··· 1578 1578 } 1579 1579 1580 1580 static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, 1581 - bool vlan_filtering) 1581 + bool vlan_filtering, 1582 + struct switchdev_trans *trans) 1582 1583 { 1583 1584 struct mv88e6xxx_chip *chip = ds->priv; 1584 1585 u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE : 1585 1586 MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED; 1586 1587 int err; 1587 1588 1588 - if (!chip->info->max_vid) 1589 - return -EOPNOTSUPP; 1589 + if (switchdev_trans_ph_prepare(trans)) 1590 + return chip->info->max_vid ? 0 : -EOPNOTSUPP; 1590 1591 1591 1592 mv88e6xxx_reg_lock(chip); 1592 1593 err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
+3 -4
drivers/net/dsa/ocelot/felix.c
··· 119 119 return 0; 120 120 } 121 121 122 - static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) 122 + static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, 123 + struct switchdev_trans *trans) 123 124 { 124 125 struct ocelot *ocelot = ds->priv; 125 126 126 - ocelot_port_vlan_filtering(ocelot, port, enabled); 127 - 128 - return 0; 127 + return ocelot_port_vlan_filtering(ocelot, port, enabled, trans); 129 128 } 130 129 131 130 static void felix_vlan_add(struct dsa_switch *ds, int port,
+5 -1
drivers/net/dsa/qca8k.c
··· 1294 1294 } 1295 1295 1296 1296 static int 1297 - qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) 1297 + qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, 1298 + struct switchdev_trans *trans) 1298 1299 { 1299 1300 struct qca8k_priv *priv = ds->priv; 1301 + 1302 + if (switchdev_trans_ph_prepare(trans)) 1303 + return 0; 1300 1304 1301 1305 if (vlan_filtering) { 1302 1306 qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
+2 -1
drivers/net/dsa/realtek-smi-core.h
··· 129 129 int rtl8366_reset_vlan(struct realtek_smi *smi); 130 130 int rtl8366_init_vlan(struct realtek_smi *smi); 131 131 int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, 132 - bool vlan_filtering); 132 + bool vlan_filtering, 133 + struct switchdev_trans *trans); 133 134 int rtl8366_vlan_prepare(struct dsa_switch *ds, int port, 134 135 const struct switchdev_obj_port_vlan *vlan); 135 136 void rtl8366_vlan_add(struct dsa_switch *ds, int port,
+8 -3
drivers/net/dsa/rtl8366.c
··· 340 340 } 341 341 EXPORT_SYMBOL_GPL(rtl8366_init_vlan); 342 342 343 - int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) 343 + int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, 344 + struct switchdev_trans *trans) 344 345 { 345 346 struct realtek_smi *smi = ds->priv; 346 347 struct rtl8366_vlan_4k vlan4k; 347 348 int ret; 348 349 349 350 /* Use VLAN nr port + 1 since VLAN0 is not valid */ 350 - if (!smi->ops->is_vlan_valid(smi, port + 1)) 351 - return -EINVAL; 351 + if (switchdev_trans_ph_prepare(trans)) { 352 + if (!smi->ops->is_vlan_valid(smi, port + 1)) 353 + return -EINVAL; 354 + 355 + return 0; 356 + } 352 357 353 358 dev_info(smi->dev, "%s filtering on port %d\n", 354 359 vlan_filtering ? "enable" : "disable",
+2 -1
drivers/net/dsa/sja1105/sja1105.h
··· 245 245 246 246 int sja1105_static_config_reload(struct sja1105_private *priv, 247 247 enum sja1105_reset_reason reason); 248 - int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled); 248 + int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, 249 + struct switchdev_trans *trans); 249 250 void sja1105_frame_memory_partitioning(struct sja1105_private *priv); 250 251 251 252 /* From sja1105_devlink.c */
+8 -1
drivers/net/dsa/sja1105/sja1105_devlink.c
··· 135 135 136 136 rtnl_lock(); 137 137 for (port = 0; port < ds->num_ports; port++) { 138 + struct switchdev_trans trans; 138 139 struct dsa_port *dp; 139 140 140 141 if (!dsa_is_user_port(ds, port)) ··· 144 143 dp = dsa_to_port(ds, port); 145 144 vlan_filtering = dsa_port_is_vlan_filtering(dp); 146 145 147 - rc = sja1105_vlan_filtering(ds, port, vlan_filtering); 146 + trans.ph_prepare = true; 147 + rc = sja1105_vlan_filtering(ds, port, vlan_filtering, &trans); 148 + if (rc) 149 + break; 150 + 151 + trans.ph_prepare = false; 152 + rc = sja1105_vlan_filtering(ds, port, vlan_filtering, &trans); 148 153 if (rc) 149 154 break; 150 155 }
+11 -6
drivers/net/dsa/sja1105/sja1105_main.c
··· 2634 2634 * which can only be partially reconfigured at runtime (and not the TPID). 2635 2635 * So a switch reset is required. 2636 2636 */ 2637 - int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) 2637 + int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, 2638 + struct switchdev_trans *trans) 2638 2639 { 2639 2640 struct sja1105_l2_lookup_params_entry *l2_lookup_params; 2640 2641 struct sja1105_general_params_entry *general_params; ··· 2647 2646 u16 tpid, tpid2; 2648 2647 int rc; 2649 2648 2650 - list_for_each_entry(rule, &priv->flow_block.rules, list) { 2651 - if (rule->type == SJA1105_RULE_VL) { 2652 - dev_err(ds->dev, 2653 - "Cannot change VLAN filtering state while VL rules are active\n"); 2654 - return -EBUSY; 2649 + if (switchdev_trans_ph_prepare(trans)) { 2650 + list_for_each_entry(rule, &priv->flow_block.rules, list) { 2651 + if (rule->type == SJA1105_RULE_VL) { 2652 + dev_err(ds->dev, 2653 + "Cannot change VLAN filtering with active VL rules\n"); 2654 + return -EBUSY; 2655 + } 2655 2656 } 2657 + 2658 + return 0; 2656 2659 } 2657 2660 2658 2661 if (enabled) {
+20 -3
drivers/net/ethernet/mscc/ocelot.c
··· 199 199 return 0; 200 200 } 201 201 202 - void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, 203 - bool vlan_aware) 202 + int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, 203 + bool vlan_aware, struct switchdev_trans *trans) 204 204 { 205 205 struct ocelot_port *ocelot_port = ocelot->ports[port]; 206 206 u32 val; 207 + 208 + if (switchdev_trans_ph_prepare(trans)) 209 + return 0; 207 210 208 211 ocelot_port->vlan_aware = vlan_aware; 209 212 ··· 221 218 ANA_PORT_VLAN_CFG, port); 222 219 223 220 ocelot_port_set_native_vlan(ocelot, port, ocelot_port->vid); 221 + 222 + return 0; 224 223 } 225 224 EXPORT_SYMBOL(ocelot_port_vlan_filtering); 226 225 ··· 1107 1102 int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, 1108 1103 struct net_device *bridge) 1109 1104 { 1105 + struct switchdev_trans trans; 1106 + int ret; 1107 + 1110 1108 ocelot->bridge_mask &= ~BIT(port); 1111 1109 1112 1110 if (!ocelot->bridge_mask) 1113 1111 ocelot->hw_bridge_dev = NULL; 1114 1112 1115 - ocelot_port_vlan_filtering(ocelot, port, 0); 1113 + trans.ph_prepare = true; 1114 + ret = ocelot_port_vlan_filtering(ocelot, port, false, &trans); 1115 + if (ret) 1116 + return ret; 1117 + 1118 + trans.ph_prepare = false; 1119 + ret = ocelot_port_vlan_filtering(ocelot, port, false, &trans); 1120 + if (ret) 1121 + return ret; 1122 + 1116 1123 ocelot_port_set_pvid(ocelot, port, 0); 1117 1124 return ocelot_port_set_native_vlan(ocelot, port, 0); 1118 1125 }
+1 -1
drivers/net/ethernet/mscc/ocelot_net.c
··· 790 790 break; 791 791 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: 792 792 ocelot_port_vlan_filtering(ocelot, port, 793 - attr->u.vlan_filtering); 793 + attr->u.vlan_filtering, trans); 794 794 break; 795 795 case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED: 796 796 ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled);
+2 -1
include/net/dsa.h
··· 552 552 * VLAN support 553 553 */ 554 554 int (*port_vlan_filtering)(struct dsa_switch *ds, int port, 555 - bool vlan_filtering); 555 + bool vlan_filtering, 556 + struct switchdev_trans *trans); 556 557 int (*port_vlan_prepare)(struct dsa_switch *ds, int port, 557 558 const struct switchdev_obj_port_vlan *vlan); 558 559 void (*port_vlan_add)(struct dsa_switch *ds, int port,
+2 -2
include/soc/mscc/ocelot.h
··· 730 730 void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs); 731 731 void ocelot_adjust_link(struct ocelot *ocelot, int port, 732 732 struct phy_device *phydev); 733 - void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, 734 - bool vlan_aware); 733 + int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, bool enabled, 734 + struct switchdev_trans *trans); 735 735 void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state); 736 736 int ocelot_port_bridge_join(struct ocelot *ocelot, int port, 737 737 struct net_device *bridge);
+9 -8
net/dsa/port.c
··· 280 280 rcu_read_unlock(); 281 281 if (!apply) 282 282 return -EINVAL; 283 - 284 - return 0; 285 283 } 286 284 287 285 if (dsa_port_is_vlan_filtering(dp) == vlan_filtering) 288 286 return 0; 289 287 290 - err = ds->ops->port_vlan_filtering(ds, dp->index, 291 - vlan_filtering); 288 + err = ds->ops->port_vlan_filtering(ds, dp->index, vlan_filtering, 289 + trans); 292 290 if (err) 293 291 return err; 294 292 295 - if (ds->vlan_filtering_is_global) 296 - ds->vlan_filtering = vlan_filtering; 297 - else 298 - dp->vlan_filtering = vlan_filtering; 293 + if (switchdev_trans_ph_commit(trans)) { 294 + if (ds->vlan_filtering_is_global) 295 + ds->vlan_filtering = vlan_filtering; 296 + else 297 + dp->vlan_filtering = vlan_filtering; 298 + } 299 + 299 300 return 0; 300 301 } 301 302
+8 -1
net/dsa/switch.c
··· 139 139 } 140 140 } 141 141 if (unset_vlan_filtering) { 142 - struct switchdev_trans trans = {0}; 142 + struct switchdev_trans trans; 143 143 144 + trans.ph_prepare = true; 145 + err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port), 146 + false, &trans); 147 + if (err && err != EOPNOTSUPP) 148 + return err; 149 + 150 + trans.ph_prepare = false; 144 151 err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port), 145 152 false, &trans); 146 153 if (err && err != EOPNOTSUPP)