Commit fce8dc5e authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Simon Horman

ARM: shmobile: rcar-gen2: Fix deadlock in regulator quirk

Simon Horman reported that Koelsch and Lager hang during boot, and
bisected this to commit 1c3c5eab ("sched/core: Enable
might_sleep() and smp_processor_id() checks early").

The da9063/da9210 regulator quirk for R-Car Gen2 boards uses a bus
notifier, and unregisters the notifier when it is no longer needed.
However, a notifier must not be unregistered from within the call chain.

This bug went unnoticed, as blocking_notifier_chain_unregister() didn't
take the semaphore during early boot.  The aforementioned commit changed
that behavior, leading to a deadlock.

Fix this by removing the call to bus_unregister_notifier(), and keeping
local completion state instead.
Reported-by: default avatarSimon Horman <horms+renesas@verge.net.au>
Fixes: 663fbb52 ("ARM: shmobile: R-Car Gen2: Add da9063/da9210 regulator quirk")
Signed-off-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: default avatarSimon Horman <horms+renesas@verge.net.au>
parent 2ea659a9
...@@ -67,8 +67,12 @@ static int regulator_quirk_notify(struct notifier_block *nb, ...@@ -67,8 +67,12 @@ static int regulator_quirk_notify(struct notifier_block *nb,
{ {
struct device *dev = data; struct device *dev = data;
struct i2c_client *client; struct i2c_client *client;
static bool done;
u32 mon; u32 mon;
if (done)
return 0;
mon = ioread32(irqc + IRQC_MONITOR); mon = ioread32(irqc + IRQC_MONITOR);
dev_dbg(dev, "%s: %ld, IRQC_MONITOR = 0x%x\n", __func__, action, mon); dev_dbg(dev, "%s: %ld, IRQC_MONITOR = 0x%x\n", __func__, action, mon);
if (mon & REGULATOR_IRQ_MASK) if (mon & REGULATOR_IRQ_MASK)
...@@ -99,7 +103,7 @@ static int regulator_quirk_notify(struct notifier_block *nb, ...@@ -99,7 +103,7 @@ static int regulator_quirk_notify(struct notifier_block *nb,
remove: remove:
dev_info(dev, "IRQ2 is not asserted, removing quirk\n"); dev_info(dev, "IRQ2 is not asserted, removing quirk\n");
bus_unregister_notifier(&i2c_bus_type, nb); done = true;
iounmap(irqc); iounmap(irqc);
return 0; return 0;
} }
......
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