[PATCH v2] ata: libata: skip sata_down_spd_limit() when no device is present

From: tongzhiwei

Date: Mon Oct 19 2026 - 23:24:09 EST


A hot-unplug goes through ata_eh_schedule_probe() -> ata_dev_init() ->
sata_spd = 0. After commit 69f2c9346313 ("ata: libata: Fix
sata_down_spd_limit() when no link speed is reported"), when the device
is unplugged, every probe lowers sata_spd_limit. This breaks
commit 2dc0b46b5ea3 ("libata: sata_down_spd_limit should return
if driver has not recorded sstatus speed").

As a result, when the device is plugged back in, it is limited to a
low speed that is never recovered.

Use the SStatus DET field to detect the no-device case and bail out
of sata_down_spd_limit() when no device is present (DET == 0).

Fixes: 69f2c9346313 ("ata: libata: Fix sata_down_spd_limit() when no link speed is reported")
Assisted-by: LLM
Signed-off-by: tongzhiwei <tongzhiwei@xxxxxxxxxxxxxxxxxxxx>
---
Changes since v1:
- v1 ("ata: libata: preserve sata_spd link cache across ata_dev_init") took the
wrong approach (caching sata_spd across ata_dev_init). This version instead
bails out of sata_down_spd_limit() when SStatus indicates no device is present
(DET == 0), without altering ata_dev_init() or the sata_spd cache.

drivers/ata/libata-sata.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c
index ad40f516c6d4..775da21cbbae 100644
--- a/drivers/ata/libata-sata.c
+++ b/drivers/ata/libata-sata.c
@@ -549,6 +549,9 @@ int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
* If not, use cached value in link->sata_spd.
*/
rc = sata_scr_read(link, SCR_STATUS, &sstatus);
+ /* No device present (DET == 0): nothing to recover by lowering speed. */
+ if (rc == 0 && (sstatus & 0xf) == 0)
+ return -EINVAL;
if (rc == 0 && ata_sstatus_online(sstatus))
spd = (sstatus >> 4) & 0xf;
else
--
2.43.0