diff options
author | David S. Miller <davem@davemloft.net> | 2016-04-18 00:54:15 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-18 00:54:15 +0200 |
commit | ccd37cffe39d7d4f1c1efcd42ec829ec16c7db66 (patch) | |
tree | 0ed8e7835063165c4c28e55059036dbb92e59336 | |
parent | Merge branch 'nfp-next' (diff) | |
parent | net: dsa: mv88e6xxx: remove switch ID from ps (diff) | |
download | linux-ccd37cffe39d7d4f1c1efcd42ec829ec16c7db66.tar.xz linux-ccd37cffe39d7d4f1c1efcd42ec829ec16c7db66.zip |
Merge branch 'dsa-mv88e6xxx-switch-factorization'
Vivien Didelot says:
====================
net: dsa: mv88e6xxx: factorize switch info
This patchset factorizes the mv88e6xxx code by sharing a new extendable
info structure to store static data such as switch family, product
number, number of ports, number of databases and the name.
The next step is to add a "flags" bitmap member to the info structure in
order to simplify the shared code with a feature-based logic instead of
checking their family/ID.
This is a step forward having a single mv88e6xxx driver supporting many
similar devices, like any usual Linux driver.
Changes v3 -> v4:
- constify probed name in DSA
- rebase patchset above conflicting commit 48ace4e
Changes v2 -> v3:
- update commit messages and add Andrew's tags
- keep the info lookup code in a separated function
- split the single switch ID reading in probe in a new commit
Changes v1 -> v2:
- define PORT_SWITCH_ID_PROD_NUM_* values
- use plain struct mv88e6xxx_info
- remove non used yet ps->rev
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 6 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6060.c | 10 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6123.c | 51 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6131.c | 59 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6171.c | 42 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6352.c | 61 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.c | 215 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.h | 97 | ||||
-rw-r--r-- | include/net/dsa.h | 5 | ||||
-rw-r--r-- | net/dsa/dsa.c | 6 |
10 files changed, 247 insertions, 305 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 7a5f0ef46bd6..448deb59b9a4 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -135,9 +135,9 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds) return BCM_SF2_STATS_SIZE; } -static char *bcm_sf2_sw_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **_priv) +static const char *bcm_sf2_sw_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **_priv) { struct bcm_sf2_priv *priv; diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 92cebab9383e..e36b40886bd8 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -51,7 +51,7 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) return __ret; \ }) -static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr) +static const char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr) { int ret; @@ -69,13 +69,13 @@ static char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr) return NULL; } -static char *mv88e6060_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **_priv) +static const char *mv88e6060_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **_priv) { struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); struct mv88e6060_priv *priv; - char *name; + const char *name; name = mv88e6060_get_name(bus, sw_addr); if (name) { diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 140e44e50e8a..534ebc84de84 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -17,21 +17,31 @@ #include <net/dsa.h> #include "mv88e6xxx.h" -static const struct mv88e6xxx_switch_id mv88e6123_table[] = { - { PORT_SWITCH_ID_6123, "Marvell 88E6123" }, - { PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)" }, - { PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)" }, - { PORT_SWITCH_ID_6161, "Marvell 88E6161" }, - { PORT_SWITCH_ID_6161_A1, "Marvell 88E6161 (A1)" }, - { PORT_SWITCH_ID_6161_A2, "Marvell 88E6161 (A2)" }, - { PORT_SWITCH_ID_6165, "Marvell 88E6165" }, - { PORT_SWITCH_ID_6165_A1, "Marvell 88E6165 (A1)" }, - { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" }, +static const struct mv88e6xxx_info mv88e6123_table[] = { + { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6123, + .family = MV88E6XXX_FAMILY_6165, + .name = "Marvell 88E6123", + .num_databases = 4096, + .num_ports = 3, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6161, + .family = MV88E6XXX_FAMILY_6165, + .name = "Marvell 88E6161", + .num_databases = 4096, + .num_ports = 6, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6165, + .family = MV88E6XXX_FAMILY_6165, + .name = "Marvell 88E6165", + .num_databases = 4096, + .num_ports = 6, + } }; -static char *mv88e6123_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **priv) +static const char *mv88e6123_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6123_table, @@ -76,27 +86,12 @@ static int mv88e6123_setup_global(struct dsa_switch *ds) static int mv88e6123_setup(struct dsa_switch *ds) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ps->ds = ds; - ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; - switch (ps->id) { - case PORT_SWITCH_ID_6123: - ps->num_ports = 3; - break; - case PORT_SWITCH_ID_6161: - case PORT_SWITCH_ID_6165: - ps->num_ports = 6; - break; - default: - return -ENODEV; - } - ret = mv88e6xxx_switch_reset(ds, false); if (ret < 0) return ret; diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 34d297b65040..c3eb9a884cfd 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -17,17 +17,37 @@ #include <net/dsa.h> #include "mv88e6xxx.h" -static const struct mv88e6xxx_switch_id mv88e6131_table[] = { - { PORT_SWITCH_ID_6085, "Marvell 88E6085" }, - { PORT_SWITCH_ID_6095, "Marvell 88E6095/88E6095F" }, - { PORT_SWITCH_ID_6131, "Marvell 88E6131" }, - { PORT_SWITCH_ID_6131_B2, "Marvell 88E6131 (B2)" }, - { PORT_SWITCH_ID_6185, "Marvell 88E6185" }, +static const struct mv88e6xxx_info mv88e6131_table[] = { + { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6095, + .family = MV88E6XXX_FAMILY_6095, + .name = "Marvell 88E6095/88E6095F", + .num_databases = 256, + .num_ports = 11, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6085, + .family = MV88E6XXX_FAMILY_6097, + .name = "Marvell 88E6085", + .num_databases = 4096, + .num_ports = 10, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6131, + .family = MV88E6XXX_FAMILY_6185, + .name = "Marvell 88E6131", + .num_databases = 256, + .num_ports = 8, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6185, + .family = MV88E6XXX_FAMILY_6185, + .name = "Marvell 88E6185", + .num_databases = 256, + .num_ports = 10, + } }; -static char *mv88e6131_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **priv) +static const char *mv88e6131_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6131_table, @@ -98,33 +118,14 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) static int mv88e6131_setup(struct dsa_switch *ds) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ps->ds = ds; - ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; mv88e6xxx_ppu_state_init(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6085: - case PORT_SWITCH_ID_6185: - ps->num_ports = 10; - break; - case PORT_SWITCH_ID_6095: - ps->num_ports = 11; - break; - case PORT_SWITCH_ID_6131: - case PORT_SWITCH_ID_6131_B2: - ps->num_ports = 8; - break; - default: - return -ENODEV; - } - ret = mv88e6xxx_switch_reset(ds, false); if (ret < 0) return ret; @@ -140,7 +141,7 @@ static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - if (port >= 0 && port < ps->num_ports) + if (port >= 0 && port < ps->info->num_ports) return port; return -EINVAL; diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index b7af2b78f8ee..841ffe14ef75 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -17,16 +17,37 @@ #include <net/dsa.h> #include "mv88e6xxx.h" -static const struct mv88e6xxx_switch_id mv88e6171_table[] = { - { PORT_SWITCH_ID_6171, "Marvell 88E6171" }, - { PORT_SWITCH_ID_6175, "Marvell 88E6175" }, - { PORT_SWITCH_ID_6350, "Marvell 88E6350" }, - { PORT_SWITCH_ID_6351, "Marvell 88E6351" }, +static const struct mv88e6xxx_info mv88e6171_table[] = { + { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6171, + .family = MV88E6XXX_FAMILY_6351, + .name = "Marvell 88E6171", + .num_databases = 4096, + .num_ports = 7, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6175, + .family = MV88E6XXX_FAMILY_6351, + .name = "Marvell 88E6175", + .num_databases = 4096, + .num_ports = 7, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6350, + .family = MV88E6XXX_FAMILY_6351, + .name = "Marvell 88E6350", + .num_databases = 4096, + .num_ports = 7, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6351, + .family = MV88E6XXX_FAMILY_6351, + .name = "Marvell 88E6351", + .num_databases = 4096, + .num_ports = 7, + } }; -static char *mv88e6171_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **priv) +static const char *mv88e6171_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6171_table, @@ -73,17 +94,12 @@ static int mv88e6171_setup_global(struct dsa_switch *ds) static int mv88e6171_setup(struct dsa_switch *ds) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ps->ds = ds; - ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; - ps->num_ports = 7; - ret = mv88e6xxx_switch_reset(ds, true); if (ret < 0) return ret; diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index e8cb03fad21a..4afc24df56b8 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -22,24 +22,49 @@ #include <net/dsa.h> #include "mv88e6xxx.h" -static const struct mv88e6xxx_switch_id mv88e6352_table[] = { - { PORT_SWITCH_ID_6172, "Marvell 88E6172" }, - { PORT_SWITCH_ID_6176, "Marvell 88E6176" }, - { PORT_SWITCH_ID_6240, "Marvell 88E6240" }, - { PORT_SWITCH_ID_6320, "Marvell 88E6320" }, - { PORT_SWITCH_ID_6320_A1, "Marvell 88E6320 (A1)" }, - { PORT_SWITCH_ID_6320_A2, "Marvell 88e6320 (A2)" }, - { PORT_SWITCH_ID_6321, "Marvell 88E6321" }, - { PORT_SWITCH_ID_6321_A1, "Marvell 88E6321 (A1)" }, - { PORT_SWITCH_ID_6321_A2, "Marvell 88e6321 (A2)" }, - { PORT_SWITCH_ID_6352, "Marvell 88E6352" }, - { PORT_SWITCH_ID_6352_A0, "Marvell 88E6352 (A0)" }, - { PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" }, +static const struct mv88e6xxx_info mv88e6352_table[] = { + { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6320, + .family = MV88E6XXX_FAMILY_6320, + .name = "Marvell 88E6320", + .num_databases = 4096, + .num_ports = 7, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6321, + .family = MV88E6XXX_FAMILY_6320, + .name = "Marvell 88E6321", + .num_databases = 4096, + .num_ports = 7, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6172, + .family = MV88E6XXX_FAMILY_6352, + .name = "Marvell 88E6172", + .num_databases = 4096, + .num_ports = 7, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6176, + .family = MV88E6XXX_FAMILY_6352, + .name = "Marvell 88E6176", + .num_databases = 4096, + .num_ports = 7, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6240, + .family = MV88E6XXX_FAMILY_6352, + .name = "Marvell 88E6240", + .num_databases = 4096, + .num_ports = 7, + }, { + .prod_num = PORT_SWITCH_ID_PROD_NUM_6352, + .family = MV88E6XXX_FAMILY_6352, + .name = "Marvell 88E6352", + .num_databases = 4096, + .num_ports = 7, + } }; -static char *mv88e6352_drv_probe(struct device *dsa_dev, - struct device *host_dev, - int sw_addr, void **priv) +static const char *mv88e6352_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, mv88e6352_table, @@ -87,14 +112,10 @@ static int mv88e6352_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ps->ds = ds; - ret = mv88e6xxx_setup_common(ds); if (ret < 0) return ret; - ps->num_ports = 7; - mutex_init(&ps->eeprom_mutex); ret = mv88e6xxx_switch_reset(ds, true); diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index b018f20829fb..1dd525d8dc0a 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -402,135 +402,63 @@ 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; + return ps->info->family == MV88E6XXX_FAMILY_6065; } 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; + return ps->info->family == MV88E6XXX_FAMILY_6095; } 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; + return ps->info->family == MV88E6XXX_FAMILY_6097; } 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; + return ps->info->family == MV88E6XXX_FAMILY_6165; } 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; + return ps->info->family == MV88E6XXX_FAMILY_6185; } static bool mv88e6xxx_6320_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - switch (ps->id) { - case PORT_SWITCH_ID_6320: - case PORT_SWITCH_ID_6321: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6320; } 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; + return ps->info->family == MV88E6XXX_FAMILY_6351; } 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_6172: - case PORT_SWITCH_ID_6176: - case PORT_SWITCH_ID_6240: - case PORT_SWITCH_ID_6352: - return true; - } - return false; + return ps->info->family == MV88E6XXX_FAMILY_6352; } static unsigned int mv88e6xxx_num_databases(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - /* The following devices have 4-bit identifiers for 16 databases */ - if (ps->id == PORT_SWITCH_ID_6061) - return 16; - - /* The following devices have 6-bit identifiers for 64 databases */ - if (ps->id == PORT_SWITCH_ID_6065) - return 64; - - /* The following devices have 8-bit identifiers for 256 databases */ - if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) - return 256; - - /* The following devices have 12-bit identifiers for 4096 databases */ - if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || - mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) - return 4096; - - return 0; + return ps->info->num_databases; } static bool mv88e6xxx_has_fid_reg(struct dsa_switch *ds) @@ -606,7 +534,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, reg |= PORT_PCS_CTRL_DUPLEX_FULL; if ((mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds)) && - (port >= ps->num_ports - 2)) { + (port >= ps->info->num_ports - 2)) { if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) @@ -1187,7 +1115,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct net_device *bridge = ps->ports[port].bridge_dev; - const u16 mask = (1 << ps->num_ports) - 1; + const u16 mask = (1 << ps->info->num_ports) - 1; u16 output_ports = 0; int reg; int i; @@ -1196,7 +1124,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port) if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { output_ports = mask; } else { - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { /* allow sending frames to every group member */ if (bridge && ps->ports[i].bridge_dev == bridge) output_ports |= BIT(i); @@ -1337,7 +1265,7 @@ static int _mv88e6xxx_vtu_stu_data_read(struct dsa_switch *ds, regs[i] = ret; } - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { unsigned int shift = (i % 4) * 4 + nibble_offset; u16 reg = regs[i / 4]; @@ -1356,7 +1284,7 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds, int i; int ret; - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { unsigned int shift = (i % 4) * 4 + nibble_offset; u8 data = entry->data[i]; @@ -1688,7 +1616,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid) bitmap_zero(fid_bitmap, MV88E6XXX_N_FID); /* Set every FID bit used by the (un)bridged ports */ - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { err = _mv88e6xxx_port_fid_get(ds, i, fid); if (err) return err; @@ -1738,7 +1666,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid, return err; /* exclude all ports except the CPU and DSA ports */ - for (i = 0; i < ps->num_ports; ++i) + for (i = 0; i < ps->info->num_ports; ++i) vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i) ? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED : GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; @@ -1827,7 +1755,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, if (vlan.vid > vid_end) break; - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i)) continue; @@ -1976,7 +1904,7 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) /* keep the VLAN unless all ports are excluded */ vlan.valid = false; - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)) continue; @@ -2285,11 +2213,11 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); /* Get or create the bridge FID and assign it to the port */ - for (i = 0; i < ps->num_ports; ++i) + for (i = 0; i < ps->info->num_ports; ++i) if (ps->ports[i].bridge_dev == bridge) break; - if (i < ps->num_ports) + if (i < ps->info->num_ports) err = _mv88e6xxx_port_fid_get(ds, i, &fid); else err = _mv88e6xxx_fid_new(ds, &fid); @@ -2303,7 +2231,7 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, /* Assign the bridge and remap each port's VLANTable */ ps->ports[port].bridge_dev = bridge; - for (i = 0; i < ps->num_ports; ++i) { + for (i = 0; i < ps->info->num_ports; ++i) { if (ps->ports[i].bridge_dev == bridge) { err = _mv88e6xxx_port_based_vlan_map(ds, i); if (err) @@ -2334,7 +2262,7 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port) /* Unassign the bridge and remap each port's VLANTable */ ps->ports[port].bridge_dev = NULL; - for (i = 0; i < ps->num_ports; ++i) + for (i = 0; i < ps->info->num_ports; ++i) if (i == port || ps->ports[i].bridge_dev == bridge) if (_mv88e6xxx_port_based_vlan_map(ds, i)) netdev_warn(ds->ports[i], "failed to remap\n"); @@ -2353,7 +2281,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work) mutex_lock(&ps->smi_mutex); - for (port = 0; port < ps->num_ports; ++port) + for (port = 0; port < ps->info->num_ports; ++port) if (test_and_clear_bit(port, ps->port_state_update_mask) && _mv88e6xxx_port_state(ds, port, ps->ports[port].state)) netdev_warn(ds->ports[port], "failed to update state to %s\n", @@ -2685,7 +2613,7 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds) int ret; int i; - for (i = 0; i < ps->num_ports; i++) { + for (i = 0; i < ps->info->num_ports; i++) { ret = mv88e6xxx_setup_port(ds, i); if (ret < 0) return ret; @@ -2700,10 +2628,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) ps->ds = ds; mutex_init(&ps->smi_mutex); - ps->id = mv88e6xxx_reg_read(ds, REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; - if (ps->id < 0) - return ps->id; - INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); return 0; @@ -2796,7 +2720,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_TRUNK_MASK, 0x8000 | (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) | - ((1 << ps->num_ports) - 1)); + ((1 << ps->info->num_ports) - 1)); if (err) goto unlock; } @@ -2849,7 +2773,7 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) * ingress rate limit registers to their initial * state. */ - for (i = 0; i < ps->num_ports; i++) { + for (i = 0; i < ps->info->num_ports; i++) { err = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_INGRESS_OP, 0x9000 | (i << 8)); @@ -2894,7 +2818,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active) mutex_lock(&ps->smi_mutex); /* Set all ports to the disabled state. */ - for (i = 0; i < ps->num_ports; i++) { + for (i = 0; i < ps->info->num_ports; i++) { ret = _mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_CONTROL); if (ret < 0) goto unlock; @@ -2977,7 +2901,7 @@ static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - if (port >= 0 && port < ps->num_ports) + if (port >= 0 && port < ps->info->num_ports) return port; return -EINVAL; } @@ -3173,61 +3097,60 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) } #endif /* CONFIG_NET_DSA_HWMON */ -static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr, - const struct mv88e6xxx_switch_id *table, - unsigned int num) +static const struct mv88e6xxx_info * +mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table, + unsigned int num) { - int i, ret; - - if (!bus) - return NULL; - - ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); - if (ret < 0) - return NULL; + int i; - /* Look up the exact switch ID */ for (i = 0; i < num; ++i) - if (table[i].id == ret) - return table[i].name; - - /* Look up only the product number */ - for (i = 0; i < num; ++i) { - if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) { - dev_warn(&bus->dev, - "unknown revision %d, using base switch 0x%x\n", - ret & PORT_SWITCH_ID_REV_MASK, - ret & PORT_SWITCH_ID_PROD_NUM_MASK); - return table[i].name; - } - } + if (table[i].prod_num == prod_num) + return &table[i]; return NULL; } -char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv, - const struct mv88e6xxx_switch_id *table, - unsigned int num) +const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr, void **priv, + const struct mv88e6xxx_info *table, + unsigned int num) { + const struct mv88e6xxx_info *info; struct mv88e6xxx_priv_state *ps; - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); - char *name; + struct mii_bus *bus; + const char *name; + int id, prod_num, rev; + bus = dsa_host_dev_to_mii_bus(host_dev); if (!bus) return NULL; - name = mv88e6xxx_lookup_name(bus, sw_addr, table, num); - if (name) { - ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); - if (!ps) - return NULL; - *priv = ps; - ps->bus = dsa_host_dev_to_mii_bus(host_dev); - if (!ps->bus) - return NULL; - ps->sw_addr = sw_addr; - } + id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); + if (id < 0) + return NULL; + + prod_num = (id & 0xfff0) >> 4; + rev = id & 0x000f; + + info = mv88e6xxx_lookup_info(prod_num, table, num); + if (!info) + return NULL; + + name = info->name; + + ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL); + if (!ps) + return NULL; + + ps->bus = bus; + ps->sw_addr = sw_addr; + ps->info = info; + + *priv = ps; + + dev_info(&ps->bus->dev, "switch 0x%x probed: %s, revision %u\n", + prod_num, name, rev); + return name; } diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 0debb9f3cf0a..0dbe2d1779dd 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -68,52 +68,23 @@ #define PORT_PCS_CTRL_UNFORCED 0x03 #define PORT_PAUSE_CTRL 0x02 #define PORT_SWITCH_ID 0x03 -#define PORT_SWITCH_ID_PROD_NUM_MASK 0xfff0 -#define PORT_SWITCH_ID_REV_MASK 0x000f -#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_6131 0x1060 -#define PORT_SWITCH_ID_6131_B2 0x1066 -#define PORT_SWITCH_ID_6152 0x1a40 -#define PORT_SWITCH_ID_6155 0x1a50 -#define PORT_SWITCH_ID_6161 0x1610 -#define PORT_SWITCH_ID_6161_A1 0x1612 -#define PORT_SWITCH_ID_6161_A2 0x1613 -#define PORT_SWITCH_ID_6165 0x1650 -#define PORT_SWITCH_ID_6165_A1 0x1652 -#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 0x1150 -#define PORT_SWITCH_ID_6320_A1 0x1151 -#define PORT_SWITCH_ID_6320_A2 0x1152 -#define PORT_SWITCH_ID_6321 0x3100 -#define PORT_SWITCH_ID_6321_A1 0x3101 -#define PORT_SWITCH_ID_6321_A2 0x3102 -#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_SWITCH_ID_PROD_NUM_6085 0x04a +#define PORT_SWITCH_ID_PROD_NUM_6095 0x095 +#define PORT_SWITCH_ID_PROD_NUM_6131 0x106 +#define PORT_SWITCH_ID_PROD_NUM_6320 0x115 +#define PORT_SWITCH_ID_PROD_NUM_6123 0x121 +#define PORT_SWITCH_ID_PROD_NUM_6161 0x161 +#define PORT_SWITCH_ID_PROD_NUM_6165 0x165 +#define PORT_SWITCH_ID_PROD_NUM_6171 0x171 +#define PORT_SWITCH_ID_PROD_NUM_6172 0x172 +#define PORT_SWITCH_ID_PROD_NUM_6175 0x175 +#define PORT_SWITCH_ID_PROD_NUM_6176 0x176 +#define PORT_SWITCH_ID_PROD_NUM_6185 0x1a7 +#define PORT_SWITCH_ID_PROD_NUM_6240 0x240 +#define PORT_SWITCH_ID_PROD_NUM_6321 0x310 +#define PORT_SWITCH_ID_PROD_NUM_6352 0x352 +#define PORT_SWITCH_ID_PROD_NUM_6350 0x371 +#define PORT_SWITCH_ID_PROD_NUM_6351 0x375 #define PORT_CONTROL 0x04 #define PORT_CONTROL_USE_CORE_TAG BIT(15) #define PORT_CONTROL_DROP_ON_LOCK BIT(14) @@ -367,9 +338,24 @@ #define MV88E6XXX_N_FID 4096 -struct mv88e6xxx_switch_id { - u16 id; - char *name; +enum mv88e6xxx_family { + MV88E6XXX_FAMILY_NONE, + MV88E6XXX_FAMILY_6065, /* 6031 6035 6061 6065 */ + MV88E6XXX_FAMILY_6095, /* 6092 6095 */ + MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ + MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ + MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ + MV88E6XXX_FAMILY_6320, /* 6320 6321 */ + MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ + MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ +}; + +struct mv88e6xxx_info { + enum mv88e6xxx_family family; + u16 prod_num; + const char *name; + unsigned int num_databases; + unsigned int num_ports; }; struct mv88e6xxx_atu_entry { @@ -397,6 +383,8 @@ struct mv88e6xxx_priv_port { }; struct mv88e6xxx_priv_state { + const struct mv88e6xxx_info *info; + /* The dsa_switch this private structure is related to */ struct dsa_switch *ds; @@ -438,9 +426,6 @@ struct mv88e6xxx_priv_state { */ struct mutex eeprom_mutex; - int id; /* switch product id */ - int num_ports; /* number of switch ports */ - struct mv88e6xxx_priv_port ports[DSA_MAX_PORTS]; DECLARE_BITMAP(port_state_update_mask, DSA_MAX_PORTS); @@ -462,10 +447,10 @@ struct mv88e6xxx_hw_stat { }; int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active); -char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv, - const struct mv88e6xxx_switch_id *table, - unsigned int num); +const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev, + int sw_addr, void **priv, + const struct mv88e6xxx_info *table, + unsigned int num); int mv88e6xxx_setup_ports(struct dsa_switch *ds); int mv88e6xxx_setup_common(struct dsa_switch *ds); diff --git a/include/net/dsa.h b/include/net/dsa.h index 689ebd3542ba..c4bc42bd3538 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -217,8 +217,9 @@ struct dsa_switch_driver { /* * Probing and setup. */ - char *(*probe)(struct device *dsa_dev, struct device *host_dev, - int sw_addr, void **priv); + const char *(*probe)(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv); int (*setup)(struct dsa_switch *ds); int (*set_addr)(struct dsa_switch *ds, u8 *addr); u32 (*get_phy_flags)(struct dsa_switch *ds, int port); diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 60ea98481806..efa612f0ab9b 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -52,11 +52,11 @@ EXPORT_SYMBOL_GPL(unregister_switch_driver); static struct dsa_switch_driver * dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr, - char **_name, void **priv) + const char **_name, void **priv) { struct dsa_switch_driver *ret; struct list_head *list; - char *name; + const char *name; ret = NULL; name = NULL; @@ -383,7 +383,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, struct dsa_switch_driver *drv; struct dsa_switch *ds; int ret; - char *name; + const char *name; void *priv; /* |