Re: [usb-storage] Infinite resets with Sony Ericsson V800-Vodafone 802SE

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Friday 09 April 2010 18:47:56 Matthew Dharm wrote:
> On Fri, Apr 09, 2010 at 06:18:35PM +0200, Ondrej Zary wrote:
> > Windows reports 1921024 sectors too. But the partition is only half the
> > size. Accessing sectors 0 to 960511 works fine. Accessing sector 960512
> > and higher causes the device to fail.
> >
> > The memory stick is SanDisk Memory Stick Pro Duo 512MB. So the device
> > reports doubled capacity.
> >
> > How to fix this? I don't see an easy way to add something like
> > US_FL_DOUBLED_CAPACITY. Initializer functions does not seem to be able to
> > modify capacity.
>
> You can't do it from usb-storage.  You need to do it in sd.c, which is
> where the sector count is kept.  In slave_configure, usb-storage does set
> some flags to tell sd.c to reduce the sector count by 1 -- look for
> references to fix_capacity or guess_capacity flags.
>
> You would have to implement a flag to reduce capacity by half in sd.c, then
> set that flag in slave_configure in response to a new flag.

Thanks. This patch seems to fix it.



Sony Ericsson V800-Vodafone 802SE phone (0fce:d008) does not work with
usb-storage. It's detected properly, kernel reads partition table but the
device never appears in /dev. The kernel then resets the device each 30
seconds infinitely. This is because it reports the capacity incorrectly,
double of the real size. Accessing the second non-existing half causes
the device not to respond anymore, resulting in timeout and reset.

Add SCSI disk and mass storage code to work-around this "doubled capacity"
breakage.

Signed-off-by: Ondrej Zary <linux@xxxxxxxxxxxxxxxxxxxx>

--- linux-source-2.6.32-orig/drivers/scsi/sd.c	2009-12-03 04:51:21.000000000 +0100
+++ linux-source-2.6.32/drivers/scsi/sd.c	2010-04-09 19:56:05.000000000 +0200
@@ -1555,6 +1555,12 @@ sd_read_capacity(struct scsi_disk *sdkp,
 				(unsigned long long) sdkp->capacity);
 		--sdkp->capacity;
 	}
+	if (sdp->doubled_capacity) {
+		sd_printk(KERN_INFO, sdkp, "Adjusting the sector count "
+				"from its reported value: %llu\n",
+				(unsigned long long) sdkp->capacity);
+		sdkp->capacity /= 2;
+	}
 
 got_data:
 	if (sector_size == 0) {
--- linux-source-2.6.32-orig/drivers/usb/storage/scsiglue.c	2009-12-03 04:51:21.000000000 +0100
+++ linux-source-2.6.32/drivers/usb/storage/scsiglue.c	2010-04-09 19:27:33.000000000 +0200
@@ -209,6 +209,10 @@ static int slave_configure(struct scsi_d
 		if (us->fflags & US_FL_CAPACITY_HEURISTICS)
 			sdev->guess_capacity = 1;
 
+		/* Some devices return the capacity doubled */
+		if (us->fflags & US_FL_DOUBLED_CAPACITY)
+			sdev->doubled_capacity = 1;
+
 		/* assume SPC3 or latter devices support sense size > 18 */
 		if (sdev->scsi_level > SCSI_SPC_2)
 			us->fflags |= US_FL_SANE_SENSE;
--- linux-source-2.6.32-orig/drivers/usb/storage/unusual_devs.h	2010-01-10 06:18:08.000000000 +0100
+++ linux-source-2.6.32/drivers/usb/storage/unusual_devs.h	2010-04-09 20:02:54.000000000 +0200
@@ -1310,12 +1310,15 @@ UNUSUAL_DEV(  0x0fca, 0x0006, 0x0001, 0x
 		US_FL_IGNORE_DEVICE ),
 #endif
 
-/* Reported by Michael Stattmann <michael@xxxxxxxxxxxxx> */
+/* Reported by Michael Stattmann <michael@xxxxxxxxxxxxx> 
+ * and Ondrej Zary <linux@xxxxxxxxxxxxxxxxxxxx> 
+ * Device reports double of the real capacity and breaks when the
+ * non-existing second half is accessed. */
 UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"V800-Vodafone 802",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_NO_WP_DETECT ),
+		US_FL_NO_WP_DETECT | US_FL_DOUBLED_CAPACITY ),
 
 /* Reported by The Solutor <thesolutor@xxxxxxxxx> */
 UNUSUAL_DEV(  0x0fce, 0xd0e1, 0x0000, 0x0000,
--- linux-source-2.6.32-orig/include/linux/usb_usual.h	2010-01-10 06:18:09.000000000 +0100
+++ linux-source-2.6.32/include/linux/usb_usual.h	2010-04-09 19:29:48.000000000 +0200
@@ -58,7 +58,9 @@
 	US_FLAG(CAPACITY_OK,	0x00010000)			\
 		/* READ CAPACITY response is correct */		\
 	US_FLAG(BAD_SENSE,	0x00020000)			\
-		/* Bad Sense (never more than 18 bytes) */
+		/* Bad Sense (never more than 18 bytes) */	\
+	US_FLAG(DOUBLED_CAPACITY,	0x00040000)		\
+		/* READ CAPACITY response is doubled */
 
 #define US_FLAG(name, value)	US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
--- linux-source-2.6.32-orig/include/scsi/scsi_device.h	2009-12-03 04:51:21.000000000 +0100
+++ linux-source-2.6.32/include/scsi/scsi_device.h	2010-04-09 19:25:44.000000000 +0200
@@ -142,6 +142,7 @@ struct scsi_device {
 	unsigned select_no_atn:1;
 	unsigned fix_capacity:1;	/* READ_CAPACITY is too high by 1 */
 	unsigned guess_capacity:1;	/* READ_CAPACITY might be too high by 1 */
+	unsigned doubled_capacity:1;	/* READ_CAPACITY is double the real size */
 	unsigned retry_hwerror:1;	/* Retry HARDWARE_ERROR */
 	unsigned last_sector_bug:1;	/* do not use multisector accesses on
 					   SD_LAST_BUGGY_SECTORS */



-- 
Ondrej Zary
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux