aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/transport.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2008-12-15 12:43:41 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-07 13:00:11 -0500
commit25ff1c316f6a763f1eefe7f8984b2d8c03888432 (patch)
tree623759675a8e2db8cbcacc665d97d874e57ab4c5 /drivers/usb/storage/transport.c
parent9ebd9616648bc0e47e7f8e1898c919305f1e6347 (diff)
USB: storage: add last-sector hacks
This patch (as1189b) adds some hacks to usb-storage for dealing with the growing problems involving bad capacity values and last-sector accesses: A new flag, US_FL_CAPACITY_OK, is created to indicate that the device is known to report its capacity correctly. An unusual_devs entry for Linux's own File-backed Storage Gadget is added with this flag set, since g_file_storage always reports the correct capacity and since the capacity need not be even (it is determined by the size of the backing file). An entry in unusual_devs.h which has only the CAPACITY_OK flag set shouldn't prejudice libusual, since the device will work perfectly well with either usb-storage or ub. So a new macro, COMPLIANT_DEV, is added to let libusual know about these entries. When a last-sector access succeeds and the total number of sectors is odd (the unexpected case, in which guessing that the number is even might cause trouble), a WARN is triggered. The kerneloops.org project will collect these warnings, allowing us to add CAPACITY_OK flags for the devices in question before implementing the default-to-even heuristic. If users want to prevent the stack dump produced by the WARN, they can disable the hack by adding an unusual_devs entry for their device with the CAPACITY_OK flag. When a last-sector access fails three times in a row and neither the FIX_CAPACITY nor the CAPACITY_OK flag is set, we assume the last-sector bug is present. We replace the existing status and sense data with values that will cause the SCSI core to fail the access immediately rather than retry indefinitely. This should fix the difficulties people have been having with Nokia phones. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/storage/transport.c')
-rw-r--r--drivers/usb/storage/transport.c110
1 files changed, 110 insertions, 0 deletions
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 */