Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 127227
b: refs/heads/master
c: d4f373e
h: refs/heads/master
i:
  127225: 75ad6cf
  127223: fd2fe77
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Jan 7, 2009
1 parent 1caebc3 commit 46a2035
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 74c71ebd8d7c7a513022851a02bb52b9fa7e0dcb
refs/heads/master: d4f373e57d3916814110968c5ea1155a8d972b5a
29 changes: 29 additions & 0 deletions trunk/Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ parameter is applicable:
SUSPEND System suspend states are enabled.
FTRACE Function tracing enabled.
TS Appropriate touchscreen support is enabled.
UMS USB Mass Storage support is enabled.
USB USB support is enabled.
USBHID USB Human Interface Device support is enabled.
V4L Video For Linux support is enabled.
Expand Down Expand Up @@ -2383,6 +2384,34 @@ and is between 256 and 4096 characters. It is defined in the file
usbhid.mousepoll=
[USBHID] The interval which mice are to be polled at.

usb-storage.delay_use=
[UMS] The delay in seconds before a new device is
scanned for Logical Units (default 5).

usb-storage.quirks=
[UMS] A list of quirks entries to supplement or
override the built-in unusual_devs list. List
entries are separated by commas. Each entry has
the form VID:PID:Flags where VID and PID are Vendor
and Product ID values (4-digit hex numbers) and
Flags is a set of characters, each corresponding
to a common usb-storage quirk flag as follows:
c = FIX_CAPACITY (decrease the reported
device capacity by one sector);
i = IGNORE_DEVICE (don't bind to this
device);
l = NOT_LOCKABLE (don't try to lock and
unlock ejectable media);
m = MAX_SECTORS_64 (don't transfer more
than 64 sectors = 32 KB at a time);
r = IGNORE_RESIDUE (the device reports
bogus residue values);
s = SINGLE_LUN (the device has only one
Logical Unit);
w = NO_WP_DETECT (don't test whether the
medium is write-protected).
Example: quirks=0419:aaf5:rl,0421:0433:rc

add_efi_memmap [EFI; x86-32,X86-64] Include EFI memory map in
kernel's map of available physical RAM.

Expand Down
113 changes: 113 additions & 0 deletions trunk/drivers/usb/storage/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ static unsigned int delay_use = 5;
module_param(delay_use, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");

static char *quirks;
module_param(quirks, charp, S_IRUGO);
MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");

struct quirks_entry {
u16 vid, pid;
u32 fflags;
};
static struct quirks_entry *quirks_list, *quirks_end;


/*
* The entries in this table correspond, line for line,
Expand Down Expand Up @@ -473,6 +483,30 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
return 0;
}

/* Adjust device flags based on the "quirks=" module parameter */
static void adjust_quirks(struct us_data *us)
{
u16 vid, pid;
struct quirks_entry *q;
unsigned int mask = (US_FL_FIX_CAPACITY | US_FL_IGNORE_DEVICE |
US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
US_FL_IGNORE_RESIDUE | US_FL_SINGLE_LUN |
US_FL_NO_WP_DETECT);

vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);

for (q = quirks_list; q != quirks_end; ++q) {
if (q->vid == vid && q->pid == pid) {
us->fflags = (us->fflags & ~mask) | q->fflags;
dev_info(&us->pusb_intf->dev, "Quirks match for "
"vid %04x pid %04x: %x\n",
vid, pid, q->fflags);
break;
}
}
}

/* Find an unusual_dev descriptor (always succeeds in the current code) */
static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
{
Expand All @@ -497,6 +531,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
idesc->bInterfaceProtocol :
unusual_dev->useTransport;
us->fflags = USB_US_ORIG_FLAGS(id->driver_info);
adjust_quirks(us);

if (us->fflags & US_FL_IGNORE_DEVICE) {
printk(KERN_INFO USB_STORAGE "device ignored\n");
Expand Down Expand Up @@ -1061,10 +1096,88 @@ static struct usb_driver usb_storage_driver = {
.soft_unbind = 1,
};

/* Works only for digits and letters, but small and fast */
#define TOLOWER(x) ((x) | 0x20)

static void __init parse_quirks(void)
{
int n, i;
char *p;

if (!quirks)
return;

/* Count the ':' characters to get 2 * the number of entries */
n = 0;
for (p = quirks; *p; ++p) {
if (*p == ':')
++n;
}
n /= 2;
if (n == 0)
return; /* Don't allocate 0 bytes */

quirks_list = kmalloc(n * sizeof(*quirks_list), GFP_KERNEL);
if (!quirks_list)
return;

p = quirks;
quirks_end = quirks_list;
for (i = 0; i < n && *p; ++i) {
unsigned f = 0;

/* Each entry consists of VID:PID:flags */
quirks_end->vid = simple_strtoul(p, &p, 16);
if (*p != ':')
goto skip_to_next;
quirks_end->pid = simple_strtoul(p+1, &p, 16);
if (*p != ':')
goto skip_to_next;

while (*++p && *p != ',') {
switch (TOLOWER(*p)) {
case 'c':
f |= US_FL_FIX_CAPACITY;
break;
case 'i':
f |= US_FL_IGNORE_DEVICE;
break;
case 'l':
f |= US_FL_NOT_LOCKABLE;
break;
case 'm':
f |= US_FL_MAX_SECTORS_64;
break;
case 'r':
f |= US_FL_IGNORE_RESIDUE;
break;
case 's':
f |= US_FL_SINGLE_LUN;
break;
case 'w':
f |= US_FL_NO_WP_DETECT;
break;
/* Ignore unrecognized flag characters */
}
}
quirks_end->fflags = f;
++quirks_end;

skip_to_next:
/* Entries are separated by commas */
while (*p) {
if (*p++ == ',')
break;
}
} /* for (i = 0; ...) */
}

static int __init usb_stor_init(void)
{
int retval;

printk(KERN_INFO "Initializing USB Mass Storage driver...\n");
parse_quirks();

/* register the driver, return usb_register return code if error */
retval = usb_register(&usb_storage_driver);
Expand Down

0 comments on commit 46a2035

Please sign in to comment.