Commit 55db0099 authored by Damien Le Moal's avatar Damien Le Moal
Browse files

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: 0ea84089 ("ata: libata-scsi: avoid Non-NCQ command starvation")
Signed-off-by: default avatarDamien Le Moal <dlemoal@kernel.org>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarIgor Pylypiv <ipylypiv@google.com>
parent eddb98ad
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -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);