aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt2
-rw-r--r--drivers/usb/storage/transport.c29
-rw-r--r--drivers/usb/storage/unusual_devs.h19
-rw-r--r--drivers/usb/storage/usb.c13
-rw-r--r--drivers/usb/storage/usb.h2
-rw-r--r--include/linux/usb_usual.h4
6 files changed, 67 insertions, 2 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d9a203b058f..fd248a31821 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2598,6 +2598,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
2598 unlock ejectable media); 2598 unlock ejectable media);
2599 m = MAX_SECTORS_64 (don't transfer more 2599 m = MAX_SECTORS_64 (don't transfer more
2600 than 64 sectors = 32 KB at a time); 2600 than 64 sectors = 32 KB at a time);
2601 n = INITIAL_READ10 (force a retry of the
2602 initial READ(10) command);
2601 o = CAPACITY_OK (accept the capacity 2603 o = CAPACITY_OK (accept the capacity
2602 reported by the device); 2604 reported by the device);
2603 r = IGNORE_RESIDUE (the device reports 2605 r = IGNORE_RESIDUE (the device reports
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 00418995d8e..e8ae21b2d38 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -819,6 +819,35 @@ Retry_Sense:
819 } 819 }
820 } 820 }
821 821
822 /*
823 * Some devices don't work or return incorrect data the first
824 * time they get a READ(10) command, or for the first READ(10)
825 * after a media change. If the INITIAL_READ10 flag is set,
826 * keep track of whether READ(10) commands succeed. If the
827 * previous one succeeded and this one failed, set the REDO_READ10
828 * flag to force a retry.
829 */
830 if (unlikely((us->fflags & US_FL_INITIAL_READ10) &&
831 srb->cmnd[0] == READ_10)) {
832 if (srb->result == SAM_STAT_GOOD) {
833 set_bit(US_FLIDX_READ10_WORKED, &us->dflags);
834 } else if (test_bit(US_FLIDX_READ10_WORKED, &us->dflags)) {
835 clear_bit(US_FLIDX_READ10_WORKED, &us->dflags);
836 set_bit(US_FLIDX_REDO_READ10, &us->dflags);
837 }
838
839 /*
840 * Next, if the REDO_READ10 flag is set, return a result
841 * code that will cause the SCSI core to retry the READ(10)
842 * command immediately.
843 */
844 if (test_bit(US_FLIDX_REDO_READ10, &us->dflags)) {
845 clear_bit(US_FLIDX_REDO_READ10, &us->dflags);
846 srb->result = DID_IMM_RETRY << 16;
847 srb->sense_buffer[0] = 0;
848 }
849 }
850
822 /* Did we transfer less than the minimum amount required? */ 851 /* Did we transfer less than the minimum amount required? */
823 if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) && 852 if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) &&
824 scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) 853 scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index c1602b8c559..ccff3483eeb 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1114,6 +1114,16 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
1114 USB_SC_DEVICE, USB_PR_DEVICE, NULL, 1114 USB_SC_DEVICE, USB_PR_DEVICE, NULL,
1115 US_FL_FIX_CAPACITY ), 1115 US_FL_FIX_CAPACITY ),
1116 1116
1117/* Reported by Paul Hartman <paul.hartman+linux@gmail.com>
1118 * This card reader returns "Illegal Request, Logical Block Address
1119 * Out of Range" for the first READ(10) after a new card is inserted.
1120 */
1121UNUSUAL_DEV( 0x090c, 0x6000, 0x0100, 0x0100,
1122 "Feiya",
1123 "SD/SDHC Card Reader",
1124 USB_SC_DEVICE, USB_PR_DEVICE, NULL,
1125 US_FL_INITIAL_READ10 ),
1126
1117/* This Pentax still camera is not conformant 1127/* This Pentax still camera is not conformant
1118 * to the USB storage specification: - 1128 * to the USB storage specification: -
1119 * - It does not like the INQUIRY command. So we must handle this command 1129 * - It does not like the INQUIRY command. So we must handle this command
@@ -1888,6 +1898,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
1888 USB_SC_DEVICE, USB_PR_DEVICE, NULL, 1898 USB_SC_DEVICE, USB_PR_DEVICE, NULL,
1889 US_FL_NO_READ_DISC_INFO ), 1899 US_FL_NO_READ_DISC_INFO ),
1890 1900
1901/* Reported by Sven Geggus <sven-usbst@geggus.net>
1902 * This encrypted pen drive returns bogus data for the initial READ(10).
1903 */
1904UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200,
1905 "Corsair",
1906 "Padlock v2",
1907 USB_SC_DEVICE, USB_PR_DEVICE, NULL,
1908 US_FL_INITIAL_READ10 ),
1909
1891/* Patch by Richard Schütz <r.schtz@t-online.de> 1910/* Patch by Richard Schütz <r.schtz@t-online.de>
1892 * This external hard drive enclosure uses a JMicron chip which 1911 * This external hard drive enclosure uses a JMicron chip which
1893 * needs the US_FL_IGNORE_RESIDUE flag to work properly. */ 1912 * needs the US_FL_IGNORE_RESIDUE flag to work properly. */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 5ee7ac42e08..0ca095820f3 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -440,7 +440,8 @@ static void adjust_quirks(struct us_data *us)
440 US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 | 440 US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
441 US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | 441 US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
442 US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT | 442 US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT |
443 US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16); 443 US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
444 US_FL_INITIAL_READ10);
444 445
445 p = quirks; 446 p = quirks;
446 while (*p) { 447 while (*p) {
@@ -490,6 +491,9 @@ static void adjust_quirks(struct us_data *us)
490 case 'm': 491 case 'm':
491 f |= US_FL_MAX_SECTORS_64; 492 f |= US_FL_MAX_SECTORS_64;
492 break; 493 break;
494 case 'n':
495 f |= US_FL_INITIAL_READ10;
496 break;
493 case 'o': 497 case 'o':
494 f |= US_FL_CAPACITY_OK; 498 f |= US_FL_CAPACITY_OK;
495 break; 499 break;
@@ -953,6 +957,13 @@ int usb_stor_probe2(struct us_data *us)
953 if (result) 957 if (result)
954 goto BadDevice; 958 goto BadDevice;
955 959
960 /*
961 * If the device returns invalid data for the first READ(10)
962 * command, indicate the command should be retried.
963 */
964 if (us->fflags & US_FL_INITIAL_READ10)
965 set_bit(US_FLIDX_REDO_READ10, &us->dflags);
966
956 /* Acquire all the other resources and add the host */ 967 /* Acquire all the other resources and add the host */
957 result = usb_stor_acquire_resources(us); 968 result = usb_stor_acquire_resources(us);
958 if (result) 969 if (result)
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 89d3bfff98d..7b0f2113632 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -73,6 +73,8 @@ struct us_unusual_dev {
73#define US_FLIDX_RESETTING 4 /* device reset in progress */ 73#define US_FLIDX_RESETTING 4 /* device reset in progress */
74#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */ 74#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */
75#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */ 75#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */
76#define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */
77#define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */
76 78
77#define USB_STOR_STRING_LEN 32 79#define USB_STOR_STRING_LEN 32
78 80
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index 71693d4a4fe..17df3600bce 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -62,7 +62,9 @@
62 US_FLAG(NO_READ_DISC_INFO, 0x00040000) \ 62 US_FLAG(NO_READ_DISC_INFO, 0x00040000) \
63 /* cannot handle READ_DISC_INFO */ \ 63 /* cannot handle READ_DISC_INFO */ \
64 US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \ 64 US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \
65 /* cannot handle READ_CAPACITY_16 */ 65 /* cannot handle READ_CAPACITY_16 */ \
66 US_FLAG(INITIAL_READ10, 0x00100000) \
67 /* Initial READ(10) (and others) must be retried */
66 68
67#define US_FLAG(name, value) US_FL_##name = value , 69#define US_FLAG(name, value) US_FL_##name = value ,
68enum { US_DO_ALL_FLAGS }; 70enum { US_DO_ALL_FLAGS };