Commit aaf1be31 authored by David S. Miller's avatar David S. Miller

Merge branch 'dsa-mv88e6xxx-802.1s-and-88E6390-VTU'

Vivien Didelot says:

====================
net: dsa: mv88e6xxx: 802.1s and 88E6390 VTU

This patch series adds support for the VLAN Table Unit (a.k.a. the VTU)
to the 88E6390 family of Marvell Ethernet switch chips. The plumbing for
the per VLAN Spanning Tree support is added as a side effect of the
necessary refactoring.

The patchset is split up so that no duplication of code is introduced.
With this patchset applied, the mv88e6xxx driver has 2 new function
pointers for the VTU GetNext and VTU Load/Purge operations (with 3
implementations), both handling programmation of 802.1q and 802.1s.

On a ZII Rev C board (featuring 2 88E6390X chips) with all ports bridged
together, we obtain the following hardware VLAN configuration:

    # cat /sys/class/net/br0/bridge/vlan_filtering
    1
    # cat /sys/class/net/br0/bridge/default_pvid
    42
    # bridge vlan add dev lan3 vid 666
    # bridge vlan show
    port    vlan ids
    lan1     42 PVID Egress Untagged

    lan1     42 PVID Egress Untagged

    lan2     42 PVID Egress Untagged

    lan2     42 PVID Egress Untagged

    lan3     42 PVID Egress Untagged
             666

    lan3     42 PVID Egress Untagged
             666

    lan4     42 PVID Egress Untagged

    lan4     42 PVID Egress Untagged

    lan5     42 PVID Egress Untagged

    lan5     42 PVID Egress Untagged

    lan6     42 PVID Egress Untagged

    lan6     42 PVID Egress Untagged

    lan7     42 PVID Egress Untagged

    lan7     42 PVID Egress Untagged

    lan8     42 PVID Egress Untagged

    lan8     42 PVID Egress Untagged

    br0      42 PVID Egress Untagged

Below are the technical details for the different implementations.

All switch families have up to 3 dedicated VTU Data registers used to
program 802.1q and 802.1s, both using 2-bit values.

On 88E6185 and 88E6352 families, port membership and state are adjacent,
while the 88E6390 family share the same bits:

    Bits        88E6185/88E6352         88E6390
    -----       -----------------       --------------------------
    0-1         Port 0 membership       Port 0 membership or state
    2-3         Port 0 state            Port 1 membership or state
    4-5         Port 1 membership       Port 2 membership or state
    6-7         Port 1 state            Port 3 membership or state
    8-9         Port 2 membership       Port 4 membership or state
    10-11       Port 2 state            Port 5 membership or state
    ...         ...                     ...

The 88E6185 family programs all ports membership and state in a single
VTU GetNext or Load/Purge operation.

The 88E6352 family introduced an indirect Spanning Tree Unit table
(a.k.a. STU) which requires additional STU GetNext and Load/Purge
operations to read and write the ports state bits.

The 88E6390 family also has an STU and requires data bits to be accessed
before and after every single VTU or STU operation.

Finally, the 88E6390 family introduced a 13th bit for the VLAN ID, which
must be taken care of regardless the VTU operating mode. This means that
iterating over the VTU now starts or ends with value 8191, not 4095.

Patch 1 adds a max_vid field to the chip info structure.
Patch 2 adds 802.1q and 802.1s data to the generic VTU entry structure.
Patches 3 to 10 move helpers to a dedicated file (later made static).
Patches 11 and 12 abstract handling of the STU behind VTU operations.
Patches 13 and 14 add the new function pointers for VTU operations.
Patches 15 and 18 polish the VTU code and add VTU support for 88E6390.

Changes in v2:
  - add Reviewed-by tags
  - fix comments in 8/18
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 152afb9b 931d1822
...@@ -2,5 +2,6 @@ obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o ...@@ -2,5 +2,6 @@ obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
mv88e6xxx-objs := chip.o mv88e6xxx-objs := chip.o
mv88e6xxx-objs += global1.o mv88e6xxx-objs += global1.o
mv88e6xxx-objs += global1_atu.o mv88e6xxx-objs += global1_atu.o
mv88e6xxx-objs += global1_vtu.o
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o
mv88e6xxx-objs += port.o mv88e6xxx-objs += port.o
This diff is collapsed.
...@@ -50,4 +50,18 @@ int mv88e6xxx_g1_atu_flush(struct mv88e6xxx_chip *chip, u16 fid, bool all); ...@@ -50,4 +50,18 @@ int mv88e6xxx_g1_atu_flush(struct mv88e6xxx_chip *chip, u16 fid, bool all);
int mv88e6xxx_g1_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, int port, int mv88e6xxx_g1_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, int port,
bool all); bool all);
int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip);
#endif /* _MV88E6XXX_GLOBAL1_H */ #endif /* _MV88E6XXX_GLOBAL1_H */
This diff is collapsed.
...@@ -249,6 +249,7 @@ ...@@ -249,6 +249,7 @@
#define GLOBAL_VTU_OP_STU_GET_NEXT ((0x06 << 12) | GLOBAL_VTU_OP_BUSY) #define GLOBAL_VTU_OP_STU_GET_NEXT ((0x06 << 12) | GLOBAL_VTU_OP_BUSY)
#define GLOBAL_VTU_VID 0x06 #define GLOBAL_VTU_VID 0x06
#define GLOBAL_VTU_VID_MASK 0xfff #define GLOBAL_VTU_VID_MASK 0xfff
#define GLOBAL_VTU_VID_PAGE BIT(13)
#define GLOBAL_VTU_VID_VALID BIT(12) #define GLOBAL_VTU_VID_VALID BIT(12)
#define GLOBAL_VTU_DATA_0_3 0x07 #define GLOBAL_VTU_DATA_0_3 0x07
#define GLOBAL_VTU_DATA_4_7 0x08 #define GLOBAL_VTU_DATA_4_7 0x08
...@@ -566,9 +567,6 @@ enum mv88e6xxx_cap { ...@@ -566,9 +567,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_G2_IRL_DATA BIT_ULL(MV88E6XXX_CAP_G2_IRL_DATA) #define MV88E6XXX_FLAG_G2_IRL_DATA BIT_ULL(MV88E6XXX_CAP_G2_IRL_DATA)
#define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT) #define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT)
#define MV88E6XXX_FLAG_STU BIT_ULL(MV88E6XXX_CAP_STU)
#define MV88E6XXX_FLAG_VTU BIT_ULL(MV88E6XXX_CAP_VTU)
/* Ingress Rate Limit unit */ /* Ingress Rate Limit unit */
#define MV88E6XXX_FLAGS_IRL \ #define MV88E6XXX_FLAGS_IRL \
(MV88E6XXX_FLAG_G2_IRL_CMD | \ (MV88E6XXX_FLAG_G2_IRL_CMD | \
...@@ -587,7 +585,6 @@ enum mv88e6xxx_cap { ...@@ -587,7 +585,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAGS_FAMILY_6095 \ #define MV88E6XXX_FLAGS_FAMILY_6095 \
(MV88E6XXX_FLAG_GLOBAL2 | \ (MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_MULTI_CHIP) MV88E6XXX_FLAGS_MULTI_CHIP)
#define MV88E6XXX_FLAGS_FAMILY_6097 \ #define MV88E6XXX_FLAGS_FAMILY_6097 \
...@@ -597,8 +594,6 @@ enum mv88e6xxx_cap { ...@@ -597,8 +594,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP) MV88E6XXX_FLAGS_MULTI_CHIP)
...@@ -609,8 +604,6 @@ enum mv88e6xxx_cap { ...@@ -609,8 +604,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP) MV88E6XXX_FLAGS_MULTI_CHIP)
...@@ -618,8 +611,7 @@ enum mv88e6xxx_cap { ...@@ -618,8 +611,7 @@ enum mv88e6xxx_cap {
(MV88E6XXX_FLAG_GLOBAL2 | \ (MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAGS_MULTI_CHIP | \ MV88E6XXX_FLAGS_MULTI_CHIP)
MV88E6XXX_FLAG_VTU)
#define MV88E6XXX_FLAGS_FAMILY_6320 \ #define MV88E6XXX_FLAGS_FAMILY_6320 \
(MV88E6XXX_FLAG_EEE | \ (MV88E6XXX_FLAG_EEE | \
...@@ -627,7 +619,6 @@ enum mv88e6xxx_cap { ...@@ -627,7 +619,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP) MV88E6XXX_FLAGS_MULTI_CHIP)
...@@ -637,8 +628,6 @@ enum mv88e6xxx_cap { ...@@ -637,8 +628,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP | \ MV88E6XXX_FLAGS_MULTI_CHIP | \
MV88E6XXX_FLAGS_SERDES) MV88E6XXX_FLAGS_SERDES)
...@@ -650,8 +639,6 @@ enum mv88e6xxx_cap { ...@@ -650,8 +639,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP) MV88E6XXX_FLAGS_MULTI_CHIP)
...@@ -663,8 +650,6 @@ enum mv88e6xxx_cap { ...@@ -663,8 +650,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \ MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP | \ MV88E6XXX_FLAGS_MULTI_CHIP | \
MV88E6XXX_FLAGS_SERDES) MV88E6XXX_FLAGS_SERDES)
...@@ -673,8 +658,6 @@ enum mv88e6xxx_cap { ...@@ -673,8 +658,6 @@ enum mv88e6xxx_cap {
(MV88E6XXX_FLAG_EEE | \ (MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_G2_INT | \ MV88E6XXX_FLAG_G2_INT | \
MV88E6XXX_FLAG_STU | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \ MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP) MV88E6XXX_FLAGS_MULTI_CHIP)
...@@ -686,6 +669,7 @@ struct mv88e6xxx_info { ...@@ -686,6 +669,7 @@ struct mv88e6xxx_info {
const char *name; const char *name;
unsigned int num_databases; unsigned int num_databases;
unsigned int num_ports; unsigned int num_ports;
unsigned int max_vid;
unsigned int port_base_addr; unsigned int port_base_addr;
unsigned int global1_addr; unsigned int global1_addr;
unsigned int age_time_coeff; unsigned int age_time_coeff;
...@@ -713,7 +697,8 @@ struct mv88e6xxx_vtu_entry { ...@@ -713,7 +697,8 @@ struct mv88e6xxx_vtu_entry {
u16 fid; u16 fid;
u8 sid; u8 sid;
bool valid; bool valid;
u8 data[DSA_MAX_PORTS]; u8 member[DSA_MAX_PORTS];
u8 state[DSA_MAX_PORTS];
}; };
struct mv88e6xxx_bus_ops; struct mv88e6xxx_bus_ops;
...@@ -898,6 +883,12 @@ struct mv88e6xxx_ops { ...@@ -898,6 +883,12 @@ struct mv88e6xxx_ops {
/* Can be either in g1 or g2, so don't use a prefix */ /* Can be either in g1 or g2, so don't use a prefix */
int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip); int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip);
/* VLAN Translation Unit operations */
int (*vtu_getnext)(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
int (*vtu_loadpurge)(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
}; };
struct mv88e6xxx_irq_ops { struct mv88e6xxx_irq_ops {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment