]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ata: libata-core: fix cancellation of a port deferred qc work
authorDamien Le Moal <dlemoal@kernel.org>
Fri, 20 Feb 2026 03:09:12 +0000 (12:09 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 26 Feb 2026 23:01:41 +0000 (15:01 -0800)
commit 55db009926634b20955bd8abbee921adbc8d2cb4 upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/ata/libata-core.c

index b7d48364cce4a7df6f2b8f396eb665151f0eab71..50dfce8d8bba09f737bbe992c788ca62a041ddf9 100644 (file)
@@ -6233,10 +6233,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);
@@ -6247,9 +6243,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);