From 95713fb8aa039e9cd89ff545b62bd2a860c36e39 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 12 Mar 2018 16:30:40 +0100 Subject: [PATCH] Revert "usb: core: Add "quirks" parameter for usbcore" This reverts commit b27560e4d9e5240b5544c9c5650c7442e482646e as it breaks the build for some arches :( Reported-by: kbuild test robot Cc: Kai-Heng Feng Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 1d1d53f85ddd..70a7398c20e2 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 f4a548471f0f..42faaeead81b 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -11,6 +11,143 @@ #include #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 2f5fbc56a9dd..0adb6345ff2e 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 149cc7480971..546a2219454b 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, --- Documentation/admin-guide/kernel-parameters.txt | 55 -------- drivers/usb/core/quirks.c | 177 +----------------------- drivers/usb/core/usb.c | 1 - drivers/usb/core/usb.h | 1 - 4 files changed, 5 insertions(+), 229 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 70a7398c20e2..1d1d53f85ddd 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4368,61 +4368,6 @@ 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 42faaeead81b..f4a548471f0f 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -11,143 +11,6 @@ #include #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 @@ -457,8 +320,8 @@ static int usb_amd_resume_quirk(struct usb_device *udev) return 0; } -static u32 usb_detect_static_quirks(struct usb_device *udev, - const struct usb_device_id *id) +static u32 __usb_detect_quirks(struct usb_device *udev, + const struct usb_device_id *id) { u32 quirks = 0; @@ -476,43 +339,21 @@ static u32 usb_detect_static_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_static_quirks(udev, usb_quirk_list); + udev->quirks = __usb_detect_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_static_quirks(udev, + udev->quirks |= __usb_detect_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); @@ -531,7 +372,7 @@ void usb_detect_interface_quirks(struct usb_device *udev) { u32 quirks; - quirks = usb_detect_static_quirks(udev, usb_interface_quirk_list); + quirks = __usb_detect_quirks(udev, usb_interface_quirk_list); if (quirks == 0) return; @@ -539,11 +380,3 @@ 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 0adb6345ff2e..2f5fbc56a9dd 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1259,7 +1259,6 @@ 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 546a2219454b..149cc7480971 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -36,7 +36,6 @@ 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, -- 2.11.0