From 3e8f83808ce6eb7554fa8637a95cc24fdc083903 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 9 Apr 2014 16:19:54 -0700 Subject: [PATCH] 3.4-stable patches added patches: usb-add-device-quirk-for-microsoft-vx700-webcam.patch usb-add-quirk-detection-based-on-interface-information.patch usb-add-usb_quirk_reset_resume-for-all-logitech-uvc-webcams.patch usb-ehci-bugfix-urb-hcpriv-should-not-be-null.patch --- queue-3.4/series | 4 + ...ice-quirk-for-microsoft-vx700-webcam.patch | 34 +++ ...ction-based-on-interface-information.patch | 256 ++++++++++++++++++ ..._resume-for-all-logitech-uvc-webcams.patch | 104 +++++++ ...bugfix-urb-hcpriv-should-not-be-null.patch | 86 ++++++ 5 files changed, 484 insertions(+) create mode 100644 queue-3.4/usb-add-device-quirk-for-microsoft-vx700-webcam.patch create mode 100644 queue-3.4/usb-add-quirk-detection-based-on-interface-information.patch create mode 100644 queue-3.4/usb-add-usb_quirk_reset_resume-for-all-logitech-uvc-webcams.patch create mode 100644 queue-3.4/usb-ehci-bugfix-urb-hcpriv-should-not-be-null.patch diff --git a/queue-3.4/series b/queue-3.4/series index e2f84181fd9..475e6627d4d 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -43,3 +43,7 @@ ath9k_htc-fix-signal-strength-handling-issues.patch ath9k_hw-fix-chain-swap-setting-when-setting-rx-chainmask-to-5.patch ath9k_hw-fix-rx-gain-initvals-for-ar9485.patch ath9k_hw-enable-hw-pll-power-save-for-ar9462.patch +usb-ehci-bugfix-urb-hcpriv-should-not-be-null.patch +usb-add-device-quirk-for-microsoft-vx700-webcam.patch +usb-add-quirk-detection-based-on-interface-information.patch +usb-add-usb_quirk_reset_resume-for-all-logitech-uvc-webcams.patch diff --git a/queue-3.4/usb-add-device-quirk-for-microsoft-vx700-webcam.patch b/queue-3.4/usb-add-device-quirk-for-microsoft-vx700-webcam.patch new file mode 100644 index 00000000000..2889183dcb3 --- /dev/null +++ b/queue-3.4/usb-add-device-quirk-for-microsoft-vx700-webcam.patch @@ -0,0 +1,34 @@ +From 3e4ba2bf729b851695f01b514e1605dc0cffd5c8 Mon Sep 17 00:00:00 2001 +From: Andreas Fleig +Date: Wed, 5 Dec 2012 16:17:49 +0100 +Subject: USB: Add device quirk for Microsoft VX700 webcam + +From: Andreas Fleig + +commit bc009eca8d539162f7271c2daf0ab5e9e3bb90a0 upstream. + +Add device quirk for Microsoft Lifecam VX700 v2.0 webcams. +Fixes squeaking noise of the microphone. + +Signed-off-by: Andreas Fleig +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/quirks.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -38,6 +38,9 @@ static const struct usb_device_id usb_qu + /* Creative SB Audigy 2 NX */ + { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Microsoft LifeCam-VX700 v2.0 */ ++ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Logitech Webcam C200 */ + { USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME }, + diff --git a/queue-3.4/usb-add-quirk-detection-based-on-interface-information.patch b/queue-3.4/usb-add-quirk-detection-based-on-interface-information.patch new file mode 100644 index 00000000000..867fb33fdf9 --- /dev/null +++ b/queue-3.4/usb-add-quirk-detection-based-on-interface-information.patch @@ -0,0 +1,256 @@ +From f94c6107b49ac52f2e0f9929aeffeceb5ed97704 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Thu, 19 Jul 2012 12:39:13 +0200 +Subject: usb: Add quirk detection based on interface information + +From: Laurent Pinchart + +commit 80da2e0df5af700518611b7d1cc4fc9945bcaf95 upstream. + +When a whole class of devices (possibly from a specific vendor, or +across multiple vendors) require a quirk, explictly listing all devices +in the class make the quirks table unnecessarily large. Fix this by +allowing matching devices based on interface information. + +Signed-off-by: Laurent Pinchart +Acked-by: Alan Stern +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/driver.c | 38 +++++++++++------- + drivers/usb/core/hub.c | 10 +++- + drivers/usb/core/quirks.c | 93 +++++++++++++++++++++++++++++++++++----------- + drivers/usb/core/usb.h | 4 + + 4 files changed, 106 insertions(+), 39 deletions(-) + +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -530,22 +530,10 @@ int usb_match_device(struct usb_device * + } + + /* returns 0 if no match, 1 if match */ +-int usb_match_one_id(struct usb_interface *interface, +- const struct usb_device_id *id) ++int usb_match_one_id_intf(struct usb_device *dev, ++ struct usb_host_interface *intf, ++ const struct usb_device_id *id) + { +- struct usb_host_interface *intf; +- struct usb_device *dev; +- +- /* proc_connectinfo in devio.c may call us with id == NULL. */ +- if (id == NULL) +- return 0; +- +- intf = interface->cur_altsetting; +- dev = interface_to_usbdev(interface); +- +- if (!usb_match_device(dev, id)) +- return 0; +- + /* The interface class, subclass, and protocol should never be + * checked for a match if the device class is Vendor Specific, + * unless the match record specifies the Vendor ID. */ +@@ -570,6 +558,26 @@ int usb_match_one_id(struct usb_interfac + + return 1; + } ++ ++/* returns 0 if no match, 1 if match */ ++int usb_match_one_id(struct usb_interface *interface, ++ const struct usb_device_id *id) ++{ ++ struct usb_host_interface *intf; ++ struct usb_device *dev; ++ ++ /* proc_connectinfo in devio.c may call us with id == NULL. */ ++ if (id == NULL) ++ return 0; ++ ++ intf = interface->cur_altsetting; ++ dev = interface_to_usbdev(interface); ++ ++ if (!usb_match_device(dev, id)) ++ return 0; ++ ++ return usb_match_one_id_intf(dev, intf, id); ++} + EXPORT_SYMBOL_GPL(usb_match_one_id); + + /** +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1916,7 +1916,7 @@ static int usb_enumerate_device(struct u + if (err < 0) { + dev_err(&udev->dev, "can't read configurations, error %d\n", + err); +- goto fail; ++ return err; + } + } + +@@ -1927,8 +1927,12 @@ static int usb_enumerate_device(struct u + udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); + + err = usb_enumerate_device_otg(udev); +-fail: +- return err; ++ if (err < 0) ++ return err; ++ ++ usb_detect_interface_quirks(udev); ++ ++ return 0; + } + + static void set_usb_port_removable(struct usb_device *udev) +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -15,17 +15,22 @@ + #include + #include "usb.h" + +-/* List of quirky USB devices. Please keep this list ordered by: ++/* 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 ++ * information. ++ * ++ * Interface quirks are applied after reading all the configuration descriptors. ++ * They can match on both device and interface information. ++ * ++ * Note that the DELAY_INIT and HONOR_BNUMINTERFACES quirks do not make sense as ++ * interface quirks, as they only influence the enumeration process which is run ++ * before processing the interface quirks. ++ * ++ * Please keep the lists ordered by: + * 1) Vendor ID + * 2) Product ID + * 3) Class ID +- * +- * as we want specific devices to be overridden first, and only after that, any +- * class specific quirks. +- * +- * Right now the logic aborts if it finds a valid device in the table, we might +- * want to change that in the future if it turns out that a whole class of +- * devices is broken... + */ + static const struct usb_device_id usb_quirk_list[] = { + /* CBM - Flash disk */ +@@ -178,16 +183,53 @@ static const struct usb_device_id usb_qu + { } /* terminating entry must be last */ + }; + +-static const struct usb_device_id *find_id(struct usb_device *udev) ++static const struct usb_device_id usb_interface_quirk_list[] = { ++ { } /* terminating entry must be last */ ++}; ++ ++static bool usb_match_any_interface(struct usb_device *udev, ++ const struct usb_device_id *id) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < udev->descriptor.bNumConfigurations; ++i) { ++ struct usb_host_config *cfg = &udev->config[i]; ++ unsigned int j; ++ ++ for (j = 0; j < cfg->desc.bNumInterfaces; ++j) { ++ struct usb_interface_cache *cache; ++ struct usb_host_interface *intf; ++ ++ cache = cfg->intf_cache[j]; ++ if (cache->num_altsetting == 0) ++ continue; ++ ++ intf = &cache->altsetting[0]; ++ if (usb_match_one_id_intf(udev, intf, id)) ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static u32 __usb_detect_quirks(struct usb_device *udev, ++ const struct usb_device_id *id) + { +- const struct usb_device_id *id = usb_quirk_list; ++ u32 quirks = 0; + +- for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || +- id->driver_info; id++) { +- if (usb_match_device(udev, id)) +- return id; ++ for (; id->match_flags; id++) { ++ if (!usb_match_device(udev, id)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO) && ++ !usb_match_any_interface(udev, id)) ++ continue; ++ ++ quirks |= (u32)(id->driver_info); + } +- return NULL; ++ ++ return quirks; + } + + /* +@@ -195,14 +237,10 @@ static const struct usb_device_id *find_ + */ + void usb_detect_quirks(struct usb_device *udev) + { +- const struct usb_device_id *id = usb_quirk_list; +- +- id = find_id(udev); +- if (id) +- udev->quirks = (u32)(id->driver_info); ++ udev->quirks = __usb_detect_quirks(udev, usb_quirk_list); + if (udev->quirks) + dev_dbg(&udev->dev, "USB quirks for this device: %x\n", +- udev->quirks); ++ udev->quirks); + + /* For the present, all devices default to USB-PERSIST enabled */ + #if 0 /* was: #ifdef CONFIG_PM */ +@@ -219,3 +257,16 @@ void usb_detect_quirks(struct usb_device + udev->persist_enabled = 1; + #endif /* CONFIG_PM */ + } ++ ++void usb_detect_interface_quirks(struct usb_device *udev) ++{ ++ u32 quirks; ++ ++ quirks = __usb_detect_quirks(udev, usb_interface_quirk_list); ++ if (quirks == 0) ++ return; ++ ++ dev_dbg(&udev->dev, "USB interface quirks for this device: %x\n", ++ quirks); ++ udev->quirks |= quirks; ++} +--- a/drivers/usb/core/usb.h ++++ b/drivers/usb/core/usb.h +@@ -24,6 +24,7 @@ extern void usb_disable_device(struct us + extern int usb_deauthorize_device(struct usb_device *); + extern int usb_authorize_device(struct usb_device *); + extern void usb_detect_quirks(struct usb_device *udev); ++extern void usb_detect_interface_quirks(struct usb_device *udev); + extern int usb_remove_device(struct usb_device *udev); + + extern int usb_get_device_descriptor(struct usb_device *dev, +@@ -35,6 +36,9 @@ extern int usb_set_configuration(struct + extern int usb_choose_configuration(struct usb_device *udev); + + extern void usb_kick_khubd(struct usb_device *dev); ++extern int usb_match_one_id_intf(struct usb_device *dev, ++ struct usb_host_interface *intf, ++ const struct usb_device_id *id); + extern int usb_match_device(struct usb_device *dev, + const struct usb_device_id *id); + extern void usb_forced_unbind_intf(struct usb_interface *intf); diff --git a/queue-3.4/usb-add-usb_quirk_reset_resume-for-all-logitech-uvc-webcams.patch b/queue-3.4/usb-add-usb_quirk_reset_resume-for-all-logitech-uvc-webcams.patch new file mode 100644 index 00000000000..eced1e0c8d1 --- /dev/null +++ b/queue-3.4/usb-add-usb_quirk_reset_resume-for-all-logitech-uvc-webcams.patch @@ -0,0 +1,104 @@ +From fdf60a1cce3e089f3f2a80505297187c3a7e39b3 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Thu, 19 Jul 2012 12:39:14 +0200 +Subject: usb: Add USB_QUIRK_RESET_RESUME for all Logitech UVC webcams + +From: Laurent Pinchart + +commit e387ef5c47ddeaeaa3cbdc54424cdb7a28dae2c0 upstream. + +Most Logitech UVC webcams (both early models that don't advertise UVC +compatibility and newer UVC-advertised devices) require the RESET_RESUME +quirk. Instead of listing each and every model, match the devices based +on the UVC interface information. + +Signed-off-by: Laurent Pinchart +Acked-by: Alan Stern +[bwh: Adjust context to apply after 3.2.38] +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/quirks.c | 58 ++++++++++++---------------------------------- + 1 file changed, 16 insertions(+), 42 deletions(-) + +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -46,53 +46,23 @@ static const struct usb_device_id usb_qu + /* Microsoft LifeCam-VX700 v2.0 */ + { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, + +- /* Logitech Webcam C200 */ +- { USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME }, ++ /* Logitech Quickcam Fusion */ ++ { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, + +- /* Logitech Webcam C250 */ +- { USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, ++ /* Logitech Quickcam Orbit MP */ ++ { USB_DEVICE(0x046d, 0x08c2), .driver_info = USB_QUIRK_RESET_RESUME }, + +- /* Logitech Webcam C300 */ +- { USB_DEVICE(0x046d, 0x0805), .driver_info = USB_QUIRK_RESET_RESUME }, ++ /* Logitech Quickcam Pro for Notebook */ ++ { USB_DEVICE(0x046d, 0x08c3), .driver_info = USB_QUIRK_RESET_RESUME }, + +- /* Logitech Webcam B/C500 */ +- { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME }, ++ /* Logitech Quickcam Pro 5000 */ ++ { USB_DEVICE(0x046d, 0x08c5), .driver_info = USB_QUIRK_RESET_RESUME }, + +- /* Logitech Webcam C600 */ +- { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME }, ++ /* Logitech Quickcam OEM Dell Notebook */ ++ { USB_DEVICE(0x046d, 0x08c6), .driver_info = USB_QUIRK_RESET_RESUME }, + +- /* Logitech Webcam Pro 9000 */ +- { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Webcam C905 */ +- { USB_DEVICE(0x046d, 0x080a), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Webcam C210 */ +- { USB_DEVICE(0x046d, 0x0819), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Webcam C260 */ +- { USB_DEVICE(0x046d, 0x081a), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Webcam C310 */ +- { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Webcam C910 */ +- { USB_DEVICE(0x046d, 0x0821), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Webcam C160 */ +- { USB_DEVICE(0x046d, 0x0824), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Webcam C270 */ +- { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Quickcam Pro 9000 */ +- { USB_DEVICE(0x046d, 0x0990), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Quickcam E3500 */ +- { USB_DEVICE(0x046d, 0x09a4), .driver_info = USB_QUIRK_RESET_RESUME }, +- +- /* Logitech Quickcam Vision Pro */ +- { USB_DEVICE(0x046d, 0x09a6), .driver_info = USB_QUIRK_RESET_RESUME }, ++ /* Logitech Quickcam OEM Cisco VT Camera II */ ++ { USB_DEVICE(0x046d, 0x08c7), .driver_info = USB_QUIRK_RESET_RESUME }, + + /* Logitech Harmony 700-series */ + { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, +@@ -184,6 +154,10 @@ static const struct usb_device_id usb_qu + }; + + static const struct usb_device_id usb_interface_quirk_list[] = { ++ /* Logitech UVC Cameras */ ++ { USB_VENDOR_AND_INTERFACE_INFO(0x046d, USB_CLASS_VIDEO, 1, 0), ++ .driver_info = USB_QUIRK_RESET_RESUME }, ++ + { } /* terminating entry must be last */ + }; + diff --git a/queue-3.4/usb-ehci-bugfix-urb-hcpriv-should-not-be-null.patch b/queue-3.4/usb-ehci-bugfix-urb-hcpriv-should-not-be-null.patch new file mode 100644 index 00000000000..327f4ae43c6 --- /dev/null +++ b/queue-3.4/usb-ehci-bugfix-urb-hcpriv-should-not-be-null.patch @@ -0,0 +1,86 @@ +From b9678188b8f570d5c620dd3822485319c38a3709 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Thu, 8 Nov 2012 10:17:01 -0500 +Subject: USB: EHCI: bugfix: urb->hcpriv should not be NULL + +From: Alan Stern + +commit 2656a9abcf1ec8dd5fee6a75d6997a0f2fa0094e upstream. + +This patch (as1632b) fixes a bug in ehci-hcd. The USB core uses +urb->hcpriv to determine whether or not an URB is active; host +controller drivers are supposed to set this pointer to a non-NULL +value when an URB is queued. However ehci-hcd sets it to NULL for +isochronous URBs, which defeats the check in usbcore. + +In itself this isn't a big deal. But people have recently found that +certain sequences of actions will cause the snd-usb-audio driver to +reuse URBs without waiting for them to complete. In the absence of +proper checking by usbcore, the URBs get added to their endpoint list +twice. This leads to list corruption and a system freeze. + +The patch makes ehci-hcd assign a meaningful value to urb->hcpriv for +isochronous URBs. Improving robustness always helps. + +Signed-off-by: Alan Stern +Reported-by: Artem S. Tashkinov +Reported-by: Christof Meerwald +[bwh: Backported to 3.2: + - Adjust context + - Also use usb_pipetype() to work out whether we should call qh_put()] +Signed-off-by: Ben Hutchings +Cc: Yang Yingliang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/ehci-q.c | 16 ++++++---------- + drivers/usb/host/ehci-sched.c | 4 ++-- + 2 files changed, 8 insertions(+), 12 deletions(-) + +--- a/drivers/usb/host/ehci-q.c ++++ b/drivers/usb/host/ehci-q.c +@@ -264,18 +264,14 @@ ehci_urb_done(struct ehci_hcd *ehci, str + __releases(ehci->lock) + __acquires(ehci->lock) + { +- if (likely (urb->hcpriv != NULL)) { +- struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; +- +- /* S-mask in a QH means it's an interrupt urb */ +- if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { +- +- /* ... update hc-wide periodic stats (for usbfs) */ +- ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; +- } +- qh_put (qh); ++ if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { ++ /* ... update hc-wide periodic stats */ ++ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; + } + ++ if (usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) ++ qh_put((struct ehci_qh *) urb->hcpriv); ++ + if (unlikely(urb->unlinked)) { + COUNT(ehci->stats.unlink); + } else { +--- a/drivers/usb/host/ehci-sched.c ++++ b/drivers/usb/host/ehci-sched.c +@@ -1684,7 +1684,7 @@ itd_link_urb ( + + /* don't need that schedule data any more */ + iso_sched_free (stream, iso_sched); +- urb->hcpriv = NULL; ++ urb->hcpriv = stream; + + timer_action (ehci, TIMER_IO_WATCHDOG); + return enable_periodic(ehci); +@@ -2094,7 +2094,7 @@ sitd_link_urb ( + + /* don't need that schedule data any more */ + iso_sched_free (stream, sched); +- urb->hcpriv = NULL; ++ urb->hcpriv = stream; + + timer_action (ehci, TIMER_IO_WATCHDOG); + return enable_periodic(ehci); -- 2.47.3