Skip to content

Commit b826d2c

Browse files
mairacanalUlf Hansson
authored andcommitted
pmdomain: bcm: bcm2835-power: Increase ASB control timeout
The bcm2835_asb_control() function uses a tight polling loop to wait for the ASB bridge to acknowledge a request. During intensive workloads, this handshake intermittently fails for V3D's master ASB on BCM2711, resulting in "Failed to disable ASB master for v3d" errors during runtime PM suspend. As a consequence, the failed power-off leaves V3D in a broken state, leading to bus faults or system hangs on later accesses. As the timeout is insufficient in some scenarios, increase the polling timeout from 1us to 5us, which is still negligible in the context of a power domain transition. Also, replace the open-coded ktime_get_ns()/ cpu_relax() polling loop with readl_poll_timeout_atomic(). Cc: stable@vger.kernel.org Fixes: 670c672 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.") Signed-off-by: Maíra Canal <mcanal@igalia.com> Reviewed-by: Stefan Wahren <wahrenst@gmx.net> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent b22c526 commit b826d2c

1 file changed

Lines changed: 4 additions & 8 deletions

File tree

drivers/pmdomain/bcm/bcm2835-power.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/clk.h>
1010
#include <linux/delay.h>
1111
#include <linux/io.h>
12+
#include <linux/iopoll.h>
1213
#include <linux/mfd/bcm2835-pm.h>
1314
#include <linux/module.h>
1415
#include <linux/platform_device.h>
@@ -153,7 +154,6 @@ struct bcm2835_power {
153154
static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable)
154155
{
155156
void __iomem *base = power->asb;
156-
u64 start;
157157
u32 val;
158158

159159
switch (reg) {
@@ -166,8 +166,6 @@ static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable
166166
break;
167167
}
168168

169-
start = ktime_get_ns();
170-
171169
/* Enable the module's async AXI bridges. */
172170
if (enable) {
173171
val = readl(base + reg) & ~ASB_REQ_STOP;
@@ -176,11 +174,9 @@ static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable
176174
}
177175
writel(PM_PASSWORD | val, base + reg);
178176

179-
while (!!(readl(base + reg) & ASB_ACK) == enable) {
180-
cpu_relax();
181-
if (ktime_get_ns() - start >= 1000)
182-
return -ETIMEDOUT;
183-
}
177+
if (readl_poll_timeout_atomic(base + reg, val,
178+
!!(val & ASB_ACK) != enable, 0, 5))
179+
return -ETIMEDOUT;
184180

185181
return 0;
186182
}

0 commit comments

Comments
 (0)