Commit f1a0743b authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

USB: storage: When a device returns no sense data, call it a Hardware Error

This patch (as1294) fixes a problem that has plagued users for several
kernel releases.  Some USB mass-storage devices don't return any sense
data when they encounter certain kinds of errors.  The SCSI layer
interprets this to mean that the operation should be retried, and the
same thing happens -- over and over again with no limit.  In some
circumstances (such as when a bus reset occurs) that is the right
thing to do, but not here.

The patch checks for this condition (a transport failure with no sense
data) and changes the result code to DID_ERROR and the sense code to
Hardware Error.  This does get only a limited number of retries, and
so the command will fail relatively quickly instead of getting stuck
in an infinite loop.

This fixes a large part of Bugzilla #14118.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Tested-by: default avatarMantas Mikulenas <grawity@gmail.com>
CC: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a5f6005d
...@@ -768,17 +768,32 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) ...@@ -768,17 +768,32 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
/* set the result so the higher layers expect this data */ /* set the result so the higher layers expect this data */
srb->result = SAM_STAT_CHECK_CONDITION; srb->result = SAM_STAT_CHECK_CONDITION;
/* If things are really okay, then let's show that. Zero /* We often get empty sense data. This could indicate that
* out the sense buffer so the higher layers won't realize * everything worked or that there was an unspecified
* we did an unsolicited auto-sense. */ * problem. We have to decide which.
if (result == USB_STOR_TRANSPORT_GOOD && */
/* Filemark 0, ignore EOM, ILI 0, no sense */ if ( /* Filemark 0, ignore EOM, ILI 0, no sense */
(srb->sense_buffer[2] & 0xaf) == 0 && (srb->sense_buffer[2] & 0xaf) == 0 &&
/* No ASC or ASCQ */ /* No ASC or ASCQ */
srb->sense_buffer[12] == 0 && srb->sense_buffer[12] == 0 &&
srb->sense_buffer[13] == 0) { srb->sense_buffer[13] == 0) {
/* If things are really okay, then let's show that.
* Zero out the sense buffer so the higher layers
* won't realize we did an unsolicited auto-sense.
*/
if (result == USB_STOR_TRANSPORT_GOOD) {
srb->result = SAM_STAT_GOOD; srb->result = SAM_STAT_GOOD;
srb->sense_buffer[0] = 0x0; srb->sense_buffer[0] = 0x0;
/* If there was a problem, report an unspecified
* hardware error to prevent the higher layers from
* entering an infinite retry loop.
*/
} else {
srb->result = DID_ERROR << 16;
srb->sense_buffer[2] = HARDWARE_ERROR;
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment