2016-03-27 02:00:13

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 0/7] net: dsa: mv88e6xxx: HW bridging support for 6185

All packets passing through a switch of the 6185 family are currently all
directed to the CPU port. This means that port bridging is software driven.

To enable hardware bridging for this switch family, we need to implement the
port mapping operations, the FDB operations, and optionally the VLAN operations
(for 802.1Q and VLAN filtering aware systems).

However this family only has 256 FDBs indexed by 8-bit identifiers, opposed to
4096 FDBs with 12-bit identifiers for other families such as 6352. It also
doesn't have dedicated FID registers for ATU and VTU operations.

This patchset fixes these differences, and enable hardware bridging for 6185.

Vivien Didelot (7):
net: dsa: mv88e6xxx: 6185 port default FID is 8-bit
net: dsa: mv88e6xxx: 6185 has only 256 FDBs
net: dsa: mv88e6xxx: write FID in ATU command
net: dsa: mv88e6xxx: fix ATU FID access for 6185
net: dsa: mv88e6xxx: fix VTU FID access for 6185
net: dsa: mv88e6xxx: map destination addresses for 6185
net: dsa: mv88e6131: enable hardware bridging

drivers/net/dsa/mv88e6131.c | 11 ++++++
drivers/net/dsa/mv88e6xxx.c | 84 ++++++++++++++++++++++++++++++++-------------
drivers/net/dsa/mv88e6xxx.h | 7 ++--
3 files changed, 76 insertions(+), 26 deletions(-)

--
2.7.4


2016-03-27 02:00:26

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 7/7] net: dsa: mv88e6131: enable hardware bridging

By adding support for bridge operations, FDB operations, and optionally
VLAN operations (for 802.1Q and VLAN filtering aware systems), the
switch bridges ports correctly, the CPU is able to populate the hardware
address databases, and thus hardware bridging becomes functional within
the 88E6185 family of switches.

Signed-off-by: Vivien Didelot <[email protected]>
---
drivers/net/dsa/mv88e6131.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index a92ca65..2407028 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -169,6 +169,17 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
.adjust_link = mv88e6xxx_adjust_link,
+ .port_bridge_join = mv88e6xxx_port_bridge_join,
+ .port_bridge_leave = mv88e6xxx_port_bridge_leave,
+ .port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
+ .port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
+ .port_vlan_add = mv88e6xxx_port_vlan_add,
+ .port_vlan_del = mv88e6xxx_port_vlan_del,
+ .port_vlan_dump = mv88e6xxx_port_vlan_dump,
+ .port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
+ .port_fdb_add = mv88e6xxx_port_fdb_add,
+ .port_fdb_del = mv88e6xxx_port_fdb_del,
+ .port_fdb_dump = mv88e6xxx_port_fdb_dump,
};

MODULE_ALIAS("platform:mv88e6085");
--
2.7.4

2016-03-27 02:00:28

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 6/7] net: dsa: mv88e6xxx: map destination addresses for 6185

The 88E6185 switch also has a MapDA bit in its Port Control 2 register.
When this bit is cleared, all frames are sent out to the CPU port.

Set this bit to rely on address databases (ATU) hits and direct frames
out of the correct ports, and thus allow hardware bridging.

Signed-off-by: Vivien Didelot <[email protected]>
---
drivers/net/dsa/mv88e6xxx.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 366fda1..35d0ace 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2413,7 +2413,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
reg = 0;
if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
- mv88e6xxx_6095_family(ds) || mv88e6xxx_6320_family(ds))
+ mv88e6xxx_6095_family(ds) || mv88e6xxx_6320_family(ds) ||
+ mv88e6xxx_6185_family(ds))
reg = PORT_CONTROL_2_MAP_DA;

if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
--
2.7.4

2016-03-27 02:00:24

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 2/7] net: dsa: mv88e6xxx: 6185 has only 256 FDBs

The 6185 family has only 256 indexable address databases, while the
others (such as 6352) have 4095. Explicit and use these maximum values
in the _mv88e6xxx_fid_new function.

Signed-off-by: Vivien Didelot <[email protected]>
---
drivers/net/dsa/mv88e6xxx.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 1d9ae48..1d9b5dd 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1575,8 +1575,12 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
struct mv88e6xxx_vtu_stu_entry vlan;
+ u16 max = 4095;
int i, err;

+ if (mv88e6xxx_6185_family(ds))
+ max = 256;
+
bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);

/* Set every FID bit used by the (un)bridged ports */
@@ -1608,7 +1612,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
* databases are not needed. Return the next positive available.
*/
*fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1);
- if (unlikely(*fid == MV88E6XXX_N_FID))
+ if (unlikely(*fid > max))
return -ENOSPC;

/* Clear the database */
--
2.7.4

2016-03-27 02:00:23

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 4/7] net: dsa: mv88e6xxx: fix ATU FID access for 6185

The 6185 family does not have a ATU FID register. It splits it in the
ATU Control register and the ATU Operation.

Add 6185 support for FID (a.k.a. DBNum) in ATU commands.

Signed-off-by: Vivien Didelot <[email protected]>
---
drivers/net/dsa/mv88e6xxx.c | 14 ++++++++++++++
drivers/net/dsa/mv88e6xxx.h | 2 +-
2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index df3f219..4b3c466 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -961,6 +961,20 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd)
ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid);
if (ret < 0)
return ret;
+ } else if (mv88e6xxx_6185_family(ds)) {
+ /* ATU DBNum[7:4] are located in ATU Control 15:12 */
+ ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL);
+ if (ret < 0)
+ return ret;
+
+ ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL,
+ (ret & 0xfff) |
+ ((fid << 8) & 0xf000));
+ if (ret < 0)
+ return ret;
+
+ /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
+ cmd |= fid & 0xf;
} else {
return -EOPNOTSUPP;
}
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index febab76..94d3cb3 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -366,7 +366,7 @@ struct mv88e6xxx_switch_id {
};

struct mv88e6xxx_atu_entry {
- u16 fid;
+ u16 fid; /* 8-bit DBNum in 88E6185 family */
u8 state;
bool trunk;
u16 portv_trunkid;
--
2.7.4

2016-03-27 02:01:41

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 5/7] net: dsa: mv88e6xxx: fix VTU FID access for 6185

The 6352 family has an entire register for its 12-bit FID used by the
VTU operations. The 6185 family has no such register. Its 8-bit FID
(called DBNum) is split in the VTU Operation register.

Modify the VTU read and write access to support this switch family.

Signed-off-by: Vivien Didelot <[email protected]>
---
drivers/net/dsa/mv88e6xxx.c | 20 +++++++++++++++++++-
drivers/net/dsa/mv88e6xxx.h | 2 +-
2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 4b3c466..366fda1 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1355,6 +1355,17 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds,
return ret;

next.sid = ret & GLOBAL_VTU_SID_MASK;
+ } else if (mv88e6xxx_6185_family(ds)) {
+ /* VTU DBNum[7:4] are located in VTU Operation 11:8, and
+ * VTU DBNum[3:0] are located in VTU Operation 3:0
+ */
+ ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL,
+ GLOBAL_VTU_OP);
+ if (ret < 0)
+ return ret;
+
+ next.fid = (ret & 0xf00) >> 4;
+ next.fid |= ret & 0xf;
}
}

@@ -1416,6 +1427,7 @@ unlock:
static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
struct mv88e6xxx_vtu_stu_entry *entry)
{
+ u16 op = GLOBAL_VTU_OP_VTU_LOAD_PURGE;
u16 reg = 0;
int ret;

@@ -1442,6 +1454,12 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_FID, reg);
if (ret < 0)
return ret;
+ } else if (mv88e6xxx_6185_family(ds)) {
+ /* VTU DBNum[7:4] are located in VTU Operation 11:8, and
+ * VTU DBNum[3:0] are located in VTU Operation 3:0
+ */
+ op |= (entry->fid & 0xf0) << 8;
+ op |= entry->fid & 0xf;
}

reg = GLOBAL_VTU_VID_VALID;
@@ -1451,7 +1469,7 @@ loadpurge:
if (ret < 0)
return ret;

- return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_VTU_LOAD_PURGE);
+ return _mv88e6xxx_vtu_cmd(ds, op);
}

static int _mv88e6xxx_stu_getnext(struct dsa_switch *ds, u8 sid,
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 94d3cb3..b1f1269 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -376,7 +376,7 @@ struct mv88e6xxx_atu_entry {
struct mv88e6xxx_vtu_stu_entry {
/* VTU only */
u16 vid;
- u16 fid;
+ u16 fid; /* 8-bit DBNum in 88E6185 family */

/* VTU and STU */
u8 sid;
--
2.7.4

2016-03-27 02:01:58

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 3/7] net: dsa: mv88e6xxx: write FID in ATU command

Some switch models don't have a separate ATU FID register, but bury it
in the ATU Operation register.

Factorize the write of the FID and opcode in the ATU command function.

Signed-off-by: Vivien Didelot <[email protected]>
---
drivers/net/dsa/mv88e6xxx.c | 31 ++++++++++++++-----------------
1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 1d9b5dd..df3f219 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -951,10 +951,20 @@ out:
return ret;
}

-static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 cmd)
+static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd)
{
int ret;

+ if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) ||
+ mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) {
+ /* 88E6352 and similar have their own ATU FID register */
+ ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid);
+ if (ret < 0)
+ return ret;
+ } else {
+ return -EOPNOTSUPP;
+ }
+
ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_OP, cmd);
if (ret < 0)
return ret;
@@ -1001,11 +1011,6 @@ static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds,
return err;

if (entry->fid) {
- err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID,
- entry->fid);
- if (err)
- return err;
-
op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB :
GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB;
} else {
@@ -1013,7 +1018,7 @@ static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds,
GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC;
}

- return _mv88e6xxx_atu_cmd(ds, op);
+ return _mv88e6xxx_atu_cmd(ds, entry->fid, op);
}

static int _mv88e6xxx_atu_flush(struct dsa_switch *ds, u16 fid, bool static_too)
@@ -1973,11 +1978,7 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds,
if (ret < 0)
return ret;

- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, entry->fid);
- if (ret < 0)
- return ret;
-
- return _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_LOAD_DB);
+ return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB);
}

static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
@@ -2060,11 +2061,7 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
if (ret < 0)
return ret;

- ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid);
- if (ret < 0)
- return ret;
-
- ret = _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_GET_NEXT_DB);
+ ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB);
if (ret < 0)
return ret;

--
2.7.4

2016-03-27 02:02:29

by Vivien Didelot

[permalink] [raw]
Subject: [PATCH net-next 1/7] net: dsa: mv88e6xxx: 6185 port default FID is 8-bit

In the 6352 family, FIDs are 12-bit. In the 6185 family, they are 8-bit.

Fix the upper mask, which was overlapping on the port Trunk ID (even
though it is not used yet).

Signed-off-by: Vivien Didelot <[email protected]>
---
drivers/net/dsa/mv88e6xxx.c | 10 +++++++---
drivers/net/dsa/mv88e6xxx.h | 3 ++-
2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index fa086e0..1d9ae48 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1511,9 +1511,13 @@ loadpurge:
static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
u16 *old)
{
+ u16 upper_mask = PORT_CONTROL_1_FID_11_4_MASK;
u16 fid;
int ret;

+ if (mv88e6xxx_6185_family(ds))
+ upper_mask = PORT_CONTROL_1_DBNUM_7_4_MASK;
+
/* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN);
if (ret < 0)
@@ -1536,11 +1540,11 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
if (ret < 0)
return ret;

- fid |= (ret & PORT_CONTROL_1_FID_11_4_MASK) << 4;
+ fid |= (ret & upper_mask) << 4;

if (new) {
- ret &= ~PORT_CONTROL_1_FID_11_4_MASK;
- ret |= (*new >> 4) & PORT_CONTROL_1_FID_11_4_MASK;
+ ret &= ~upper_mask;
+ ret |= (*new >> 4) & upper_mask;

ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1,
ret);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 9a038ab..febab76 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -133,7 +133,8 @@
#define PORT_CONTROL_STATE_LEARNING 0x02
#define PORT_CONTROL_STATE_FORWARDING 0x03
#define PORT_CONTROL_1 0x05
-#define PORT_CONTROL_1_FID_11_4_MASK (0xff << 0)
+#define PORT_CONTROL_1_DBNUM_7_4_MASK (0xf << 0) /* 6185 */
+#define PORT_CONTROL_1_FID_11_4_MASK (0xff << 0) /* 6352 */
#define PORT_BASE_VLAN 0x06
#define PORT_BASE_VLAN_FID_3_0_MASK (0xf << 12)
#define PORT_DEFAULT_VLAN 0x07
--
2.7.4

2016-03-27 02:52:33

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next 2/7] net: dsa: mv88e6xxx: 6185 has only 256 FDBs

On Sat, Mar 26, 2016 at 09:59:38PM -0400, Vivien Didelot wrote:
> The 6185 family has only 256 indexable address databases, while the
> others (such as 6352) have 4095. Explicit and use these maximum values
> in the _mv88e6xxx_fid_new function.

Hi Vivien

I've been looking at the Marvell reference code, in particular, the
function gfdbGetAtuAllCount().

The following device have 16 databases.

( DEV_88E6021 | DEV_88E6060 | DEV_88E6063 | \
DEV_FH_VPN | DEV_88E6083 | DEV_88E6183 | DEV_88E6093 | DEV_88E6061 )

The following device have 64 databases.
( DEV_88E6065 )

The following devices have 256 databases
( DEV_88E6095_FAMILY | DEV_88E6185_FAMILY )

And the following devices have 4096
( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6\
351_FAMILY| DEV_88E6352_FAMILY )

Andrew

2016-03-27 03:04:38

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next 4/7] net: dsa: mv88e6xxx: fix ATU FID access for 6185

On Sat, Mar 26, 2016 at 09:59:40PM -0400, Vivien Didelot wrote:
> The 6185 family does not have a ATU FID register. It splits it in the
> ATU Control register and the ATU Operation.

Looking at the reference code, the following devices have a FID
register:
( DEV_88E6097_FAMILY | DEV_88E6165_FAMILY | DEV_88E6351_FAMILY |
DEV_88E6352_FAMILY)

If there are 256 databases, it gets split across the two registers.

If there are only 64, it all goes in the ATU operation.

Andrew

>
> Add 6185 support for FID (a.k.a. DBNum) in ATU commands.
>
> Signed-off-by: Vivien Didelot <[email protected]>
> ---
> drivers/net/dsa/mv88e6xxx.c | 14 ++++++++++++++
> drivers/net/dsa/mv88e6xxx.h | 2 +-
> 2 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
> index df3f219..4b3c466 100644
> --- a/drivers/net/dsa/mv88e6xxx.c
> +++ b/drivers/net/dsa/mv88e6xxx.c
> @@ -961,6 +961,20 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd)
> ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid);
> if (ret < 0)
> return ret;
> + } else if (mv88e6xxx_6185_family(ds)) {
> + /* ATU DBNum[7:4] are located in ATU Control 15:12 */
> + ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL);
> + if (ret < 0)
> + return ret;
> +
> + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL,
> + (ret & 0xfff) |
> + ((fid << 8) & 0xf000));
> + if (ret < 0)
> + return ret;
> +
> + /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
> + cmd |= fid & 0xf;
> } else {
> return -EOPNOTSUPP;
> }
> diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
> index febab76..94d3cb3 100644
> --- a/drivers/net/dsa/mv88e6xxx.h
> +++ b/drivers/net/dsa/mv88e6xxx.h
> @@ -366,7 +366,7 @@ struct mv88e6xxx_switch_id {
> };
>
> struct mv88e6xxx_atu_entry {
> - u16 fid;
> + u16 fid; /* 8-bit DBNum in 88E6185 family */
> u8 state;
> bool trunk;
> u16 portv_trunkid;
> --
> 2.7.4
>