aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/storage/libusual.c7
-rw-r--r--drivers/usb/storage/scsiglue.c8
-rw-r--r--drivers/usb/storage/transport.c110
-rw-r--r--drivers/usb/storage/unusual_devs.h16
-rw-r--r--drivers/usb/storage/usb.c6
-rw-r--r--drivers/usb/storage/usb.h4
6 files changed, 150 insertions, 1 deletions
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
index d617e8ae6b0..f970b27ba30 100644
--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -46,6 +46,12 @@ static int usu_probe_thread(void *arg);
46{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ 46{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
47 .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } 47 .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
48 48
49#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
50 vendorName, productName, useProtocol, useTransport, \
51 initFunction, flags) \
52{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
53 .driver_info = (flags) }
54
49#define USUAL_DEV(useProto, useTrans, useType) \ 55#define USUAL_DEV(useProto, useTrans, useType) \
50{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ 56{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
51 .driver_info = ((useType)<<24) } 57 .driver_info = ((useType)<<24) }
@@ -57,6 +63,7 @@ struct usb_device_id storage_usb_ids [] = {
57 63
58#undef USUAL_DEV 64#undef USUAL_DEV
59#undef UNUSUAL_DEV 65#undef UNUSUAL_DEV
66#undef COMPLIANT_DEV
60 67
61MODULE_DEVICE_TABLE(usb, storage_usb_ids); 68MODULE_DEVICE_TABLE(usb, storage_usb_ids);
62EXPORT_SYMBOL_GPL(storage_usb_ids); 69EXPORT_SYMBOL_GPL(storage_usb_ids);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index e9d6c196a7a..8d78084abf9 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -208,6 +208,14 @@ static int slave_configure(struct scsi_device *sdev)
208 * sector in a larger then 1 sector read, since the performance 208 * sector in a larger then 1 sector read, since the performance
209 * impact is negible we set this flag for all USB disks */ 209 * impact is negible we set this flag for all USB disks */
210 sdev->last_sector_bug = 1; 210 sdev->last_sector_bug = 1;
211
212 /* Enable last-sector hacks for single-target devices using
213 * the Bulk-only transport, unless we already know the
214 * capacity will be decremented or is correct. */
215 if (!(us->fflags & (US_FL_FIX_CAPACITY | US_FL_CAPACITY_OK |
216 US_FL_SCM_MULT_TARG)) &&
217 us->protocol == US_PR_BULK)
218 us->use_last_sector_hacks = 1;
211 } else { 219 } else {
212 220
213 /* Non-disk-type devices don't need to blacklist any pages 221 /* Non-disk-type devices don't need to blacklist any pages
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 9cc30afd6d3..1d5438e6363 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -57,6 +57,9 @@
57#include "scsiglue.h" 57#include "scsiglue.h"
58#include "debug.h" 58#include "debug.h"
59 59
60#include <linux/blkdev.h>
61#include "../../scsi/sd.h"
62
60 63
61/*********************************************************************** 64/***********************************************************************
62 * Data transfer routines 65 * Data transfer routines
@@ -511,6 +514,110 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
511 * Transport routines 514 * Transport routines
512 ***********************************************************************/ 515 ***********************************************************************/
513 516
517/* There are so many devices that report the capacity incorrectly,
518 * this routine was written to counteract some of the resulting
519 * problems.
520 */
521static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb)
522{
523 struct gendisk *disk;
524 struct scsi_disk *sdkp;
525 u32 sector;
526
527 /* To Report "Medium Error: Record Not Found */
528 static unsigned char record_not_found[18] = {
529 [0] = 0x70, /* current error */
530 [2] = MEDIUM_ERROR, /* = 0x03 */
531 [7] = 0x0a, /* additional length */
532 [12] = 0x14 /* Record Not Found */
533 };
534
535 /* If last-sector problems can't occur, whether because the
536 * capacity was already decremented or because the device is
537 * known to report the correct capacity, then we don't need
538 * to do anything.
539 */
540 if (!us->use_last_sector_hacks)
541 return;
542
543 /* Was this command a READ(10) or a WRITE(10)? */
544 if (srb->cmnd[0] != READ_10 && srb->cmnd[0] != WRITE_10)
545 goto done;
546
547 /* Did this command access the last sector? */
548 sector = (srb->cmnd[2] << 24) | (srb->cmnd[3] << 16) |
549 (srb->cmnd[4] << 8) | (srb->cmnd[5]);
550 disk = srb->request->rq_disk;
551 if (!disk)
552 goto done;
553 sdkp = scsi_disk(disk);
554 if (!sdkp)
555 goto done;
556 if (sector + 1 != sdkp->capacity)
557 goto done;
558
559 if (srb->result == SAM_STAT_GOOD && scsi_get_resid(srb) == 0) {
560
561 /* The command succeeded. If the capacity is odd
562 * (i.e., if the sector number is even) then the
563 * "always-even" heuristic would be wrong for this
564 * device. Issue a WARN() so that the kerneloops.org
565 * project will be notified and we will then know to
566 * mark the device with a CAPACITY_OK flag. Hopefully
567 * this will occur for only a few devices.
568 *
569 * Use the sign of us->last_sector_hacks to tell whether
570 * the warning has already been issued; we don't need
571 * more than one warning per device.
572 */
573 if (!(sector & 1) && us->use_last_sector_hacks > 0) {
574 unsigned vid = le16_to_cpu(
575 us->pusb_dev->descriptor.idVendor);
576 unsigned pid = le16_to_cpu(
577 us->pusb_dev->descriptor.idProduct);
578 unsigned rev = le16_to_cpu(
579 us->pusb_dev->descriptor.bcdDevice);
580
581 WARN(1, "%s: Successful last sector success at %u, "
582 "device %04x:%04x:%04x\n",
583 sdkp->disk->disk_name, sector,
584 vid, pid, rev);
585 us->use_last_sector_hacks = -1;
586 }
587
588 } else {
589 /* The command failed. Allow up to 3 retries in case this
590 * is some normal sort of failure. After that, assume the
591 * capacity is wrong and we're trying to access the sector
592 * beyond the end. Replace the result code and sense data
593 * with values that will cause the SCSI core to fail the
594 * command immediately, instead of going into an infinite
595 * (or even just a very long) retry loop.
596 */
597 if (++us->last_sector_retries < 3)
598 return;
599 srb->result = SAM_STAT_CHECK_CONDITION;
600 memcpy(srb->sense_buffer, record_not_found,
601 sizeof(record_not_found));
602
603 /* In theory we might want to issue a WARN() here if the
604 * capacity is even, since it could indicate the device
605 * has the READ CAPACITY bug _and_ the real capacity is
606 * odd. But it could also indicate that the device
607 * simply can't access its last sector, a failure mode
608 * which is surprisingly common. So no warning.
609 */
610 }
611
612 done:
613 /* Don't reset the retry counter for TEST UNIT READY commands,
614 * because they get issued after device resets which might be
615 * caused by a failed last-sector access.
616 */
617 if (srb->cmnd[0] != TEST_UNIT_READY)
618 us->last_sector_retries = 0;
619}
620
514/* Invoke the transport and basic error-handling/recovery methods 621/* Invoke the transport and basic error-handling/recovery methods
515 * 622 *
516 * This is used by the protocol layers to actually send the message to 623 * This is used by the protocol layers to actually send the message to
@@ -544,6 +651,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
544 /* if the transport provided its own sense data, don't auto-sense */ 651 /* if the transport provided its own sense data, don't auto-sense */
545 if (result == USB_STOR_TRANSPORT_NO_SENSE) { 652 if (result == USB_STOR_TRANSPORT_NO_SENSE) {
546 srb->result = SAM_STAT_CHECK_CONDITION; 653 srb->result = SAM_STAT_CHECK_CONDITION;
654 last_sector_hacks(us, srb);
547 return; 655 return;
548 } 656 }
549 657
@@ -705,6 +813,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
705 scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) 813 scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
706 srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24); 814 srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24);
707 815
816 last_sector_hacks(us, srb);
708 return; 817 return;
709 818
710 /* Error and abort processing: try to resynchronize with the device 819 /* Error and abort processing: try to resynchronize with the device
@@ -732,6 +841,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
732 us->transport_reset(us); 841 us->transport_reset(us);
733 } 842 }
734 clear_bit(US_FLIDX_RESETTING, &us->dflags); 843 clear_bit(US_FLIDX_RESETTING, &us->dflags);
844 last_sector_hacks(us, srb);
735} 845}
736 846
737/* Stop the current URB transfer */ 847/* Stop the current URB transfer */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 0330ed53ec1..035bbc5d823 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -27,7 +27,8 @@
27 27
28/* IMPORTANT NOTE: This file must be included in another file which does 28/* IMPORTANT NOTE: This file must be included in another file which does
29 * the following thing for it to work: 29 * the following thing for it to work:
30 * The macro UNUSUAL_DEV() must be defined before this file is included 30 * The UNUSUAL_DEV, COMPLIANT_DEV, and USUAL_DEV macros must be defined
31 * before this file is included.
31 */ 32 */
32 33
33/* If you edit this file, please try to keep it sorted first by VendorID, 34/* If you edit this file, please try to keep it sorted first by VendorID,
@@ -46,6 +47,12 @@
46 * <usb-storage@lists.one-eyed-alien.net> 47 * <usb-storage@lists.one-eyed-alien.net>
47 */ 48 */
48 49
50/* Note: If you add an entry only in order to set the CAPACITY_OK flag,
51 * use the COMPLIANT_DEV macro instead of UNUSUAL_DEV. This is
52 * because such entries mark devices which actually work correctly,
53 * as opposed to devices that do something strangely or wrongly.
54 */
55
49/* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr> 56/* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr>
50 */ 57 */
51UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, 58UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100,
@@ -704,6 +711,13 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
704 US_SC_8070, US_PR_DEVICE, NULL, 711 US_SC_8070, US_PR_DEVICE, NULL,
705 US_FL_FIX_INQUIRY ), 712 US_FL_FIX_INQUIRY ),
706 713
714/* Added by Alan Stern <stern@rowland.harvard.edu> */
715COMPLIANT_DEV(0x0525, 0xa4a5, 0x0000, 0x9999,
716 "Linux",
717 "File-backed Storage Gadget",
718 US_SC_DEVICE, US_PR_DEVICE, NULL,
719 US_FL_CAPACITY_OK ),
720
707/* Yakumo Mega Image 37 721/* Yakumo Mega Image 37
708 * Submitted by Stephan Fuhrmann <atomenergie@t-online.de> */ 722 * Submitted by Stephan Fuhrmann <atomenergie@t-online.de> */
709UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100, 723UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100,
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index ce0b580db5e..80e234bf4e5 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -134,6 +134,8 @@ static struct quirks_entry *quirks_list, *quirks_end;
134{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ 134{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
135 .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } 135 .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
136 136
137#define COMPLIANT_DEV UNUSUAL_DEV
138
137#define USUAL_DEV(useProto, useTrans, useType) \ 139#define USUAL_DEV(useProto, useTrans, useType) \
138{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ 140{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
139 .driver_info = (USB_US_TYPE_STOR<<24) } 141 .driver_info = (USB_US_TYPE_STOR<<24) }
@@ -142,6 +144,7 @@ static struct usb_device_id storage_usb_ids [] = {
142 144
143# include "unusual_devs.h" 145# include "unusual_devs.h"
144#undef UNUSUAL_DEV 146#undef UNUSUAL_DEV
147#undef COMPLIANT_DEV
145#undef USUAL_DEV 148#undef USUAL_DEV
146 /* Terminating entry */ 149 /* Terminating entry */
147 { } 150 { }
@@ -172,6 +175,8 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
172 .initFunction = init_function, \ 175 .initFunction = init_function, \
173} 176}
174 177
178#define COMPLIANT_DEV UNUSUAL_DEV
179
175#define USUAL_DEV(use_protocol, use_transport, use_type) \ 180#define USUAL_DEV(use_protocol, use_transport, use_type) \
176{ \ 181{ \
177 .useProtocol = use_protocol, \ 182 .useProtocol = use_protocol, \
@@ -181,6 +186,7 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
181static struct us_unusual_dev us_unusual_dev_list[] = { 186static struct us_unusual_dev us_unusual_dev_list[] = {
182# include "unusual_devs.h" 187# include "unusual_devs.h"
183# undef UNUSUAL_DEV 188# undef UNUSUAL_DEV
189# undef COMPLIANT_DEV
184# undef USUAL_DEV 190# undef USUAL_DEV
185 191
186 /* Terminating entry */ 192 /* Terminating entry */
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index e4674fc715e..65e674e4be9 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -154,6 +154,10 @@ struct us_data {
154#ifdef CONFIG_PM 154#ifdef CONFIG_PM
155 pm_hook suspend_resume_hook; 155 pm_hook suspend_resume_hook;
156#endif 156#endif
157
158 /* hacks for READ CAPACITY bug handling */
159 int use_last_sector_hacks;
160 int last_sector_retries;
157}; 161};
158 162
159/* Convert between us_data and the corresponding Scsi_Host */ 163/* Convert between us_data and the corresponding Scsi_Host */