Add support for probing MMDs above 7 for a valid devices-in-package
specifier.

Signed-off-by: Russell King <[email protected]>
---
 drivers/net/phy/phy_device.c | 39 ++++++++++++++++++++++++++++++++++--
 include/linux/phy.h          |  2 ++
 2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 0d6b6ca66216..fa9164ac0f3d 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -659,6 +659,28 @@ struct phy_device *phy_device_create(struct mii_bus *bus, 
int addr, u32 phy_id,
 }
 EXPORT_SYMBOL(phy_device_create);
 
+/* phy_c45_probe_present - checks to see if a MMD is present in the package
+ * @bus: the target MII bus
+ * @prtad: PHY package address on the MII bus
+ * @devad: PHY device (MMD) address
+ *
+ * Read the MDIO_STAT2 register, and check whether a device is responding
+ * at this address.
+ *
+ * Returns: negative error number on bus access error, zero if no device
+ * is responding, or positive if a device is present.
+ */
+static int phy_c45_probe_present(struct mii_bus *bus, int prtad, int devad)
+{
+       int stat2;
+
+       stat2 = mdiobus_c45_read(bus, prtad, devad, MDIO_STAT2);
+       if (stat2 < 0)
+               return stat2;
+
+       return (stat2 & MDIO_STAT2_DEVPRST) == MDIO_STAT2_DEVPRST_VAL;
+}
+
 /* get_phy_c45_devs_in_pkg - reads a MMD's devices in package registers.
  * @bus: the target MII bus
  * @addr: PHY address on the MII bus
@@ -709,12 +731,25 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, 
u32 *phy_id,
 {
        const int num_ids = ARRAY_SIZE(c45_ids->device_ids);
        u32 *devs = &c45_ids->devices_in_package;
-       int i, phy_reg;
+       int i, ret, phy_reg;
 
        /* Find first non-zero Devices In package. Device zero is reserved
         * for 802.3 c45 complied PHYs, so don't probe it at first.
         */
-       for (i = 1; i < num_ids && *devs == 0; i++) {
+       for (i = 1; i < MDIO_MMD_NUM && *devs == 0; i++) {
+               if (i >= 8) {
+                       /* Only probe for the devices-in-package if there
+                        * is a PHY reporting as present here; this avoids
+                        * picking up on PHYs that implement non-IEEE802.3
+                        * compliant register spaces.
+                        */
+                       ret = phy_c45_probe_present(bus, addr, i);
+                       if (ret < 0)
+                               return -EIO;
+
+                       if (!ret)
+                               continue;
+               }
                phy_reg = get_phy_c45_devs_in_pkg(bus, addr, i, devs);
                if (phy_reg < 0)
                        return -EIO;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 9b7c46cf14d3..41c046545354 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -350,6 +350,8 @@ enum phy_state {
        PHY_NOLINK,
 };
 
+#define MDIO_MMD_NUM 32
+
 /**
  * struct phy_c45_device_ids - 802.3-c45 Device Identifiers
  * @devices_in_package: Bit vector of devices present.
-- 
2.20.1

Reply via email to