}
 EXPORT_SYMBOL(b53_phylink_mac_link_up);
 
-int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
+int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                      struct switchdev_trans *trans)
 {
        struct b53_device *dev = ds->priv;
 
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
        b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering);
 
        return 0;
 
                             struct phy_device *phydev,
                             int speed, int duplex,
                             bool tx_pause, bool rx_pause);
-int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering);
+int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                      struct switchdev_trans *trans);
 int b53_vlan_prepare(struct dsa_switch *ds, int port,
                     const struct switchdev_obj_port_vlan *vlan);
 void b53_vlan_add(struct dsa_switch *ds, int port,
 
 }
 
 static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                       bool vlan_filtering)
+                                       bool vlan_filtering,
+                                       struct switchdev_trans *trans)
 {
        dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
                __func__, port, vlan_filtering);
 
 }
 
 static int gswip_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                    bool vlan_filtering)
+                                    bool vlan_filtering,
+                                    struct switchdev_trans *trans)
 {
        struct gswip_priv *priv = ds->priv;
-       struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
 
        /* Do not allow changing the VLAN filtering options while in bridge */
-       if (!!(priv->port_vlan_filter & BIT(port)) != vlan_filtering && bridge)
-               return -EIO;
+       if (switchdev_trans_ph_prepare(trans)) {
+               struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
+
+               if (!bridge)
+                       return 0;
+
+               if (!!(priv->port_vlan_filter & BIT(port)) != vlan_filtering)
+                       return -EIO;
+
+               return 0;
+       }
 
        if (vlan_filtering) {
                /* Use port based VLAN tag */
 
        /* disable port fetch/store dma on all ports */
        for (i = 0; i < priv->hw_info->max_ports; i++) {
+               struct switchdev_trans trans;
+
+               /* Skip the prepare phase, this shouldn't return an error
+                * during setup.
+                */
+               trans.ph_prepare = false;
+
                gswip_port_disable(ds, i);
-               gswip_port_vlan_filtering(ds, i, false);
+               gswip_port_vlan_filtering(ds, i, false, &trans);
        }
 
        /* enable Switch */
 
 }
 
 static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                      bool flag)
+                                      bool flag,
+                                      struct switchdev_trans *trans)
 {
        struct ksz_device *dev = ds->priv;
 
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
        ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag);
 
        return 0;
 
 }
 
 static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                      bool flag)
+                                      bool flag,
+                                      struct switchdev_trans *trans)
 {
        struct ksz_device *dev = ds->priv;
 
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
        if (flag) {
                ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL,
                             PORT_VLAN_LOOKUP_VID_0, true);
 
 
 static int
 mt7530_port_vlan_filtering(struct dsa_switch *ds, int port,
-                          bool vlan_filtering)
+                          bool vlan_filtering,
+                          struct switchdev_trans *trans)
 {
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
        if (vlan_filtering) {
                /* The port is being kept as VLAN-unaware port when bridge is
                 * set up with vlan_filtering not being set, Otherwise, the
 
 }
 
 static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
-                                        bool vlan_filtering)
+                                        bool vlan_filtering,
+                                        struct switchdev_trans *trans)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
        u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
                MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED;
        int err;
 
-       if (!chip->info->max_vid)
-               return -EOPNOTSUPP;
+       if (switchdev_trans_ph_prepare(trans))
+               return chip->info->max_vid ? 0 : -EOPNOTSUPP;
 
        mv88e6xxx_reg_lock(chip);
        err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
 
        return 0;
 }
 
-static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
+static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
+                               struct switchdev_trans *trans)
 {
        struct ocelot *ocelot = ds->priv;
 
-       ocelot_port_vlan_filtering(ocelot, port, enabled);
-
-       return 0;
+       return ocelot_port_vlan_filtering(ocelot, port, enabled, trans);
 }
 
 static void felix_vlan_add(struct dsa_switch *ds, int port,
 
 }
 
 static int
-qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
+qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                         struct switchdev_trans *trans)
 {
        struct qca8k_priv *priv = ds->priv;
 
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
        if (vlan_filtering) {
                qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
                          QCA8K_PORT_LOOKUP_VLAN_MODE,
 
 int rtl8366_reset_vlan(struct realtek_smi *smi);
 int rtl8366_init_vlan(struct realtek_smi *smi);
 int rtl8366_vlan_filtering(struct dsa_switch *ds, int port,
-                          bool vlan_filtering);
+                          bool vlan_filtering,
+                          struct switchdev_trans *trans);
 int rtl8366_vlan_prepare(struct dsa_switch *ds, int port,
                         const struct switchdev_obj_port_vlan *vlan);
 void rtl8366_vlan_add(struct dsa_switch *ds, int port,
 
 }
 EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
 
-int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
+int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+                          struct switchdev_trans *trans)
 {
        struct realtek_smi *smi = ds->priv;
        struct rtl8366_vlan_4k vlan4k;
        int ret;
 
        /* Use VLAN nr port + 1 since VLAN0 is not valid */
-       if (!smi->ops->is_vlan_valid(smi, port + 1))
-               return -EINVAL;
+       if (switchdev_trans_ph_prepare(trans)) {
+               if (!smi->ops->is_vlan_valid(smi, port + 1))
+                       return -EINVAL;
+
+               return 0;
+       }
 
        dev_info(smi->dev, "%s filtering on port %d\n",
                 vlan_filtering ? "enable" : "disable",
 
 
 int sja1105_static_config_reload(struct sja1105_private *priv,
                                 enum sja1105_reset_reason reason);
-int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled);
+int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
+                          struct switchdev_trans *trans);
 void sja1105_frame_memory_partitioning(struct sja1105_private *priv);
 
 /* From sja1105_devlink.c */
 
 
        rtnl_lock();
        for (port = 0; port < ds->num_ports; port++) {
+               struct switchdev_trans trans;
                struct dsa_port *dp;
 
                if (!dsa_is_user_port(ds, port))
                dp = dsa_to_port(ds, port);
                vlan_filtering = dsa_port_is_vlan_filtering(dp);
 
-               rc = sja1105_vlan_filtering(ds, port, vlan_filtering);
+               trans.ph_prepare = true;
+               rc = sja1105_vlan_filtering(ds, port, vlan_filtering, &trans);
+               if (rc)
+                       break;
+
+               trans.ph_prepare = false;
+               rc = sja1105_vlan_filtering(ds, port, vlan_filtering, &trans);
                if (rc)
                        break;
        }
 
  * which can only be partially reconfigured at runtime (and not the TPID).
  * So a switch reset is required.
  */
-int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
+int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
+                          struct switchdev_trans *trans)
 {
        struct sja1105_l2_lookup_params_entry *l2_lookup_params;
        struct sja1105_general_params_entry *general_params;
        u16 tpid, tpid2;
        int rc;
 
-       list_for_each_entry(rule, &priv->flow_block.rules, list) {
-               if (rule->type == SJA1105_RULE_VL) {
-                       dev_err(ds->dev,
-                               "Cannot change VLAN filtering state while VL rules are active\n");
-                       return -EBUSY;
+       if (switchdev_trans_ph_prepare(trans)) {
+               list_for_each_entry(rule, &priv->flow_block.rules, list) {
+                       if (rule->type == SJA1105_RULE_VL) {
+                               dev_err(ds->dev,
+                                       "Cannot change VLAN filtering with active VL rules\n");
+                               return -EBUSY;
+                       }
                }
+
+               return 0;
        }
 
        if (enabled) {
 
        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)
                       ANA_PORT_VLAN_CFG, port);
 
        ocelot_port_set_native_vlan(ocelot, port, ocelot_port->vid);
+
+       return 0;
 }
 EXPORT_SYMBOL(ocelot_port_vlan_filtering);
 
 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);
 }
 
                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);
 
         * VLAN support
         */
        int     (*port_vlan_filtering)(struct dsa_switch *ds, int port,
-                                      bool vlan_filtering);
+                                      bool vlan_filtering,
+                                      struct switchdev_trans *trans);
        int (*port_vlan_prepare)(struct dsa_switch *ds, int port,
                                 const struct switchdev_obj_port_vlan *vlan);
        void (*port_vlan_add)(struct dsa_switch *ds, int port,
 
 void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs);
 void ocelot_adjust_link(struct ocelot *ocelot, int port,
                        struct phy_device *phydev);
-void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
-                               bool vlan_aware);
+int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, bool enabled,
+                              struct switchdev_trans *trans);
 void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state);
 int ocelot_port_bridge_join(struct ocelot *ocelot, int port,
                            struct net_device *bridge);
 
                rcu_read_unlock();
                if (!apply)
                        return -EINVAL;
-
-               return 0;
        }
 
        if (dsa_port_is_vlan_filtering(dp) == vlan_filtering)
                return 0;
 
-       err = ds->ops->port_vlan_filtering(ds, dp->index,
-                                          vlan_filtering);
+       err = ds->ops->port_vlan_filtering(ds, dp->index, vlan_filtering,
+                                          trans);
        if (err)
                return err;
 
-       if (ds->vlan_filtering_is_global)
-               ds->vlan_filtering = vlan_filtering;
-       else
-               dp->vlan_filtering = vlan_filtering;
+       if (switchdev_trans_ph_commit(trans)) {
+               if (ds->vlan_filtering_is_global)
+                       ds->vlan_filtering = vlan_filtering;
+               else
+                       dp->vlan_filtering = vlan_filtering;
+       }
+
        return 0;
 }
 
 
                }
        }
        if (unset_vlan_filtering) {
-               struct switchdev_trans trans = {0};
+               struct switchdev_trans trans;
 
+               trans.ph_prepare = true;
+               err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port),
+                                             false, &trans);
+               if (err && err != EOPNOTSUPP)
+                       return err;
+
+               trans.ph_prepare = false;
                err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port),
                                              false, &trans);
                if (err && err != EOPNOTSUPP)