summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2016-01-06 20:11:18 +0100
committerDavid S. Miller <davem@davemloft.net>2016-01-07 14:31:26 -0500
commit7f854420fbfe9d49afe2ffb1df052cfe8e215541 (patch)
tree1f3c8d932976b597cdb6db3e53b06b4a95c5d303 /drivers/net
parent801a8ef54e8b21eb6699aaa88681259dafb1d1b5 (diff)
downloadlinux-7f854420fbfe9d49afe2ffb1df052cfe8e215541.tar.bz2
phy: Add API for {un}registering an mdio device to a bus.
Rather than have drivers directly manipulate the mii_bus structure, provide and API for registering and unregistering devices on an MDIO bus, and performing lookups. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c9
-rw-r--r--drivers/net/ethernet/broadcom/b44.c2
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c2
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c30
-rw-r--r--drivers/net/ethernet/ethoc.c4
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c2
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c7
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c2
-rw-r--r--drivers/net/ethernet/smsc/smsc9420.c3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c2
-rw-r--r--drivers/net/ethernet/ti/davinci_mdio.c2
-rw-r--r--drivers/net/phy/mdio_bus.c46
-rw-r--r--drivers/net/phy/phy_device.c21
13 files changed, 86 insertions, 46 deletions
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index 982b581d3484..c8640418fc37 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -502,7 +502,7 @@ static int au1000_mii_probe(struct net_device *dev)
BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
if (aup->phy_addr)
- phydev = aup->mii_bus->phy_map[aup->phy_addr];
+ phydev = mdiobus_get_phy(aup->mii_bus, aup->phy_addr);
else
netdev_info(dev, "using PHY-less setup\n");
return 0;
@@ -512,8 +512,8 @@ static int au1000_mii_probe(struct net_device *dev)
* on the current MAC's MII bus
*/
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
- if (aup->mii_bus->phy_map[phy_addr]) {
- phydev = aup->mii_bus->phy_map[phy_addr];
+ if (mdiobus_get_phy(aup->mii_bus, aup->phy_addr)) {
+ phydev = mdiobus_get_phy(aup->mii_bus, aup->phy_addr);
if (!aup->phy_search_highest_addr)
/* break out with first one found */
break;
@@ -531,7 +531,8 @@ static int au1000_mii_probe(struct net_device *dev)
*/
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
struct phy_device *const tmp_phydev =
- aup->mii_bus->phy_map[phy_addr];
+ mdiobus_get_phy(aup->mii_bus,
+ phy_addr);
if (aup->mac_id == 1)
break;
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 843a4a5864fc..74f0a37c4eb6 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2272,7 +2272,7 @@ static int b44_register_phy_one(struct b44 *bp)
goto err_out_mdiobus;
}
- if (!bp->mii_bus->phy_map[bp->phy_addr] &&
+ if (!mdiobus_is_registered_device(bp->mii_bus, bp->phy_addr) &&
(sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) {
dev_info(sdev->dev,
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index 633b59db813a..0d775964b060 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -573,7 +573,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
}
if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR)
- phydev = mdio->phy_map[pd->phy_address];
+ phydev = mdiobus_get_phy(mdio, pd->phy_address);
else
phydev = phy_find_first(mdio);
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 04e7d0d0e5b1..9293675df7ba 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -1406,7 +1406,7 @@ static void tg3_mdio_config_5785(struct tg3 *tp)
u32 val;
struct phy_device *phydev;
- phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
case PHY_ID_BCM50610:
case PHY_ID_BCM50610M:
@@ -1554,7 +1554,7 @@ static int tg3_mdio_init(struct tg3 *tp)
return i;
}
- phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
if (!phydev || !phydev->drv) {
dev_warn(&tp->pdev->dev, "No PHY devices\n");
@@ -1964,7 +1964,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
u32 old_tx_mode = tp->tx_mode;
if (tg3_flag(tp, USE_PHYLIB))
- autoneg = tp->mdio_bus->phy_map[tp->phy_addr]->autoneg;
+ autoneg = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr)->autoneg;
else
autoneg = tp->link_config.autoneg;
@@ -2000,7 +2000,7 @@ static void tg3_adjust_link(struct net_device *dev)
u8 oldflowctrl, linkmesg = 0;
u32 mac_mode, lcl_adv, rmt_adv;
struct tg3 *tp = netdev_priv(dev);
- struct phy_device *phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ struct phy_device *phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
spin_lock_bh(&tp->lock);
@@ -2089,7 +2089,7 @@ static int tg3_phy_init(struct tg3 *tp)
/* Bring the PHY back to a known state. */
tg3_bmcr_reset(tp);
- phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
/* Attach the MAC to the PHY. */
phydev = phy_connect(tp->dev, phydev_name(phydev),
@@ -2116,7 +2116,7 @@ static int tg3_phy_init(struct tg3 *tp)
SUPPORTED_Asym_Pause);
break;
default:
- phy_disconnect(tp->mdio_bus->phy_map[tp->phy_addr]);
+ phy_disconnect(mdiobus_get_phy(tp->mdio_bus, tp->phy_addr));
return -EINVAL;
}
@@ -2136,7 +2136,7 @@ static void tg3_phy_start(struct tg3 *tp)
if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
return;
- phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER;
@@ -2156,13 +2156,13 @@ static void tg3_phy_stop(struct tg3 *tp)
if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
return;
- phy_stop(tp->mdio_bus->phy_map[tp->phy_addr]);
+ phy_stop(mdiobus_get_phy(tp->mdio_bus, tp->phy_addr));
}
static void tg3_phy_fini(struct tg3 *tp)
{
if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) {
- phy_disconnect(tp->mdio_bus->phy_map[tp->phy_addr]);
+ phy_disconnect(mdiobus_get_phy(tp->mdio_bus, tp->phy_addr));
tp->phy_flags &= ~TG3_PHYFLG_IS_CONNECTED;
}
}
@@ -4046,7 +4046,7 @@ static int tg3_power_down_prepare(struct tg3 *tp)
struct phy_device *phydev;
u32 phyid, advertising;
- phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
@@ -12074,7 +12074,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
struct phy_device *phydev;
if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
return -EAGAIN;
- phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
return phy_ethtool_gset(phydev, cmd);
}
@@ -12141,7 +12141,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
struct phy_device *phydev;
if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
return -EAGAIN;
- phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
return phy_ethtool_sset(phydev, cmd);
}
@@ -12296,7 +12296,7 @@ static int tg3_nway_reset(struct net_device *dev)
if (tg3_flag(tp, USE_PHYLIB)) {
if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
return -EAGAIN;
- r = phy_start_aneg(tp->mdio_bus->phy_map[tp->phy_addr]);
+ r = phy_start_aneg(mdiobus_get_phy(tp->mdio_bus, tp->phy_addr));
} else {
u32 bmcr;
@@ -12414,7 +12414,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
u32 newadv;
struct phy_device *phydev;
- phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
if (!(phydev->supported & SUPPORTED_Pause) ||
(!(phydev->supported & SUPPORTED_Asym_Pause) &&
@@ -13924,7 +13924,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct phy_device *phydev;
if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
return -EAGAIN;
- phydev = tp->mdio_bus->phy_map[tp->phy_addr];
+ phydev = mdiobus_get_phy(tp->mdio_bus, tp->phy_addr);
return phy_mii_ioctl(phydev, ifr, cmd);
}
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index c028b299ab3f..62fa136554ac 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -678,7 +678,7 @@ static int ethoc_mdio_probe(struct net_device *dev)
int err;
if (priv->phy_id != -1)
- phy = priv->mdio->phy_map[priv->phy_id];
+ phy = mdiobus_get_phy(priv->mdio, priv->phy_id);
else
phy = phy_find_first(priv->mdio);
@@ -766,7 +766,7 @@ static int ethoc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (mdio->phy_id >= PHY_MAX_ADDR)
return -ERANGE;
- phy = priv->mdio->phy_map[mdio->phy_id];
+ phy = mdiobus_get_phy(priv->mdio, mdio->phy_id);
if (!phy)
return -ENODEV;
} else {
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 8f3f2cf0dcbf..bb116ad646f6 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -839,7 +839,7 @@ static int ftgmac100_mii_probe(struct ftgmac100 *priv)
/* search for connect PHY device */
for (i = 0; i < PHY_MAX_ADDR; i++) {
- struct phy_device *tmp = priv->mii_bus->phy_map[i];
+ struct phy_device *tmp = mdiobus_get_phy(priv->mii_bus, i);
if (tmp) {
phydev = tmp;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index da255fb4f1d5..502da6f48f95 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -48,6 +48,7 @@
#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/mdio.h>
#include <linux/phy.h>
#include <linux/fec.h>
#include <linux/of.h>
@@ -1926,11 +1927,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)
} else {
/* check for attached phy */
for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
- if ((fep->mii_bus->phy_mask & (1 << phy_id)))
- continue;
- if (fep->mii_bus->phy_map[phy_id] == NULL)
- continue;
- if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
+ if (!mdiobus_is_registered_device(fep->mii_bus, phy_id))
continue;
if (dev_id--)
continue;
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
index 5b13b8c11bef..467ff7033606 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
@@ -180,7 +180,7 @@ int sxgbe_mdio_register(struct net_device *ndev)
}
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
- struct phy_device *phy = mdio_bus->phy_map[phy_addr];
+ struct phy_device *phy = mdiobus_get_phy(mdio_bus, phy_addr);
if (phy) {
char irq_num[4];
diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index 53355c323f54..8594b9e8b28b 100644
--- a/drivers/net/ethernet/smsc/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -1158,7 +1158,8 @@ static int smsc9420_mii_probe(struct net_device *dev)
BUG_ON(pd->phy_dev);
/* Device only supports internal PHY at address 1 */
- if (!pd->mii_bus->phy_map[1]) {
+ phydev = mdiobus_get_phy(pd->mii_bus, 1);
+ if (!phydev) {
netdev_err(dev, "no PHY found at address 1\n");
return -ENODEV;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index f0990eb9460f..bff28595b427 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -252,7 +252,7 @@ int stmmac_mdio_register(struct net_device *ndev)
found = 0;
for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
- struct phy_device *phydev = new_bus->phy_map[addr];
+ struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
if (phydev) {
int act = 0;
char irq_num[4];
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 78299c1592c1..4e7c9b9b042a 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -393,7 +393,7 @@ static int davinci_mdio_probe(struct platform_device *pdev)
/* scan and dump the bus */
for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
- phy = data->bus->phy_map[addr];
+ phy = mdiobus_get_phy(data->bus, addr);
if (phy) {
dev_info(dev, "phy[%d]: device %s, driver %s\n",
phy->mdio.addr, phydev_name(phy),
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index e5b1ccde835b..f28f89e109ba 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -38,6 +38,48 @@
#include <asm/irq.h>
+int mdiobus_register_device(struct mdio_device *mdiodev)
+{
+ if (mdiodev->bus->mdio_map[mdiodev->addr])
+ return -EBUSY;
+
+ mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev;
+
+ return 0;
+}
+EXPORT_SYMBOL(mdiobus_register_device);
+
+int mdiobus_unregister_device(struct mdio_device *mdiodev)
+{
+ if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
+ return -EINVAL;
+
+ mdiodev->bus->mdio_map[mdiodev->addr] = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL(mdiobus_unregister_device);
+
+struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr)
+{
+ struct mdio_device *mdiodev = bus->mdio_map[addr];
+
+ if (!mdiodev)
+ return NULL;
+
+ if (!(mdiodev->flags & MDIO_DEVICE_FLAG_PHY))
+ return NULL;
+
+ return container_of(mdiodev, struct phy_device, mdio);
+}
+EXPORT_SYMBOL(mdiobus_get_phy);
+
+bool mdiobus_is_registered_device(struct mii_bus *bus, int addr)
+{
+ return bus->mdio_map[addr];
+}
+EXPORT_SYMBOL(mdiobus_is_registered_device);
+
/**
* mdiobus_alloc_size - allocate a mii_bus structure
* @size: extra amount of memory to allocate for private storage.
@@ -299,7 +341,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
error:
while (--i >= 0) {
- struct phy_device *phydev = bus->phy_map[i];
+ struct phy_device *phydev = mdiobus_get_phy(bus, i);
if (phydev) {
phy_device_remove(phydev);
phy_device_free(phydev);
@@ -318,7 +360,7 @@ void mdiobus_unregister(struct mii_bus *bus)
bus->state = MDIOBUS_UNREGISTERED;
for (i = 0; i < PHY_MAX_ADDR; i++) {
- struct phy_device *phydev = bus->phy_map[i];
+ struct phy_device *phydev = mdiobus_get_phy(bus, i);
if (phydev) {
phy_device_remove(phydev);
phy_device_free(phydev);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 01e5d52dc37c..e0d5dbb96700 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -166,6 +166,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
mdiodev->dev.bus = &mdio_bus_type;
mdiodev->bus = bus;
mdiodev->addr = addr;
+ mdiodev->flags = MDIO_DEVICE_FLAG_PHY;
dev->speed = 0;
dev->duplex = -1;
@@ -383,10 +384,9 @@ int phy_device_register(struct phy_device *phydev)
{
int err;
- /* Don't register a phy if one is already registered at this address */
- if (phydev->mdio.bus->phy_map[phydev->mdio.addr])
- return -EINVAL;
- phydev->mdio.bus->phy_map[phydev->mdio.addr] = phydev;
+ err = mdiobus_register_device(&phydev->mdio);
+ if (err)
+ return err;
/* Run all of the fixups for this PHY */
err = phy_scan_fixups(phydev);
@@ -404,7 +404,7 @@ int phy_device_register(struct phy_device *phydev)
return 0;
out:
- phydev->mdio.bus->phy_map[phydev->mdio.addr] = NULL;
+ mdiobus_unregister_device(&phydev->mdio);
return err;
}
EXPORT_SYMBOL(phy_device_register);
@@ -419,11 +419,8 @@ EXPORT_SYMBOL(phy_device_register);
*/
void phy_device_remove(struct phy_device *phydev)
{
- struct mii_bus *bus = phydev->mdio.bus;
- int addr = phydev->mdio.addr;
-
device_del(&phydev->mdio.dev);
- bus->phy_map[addr] = NULL;
+ mdiobus_unregister_device(&phydev->mdio);
}
EXPORT_SYMBOL(phy_device_remove);
@@ -433,11 +430,13 @@ EXPORT_SYMBOL(phy_device_remove);
*/
struct phy_device *phy_find_first(struct mii_bus *bus)
{
+ struct phy_device *phydev;
int addr;
for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
- if (bus->phy_map[addr])
- return bus->phy_map[addr];
+ phydev = mdiobus_get_phy(bus, addr);
+ if (phydev)
+ return phydev;
}
return NULL;
}