list_for_each_entry_safe(mlxsw_sp_port_vlan, tmp,
                                 &mlxsw_sp_port->vlans_list, list)
-               mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
+               mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
 }
 
-static struct mlxsw_sp_port_vlan *
+struct mlxsw_sp_port_vlan *
 mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
 {
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
        bool untagged = vid == 1;
        int err;
 
+       mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
+       if (mlxsw_sp_port_vlan)
+               return ERR_PTR(-EEXIST);
+
        err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, true, untagged);
        if (err)
                return ERR_PTR(err);
        }
 
        mlxsw_sp_port_vlan->mlxsw_sp_port = mlxsw_sp_port;
-       mlxsw_sp_port_vlan->ref_count = 1;
        mlxsw_sp_port_vlan->vid = vid;
        list_add(&mlxsw_sp_port_vlan->list, &mlxsw_sp_port->vlans_list);
 
        return ERR_PTR(err);
 }
 
-static void
-mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
+void mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
        u16 vid = mlxsw_sp_port_vlan->vid;
 
-       list_del(&mlxsw_sp_port_vlan->list);
-       kfree(mlxsw_sp_port_vlan);
-       mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
-}
-
-struct mlxsw_sp_port_vlan *
-mlxsw_sp_port_vlan_get(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
-{
-       struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
-
-       mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
-       if (mlxsw_sp_port_vlan) {
-               mlxsw_sp_port_vlan->ref_count++;
-               return mlxsw_sp_port_vlan;
-       }
-
-       return mlxsw_sp_port_vlan_create(mlxsw_sp_port, vid);
-}
-
-void mlxsw_sp_port_vlan_put(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
-{
-       struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
-
-       if (--mlxsw_sp_port_vlan->ref_count != 0)
-               return;
-
        if (mlxsw_sp_port_vlan->bridge_port)
                mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan);
-       else if (fid)
+       else if (mlxsw_sp_port_vlan->fid)
                mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
 
-       mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
+       list_del(&mlxsw_sp_port_vlan->list);
+       kfree(mlxsw_sp_port_vlan);
+       mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
 }
 
 static int mlxsw_sp_port_add_vid(struct net_device *dev,
        if (!vid)
                return 0;
 
-       return PTR_ERR_OR_ZERO(mlxsw_sp_port_vlan_get(mlxsw_sp_port, vid));
+       return PTR_ERR_OR_ZERO(mlxsw_sp_port_vlan_create(mlxsw_sp_port, vid));
 }
 
 static int mlxsw_sp_port_kill_vid(struct net_device *dev,
        mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
        if (!mlxsw_sp_port_vlan)
                return 0;
-       mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
+       mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
 
        return 0;
 }
                goto err_port_nve_init;
        }
 
-       mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_get(mlxsw_sp_port, 1);
+       mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port, 1);
        if (IS_ERR(mlxsw_sp_port_vlan)) {
                dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to create VID 1\n",
                        mlxsw_sp_port->local_port);
                err = PTR_ERR(mlxsw_sp_port_vlan);
-               goto err_port_vlan_get;
+               goto err_port_vlan_create;
        }
 
        mlxsw_sp_port_switchdev_init(mlxsw_sp_port);
 err_register_netdev:
        mlxsw_sp->ports[local_port] = NULL;
        mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
-       mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
-err_port_vlan_get:
+       mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
+err_port_vlan_create:
        mlxsw_sp_port_nve_fini(mlxsw_sp_port);
 err_port_nve_init:
        mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
        mlxsw_sp_port->lagged = 0;
        lag->ref_count--;
 
-       mlxsw_sp_port_vlan_get(mlxsw_sp_port, 1);
+       mlxsw_sp_port_vlan_create(mlxsw_sp_port, 1);
        /* Make sure untagged frames are allowed to ingress */
        mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
 }
 
        struct list_head list;
        struct mlxsw_sp_port *mlxsw_sp_port;
        struct mlxsw_sp_fid *fid;
-       unsigned int ref_count;
        u16 vid;
        struct mlxsw_sp_bridge_port *bridge_port;
        struct list_head bridge_vlan_node;
                                   bool learn_enable);
 int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
 struct mlxsw_sp_port_vlan *
-mlxsw_sp_port_vlan_get(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
-void mlxsw_sp_port_vlan_put(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
+mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
+void mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
 int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin,
                           u16 vid_end, bool is_member, bool untagged);
 int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
 
        int err;
 
        /* No need to continue if only VLAN flags were changed */
-       if (mlxsw_sp_port_vlan->bridge_port) {
-               mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
+       if (mlxsw_sp_port_vlan->bridge_port)
                return 0;
-       }
 
        err = mlxsw_sp_port_vlan_fid_join(mlxsw_sp_port_vlan, bridge_port,
                                          extack);
 mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
                              struct mlxsw_sp_bridge_port *bridge_port,
                              u16 vid, bool is_untagged, bool is_pvid,
-                             struct netlink_ext_ack *extack)
+                             struct netlink_ext_ack *extack,
+                             struct switchdev_trans *trans)
 {
        u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid);
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
        u16 old_pvid = mlxsw_sp_port->pvid;
        int err;
 
-       mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_get(mlxsw_sp_port, vid);
-       if (IS_ERR(mlxsw_sp_port_vlan))
-               return PTR_ERR(mlxsw_sp_port_vlan);
+       /* The only valid scenario in which a port-vlan already exists, is if
+        * the VLAN flags were changed and the port-vlan is associated with the
+        * correct bridge port
+        */
+       mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
+       if (mlxsw_sp_port_vlan &&
+           mlxsw_sp_port_vlan->bridge_port != bridge_port)
+               return -EEXIST;
+
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
+       if (!mlxsw_sp_port_vlan) {
+               mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port,
+                                                              vid);
+               if (IS_ERR(mlxsw_sp_port_vlan))
+                       return PTR_ERR(mlxsw_sp_port_vlan);
+       }
 
        err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, true,
                                     is_untagged);
 err_port_pvid_set:
        mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
 err_port_vlan_set:
-       mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
+       mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
        return err;
 }
 
                return err;
        }
 
-       if (switchdev_trans_ph_prepare(trans))
-               return 0;
-
        bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
        if (WARN_ON(!bridge_port))
                return -EINVAL;
 
                err = mlxsw_sp_bridge_port_vlan_add(mlxsw_sp_port, bridge_port,
                                                    vid, flag_untagged,
-                                                   flag_pvid, extack);
+                                                   flag_pvid, extack, trans);
                if (err)
                        return err;
        }
        mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan);
        mlxsw_sp_port_pvid_set(mlxsw_sp_port, pvid);
        mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
-       mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
+       mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
 }
 
 static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
                return -EINVAL;
 
        /* Let VLAN-aware bridge take care of its own VLANs */
-       mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
+       mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
 
        return 0;
 }
                                 struct mlxsw_sp_bridge_port *bridge_port,
                                 struct mlxsw_sp_port *mlxsw_sp_port)
 {
-       mlxsw_sp_port_vlan_get(mlxsw_sp_port, 1);
+       mlxsw_sp_port_vlan_create(mlxsw_sp_port, 1);
        /* Make sure untagged frames are allowed to ingress */
        mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
 }