public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org,
	Greg KH <greg@kroah.com>
Cc: Justin Forbes <jmforbes@linuxtx.org>,
	Zwane Mwaikambo <zwane@arm.linux.org.uk>,
	"Theodore Ts'o" <tytso@mit.edu>,
	Randy Dunlap <rdunlap@xenotime.net>,
	Dave Jones <davej@redhat.com>,
	Chuck Wolber <chuckw@quantumlinux.com>,
	Chris Wedgwood <reviews@ml.cw.f00f.org>,
	Michael Krufky <mkrufky@linuxtv.org>,
	Chuck Ebbert <cebbert@redhat.com>,
	Domenico Andreoli <cavokz@gmail.com>, Willy Tarreau <w@1wt.eu>,
	Rodrigo Rubira Branco <rbranco@la.checkpoint.com>,
	Jake Edge <jake@lwn.net>, Eugene Teo <eteo@redhat.com>,
	torvalds@linux-foundation.org, akpm@linux-foundation.org,
	alan@lxorguk.ukuu.org.uk,
	USB Storage list <usb-storage@lists.one-eyed-alien.net>,
	Alan Stern <stern@rowland.harvard.edu>
Subject: [patch 16/46] usb-storage: add last-sector hacks
Date: Thu, 22 Jan 2009 17:12:00 -0800	[thread overview]
Message-ID: <20090123011200.GQ19756@kroah.com> (raw)
In-Reply-To: <20090123011110.GA19756@kroah.com>

[-- Attachment #1: usb-storage-add-last-sector-hacks.patch --]
[-- Type: text/plain, Size: 10824 bytes --]

2.6.28-stable review patch.  If anyone has any objections, please let us know.

------------------

From: Alan Stern <stern@rowland.harvard.edu>

commit 25ff1c316f6a763f1eefe7f8984b2d8c03888432 upstream.

This patch (as1189c) 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 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.

This version of the patch differs from the version accepted into the
mainline only in that it does not trigger a WARN() when an
odd-numbered last-sector access succeeds.  In a stable kernel series
we don't want to go around spamming users' logs and consoles for no
good reason.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/usb/storage/libusual.c     |    7 +++
 drivers/usb/storage/scsiglue.c     |    8 +++
 drivers/usb/storage/transport.c    |   80 +++++++++++++++++++++++++++++++++++++
 drivers/usb/storage/unusual_devs.h |   16 ++++++-
 drivers/usb/storage/usb.c          |    6 ++
 drivers/usb/storage/usb.h          |    4 +
 include/linux/usb_usual.h          |    5 +-
 7 files changed, 123 insertions(+), 3 deletions(-)

--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -46,6 +46,12 @@ static int usu_probe_thread(void *arg);
 { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
   .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
 
+#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+  .driver_info = (flags) }
+
 #define USUAL_DEV(useProto, useTrans, useType) \
 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
   .driver_info = ((useType)<<24) }
@@ -57,6 +63,7 @@ struct usb_device_id storage_usb_ids [] 
 
 #undef USUAL_DEV
 #undef UNUSUAL_DEV
+#undef COMPLIANT_DEV
 
 MODULE_DEVICE_TABLE(usb, storage_usb_ids);
 EXPORT_SYMBOL_GPL(storage_usb_ids);
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -196,6 +196,14 @@ static int slave_configure(struct scsi_d
 		 * sector in a larger then 1 sector read, since the performance
 		 * impact is negible we set this flag for all USB disks */
 		sdev->last_sector_bug = 1;
+
+		/* Enable last-sector hacks for single-target devices using
+		 * the Bulk-only transport, unless we already know the
+		 * capacity will be decremented or is correct. */
+		if (!(us->fflags & (US_FL_FIX_CAPACITY | US_FL_CAPACITY_OK |
+					US_FL_SCM_MULT_TARG)) &&
+				us->protocol == US_PR_BULK)
+			us->use_last_sector_hacks = 1;
 	} else {
 
 		/* Non-disk-type devices don't need to blacklist any pages
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -57,6 +57,9 @@
 #include "scsiglue.h"
 #include "debug.h"
 
+#include <linux/blkdev.h>
+#include "../../scsi/sd.h"
+
 
 /***********************************************************************
  * Data transfer routines
@@ -511,6 +514,80 @@ int usb_stor_bulk_transfer_sg(struct us_
  * Transport routines
  ***********************************************************************/
 
+/* There are so many devices that report the capacity incorrectly,
+ * this routine was written to counteract some of the resulting
+ * problems.
+ */
+static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb)
+{
+	struct gendisk *disk;
+	struct scsi_disk *sdkp;
+	u32 sector;
+
+	/* To Report "Medium Error: Record Not Found */
+	static unsigned char record_not_found[18] = {
+		[0]	= 0x70,			/* current error */
+		[2]	= MEDIUM_ERROR,		/* = 0x03 */
+		[7]	= 0x0a,			/* additional length */
+		[12]	= 0x14			/* Record Not Found */
+	};
+
+	/* If last-sector problems can't occur, whether because the
+	 * capacity was already decremented or because the device is
+	 * known to report the correct capacity, then we don't need
+	 * to do anything.
+	 */
+	if (!us->use_last_sector_hacks)
+		return;
+
+	/* Was this command a READ(10) or a WRITE(10)? */
+	if (srb->cmnd[0] != READ_10 && srb->cmnd[0] != WRITE_10)
+		goto done;
+
+	/* Did this command access the last sector? */
+	sector = (srb->cmnd[2] << 24) | (srb->cmnd[3] << 16) |
+			(srb->cmnd[4] << 8) | (srb->cmnd[5]);
+	disk = srb->request->rq_disk;
+	if (!disk)
+		goto done;
+	sdkp = scsi_disk(disk);
+	if (!sdkp)
+		goto done;
+	if (sector + 1 != sdkp->capacity)
+		goto done;
+
+	if (srb->result == SAM_STAT_GOOD && scsi_get_resid(srb) == 0) {
+
+		/* The command succeeded.  We know this device doesn't
+		 * have the last-sector bug, so stop checking it.
+		 */
+		us->use_last_sector_hacks = 0;
+
+	} else {
+		/* The command failed.  Allow up to 3 retries in case this
+		 * is some normal sort of failure.  After that, assume the
+		 * capacity is wrong and we're trying to access the sector
+		 * beyond the end.  Replace the result code and sense data
+		 * with values that will cause the SCSI core to fail the
+		 * command immediately, instead of going into an infinite
+		 * (or even just a very long) retry loop.
+		 */
+		if (++us->last_sector_retries < 3)
+			return;
+		srb->result = SAM_STAT_CHECK_CONDITION;
+		memcpy(srb->sense_buffer, record_not_found,
+				sizeof(record_not_found));
+	}
+
+ done:
+	/* Don't reset the retry counter for TEST UNIT READY commands,
+	 * because they get issued after device resets which might be
+	 * caused by a failed last-sector access.
+	 */
+	if (srb->cmnd[0] != TEST_UNIT_READY)
+		us->last_sector_retries = 0;
+}
+
 /* Invoke the transport and basic error-handling/recovery methods
  *
  * This is used by the protocol layers to actually send the message to
@@ -544,6 +621,7 @@ void usb_stor_invoke_transport(struct sc
 	/* if the transport provided its own sense data, don't auto-sense */
 	if (result == USB_STOR_TRANSPORT_NO_SENSE) {
 		srb->result = SAM_STAT_CHECK_CONDITION;
+		last_sector_hacks(us, srb);
 		return;
 	}
 
@@ -667,6 +745,7 @@ void usb_stor_invoke_transport(struct sc
 			scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
 		srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24);
 
+	last_sector_hacks(us, srb);
 	return;
 
 	/* Error and abort processing: try to resynchronize with the device
@@ -694,6 +773,7 @@ void usb_stor_invoke_transport(struct sc
 		us->transport_reset(us);
 	}
 	clear_bit(US_FLIDX_RESETTING, &us->dflags);
+	last_sector_hacks(us, srb);
 }
 
 /* Stop the current URB transfer */
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -27,7 +27,8 @@
 
 /* IMPORTANT NOTE: This file must be included in another file which does
  * the following thing for it to work:
- * The macro UNUSUAL_DEV() must be defined before this file is included
+ * The UNUSUAL_DEV, COMPLIANT_DEV, and USUAL_DEV macros must be defined
+ * before this file is included.
  */
 
 /* If you edit this file, please try to keep it sorted first by VendorID,
@@ -46,6 +47,12 @@
  * <usb-storage@lists.one-eyed-alien.net>
  */
 
+/* Note: If you add an entry only in order to set the CAPACITY_OK flag,
+ * use the COMPLIANT_DEV macro instead of UNUSUAL_DEV.  This is
+ * because such entries mark devices which actually work correctly,
+ * as opposed to devices that do something strangely or wrongly.
+ */
+
 /* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr>
  */
 UNUSUAL_DEV(  0x03eb, 0x2002, 0x0100, 0x0100,
@@ -692,6 +699,13 @@ UNUSUAL_DEV(  0x0525, 0xa140, 0x0100, 0x
 		US_SC_8070, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* Added by Alan Stern <stern@rowland.harvard.edu> */
+COMPLIANT_DEV(0x0525, 0xa4a5, 0x0000, 0x9999,
+		"Linux",
+		"File-backed Storage Gadget",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_CAPACITY_OK ),
+
 /* Yakumo Mega Image 37
  * Submitted by Stephan Fuhrmann <atomenergie@t-online.de> */
 UNUSUAL_DEV(  0x052b, 0x1801, 0x0100, 0x0100,
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -126,6 +126,8 @@ MODULE_PARM_DESC(delay_use, "seconds to 
 { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
   .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
 
+#define COMPLIANT_DEV	UNUSUAL_DEV
+
 #define USUAL_DEV(useProto, useTrans, useType) \
 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
   .driver_info = (USB_US_TYPE_STOR<<24) }
@@ -134,6 +136,7 @@ static struct usb_device_id storage_usb_
 
 #	include "unusual_devs.h"
 #undef UNUSUAL_DEV
+#undef COMPLIANT_DEV
 #undef USUAL_DEV
 	/* Terminating entry */
 	{ }
@@ -164,6 +167,8 @@ MODULE_DEVICE_TABLE (usb, storage_usb_id
 	.initFunction = init_function,	\
 }
 
+#define COMPLIANT_DEV	UNUSUAL_DEV
+
 #define USUAL_DEV(use_protocol, use_transport, use_type) \
 { \
 	.useProtocol = use_protocol,	\
@@ -173,6 +178,7 @@ MODULE_DEVICE_TABLE (usb, storage_usb_id
 static struct us_unusual_dev us_unusual_dev_list[] = {
 #	include "unusual_devs.h" 
 #	undef UNUSUAL_DEV
+#	undef COMPLIANT_DEV
 #	undef USUAL_DEV
 
 	/* Terminating entry */
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -155,6 +155,10 @@ struct us_data {
 #ifdef CONFIG_PM
 	pm_hook			suspend_resume_hook;
 #endif
+
+	/* hacks for READ CAPACITY bug handling */
+	int			use_last_sector_hacks;
+	int			last_sector_retries;
 };
 
 /* Convert between us_data and the corresponding Scsi_Host */
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -52,8 +52,9 @@
 	US_FLAG(MAX_SECTORS_MIN,0x00002000)			\
 		/* Sets max_sectors to arch min */		\
 	US_FLAG(BULK_IGNORE_TAG,0x00004000)			\
-		/* Ignore tag mismatch in bulk operations */
-
+		/* Ignore tag mismatch in bulk operations */	\
+	US_FLAG(CAPACITY_OK,	0x00010000)			\
+		/* READ CAPACITY response is correct */
 
 #define US_FLAG(name, value)	US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };


  parent reply	other threads:[~2009-01-23  1:19 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20090123010651.683741823@mini.kroah.org>
2009-01-23  1:11 ` [patch 00/46] 2.6.28-stable review Greg KH
2009-01-23  1:11   ` [patch 01/46] PCI: keep ASPM link state consistent throughout PCIe hierarchy Greg KH
2009-01-23  1:11   ` [patch 02/46] security: introduce missing kfree Greg KH
2009-01-23  1:11   ` [patch 03/46] rt2x00: add USB ID for the Linksys WUSB200 Greg KH
2009-01-23  1:11   ` [patch 04/46] p54usb: Add USB ID for Thomson Speedtouch 121g Greg KH
2009-01-23  1:11   ` [patch 05/46] lib/idr.c: use kmem_cache_zalloc() for the idr_layer cache Greg KH
2009-01-23  1:11   ` [patch 06/46] sgi-xp: eliminate false detection of no heartbeat Greg KH
2009-01-23  1:11   ` [patch 07/46] sched: fix update_min_vruntime Greg KH
2009-01-23  1:11   ` [patch 08/46] IA64: Turn on CONFIG_HAVE_UNSTABLE_CLOCK Greg KH
2009-01-23  1:11   ` [patch 09/46] sound: virtuoso: do not overwrite EEPROM on Xonar D2/D2X Greg KH
2009-01-23  1:11   ` [patch 10/46] ALSA: hda - Add quirk for another HP dv5 Greg KH
2009-01-23  1:11   ` [patch 11/46] ALSA: hda - Fix HP dv5 mic input Greg KH
2009-01-23  1:11   ` [patch 12/46] ALSA: hda - Add automatic model setting for Samsung Q45 Greg KH
2009-01-23  1:11   ` [patch 13/46] ALSA: hda - Dont reset HP pinctl in patch_sigmatel.c Greg KH
2009-01-23  1:11   ` [patch 14/46] ALSA: hda - make laptop-eapd model back for AD1986A Greg KH
2009-01-23  1:11   ` [patch 15/46] drivers/net/irda/irda-usb.c: fix buffer overflow Greg KH
2009-01-23  1:12   ` Greg KH [this message]
2009-01-23  1:12   ` [patch 17/46] usb-storage: set CAPACITY_HEURISTICS flag for bad vendors Greg KH
2009-01-23  1:12   ` [patch 18/46] pkt_sched: sch_htb: Fix deadlock in hrtimers triggered by HTB Greg KH
2009-01-23  1:12   ` [patch 19/46] ipv6: Fix fib6_dump_table walker leak Greg KH
2009-01-23  1:12   ` [patch 20/46] sctp: Avoid memory overflow while FWD-TSN chunk is received with bad stream ID Greg KH
2009-01-23  1:12   ` [patch 21/46] pkt_sched: cls_u32: Fix locking in u32_change() Greg KH
2009-01-23  1:12   ` [patch 22/46] r6040: fix wrong logic in mdio code Greg KH
2009-01-23  1:12   ` [patch 23/46] r6040: save and restore MIER correctly in the interrupt routine Greg KH
2009-01-23  1:12   ` [patch 24/46] r6040: bump release number to 0.19 Greg KH
2009-01-23  1:31     ` Jesper Juhl
2009-01-23  2:04       ` [stable] " Greg KH
2009-01-23  7:53         ` Willy Tarreau
2009-01-23  7:49       ` David Miller
2009-01-23  1:12   ` [patch 25/46] tcp: dont mask EOF and socket errors on nonblocking splice receive Greg KH
2009-01-23  1:12   ` [patch 26/46] USB: re-enable interface after driver unbinds Greg KH
2009-01-23  1:12   ` [patch 27/46] p54usb: fix traffic stalls / packet drop Greg KH
2009-01-23  1:12   ` [patch 28/46] netfilter: x_tables: fix match/target revision lookup Greg KH
2009-01-23  1:12   ` [patch 29/46] netfilter: ebtables: fix inversion in match code Greg KH
2009-01-23  1:12   ` [patch 30/46] netfilter: nf_conntrack: fix ICMP/ICMPv6 timeout sysctls on big-endian Greg KH
2009-01-23  1:12   ` [patch 31/46] dell_rbu: use scnprintf() instead of less secure sprintf() Greg KH
2009-01-23  1:12   ` [patch 32/46] powerpc: is_hugepage_only_range() must account for both 4kB and 64kB slices Greg KH
2009-01-23  1:12   ` [patch 33/46] hwmon: (abituguru3) Fix CONFIG_DMI=n fallback to probe Greg KH
2009-01-23  1:12   ` [patch 34/46] mm: write_cache_pages cyclic fix Greg KH
2009-01-23  1:12   ` [patch 35/46] mm: write_cache_pages early loop termination Greg KH
2009-01-23  1:12   ` [patch 36/46] mm: write_cache_pages writepage error fix Greg KH
2009-01-23  1:12   ` [patch 38/46] mm: write_cache_pages cleanups Greg KH
2009-01-23  1:12   ` [patch 37/46] mm: write_cache_pages integrity fix Greg KH
2009-01-23  1:12   ` [patch 39/46] mm: write_cache_pages optimise page cleaning Greg KH
2009-01-23  1:13   ` [patch 40/46] mm: write_cache_pages terminate quickly Greg KH
2009-01-23  1:13   ` [patch 41/46] mm: write_cache_pages more " Greg KH
2009-01-23  1:13   ` [patch 42/46] mm: do_sync_mapping_range integrity fix Greg KH
2009-01-23  1:13   ` [patch 43/46] mm: direct IO starvation improvement Greg KH
2009-01-23  1:13   ` [patch 44/46] fs: remove WB_SYNC_HOLD Greg KH
2009-01-23  1:13   ` [patch 45/46] fs: sync_sb_inodes fix Greg KH
2009-01-23  1:13   ` [patch 46/46] fs: sys_sync fix Greg KH
2009-01-23  1:50   ` [patch 00/46] 2.6.28-stable review Stefan Lippers-Hollmann
2009-01-23  2:02     ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090123011200.GQ19756@kroah.com \
    --to=gregkh@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=cavokz@gmail.com \
    --cc=cebbert@redhat.com \
    --cc=chuckw@quantumlinux.com \
    --cc=davej@redhat.com \
    --cc=eteo@redhat.com \
    --cc=greg@kroah.com \
    --cc=jake@lwn.net \
    --cc=jmforbes@linuxtx.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mkrufky@linuxtv.org \
    --cc=rbranco@la.checkpoint.com \
    --cc=rdunlap@xenotime.net \
    --cc=reviews@ml.cw.f00f.org \
    --cc=stable@kernel.org \
    --cc=stern@rowland.harvard.edu \
    --cc=torvalds@linux-foundation.org \
    --cc=tytso@mit.edu \
    --cc=usb-storage@lists.one-eyed-alien.net \
    --cc=w@1wt.eu \
    --cc=zwane@arm.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox