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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.