]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Apr 2014 23:19:54 +0000 (16:19 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Apr 2014 23:19:54 +0000 (16:19 -0700)
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
queue-3.4/usb-add-device-quirk-for-microsoft-vx700-webcam.patch [new file with mode: 0644]
queue-3.4/usb-add-quirk-detection-based-on-interface-information.patch [new file with mode: 0644]
queue-3.4/usb-add-usb_quirk_reset_resume-for-all-logitech-uvc-webcams.patch [new file with mode: 0644]
queue-3.4/usb-ehci-bugfix-urb-hcpriv-should-not-be-null.patch [new file with mode: 0644]

index e2f84181fd90636da0038183dcfd1e9b985284f4..475e6627d4dc062606128898a564e33955ee5715 100644 (file)
@@ -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 (file)
index 0000000..2889183
--- /dev/null
@@ -0,0 +1,34 @@
+From 3e4ba2bf729b851695f01b514e1605dc0cffd5c8 Mon Sep 17 00:00:00 2001
+From: Andreas Fleig <andreasfleig@gmail.com>
+Date: Wed, 5 Dec 2012 16:17:49 +0100
+Subject: USB: Add device quirk for Microsoft VX700 webcam
+
+From: Andreas Fleig <andreasfleig@gmail.com>
+
+commit bc009eca8d539162f7271c2daf0ab5e9e3bb90a0 upstream.
+
+Add device quirk for Microsoft Lifecam VX700 v2.0 webcams.
+Fixes squeaking noise of the microphone.
+
+Signed-off-by: Andreas Fleig <andreasfleig@gmail.com>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Yang Yingliang <yangyingliang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..867fb33
--- /dev/null
@@ -0,0 +1,256 @@
+From f94c6107b49ac52f2e0f9929aeffeceb5ed97704 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 19 Jul 2012 12:39:13 +0200
+Subject: usb: Add quirk detection based on interface information
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+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 <laurent.pinchart@ideasonboard.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Yang Yingliang <yangyingliang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 <linux/usb/quirks.h>
+ #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 (file)
index 0000000..eced1e0
--- /dev/null
@@ -0,0 +1,104 @@
+From fdf60a1cce3e089f3f2a80505297187c3a7e39b3 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 19 Jul 2012 12:39:14 +0200
+Subject: usb: Add USB_QUIRK_RESET_RESUME for all Logitech UVC webcams
+
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+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 <laurent.pinchart@ideasonboard.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+[bwh: Adjust context to apply after 3.2.38]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Yang Yingliang <yangyingliang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..327f4ae
--- /dev/null
@@ -0,0 +1,86 @@
+From b9678188b8f570d5c620dd3822485319c38a3709 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Thu, 8 Nov 2012 10:17:01 -0500
+Subject: USB: EHCI: bugfix: urb->hcpriv should not be NULL
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <stern@rowland.harvard.edu>
+Reported-by: Artem S. Tashkinov <t.artem@lycos.com>
+Reported-by: Christof Meerwald <cmeerw@cmeerw.org>
+[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 <ben@decadent.org.uk>
+Cc: Yang Yingliang <yangyingliang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);