diff options
Diffstat (limited to 'target/linux/layerscape/patches-5.4/701-net-0238-net-mscc-ocelot-break-apart-ocelot_vlan_port_apply.patch')
-rw-r--r-- | target/linux/layerscape/patches-5.4/701-net-0238-net-mscc-ocelot-break-apart-ocelot_vlan_port_apply.patch | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/701-net-0238-net-mscc-ocelot-break-apart-ocelot_vlan_port_apply.patch b/target/linux/layerscape/patches-5.4/701-net-0238-net-mscc-ocelot-break-apart-ocelot_vlan_port_apply.patch new file mode 100644 index 0000000000..42ea2851e9 --- /dev/null +++ b/target/linux/layerscape/patches-5.4/701-net-0238-net-mscc-ocelot-break-apart-ocelot_vlan_port_apply.patch @@ -0,0 +1,314 @@ +From d00ac78e74e433109307f365ba90d34cd73aaf20 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean <vladimir.oltean@nxp.com> +Date: Sat, 9 Nov 2019 15:02:47 +0200 +Subject: [PATCH] net: mscc: ocelot: break apart ocelot_vlan_port_apply + +This patch transforms the ocelot_vlan_port_apply function ("apply +what?") into 3 standalone functions: + +- ocelot_port_vlan_filtering +- ocelot_port_set_native_vlan +- ocelot_port_set_pvid + +These functions have a prototype that is better aligned to the DSA API. + +The function also had some static initialization (TPID, drop frames with +multicast source MAC) which was not being changed from any place, so +that was just moved to ocelot_probe_port (one of the 6 callers of +ocelot_vlan_port_apply). + +Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/mscc/ocelot.c | 168 ++++++++++++++++++++++--------------- + 1 file changed, 100 insertions(+), 68 deletions(-) + +--- a/drivers/net/ethernet/mscc/ocelot.c ++++ b/drivers/net/ethernet/mscc/ocelot.c +@@ -185,65 +185,97 @@ static void ocelot_vlan_mode(struct ocel + ocelot_write(ocelot, val, ANA_VLANMASK); + } + +-static void ocelot_vlan_port_apply(struct ocelot *ocelot, +- struct ocelot_port *port) ++static void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, ++ bool vlan_aware) + { ++ struct ocelot_port *ocelot_port = ocelot->ports[port]; + u32 val; + +- /* Ingress clasification (ANA_PORT_VLAN_CFG) */ +- /* Default vlan to clasify for untagged frames (may be zero) */ +- val = ANA_PORT_VLAN_CFG_VLAN_VID(port->pvid); +- if (port->vlan_aware) +- val |= ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA | +- ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1); +- ++ if (vlan_aware) ++ val = ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA | ++ ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1); ++ else ++ val = 0; + ocelot_rmw_gix(ocelot, val, +- ANA_PORT_VLAN_CFG_VLAN_VID_M | + ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA | + ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M, +- ANA_PORT_VLAN_CFG, port->chip_port); ++ ANA_PORT_VLAN_CFG, port); + +- /* Drop frames with multicast source address */ +- val = ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA; +- if (port->vlan_aware && !port->vid) ++ if (vlan_aware && !ocelot_port->vid) + /* If port is vlan-aware and tagged, drop untagged and priority + * tagged frames. + */ +- val |= ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA | ++ val = ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA | ++ ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA | ++ ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA; ++ else ++ val = 0; ++ ocelot_rmw_gix(ocelot, val, ++ ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA | + ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA | +- ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA; +- ocelot_write_gix(ocelot, val, ANA_PORT_DROP_CFG, port->chip_port); +- +- /* Egress configuration (REW_TAG_CFG): VLAN tag type to 8021Q. */ +- val = REW_TAG_CFG_TAG_TPID_CFG(0); ++ ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA, ++ ANA_PORT_DROP_CFG, port); + +- if (port->vlan_aware) { +- if (port->vid) ++ if (vlan_aware) { ++ if (ocelot_port->vid) + /* Tag all frames except when VID == DEFAULT_VLAN */ + val |= REW_TAG_CFG_TAG_CFG(1); + else + /* Tag all frames */ + val |= REW_TAG_CFG_TAG_CFG(3); ++ } else { ++ /* Port tagging disabled. */ ++ val = REW_TAG_CFG_TAG_CFG(0); + } + ocelot_rmw_gix(ocelot, val, +- REW_TAG_CFG_TAG_TPID_CFG_M | + REW_TAG_CFG_TAG_CFG_M, +- REW_TAG_CFG, port->chip_port); ++ REW_TAG_CFG, port); + +- /* Set default VLAN and tag type to 8021Q. */ +- val = REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021Q) | +- REW_PORT_VLAN_CFG_PORT_VID(port->vid); +- ocelot_rmw_gix(ocelot, val, +- REW_PORT_VLAN_CFG_PORT_TPID_M | ++ ocelot_port->vlan_aware = vlan_aware; ++} ++ ++static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port, ++ u16 vid) ++{ ++ struct ocelot_port *ocelot_port = ocelot->ports[port]; ++ ++ if (ocelot_port->vid != vid) { ++ /* Always permit deleting the native VLAN (vid = 0) */ ++ if (ocelot_port->vid && vid) { ++ dev_err(ocelot->dev, ++ "Port already has a native VLAN: %d\n", ++ ocelot_port->vid); ++ return -EBUSY; ++ } ++ ocelot_port->vid = vid; ++ } ++ ++ ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid), + REW_PORT_VLAN_CFG_PORT_VID_M, +- REW_PORT_VLAN_CFG, port->chip_port); ++ REW_PORT_VLAN_CFG, port); ++ ++ return 0; ++} ++ ++/* Default vlan to clasify for untagged frames (may be zero) */ ++static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, u16 pvid) ++{ ++ struct ocelot_port *ocelot_port = ocelot->ports[port]; ++ ++ ocelot_rmw_gix(ocelot, ++ ANA_PORT_VLAN_CFG_VLAN_VID(pvid), ++ ANA_PORT_VLAN_CFG_VLAN_VID_M, ++ ANA_PORT_VLAN_CFG, port); ++ ++ ocelot_port->pvid = pvid; + } + + static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid, + bool untagged) + { +- struct ocelot_port *port = netdev_priv(dev); +- struct ocelot *ocelot = port->ocelot; ++ struct ocelot_port *ocelot_port = netdev_priv(dev); ++ struct ocelot *ocelot = ocelot_port->ocelot; ++ int port = ocelot_port->chip_port; + int ret; + + /* Add the port MAC address to with the right VLAN information */ +@@ -251,35 +283,30 @@ static int ocelot_vlan_vid_add(struct ne + ENTRYTYPE_LOCKED); + + /* Make the port a member of the VLAN */ +- ocelot->vlan_mask[vid] |= BIT(port->chip_port); ++ ocelot->vlan_mask[vid] |= BIT(port); + ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]); + if (ret) + return ret; + + /* Default ingress vlan classification */ + if (pvid) +- port->pvid = vid; ++ ocelot_port_set_pvid(ocelot, port, vid); + + /* Untagged egress vlan clasification */ +- if (untagged && port->vid != vid) { +- if (port->vid) { +- dev_err(ocelot->dev, +- "Port already has a native VLAN: %d\n", +- port->vid); +- return -EBUSY; +- } +- port->vid = vid; ++ if (untagged) { ++ ret = ocelot_port_set_native_vlan(ocelot, port, vid); ++ if (ret) ++ return ret; + } + +- ocelot_vlan_port_apply(ocelot, port); +- + return 0; + } + + static int ocelot_vlan_vid_del(struct net_device *dev, u16 vid) + { +- struct ocelot_port *port = netdev_priv(dev); +- struct ocelot *ocelot = port->ocelot; ++ struct ocelot_port *ocelot_port = netdev_priv(dev); ++ struct ocelot *ocelot = ocelot_port->ocelot; ++ int port = ocelot_port->chip_port; + int ret; + + /* 8021q removes VID 0 on module unload for all interfaces +@@ -293,20 +320,18 @@ static int ocelot_vlan_vid_del(struct ne + ocelot_mact_forget(ocelot, dev->dev_addr, vid); + + /* Stop the port from being a member of the vlan */ +- ocelot->vlan_mask[vid] &= ~BIT(port->chip_port); ++ ocelot->vlan_mask[vid] &= ~BIT(port); + ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]); + if (ret) + return ret; + + /* Ingress */ +- if (port->pvid == vid) +- port->pvid = 0; ++ if (ocelot_port->pvid == vid) ++ ocelot_port_set_pvid(ocelot, port, 0); + + /* Egress */ +- if (port->vid == vid) +- port->vid = 0; +- +- ocelot_vlan_port_apply(ocelot, port); ++ if (ocelot_port->vid == vid) ++ ocelot_port_set_native_vlan(ocelot, port, 0); + + return 0; + } +@@ -1306,6 +1331,7 @@ static int ocelot_port_attr_set(struct n + struct switchdev_trans *trans) + { + struct ocelot_port *ocelot_port = netdev_priv(dev); ++ struct ocelot *ocelot = ocelot_port->ocelot; + int err = 0; + + switch (attr->id) { +@@ -1317,8 +1343,8 @@ static int ocelot_port_attr_set(struct n + ocelot_port_attr_ageing_set(ocelot_port, attr->u.ageing_time); + break; + case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: +- ocelot_port->vlan_aware = attr->u.vlan_filtering; +- ocelot_vlan_port_apply(ocelot_port->ocelot, ocelot_port); ++ ocelot_port_vlan_filtering(ocelot, ocelot_port->chip_port, ++ attr->u.vlan_filtering); + break; + case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED: + ocelot_port_attr_mc_set(ocelot_port, !attr->u.mc_disabled); +@@ -1520,20 +1546,20 @@ static int ocelot_port_bridge_join(struc + return 0; + } + +-static void ocelot_port_bridge_leave(struct ocelot_port *ocelot_port, +- struct net_device *bridge) ++static int ocelot_port_bridge_leave(struct ocelot_port *ocelot_port, ++ struct net_device *bridge) + { + struct ocelot *ocelot = ocelot_port->ocelot; ++ int port = ocelot_port->chip_port; + +- ocelot->bridge_mask &= ~BIT(ocelot_port->chip_port); ++ ocelot->bridge_mask &= ~BIT(port); + + if (!ocelot->bridge_mask) + ocelot->hw_bridge_dev = NULL; + +- /* Clear bridge vlan settings before calling ocelot_vlan_port_apply */ +- ocelot_port->vlan_aware = 0; +- ocelot_port->pvid = 0; +- ocelot_port->vid = 0; ++ ocelot_port_vlan_filtering(ocelot, port, 0); ++ ocelot_port_set_pvid(ocelot, port, 0); ++ return ocelot_port_set_native_vlan(ocelot, port, 0); + } + + static void ocelot_set_aggr_pgids(struct ocelot *ocelot) +@@ -1687,11 +1713,8 @@ static int ocelot_netdevice_port_event(s + err = ocelot_port_bridge_join(ocelot_port, + info->upper_dev); + else +- ocelot_port_bridge_leave(ocelot_port, +- info->upper_dev); +- +- ocelot_vlan_port_apply(ocelot_port->ocelot, +- ocelot_port); ++ err = ocelot_port_bridge_leave(ocelot_port, ++ info->upper_dev); + } + if (netif_is_lag_master(info->upper_dev)) { + if (info->linking) +@@ -2011,6 +2034,7 @@ int ocelot_probe_port(struct ocelot *oce + { + struct ocelot_port *ocelot_port; + struct net_device *dev; ++ u32 val; + int err; + + dev = alloc_etherdev(sizeof(struct ocelot_port)); +@@ -2046,7 +2070,15 @@ int ocelot_probe_port(struct ocelot *oce + } + + /* Basic L2 initialization */ +- ocelot_vlan_port_apply(ocelot, ocelot_port); ++ ++ /* Drop frames with multicast source address */ ++ val = ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA; ++ ocelot_rmw_gix(ocelot, val, val, ANA_PORT_DROP_CFG, port); ++ ++ /* Set default VLAN and tag type to 8021Q. */ ++ ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021Q), ++ REW_PORT_VLAN_CFG_PORT_TPID_M, ++ REW_PORT_VLAN_CFG, port); + + /* Enable vcap lookups */ + ocelot_vcap_enable(ocelot, ocelot_port); |