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

Merge branch 'dsa-next'

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 239fb791 448b4482
...@@ -37,22 +37,22 @@ config NET_DSA_MV88E6123_61_65 ...@@ -37,22 +37,22 @@ config NET_DSA_MV88E6123_61_65
ethernet switch chips. ethernet switch chips.
config NET_DSA_MV88E6171 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 depends on NET_DSA
select NET_DSA_MV88E6XXX select NET_DSA_MV88E6XXX
select NET_DSA_TAG_EDSA select NET_DSA_TAG_EDSA
---help--- ---help---
This enables support for the Marvell 88E6171/6172 ethernet switch This enables support for the Marvell 88E6171/6175/6350/6351
chips. ethernet switches chips.
config NET_DSA_MV88E6352 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 depends on NET_DSA
select NET_DSA_MV88E6XXX select NET_DSA_MV88E6XXX
select NET_DSA_TAG_EDSA select NET_DSA_TAG_EDSA
---help--- ---help---
This enables support for the Marvell 88E6176 and 88E6352 ethernet This enables support for the Marvell 88E6172, 88E6176 and 88E6352
switch chips. ethernet switch chips.
config NET_DSA_BCM_SF2 config NET_DSA_BCM_SF2
tristate "Broadcom Starfighter 2 Ethernet switch support" tristate "Broadcom Starfighter 2 Ethernet switch support"
......
...@@ -54,192 +54,40 @@ static char *mv88e6123_61_65_probe(struct device *host_dev, int sw_addr) ...@@ -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) static int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
{ {
u32 upstream_port = dsa_upstream_port(ds);
int ret; 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 /* Disable the PHY polling unit (since there won't be any
* external PHYs to poll), don't discard packets with * external PHYs to poll), don't discard packets with
* excessive collisions, and mask all interrupt sources. * excessive collisions, and mask all interrupt sources.
*/ */
REG_WRITE(REG_GLOBAL, 0x04, 0x0000); REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, 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;
/* Configure the upstream port, and configure the upstream /* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames * port as the port to which ingress and egress monitor frames
* are to be sent. * 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 /* Disable remote management for now, and set the switch's
* DSA device number. * DSA device number.
*/ */
REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, 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 */
return 0; 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) static int mv88e6123_61_65_setup(struct dsa_switch *ds)
{ {
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int i;
int ret; int ret;
ret = mv88e6xxx_setup_common(ds); ret = mv88e6xxx_setup_common(ds);
...@@ -262,19 +110,11 @@ static int mv88e6123_61_65_setup(struct dsa_switch *ds) ...@@ -262,19 +110,11 @@ static int mv88e6123_61_65_setup(struct dsa_switch *ds)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* @@@ initialise vtu and atu */
ret = mv88e6123_61_65_setup_global(ds); ret = mv88e6123_61_65_setup_global(ds);
if (ret < 0) if (ret < 0)
return ret; return ret;
for (i = 0; i < ps->num_ports; i++) { return mv88e6xxx_setup_ports(ds);
ret = mv88e6123_61_65_setup_port(ds, i);
if (ret < 0)
return ret;
}
return 0;
} }
struct dsa_switch_driver mv88e6123_61_65_switch_driver = { struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
......
...@@ -37,6 +37,8 @@ static char *mv88e6131_probe(struct device *host_dev, int sw_addr) ...@@ -37,6 +37,8 @@ static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
return "Marvell 88E6131 (B2)"; return "Marvell 88E6131 (B2)";
if (ret_masked == PORT_SWITCH_ID_6131) if (ret_masked == PORT_SWITCH_ID_6131)
return "Marvell 88E6131"; return "Marvell 88E6131";
if (ret_masked == PORT_SWITCH_ID_6185)
return "Marvell 88E6185";
} }
return NULL; return NULL;
...@@ -44,186 +46,62 @@ static char *mv88e6131_probe(struct device *host_dev, int sw_addr) ...@@ -44,186 +46,62 @@ static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
static int mv88e6131_setup_global(struct dsa_switch *ds) static int mv88e6131_setup_global(struct dsa_switch *ds)
{ {
u32 upstream_port = dsa_upstream_port(ds);
int ret; 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 /* Enable the PHY polling unit, don't discard packets with
* excessive collisions, use a weighted fair queueing scheme * excessive collisions, use a weighted fair queueing scheme
* to arbitrate between packet queues, set the maximum frame * to arbitrate between packet queues, set the maximum frame
* size to 1632, and mask all interrupt sources. * size to 1632, and mask all interrupt sources.
*/ */
REG_WRITE(REG_GLOBAL, 0x04, 0x4400); REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_MAX_FRAME_1632);
/* 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;
/* Set the VLAN ethertype to 0x8100. */ /* 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 /* Disable ARP mirroring, and configure the upstream port as
* the port to which ingress and egress monitor frames are to * the port to which ingress and egress monitor frames are to
* be sent. * 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 /* Disable cascade port functionality unless this device
* is used in a cascade configuration, and set the switch's * is used in a cascade configuration, and set the switch's
* DSA device number. * DSA device number.
*/ */
if (ds->dst->pd->nr_chips > 1) 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 else
REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f)); REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2,
GLOBAL_CONTROL_2_NO_CASCADE |
/* Send all frames with destination addresses matching (ds->index & 0x1f));
* 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));
/* Force the priority of IGMP/MLD snoop frames and ARP frames /* Force the priority of IGMP/MLD snoop frames and ARP frames
* to the highest setting. * 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; 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) static int mv88e6131_setup(struct dsa_switch *ds)
{ {
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int i;
int ret; int ret;
ret = mv88e6xxx_setup_common(ds); ret = mv88e6xxx_setup_common(ds);
...@@ -234,6 +112,7 @@ static int mv88e6131_setup(struct dsa_switch *ds) ...@@ -234,6 +112,7 @@ static int mv88e6131_setup(struct dsa_switch *ds)
switch (ps->id) { switch (ps->id) {
case PORT_SWITCH_ID_6085: case PORT_SWITCH_ID_6085:
case PORT_SWITCH_ID_6185:
ps->num_ports = 10; ps->num_ports = 10;
break; break;
case PORT_SWITCH_ID_6095: case PORT_SWITCH_ID_6095:
...@@ -251,19 +130,11 @@ static int mv88e6131_setup(struct dsa_switch *ds) ...@@ -251,19 +130,11 @@ static int mv88e6131_setup(struct dsa_switch *ds)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* @@@ initialise vtu and atu */
ret = mv88e6131_setup_global(ds); ret = mv88e6131_setup_global(ds);
if (ret < 0) if (ret < 0)
return ret; return ret;
for (i = 0; i < ps->num_ports; i++) { return mv88e6xxx_setup_ports(ds);
ret = mv88e6131_setup_port(ds, i);
if (ret < 0)
return ret;
}
return 0;
} }
static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port) static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port)
......
/* 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) 2008-2009 Marvell Semiconductor
* Copyright (c) 2014 Claudio Leite <leitec@staticky.com> * Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
* *
...@@ -29,8 +29,12 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr) ...@@ -29,8 +29,12 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
if (ret >= 0) { if (ret >= 0) {
if ((ret & 0xfff0) == PORT_SWITCH_ID_6171) if ((ret & 0xfff0) == PORT_SWITCH_ID_6171)
return "Marvell 88E6171"; return "Marvell 88E6171";
if ((ret & 0xfff0) == PORT_SWITCH_ID_6172) if ((ret & 0xfff0) == PORT_SWITCH_ID_6175)
return "Marvell 88E6172"; 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; return NULL;
...@@ -38,196 +42,41 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr) ...@@ -38,196 +42,41 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
static int mv88e6171_setup_global(struct dsa_switch *ds) 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 ret;
int i; u32 reg;
ret = mv88e6xxx_setup_global(ds);
if (ret)
return ret;
/* Discard packets with excessive collisions, mask all /* Discard packets with excessive collisions, mask all
* interrupt sources, enable PPU. * interrupt sources, enable PPU.
*/ */
REG_WRITE(REG_GLOBAL, 0x04, 0x6000); REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS);
/* 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;
/* Configure the upstream port, and configure the upstream /* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames * port as the port to which ingress and egress monitor frames
* are to be sent. * are to be sent.
*/ */
if (REG_READ(REG_PORT(0), 0x03) == 0x1710) reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1111)); upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
else upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT |
REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1110)); 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 /* Disable remote management for now, and set the switch's
* DSA device number. * DSA device number.
*/ */
REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, 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 */
return 0; 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) static int mv88e6171_setup(struct dsa_switch *ds)
{ {
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int i;
int ret; int ret;
ret = mv88e6xxx_setup_common(ds); ret = mv88e6xxx_setup_common(ds);
...@@ -240,44 +89,11 @@ static int mv88e6171_setup(struct dsa_switch *ds) ...@@ -240,44 +89,11 @@ static int mv88e6171_setup(struct dsa_switch *ds)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* @@@ initialise vtu and atu */
ret = mv88e6171_setup_global(ds); ret = mv88e6171_setup_global(ds);
if (ret < 0) if (ret < 0)
return ret; return ret;
for (i = 0; i < ps->num_ports; i++) { return mv88e6xxx_setup_ports(ds);
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;
} }
struct dsa_switch_driver mv88e6171_switch_driver = { struct dsa_switch_driver mv88e6171_switch_driver = {
...@@ -292,8 +108,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = { ...@@ -292,8 +108,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
.get_strings = mv88e6xxx_get_strings, .get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count, .get_sset_count = mv88e6xxx_get_sset_count,
.set_eee = mv88e6171_set_eee,
.get_eee = mv88e6171_get_eee,
#ifdef CONFIG_NET_DSA_HWMON #ifdef CONFIG_NET_DSA_HWMON
.get_temp = mv88e6xxx_get_temp, .get_temp = mv88e6xxx_get_temp,
#endif #endif
...@@ -308,4 +122,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = { ...@@ -308,4 +122,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
}; };
MODULE_ALIAS("platform:mv88e6171"); MODULE_ALIAS("platform:mv88e6171");
MODULE_ALIAS("platform:mv88e6172"); MODULE_ALIAS("platform:mv88e6175");
MODULE_ALIAS("platform:mv88e6350");
MODULE_ALIAS("platform:mv88e6351");
...@@ -32,6 +32,8 @@ static char *mv88e6352_probe(struct device *host_dev, int sw_addr) ...@@ -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); ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
if (ret >= 0) { if (ret >= 0) {
if ((ret & 0xfff0) == PORT_SWITCH_ID_6172)
return "Marvell 88E6172";
if ((ret & 0xfff0) == PORT_SWITCH_ID_6176) if ((ret & 0xfff0) == PORT_SWITCH_ID_6176)
return "Marvell 88E6176"; return "Marvell 88E6176";
if (ret == PORT_SWITCH_ID_6352_A0) if (ret == PORT_SWITCH_ID_6352_A0)
...@@ -47,187 +49,37 @@ static char *mv88e6352_probe(struct device *host_dev, int sw_addr) ...@@ -47,187 +49,37 @@ static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
static int mv88e6352_setup_global(struct dsa_switch *ds) 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 ret;
int i; u32 reg;
ret = mv88e6xxx_setup_global(ds);
if (ret)
return ret;
/* Discard packets with excessive collisions, /* Discard packets with excessive collisions,
* mask all interrupt sources, enable PPU (bit 14, undocumented). * mask all interrupt sources, enable PPU (bit 14, undocumented).
*/ */
REG_WRITE(REG_GLOBAL, 0x04, 0x6000); REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL,
GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS);
/* 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;
/* Configure the upstream port, and configure the upstream /* Configure the upstream port, and configure the upstream
* port as the port to which ingress and egress monitor frames * port as the port to which ingress and egress monitor frames
* are to be sent. * 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 /* Disable remote management for now, and set the switch's
* DSA device number. * DSA device number.
*/ */
REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); 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; 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 #ifdef CONFIG_NET_DSA_HWMON
static int mv88e6352_get_temp(struct dsa_switch *ds, int *temp) static int mv88e6352_get_temp(struct dsa_switch *ds, int *temp)
...@@ -292,7 +144,6 @@ static int mv88e6352_setup(struct dsa_switch *ds) ...@@ -292,7 +144,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
{ {
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret; int ret;
int i;
ret = mv88e6xxx_setup_common(ds); ret = mv88e6xxx_setup_common(ds);
if (ret < 0) if (ret < 0)
...@@ -306,19 +157,11 @@ static int mv88e6352_setup(struct dsa_switch *ds) ...@@ -306,19 +157,11 @@ static int mv88e6352_setup(struct dsa_switch *ds)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* @@@ initialise vtu and atu */
ret = mv88e6352_setup_global(ds); ret = mv88e6352_setup_global(ds);
if (ret < 0) if (ret < 0)
return ret; return ret;
for (i = 0; i < ps->num_ports; i++) { return mv88e6xxx_setup_ports(ds);
ret = mv88e6352_setup_port(ds, i);
if (ret < 0)
return ret;
}
return 0;
} }
static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr) static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
...@@ -552,3 +395,4 @@ struct dsa_switch_driver mv88e6352_switch_driver = { ...@@ -552,3 +395,4 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
}; };
MODULE_ALIAS("platform:mv88e6352"); MODULE_ALIAS("platform:mv88e6352");
MODULE_ALIAS("platform:mv88e6172");
This diff is collapsed.
...@@ -40,9 +40,31 @@ ...@@ -40,9 +40,31 @@
#define PORT_STATUS_TX_PAUSED BIT(5) #define PORT_STATUS_TX_PAUSED BIT(5)
#define PORT_STATUS_FLOW_CTRL BIT(4) #define PORT_STATUS_FLOW_CTRL BIT(4)
#define PORT_PCS_CTRL 0x01 #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 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_6085 0x04a0
#define PORT_SWITCH_ID_6092 0x0970
#define PORT_SWITCH_ID_6095 0x0950 #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 0x1210
#define PORT_SWITCH_ID_6123_A1 0x1212 #define PORT_SWITCH_ID_6123_A1 0x1212
#define PORT_SWITCH_ID_6123_A2 0x1213 #define PORT_SWITCH_ID_6123_A2 0x1213
...@@ -58,13 +80,38 @@ ...@@ -58,13 +80,38 @@
#define PORT_SWITCH_ID_6165_A2 0x1653 #define PORT_SWITCH_ID_6165_A2 0x1653
#define PORT_SWITCH_ID_6171 0x1710 #define PORT_SWITCH_ID_6171 0x1710
#define PORT_SWITCH_ID_6172 0x1720 #define PORT_SWITCH_ID_6172 0x1720
#define PORT_SWITCH_ID_6175 0x1750
#define PORT_SWITCH_ID_6176 0x1760 #define PORT_SWITCH_ID_6176 0x1760
#define PORT_SWITCH_ID_6182 0x1a60 #define PORT_SWITCH_ID_6182 0x1a60
#define PORT_SWITCH_ID_6185 0x1a70 #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 0x3520
#define PORT_SWITCH_ID_6352_A0 0x3521 #define PORT_SWITCH_ID_6352_A0 0x3521
#define PORT_SWITCH_ID_6352_A1 0x3522 #define PORT_SWITCH_ID_6352_A1 0x3522
#define PORT_CONTROL 0x04 #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_MASK 0x03
#define PORT_CONTROL_STATE_DISABLED 0x00 #define PORT_CONTROL_STATE_DISABLED 0x00
#define PORT_CONTROL_STATE_BLOCKING 0x01 #define PORT_CONTROL_STATE_BLOCKING 0x01
...@@ -74,15 +121,32 @@ ...@@ -74,15 +121,32 @@
#define PORT_BASE_VLAN 0x06 #define PORT_BASE_VLAN 0x06
#define PORT_DEFAULT_VLAN 0x07 #define PORT_DEFAULT_VLAN 0x07
#define PORT_CONTROL_2 0x08 #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 0x09
#define PORT_RATE_CONTROL_2 0x0a #define PORT_RATE_CONTROL_2 0x0a
#define PORT_ASSOC_VECTOR 0x0b #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_LO 0x10
#define PORT_IN_DISCARD_HI 0x11 #define PORT_IN_DISCARD_HI 0x11
#define PORT_IN_FILTERED 0x12 #define PORT_IN_FILTERED 0x12
#define PORT_OUT_FILTERED 0x13 #define PORT_OUT_FILTERED 0x13
#define PORT_TAG_REGMAP_0123 0x19 #define PORT_TAG_REGMAP_0123 0x18
#define PORT_TAG_REGMAP_4567 0x1a #define PORT_TAG_REGMAP_4567 0x19
#define REG_GLOBAL 0x1b #define REG_GLOBAL 0x1b
#define GLOBAL_STATUS 0x00 #define GLOBAL_STATUS 0x00
...@@ -117,6 +181,7 @@ ...@@ -117,6 +181,7 @@
#define GLOBAL_VTU_DATA_4_7 0x08 #define GLOBAL_VTU_DATA_4_7 0x08
#define GLOBAL_VTU_DATA_8_11 0x09 #define GLOBAL_VTU_DATA_8_11 0x09
#define GLOBAL_ATU_CONTROL 0x0a #define GLOBAL_ATU_CONTROL 0x0a
#define GLOBAL_ATU_CONTROL_LEARN2ALL BIT(3)
#define GLOBAL_ATU_OP 0x0b #define GLOBAL_ATU_OP 0x0b
#define GLOBAL_ATU_OP_BUSY BIT(15) #define GLOBAL_ATU_OP_BUSY BIT(15)
#define GLOBAL_ATU_OP_NOP (0 << 12) #define GLOBAL_ATU_OP_NOP (0 << 12)
...@@ -151,7 +216,15 @@ ...@@ -151,7 +216,15 @@
#define GLOBAL_IEEE_PRI 0x18 #define GLOBAL_IEEE_PRI 0x18
#define GLOBAL_CORE_TAG_TYPE 0x19 #define GLOBAL_CORE_TAG_TYPE 0x19
#define GLOBAL_MONITOR_CONTROL 0x1a #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 0x1c
#define GLOBAL_CONTROL_2_NO_CASCADE 0xe000
#define GLOBAL_CONTROL_2_MULTIPLE_CASCADE 0xf000
#define GLOBAL_STATS_OP 0x1d #define GLOBAL_STATS_OP 0x1d
#define GLOBAL_STATS_OP_BUSY BIT(15) #define GLOBAL_STATS_OP_BUSY BIT(15)
#define GLOBAL_STATS_OP_NOP (0 << 12) #define GLOBAL_STATS_OP_NOP (0 << 12)
...@@ -172,9 +245,20 @@ ...@@ -172,9 +245,20 @@
#define GLOBAL2_MGMT_EN_0X 0x03 #define GLOBAL2_MGMT_EN_0X 0x03
#define GLOBAL2_FLOW_CONTROL 0x04 #define GLOBAL2_FLOW_CONTROL 0x04
#define GLOBAL2_SWITCH_MGMT 0x05 #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 0x06
#define GLOBAL2_DEVICE_MAPPING_UPDATE BIT(15)
#define GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT 8
#define GLOBAL2_TRUNK_MASK 0x07 #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 0x08
#define GLOBAL2_TRUNK_MAPPING_UPDATE BIT(15)
#define GLOBAL2_TRUNK_MAPPING_ID_SHIFT 11
#define GLOBAL2_INGRESS_OP 0x09 #define GLOBAL2_INGRESS_OP 0x09
#define GLOBAL2_INGRESS_DATA 0x0a #define GLOBAL2_INGRESS_DATA 0x0a
#define GLOBAL2_PVT_ADDR 0x0b #define GLOBAL2_PVT_ADDR 0x0b
...@@ -183,6 +267,10 @@ ...@@ -183,6 +267,10 @@
#define GLOBAL2_SWITCH_MAC_BUSY BIT(15) #define GLOBAL2_SWITCH_MAC_BUSY BIT(15)
#define GLOBAL2_ATU_STATS 0x0e #define GLOBAL2_ATU_STATS 0x0e
#define GLOBAL2_PRIO_OVERRIDE 0x0f #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 0x14
#define GLOBAL2_EEPROM_OP_BUSY BIT(15) #define GLOBAL2_EEPROM_OP_BUSY BIT(15)
#define GLOBAL2_EEPROM_OP_LOAD BIT(11) #define GLOBAL2_EEPROM_OP_LOAD BIT(11)
...@@ -260,14 +348,14 @@ struct mv88e6xxx_hw_stat { ...@@ -260,14 +348,14 @@ struct mv88e6xxx_hw_stat {
}; };
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active); 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_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 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_read(struct dsa_switch *ds, int addr, int reg);
int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
int reg, u16 val); int reg, u16 val);
int mv88e6xxx_reg_write(struct dsa_switch *ds, 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_direct(struct dsa_switch *ds, u8 *addr);
int mv88e6xxx_set_addr_indirect(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); 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); ...@@ -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, void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
struct ethtool_regs *regs, void *_p); struct ethtool_regs *regs, void *_p);
int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp); 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_load_wait(struct dsa_switch *ds);
int mv88e6xxx_eeprom_busy_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); int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum);
......
...@@ -810,12 +810,19 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, ...@@ -810,12 +810,19 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
return 0; 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) int dsa_slave_suspend(struct net_device *slave_dev)
{ {
struct dsa_slave_priv *p = netdev_priv(slave_dev); struct dsa_slave_priv *p = netdev_priv(slave_dev);
netif_device_detach(slave_dev);
if (p->phy) { if (p->phy) {
phy_stop(p->phy); phy_stop(p->phy);
p->old_pause = -1; p->old_pause = -1;
...@@ -861,6 +868,9 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent, ...@@ -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->netdev_ops = &dsa_slave_netdev_ops;
slave_dev->swdev_ops = &dsa_slave_swdev_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); SET_NETDEV_DEV(slave_dev, parent);
slave_dev->dev.of_node = ds->pd->port_dn[port]; slave_dev->dev.of_node = ds->pd->port_dn[port];
slave_dev->vlan_features = master->vlan_features; slave_dev->vlan_features = master->vlan_features;
......
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