netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot
@ 2019-11-09 13:02 Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 01/15] net: mscc: ocelot: break apart ocelot_vlan_port_apply Vladimir Oltean
                   ` (17 more replies)
  0 siblings, 18 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

After the nice "change-my-mind" discussion about Ocelot, Felix and
LS1028A (which can be read here: https://lkml.org/lkml/2019/6/21/630),
we have decided to take the route of reworking the Ocelot implementation
in a way that is DSA-compatible.

This is a large series, but hopefully is easy enough to digest, since it
contains mostly code refactoring. What needs to be changed:
- The struct net_device, phy_device needs to be isolated from Ocelot
  private structures (struct ocelot, struct ocelot_port). These will
  live as 1-to-1 equivalents to struct dsa_switch and struct dsa_port.
- The function prototypes need to be compatible with DSA (of course,
  struct dsa_switch will become struct ocelot).
- The CPU port needs to be assigned via a higher-level API, not
  hardcoded in the driver.

What is going to be interesting is that the new DSA front-end of Ocelot
will need to have features in lockstep with the DSA core itself. At the
moment, some more advanced tc offloading features of Ocelot (tc-flower,
etc) are not available in the DSA front-end due to lack of API in the
DSA core. It also means that Ocelot practically re-implements large
parts of DSA (although it is not a DSA switch per se) - see the FDB API
for example.

The code has been only compile-tested on Ocelot, since I don't have
access to any VSC7514 hardware. It was proven to work on NXP LS1028A,
which instantiates a DSA derivative of Ocelot. So I would like to ask
Alex Belloni if you could confirm this series causes no regression on
the Ocelot MIPS SoC.

The goal is to get this rework upstream as quickly as possible,
precisely because it is a large volume of code that risks gaining merge
conflicts if we keep it for too long.

This is but the first chunk of the LS1028A Felix DSA driver upstreaming.
For those who are interested, the concept can be seen on my private
Github repo, the user of this reworked Ocelot driver living under
drivers/net/dsa/vitesse/:
https://github.com/vladimiroltean/ls1028ardb-linux

Claudiu Manoil (1):
  net: mscc: ocelot: initialize list of multicast addresses in common
    code

Vladimir Oltean (14):
  net: mscc: ocelot: break apart ocelot_vlan_port_apply
  net: mscc: ocelot: break apart vlan operations into
    ocelot_vlan_{add,del}
  net: mscc: ocelot: break out fdb operations into abstract
    implementations
  net: mscc: ocelot: change prototypes of hwtstamping ioctls
  net: mscc: ocelot: change prototypes of switchdev port attribute
    handlers
  net: mscc: ocelot: refactor struct ocelot_port out of function
    prototypes
  net: mscc: ocelot: separate net_device related items out of
    ocelot_port
  net: mscc: ocelot: refactor ethtool callbacks
  net: mscc: ocelot: limit vlan ingress filtering to actual number of
    ports
  net: mscc: ocelot: move port initialization into separate function
  net: mscc: ocelot: separate the common implementation of ndo_open and
    ndo_stop
  net: mscc: ocelot: refactor adjust_link into a netdev-independent
    function
  net: mscc: ocelot: split assignment of the cpu port into a separate
    function
  net: mscc: ocelot: don't hardcode the number of the CPU port

 drivers/net/ethernet/mscc/ocelot.c        | 948 +++++++++++++---------
 drivers/net/ethernet/mscc/ocelot.h        |  33 +-
 drivers/net/ethernet/mscc/ocelot_ace.h    |   4 +-
 drivers/net/ethernet/mscc/ocelot_board.c  |  24 +-
 drivers/net/ethernet/mscc/ocelot_flower.c |  32 +-
 drivers/net/ethernet/mscc/ocelot_police.c |  36 +-
 drivers/net/ethernet/mscc/ocelot_police.h |   4 +-
 drivers/net/ethernet/mscc/ocelot_tc.c     |  56 +-
 8 files changed, 680 insertions(+), 457 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH net-next 01/15] net: mscc: ocelot: break apart ocelot_vlan_port_apply
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 02/15] net: mscc: ocelot: break apart vlan operations into ocelot_vlan_{add,del} Vladimir Oltean
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

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>
---
 drivers/net/ethernet/mscc/ocelot.c | 168 +++++++++++++++++------------
 1 file changed, 100 insertions(+), 68 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 672ea1342add..029c5ea59e35 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -185,65 +185,97 @@ static void ocelot_vlan_mode(struct ocelot_port *port,
 	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 net_device *dev, u16 vid, bool pvid,
 			  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 net_device *dev, u16 vid)
 	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 net_device *dev,
 				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 net_device *dev,
 		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(struct ocelot_port *ocelot_port,
 	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(struct net_device *dev,
 				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)
@@ -2007,6 +2030,7 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 {
 	struct ocelot_port *ocelot_port;
 	struct net_device *dev;
+	u32 val;
 	int err;
 
 	dev = alloc_etherdev(sizeof(struct ocelot_port));
@@ -2042,7 +2066,15 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 	}
 
 	/* 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);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 02/15] net: mscc: ocelot: break apart vlan operations into ocelot_vlan_{add,del}
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 01/15] net: mscc: ocelot: break apart ocelot_vlan_port_apply Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 03/15] net: mscc: ocelot: break out fdb operations into abstract implementations Vladimir Oltean
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

We need an implementation of these functions that is agnostic to the
higher layer (switchdev or dsa).

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 60 +++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 029c5ea59e35..5b9cde6d3e38 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -270,18 +270,11 @@ static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, u16 pvid)
 	ocelot_port->pvid = pvid;
 }
 
-static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid,
-			       bool untagged)
+static int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
+			   bool untagged)
 {
-	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 */
-	ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, vid,
-			  ENTRYTYPE_LOCKED);
-
 	/* Make the port a member of the VLAN */
 	ocelot->vlan_mask[vid] |= BIT(port);
 	ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
@@ -302,22 +295,29 @@ static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid,
 	return 0;
 }
 
-static int ocelot_vlan_vid_del(struct net_device *dev, u16 vid)
+static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid,
+			       bool untagged)
 {
 	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
-	 * with VLAN filtering feature. We need to keep it to receive
-	 * untagged traffic.
-	 */
-	if (vid == 0)
-		return 0;
+	ret = ocelot_vlan_add(ocelot, port, vid, pvid, untagged);
+	if (ret)
+		return ret;
 
-	/* Del the port MAC address to with the right VLAN information */
-	ocelot_mact_forget(ocelot, dev->dev_addr, vid);
+	/* Add the port MAC address to with the right VLAN information */
+	ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, vid,
+			  ENTRYTYPE_LOCKED);
+
+	return 0;
+}
+
+static int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid)
+{
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
+	int ret;
 
 	/* Stop the port from being a member of the vlan */
 	ocelot->vlan_mask[vid] &= ~BIT(port);
@@ -336,6 +336,30 @@ static int ocelot_vlan_vid_del(struct net_device *dev, u16 vid)
 	return 0;
 }
 
+static int ocelot_vlan_vid_del(struct net_device *dev, u16 vid)
+{
+	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
+	 * with VLAN filtering feature. We need to keep it to receive
+	 * untagged traffic.
+	 */
+	if (vid == 0)
+		return 0;
+
+	ret = ocelot_vlan_del(ocelot, port, vid);
+	if (ret)
+		return ret;
+
+	/* Del the port MAC address to with the right VLAN information */
+	ocelot_mact_forget(ocelot, dev->dev_addr, vid);
+
+	return 0;
+}
+
 static void ocelot_vlan_init(struct ocelot *ocelot)
 {
 	u16 port, vid;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 03/15] net: mscc: ocelot: break out fdb operations into abstract implementations
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 01/15] net: mscc: ocelot: break apart ocelot_vlan_port_apply Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 02/15] net: mscc: ocelot: break apart vlan operations into ocelot_vlan_{add,del} Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 04/15] net: mscc: ocelot: change prototypes of hwtstamping ioctls Vladimir Oltean
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

To be able to implement a DSA front-end over ocelot_fdb_add,
ocelot_fdb_del, ocelot_fdb_dump, these need to have a simple function
prototype that is independent of struct net_device, netlink skb, etc.

So rename the ndo ops of the ocelot driver into
ocelot_port_fdb_{add,del,dump}, and have them all call the abstract
implementations. At the same time, refactor ocelot_port_fdb_do_dump into
a function whose prototype is compatible with dsa_fdb_dump_cb_t, so that
the do_dump implementations can live together and be called by the
ocelot_fdb_dump through a function pointer.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 124 ++++++++++++++++++-----------
 1 file changed, 78 insertions(+), 46 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 5b9cde6d3e38..3e03c4dd80a0 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -21,6 +21,7 @@
 #include <net/netevent.h>
 #include <net/rtnetlink.h>
 #include <net/switchdev.h>
+#include <net/dsa.h>
 
 #include "ocelot.h"
 #include "ocelot_ace.h"
@@ -814,21 +815,18 @@ static void ocelot_get_stats64(struct net_device *dev,
 	stats->collisions = ocelot_read(ocelot, SYS_COUNT_TX_COLLISION);
 }
 
-static int ocelot_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
-			  struct net_device *dev, const unsigned char *addr,
-			  u16 vid, u16 flags,
-			  struct netlink_ext_ack *extack)
+static int ocelot_fdb_add(struct ocelot *ocelot, int port,
+			  const unsigned char *addr, u16 vid)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
 
 	if (!vid) {
-		if (!port->vlan_aware)
+		if (!ocelot_port->vlan_aware)
 			/* If the bridge is not VLAN aware and no VID was
 			 * provided, set it to pvid to ensure the MAC entry
 			 * matches incoming untagged packets
 			 */
-			vid = port->pvid;
+			vid = ocelot_port->pvid;
 		else
 			/* If the bridge is VLAN aware a VID must be provided as
 			 * otherwise the learnt entry wouldn't match any frame.
@@ -836,20 +834,37 @@ static int ocelot_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 			return -EINVAL;
 	}
 
-	return ocelot_mact_learn(ocelot, port->chip_port, addr, vid,
-				 ENTRYTYPE_LOCKED);
+	return ocelot_mact_learn(ocelot, port, addr, vid, ENTRYTYPE_LOCKED);
 }
 
-static int ocelot_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
-			  struct net_device *dev,
-			  const unsigned char *addr, u16 vid)
+static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
+			       struct net_device *dev,
+			       const unsigned char *addr,
+			       u16 vid, u16 flags,
+			       struct netlink_ext_ack *extack)
 {
-	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;
+
+	return ocelot_fdb_add(ocelot, ocelot_port->chip_port, addr, vid);
+}
 
+static int ocelot_fdb_del(struct ocelot *ocelot, int port,
+			  const unsigned char *addr, u16 vid)
+{
 	return ocelot_mact_forget(ocelot, addr, vid);
 }
 
+static int ocelot_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
+			       struct net_device *dev,
+			       const unsigned char *addr, u16 vid)
+{
+	struct ocelot_port *ocelot_port = netdev_priv(dev);
+	struct ocelot *ocelot = ocelot_port->ocelot;
+
+	return ocelot_fdb_del(ocelot, ocelot_port->chip_port, addr, vid);
+}
+
 struct ocelot_dump_ctx {
 	struct net_device *dev;
 	struct sk_buff *skb;
@@ -857,9 +872,10 @@ struct ocelot_dump_ctx {
 	int idx;
 };
 
-static int ocelot_fdb_do_dump(struct ocelot_mact_entry *entry,
-			      struct ocelot_dump_ctx *dump)
+static int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,
+				   bool is_static, void *data)
 {
+	struct ocelot_dump_ctx *dump = data;
 	u32 portid = NETLINK_CB(dump->cb->skb).portid;
 	u32 seq = dump->cb->nlh->nlmsg_seq;
 	struct nlmsghdr *nlh;
@@ -880,12 +896,12 @@ static int ocelot_fdb_do_dump(struct ocelot_mact_entry *entry,
 	ndm->ndm_flags   = NTF_SELF;
 	ndm->ndm_type    = 0;
 	ndm->ndm_ifindex = dump->dev->ifindex;
-	ndm->ndm_state   = NUD_REACHABLE;
+	ndm->ndm_state   = is_static ? NUD_NOARP : NUD_REACHABLE;
 
-	if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, entry->mac))
+	if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, addr))
 		goto nla_put_failure;
 
-	if (entry->vid && nla_put_u16(dump->skb, NDA_VLAN, entry->vid))
+	if (vid && nla_put_u16(dump->skb, NDA_VLAN, vid))
 		goto nla_put_failure;
 
 	nlmsg_end(dump->skb, nlh);
@@ -899,12 +915,11 @@ static int ocelot_fdb_do_dump(struct ocelot_mact_entry *entry,
 	return -EMSGSIZE;
 }
 
-static inline int ocelot_mact_read(struct ocelot_port *port, int row, int col,
-				   struct ocelot_mact_entry *entry)
+static int ocelot_mact_read(struct ocelot *ocelot, int port, int row, int col,
+			    struct ocelot_mact_entry *entry)
 {
-	struct ocelot *ocelot = port->ocelot;
-	char mac[ETH_ALEN];
 	u32 val, dst, macl, mach;
+	char mac[ETH_ALEN];
 
 	/* Set row and column to read from */
 	ocelot_field_write(ocelot, ANA_TABLES_MACTINDX_M_INDEX, row);
@@ -927,7 +942,7 @@ static inline int ocelot_mact_read(struct ocelot_port *port, int row, int col,
 	 * do not report it.
 	 */
 	dst = (val & ANA_TABLES_MACACCESS_DEST_IDX_M) >> 3;
-	if (dst != port->chip_port)
+	if (dst != port)
 		return -EINVAL;
 
 	/* Get the entry's MAC address and VLAN id */
@@ -947,43 +962,60 @@ static inline int ocelot_mact_read(struct ocelot_port *port, int row, int col,
 	return 0;
 }
 
-static int ocelot_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
-			   struct net_device *dev,
-			   struct net_device *filter_dev, int *idx)
+static int ocelot_fdb_dump(struct ocelot *ocelot, int port,
+			   dsa_fdb_dump_cb_t *cb, void *data)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	int i, j, ret = 0;
-	struct ocelot_dump_ctx dump = {
-		.dev = dev,
-		.skb = skb,
-		.cb = cb,
-		.idx = *idx,
-	};
-
-	struct ocelot_mact_entry entry;
+	int i, j;
 
 	/* Loop through all the mac tables entries. There are 1024 rows of 4
 	 * entries.
 	 */
 	for (i = 0; i < 1024; i++) {
 		for (j = 0; j < 4; j++) {
-			ret = ocelot_mact_read(port, i, j, &entry);
+			struct ocelot_mact_entry entry;
+			bool is_static;
+			int ret;
+
+			ret = ocelot_mact_read(ocelot, port, i, j, &entry);
 			/* If the entry is invalid (wrong port, invalid...),
 			 * skip it.
 			 */
 			if (ret == -EINVAL)
 				continue;
 			else if (ret)
-				goto end;
+				return ret;
+
+			is_static = (entry.type == ENTRYTYPE_LOCKED);
 
-			ret = ocelot_fdb_do_dump(&entry, &dump);
+			ret = cb(entry.mac, entry.vid, is_static, data);
 			if (ret)
-				goto end;
+				return ret;
 		}
 	}
 
-end:
+	return 0;
+}
+
+static int ocelot_port_fdb_dump(struct sk_buff *skb,
+				struct netlink_callback *cb,
+				struct net_device *dev,
+				struct net_device *filter_dev, int *idx)
+{
+	struct ocelot_port *ocelot_port = netdev_priv(dev);
+	struct ocelot *ocelot = ocelot_port->ocelot;
+	struct ocelot_dump_ctx dump = {
+		.dev = dev,
+		.skb = skb,
+		.cb = cb,
+		.idx = *idx,
+	};
+	int ret;
+
+	ret = ocelot_fdb_dump(ocelot, ocelot_port->chip_port,
+			      ocelot_port_fdb_do_dump, &dump);
+
 	*idx = dump.idx;
+
 	return ret;
 }
 
@@ -1129,9 +1161,9 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
 	.ndo_get_phys_port_name		= ocelot_port_get_phys_port_name,
 	.ndo_set_mac_address		= ocelot_port_set_mac_address,
 	.ndo_get_stats64		= ocelot_get_stats64,
-	.ndo_fdb_add			= ocelot_fdb_add,
-	.ndo_fdb_del			= ocelot_fdb_del,
-	.ndo_fdb_dump			= ocelot_fdb_dump,
+	.ndo_fdb_add			= ocelot_port_fdb_add,
+	.ndo_fdb_del			= ocelot_port_fdb_del,
+	.ndo_fdb_dump			= ocelot_port_fdb_dump,
 	.ndo_vlan_rx_add_vid		= ocelot_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid		= ocelot_vlan_rx_kill_vid,
 	.ndo_set_features		= ocelot_set_features,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 04/15] net: mscc: ocelot: change prototypes of hwtstamping ioctls
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (2 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 03/15] net: mscc: ocelot: break out fdb operations into abstract implementations Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 05/15] net: mscc: ocelot: change prototypes of switchdev port attribute handlers Vladimir Oltean
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

This is needed in order to present a simpler prototype to the DSA
front-end of ocelot.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 3e03c4dd80a0..8b7d46693e49 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1062,17 +1062,17 @@ static int ocelot_get_port_parent_id(struct net_device *dev,
 	return 0;
 }
 
-static int ocelot_hwstamp_get(struct ocelot_port *port, struct ifreq *ifr)
+static int ocelot_hwstamp_get(struct ocelot *ocelot, int port,
+			      struct ifreq *ifr)
 {
-	struct ocelot *ocelot = port->ocelot;
-
 	return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config,
 			    sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0;
 }
 
-static int ocelot_hwstamp_set(struct ocelot_port *port, struct ifreq *ifr)
+static int ocelot_hwstamp_set(struct ocelot *ocelot, int port,
+			      struct ifreq *ifr)
 {
-	struct ocelot *ocelot = port->ocelot;
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
 	struct hwtstamp_config cfg;
 
 	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
@@ -1085,16 +1085,16 @@ static int ocelot_hwstamp_set(struct ocelot_port *port, struct ifreq *ifr)
 	/* Tx type sanity check */
 	switch (cfg.tx_type) {
 	case HWTSTAMP_TX_ON:
-		port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
+		ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
 		break;
 	case HWTSTAMP_TX_ONESTEP_SYNC:
 		/* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
 		 * need to update the origin time.
 		 */
-		port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
+		ocelot_port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
 		break;
 	case HWTSTAMP_TX_OFF:
-		port->ptp_cmd = 0;
+		ocelot_port->ptp_cmd = 0;
 		break;
 	default:
 		return -ERANGE;
@@ -1136,8 +1136,9 @@ static int ocelot_hwstamp_set(struct ocelot_port *port, struct ifreq *ifr)
 
 static int ocelot_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	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;
 
 	/* The function is only used for PTP operations for now */
 	if (!ocelot->ptp)
@@ -1145,9 +1146,9 @@ static int ocelot_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 	switch (cmd) {
 	case SIOCSHWTSTAMP:
-		return ocelot_hwstamp_set(port, ifr);
+		return ocelot_hwstamp_set(ocelot, port, ifr);
 	case SIOCGHWTSTAMP:
-		return ocelot_hwstamp_get(port, ifr);
+		return ocelot_hwstamp_get(ocelot, port, ifr);
 	default:
 		return -EOPNOTSUPP;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 05/15] net: mscc: ocelot: change prototypes of switchdev port attribute handlers
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (3 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 04/15] net: mscc: ocelot: change prototypes of hwtstamping ioctls Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 06/15] net: mscc: ocelot: refactor struct ocelot_port out of function prototypes Vladimir Oltean
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

This is needed so that the Felix DSA front-end can call the Ocelot
implementations.

The implementation of the "mc_disabled" switchdev attribute has also
been simplified by using the read-modify-write macro instead of
open-coding that operation.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 88 +++++++++++++++---------------
 1 file changed, 45 insertions(+), 43 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 8b7d46693e49..ba8996bf995e 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1285,26 +1285,20 @@ static const struct ethtool_ops ocelot_ethtool_ops = {
 	.get_ts_info		= ocelot_get_ts_info,
 };
 
-static int ocelot_port_attr_stp_state_set(struct ocelot_port *ocelot_port,
-					  struct switchdev_trans *trans,
-					  u8 state)
+static void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port,
+					u8 state)
 {
-	struct ocelot *ocelot = ocelot_port->ocelot;
 	u32 port_cfg;
-	int port, i;
-
-	if (switchdev_trans_ph_prepare(trans))
-		return 0;
+	int p, i;
 
-	if (!(BIT(ocelot_port->chip_port) & ocelot->bridge_mask))
-		return 0;
+	if (!(BIT(port) & ocelot->bridge_mask))
+		return;
 
-	port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG,
-				   ocelot_port->chip_port);
+	port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, port);
 
 	switch (state) {
 	case BR_STATE_FORWARDING:
-		ocelot->bridge_fwd_mask |= BIT(ocelot_port->chip_port);
+		ocelot->bridge_fwd_mask |= BIT(port);
 		/* Fallthrough */
 	case BR_STATE_LEARNING:
 		port_cfg |= ANA_PORT_PORT_CFG_LEARN_ENA;
@@ -1312,19 +1306,18 @@ static int ocelot_port_attr_stp_state_set(struct ocelot_port *ocelot_port,
 
 	default:
 		port_cfg &= ~ANA_PORT_PORT_CFG_LEARN_ENA;
-		ocelot->bridge_fwd_mask &= ~BIT(ocelot_port->chip_port);
+		ocelot->bridge_fwd_mask &= ~BIT(port);
 		break;
 	}
 
-	ocelot_write_gix(ocelot, port_cfg, ANA_PORT_PORT_CFG,
-			 ocelot_port->chip_port);
+	ocelot_write_gix(ocelot, port_cfg, ANA_PORT_PORT_CFG, port);
 
 	/* Apply FWD mask. The loop is needed to add/remove the current port as
 	 * a source for the other ports.
 	 */
-	for (port = 0; port < ocelot->num_phys_ports; port++) {
-		if (ocelot->bridge_fwd_mask & BIT(port)) {
-			unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(port);
+	for (p = 0; p < ocelot->num_phys_ports; p++) {
+		if (ocelot->bridge_fwd_mask & BIT(p)) {
+			unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(p);
 
 			for (i = 0; i < ocelot->num_phys_ports; i++) {
 				unsigned long bond_mask = ocelot->lags[i];
@@ -1332,7 +1325,7 @@ static int ocelot_port_attr_stp_state_set(struct ocelot_port *ocelot_port,
 				if (!bond_mask)
 					continue;
 
-				if (bond_mask & BIT(port)) {
+				if (bond_mask & BIT(p)) {
 					mask &= ~bond_mask;
 					break;
 				}
@@ -1340,47 +1333,55 @@ static int ocelot_port_attr_stp_state_set(struct ocelot_port *ocelot_port,
 
 			ocelot_write_rix(ocelot,
 					 BIT(ocelot->num_phys_ports) | mask,
-					 ANA_PGID_PGID, PGID_SRC + port);
+					 ANA_PGID_PGID, PGID_SRC + p);
 		} else {
 			/* Only the CPU port, this is compatible with link
 			 * aggregation.
 			 */
 			ocelot_write_rix(ocelot,
 					 BIT(ocelot->num_phys_ports),
-					 ANA_PGID_PGID, PGID_SRC + port);
+					 ANA_PGID_PGID, PGID_SRC + p);
 		}
 	}
+}
 
-	return 0;
+static void ocelot_port_attr_stp_state_set(struct ocelot *ocelot, int port,
+					   struct switchdev_trans *trans,
+					   u8 state)
+{
+	if (switchdev_trans_ph_prepare(trans))
+		return;
+
+	ocelot_bridge_stp_state_set(ocelot, port, state);
+}
+
+static void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs)
+{
+	ocelot_write(ocelot, ANA_AUTOAGE_AGE_PERIOD(msecs / 2),
+		     ANA_AUTOAGE);
 }
 
-static void ocelot_port_attr_ageing_set(struct ocelot_port *ocelot_port,
+static void ocelot_port_attr_ageing_set(struct ocelot *ocelot, int port,
 					unsigned long ageing_clock_t)
 {
-	struct ocelot *ocelot = ocelot_port->ocelot;
 	unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t);
 	u32 ageing_time = jiffies_to_msecs(ageing_jiffies) / 1000;
 
-	ocelot_write(ocelot, ANA_AUTOAGE_AGE_PERIOD(ageing_time / 2),
-		     ANA_AUTOAGE);
+	ocelot_set_ageing_time(ocelot, ageing_time);
 }
 
-static void ocelot_port_attr_mc_set(struct ocelot_port *port, bool mc)
+static void ocelot_port_attr_mc_set(struct ocelot *ocelot, int port, bool mc)
 {
-	struct ocelot *ocelot = port->ocelot;
-	u32 val = ocelot_read_gix(ocelot, ANA_PORT_CPU_FWD_CFG,
-				  port->chip_port);
+	u32 cpu_fwd_mcast = ANA_PORT_CPU_FWD_CFG_CPU_IGMP_REDIR_ENA |
+			    ANA_PORT_CPU_FWD_CFG_CPU_MLD_REDIR_ENA |
+			    ANA_PORT_CPU_FWD_CFG_CPU_IPMC_CTRL_COPY_ENA;
+	u32 val = 0;
 
 	if (mc)
-		val |= ANA_PORT_CPU_FWD_CFG_CPU_IGMP_REDIR_ENA |
-		       ANA_PORT_CPU_FWD_CFG_CPU_MLD_REDIR_ENA |
-		       ANA_PORT_CPU_FWD_CFG_CPU_IPMC_CTRL_COPY_ENA;
-	else
-		val &= ~(ANA_PORT_CPU_FWD_CFG_CPU_IGMP_REDIR_ENA |
-			 ANA_PORT_CPU_FWD_CFG_CPU_MLD_REDIR_ENA |
-			 ANA_PORT_CPU_FWD_CFG_CPU_IPMC_CTRL_COPY_ENA);
+		val = cpu_fwd_mcast;
 
-	ocelot_write_gix(ocelot, val, ANA_PORT_CPU_FWD_CFG, port->chip_port);
+	ocelot_rmw_gix(ocelot, val, cpu_fwd_mcast,
+		       ANA_PORT_CPU_FWD_CFG, port);
 }
 
 static int ocelot_port_attr_set(struct net_device *dev,
@@ -1389,22 +1390,23 @@ static int ocelot_port_attr_set(struct net_device *dev,
 {
 	struct ocelot_port *ocelot_port = netdev_priv(dev);
 	struct ocelot *ocelot = ocelot_port->ocelot;
+	int port = ocelot_port->chip_port;
 	int err = 0;
 
 	switch (attr->id) {
 	case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
-		ocelot_port_attr_stp_state_set(ocelot_port, trans,
+		ocelot_port_attr_stp_state_set(ocelot, port, trans,
 					       attr->u.stp_state);
 		break;
 	case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
-		ocelot_port_attr_ageing_set(ocelot_port, attr->u.ageing_time);
+		ocelot_port_attr_ageing_set(ocelot, port, attr->u.ageing_time);
 		break;
 	case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
-		ocelot_port_vlan_filtering(ocelot, ocelot_port->chip_port,
+		ocelot_port_vlan_filtering(ocelot, port,
 					   attr->u.vlan_filtering);
 		break;
 	case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
-		ocelot_port_attr_mc_set(ocelot_port, !attr->u.mc_disabled);
+		ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled);
 		break;
 	default:
 		err = -EOPNOTSUPP;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 06/15] net: mscc: ocelot: refactor struct ocelot_port out of function prototypes
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (4 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 05/15] net: mscc: ocelot: change prototypes of switchdev port attribute handlers Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 07/15] net: mscc: ocelot: separate net_device related items out of ocelot_port Vladimir Oltean
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

The ocelot_port structure has a net_device embedded in it, which makes
it unsuitable for leaving it in the driver implementation functions.

Leave ocelot_flower.c untouched. In that file, ocelot_port is used as an
interface to the tc shared blocks. That will be addressed in the next
patch.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c        | 79 +++++++++++------------
 drivers/net/ethernet/mscc/ocelot_police.c | 36 +++++------
 drivers/net/ethernet/mscc/ocelot_police.h |  4 +-
 drivers/net/ethernet/mscc/ocelot_tc.c     |  5 +-
 4 files changed, 59 insertions(+), 65 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index ba8996bf995e..492193af2f73 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -133,11 +133,11 @@ static void ocelot_mact_init(struct ocelot *ocelot)
 	ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS);
 }
 
-static void ocelot_vcap_enable(struct ocelot *ocelot, struct ocelot_port *port)
+static void ocelot_vcap_enable(struct ocelot *ocelot, int port)
 {
 	ocelot_write_gix(ocelot, ANA_PORT_VCAP_S2_CFG_S2_ENA |
 			 ANA_PORT_VCAP_S2_CFG_S2_IP6_CFG(0xa),
-			 ANA_PORT_VCAP_S2_CFG, port->chip_port);
+			 ANA_PORT_VCAP_S2_CFG, port);
 }
 
 static inline u32 ocelot_vlant_read_vlanaccess(struct ocelot *ocelot)
@@ -170,19 +170,17 @@ static int ocelot_vlant_set_mask(struct ocelot *ocelot, u16 vid, u32 mask)
 	return ocelot_vlant_wait_for_completion(ocelot);
 }
 
-static void ocelot_vlan_mode(struct ocelot_port *port,
+static void ocelot_vlan_mode(struct ocelot *ocelot, int port,
 			     netdev_features_t features)
 {
-	struct ocelot *ocelot = port->ocelot;
-	u8 p = port->chip_port;
 	u32 val;
 
 	/* Filtering */
 	val = ocelot_read(ocelot, ANA_VLANMASK);
 	if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
-		val |= BIT(p);
+		val |= BIT(port);
 	else
-		val &= ~BIT(p);
+		val &= ~BIT(port);
 	ocelot_write(ocelot, val, ANA_VLANMASK);
 }
 
@@ -1034,18 +1032,20 @@ static int ocelot_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
 static int ocelot_set_features(struct net_device *dev,
 			       netdev_features_t features)
 {
-	struct ocelot_port *port = netdev_priv(dev);
 	netdev_features_t changed = dev->features ^ features;
+	struct ocelot_port *ocelot_port = netdev_priv(dev);
+	struct ocelot *ocelot = ocelot_port->ocelot;
+	int port = ocelot_port->chip_port;
 
 	if ((dev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
-	    port->tc.offload_cnt) {
+	    ocelot_port->tc.offload_cnt) {
 		netdev_err(dev,
 			   "Cannot disable HW TC offload while offloads active\n");
 		return -EBUSY;
 	}
 
 	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER)
-		ocelot_vlan_mode(port, features);
+		ocelot_vlan_mode(ocelot, port, features);
 
 	return 0;
 }
@@ -1586,11 +1586,9 @@ static int ocelot_port_obj_del(struct net_device *dev,
 	return ret;
 }
 
-static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port,
+static int ocelot_port_bridge_join(struct ocelot *ocelot, int port,
 				   struct net_device *bridge)
 {
-	struct ocelot *ocelot = ocelot_port->ocelot;
-
 	if (!ocelot->bridge_mask) {
 		ocelot->hw_bridge_dev = bridge;
 	} else {
@@ -1600,17 +1598,14 @@ static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port,
 			return -ENODEV;
 	}
 
-	ocelot->bridge_mask |= BIT(ocelot_port->chip_port);
+	ocelot->bridge_mask |= BIT(port);
 
 	return 0;
 }
 
-static int ocelot_port_bridge_leave(struct ocelot_port *ocelot_port,
+static int ocelot_port_bridge_leave(struct ocelot *ocelot, int port,
 				    struct net_device *bridge)
 {
-	struct ocelot *ocelot = ocelot_port->ocelot;
-	int port = ocelot_port->chip_port;
-
 	ocelot->bridge_mask &= ~BIT(port);
 
 	if (!ocelot->bridge_mask)
@@ -1679,14 +1674,12 @@ static void ocelot_setup_lag(struct ocelot *ocelot, int lag)
 	}
 }
 
-static int ocelot_port_lag_join(struct ocelot_port *ocelot_port,
+static int ocelot_port_lag_join(struct ocelot *ocelot, int port,
 				struct net_device *bond)
 {
-	struct ocelot *ocelot = ocelot_port->ocelot;
-	int p = ocelot_port->chip_port;
-	int lag, lp;
 	struct net_device *ndev;
 	u32 bond_mask = 0;
+	int lag, lp;
 
 	rcu_read_lock();
 	for_each_netdev_in_bond_rcu(bond, ndev) {
@@ -1701,17 +1694,17 @@ static int ocelot_port_lag_join(struct ocelot_port *ocelot_port,
 	/* If the new port is the lowest one, use it as the logical port from
 	 * now on
 	 */
-	if (p == lp) {
-		lag = p;
-		ocelot->lags[p] = bond_mask;
-		bond_mask &= ~BIT(p);
+	if (port == lp) {
+		lag = port;
+		ocelot->lags[port] = bond_mask;
+		bond_mask &= ~BIT(port);
 		if (bond_mask) {
 			lp = __ffs(bond_mask);
 			ocelot->lags[lp] = 0;
 		}
 	} else {
 		lag = lp;
-		ocelot->lags[lp] |= BIT(p);
+		ocelot->lags[lp] |= BIT(port);
 	}
 
 	ocelot_setup_lag(ocelot, lag);
@@ -1720,34 +1713,32 @@ static int ocelot_port_lag_join(struct ocelot_port *ocelot_port,
 	return 0;
 }
 
-static void ocelot_port_lag_leave(struct ocelot_port *ocelot_port,
+static void ocelot_port_lag_leave(struct ocelot *ocelot, int port,
 				  struct net_device *bond)
 {
-	struct ocelot *ocelot = ocelot_port->ocelot;
-	int p = ocelot_port->chip_port;
 	u32 port_cfg;
 	int i;
 
 	/* Remove port from any lag */
 	for (i = 0; i < ocelot->num_phys_ports; i++)
-		ocelot->lags[i] &= ~BIT(ocelot_port->chip_port);
+		ocelot->lags[i] &= ~BIT(port);
 
 	/* if it was the logical port of the lag, move the lag config to the
 	 * next port
 	 */
-	if (ocelot->lags[p]) {
-		int n = __ffs(ocelot->lags[p]);
+	if (ocelot->lags[port]) {
+		int n = __ffs(ocelot->lags[port]);
 
-		ocelot->lags[n] = ocelot->lags[p];
-		ocelot->lags[p] = 0;
+		ocelot->lags[n] = ocelot->lags[port];
+		ocelot->lags[port] = 0;
 
 		ocelot_setup_lag(ocelot, n);
 	}
 
-	port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, p);
+	port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, port);
 	port_cfg &= ~ANA_PORT_PORT_CFG_PORTID_VAL_M;
-	ocelot_write_gix(ocelot, port_cfg | ANA_PORT_PORT_CFG_PORTID_VAL(p),
-			 ANA_PORT_PORT_CFG, p);
+	ocelot_write_gix(ocelot, port_cfg | ANA_PORT_PORT_CFG_PORTID_VAL(port),
+			 ANA_PORT_PORT_CFG, port);
 
 	ocelot_set_aggr_pgids(ocelot);
 }
@@ -1763,24 +1754,26 @@ static int ocelot_netdevice_port_event(struct net_device *dev,
 				       struct netdev_notifier_changeupper_info *info)
 {
 	struct ocelot_port *ocelot_port = netdev_priv(dev);
+	struct ocelot *ocelot = ocelot_port->ocelot;
+	int port = ocelot_port->chip_port;
 	int err = 0;
 
 	switch (event) {
 	case NETDEV_CHANGEUPPER:
 		if (netif_is_bridge_master(info->upper_dev)) {
 			if (info->linking)
-				err = ocelot_port_bridge_join(ocelot_port,
+				err = ocelot_port_bridge_join(ocelot, port,
 							      info->upper_dev);
 			else
-				err = ocelot_port_bridge_leave(ocelot_port,
+				err = ocelot_port_bridge_leave(ocelot, port,
 							       info->upper_dev);
 		}
 		if (netif_is_lag_master(info->upper_dev)) {
 			if (info->linking)
-				err = ocelot_port_lag_join(ocelot_port,
+				err = ocelot_port_lag_join(ocelot, port,
 							   info->upper_dev);
 			else
-				ocelot_port_lag_leave(ocelot_port,
+				ocelot_port_lag_leave(ocelot, port,
 						      info->upper_dev);
 		}
 		break;
@@ -2136,7 +2129,7 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 		       REW_PORT_VLAN_CFG, port);
 
 	/* Enable vcap lookups */
-	ocelot_vcap_enable(ocelot, ocelot_port);
+	ocelot_vcap_enable(ocelot, port);
 
 	return 0;
 
diff --git a/drivers/net/ethernet/mscc/ocelot_police.c b/drivers/net/ethernet/mscc/ocelot_police.c
index 701e82dd749a..faddce43f2e3 100644
--- a/drivers/net/ethernet/mscc/ocelot_police.c
+++ b/drivers/net/ethernet/mscc/ocelot_police.c
@@ -40,13 +40,12 @@ struct qos_policer_conf {
 	u8   ipg; /* Size of IPG when MSCC_QOS_RATE_MODE_LINE is chosen */
 };
 
-static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix,
+static int qos_policer_conf_set(struct ocelot *ocelot, int port, u32 pol_ix,
 				struct qos_policer_conf *conf)
 {
 	u32 cf = 0, cir_ena = 0, frm_mode = POL_MODE_LINERATE;
 	u32 cir = 0, cbs = 0, pir = 0, pbs = 0;
 	bool cir_discard = 0, pir_discard = 0;
-	struct ocelot *ocelot = port->ocelot;
 	u32 pbs_max = 0, cbs_max = 0;
 	u8 ipg = 20;
 	u32 value;
@@ -123,22 +122,26 @@ static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix,
 
 	/* Check limits */
 	if (pir > GENMASK(15, 0)) {
-		netdev_err(port->dev, "Invalid pir\n");
+		dev_err(ocelot->dev, "Invalid pir for port %d: %u (max %lu)\n",
+			port, pir, GENMASK(15, 0));
 		return -EINVAL;
 	}
 
 	if (cir > GENMASK(15, 0)) {
-		netdev_err(port->dev, "Invalid cir\n");
+		dev_err(ocelot->dev, "Invalid cir for port %d: %u (max %lu)\n",
+			port, cir, GENMASK(15, 0));
 		return -EINVAL;
 	}
 
 	if (pbs > pbs_max) {
-		netdev_err(port->dev, "Invalid pbs\n");
+		dev_err(ocelot->dev, "Invalid pbs for port %d: %u (max %u)\n",
+			port, pbs, pbs_max);
 		return -EINVAL;
 	}
 
 	if (cbs > cbs_max) {
-		netdev_err(port->dev, "Invalid cbs\n");
+		dev_err(ocelot->dev, "Invalid cbs for port %d: %u (max %u)\n",
+			port, cbs, cbs_max);
 		return -EINVAL;
 	}
 
@@ -171,10 +174,9 @@ static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix,
 	return 0;
 }
 
-int ocelot_port_policer_add(struct ocelot_port *port,
+int ocelot_port_policer_add(struct ocelot *ocelot, int port,
 			    struct ocelot_policer *pol)
 {
-	struct ocelot *ocelot = port->ocelot;
 	struct qos_policer_conf pp = { 0 };
 	int err;
 
@@ -185,11 +187,10 @@ int ocelot_port_policer_add(struct ocelot_port *port,
 	pp.pir = pol->rate;
 	pp.pbs = pol->burst;
 
-	netdev_dbg(port->dev,
-		   "%s: port %u pir %u kbps, pbs %u bytes\n",
-		   __func__, port->chip_port, pp.pir, pp.pbs);
+	dev_dbg(ocelot->dev, "%s: port %u pir %u kbps, pbs %u bytes\n",
+		__func__, port, pp.pir, pp.pbs);
 
-	err = qos_policer_conf_set(port, POL_IX_PORT + port->chip_port, &pp);
+	err = qos_policer_conf_set(ocelot, port, POL_IX_PORT + port, &pp);
 	if (err)
 		return err;
 
@@ -198,22 +199,21 @@ int ocelot_port_policer_add(struct ocelot_port *port,
 		       ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
 		       ANA_PORT_POL_CFG_PORT_POL_ENA |
 		       ANA_PORT_POL_CFG_POL_ORDER_M,
-		       ANA_PORT_POL_CFG, port->chip_port);
+		       ANA_PORT_POL_CFG, port);
 
 	return 0;
 }
 
-int ocelot_port_policer_del(struct ocelot_port *port)
+int ocelot_port_policer_del(struct ocelot *ocelot, int port)
 {
-	struct ocelot *ocelot = port->ocelot;
 	struct qos_policer_conf pp = { 0 };
 	int err;
 
-	netdev_dbg(port->dev, "%s: port %u\n", __func__, port->chip_port);
+	dev_dbg(ocelot->dev, "%s: port %u\n", __func__, port);
 
 	pp.mode = MSCC_QOS_RATE_MODE_DISABLED;
 
-	err = qos_policer_conf_set(port, POL_IX_PORT + port->chip_port, &pp);
+	err = qos_policer_conf_set(ocelot, port, POL_IX_PORT + port, &pp);
 	if (err)
 		return err;
 
@@ -221,7 +221,7 @@ int ocelot_port_policer_del(struct ocelot_port *port)
 		       ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
 		       ANA_PORT_POL_CFG_PORT_POL_ENA |
 		       ANA_PORT_POL_CFG_POL_ORDER_M,
-		       ANA_PORT_POL_CFG, port->chip_port);
+		       ANA_PORT_POL_CFG, port);
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/mscc/ocelot_police.h b/drivers/net/ethernet/mscc/ocelot_police.h
index d1137f79efda..ae9509229463 100644
--- a/drivers/net/ethernet/mscc/ocelot_police.h
+++ b/drivers/net/ethernet/mscc/ocelot_police.h
@@ -14,9 +14,9 @@ struct ocelot_policer {
 	u32 burst; /* bytes */
 };
 
-int ocelot_port_policer_add(struct ocelot_port *port,
+int ocelot_port_policer_add(struct ocelot *ocelot, int port,
 			    struct ocelot_policer *pol);
 
-int ocelot_port_policer_del(struct ocelot_port *port);
+int ocelot_port_policer_del(struct ocelot *ocelot, int port);
 
 #endif /* _MSCC_OCELOT_POLICE_H_ */
diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
index 16a6db71ca5e..9be8e7369d6a 100644
--- a/drivers/net/ethernet/mscc/ocelot_tc.c
+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
@@ -58,7 +58,8 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port,
 					 PSCHED_NS2TICKS(action->police.burst),
 					 PSCHED_TICKS_PER_SEC);
 
-		err = ocelot_port_policer_add(port, &pol);
+		err = ocelot_port_policer_add(port->ocelot, port->chip_port,
+					      &pol);
 		if (err) {
 			NL_SET_ERR_MSG_MOD(extack, "Could not add policer\n");
 			return err;
@@ -71,7 +72,7 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port,
 		if (port->tc.police_id != f->cookie)
 			return -ENOENT;
 
-		err = ocelot_port_policer_del(port);
+		err = ocelot_port_policer_del(port->ocelot, port->chip_port);
 		if (err) {
 			NL_SET_ERR_MSG_MOD(extack,
 					   "Could not delete policer\n");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 07/15] net: mscc: ocelot: separate net_device related items out of ocelot_port
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (5 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 06/15] net: mscc: ocelot: refactor struct ocelot_port out of function prototypes Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 08/15] net: mscc: ocelot: refactor ethtool callbacks Vladimir Oltean
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

The ocelot and ocelot_port structures will be used by a new DSA driver,
so the ocelot_board.c file will have to allocate and work with a private
structure (ocelot_port_private), which embeds the generic struct
ocelot_port. This is because in DSA, at least one interface does not
have a net_device, and the DSA driver API does not interact with that
anyway.

The ocelot_port structure is equivalent to dsa_port, and ocelot to
dsa_switch. The members of ocelot_port which have an equivalent in
dsa_port (such as dp->vlan_filtering) have been moved to
ocelot_port_private.

We want to enforce the coding convention that "ocelot_port" refers to
the structure, and "port" refers to the integer index. One can retrieve
the structure at any time from ocelot->ports[port].

The patch is large but only contains variable renaming and mechanical
movement of fields from one structure to another.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c        | 288 ++++++++++++----------
 drivers/net/ethernet/mscc/ocelot.h        |  21 +-
 drivers/net/ethernet/mscc/ocelot_ace.h    |   4 +-
 drivers/net/ethernet/mscc/ocelot_board.c  |  21 +-
 drivers/net/ethernet/mscc/ocelot_flower.c |  32 +--
 drivers/net/ethernet/mscc/ocelot_tc.c     |  57 ++---
 6 files changed, 233 insertions(+), 190 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 492193af2f73..ad808344e33b 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -229,8 +229,6 @@ static void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
 	ocelot_rmw_gix(ocelot, val,
 		       REW_TAG_CFG_TAG_CFG_M,
 		       REW_TAG_CFG, port);
-
-	ocelot_port->vlan_aware = vlan_aware;
 }
 
 static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
@@ -297,9 +295,10 @@ static int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid,
 static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid,
 			       bool untagged)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot_port *ocelot_port = &priv->port;
 	struct ocelot *ocelot = ocelot_port->ocelot;
-	int port = ocelot_port->chip_port;
+	int port = priv->chip_port;
 	int ret;
 
 	ret = ocelot_vlan_add(ocelot, port, vid, pvid, untagged);
@@ -337,9 +336,9 @@ static int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid)
 
 static int ocelot_vlan_vid_del(struct net_device *dev, u16 vid)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
-	struct ocelot *ocelot = ocelot_port->ocelot;
-	int port = ocelot_port->chip_port;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 	int ret;
 
 	/* 8021q removes VID 0 on module unload for all interfaces
@@ -412,10 +411,11 @@ static u16 ocelot_wm_enc(u16 value)
 
 static void ocelot_port_adjust_link(struct net_device *dev)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
-	u8 p = port->chip_port;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot_port *ocelot_port = &priv->port;
+	struct ocelot *ocelot = ocelot_port->ocelot;
 	int speed, atop_wm, mode = 0;
+	u8 port = priv->chip_port;
 
 	switch (dev->phydev->speed) {
 	case SPEED_10:
@@ -444,62 +444,66 @@ static void ocelot_port_adjust_link(struct net_device *dev)
 		return;
 
 	/* Only full duplex supported for now */
-	ocelot_port_writel(port, DEV_MAC_MODE_CFG_FDX_ENA |
+	ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA |
 			   mode, DEV_MAC_MODE_CFG);
 
 	/* Set MAC IFG Gaps
 	 * FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 0
 	 * !FDX: TX_IFG = 5, RX_IFG1 = RX_IFG2 = 5
 	 */
-	ocelot_port_writel(port, DEV_MAC_IFG_CFG_TX_IFG(5), DEV_MAC_IFG_CFG);
+	ocelot_port_writel(ocelot_port, DEV_MAC_IFG_CFG_TX_IFG(5),
+			   DEV_MAC_IFG_CFG);
 
 	/* Load seed (0) and set MAC HDX late collision  */
-	ocelot_port_writel(port, DEV_MAC_HDX_CFG_LATE_COL_POS(67) |
+	ocelot_port_writel(ocelot_port, DEV_MAC_HDX_CFG_LATE_COL_POS(67) |
 			   DEV_MAC_HDX_CFG_SEED_LOAD,
 			   DEV_MAC_HDX_CFG);
 	mdelay(1);
-	ocelot_port_writel(port, DEV_MAC_HDX_CFG_LATE_COL_POS(67),
+	ocelot_port_writel(ocelot_port, DEV_MAC_HDX_CFG_LATE_COL_POS(67),
 			   DEV_MAC_HDX_CFG);
 
 	/* Disable HDX fast control */
-	ocelot_port_writel(port, DEV_PORT_MISC_HDX_FAST_DIS, DEV_PORT_MISC);
+	ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
+			   DEV_PORT_MISC);
 
 	/* SGMII only for now */
-	ocelot_port_writel(port, PCS1G_MODE_CFG_SGMII_MODE_ENA, PCS1G_MODE_CFG);
-	ocelot_port_writel(port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
+	ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
+			   PCS1G_MODE_CFG);
+	ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
 
 	/* Enable PCS */
-	ocelot_port_writel(port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
+	ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
 
 	/* No aneg on SGMII */
-	ocelot_port_writel(port, 0, PCS1G_ANEG_CFG);
+	ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);
 
 	/* No loopback */
-	ocelot_port_writel(port, 0, PCS1G_LB_CFG);
+	ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
 
 	/* Set Max Length and maximum tags allowed */
-	ocelot_port_writel(port, VLAN_ETH_FRAME_LEN, DEV_MAC_MAXLEN_CFG);
-	ocelot_port_writel(port, DEV_MAC_TAGS_CFG_TAG_ID(ETH_P_8021AD) |
+	ocelot_port_writel(ocelot_port, VLAN_ETH_FRAME_LEN,
+			   DEV_MAC_MAXLEN_CFG);
+	ocelot_port_writel(ocelot_port, DEV_MAC_TAGS_CFG_TAG_ID(ETH_P_8021AD) |
 			   DEV_MAC_TAGS_CFG_VLAN_AWR_ENA |
 			   DEV_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA,
 			   DEV_MAC_TAGS_CFG);
 
 	/* Enable MAC module */
-	ocelot_port_writel(port, DEV_MAC_ENA_CFG_RX_ENA |
+	ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
 			   DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG);
 
 	/* Take MAC, Port, Phy (intern) and PCS (SGMII/Serdes) clock out of
 	 * reset */
-	ocelot_port_writel(port, DEV_CLOCK_CFG_LINK_SPEED(speed),
+	ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(speed),
 			   DEV_CLOCK_CFG);
 
 	/* Set SMAC of Pause frame (00:00:00:00:00:00) */
-	ocelot_port_writel(port, 0, DEV_MAC_FC_MAC_HIGH_CFG);
-	ocelot_port_writel(port, 0, DEV_MAC_FC_MAC_LOW_CFG);
+	ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_HIGH_CFG);
+	ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_LOW_CFG);
 
 	/* No PFC */
 	ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(speed),
-			 ANA_PFC_PFC_CFG, p);
+			 ANA_PFC_PFC_CFG, port);
 
 	/* Set Pause WM hysteresis
 	 * 152 = 6 * VLAN_ETH_FRAME_LEN / OCELOT_BUFFER_CELL_SZ
@@ -507,13 +511,13 @@ static void ocelot_port_adjust_link(struct net_device *dev)
 	 */
 	ocelot_write_rix(ocelot, SYS_PAUSE_CFG_PAUSE_ENA |
 			 SYS_PAUSE_CFG_PAUSE_STOP(101) |
-			 SYS_PAUSE_CFG_PAUSE_START(152), SYS_PAUSE_CFG, p);
+			 SYS_PAUSE_CFG_PAUSE_START(152), SYS_PAUSE_CFG, port);
 
 	/* Core: Enable port for frame transfer */
 	ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
 			 QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
 			 QSYS_SWITCH_PORT_MODE_PORT_ENA,
-			 QSYS_SWITCH_PORT_MODE, p);
+			 QSYS_SWITCH_PORT_MODE, port);
 
 	/* Flow control */
 	ocelot_write_rix(ocelot, SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
@@ -521,20 +525,21 @@ static void ocelot_port_adjust_link(struct net_device *dev)
 			 SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
 			 SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
 			 SYS_MAC_FC_CFG_FC_LINK_SPEED(speed),
-			 SYS_MAC_FC_CFG, p);
-	ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, p);
+			 SYS_MAC_FC_CFG, port);
+	ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port);
 
 	/* Tail dropping watermark */
 	atop_wm = (ocelot->shared_queue_sz - 9 * VLAN_ETH_FRAME_LEN) / OCELOT_BUFFER_CELL_SZ;
 	ocelot_write_rix(ocelot, ocelot_wm_enc(9 * VLAN_ETH_FRAME_LEN),
-			 SYS_ATOP, p);
+			 SYS_ATOP, port);
 	ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
 }
 
 static int ocelot_port_open(struct net_device *dev)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 	int err;
 
 	/* Enable receiving frames on the port, and activate auto-learning of
@@ -542,43 +547,44 @@ static int ocelot_port_open(struct net_device *dev)
 	 */
 	ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_LEARNAUTO |
 			 ANA_PORT_PORT_CFG_RECV_ENA |
-			 ANA_PORT_PORT_CFG_PORTID_VAL(port->chip_port),
-			 ANA_PORT_PORT_CFG, port->chip_port);
+			 ANA_PORT_PORT_CFG_PORTID_VAL(port),
+			 ANA_PORT_PORT_CFG, port);
 
-	if (port->serdes) {
-		err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET,
-				       port->phy_mode);
+	if (priv->serdes) {
+		err = phy_set_mode_ext(priv->serdes, PHY_MODE_ETHERNET,
+				       priv->phy_mode);
 		if (err) {
 			netdev_err(dev, "Could not set mode of SerDes\n");
 			return err;
 		}
 	}
 
-	err = phy_connect_direct(dev, port->phy, &ocelot_port_adjust_link,
-				 port->phy_mode);
+	err = phy_connect_direct(dev, priv->phy, &ocelot_port_adjust_link,
+				 priv->phy_mode);
 	if (err) {
 		netdev_err(dev, "Could not attach to PHY\n");
 		return err;
 	}
 
-	dev->phydev = port->phy;
+	dev->phydev = priv->phy;
 
-	phy_attached_info(port->phy);
-	phy_start(port->phy);
+	phy_attached_info(priv->phy);
+	phy_start(priv->phy);
 	return 0;
 }
 
 static int ocelot_port_stop(struct net_device *dev)
 {
-	struct ocelot_port *port = netdev_priv(dev);
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot_port *port = &priv->port;
 
-	phy_disconnect(port->phy);
+	phy_disconnect(priv->phy);
 
 	dev->phydev = NULL;
 
 	ocelot_port_writel(port, 0, DEV_MAC_ENA_CFG);
 	ocelot_rmw_rix(port->ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
-			 QSYS_SWITCH_PORT_MODE, port->chip_port);
+		       QSYS_SWITCH_PORT_MODE, priv->chip_port);
 	return 0;
 }
 
@@ -604,13 +610,15 @@ static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
 
 static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	struct ocelot_port_private *priv = netdev_priv(dev);
 	struct skb_shared_info *shinfo = skb_shinfo(skb);
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
-	u32 val, ifh[IFH_LEN];
+	struct ocelot_port *ocelot_port = &priv->port;
+	struct ocelot *ocelot = ocelot_port->ocelot;
 	struct frame_info info = {};
 	u8 grp = 0; /* Send everything on CPU group 0 */
 	unsigned int i, count, last;
+	int port = priv->chip_port;
+	u32 val, ifh[IFH_LEN];
 
 	val = ocelot_read(ocelot, QS_INJ_STATUS);
 	if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))) ||
@@ -620,15 +628,15 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 	ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
 			 QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp);
 
-	info.port = BIT(port->chip_port);
+	info.port = BIT(port);
 	info.tag_type = IFH_TAG_TYPE_C;
 	info.vid = skb_vlan_tag_get(skb);
 
 	/* Check if timestamping is needed */
 	if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
-		info.rew_op = port->ptp_cmd;
-		if (port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
-			info.rew_op |= (port->ts_id  % 4) << 3;
+		info.rew_op = ocelot_port->ptp_cmd;
+		if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
+			info.rew_op |= (ocelot_port->ts_id  % 4) << 3;
 	}
 
 	ocelot_gen_ifh(ifh, &info);
@@ -663,7 +671,7 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 	dev->stats.tx_bytes += skb->len;
 
 	if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
-	    port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
+	    ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
 		struct ocelot_skb *oskb =
 			kzalloc(sizeof(struct ocelot_skb), GFP_ATOMIC);
 
@@ -673,10 +681,10 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
 		oskb->skb = skb;
-		oskb->id = port->ts_id % 4;
-		port->ts_id++;
+		oskb->id = ocelot_port->ts_id % 4;
+		ocelot_port->ts_id++;
 
-		list_add_tail(&oskb->head, &port->skbs);
+		list_add_tail(&oskb->head, &ocelot_port->skbs);
 
 		return NETDEV_TX_OK;
 	}
@@ -715,25 +723,29 @@ EXPORT_SYMBOL(ocelot_get_hwtimestamp);
 
 static int ocelot_mc_unsync(struct net_device *dev, const unsigned char *addr)
 {
-	struct ocelot_port *port = netdev_priv(dev);
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot_port *ocelot_port = &priv->port;
+	struct ocelot *ocelot = ocelot_port->ocelot;
 
-	return ocelot_mact_forget(port->ocelot, addr, port->pvid);
+	return ocelot_mact_forget(ocelot, addr, ocelot_port->pvid);
 }
 
 static int ocelot_mc_sync(struct net_device *dev, const unsigned char *addr)
 {
-	struct ocelot_port *port = netdev_priv(dev);
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot_port *ocelot_port = &priv->port;
+	struct ocelot *ocelot = ocelot_port->ocelot;
 
-	return ocelot_mact_learn(port->ocelot, PGID_CPU, addr, port->pvid,
+	return ocelot_mact_learn(ocelot, PGID_CPU, addr, ocelot_port->pvid,
 				 ENTRYTYPE_LOCKED);
 }
 
 static void ocelot_set_rx_mode(struct net_device *dev)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
-	int i;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
 	u32 val;
+	int i;
 
 	/* This doesn't handle promiscuous mode because the bridge core is
 	 * setting IFF_PROMISC on all slave interfaces and all frames would be
@@ -749,10 +761,11 @@ static void ocelot_set_rx_mode(struct net_device *dev)
 static int ocelot_port_get_phys_port_name(struct net_device *dev,
 					  char *buf, size_t len)
 {
-	struct ocelot_port *port = netdev_priv(dev);
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	int port = priv->chip_port;
 	int ret;
 
-	ret = snprintf(buf, len, "p%d", port->chip_port);
+	ret = snprintf(buf, len, "p%d", port);
 	if (ret >= len)
 		return -EINVAL;
 
@@ -761,15 +774,16 @@ static int ocelot_port_get_phys_port_name(struct net_device *dev,
 
 static int ocelot_port_set_mac_address(struct net_device *dev, void *p)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot_port *ocelot_port = &priv->port;
+	struct ocelot *ocelot = ocelot_port->ocelot;
 	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, port->pvid,
+	ocelot_mact_learn(ocelot, PGID_CPU, addr->sa_data, ocelot_port->pvid,
 			  ENTRYTYPE_LOCKED);
 	/* Then forget the previous one. */
-	ocelot_mact_forget(ocelot, dev->dev_addr, port->pvid);
+	ocelot_mact_forget(ocelot, dev->dev_addr, ocelot_port->pvid);
 
 	ether_addr_copy(dev->dev_addr, addr->sa_data);
 	return 0;
@@ -778,11 +792,12 @@ static int ocelot_port_set_mac_address(struct net_device *dev, void *p)
 static void ocelot_get_stats64(struct net_device *dev,
 			       struct rtnl_link_stats64 *stats)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 
 	/* Configure the port to read the stats from */
-	ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port->chip_port),
+	ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port),
 		     SYS_STAT_CFG);
 
 	/* Get Rx stats */
@@ -814,12 +829,13 @@ static void ocelot_get_stats64(struct net_device *dev,
 }
 
 static int ocelot_fdb_add(struct ocelot *ocelot, int port,
-			  const unsigned char *addr, u16 vid)
+			  const unsigned char *addr, u16 vid,
+			  bool vlan_aware)
 {
 	struct ocelot_port *ocelot_port = ocelot->ports[port];
 
 	if (!vid) {
-		if (!ocelot_port->vlan_aware)
+		if (!vlan_aware)
 			/* If the bridge is not VLAN aware and no VID was
 			 * provided, set it to pvid to ensure the MAC entry
 			 * matches incoming untagged packets
@@ -841,10 +857,11 @@ static int ocelot_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 			       u16 vid, u16 flags,
 			       struct netlink_ext_ack *extack)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
-	struct ocelot *ocelot = ocelot_port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 
-	return ocelot_fdb_add(ocelot, ocelot_port->chip_port, addr, vid);
+	return ocelot_fdb_add(ocelot, port, addr, vid, priv->vlan_aware);
 }
 
 static int ocelot_fdb_del(struct ocelot *ocelot, int port,
@@ -857,10 +874,11 @@ static int ocelot_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
 			       struct net_device *dev,
 			       const unsigned char *addr, u16 vid)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
-	struct ocelot *ocelot = ocelot_port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 
-	return ocelot_fdb_del(ocelot, ocelot_port->chip_port, addr, vid);
+	return ocelot_fdb_del(ocelot, port, addr, vid);
 }
 
 struct ocelot_dump_ctx {
@@ -999,18 +1017,18 @@ static int ocelot_port_fdb_dump(struct sk_buff *skb,
 				struct net_device *dev,
 				struct net_device *filter_dev, int *idx)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
-	struct ocelot *ocelot = ocelot_port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
 	struct ocelot_dump_ctx dump = {
 		.dev = dev,
 		.skb = skb,
 		.cb = cb,
 		.idx = *idx,
 	};
+	int port = priv->chip_port;
 	int ret;
 
-	ret = ocelot_fdb_dump(ocelot, ocelot_port->chip_port,
-			      ocelot_port_fdb_do_dump, &dump);
+	ret = ocelot_fdb_dump(ocelot, port, ocelot_port_fdb_do_dump, &dump);
 
 	*idx = dump.idx;
 
@@ -1033,12 +1051,12 @@ static int ocelot_set_features(struct net_device *dev,
 			       netdev_features_t features)
 {
 	netdev_features_t changed = dev->features ^ features;
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
-	struct ocelot *ocelot = ocelot_port->ocelot;
-	int port = ocelot_port->chip_port;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 
 	if ((dev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
-	    ocelot_port->tc.offload_cnt) {
+	    priv->tc.offload_cnt) {
 		netdev_err(dev,
 			   "Cannot disable HW TC offload while offloads active\n");
 		return -EBUSY;
@@ -1053,8 +1071,8 @@ static int ocelot_set_features(struct net_device *dev,
 static int ocelot_get_port_parent_id(struct net_device *dev,
 				     struct netdev_phys_item_id *ppid)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
-	struct ocelot *ocelot = ocelot_port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
 
 	ppid->id_len = sizeof(ocelot->base_mac);
 	memcpy(&ppid->id, &ocelot->base_mac, ppid->id_len);
@@ -1136,9 +1154,9 @@ static int ocelot_hwstamp_set(struct ocelot *ocelot, int port,
 
 static int ocelot_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
-	struct ocelot *ocelot = ocelot_port->ocelot;
-	int port = ocelot_port->chip_port;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 
 	/* The function is only used for PTP operations for now */
 	if (!ocelot->ptp)
@@ -1175,8 +1193,8 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
 
 static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data)
 {
-	struct ocelot_port *port = netdev_priv(netdev);
-	struct ocelot *ocelot = port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(netdev);
+	struct ocelot *ocelot = priv->port.ocelot;
 	int i;
 
 	if (sset != ETH_SS_STATS)
@@ -1230,8 +1248,9 @@ static void ocelot_check_stats_work(struct work_struct *work)
 static void ocelot_get_ethtool_stats(struct net_device *dev,
 				     struct ethtool_stats *stats, u64 *data)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 	int i;
 
 	/* check and update now */
@@ -1239,13 +1258,13 @@ static void ocelot_get_ethtool_stats(struct net_device *dev,
 
 	/* Copy all counters */
 	for (i = 0; i < ocelot->num_stats; i++)
-		*data++ = ocelot->stats[port->chip_port * ocelot->num_stats + i];
+		*data++ = ocelot->stats[port * ocelot->num_stats + i];
 }
 
 static int ocelot_get_sset_count(struct net_device *dev, int sset)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
 
 	if (sset != ETH_SS_STATS)
 		return -EOPNOTSUPP;
@@ -1255,8 +1274,8 @@ static int ocelot_get_sset_count(struct net_device *dev, int sset)
 static int ocelot_get_ts_info(struct net_device *dev,
 			      struct ethtool_ts_info *info)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
-	struct ocelot *ocelot = ocelot_port->ocelot;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
 
 	if (!ocelot->ptp)
 		return ethtool_op_get_ts_info(dev, info);
@@ -1388,9 +1407,9 @@ static int ocelot_port_attr_set(struct net_device *dev,
 				const struct switchdev_attr *attr,
 				struct switchdev_trans *trans)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
-	struct ocelot *ocelot = ocelot_port->ocelot;
-	int port = ocelot_port->chip_port;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 	int err = 0;
 
 	switch (attr->id) {
@@ -1402,8 +1421,8 @@ static int ocelot_port_attr_set(struct net_device *dev,
 		ocelot_port_attr_ageing_set(ocelot, port, attr->u.ageing_time);
 		break;
 	case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
-		ocelot_port_vlan_filtering(ocelot, port,
-					   attr->u.vlan_filtering);
+		priv->vlan_aware = attr->u.vlan_filtering;
+		ocelot_port_vlan_filtering(ocelot, port, priv->vlan_aware);
 		break;
 	case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
 		ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled);
@@ -1468,15 +1487,17 @@ static int ocelot_port_obj_add_mdb(struct net_device *dev,
 				   const struct switchdev_obj_port_mdb *mdb,
 				   struct switchdev_trans *trans)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
-	struct ocelot_multicast *mc;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot_port *ocelot_port = &priv->port;
+	struct ocelot *ocelot = ocelot_port->ocelot;
 	unsigned char addr[ETH_ALEN];
+	struct ocelot_multicast *mc;
+	int port = priv->chip_port;
 	u16 vid = mdb->vid;
 	bool new = false;
 
 	if (!vid)
-		vid = port->pvid;
+		vid = ocelot_port->pvid;
 
 	mc = ocelot_multicast_get(ocelot, mdb->addr, vid);
 	if (!mc) {
@@ -1500,7 +1521,7 @@ static int ocelot_port_obj_add_mdb(struct net_device *dev,
 		ocelot_mact_forget(ocelot, addr, vid);
 	}
 
-	mc->ports |= BIT(port->chip_port);
+	mc->ports |= BIT(port);
 	addr[2] = mc->ports << 0;
 	addr[1] = mc->ports << 8;
 
@@ -1510,14 +1531,16 @@ static int ocelot_port_obj_add_mdb(struct net_device *dev,
 static int ocelot_port_obj_del_mdb(struct net_device *dev,
 				   const struct switchdev_obj_port_mdb *mdb)
 {
-	struct ocelot_port *port = netdev_priv(dev);
-	struct ocelot *ocelot = port->ocelot;
-	struct ocelot_multicast *mc;
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot_port *ocelot_port = &priv->port;
+	struct ocelot *ocelot = ocelot_port->ocelot;
 	unsigned char addr[ETH_ALEN];
+	struct ocelot_multicast *mc;
+	int port = priv->chip_port;
 	u16 vid = mdb->vid;
 
 	if (!vid)
-		vid = port->pvid;
+		vid = ocelot_port->pvid;
 
 	mc = ocelot_multicast_get(ocelot, mdb->addr, vid);
 	if (!mc)
@@ -1529,7 +1552,7 @@ static int ocelot_port_obj_del_mdb(struct net_device *dev,
 	addr[0] = 0;
 	ocelot_mact_forget(ocelot, addr, vid);
 
-	mc->ports &= ~BIT(port->chip_port);
+	mc->ports &= ~BIT(port);
 	if (!mc->ports) {
 		list_del(&mc->list);
 		devm_kfree(ocelot->dev, mc);
@@ -1683,9 +1706,9 @@ static int ocelot_port_lag_join(struct ocelot *ocelot, int port,
 
 	rcu_read_lock();
 	for_each_netdev_in_bond_rcu(bond, ndev) {
-		struct ocelot_port *port = netdev_priv(ndev);
+		struct ocelot_port_private *priv = netdev_priv(ndev);
 
-		bond_mask |= BIT(port->chip_port);
+		bond_mask |= BIT(priv->chip_port);
 	}
 	rcu_read_unlock();
 
@@ -1753,20 +1776,23 @@ static int ocelot_netdevice_port_event(struct net_device *dev,
 				       unsigned long event,
 				       struct netdev_notifier_changeupper_info *info)
 {
-	struct ocelot_port *ocelot_port = netdev_priv(dev);
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot_port *ocelot_port = &priv->port;
 	struct ocelot *ocelot = ocelot_port->ocelot;
-	int port = ocelot_port->chip_port;
+	int port = priv->chip_port;
 	int err = 0;
 
 	switch (event) {
 	case NETDEV_CHANGEUPPER:
 		if (netif_is_bridge_master(info->upper_dev)) {
-			if (info->linking)
+			if (info->linking) {
 				err = ocelot_port_bridge_join(ocelot, port,
 							      info->upper_dev);
-			else
+			} else {
 				err = ocelot_port_bridge_leave(ocelot, port,
 							       info->upper_dev);
+				priv->vlan_aware = false;
+			}
 		}
 		if (netif_is_lag_master(info->upper_dev)) {
 			if (info->linking)
@@ -2080,21 +2106,23 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 		      void __iomem *regs,
 		      struct phy_device *phy)
 {
+	struct ocelot_port_private *priv;
 	struct ocelot_port *ocelot_port;
 	struct net_device *dev;
 	u32 val;
 	int err;
 
-	dev = alloc_etherdev(sizeof(struct ocelot_port));
+	dev = alloc_etherdev(sizeof(struct ocelot_port_private));
 	if (!dev)
 		return -ENOMEM;
 	SET_NETDEV_DEV(dev, ocelot->dev);
-	ocelot_port = netdev_priv(dev);
-	ocelot_port->dev = dev;
+	priv = netdev_priv(dev);
+	priv->dev = dev;
+	priv->phy = phy;
+	priv->chip_port = port;
+	ocelot_port = &priv->port;
 	ocelot_port->ocelot = ocelot;
 	ocelot_port->regs = regs;
-	ocelot_port->chip_port = port;
-	ocelot_port->phy = phy;
 	ocelot->ports[port] = ocelot_port;
 
 	dev->netdev_ops = &ocelot_port_netdev_ops;
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 06ac806052bc..7f3526151fa9 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -479,11 +479,9 @@ struct ocelot {
 };
 
 struct ocelot_port {
-	struct net_device *dev;
 	struct ocelot *ocelot;
-	struct phy_device *phy;
+
 	void __iomem *regs;
-	u8 chip_port;
 
 	/* Ingress default VLAN (pvid) */
 	u16 pvid;
@@ -491,18 +489,23 @@ struct ocelot_port {
 	/* Egress default VLAN (vid) */
 	u16 vid;
 
-	u8 vlan_aware;
+	u8 ptp_cmd;
+	struct list_head skbs;
+	u8 ts_id;
+};
 
-	u64 *stats;
+struct ocelot_port_private {
+	struct ocelot_port port;
+	struct net_device *dev;
+	struct phy_device *phy;
+	u8 chip_port;
+
+	u8 vlan_aware;
 
 	phy_interface_t phy_mode;
 	struct phy *serdes;
 
 	struct ocelot_port_tc tc;
-
-	u8 ptp_cmd;
-	struct list_head skbs;
-	u8 ts_id;
 };
 
 struct ocelot_skb {
diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h b/drivers/net/ethernet/mscc/ocelot_ace.h
index e98944c87259..c08e3e8482e7 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.h
+++ b/drivers/net/ethernet/mscc/ocelot_ace.h
@@ -224,9 +224,9 @@ int ocelot_ace_rule_stats_update(struct ocelot_ace_rule *rule);
 int ocelot_ace_init(struct ocelot *ocelot);
 void ocelot_ace_deinit(void);
 
-int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
+int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv,
 				      struct flow_block_offload *f);
-void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
+void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv,
 					 struct flow_block_offload *f);
 
 #endif /* _MSCC_OCELOT_ACE_H_ */
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 723724bdc139..4793d275d845 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -95,6 +95,8 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
 
 	do {
 		struct skb_shared_hwtstamps *shhwtstamps;
+		struct ocelot_port_private *priv;
+		struct ocelot_port *ocelot_port;
 		u64 tod_in_ns, full_ts_in_ns;
 		struct frame_info info = {};
 		struct net_device *dev;
@@ -114,7 +116,10 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
 
 		ocelot_parse_ifh(ifh, &info);
 
-		dev = ocelot->ports[info.port]->dev;
+		ocelot_port = ocelot->ports[info.port];
+		priv = container_of(ocelot_port, struct ocelot_port_private,
+				    port);
+		dev = priv->dev;
 
 		skb = netdev_alloc_skb(dev, info.len);
 
@@ -363,6 +368,8 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 	ocelot_init(ocelot);
 
 	for_each_available_child_of_node(ports, portnp) {
+		struct ocelot_port_private *priv;
+		struct ocelot_port *ocelot_port;
 		struct device_node *phy_node;
 		phy_interface_t phy_mode;
 		struct phy_device *phy;
@@ -398,13 +405,17 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 			goto out_put_ports;
 		}
 
+		ocelot_port = ocelot->ports[port];
+		priv = container_of(ocelot_port, struct ocelot_port_private,
+				    port);
+
 		err = of_get_phy_mode(portnp, &phy_mode);
 		if (err && err != -ENODEV)
 			goto out_put_ports;
 
-		ocelot->ports[port]->phy_mode = phy_mode;
+		priv->phy_mode = phy_mode;
 
-		switch (ocelot->ports[port]->phy_mode) {
+		switch (priv->phy_mode) {
 		case PHY_INTERFACE_MODE_NA:
 			continue;
 		case PHY_INTERFACE_MODE_SGMII:
@@ -413,7 +424,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 			/* Ensure clock signals and speed is set on all
 			 * QSGMII links
 			 */
-			ocelot_port_writel(ocelot->ports[port],
+			ocelot_port_writel(ocelot_port,
 					   DEV_CLOCK_CFG_LINK_SPEED
 					   (OCELOT_SPEED_1000),
 					   DEV_CLOCK_CFG);
@@ -441,7 +452,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 			goto out_put_ports;
 		}
 
-		ocelot->ports[port]->serdes = serdes;
+		priv->serdes = serdes;
 	}
 
 	register_netdevice_notifier(&ocelot_netdevice_nb);
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index b894bc0c9c16..3d65b99b9734 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -10,7 +10,7 @@
 
 struct ocelot_port_block {
 	struct ocelot_acl_block *block;
-	struct ocelot_port *port;
+	struct ocelot_port_private *priv;
 };
 
 static int ocelot_flower_parse_action(struct flow_cls_offload *f,
@@ -177,8 +177,8 @@ struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f,
 	if (!rule)
 		return NULL;
 
-	rule->port = block->port;
-	rule->chip_port = block->port->chip_port;
+	rule->port = &block->priv->port;
+	rule->chip_port = block->priv->chip_port;
 	return rule;
 }
 
@@ -202,7 +202,7 @@ static int ocelot_flower_replace(struct flow_cls_offload *f,
 	if (ret)
 		return ret;
 
-	port_block->port->tc.offload_cnt++;
+	port_block->priv->tc.offload_cnt++;
 	return 0;
 }
 
@@ -213,14 +213,14 @@ static int ocelot_flower_destroy(struct flow_cls_offload *f,
 	int ret;
 
 	rule.prio = f->common.prio;
-	rule.port = port_block->port;
+	rule.port = &port_block->priv->port;
 	rule.id = f->cookie;
 
 	ret = ocelot_ace_rule_offload_del(&rule);
 	if (ret)
 		return ret;
 
-	port_block->port->tc.offload_cnt--;
+	port_block->priv->tc.offload_cnt--;
 	return 0;
 }
 
@@ -231,7 +231,7 @@ static int ocelot_flower_stats_update(struct flow_cls_offload *f,
 	int ret;
 
 	rule.prio = f->common.prio;
-	rule.port = port_block->port;
+	rule.port = &port_block->priv->port;
 	rule.id = f->cookie;
 	ret = ocelot_ace_rule_stats_update(&rule);
 	if (ret)
@@ -261,7 +261,7 @@ static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type,
 {
 	struct ocelot_port_block *port_block = cb_priv;
 
-	if (!tc_cls_can_offload_and_chain0(port_block->port->dev, type_data))
+	if (!tc_cls_can_offload_and_chain0(port_block->priv->dev, type_data))
 		return -EOPNOTSUPP;
 
 	switch (type) {
@@ -275,7 +275,7 @@ static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type,
 }
 
 static struct ocelot_port_block*
-ocelot_port_block_create(struct ocelot_port *port)
+ocelot_port_block_create(struct ocelot_port_private *priv)
 {
 	struct ocelot_port_block *port_block;
 
@@ -283,7 +283,7 @@ ocelot_port_block_create(struct ocelot_port *port)
 	if (!port_block)
 		return NULL;
 
-	port_block->port = port;
+	port_block->priv = priv;
 
 	return port_block;
 }
@@ -300,7 +300,7 @@ static void ocelot_tc_block_unbind(void *cb_priv)
 	ocelot_port_block_destroy(port_block);
 }
 
-int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
+int ocelot_setup_tc_block_flower_bind(struct ocelot_port_private *priv,
 				      struct flow_block_offload *f)
 {
 	struct ocelot_port_block *port_block;
@@ -311,14 +311,14 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
 		return -EOPNOTSUPP;
 
 	block_cb = flow_block_cb_lookup(f->block,
-					ocelot_setup_tc_block_cb_flower, port);
+					ocelot_setup_tc_block_cb_flower, priv);
 	if (!block_cb) {
-		port_block = ocelot_port_block_create(port);
+		port_block = ocelot_port_block_create(priv);
 		if (!port_block)
 			return -ENOMEM;
 
 		block_cb = flow_block_cb_alloc(ocelot_setup_tc_block_cb_flower,
-					       port, port_block,
+					       priv, port_block,
 					       ocelot_tc_block_unbind);
 		if (IS_ERR(block_cb)) {
 			ret = PTR_ERR(block_cb);
@@ -339,13 +339,13 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
 	return ret;
 }
 
-void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
+void ocelot_setup_tc_block_flower_unbind(struct ocelot_port_private *priv,
 					 struct flow_block_offload *f)
 {
 	struct flow_block_cb *block_cb;
 
 	block_cb = flow_block_cb_lookup(f->block,
-					ocelot_setup_tc_block_cb_flower, port);
+					ocelot_setup_tc_block_cb_flower, priv);
 	if (!block_cb)
 		return;
 
diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
index 9be8e7369d6a..a4f7fbd76507 100644
--- a/drivers/net/ethernet/mscc/ocelot_tc.c
+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
@@ -9,17 +9,19 @@
 #include "ocelot_ace.h"
 #include <net/pkt_cls.h>
 
-static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port,
+static int ocelot_setup_tc_cls_matchall(struct ocelot_port_private *priv,
 					struct tc_cls_matchall_offload *f,
 					bool ingress)
 {
 	struct netlink_ext_ack *extack = f->common.extack;
+	struct ocelot *ocelot = priv->port.ocelot;
 	struct ocelot_policer pol = { 0 };
 	struct flow_action_entry *action;
+	int port = priv->chip_port;
 	int err;
 
-	netdev_dbg(port->dev, "%s: port %u command %d cookie %lu\n",
-		   __func__, port->chip_port, f->command, f->cookie);
+	netdev_dbg(priv->dev, "%s: port %u command %d cookie %lu\n",
+		   __func__, port, f->command, f->cookie);
 
 	if (!ingress) {
 		NL_SET_ERR_MSG_MOD(extack, "Only ingress is supported");
@@ -34,7 +36,7 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port,
 			return -EOPNOTSUPP;
 		}
 
-		if (port->tc.block_shared) {
+		if (priv->tc.block_shared) {
 			NL_SET_ERR_MSG_MOD(extack,
 					   "Rate limit is not supported on shared blocks");
 			return -EOPNOTSUPP;
@@ -47,7 +49,7 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port,
 			return -EOPNOTSUPP;
 		}
 
-		if (port->tc.police_id && port->tc.police_id != f->cookie) {
+		if (priv->tc.police_id && priv->tc.police_id != f->cookie) {
 			NL_SET_ERR_MSG_MOD(extack,
 					   "Only one policer per port is supported\n");
 			return -EEXIST;
@@ -58,28 +60,27 @@ static int ocelot_setup_tc_cls_matchall(struct ocelot_port *port,
 					 PSCHED_NS2TICKS(action->police.burst),
 					 PSCHED_TICKS_PER_SEC);
 
-		err = ocelot_port_policer_add(port->ocelot, port->chip_port,
-					      &pol);
+		err = ocelot_port_policer_add(ocelot, port, &pol);
 		if (err) {
 			NL_SET_ERR_MSG_MOD(extack, "Could not add policer\n");
 			return err;
 		}
 
-		port->tc.police_id = f->cookie;
-		port->tc.offload_cnt++;
+		priv->tc.police_id = f->cookie;
+		priv->tc.offload_cnt++;
 		return 0;
 	case TC_CLSMATCHALL_DESTROY:
-		if (port->tc.police_id != f->cookie)
+		if (priv->tc.police_id != f->cookie)
 			return -ENOENT;
 
-		err = ocelot_port_policer_del(port->ocelot, port->chip_port);
+		err = ocelot_port_policer_del(ocelot, port);
 		if (err) {
 			NL_SET_ERR_MSG_MOD(extack,
 					   "Could not delete policer\n");
 			return err;
 		}
-		port->tc.police_id = 0;
-		port->tc.offload_cnt--;
+		priv->tc.police_id = 0;
+		priv->tc.offload_cnt--;
 		return 0;
 	case TC_CLSMATCHALL_STATS: /* fall through */
 	default:
@@ -91,21 +92,21 @@ static int ocelot_setup_tc_block_cb(enum tc_setup_type type,
 				    void *type_data,
 				    void *cb_priv, bool ingress)
 {
-	struct ocelot_port *port = cb_priv;
+	struct ocelot_port_private *priv = cb_priv;
 
-	if (!tc_cls_can_offload_and_chain0(port->dev, type_data))
+	if (!tc_cls_can_offload_and_chain0(priv->dev, type_data))
 		return -EOPNOTSUPP;
 
 	switch (type) {
 	case TC_SETUP_CLSMATCHALL:
-		netdev_dbg(port->dev, "tc_block_cb: TC_SETUP_CLSMATCHALL %s\n",
+		netdev_dbg(priv->dev, "tc_block_cb: TC_SETUP_CLSMATCHALL %s\n",
 			   ingress ? "ingress" : "egress");
 
-		return ocelot_setup_tc_cls_matchall(port, type_data, ingress);
+		return ocelot_setup_tc_cls_matchall(priv, type_data, ingress);
 	case TC_SETUP_CLSFLOWER:
 		return 0;
 	default:
-		netdev_dbg(port->dev, "tc_block_cb: type %d %s\n",
+		netdev_dbg(priv->dev, "tc_block_cb: type %d %s\n",
 			   type,
 			   ingress ? "ingress" : "egress");
 
@@ -131,19 +132,19 @@ static int ocelot_setup_tc_block_cb_eg(enum tc_setup_type type,
 
 static LIST_HEAD(ocelot_block_cb_list);
 
-static int ocelot_setup_tc_block(struct ocelot_port *port,
+static int ocelot_setup_tc_block(struct ocelot_port_private *priv,
 				 struct flow_block_offload *f)
 {
 	struct flow_block_cb *block_cb;
 	flow_setup_cb_t *cb;
 	int err;
 
-	netdev_dbg(port->dev, "tc_block command %d, binder_type %d\n",
+	netdev_dbg(priv->dev, "tc_block command %d, binder_type %d\n",
 		   f->command, f->binder_type);
 
 	if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
 		cb = ocelot_setup_tc_block_cb_ig;
-		port->tc.block_shared = f->block_shared;
+		priv->tc.block_shared = f->block_shared;
 	} else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
 		cb = ocelot_setup_tc_block_cb_eg;
 	} else {
@@ -154,14 +155,14 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
 
 	switch (f->command) {
 	case FLOW_BLOCK_BIND:
-		if (flow_block_cb_is_busy(cb, port, &ocelot_block_cb_list))
+		if (flow_block_cb_is_busy(cb, priv, &ocelot_block_cb_list))
 			return -EBUSY;
 
-		block_cb = flow_block_cb_alloc(cb, port, port, NULL);
+		block_cb = flow_block_cb_alloc(cb, priv, priv, NULL);
 		if (IS_ERR(block_cb))
 			return PTR_ERR(block_cb);
 
-		err = ocelot_setup_tc_block_flower_bind(port, f);
+		err = ocelot_setup_tc_block_flower_bind(priv, f);
 		if (err < 0) {
 			flow_block_cb_free(block_cb);
 			return err;
@@ -170,11 +171,11 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
 		list_add_tail(&block_cb->driver_list, f->driver_block_list);
 		return 0;
 	case FLOW_BLOCK_UNBIND:
-		block_cb = flow_block_cb_lookup(f->block, cb, port);
+		block_cb = flow_block_cb_lookup(f->block, cb, priv);
 		if (!block_cb)
 			return -ENOENT;
 
-		ocelot_setup_tc_block_flower_unbind(port, f);
+		ocelot_setup_tc_block_flower_unbind(priv, f);
 		flow_block_cb_remove(block_cb, f);
 		list_del(&block_cb->driver_list);
 		return 0;
@@ -186,11 +187,11 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
 int ocelot_setup_tc(struct net_device *dev, enum tc_setup_type type,
 		    void *type_data)
 {
-	struct ocelot_port *port = netdev_priv(dev);
+	struct ocelot_port_private *priv = netdev_priv(dev);
 
 	switch (type) {
 	case TC_SETUP_BLOCK:
-		return ocelot_setup_tc_block(port, type_data);
+		return ocelot_setup_tc_block(priv, type_data);
 	default:
 		return -EOPNOTSUPP;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 08/15] net: mscc: ocelot: refactor ethtool callbacks
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (6 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 07/15] net: mscc: ocelot: separate net_device related items out of ocelot_port Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 09/15] net: mscc: ocelot: limit vlan ingress filtering to actual number of ports Vladimir Oltean
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

Convert them into an implementation that can be called from DSA as well.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 64 ++++++++++++++++++++++--------
 1 file changed, 47 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index ad808344e33b..58ead0652bce 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1191,10 +1191,9 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
 	.ndo_do_ioctl			= ocelot_ioctl,
 };
 
-static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data)
+static void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset,
+			       u8 *data)
 {
-	struct ocelot_port_private *priv = netdev_priv(netdev);
-	struct ocelot *ocelot = priv->port.ocelot;
 	int i;
 
 	if (sset != ETH_SS_STATS)
@@ -1205,6 +1204,16 @@ static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data)
 		       ETH_GSTRING_LEN);
 }
 
+static void ocelot_port_get_strings(struct net_device *netdev, u32 sset,
+				    u8 *data)
+{
+	struct ocelot_port_private *priv = netdev_priv(netdev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
+
+	ocelot_get_strings(ocelot, port, sset, data);
+}
+
 static void ocelot_update_stats(struct ocelot *ocelot)
 {
 	int i, j;
@@ -1245,12 +1254,8 @@ static void ocelot_check_stats_work(struct work_struct *work)
 			   OCELOT_STATS_CHECK_DELAY);
 }
 
-static void ocelot_get_ethtool_stats(struct net_device *dev,
-				     struct ethtool_stats *stats, u64 *data)
+static void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data)
 {
-	struct ocelot_port_private *priv = netdev_priv(dev);
-	struct ocelot *ocelot = priv->port.ocelot;
-	int port = priv->chip_port;
 	int i;
 
 	/* check and update now */
@@ -1261,25 +1266,37 @@ static void ocelot_get_ethtool_stats(struct net_device *dev,
 		*data++ = ocelot->stats[port * ocelot->num_stats + i];
 }
 
-static int ocelot_get_sset_count(struct net_device *dev, int sset)
+static void ocelot_port_get_ethtool_stats(struct net_device *dev,
+					  struct ethtool_stats *stats,
+					  u64 *data)
 {
 	struct ocelot_port_private *priv = netdev_priv(dev);
 	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 
+	ocelot_get_ethtool_stats(ocelot, port, data);
+}
+
+static int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset)
+{
 	if (sset != ETH_SS_STATS)
 		return -EOPNOTSUPP;
+
 	return ocelot->num_stats;
 }
 
-static int ocelot_get_ts_info(struct net_device *dev,
-			      struct ethtool_ts_info *info)
+static int ocelot_port_get_sset_count(struct net_device *dev, int sset)
 {
 	struct ocelot_port_private *priv = netdev_priv(dev);
 	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 
-	if (!ocelot->ptp)
-		return ethtool_op_get_ts_info(dev, info);
+	return ocelot_get_sset_count(ocelot, port, sset);
+}
 
+static int ocelot_get_ts_info(struct ocelot *ocelot, int port,
+			      struct ethtool_ts_info *info)
+{
 	info->phc_index = ocelot->ptp_clock ?
 			  ptp_clock_index(ocelot->ptp_clock) : -1;
 	info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
@@ -1295,13 +1312,26 @@ static int ocelot_get_ts_info(struct net_device *dev,
 	return 0;
 }
 
+static int ocelot_port_get_ts_info(struct net_device *dev,
+				   struct ethtool_ts_info *info)
+{
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
+
+	if (!ocelot->ptp)
+		return ethtool_op_get_ts_info(dev, info);
+
+	return ocelot_get_ts_info(ocelot, port, info);
+}
+
 static const struct ethtool_ops ocelot_ethtool_ops = {
-	.get_strings		= ocelot_get_strings,
-	.get_ethtool_stats	= ocelot_get_ethtool_stats,
-	.get_sset_count		= ocelot_get_sset_count,
+	.get_strings		= ocelot_port_get_strings,
+	.get_ethtool_stats	= ocelot_port_get_ethtool_stats,
+	.get_sset_count		= ocelot_port_get_sset_count,
 	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
 	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
-	.get_ts_info		= ocelot_get_ts_info,
+	.get_ts_info		= ocelot_port_get_ts_info,
 };
 
 static void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 09/15] net: mscc: ocelot: limit vlan ingress filtering to actual number of ports
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (7 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 08/15] net: mscc: ocelot: refactor ethtool callbacks Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-10 16:25   ` Andrew Lunn
  2019-11-09 13:02 ` [PATCH net-next 10/15] net: mscc: ocelot: move port initialization into separate function Vladimir Oltean
                   ` (8 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

The VSC7514 switch (Ocelot) is a 10-port device, while VSC9959 (Felix)
is 6-port. Therefore the VLAN filtering mask would be out of bounds when
calling for this new switch. Fix that.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 58ead0652bce..107a07cfaec9 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -389,7 +389,8 @@ static void ocelot_vlan_init(struct ocelot *ocelot)
 	/* Set vlan ingress filter mask to all ports but the CPU port by
 	 * default.
 	 */
-	ocelot_write(ocelot, GENMASK(9, 0), ANA_VLANMASK);
+	ocelot_write(ocelot, GENMASK(ocelot->num_phys_ports - 1, 0),
+		     ANA_VLANMASK);
 
 	for (port = 0; port < ocelot->num_phys_ports; port++) {
 		ocelot_write_gix(ocelot, 0, REW_PORT_VLAN_CFG, port);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 10/15] net: mscc: ocelot: move port initialization into separate function
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (8 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 09/15] net: mscc: ocelot: limit vlan ingress filtering to actual number of ports Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 11/15] net: mscc: ocelot: separate the common implementation of ndo_open and ndo_stop Vladimir Oltean
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

We need a function for the DSA front-end that does none of the
net_device registration, but initializes the hardware ports.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 45 ++++++++++++++++--------------
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 107a07cfaec9..83ecbbd720fd 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2133,6 +2133,28 @@ static int ocelot_init_timestamp(struct ocelot *ocelot)
 	return 0;
 }
 
+static void ocelot_init_port(struct ocelot *ocelot, int port)
+{
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
+
+	INIT_LIST_HEAD(&ocelot_port->skbs);
+
+	/* Basic L2 initialization */
+
+	/* Drop frames with multicast source address */
+	ocelot_rmw_gix(ocelot, ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
+		       ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
+		       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, port);
+}
+
 int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 		      void __iomem *regs,
 		      struct phy_device *phy)
@@ -2140,7 +2162,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 	struct ocelot_port_private *priv;
 	struct ocelot_port *ocelot_port;
 	struct net_device *dev;
-	u32 val;
 	int err;
 
 	dev = alloc_etherdev(sizeof(struct ocelot_port_private));
@@ -2168,32 +2189,14 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 	ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, ocelot_port->pvid,
 			  ENTRYTYPE_LOCKED);
 
-	INIT_LIST_HEAD(&ocelot_port->skbs);
+	ocelot_init_port(ocelot, port);
 
 	err = register_netdev(dev);
 	if (err) {
 		dev_err(ocelot->dev, "register_netdev failed\n");
-		goto err_register_netdev;
+		free_netdev(dev);
 	}
 
-	/* Basic L2 initialization */
-
-	/* 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, port);
-
-	return 0;
-
-err_register_netdev:
-	free_netdev(dev);
 	return err;
 }
 EXPORT_SYMBOL(ocelot_probe_port);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 11/15] net: mscc: ocelot: separate the common implementation of ndo_open and ndo_stop
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (9 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 10/15] net: mscc: ocelot: move port initialization into separate function Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 12/15] net: mscc: ocelot: initialize list of multicast addresses in common code Vladimir Oltean
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

Allow these functions to be called from the .port_enable and
.port_disable callbacks of DSA.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 36 +++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 83ecbbd720fd..df8796f05ff9 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -536,13 +536,9 @@ static void ocelot_port_adjust_link(struct net_device *dev)
 	ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
 }
 
-static int ocelot_port_open(struct net_device *dev)
+static void ocelot_port_enable(struct ocelot *ocelot, int port,
+			       struct phy_device *phy)
 {
-	struct ocelot_port_private *priv = netdev_priv(dev);
-	struct ocelot *ocelot = priv->port.ocelot;
-	int port = priv->chip_port;
-	int err;
-
 	/* Enable receiving frames on the port, and activate auto-learning of
 	 * MAC addresses.
 	 */
@@ -550,6 +546,14 @@ static int ocelot_port_open(struct net_device *dev)
 			 ANA_PORT_PORT_CFG_RECV_ENA |
 			 ANA_PORT_PORT_CFG_PORTID_VAL(port),
 			 ANA_PORT_PORT_CFG, port);
+}
+
+static int ocelot_port_open(struct net_device *dev)
+{
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
+	int err;
 
 	if (priv->serdes) {
 		err = phy_set_mode_ext(priv->serdes, PHY_MODE_ETHERNET,
@@ -571,21 +575,33 @@ static int ocelot_port_open(struct net_device *dev)
 
 	phy_attached_info(priv->phy);
 	phy_start(priv->phy);
+
+	ocelot_port_enable(ocelot, port, priv->phy);
+
 	return 0;
 }
 
+static void ocelot_port_disable(struct ocelot *ocelot, int port)
+{
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
+
+	ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
+	ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
+		       QSYS_SWITCH_PORT_MODE, port);
+}
+
 static int ocelot_port_stop(struct net_device *dev)
 {
 	struct ocelot_port_private *priv = netdev_priv(dev);
-	struct ocelot_port *port = &priv->port;
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
 
 	phy_disconnect(priv->phy);
 
 	dev->phydev = NULL;
 
-	ocelot_port_writel(port, 0, DEV_MAC_ENA_CFG);
-	ocelot_rmw_rix(port->ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
-		       QSYS_SWITCH_PORT_MODE, priv->chip_port);
+	ocelot_port_disable(ocelot, port);
+
 	return 0;
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 12/15] net: mscc: ocelot: initialize list of multicast addresses in common code
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (10 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 11/15] net: mscc: ocelot: separate the common implementation of ndo_open and ndo_stop Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:02 ` [PATCH net-next 13/15] net: mscc: ocelot: refactor adjust_link into a netdev-independent function Vladimir Oltean
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Claudiu Manoil <claudiu.manoil@nxp.com>

This is just common path code that belongs to ocelot_init,
it has nothing to do with a specific SoC/board instance.

Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c       | 1 +
 drivers/net/ethernet/mscc/ocelot_board.c | 1 -
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index df8796f05ff9..4cb78e14f2fd 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2243,6 +2243,7 @@ int ocelot_init(struct ocelot *ocelot)
 	if (!ocelot->stats_queue)
 		return -ENOMEM;
 
+	INIT_LIST_HEAD(&ocelot->multicast);
 	ocelot_mact_init(ocelot);
 	ocelot_vlan_init(ocelot);
 	ocelot_ace_init(ocelot);
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 4793d275d845..9985fb334aac 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -364,7 +364,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 	ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,
 				     sizeof(struct ocelot_port *), GFP_KERNEL);
 
-	INIT_LIST_HEAD(&ocelot->multicast);
 	ocelot_init(ocelot);
 
 	for_each_available_child_of_node(ports, portnp) {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 13/15] net: mscc: ocelot: refactor adjust_link into a netdev-independent function
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (11 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 12/15] net: mscc: ocelot: initialize list of multicast addresses in common code Vladimir Oltean
@ 2019-11-09 13:02 ` Vladimir Oltean
  2019-11-09 13:03 ` [PATCH net-next 14/15] net: mscc: ocelot: split assignment of the cpu port into a separate function Vladimir Oltean
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:02 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

This will be called from the Felix DSA frontend, which will work in
PHYLIB compatibility mode initially.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 4cb78e14f2fd..7f0bd89fc363 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -410,15 +410,13 @@ static u16 ocelot_wm_enc(u16 value)
 	return value;
 }
 
-static void ocelot_port_adjust_link(struct net_device *dev)
+static void ocelot_adjust_link(struct ocelot *ocelot, int port,
+			       struct phy_device *phydev)
 {
-	struct ocelot_port_private *priv = netdev_priv(dev);
-	struct ocelot_port *ocelot_port = &priv->port;
-	struct ocelot *ocelot = ocelot_port->ocelot;
+	struct ocelot_port *ocelot_port = ocelot->ports[port];
 	int speed, atop_wm, mode = 0;
-	u8 port = priv->chip_port;
 
-	switch (dev->phydev->speed) {
+	switch (phydev->speed) {
 	case SPEED_10:
 		speed = OCELOT_SPEED_10;
 		break;
@@ -434,14 +432,14 @@ static void ocelot_port_adjust_link(struct net_device *dev)
 		mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
 		break;
 	default:
-		netdev_err(dev, "Unsupported PHY speed: %d\n",
-			   dev->phydev->speed);
+		dev_err(ocelot->dev, "Unsupported PHY speed on port %d: %d\n",
+			port, phydev->speed);
 		return;
 	}
 
-	phy_print_status(dev->phydev);
+	phy_print_status(phydev);
 
-	if (!dev->phydev->link)
+	if (!phydev->link)
 		return;
 
 	/* Only full duplex supported for now */
@@ -536,6 +534,15 @@ static void ocelot_port_adjust_link(struct net_device *dev)
 	ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
 }
 
+static void ocelot_port_adjust_link(struct net_device *dev)
+{
+	struct ocelot_port_private *priv = netdev_priv(dev);
+	struct ocelot *ocelot = priv->port.ocelot;
+	int port = priv->chip_port;
+
+	ocelot_adjust_link(ocelot, port, dev->phydev);
+}
+
 static void ocelot_port_enable(struct ocelot *ocelot, int port,
 			       struct phy_device *phy)
 {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 14/15] net: mscc: ocelot: split assignment of the cpu port into a separate function
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (12 preceding siblings ...)
  2019-11-09 13:02 ` [PATCH net-next 13/15] net: mscc: ocelot: refactor adjust_link into a netdev-independent function Vladimir Oltean
@ 2019-11-09 13:03 ` Vladimir Oltean
  2019-11-10 16:32   ` Andrew Lunn
  2019-11-09 13:03 ` [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port Vladimir Oltean
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:03 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

Now that the places that configure routing destinations for the CPU port
have been marked as such, allow callers to specify their own CPU port
that is different than ocelot->num_phys_ports. A user will be the Felix
DSA driver, where the CPU port is one of the physical ports (NPI mode).

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c       | 65 ++++++++++++++++--------
 drivers/net/ethernet/mscc/ocelot.h       | 12 +++++
 drivers/net/ethernet/mscc/ocelot_board.c |  2 +
 3 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 7f0bd89fc363..bba6d60dc5a8 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -380,12 +380,6 @@ static void ocelot_vlan_init(struct ocelot *ocelot)
 	ocelot->vlan_mask[0] = GENMASK(ocelot->num_phys_ports - 1, 0);
 	ocelot_vlant_set_mask(ocelot, 0, ocelot->vlan_mask[0]);
 
-	/* Configure the CPU port to be VLAN aware */
-	ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
-				 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
-				 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
-			 ANA_PORT_VLAN_CFG, ocelot->num_phys_ports);
-
 	/* Set vlan ingress filter mask to all ports but the CPU port by
 	 * default.
 	 */
@@ -2224,11 +2218,52 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 }
 EXPORT_SYMBOL(ocelot_probe_port);
 
+void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
+			 enum ocelot_tag_prefix injection,
+			 enum ocelot_tag_prefix extraction)
+{
+	/* Configure and enable the CPU port. */
+	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
+	ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
+	ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
+			 ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
+			 ANA_PORT_PORT_CFG, cpu);
+
+	/* If the CPU port is a physical port, set up the port in Node
+	 * Processor Interface (NPI) mode. This is the mode through which
+	 * frames can be injected from and extracted to an external CPU.
+	 * Only one port can be an NPI at the same time.
+	 */
+	if (cpu < ocelot->num_phys_ports) {
+		ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
+			     QSYS_EXT_CPU_CFG_EXT_CPU_PORT(cpu),
+			     QSYS_EXT_CPU_CFG);
+	}
+
+	/* CPU port Injection/Extraction configuration */
+	ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
+			 QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
+			 QSYS_SWITCH_PORT_MODE_PORT_ENA,
+			 QSYS_SWITCH_PORT_MODE, cpu);
+	ocelot_write_rix(ocelot, SYS_PORT_MODE_INCL_XTR_HDR(extraction) |
+			 SYS_PORT_MODE_INCL_INJ_HDR(injection),
+			 SYS_PORT_MODE, cpu);
+
+	/* Configure the CPU port to be VLAN aware */
+	ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
+				 ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
+				 ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
+			 ANA_PORT_VLAN_CFG, cpu);
+
+	ocelot->cpu = cpu;
+}
+EXPORT_SYMBOL(ocelot_set_cpu_port);
+
 int ocelot_init(struct ocelot *ocelot)
 {
-	u32 port;
-	int i, ret, cpu = ocelot->num_phys_ports;
 	char queue_name[32];
+	int i, ret;
+	u32 port;
 
 	ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
 				    sizeof(u32), GFP_KERNEL);
@@ -2308,13 +2343,6 @@ int ocelot_init(struct ocelot *ocelot)
 		ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_SRC + port);
 	}
 
-	/* Configure and enable the CPU port. */
-	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
-	ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
-	ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
-			 ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
-			 ANA_PORT_PORT_CFG, cpu);
-
 	/* Allow broadcast MAC frames. */
 	for (i = ocelot->num_phys_ports + 1; i < PGID_CPU; i++) {
 		u32 val = ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports - 1, 0));
@@ -2327,13 +2355,6 @@ int ocelot_init(struct ocelot *ocelot)
 	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV4);
 	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV6);
 
-	/* CPU port Injection/Extraction configuration */
-	ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
-			 QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG(1) |
-			 QSYS_SWITCH_PORT_MODE_PORT_ENA,
-			 QSYS_SWITCH_PORT_MODE, cpu);
-	ocelot_write_rix(ocelot, SYS_PORT_MODE_INCL_XTR_HDR(1) |
-			 SYS_PORT_MODE_INCL_INJ_HDR(1), SYS_PORT_MODE, cpu);
 	/* Allow manual injection via DEVCPU_QS registers, and byte swap these
 	 * registers endianness.
 	 */
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 7f3526151fa9..4d8e769ccad9 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -427,6 +427,13 @@ struct ocelot_multicast {
 	u16 ports;
 };
 
+enum ocelot_tag_prefix {
+	OCELOT_TAG_PREFIX_DISABLED	= 0,
+	OCELOT_TAG_PREFIX_NONE,
+	OCELOT_TAG_PREFIX_SHORT,
+	OCELOT_TAG_PREFIX_LONG,
+};
+
 struct ocelot_port;
 
 struct ocelot_stat_layout {
@@ -455,6 +462,7 @@ struct ocelot {
 
 	u8 num_phys_ports;
 	u8 num_cpu_ports;
+	u8 cpu;
 	struct ocelot_port **ports;
 
 	u32 *lags;
@@ -552,6 +560,10 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
 		      void __iomem *regs,
 		      struct phy_device *phy);
 
+void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
+			 enum ocelot_tag_prefix injection,
+			 enum ocelot_tag_prefix extraction);
+
 extern struct notifier_block ocelot_netdevice_nb;
 extern struct notifier_block ocelot_switchdev_nb;
 extern struct notifier_block ocelot_switchdev_blocking_nb;
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 9985fb334aac..811599f32910 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -365,6 +365,8 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 				     sizeof(struct ocelot_port *), GFP_KERNEL);
 
 	ocelot_init(ocelot);
+	ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports,
+			    OCELOT_TAG_PREFIX_NONE, OCELOT_TAG_PREFIX_NONE);
 
 	for_each_available_child_of_node(ports, portnp) {
 		struct ocelot_port_private *priv;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (13 preceding siblings ...)
  2019-11-09 13:03 ` [PATCH net-next 14/15] net: mscc: ocelot: split assignment of the cpu port into a separate function Vladimir Oltean
@ 2019-11-09 13:03 ` Vladimir Oltean
  2019-11-10 16:50   ` Andrew Lunn
  2019-11-10 17:16 ` [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Andrew Lunn
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-09 13:03 UTC (permalink / raw)
  To: jakub.kicinski, davem, alexandre.belloni
  Cc: andrew, f.fainelli, vivien.didelot, joergen.andreasen,
	allan.nielsen, horatiu.vultur, claudiu.manoil, netdev,
	Vladimir Oltean

From: Vladimir Oltean <vladimir.oltean@nxp.com>

VSC7514 is a 10-port switch with 2 extra "CPU ports" (targets in the
queuing subsystem for terminating traffic locally).

There are 2 issues with hardcoding the CPU port as #10:
- It is not clear which snippets of the code are configuring something
  for one of the CPU ports, and which snippets are just doing something
  related to the number of physical ports.
- Actually any physical port can act as a CPU port connected to an
  external CPU (in addition to the local CPU). This is called NPI mode
  (Node Processor Interface) and is the way that the 6-port VSC9959
  (Felix) switch is integrated inside NXP LS1028A (the "local management
  CPU" functionality is not used there).

This patch makes it clear that the ocelot_bridge_stp_state_set function
operates on the CPU port (by making it an implicit member of the
bridging domain), and at the same time adds logic for the NPI port (aka
a physical port) to play the role of a CPU port (it shouldn't be part of
bridge_fwd_mask, as it's not explicitly enslaved to a bridge).

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/mscc/ocelot.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index bba6d60dc5a8..3e7a2796c37d 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1383,7 +1383,7 @@ static void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port,
 	 * a source for the other ports.
 	 */
 	for (p = 0; p < ocelot->num_phys_ports; p++) {
-		if (ocelot->bridge_fwd_mask & BIT(p)) {
+		if (p == ocelot->cpu || (ocelot->bridge_fwd_mask & BIT(p))) {
 			unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(p);
 
 			for (i = 0; i < ocelot->num_phys_ports; i++) {
@@ -1398,15 +1398,18 @@ static void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port,
 				}
 			}
 
-			ocelot_write_rix(ocelot,
-					 BIT(ocelot->num_phys_ports) | mask,
+			/* Avoid the NPI port from looping back to itself */
+			if (p != ocelot->cpu)
+				mask |= BIT(ocelot->cpu);
+
+			ocelot_write_rix(ocelot, mask,
 					 ANA_PGID_PGID, PGID_SRC + p);
 		} else {
 			/* Only the CPU port, this is compatible with link
 			 * aggregation.
 			 */
 			ocelot_write_rix(ocelot,
-					 BIT(ocelot->num_phys_ports),
+					 BIT(ocelot->cpu),
 					 ANA_PGID_PGID, PGID_SRC + p);
 		}
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 09/15] net: mscc: ocelot: limit vlan ingress filtering to actual number of ports
  2019-11-09 13:02 ` [PATCH net-next 09/15] net: mscc: ocelot: limit vlan ingress filtering to actual number of ports Vladimir Oltean
@ 2019-11-10 16:25   ` Andrew Lunn
  2019-11-10 16:29     ` Vladimir Oltean
  0 siblings, 1 reply; 33+ messages in thread
From: Andrew Lunn @ 2019-11-10 16:25 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: jakub.kicinski, davem, alexandre.belloni, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, horatiu.vultur,
	claudiu.manoil, netdev, Vladimir Oltean

On Sat, Nov 09, 2019 at 03:02:55PM +0200, Vladimir Oltean wrote:
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
> 
> The VSC7514 switch (Ocelot) is a 10-port device, while VSC9959 (Felix)
> is 6-port. Therefore the VLAN filtering mask would be out of bounds when
> calling for this new switch. Fix that.

Hi Vladimir

Is this a real fix? Should it be posted to net?

Thanks
	Andrew

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 09/15] net: mscc: ocelot: limit vlan ingress filtering to actual number of ports
  2019-11-10 16:25   ` Andrew Lunn
@ 2019-11-10 16:29     ` Vladimir Oltean
  0 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-10 16:29 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Jakub Kicinski, David S. Miller, Alexandre Belloni,
	Florian Fainelli, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Horatiu Vultur, Claudiu Manoil, netdev,
	Vladimir Oltean

On Sun, 10 Nov 2019 at 18:26, Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Sat, Nov 09, 2019 at 03:02:55PM +0200, Vladimir Oltean wrote:
> > From: Vladimir Oltean <vladimir.oltean@nxp.com>
> >
> > The VSC7514 switch (Ocelot) is a 10-port device, while VSC9959 (Felix)
> > is 6-port. Therefore the VLAN filtering mask would be out of bounds when
> > calling for this new switch. Fix that.
>
> Hi Vladimir
>
> Is this a real fix? Should it be posted to net?
>
> Thanks
>         Andrew

Hi Andrew,

Felix is not supported by the mainline ocelot driver yet, so there's
no bug per se: ocelot->num_phys_ports can only be 10 at the moment.

Thanks,
-Vladimir

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 14/15] net: mscc: ocelot: split assignment of the cpu port into a separate function
  2019-11-09 13:03 ` [PATCH net-next 14/15] net: mscc: ocelot: split assignment of the cpu port into a separate function Vladimir Oltean
@ 2019-11-10 16:32   ` Andrew Lunn
  2019-11-10 16:40     ` Vladimir Oltean
  0 siblings, 1 reply; 33+ messages in thread
From: Andrew Lunn @ 2019-11-10 16:32 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: jakub.kicinski, davem, alexandre.belloni, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, horatiu.vultur,
	claudiu.manoil, netdev, Vladimir Oltean

> +void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
> +			 enum ocelot_tag_prefix injection,
> +			 enum ocelot_tag_prefix extraction)
> +{
> +	/* Configure and enable the CPU port. */
> +	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
> +	ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
> +	ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
> +			 ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
> +			 ANA_PORT_PORT_CFG, cpu);
> +
> +	/* If the CPU port is a physical port, set up the port in Node
> +	 * Processor Interface (NPI) mode. This is the mode through which
> +	 * frames can be injected from and extracted to an external CPU.
> +	 * Only one port can be an NPI at the same time.
> +	 */
> +	if (cpu < ocelot->num_phys_ports) {
> +		ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
> +			     QSYS_EXT_CPU_CFG_EXT_CPU_PORT(cpu),
> +			     QSYS_EXT_CPU_CFG);
> +	}

If a port is not a physical port, what is it? Is it actually an error
if the CPU port is not physical? Should we be returning -EINVAL here,
indicating the device tree is bad?

	   Andrew

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 14/15] net: mscc: ocelot: split assignment of the cpu port into a separate function
  2019-11-10 16:32   ` Andrew Lunn
@ 2019-11-10 16:40     ` Vladimir Oltean
  2019-11-10 16:50       ` Vladimir Oltean
  0 siblings, 1 reply; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-10 16:40 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Jakub Kicinski, David S. Miller, Alexandre Belloni,
	Florian Fainelli, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Horatiu Vultur, Claudiu Manoil, netdev,
	Vladimir Oltean

On Sun, 10 Nov 2019 at 18:32, Andrew Lunn <andrew@lunn.ch> wrote:
>
> > +void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
> > +                      enum ocelot_tag_prefix injection,
> > +                      enum ocelot_tag_prefix extraction)
> > +{
> > +     /* Configure and enable the CPU port. */
> > +     ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
> > +     ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
> > +     ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
> > +                      ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
> > +                      ANA_PORT_PORT_CFG, cpu);
> > +
> > +     /* If the CPU port is a physical port, set up the port in Node
> > +      * Processor Interface (NPI) mode. This is the mode through which
> > +      * frames can be injected from and extracted to an external CPU.
> > +      * Only one port can be an NPI at the same time.
> > +      */
> > +     if (cpu < ocelot->num_phys_ports) {
> > +             ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
> > +                          QSYS_EXT_CPU_CFG_EXT_CPU_PORT(cpu),
> > +                          QSYS_EXT_CPU_CFG);
> > +     }
>
> If a port is not a physical port, what is it? Is it actually an error
> if the CPU port is not physical? Should we be returning -EINVAL here,
> indicating the device tree is bad?
>
>            Andrew

The Vitesse switches have a number of "physical" ports and a number of
"CPU" ports. By "port", one understands a target in the queuing
subsystem, with learning, flooding, forwarding, etc. The CPU ports
that are not physical don't have an 802.3 MAC. Then frame transfer
happens over DMA from its queues, PIO, etc (depending on SoC
integration). In the LS1028A SoC instantiation of the Felix switch
(which is an instantiation of the Ocelot core with less ports and
support for TSN), the CPU port _is_ physical (aka is a MAC connected
back-to-back to an ENETC DSA master), and that is what is being
understood by NPI mode.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port
  2019-11-09 13:03 ` [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port Vladimir Oltean
@ 2019-11-10 16:50   ` Andrew Lunn
  2019-11-10 17:00     ` Vladimir Oltean
  0 siblings, 1 reply; 33+ messages in thread
From: Andrew Lunn @ 2019-11-10 16:50 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: jakub.kicinski, davem, alexandre.belloni, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, horatiu.vultur,
	claudiu.manoil, netdev, Vladimir Oltean

On Sat, Nov 09, 2019 at 03:03:01PM +0200, Vladimir Oltean wrote:
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
> 
> VSC7514 is a 10-port switch with 2 extra "CPU ports" (targets in the
> queuing subsystem for terminating traffic locally).

So maybe that answers my last question.
 
> There are 2 issues with hardcoding the CPU port as #10:
> - It is not clear which snippets of the code are configuring something
>   for one of the CPU ports, and which snippets are just doing something
>   related to the number of physical ports.
> - Actually any physical port can act as a CPU port connected to an
>   external CPU (in addition to the local CPU). This is called NPI mode
>   (Node Processor Interface) and is the way that the 6-port VSC9959
>   (Felix) switch is integrated inside NXP LS1028A (the "local management
>   CPU" functionality is not used there).

So i'm having trouble reading this and spotting the difference between
the DSA concept of a CPU port and the two extra "CPU ports". Maybe
using the concept of virtual ports would help?

Are the physical ports number 0-9, and so port #10 is the first extra
"CPU port", aka a virtual port? And so that would not work for DSA,
where you need a physical port.

      Andrew

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 14/15] net: mscc: ocelot: split assignment of the cpu port into a separate function
  2019-11-10 16:40     ` Vladimir Oltean
@ 2019-11-10 16:50       ` Vladimir Oltean
  0 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-10 16:50 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Jakub Kicinski, David S. Miller, Alexandre Belloni,
	Florian Fainelli, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Horatiu Vultur, Claudiu Manoil, netdev,
	Vladimir Oltean

On Sun, 10 Nov 2019 at 18:40, Vladimir Oltean <olteanv@gmail.com> wrote:
>
> On Sun, 10 Nov 2019 at 18:32, Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > > +void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
> > > +                      enum ocelot_tag_prefix injection,
> > > +                      enum ocelot_tag_prefix extraction)
> > > +{
> > > +     /* Configure and enable the CPU port. */
> > > +     ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
> > > +     ocelot_write_rix(ocelot, BIT(cpu), ANA_PGID_PGID, PGID_CPU);
> > > +     ocelot_write_gix(ocelot, ANA_PORT_PORT_CFG_RECV_ENA |
> > > +                      ANA_PORT_PORT_CFG_PORTID_VAL(cpu),
> > > +                      ANA_PORT_PORT_CFG, cpu);
> > > +
> > > +     /* If the CPU port is a physical port, set up the port in Node
> > > +      * Processor Interface (NPI) mode. This is the mode through which
> > > +      * frames can be injected from and extracted to an external CPU.
> > > +      * Only one port can be an NPI at the same time.
> > > +      */
> > > +     if (cpu < ocelot->num_phys_ports) {
> > > +             ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
> > > +                          QSYS_EXT_CPU_CFG_EXT_CPU_PORT(cpu),
> > > +                          QSYS_EXT_CPU_CFG);
> > > +     }
> >
> > If a port is not a physical port, what is it? Is it actually an error
> > if the CPU port is not physical? Should we be returning -EINVAL here,
> > indicating the device tree is bad?
> >
> >            Andrew
>
> The Vitesse switches have a number of "physical" ports and a number of
> "CPU" ports. By "port", one understands a target in the queuing
> subsystem, with learning, flooding, forwarding, etc. The CPU ports
> that are not physical don't have an 802.3 MAC. Then frame transfer
> happens over DMA from its queues, PIO, etc (depending on SoC
> integration). In the LS1028A SoC instantiation of the Felix switch
> (which is an instantiation of the Ocelot core with less ports and
> support for TSN), the CPU port _is_ physical (aka is a MAC connected
> back-to-back to an ENETC DSA master), and that is what is being
> understood by NPI mode.

If this is still confusing, take for example Ocelot
(http://ww1.microchip.com/downloads/en/DeviceDoc/VMDS-10491.pdf). The
physical ports are 0-9, and the CPU ports are 10 and 11. So the ocelot
driver was hardcoding the CPU port to 10, which is the first port
outside the num_phys_ports range.

I don't expect any caller to specify an invalid CPU port, so returning
-EINVAL would just be overhead here. Neither of the 2 entry points of
this function (one in mainline, one as a currently downstream patch)
can. The Ocelot SoC driver (ocelot_board.c) always sets port #10 as
CPU port, which is legit, and the Felix driver always sets one of the
physical ports as CPU port, which again is legit.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port
  2019-11-10 16:50   ` Andrew Lunn
@ 2019-11-10 17:00     ` Vladimir Oltean
  2019-11-10 17:12       ` Andrew Lunn
  0 siblings, 1 reply; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-10 17:00 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Jakub Kicinski, David S. Miller, Alexandre Belloni,
	Florian Fainelli, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Horatiu Vultur, Claudiu Manoil, netdev,
	Vladimir Oltean

On Sun, 10 Nov 2019 at 18:50, Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Sat, Nov 09, 2019 at 03:03:01PM +0200, Vladimir Oltean wrote:
> > From: Vladimir Oltean <vladimir.oltean@nxp.com>
> >
> > VSC7514 is a 10-port switch with 2 extra "CPU ports" (targets in the
> > queuing subsystem for terminating traffic locally).
>
> So maybe that answers my last question.
>
> > There are 2 issues with hardcoding the CPU port as #10:
> > - It is not clear which snippets of the code are configuring something
> >   for one of the CPU ports, and which snippets are just doing something
> >   related to the number of physical ports.
> > - Actually any physical port can act as a CPU port connected to an
> >   external CPU (in addition to the local CPU). This is called NPI mode
> >   (Node Processor Interface) and is the way that the 6-port VSC9959
> >   (Felix) switch is integrated inside NXP LS1028A (the "local management
> >   CPU" functionality is not used there).
>
> So i'm having trouble reading this and spotting the difference between
> the DSA concept of a CPU port and the two extra "CPU ports". Maybe
> using the concept of virtual ports would help?
>
> Are the physical ports number 0-9, and so port #10 is the first extra
> "CPU port", aka a virtual port? And so that would not work for DSA,
> where you need a physical port.
>
>       Andrew

Right. See my other answer which links to Ocelot documentation. The
3.14 chapter "CPU Port Module" should clarify. The switch core has a
number of CPU ports (typically 2) which are to be integrated with
SoC-specific frame transfer abilities, typically DMA. The way this was
integrated in LS1028A is described by: "It is also possible to use a
regular front port as a CPU port. This is known as a Node Processor
Interface (NPI)." So the embedded switch and the rest of the system
are strangers and talk over Ethernet (the 2 "virtual" CPU ports are
not used), hence the reason why the "normal" (virtual, etc) CPU ports
are better modelled as switchdev and the "NPI" CPU port is better
modelled as DSA.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port
  2019-11-10 17:00     ` Vladimir Oltean
@ 2019-11-10 17:12       ` Andrew Lunn
  2019-11-10 17:33         ` Vladimir Oltean
  0 siblings, 1 reply; 33+ messages in thread
From: Andrew Lunn @ 2019-11-10 17:12 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Jakub Kicinski, David S. Miller, Alexandre Belloni,
	Florian Fainelli, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Horatiu Vultur, Claudiu Manoil, netdev,
	Vladimir Oltean

On Sun, Nov 10, 2019 at 07:00:33PM +0200, Vladimir Oltean wrote:
> On Sun, 10 Nov 2019 at 18:50, Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > On Sat, Nov 09, 2019 at 03:03:01PM +0200, Vladimir Oltean wrote:
> > > From: Vladimir Oltean <vladimir.oltean@nxp.com>
> > >
> > > VSC7514 is a 10-port switch with 2 extra "CPU ports" (targets in the
> > > queuing subsystem for terminating traffic locally).
> >
> > So maybe that answers my last question.
> >
> > > There are 2 issues with hardcoding the CPU port as #10:
> > > - It is not clear which snippets of the code are configuring something
> > >   for one of the CPU ports, and which snippets are just doing something
> > >   related to the number of physical ports.
> > > - Actually any physical port can act as a CPU port connected to an
> > >   external CPU (in addition to the local CPU). This is called NPI mode
> > >   (Node Processor Interface) and is the way that the 6-port VSC9959
> > >   (Felix) switch is integrated inside NXP LS1028A (the "local management
> > >   CPU" functionality is not used there).
> >
> > So i'm having trouble reading this and spotting the difference between
> > the DSA concept of a CPU port and the two extra "CPU ports". Maybe
> > using the concept of virtual ports would help?
> >
> > Are the physical ports number 0-9, and so port #10 is the first extra
> > "CPU port", aka a virtual port? And so that would not work for DSA,
> > where you need a physical port.
> >
> >       Andrew
> 
> Right. See my other answer which links to Ocelot documentation.

Yes, i'm getting the picture now.

The basic problem is that in the Linux kernel CPU port has a specific
meaning, and it is clashing with the meaning used in the datasheet. So
maybe in the driver, we need to refer to these two ports as 'local
ports'?

The mv88e6xxx driver has a similar problem. Some of the switches have
a Z80 embedded in them. And this Z80 has an ethernet interface
connected to the switch core as port 12. So far we don't support it,
but if we ever do, i'm sure we will end up calling it the z80 port,
not the cpu port.

    Andrew

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (14 preceding siblings ...)
  2019-11-09 13:03 ` [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port Vladimir Oltean
@ 2019-11-10 17:16 ` Andrew Lunn
  2019-11-10 17:22   ` Vladimir Oltean
  2019-11-11 12:10 ` Horatiu Vultur
  2019-11-11 20:59 ` David Miller
  17 siblings, 1 reply; 33+ messages in thread
From: Andrew Lunn @ 2019-11-10 17:16 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: jakub.kicinski, davem, alexandre.belloni, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, horatiu.vultur,
	claudiu.manoil, netdev

On Sat, Nov 09, 2019 at 03:02:46PM +0200, Vladimir Oltean wrote:
> After the nice "change-my-mind" discussion about Ocelot, Felix and
> LS1028A (which can be read here: https://lkml.org/lkml/2019/6/21/630),
> we have decided to take the route of reworking the Ocelot implementation
> in a way that is DSA-compatible.
> 
> This is a large series, but hopefully is easy enough to digest, since it
> contains mostly code refactoring.

I just skimmed over the patches. Apart from the naming confusion at
the end, it all looks O.K.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

> It also means that Ocelot practically re-implements large parts of
> DSA (although it is not a DSA switch per se)

Would it make sense to refactor parts of the DSA core and export them
as helper function?

   Andrew

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot
  2019-11-10 17:16 ` [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Andrew Lunn
@ 2019-11-10 17:22   ` Vladimir Oltean
  0 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-10 17:22 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Jakub Kicinski, David S. Miller, Alexandre Belloni,
	Florian Fainelli, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Horatiu Vultur, Claudiu Manoil, netdev

On Sun, 10 Nov 2019 at 19:16, Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Sat, Nov 09, 2019 at 03:02:46PM +0200, Vladimir Oltean wrote:
> > After the nice "change-my-mind" discussion about Ocelot, Felix and
> > LS1028A (which can be read here: https://lkml.org/lkml/2019/6/21/630),
> > we have decided to take the route of reworking the Ocelot implementation
> > in a way that is DSA-compatible.
> >
> > This is a large series, but hopefully is easy enough to digest, since it
> > contains mostly code refactoring.
>
> I just skimmed over the patches. Apart from the naming confusion at
> the end, it all looks O.K.
>
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
>

Thanks a lot! Would it be too early if I also posted the Felix DSA
driver as well?

> > It also means that Ocelot practically re-implements large parts of
> > DSA (although it is not a DSA switch per se)
>
> Would it make sense to refactor parts of the DSA core and export them
> as helper function?

Where it helps, I'll sure consider doing that. We'll anyway need to
add support for tc-flower in DSA, filter blocks and all of that. At
the moment, only the FDB dump code was slightly duplicated, but then
again, that's because some boilerplate is needed, and it was there
anyway. So far it's manageable.

>
>    Andrew

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port
  2019-11-10 17:12       ` Andrew Lunn
@ 2019-11-10 17:33         ` Vladimir Oltean
  2019-11-10 20:54           ` Florian Fainelli
  0 siblings, 1 reply; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-10 17:33 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Jakub Kicinski, David S. Miller, Alexandre Belloni,
	Florian Fainelli, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Horatiu Vultur, Claudiu Manoil, netdev,
	Vladimir Oltean

On Sun, 10 Nov 2019 at 19:12, Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Sun, Nov 10, 2019 at 07:00:33PM +0200, Vladimir Oltean wrote:
> > On Sun, 10 Nov 2019 at 18:50, Andrew Lunn <andrew@lunn.ch> wrote:
> > >
> > > On Sat, Nov 09, 2019 at 03:03:01PM +0200, Vladimir Oltean wrote:
> > > > From: Vladimir Oltean <vladimir.oltean@nxp.com>
> > > >
> > > > VSC7514 is a 10-port switch with 2 extra "CPU ports" (targets in the
> > > > queuing subsystem for terminating traffic locally).
> > >
> > > So maybe that answers my last question.
> > >
> > > > There are 2 issues with hardcoding the CPU port as #10:
> > > > - It is not clear which snippets of the code are configuring something
> > > >   for one of the CPU ports, and which snippets are just doing something
> > > >   related to the number of physical ports.
> > > > - Actually any physical port can act as a CPU port connected to an
> > > >   external CPU (in addition to the local CPU). This is called NPI mode
> > > >   (Node Processor Interface) and is the way that the 6-port VSC9959
> > > >   (Felix) switch is integrated inside NXP LS1028A (the "local management
> > > >   CPU" functionality is not used there).
> > >
> > > So i'm having trouble reading this and spotting the difference between
> > > the DSA concept of a CPU port and the two extra "CPU ports". Maybe
> > > using the concept of virtual ports would help?
> > >
> > > Are the physical ports number 0-9, and so port #10 is the first extra
> > > "CPU port", aka a virtual port? And so that would not work for DSA,
> > > where you need a physical port.
> > >
> > >       Andrew
> >
> > Right. See my other answer which links to Ocelot documentation.
>
> Yes, i'm getting the picture now.
>
> The basic problem is that in the Linux kernel CPU port has a specific
> meaning, and it is clashing with the meaning used in the datasheet. So
> maybe in the driver, we need to refer to these two ports as 'local
> ports'?
>

Hmm, I don't know. Both types of CPU ports lead to management CPUs,
but to different types of them. I understand the clash with the DSA
meaning, but even if I rename it I would have to provide an
explanation relative to the datasheet definitions (and I already
explain that the NPI mode is the DSA type of CPU port). I'm not sure
there is a net gain.

> The mv88e6xxx driver has a similar problem. Some of the switches have
> a Z80 embedded in them. And this Z80 has an ethernet interface
> connected to the switch core as port 12. So far we don't support it,
> but if we ever do, i'm sure we will end up calling it the z80 port,
> not the cpu port.
>
>     Andrew

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port
  2019-11-10 17:33         ` Vladimir Oltean
@ 2019-11-10 20:54           ` Florian Fainelli
  2019-11-12  0:53             ` Vladimir Oltean
  0 siblings, 1 reply; 33+ messages in thread
From: Florian Fainelli @ 2019-11-10 20:54 UTC (permalink / raw)
  To: Vladimir Oltean, Andrew Lunn
  Cc: Jakub Kicinski, David S. Miller, Alexandre Belloni,
	Vivien Didelot, Joergen Andreasen, Allan W. Nielsen,
	Horatiu Vultur, Claudiu Manoil, netdev, Vladimir Oltean



On 11/10/2019 9:33 AM, Vladimir Oltean wrote:
> On Sun, 10 Nov 2019 at 19:12, Andrew Lunn <andrew@lunn.ch> wrote:
>>
>> On Sun, Nov 10, 2019 at 07:00:33PM +0200, Vladimir Oltean wrote:
>>> On Sun, 10 Nov 2019 at 18:50, Andrew Lunn <andrew@lunn.ch> wrote:
>>>>
>>>> On Sat, Nov 09, 2019 at 03:03:01PM +0200, Vladimir Oltean wrote:
>>>>> From: Vladimir Oltean <vladimir.oltean@nxp.com>
>>>>>
>>>>> VSC7514 is a 10-port switch with 2 extra "CPU ports" (targets in the
>>>>> queuing subsystem for terminating traffic locally).
>>>>
>>>> So maybe that answers my last question.
>>>>
>>>>> There are 2 issues with hardcoding the CPU port as #10:
>>>>> - It is not clear which snippets of the code are configuring something
>>>>>   for one of the CPU ports, and which snippets are just doing something
>>>>>   related to the number of physical ports.
>>>>> - Actually any physical port can act as a CPU port connected to an
>>>>>   external CPU (in addition to the local CPU). This is called NPI mode
>>>>>   (Node Processor Interface) and is the way that the 6-port VSC9959
>>>>>   (Felix) switch is integrated inside NXP LS1028A (the "local management
>>>>>   CPU" functionality is not used there).
>>>>
>>>> So i'm having trouble reading this and spotting the difference between
>>>> the DSA concept of a CPU port and the two extra "CPU ports". Maybe
>>>> using the concept of virtual ports would help?
>>>>
>>>> Are the physical ports number 0-9, and so port #10 is the first extra
>>>> "CPU port", aka a virtual port? And so that would not work for DSA,
>>>> where you need a physical port.
>>>>
>>>>       Andrew
>>>
>>> Right. See my other answer which links to Ocelot documentation.
>>
>> Yes, i'm getting the picture now.
>>
>> The basic problem is that in the Linux kernel CPU port has a specific
>> meaning, and it is clashing with the meaning used in the datasheet. So
>> maybe in the driver, we need to refer to these two ports as 'local
>> ports'?
>>
> 
> Hmm, I don't know. Both types of CPU ports lead to management CPUs,
> but to different types of them. I understand the clash with the DSA
> meaning, but even if I rename it I would have to provide an
> explanation relative to the datasheet definitions (and I already
> explain that the NPI mode is the DSA type of CPU port). I'm not sure
> there is a net gain.

Maybe we need to agree on renaming DSA's CPU port to "mgmt_port" or
something that indicates that there is in-band signaling to help support
the function of managing the switch, incidentally Broadcom switches call
their ports In-Band Management Port (IMP) which is clearer IMHO.
-- 
Florian

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (15 preceding siblings ...)
  2019-11-10 17:16 ` [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Andrew Lunn
@ 2019-11-11 12:10 ` Horatiu Vultur
  2019-11-11 12:17   ` Vladimir Oltean
  2019-11-11 20:59 ` David Miller
  17 siblings, 1 reply; 33+ messages in thread
From: Horatiu Vultur @ 2019-11-11 12:10 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: jakub.kicinski, davem, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, claudiu.manoil,
	netdev

The 11/09/2019 15:02, Vladimir Oltean wrote:
> External E-Mail
> 
> 
> After the nice "change-my-mind" discussion about Ocelot, Felix and
> LS1028A (which can be read here: https://lkml.org/lkml/2019/6/21/630),
> we have decided to take the route of reworking the Ocelot implementation
> in a way that is DSA-compatible.
> 
> This is a large series, but hopefully is easy enough to digest, since it
> contains mostly code refactoring. What needs to be changed:
> - The struct net_device, phy_device needs to be isolated from Ocelot
>   private structures (struct ocelot, struct ocelot_port). These will
>   live as 1-to-1 equivalents to struct dsa_switch and struct dsa_port.
> - The function prototypes need to be compatible with DSA (of course,
>   struct dsa_switch will become struct ocelot).
> - The CPU port needs to be assigned via a higher-level API, not
>   hardcoded in the driver.
> 
> What is going to be interesting is that the new DSA front-end of Ocelot
> will need to have features in lockstep with the DSA core itself. At the
> moment, some more advanced tc offloading features of Ocelot (tc-flower,
> etc) are not available in the DSA front-end due to lack of API in the
> DSA core. It also means that Ocelot practically re-implements large
> parts of DSA (although it is not a DSA switch per se) - see the FDB API
> for example.
> 
> The code has been only compile-tested on Ocelot, since I don't have
> access to any VSC7514 hardware. It was proven to work on NXP LS1028A,
> which instantiates a DSA derivative of Ocelot. So I would like to ask
> Alex Belloni if you could confirm this series causes no regression on
> the Ocelot MIPS SoC.
> 
> The goal is to get this rework upstream as quickly as possible,
> precisely because it is a large volume of code that risks gaining merge
> conflicts if we keep it for too long.
> 
> This is but the first chunk of the LS1028A Felix DSA driver upstreaming.
> For those who are interested, the concept can be seen on my private
> Github repo, the user of this reworked Ocelot driver living under
> drivers/net/dsa/vitesse/:
> https://github.com/vladimiroltean/ls1028ardb-linux

I have done some tests on Ocelot hardware and it seems to work fine.

Acked-by: Horatiu Vultur <horatiu.vultur@microchip.com>

> 
> Claudiu Manoil (1):
>   net: mscc: ocelot: initialize list of multicast addresses in common
>     code
> 
> Vladimir Oltean (14):
>   net: mscc: ocelot: break apart ocelot_vlan_port_apply
>   net: mscc: ocelot: break apart vlan operations into
>     ocelot_vlan_{add,del}
>   net: mscc: ocelot: break out fdb operations into abstract
>     implementations
>   net: mscc: ocelot: change prototypes of hwtstamping ioctls
>   net: mscc: ocelot: change prototypes of switchdev port attribute
>     handlers
>   net: mscc: ocelot: refactor struct ocelot_port out of function
>     prototypes
>   net: mscc: ocelot: separate net_device related items out of
>     ocelot_port
>   net: mscc: ocelot: refactor ethtool callbacks
>   net: mscc: ocelot: limit vlan ingress filtering to actual number of
>     ports
>   net: mscc: ocelot: move port initialization into separate function
>   net: mscc: ocelot: separate the common implementation of ndo_open and
>     ndo_stop
>   net: mscc: ocelot: refactor adjust_link into a netdev-independent
>     function
>   net: mscc: ocelot: split assignment of the cpu port into a separate
>     function
>   net: mscc: ocelot: don't hardcode the number of the CPU port
> 
>  drivers/net/ethernet/mscc/ocelot.c        | 948 +++++++++++++---------
>  drivers/net/ethernet/mscc/ocelot.h        |  33 +-
>  drivers/net/ethernet/mscc/ocelot_ace.h    |   4 +-
>  drivers/net/ethernet/mscc/ocelot_board.c  |  24 +-
>  drivers/net/ethernet/mscc/ocelot_flower.c |  32 +-
>  drivers/net/ethernet/mscc/ocelot_police.c |  36 +-
>  drivers/net/ethernet/mscc/ocelot_police.h |   4 +-
>  drivers/net/ethernet/mscc/ocelot_tc.c     |  56 +-
>  8 files changed, 680 insertions(+), 457 deletions(-)
> 
> -- 
> 2.17.1
> 
> 

-- 
/Horatiu

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot
  2019-11-11 12:10 ` Horatiu Vultur
@ 2019-11-11 12:17   ` Vladimir Oltean
  0 siblings, 0 replies; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-11 12:17 UTC (permalink / raw)
  To: Horatiu Vultur
  Cc: Jakub Kicinski, David S. Miller, Alexandre Belloni, Andrew Lunn,
	Florian Fainelli, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Claudiu Manoil, netdev

On Mon, 11 Nov 2019 at 14:10, Horatiu Vultur
<horatiu.vultur@microchip.com> wrote:
>
> The 11/09/2019 15:02, Vladimir Oltean wrote:
> > External E-Mail
> >
> >
> > After the nice "change-my-mind" discussion about Ocelot, Felix and
> > LS1028A (which can be read here: https://lkml.org/lkml/2019/6/21/630),
> > we have decided to take the route of reworking the Ocelot implementation
> > in a way that is DSA-compatible.
> >
> > This is a large series, but hopefully is easy enough to digest, since it
> > contains mostly code refactoring. What needs to be changed:
> > - The struct net_device, phy_device needs to be isolated from Ocelot
> >   private structures (struct ocelot, struct ocelot_port). These will
> >   live as 1-to-1 equivalents to struct dsa_switch and struct dsa_port.
> > - The function prototypes need to be compatible with DSA (of course,
> >   struct dsa_switch will become struct ocelot).
> > - The CPU port needs to be assigned via a higher-level API, not
> >   hardcoded in the driver.
> >
> > What is going to be interesting is that the new DSA front-end of Ocelot
> > will need to have features in lockstep with the DSA core itself. At the
> > moment, some more advanced tc offloading features of Ocelot (tc-flower,
> > etc) are not available in the DSA front-end due to lack of API in the
> > DSA core. It also means that Ocelot practically re-implements large
> > parts of DSA (although it is not a DSA switch per se) - see the FDB API
> > for example.
> >
> > The code has been only compile-tested on Ocelot, since I don't have
> > access to any VSC7514 hardware. It was proven to work on NXP LS1028A,
> > which instantiates a DSA derivative of Ocelot. So I would like to ask
> > Alex Belloni if you could confirm this series causes no regression on
> > the Ocelot MIPS SoC.
> >
> > The goal is to get this rework upstream as quickly as possible,
> > precisely because it is a large volume of code that risks gaining merge
> > conflicts if we keep it for too long.
> >
> > This is but the first chunk of the LS1028A Felix DSA driver upstreaming.
> > For those who are interested, the concept can be seen on my private
> > Github repo, the user of this reworked Ocelot driver living under
> > drivers/net/dsa/vitesse/:
> > https://github.com/vladimiroltean/ls1028ardb-linux
>
> I have done some tests on Ocelot hardware and it seems to work fine.
>
> Acked-by: Horatiu Vultur <horatiu.vultur@microchip.com>
>

Thanks, Horatiu!

> --
> /Horatiu

-Vladimir

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot
  2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
                   ` (16 preceding siblings ...)
  2019-11-11 12:10 ` Horatiu Vultur
@ 2019-11-11 20:59 ` David Miller
  17 siblings, 0 replies; 33+ messages in thread
From: David Miller @ 2019-11-11 20:59 UTC (permalink / raw)
  To: olteanv
  Cc: jakub.kicinski, alexandre.belloni, andrew, f.fainelli,
	vivien.didelot, joergen.andreasen, allan.nielsen, horatiu.vultur,
	claudiu.manoil, netdev

From: Vladimir Oltean <olteanv@gmail.com>
Date: Sat,  9 Nov 2019 15:02:46 +0200

> After the nice "change-my-mind" discussion about Ocelot, Felix and
> LS1028A (which can be read here: https://lkml.org/lkml/2019/6/21/630),
> we have decided to take the route of reworking the Ocelot implementation
> in a way that is DSA-compatible.
 ...

I'm going to apply this series as-is.

But please address Andrew's feedback about port naming and such.

Thank you.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port
  2019-11-10 20:54           ` Florian Fainelli
@ 2019-11-12  0:53             ` Vladimir Oltean
  2019-11-12  2:53               ` Andrew Lunn
  0 siblings, 1 reply; 33+ messages in thread
From: Vladimir Oltean @ 2019-11-12  0:53 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Andrew Lunn, Jakub Kicinski, David S. Miller, Alexandre Belloni,
	Vivien Didelot, Joergen Andreasen, Allan W. Nielsen,
	Horatiu Vultur, Claudiu Manoil, netdev, Vladimir Oltean

On Sun, 10 Nov 2019 at 22:54, Florian Fainelli <f.fainelli@gmail.com> wrote:
>
>
>
> On 11/10/2019 9:33 AM, Vladimir Oltean wrote:
> > On Sun, 10 Nov 2019 at 19:12, Andrew Lunn <andrew@lunn.ch> wrote:
> >>
> >> On Sun, Nov 10, 2019 at 07:00:33PM +0200, Vladimir Oltean wrote:
> >>> On Sun, 10 Nov 2019 at 18:50, Andrew Lunn <andrew@lunn.ch> wrote:
> >>>>
> >>>> On Sat, Nov 09, 2019 at 03:03:01PM +0200, Vladimir Oltean wrote:
> >>>>> From: Vladimir Oltean <vladimir.oltean@nxp.com>
> >>>>>
> >>>>> VSC7514 is a 10-port switch with 2 extra "CPU ports" (targets in the
> >>>>> queuing subsystem for terminating traffic locally).
> >>>>
> >>>> So maybe that answers my last question.
> >>>>
> >>>>> There are 2 issues with hardcoding the CPU port as #10:
> >>>>> - It is not clear which snippets of the code are configuring something
> >>>>>   for one of the CPU ports, and which snippets are just doing something
> >>>>>   related to the number of physical ports.
> >>>>> - Actually any physical port can act as a CPU port connected to an
> >>>>>   external CPU (in addition to the local CPU). This is called NPI mode
> >>>>>   (Node Processor Interface) and is the way that the 6-port VSC9959
> >>>>>   (Felix) switch is integrated inside NXP LS1028A (the "local management
> >>>>>   CPU" functionality is not used there).
> >>>>
> >>>> So i'm having trouble reading this and spotting the difference between
> >>>> the DSA concept of a CPU port and the two extra "CPU ports". Maybe
> >>>> using the concept of virtual ports would help?
> >>>>
> >>>> Are the physical ports number 0-9, and so port #10 is the first extra
> >>>> "CPU port", aka a virtual port? And so that would not work for DSA,
> >>>> where you need a physical port.
> >>>>
> >>>>       Andrew
> >>>
> >>> Right. See my other answer which links to Ocelot documentation.
> >>
> >> Yes, i'm getting the picture now.
> >>
> >> The basic problem is that in the Linux kernel CPU port has a specific
> >> meaning, and it is clashing with the meaning used in the datasheet. So
> >> maybe in the driver, we need to refer to these two ports as 'local
> >> ports'?
> >>
> >
> > Hmm, I don't know. Both types of CPU ports lead to management CPUs,
> > but to different types of them. I understand the clash with the DSA
> > meaning, but even if I rename it I would have to provide an
> > explanation relative to the datasheet definitions (and I already
> > explain that the NPI mode is the DSA type of CPU port). I'm not sure
> > there is a net gain.
>
> Maybe we need to agree on renaming DSA's CPU port to "mgmt_port" or
> something that indicates that there is in-band signaling to help support
> the function of managing the switch, incidentally Broadcom switches call
> their ports In-Band Management Port (IMP) which is clearer IMHO.
> --
> Florian

In the hardware conceptions that I float in, a "management port" has
the connotation of "exclusively management" (link-local multicast plus
user-defined trapping rules). While I completely understand that this
model is something that doesn't help the Linux abstraction at all, it
is something that apparently enough people in NXP have thought of as
being a good idea since they actually put it in practice in designs.
Just something to keep in mind.

Andrew, is the Z80 embedded CPU able to run Linux? If not, then from
what perspective are you saying you're going to call it "the z80 port"
instead of "CPU port", and why would you add support for it?
The current ocelot driver runs on the little CPU and doesn't support
external management, and the downstream felix driver runs on the big
CPU and doesn't support "local" I/O (DMA, PIO), so there are both at
the extremes. I don't know of any kernel driver that sets up the
switch for a remote DSA master, but I'd be curious to see what is the
terminology there.

But otherwise, I don't know whether there's anything really actionable
here. What the ocelot driver calls a CPU port is always a "port
towards the CPU running Linux and managing the switch", so the CPU
port is always local by definition, no matter whether the CPU is
connected over DMA or over Ethernet (aka NPI mode or not).

Thanks,
-Vladimir

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port
  2019-11-12  0:53             ` Vladimir Oltean
@ 2019-11-12  2:53               ` Andrew Lunn
  0 siblings, 0 replies; 33+ messages in thread
From: Andrew Lunn @ 2019-11-12  2:53 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Florian Fainelli, Jakub Kicinski, David S. Miller,
	Alexandre Belloni, Vivien Didelot, Joergen Andreasen,
	Allan W. Nielsen, Horatiu Vultur, Claudiu Manoil, netdev,
	Vladimir Oltean

> Andrew, is the Z80 embedded CPU able to run Linux?

No. 

If not, then from
> what perspective are you saying you're going to call it "the z80 port"
> instead of "CPU port", and why would you add support for it?

I've wanted to do a Hello World, but never got around to it.  I have
seen uses cases where it is possible to hot {un}plug the host. The
switch keeps on running. While the host is missing, STP packets are no
longer sent, but the switch keeps on switching. At some point the
other switches in the net are going to do something and STP will break
down, either partitioning the net, or causing loops. You could have
the Z80 monitor for the host going away, and either taking over the
STP, or cleanly shutting the switch down.

But Marvells real use case for the Z80 is for it to manage the switch,
no DSA at all. Just a dumb unmanaged, so very simple managed switch.

> But otherwise, I don't know whether there's anything really actionable
> here. What the ocelot driver calls a CPU port is always a "port
> towards the CPU running Linux and managing the switch", so the CPU
> port is always local by definition, no matter whether the CPU is
> connected over DMA or over Ethernet (aka NPI mode or not).

Well, it got me confused, but i think i have it now. It is more about
new people getting up to speed on the driver, especially if they have
experience with other DSA drivers, and suddenly the CPU port can mean
something different.

	  Andrew

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2019-11-12  2:53 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-09 13:02 [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 01/15] net: mscc: ocelot: break apart ocelot_vlan_port_apply Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 02/15] net: mscc: ocelot: break apart vlan operations into ocelot_vlan_{add,del} Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 03/15] net: mscc: ocelot: break out fdb operations into abstract implementations Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 04/15] net: mscc: ocelot: change prototypes of hwtstamping ioctls Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 05/15] net: mscc: ocelot: change prototypes of switchdev port attribute handlers Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 06/15] net: mscc: ocelot: refactor struct ocelot_port out of function prototypes Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 07/15] net: mscc: ocelot: separate net_device related items out of ocelot_port Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 08/15] net: mscc: ocelot: refactor ethtool callbacks Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 09/15] net: mscc: ocelot: limit vlan ingress filtering to actual number of ports Vladimir Oltean
2019-11-10 16:25   ` Andrew Lunn
2019-11-10 16:29     ` Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 10/15] net: mscc: ocelot: move port initialization into separate function Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 11/15] net: mscc: ocelot: separate the common implementation of ndo_open and ndo_stop Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 12/15] net: mscc: ocelot: initialize list of multicast addresses in common code Vladimir Oltean
2019-11-09 13:02 ` [PATCH net-next 13/15] net: mscc: ocelot: refactor adjust_link into a netdev-independent function Vladimir Oltean
2019-11-09 13:03 ` [PATCH net-next 14/15] net: mscc: ocelot: split assignment of the cpu port into a separate function Vladimir Oltean
2019-11-10 16:32   ` Andrew Lunn
2019-11-10 16:40     ` Vladimir Oltean
2019-11-10 16:50       ` Vladimir Oltean
2019-11-09 13:03 ` [PATCH net-next 15/15] net: mscc: ocelot: don't hardcode the number of the CPU port Vladimir Oltean
2019-11-10 16:50   ` Andrew Lunn
2019-11-10 17:00     ` Vladimir Oltean
2019-11-10 17:12       ` Andrew Lunn
2019-11-10 17:33         ` Vladimir Oltean
2019-11-10 20:54           ` Florian Fainelli
2019-11-12  0:53             ` Vladimir Oltean
2019-11-12  2:53               ` Andrew Lunn
2019-11-10 17:16 ` [PATCH net-next 00/15] Accomodate DSA front-end into Ocelot Andrew Lunn
2019-11-10 17:22   ` Vladimir Oltean
2019-11-11 12:10 ` Horatiu Vultur
2019-11-11 12:17   ` Vladimir Oltean
2019-11-11 20:59 ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).