diff options
Diffstat (limited to 'drivers/net/ethernet/mscc/ocelot.c')
-rw-r--r-- | drivers/net/ethernet/mscc/ocelot.c | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index ae25a79bf907..a7e724ae01f7 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -148,27 +148,27 @@ static int ocelot_vlant_set_mask(struct ocelot *ocelot, u16 vid, u32 mask) } static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port, - u16 vid) + struct ocelot_vlan native_vlan) { struct ocelot_port *ocelot_port = ocelot->ports[port]; u32 val = 0; - if (ocelot_port->vid != vid) { + if (ocelot_port->native_vlan.vid != native_vlan.vid) { /* Always permit deleting the native VLAN (vid = 0) */ - if (ocelot_port->vid && vid) { + if (ocelot_port->native_vlan.vid && native_vlan.vid) { dev_err(ocelot->dev, "Port already has a native VLAN: %d\n", - ocelot_port->vid); + ocelot_port->native_vlan.vid); return -EBUSY; } - ocelot_port->vid = vid; + ocelot_port->native_vlan = native_vlan; } - ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid), + 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->vid) + if (ocelot_port->vlan_aware && !ocelot_port->native_vlan.vid) /* 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->vid) + if (ocelot_port->native_vlan.vid) /* Tag all frames except when VID == DEFAULT_VLAN */ val = REW_TAG_CFG_TAG_CFG(1); else @@ -200,17 +200,18 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port, } /* Default vlan to clasify for untagged frames (may be zero) */ -static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, u16 pvid) +static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, + struct ocelot_vlan pvid_vlan) { struct ocelot_port *ocelot_port = ocelot->ports[port]; - ocelot_port->pvid = pvid; + ocelot_port->pvid_vlan = pvid_vlan; if (!ocelot_port->vlan_aware) - pvid = 0; + pvid_vlan.vid = 0; ocelot_rmw_gix(ocelot, - ANA_PORT_VLAN_CFG_VLAN_VID(pvid), + ANA_PORT_VLAN_CFG_VLAN_VID(pvid_vlan.vid), ANA_PORT_VLAN_CFG_VLAN_VID_M, ANA_PORT_VLAN_CFG, port); } @@ -249,8 +250,8 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M, ANA_PORT_VLAN_CFG, port); - ocelot_port_set_pvid(ocelot, port, ocelot_port->pvid); - ocelot_port_set_native_vlan(ocelot, port, ocelot_port->vid); + ocelot_port_set_pvid(ocelot, port, ocelot_port->pvid_vlan); + ocelot_port_set_native_vlan(ocelot, port, ocelot_port->native_vlan); return 0; } @@ -268,12 +269,19 @@ int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid, return ret; /* Default ingress vlan classification */ - if (pvid) - ocelot_port_set_pvid(ocelot, port, vid); + if (pvid) { + struct ocelot_vlan pvid_vlan; + + pvid_vlan.vid = vid; + ocelot_port_set_pvid(ocelot, port, pvid_vlan); + } /* Untagged egress vlan clasification */ if (untagged) { - ret = ocelot_port_set_native_vlan(ocelot, port, vid); + struct ocelot_vlan native_vlan; + + native_vlan.vid = vid; + ret = ocelot_port_set_native_vlan(ocelot, port, native_vlan); if (ret) return ret; } @@ -294,8 +302,12 @@ int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid) return ret; /* Egress */ - if (ocelot_port->vid == vid) - ocelot_port_set_native_vlan(ocelot, port, 0); + if (ocelot_port->native_vlan.vid == vid) { + struct ocelot_vlan native_vlan; + + native_vlan.vid = 0; + ocelot_port_set_native_vlan(ocelot, port, native_vlan); + } return 0; } @@ -1151,6 +1163,7 @@ EXPORT_SYMBOL(ocelot_port_bridge_join); int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, struct net_device *bridge) { + struct ocelot_vlan pvid = {0}, native_vlan = {0}; struct switchdev_trans trans; int ret; @@ -1169,8 +1182,8 @@ int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, if (ret) return ret; - ocelot_port_set_pvid(ocelot, port, 0); - return ocelot_port_set_native_vlan(ocelot, port, 0); + ocelot_port_set_pvid(ocelot, port, pvid); + return ocelot_port_set_native_vlan(ocelot, port, native_vlan); } EXPORT_SYMBOL(ocelot_port_bridge_leave); |