* [PATCH v3] mmc: sunxi: reset the controller after an update-clock timeout
@ 2026-10-28 11:43 Tam Do
2026-10-30 13:48 ` Ulf Hansson
0 siblings, 1 reply; 3+ messages in thread
From: Tam Do @ 2026-10-28 11:43 UTC (permalink / raw)
To: Ulf Hansson
Cc: Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, linux-mmc,
linux-sunxi, linux-arm-kernel, linux-kernel
If the clock-update command times out it stays pending in the
controller, and every later clock update times out as well, so the
card cannot be initialised until the next probe.
This happens on an R16 board whose SDIO Wi-Fi holds DAT0 busy while
its supply comes up during the first clock update.
Reset the controller on timeout so the next attempt can succeed. This
runs sunxi_mmc_init_host() with the interrupt enabled for the first
time, so write REG_IMASK from sdio_imask under host->lock, as
sunxi_mmc_enable_sdio_irq() updates both under that lock.
Fixes: 3cbcb16095f9 ("mmc: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs")
Cc: stable@vger.kernel.org
Signed-off-by: Tam Do <tam.do@manyhobbies.com>
---
v3: take host->lock only around the REG_IMASK write in
sunxi_mmc_init_host(), not across the reset; v2 polled the reset on
jiffies with interrupts off. The return value stays unchecked, as in
sunxi_mmc_runtime_resume(): if the reset itself times out the
controller is wedged either way.
v2: held host->lock across the reset (not posted)
v1: https://lore.kernel.org/all/179307312104.39863.12372814163472848752@manyhobbies.com/
drivers/mmc/host/sunxi-mmc.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index fe4c0f6d73f3..55313780d06d 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -322,6 +322,7 @@ static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host)
static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
{
+ unsigned long flags;
u32 rval;
if (sunxi_mmc_reset_host(host))
@@ -336,7 +337,9 @@ static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
/* Maximum timeout value */
mmc_writel(host, REG_TMOUT, 0xffffffff);
/* Unmask SDIO interrupt if needed */
+ spin_lock_irqsave(&host->lock, flags);
mmc_writel(host, REG_IMASK, host->sdio_imask);
+ spin_unlock_irqrestore(&host->lock, flags);
/* Clear all pending interrupts */
mmc_writel(host, REG_RINTR, 0xffffffff);
/* Debug register? undocumented */
@@ -688,6 +691,7 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
if (rval & SDXC_START) {
dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n");
+ sunxi_mmc_init_host(host);
return -EIO;
}
--
2.39.5
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v3] mmc: sunxi: reset the controller after an update-clock timeout
2026-10-28 11:43 [PATCH v3] mmc: sunxi: reset the controller after an update-clock timeout Tam Do
@ 2026-10-30 13:48 ` Ulf Hansson
2026-10-30 22:40 ` tam.do
0 siblings, 1 reply; 3+ messages in thread
From: Ulf Hansson @ 2026-10-30 13:48 UTC (permalink / raw)
To: Tam Do
Cc: Ulf Hansson, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
linux-mmc, linux-sunxi, linux-arm-kernel, linux-kernel
On Wed, Oct 28, 2026 at 12:43 PM Tam Do <tam.do@manyhobbies.com> wrote:
>
> If the clock-update command times out it stays pending in the
> controller, and every later clock update times out as well, so the
> card cannot be initialised until the next probe.
>
> This happens on an R16 board whose SDIO Wi-Fi holds DAT0 busy while
> its supply comes up during the first clock update.
It would be nice if you could elaborate a bit more on what goes on here.
I assume it's sunxi_mmc_oclk_onoff() that is being called and it's the
loop in there that times out. The question is then, under what
circumstances are sunxi_mmc_oclk_onoff() being called when we are also
waiting for the SDIO card to release the busy indication on DAT0?
>
> Reset the controller on timeout so the next attempt can succeed. This
> runs sunxi_mmc_init_host() with the interrupt enabled for the first
> time, so write REG_IMASK from sdio_imask under host->lock, as
> sunxi_mmc_enable_sdio_irq() updates both under that lock.
>
> Fixes: 3cbcb16095f9 ("mmc: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs")
> Cc: stable@vger.kernel.org
> Signed-off-by: Tam Do <tam.do@manyhobbies.com>
Kind regards
Uffe
> ---
> v3: take host->lock only around the REG_IMASK write in
> sunxi_mmc_init_host(), not across the reset; v2 polled the reset on
> jiffies with interrupts off. The return value stays unchecked, as in
> sunxi_mmc_runtime_resume(): if the reset itself times out the
> controller is wedged either way.
> v2: held host->lock across the reset (not posted)
> v1: https://lore.kernel.org/all/179307312104.39863.12372814163472848752@manyhobbies.com/
>
> drivers/mmc/host/sunxi-mmc.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
> index fe4c0f6d73f3..55313780d06d 100644
> --- a/drivers/mmc/host/sunxi-mmc.c
> +++ b/drivers/mmc/host/sunxi-mmc.c
> @@ -322,6 +322,7 @@ static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host)
>
> static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
> {
> + unsigned long flags;
> u32 rval;
>
> if (sunxi_mmc_reset_host(host))
> @@ -336,7 +337,9 @@ static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
> /* Maximum timeout value */
> mmc_writel(host, REG_TMOUT, 0xffffffff);
> /* Unmask SDIO interrupt if needed */
> + spin_lock_irqsave(&host->lock, flags);
> mmc_writel(host, REG_IMASK, host->sdio_imask);
> + spin_unlock_irqrestore(&host->lock, flags);
> /* Clear all pending interrupts */
> mmc_writel(host, REG_RINTR, 0xffffffff);
> /* Debug register? undocumented */
> @@ -688,6 +691,7 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
>
> if (rval & SDXC_START) {
> dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n");
> + sunxi_mmc_init_host(host);
> return -EIO;
> }
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v3] mmc: sunxi: reset the controller after an update-clock timeout
2026-10-30 13:48 ` Ulf Hansson
@ 2026-10-30 22:40 ` tam.do
0 siblings, 0 replies; 3+ messages in thread
From: tam.do @ 2026-10-30 22:40 UTC (permalink / raw)
To: Ulf Hansson
Cc: Ulf Hansson, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
linux-mmc, linux-sunxi, linux-arm-kernel, linux-kernel
> I assume it's sunxi_mmc_oclk_onoff() that is being called and it's the
> loop in there that times out. The question is then, under what
> circumstances are sunxi_mmc_oclk_onoff() being called when we are also
> waiting for the SDIO card to release the busy indication on DAT0?
Yes. It's the first update after probe, from the MMC_POWER_UP set_ios:
sunxi_mmc_oclk_onoff+0x17c/0x1a0
sunxi_mmc_clk_set_rate+0x1c/0x2c8
sunxi_mmc_set_ios+0xe4/0x144
mmc_power_up.part.0+0x40/0x150
mmc_start_host+0x90/0x9c
mmc_add_host+0x6c/0xa0
sunxi_mmc_probe+0x35c/0x478
STAS already reads 0x206 there, before anything has been sent to the
card; on good boots it's 0x106. So the card is holding DAT0 when Linux
takes over. These are warm boots from the vendor firmware and it
happens on roughly half of them.
The supply explanation in the commit message is wrong, sorry. The rails
are up ~20 ms later and the command is still pending at the 750 ms
timeout. From then on every update times out until the controller is
reset. Rebinding with the card idle never hit it (0/20 tries).
I'll fix the commit message in v4.
Tam
> On Oct 30, 2026, at 8:48 AM, Ulf Hansson <ulf.hansson@oss.qualcomm.com> wrote:
>
> On Wed, Oct 28, 2026 at 12:43 PM Tam Do <tam.do@manyhobbies.com> wrote:
>>
>> If the clock-update command times out it stays pending in the
>> controller, and every later clock update times out as well, so the
>> card cannot be initialised until the next probe.
>>
>> This happens on an R16 board whose SDIO Wi-Fi holds DAT0 busy while
>> its supply comes up during the first clock update.
>
> It would be nice if you could elaborate a bit more on what goes on here.
>
> I assume it's sunxi_mmc_oclk_onoff() that is being called and it's the
> loop in there that times out. The question is then, under what
> circumstances are sunxi_mmc_oclk_onoff() being called when we are also
> waiting for the SDIO card to release the busy indication on DAT0?
>
>>
>> Reset the controller on timeout so the next attempt can succeed. This
>> runs sunxi_mmc_init_host() with the interrupt enabled for the first
>> time, so write REG_IMASK from sdio_imask under host->lock, as
>> sunxi_mmc_enable_sdio_irq() updates both under that lock.
>>
>> Fixes: 3cbcb16095f9 ("mmc: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Tam Do <tam.do@manyhobbies.com>
>
> Kind regards
> Uffe
>
>> ---
>> v3: take host->lock only around the REG_IMASK write in
>> sunxi_mmc_init_host(), not across the reset; v2 polled the reset on
>> jiffies with interrupts off. The return value stays unchecked, as in
>> sunxi_mmc_runtime_resume(): if the reset itself times out the
>> controller is wedged either way.
>> v2: held host->lock across the reset (not posted)
>> v1: https://lore.kernel.org/all/179307312104.39863.12372814163472848752@manyhobbies.com/
>>
>> drivers/mmc/host/sunxi-mmc.c | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
>> index fe4c0f6d73f3..55313780d06d 100644
>> --- a/drivers/mmc/host/sunxi-mmc.c
>> +++ b/drivers/mmc/host/sunxi-mmc.c
>> @@ -322,6 +322,7 @@ static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host)
>>
>> static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
>> {
>> + unsigned long flags;
>> u32 rval;
>>
>> if (sunxi_mmc_reset_host(host))
>> @@ -336,7 +337,9 @@ static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
>> /* Maximum timeout value */
>> mmc_writel(host, REG_TMOUT, 0xffffffff);
>> /* Unmask SDIO interrupt if needed */
>> + spin_lock_irqsave(&host->lock, flags);
>> mmc_writel(host, REG_IMASK, host->sdio_imask);
>> + spin_unlock_irqrestore(&host->lock, flags);
>> /* Clear all pending interrupts */
>> mmc_writel(host, REG_RINTR, 0xffffffff);
>> /* Debug register? undocumented */
>> @@ -688,6 +691,7 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
>>
>> if (rval & SDXC_START) {
>> dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n");
>> + sunxi_mmc_init_host(host);
>> return -EIO;
>> }
>>
>> --
>> 2.39.5
>>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-30 22:41 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-28 11:43 [PATCH v3] mmc: sunxi: reset the controller after an update-clock timeout Tam Do
2026-10-30 13:48 ` Ulf Hansson
2026-10-30 22:40 ` tam.do
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®