net: mscc: ocelot: deny changing the native VLAN from the prepare phase
[platform/kernel/linux-starfive.git] / drivers / net / ethernet / mscc / ocelot_net.c
index b34da11..c65ae6f 100644 (file)
@@ -206,6 +206,17 @@ static void ocelot_port_adjust_link(struct net_device *dev)
        ocelot_adjust_link(ocelot, port, dev->phydev);
 }
 
+static int ocelot_vlan_vid_prepare(struct net_device *dev, u16 vid, bool pvid,
+                                  bool untagged)
+{
+       struct ocelot_port_private *priv = netdev_priv(dev);
+       struct ocelot_port *ocelot_port = &priv->port;
+       struct ocelot *ocelot = ocelot_port->ocelot;
+       int port = priv->chip_port;
+
+       return ocelot_vlan_prepare(ocelot, port, vid, pvid, untagged);
+}
+
 static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid,
                               bool untagged)
 {
@@ -409,7 +420,7 @@ static int ocelot_mc_unsync(struct net_device *dev, const unsigned char *addr)
        struct ocelot_port *ocelot_port = &priv->port;
        struct ocelot *ocelot = ocelot_port->ocelot;
 
-       return ocelot_mact_forget(ocelot, addr, ocelot_port->pvid);
+       return ocelot_mact_forget(ocelot, addr, ocelot_port->pvid_vlan.vid);
 }
 
 static int ocelot_mc_sync(struct net_device *dev, const unsigned char *addr)
@@ -418,8 +429,8 @@ static int ocelot_mc_sync(struct net_device *dev, const unsigned char *addr)
        struct ocelot_port *ocelot_port = &priv->port;
        struct ocelot *ocelot = ocelot_port->ocelot;
 
-       return ocelot_mact_learn(ocelot, PGID_CPU, addr, ocelot_port->pvid,
-                                ENTRYTYPE_LOCKED);
+       return ocelot_mact_learn(ocelot, PGID_CPU, addr,
+                                ocelot_port->pvid_vlan.vid, ENTRYTYPE_LOCKED);
 }
 
 static void ocelot_set_rx_mode(struct net_device *dev)
@@ -462,10 +473,10 @@ static int ocelot_port_set_mac_address(struct net_device *dev, void *p)
        const struct sockaddr *addr = p;
 
        /* Learn the new net device MAC address in the mac table. */
-       ocelot_mact_learn(ocelot, PGID_CPU, addr->sa_data, ocelot_port->pvid,
-                         ENTRYTYPE_LOCKED);
+       ocelot_mact_learn(ocelot, PGID_CPU, addr->sa_data,
+                         ocelot_port->pvid_vlan.vid, ENTRYTYPE_LOCKED);
        /* Then forget the previous one. */
-       ocelot_mact_forget(ocelot, dev->dev_addr, ocelot_port->pvid);
+       ocelot_mact_forget(ocelot, dev->dev_addr, ocelot_port->pvid_vlan.vid);
 
        ether_addr_copy(dev->dev_addr, addr->sa_data);
        return 0;
@@ -812,9 +823,14 @@ static int ocelot_port_obj_add_vlan(struct net_device *dev,
        u16 vid;
 
        for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
-               ret = ocelot_vlan_vid_add(dev, vid,
-                                         vlan->flags & BRIDGE_VLAN_INFO_PVID,
-                                         vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
+               bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+               bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
+
+               if (switchdev_trans_ph_prepare(trans))
+                       ret = ocelot_vlan_vid_prepare(dev, vid, pvid,
+                                                     untagged);
+               else
+                       ret = ocelot_vlan_vid_add(dev, vid, pvid, untagged);
                if (ret)
                        return ret;
        }
@@ -1074,8 +1090,8 @@ int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target,
 
        memcpy(dev->dev_addr, ocelot->base_mac, ETH_ALEN);
        dev->dev_addr[ETH_ALEN - 1] += port;
-       ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, ocelot_port->pvid,
-                         ENTRYTYPE_LOCKED);
+       ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr,
+                         ocelot_port->pvid_vlan.vid, ENTRYTYPE_LOCKED);
 
        ocelot_init_port(ocelot, port);