]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
phy: Add API for {un}registering an mdio device to a bus.
authorAndrew Lunn <andrew@lunn.ch>
Wed, 6 Jan 2016 19:11:18 +0000 (20:11 +0100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 7 Jan 2016 19:31:26 +0000 (14:31 -0500)
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>
17 files changed:
drivers/net/ethernet/amd/au1000_eth.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/ethoc.c
drivers/net/ethernet/faraday/ftgmac100.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
drivers/net/ethernet/smsc/smsc9420.c
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
drivers/net/ethernet/ti/davinci_mdio.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy_device.c
drivers/of/of_mdio.c
include/linux/mdio.h
include/linux/phy.h
net/dsa/slave.c

index 982b581d3484a12c36a4b66ad79724118fbbd6d8..c8640418fc37853020734aef4eb9f6b04a061e03 100644 (file)
@@ -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;
index 843a4a5864fc9657c48cb7bc73fe59506dbfb7f4..74f0a37c4eb662849212a2a6d0184f65d0fd5512 100644 (file)
@@ -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,
index 633b59db813a9d644309d17bc788ef2331b1746a..0d775964b06016bfcc66352c99c0164c6957d773 100644 (file)
@@ -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);
 
index 04e7d0d0e5b138e9e123c8b4ddfd59a191bf5da4..9293675df7ba99c44b2f77c739fbe12da0e86093 100644 (file)
@@ -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);
        }
 
index c028b299ab3f6f917528373748ff2df88326466f..62fa136554ac29a49074e5f176b3fc9ac8d37042 100644 (file)
@@ -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 {
index 8f3f2cf0dcbf6c77b30eafd124c45c8085f07e0e..bb116ad646f6a7ae1ebd4232b5218018aede3eb9 100644 (file)
@@ -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;
index da255fb4f1d56fca1b25b94a436a8279486bb9b6..502da6f48f95e5e52a43ce5666a5c265fcd9cfe3 100644 (file)
@@ -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;
index 5b13b8c11bef240f6c4a4b655509da29de9634be..467ff7033606f50dccf9c775e91d54be5e9a6db3 100644 (file)
@@ -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];
index 53355c323f54d5b75b79e2896123d3654092c4ed..8594b9e8b28b31d1a6f8504511df0808f4dcfefb 100644 (file)
@@ -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;
        }
index f0990eb9460fa78eed37a160d1e4e8332f90fb93..bff28595b427927700c27fe48c7eb75b78cfecde 100644 (file)
@@ -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];
index 78299c1592c1508f5de67ae3c9fee062290dd7b4..4e7c9b9b042a3724ee9b8dda0b19e2f441caf836 100644 (file)
@@ -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),
index e5b1ccde835bc9656c0571c8afde606aa3471567..f28f89e109ba2c8d3e839cafa9ccc13122ab180e 100644 (file)
 
 #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);
index 01e5d52dc37ca9a34ea62f6e31cce331a372b8db..e0d5dbb967009d0ad8bbac945fc4b8dd114e1f2e 100644 (file)
@@ -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;
 }
index c0292051392e9b93421175b98e93a8f6153f77b1..6febe2df76f902a823bb8b94ca742c3299439a5a 100644 (file)
@@ -193,7 +193,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 
                for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
                        /* skip already registered PHYs */
-                       if (mdio->phy_map[addr])
+                       if (mdiobus_is_registered_device(mdio, addr))
                                continue;
 
                        /* be noisy to encourage people to set reg property */
index 94f9f1491cdeaaf2364d2bba48d2818117559b22..8cd9579e18ea7648dab189997a9b8458427e925d 100644 (file)
@@ -19,9 +19,12 @@ struct mdio_device {
        struct mii_bus *bus;
        /* Bus address of the MDIO device (0-31) */
        int addr;
+       int flags;
 };
 #define to_mdio_device(d) container_of(d, struct mdio_device, dev)
 
+#define MDIO_DEVICE_FLAG_PHY           1
+
 static inline bool mdio_phy_id_is_c45(int phy_id)
 {
        return (phy_id & MDIO_PHY_ID_C45) && !(phy_id & ~MDIO_PHY_ID_C45_MASK);
@@ -188,4 +191,9 @@ int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum);
 int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
 int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val);
 
+int mdiobus_register_device(struct mdio_device *mdiodev);
+int mdiobus_unregister_device(struct mdio_device *mdiodev);
+bool mdiobus_is_registered_device(struct mii_bus *bus, int addr);
+struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr);
+
 #endif /* __LINUX_MDIO_H__ */
index 239a0c2bc49dfaecccb137f01cbef97a12a1aeb9..2d7beef208258b64b0434dfac24b90d94521544e 100644 (file)
@@ -180,7 +180,7 @@ struct mii_bus {
        struct device dev;
 
        /* list of all PHYs on bus */
-       struct phy_device *phy_map[PHY_MAX_ADDR];
+       struct mdio_device *mdio_map[PHY_MAX_ADDR];
 
        /* PHY addresses to be ignored when probing */
        u32 phy_mask;
index 5f45e68b52dca9c1dcd1965086254995c162ce1c..2771713714f1803c18020f1b84741c80a9e2e26e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/phy_fixed.h>
 #include <linux/of_net.h>
 #include <linux/of_mdio.h>
+#include <linux/mdio.h>
 #include <net/rtnetlink.h>
 #include <net/switchdev.h>
 #include <linux/if_bridge.h>
@@ -997,7 +998,7 @@ static int dsa_slave_phy_connect(struct dsa_slave_priv *p,
 {
        struct dsa_switch *ds = p->parent;
 
-       p->phy = ds->slave_mii_bus->phy_map[addr];
+       p->phy = mdiobus_get_phy(ds->slave_mii_bus, addr);
        if (!p->phy) {
                netdev_err(slave_dev, "no phy at %d\n", addr);
                return -ENODEV;