diff options
Diffstat (limited to 'drivers/usb/storage/transport.c')
-rw-r--r-- | drivers/usb/storage/transport.c | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index e20dc525d17..589f6b4404f 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c | |||
@@ -696,7 +696,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
696 | /* device supports and needs bigger sense buffer */ | 696 | /* device supports and needs bigger sense buffer */ |
697 | if (us->fflags & US_FL_SANE_SENSE) | 697 | if (us->fflags & US_FL_SANE_SENSE) |
698 | sense_size = ~0; | 698 | sense_size = ~0; |
699 | 699 | Retry_Sense: | |
700 | US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); | 700 | US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); |
701 | 701 | ||
702 | scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size); | 702 | scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size); |
@@ -720,6 +720,21 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
720 | srb->result = DID_ABORT << 16; | 720 | srb->result = DID_ABORT << 16; |
721 | goto Handle_Errors; | 721 | goto Handle_Errors; |
722 | } | 722 | } |
723 | |||
724 | /* Some devices claim to support larger sense but fail when | ||
725 | * trying to request it. When a transport failure happens | ||
726 | * using US_FS_SANE_SENSE, we always retry with a standard | ||
727 | * (small) sense request. This fixes some USB GSM modems | ||
728 | */ | ||
729 | if (temp_result == USB_STOR_TRANSPORT_FAILED && | ||
730 | (us->fflags & US_FL_SANE_SENSE) && | ||
731 | sense_size != US_SENSE_SIZE) { | ||
732 | US_DEBUGP("-- auto-sense failure, retry small sense\n"); | ||
733 | sense_size = US_SENSE_SIZE; | ||
734 | goto Retry_Sense; | ||
735 | } | ||
736 | |||
737 | /* Other failures */ | ||
723 | if (temp_result != USB_STOR_TRANSPORT_GOOD) { | 738 | if (temp_result != USB_STOR_TRANSPORT_GOOD) { |
724 | US_DEBUGP("-- auto-sense failure\n"); | 739 | US_DEBUGP("-- auto-sense failure\n"); |
725 | 740 | ||
@@ -768,17 +783,32 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
768 | /* set the result so the higher layers expect this data */ | 783 | /* set the result so the higher layers expect this data */ |
769 | srb->result = SAM_STAT_CHECK_CONDITION; | 784 | srb->result = SAM_STAT_CHECK_CONDITION; |
770 | 785 | ||
771 | /* If things are really okay, then let's show that. Zero | 786 | /* We often get empty sense data. This could indicate that |
772 | * out the sense buffer so the higher layers won't realize | 787 | * everything worked or that there was an unspecified |
773 | * we did an unsolicited auto-sense. */ | 788 | * problem. We have to decide which. |
774 | if (result == USB_STOR_TRANSPORT_GOOD && | 789 | */ |
775 | /* Filemark 0, ignore EOM, ILI 0, no sense */ | 790 | if ( /* Filemark 0, ignore EOM, ILI 0, no sense */ |
776 | (srb->sense_buffer[2] & 0xaf) == 0 && | 791 | (srb->sense_buffer[2] & 0xaf) == 0 && |
777 | /* No ASC or ASCQ */ | 792 | /* No ASC or ASCQ */ |
778 | srb->sense_buffer[12] == 0 && | 793 | srb->sense_buffer[12] == 0 && |
779 | srb->sense_buffer[13] == 0) { | 794 | srb->sense_buffer[13] == 0) { |
780 | srb->result = SAM_STAT_GOOD; | 795 | |
781 | srb->sense_buffer[0] = 0x0; | 796 | /* If things are really okay, then let's show that. |
797 | * Zero out the sense buffer so the higher layers | ||
798 | * won't realize we did an unsolicited auto-sense. | ||
799 | */ | ||
800 | if (result == USB_STOR_TRANSPORT_GOOD) { | ||
801 | srb->result = SAM_STAT_GOOD; | ||
802 | srb->sense_buffer[0] = 0x0; | ||
803 | |||
804 | /* If there was a problem, report an unspecified | ||
805 | * hardware error to prevent the higher layers from | ||
806 | * entering an infinite retry loop. | ||
807 | */ | ||
808 | } else { | ||
809 | srb->result = DID_ERROR << 16; | ||
810 | srb->sense_buffer[2] = HARDWARE_ERROR; | ||
811 | } | ||
782 | } | 812 | } |
783 | } | 813 | } |
784 | 814 | ||