Message ID | 20090310102805.GO4738@xi.wantstofly.org |
---|---|
State | RFC, archived |
Delegated to: | David Miller |
Headers | show |
Lennert Buytenhek wrote: > On Fri, Mar 06, 2009 at 08:49:19AM -0700, Gary Thomas wrote: > >> After much experimentation, I finally found out what was >> wrong. Basically, the trunk masks have 8 bits on the 6131, >> but 11 bits on the 609x and this wasn't being handled. Once >> the trunk masks were reset by the init code, there was no >> path to the CPU port from the LAN ports :-( The attached >> patch is what I've ended up with. It works, at least for >> a single switch. > > Cool. How about the patch below then? > This looks fine to me - is this part safe on the smaller parts (6131, etc)? I wasn't sure about setting those "reserved" bits on other chips. > @@ -136,7 +138,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) > * Clear all trunk masks. > */ > for (i = 0; i < 8; i++) > - REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff); > + REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7ff); > > /* > * Clear all trunk mappings. > >> Next, I need to get it to work with multiple switches (separate >> ethernet controllers, same/shared MII bus), > > That should be easy -- the DSA driver only accesses MII buses via > phylib, and that does the required locking, etc. Also, we've > verified that multi-chip addressing mode works. > > >> as well as a cascaded switch. > > That's a bit trickier, but also not entirely hard: > - Instead of the CPU port concept, we'll have to use the port number > that brings us one hop closer to the CPU (i.e. the upstream port). > - Assign each chip a DSA device address (instead of always setting it > to zero). > - Populate the 'DSA device address -> port' mapping table for each > switch. > - Enable DSA tagging and flooding of unknown unicasts and multicasts > on all inter-switch links and not just on the CPU port on switch 0. > > I don't think it makes sense to implement Dijkstra in the kernel, so > it's probably easiest to just pass in a precomputed NxN array of how > to go from which switch to which switch via which port, along with a > separate DSA port list for each switch chip. > > I don't have multi-switch chip setups myself, or I would have > implemented this already. But I can whip up some patches to try.. > That would be great. What I'd like to figure out is a way to provide that mapping (static from the driver point of view), much like the current "port_names[]" table now. For my particular setup, there are two cases (on the same board): Switch 1 - ports 1..8 Switch 2 - ports 9..16 Switch 3 - ports 17..24 (cascaded off of Switch 2) Thus, the only access to Switch 3 and its ports is indirect via Switch 2. Presumably, one could have a multiple cascade, so this structure should be considered from the start. Thanks for your help
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 49211b3..c51b554 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -41,13 +41,13 @@ config NET_DSA_MV88E6XXX_NEED_PPU default n config NET_DSA_MV88E6131 - bool "Marvell 88E6131 ethernet switch chip support" + bool "Marvell 88E6095/6095F/6131 ethernet switch chip support" select NET_DSA_MV88E6XXX select NET_DSA_MV88E6XXX_NEED_PPU select NET_DSA_TAG_DSA ---help--- - This enables support for the Marvell 88E6131 ethernet switch - chip. + This enables support for the Marvell 88E6095/6095F/6131 + ethernet switch chips. config NET_DSA_MV88E6123_61_65 bool "Marvell 88E6123/6161/6165 ethernet switch chip support" diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c index 374d46a..bb7d450 100644 --- a/net/dsa/mv88e6131.c +++ b/net/dsa/mv88e6131.c @@ -21,6 +21,8 @@ static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); if (ret >= 0) { ret &= 0xfff0; + if (ret == 0x0950) + return "Marvell 88E6095/88E6095F"; if (ret == 0x1060) return "Marvell 88E6131"; } @@ -36,7 +38,7 @@ static int mv88e6131_switch_reset(struct dsa_switch *ds) /* * Set all ports to the disabled state. */ - for (i = 0; i < 8; i++) { + for (i = 0; i < 11; i++) { ret = REG_READ(REG_PORT(i), 0x04); REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); } @@ -136,7 +138,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) * Clear all trunk masks. */ for (i = 0; i < 8; i++) - REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff); + REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7ff); /* * Clear all trunk mappings. @@ -159,9 +161,13 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) /* * MAC Forcing register: don't force link, speed, duplex - * or flow control state to any particular values. + * or flow control state to any particular values on physical + * ports, but force the CPU port to 1000 Mb/s full duplex. */ - REG_WRITE(addr, 0x01, 0x0003); + if (p == ds->cpu_port) + REG_WRITE(addr, 0x01, 0x003e); + else + REG_WRITE(addr, 0x01, 0x0003); /* * Port Control: disable Core Tag, disable Drop-on-Lock, @@ -268,7 +274,7 @@ static int mv88e6131_setup(struct dsa_switch *ds) if (ret < 0) return ret; - for (i = 0; i < 6; i++) { + for (i = 0; i < 11; i++) { ret = mv88e6131_setup_port(ds, i); if (ret < 0) return ret; @@ -279,7 +285,7 @@ static int mv88e6131_setup(struct dsa_switch *ds) static int mv88e6131_port_to_phy_addr(int port) { - if (port >= 0 && port != 3 && port <= 7) + if (port >= 0 && port <= 11) return port; return -1; }