Merge branch 'dsa-next'
authorDavid S. Miller <davem@davemloft.net>
Sat, 9 May 2015 20:05:54 +0000 (16:05 -0400)
committerDavid S. Miller <davem@davemloft.net>
Sat, 9 May 2015 20:05:54 +0000 (16:05 -0400)
Andrew Lunn says:

====================
More Marvell DSA refactring and fixup

This patch setup continues the refactoring and cleanup of the Marvell
DSA drivers.

Patch #1 Centralizes the duplicated parts of port setup and global
setup into the shared mv88e6xxx.

Patch #2 Centralizes looping over the ports setting them up

Patch #3 Uses mnemonics for the remaining register access in the
drivers.

Patch #4 The 6172 is actually a member of the 6352 family. This moves
the probe code into the correct driver.

Patch #5 Adds more members of the 6171 family to the 6171 driver. The
new devices are untested.

Patch #6 The 6185 is a member of the 6131 family. Add it to the probe
code of the 6131 driver.

Patch #7 and Patch #8 Simply the mutex's in mv88e6xxx.c. The SMI bus
is the bottleneck, not the granularity of the mutex's so simply the
code down to a single mutex.

Patch #8 Fixes a false positive lockdep splat, due to nested uses of
MDIO busses.

Patch #9 Fixes another false positive lockdep splat with the transmit
queue because of stacked Ethernet devices.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/Kconfig
drivers/net/dsa/mv88e6123_61_65.c
drivers/net/dsa/mv88e6131.c
drivers/net/dsa/mv88e6171.c
drivers/net/dsa/mv88e6352.c
drivers/net/dsa/mv88e6xxx.c
drivers/net/dsa/mv88e6xxx.h
net/dsa/slave.c

index 18550c7ebe6f1beb225ba9c56717d14aacf45896..7ad0a4d8e475f519b0f1a6618091c3c93cb60427 100644 (file)
@@ -37,22 +37,22 @@ config NET_DSA_MV88E6123_61_65
          ethernet switch chips.
 
 config NET_DSA_MV88E6171
-       tristate "Marvell 88E6171/6172 ethernet switch chip support"
+       tristate "Marvell 88E6171/6175/6350/6351 ethernet switch chip support"
        depends on NET_DSA
        select NET_DSA_MV88E6XXX
        select NET_DSA_TAG_EDSA
        ---help---
-         This enables support for the Marvell 88E6171/6172 ethernet switch
-         chips.
+         This enables support for the Marvell 88E6171/6175/6350/6351
+         ethernet switches chips.
 
 config NET_DSA_MV88E6352
-       tristate "Marvell 88E6176/88E6352 ethernet switch chip support"
+       tristate "Marvell 88E6172/88E6176/88E6352 ethernet switch chip support"
        depends on NET_DSA
        select NET_DSA_MV88E6XXX
        select NET_DSA_TAG_EDSA
        ---help---
-         This enables support for the Marvell 88E6176 and 88E6352 ethernet
-         switch chips.
+         This enables support for the Marvell 88E6172, 88E6176 and 88E6352
+         ethernet switch chips.
 
 config NET_DSA_BCM_SF2
        tristate "Broadcom Starfighter 2 Ethernet switch support"
index b4af6d5aff7cc970773f55c3f9a8fedbe3c06f1f..71a29a7ce538d70193c2813bfd10dc4947237f24 100644 (file)
@@ -54,192 +54,40 @@ static char *mv88e6123_61_65_probe(struct device *host_dev, int sw_addr)
 
 static int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
 {
+       u32 upstream_port = dsa_upstream_port(ds);
        int ret;
-       int i;
+       u32 reg;
+
+       ret = mv88e6xxx_setup_global(ds);
+       if (ret)
+               return ret;
 
        /* Disable the PHY polling unit (since there won't be any
         * external PHYs to poll), don't discard packets with
         * excessive collisions, and mask all interrupt sources.
         */
-       REG_WRITE(REG_GLOBAL, 0x04, 0x0000);
-
-       /* Set the default address aging time to 5 minutes, and
-        * enable address learn messages to be sent to all message
-        * ports.
-        */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
-
-       /* Configure the priority mapping registers. */
-       ret = mv88e6xxx_config_prio(ds);
-       if (ret < 0)
-               return ret;
+       REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, 0x0000);
 
        /* Configure the upstream port, and configure the upstream
         * port as the port to which ingress and egress monitor frames
         * are to be sent.
         */
-       REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110));
+       reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
+               upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
+               upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
+       REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
 
        /* Disable remote management for now, and set the switch's
         * DSA device number.
         */
-       REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f);
-
-       /* Send all frames with destination addresses matching
-        * 01:80:c2:00:00:2x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x02, 0xffff);
-
-       /* Send all frames with destination addresses matching
-        * 01:80:c2:00:00:0x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
-
-       /* Disable the loopback filter, disable flow control
-        * messages, disable flood broadcast override, disable
-        * removing of provider tags, disable ATU age violation
-        * interrupts, disable tag flow control, force flow
-        * control priority to the highest, and send all special
-        * multicast frames to the CPU at the highest priority.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
-
-       /* Program the DSA routing table. */
-       for (i = 0; i < 32; i++) {
-               int nexthop;
-
-               nexthop = 0x1f;
-               if (i != ds->index && i < ds->dst->pd->nr_chips)
-                       nexthop = ds->pd->rtable[i] & 0x1f;
-
-               REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
-       }
-
-       /* Clear all trunk masks. */
-       for (i = 0; i < 8; i++)
-               REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff);
-
-       /* Clear all trunk mappings. */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
-
-       /* Disable ingress rate limiting by resetting all ingress
-        * rate limit registers to their initial state.
-        */
-       for (i = 0; i < 6; i++)
-               REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8));
-
-       /* Initialise cross-chip port VLAN table to reset defaults. */
-       REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000);
-
-       /* Clear the priority override table. */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8));
-
-       /* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */
+       REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f);
 
        return 0;
 }
 
-static int mv88e6123_61_65_setup_port(struct dsa_switch *ds, int p)
-{
-       int addr = REG_PORT(p);
-       u16 val;
-
-       /* MAC Forcing register: don't force link, speed, duplex
-        * or flow control state to any particular values on physical
-        * ports, but force the CPU port and all DSA ports to 1000 Mb/s
-        * full duplex.
-        */
-       if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
-               REG_WRITE(addr, 0x01, 0x003e);
-       else
-               REG_WRITE(addr, 0x01, 0x0003);
-
-       /* Do not limit the period of time that this port can be
-        * paused for by the remote end or the period of time that
-        * this port can pause the remote end.
-        */
-       REG_WRITE(addr, 0x02, 0x0000);
-
-       /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
-        * disable Header mode, enable IGMP/MLD snooping, disable VLAN
-        * tunneling, determine priority by looking at 802.1p and IP
-        * priority fields (IP prio has precedence), and set STP state
-        * to Forwarding.
-        *
-        * If this is the CPU link, use DSA or EDSA tagging depending
-        * on which tagging mode was configured.
-        *
-        * If this is a link to another switch, use DSA tagging mode.
-        *
-        * If this is the upstream port for this switch, enable
-        * forwarding of unknown unicasts and multicasts.
-        */
-       val = 0x0433;
-       if (dsa_is_cpu_port(ds, p)) {
-               if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
-                       val |= 0x3300;
-               else
-                       val |= 0x0100;
-       }
-       if (ds->dsa_port_mask & (1 << p))
-               val |= 0x0100;
-       if (p == dsa_upstream_port(ds))
-               val |= 0x000c;
-       REG_WRITE(addr, 0x04, val);
-
-       /* 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
-        * on this port, do a destination address lookup on all
-        * received packets as usual, disable ARP mirroring and don't
-        * send a copy of all transmitted/received frames on this port
-        * to the CPU.
-        */
-       REG_WRITE(addr, 0x08, 0x2080);
-
-       /* Egress rate control: disable egress rate control. */
-       REG_WRITE(addr, 0x09, 0x0001);
-
-       /* Egress rate control 2: disable egress rate control. */
-       REG_WRITE(addr, 0x0a, 0x0000);
-
-       /* Port Association Vector: when learning source addresses
-        * of packets, add the address to the address database using
-        * a port bitmap that has only the bit for this port set and
-        * the other bits clear.
-        */
-       REG_WRITE(addr, 0x0b, 1 << p);
-
-       /* Port ATU control: disable limiting the number of address
-        * database entries that this port is allowed to use.
-        */
-       REG_WRITE(addr, 0x0c, 0x0000);
-
-       /* Priority Override: disable DA, SA and VTU priority override. */
-       REG_WRITE(addr, 0x0d, 0x0000);
-
-       /* Port Ethertype: use the Ethertype DSA Ethertype value. */
-       REG_WRITE(addr, 0x0f, ETH_P_EDSA);
-
-       /* Tag Remap: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x18, 0x3210);
-
-       /* Tag Remap 2: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x19, 0x7654);
-
-       return mv88e6xxx_setup_port_common(ds, p);
-}
-
 static int mv88e6123_61_65_setup(struct dsa_switch *ds)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-       int i;
        int ret;
 
        ret = mv88e6xxx_setup_common(ds);
@@ -262,19 +110,11 @@ static int mv88e6123_61_65_setup(struct dsa_switch *ds)
        if (ret < 0)
                return ret;
 
-       /* @@@ initialise vtu and atu */
-
        ret = mv88e6123_61_65_setup_global(ds);
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < ps->num_ports; i++) {
-               ret = mv88e6123_61_65_setup_port(ds, i);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
+       return mv88e6xxx_setup_ports(ds);
 }
 
 struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
index e54824fa0d959f919586c7ec07cbb678a40a031a..32f4a08e9bc99dce2fa59af8cae8b34475bb24d6 100644 (file)
@@ -37,6 +37,8 @@ static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
                        return "Marvell 88E6131 (B2)";
                if (ret_masked == PORT_SWITCH_ID_6131)
                        return "Marvell 88E6131";
+               if (ret_masked == PORT_SWITCH_ID_6185)
+                       return "Marvell 88E6185";
        }
 
        return NULL;
@@ -44,186 +46,62 @@ static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
 
 static int mv88e6131_setup_global(struct dsa_switch *ds)
 {
+       u32 upstream_port = dsa_upstream_port(ds);
        int ret;
-       int i;
+       u32 reg;
+
+       ret = mv88e6xxx_setup_global(ds);
+       if (ret)
+               return ret;
 
        /* Enable the PHY polling unit, don't discard packets with
         * excessive collisions, use a weighted fair queueing scheme
         * to arbitrate between packet queues, set the maximum frame
         * size to 1632, and mask all interrupt sources.
         */
-       REG_WRITE(REG_GLOBAL, 0x04, 0x4400);
-
-       /* Set the default address aging time to 5 minutes, and
-        * enable address learn messages to be sent to all message
-        * ports.
-        */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
-
-       /* Configure the priority mapping registers. */
-       ret = mv88e6xxx_config_prio(ds);
-       if (ret < 0)
-               return ret;
+       REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
+                 GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_MAX_FRAME_1632);
 
        /* Set the VLAN ethertype to 0x8100. */
-       REG_WRITE(REG_GLOBAL, 0x19, 0x8100);
+       REG_WRITE(REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100);
 
        /* Disable ARP mirroring, and configure the upstream port as
         * the port to which ingress and egress monitor frames are to
         * be sent.
         */
-       REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1100) | 0x00f0);
+       reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
+               upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
+               GLOBAL_MONITOR_CONTROL_ARP_DISABLED;
+       REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
 
        /* Disable cascade port functionality unless this device
         * is used in a cascade configuration, and set the switch's
         * DSA device number.
         */
        if (ds->dst->pd->nr_chips > 1)
-               REG_WRITE(REG_GLOBAL, 0x1c, 0xf000 | (ds->index & 0x1f));
+               REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2,
+                         GLOBAL_CONTROL_2_MULTIPLE_CASCADE |
+                         (ds->index & 0x1f));
        else
-               REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f));
-
-       /* Send all frames with destination addresses matching
-        * 01:80:c2:00:00:0x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
-
-       /* Ignore removed tag data on doubly tagged packets, disable
-        * flow control messages, force flow control priority to the
-        * highest, and send all special multicast frames to the CPU
-        * port at the highest priority.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
-
-       /* Program the DSA routing table. */
-       for (i = 0; i < 32; i++) {
-               int nexthop;
-
-               nexthop = 0x1f;
-               if (ds->pd->rtable &&
-                   i != ds->index && i < ds->dst->pd->nr_chips)
-                       nexthop = ds->pd->rtable[i] & 0x1f;
-
-               REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
-       }
-
-       /* Clear all trunk masks. */
-       for (i = 0; i < 8; i++)
-               REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7ff);
-
-       /* Clear all trunk mappings. */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
+               REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2,
+                         GLOBAL_CONTROL_2_NO_CASCADE |
+                         (ds->index & 0x1f));
 
        /* Force the priority of IGMP/MLD snoop frames and ARP frames
         * to the highest setting.
         */
-       REG_WRITE(REG_GLOBAL2, 0x0f, 0x00ff);
+       REG_WRITE(REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE,
+                 GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP |
+                 7 << GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT |
+                 GLOBAL2_PRIO_OVERRIDE_FORCE_ARP |
+                 7 << GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT);
 
        return 0;
 }
 
-static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
-{
-       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-       int addr = REG_PORT(p);
-       u16 val;
-
-       /* MAC Forcing register: don't force link, speed, duplex
-        * or flow control state to any particular values on physical
-        * ports, but force the CPU port and all DSA ports to 1000 Mb/s
-        * (100 Mb/s on 6085) full duplex.
-        */
-       if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
-               if (ps->id == PORT_SWITCH_ID_6085)
-                       REG_WRITE(addr, 0x01, 0x003d); /* 100 Mb/s */
-               else
-                       REG_WRITE(addr, 0x01, 0x003e); /* 1000 Mb/s */
-       else
-               REG_WRITE(addr, 0x01, 0x0003);
-
-       /* Port Control: disable Core Tag, disable Drop-on-Lock,
-        * transmit frames unmodified, disable Header mode,
-        * enable IGMP/MLD snoop, disable DoubleTag, disable VLAN
-        * tunneling, determine priority by looking at 802.1p and
-        * IP priority fields (IP prio has precedence), and set STP
-        * state to Forwarding.
-        *
-        * If this is the upstream port for this switch, enable
-        * forwarding of unknown unicasts, and enable DSA tagging
-        * mode.
-        *
-        * If this is the link to another switch, use DSA tagging
-        * mode, but do not enable forwarding of unknown unicasts.
-        */
-       val = 0x0433;
-       if (p == dsa_upstream_port(ds)) {
-               val |= 0x0104;
-               /* On 6085, unknown multicast forward is controlled
-                * here rather than in Port Control 2 register.
-                */
-               if (ps->id == PORT_SWITCH_ID_6085)
-                       val |= 0x0008;
-       }
-       if (ds->dsa_port_mask & (1 << p))
-               val |= 0x0100;
-       REG_WRITE(addr, 0x04, val);
-
-       /* Port Control 2: don't force a good FCS, don't use
-        * VLAN-based, source address-based or destination
-        * address-based priority overrides, don't let the switch
-        * add or strip 802.1q tags, don't discard tagged or
-        * untagged frames on this port, do a destination address
-        * lookup on received packets as usual, don't send a copy
-        * of all transmitted/received frames on this port to the
-        * CPU, and configure the upstream port number.
-        *
-        * If this is the upstream port for this switch, enable
-        * forwarding of unknown multicast addresses.
-        */
-       if (ps->id == PORT_SWITCH_ID_6085)
-               /* on 6085, bits 3:0 are reserved, bit 6 control ARP
-                * mirroring, and multicast forward is handled in
-                * Port Control register.
-                */
-               REG_WRITE(addr, 0x08, 0x0080);
-       else {
-               val = 0x0080 | dsa_upstream_port(ds);
-               if (p == dsa_upstream_port(ds))
-                       val |= 0x0040;
-               REG_WRITE(addr, 0x08, val);
-       }
-
-       /* Rate Control: disable ingress rate limiting. */
-       REG_WRITE(addr, 0x09, 0x0000);
-
-       /* Rate Control 2: disable egress rate limiting. */
-       REG_WRITE(addr, 0x0a, 0x0000);
-
-       /* Port Association Vector: when learning source addresses
-        * of packets, add the address to the address database using
-        * a port bitmap that has only the bit for this port set and
-        * the other bits clear.
-        */
-       REG_WRITE(addr, 0x0b, 1 << p);
-
-       /* Tag Remap: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x18, 0x3210);
-
-       /* Tag Remap 2: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x19, 0x7654);
-
-       return mv88e6xxx_setup_port_common(ds, p);
-}
-
 static int mv88e6131_setup(struct dsa_switch *ds)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-       int i;
        int ret;
 
        ret = mv88e6xxx_setup_common(ds);
@@ -234,6 +112,7 @@ static int mv88e6131_setup(struct dsa_switch *ds)
 
        switch (ps->id) {
        case PORT_SWITCH_ID_6085:
+       case PORT_SWITCH_ID_6185:
                ps->num_ports = 10;
                break;
        case PORT_SWITCH_ID_6095:
@@ -251,19 +130,11 @@ static int mv88e6131_setup(struct dsa_switch *ds)
        if (ret < 0)
                return ret;
 
-       /* @@@ initialise vtu and atu */
-
        ret = mv88e6131_setup_global(ds);
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < ps->num_ports; i++) {
-               ret = mv88e6131_setup_port(ds, i);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
+       return mv88e6xxx_setup_ports(ds);
 }
 
 static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port)
index 9104efea0e3e8289803c53348e79eded3d80e50c..1c7808495a9dd8198936e6db4ce23fd7f2d29ed3 100644 (file)
@@ -1,4 +1,4 @@
-/* net/dsa/mv88e6171.c - Marvell 88e6171/8826172 switch chip support
+/* net/dsa/mv88e6171.c - Marvell 88e6171 switch chip support
  * Copyright (c) 2008-2009 Marvell Semiconductor
  * Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
  *
@@ -29,8 +29,12 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
        if (ret >= 0) {
                if ((ret & 0xfff0) == PORT_SWITCH_ID_6171)
                        return "Marvell 88E6171";
-               if ((ret & 0xfff0) == PORT_SWITCH_ID_6172)
-                       return "Marvell 88E6172";
+               if ((ret & 0xfff0) == PORT_SWITCH_ID_6175)
+                       return "Marvell 88E6175";
+               if ((ret & 0xfff0) == PORT_SWITCH_ID_6350)
+                       return "Marvell 88E6350";
+               if ((ret & 0xfff0) == PORT_SWITCH_ID_6351)
+                       return "Marvell 88E6351";
        }
 
        return NULL;
@@ -38,196 +42,41 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
 
 static int mv88e6171_setup_global(struct dsa_switch *ds)
 {
-       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       u32 upstream_port = dsa_upstream_port(ds);
        int ret;
-       int i;
+       u32 reg;
+
+       ret = mv88e6xxx_setup_global(ds);
+       if (ret)
+               return ret;
 
        /* Discard packets with excessive collisions, mask all
         * interrupt sources, enable PPU.
         */
-       REG_WRITE(REG_GLOBAL, 0x04, 0x6000);
-
-       /* Set the default address aging time to 5 minutes, and
-        * enable address learn messages to be sent to all message
-        * ports.
-        */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
-
-       /* Configure the priority mapping registers. */
-       ret = mv88e6xxx_config_prio(ds);
-       if (ret < 0)
-               return ret;
+       REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
+                 GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS);
 
        /* Configure the upstream port, and configure the upstream
         * port as the port to which ingress and egress monitor frames
         * are to be sent.
         */
-       if (REG_READ(REG_PORT(0), 0x03) == 0x1710)
-               REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1111));
-       else
-               REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110));
+       reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
+               upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
+               upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT |
+               upstream_port << GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT;
+       REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
 
        /* Disable remote management for now, and set the switch's
         * DSA device number.
         */
-       REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f);
-
-       /* Send all frames with destination addresses matching
-        * 01:80:c2:00:00:2x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x02, 0xffff);
-
-       /* Send all frames with destination addresses matching
-        * 01:80:c2:00:00:0x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
-
-       /* Disable the loopback filter, disable flow control
-        * messages, disable flood broadcast override, disable
-        * removing of provider tags, disable ATU age violation
-        * interrupts, disable tag flow control, force flow
-        * control priority to the highest, and send all special
-        * multicast frames to the CPU at the highest priority.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
-
-       /* Program the DSA routing table. */
-       for (i = 0; i < 32; i++) {
-               int nexthop;
-
-               nexthop = 0x1f;
-               if (i != ds->index && i < ds->dst->pd->nr_chips)
-                       nexthop = ds->pd->rtable[i] & 0x1f;
-
-               REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
-       }
-
-       /* Clear all trunk masks. */
-       for (i = 0; i < ps->num_ports; i++)
-               REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff);
-
-       /* Clear all trunk mappings. */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
-
-       /* Disable ingress rate limiting by resetting all ingress
-        * rate limit registers to their initial state.
-        */
-       for (i = 0; i < 6; i++)
-               REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8));
-
-       /* Initialise cross-chip port VLAN table to reset defaults. */
-       REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000);
-
-       /* Clear the priority override table. */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8));
-
-       /* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */
+       REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f);
 
        return 0;
 }
 
-static int mv88e6171_setup_port(struct dsa_switch *ds, int p)
-{
-       int addr = REG_PORT(p);
-       u16 val;
-
-       /* MAC Forcing register: don't force link, speed, duplex
-        * or flow control state to any particular values on physical
-        * ports, but force the CPU port and all DSA ports to 1000 Mb/s
-        * full duplex.
-        */
-       val = REG_READ(addr, 0x01);
-       if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
-               REG_WRITE(addr, 0x01, val | 0x003e);
-       else
-               REG_WRITE(addr, 0x01, val | 0x0003);
-
-       /* Do not limit the period of time that this port can be
-        * paused for by the remote end or the period of time that
-        * this port can pause the remote end.
-        */
-       REG_WRITE(addr, 0x02, 0x0000);
-
-       /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
-        * disable Header mode, enable IGMP/MLD snooping, disable VLAN
-        * tunneling, determine priority by looking at 802.1p and IP
-        * priority fields (IP prio has precedence), and set STP state
-        * to Forwarding.
-        *
-        * If this is the CPU link, use DSA or EDSA tagging depending
-        * on which tagging mode was configured.
-        *
-        * If this is a link to another switch, use DSA tagging mode.
-        *
-        * If this is the upstream port for this switch, enable
-        * forwarding of unknown unicasts and multicasts.
-        */
-       val = 0x0433;
-       if (dsa_is_cpu_port(ds, p)) {
-               if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
-                       val |= 0x3300;
-               else
-                       val |= 0x0100;
-       }
-       if (ds->dsa_port_mask & (1 << p))
-               val |= 0x0100;
-       if (p == dsa_upstream_port(ds))
-               val |= 0x000c;
-       REG_WRITE(addr, 0x04, val);
-
-       /* 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
-        * on this port, do a destination address lookup on all
-        * received packets as usual, disable ARP mirroring and don't
-        * send a copy of all transmitted/received frames on this port
-        * to the CPU.
-        */
-       REG_WRITE(addr, 0x08, 0x2080);
-
-       /* Egress rate control: disable egress rate control. */
-       REG_WRITE(addr, 0x09, 0x0001);
-
-       /* Egress rate control 2: disable egress rate control. */
-       REG_WRITE(addr, 0x0a, 0x0000);
-
-       /* Port Association Vector: when learning source addresses
-        * of packets, add the address to the address database using
-        * a port bitmap that has only the bit for this port set and
-        * the other bits clear.
-        */
-       REG_WRITE(addr, 0x0b, 1 << p);
-
-       /* Port ATU control: disable limiting the number of address
-        * database entries that this port is allowed to use.
-        */
-       REG_WRITE(addr, 0x0c, 0x0000);
-
-       /* Priority Override: disable DA, SA and VTU priority override. */
-       REG_WRITE(addr, 0x0d, 0x0000);
-
-       /* Port Ethertype: use the Ethertype DSA Ethertype value. */
-       REG_WRITE(addr, 0x0f, ETH_P_EDSA);
-
-       /* Tag Remap: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x18, 0x3210);
-
-       /* Tag Remap 2: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x19, 0x7654);
-
-       return mv88e6xxx_setup_port_common(ds, p);
-}
-
 static int mv88e6171_setup(struct dsa_switch *ds)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-       int i;
        int ret;
 
        ret = mv88e6xxx_setup_common(ds);
@@ -240,44 +89,11 @@ static int mv88e6171_setup(struct dsa_switch *ds)
        if (ret < 0)
                return ret;
 
-       /* @@@ initialise vtu and atu */
-
        ret = mv88e6171_setup_global(ds);
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < ps->num_ports; i++) {
-               if (!(dsa_is_cpu_port(ds, i) || ds->phys_port_mask & (1 << i)))
-                       continue;
-
-               ret = mv88e6171_setup_port(ds, i);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-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 == PORT_SWITCH_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 == PORT_SWITCH_ID_6172)
-               return mv88e6xxx_set_eee(ds, port, phydev, e);
-
-       return -EOPNOTSUPP;
+       return mv88e6xxx_setup_ports(ds);
 }
 
 struct dsa_switch_driver mv88e6171_switch_driver = {
@@ -292,8 +108,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
        .get_strings            = mv88e6xxx_get_strings,
        .get_ethtool_stats      = mv88e6xxx_get_ethtool_stats,
        .get_sset_count         = mv88e6xxx_get_sset_count,
-       .set_eee                = mv88e6171_set_eee,
-       .get_eee                = mv88e6171_get_eee,
 #ifdef CONFIG_NET_DSA_HWMON
        .get_temp               = mv88e6xxx_get_temp,
 #endif
@@ -308,4 +122,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
 };
 
 MODULE_ALIAS("platform:mv88e6171");
-MODULE_ALIAS("platform:mv88e6172");
+MODULE_ALIAS("platform:mv88e6175");
+MODULE_ALIAS("platform:mv88e6350");
+MODULE_ALIAS("platform:mv88e6351");
index 126c11b81e756ec232106de72583904638ccb024..632815c10a401f7bd873e077a262528b73ceed7d 100644 (file)
@@ -32,6 +32,8 @@ static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
 
        ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
        if (ret >= 0) {
+               if ((ret & 0xfff0) == PORT_SWITCH_ID_6172)
+                       return "Marvell 88E6172";
                if ((ret & 0xfff0) == PORT_SWITCH_ID_6176)
                        return "Marvell 88E6176";
                if (ret == PORT_SWITCH_ID_6352_A0)
@@ -47,187 +49,37 @@ static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
 
 static int mv88e6352_setup_global(struct dsa_switch *ds)
 {
-       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       u32 upstream_port = dsa_upstream_port(ds);
        int ret;
-       int i;
+       u32 reg;
+
+       ret = mv88e6xxx_setup_global(ds);
+       if (ret)
+               return ret;
 
        /* Discard packets with excessive collisions,
         * mask all interrupt sources, enable PPU (bit 14, undocumented).
         */
-       REG_WRITE(REG_GLOBAL, 0x04, 0x6000);
-
-       /* Set the default address aging time to 5 minutes, and
-        * enable address learn messages to be sent to all message
-        * ports.
-        */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0x0148);
-
-       /* Configure the priority mapping registers. */
-       ret = mv88e6xxx_config_prio(ds);
-       if (ret < 0)
-               return ret;
+       REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
+                 GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS);
 
        /* Configure the upstream port, and configure the upstream
         * port as the port to which ingress and egress monitor frames
         * are to be sent.
         */
-       REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110));
+       reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
+               upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
+               upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
+       REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
 
        /* Disable remote management for now, and set the switch's
         * DSA device number.
         */
        REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f);
 
-       /* Send all frames with destination addresses matching
-        * 01:80:c2:00:00:2x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x02, 0xffff);
-
-       /* Send all frames with destination addresses matching
-        * 01:80:c2:00:00:0x to the CPU port.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x03, 0xffff);
-
-       /* Disable the loopback filter, disable flow control
-        * messages, disable flood broadcast override, disable
-        * removing of provider tags, disable ATU age violation
-        * interrupts, disable tag flow control, force flow
-        * control priority to the highest, and send all special
-        * multicast frames to the CPU at the highest priority.
-        */
-       REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
-
-       /* Program the DSA routing table. */
-       for (i = 0; i < 32; i++) {
-               int nexthop = 0x1f;
-
-               if (i != ds->index && i < ds->dst->pd->nr_chips)
-                       nexthop = ds->pd->rtable[i] & 0x1f;
-
-               REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
-       }
-
-       /* Clear all trunk masks. */
-       for (i = 0; i < 8; i++)
-               REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7f);
-
-       /* Clear all trunk mappings. */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x08, 0x8000 | (i << 11));
-
-       /* Disable ingress rate limiting by resetting all ingress
-        * rate limit registers to their initial state.
-        */
-       for (i = 0; i < ps->num_ports; i++)
-               REG_WRITE(REG_GLOBAL2, 0x09, 0x9000 | (i << 8));
-
-       /* Initialise cross-chip port VLAN table to reset defaults. */
-       REG_WRITE(REG_GLOBAL2, 0x0b, 0x9000);
-
-       /* Clear the priority override table. */
-       for (i = 0; i < 16; i++)
-               REG_WRITE(REG_GLOBAL2, 0x0f, 0x8000 | (i << 8));
-
-       /* @@@ initialise AVB (22/23) watchdog (27) sdet (29) registers */
-
        return 0;
 }
 
-static int mv88e6352_setup_port(struct dsa_switch *ds, int p)
-{
-       int addr = REG_PORT(p);
-       u16 val;
-
-       /* MAC Forcing register: don't force link, speed, duplex
-        * or flow control state to any particular values on physical
-        * ports, but force the CPU port and all DSA ports to 1000 Mb/s
-        * full duplex.
-        */
-       if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
-               REG_WRITE(addr, 0x01, 0x003e);
-       else
-               REG_WRITE(addr, 0x01, 0x0003);
-
-       /* Do not limit the period of time that this port can be
-        * paused for by the remote end or the period of time that
-        * this port can pause the remote end.
-        */
-       REG_WRITE(addr, 0x02, 0x0000);
-
-       /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
-        * disable Header mode, enable IGMP/MLD snooping, disable VLAN
-        * tunneling, determine priority by looking at 802.1p and IP
-        * priority fields (IP prio has precedence), and set STP state
-        * to Forwarding.
-        *
-        * If this is the CPU link, use DSA or EDSA tagging depending
-        * on which tagging mode was configured.
-        *
-        * If this is a link to another switch, use DSA tagging mode.
-        *
-        * If this is the upstream port for this switch, enable
-        * forwarding of unknown unicasts and multicasts.
-        */
-       val = 0x0433;
-       if (dsa_is_cpu_port(ds, p)) {
-               if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
-                       val |= 0x3300;
-               else
-                       val |= 0x0100;
-       }
-       if (ds->dsa_port_mask & (1 << p))
-               val |= 0x0100;
-       if (p == dsa_upstream_port(ds))
-               val |= 0x000c;
-       REG_WRITE(addr, 0x04, val);
-
-       /* 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
-        * on this port, do a destination address lookup on all
-        * received packets as usual, disable ARP mirroring and don't
-        * send a copy of all transmitted/received frames on this port
-        * to the CPU.
-        */
-       REG_WRITE(addr, 0x08, 0x2080);
-
-       /* Egress rate control: disable egress rate control. */
-       REG_WRITE(addr, 0x09, 0x0001);
-
-       /* Egress rate control 2: disable egress rate control. */
-       REG_WRITE(addr, 0x0a, 0x0000);
-
-       /* Port Association Vector: when learning source addresses
-        * of packets, add the address to the address database using
-        * a port bitmap that has only the bit for this port set and
-        * the other bits clear.
-        */
-       REG_WRITE(addr, 0x0b, 1 << p);
-
-       /* Port ATU control: disable limiting the number of address
-        * database entries that this port is allowed to use.
-        */
-       REG_WRITE(addr, 0x0c, 0x0000);
-
-       /* Priority Override: disable DA, SA and VTU priority override. */
-       REG_WRITE(addr, 0x0d, 0x0000);
-
-       /* Port Ethertype: use the Ethertype DSA Ethertype value. */
-       REG_WRITE(addr, 0x0f, ETH_P_EDSA);
-
-       /* Tag Remap: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x18, 0x3210);
-
-       /* Tag Remap 2: use an identity 802.1p prio -> switch prio
-        * mapping.
-        */
-       REG_WRITE(addr, 0x19, 0x7654);
-
-       return mv88e6xxx_setup_port_common(ds, p);
-}
-
 #ifdef CONFIG_NET_DSA_HWMON
 
 static int mv88e6352_get_temp(struct dsa_switch *ds, int *temp)
@@ -292,7 +144,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
        int ret;
-       int i;
 
        ret = mv88e6xxx_setup_common(ds);
        if (ret < 0)
@@ -306,19 +157,11 @@ static int mv88e6352_setup(struct dsa_switch *ds)
        if (ret < 0)
                return ret;
 
-       /* @@@ initialise vtu and atu */
-
        ret = mv88e6352_setup_global(ds);
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < ps->num_ports; i++) {
-               ret = mv88e6352_setup_port(ds, i);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
+       return mv88e6xxx_setup_ports(ds);
 }
 
 static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
@@ -552,3 +395,4 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
 };
 
 MODULE_ALIAS("platform:mv88e6352");
+MODULE_ALIAS("platform:mv88e6172");
index af639ab4c55b64fd886df0413d090afd2fe618ba..56ecbe49eb86c0dfcc390b68b5be922dc0a85b8e 100644 (file)
 #include <net/dsa.h>
 #include "mv88e6xxx.h"
 
+/* MDIO bus access can be nested in the case of PHYs connected to the
+ * internal MDIO bus of the switch, which is accessed via MDIO bus of
+ * the Ethernet interface. Avoid lockdep false positives by using
+ * mutex_lock_nested().
+ */
+static int mv88e6xxx_mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
+{
+       int ret;
+
+       mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING);
+       ret = bus->read(bus, addr, regnum);
+       mutex_unlock(&bus->mdio_lock);
+
+       return ret;
+}
+
+static int mv88e6xxx_mdiobus_write(struct mii_bus *bus, int addr, u32 regnum,
+                                  u16 val)
+{
+       int ret;
+
+       mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING);
+       ret = bus->write(bus, addr, regnum, val);
+       mutex_unlock(&bus->mdio_lock);
+
+       return ret;
+}
+
 /* If the switch's ADDR[4:0] strap pins are strapped to zero, it will
  * use all 32 SMI bus addresses on its SMI bus, and all switch registers
  * will be directly accessible on some {device address,register address}
@@ -33,7 +61,7 @@ static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
        int i;
 
        for (i = 0; i < 16; i++) {
-               ret = mdiobus_read(bus, sw_addr, SMI_CMD);
+               ret = mv88e6xxx_mdiobus_read(bus, sw_addr, SMI_CMD);
                if (ret < 0)
                        return ret;
 
@@ -49,7 +77,7 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
        int ret;
 
        if (sw_addr == 0)
-               return mdiobus_read(bus, addr, reg);
+               return mv88e6xxx_mdiobus_read(bus, addr, reg);
 
        /* Wait for the bus to become free. */
        ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
@@ -57,8 +85,8 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
                return ret;
 
        /* Transmit the read command. */
-       ret = mdiobus_write(bus, sw_addr, SMI_CMD,
-                           SMI_CMD_OP_22_READ | (addr << 5) | reg);
+       ret = mv88e6xxx_mdiobus_write(bus, sw_addr, SMI_CMD,
+                                     SMI_CMD_OP_22_READ | (addr << 5) | reg);
        if (ret < 0)
                return ret;
 
@@ -68,7 +96,7 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
                return ret;
 
        /* Read the data. */
-       ret = mdiobus_read(bus, sw_addr, SMI_DATA);
+       ret = mv88e6xxx_mdiobus_read(bus, sw_addr, SMI_DATA);
        if (ret < 0)
                return ret;
 
@@ -112,7 +140,7 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
        int ret;
 
        if (sw_addr == 0)
-               return mdiobus_write(bus, addr, reg, val);
+               return mv88e6xxx_mdiobus_write(bus, addr, reg, val);
 
        /* Wait for the bus to become free. */
        ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
@@ -120,13 +148,13 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
                return ret;
 
        /* Transmit the data to write. */
-       ret = mdiobus_write(bus, sw_addr, SMI_DATA, val);
+       ret = mv88e6xxx_mdiobus_write(bus, sw_addr, SMI_DATA, val);
        if (ret < 0)
                return ret;
 
        /* Transmit the write command. */
-       ret = mdiobus_write(bus, sw_addr, SMI_CMD,
-                           SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
+       ret = mv88e6xxx_mdiobus_write(bus, sw_addr, SMI_CMD,
+                                     SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
        if (ret < 0)
                return ret;
 
@@ -165,24 +193,6 @@ int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
        return ret;
 }
 
-int mv88e6xxx_config_prio(struct dsa_switch *ds)
-{
-       /* Configure the IP ToS mapping registers. */
-       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
-       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
-       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
-       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
-       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
-       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
-       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
-       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
-
-       /* Configure the IEEE 802.1p priority mapping register. */
-       REG_WRITE(REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
-
-       return 0;
-}
-
 int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
 {
        REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 8) | addr[1]);
@@ -217,20 +227,20 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
        return 0;
 }
 
-/* Must be called with phy mutex held */
+/* Must be called with SMI mutex held */
 static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
 {
        if (addr >= 0)
-               return mv88e6xxx_reg_read(ds, addr, regnum);
+               return _mv88e6xxx_reg_read(ds, addr, regnum);
        return 0xffff;
 }
 
-/* Must be called with phy mutex held */
+/* Must be called with SMI mutex held */
 static int _mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum,
                                u16 val)
 {
        if (addr >= 0)
-               return mv88e6xxx_reg_write(ds, addr, regnum, val);
+               return _mv88e6xxx_reg_write(ds, addr, regnum, val);
        return 0;
 }
 
@@ -434,26 +444,113 @@ void mv88e6xxx_poll_link(struct dsa_switch *ds)
        }
 }
 
+static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+       switch (ps->id) {
+       case PORT_SWITCH_ID_6031:
+       case PORT_SWITCH_ID_6061:
+       case PORT_SWITCH_ID_6035:
+       case PORT_SWITCH_ID_6065:
+               return true;
+       }
+       return false;
+}
+
+static bool mv88e6xxx_6095_family(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+       switch (ps->id) {
+       case PORT_SWITCH_ID_6092:
+       case PORT_SWITCH_ID_6095:
+               return true;
+       }
+       return false;
+}
+
+static bool mv88e6xxx_6097_family(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+       switch (ps->id) {
+       case PORT_SWITCH_ID_6046:
+       case PORT_SWITCH_ID_6085:
+       case PORT_SWITCH_ID_6096:
+       case PORT_SWITCH_ID_6097:
+               return true;
+       }
+       return false;
+}
+
+static bool mv88e6xxx_6165_family(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+       switch (ps->id) {
+       case PORT_SWITCH_ID_6123:
+       case PORT_SWITCH_ID_6161:
+       case PORT_SWITCH_ID_6165:
+               return true;
+       }
+       return false;
+}
+
+static bool mv88e6xxx_6185_family(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+       switch (ps->id) {
+       case PORT_SWITCH_ID_6121:
+       case PORT_SWITCH_ID_6122:
+       case PORT_SWITCH_ID_6152:
+       case PORT_SWITCH_ID_6155:
+       case PORT_SWITCH_ID_6182:
+       case PORT_SWITCH_ID_6185:
+       case PORT_SWITCH_ID_6108:
+       case PORT_SWITCH_ID_6131:
+               return true;
+       }
+       return false;
+}
+
+static bool mv88e6xxx_6351_family(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+       switch (ps->id) {
+       case PORT_SWITCH_ID_6171:
+       case PORT_SWITCH_ID_6175:
+       case PORT_SWITCH_ID_6350:
+       case PORT_SWITCH_ID_6351:
+               return true;
+       }
+       return false;
+}
+
 static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
        switch (ps->id) {
-       case PORT_SWITCH_ID_6352:
        case PORT_SWITCH_ID_6172:
        case PORT_SWITCH_ID_6176:
+       case PORT_SWITCH_ID_6240:
+       case PORT_SWITCH_ID_6352:
                return true;
        }
        return false;
 }
 
-static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
+/* Must be called with SMI mutex held */
+static int _mv88e6xxx_stats_wait(struct dsa_switch *ds)
 {
        int ret;
        int i;
 
        for (i = 0; i < 10; i++) {
-               ret = REG_READ(REG_GLOBAL, GLOBAL_STATS_OP);
+               ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_OP);
                if ((ret & GLOBAL_STATS_OP_BUSY) == 0)
                        return 0;
        }
@@ -461,7 +558,8 @@ static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
        return -ETIMEDOUT;
 }
 
-static int mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
+/* Must be called with SMI mutex held */
+static int _mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
 {
        int ret;
 
@@ -469,42 +567,45 @@ static int mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
                port = (port + 1) << 5;
 
        /* Snapshot the hardware statistics counters for this port. */
-       REG_WRITE(REG_GLOBAL, GLOBAL_STATS_OP,
-                 GLOBAL_STATS_OP_CAPTURE_PORT |
-                 GLOBAL_STATS_OP_HIST_RX_TX | port);
+       ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP,
+                                  GLOBAL_STATS_OP_CAPTURE_PORT |
+                                  GLOBAL_STATS_OP_HIST_RX_TX | port);
+       if (ret < 0)
+               return ret;
 
        /* Wait for the snapshotting to complete. */
-       ret = mv88e6xxx_stats_wait(ds);
+       ret = _mv88e6xxx_stats_wait(ds);
        if (ret < 0)
                return ret;
 
        return 0;
 }
 
-static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
+/* Must be called with SMI mutex held */
+static void _mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
 {
        u32 _val;
        int ret;
 
        *val = 0;
 
-       ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP,
-                                 GLOBAL_STATS_OP_READ_CAPTURED |
-                                 GLOBAL_STATS_OP_HIST_RX_TX | stat);
+       ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP,
+                                  GLOBAL_STATS_OP_READ_CAPTURED |
+                                  GLOBAL_STATS_OP_HIST_RX_TX | stat);
        if (ret < 0)
                return;
 
-       ret = mv88e6xxx_stats_wait(ds);
+       ret = _mv88e6xxx_stats_wait(ds);
        if (ret < 0)
                return;
 
-       ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_COUNTER_32);
+       ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_COUNTER_32);
        if (ret < 0)
                return;
 
        _val = ret << 16;
 
-       ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_COUNTER_01);
+       ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_COUNTER_01);
        if (ret < 0)
                return;
 
@@ -587,11 +688,11 @@ static void _mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
        int ret;
        int i;
 
-       mutex_lock(&ps->stats_mutex);
+       mutex_lock(&ps->smi_mutex);
 
-       ret = mv88e6xxx_stats_snapshot(ds, port);
+       ret = _mv88e6xxx_stats_snapshot(ds, port);
        if (ret < 0) {
-               mutex_unlock(&ps->stats_mutex);
+               mutex_unlock(&ps->smi_mutex);
                return;
        }
 
@@ -608,8 +709,8 @@ static void _mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
                                goto error;
                        low = ret;
                        if (s->sizeof_stat == 4) {
-                               ret = mv88e6xxx_reg_read(ds, REG_PORT(port),
-                                                        s->reg - 0x100 + 1);
+                               ret = _mv88e6xxx_reg_read(ds, REG_PORT(port),
+                                                         s->reg - 0x100 + 1);
                                if (ret < 0)
                                        goto error;
                                high = ret;
@@ -617,14 +718,14 @@ static void _mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
                        data[i] = (((u64)high) << 16) | low;
                        continue;
                }
-               mv88e6xxx_stats_read(ds, s->reg, &low);
+               _mv88e6xxx_stats_read(ds, s->reg, &low);
                if (s->sizeof_stat == 8)
-                       mv88e6xxx_stats_read(ds, s->reg + 1, &high);
+                       _mv88e6xxx_stats_read(ds, s->reg + 1, &high);
 
                data[i] = (((u64)high) << 32) | low;
        }
 error:
-       mutex_unlock(&ps->stats_mutex);
+       mutex_unlock(&ps->smi_mutex);
 }
 
 /* All the statistics in the table */
@@ -694,7 +795,7 @@ int  mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
 
        *temp = 0;
 
-       mutex_lock(&ps->phy_mutex);
+       mutex_lock(&ps->smi_mutex);
 
        ret = _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6);
        if (ret < 0)
@@ -727,19 +828,23 @@ int  mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
 
 error:
        _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0);
-       mutex_unlock(&ps->phy_mutex);
+       mutex_unlock(&ps->smi_mutex);
        return ret;
 }
 #endif /* CONFIG_NET_DSA_HWMON */
 
-static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
+/* 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 = REG_READ(reg, offset);
+               ret = _mv88e6xxx_reg_read(ds, reg, offset);
+               if (ret < 0)
+                       return ret;
                if (!(ret & mask))
                        return 0;
 
@@ -748,10 +853,22 @@ static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
        return -ETIMEDOUT;
 }
 
-int mv88e6xxx_phy_wait(struct dsa_switch *ds)
+static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       int ret;
+
+       mutex_lock(&ps->smi_mutex);
+       ret = _mv88e6xxx_wait(ds, reg, offset, mask);
+       mutex_unlock(&ps->smi_mutex);
+
+       return ret;
+}
+
+static int _mv88e6xxx_phy_wait(struct dsa_switch *ds)
 {
-       return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
-                             GLOBAL2_SMI_OP_BUSY);
+       return _mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
+                              GLOBAL2_SMI_OP_BUSY);
 }
 
 int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
@@ -766,25 +883,6 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
                              GLOBAL2_EEPROM_OP_BUSY);
 }
 
-/* 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)
 {
@@ -792,31 +890,40 @@ static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
                               GLOBAL_ATU_OP_BUSY);
 }
 
-/* Must be called with phy mutex held */
+/* Must be called with SMI mutex held */
 static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr,
                                        int regnum)
 {
        int ret;
 
-       REG_WRITE(REG_GLOBAL2, GLOBAL2_SMI_OP,
-                 GLOBAL2_SMI_OP_22_READ | (addr << 5) | regnum);
+       ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
+                                  GLOBAL2_SMI_OP_22_READ | (addr << 5) |
+                                  regnum);
+       if (ret < 0)
+               return ret;
 
-       ret = mv88e6xxx_phy_wait(ds);
+       ret = _mv88e6xxx_phy_wait(ds);
        if (ret < 0)
                return ret;
 
-       return REG_READ(REG_GLOBAL2, GLOBAL2_SMI_DATA);
+       return _mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA);
 }
 
-/* Must be called with phy mutex held */
+/* Must be called with SMI mutex held */
 static int _mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr,
                                         int regnum, u16 val)
 {
-       REG_WRITE(REG_GLOBAL2, GLOBAL2_SMI_DATA, val);
-       REG_WRITE(REG_GLOBAL2, GLOBAL2_SMI_OP,
-                 GLOBAL2_SMI_OP_22_WRITE | (addr << 5) | regnum);
+       int ret;
 
-       return mv88e6xxx_phy_wait(ds);
+       ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA, val);
+       if (ret < 0)
+               return ret;
+
+       ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_OP,
+                                  GLOBAL2_SMI_OP_22_WRITE | (addr << 5) |
+                                  regnum);
+
+       return _mv88e6xxx_phy_wait(ds);
 }
 
 int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
@@ -824,7 +931,7 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
        int reg;
 
-       mutex_lock(&ps->phy_mutex);
+       mutex_lock(&ps->smi_mutex);
 
        reg = _mv88e6xxx_phy_read_indirect(ds, port, 16);
        if (reg < 0)
@@ -833,7 +940,7 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
        e->eee_enabled = !!(reg & 0x0200);
        e->tx_lpi_enabled = !!(reg & 0x0100);
 
-       reg = mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS);
+       reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS);
        if (reg < 0)
                goto out;
 
@@ -841,7 +948,7 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
        reg = 0;
 
 out:
-       mutex_unlock(&ps->phy_mutex);
+       mutex_unlock(&ps->smi_mutex);
        return reg;
 }
 
@@ -852,7 +959,7 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
        int reg;
        int ret;
 
-       mutex_lock(&ps->phy_mutex);
+       mutex_lock(&ps->smi_mutex);
 
        ret = _mv88e6xxx_phy_read_indirect(ds, port, 16);
        if (ret < 0)
@@ -866,7 +973,7 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 
        ret = _mv88e6xxx_phy_write_indirect(ds, port, 16, reg);
 out:
-       mutex_unlock(&ps->phy_mutex);
+       mutex_unlock(&ps->smi_mutex);
 
        return ret;
 }
@@ -1241,13 +1348,212 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
        }
 }
 
-int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
+static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
        int ret, fid;
+       u16 reg;
 
        mutex_lock(&ps->smi_mutex);
 
+       if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+           mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
+           mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds) ||
+           mv88e6xxx_6065_family(ds)) {
+               /* MAC Forcing register: don't force link, speed,
+                * duplex or flow control state to any particular
+                * values on physical ports, but force the CPU port
+                * and all DSA ports to their maximum bandwidth and
+                * full duplex.
+                */
+               reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL);
+               if (dsa_is_cpu_port(ds, port) ||
+                   ds->dsa_port_mask & (1 << port)) {
+                       reg |= PORT_PCS_CTRL_FORCE_LINK |
+                               PORT_PCS_CTRL_LINK_UP |
+                               PORT_PCS_CTRL_DUPLEX_FULL |
+                               PORT_PCS_CTRL_FORCE_DUPLEX;
+                       if (mv88e6xxx_6065_family(ds))
+                               reg |= PORT_PCS_CTRL_100;
+                       else
+                               reg |= PORT_PCS_CTRL_1000;
+               } else {
+                       reg |= PORT_PCS_CTRL_UNFORCED;
+               }
+
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_PCS_CTRL, reg);
+               if (ret)
+                       goto abort;
+       }
+
+       /* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
+        * disable Header mode, enable IGMP/MLD snooping, disable VLAN
+        * tunneling, determine priority by looking at 802.1p and IP
+        * priority fields (IP prio has precedence), and set STP state
+        * to Forwarding.
+        *
+        * If this is the CPU link, use DSA or EDSA tagging depending
+        * on which tagging mode was configured.
+        *
+        * If this is a link to another switch, use DSA tagging mode.
+        *
+        * If this is the upstream port for this switch, enable
+        * forwarding of unknown unicasts and multicasts.
+        */
+       reg = 0;
+       if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+           mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
+           mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) ||
+           mv88e6xxx_6185_family(ds))
+               reg = PORT_CONTROL_IGMP_MLD_SNOOP |
+               PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP |
+               PORT_CONTROL_STATE_FORWARDING;
+       if (dsa_is_cpu_port(ds, port)) {
+               if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds))
+                       reg |= PORT_CONTROL_DSA_TAG;
+               if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+                   mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds)) {
+                       if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
+                               reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA;
+                       else
+                               reg |= PORT_CONTROL_FRAME_MODE_DSA;
+               }
+
+               if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+                   mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
+                   mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds) ||
+                   mv88e6xxx_6185_family(ds)) {
+                       if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA)
+                               reg |= PORT_CONTROL_EGRESS_ADD_TAG;
+               }
+       }
+       if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+           mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
+           mv88e6xxx_6095_family(ds) || mv88e6xxx_6065_family(ds)) {
+               if (ds->dsa_port_mask & (1 << port))
+                       reg |= PORT_CONTROL_FRAME_MODE_DSA;
+               if (port == dsa_upstream_port(ds))
+                       reg |= PORT_CONTROL_FORWARD_UNKNOWN |
+                               PORT_CONTROL_FORWARD_UNKNOWN_MC;
+       }
+       if (reg) {
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_CONTROL, reg);
+               if (ret)
+                       goto abort;
+       }
+
+       /* 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
+        * on this port, do a destination address lookup on all
+        * received packets as usual, disable ARP mirroring and don't
+        * send a copy of all transmitted/received frames on this port
+        * to the CPU.
+        */
+       reg = 0;
+       if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+           mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
+           mv88e6xxx_6095_family(ds))
+               reg = PORT_CONTROL_2_MAP_DA;
+
+       if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+           mv88e6xxx_6165_family(ds))
+               reg |= PORT_CONTROL_2_JUMBO_10240;
+
+       if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) {
+               /* Set the upstream port this port should use */
+               reg |= dsa_upstream_port(ds);
+               /* enable forwarding of unknown multicast addresses to
+                * the upstream port
+                */
+               if (port == dsa_upstream_port(ds))
+                       reg |= PORT_CONTROL_2_FORWARD_UNKNOWN;
+       }
+
+       if (reg) {
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_CONTROL_2, reg);
+               if (ret)
+                       goto abort;
+       }
+
+       /* Port Association Vector: when learning source addresses
+        * of packets, add the address to the address database using
+        * a port bitmap that has only the bit for this port set and
+        * the other bits clear.
+        */
+       ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_ASSOC_VECTOR,
+                                  1 << port);
+       if (ret)
+               goto abort;
+
+       /* Egress rate control 2: disable egress rate control. */
+       ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_RATE_CONTROL_2,
+                                  0x0000);
+       if (ret)
+               goto abort;
+
+       if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+           mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds)) {
+               /* Do not limit the period of time that this port can
+                * be paused for by the remote end or the period of
+                * time that this port can pause the remote end.
+                */
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_PAUSE_CTRL, 0x0000);
+               if (ret)
+                       goto abort;
+
+               /* Port ATU control: disable limiting the number of
+                * address database entries that this port is allowed
+                * to use.
+                */
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_ATU_CONTROL, 0x0000);
+               /* Priority Override: disable DA, SA and VTU priority
+                * override.
+                */
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_PRI_OVERRIDE, 0x0000);
+               if (ret)
+                       goto abort;
+
+               /* Port Ethertype: use the Ethertype DSA Ethertype
+                * value.
+                */
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_ETH_TYPE, ETH_P_EDSA);
+               if (ret)
+                       goto abort;
+               /* Tag Remap: use an identity 802.1p prio -> switch
+                * prio mapping.
+                */
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_TAG_REGMAP_0123, 0x3210);
+               if (ret)
+                       goto abort;
+
+               /* Tag Remap 2: use an identity 802.1p prio -> switch
+                * prio mapping.
+                */
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_TAG_REGMAP_4567, 0x7654);
+               if (ret)
+                       goto abort;
+       }
+
+       if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+           mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
+           mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds)) {
+               /* Rate Control: disable ingress rate limiting. */
+               ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
+                                          PORT_RATE_CONTROL, 0x0001);
+               if (ret)
+                       goto abort;
+       }
+
        /* Port Control 1: disable trunking, disable sending
         * learning messages to this port.
         */
@@ -1281,13 +1587,25 @@ abort:
        return ret;
 }
 
+int mv88e6xxx_setup_ports(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       int ret;
+       int i;
+
+       for (i = 0; i < ps->num_ports; i++) {
+               ret = mv88e6xxx_setup_port(ds, i);
+               if (ret < 0)
+                       return ret;
+       }
+       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);
 
        ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
 
@@ -1298,6 +1616,104 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
        return 0;
 }
 
+int mv88e6xxx_setup_global(struct dsa_switch *ds)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       int i;
+
+       /* Set the default address aging time to 5 minutes, and
+        * enable address learn messages to be sent to all message
+        * ports.
+        */
+       REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
+                 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL);
+
+       /* Configure the IP ToS mapping registers. */
+       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000);
+       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000);
+       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555);
+       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555);
+       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa);
+       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa);
+       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff);
+       REG_WRITE(REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff);
+
+       /* Configure the IEEE 802.1p priority mapping register. */
+       REG_WRITE(REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41);
+
+       /* Send all frames with destination addresses matching
+        * 01:80:c2:00:00:0x to the CPU port.
+        */
+       REG_WRITE(REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff);
+
+       /* Ignore removed tag data on doubly tagged packets, disable
+        * flow control messages, force flow control priority to the
+        * highest, and send all special multicast frames to the CPU
+        * port at the highest priority.
+        */
+       REG_WRITE(REG_GLOBAL2, GLOBAL2_SWITCH_MGMT,
+                 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 |
+                 GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI);
+
+       /* Program the DSA routing table. */
+       for (i = 0; i < 32; i++) {
+               int nexthop = 0x1f;
+
+               if (ds->pd->rtable &&
+                   i != ds->index && i < ds->dst->pd->nr_chips)
+                       nexthop = ds->pd->rtable[i] & 0x1f;
+
+               REG_WRITE(REG_GLOBAL2, GLOBAL2_DEVICE_MAPPING,
+                         GLOBAL2_DEVICE_MAPPING_UPDATE |
+                         (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) |
+                         nexthop);
+       }
+
+       /* Clear all trunk masks. */
+       for (i = 0; i < 8; i++)
+               REG_WRITE(REG_GLOBAL2, GLOBAL2_TRUNK_MASK,
+                         0x8000 | (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) |
+                         ((1 << ps->num_ports) - 1));
+
+       /* Clear all trunk mappings. */
+       for (i = 0; i < 16; i++)
+               REG_WRITE(REG_GLOBAL2, GLOBAL2_TRUNK_MAPPING,
+                         GLOBAL2_TRUNK_MAPPING_UPDATE |
+                         (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT));
+
+       if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+           mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds)) {
+               /* Send all frames with destination addresses matching
+                * 01:80:c2:00:00:2x to the CPU port.
+                */
+               REG_WRITE(REG_GLOBAL2, GLOBAL2_MGMT_EN_2X, 0xffff);
+
+               /* Initialise cross-chip port VLAN table to reset
+                * defaults.
+                */
+               REG_WRITE(REG_GLOBAL2, GLOBAL2_PVT_ADDR, 0x9000);
+
+               /* Clear the priority override table. */
+               for (i = 0; i < 16; i++)
+                       REG_WRITE(REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE,
+                                 0x8000 | (i << 8));
+       }
+
+       if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
+           mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) ||
+           mv88e6xxx_6185_family(ds) || mv88e6xxx_6095_family(ds)) {
+               /* Disable ingress rate limiting by resetting all
+                * ingress rate limit registers to their initial
+                * state.
+                */
+               for (i = 0; i < ps->num_ports; i++)
+                       REG_WRITE(REG_GLOBAL2, GLOBAL2_INGRESS_OP,
+                                 0x9000 | (i << 8));
+       }
+
+       return 0;
+}
+
 int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -1343,14 +1759,14 @@ int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
        int ret;
 
-       mutex_lock(&ps->phy_mutex);
+       mutex_lock(&ps->smi_mutex);
        ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
        if (ret < 0)
                goto error;
        ret = _mv88e6xxx_phy_read_indirect(ds, port, reg);
 error:
        _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
-       mutex_unlock(&ps->phy_mutex);
+       mutex_unlock(&ps->smi_mutex);
        return ret;
 }
 
@@ -1360,7 +1776,7 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
        int ret;
 
-       mutex_lock(&ps->phy_mutex);
+       mutex_lock(&ps->smi_mutex);
        ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
        if (ret < 0)
                goto error;
@@ -1368,7 +1784,7 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
        ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val);
 error:
        _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
-       mutex_unlock(&ps->phy_mutex);
+       mutex_unlock(&ps->smi_mutex);
        return ret;
 }
 
@@ -1391,9 +1807,9 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
        if (addr < 0)
                return addr;
 
-       mutex_lock(&ps->phy_mutex);
+       mutex_lock(&ps->smi_mutex);
        ret = _mv88e6xxx_phy_read(ds, addr, regnum);
-       mutex_unlock(&ps->phy_mutex);
+       mutex_unlock(&ps->smi_mutex);
        return ret;
 }
 
@@ -1407,9 +1823,9 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
        if (addr < 0)
                return addr;
 
-       mutex_lock(&ps->phy_mutex);
+       mutex_lock(&ps->smi_mutex);
        ret = _mv88e6xxx_phy_write(ds, addr, regnum, val);
-       mutex_unlock(&ps->phy_mutex);
+       mutex_unlock(&ps->smi_mutex);
        return ret;
 }
 
@@ -1423,9 +1839,9 @@ mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
        if (addr < 0)
                return addr;
 
-       mutex_lock(&ps->phy_mutex);
+       mutex_lock(&ps->smi_mutex);
        ret = _mv88e6xxx_phy_read_indirect(ds, addr, regnum);
-       mutex_unlock(&ps->phy_mutex);
+       mutex_unlock(&ps->smi_mutex);
        return ret;
 }
 
@@ -1440,9 +1856,9 @@ mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
        if (addr < 0)
                return addr;
 
-       mutex_lock(&ps->phy_mutex);
+       mutex_lock(&ps->smi_mutex);
        ret = _mv88e6xxx_phy_write_indirect(ds, addr, regnum, val);
-       mutex_unlock(&ps->phy_mutex);
+       mutex_unlock(&ps->smi_mutex);
        return ret;
 }
 
index e045154f33646692cb292150efde8e0ad78a9326..e10ccdb4ffbcf9e5a63d6673e12f5cf05c638699 100644 (file)
 #define PORT_STATUS_TX_PAUSED  BIT(5)
 #define PORT_STATUS_FLOW_CTRL  BIT(4)
 #define PORT_PCS_CTRL          0x01
+#define PORT_PCS_CTRL_FC               BIT(7)
+#define PORT_PCS_CTRL_FORCE_FC         BIT(6)
+#define PORT_PCS_CTRL_LINK_UP          BIT(5)
+#define PORT_PCS_CTRL_FORCE_LINK       BIT(4)
+#define PORT_PCS_CTRL_DUPLEX_FULL      BIT(3)
+#define PORT_PCS_CTRL_FORCE_DUPLEX     BIT(2)
+#define PORT_PCS_CTRL_10               0x00
+#define PORT_PCS_CTRL_100              0x01
+#define PORT_PCS_CTRL_1000             0x02
+#define PORT_PCS_CTRL_UNFORCED         0x03
+#define PORT_PAUSE_CTRL                0x02
 #define PORT_SWITCH_ID         0x03
+#define PORT_SWITCH_ID_6031    0x0310
+#define PORT_SWITCH_ID_6035    0x0350
+#define PORT_SWITCH_ID_6046    0x0480
+#define PORT_SWITCH_ID_6061    0x0610
+#define PORT_SWITCH_ID_6065    0x0650
 #define PORT_SWITCH_ID_6085    0x04a0
+#define PORT_SWITCH_ID_6092    0x0970
 #define PORT_SWITCH_ID_6095    0x0950
+#define PORT_SWITCH_ID_6096    0x0980
+#define PORT_SWITCH_ID_6097    0x0990
+#define PORT_SWITCH_ID_6108    0x1070
+#define PORT_SWITCH_ID_6121    0x1040
+#define PORT_SWITCH_ID_6122    0x1050
 #define PORT_SWITCH_ID_6123    0x1210
 #define PORT_SWITCH_ID_6123_A1 0x1212
 #define PORT_SWITCH_ID_6123_A2 0x1213
 #define PORT_SWITCH_ID_6165_A2 0x1653
 #define PORT_SWITCH_ID_6171    0x1710
 #define PORT_SWITCH_ID_6172    0x1720
+#define PORT_SWITCH_ID_6175    0x1750
 #define PORT_SWITCH_ID_6176    0x1760
 #define PORT_SWITCH_ID_6182    0x1a60
 #define PORT_SWITCH_ID_6185    0x1a70
+#define PORT_SWITCH_ID_6240    0x2400
+#define PORT_SWITCH_ID_6320    0x1250
+#define PORT_SWITCH_ID_6350    0x3710
+#define PORT_SWITCH_ID_6351    0x3750
 #define PORT_SWITCH_ID_6352    0x3520
 #define PORT_SWITCH_ID_6352_A0 0x3521
 #define PORT_SWITCH_ID_6352_A1 0x3522
 #define PORT_CONTROL           0x04
+#define PORT_CONTROL_USE_CORE_TAG      BIT(15)
+#define PORT_CONTROL_DROP_ON_LOCK      BIT(14)
+#define PORT_CONTROL_EGRESS_UNMODIFIED (0x0 << 12)
+#define PORT_CONTROL_EGRESS_UNTAGGED   (0x1 << 12)
+#define PORT_CONTROL_EGRESS_TAGGED     (0x2 << 12)
+#define PORT_CONTROL_EGRESS_ADD_TAG    (0x3 << 12)
+#define PORT_CONTROL_HEADER            BIT(11)
+#define PORT_CONTROL_IGMP_MLD_SNOOP    BIT(10)
+#define PORT_CONTROL_DOUBLE_TAG                BIT(9)
+#define PORT_CONTROL_FRAME_MODE_NORMAL         (0x0 << 8)
+#define PORT_CONTROL_FRAME_MODE_DSA            (0x1 << 8)
+#define PORT_CONTROL_FRAME_MODE_PROVIDER       (0x2 << 8)
+#define PORT_CONTROL_FRAME_ETHER_TYPE_DSA      (0x3 << 8)
+#define PORT_CONTROL_DSA_TAG           BIT(8)
+#define PORT_CONTROL_VLAN_TUNNEL       BIT(7)
+#define PORT_CONTROL_TAG_IF_BOTH       BIT(6)
+#define PORT_CONTROL_USE_IP            BIT(5)
+#define PORT_CONTROL_USE_TAG           BIT(4)
+#define PORT_CONTROL_FORWARD_UNKNOWN_MC        BIT(3)
+#define PORT_CONTROL_FORWARD_UNKNOWN   BIT(2)
 #define PORT_CONTROL_STATE_MASK                0x03
 #define PORT_CONTROL_STATE_DISABLED    0x00
 #define PORT_CONTROL_STATE_BLOCKING    0x01
 #define PORT_BASE_VLAN         0x06
 #define PORT_DEFAULT_VLAN      0x07
 #define PORT_CONTROL_2         0x08
+#define PORT_CONTROL_2_IGNORE_FCS      BIT(15)
+#define PORT_CONTROL_2_VTU_PRI_OVERRIDE        BIT(14)
+#define PORT_CONTROL_2_SA_PRIO_OVERRIDE        BIT(13)
+#define PORT_CONTROL_2_DA_PRIO_OVERRIDE        BIT(12)
+#define PORT_CONTROL_2_JUMBO_1522      (0x00 << 12)
+#define PORT_CONTROL_2_JUMBO_2048      (0x01 << 12)
+#define PORT_CONTROL_2_JUMBO_10240     (0x02 << 12)
+#define PORT_CONTROL_2_DISCARD_TAGGED  BIT(9)
+#define PORT_CONTROL_2_DISCARD_UNTAGGED        BIT(8)
+#define PORT_CONTROL_2_MAP_DA          BIT(7)
+#define PORT_CONTROL_2_DEFAULT_FORWARD BIT(6)
+#define PORT_CONTROL_2_FORWARD_UNKNOWN BIT(6)
+#define PORT_CONTROL_2_EGRESS_MONITOR  BIT(5)
+#define PORT_CONTROL_2_INGRESS_MONITOR BIT(4)
 #define PORT_RATE_CONTROL      0x09
 #define PORT_RATE_CONTROL_2    0x0a
 #define PORT_ASSOC_VECTOR      0x0b
+#define PORT_ATU_CONTROL       0x0c
+#define PORT_PRI_OVERRIDE      0x0d
+#define PORT_ETH_TYPE          0x0f
 #define PORT_IN_DISCARD_LO     0x10
 #define PORT_IN_DISCARD_HI     0x11
 #define PORT_IN_FILTERED       0x12
 #define PORT_OUT_FILTERED      0x13
-#define PORT_TAG_REGMAP_0123   0x19
-#define PORT_TAG_REGMAP_4567   0x1a
+#define PORT_TAG_REGMAP_0123   0x18
+#define PORT_TAG_REGMAP_4567   0x19
 
 #define REG_GLOBAL             0x1b
 #define GLOBAL_STATUS          0x00
 #define GLOBAL_CONTROL_DISCARD_EXCESS  BIT(13) /* 6352 */
 #define GLOBAL_CONTROL_SCHED_PRIO      BIT(11) /* 6152 */
 #define GLOBAL_CONTROL_MAX_FRAME_1632  BIT(10) /* 6152 */
-#define GLOBAL_CONTROL_RELOAD_EEPROM   BIT(9)  /* 6152 */
+#define GLOBAL_CONTROL_RELOAD_EEPROM   BIT(9)  /* 6152 */
 #define GLOBAL_CONTROL_DEVICE_EN       BIT(7)
 #define GLOBAL_CONTROL_STATS_DONE_EN   BIT(6)
 #define GLOBAL_CONTROL_VTU_PROBLEM_EN  BIT(5)
 #define GLOBAL_VTU_DATA_4_7    0x08
 #define GLOBAL_VTU_DATA_8_11   0x09
 #define GLOBAL_ATU_CONTROL     0x0a
+#define GLOBAL_ATU_CONTROL_LEARN2ALL   BIT(3)
 #define GLOBAL_ATU_OP          0x0b
 #define GLOBAL_ATU_OP_BUSY     BIT(15)
 #define GLOBAL_ATU_OP_NOP              (0 << 12)
 #define GLOBAL_IEEE_PRI                0x18
 #define GLOBAL_CORE_TAG_TYPE   0x19
 #define GLOBAL_MONITOR_CONTROL 0x1a
+#define GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT   12
+#define GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT    8
+#define GLOBAL_MONITOR_CONTROL_ARP_SHIFT       4
+#define GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT    0
+#define GLOBAL_MONITOR_CONTROL_ARP_DISABLED    (0xf0)
 #define GLOBAL_CONTROL_2       0x1c
+#define GLOBAL_CONTROL_2_NO_CASCADE            0xe000
+#define GLOBAL_CONTROL_2_MULTIPLE_CASCADE      0xf000
+
 #define GLOBAL_STATS_OP                0x1d
 #define GLOBAL_STATS_OP_BUSY   BIT(15)
 #define GLOBAL_STATS_OP_NOP            (0 << 12)
 #define GLOBAL2_MGMT_EN_0X     0x03
 #define GLOBAL2_FLOW_CONTROL   0x04
 #define GLOBAL2_SWITCH_MGMT    0x05
+#define GLOBAL2_SWITCH_MGMT_USE_DOUBLE_TAG_DATA        BIT(15)
+#define GLOBAL2_SWITCH_MGMT_PREVENT_LOOPS      BIT(14)
+#define GLOBAL2_SWITCH_MGMT_FLOW_CONTROL_MSG   BIT(13)
+#define GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI        BIT(7)
+#define GLOBAL2_SWITCH_MGMT_RSVD2CPU           BIT(3)
 #define GLOBAL2_DEVICE_MAPPING 0x06
+#define GLOBAL2_DEVICE_MAPPING_UPDATE          BIT(15)
+#define GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT    8
 #define GLOBAL2_TRUNK_MASK     0x07
+#define GLOBAL2_TRUNK_MASK_UPDATE              BIT(15)
+#define GLOBAL2_TRUNK_MASK_NUM_SHIFT           12
 #define GLOBAL2_TRUNK_MAPPING  0x08
+#define GLOBAL2_TRUNK_MAPPING_UPDATE           BIT(15)
+#define GLOBAL2_TRUNK_MAPPING_ID_SHIFT         11
 #define GLOBAL2_INGRESS_OP     0x09
 #define GLOBAL2_INGRESS_DATA   0x0a
 #define GLOBAL2_PVT_ADDR       0x0b
 #define GLOBAL2_SWITCH_MAC_BUSY BIT(15)
 #define GLOBAL2_ATU_STATS      0x0e
 #define GLOBAL2_PRIO_OVERRIDE  0x0f
+#define GLOBAL2_PRIO_OVERRIDE_FORCE_SNOOP      BIT(7)
+#define GLOBAL2_PRIO_OVERRIDE_SNOOP_SHIFT      4
+#define GLOBAL2_PRIO_OVERRIDE_FORCE_ARP                BIT(3)
+#define GLOBAL2_PRIO_OVERRIDE_ARP_SHIFT                0
 #define GLOBAL2_EEPROM_OP      0x14
 #define GLOBAL2_EEPROM_OP_BUSY BIT(15)
 #define GLOBAL2_EEPROM_OP_LOAD BIT(11)
@@ -260,14 +348,14 @@ struct mv88e6xxx_hw_stat {
 };
 
 int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
-int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port);
+int mv88e6xxx_setup_ports(struct dsa_switch *ds);
 int mv88e6xxx_setup_common(struct dsa_switch *ds);
+int mv88e6xxx_setup_global(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,
                          int reg, u16 val);
 int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val);
-int mv88e6xxx_config_prio(struct dsa_switch *ds);
 int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
 int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
 int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum);
@@ -289,7 +377,6 @@ int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port);
 void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
                        struct ethtool_regs *regs, void *_p);
 int  mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp);
-int mv88e6xxx_phy_wait(struct dsa_switch *ds);
 int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
 int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
 int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum);
index 827cda560a552b7b0dca45d49a06816e6dda513b..03e041addea39d0b3354163f969b3f6ac067f655 100644 (file)
@@ -810,12 +810,19 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
        return 0;
 }
 
+static struct lock_class_key dsa_slave_netdev_xmit_lock_key;
+static void dsa_slave_set_lockdep_class_one(struct net_device *dev,
+                                           struct netdev_queue *txq,
+                                           void *_unused)
+{
+       lockdep_set_class(&txq->_xmit_lock,
+                         &dsa_slave_netdev_xmit_lock_key);
+}
+
 int dsa_slave_suspend(struct net_device *slave_dev)
 {
        struct dsa_slave_priv *p = netdev_priv(slave_dev);
 
-       netif_device_detach(slave_dev);
-
        if (p->phy) {
                phy_stop(p->phy);
                p->old_pause = -1;
@@ -861,6 +868,9 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
        slave_dev->netdev_ops = &dsa_slave_netdev_ops;
        slave_dev->swdev_ops = &dsa_slave_swdev_ops;
 
+       netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one,
+                                NULL);
+
        SET_NETDEV_DEV(slave_dev, parent);
        slave_dev->dev.of_node = ds->pd->port_dn[port];
        slave_dev->vlan_features = master->vlan_features;
This page took 0.052572 seconds and 5 git commands to generate.