From: Damien Le Moal <dlemoal@kernel.org>
To: Niklas Cassel <cassel@kernel.org>
Cc: linux-ide@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH] ata: libahci: Stop the SW activity blink timers on port suspend
Date: Thu, 12 Nov 2026 08:35:56 +0900 [thread overview]
Message-ID: <0ce11245-3da6-423c-9f54-175eed413182@kernel.org> (raw)
In-Reply-To: <20261110135615.291884-2-cassel@kernel.org>
On 11/10/26 22:56, Niklas Cassel wrote:
> The SW activity blink timers are not stopped when a port is suspended.
> Every command goes through ahci_qc_issue() -> ahci_sw_activity(), so
> with SW activity enabled, a blink timer can still be pending when
> ahci_port_suspend() runs, e.g. armed by the commands issued just before
> it, and ahci_sw_activity_blink() re-arms it as long as there was
> activity.
>
> If the timer fires while the port is suspended, ahci_sw_activity_blink()
> -> ahci_transmit_led_message() -> ahci_rpm_get_port() calls
> pm_runtime_get_sync() from timer softirq context, and the EM registers
> of a suspended controller get written. If the port is resumed while the
> timer is still pending, ahci_port_resume() -> ahci_start_port() ->
> ahci_init_sw_activity() calls timer_setup() on a timer that is still
> queued in the timer wheel, corrupting it.
>
> Stop the timers in ahci_port_suspend(). Use timer_delete_sync() rather
> than timer_shutdown_sync(): the timers are only stopped until the port
> is resumed, while timer_shutdown_sync() is meant for timers that are
> torn down for good.
>
> Fixes: 18f7ba4c2f4b ("libata/ahci: enclosure management support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Niklas Cassel <cassel@kernel.org>
> ---
> Developed with the assistance of an LLM.
>
> Tested in QEMU (q35, KVM) with KASAN, UBSAN, DEBUG_OBJECTS_TIMERS and
> lockdep, using TEST-ONLY hooks: one fakes enclosure management (QEMU's
> AHCI has none), the other arms the blink timer as ahci_qc_issue() does
> and then calls ->port_suspend() and ->port_resume() back to back, while
> the timer is still pending.
>
> unpatched patched
> ODEBUG: init active ... timer_list no warnings,
> hint: ahci_sw_activity_blink, I/O after resume works
> from ahci_port_resume()
>
> The timer firing while the port is suspended is not covered, as the
> fake EM support never reaches ahci_rpm_get_port().
>
> drivers/ata/libahci.c | 15 ++++++++++++++-
> 1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
> index ef760d81d1d1..2e71ba7ea374 100644
> --- a/drivers/ata/libahci.c
> +++ b/drivers/ata/libahci.c
> @@ -2491,8 +2491,21 @@ static void ahci_handle_s2idle(struct ata_port *ap)
>
> static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
> {
> + struct ahci_port_priv *pp = ap->private_data;
> const char *emsg = NULL;
> - int rc;
> + int rc, i;
> +
> + /*
> + * Stop the SW activity blink timers, so that they cannot fire while
> + * the port is suspended. ahci_init_sw_activity() sets them up again
> + * on resume.
> + */
> + for (i = 0; i < EM_MAX_SLOTS; i++) {
> + struct ahci_em_priv *emp = &pp->em_priv[i];
> +
> + if (emp->timer.function)
> + timer_delete_sync(&emp->timer);
Looks OK. Did you check that the timer handler does not restart/requeue the
timer? timer_delete_sync() states that it should not.
> + }
>
> rc = ahci_deinit_port(ap, &emsg);
> if (rc == 0)
--
Damien Le Moal
Western Digital Research
prev parent reply other threads:[~2026-11-11 23:35 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 13:56 [PATCH] ata: libahci: Stop the SW activity blink timers on port suspend Niklas Cassel
2026-11-11 23:35 ` Damien Le Moal [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0ce11245-3da6-423c-9f54-175eed413182@kernel.org \
--to=dlemoal@kernel.org \
--cc=cassel@kernel.org \
--cc=linux-ide@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox