summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDamien Le Moal <dlemoal@kernel.org>2026-02-20 12:09:12 +0900
committerDamien Le Moal <dlemoal@kernel.org>2026-02-24 09:38:55 +0900
commit55db009926634b20955bd8abbee921adbc8d2cb4 (patch)
tree8e9d579082fb17a02ab0f9578af892e193c96380 /drivers
parenteddb98ad9364b4e778768785d46cfab04ce52100 (diff)
ata: libata-core: fix cancellation of a port deferred qc work
cancel_work_sync() is a sleeping function so it cannot be called with the spin lock of a port being held. Move the call to this function in ata_port_detach() after EH completes, with the port lock released, together with other work cancellation calls. Fixes: 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command starvation") Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Igor Pylypiv <ipylypiv@google.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libata-core.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 11909417f017..ccbf320524da 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6269,10 +6269,6 @@ static void ata_port_detach(struct ata_port *ap)
}
}
- /* Make sure the deferred qc work finished. */
- cancel_work_sync(&ap->deferred_qc_work);
- WARN_ON(ap->deferred_qc);
-
/* Tell EH to disable all devices */
ap->pflags |= ATA_PFLAG_UNLOADING;
ata_port_schedule_eh(ap);
@@ -6283,9 +6279,11 @@ static void ata_port_detach(struct ata_port *ap)
/* wait till EH commits suicide */
ata_port_wait_eh(ap);
- /* it better be dead now */
+ /* It better be dead now and not have any remaining deferred qc. */
WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED));
+ WARN_ON(ap->deferred_qc);
+ cancel_work_sync(&ap->deferred_qc_work);
cancel_delayed_work_sync(&ap->hotplug_task);
cancel_delayed_work_sync(&ap->scsi_rescan_task);