diff options
-rw-r--r-- | drivers/net/ethernet/mscc/ocelot.c | 27 | ||||
-rw-r--r-- | include/soc/mscc/ocelot.h | 1 |
2 files changed, 15 insertions, 13 deletions
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index a7e724ae01f7..d49e34430e23 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -153,22 +153,22 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port, struct ocelot_port *ocelot_port = ocelot->ports[port]; u32 val = 0; - if (ocelot_port->native_vlan.vid != native_vlan.vid) { - /* Always permit deleting the native VLAN (vid = 0) */ - if (ocelot_port->native_vlan.vid && native_vlan.vid) { - dev_err(ocelot->dev, - "Port already has a native VLAN: %d\n", - ocelot_port->native_vlan.vid); - return -EBUSY; - } - ocelot_port->native_vlan = native_vlan; + /* Deny changing the native VLAN, but always permit deleting it */ + if (ocelot_port->native_vlan.vid != native_vlan.vid && + ocelot_port->native_vlan.valid && native_vlan.valid) { + dev_err(ocelot->dev, + "Port already has a native VLAN: %d\n", + ocelot_port->native_vlan.vid); + return -EBUSY; } + ocelot_port->native_vlan = native_vlan; + ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(native_vlan.vid), REW_PORT_VLAN_CFG_PORT_VID_M, REW_PORT_VLAN_CFG, port); - if (ocelot_port->vlan_aware && !ocelot_port->native_vlan.vid) + if (ocelot_port->vlan_aware && !ocelot_port->native_vlan.valid) /* If port is vlan-aware and tagged, drop untagged and priority * tagged frames. */ @@ -182,7 +182,7 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port, ANA_PORT_DROP_CFG, port); if (ocelot_port->vlan_aware) { - if (ocelot_port->native_vlan.vid) + if (native_vlan.valid) /* Tag all frames except when VID == DEFAULT_VLAN */ val = REW_TAG_CFG_TAG_CFG(1); else @@ -273,6 +273,7 @@ int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid, struct ocelot_vlan pvid_vlan; pvid_vlan.vid = vid; + pvid_vlan.valid = true; ocelot_port_set_pvid(ocelot, port, pvid_vlan); } @@ -281,6 +282,7 @@ int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid, struct ocelot_vlan native_vlan; native_vlan.vid = vid; + native_vlan.valid = true; ret = ocelot_port_set_native_vlan(ocelot, port, native_vlan); if (ret) return ret; @@ -303,9 +305,8 @@ int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid) /* Egress */ if (ocelot_port->native_vlan.vid == vid) { - struct ocelot_vlan native_vlan; + struct ocelot_vlan native_vlan = {0}; - native_vlan.vid = 0; ocelot_port_set_native_vlan(ocelot, port, native_vlan); } diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index baf6a498f7d1..67c2af1c4c5c 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -572,6 +572,7 @@ struct ocelot_vcap_block { }; struct ocelot_vlan { + bool valid; u16 vid; }; |