diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2017-07-12 10:45:20 -0400 |
---|---|---|
committer | Simon Horman <horms+renesas@verge.net.au> | 2017-07-29 04:32:52 -0400 |
commit | fce8dc5e50e44d8f644e0f7854e6d7d518fedb68 (patch) | |
tree | 92bc3affede983b7ba38cbef8371fc8e6a9e78c5 | |
parent | 2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff) |
ARM: shmobile: rcar-gen2: Fix deadlock in regulator quirk
Simon Horman reported that Koelsch and Lager hang during boot, and
bisected this to commit 1c3c5eab171590f8 ("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: Simon Horman <horms+renesas@verge.net.au>
Fixes: 663fbb52159cca6f ("ARM: shmobile: R-Car Gen2: Add da9063/da9210 regulator quirk")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-rw-r--r-- | arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c index 73e3adbc1330..44438f344dc8 100644 --- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c +++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c | |||
@@ -67,8 +67,12 @@ static int regulator_quirk_notify(struct notifier_block *nb, | |||
67 | { | 67 | { |
68 | struct device *dev = data; | 68 | struct device *dev = data; |
69 | struct i2c_client *client; | 69 | struct i2c_client *client; |
70 | static bool done; | ||
70 | u32 mon; | 71 | u32 mon; |
71 | 72 | ||
73 | if (done) | ||
74 | return 0; | ||
75 | |||
72 | mon = ioread32(irqc + IRQC_MONITOR); | 76 | mon = ioread32(irqc + IRQC_MONITOR); |
73 | dev_dbg(dev, "%s: %ld, IRQC_MONITOR = 0x%x\n", __func__, action, mon); | 77 | dev_dbg(dev, "%s: %ld, IRQC_MONITOR = 0x%x\n", __func__, action, mon); |
74 | if (mon & REGULATOR_IRQ_MASK) | 78 | if (mon & REGULATOR_IRQ_MASK) |
@@ -99,7 +103,7 @@ static int regulator_quirk_notify(struct notifier_block *nb, | |||
99 | remove: | 103 | remove: |
100 | dev_info(dev, "IRQ2 is not asserted, removing quirk\n"); | 104 | dev_info(dev, "IRQ2 is not asserted, removing quirk\n"); |
101 | 105 | ||
102 | bus_unregister_notifier(&i2c_bus_type, nb); | 106 | done = true; |
103 | iounmap(irqc); | 107 | iounmap(irqc); |
104 | return 0; | 108 | return 0; |
105 | } | 109 | } |