Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi/sd: add a no_read_capacity_16 scsi_device flag

I seem to have a knack for digging up buggy usb devices which don't work
with Linux, and I'm crazy enough to try to make them work. So this time a
friend of mine asked me to get an mp4 player (an mp3 player which can play
videos on a small screen) to work with Linux.

It is based on the well known rockbox chipset for which we already have an
unusual devs entries to work around some of its bugs. But this model
comes with an additional twist.

This model chokes on read_capacity_16 calls. Now normally we don't make
those calls, but this model comes with an sdcard slot and when there is no
card in there (and shipped from the factory there is none), it reports a
size of 0. However this time the programmers actually got the
read_capacity_10 response right! So they substract one from the size as
stored internally in the mp3 player before reporting it back, resulting in
an answer of ... 0xffffffff sectors, causing sd.c to try a
read_capacity_16, on which the device crashes.

This patch adds a flag to scsi_device to indicate that a a device cannot
handle read_capacity_16, and when this flag is set if a device reports an
lba of 0xffffffff as answer to a read_capacity_10, assumes it tries to
report a size of 0.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Hans de Goede and committed by
Greg Kroah-Hartman
5ce524bd ae38c78a

+13
+12
drivers/scsi/sd.c
··· 1498 1498 unsigned long long lba; 1499 1499 unsigned sector_size; 1500 1500 1501 + if (sdp->no_read_capacity_16) 1502 + return -EINVAL; 1503 + 1501 1504 do { 1502 1505 memset(cmd, 0, 16); 1503 1506 cmd[0] = SERVICE_ACTION_IN; ··· 1628 1625 1629 1626 sector_size = get_unaligned_be32(&buffer[4]); 1630 1627 lba = get_unaligned_be32(&buffer[0]); 1628 + 1629 + if (sdp->no_read_capacity_16 && (lba == 0xffffffff)) { 1630 + /* Some buggy (usb cardreader) devices return an lba of 1631 + 0xffffffff when the want to report a size of 0 (with 1632 + which they really mean no media is present) */ 1633 + sdkp->capacity = 0; 1634 + sdkp->hw_sector_size = sector_size; 1635 + return sector_size; 1636 + } 1631 1637 1632 1638 if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) { 1633 1639 sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
+1
include/scsi/scsi_device.h
··· 149 149 unsigned last_sector_bug:1; /* do not use multisector accesses on 150 150 SD_LAST_BUGGY_SECTORS */ 151 151 unsigned no_read_disc_info:1; /* Avoid READ_DISC_INFO cmds */ 152 + unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */ 152 153 unsigned is_visible:1; /* is the device visible in sysfs */ 153 154 154 155 DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */