All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/16] net: dsa: HW bridging, EEE support
@ 2015-03-27  1:36 Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 01/16] net: dsa: mv88e6xxx: Factor out common initialization code Guenter Roeck
                   ` (18 more replies)
  0 siblings, 19 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Patch 1 to 7 of this series prepare the drivers using the mv88e6xxx code
for HW bridging support, without adding the code itself. For the most part
this factors out common port initialization code. There is no functional
change except for patch 3, which disables the message port bit for the
CPU port to prevent packet duplication if HW bridging is configured.

Patch 8 adds the infrastructure for hardware bridging support to the
mv88e6xxx code.

Patch 9 wires the MV88E6352 driver to support hardware bridging.

Patches 10 to 12 add support for ndo_fdb functions to the dsa subsystem,
and wire up the MV88E6352 driver to support those functions.

Patches 13 to 16 add EEE support and HW bridging support to the mv88e6171
driver. This set of patches is from Andrew, applied on top of the first
set of patches.

The series applies to net-next as of 3/24/2015.

Thanks a lot to Andrew Lunn for testing and valuable feedback.

---
Changes since v1:
- Fixed compile error in patch 02/16. That was previously addressed in
  a later patch but broke bisectability.
- Dropped the RFT patches introducing HW bridging support for MV88E6131
  and compatibles. There was a bug in stat code, and those patches should
  be handled separately anyway since they are untested.
- Removed duplicate defines from mv88e6xxx.h.

Changes since RFT:
- Various bug fixes
  - Fixed packet duplication seen when HW bridging is enabled
- Cleanup; use more defines and restructure patches
- Added ndo_fdb functions
- New patches adding support for HW bridging and EEE support
  to the mv88e6171 driver.

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

* [PATCH v2 01/16] net: dsa: mv88e6xxx: Factor out common initialization code
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 02/16] net: dsa: mv88e6xxx: Provide function for common port initialization Guenter Roeck
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Code used and needed in mv886xxx.c should be initialized there as well,
so factor it out from the individual initialization files.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6123_61_65.c |  7 +++----
 drivers/net/dsa/mv88e6171.c       |  8 +++-----
 drivers/net/dsa/mv88e6352.c       |  7 ++++---
 drivers/net/dsa/mv88e6xxx.c       | 11 +++++++++++
 drivers/net/dsa/mv88e6xxx.h       |  1 +
 5 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
index e9c736e1cef3..6ebe57044afc 100644
--- a/drivers/net/dsa/mv88e6123_61_65.c
+++ b/drivers/net/dsa/mv88e6123_61_65.c
@@ -293,13 +293,12 @@ static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p)
 
 static int mv88e6123_61_65_setup(struct dsa_switch *ds)
 {
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int i;
 	int ret;
 
-	mutex_init(&ps->smi_mutex);
-	mutex_init(&ps->stats_mutex);
-	mutex_init(&ps->phy_mutex);
+	ret = mv88e6xxx_setup_common(ds);
+	if (ret < 0)
+		return ret;
 
 	ret = mv88e6123_61_65_switch_reset(ds);
 	if (ret < 0)
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 9808c860a797..2f6662c246fa 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -292,12 +292,12 @@ static int mv88e6171_setup_port(struct dsa_switch *ds, int p)
 
 static int mv88e6171_setup(struct dsa_switch *ds)
 {
-	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
 	int i;
 	int ret;
 
-	mutex_init(&ps->smi_mutex);
-	mutex_init(&ps->stats_mutex);
+	ret = mv88e6xxx_setup_common(ds);
+	if (ret < 0)
+		return ret;
 
 	ret = mv88e6171_switch_reset(ds);
 	if (ret < 0)
@@ -318,8 +318,6 @@ static int mv88e6171_setup(struct dsa_switch *ds)
 			return ret;
 	}
 
-	mutex_init(&ps->phy_mutex);
-
 	return 0;
 }
 
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 7bc5998384c6..75cf9e1c5a44 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -385,9 +385,10 @@ static int mv88e6352_setup(struct dsa_switch *ds)
 	int ret;
 	int i;
 
-	mutex_init(&ps->smi_mutex);
-	mutex_init(&ps->stats_mutex);
-	mutex_init(&ps->phy_mutex);
+	ret = mv88e6xxx_setup_common(ds);
+	if (ret < 0)
+		return ret;
+
 	mutex_init(&ps->eeprom_mutex);
 
 	ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0;
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index c18ffc98aacc..6496beb74510 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -700,6 +700,17 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 	return 0;
 }
 
+int mv88e6xxx_setup_common(struct dsa_switch *ds)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+	mutex_init(&ps->smi_mutex);
+	mutex_init(&ps->stats_mutex);
+	mutex_init(&ps->phy_mutex);
+
+	return 0;
+}
+
 static int __init mv88e6xxx_init(void)
 {
 #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 5fd42ced9011..a02d95a9b313 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -57,6 +57,7 @@ struct mv88e6xxx_hw_stat {
 	int reg;
 };
 
+int mv88e6xxx_setup_common(struct dsa_switch *ds);
 int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg);
 int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg);
 int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
-- 
2.1.0


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

* [PATCH v2 02/16] net: dsa: mv88e6xxx: Provide function for common port initialization
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 01/16] net: dsa: mv88e6xxx: Factor out common initialization code Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 03/16] net: dsa: mv88e6xxx: Disable Message Port bit for CPU port Guenter Roeck
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Provide mv88e6xxx_setup_port_common() for common port initialization.
Currently only write Port 1 Control and VLAN configuration since
this will be needed for hardware bridging. More can be added later
if desired/needed.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6xxx.c | 39 +++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/mv88e6xxx.h |  1 +
 2 files changed, 40 insertions(+)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 6496beb74510..2052e51edd5d 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -700,6 +700,45 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 	return 0;
 }
 
+int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret, reg;
+
+	mutex_lock(&ps->smi_mutex);
+
+	/* Port Control 1: disable trunking.  Also, if this is the
+	 * CPU port, enable learn messages to be sent to this port.
+	 */
+	ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x05,
+				   dsa_is_cpu_port(ds, port) ? 0x8000 : 0x0000);
+	if (ret)
+		goto abort;
+
+	/* Port based VLAN map: give each port its own address
+	 * database, allow the CPU port to talk to each of the 'real'
+	 * ports, and allow each of the 'real' ports to only talk to
+	 * the upstream port.
+	 */
+	reg = (port & 0xf) << 12;
+	if (dsa_is_cpu_port(ds, port))
+		reg |= ds->phys_port_mask;
+	else
+		reg |= 1 << dsa_upstream_port(ds);
+
+	ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x06, reg);
+	if (ret)
+		goto abort;
+
+	/* Default VLAN ID and priority: don't set a default VLAN
+	 * ID, and set the default packet priority to zero.
+	 */
+	ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x07, 0x0000);
+abort:
+	mutex_unlock(&ps->smi_mutex);
+	return ret;
+}
+
 int mv88e6xxx_setup_common(struct dsa_switch *ds)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index a02d95a9b313..a4df4968594e 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -57,6 +57,7 @@ struct mv88e6xxx_hw_stat {
 	int reg;
 };
 
+int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port);
 int mv88e6xxx_setup_common(struct dsa_switch *ds);
 int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg);
 int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg);
-- 
2.1.0


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

* [PATCH v2 03/16] net: dsa: mv88e6xxx: Disable Message Port bit for CPU port
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 01/16] net: dsa: mv88e6xxx: Factor out common initialization code Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 02/16] net: dsa: mv88e6xxx: Provide function for common port initialization Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 04/16] net: dsa: mv88e6xxx: Split mv88e6xxx_reg_read and mv88e6xxx_reg_write Guenter Roeck
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Datasheet says that the Message Port bit should not be set for the CPU port.
Having it set causes DSA tagged packets to be sent to the CPU port roughly
every 30 seconds. Those packets are the same as real packets forwarded between
switch ports if the switch is configured for switching between multiple ports.
The packets are then bridged by the software bridge, resulting in duplicated
packets on the network.

Reported-by: Andrew Lunn <andrew@lunn.ch>
Cc: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6xxx.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 2052e51edd5d..5da50b00fdf6 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -707,11 +707,10 @@ int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
 
 	mutex_lock(&ps->smi_mutex);
 
-	/* Port Control 1: disable trunking.  Also, if this is the
-	 * CPU port, enable learn messages to be sent to this port.
+	/* Port Control 1: disable trunking, disable sending
+	 * learning messages to this port.
 	 */
-	ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x05,
-				   dsa_is_cpu_port(ds, port) ? 0x8000 : 0x0000);
+	ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x05, 0x0000);
 	if (ret)
 		goto abort;
 
-- 
2.1.0


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

* [PATCH v2 04/16] net: dsa: mv88e6xxx: Split mv88e6xxx_reg_read and mv88e6xxx_reg_write
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (2 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 03/16] net: dsa: mv88e6xxx: Disable Message Port bit for CPU port Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 05/16] net: dsa: mv88e6352: Use common port initialization code Guenter Roeck
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Split mv88e6xxx_reg_read and mv88e6xxx_reg_write into two functions each,
one to acquire smi_mutex and one to get struct mii_bus *bus from
struct dsa_switch *ds and to call the actual read/write function.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6xxx.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 5da50b00fdf6..d8f13327a438 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -72,19 +72,16 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
 	return ret & 0xffff;
 }
 
-int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
+/* Must be called with SMI mutex held */
+static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
 {
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
 	int ret;
 
 	if (bus == NULL)
 		return -EINVAL;
 
-	mutex_lock(&ps->smi_mutex);
 	ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg);
-	mutex_unlock(&ps->smi_mutex);
-
 	if (ret < 0)
 		return ret;
 
@@ -94,6 +91,18 @@ int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
 	return ret;
 }
 
+int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret;
+
+	mutex_lock(&ps->smi_mutex);
+	ret = _mv88e6xxx_reg_read(ds, addr, reg);
+	mutex_unlock(&ps->smi_mutex);
+
+	return ret;
+}
+
 int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
 			  int reg, u16 val)
 {
@@ -125,11 +134,11 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
 	return 0;
 }
 
-int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
+/* Must be called with SMI mutex held */
+static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg,
+				u16 val)
 {
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
-	int ret;
 
 	if (bus == NULL)
 		return -EINVAL;
@@ -137,8 +146,16 @@ int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
 	dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
 		addr, reg, val);
 
+	return __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val);
+}
+
+int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret;
+
 	mutex_lock(&ps->smi_mutex);
-	ret = __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val);
+	ret = _mv88e6xxx_reg_write(ds, addr, reg, val);
 	mutex_unlock(&ps->smi_mutex);
 
 	return ret;
-- 
2.1.0


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

* [PATCH v2 05/16] net: dsa: mv88e6352: Use common port initialization code
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (3 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 04/16] net: dsa: mv88e6xxx: Split mv88e6xxx_reg_read and mv88e6xxx_reg_write Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 06/16] net: dsa: mv88e6123_61_65: Use common port configuration Guenter Roeck
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

This prepares the driver for hardware bridging.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6352.c | 24 +-----------------------
 1 file changed, 1 insertion(+), 23 deletions(-)

diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 75cf9e1c5a44..f7e7c0f1dff4 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -215,28 +215,6 @@ static int mv88e6352_setup_port(struct dsa_switch *ds, int p)
 		val |= 0x000c;
 	REG_WRITE(addr, 0x04, val);
 
-	/* Port Control 1: disable trunking.  Also, if this is the
-	 * CPU port, enable learn messages to be sent to this port.
-	 */
-	REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
-
-	/* Port based VLAN map: give each port its own address
-	 * database, allow the CPU port to talk to each of the 'real'
-	 * ports, and allow each of the 'real' ports to only talk to
-	 * the upstream port.
-	 */
-	val = (p & 0xf) << 12;
-	if (dsa_is_cpu_port(ds, p))
-		val |= ds->phys_port_mask;
-	else
-		val |= 1 << dsa_upstream_port(ds);
-	REG_WRITE(addr, 0x06, val);
-
-	/* Default VLAN ID and priority: don't set a default VLAN
-	 * ID, and set the default packet priority to zero.
-	 */
-	REG_WRITE(addr, 0x07, 0x0000);
-
 	/* Port Control 2: don't force a good FCS, set the maximum
 	 * frame size to 10240 bytes, don't let the switch add or
 	 * strip 802.1q tags, don't discard tagged or untagged frames
@@ -281,7 +259,7 @@ static int mv88e6352_setup_port(struct dsa_switch *ds, int p)
 	 */
 	REG_WRITE(addr, 0x19, 0x7654);
 
-	return 0;
+	return mv88e6xxx_setup_port_common(ds, p);
 }
 
 #ifdef CONFIG_NET_DSA_HWMON
-- 
2.1.0


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

* [PATCH v2 06/16] net: dsa: mv88e6123_61_65: Use common port configuration
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (4 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 05/16] net: dsa: mv88e6352: Use common port initialization code Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 07/16] net: dsa: mv88e6171: " Guenter Roeck
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

This will simplify adding offloaded bridge support later on.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6123_61_65.c | 24 +-----------------------
 1 file changed, 1 insertion(+), 23 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
index 6ebe57044afc..2d7e1ffe9fdc 100644
--- a/drivers/net/dsa/mv88e6123_61_65.c
+++ b/drivers/net/dsa/mv88e6123_61_65.c
@@ -222,28 +222,6 @@ static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p)
 		val |= 0x000c;
 	REG_WRITE(addr, 0x04, val);
 
-	/* Port Control 1: disable trunking.  Also, if this is the
-	 * CPU port, enable learn messages to be sent to this port.
-	 */
-	REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
-
-	/* Port based VLAN map: give each port its own address
-	 * database, allow the CPU port to talk to each of the 'real'
-	 * ports, and allow each of the 'real' ports to only talk to
-	 * the upstream port.
-	 */
-	val = (p & 0xf) << 12;
-	if (dsa_is_cpu_port(ds, p))
-		val |= ds->phys_port_mask;
-	else
-		val |= 1 << dsa_upstream_port(ds);
-	REG_WRITE(addr, 0x06, val);
-
-	/* Default VLAN ID and priority: don't set a default VLAN
-	 * ID, and set the default packet priority to zero.
-	 */
-	REG_WRITE(addr, 0x07, 0x0000);
-
 	/* Port Control 2: don't force a good FCS, set the maximum
 	 * frame size to 10240 bytes, don't let the switch add or
 	 * strip 802.1q tags, don't discard tagged or untagged frames
@@ -288,7 +266,7 @@ static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p)
 	 */
 	REG_WRITE(addr, 0x19, 0x7654);
 
-	return 0;
+	return mv88e6xxx_setup_port_common(ds, p);
 }
 
 static int mv88e6123_61_65_setup(struct dsa_switch *ds)
-- 
2.1.0


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

* [PATCH v2 07/16] net: dsa: mv88e6171: Use common port configuration
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (5 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 06/16] net: dsa: mv88e6123_61_65: Use common port configuration Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 08/16] net: dsa: mv88e6xxx: Add Hardware bridging support Guenter Roeck
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6171.c | 24 +-----------------------
 1 file changed, 1 insertion(+), 23 deletions(-)

diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 2f6662c246fa..6ce6a3ea1b8d 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -221,28 +221,6 @@ static int mv88e6171_setup_port(struct dsa_switch *ds, int p)
 		val |= 0x000c;
 	REG_WRITE(addr, 0x04, val);
 
-	/* Port Control 1: disable trunking.  Also, if this is the
-	 * CPU port, enable learn messages to be sent to this port.
-	 */
-	REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
-
-	/* Port based VLAN map: give each port its own address
-	 * database, allow the CPU port to talk to each of the 'real'
-	 * ports, and allow each of the 'real' ports to only talk to
-	 * the upstream port.
-	 */
-	val = (p & 0xf) << 12;
-	if (dsa_is_cpu_port(ds, p))
-		val |= ds->phys_port_mask;
-	else
-		val |= 1 << dsa_upstream_port(ds);
-	REG_WRITE(addr, 0x06, val);
-
-	/* Default VLAN ID and priority: don't set a default VLAN
-	 * ID, and set the default packet priority to zero.
-	 */
-	REG_WRITE(addr, 0x07, 0x0000);
-
 	/* Port Control 2: don't force a good FCS, set the maximum
 	 * frame size to 10240 bytes, don't let the switch add or
 	 * strip 802.1q tags, don't discard tagged or untagged frames
@@ -287,7 +265,7 @@ static int mv88e6171_setup_port(struct dsa_switch *ds, int p)
 	 */
 	REG_WRITE(addr, 0x19, 0x7654);
 
-	return 0;
+	return mv88e6xxx_setup_port_common(ds, p);
 }
 
 static int mv88e6171_setup(struct dsa_switch *ds)
-- 
2.1.0


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

* [PATCH v2 08/16] net: dsa: mv88e6xxx: Add Hardware bridging support
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (6 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 07/16] net: dsa: mv88e6171: " Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 09/16] net: dsa: mv88e6352: Add support for hardware bridging Guenter Roeck
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Bridge support is similar for all chips supported by the mv88e6xxx code,
so add the code there.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6xxx.c | 271 ++++++++++++++++++++++++++++++++++++++++++--
 drivers/net/dsa/mv88e6xxx.h |  28 +++++
 2 files changed, 292 insertions(+), 7 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index d8f13327a438..17aa74f64233 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/if_bridge.h>
 #include <linux/jiffies.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -644,6 +645,31 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
 	return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x8000);
 }
 
+/* Must be called with SMI lock held */
+static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
+{
+	unsigned long timeout = jiffies + HZ / 10;
+
+	while (time_before(jiffies, timeout)) {
+		int ret;
+
+		ret = _mv88e6xxx_reg_read(ds, reg, offset);
+		if (ret < 0)
+			return ret;
+		if (!(ret & mask))
+			return 0;
+
+		usleep_range(1000, 2000);
+	}
+	return -ETIMEDOUT;
+}
+
+/* Must be called with SMI lock held */
+static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
+{
+	return _mv88e6xxx_wait(ds, REG_GLOBAL, 0x0b, ATU_BUSY);
+}
+
 int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum)
 {
 	int ret;
@@ -717,10 +743,236 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 	return 0;
 }
 
+static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd)
+{
+	int ret;
+
+	ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x01, fid);
+	if (ret < 0)
+		return ret;
+
+	ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0b, cmd);
+	if (ret < 0)
+		return ret;
+
+	return _mv88e6xxx_atu_wait(ds);
+}
+
+static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid)
+{
+	int ret;
+
+	ret = _mv88e6xxx_atu_wait(ds);
+	if (ret < 0)
+		return ret;
+
+	return _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_FLUSH_NONSTATIC_FID);
+}
+
+static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int reg, ret;
+	u8 oldstate;
+
+	mutex_lock(&ps->smi_mutex);
+
+	reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), 0x04);
+	if (reg < 0)
+		goto abort;
+
+	oldstate = reg & PSTATE_MASK;
+	if (oldstate != state) {
+		/* Flush forwarding database if we're moving a port
+		 * from Learning or Forwarding state to Disabled or
+		 * Blocking or Listening state.
+		 */
+		if (oldstate >= PSTATE_LEARNING && state <= PSTATE_BLOCKING) {
+			ret = _mv88e6xxx_flush_fid(ds, ps->fid[port]);
+			if (ret)
+				goto abort;
+		}
+		reg = (reg & ~PSTATE_MASK) | state;
+		ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x04, reg);
+	}
+
+abort:
+	mutex_unlock(&ps->smi_mutex);
+	return ret;
+}
+
+/* Must be called with smi lock held */
+static int _mv88e6xxx_update_port_config(struct dsa_switch *ds, int port)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	u8 fid = ps->fid[port];
+	u16 reg = fid << 12;
+
+	if (dsa_is_cpu_port(ds, port))
+		reg |= ds->phys_port_mask;
+	else
+		reg |= (ps->bridge_mask[fid] |
+		       (1 << dsa_upstream_port(ds))) & ~(1 << port);
+
+	return _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x06, reg);
+}
+
+/* Must be called with smi lock held */
+static int _mv88e6xxx_update_bridge_config(struct dsa_switch *ds, int fid)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int port;
+	u32 mask;
+	int ret;
+
+	mask = ds->phys_port_mask;
+	while (mask) {
+		port = __ffs(mask);
+		mask &= ~(1 << port);
+		if (ps->fid[port] != fid)
+			continue;
+
+		ret = _mv88e6xxx_update_port_config(ds, port);
+		if (ret)
+			return ret;
+	}
+
+	return _mv88e6xxx_flush_fid(ds, fid);
+}
+
+/* Bridge handling functions */
+
+int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret = 0;
+	u32 nmask;
+	int fid;
+
+	/* If the bridge group is not empty, join that group.
+	 * Otherwise create a new group.
+	 */
+	fid = ps->fid[port];
+	nmask = br_port_mask & ~(1 << port);
+	if (nmask)
+		fid = ps->fid[__ffs(nmask)];
+
+	nmask = ps->bridge_mask[fid] | (1 << port);
+	if (nmask != br_port_mask) {
+		netdev_err(ds->ports[port],
+			   "join: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
+			   fid, br_port_mask, nmask);
+		return -EINVAL;
+	}
+
+	mutex_lock(&ps->smi_mutex);
+
+	ps->bridge_mask[fid] = br_port_mask;
+
+	if (fid != ps->fid[port]) {
+		ps->fid_mask |= 1 << ps->fid[port];
+		ps->fid[port] = fid;
+		ret = _mv88e6xxx_update_bridge_config(ds, fid);
+	}
+
+	mutex_unlock(&ps->smi_mutex);
+
+	return ret;
+}
+
+int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	u8 fid, newfid;
+	int ret;
+
+	fid = ps->fid[port];
+
+	if (ps->bridge_mask[fid] != br_port_mask) {
+		netdev_err(ds->ports[port],
+			   "leave: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
+			   fid, br_port_mask, ps->bridge_mask[fid]);
+		return -EINVAL;
+	}
+
+	/* If the port was the last port of a bridge, we are done.
+	 * Otherwise assign a new fid to the port, and fix up
+	 * the bridge configuration.
+	 */
+	if (br_port_mask == (1 << port))
+		return 0;
+
+	mutex_lock(&ps->smi_mutex);
+
+	newfid = __ffs(ps->fid_mask);
+	ps->fid[port] = newfid;
+	ps->fid_mask &= (1 << newfid);
+	ps->bridge_mask[fid] &= ~(1 << port);
+	ps->bridge_mask[newfid] = 1 << port;
+
+	ret = _mv88e6xxx_update_bridge_config(ds, fid);
+	if (!ret)
+		ret = _mv88e6xxx_update_bridge_config(ds, newfid);
+
+	mutex_unlock(&ps->smi_mutex);
+
+	return ret;
+}
+
+int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int stp_state;
+
+	switch (state) {
+	case BR_STATE_DISABLED:
+		stp_state = PSTATE_DISABLED;
+		break;
+	case BR_STATE_BLOCKING:
+	case BR_STATE_LISTENING:
+		stp_state = PSTATE_BLOCKING;
+		break;
+	case BR_STATE_LEARNING:
+		stp_state = PSTATE_LEARNING;
+		break;
+	case BR_STATE_FORWARDING:
+	default:
+		stp_state = PSTATE_FORWARDING;
+		break;
+	}
+
+	netdev_dbg(ds->ports[port], "port state %d [%d]\n", state, stp_state);
+
+	/* mv88e6xxx_port_stp_update may be called with softirqs disabled,
+	 * so we can not update the port state directly but need to schedule it.
+	 */
+	ps->port_state[port] = stp_state;
+	set_bit(port, &ps->port_state_update_mask);
+	schedule_work(&ps->bridge_work);
+
+	return 0;
+}
+
+static void mv88e6xxx_bridge_work(struct work_struct *work)
+{
+	struct mv88e6xxx_priv_state *ps;
+	struct dsa_switch *ds;
+	int port;
+
+	ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work);
+	ds = ((struct dsa_switch *)ps) - 1;
+
+	while (ps->port_state_update_mask) {
+		port = __ffs(ps->port_state_update_mask);
+		clear_bit(port, &ps->port_state_update_mask);
+		mv88e6xxx_set_port_state(ds, port, ps->port_state[port]);
+	}
+}
+
 int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-	int ret, reg;
+	int ret, fid;
 
 	mutex_lock(&ps->smi_mutex);
 
@@ -736,13 +988,14 @@ int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
 	 * ports, and allow each of the 'real' ports to only talk to
 	 * the upstream port.
 	 */
-	reg = (port & 0xf) << 12;
-	if (dsa_is_cpu_port(ds, port))
-		reg |= ds->phys_port_mask;
-	else
-		reg |= 1 << dsa_upstream_port(ds);
+	fid = __ffs(ps->fid_mask);
+	ps->fid[port] = fid;
+	ps->fid_mask &= ~(1 << fid);
+
+	if (!dsa_is_cpu_port(ds, port))
+		ps->bridge_mask[fid] = 1 << port;
 
-	ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x06, reg);
+	ret = _mv88e6xxx_update_port_config(ds, port);
 	if (ret)
 		goto abort;
 
@@ -763,6 +1016,10 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
 	mutex_init(&ps->stats_mutex);
 	mutex_init(&ps->phy_mutex);
 
+	ps->fid_mask = (1 << DSA_MAX_PORTS) - 1;
+
+	INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
+
 	return 0;
 }
 
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index a4df4968594e..8e215ebc8d34 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -15,6 +15,20 @@
 #define REG_GLOBAL		0x1b
 #define REG_GLOBAL2		0x1c
 
+/* ATU commands */
+
+#define ATU_BUSY			0x8000
+
+#define ATU_CMD_FLUSH_NONSTATIC_FID	(ATU_BUSY | 0x6000)
+
+/* port states */
+
+#define PSTATE_MASK		0x03
+#define PSTATE_DISABLED		0x00
+#define PSTATE_BLOCKING		0x01
+#define PSTATE_LEARNING		0x02
+#define PSTATE_FORWARDING	0x03
+
 struct mv88e6xxx_priv_state {
 	/* When using multi-chip addressing, this mutex protects
 	 * access to the indirect access registers.  (In single-chip
@@ -49,6 +63,17 @@ struct mv88e6xxx_priv_state {
 	struct mutex eeprom_mutex;
 
 	int		id; /* switch product id */
+
+	/* hw bridging */
+
+	u32 fid_mask;
+	u8 fid[DSA_MAX_PORTS];
+	u16 bridge_mask[DSA_MAX_PORTS];
+
+	unsigned long port_state_update_mask;
+	u8 port_state[DSA_MAX_PORTS];
+
+	struct work_struct bridge_work;
 };
 
 struct mv88e6xxx_hw_stat {
@@ -93,6 +118,9 @@ int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
 int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
 int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 		      struct phy_device *phydev, struct ethtool_eee *e);
+int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
+int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
+int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
 
 extern struct dsa_switch_driver mv88e6131_switch_driver;
 extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
-- 
2.1.0


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

* [PATCH v2 09/16] net: dsa: mv88e6352: Add support for hardware bridging
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (7 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 08/16] net: dsa: mv88e6xxx: Add Hardware bridging support Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 10/16] net: dsa: Add basic framework to support ndo_fdb functions Guenter Roeck
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6352.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index f7e7c0f1dff4..51acd1614ce8 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -708,6 +708,9 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
 	.set_eeprom		= mv88e6352_set_eeprom,
 	.get_regs_len		= mv88e6xxx_get_regs_len,
 	.get_regs		= mv88e6xxx_get_regs,
+	.port_join_bridge	= mv88e6xxx_join_bridge,
+	.port_leave_bridge	= mv88e6xxx_leave_bridge,
+	.port_stp_update	= mv88e6xxx_port_stp_update,
 };
 
 MODULE_ALIAS("platform:mv88e6352");
-- 
2.1.0


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

* [PATCH v2 10/16] net: dsa: Add basic framework to support ndo_fdb functions
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (8 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 09/16] net: dsa: mv88e6352: Add support for hardware bridging Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 11/16] net: dsa: mv88e6xxx: Add support for fdb_add, fdb_del, and fdb_getnext Guenter Roeck
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Provide callbacks for ndo_fdb_add, ndo_fdb_del, and ndo_fdb_dump.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 include/net/dsa.h |   6 ++++
 net/dsa/slave.c   | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 47917e5e1e12..fbca63ba8f73 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -296,6 +296,12 @@ struct dsa_switch_driver {
 				     u32 br_port_mask);
 	int	(*port_stp_update)(struct dsa_switch *ds, int port,
 				   u8 state);
+	int	(*fdb_add)(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid);
+	int	(*fdb_del)(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid);
+	int	(*fdb_getnext)(struct dsa_switch *ds, int port,
+			       unsigned char *addr, bool *is_static);
 };
 
 void register_switch_driver(struct dsa_switch_driver *type);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 39555f3f263b..3597724ec3d8 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -201,6 +201,105 @@ out:
 	return 0;
 }
 
+static int dsa_slave_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
+			     struct net_device *dev,
+			     const unsigned char *addr, u16 vid, u16 nlm_flags)
+{
+	struct dsa_slave_priv *p = netdev_priv(dev);
+	struct dsa_switch *ds = p->parent;
+	int ret = -EOPNOTSUPP;
+
+	if (ds->drv->fdb_add)
+		ret = ds->drv->fdb_add(ds, p->port, addr, vid);
+
+	return ret;
+}
+
+static int dsa_slave_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
+			     struct net_device *dev,
+			     const unsigned char *addr, u16 vid)
+{
+	struct dsa_slave_priv *p = netdev_priv(dev);
+	struct dsa_switch *ds = p->parent;
+	int ret = -EOPNOTSUPP;
+
+	if (ds->drv->fdb_del)
+		ret = ds->drv->fdb_del(ds, p->port, addr, vid);
+
+	return ret;
+}
+
+static int dsa_slave_fill_info(struct net_device *dev, struct sk_buff *skb,
+			       const unsigned char *addr, u16 vid,
+			       bool is_static,
+			       u32 portid, u32 seq, int type,
+			       unsigned int flags)
+{
+	struct nlmsghdr *nlh;
+	struct ndmsg *ndm;
+
+	nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
+	if (!nlh)
+		return -EMSGSIZE;
+
+	ndm = nlmsg_data(nlh);
+	ndm->ndm_family	 = AF_BRIDGE;
+	ndm->ndm_pad1    = 0;
+	ndm->ndm_pad2    = 0;
+	ndm->ndm_flags	 = NTF_EXT_LEARNED;
+	ndm->ndm_type	 = 0;
+	ndm->ndm_ifindex = dev->ifindex;
+	ndm->ndm_state   = is_static ? NUD_NOARP : NUD_REACHABLE;
+
+	if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
+		goto nla_put_failure;
+
+	if (vid && nla_put_u16(skb, NDA_VLAN, vid))
+		goto nla_put_failure;
+
+	nlmsg_end(skb, nlh);
+	return 0;
+
+nla_put_failure:
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
+}
+
+/* Dump information about entries, in response to GETNEIGH */
+static int dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
+			      struct net_device *dev,
+			      struct net_device *filter_dev, int idx)
+{
+	struct dsa_slave_priv *p = netdev_priv(dev);
+	struct dsa_switch *ds = p->parent;
+	unsigned char addr[ETH_ALEN] = { 0 };
+	int ret;
+
+	if (!ds->drv->fdb_getnext)
+		return -EOPNOTSUPP;
+
+	for (; ; idx++) {
+		bool is_static;
+
+		ret = ds->drv->fdb_getnext(ds, p->port, addr, &is_static);
+		if (ret < 0)
+			break;
+
+		if (idx < cb->args[0])
+			continue;
+
+		ret = dsa_slave_fill_info(dev, skb, addr, 0,
+					  is_static,
+					  NETLINK_CB(cb->skb).portid,
+					  cb->nlh->nlmsg_seq,
+					  RTM_NEWNEIGH, NLM_F_MULTI);
+		if (ret < 0)
+			break;
+	}
+
+	return idx;
+}
+
 static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
@@ -572,6 +671,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
 	.ndo_change_rx_flags	= dsa_slave_change_rx_flags,
 	.ndo_set_rx_mode	= dsa_slave_set_rx_mode,
 	.ndo_set_mac_address	= dsa_slave_set_mac_address,
+	.ndo_fdb_add		= dsa_slave_fdb_add,
+	.ndo_fdb_del		= dsa_slave_fdb_del,
+	.ndo_fdb_dump		= dsa_slave_fdb_dump,
 	.ndo_do_ioctl		= dsa_slave_ioctl,
 };
 
-- 
2.1.0


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

* [PATCH v2 11/16] net: dsa: mv88e6xxx: Add support for fdb_add, fdb_del, and fdb_getnext
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (9 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 10/16] net: dsa: Add basic framework to support ndo_fdb functions Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 12/16] net: dsa: mv88e6352: Add support for ndo_fdb functions Guenter Roeck
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

No vlan support at this time.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6xxx.c | 136 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/dsa/mv88e6xxx.h |  16 ++++++
 2 files changed, 152 insertions(+)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 17aa74f64233..038802229e32 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/etherdevice.h>
 #include <linux/if_bridge.h>
 #include <linux/jiffies.h>
 #include <linux/list.h>
@@ -953,6 +954,141 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
 	return 0;
 }
 
+static int __mv88e6xxx_write_addr(struct dsa_switch *ds,
+				  const unsigned char *addr)
+{
+	int i, ret;
+
+	for (i = 0; i < 3; i++) {
+		ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0d + i,
+					(addr[i * 2] << 8) | addr[i * 2 + 1]);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr)
+{
+	int i, ret;
+
+	for (i = 0; i < 3; i++) {
+		ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0d + i);
+		if (ret < 0)
+			return ret;
+		addr[i * 2] = ret >> 8;
+		addr[i * 2 + 1] = ret & 0xff;
+	}
+
+	return 0;
+}
+
+static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port,
+				    const unsigned char *addr, int state)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	u8 fid = ps->fid[port];
+	int ret;
+
+	ret = _mv88e6xxx_atu_wait(ds);
+	if (ret < 0)
+		return ret;
+
+	ret = __mv88e6xxx_write_addr(ds, addr);
+	if (ret < 0)
+		return ret;
+
+	ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0c,
+				   (0x10 << port) | state);
+	if (ret)
+		return ret;
+
+	ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_LOAD_FID);
+
+	return ret;
+}
+
+int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid)
+{
+	int state = is_multicast_ether_addr(addr) ?
+					FDB_STATE_MC_STATIC : FDB_STATE_STATIC;
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret;
+
+	mutex_lock(&ps->smi_mutex);
+	ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state);
+	mutex_unlock(&ps->smi_mutex);
+
+	return ret;
+}
+
+int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret;
+
+	mutex_lock(&ps->smi_mutex);
+	ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, FDB_STATE_UNUSED);
+	mutex_unlock(&ps->smi_mutex);
+
+	return ret;
+}
+
+static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port,
+				    unsigned char *addr, bool *is_static)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	u8 fid = ps->fid[port];
+	int ret, state;
+
+	ret = _mv88e6xxx_atu_wait(ds);
+	if (ret < 0)
+		return ret;
+
+	ret = __mv88e6xxx_write_addr(ds, addr);
+	if (ret < 0)
+		return ret;
+
+	do {
+		ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_GETNEXT_FID);
+		if (ret < 0)
+			return ret;
+
+		ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0c);
+		if (ret < 0)
+			return ret;
+		state = ret & FDB_STATE_MASK;
+		if (state == FDB_STATE_UNUSED)
+			return -ENOENT;
+	} while (!(((ret >> 4) & 0xff) & (1 << port)));
+
+	ret = __mv88e6xxx_read_addr(ds, addr);
+	if (ret < 0)
+		return ret;
+
+	*is_static = state == (is_multicast_ether_addr(addr) ?
+			       FDB_STATE_MC_STATIC : FDB_STATE_STATIC);
+
+	return 0;
+}
+
+/* get next entry for port */
+int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
+			       unsigned char *addr, bool *is_static)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+	int ret;
+
+	mutex_lock(&ps->smi_mutex);
+	ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static);
+	mutex_unlock(&ps->smi_mutex);
+
+	return ret;
+}
+
 static void mv88e6xxx_bridge_work(struct work_struct *work)
 {
 	struct mv88e6xxx_priv_state *ps;
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 8e215ebc8d34..aaf239aba726 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -19,6 +19,8 @@
 
 #define ATU_BUSY			0x8000
 
+#define ATU_CMD_LOAD_FID		(ATU_BUSY | 0x3000)
+#define ATU_CMD_GETNEXT_FID		(ATU_BUSY | 0x4000)
 #define ATU_CMD_FLUSH_NONSTATIC_FID	(ATU_BUSY | 0x6000)
 
 /* port states */
@@ -29,6 +31,14 @@
 #define PSTATE_LEARNING		0x02
 #define PSTATE_FORWARDING	0x03
 
+/* FDB states */
+
+#define FDB_STATE_MASK			0x0f
+
+#define FDB_STATE_UNUSED		0x00
+#define FDB_STATE_MC_STATIC		0x07	/* static multicast */
+#define FDB_STATE_STATIC		0x0e	/* static unicast */
+
 struct mv88e6xxx_priv_state {
 	/* When using multi-chip addressing, this mutex protects
 	 * access to the indirect access registers.  (In single-chip
@@ -121,6 +131,12 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
 int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
 int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
+int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid);
+int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
+			   const unsigned char *addr, u16 vid);
+int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
+			       unsigned char *addr, bool *is_static);
 
 extern struct dsa_switch_driver mv88e6131_switch_driver;
 extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
-- 
2.1.0


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

* [PATCH v2 12/16] net: dsa: mv88e6352: Add support for ndo_fdb functions
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (10 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 11/16] net: dsa: mv88e6xxx: Add support for fdb_add, fdb_del, and fdb_getnext Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 13/16] net: dsa: Centralise getting switch id Guenter Roeck
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

Add support for manipulating switch fdb entries by pointing to the
ndo_fdb functions implemented for mv88e6xxxx.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6352.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 51acd1614ce8..7285bd053363 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -711,6 +711,9 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
 	.port_join_bridge	= mv88e6xxx_join_bridge,
 	.port_leave_bridge	= mv88e6xxx_leave_bridge,
 	.port_stp_update	= mv88e6xxx_port_stp_update,
+	.fdb_add		= mv88e6xxx_port_fdb_add,
+	.fdb_del		= mv88e6xxx_port_fdb_del,
+	.fdb_getnext		= mv88e6xxx_port_fdb_getnext,
 };
 
 MODULE_ALIAS("platform:mv88e6352");
-- 
2.1.0


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

* [PATCH v2 13/16] net: dsa: Centralise getting switch id
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (11 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 12/16] net: dsa: mv88e6352: Add support for ndo_fdb functions Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 14/16] net: dsa: mv88e6171: Add defines for switch product IDs Guenter Roeck
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

From: Andrew Lunn <andrew@lunn.ch>

Get the switch id and save it away in the private mv88x6xxx structure
in a centralised piece of code, rather than each driver doing it itself.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6352.c | 2 --
 drivers/net/dsa/mv88e6xxx.c | 2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 7285bd053363..41fe3a6a72d1 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -369,8 +369,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
 
 	mutex_init(&ps->eeprom_mutex);
 
-	ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0;
-
 	ret = mv88e6352_switch_reset(ds);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 038802229e32..13572cc24c6d 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1152,6 +1152,8 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
 	mutex_init(&ps->stats_mutex);
 	mutex_init(&ps->phy_mutex);
 
+	ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0;
+
 	ps->fid_mask = (1 << DSA_MAX_PORTS) - 1;
 
 	INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
-- 
2.1.0


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

* [PATCH v2 14/16] net: dsa: mv88e6171: Add defines for switch product IDs
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (12 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 13/16] net: dsa: Centralise getting switch id Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 15/16] net: dsa: mv88e6171: Add EEE support to the mv88e6172 Guenter Roeck
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

From: Andrew Lunn <andrew@lunn.ch>

Make the code more readable by using defines for the switch IDs.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6171.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 6ce6a3ea1b8d..54ebfed1b938 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -17,6 +17,10 @@
 #include <net/dsa.h>
 #include "mv88e6xxx.h"
 
+/* Switch product IDs */
+#define ID_6171	0x1710
+#define ID_6172	0x1720
+
 static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
 {
 	struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
@@ -27,9 +31,9 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
 
 	ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
 	if (ret >= 0) {
-		if ((ret & 0xfff0) == 0x1710)
+		if ((ret & 0xfff0) == ID_6171)
 			return "Marvell 88E6171";
-		if ((ret & 0xfff0) == 0x1720)
+		if ((ret & 0xfff0) == ID_6172)
 			return "Marvell 88E6172";
 	}
 
-- 
2.1.0


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

* [PATCH v2 15/16] net: dsa: mv88e6171: Add EEE support to the mv88e6172
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (13 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 14/16] net: dsa: mv88e6171: Add defines for switch product IDs Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  1:36 ` [PATCH v2 16/16] net: dsa: mv88e6171: Add support for hardware bridging Guenter Roeck
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

From: Andrew Lunn <andrew@lunn.ch>

The mv88e6172 has support for EEE. Check for the product ID and call
the common code if applicable.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6171.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 54ebfed1b938..e1700cd8badc 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -390,6 +390,28 @@ static int mv88e6171_get_sset_count(struct dsa_switch *ds)
 	return ARRAY_SIZE(mv88e6171_hw_stats);
 }
 
+static int mv88e6171_get_eee(struct dsa_switch *ds, int port,
+			     struct ethtool_eee *e)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+	if (ps->id == ID_6172)
+		return mv88e6xxx_get_eee(ds, port, e);
+
+	return -EOPNOTSUPP;
+}
+
+static int mv88e6171_set_eee(struct dsa_switch *ds, int port,
+			     struct phy_device *phydev, struct ethtool_eee *e)
+{
+	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+	if (ps->id == ID_6172)
+		return mv88e6xxx_set_eee(ds, port, phydev, e);
+
+	return -EOPNOTSUPP;
+}
+
 struct dsa_switch_driver mv88e6171_switch_driver = {
 	.tag_protocol		= DSA_TAG_PROTO_EDSA,
 	.priv_size		= sizeof(struct mv88e6xxx_priv_state),
@@ -402,6 +424,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
 	.get_strings		= mv88e6171_get_strings,
 	.get_ethtool_stats	= mv88e6171_get_ethtool_stats,
 	.get_sset_count		= mv88e6171_get_sset_count,
+	.set_eee		= mv88e6171_set_eee,
+	.get_eee		= mv88e6171_get_eee,
 #ifdef CONFIG_NET_DSA_HWMON
 	.get_temp               = mv88e6xxx_get_temp,
 #endif
-- 
2.1.0


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

* [PATCH v2 16/16] net: dsa: mv88e6171: Add support for hardware bridging
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (14 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 15/16] net: dsa: mv88e6171: Add EEE support to the mv88e6172 Guenter Roeck
@ 2015-03-27  1:36 ` Guenter Roeck
  2015-03-27  6:01 ` [PATCH v2 00/16] net: dsa: HW bridging, EEE support Florian Fainelli
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2015-03-27  1:36 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Andrew Lunn, Florian Fainelli, linux-kernel,
	Guenter Roeck

From: Andrew Lunn <andrew@lunn.ch>

Wire up the common code for setting up hardware bridging
and access to the forwarding database.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/net/dsa/mv88e6171.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index e1700cd8badc..18cfead83dc9 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -431,6 +431,12 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
 #endif
 	.get_regs_len		= mv88e6xxx_get_regs_len,
 	.get_regs		= mv88e6xxx_get_regs,
+	.port_join_bridge       = mv88e6xxx_join_bridge,
+	.port_leave_bridge      = mv88e6xxx_leave_bridge,
+	.port_stp_update        = mv88e6xxx_port_stp_update,
+	.fdb_add		= mv88e6xxx_port_fdb_add,
+	.fdb_del		= mv88e6xxx_port_fdb_del,
+	.fdb_getnext		= mv88e6xxx_port_fdb_getnext,
 };
 
 MODULE_ALIAS("platform:mv88e6171");
-- 
2.1.0


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

* Re: [PATCH v2 00/16] net: dsa: HW bridging, EEE support
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (15 preceding siblings ...)
  2015-03-27  1:36 ` [PATCH v2 16/16] net: dsa: mv88e6171: Add support for hardware bridging Guenter Roeck
@ 2015-03-27  6:01 ` Florian Fainelli
  2015-03-27 15:54 ` Andrew Lunn
  2015-03-29 20:24 ` David Miller
  18 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2015-03-27  6:01 UTC (permalink / raw)
  To: Guenter Roeck; +Cc: netdev, David S. Miller, Andrew Lunn, linux-kernel

Hi Guenter,

2015-03-26 18:36 GMT-07:00 Guenter Roeck <linux@roeck-us.net>:
> Patch 1 to 7 of this series prepare the drivers using the mv88e6xxx code
> for HW bridging support, without adding the code itself. For the most part
> this factors out common port initialization code. There is no functional
> change except for patch 3, which disables the message port bit for the
> CPU port to prevent packet duplication if HW bridging is configured.
>
> Patch 8 adds the infrastructure for hardware bridging support to the
> mv88e6xxx code.
>
> Patch 9 wires the MV88E6352 driver to support hardware bridging.
>
> Patches 10 to 12 add support for ndo_fdb functions to the dsa subsystem,
> and wire up the MV88E6352 driver to support those functions.
>
> Patches 13 to 16 add EEE support and HW bridging support to the mv88e6171
> driver. This set of patches is from Andrew, applied on top of the first
> set of patches.
>
> The series applies to net-next as of 3/24/2015.
>
> Thanks a lot to Andrew Lunn for testing and valuable feedback.

This looks really good to me:

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
--
Florian

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

* Re: [PATCH v2 00/16] net: dsa: HW bridging, EEE support
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (16 preceding siblings ...)
  2015-03-27  6:01 ` [PATCH v2 00/16] net: dsa: HW bridging, EEE support Florian Fainelli
@ 2015-03-27 15:54 ` Andrew Lunn
  2015-03-29 20:24 ` David Miller
  18 siblings, 0 replies; 20+ messages in thread
From: Andrew Lunn @ 2015-03-27 15:54 UTC (permalink / raw)
  To: Guenter Roeck; +Cc: netdev, David S. Miller, Florian Fainelli, linux-kernel

On Thu, Mar 26, 2015 at 06:36:27PM -0700, Guenter Roeck wrote:
> Patch 1 to 7 of this series prepare the drivers using the mv88e6xxx code
> for HW bridging support, without adding the code itself. For the most part
> this factors out common port initialization code. There is no functional
> change except for patch 3, which disables the message port bit for the
> CPU port to prevent packet duplication if HW bridging is configured.

I just re-tested on my WRT1900AC and 370RD. All looks good.

  Andrew

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

* Re: [PATCH v2 00/16] net: dsa: HW bridging, EEE support
  2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
                   ` (17 preceding siblings ...)
  2015-03-27 15:54 ` Andrew Lunn
@ 2015-03-29 20:24 ` David Miller
  18 siblings, 0 replies; 20+ messages in thread
From: David Miller @ 2015-03-29 20:24 UTC (permalink / raw)
  To: linux; +Cc: netdev, andrew, f.fainelli, linux-kernel

From: Guenter Roeck <linux@roeck-us.net>
Date: Thu, 26 Mar 2015 18:36:27 -0700

> Patch 1 to 7 of this series prepare the drivers using the mv88e6xxx code
> for HW bridging support, without adding the code itself. For the most part
> this factors out common port initialization code. There is no functional
> change except for patch 3, which disables the message port bit for the
> CPU port to prevent packet duplication if HW bridging is configured.
> 
> Patch 8 adds the infrastructure for hardware bridging support to the
> mv88e6xxx code.
> 
> Patch 9 wires the MV88E6352 driver to support hardware bridging.
> 
> Patches 10 to 12 add support for ndo_fdb functions to the dsa subsystem,
> and wire up the MV88E6352 driver to support those functions.
> 
> Patches 13 to 16 add EEE support and HW bridging support to the mv88e6171
> driver. This set of patches is from Andrew, applied on top of the first
> set of patches.
> 
> The series applies to net-next as of 3/24/2015.
> 
> Thanks a lot to Andrew Lunn for testing and valuable feedback.

Series applied, thanks!

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

end of thread, other threads:[~2015-03-29 20:15 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-27  1:36 [PATCH v2 00/16] net: dsa: HW bridging, EEE support Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 01/16] net: dsa: mv88e6xxx: Factor out common initialization code Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 02/16] net: dsa: mv88e6xxx: Provide function for common port initialization Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 03/16] net: dsa: mv88e6xxx: Disable Message Port bit for CPU port Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 04/16] net: dsa: mv88e6xxx: Split mv88e6xxx_reg_read and mv88e6xxx_reg_write Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 05/16] net: dsa: mv88e6352: Use common port initialization code Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 06/16] net: dsa: mv88e6123_61_65: Use common port configuration Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 07/16] net: dsa: mv88e6171: " Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 08/16] net: dsa: mv88e6xxx: Add Hardware bridging support Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 09/16] net: dsa: mv88e6352: Add support for hardware bridging Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 10/16] net: dsa: Add basic framework to support ndo_fdb functions Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 11/16] net: dsa: mv88e6xxx: Add support for fdb_add, fdb_del, and fdb_getnext Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 12/16] net: dsa: mv88e6352: Add support for ndo_fdb functions Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 13/16] net: dsa: Centralise getting switch id Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 14/16] net: dsa: mv88e6171: Add defines for switch product IDs Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 15/16] net: dsa: mv88e6171: Add EEE support to the mv88e6172 Guenter Roeck
2015-03-27  1:36 ` [PATCH v2 16/16] net: dsa: mv88e6171: Add support for hardware bridging Guenter Roeck
2015-03-27  6:01 ` [PATCH v2 00/16] net: dsa: HW bridging, EEE support Florian Fainelli
2015-03-27 15:54 ` Andrew Lunn
2015-03-29 20:24 ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.