diff options
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 33 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6060.c | 47 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6060.h | 11 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6123.c | 74 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6131.c | 112 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6171.c | 68 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6352.c | 98 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.c | 1312 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.h | 141 |
9 files changed, 1005 insertions, 891 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 780f22876538..448deb59b9a4 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -135,8 +135,17 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds) return BCM_SF2_STATS_SIZE; } -static char *bcm_sf2_sw_probe(struct device *host_dev, int sw_addr) +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; + + priv = devm_kzalloc(dsa_dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return NULL; + *_priv = priv; + return "Broadcom Starfighter 2"; } @@ -151,7 +160,7 @@ static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port) * the same VLAN. */ for (i = 0; i < priv->hw_params.num_ports; i++) { - if (!((1 << i) & ds->phys_port_mask)) + if (!((1 << i) & ds->enabled_port_mask)) continue; reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i)); @@ -1000,7 +1009,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) /* Enable all valid ports and disable those unused */ for (port = 0; port < priv->hw_params.num_ports; port++) { /* IMP port receives special treatment */ - if ((1 << port) & ds->phys_port_mask) + if ((1 << port) & ds->enabled_port_mask) bcm_sf2_port_setup(ds, port, NULL); else if (dsa_is_cpu_port(ds, port)) bcm_sf2_imp_setup(ds, port); @@ -1013,11 +1022,12 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such * that we can use the regular SWITCH_MDIO master controller instead. * - * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask - * to have a 1:1 mapping between Port address and PHY address in order - * to utilize the slave_mii_bus instance to read from Port PHYs. This is - * not what we want here, so we initialize phys_mii_mask 0 to always - * utilize the "master" MDIO bus backed by the "mdio-unimac" driver. + * By default, DSA initializes ds->phys_mii_mask to + * ds->enabled_port_mask to have a 1:1 mapping between Port address + * and PHY address in order to utilize the slave_mii_bus instance to + * read from Port PHYs. This is not what we want here, so we + * initialize phys_mii_mask 0 to always utilize the "master" MDIO + * bus backed by the "mdio-unimac" driver. */ if (of_machine_is_compatible("brcm,bcm7445d0")) ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0)); @@ -1275,7 +1285,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds) * bcm_sf2_sw_setup */ for (port = 0; port < DSA_MAX_PORTS; port++) { - if ((1 << port) & ds->phys_port_mask || + if ((1 << port) & ds->enabled_port_mask || dsa_is_cpu_port(ds, port)) bcm_sf2_port_disable(ds, port, NULL); } @@ -1299,7 +1309,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) bcm_sf2_gphy_enable_set(ds, true); for (port = 0; port < DSA_MAX_PORTS; port++) { - if ((1 << port) & ds->phys_port_mask) + if ((1 << port) & ds->enabled_port_mask) bcm_sf2_port_setup(ds, port, NULL); else if (dsa_is_cpu_port(ds, port)) bcm_sf2_imp_setup(ds, port); @@ -1362,8 +1372,7 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port, static struct dsa_switch_driver bcm_sf2_switch_driver = { .tag_protocol = DSA_TAG_PROTO_BRCM, - .priv_size = sizeof(struct bcm_sf2_priv), - .probe = bcm_sf2_sw_probe, + .probe = bcm_sf2_sw_drv_probe, .setup = bcm_sf2_sw_setup, .set_addr = bcm_sf2_sw_set_addr, .get_phy_flags = bcm_sf2_sw_get_phy_flags, diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 0527f485c3dc..e36b40886bd8 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -19,12 +19,9 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); + struct mv88e6060_priv *priv = ds_to_priv(ds); - if (bus == NULL) - return -EINVAL; - - return mdiobus_read_nested(bus, ds->pd->sw_addr + addr, reg); + return mdiobus_read_nested(priv->bus, priv->sw_addr + addr, reg); } #define REG_READ(addr, reg) \ @@ -40,12 +37,9 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg) static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); - - if (bus == NULL) - return -EINVAL; + struct mv88e6060_priv *priv = ds_to_priv(ds); - return mdiobus_write_nested(bus, ds->pd->sw_addr + addr, reg, val); + return mdiobus_write_nested(priv->bus, priv->sw_addr + addr, reg, val); } #define REG_WRITE(addr, reg, val) \ @@ -57,14 +51,10 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) return __ret; \ }) -static char *mv88e6060_probe(struct device *host_dev, int sw_addr) +static const char *mv88e6060_get_name(struct mii_bus *bus, int sw_addr) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); int ret; - if (bus == NULL) - return NULL; - ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID); if (ret >= 0) { if (ret == PORT_SWITCH_ID_6060) @@ -79,6 +69,27 @@ static char *mv88e6060_probe(struct device *host_dev, int sw_addr) return NULL; } +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; + const char *name; + + name = mv88e6060_get_name(bus, sw_addr); + if (name) { + priv = devm_kzalloc(dsa_dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return NULL; + *_priv = priv; + priv->bus = bus; + priv->sw_addr = sw_addr; + } + + return name; +} + static int mv88e6060_switch_reset(struct dsa_switch *ds) { int i; @@ -159,7 +170,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p) REG_WRITE(addr, PORT_VLAN_MAP, ((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) | (dsa_is_cpu_port(ds, p) ? - ds->phys_port_mask : + ds->enabled_port_mask : BIT(ds->dst->cpu_port))); /* Port Association Vector: when learning source addresses @@ -174,8 +185,8 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p) static int mv88e6060_setup(struct dsa_switch *ds) { - int i; int ret; + int i; ret = mv88e6060_switch_reset(ds); if (ret < 0) @@ -238,7 +249,7 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) static struct dsa_switch_driver mv88e6060_switch_driver = { .tag_protocol = DSA_TAG_PROTO_TRAILER, - .probe = mv88e6060_probe, + .probe = mv88e6060_drv_probe, .setup = mv88e6060_setup, .set_addr = mv88e6060_set_addr, .phy_read = mv88e6060_phy_read, diff --git a/drivers/net/dsa/mv88e6060.h b/drivers/net/dsa/mv88e6060.h index cc9b2ed4aff4..10249bd16292 100644 --- a/drivers/net/dsa/mv88e6060.h +++ b/drivers/net/dsa/mv88e6060.h @@ -108,4 +108,15 @@ #define GLOBAL_ATU_MAC_23 0x0e #define GLOBAL_ATU_MAC_45 0x0f +struct mv88e6060_priv { + /* MDIO bus and address on bus to use. When in single chip + * mode, address is 0, and the switch uses multiple addresses + * on the bus. When in multi-chip mode, the switch uses a + * single address which contains two registers used for + * indirect access to more registers. + */ + struct mii_bus *bus; + int sw_addr; +}; + #endif diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c index 69a6f79dcb10..5535a42a6113 100644 --- a/drivers/net/dsa/mv88e6123.c +++ b/drivers/net/dsa/mv88e6123.c @@ -17,26 +17,40 @@ #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_probe(struct device *host_dev, int sw_addr) +static const char *mv88e6123_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { - return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table, - ARRAY_SIZE(mv88e6123_table)); + return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, + mv88e6123_table, + ARRAY_SIZE(mv88e6123_table)); } static int mv88e6123_setup_global(struct dsa_switch *ds) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u32 upstream_port = dsa_upstream_port(ds); int ret; u32 reg; @@ -49,7 +63,9 @@ static int mv88e6123_setup_global(struct dsa_switch *ds) * external PHYs to poll), don't discard packets with * excessive collisions, and mask all interrupt sources. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, 0x0000); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, 0x0000); + if (ret) + return ret; /* Configure the upstream port, and configure the upstream * port as the port to which ingress and egress monitor frames @@ -58,14 +74,15 @@ static int mv88e6123_setup_global(struct dsa_switch *ds) 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); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + if (ret) + return ret; /* Disable remote management for now, and set the switch's * DSA device number. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f); - - return 0; + return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2, + ds->index & 0x1f); } static int mv88e6123_setup(struct dsa_switch *ds) @@ -73,23 +90,13 @@ static int mv88e6123_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ret = mv88e6xxx_setup_common(ds); + ps->ds = ds; + + ret = mv88e6xxx_setup_common(ps); 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); + ret = mv88e6xxx_switch_reset(ps, false); if (ret < 0) return ret; @@ -102,8 +109,7 @@ static int mv88e6123_setup(struct dsa_switch *ds) struct dsa_switch_driver mv88e6123_switch_driver = { .tag_protocol = DSA_TAG_PROTO_EDSA, - .priv_size = sizeof(struct mv88e6xxx_priv_state), - .probe = mv88e6123_probe, + .probe = mv88e6123_drv_probe, .setup = mv88e6123_setup, .set_addr = mv88e6xxx_set_addr_indirect, .phy_read = mv88e6xxx_phy_read, diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 24070287c2bc..357ab794d720 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -17,22 +17,46 @@ #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_probe(struct device *host_dev, int sw_addr) +static const char *mv88e6131_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { - return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table, - ARRAY_SIZE(mv88e6131_table)); + return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, + mv88e6131_table, + ARRAY_SIZE(mv88e6131_table)); } static int mv88e6131_setup_global(struct dsa_switch *ds) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u32 upstream_port = dsa_upstream_port(ds); int ret; u32 reg; @@ -46,11 +70,16 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) * to arbitrate between packet queues, set the maximum frame * size to 1632, and mask all interrupt sources. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, - GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_MAX_FRAME_1632); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, + GLOBAL_CONTROL_PPU_ENABLE | + GLOBAL_CONTROL_MAX_FRAME_1632); + if (ret) + return ret; /* Set the VLAN ethertype to 0x8100. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CORE_TAG_TYPE, 0x8100); + if (ret) + return ret; /* Disable ARP mirroring, and configure the upstream port as * the port to which ingress and egress monitor frames are to @@ -59,31 +88,33 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) 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); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + if (ret) + return ret; /* 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, GLOBAL_CONTROL_2, - GLOBAL_CONTROL_2_MULTIPLE_CASCADE | - (ds->index & 0x1f)); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2, + GLOBAL_CONTROL_2_MULTIPLE_CASCADE | + (ds->index & 0x1f)); else - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, - GLOBAL_CONTROL_2_NO_CASCADE | - (ds->index & 0x1f)); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2, + GLOBAL_CONTROL_2_NO_CASCADE | + (ds->index & 0x1f)); + if (ret) + return ret; /* Force the priority of IGMP/MLD snoop frames and ARP frames * to the highest setting. */ - 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 mv88e6xxx_reg_write(ps, 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); } static int mv88e6131_setup(struct dsa_switch *ds) @@ -91,29 +122,15 @@ static int mv88e6131_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ret = mv88e6xxx_setup_common(ds); + ps->ds = ds; + + ret = mv88e6xxx_setup_common(ps); 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; - } + mv88e6xxx_ppu_state_init(ps); - ret = mv88e6xxx_switch_reset(ds, false); + ret = mv88e6xxx_switch_reset(ps, false); if (ret < 0) return ret; @@ -128,7 +145,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; @@ -159,8 +176,7 @@ mv88e6131_phy_write(struct dsa_switch *ds, struct dsa_switch_driver mv88e6131_switch_driver = { .tag_protocol = DSA_TAG_PROTO_DSA, - .priv_size = sizeof(struct mv88e6xxx_priv_state), - .probe = mv88e6131_probe, + .probe = mv88e6131_drv_probe, .setup = mv88e6131_setup, .set_addr = mv88e6xxx_set_addr_direct, .phy_read = mv88e6131_phy_read, diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 0e62f3b5bc81..f75164dc3bd6 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -17,21 +17,46 @@ #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_probe(struct device *host_dev, int sw_addr) +static const char *mv88e6171_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { - return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table, - ARRAY_SIZE(mv88e6171_table)); + return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, + mv88e6171_table, + ARRAY_SIZE(mv88e6171_table)); } 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; u32 reg; @@ -43,8 +68,11 @@ static int mv88e6171_setup_global(struct dsa_switch *ds) /* Discard packets with excessive collisions, mask all * interrupt sources, enable PPU. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, - GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, + GLOBAL_CONTROL_PPU_ENABLE | + GLOBAL_CONTROL_DISCARD_EXCESS); + if (ret) + return ret; /* Configure the upstream port, and configure the upstream * port as the port to which ingress and egress monitor frames @@ -54,14 +82,15 @@ static int mv88e6171_setup_global(struct dsa_switch *ds) 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); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + if (ret) + return ret; /* Disable remote management for now, and set the switch's * DSA device number. */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f); - - return 0; + return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL_2, + ds->index & 0x1f); } static int mv88e6171_setup(struct dsa_switch *ds) @@ -69,13 +98,13 @@ static int mv88e6171_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ret = mv88e6xxx_setup_common(ds); + ps->ds = ds; + + ret = mv88e6xxx_setup_common(ps); if (ret < 0) return ret; - ps->num_ports = 7; - - ret = mv88e6xxx_switch_reset(ds, true); + ret = mv88e6xxx_switch_reset(ps, true); if (ret < 0) return ret; @@ -88,8 +117,7 @@ static int mv88e6171_setup(struct dsa_switch *ds) struct dsa_switch_driver mv88e6171_switch_driver = { .tag_protocol = DSA_TAG_PROTO_EDSA, - .priv_size = sizeof(struct mv88e6xxx_priv_state), - .probe = mv88e6171_probe, + .probe = mv88e6171_drv_probe, .setup = mv88e6171_setup, .set_addr = mv88e6xxx_set_addr_indirect, .phy_read = mv88e6xxx_phy_read_indirect, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 7f452e4a04a5..c622a1d58480 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -22,29 +22,58 @@ #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_probe(struct device *host_dev, int sw_addr) +static const char *mv88e6352_drv_probe(struct device *dsa_dev, + struct device *host_dev, int sw_addr, + void **priv) { - return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table, - ARRAY_SIZE(mv88e6352_table)); + return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv, + mv88e6352_table, + ARRAY_SIZE(mv88e6352_table)); } 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; u32 reg; @@ -56,8 +85,11 @@ static int mv88e6352_setup_global(struct dsa_switch *ds) /* Discard packets with excessive collisions, * mask all interrupt sources, enable PPU (bit 14, undocumented). */ - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, - GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, + GLOBAL_CONTROL_PPU_ENABLE | + GLOBAL_CONTROL_DISCARD_EXCESS); + if (ret) + return ret; /* Configure the upstream port, and configure the upstream * port as the port to which ingress and egress monitor frames @@ -66,14 +98,14 @@ static int mv88e6352_setup_global(struct dsa_switch *ds) 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); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); + if (ret) + return ret; /* Disable remote management for now, and set the switch's * DSA device number. */ - REG_WRITE(REG_GLOBAL, 0x1c, ds->index & 0x1f); - - return 0; + return mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x1c, ds->index & 0x1f); } static int mv88e6352_setup(struct dsa_switch *ds) @@ -81,15 +113,15 @@ static int mv88e6352_setup(struct dsa_switch *ds) struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ret = mv88e6xxx_setup_common(ds); + ps->ds = ds; + + ret = mv88e6xxx_setup_common(ps); if (ret < 0) return ret; - ps->num_ports = 7; - mutex_init(&ps->eeprom_mutex); - ret = mv88e6xxx_switch_reset(ds, true); + ret = mv88e6xxx_switch_reset(ps, true); if (ret < 0) return ret; @@ -107,7 +139,7 @@ static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr) mutex_lock(&ps->eeprom_mutex); - ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP, + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP, GLOBAL2_EEPROM_OP_READ | (addr & GLOBAL2_EEPROM_OP_ADDR_MASK)); if (ret < 0) @@ -117,7 +149,7 @@ static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr) if (ret < 0) goto error; - ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_EEPROM_DATA); + ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA); error: mutex_unlock(&ps->eeprom_mutex); return ret; @@ -188,9 +220,10 @@ static int mv88e6352_get_eeprom(struct dsa_switch *ds, static int mv88e6352_eeprom_is_readonly(struct dsa_switch *ds) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ret = mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP); + ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP); if (ret < 0) return ret; @@ -208,11 +241,11 @@ static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr, mutex_lock(&ps->eeprom_mutex); - ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_DATA, data); if (ret < 0) goto error; - ret = mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP, + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP, GLOBAL2_EEPROM_OP_WRITE | (addr & GLOBAL2_EEPROM_OP_ADDR_MASK)); if (ret < 0) @@ -302,8 +335,7 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds, struct dsa_switch_driver mv88e6352_switch_driver = { .tag_protocol = DSA_TAG_PROTO_EDSA, - .priv_size = sizeof(struct mv88e6xxx_priv_state), - .probe = mv88e6352_probe, + .probe = mv88e6352_drv_probe, .setup = mv88e6352_setup, .set_addr = mv88e6xxx_set_addr_indirect, .phy_read = mv88e6xxx_phy_read_indirect, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 62320fca6712..61150af37bc7 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -25,12 +25,10 @@ #include <net/switchdev.h> #include "mv88e6xxx.h" -static void assert_smi_lock(struct dsa_switch *ds) +static void assert_smi_lock(struct mv88e6xxx_priv_state *ps) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - if (unlikely(!mutex_is_locked(&ps->smi_mutex))) { - dev_err(ds->master_dev, "SMI lock not held!\n"); + dev_err(ps->dev, "SMI lock not held!\n"); dump_stack(); } } @@ -92,33 +90,29 @@ static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, return ret & 0xffff; } -static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg) +static int _mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, + int addr, int reg) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); int ret; - assert_smi_lock(ds); - - if (bus == NULL) - return -EINVAL; + assert_smi_lock(ps); - ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg); + ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg); if (ret < 0) return ret; - dev_dbg(ds->master_dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n", + dev_dbg(ps->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n", addr, reg, ret); return ret; } -int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg) +int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_reg_read(ds, addr, reg); + ret = _mv88e6xxx_reg_read(ps, addr, reg); mutex_unlock(&ps->smi_mutex); return ret; @@ -156,29 +150,24 @@ static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, return 0; } -static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, - u16 val) +static int _mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr, + int reg, u16 val) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); - - assert_smi_lock(ds); - - if (bus == NULL) - return -EINVAL; + assert_smi_lock(ps); - dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n", + dev_dbg(ps->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n", addr, reg, val); - return __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val); + return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val); } -int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) +int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr, + int reg, u16 val) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_reg_write(ds, addr, reg, val); + ret = _mv88e6xxx_reg_write(ps, addr, reg, val); mutex_unlock(&ps->smi_mutex); return ret; @@ -186,28 +175,46 @@ int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr) { - REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 8) | addr[1]); - REG_WRITE(REG_GLOBAL, GLOBAL_MAC_23, (addr[2] << 8) | addr[3]); - REG_WRITE(REG_GLOBAL, GLOBAL_MAC_45, (addr[4] << 8) | addr[5]); + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int err; - return 0; + err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_01, + (addr[0] << 8) | addr[1]); + if (err) + return err; + + err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_23, + (addr[2] << 8) | addr[3]); + if (err) + return err; + + return mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_MAC_45, + (addr[4] << 8) | addr[5]); } int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr) { - int i; + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; + int i; for (i = 0; i < 6; i++) { int j; /* Write the MAC address byte. */ - REG_WRITE(REG_GLOBAL2, GLOBAL2_SWITCH_MAC, - GLOBAL2_SWITCH_MAC_BUSY | (i << 8) | addr[i]); + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SWITCH_MAC, + GLOBAL2_SWITCH_MAC_BUSY | + (i << 8) | addr[i]); + if (ret) + return ret; /* Wait for the write to complete. */ for (j = 0; j < 16; j++) { - ret = REG_READ(REG_GLOBAL2, GLOBAL2_SWITCH_MAC); + ret = mv88e6xxx_reg_read(ps, REG_GLOBAL2, + GLOBAL2_SWITCH_MAC); + if (ret < 0) + return ret; + if ((ret & GLOBAL2_SWITCH_MAC_BUSY) == 0) break; } @@ -218,34 +225,43 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr) return 0; } -static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum) +static int _mv88e6xxx_phy_read(struct mv88e6xxx_priv_state *ps, int addr, + int regnum) { if (addr >= 0) - return _mv88e6xxx_reg_read(ds, addr, regnum); + return _mv88e6xxx_reg_read(ps, addr, regnum); return 0xffff; } -static int _mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, - u16 val) +static int _mv88e6xxx_phy_write(struct mv88e6xxx_priv_state *ps, int addr, + int regnum, u16 val) { if (addr >= 0) - return _mv88e6xxx_reg_write(ds, addr, regnum, val); + return _mv88e6xxx_reg_write(ps, addr, regnum, val); return 0; } #ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU -static int mv88e6xxx_ppu_disable(struct dsa_switch *ds) +static int mv88e6xxx_ppu_disable(struct mv88e6xxx_priv_state *ps) { int ret; unsigned long timeout; - ret = REG_READ(REG_GLOBAL, GLOBAL_CONTROL); - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, - ret & ~GLOBAL_CONTROL_PPU_ENABLE); + ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL); + if (ret < 0) + return ret; + + ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, + ret & ~GLOBAL_CONTROL_PPU_ENABLE); + if (ret) + return ret; timeout = jiffies + 1 * HZ; while (time_before(jiffies, timeout)) { - ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS); + ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS); + if (ret < 0) + return ret; + usleep_range(1000, 2000); if ((ret & GLOBAL_STATUS_PPU_MASK) != GLOBAL_STATUS_PPU_POLLING) @@ -255,17 +271,26 @@ static int mv88e6xxx_ppu_disable(struct dsa_switch *ds) return -ETIMEDOUT; } -static int mv88e6xxx_ppu_enable(struct dsa_switch *ds) +static int mv88e6xxx_ppu_enable(struct mv88e6xxx_priv_state *ps) { - int ret; + int ret, err; unsigned long timeout; - ret = REG_READ(REG_GLOBAL, GLOBAL_CONTROL); - REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, ret | GLOBAL_CONTROL_PPU_ENABLE); + ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL); + if (ret < 0) + return ret; + + err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, + ret | GLOBAL_CONTROL_PPU_ENABLE); + if (err) + return err; timeout = jiffies + 1 * HZ; while (time_before(jiffies, timeout)) { - ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS); + ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS); + if (ret < 0) + return ret; + usleep_range(1000, 2000); if ((ret & GLOBAL_STATUS_PPU_MASK) == GLOBAL_STATUS_PPU_POLLING) @@ -281,9 +306,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly) ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work); if (mutex_trylock(&ps->ppu_mutex)) { - struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1; - - if (mv88e6xxx_ppu_enable(ds) == 0) + if (mv88e6xxx_ppu_enable(ps) == 0) ps->ppu_disabled = 0; mutex_unlock(&ps->ppu_mutex); } @@ -296,9 +319,8 @@ static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps) schedule_work(&ps->ppu_work); } -static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds) +static int mv88e6xxx_ppu_access_get(struct mv88e6xxx_priv_state *ps) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->ppu_mutex); @@ -309,7 +331,7 @@ static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds) * it. */ if (!ps->ppu_disabled) { - ret = mv88e6xxx_ppu_disable(ds); + ret = mv88e6xxx_ppu_disable(ps); if (ret < 0) { mutex_unlock(&ps->ppu_mutex); return ret; @@ -323,19 +345,15 @@ static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds) return ret; } -static void mv88e6xxx_ppu_access_put(struct dsa_switch *ds) +static void mv88e6xxx_ppu_access_put(struct mv88e6xxx_priv_state *ps) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - /* Schedule a timer to re-enable the PHY polling unit. */ mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10)); mutex_unlock(&ps->ppu_mutex); } -void mv88e6xxx_ppu_state_init(struct dsa_switch *ds) +void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - mutex_init(&ps->ppu_mutex); INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work); init_timer(&ps->ppu_timer); @@ -345,12 +363,13 @@ void mv88e6xxx_ppu_state_init(struct dsa_switch *ds) int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ret = mv88e6xxx_ppu_access_get(ds); + ret = mv88e6xxx_ppu_access_get(ps); if (ret >= 0) { - ret = mv88e6xxx_reg_read(ds, addr, regnum); - mv88e6xxx_ppu_access_put(ds); + ret = mv88e6xxx_reg_read(ps, addr, regnum); + mv88e6xxx_ppu_access_put(ps); } return ret; @@ -359,168 +378,79 @@ int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum) int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr, int regnum, u16 val) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; - ret = mv88e6xxx_ppu_access_get(ds); + ret = mv88e6xxx_ppu_access_get(ps); if (ret >= 0) { - ret = mv88e6xxx_reg_write(ds, addr, regnum, val); - mv88e6xxx_ppu_access_put(ds); + ret = mv88e6xxx_reg_write(ps, addr, regnum, val); + mv88e6xxx_ppu_access_put(ps); } return ret; } #endif -static bool mv88e6xxx_6065_family(struct dsa_switch *ds) +static bool mv88e6xxx_6065_family(struct mv88e6xxx_priv_state *ps) { - 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) +static bool mv88e6xxx_6095_family(struct mv88e6xxx_priv_state *ps) { - 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) +static bool mv88e6xxx_6097_family(struct mv88e6xxx_priv_state *ps) { - 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) +static bool mv88e6xxx_6165_family(struct mv88e6xxx_priv_state *ps) { - 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) +static bool mv88e6xxx_6185_family(struct mv88e6xxx_priv_state *ps) { - 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) +static bool mv88e6xxx_6320_family(struct mv88e6xxx_priv_state *ps) { - 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) +static bool mv88e6xxx_6351_family(struct mv88e6xxx_priv_state *ps) { - 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) +static bool mv88e6xxx_6352_family(struct mv88e6xxx_priv_state *ps) { - 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) +static unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_priv_state *ps) { - 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) +static bool mv88e6xxx_has_fid_reg(struct mv88e6xxx_priv_state *ps) { /* Does the device have dedicated FID registers for ATU and VTU ops? */ - if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || - mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) + if (mv88e6xxx_6097_family(ps) || mv88e6xxx_6165_family(ps) || + mv88e6xxx_6351_family(ps) || mv88e6xxx_6352_family(ps)) return true; return false; } -static bool mv88e6xxx_has_stu(struct dsa_switch *ds) +static bool mv88e6xxx_has_stu(struct mv88e6xxx_priv_state *ps) { /* Does the device have STU and dedicated SID registers for VTU ops? */ - if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || - mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) + if (mv88e6xxx_6097_family(ps) || mv88e6xxx_6165_family(ps) || + mv88e6xxx_6351_family(ps) || mv88e6xxx_6352_family(ps)) return true; return false; @@ -542,7 +472,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL); + ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_PCS_CTRL); if (ret < 0) goto out; @@ -556,7 +486,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, if (phydev->link) reg |= PORT_PCS_CTRL_LINK_UP; - if (mv88e6xxx_6065_family(ds) && phydev->speed > SPEED_100) + if (mv88e6xxx_6065_family(ps) && phydev->speed > SPEED_100) goto out; switch (phydev->speed) { @@ -578,8 +508,8 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, if (phydev->duplex == DUPLEX_FULL) reg |= PORT_PCS_CTRL_DUPLEX_FULL; - if ((mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds)) && - (port >= ps->num_ports - 2)) { + if ((mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps)) && + (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) @@ -588,19 +518,19 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK | PORT_PCS_CTRL_RGMII_DELAY_TXCLK); } - _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_PCS_CTRL, reg); + _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_PCS_CTRL, reg); out: mutex_unlock(&ps->smi_mutex); } -static int _mv88e6xxx_stats_wait(struct dsa_switch *ds) +static int _mv88e6xxx_stats_wait(struct mv88e6xxx_priv_state *ps) { int ret; int i; for (i = 0; i < 10; i++) { - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_OP); + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATS_OP); if ((ret & GLOBAL_STATS_OP_BUSY) == 0) return 0; } @@ -608,52 +538,54 @@ static int _mv88e6xxx_stats_wait(struct dsa_switch *ds) return -ETIMEDOUT; } -static int _mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port) +static int _mv88e6xxx_stats_snapshot(struct mv88e6xxx_priv_state *ps, + int port) { int ret; - if (mv88e6xxx_6320_family(ds) || mv88e6xxx_6352_family(ds)) + if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps)) port = (port + 1) << 5; /* Snapshot the hardware statistics counters for this port. */ - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP, + ret = _mv88e6xxx_reg_write(ps, 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(ps); if (ret < 0) return ret; return 0; } -static void _mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val) +static void _mv88e6xxx_stats_read(struct mv88e6xxx_priv_state *ps, + int stat, u32 *val) { u32 _val; int ret; *val = 0; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_STATS_OP, + ret = _mv88e6xxx_reg_write(ps, 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(ps); if (ret < 0) return; - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_STATS_COUNTER_32); + ret = _mv88e6xxx_reg_read(ps, 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(ps, REG_GLOBAL, GLOBAL_STATS_COUNTER_01); if (ret < 0) return; @@ -722,26 +654,26 @@ static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = { { "out_management", 4, 0x1f | GLOBAL_STATS_OP_BANK_1, BANK1, }, }; -static bool mv88e6xxx_has_stat(struct dsa_switch *ds, +static bool mv88e6xxx_has_stat(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_hw_stat *stat) { switch (stat->type) { case BANK0: return true; case BANK1: - return mv88e6xxx_6320_family(ds); + return mv88e6xxx_6320_family(ps); case PORT: - return mv88e6xxx_6095_family(ds) || - mv88e6xxx_6185_family(ds) || - mv88e6xxx_6097_family(ds) || - mv88e6xxx_6165_family(ds) || - mv88e6xxx_6351_family(ds) || - mv88e6xxx_6352_family(ds); + return mv88e6xxx_6095_family(ps) || + mv88e6xxx_6185_family(ps) || + mv88e6xxx_6097_family(ps) || + mv88e6xxx_6165_family(ps) || + mv88e6xxx_6351_family(ps) || + mv88e6xxx_6352_family(ps); } return false; } -static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds, +static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_hw_stat *s, int port) { @@ -752,13 +684,13 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds, switch (s->type) { case PORT: - ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), s->reg); + ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), s->reg); if (ret < 0) return UINT64_MAX; low = ret; if (s->sizeof_stat == 4) { - ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), s->reg + 1); if (ret < 0) return UINT64_MAX; @@ -767,9 +699,9 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds, break; case BANK0: case BANK1: - _mv88e6xxx_stats_read(ds, s->reg, &low); + _mv88e6xxx_stats_read(ps, s->reg, &low); if (s->sizeof_stat == 8) - _mv88e6xxx_stats_read(ds, s->reg + 1, &high); + _mv88e6xxx_stats_read(ps, s->reg + 1, &high); } value = (((u64)high) << 16) | low; return value; @@ -777,12 +709,13 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds, void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_hw_stat *stat; int i, j; for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { stat = &mv88e6xxx_hw_stats[i]; - if (mv88e6xxx_has_stat(ds, stat)) { + if (mv88e6xxx_has_stat(ps, stat)) { memcpy(data + j * ETH_GSTRING_LEN, stat->string, ETH_GSTRING_LEN); j++; @@ -792,12 +725,13 @@ void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data) int mv88e6xxx_get_sset_count(struct dsa_switch *ds) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_hw_stat *stat; int i, j; for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { stat = &mv88e6xxx_hw_stats[i]; - if (mv88e6xxx_has_stat(ds, stat)) + if (mv88e6xxx_has_stat(ps, stat)) j++; } return j; @@ -814,15 +748,15 @@ mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_stats_snapshot(ds, port); + ret = _mv88e6xxx_stats_snapshot(ps, port); if (ret < 0) { mutex_unlock(&ps->smi_mutex); return; } for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { stat = &mv88e6xxx_hw_stats[i]; - if (mv88e6xxx_has_stat(ds, stat)) { - data[j] = _mv88e6xxx_get_ethtool_stat(ds, stat, port); + if (mv88e6xxx_has_stat(ps, stat)) { + data[j] = _mv88e6xxx_get_ethtool_stat(ps, stat, port); j++; } } @@ -838,6 +772,7 @@ 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) { + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u16 *p = _p; int i; @@ -848,13 +783,13 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, for (i = 0; i < 32; i++) { int ret; - ret = mv88e6xxx_reg_read(ds, REG_PORT(port), i); + ret = mv88e6xxx_reg_read(ps, REG_PORT(port), i); if (ret >= 0) p[i] = ret; } } -static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, +static int _mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg, int offset, u16 mask) { unsigned long timeout = jiffies + HZ / 10; @@ -862,7 +797,7 @@ static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, while (time_before(jiffies, timeout)) { int ret; - ret = _mv88e6xxx_reg_read(ds, reg, offset); + ret = _mv88e6xxx_reg_read(ps, reg, offset); if (ret < 0) return ret; if (!(ret & mask)) @@ -873,74 +808,80 @@ static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, return -ETIMEDOUT; } -static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask) +static int mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, 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); + ret = _mv88e6xxx_wait(ps, reg, offset, mask); mutex_unlock(&ps->smi_mutex); return ret; } -static int _mv88e6xxx_phy_wait(struct dsa_switch *ds) +static int _mv88e6xxx_phy_wait(struct mv88e6xxx_priv_state *ps) { - return _mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SMI_OP, + return _mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_SMI_OP, GLOBAL2_SMI_OP_BUSY); } int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds) { - return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP, + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + + return mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP, GLOBAL2_EEPROM_OP_LOAD); } int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds) { - return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP, + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + + return mv88e6xxx_wait(ps, REG_GLOBAL2, GLOBAL2_EEPROM_OP, GLOBAL2_EEPROM_OP_BUSY); } -static int _mv88e6xxx_atu_wait(struct dsa_switch *ds) +static int _mv88e6xxx_atu_wait(struct mv88e6xxx_priv_state *ps) { - return _mv88e6xxx_wait(ds, REG_GLOBAL, GLOBAL_ATU_OP, + return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_ATU_OP, GLOBAL_ATU_OP_BUSY); } -static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, - int regnum) +static int _mv88e6xxx_phy_read_indirect(struct mv88e6xxx_priv_state *ps, + int addr, int regnum) { int ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_OP, + ret = _mv88e6xxx_reg_write(ps, 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(ps); if (ret < 0) return ret; - return _mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA); + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL2, GLOBAL2_SMI_DATA); + + return ret; } -static int _mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, - int regnum, u16 val) +static int _mv88e6xxx_phy_write_indirect(struct mv88e6xxx_priv_state *ps, + int addr, int regnum, u16 val) { int ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA, val); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SMI_DATA, val); if (ret < 0) return ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL2, GLOBAL2_SMI_OP, + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SMI_OP, GLOBAL2_SMI_OP_22_WRITE | (addr << 5) | regnum); - return _mv88e6xxx_phy_wait(ds); + return _mv88e6xxx_phy_wait(ps); } int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e) @@ -950,14 +891,14 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e) mutex_lock(&ps->smi_mutex); - reg = _mv88e6xxx_phy_read_indirect(ds, port, 16); + reg = _mv88e6xxx_phy_read_indirect(ps, port, 16); if (reg < 0) goto out; 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(ps, REG_PORT(port), PORT_STATUS); if (reg < 0) goto out; @@ -978,7 +919,7 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_read_indirect(ds, port, 16); + ret = _mv88e6xxx_phy_read_indirect(ps, port, 16); if (ret < 0) goto out; @@ -988,28 +929,28 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, if (e->tx_lpi_enabled) reg |= 0x0100; - ret = _mv88e6xxx_phy_write_indirect(ds, port, 16, reg); + ret = _mv88e6xxx_phy_write_indirect(ps, port, 16, reg); out: mutex_unlock(&ps->smi_mutex); return ret; } -static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd) +static int _mv88e6xxx_atu_cmd(struct mv88e6xxx_priv_state *ps, u16 fid, u16 cmd) { int ret; - if (mv88e6xxx_has_fid_reg(ds)) { - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); + if (mv88e6xxx_has_fid_reg(ps)) { + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_FID, fid); if (ret < 0) return ret; - } else if (mv88e6xxx_num_databases(ds) == 256) { + } else if (mv88e6xxx_num_databases(ps) == 256) { /* ATU DBNum[7:4] are located in ATU Control 15:12 */ - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL); + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL); if (ret < 0) return ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_CONTROL, + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL, (ret & 0xfff) | ((fid << 8) & 0xf000)); if (ret < 0) @@ -1019,14 +960,14 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 fid, u16 cmd) cmd |= fid & 0xf; } - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_OP, cmd); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_OP, cmd); if (ret < 0) return ret; - return _mv88e6xxx_atu_wait(ds); + return _mv88e6xxx_atu_wait(ps); } -static int _mv88e6xxx_atu_data_write(struct dsa_switch *ds, +static int _mv88e6xxx_atu_data_write(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_atu_entry *entry) { u16 data = entry->state & GLOBAL_ATU_DATA_STATE_MASK; @@ -1046,21 +987,21 @@ static int _mv88e6xxx_atu_data_write(struct dsa_switch *ds, data |= (entry->portv_trunkid << shift) & mask; } - return _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, data); + return _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_DATA, data); } -static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds, +static int _mv88e6xxx_atu_flush_move(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_atu_entry *entry, bool static_too) { int op; int err; - err = _mv88e6xxx_atu_wait(ds); + err = _mv88e6xxx_atu_wait(ps); if (err) return err; - err = _mv88e6xxx_atu_data_write(ds, entry); + err = _mv88e6xxx_atu_data_write(ps, entry); if (err) return err; @@ -1072,21 +1013,22 @@ static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds, GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC; } - return _mv88e6xxx_atu_cmd(ds, entry->fid, op); + return _mv88e6xxx_atu_cmd(ps, entry->fid, op); } -static int _mv88e6xxx_atu_flush(struct dsa_switch *ds, u16 fid, bool static_too) +static int _mv88e6xxx_atu_flush(struct mv88e6xxx_priv_state *ps, + u16 fid, bool static_too) { struct mv88e6xxx_atu_entry entry = { .fid = fid, .state = 0, /* EntryState bits must be 0 */ }; - return _mv88e6xxx_atu_flush_move(ds, &entry, static_too); + return _mv88e6xxx_atu_flush_move(ps, &entry, static_too); } -static int _mv88e6xxx_atu_move(struct dsa_switch *ds, u16 fid, int from_port, - int to_port, bool static_too) +static int _mv88e6xxx_atu_move(struct mv88e6xxx_priv_state *ps, u16 fid, + int from_port, int to_port, bool static_too) { struct mv88e6xxx_atu_entry entry = { .trunk = false, @@ -1100,14 +1042,14 @@ static int _mv88e6xxx_atu_move(struct dsa_switch *ds, u16 fid, int from_port, entry.portv_trunkid = (to_port & 0x0f) << 4; entry.portv_trunkid |= from_port & 0x0f; - return _mv88e6xxx_atu_flush_move(ds, &entry, static_too); + return _mv88e6xxx_atu_flush_move(ps, &entry, static_too); } -static int _mv88e6xxx_atu_remove(struct dsa_switch *ds, u16 fid, int port, - bool static_too) +static int _mv88e6xxx_atu_remove(struct mv88e6xxx_priv_state *ps, u16 fid, + int port, bool static_too) { /* Destination port 0xF means remove the entries */ - return _mv88e6xxx_atu_move(ds, fid, port, 0x0f, static_too); + return _mv88e6xxx_atu_move(ps, fid, port, 0x0f, static_too); } static const char * const mv88e6xxx_port_state_names[] = { @@ -1117,12 +1059,14 @@ static const char * const mv88e6xxx_port_state_names[] = { [PORT_CONTROL_STATE_FORWARDING] = "Forwarding", }; -static int _mv88e6xxx_port_state(struct dsa_switch *ds, int port, u8 state) +static int _mv88e6xxx_port_state(struct mv88e6xxx_priv_state *ps, int port, + u8 state) { + struct dsa_switch *ds = ps->ds; int reg, ret = 0; u8 oldstate; - reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL); + reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL); if (reg < 0) return reg; @@ -1137,13 +1081,13 @@ static int _mv88e6xxx_port_state(struct dsa_switch *ds, int port, u8 state) oldstate == PORT_CONTROL_STATE_FORWARDING) && (state == PORT_CONTROL_STATE_DISABLED || state == PORT_CONTROL_STATE_BLOCKING)) { - ret = _mv88e6xxx_atu_remove(ds, 0, port, false); + ret = _mv88e6xxx_atu_remove(ps, 0, port, false); if (ret) return ret; } reg = (reg & ~PORT_CONTROL_STATE_MASK) | state; - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL, + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL, reg); if (ret) return ret; @@ -1156,11 +1100,12 @@ static int _mv88e6xxx_port_state(struct dsa_switch *ds, int port, u8 state) return ret; } -static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port) +static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_priv_state *ps, + 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; + struct dsa_switch *ds = ps->ds; u16 output_ports = 0; int reg; int i; @@ -1169,7 +1114,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); @@ -1183,14 +1128,14 @@ static int _mv88e6xxx_port_based_vlan_map(struct dsa_switch *ds, int port) /* prevent frames from going back out of the port they came in on */ output_ports &= ~BIT(port); - reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN); + reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_BASE_VLAN); if (reg < 0) return reg; reg &= ~mask; reg |= output_ports & mask; - return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg); + return _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_BASE_VLAN, reg); } void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) @@ -1223,13 +1168,14 @@ void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) schedule_work(&ps->bridge_work); } -static int _mv88e6xxx_port_pvid(struct dsa_switch *ds, int port, u16 *new, - u16 *old) +static int _mv88e6xxx_port_pvid(struct mv88e6xxx_priv_state *ps, int port, + u16 *new, u16 *old) { + struct dsa_switch *ds = ps->ds; u16 pvid; int ret; - ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_DEFAULT_VLAN); + ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_DEFAULT_VLAN); if (ret < 0) return ret; @@ -1239,7 +1185,7 @@ static int _mv88e6xxx_port_pvid(struct dsa_switch *ds, int port, u16 *new, ret &= ~PORT_DEFAULT_VLAN_MASK; ret |= *new & PORT_DEFAULT_VLAN_MASK; - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_DEFAULT_VLAN, ret); if (ret < 0) return ret; @@ -1254,55 +1200,56 @@ static int _mv88e6xxx_port_pvid(struct dsa_switch *ds, int port, u16 *new, return 0; } -static int _mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid) +static int _mv88e6xxx_port_pvid_get(struct mv88e6xxx_priv_state *ps, + int port, u16 *pvid) { - return _mv88e6xxx_port_pvid(ds, port, NULL, pvid); + return _mv88e6xxx_port_pvid(ps, port, NULL, pvid); } -static int _mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 pvid) +static int _mv88e6xxx_port_pvid_set(struct mv88e6xxx_priv_state *ps, + int port, u16 pvid) { - return _mv88e6xxx_port_pvid(ds, port, &pvid, NULL); + return _mv88e6xxx_port_pvid(ps, port, &pvid, NULL); } -static int _mv88e6xxx_vtu_wait(struct dsa_switch *ds) +static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_priv_state *ps) { - return _mv88e6xxx_wait(ds, REG_GLOBAL, GLOBAL_VTU_OP, + return _mv88e6xxx_wait(ps, REG_GLOBAL, GLOBAL_VTU_OP, GLOBAL_VTU_OP_BUSY); } -static int _mv88e6xxx_vtu_cmd(struct dsa_switch *ds, u16 op) +static int _mv88e6xxx_vtu_cmd(struct mv88e6xxx_priv_state *ps, u16 op) { int ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_OP, op); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_OP, op); if (ret < 0) return ret; - return _mv88e6xxx_vtu_wait(ds); + return _mv88e6xxx_vtu_wait(ps); } -static int _mv88e6xxx_vtu_stu_flush(struct dsa_switch *ds) +static int _mv88e6xxx_vtu_stu_flush(struct mv88e6xxx_priv_state *ps) { int ret; - ret = _mv88e6xxx_vtu_wait(ds); + ret = _mv88e6xxx_vtu_wait(ps); if (ret < 0) return ret; - return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_FLUSH_ALL); + return _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_FLUSH_ALL); } -static int _mv88e6xxx_vtu_stu_data_read(struct dsa_switch *ds, +static int _mv88e6xxx_vtu_stu_data_read(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_vtu_stu_entry *entry, unsigned int nibble_offset) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u16 regs[3]; int i; int ret; for (i = 0; i < 3; ++i) { - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_DATA_0_3 + i); if (ret < 0) return ret; @@ -1310,7 +1257,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]; @@ -1320,16 +1267,15 @@ static int _mv88e6xxx_vtu_stu_data_read(struct dsa_switch *ds, return 0; } -static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds, +static int _mv88e6xxx_vtu_stu_data_write(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_vtu_stu_entry *entry, unsigned int nibble_offset) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u16 regs[3] = { 0 }; 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]; @@ -1337,7 +1283,7 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds, } for (i = 0; i < 3; ++i) { - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_DATA_0_3 + i, regs[i]); if (ret < 0) return ret; @@ -1346,27 +1292,27 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds, return 0; } -static int _mv88e6xxx_vtu_vid_write(struct dsa_switch *ds, u16 vid) +static int _mv88e6xxx_vtu_vid_write(struct mv88e6xxx_priv_state *ps, u16 vid) { - return _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID, + return _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_VID, vid & GLOBAL_VTU_VID_MASK); } -static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, +static int _mv88e6xxx_vtu_getnext(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_vtu_stu_entry *entry) { struct mv88e6xxx_vtu_stu_entry next = { 0 }; int ret; - ret = _mv88e6xxx_vtu_wait(ds); + ret = _mv88e6xxx_vtu_wait(ps); if (ret < 0) return ret; - ret = _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_VTU_GET_NEXT); + ret = _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_VTU_GET_NEXT); if (ret < 0) return ret; - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_VTU_VID); + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_VID); if (ret < 0) return ret; @@ -1374,22 +1320,22 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, next.valid = !!(ret & GLOBAL_VTU_VID_VALID); if (next.valid) { - ret = _mv88e6xxx_vtu_stu_data_read(ds, &next, 0); + ret = _mv88e6xxx_vtu_stu_data_read(ps, &next, 0); if (ret < 0) return ret; - if (mv88e6xxx_has_fid_reg(ds)) { - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, + if (mv88e6xxx_has_fid_reg(ps)) { + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_FID); if (ret < 0) return ret; next.fid = ret & GLOBAL_VTU_FID_MASK; - } else if (mv88e6xxx_num_databases(ds) == 256) { + } else if (mv88e6xxx_num_databases(ps) == 256) { /* VTU DBNum[7:4] are located in VTU Operation 11:8, and * VTU DBNum[3:0] are located in VTU Operation 3:0 */ - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_OP); if (ret < 0) return ret; @@ -1398,8 +1344,8 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, next.fid |= ret & 0xf; } - if (mv88e6xxx_has_stu(ds)) { - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, + if (mv88e6xxx_has_stu(ps)) { + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_SID); if (ret < 0) return ret; @@ -1423,16 +1369,16 @@ int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_port_pvid_get(ds, port, &pvid); + err = _mv88e6xxx_port_pvid_get(ps, port, &pvid); if (err) goto unlock; - err = _mv88e6xxx_vtu_vid_write(ds, GLOBAL_VTU_VID_MASK); + err = _mv88e6xxx_vtu_vid_write(ps, GLOBAL_VTU_VID_MASK); if (err) goto unlock; do { - err = _mv88e6xxx_vtu_getnext(ds, &next); + err = _mv88e6xxx_vtu_getnext(ps, &next); if (err) break; @@ -1463,14 +1409,14 @@ unlock: return err; } -static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, +static int _mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_vtu_stu_entry *entry) { u16 op = GLOBAL_VTU_OP_VTU_LOAD_PURGE; u16 reg = 0; int ret; - ret = _mv88e6xxx_vtu_wait(ds); + ret = _mv88e6xxx_vtu_wait(ps); if (ret < 0) return ret; @@ -1478,23 +1424,23 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, goto loadpurge; /* Write port member tags */ - ret = _mv88e6xxx_vtu_stu_data_write(ds, entry, 0); + ret = _mv88e6xxx_vtu_stu_data_write(ps, entry, 0); if (ret < 0) return ret; - if (mv88e6xxx_has_stu(ds)) { + if (mv88e6xxx_has_stu(ps)) { reg = entry->sid & GLOBAL_VTU_SID_MASK; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_SID, reg); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_SID, reg); if (ret < 0) return ret; } - if (mv88e6xxx_has_fid_reg(ds)) { + if (mv88e6xxx_has_fid_reg(ps)) { reg = entry->fid & GLOBAL_VTU_FID_MASK; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_FID, reg); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_FID, reg); if (ret < 0) return ret; - } else if (mv88e6xxx_num_databases(ds) == 256) { + } else if (mv88e6xxx_num_databases(ps) == 256) { /* VTU DBNum[7:4] are located in VTU Operation 11:8, and * VTU DBNum[3:0] are located in VTU Operation 3:0 */ @@ -1505,46 +1451,46 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds, reg = GLOBAL_VTU_VID_VALID; loadpurge: reg |= entry->vid & GLOBAL_VTU_VID_MASK; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID, reg); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_VID, reg); if (ret < 0) return ret; - return _mv88e6xxx_vtu_cmd(ds, op); + return _mv88e6xxx_vtu_cmd(ps, op); } -static int _mv88e6xxx_stu_getnext(struct dsa_switch *ds, u8 sid, +static int _mv88e6xxx_stu_getnext(struct mv88e6xxx_priv_state *ps, u8 sid, struct mv88e6xxx_vtu_stu_entry *entry) { struct mv88e6xxx_vtu_stu_entry next = { 0 }; int ret; - ret = _mv88e6xxx_vtu_wait(ds); + ret = _mv88e6xxx_vtu_wait(ps); if (ret < 0) return ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_SID, + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_SID, sid & GLOBAL_VTU_SID_MASK); if (ret < 0) return ret; - ret = _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_STU_GET_NEXT); + ret = _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_STU_GET_NEXT); if (ret < 0) return ret; - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_VTU_SID); + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_SID); if (ret < 0) return ret; next.sid = ret & GLOBAL_VTU_SID_MASK; - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_VTU_VID); + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_VTU_VID); if (ret < 0) return ret; next.valid = !!(ret & GLOBAL_VTU_VID_VALID); if (next.valid) { - ret = _mv88e6xxx_vtu_stu_data_read(ds, &next, 2); + ret = _mv88e6xxx_vtu_stu_data_read(ps, &next, 2); if (ret < 0) return ret; } @@ -1553,13 +1499,13 @@ static int _mv88e6xxx_stu_getnext(struct dsa_switch *ds, u8 sid, return 0; } -static int _mv88e6xxx_stu_loadpurge(struct dsa_switch *ds, +static int _mv88e6xxx_stu_loadpurge(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_vtu_stu_entry *entry) { u16 reg = 0; int ret; - ret = _mv88e6xxx_vtu_wait(ds); + ret = _mv88e6xxx_vtu_wait(ps); if (ret < 0) return ret; @@ -1567,40 +1513,41 @@ static int _mv88e6xxx_stu_loadpurge(struct dsa_switch *ds, goto loadpurge; /* Write port states */ - ret = _mv88e6xxx_vtu_stu_data_write(ds, entry, 2); + ret = _mv88e6xxx_vtu_stu_data_write(ps, entry, 2); if (ret < 0) return ret; reg = GLOBAL_VTU_VID_VALID; loadpurge: - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID, reg); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_VID, reg); if (ret < 0) return ret; reg = entry->sid & GLOBAL_VTU_SID_MASK; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_SID, reg); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_VTU_SID, reg); if (ret < 0) return ret; - return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_STU_LOAD_PURGE); + return _mv88e6xxx_vtu_cmd(ps, GLOBAL_VTU_OP_STU_LOAD_PURGE); } -static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new, - u16 *old) +static int _mv88e6xxx_port_fid(struct mv88e6xxx_priv_state *ps, int port, + u16 *new, u16 *old) { + struct dsa_switch *ds = ps->ds; u16 upper_mask; u16 fid; int ret; - if (mv88e6xxx_num_databases(ds) == 4096) + if (mv88e6xxx_num_databases(ps) == 4096) upper_mask = 0xff; - else if (mv88e6xxx_num_databases(ds) == 256) + else if (mv88e6xxx_num_databases(ps) == 256) upper_mask = 0xf; else return -EOPNOTSUPP; /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */ - ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN); + ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_BASE_VLAN); if (ret < 0) return ret; @@ -1610,14 +1557,14 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new, ret &= ~PORT_BASE_VLAN_FID_3_0_MASK; ret |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK; - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_BASE_VLAN, ret); if (ret < 0) return ret; } /* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */ - ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_1); + ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_1); if (ret < 0) return ret; @@ -1627,7 +1574,7 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new, ret &= ~upper_mask; ret |= (*new >> 4) & upper_mask; - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1, + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1, ret); if (ret < 0) return ret; @@ -1641,19 +1588,20 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new, return 0; } -static int _mv88e6xxx_port_fid_get(struct dsa_switch *ds, int port, u16 *fid) +static int _mv88e6xxx_port_fid_get(struct mv88e6xxx_priv_state *ps, + int port, u16 *fid) { - return _mv88e6xxx_port_fid(ds, port, NULL, fid); + return _mv88e6xxx_port_fid(ps, port, NULL, fid); } -static int _mv88e6xxx_port_fid_set(struct dsa_switch *ds, int port, u16 fid) +static int _mv88e6xxx_port_fid_set(struct mv88e6xxx_priv_state *ps, + int port, u16 fid) { - return _mv88e6xxx_port_fid(ds, port, &fid, NULL); + return _mv88e6xxx_port_fid(ps, port, &fid, NULL); } -static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid) +static int _mv88e6xxx_fid_new(struct mv88e6xxx_priv_state *ps, u16 *fid) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID); struct mv88e6xxx_vtu_stu_entry vlan; int i, err; @@ -1661,8 +1609,8 @@ 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) { - err = _mv88e6xxx_port_fid_get(ds, i, fid); + for (i = 0; i < ps->info->num_ports; ++i) { + err = _mv88e6xxx_port_fid_get(ps, i, fid); if (err) return err; @@ -1670,12 +1618,12 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid) } /* Set every FID bit used by the VLAN entries */ - err = _mv88e6xxx_vtu_vid_write(ds, GLOBAL_VTU_VID_MASK); + err = _mv88e6xxx_vtu_vid_write(ps, GLOBAL_VTU_VID_MASK); if (err) return err; do { - err = _mv88e6xxx_vtu_getnext(ds, &vlan); + err = _mv88e6xxx_vtu_getnext(ps, &vlan); if (err) return err; @@ -1689,35 +1637,35 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid) * databases are not needed. Return the next positive available. */ *fid = find_next_zero_bit(fid_bitmap, MV88E6XXX_N_FID, 1); - if (unlikely(*fid >= mv88e6xxx_num_databases(ds))) + if (unlikely(*fid >= mv88e6xxx_num_databases(ps))) return -ENOSPC; /* Clear the database */ - return _mv88e6xxx_atu_flush(ds, *fid, true); + return _mv88e6xxx_atu_flush(ps, *fid, true); } -static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid, +static int _mv88e6xxx_vtu_new(struct mv88e6xxx_priv_state *ps, u16 vid, struct mv88e6xxx_vtu_stu_entry *entry) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + struct dsa_switch *ds = ps->ds; struct mv88e6xxx_vtu_stu_entry vlan = { .valid = true, .vid = vid, }; int i, err; - err = _mv88e6xxx_fid_new(ds, &vlan.fid); + err = _mv88e6xxx_fid_new(ps, &vlan.fid); if (err) 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; - if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || - mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) { + if (mv88e6xxx_6097_family(ps) || mv88e6xxx_6165_family(ps) || + mv88e6xxx_6351_family(ps) || mv88e6xxx_6352_family(ps)) { struct mv88e6xxx_vtu_stu_entry vstp; /* Adding a VTU entry requires a valid STU entry. As VSTP is not @@ -1725,7 +1673,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid, * entries. Thus, validate the SID 0. */ vlan.sid = 0; - err = _mv88e6xxx_stu_getnext(ds, GLOBAL_VTU_SID_MASK, &vstp); + err = _mv88e6xxx_stu_getnext(ps, GLOBAL_VTU_SID_MASK, &vstp); if (err) return err; @@ -1734,7 +1682,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid, vstp.valid = true; vstp.sid = vlan.sid; - err = _mv88e6xxx_stu_loadpurge(ds, &vstp); + err = _mv88e6xxx_stu_loadpurge(ps, &vstp); if (err) return err; } @@ -1744,7 +1692,7 @@ static int _mv88e6xxx_vtu_new(struct dsa_switch *ds, u16 vid, return 0; } -static int _mv88e6xxx_vtu_get(struct dsa_switch *ds, u16 vid, +static int _mv88e6xxx_vtu_get(struct mv88e6xxx_priv_state *ps, u16 vid, struct mv88e6xxx_vtu_stu_entry *entry, bool creat) { int err; @@ -1752,11 +1700,11 @@ static int _mv88e6xxx_vtu_get(struct dsa_switch *ds, u16 vid, if (!vid) return -EINVAL; - err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); + err = _mv88e6xxx_vtu_vid_write(ps, vid - 1); if (err) return err; - err = _mv88e6xxx_vtu_getnext(ds, entry); + err = _mv88e6xxx_vtu_getnext(ps, entry); if (err) return err; @@ -1767,7 +1715,7 @@ static int _mv88e6xxx_vtu_get(struct dsa_switch *ds, u16 vid, * -EOPNOTSUPP to inform bridge about an eventual software VLAN. */ - err = _mv88e6xxx_vtu_new(ds, vid, entry); + err = _mv88e6xxx_vtu_new(ps, vid, entry); } return err; @@ -1785,12 +1733,12 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_vtu_vid_write(ds, vid_begin - 1); + err = _mv88e6xxx_vtu_vid_write(ps, vid_begin - 1); if (err) goto unlock; do { - err = _mv88e6xxx_vtu_getnext(ds, &vlan); + err = _mv88e6xxx_vtu_getnext(ps, &vlan); if (err) goto unlock; @@ -1800,7 +1748,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; @@ -1844,7 +1792,7 @@ int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_2); + ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_2); if (ret < 0) goto unlock; @@ -1854,7 +1802,7 @@ int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, ret &= ~PORT_CONTROL_2_8021Q_MASK; ret |= new & PORT_CONTROL_2_8021Q_MASK; - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_2, + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_2, ret); if (ret < 0) goto unlock; @@ -1891,13 +1839,13 @@ int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, return 0; } -static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid, - bool untagged) +static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_priv_state *ps, int port, + u16 vid, bool untagged) { struct mv88e6xxx_vtu_stu_entry vlan; int err; - err = _mv88e6xxx_vtu_get(ds, vid, &vlan, true); + err = _mv88e6xxx_vtu_get(ps, vid, &vlan, true); if (err) return err; @@ -1905,7 +1853,7 @@ static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid, GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED : GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED; - return _mv88e6xxx_vtu_loadpurge(ds, &vlan); + return _mv88e6xxx_vtu_loadpurge(ps, &vlan); } void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, @@ -1920,24 +1868,25 @@ void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) - if (_mv88e6xxx_port_vlan_add(ds, port, vid, untagged)) + if (_mv88e6xxx_port_vlan_add(ps, port, vid, untagged)) netdev_err(ds->ports[port], "failed to add VLAN %d%c\n", vid, untagged ? 'u' : 't'); - if (pvid && _mv88e6xxx_port_pvid_set(ds, port, vlan->vid_end)) + if (pvid && _mv88e6xxx_port_pvid_set(ps, port, vlan->vid_end)) netdev_err(ds->ports[port], "failed to set PVID %d\n", vlan->vid_end); mutex_unlock(&ps->smi_mutex); } -static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) +static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_priv_state *ps, + int port, u16 vid) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + struct dsa_switch *ds = ps->ds; struct mv88e6xxx_vtu_stu_entry vlan; int i, err; - err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false); + err = _mv88e6xxx_vtu_get(ps, vid, &vlan, false); if (err) return err; @@ -1949,7 +1898,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; @@ -1959,11 +1908,11 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) } } - err = _mv88e6xxx_vtu_loadpurge(ds, &vlan); + err = _mv88e6xxx_vtu_loadpurge(ps, &vlan); if (err) return err; - return _mv88e6xxx_atu_remove(ds, vlan.fid, port, false); + return _mv88e6xxx_atu_remove(ps, vlan.fid, port, false); } int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, @@ -1975,17 +1924,17 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_port_pvid_get(ds, port, &pvid); + err = _mv88e6xxx_port_pvid_get(ps, port, &pvid); if (err) goto unlock; for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { - err = _mv88e6xxx_port_vlan_del(ds, port, vid); + err = _mv88e6xxx_port_vlan_del(ps, port, vid); if (err) goto unlock; if (vid == pvid) { - err = _mv88e6xxx_port_pvid_set(ds, port, 0); + err = _mv88e6xxx_port_pvid_set(ps, port, 0); if (err) goto unlock; } @@ -1997,14 +1946,14 @@ unlock: return err; } -static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, +static int _mv88e6xxx_atu_mac_write(struct mv88e6xxx_priv_state *ps, const unsigned char *addr) { int i, ret; for (i = 0; i < 3; i++) { ret = _mv88e6xxx_reg_write( - ds, REG_GLOBAL, GLOBAL_ATU_MAC_01 + i, + ps, REG_GLOBAL, GLOBAL_ATU_MAC_01 + i, (addr[i * 2] << 8) | addr[i * 2 + 1]); if (ret < 0) return ret; @@ -2013,12 +1962,13 @@ static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds, return 0; } -static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, unsigned char *addr) +static int _mv88e6xxx_atu_mac_read(struct mv88e6xxx_priv_state *ps, + unsigned char *addr) { int i, ret; for (i = 0; i < 3; i++) { - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_ATU_MAC_01 + i); if (ret < 0) return ret; @@ -2029,27 +1979,27 @@ static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, unsigned char *addr) return 0; } -static int _mv88e6xxx_atu_load(struct dsa_switch *ds, +static int _mv88e6xxx_atu_load(struct mv88e6xxx_priv_state *ps, struct mv88e6xxx_atu_entry *entry) { int ret; - ret = _mv88e6xxx_atu_wait(ds); + ret = _mv88e6xxx_atu_wait(ps); if (ret < 0) return ret; - ret = _mv88e6xxx_atu_mac_write(ds, entry->mac); + ret = _mv88e6xxx_atu_mac_write(ps, entry->mac); if (ret < 0) return ret; - ret = _mv88e6xxx_atu_data_write(ds, entry); + ret = _mv88e6xxx_atu_data_write(ps, entry); if (ret < 0) return ret; - return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB); + return _mv88e6xxx_atu_cmd(ps, entry->fid, GLOBAL_ATU_OP_LOAD_DB); } -static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, +static int _mv88e6xxx_port_fdb_load(struct mv88e6xxx_priv_state *ps, int port, const unsigned char *addr, u16 vid, u8 state) { @@ -2059,9 +2009,9 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, /* Null VLAN ID corresponds to the port private database */ if (vid == 0) - err = _mv88e6xxx_port_fid_get(ds, port, &vlan.fid); + err = _mv88e6xxx_port_fid_get(ps, port, &vlan.fid); else - err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false); + err = _mv88e6xxx_vtu_get(ps, vid, &vlan, false); if (err) return err; @@ -2073,7 +2023,7 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, entry.portv_trunkid = BIT(port); } - return _mv88e6xxx_atu_load(ds, &entry); + return _mv88e6xxx_atu_load(ps, &entry); } int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, @@ -2096,7 +2046,7 @@ void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); mutex_lock(&ps->smi_mutex); - if (_mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid, state)) + if (_mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid, state)) netdev_err(ds->ports[port], "failed to load MAC address\n"); mutex_unlock(&ps->smi_mutex); } @@ -2108,14 +2058,14 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid, + ret = _mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid, GLOBAL_ATU_DATA_STATE_UNUSED); mutex_unlock(&ps->smi_mutex); return ret; } -static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, +static int _mv88e6xxx_atu_getnext(struct mv88e6xxx_priv_state *ps, u16 fid, struct mv88e6xxx_atu_entry *entry) { struct mv88e6xxx_atu_entry next = { 0 }; @@ -2123,19 +2073,19 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, next.fid = fid; - ret = _mv88e6xxx_atu_wait(ds); + ret = _mv88e6xxx_atu_wait(ps); if (ret < 0) return ret; - ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); + ret = _mv88e6xxx_atu_cmd(ps, fid, GLOBAL_ATU_OP_GET_NEXT_DB); if (ret < 0) return ret; - ret = _mv88e6xxx_atu_mac_read(ds, next.mac); + ret = _mv88e6xxx_atu_mac_read(ps, next.mac); if (ret < 0) return ret; - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_ATU_DATA); if (ret < 0) return ret; @@ -2160,8 +2110,8 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, return 0; } -static int _mv88e6xxx_port_fdb_dump_one(struct dsa_switch *ds, u16 fid, u16 vid, - int port, +static int _mv88e6xxx_port_fdb_dump_one(struct mv88e6xxx_priv_state *ps, + u16 fid, u16 vid, int port, struct switchdev_obj_port_fdb *fdb, int (*cb)(struct switchdev_obj *obj)) { @@ -2170,12 +2120,12 @@ static int _mv88e6xxx_port_fdb_dump_one(struct dsa_switch *ds, u16 fid, u16 vid, }; int err; - err = _mv88e6xxx_atu_mac_write(ds, addr.mac); + err = _mv88e6xxx_atu_mac_write(ps, addr.mac); if (err) return err; do { - err = _mv88e6xxx_atu_getnext(ds, fid, &addr); + err = _mv88e6xxx_atu_getnext(ps, fid, &addr); if (err) break; @@ -2215,28 +2165,28 @@ int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, mutex_lock(&ps->smi_mutex); /* Dump port's default Filtering Information Database (VLAN ID 0) */ - err = _mv88e6xxx_port_fid_get(ds, port, &fid); + err = _mv88e6xxx_port_fid_get(ps, port, &fid); if (err) goto unlock; - err = _mv88e6xxx_port_fdb_dump_one(ds, fid, 0, port, fdb, cb); + err = _mv88e6xxx_port_fdb_dump_one(ps, fid, 0, port, fdb, cb); if (err) goto unlock; /* Dump VLANs' Filtering Information Databases */ - err = _mv88e6xxx_vtu_vid_write(ds, vlan.vid); + err = _mv88e6xxx_vtu_vid_write(ps, vlan.vid); if (err) goto unlock; do { - err = _mv88e6xxx_vtu_getnext(ds, &vlan); + err = _mv88e6xxx_vtu_getnext(ps, &vlan); if (err) break; if (!vlan.valid) break; - err = _mv88e6xxx_port_fdb_dump_one(ds, vlan.fid, vlan.vid, port, + err = _mv88e6xxx_port_fdb_dump_one(ps, vlan.fid, vlan.vid, port, fdb, cb); if (err) break; @@ -2252,39 +2202,21 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *bridge) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - u16 fid; int i, err; 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) - if (ps->ports[i].bridge_dev == bridge) - break; - - if (i < ps->num_ports) - err = _mv88e6xxx_port_fid_get(ds, i, &fid); - else - err = _mv88e6xxx_fid_new(ds, &fid); - if (err) - goto unlock; - - err = _mv88e6xxx_port_fid_set(ds, port, fid); - if (err) - goto unlock; - /* 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); + err = _mv88e6xxx_port_based_vlan_map(ps, i); if (err) break; } } -unlock: mutex_unlock(&ps->smi_mutex); return err; @@ -2294,22 +2226,16 @@ void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct net_device *bridge = ps->ports[port].bridge_dev; - u16 fid; int i; mutex_lock(&ps->smi_mutex); - /* Give the port a fresh Filtering Information Database */ - if (_mv88e6xxx_fid_new(ds, &fid) || - _mv88e6xxx_port_fid_set(ds, port, fid)) - netdev_warn(ds->ports[port], "failed to assign a new FID\n"); - /* 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)) + if (_mv88e6xxx_port_based_vlan_map(ps, i)) netdev_warn(ds->ports[i], "failed to remap\n"); mutex_unlock(&ps->smi_mutex); @@ -2322,63 +2248,64 @@ static void mv88e6xxx_bridge_work(struct work_struct *work) int port; ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work); - ds = ((struct dsa_switch *)ps) - 1; + ds = ps->ds; 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", + _mv88e6xxx_port_state(ps, port, ps->ports[port].state)) + netdev_warn(ds->ports[port], + "failed to update state to %s\n", mv88e6xxx_port_state_names[ps->ports[port].state]); mutex_unlock(&ps->smi_mutex); } -static int _mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, - int reg, int val) +static int _mv88e6xxx_phy_page_write(struct mv88e6xxx_priv_state *ps, + int port, int page, int reg, int val) { int ret; - ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); + ret = _mv88e6xxx_phy_write_indirect(ps, port, 0x16, page); if (ret < 0) goto restore_page_0; - ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val); + ret = _mv88e6xxx_phy_write_indirect(ps, port, reg, val); restore_page_0: - _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + _mv88e6xxx_phy_write_indirect(ps, port, 0x16, 0x0); return ret; } -static int _mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, - int reg) +static int _mv88e6xxx_phy_page_read(struct mv88e6xxx_priv_state *ps, + int port, int page, int reg) { int ret; - ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); + ret = _mv88e6xxx_phy_write_indirect(ps, port, 0x16, page); if (ret < 0) goto restore_page_0; - ret = _mv88e6xxx_phy_read_indirect(ds, port, reg); + ret = _mv88e6xxx_phy_read_indirect(ps, port, reg); restore_page_0: - _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + _mv88e6xxx_phy_write_indirect(ps, port, 0x16, 0x0); return ret; } -static int mv88e6xxx_power_on_serdes(struct dsa_switch *ds) +static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps) { int ret; - ret = _mv88e6xxx_phy_page_read(ds, REG_FIBER_SERDES, PAGE_FIBER_SERDES, + ret = _mv88e6xxx_phy_page_read(ps, REG_FIBER_SERDES, PAGE_FIBER_SERDES, MII_BMCR); if (ret < 0) return ret; if (ret & BMCR_PDOWN) { ret &= ~BMCR_PDOWN; - ret = _mv88e6xxx_phy_page_write(ds, REG_FIBER_SERDES, + ret = _mv88e6xxx_phy_page_write(ps, REG_FIBER_SERDES, PAGE_FIBER_SERDES, MII_BMCR, ret); } @@ -2394,24 +2321,24 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) 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) || mv88e6xxx_6320_family(ds)) { + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) || + mv88e6xxx_6065_family(ps) || mv88e6xxx_6320_family(ps)) { /* 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); + reg = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_PCS_CTRL); if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { reg &= ~PORT_PCS_CTRL_UNFORCED; 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)) + if (mv88e6xxx_6065_family(ps)) reg |= PORT_PCS_CTRL_100; else reg |= PORT_PCS_CTRL_1000; @@ -2419,7 +2346,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) reg |= PORT_PCS_CTRL_UNFORCED; } - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_PCS_CTRL, reg); if (ret) goto abort; @@ -2440,19 +2367,19 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) * 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) || mv88e6xxx_6320_family(ds)) + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6095_family(ps) || mv88e6xxx_6065_family(ps) || + mv88e6xxx_6185_family(ps) || mv88e6xxx_6320_family(ps)) 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)) + if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps)) reg |= PORT_CONTROL_DSA_TAG; - if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || - mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || - mv88e6xxx_6320_family(ds)) { + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6320_family(ps)) { if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA) reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA; else @@ -2461,20 +2388,20 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) PORT_CONTROL_FORWARD_UNKNOWN_MC; } - 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) || mv88e6xxx_6320_family(ds)) { + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6095_family(ps) || mv88e6xxx_6065_family(ps) || + mv88e6xxx_6185_family(ps) || mv88e6xxx_6320_family(ps)) { if (ds->dst->tag_protocol == DSA_TAG_PROTO_EDSA) reg |= PORT_CONTROL_EGRESS_ADD_TAG; } } if (dsa_is_dsa_port(ds, port)) { - if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) + if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps)) reg |= PORT_CONTROL_DSA_TAG; - if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || - mv88e6xxx_6165_family(ds) || mv88e6xxx_6097_family(ds) || - mv88e6xxx_6320_family(ds)) { + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6320_family(ps)) { reg |= PORT_CONTROL_FRAME_MODE_DSA; } @@ -2483,7 +2410,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) PORT_CONTROL_FORWARD_UNKNOWN_MC; } if (reg) { - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL, reg); if (ret) goto abort; @@ -2492,15 +2419,15 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) /* If this port is connected to a SerDes, make sure the SerDes is not * powered down. */ - if (mv88e6xxx_6352_family(ds)) { - ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS); + if (mv88e6xxx_6352_family(ps)) { + ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_STATUS); if (ret < 0) goto abort; ret &= PORT_STATUS_CMODE_MASK; if ((ret == PORT_STATUS_CMODE_100BASE_X) || (ret == PORT_STATUS_CMODE_1000BASE_X) || (ret == PORT_STATUS_CMODE_SGMII)) { - ret = mv88e6xxx_power_on_serdes(ds); + ret = mv88e6xxx_power_on_serdes(ps); if (ret < 0) goto abort; } @@ -2513,17 +2440,17 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) * 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) || mv88e6xxx_6320_family(ds) || - mv88e6xxx_6185_family(ds)) + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6095_family(ps) || mv88e6xxx_6320_family(ps) || + mv88e6xxx_6185_family(ps)) reg = PORT_CONTROL_2_MAP_DA; - if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) || - mv88e6xxx_6165_family(ds) || mv88e6xxx_6320_family(ds)) + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6320_family(ps)) reg |= PORT_CONTROL_2_JUMBO_10240; - if (mv88e6xxx_6095_family(ds) || mv88e6xxx_6185_family(ds)) { + if (mv88e6xxx_6095_family(ps) || mv88e6xxx_6185_family(ps)) { /* Set the upstream port this port should use */ reg |= dsa_upstream_port(ds); /* enable forwarding of unknown multicast addresses to @@ -2536,7 +2463,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) reg |= PORT_CONTROL_2_8021Q_DISABLED; if (reg) { - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_2, reg); if (ret) goto abort; @@ -2548,28 +2475,28 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) * the other bits clear. */ reg = 1 << port; - /* Disable learning for DSA and CPU ports */ - if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) - reg = PORT_ASSOC_VECTOR_LOCKED_PORT; + /* Disable learning for CPU port */ + if (dsa_is_cpu_port(ds, port)) + reg = 0; - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_ASSOC_VECTOR, reg); + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_ASSOC_VECTOR, reg); if (ret) goto abort; /* Egress rate control 2: disable egress rate control. */ - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_RATE_CONTROL_2, + ret = _mv88e6xxx_reg_write(ps, 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) || - mv88e6xxx_6320_family(ds)) { + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6320_family(ps)) { /* 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), + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_PAUSE_CTRL, 0x0000); if (ret) goto abort; @@ -2578,12 +2505,12 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) * address database entries that this port is allowed * to use. */ - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_ATU_CONTROL, 0x0000); /* Priority Override: disable DA, SA and VTU priority * override. */ - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_PRI_OVERRIDE, 0x0000); if (ret) goto abort; @@ -2591,14 +2518,14 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) /* Port Ethertype: use the Ethertype DSA Ethertype * value. */ - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_write(ps, 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), + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_TAG_REGMAP_0123, 0x3210); if (ret) goto abort; @@ -2606,18 +2533,18 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) /* Tag Remap 2: use an identity 802.1p prio -> switch * prio mapping. */ - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_write(ps, 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) || - mv88e6xxx_6320_family(ds)) { + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) || + mv88e6xxx_6320_family(ps)) { /* Rate Control: disable ingress rate limiting. */ - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_RATE_CONTROL, 0x0001); if (ret) goto abort; @@ -2626,26 +2553,26 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) /* Port Control 1: disable trunking, disable sending * learning messages to this port. */ - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1, 0x0000); + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_CONTROL_1, 0x0000); if (ret) goto abort; - /* Port based VLAN map: give each port its own address + /* Port based VLAN map: give each port the same default address * database, and allow bidirectional communication between the * CPU and DSA port(s), and the other ports. */ - ret = _mv88e6xxx_port_fid_set(ds, port, port + 1); + ret = _mv88e6xxx_port_fid_set(ps, port, 0); if (ret) goto abort; - ret = _mv88e6xxx_port_based_vlan_map(ds, port); + ret = _mv88e6xxx_port_based_vlan_map(ps, port); if (ret) goto abort; /* Default VLAN ID and priority: don't set a default VLAN * ID, and set the default packet priority to zero. */ - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN, + ret = _mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_DEFAULT_VLAN, 0x0000); abort: mutex_unlock(&ps->smi_mutex); @@ -2658,7 +2585,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; @@ -2666,14 +2593,10 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds) return 0; } -int mv88e6xxx_setup_common(struct dsa_switch *ds) +int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - mutex_init(&ps->smi_mutex); - ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; - INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); return 0; @@ -2682,42 +2605,67 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) int mv88e6xxx_setup_global(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int ret; + int err; int i; + mutex_lock(&ps->smi_mutex); /* 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); + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_ATU_CONTROL, + 0x0140 | GLOBAL_ATU_CONTROL_LEARN2ALL); + if (err) + goto unlock; /* 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); + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_0, 0x0000); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_1, 0x0000); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_2, 0x5555); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_3, 0x5555); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_4, 0xaaaa); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_5, 0xaaaa); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_6, 0xffff); + if (err) + goto unlock; + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IP_PRI_7, 0xffff); + if (err) + goto unlock; /* Configure the IEEE 802.1p priority mapping register. */ - REG_WRITE(REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41); + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_IEEE_PRI, 0xfa41); + if (err) + goto unlock; /* 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); + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_MGMT_EN_0X, 0xffff); + if (err) + goto unlock; /* 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); + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_SWITCH_MGMT, + 0x7 | GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x70 | + GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI); + if (err) + goto unlock; /* Program the DSA routing table. */ for (i = 0; i < 32; i++) { @@ -2727,91 +2675,126 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) 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); + err = _mv88e6xxx_reg_write( + ps, REG_GLOBAL2, + GLOBAL2_DEVICE_MAPPING, + GLOBAL2_DEVICE_MAPPING_UPDATE | + (i << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT) | nexthop); + if (err) + goto unlock; } /* 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)); + for (i = 0; i < 8; i++) { + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, GLOBAL2_TRUNK_MASK, + 0x8000 | + (i << GLOBAL2_TRUNK_MASK_NUM_SHIFT) | + ((1 << ps->info->num_ports) - 1)); + if (err) + goto unlock; + } /* 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) || - mv88e6xxx_6320_family(ds)) { + for (i = 0; i < 16; i++) { + err = _mv88e6xxx_reg_write( + ps, REG_GLOBAL2, + GLOBAL2_TRUNK_MAPPING, + GLOBAL2_TRUNK_MAPPING_UPDATE | + (i << GLOBAL2_TRUNK_MAPPING_ID_SHIFT)); + if (err) + goto unlock; + } + + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6320_family(ps)) { /* 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); + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, + GLOBAL2_MGMT_EN_2X, 0xffff); + if (err) + goto unlock; /* Initialise cross-chip port VLAN table to reset * defaults. */ - REG_WRITE(REG_GLOBAL2, GLOBAL2_PVT_ADDR, 0x9000); + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, + GLOBAL2_PVT_ADDR, 0x9000); + if (err) + goto unlock; /* Clear the priority override table. */ - for (i = 0; i < 16; i++) - REG_WRITE(REG_GLOBAL2, GLOBAL2_PRIO_OVERRIDE, - 0x8000 | (i << 8)); + for (i = 0; i < 16; i++) { + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, + GLOBAL2_PRIO_OVERRIDE, + 0x8000 | (i << 8)); + if (err) + goto unlock; + } } - 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_6320_family(ds)) { + if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) || + mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) || + mv88e6xxx_6185_family(ps) || mv88e6xxx_6095_family(ps) || + mv88e6xxx_6320_family(ps)) { /* 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)); + for (i = 0; i < ps->info->num_ports; i++) { + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL2, + GLOBAL2_INGRESS_OP, + 0x9000 | (i << 8)); + if (err) + goto unlock; + } } /* Clear the statistics counters for all ports */ - REG_WRITE(REG_GLOBAL, GLOBAL_STATS_OP, GLOBAL_STATS_OP_FLUSH_ALL); + err = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_STATS_OP, + GLOBAL_STATS_OP_FLUSH_ALL); + if (err) + goto unlock; /* Wait for the flush to complete. */ - mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_stats_wait(ds); - if (ret < 0) + err = _mv88e6xxx_stats_wait(ps); + if (err < 0) goto unlock; /* Clear all ATU entries */ - ret = _mv88e6xxx_atu_flush(ds, 0, true); - if (ret < 0) + err = _mv88e6xxx_atu_flush(ps, 0, true); + if (err < 0) goto unlock; /* Clear all the VTU and STU entries */ - ret = _mv88e6xxx_vtu_stu_flush(ds); + err = _mv88e6xxx_vtu_stu_flush(ps); unlock: mutex_unlock(&ps->smi_mutex); - return ret; + return err; } -int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active) +int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); u16 is_reset = (ppu_active ? 0x8800 : 0xc800); - struct gpio_desc *gpiod = ds->pd->reset; + struct gpio_desc *gpiod = ps->ds->pd->reset; unsigned long timeout; int ret; int i; + mutex_lock(&ps->smi_mutex); + /* Set all ports to the disabled state. */ - for (i = 0; i < ps->num_ports; i++) { - ret = REG_READ(REG_PORT(i), PORT_CONTROL); - REG_WRITE(REG_PORT(i), PORT_CONTROL, ret & 0xfffc); + for (i = 0; i < ps->info->num_ports; i++) { + ret = _mv88e6xxx_reg_read(ps, REG_PORT(i), PORT_CONTROL); + if (ret < 0) + goto unlock; + + ret = _mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL, + ret & 0xfffc); + if (ret) + goto unlock; } /* Wait for transmit queues to drain. */ @@ -2830,22 +2813,31 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active) * through global registers 0x18 and 0x19. */ if (ppu_active) - REG_WRITE(REG_GLOBAL, 0x04, 0xc000); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc000); else - REG_WRITE(REG_GLOBAL, 0x04, 0xc400); + ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc400); + if (ret) + goto unlock; /* Wait up to one second for reset to complete. */ timeout = jiffies + 1 * HZ; while (time_before(jiffies, timeout)) { - ret = REG_READ(REG_GLOBAL, 0x00); + ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00); + if (ret < 0) + goto unlock; + if ((ret & is_reset) == is_reset) break; usleep_range(1000, 2000); } if (time_after(jiffies, timeout)) - return -ETIMEDOUT; + ret = -ETIMEDOUT; + else + ret = 0; +unlock: + mutex_unlock(&ps->smi_mutex); - return 0; + return ret; } int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg) @@ -2854,7 +2846,7 @@ int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg) int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_page_read(ds, port, page, reg); + ret = _mv88e6xxx_phy_page_read(ps, port, page, reg); mutex_unlock(&ps->smi_mutex); return ret; @@ -2867,17 +2859,16 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_page_write(ds, port, page, reg, val); + ret = _mv88e6xxx_phy_page_write(ps, port, page, reg, val); mutex_unlock(&ps->smi_mutex); return ret; } -static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port) +static int mv88e6xxx_port_to_phy_addr(struct mv88e6xxx_priv_state *ps, + 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; } @@ -2886,14 +2877,14 @@ int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int addr = mv88e6xxx_port_to_phy_addr(ds, port); + int addr = mv88e6xxx_port_to_phy_addr(ps, port); int ret; if (addr < 0) - return addr; + return 0xffff; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_read(ds, addr, regnum); + ret = _mv88e6xxx_phy_read(ps, addr, regnum); mutex_unlock(&ps->smi_mutex); return ret; } @@ -2902,14 +2893,14 @@ int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int addr = mv88e6xxx_port_to_phy_addr(ds, port); + int addr = mv88e6xxx_port_to_phy_addr(ps, port); int ret; if (addr < 0) - return addr; + return 0xffff; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_write(ds, addr, regnum, val); + ret = _mv88e6xxx_phy_write(ps, addr, regnum, val); mutex_unlock(&ps->smi_mutex); return ret; } @@ -2918,14 +2909,14 @@ int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int addr = mv88e6xxx_port_to_phy_addr(ds, port); + int addr = mv88e6xxx_port_to_phy_addr(ps, port); int ret; if (addr < 0) - return addr; + return 0xffff; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_read_indirect(ds, addr, regnum); + ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum); mutex_unlock(&ps->smi_mutex); return ret; } @@ -2935,14 +2926,14 @@ mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum, u16 val) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int addr = mv88e6xxx_port_to_phy_addr(ds, port); + int addr = mv88e6xxx_port_to_phy_addr(ps, port); int ret; if (addr < 0) return addr; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_write_indirect(ds, addr, regnum, val); + ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val); mutex_unlock(&ps->smi_mutex); return ret; } @@ -2959,44 +2950,45 @@ static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp) mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6); + ret = _mv88e6xxx_phy_write(ps, 0x0, 0x16, 0x6); if (ret < 0) goto error; /* Enable temperature sensor */ - ret = _mv88e6xxx_phy_read(ds, 0x0, 0x1a); + ret = _mv88e6xxx_phy_read(ps, 0x0, 0x1a); if (ret < 0) goto error; - ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret | (1 << 5)); + ret = _mv88e6xxx_phy_write(ps, 0x0, 0x1a, ret | (1 << 5)); if (ret < 0) goto error; /* Wait for temperature to stabilize */ usleep_range(10000, 12000); - val = _mv88e6xxx_phy_read(ds, 0x0, 0x1a); + val = _mv88e6xxx_phy_read(ps, 0x0, 0x1a); if (val < 0) { ret = val; goto error; } /* Disable temperature sensor */ - ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret & ~(1 << 5)); + ret = _mv88e6xxx_phy_write(ps, 0x0, 0x1a, ret & ~(1 << 5)); if (ret < 0) goto error; *temp = ((val & 0x1f) - 5) * 5; error: - _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0); + _mv88e6xxx_phy_write(ps, 0x0, 0x16, 0x0); mutex_unlock(&ps->smi_mutex); return ret; } static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp) { - int phy = mv88e6xxx_6320_family(ds) ? 3 : 0; + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int phy = mv88e6xxx_6320_family(ps) ? 3 : 0; int ret; *temp = 0; @@ -3012,7 +3004,9 @@ static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp) int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp) { - if (mv88e6xxx_6320_family(ds) || mv88e6xxx_6352_family(ds)) + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + + if (mv88e6xxx_6320_family(ps) || mv88e6xxx_6352_family(ps)) return mv88e63xx_get_temp(ds, temp); return mv88e61xx_get_temp(ds, temp); @@ -3020,10 +3014,11 @@ int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp) int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp) { - int phy = mv88e6xxx_6320_family(ds) ? 3 : 0; + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int phy = mv88e6xxx_6320_family(ps) ? 3 : 0; int ret; - if (!mv88e6xxx_6320_family(ds) && !mv88e6xxx_6352_family(ds)) + if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps)) return -EOPNOTSUPP; *temp = 0; @@ -3039,10 +3034,11 @@ int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp) int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp) { - int phy = mv88e6xxx_6320_family(ds) ? 3 : 0; + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int phy = mv88e6xxx_6320_family(ps) ? 3 : 0; int ret; - if (!mv88e6xxx_6320_family(ds) && !mv88e6xxx_6352_family(ds)) + if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps)) return -EOPNOTSUPP; ret = mv88e6xxx_phy_page_read(ds, phy, 6, 26); @@ -3055,10 +3051,11 @@ int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp) int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) { - int phy = mv88e6xxx_6320_family(ds) ? 3 : 0; + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + int phy = mv88e6xxx_6320_family(ps) ? 3 : 0; int ret; - if (!mv88e6xxx_6320_family(ds) && !mv88e6xxx_6352_family(ds)) + if (!mv88e6xxx_6320_family(ps) && !mv88e6xxx_6352_family(ps)) return -EOPNOTSUPP; *alarm = false; @@ -3073,36 +3070,61 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) } #endif /* CONFIG_NET_DSA_HWMON */ -char *mv88e6xxx_lookup_name(struct device *host_dev, 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) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); - int i, ret; + int i; + for (i = 0; i < num; ++i) + if (table[i].prod_num == prod_num) + return &table[i]; + + return NULL; +} + +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; + const char *name; + int id, prod_num, rev; + + bus = dsa_host_dev_to_mii_bus(host_dev); if (!bus) return NULL; - ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); - if (ret < 0) + id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); + if (id < 0) return NULL; - /* 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(host_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; - } - } + prod_num = (id & 0xfff0) >> 4; + rev = id & 0x000f; - return NULL; + 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; } static int __init mv88e6xxx_init(void) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 236bcaa606e7..4f455d219859 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,12 +383,26 @@ 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; + + /* The device this structure is associated to */ + struct device *dev; + /* When using multi-chip addressing, this mutex protects * access to the indirect access registers. (In single-chip * mode, this mutex is effectively useless.) */ struct mutex smi_mutex; + /* The MII bus and the address on the bus that is used to + * communication with the switch + */ + struct mii_bus *bus; + int sw_addr; + #ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU /* Handles automatic disabling and re-enabling of the PHY * polling unit. @@ -429,9 +429,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); @@ -452,15 +449,18 @@ struct mv88e6xxx_hw_stat { enum stat_type type; }; -int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active); -char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, - const struct mv88e6xxx_switch_id *table, - unsigned int num); +int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active); +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); +int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps); int mv88e6xxx_setup_global(struct dsa_switch *ds); -int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg); -int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val); +int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg); +int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr, + int reg, u16 val); 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); @@ -468,7 +468,7 @@ int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val); int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum); int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum, u16 val); -void mv88e6xxx_ppu_state_init(struct dsa_switch *ds); +void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps); int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum); int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr, int regnum, u16 val); @@ -531,25 +531,4 @@ extern struct dsa_switch_driver mv88e6123_switch_driver; extern struct dsa_switch_driver mv88e6352_switch_driver; extern struct dsa_switch_driver mv88e6171_switch_driver; -#define REG_READ(addr, reg) \ - ({ \ - int __ret; \ - \ - __ret = mv88e6xxx_reg_read(ds, addr, reg); \ - if (__ret < 0) \ - return __ret; \ - __ret; \ - }) - -#define REG_WRITE(addr, reg, val) \ - ({ \ - int __ret; \ - \ - __ret = mv88e6xxx_reg_write(ds, addr, reg, val); \ - if (__ret < 0) \ - return __ret; \ - }) - - - #endif |