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