Patch "ata: libata: Clear DID_TIME_OUT for ATA PT commands with sense data" has been added to the 6.6-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    ata: libata: Clear DID_TIME_OUT for ATA PT commands with sense data

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     ata-libata-clear-did_time_out-for-ata-pt-commands-wi.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 45c1535f1cf521c4cc8f388abf4cb0c7348b479a
Author: Niklas Cassel <cassel@xxxxxxxxxx>
Date:   Mon Sep 9 17:42:38 2024 +0200

    ata: libata: Clear DID_TIME_OUT for ATA PT commands with sense data
    
    [ Upstream commit e5dd410acb34c7341a0a93b429dcf3dabf9e3323 ]
    
    When ata_qc_complete() schedules a command for EH using
    ata_qc_schedule_eh(), blk_abort_request() will be called, which leads to
    req->q->mq_ops->timeout() / scsi_timeout() being called.
    
    scsi_timeout(), if the LLDD has no abort handler (libata has no abort
    handler), will set host byte to DID_TIME_OUT, and then call
    scsi_eh_scmd_add() to add the command to EH.
    
    Thus, when commands first enter libata's EH strategy_handler, all the
    commands that have been added to EH will have DID_TIME_OUT set.
    
    libata has its own flag (AC_ERR_TIMEOUT), that it sets for commands that
    have not received a completion at the time of entering EH.
    
    Thus, libata doesn't really care about DID_TIME_OUT at all, and currently
    clears the host byte at the end of EH, in ata_scsi_qc_complete(), before
    scsi_eh_finish_cmd() is called.
    
    However, this clearing in ata_scsi_qc_complete() is currently only done
    for commands that are not ATA passthrough commands.
    
    Since the host byte is visible in the completion that we return to user
    space for ATA passthrough commands, for ATA passthrough commands that got
    completed via EH (commands with sense data), the user will incorrectly see:
    ATA pass-through(16): transport error: Host_status=0x03 [DID_TIME_OUT]
    
    Fix this by moving the clearing of the host byte (which is currently only
    done for commands that are not ATA passthrough commands) from
    ata_scsi_qc_complete() to the start of EH (regardless if the command is
    ATA passthrough or not).
    
    While at it, use the proper helper function to clear the host byte, rather
    than open coding the clearing.
    
    This will make sure that we:
    -Correctly clear DID_TIME_OUT for both ATA passthrough commands and
     commands that are not ATA passthrough commands.
    -Do not needlessly clear the host byte for commands that did not go via EH.
     ata_scsi_qc_complete() is called both for commands that are completed
     normally (without going via EH), and for commands that went via EH,
     however, only commands that went via EH will have DID_TIME_OUT set.
    
    Fixes: 24aeebbf8ea9 ("scsi: ata: libata: Change ata_eh_request_sense() to not set CHECK_CONDITION")
    Reported-by: Igor Pylypiv <ipylypiv@xxxxxxxxxx>
    Closes: https://lore.kernel.org/linux-ide/ZttIN8He8TOZ7Lct@xxxxxxxxxx/
    Signed-off-by: Niklas Cassel <cassel@xxxxxxxxxx>
    Tested-by: Igor Pylypiv <ipylypiv@xxxxxxxxxx>
    Reviewed-by: Hannes Reinecke <hare@xxxxxxx>
    Signed-off-by: Damien Le Moal <dlemoal@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 1168e29cae86e..cd87457375454 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -618,6 +618,14 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
 	list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) {
 		struct ata_queued_cmd *qc;
 
+		/*
+		 * If the scmd was added to EH, via ata_qc_schedule_eh() ->
+		 * scsi_timeout() -> scsi_eh_scmd_add(), scsi_timeout() will
+		 * have set DID_TIME_OUT (since libata does not have an abort
+		 * handler). Thus, to clear DID_TIME_OUT, clear the host byte.
+		 */
+		set_host_byte(scmd, DID_OK);
+
 		ata_qc_for_each_raw(ap, qc, i) {
 			if (qc->flags & ATA_QCFLAG_ACTIVE &&
 			    qc->scsicmd == scmd)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index c91f8746289f4..7a71add807a3a 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1725,9 +1725,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
 			set_status_byte(qc->scsicmd, SAM_STAT_CHECK_CONDITION);
 	} else if (is_error && !have_sense) {
 		ata_gen_ata_sense(qc);
-	} else {
-		/* Keep the SCSI ML and status byte, clear host byte. */
-		cmd->result &= 0x0000ffff;
 	}
 
 	ata_qc_done(qc);




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux