Commit 8ebf408e authored by Igor Pylypiv's avatar Igor Pylypiv Committed by Niklas Cassel
Browse files

ata: libata-scsi: fix requeue of deferred ATA PASS-THROUGH commands



Commit 0ea84089 ("ata: libata-scsi: avoid Non-NCQ command starvation")
introduced ata_scsi_requeue_deferred_qc() to handle commands deferred
during resets or NCQ failures. This deferral logic completed commands
with DID_SOFT_ERROR to trigger a retry in the SCSI mid-layer.

However, DID_SOFT_ERROR is subject to scsi_cmd_retry_allowed() checks.
ATA PASS-THROUGH commands sent via SG_IO ioctl have scmd->allowed set
to zero. This causes the mid-layer to fail the command immediately
instead of retrying, even though the command was never actually issued
to the hardware.

Switch to DID_REQUEUE to ensure these commands are inserted back into
the request queue regardless of retry limits.

Fixes: 0ea84089 ("ata: libata-scsi: avoid Non-NCQ command starvation")
Reviewed-by: default avatarDamien Le Moal <dlemoal@kernel.org>
Signed-off-by: default avatarIgor Pylypiv <ipylypiv@google.com>
Signed-off-by: default avatarNiklas Cassel <cassel@kernel.org>
parent 797f6298
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1695,12 +1695,12 @@ void ata_scsi_requeue_deferred_qc(struct ata_port *ap)
	/*
	 * If we have a deferred qc when a reset occurs or NCQ commands fail,
	 * do not try to be smart about what to do with this deferred command
	 * and simply retry it by completing it with DID_SOFT_ERROR.
	 * and simply requeue it by completing it with DID_REQUEUE.
	 */
	if (qc) {
		ap->deferred_qc = NULL;
		cancel_work(&ap->deferred_qc_work);
		ata_scsi_qc_done(qc, true, DID_SOFT_ERROR << 16);
		ata_scsi_qc_done(qc, true, DID_REQUEUE << 16);
	}
}