aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorLuben Tuikov <ltuikov@yahoo.com>2010-11-11 18:43:11 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-09-09 18:55:03 -0400
commite16da02fcdf1c5e824432f88abf42623dafdf191 (patch)
tree5484c82c1a9a7467ec1c552e1eee753bc3c81122 /drivers/usb
parent73ddc2474bcc5234fa0a4e406e015ed16d16b6c8 (diff)
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: Luben Tuikov <ltuikov@yahoo.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/storage/transport.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index e8ae21b2d387..ff32390d61e5 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -691,6 +691,9 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
691 int temp_result; 691 int temp_result;
692 struct scsi_eh_save ses; 692 struct scsi_eh_save ses;
693 int sense_size = US_SENSE_SIZE; 693 int sense_size = US_SENSE_SIZE;
694 struct scsi_sense_hdr sshdr;
695 const u8 *scdd;
696 u8 fm_ili;
694 697
695 /* device supports and needs bigger sense buffer */ 698 /* device supports and needs bigger sense buffer */
696 if (us->fflags & US_FL_SANE_SENSE) 699 if (us->fflags & US_FL_SANE_SENSE)
@@ -774,32 +777,30 @@ Retry_Sense:
774 srb->sense_buffer[7] = (US_SENSE_SIZE - 8); 777 srb->sense_buffer[7] = (US_SENSE_SIZE - 8);
775 } 778 }
776 779
780 scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE,
781 &sshdr);
782
777 US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); 783 US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
778 US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", 784 US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
779 srb->sense_buffer[0], 785 sshdr.response_code, sshdr.sense_key,
780 srb->sense_buffer[2] & 0xf, 786 sshdr.asc, sshdr.ascq);
781 srb->sense_buffer[12],
782 srb->sense_buffer[13]);
783#ifdef CONFIG_USB_STORAGE_DEBUG 787#ifdef CONFIG_USB_STORAGE_DEBUG
784 usb_stor_show_sense( 788 usb_stor_show_sense(sshdr.sense_key, sshdr.asc, sshdr.ascq);
785 srb->sense_buffer[2] & 0xf,
786 srb->sense_buffer[12],
787 srb->sense_buffer[13]);
788#endif 789#endif
789 790
790 /* set the result so the higher layers expect this data */ 791 /* set the result so the higher layers expect this data */
791 srb->result = SAM_STAT_CHECK_CONDITION; 792 srb->result = SAM_STAT_CHECK_CONDITION;
792 793
794 scdd = scsi_sense_desc_find(srb->sense_buffer,
795 SCSI_SENSE_BUFFERSIZE, 4);
796 fm_ili = (scdd ? scdd[3] : srb->sense_buffer[2]) & 0xA0;
797
793 /* We often get empty sense data. This could indicate that 798 /* We often get empty sense data. This could indicate that
794 * everything worked or that there was an unspecified 799 * everything worked or that there was an unspecified
795 * problem. We have to decide which. 800 * problem. We have to decide which.
796 */ 801 */
797 if ( /* Filemark 0, ignore EOM, ILI 0, no sense */ 802 if (sshdr.sense_key == 0 && sshdr.asc == 0 && sshdr.ascq == 0 &&
798 (srb->sense_buffer[2] & 0xaf) == 0 && 803 fm_ili == 0) {
799 /* No ASC or ASCQ */
800 srb->sense_buffer[12] == 0 &&
801 srb->sense_buffer[13] == 0) {
802
803 /* If things are really okay, then let's show that. 804 /* If things are really okay, then let's show that.
804 * Zero out the sense buffer so the higher layers 805 * Zero out the sense buffer so the higher layers
805 * won't realize we did an unsolicited auto-sense. 806 * won't realize we did an unsolicited auto-sense.
@@ -814,7 +815,10 @@ Retry_Sense:
814 */ 815 */
815 } else { 816 } else {
816 srb->result = DID_ERROR << 16; 817 srb->result = DID_ERROR << 16;
817 srb->sense_buffer[2] = HARDWARE_ERROR; 818 if ((sshdr.response_code & 0x72) == 0x72)
819 srb->sense_buffer[1] = HARDWARE_ERROR;
820 else
821 srb->sense_buffer[2] = HARDWARE_ERROR;
818 } 822 }
819 } 823 }
820 } 824 }