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); diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index b34da11acf65..cf5c2a0ddfc0 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -409,7 +409,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 +418,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 +462,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; @@ -1074,8 +1074,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); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index cc126d1796be..baf6a498f7d1 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -571,18 +571,20 @@ struct ocelot_vcap_block { int pol_lpr; }; +struct ocelot_vlan { + u16 vid; +}; + struct ocelot_port { struct ocelot *ocelot; struct regmap *target; bool vlan_aware; - - /* Ingress default VLAN (pvid) */ - u16 pvid; - - /* Egress default VLAN (vid) */ - u16 vid; + /* VLAN that untagged frames are classified to, on ingress */ + struct ocelot_vlan pvid_vlan; + /* The VLAN ID that will be transmitted as untagged, on egress */ + struct ocelot_vlan native_vlan; u8 ptp_cmd; struct sk_buff_head tx_skbs;