Commit e16da02f authored by Luben Tuikov's avatar Luben Tuikov Committed by Greg Kroah-Hartman

USB: storage: Use normalized sense when emulating autosense

This patch solves two things:
1) Enables autosense emulation code to correctly
interpret descriptor format sense data, and
2) Fixes a bug whereby the autosense emulation
code would overwrite descriptor format sense data
with SENSE KEY HARDWARE ERROR in fixed format, to
incorrectly look like this:

Oct 21 14:11:07 localhost kernel: sd 7:0:0:0: [sdc]  Sense Key : Recovered Error [current] [descriptor]
Oct 21 14:11:07 localhost kernel: Descriptor sense data with sense descriptors (in hex):
Oct 21 14:11:07 localhost kernel:        72 01 04 1d 00 00 00 0e 09 0c 00 00 00 00 00 00
Oct 21 14:11:07 localhost kernel:        00 4f 00 c2 00 50
Oct 21 14:11:07 localhost kernel: sd 7:0:0:0: [sdc]  ASC=0x4 ASCQ=0x1d
Signed-off-by: default avatarLuben Tuikov <ltuikov@yahoo.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Acked-by: default avatarMatthew Dharm <mdharm-usb@one-eyed-alien.net>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 73ddc247
...@@ -691,6 +691,9 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) ...@@ -691,6 +691,9 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
int temp_result; int temp_result;
struct scsi_eh_save ses; struct scsi_eh_save ses;
int sense_size = US_SENSE_SIZE; int sense_size = US_SENSE_SIZE;
struct scsi_sense_hdr sshdr;
const u8 *scdd;
u8 fm_ili;
/* device supports and needs bigger sense buffer */ /* device supports and needs bigger sense buffer */
if (us->fflags & US_FL_SANE_SENSE) if (us->fflags & US_FL_SANE_SENSE)
...@@ -774,32 +777,30 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) ...@@ -774,32 +777,30 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
srb->sense_buffer[7] = (US_SENSE_SIZE - 8); srb->sense_buffer[7] = (US_SENSE_SIZE - 8);
} }
scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE,
&sshdr);
US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
srb->sense_buffer[0], sshdr.response_code, sshdr.sense_key,
srb->sense_buffer[2] & 0xf, sshdr.asc, sshdr.ascq);
srb->sense_buffer[12],
srb->sense_buffer[13]);
#ifdef CONFIG_USB_STORAGE_DEBUG #ifdef CONFIG_USB_STORAGE_DEBUG
usb_stor_show_sense( usb_stor_show_sense(sshdr.sense_key, sshdr.asc, sshdr.ascq);
srb->sense_buffer[2] & 0xf,
srb->sense_buffer[12],
srb->sense_buffer[13]);
#endif #endif
/* 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;
scdd = scsi_sense_desc_find(srb->sense_buffer,
SCSI_SENSE_BUFFERSIZE, 4);
fm_ili = (scdd ? scdd[3] : srb->sense_buffer[2]) & 0xA0;
/* We often get empty sense data. This could indicate that /* We often get empty sense data. This could indicate that
* everything worked or that there was an unspecified * everything worked or that there was an unspecified
* problem. We have to decide which. * problem. We have to decide which.
*/ */
if ( /* Filemark 0, ignore EOM, ILI 0, no sense */ if (sshdr.sense_key == 0 && sshdr.asc == 0 && sshdr.ascq == 0 &&
(srb->sense_buffer[2] & 0xaf) == 0 && fm_ili == 0) {
/* No ASC or ASCQ */
srb->sense_buffer[12] == 0 &&
srb->sense_buffer[13] == 0) {
/* If things are really okay, then let's show that. /* If things are really okay, then let's show that.
* Zero out the sense buffer so the higher layers * Zero out the sense buffer so the higher layers
* won't realize we did an unsolicited auto-sense. * won't realize we did an unsolicited auto-sense.
...@@ -814,7 +815,10 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) ...@@ -814,7 +815,10 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
*/ */
} else { } else {
srb->result = DID_ERROR << 16; srb->result = DID_ERROR << 16;
srb->sense_buffer[2] = HARDWARE_ERROR; if ((sshdr.response_code & 0x72) == 0x72)
srb->sense_buffer[1] = HARDWARE_ERROR;
else
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