Skip to content

Commit 95713fb

Browse files
committed
Revert "usb: core: Add "quirks" parameter for usbcore"
This reverts commit b27560e as it breaks the build for some arches :( Reported-by: kbuild test robot <[email protected]> Cc: Kai-Heng Feng <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 1d1d53f..70a7398 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4368,6 +4368,61 @@ usbcore.nousb [USB] Disable the USB subsystem + usbcore.quirks= + [USB] A list of quirks entries to supplement or + override the built-in usb core quirk 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 core quirk flag as follows: + a = USB_QUIRK_STRING_FETCH_255 (string + descriptors must not be fetched using + a 255-byte read); + b = USB_QUIRK_RESET_RESUME (device can't resume + correctly so reset it instead); + c = USB_QUIRK_NO_SET_INTF (device can't handle + Set-Interface requests); + d = USB_QUIRK_CONFIG_INTF_STRINGS (device can't + handle its Configuration or Interface + strings); + e = USB_QUIRK_RESET (device can't be reset + (e.g morph devices), don't use reset); + f = USB_QUIRK_HONOR_BNUMINTERFACES (device has + more interface descriptions than the + bNumInterfaces count, and can't handle + talking to these interfaces); + g = USB_QUIRK_DELAY_INIT (device needs a pause + during initialization, after we read + the device descriptor); + h = USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL (For + high speed and super speed interrupt + endpoints, the USB 2.0 and USB 3.0 spec + require the interval in microframes (1 + microframe = 125 microseconds) to be + calculated as interval = 2 ^ + (bInterval-1). + Devices with this quirk report their + bInterval as the result of this + calculation instead of the exponent + variable used in the calculation); + i = USB_QUIRK_DEVICE_QUALIFIER (device can't + handle device_qualifier descriptor + requests); + j = USB_QUIRK_IGNORE_REMOTE_WAKEUP (device + generates spurious wakeup, ignore + remote wakeup capability); + k = USB_QUIRK_NO_LPM (device can't handle Link + Power Management); + l = USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL + (Device reports its bInterval as linear + frames instead of the USB 2.0 + calculation); + m = USB_QUIRK_DISCONNECT_SUSPEND (Device needs + to be disconnected before suspend to + prevent spurious wakeup) + Example: quirks=0781:5580:bk,0a5c:5834:gij + usbhid.mousepoll= [USBHID] The interval which mice are to be polled at. diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f4a5484..42faaee 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -11,6 +11,143 @@ #include <linux/usb/hcd.h> #include "usb.h" +struct quirk_entry { + u16 vid; + u16 pid; + u32 flags; +}; + +static DEFINE_MUTEX(quirk_mutex); + +static struct quirk_entry *quirk_list; +static unsigned int quirk_count; + +static char quirks_param[128]; + +static int quirks_param_set(const char *val, const struct kernel_param *kp) +{ + char *p, *field; + u16 vid, pid; + u32 flags; + size_t i; + + mutex_lock(&quirk_mutex); + + if (!val || !*val) { + quirk_count = 0; + kfree(quirk_list); + quirk_list = NULL; + goto unlock; + } + + for (quirk_count = 1, i = 0; val[i]; i++) + if (val[i] == ',') + quirk_count++; + + if (quirk_list) { + kfree(quirk_list); + quirk_list = NULL; + } + + quirk_list = kcalloc(quirk_count, sizeof(struct quirk_entry), + GFP_KERNEL); + if (!quirk_list) { + mutex_unlock(&quirk_mutex); + return -ENOMEM; + } + + for (i = 0, p = (char *)val; p && *p;) { + /* Each entry consists of VID:PID:flags */ + field = strsep(&p, ":"); + if (!field) + break; + + if (kstrtou16(field, 16, &vid)) + break; + + field = strsep(&p, ":"); + if (!field) + break; + + if (kstrtou16(field, 16, &pid)) + break; + + field = strsep(&p, ","); + if (!field || !*field) + break; + + /* Collect the flags */ + for (flags = 0; *field; field++) { + switch (*field) { + case 'a': + flags |= USB_QUIRK_STRING_FETCH_255; + break; + case 'b': + flags |= USB_QUIRK_RESET_RESUME; + break; + case 'c': + flags |= USB_QUIRK_NO_SET_INTF; + break; + case 'd': + flags |= USB_QUIRK_CONFIG_INTF_STRINGS; + break; + case 'e': + flags |= USB_QUIRK_RESET; + break; + case 'f': + flags |= USB_QUIRK_HONOR_BNUMINTERFACES; + break; + case 'g': + flags |= USB_QUIRK_DELAY_INIT; + break; + case 'h': + flags |= USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL; + break; + case 'i': + flags |= USB_QUIRK_DEVICE_QUALIFIER; + break; + case 'j': + flags |= USB_QUIRK_IGNORE_REMOTE_WAKEUP; + break; + case 'k': + flags |= USB_QUIRK_NO_LPM; + break; + case 'l': + flags |= USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL; + break; + case 'm': + flags |= USB_QUIRK_DISCONNECT_SUSPEND; + break; + /* Ignore unrecognized flag characters */ + } + } + + quirk_list[i++] = (struct quirk_entry) + { .vid = vid, .pid = pid, .flags = flags }; + } + + if (i < quirk_count) + quirk_count = i; + +unlock: + mutex_unlock(&quirk_mutex); + + return param_set_copystring(val, kp); +} + +static const struct kernel_param_ops quirks_param_ops = { + .set = quirks_param_set, + .get = param_get_string, +}; + +static struct kparam_string quirks_param_string = { + .maxlen = sizeof(quirks_param), + .string = quirks_param, +}; + +module_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0644); +MODULE_PARM_DESC(quirks, "Add/modify USB quirks by specifying quirks=vendorID:productID:quirks"); + /* Lists of quirky USB devices, split in device quirks and interface quirks. * Device quirks are applied at the very beginning of the enumeration process, * right after reading the device descriptor. They can thus only match on device @@ -320,8 +457,8 @@ static int usb_amd_resume_quirk(struct usb_device *udev) return 0; } -static u32 __usb_detect_quirks(struct usb_device *udev, - const struct usb_device_id *id) +static u32 usb_detect_static_quirks(struct usb_device *udev, + const struct usb_device_id *id) { u32 quirks = 0; @@ -339,21 +476,43 @@ static u32 __usb_detect_quirks(struct usb_device *udev, return quirks; } +static u32 usb_detect_dynamic_quirks(struct usb_device *udev) +{ + u16 vid = le16_to_cpu(udev->descriptor.idVendor); + u16 pid = le16_to_cpu(udev->descriptor.idProduct); + int i, flags = 0; + + mutex_lock(&quirk_mutex); + + for (i = 0; i < quirk_count; i++) { + if (vid == quirk_list[i].vid && pid == quirk_list[i].pid) { + flags = quirk_list[i].flags; + break; + } + } + + mutex_unlock(&quirk_mutex); + + return flags; +} + /* * Detect any quirks the device has, and do any housekeeping for it if needed. */ void usb_detect_quirks(struct usb_device *udev) { - udev->quirks = __usb_detect_quirks(udev, usb_quirk_list); + udev->quirks = usb_detect_static_quirks(udev, usb_quirk_list); /* * Pixart-based mice would trigger remote wakeup issue on AMD * Yangtze chipset, so set them as RESET_RESUME flag. */ if (usb_amd_resume_quirk(udev)) - udev->quirks |= __usb_detect_quirks(udev, + udev->quirks |= usb_detect_static_quirks(udev, usb_amd_resume_quirk_list); + udev->quirks ^= usb_detect_dynamic_quirks(udev); + if (udev->quirks) dev_dbg(&udev->dev, "USB quirks for this device: %x\n", udev->quirks); @@ -372,7 +531,7 @@ void usb_detect_interface_quirks(struct usb_device *udev) { u32 quirks; - quirks = __usb_detect_quirks(udev, usb_interface_quirk_list); + quirks = usb_detect_static_quirks(udev, usb_interface_quirk_list); if (quirks == 0) return; @@ -380,3 +539,11 @@ void usb_detect_interface_quirks(struct usb_device *udev) quirks); udev->quirks |= quirks; } + +void usb_release_quirk_list(void) +{ + mutex_lock(&quirk_mutex); + kfree(quirk_list); + quirk_list = NULL; + mutex_unlock(&quirk_mutex); +} diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 2f5fbc5..0adb634 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1259,6 +1259,7 @@ static void __exit usb_exit(void) if (usb_disabled()) return; + usb_release_quirk_list(); usb_deregister_device_driver(&usb_generic_driver); usb_major_cleanup(); usb_deregister(&usbfs_driver); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 149cc74..546a221 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -36,6 +36,7 @@ extern void usb_deauthorize_interface(struct usb_interface *); extern void usb_authorize_interface(struct usb_interface *); extern void usb_detect_quirks(struct usb_device *udev); extern void usb_detect_interface_quirks(struct usb_device *udev); +extern void usb_release_quirk_list(void); extern int usb_remove_device(struct usb_device *udev); extern int usb_get_device_descriptor(struct usb_device *dev,
1 parent 7d287a5 commit 95713fb

File tree

4 files changed

+5
-229
lines changed

4 files changed

+5
-229
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4368,61 +4368,6 @@
43684368

43694369
usbcore.nousb [USB] Disable the USB subsystem
43704370

4371-
usbcore.quirks=
4372-
[USB] A list of quirks entries to supplement or
4373-
override the built-in usb core quirk list. List
4374-
entries are separated by commas. Each entry has
4375-
the form VID:PID:Flags where VID and PID are Vendor
4376-
and Product ID values (4-digit hex numbers) and
4377-
Flags is a set of characters, each corresponding
4378-
to a common usb core quirk flag as follows:
4379-
a = USB_QUIRK_STRING_FETCH_255 (string
4380-
descriptors must not be fetched using
4381-
a 255-byte read);
4382-
b = USB_QUIRK_RESET_RESUME (device can't resume
4383-
correctly so reset it instead);
4384-
c = USB_QUIRK_NO_SET_INTF (device can't handle
4385-
Set-Interface requests);
4386-
d = USB_QUIRK_CONFIG_INTF_STRINGS (device can't
4387-
handle its Configuration or Interface
4388-
strings);
4389-
e = USB_QUIRK_RESET (device can't be reset
4390-
(e.g morph devices), don't use reset);
4391-
f = USB_QUIRK_HONOR_BNUMINTERFACES (device has
4392-
more interface descriptions than the
4393-
bNumInterfaces count, and can't handle
4394-
talking to these interfaces);
4395-
g = USB_QUIRK_DELAY_INIT (device needs a pause
4396-
during initialization, after we read
4397-
the device descriptor);
4398-
h = USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL (For
4399-
high speed and super speed interrupt
4400-
endpoints, the USB 2.0 and USB 3.0 spec
4401-
require the interval in microframes (1
4402-
microframe = 125 microseconds) to be
4403-
calculated as interval = 2 ^
4404-
(bInterval-1).
4405-
Devices with this quirk report their
4406-
bInterval as the result of this
4407-
calculation instead of the exponent
4408-
variable used in the calculation);
4409-
i = USB_QUIRK_DEVICE_QUALIFIER (device can't
4410-
handle device_qualifier descriptor
4411-
requests);
4412-
j = USB_QUIRK_IGNORE_REMOTE_WAKEUP (device
4413-
generates spurious wakeup, ignore
4414-
remote wakeup capability);
4415-
k = USB_QUIRK_NO_LPM (device can't handle Link
4416-
Power Management);
4417-
l = USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL
4418-
(Device reports its bInterval as linear
4419-
frames instead of the USB 2.0
4420-
calculation);
4421-
m = USB_QUIRK_DISCONNECT_SUSPEND (Device needs
4422-
to be disconnected before suspend to
4423-
prevent spurious wakeup)
4424-
Example: quirks=0781:5580:bk,0a5c:5834:gij
4425-
44264371
usbhid.mousepoll=
44274372
[USBHID] The interval which mice are to be polled at.
44284373

drivers/usb/core/quirks.c

Lines changed: 5 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -11,143 +11,6 @@
1111
#include <linux/usb/hcd.h>
1212
#include "usb.h"
1313

14-
struct quirk_entry {
15-
u16 vid;
16-
u16 pid;
17-
u32 flags;
18-
};
19-
20-
static DEFINE_MUTEX(quirk_mutex);
21-
22-
static struct quirk_entry *quirk_list;
23-
static unsigned int quirk_count;
24-
25-
static char quirks_param[128];
26-
27-
static int quirks_param_set(const char *val, const struct kernel_param *kp)
28-
{
29-
char *p, *field;
30-
u16 vid, pid;
31-
u32 flags;
32-
size_t i;
33-
34-
mutex_lock(&quirk_mutex);
35-
36-
if (!val || !*val) {
37-
quirk_count = 0;
38-
kfree(quirk_list);
39-
quirk_list = NULL;
40-
goto unlock;
41-
}
42-
43-
for (quirk_count = 1, i = 0; val[i]; i++)
44-
if (val[i] == ',')
45-
quirk_count++;
46-
47-
if (quirk_list) {
48-
kfree(quirk_list);
49-
quirk_list = NULL;
50-
}
51-
52-
quirk_list = kcalloc(quirk_count, sizeof(struct quirk_entry),
53-
GFP_KERNEL);
54-
if (!quirk_list) {
55-
mutex_unlock(&quirk_mutex);
56-
return -ENOMEM;
57-
}
58-
59-
for (i = 0, p = (char *)val; p && *p;) {
60-
/* Each entry consists of VID:PID:flags */
61-
field = strsep(&p, ":");
62-
if (!field)
63-
break;
64-
65-
if (kstrtou16(field, 16, &vid))
66-
break;
67-
68-
field = strsep(&p, ":");
69-
if (!field)
70-
break;
71-
72-
if (kstrtou16(field, 16, &pid))
73-
break;
74-
75-
field = strsep(&p, ",");
76-
if (!field || !*field)
77-
break;
78-
79-
/* Collect the flags */
80-
for (flags = 0; *field; field++) {
81-
switch (*field) {
82-
case 'a':
83-
flags |= USB_QUIRK_STRING_FETCH_255;
84-
break;
85-
case 'b':
86-
flags |= USB_QUIRK_RESET_RESUME;
87-
break;
88-
case 'c':
89-
flags |= USB_QUIRK_NO_SET_INTF;
90-
break;
91-
case 'd':
92-
flags |= USB_QUIRK_CONFIG_INTF_STRINGS;
93-
break;
94-
case 'e':
95-
flags |= USB_QUIRK_RESET;
96-
break;
97-
case 'f':
98-
flags |= USB_QUIRK_HONOR_BNUMINTERFACES;
99-
break;
100-
case 'g':
101-
flags |= USB_QUIRK_DELAY_INIT;
102-
break;
103-
case 'h':
104-
flags |= USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL;
105-
break;
106-
case 'i':
107-
flags |= USB_QUIRK_DEVICE_QUALIFIER;
108-
break;
109-
case 'j':
110-
flags |= USB_QUIRK_IGNORE_REMOTE_WAKEUP;
111-
break;
112-
case 'k':
113-
flags |= USB_QUIRK_NO_LPM;
114-
break;
115-
case 'l':
116-
flags |= USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL;
117-
break;
118-
case 'm':
119-
flags |= USB_QUIRK_DISCONNECT_SUSPEND;
120-
break;
121-
/* Ignore unrecognized flag characters */
122-
}
123-
}
124-
125-
quirk_list[i++] = (struct quirk_entry)
126-
{ .vid = vid, .pid = pid, .flags = flags };
127-
}
128-
129-
if (i < quirk_count)
130-
quirk_count = i;
131-
132-
unlock:
133-
mutex_unlock(&quirk_mutex);
134-
135-
return param_set_copystring(val, kp);
136-
}
137-
138-
static const struct kernel_param_ops quirks_param_ops = {
139-
.set = quirks_param_set,
140-
.get = param_get_string,
141-
};
142-
143-
static struct kparam_string quirks_param_string = {
144-
.maxlen = sizeof(quirks_param),
145-
.string = quirks_param,
146-
};
147-
148-
module_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0644);
149-
MODULE_PARM_DESC(quirks, "Add/modify USB quirks by specifying quirks=vendorID:productID:quirks");
150-
15114
/* Lists of quirky USB devices, split in device quirks and interface quirks.
15215
* Device quirks are applied at the very beginning of the enumeration process,
15316
* right after reading the device descriptor. They can thus only match on device
@@ -457,8 +320,8 @@ static int usb_amd_resume_quirk(struct usb_device *udev)
457320
return 0;
458321
}
459322

460-
static u32 usb_detect_static_quirks(struct usb_device *udev,
461-
const struct usb_device_id *id)
323+
static u32 __usb_detect_quirks(struct usb_device *udev,
324+
const struct usb_device_id *id)
462325
{
463326
u32 quirks = 0;
464327

@@ -476,43 +339,21 @@ static u32 usb_detect_static_quirks(struct usb_device *udev,
476339
return quirks;
477340
}
478341

479-
static u32 usb_detect_dynamic_quirks(struct usb_device *udev)
480-
{
481-
u16 vid = le16_to_cpu(udev->descriptor.idVendor);
482-
u16 pid = le16_to_cpu(udev->descriptor.idProduct);
483-
int i, flags = 0;
484-
485-
mutex_lock(&quirk_mutex);
486-
487-
for (i = 0; i < quirk_count; i++) {
488-
if (vid == quirk_list[i].vid && pid == quirk_list[i].pid) {
489-
flags = quirk_list[i].flags;
490-
break;
491-
}
492-
}
493-
494-
mutex_unlock(&quirk_mutex);
495-
496-
return flags;
497-
}
498-
499342
/*
500343
* Detect any quirks the device has, and do any housekeeping for it if needed.
501344
*/
502345
void usb_detect_quirks(struct usb_device *udev)
503346
{
504-
udev->quirks = usb_detect_static_quirks(udev, usb_quirk_list);
347+
udev->quirks = __usb_detect_quirks(udev, usb_quirk_list);
505348

506349
/*
507350
* Pixart-based mice would trigger remote wakeup issue on AMD
508351
* Yangtze chipset, so set them as RESET_RESUME flag.
509352
*/
510353
if (usb_amd_resume_quirk(udev))
511-
udev->quirks |= usb_detect_static_quirks(udev,
354+
udev->quirks |= __usb_detect_quirks(udev,
512355
usb_amd_resume_quirk_list);
513356

514-
udev->quirks ^= usb_detect_dynamic_quirks(udev);
515-
516357
if (udev->quirks)
517358
dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
518359
udev->quirks);
@@ -531,19 +372,11 @@ void usb_detect_interface_quirks(struct usb_device *udev)
531372
{
532373
u32 quirks;
533374

534-
quirks = usb_detect_static_quirks(udev, usb_interface_quirk_list);
375+
quirks = __usb_detect_quirks(udev, usb_interface_quirk_list);
535376
if (quirks == 0)
536377
return;
537378

538379
dev_dbg(&udev->dev, "USB interface quirks for this device: %x\n",
539380
quirks);
540381
udev->quirks |= quirks;
541382
}
542-
543-
void usb_release_quirk_list(void)
544-
{
545-
mutex_lock(&quirk_mutex);
546-
kfree(quirk_list);
547-
quirk_list = NULL;
548-
mutex_unlock(&quirk_mutex);
549-
}

drivers/usb/core/usb.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1259,7 +1259,6 @@ static void __exit usb_exit(void)
12591259
if (usb_disabled())
12601260
return;
12611261

1262-
usb_release_quirk_list();
12631262
usb_deregister_device_driver(&usb_generic_driver);
12641263
usb_major_cleanup();
12651264
usb_deregister(&usbfs_driver);

drivers/usb/core/usb.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ extern void usb_deauthorize_interface(struct usb_interface *);
3636
extern void usb_authorize_interface(struct usb_interface *);
3737
extern void usb_detect_quirks(struct usb_device *udev);
3838
extern void usb_detect_interface_quirks(struct usb_device *udev);
39-
extern void usb_release_quirk_list(void);
4039
extern int usb_remove_device(struct usb_device *udev);
4140

4241
extern int usb_get_device_descriptor(struct usb_device *dev,

0 commit comments

Comments
 (0)