Commit 9a6f2b01 authored by Andrew Lunn's avatar Andrew Lunn Committed by David S. Miller

net: mdio: Fix lockdep falls positive splat

MDIO devices can be stacked upon each other. The current code supports
two levels, which until recently has been enough for a DSA mdio bus on
top of another bus. Now we have hardware which has an MDIO mux in the
middle.

Define an MDIO MUTEX class with three levels.
Signed-off-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c3da7d0
...@@ -45,13 +45,7 @@ static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum) ...@@ -45,13 +45,7 @@ static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum)
struct mdio_mux_parent_bus *pb = cb->parent; struct mdio_mux_parent_bus *pb = cb->parent;
int r; int r;
/* In theory multiple mdio_mux could be stacked, thus creating mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX);
* more than a single level of nesting. But in practice,
* SINGLE_DEPTH_NESTING will cover the vast majority of use
* cases. We use it, instead of trying to handle the general
* case.
*/
mutex_lock_nested(&pb->mii_bus->mdio_lock, SINGLE_DEPTH_NESTING);
r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
if (r) if (r)
goto out; goto out;
...@@ -76,7 +70,7 @@ static int mdio_mux_write(struct mii_bus *bus, int phy_id, ...@@ -76,7 +70,7 @@ static int mdio_mux_write(struct mii_bus *bus, int phy_id,
int r; int r;
mutex_lock_nested(&pb->mii_bus->mdio_lock, SINGLE_DEPTH_NESTING); mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX);
r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data); r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
if (r) if (r)
goto out; goto out;
......
...@@ -457,7 +457,7 @@ int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum) ...@@ -457,7 +457,7 @@ int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum)
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING); mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
retval = bus->read(bus, addr, regnum); retval = bus->read(bus, addr, regnum);
mutex_unlock(&bus->mdio_lock); mutex_unlock(&bus->mdio_lock);
...@@ -509,7 +509,7 @@ int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val) ...@@ -509,7 +509,7 @@ int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val)
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING); mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
err = bus->write(bus, addr, regnum, val); err = bus->write(bus, addr, regnum, val);
mutex_unlock(&bus->mdio_lock); mutex_unlock(&bus->mdio_lock);
......
...@@ -13,6 +13,17 @@ ...@@ -13,6 +13,17 @@
struct mii_bus; struct mii_bus;
/* Multiple levels of nesting are possible. However typically this is
* limited to nested DSA like layer, a MUX layer, and the normal
* user. Instead of trying to handle the general case, just define
* these cases.
*/
enum mdio_mutex_lock_class {
MDIO_MUTEX_NORMAL,
MDIO_MUTEX_MUX,
MDIO_MUTEX_NESTED,
};
struct mdio_device { struct mdio_device {
struct device dev; struct device dev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment