diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 522cbe6a0b23e13be0e2cf83fb03f3722401326b..902e1c88ef5854e2ca08c486a204090de54caa4a 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -1008,6 +1008,33 @@ int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) } EXPORT_SYMBOL(mdiobus_c45_read); +/** + * mdiobus_c45_read_nested - Nested version of the mdiobus_c45_read function + * @bus: the mii_bus struct + * @addr: the phy address + * @devad: device address to read + * @regnum: register number to read + * + * In case of nested MDIO bus access avoid lockdep false positives by + * using mutex_lock_nested(). + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int mdiobus_c45_read_nested(struct mii_bus *bus, int addr, int devad, + u32 regnum) +{ + int retval; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + retval = __mdiobus_c45_read(bus, addr, devad, regnum); + mutex_unlock(&bus->mdio_lock); + + return retval; +} +EXPORT_SYMBOL(mdiobus_c45_read_nested); + /** * mdiobus_write_nested - Nested version of the mdiobus_write function * @bus: the mii_bus struct @@ -1082,6 +1109,34 @@ int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, } EXPORT_SYMBOL(mdiobus_c45_write); +/** + * mdiobus_c45_write_nested - Nested version of the mdiobus_c45_write function + * @bus: the mii_bus struct + * @addr: the phy address + * @devad: device address to read + * @regnum: register number to write + * @val: value to write to @regnum + * + * In case of nested MDIO bus access avoid lockdep false positives by + * using mutex_lock_nested(). + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int mdiobus_c45_write_nested(struct mii_bus *bus, int addr, int devad, + u32 regnum, u16 val) +{ + int err; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + err = __mdiobus_c45_write(bus, addr, devad, regnum, val); + mutex_unlock(&bus->mdio_lock); + + return err; +} +EXPORT_SYMBOL(mdiobus_c45_write_nested); + /** * mdiobus_modify - Convenience function for modifying a given mdio device * register diff --git a/include/linux/mdio.h b/include/linux/mdio.h index 97b49765e8b5b7e1ccd2d96e52b1cbe8bc6c4ae0..220f3ca8702d596e3897a70f8607f3f12871c909 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -425,10 +425,14 @@ int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set); int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); +int mdiobus_c45_read_nested(struct mii_bus *bus, int addr, int devad, + u32 regnum); int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 val); int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 val); +int mdiobus_c45_write_nested(struct mii_bus *bus, int addr, int devad, + u32 regnum, u16 val); int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, u16 mask, u16 set);