Merge branch 'dsa_phy_divert'

Florian Fainelli says:

====================
net: dsa: support PHY reads/writes diversion

This patch series completes the PHY reads/writes diversion when we need to use
the slave MII bus provided by DSA and the underlying switch drivers to
implement the real PHY reads and writes. This is particularly useful when they
are conflicting MDIO bus addresses as in the case of multiple Broadcom switches
connected to each other (internal and external, or just external).
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2015-03-11 17:56:39 -04:00
commit 388a83576a
3 changed files with 48 additions and 13 deletions

View File

@ -88,7 +88,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
return 0;
}
static int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
{
u32 addr;
int ret;
@ -108,6 +108,7 @@ static int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
return addr;
}
EXPORT_SYMBOL(of_mdio_parse_addr);
/**
* of_mdiobus_register - Register mii_bus and create PHYs from the device tree

View File

@ -24,6 +24,7 @@ struct phy_device *of_phy_attach(struct net_device *dev,
phy_interface_t iface);
extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
extern int of_mdio_parse_addr(struct device *dev, const struct device_node *np);
#else /* CONFIG_OF */
static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
@ -60,6 +61,12 @@ static inline struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np)
{
return NULL;
}
static inline int of_mdio_parse_addr(struct device *dev,
const struct device_node *np)
{
return -ENOSYS;
}
#endif /* CONFIG_OF */
#if defined(CONFIG_OF) && defined(CONFIG_FIXED_PHY)

View File

@ -617,6 +617,24 @@ static int dsa_slave_fixed_link_update(struct net_device *dev,
}
/* slave device setup *******************************************************/
static int dsa_slave_phy_connect(struct dsa_slave_priv *p,
struct net_device *slave_dev,
int addr)
{
struct dsa_switch *ds = p->parent;
p->phy = ds->slave_mii_bus->phy_map[addr];
if (!p->phy)
return -ENODEV;
/* Use already configured phy mode */
p->phy_interface = p->phy->interface;
phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
p->phy_interface);
return 0;
}
static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
struct net_device *slave_dev)
{
@ -650,10 +668,24 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
if (ds->drv->get_phy_flags)
phy_flags = ds->drv->get_phy_flags(ds, p->port);
if (phy_dn)
p->phy = of_phy_connect(slave_dev, phy_dn,
dsa_slave_adjust_link, phy_flags,
p->phy_interface);
if (phy_dn) {
ret = of_mdio_parse_addr(&slave_dev->dev, phy_dn);
/* If this PHY address is part of phys_mii_mask, which means
* that we need to divert reads and writes to/from it, then we
* want to bind this device using the slave MII bus created by
* DSA to make that happen.
*/
if (ret >= 0 && (ds->phys_mii_mask & (1 << ret))) {
ret = dsa_slave_phy_connect(p, slave_dev, ret);
if (ret)
return ret;
} else {
p->phy = of_phy_connect(slave_dev, phy_dn,
dsa_slave_adjust_link,
phy_flags,
p->phy_interface);
}
}
if (p->phy && phy_is_fixed)
fixed_phy_set_link_update(p->phy, dsa_slave_fixed_link_update);
@ -662,14 +694,9 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
* MDIO bus instead
*/
if (!p->phy) {
p->phy = ds->slave_mii_bus->phy_map[p->port];
if (!p->phy)
return -ENODEV;
/* Use already configured phy mode */
p->phy_interface = p->phy->interface;
phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
p->phy_interface);
ret = dsa_slave_phy_connect(p, slave_dev, p->port);
if (ret)
return ret;
} else {
netdev_info(slave_dev, "attached PHY at address %d [%s]\n",
p->phy->addr, p->phy->drv->name);