Skip to contentSkip to conversation

net: dsa: mv88e6060: Fix false positive lockdep splat

PATCH In review Neil Armstrong 2 participants 6 messages Oct 21, 2015 – Oct 22, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 net: dsa: mv88e6060: Fix false positive lockdep splat

Like the change made for mv88e6xxx, use mutex_lock_nested() to avoid lockdep to give false positives because of nested MDIO busses.

The false positive was observed using a mv88e6060 from a TI816X SoC.

---
 drivers/net/dsa/mv88e6060.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)
drivers/net/dsa/mv88e6060.c +17 -2
index c29aebe..b1db460 100644
@@ -19,14 +19,24 @@
 #define REG_PORT(p)		(8 + (p))
 #define REG_GLOBAL		0x0f
 
+/* MDIO bus access can be nested in the case of PHYs connected to the
+ * internal MDIO bus of the switch, which is accessed via MDIO bus of
+ * the Ethernet interface. Avoid lockdep false positives by using
+ * mutex_lock_nested().
+ */
 static int reg_read(struct dsa_switch *ds, int addr, int reg)
 {
+	int ret;
 	struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
 
 	if (bus == NULL)
 		return -EINVAL;
 
-	return mdiobus_read(bus, ds->pd->sw_addr + addr, reg);
+	mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING);
+	ret = bus->read(bus, ds->pd->sw_addr, reg);
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret;
 }
 
 #define REG_READ(addr, reg)					\
@@ -42,12 +52,17 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg)
 
 static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
 {
+	int ret;
 	struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
 
 	if (bus == NULL)
 		return -EINVAL;
 
-	return mdiobus_write(bus, ds->pd->sw_addr + addr, reg, val);
+	mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING);
+	ret = bus->write(bus, ds->pd->sw_addr, reg, val);
+	mutex_unlock(&bus->mdio_lock);
+
+	return ret;
 }
 
 #define REG_WRITE(addr, reg, val)				\
Signature · 1 line
1.9.1
maintainer
#1 lore raw
Quoted 2 lines · Neil Armstrong

Like the change made for mv88e6xxx, use mutex_lock_nested() to avoid lockdep to give false positives because of nested MDIO busses.

Hi Neil

We now have three instances of this, since mdio-mux.c has the same code. Maybe now would be a good time to refactor this code into mdiobus_read_nested() and mdiobus_write_nested() in mdio_bus.c? At the same time, add BUG_ON(in_interrupt()) similar to the non-nested versions?

Andrew

#2 lore raw

Hi Andrew,

Quoted 6 lines · Andrew Lunn
Quoted 2 lines · Neil Armstrong

Like the change made for mv88e6xxx, use mutex_lock_nested() to avoid lockdep to give false positives because of nested MDIO busses.

Hi Neil

Quoted 8 lines

We now have three instances of this, since mdio-mux.c has the same code. Maybe now would be a good time to refactor this code into mdiobus_read_nested() and mdiobus_write_nested() in mdio_bus.c? At the same time, add BUG_ON(in_interrupt()) similar to the non-nested versions?

Andrew

Indeed, you are right, I will post a serie with this refactoring.

Neil

#3 lore raw
In reply to Andrew Lunn
Quoted 6 lines · Andrew Lunn
Quoted 2 lines · Neil Armstrong

Like the change made for mv88e6xxx, use mutex_lock_nested() to avoid lockdep to give false positives because of nested MDIO busses.

Hi Neil

Quoted 8 lines

We now have three instances of this, since mdio-mux.c has the same code. Maybe now would be a good time to refactor this code into mdiobus_read_nested() and mdiobus_write_nested() in mdio_bus.c? At the same time, add BUG_ON(in_interrupt()) similar to the non-nested versions?

Andrew

Well, mdio-mux also calls switch_fn inside the mdio_lock, clean refactoring would introduce a separate lock and call the nested variants. Is that ok ? Can someone test mdio-mux is I make the change ?

Neil

#4 lore raw
In reply to Andrew Lunn
Quoted 6 lines · Andrew Lunn
Quoted 2 lines · Neil Armstrong

Like the change made for mv88e6xxx, use mutex_lock_nested() to avoid lockdep to give false positives because of nested MDIO busses.

Hi Neil

Quoted 8 lines

We now have three instances of this, since mdio-mux.c has the same code. Maybe now would be a good time to refactor this code into mdiobus_read_nested() and mdiobus_write_nested() in mdio_bus.c? At the same time, add BUG_ON(in_interrupt()) similar to the non-nested versions?

Andrew

Well, mdio-mux also calls switch_fn inside the mdio_lock, clean refactoring would introduce a separate lock and call the nested variants. Is that ok ? Can someone test mdio-mux if I make the change ?

Neil

maintainer
#5 lore raw
Quoted 3 lines

Well, mdio-mux also calls switch_fn inside the mdio_lock, clean refactoring would introduce a separate lock and call the nested variants. Is that ok ? Can someone test mdio-mux if I make the change ?

Hi Neil

I would not touch mdio-mux. As you said, it does more than lock, read, unlock. It is not something sufficiently generic to place into shared code.

Andrew