Commit 99717bdf authored by David S. Miller's avatar David S. Miller

Merge branch 'dsa-refactoring-set-1'

Andrew Lunn says:

====================
DSA refactoring: set 1

There has been a long running effort to refractor DSA probing to make
the switches true linux devices. Here are a small collection of
patches moving in this direction. Most have been seen before.

We take a little step forward by passing the dsa device point to the
driver, thus allowing it to perform resource allocations using the
normal mechanisms. This device structure will later be replaced by the
devices own device structure.

Future patches will add a true driver probe function, so we rename the
current probe function, cleaning up the namespace.

phys_port_mask continually confuses me, thinking it is about PHYs. But
it is actually about ports enabled to the outside world. So rename it to
enabled_port_mask.

Lots more patches yet to follow, this is just doing some ground work.

v2:
  enabled_port_mask instread of user_port_masks
  Added Tested-by's and Reviewed-by.
====================
Tested-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 71bbe25d c156913b
...@@ -135,8 +135,17 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds) ...@@ -135,8 +135,17 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds)
return BCM_SF2_STATS_SIZE; return BCM_SF2_STATS_SIZE;
} }
static char *bcm_sf2_sw_probe(struct device *host_dev, int sw_addr) static 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"; return "Broadcom Starfighter 2";
} }
...@@ -151,7 +160,7 @@ static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port) ...@@ -151,7 +160,7 @@ static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
* the same VLAN. * the same VLAN.
*/ */
for (i = 0; i < priv->hw_params.num_ports; i++) { 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; continue;
reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i)); reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i));
...@@ -1000,7 +1009,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) ...@@ -1000,7 +1009,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
/* Enable all valid ports and disable those unused */ /* Enable all valid ports and disable those unused */
for (port = 0; port < priv->hw_params.num_ports; port++) { for (port = 0; port < priv->hw_params.num_ports; port++) {
/* IMP port receives special treatment */ /* 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); bcm_sf2_port_setup(ds, port, NULL);
else if (dsa_is_cpu_port(ds, port)) else if (dsa_is_cpu_port(ds, port))
bcm_sf2_imp_setup(ds, port); bcm_sf2_imp_setup(ds, port);
...@@ -1013,11 +1022,12 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) ...@@ -1013,11 +1022,12 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
* 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such
* that we can use the regular SWITCH_MDIO master controller instead. * that we can use the regular SWITCH_MDIO master controller instead.
* *
* By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask * By default, DSA initializes ds->phys_mii_mask to
* to have a 1:1 mapping between Port address and PHY address in order * ds->enabled_port_mask to have a 1:1 mapping between Port address
* to utilize the slave_mii_bus instance to read from Port PHYs. This is * and PHY address in order to utilize the slave_mii_bus instance to
* not what we want here, so we initialize phys_mii_mask 0 to always * read from Port PHYs. This is not what we want here, so we
* utilize the "master" MDIO bus backed by the "mdio-unimac" driver. * 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")) if (of_machine_is_compatible("brcm,bcm7445d0"))
ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0)); 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) ...@@ -1275,7 +1285,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
* bcm_sf2_sw_setup * bcm_sf2_sw_setup
*/ */
for (port = 0; port < DSA_MAX_PORTS; port++) { 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)) dsa_is_cpu_port(ds, port))
bcm_sf2_port_disable(ds, port, NULL); bcm_sf2_port_disable(ds, port, NULL);
} }
...@@ -1299,7 +1309,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) ...@@ -1299,7 +1309,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
bcm_sf2_gphy_enable_set(ds, true); bcm_sf2_gphy_enable_set(ds, true);
for (port = 0; port < DSA_MAX_PORTS; port++) { 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); bcm_sf2_port_setup(ds, port, NULL);
else if (dsa_is_cpu_port(ds, port)) else if (dsa_is_cpu_port(ds, port))
bcm_sf2_imp_setup(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, ...@@ -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 = { static struct dsa_switch_driver bcm_sf2_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_BRCM, .tag_protocol = DSA_TAG_PROTO_BRCM,
.priv_size = sizeof(struct bcm_sf2_priv), .probe = bcm_sf2_sw_drv_probe,
.probe = bcm_sf2_sw_probe,
.setup = bcm_sf2_sw_setup, .setup = bcm_sf2_sw_setup,
.set_addr = bcm_sf2_sw_set_addr, .set_addr = bcm_sf2_sw_set_addr,
.get_phy_flags = bcm_sf2_sw_get_phy_flags, .get_phy_flags = bcm_sf2_sw_get_phy_flags,
......
...@@ -19,12 +19,9 @@ ...@@ -19,12 +19,9 @@
static int reg_read(struct dsa_switch *ds, int addr, int reg) 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 mdiobus_read_nested(priv->bus, priv->sw_addr + addr, reg);
return -EINVAL;
return mdiobus_read_nested(bus, ds->pd->sw_addr + addr, reg);
} }
#define REG_READ(addr, reg) \ #define REG_READ(addr, reg) \
...@@ -40,12 +37,9 @@ static int reg_read(struct dsa_switch *ds, int addr, int 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) 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); struct mv88e6060_priv *priv = ds_to_priv(ds);
if (bus == NULL)
return -EINVAL;
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) \ #define REG_WRITE(addr, reg, val) \
...@@ -57,14 +51,10 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) ...@@ -57,14 +51,10 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
return __ret; \ return __ret; \
}) })
static char *mv88e6060_probe(struct device *host_dev, int sw_addr) static 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; int ret;
if (bus == NULL)
return NULL;
ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID); ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID);
if (ret >= 0) { if (ret >= 0) {
if (ret == PORT_SWITCH_ID_6060) if (ret == PORT_SWITCH_ID_6060)
...@@ -79,6 +69,27 @@ static char *mv88e6060_probe(struct device *host_dev, int sw_addr) ...@@ -79,6 +69,27 @@ static char *mv88e6060_probe(struct device *host_dev, int sw_addr)
return NULL; return NULL;
} }
static char *mv88e6060_drv_probe(struct device *dsa_dev,
struct device *host_dev,
int sw_addr, void **_priv)
{
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
struct mv88e6060_priv *priv;
char *name;
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) static int mv88e6060_switch_reset(struct dsa_switch *ds)
{ {
int i; int i;
...@@ -159,7 +170,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p) ...@@ -159,7 +170,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
REG_WRITE(addr, PORT_VLAN_MAP, REG_WRITE(addr, PORT_VLAN_MAP,
((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) | ((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
(dsa_is_cpu_port(ds, p) ? (dsa_is_cpu_port(ds, p) ?
ds->phys_port_mask : ds->enabled_port_mask :
BIT(ds->dst->cpu_port))); BIT(ds->dst->cpu_port)));
/* Port Association Vector: when learning source addresses /* Port Association Vector: when learning source addresses
...@@ -174,8 +185,8 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p) ...@@ -174,8 +185,8 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
static int mv88e6060_setup(struct dsa_switch *ds) static int mv88e6060_setup(struct dsa_switch *ds)
{ {
int i;
int ret; int ret;
int i;
ret = mv88e6060_switch_reset(ds); ret = mv88e6060_switch_reset(ds);
if (ret < 0) if (ret < 0)
...@@ -238,7 +249,7 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) ...@@ -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 = { static struct dsa_switch_driver mv88e6060_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_TRAILER, .tag_protocol = DSA_TAG_PROTO_TRAILER,
.probe = mv88e6060_probe, .probe = mv88e6060_drv_probe,
.setup = mv88e6060_setup, .setup = mv88e6060_setup,
.set_addr = mv88e6060_set_addr, .set_addr = mv88e6060_set_addr,
.phy_read = mv88e6060_phy_read, .phy_read = mv88e6060_phy_read,
......
...@@ -108,4 +108,15 @@ ...@@ -108,4 +108,15 @@
#define GLOBAL_ATU_MAC_23 0x0e #define GLOBAL_ATU_MAC_23 0x0e
#define GLOBAL_ATU_MAC_45 0x0f #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 #endif
...@@ -29,10 +29,13 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = { ...@@ -29,10 +29,13 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
{ PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" }, { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" },
}; };
static char *mv88e6123_probe(struct device *host_dev, int sw_addr) static 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, return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
ARRAY_SIZE(mv88e6123_table)); mv88e6123_table,
ARRAY_SIZE(mv88e6123_table));
} }
static int mv88e6123_setup_global(struct dsa_switch *ds) static int mv88e6123_setup_global(struct dsa_switch *ds)
...@@ -73,6 +76,8 @@ static int mv88e6123_setup(struct dsa_switch *ds) ...@@ -73,6 +76,8 @@ static int mv88e6123_setup(struct dsa_switch *ds)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret; int ret;
ps->ds = ds;
ret = mv88e6xxx_setup_common(ds); ret = mv88e6xxx_setup_common(ds);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -102,8 +107,7 @@ static int mv88e6123_setup(struct dsa_switch *ds) ...@@ -102,8 +107,7 @@ static int mv88e6123_setup(struct dsa_switch *ds)
struct dsa_switch_driver mv88e6123_switch_driver = { struct dsa_switch_driver mv88e6123_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA, .tag_protocol = DSA_TAG_PROTO_EDSA,
.priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6123_drv_probe,
.probe = mv88e6123_probe,
.setup = mv88e6123_setup, .setup = mv88e6123_setup,
.set_addr = mv88e6xxx_set_addr_indirect, .set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read, .phy_read = mv88e6xxx_phy_read,
......
...@@ -25,10 +25,13 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = { ...@@ -25,10 +25,13 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
{ PORT_SWITCH_ID_6185, "Marvell 88E6185" }, { PORT_SWITCH_ID_6185, "Marvell 88E6185" },
}; };
static char *mv88e6131_probe(struct device *host_dev, int sw_addr) static 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, return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
ARRAY_SIZE(mv88e6131_table)); mv88e6131_table,
ARRAY_SIZE(mv88e6131_table));
} }
static int mv88e6131_setup_global(struct dsa_switch *ds) static int mv88e6131_setup_global(struct dsa_switch *ds)
...@@ -91,6 +94,8 @@ static int mv88e6131_setup(struct dsa_switch *ds) ...@@ -91,6 +94,8 @@ static int mv88e6131_setup(struct dsa_switch *ds)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret; int ret;
ps->ds = ds;
ret = mv88e6xxx_setup_common(ds); ret = mv88e6xxx_setup_common(ds);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -159,8 +164,7 @@ mv88e6131_phy_write(struct dsa_switch *ds, ...@@ -159,8 +164,7 @@ mv88e6131_phy_write(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6131_switch_driver = { struct dsa_switch_driver mv88e6131_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_DSA, .tag_protocol = DSA_TAG_PROTO_DSA,
.priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6131_drv_probe,
.probe = mv88e6131_probe,
.setup = mv88e6131_setup, .setup = mv88e6131_setup,
.set_addr = mv88e6xxx_set_addr_direct, .set_addr = mv88e6xxx_set_addr_direct,
.phy_read = mv88e6131_phy_read, .phy_read = mv88e6131_phy_read,
......
...@@ -24,10 +24,13 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = { ...@@ -24,10 +24,13 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
{ PORT_SWITCH_ID_6351, "Marvell 88E6351" }, { PORT_SWITCH_ID_6351, "Marvell 88E6351" },
}; };
static char *mv88e6171_probe(struct device *host_dev, int sw_addr) static 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, return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
ARRAY_SIZE(mv88e6171_table)); mv88e6171_table,
ARRAY_SIZE(mv88e6171_table));
} }
static int mv88e6171_setup_global(struct dsa_switch *ds) static int mv88e6171_setup_global(struct dsa_switch *ds)
...@@ -69,6 +72,8 @@ static int mv88e6171_setup(struct dsa_switch *ds) ...@@ -69,6 +72,8 @@ static int mv88e6171_setup(struct dsa_switch *ds)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret; int ret;
ps->ds = ds;
ret = mv88e6xxx_setup_common(ds); ret = mv88e6xxx_setup_common(ds);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -88,8 +93,7 @@ static int mv88e6171_setup(struct dsa_switch *ds) ...@@ -88,8 +93,7 @@ static int mv88e6171_setup(struct dsa_switch *ds)
struct dsa_switch_driver mv88e6171_switch_driver = { struct dsa_switch_driver mv88e6171_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA, .tag_protocol = DSA_TAG_PROTO_EDSA,
.priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6171_drv_probe,
.probe = mv88e6171_probe,
.setup = mv88e6171_setup, .setup = mv88e6171_setup,
.set_addr = mv88e6xxx_set_addr_indirect, .set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect, .phy_read = mv88e6xxx_phy_read_indirect,
......
...@@ -37,10 +37,13 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = { ...@@ -37,10 +37,13 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
{ PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" }, { PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" },
}; };
static char *mv88e6352_probe(struct device *host_dev, int sw_addr) static 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, return mv88e6xxx_drv_probe(dsa_dev, host_dev, sw_addr, priv,
ARRAY_SIZE(mv88e6352_table)); mv88e6352_table,
ARRAY_SIZE(mv88e6352_table));
} }
static int mv88e6352_setup_global(struct dsa_switch *ds) static int mv88e6352_setup_global(struct dsa_switch *ds)
...@@ -81,6 +84,8 @@ static int mv88e6352_setup(struct dsa_switch *ds) ...@@ -81,6 +84,8 @@ static int mv88e6352_setup(struct dsa_switch *ds)
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret; int ret;
ps->ds = ds;
ret = mv88e6xxx_setup_common(ds); ret = mv88e6xxx_setup_common(ds);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -302,8 +307,7 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds, ...@@ -302,8 +307,7 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6352_switch_driver = { struct dsa_switch_driver mv88e6352_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA, .tag_protocol = DSA_TAG_PROTO_EDSA,
.priv_size = sizeof(struct mv88e6xxx_priv_state), .probe = mv88e6352_drv_probe,
.probe = mv88e6352_probe,
.setup = mv88e6352_setup, .setup = mv88e6352_setup,
.set_addr = mv88e6xxx_set_addr_indirect, .set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect, .phy_read = mv88e6xxx_phy_read_indirect,
......
...@@ -94,15 +94,12 @@ static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, ...@@ -94,15 +94,12 @@ static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr,
static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg) static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
{ {
struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret; int ret;
assert_smi_lock(ds); assert_smi_lock(ds);
if (bus == NULL) ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg);
return -EINVAL;
ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -159,17 +156,14 @@ static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, ...@@ -159,17 +156,14 @@ static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg,
u16 val) u16 val)
{ {
struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
assert_smi_lock(ds); assert_smi_lock(ds);
if (bus == NULL)
return -EINVAL;
dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n", dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
addr, reg, val); 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 dsa_switch *ds, int addr, int reg, u16 val)
...@@ -281,7 +275,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly) ...@@ -281,7 +275,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work); ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
if (mutex_trylock(&ps->ppu_mutex)) { if (mutex_trylock(&ps->ppu_mutex)) {
struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1; struct dsa_switch *ds = ps->ds;
if (mv88e6xxx_ppu_enable(ds) == 0) if (mv88e6xxx_ppu_enable(ds) == 0)
ps->ppu_disabled = 0; ps->ppu_disabled = 0;
...@@ -2322,7 +2316,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work) ...@@ -2322,7 +2316,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
int port; int port;
ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work); ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work);
ds = ((struct dsa_switch *)ps) - 1; ds = ps->ds;
mutex_lock(&ps->smi_mutex); mutex_lock(&ps->smi_mutex);
...@@ -2670,6 +2664,7 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) ...@@ -2670,6 +2664,7 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
{ {
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
ps->ds = ds;
mutex_init(&ps->smi_mutex); mutex_init(&ps->smi_mutex);
ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0; ps->id = REG_READ(REG_PORT(0), PORT_SWITCH_ID) & 0xfff0;
...@@ -3073,11 +3068,10 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) ...@@ -3073,11 +3068,10 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
} }
#endif /* CONFIG_NET_DSA_HWMON */ #endif /* CONFIG_NET_DSA_HWMON */
char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, static char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
const struct mv88e6xxx_switch_id *table, const struct mv88e6xxx_switch_id *table,
unsigned int num) unsigned int num)
{ {
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
int i, ret; int i, ret;
if (!bus) if (!bus)
...@@ -3095,7 +3089,8 @@ char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, ...@@ -3095,7 +3089,8 @@ char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
/* Look up only the product number */ /* Look up only the product number */
for (i = 0; i < num; ++i) { for (i = 0; i < num; ++i) {
if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) { if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) {
dev_warn(host_dev, "unknown revision %d, using base switch 0x%x\n", dev_warn(&bus->dev,
"unknown revision %d, using base switch 0x%x\n",
ret & PORT_SWITCH_ID_REV_MASK, ret & PORT_SWITCH_ID_REV_MASK,
ret & PORT_SWITCH_ID_PROD_NUM_MASK); ret & PORT_SWITCH_ID_PROD_NUM_MASK);
return table[i].name; return table[i].name;
...@@ -3105,6 +3100,32 @@ char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, ...@@ -3105,6 +3100,32 @@ char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
return NULL; return NULL;
} }
char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv,
const struct mv88e6xxx_switch_id *table,
unsigned int num)
{
struct mv88e6xxx_priv_state *ps;
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
char *name;
if (!bus)
return NULL;
name = mv88e6xxx_lookup_name(bus, sw_addr, table, num);
if (name) {
ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
if (!ps)
return NULL;
*priv = ps;
ps->bus = dsa_host_dev_to_mii_bus(host_dev);
if (!ps->bus)
return NULL;
ps->sw_addr = sw_addr;
}
return name;
}
static int __init mv88e6xxx_init(void) static int __init mv88e6xxx_init(void)
{ {
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
......
...@@ -397,12 +397,21 @@ struct mv88e6xxx_priv_port { ...@@ -397,12 +397,21 @@ struct mv88e6xxx_priv_port {
}; };
struct mv88e6xxx_priv_state { struct mv88e6xxx_priv_state {
/* The dsa_switch this private structure is related to */
struct dsa_switch *ds;
/* When using multi-chip addressing, this mutex protects /* When using multi-chip addressing, this mutex protects
* access to the indirect access registers. (In single-chip * access to the indirect access registers. (In single-chip
* mode, this mutex is effectively useless.) * mode, this mutex is effectively useless.)
*/ */
struct mutex smi_mutex; 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 #ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
/* Handles automatic disabling and re-enabling of the PHY /* Handles automatic disabling and re-enabling of the PHY
* polling unit. * polling unit.
...@@ -453,9 +462,11 @@ struct mv88e6xxx_hw_stat { ...@@ -453,9 +462,11 @@ struct mv88e6xxx_hw_stat {
}; };
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active); int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
const struct mv88e6xxx_switch_id *table, int sw_addr, void **priv,
unsigned int num); const struct mv88e6xxx_switch_id *table,
unsigned int num);
int mv88e6xxx_setup_ports(struct dsa_switch *ds); int mv88e6xxx_setup_ports(struct dsa_switch *ds);
int mv88e6xxx_setup_common(struct dsa_switch *ds); int mv88e6xxx_setup_common(struct dsa_switch *ds);
int mv88e6xxx_setup_global(struct dsa_switch *ds); int mv88e6xxx_setup_global(struct dsa_switch *ds);
......
...@@ -129,6 +129,12 @@ struct dsa_switch { ...@@ -129,6 +129,12 @@ struct dsa_switch {
struct dsa_switch_tree *dst; struct dsa_switch_tree *dst;
int index; int index;
/*
* Give the switch driver somewhere to hang its private data
* structure.
*/
void *priv;
/* /*
* Tagging protocol understood by this switch * Tagging protocol understood by this switch
*/ */
...@@ -161,7 +167,7 @@ struct dsa_switch { ...@@ -161,7 +167,7 @@ struct dsa_switch {
* Slave mii_bus and devices for the individual ports. * Slave mii_bus and devices for the individual ports.
*/ */
u32 dsa_port_mask; u32 dsa_port_mask;
u32 phys_port_mask; u32 enabled_port_mask;
u32 phys_mii_mask; u32 phys_mii_mask;
struct mii_bus *slave_mii_bus; struct mii_bus *slave_mii_bus;
struct net_device *ports[DSA_MAX_PORTS]; struct net_device *ports[DSA_MAX_PORTS];
...@@ -179,7 +185,7 @@ static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p) ...@@ -179,7 +185,7 @@ static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p) static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
{ {
return ds->phys_port_mask & (1 << p) && ds->ports[p]; return ds->enabled_port_mask & (1 << p) && ds->ports[p];
} }
static inline u8 dsa_upstream_port(struct dsa_switch *ds) static inline u8 dsa_upstream_port(struct dsa_switch *ds)
...@@ -207,12 +213,12 @@ struct dsa_switch_driver { ...@@ -207,12 +213,12 @@ struct dsa_switch_driver {
struct list_head list; struct list_head list;
enum dsa_tag_protocol tag_protocol; enum dsa_tag_protocol tag_protocol;
int priv_size;
/* /*
* Probing and setup. * Probing and setup.
*/ */
char *(*probe)(struct device *host_dev, int sw_addr); char *(*probe)(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv);
int (*setup)(struct dsa_switch *ds); int (*setup)(struct dsa_switch *ds);
int (*set_addr)(struct dsa_switch *ds, u8 *addr); int (*set_addr)(struct dsa_switch *ds, u8 *addr);
u32 (*get_phy_flags)(struct dsa_switch *ds, int port); u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
...@@ -341,7 +347,7 @@ struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev); ...@@ -341,7 +347,7 @@ struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev);
static inline void *ds_to_priv(struct dsa_switch *ds) static inline void *ds_to_priv(struct dsa_switch *ds)
{ {
return (void *)(ds + 1); return ds->priv;
} }
static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst) static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst)
......
...@@ -51,7 +51,8 @@ void unregister_switch_driver(struct dsa_switch_driver *drv) ...@@ -51,7 +51,8 @@ void unregister_switch_driver(struct dsa_switch_driver *drv)
EXPORT_SYMBOL_GPL(unregister_switch_driver); EXPORT_SYMBOL_GPL(unregister_switch_driver);
static struct dsa_switch_driver * static struct dsa_switch_driver *
dsa_switch_probe(struct device *host_dev, int sw_addr, char **_name) dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr,
char **_name, void **priv)
{ {
struct dsa_switch_driver *ret; struct dsa_switch_driver *ret;
struct list_head *list; struct list_head *list;
...@@ -66,7 +67,7 @@ dsa_switch_probe(struct device *host_dev, int sw_addr, char **_name) ...@@ -66,7 +67,7 @@ dsa_switch_probe(struct device *host_dev, int sw_addr, char **_name)
drv = list_entry(list, struct dsa_switch_driver, list); drv = list_entry(list, struct dsa_switch_driver, list);
name = drv->probe(host_dev, sw_addr); name = drv->probe(parent, host_dev, sw_addr, priv);
if (name != NULL) { if (name != NULL) {
ret = drv; ret = drv;
break; break;
...@@ -245,7 +246,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) ...@@ -245,7 +246,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
} else if (!strcmp(name, "dsa")) { } else if (!strcmp(name, "dsa")) {
ds->dsa_port_mask |= 1 << i; ds->dsa_port_mask |= 1 << i;
} else { } else {
ds->phys_port_mask |= 1 << i; ds->enabled_port_mask |= 1 << i;
} }
valid_name_found = true; valid_name_found = true;
} }
...@@ -258,7 +259,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) ...@@ -258,7 +259,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
/* Make the built-in MII bus mask match the number of ports, /* Make the built-in MII bus mask match the number of ports,
* switch drivers can override this later * switch drivers can override this later
*/ */
ds->phys_mii_mask = ds->phys_port_mask; ds->phys_mii_mask = ds->enabled_port_mask;
/* /*
* If the CPU connects to this switch, set the switch tree * If the CPU connects to this switch, set the switch tree
...@@ -324,7 +325,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) ...@@ -324,7 +325,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
* Create network devices for physical switch ports. * Create network devices for physical switch ports.
*/ */
for (i = 0; i < DSA_MAX_PORTS; i++) { for (i = 0; i < DSA_MAX_PORTS; i++) {
if (!(ds->phys_port_mask & (1 << i))) if (!(ds->enabled_port_mask & (1 << i)))
continue; continue;
ret = dsa_slave_create(ds, parent, i, pd->port_names[i]); ret = dsa_slave_create(ds, parent, i, pd->port_names[i]);
...@@ -383,11 +384,12 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, ...@@ -383,11 +384,12 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
struct dsa_switch *ds; struct dsa_switch *ds;
int ret; int ret;
char *name; char *name;
void *priv;
/* /*
* Probe for switch model. * Probe for switch model.
*/ */
drv = dsa_switch_probe(host_dev, pd->sw_addr, &name); drv = dsa_switch_probe(parent, host_dev, pd->sw_addr, &name, &priv);
if (drv == NULL) { if (drv == NULL) {
netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n", netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n",
index); index);
...@@ -400,7 +402,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, ...@@ -400,7 +402,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
/* /*
* Allocate and initialise switch state. * Allocate and initialise switch state.
*/ */
ds = devm_kzalloc(parent, sizeof(*ds) + drv->priv_size, GFP_KERNEL); ds = devm_kzalloc(parent, sizeof(*ds), GFP_KERNEL);
if (ds == NULL) if (ds == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -408,6 +410,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, ...@@ -408,6 +410,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
ds->index = index; ds->index = index;
ds->pd = pd; ds->pd = pd;
ds->drv = drv; ds->drv = drv;
ds->priv = priv;
ds->tag_protocol = drv->tag_protocol; ds->tag_protocol = drv->tag_protocol;
ds->master_dev = host_dev; ds->master_dev = host_dev;
...@@ -432,7 +435,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds) ...@@ -432,7 +435,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
/* Destroy network devices for physical switch ports. */ /* Destroy network devices for physical switch ports. */
for (port = 0; port < DSA_MAX_PORTS; port++) { for (port = 0; port < DSA_MAX_PORTS; port++) {
if (!(ds->phys_port_mask & (1 << port))) if (!(ds->enabled_port_mask & (1 << port)))
continue; continue;
if (!ds->ports[port]) if (!ds->ports[port])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment