| From a0bb108112a872c0b0c4b3ef4974f95fb75b155d Mon Sep 17 00:00:00 2001 |
| From: Alan Stern <stern@rowland.harvard.edu> |
| Date: Mon, 7 Dec 2009 16:39:16 -0500 |
| Subject: USB: usb-storage: add BAD_SENSE flag |
| |
| From: Alan Stern <stern@rowland.harvard.edu> |
| |
| commit a0bb108112a872c0b0c4b3ef4974f95fb75b155d upstream. |
| |
| This patch (as1311) fixes a problem in usb-storage: Some devices are |
| pretty broken when it comes to reporting sense data. The information |
| they send back indicates that they have more than 18 bytes of sense |
| data available, but when the system asks for more than 18 they fail or |
| hang. The symptom is that probing fails with multiple resets. |
| |
| The patch adds a new BAD_SENSE flag to indicate that usb-storage |
| should never ask for more than 18 bytes of sense data. The flag can |
| be set in an unusual_devs entry or via the "quirks=" module parameter, |
| and it is set automatically whenever a REQUEST SENSE command for more |
| than 18 bytes fails or times out. |
| |
| An unusual_devs entry is added for the Agfa photo frame, which uses a |
| Prolific chip having this bug. |
| |
| Signed-off-by: Alan Stern <stern@rowland.harvard.edu> |
| Tested-by: Daniel Kukula <daniel.kuku@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- a/Documentation/kernel-parameters.txt |
| +++ b/Documentation/kernel-parameters.txt |
| @@ -2663,6 +2663,8 @@ and is between 256 and 4096 characters. It is defined in the file |
| to a common usb-storage quirk flag as follows: |
| a = SANE_SENSE (collect more than 18 bytes |
| of sense data); |
| + b = BAD_SENSE (don't collect more than 18 |
| + bytes of sense data); |
| c = FIX_CAPACITY (decrease the reported |
| device capacity by one sector); |
| h = CAPACITY_HEURISTICS (decrease the |
| diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c |
| index 589f6b4..cc313d1 100644 |
| --- a/drivers/usb/storage/transport.c |
| +++ b/drivers/usb/storage/transport.c |
| @@ -666,10 +666,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) |
| * to wait for at least one CHECK_CONDITION to determine |
| * SANE_SENSE support |
| */ |
| - if ((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && |
| + if (unlikely((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && |
| result == USB_STOR_TRANSPORT_GOOD && |
| !(us->fflags & US_FL_SANE_SENSE) && |
| - !(srb->cmnd[2] & 0x20)) { |
| + !(us->fflags & US_FL_BAD_SENSE) && |
| + !(srb->cmnd[2] & 0x20))) { |
| US_DEBUGP("-- SAT supported, increasing auto-sense\n"); |
| us->fflags |= US_FL_SANE_SENSE; |
| } |
| @@ -718,6 +719,12 @@ Retry_Sense: |
| if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { |
| US_DEBUGP("-- auto-sense aborted\n"); |
| srb->result = DID_ABORT << 16; |
| + |
| + /* If SANE_SENSE caused this problem, disable it */ |
| + if (sense_size != US_SENSE_SIZE) { |
| + us->fflags &= ~US_FL_SANE_SENSE; |
| + us->fflags |= US_FL_BAD_SENSE; |
| + } |
| goto Handle_Errors; |
| } |
| |
| @@ -727,10 +734,11 @@ Retry_Sense: |
| * (small) sense request. This fixes some USB GSM modems |
| */ |
| if (temp_result == USB_STOR_TRANSPORT_FAILED && |
| - (us->fflags & US_FL_SANE_SENSE) && |
| - sense_size != US_SENSE_SIZE) { |
| + sense_size != US_SENSE_SIZE) { |
| US_DEBUGP("-- auto-sense failure, retry small sense\n"); |
| sense_size = US_SENSE_SIZE; |
| + us->fflags &= ~US_FL_SANE_SENSE; |
| + us->fflags |= US_FL_BAD_SENSE; |
| goto Retry_Sense; |
| } |
| |
| @@ -754,6 +762,7 @@ Retry_Sense: |
| */ |
| if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) && |
| !(us->fflags & US_FL_SANE_SENSE) && |
| + !(us->fflags & US_FL_BAD_SENSE) && |
| (srb->sense_buffer[0] & 0x7C) == 0x70) { |
| US_DEBUGP("-- SANE_SENSE support enabled\n"); |
| us->fflags |= US_FL_SANE_SENSE; |
| diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h |
| index d4f034e..64a0a2c 100644 |
| --- a/drivers/usb/storage/unusual_devs.h |
| +++ b/drivers/usb/storage/unusual_devs.h |
| @@ -818,6 +818,13 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, |
| US_SC_DEVICE, US_PR_DEVICE, NULL, |
| US_FL_FIX_CAPACITY ), |
| |
| +/* Reported by Daniel Kukula <daniel.kuku@gmail.com> */ |
| +UNUSUAL_DEV( 0x067b, 0x1063, 0x0100, 0x0100, |
| + "Prolific Technology, Inc.", |
| + "Prolific Storage Gadget", |
| + US_SC_DEVICE, US_PR_DEVICE, NULL, |
| + US_FL_BAD_SENSE ), |
| + |
| /* Reported by Rogerio Brito <rbrito@ime.usp.br> */ |
| UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001, |
| "Prolific Technology, Inc.", |
| diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c |
| index 1599d86..f5c0264 100644 |
| --- a/drivers/usb/storage/usb.c |
| +++ b/drivers/usb/storage/usb.c |
| @@ -463,6 +463,9 @@ static void adjust_quirks(struct us_data *us) |
| case 'a': |
| f |= US_FL_SANE_SENSE; |
| break; |
| + case 'b': |
| + f |= US_FL_BAD_SENSE; |
| + break; |
| case 'c': |
| f |= US_FL_FIX_CAPACITY; |
| break; |
| diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h |
| index 3d15fb9..a4b947e 100644 |
| --- a/include/linux/usb_usual.h |
| +++ b/include/linux/usb_usual.h |
| @@ -56,7 +56,9 @@ |
| US_FLAG(SANE_SENSE, 0x00008000) \ |
| /* Sane Sense (> 18 bytes) */ \ |
| US_FLAG(CAPACITY_OK, 0x00010000) \ |
| - /* READ CAPACITY response is correct */ |
| + /* READ CAPACITY response is correct */ \ |
| + US_FLAG(BAD_SENSE, 0x00020000) \ |
| + /* Bad Sense (never more than 18 bytes) */ |
| |
| #define US_FLAG(name, value) US_FL_##name = value , |
| enum { US_DO_ALL_FLAGS }; |