]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.38 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 19 Apr 2011 00:20:23 +0000 (17:20 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 19 Apr 2011 00:20:23 +0000 (17:20 -0700)
queue-2.6.38/series
queue-2.6.38/usb-ehci-unlink-unused-qhs-when-the-controller-is-stopped.patch [new file with mode: 0644]
queue-2.6.38/usb-fix-formatting-of-superspeed-endpoints-in-proc-bus-usb-devices.patch [new file with mode: 0644]
queue-2.6.38/usb-fix-qcserial-memory-leak-on-rmmod.patch [new file with mode: 0644]
queue-2.6.38/usb-fix-unplug-of-device-with-active-streams.patch [new file with mode: 0644]
queue-2.6.38/usb-qcserial-add-missing-errorpath-kfrees.patch [new file with mode: 0644]
queue-2.6.38/usb-qcserial-avoid-pointing-to-freed-memory.patch [new file with mode: 0644]
queue-2.6.38/usb-xhci-also-free-streams-when-resetting-devices.patch [new file with mode: 0644]
queue-2.6.38/usb-xhci-fix-math-in-xhci_get_endpoint_interval.patch [new file with mode: 0644]
queue-2.6.38/usb-xhci-fix-unsafe-macro-definitions.patch [new file with mode: 0644]

index 14797ef74849ea4faef8262255f1fcdbf6b30e1e..a51a03e9ffc123985f06db207bfb1c26173e8852 100644 (file)
@@ -56,3 +56,12 @@ next_pidmap-fix-overflow-condition.patch
 proc-do-proper-range-check-on-readdir-offset.patch
 powerpc-fix-oops-if-scan_dispatch_log-is-called-too-early.patch
 powerpc-perf_event-skip-updating-kernel-counters-if-register-value-shrinks.patch
+usb-fix-qcserial-memory-leak-on-rmmod.patch
+usb-qcserial-avoid-pointing-to-freed-memory.patch
+usb-qcserial-add-missing-errorpath-kfrees.patch
+usb-ehci-unlink-unused-qhs-when-the-controller-is-stopped.patch
+usb-fix-formatting-of-superspeed-endpoints-in-proc-bus-usb-devices.patch
+usb-xhci-fix-unsafe-macro-definitions.patch
+usb-xhci-fix-math-in-xhci_get_endpoint_interval.patch
+usb-xhci-also-free-streams-when-resetting-devices.patch
+usb-fix-unplug-of-device-with-active-streams.patch
diff --git a/queue-2.6.38/usb-ehci-unlink-unused-qhs-when-the-controller-is-stopped.patch b/queue-2.6.38/usb-ehci-unlink-unused-qhs-when-the-controller-is-stopped.patch
new file mode 100644 (file)
index 0000000..7333af1
--- /dev/null
@@ -0,0 +1,76 @@
+From 94ae4976e253757e9b03a44d27d41b20f1829d80 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Tue, 5 Apr 2011 13:36:15 -0400
+Subject: USB: EHCI: unlink unused QHs when the controller is stopped
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 94ae4976e253757e9b03a44d27d41b20f1829d80 upstream.
+
+This patch (as1458) fixes a problem affecting ultra-reliable systems:
+When hardware failover of an EHCI controller occurs, the data
+structures do not get released correctly.  This is because the routine
+responsible for removing unused QHs from the async schedule assumes
+the controller is running properly (the frame counter is used in
+determining how long the QH has been idle) -- but when a failover
+causes the controller to be electronically disconnected from the PCI
+bus, obviously it stops running.
+
+The solution is simple: Allow scan_async() to remove a QH from the
+async schedule if it has been idle for long enough _or_ if the
+controller is stopped.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Reported-and-Tested-by: Dan Duval <dan.duval@stratus.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-q.c |   15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -1245,24 +1245,27 @@ static void start_unlink_async (struct e
+ static void scan_async (struct ehci_hcd *ehci)
+ {
++      bool                    stopped;
+       struct ehci_qh          *qh;
+       enum ehci_timer_action  action = TIMER_IO_WATCHDOG;
+       ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
+       timer_action_done (ehci, TIMER_ASYNC_SHRINK);
+ rescan:
++      stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
+       qh = ehci->async->qh_next.qh;
+       if (likely (qh != NULL)) {
+               do {
+                       /* clean any finished work for this qh */
+-                      if (!list_empty (&qh->qtd_list)
+-                                      && qh->stamp != ehci->stamp) {
++                      if (!list_empty(&qh->qtd_list) && (stopped ||
++                                      qh->stamp != ehci->stamp)) {
+                               int temp;
+                               /* unlinks could happen here; completion
+                                * reporting drops the lock.  rescan using
+                                * the latest schedule, but don't rescan
+-                               * qhs we already finished (no looping).
++                               * qhs we already finished (no looping)
++                               * unless the controller is stopped.
+                                */
+                               qh = qh_get (qh);
+                               qh->stamp = ehci->stamp;
+@@ -1283,9 +1286,9 @@ rescan:
+                        */
+                       if (list_empty(&qh->qtd_list)
+                                       && qh->qh_state == QH_STATE_LINKED) {
+-                              if (!ehci->reclaim
+-                                      && ((ehci->stamp - qh->stamp) & 0x1fff)
+-                                              >= (EHCI_SHRINK_FRAMES * 8))
++                              if (!ehci->reclaim && (stopped ||
++                                      ((ehci->stamp - qh->stamp) & 0x1fff)
++                                              >= EHCI_SHRINK_FRAMES * 8))
+                                       start_unlink_async(ehci, qh);
+                               else
+                                       action = TIMER_ASYNC_SHRINK;
diff --git a/queue-2.6.38/usb-fix-formatting-of-superspeed-endpoints-in-proc-bus-usb-devices.patch b/queue-2.6.38/usb-fix-formatting-of-superspeed-endpoints-in-proc-bus-usb-devices.patch
new file mode 100644 (file)
index 0000000..bfa6441
--- /dev/null
@@ -0,0 +1,56 @@
+From 2868a2b1ba8f9c7f6c4170519ebb6c62934df70e Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dtor@vmware.com>
+Date: Fri, 18 Mar 2011 21:29:01 -0700
+Subject: USB: fix formatting of SuperSpeed endpoints in /proc/bus/usb/devices
+
+From: Dmitry Torokhov <dtor@vmware.com>
+
+commit 2868a2b1ba8f9c7f6c4170519ebb6c62934df70e upstream.
+
+Isochronous and interrupt SuperSpeed endpoints use the same mechanisms
+for decoding bInterval values as HighSpeed ones so adjust the code
+accordingly.
+
+Also bandwidth reservation for SuperSpeed matches highspeed, not
+low/full speed.
+
+Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/devices.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/core/devices.c
++++ b/drivers/usb/core/devices.c
+@@ -221,7 +221,7 @@ static char *usb_dump_endpoint_descripto
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               type = "Int.";
+-              if (speed == USB_SPEED_HIGH)
++              if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER)
+                       interval = 1 << (desc->bInterval - 1);
+               else
+                       interval = desc->bInterval;
+@@ -229,7 +229,8 @@ static char *usb_dump_endpoint_descripto
+       default:        /* "can't happen" */
+               return start;
+       }
+-      interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000;
++      interval *= (speed == USB_SPEED_HIGH ||
++                   speed == USB_SPEED_SUPER) ? 125 : 1000;
+       if (interval % 1000)
+               unit = 'u';
+       else {
+@@ -542,8 +543,9 @@ static ssize_t usb_device_dump(char __us
+       if (level == 0) {
+               int     max;
+-              /* high speed reserves 80%, full/low reserves 90% */
+-              if (usbdev->speed == USB_SPEED_HIGH)
++              /* super/high speed reserves 80%, full/low reserves 90% */
++              if (usbdev->speed == USB_SPEED_HIGH ||
++                  usbdev->speed == USB_SPEED_SUPER)
+                       max = 800;
+               else
+                       max = FRAME_TIME_MAX_USECS_ALLOC;
diff --git a/queue-2.6.38/usb-fix-qcserial-memory-leak-on-rmmod.patch b/queue-2.6.38/usb-fix-qcserial-memory-leak-on-rmmod.patch
new file mode 100644 (file)
index 0000000..8d245ed
--- /dev/null
@@ -0,0 +1,50 @@
+From 10c9ab15d6aee153968d150c05b3ee3df89673de Mon Sep 17 00:00:00 2001
+From: Steven Hardy <shardy@redhat.com>
+Date: Mon, 4 Apr 2011 17:57:37 +0100
+Subject: usb: Fix qcserial memory leak on rmmod
+
+From: Steven Hardy <shardy@redhat.com>
+
+commit 10c9ab15d6aee153968d150c05b3ee3df89673de upstream.
+
+qcprobe function allocates serial->private but this is never freed, this
+patch adds a new function qc_release() which frees serial->private, after
+calling usb_wwan_release
+
+Signed-off-by: Steven Hardy <shardy@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/qcserial.c |   14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -205,6 +205,18 @@ static int qcprobe(struct usb_serial *se
+       return retval;
+ }
++static void qc_release(struct usb_serial *serial)
++{
++      struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
++
++      dbg("%s", __func__);
++
++      /* Call usb_wwan release & free the private data allocated in qcprobe */
++      usb_wwan_release(serial);
++      usb_set_serial_data(serial, NULL);
++      kfree(priv);
++}
++
+ static struct usb_serial_driver qcdevice = {
+       .driver = {
+               .owner     = THIS_MODULE,
+@@ -222,7 +234,7 @@ static struct usb_serial_driver qcdevice
+       .chars_in_buffer     = usb_wwan_chars_in_buffer,
+       .attach              = usb_wwan_startup,
+       .disconnect          = usb_wwan_disconnect,
+-      .release             = usb_wwan_release,
++      .release             = qc_release,
+ #ifdef CONFIG_PM
+       .suspend             = usb_wwan_suspend,
+       .resume              = usb_wwan_resume,
diff --git a/queue-2.6.38/usb-fix-unplug-of-device-with-active-streams.patch b/queue-2.6.38/usb-fix-unplug-of-device-with-active-streams.patch
new file mode 100644 (file)
index 0000000..45eb889
--- /dev/null
@@ -0,0 +1,50 @@
+From b214f191d95ba4b5a35aebd69cd129cf7e3b1884 Mon Sep 17 00:00:00 2001
+From: Matthew Wilcox <willy@linux.intel.com>
+Date: Tue, 28 Sep 2010 00:57:32 -0400
+Subject: USB: Fix unplug of device with active streams
+
+From: Matthew Wilcox <willy@linux.intel.com>
+
+commit b214f191d95ba4b5a35aebd69cd129cf7e3b1884 upstream.
+
+If I unplug a device while the UAS driver is loaded, I get an oops
+in usb_free_streams().  This is because usb_unbind_interface() calls
+usb_disable_interface() which calls usb_disable_endpoint() which sets
+ep_out and ep_in to NULL.  Then the UAS driver calls usb_pipe_endpoint()
+which returns a NULL pointer and passes an array of NULL pointers to
+usb_free_streams().
+
+I think the correct fix for this is to check for the NULL pointer
+in usb_free_streams() rather than making the driver check for this
+situation.  My original patch for this checked for dev->state ==
+USB_STATE_NOTATTACHED, but the call to usb_disable_interface() is
+conditional, so not all drivers would want this check.
+
+Note from Sarah Sharp: This patch does avoid a potential dereference,
+but the real fix (which will be implemented later) is to set the
+.soft_unbind flag in the usb_driver structure for the UAS driver, and
+all drivers that allocate streams.  The driver should free any streams
+when it is unbound from the interface.  This avoids leaking stream rings
+in the xHCI driver when usb_disable_interface() is called.
+
+This should be queued for stable trees back to 2.6.35.
+
+Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hcd.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -1885,7 +1885,7 @@ void usb_free_streams(struct usb_interfa
+       /* Streams only apply to bulk endpoints. */
+       for (i = 0; i < num_eps; i++)
+-              if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
++              if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc))
+                       return;
+       hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
diff --git a/queue-2.6.38/usb-qcserial-add-missing-errorpath-kfrees.patch b/queue-2.6.38/usb-qcserial-add-missing-errorpath-kfrees.patch
new file mode 100644 (file)
index 0000000..3aab5fd
--- /dev/null
@@ -0,0 +1,38 @@
+From cb62d65f966146a39fdde548cb474dacf1d00fa5 Mon Sep 17 00:00:00 2001
+From: Steven Hardy <shardy@redhat.com>
+Date: Mon, 4 Apr 2011 18:02:25 +0100
+Subject: usb: qcserial add missing errorpath kfrees
+
+From: Steven Hardy <shardy@redhat.com>
+
+commit cb62d65f966146a39fdde548cb474dacf1d00fa5 upstream.
+
+There are two -ENODEV error paths in qcprobe where the allocated private
+data is not freed, this patch adds the two missing kfrees to avoid
+leaking memory on the error path
+
+Signed-off-by: Steven Hardy <shardy@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/qcserial.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -167,6 +167,7 @@ static int qcprobe(struct usb_serial *se
+                                       "Could not set interface, error %d\n",
+                                       retval);
+                               retval = -ENODEV;
++                              kfree(data);
+                       }
+               } else if (ifnum == 2) {
+                       dbg("Modem port found");
+@@ -191,6 +192,7 @@ static int qcprobe(struct usb_serial *se
+                                       "Could not set interface, error %d\n",
+                                       retval);
+                               retval = -ENODEV;
++                              kfree(data);
+                       }
+               }
+               break;
diff --git a/queue-2.6.38/usb-qcserial-avoid-pointing-to-freed-memory.patch b/queue-2.6.38/usb-qcserial-avoid-pointing-to-freed-memory.patch
new file mode 100644 (file)
index 0000000..b88e775
--- /dev/null
@@ -0,0 +1,74 @@
+From 99ab3f9e4eaec35fd2d7159c31b71f17f7e613e3 Mon Sep 17 00:00:00 2001
+From: Steven Hardy <shardy@redhat.com>
+Date: Mon, 4 Apr 2011 17:59:55 +0100
+Subject: usb: qcserial avoid pointing to freed memory
+
+From: Steven Hardy <shardy@redhat.com>
+
+commit 99ab3f9e4eaec35fd2d7159c31b71f17f7e613e3 upstream.
+
+Rework the qcprobe logic such that serial->private is not set when
+qcprobe exits with -ENODEV, otherwise serial->private will point to freed
+memory on -ENODEV
+
+Signed-off-by: Steven Hardy <shardy@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/qcserial.c |   15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -111,7 +111,7 @@ static int qcprobe(struct usb_serial *se
+       ifnum = intf->desc.bInterfaceNumber;
+       dbg("This Interface = %d", ifnum);
+-      data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
++      data = kzalloc(sizeof(struct usb_wwan_intf_private),
+                                        GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+@@ -134,8 +134,10 @@ static int qcprobe(struct usb_serial *se
+                   usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
+                       dbg("QDL port found");
+-                      if (serial->interface->num_altsetting == 1)
+-                              return 0;
++                      if (serial->interface->num_altsetting == 1) {
++                              retval = 0; /* Success */
++                              break;
++                      }
+                       retval = usb_set_interface(serial->dev, ifnum, 1);
+                       if (retval < 0) {
+@@ -145,7 +147,6 @@ static int qcprobe(struct usb_serial *se
+                               retval = -ENODEV;
+                               kfree(data);
+                       }
+-                      return retval;
+               }
+               break;
+@@ -177,7 +178,6 @@ static int qcprobe(struct usb_serial *se
+                               retval = -ENODEV;
+                               kfree(data);
+                       }
+-                      return retval;
+               } else if (ifnum==3) {
+                       /*
+                        * NMEA (serial line 9600 8N1)
+@@ -199,9 +199,12 @@ static int qcprobe(struct usb_serial *se
+               dev_err(&serial->dev->dev,
+                       "unknown number of interfaces: %d\n", nintf);
+               kfree(data);
+-              return -ENODEV;
++              retval = -ENODEV;
+       }
++      /* Set serial->private if not returning -ENODEV */
++      if (retval != -ENODEV)
++              usb_set_serial_data(serial, data);
+       return retval;
+ }
diff --git a/queue-2.6.38/usb-xhci-also-free-streams-when-resetting-devices.patch b/queue-2.6.38/usb-xhci-also-free-streams-when-resetting-devices.patch
new file mode 100644 (file)
index 0000000..3c45588
--- /dev/null
@@ -0,0 +1,54 @@
+From 2dea75d96ade3c7cd2bfe73f99c7b3291dc3d03a Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dtor@vmware.com>
+Date: Tue, 12 Apr 2011 23:06:28 -0700
+Subject: USB: xhci - also free streams when resetting devices
+
+From: Dmitry Torokhov <dtor@vmware.com>
+
+commit 2dea75d96ade3c7cd2bfe73f99c7b3291dc3d03a upstream.
+
+Currently, when resetting a device, xHCI driver disables all but one
+endpoints and frees their rings, but leaves alone any streams that
+might have been allocated. Later, when users try to free allocated
+streams, we oops in xhci_setup_no_streams_ep_input_ctx() because
+ep->ring is NULL.
+
+Let's free not only rings but also stream data as well, so that
+calling free_streams() on a device that was reset will be safe.
+
+This should be queued for stable trees back to 2.6.35.
+
+Reviewed-by: Micah Elizabeth Scott <micah@vmware.com>
+Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci.c |   16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -2335,10 +2335,18 @@ int xhci_discover_or_reset_device(struct
+       /* Everything but endpoint 0 is disabled, so free or cache the rings. */
+       last_freed_endpoint = 1;
+       for (i = 1; i < 31; ++i) {
+-              if (!virt_dev->eps[i].ring)
+-                      continue;
+-              xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+-              last_freed_endpoint = i;
++              struct xhci_virt_ep *ep = &virt_dev->eps[i];
++
++              if (ep->ep_state & EP_HAS_STREAMS) {
++                      xhci_free_stream_info(xhci, ep->stream_info);
++                      ep->stream_info = NULL;
++                      ep->ep_state &= ~EP_HAS_STREAMS;
++              }
++
++              if (ep->ring) {
++                      xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
++                      last_freed_endpoint = i;
++              }
+       }
+       xhci_dbg(xhci, "Output context after successful reset device cmd:\n");
+       xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint);
diff --git a/queue-2.6.38/usb-xhci-fix-math-in-xhci_get_endpoint_interval.patch b/queue-2.6.38/usb-xhci-fix-math-in-xhci_get_endpoint_interval.patch
new file mode 100644 (file)
index 0000000..7f499f1
--- /dev/null
@@ -0,0 +1,148 @@
+From dfa49c4ad120a784ef1ff0717168aa79f55a483a Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dtor@vmware.com>
+Date: Wed, 23 Mar 2011 22:41:23 -0700
+Subject: USB: xhci - fix math in xhci_get_endpoint_interval()
+
+From: Dmitry Torokhov <dtor@vmware.com>
+
+commit dfa49c4ad120a784ef1ff0717168aa79f55a483a upstream.
+
+When parsing exponent-expressed intervals we subtract 1 from the
+value and then expect it to match with original + 1, which is
+highly unlikely, and we end with frequent spew:
+
+       usb 3-4: ep 0x83 - rounding interval to 512 microframes
+
+Also, parsing interval for fullspeed isochronous endpoints was
+incorrect - according to USB spec they use exponent-based
+intervals (but xHCI spec claims frame-based intervals). I trust
+USB spec more, especially since USB core agrees with it.
+
+This should be queued for stable kernels back to 2.6.31.
+
+Reviewed-by: Micah Elizabeth Scott <micah@vmware.com>
+Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c |   90 ++++++++++++++++++++++++++++++--------------
+ 1 file changed, 62 insertions(+), 28 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -920,6 +920,47 @@ int xhci_setup_addressable_virt_dev(stru
+       return 0;
+ }
++/*
++ * Convert interval expressed as 2^(bInterval - 1) == interval into
++ * straight exponent value 2^n == interval.
++ *
++ */
++static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
++              struct usb_host_endpoint *ep)
++{
++      unsigned int interval;
++
++      interval = clamp_val(ep->desc.bInterval, 1, 16) - 1;
++      if (interval != ep->desc.bInterval - 1)
++              dev_warn(&udev->dev,
++                       "ep %#x - rounding interval to %d microframes\n",
++                       ep->desc.bEndpointAddress,
++                       1 << interval);
++
++      return interval;
++}
++
++/*
++ * Convert bInterval expressed in frames (in 1-255 range) to exponent of
++ * microframes, rounded down to nearest power of 2.
++ */
++static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
++              struct usb_host_endpoint *ep)
++{
++      unsigned int interval;
++
++      interval = fls(8 * ep->desc.bInterval) - 1;
++      interval = clamp_val(interval, 3, 10);
++      if ((1 << interval) != 8 * ep->desc.bInterval)
++              dev_warn(&udev->dev,
++                       "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
++                       ep->desc.bEndpointAddress,
++                       1 << interval,
++                       8 * ep->desc.bInterval);
++
++      return interval;
++}
++
+ /* Return the polling or NAK interval.
+  *
+  * The polling interval is expressed in "microframes".  If xHCI's Interval field
+@@ -937,45 +978,38 @@ static inline unsigned int xhci_get_endp
+       case USB_SPEED_HIGH:
+               /* Max NAK rate */
+               if (usb_endpoint_xfer_control(&ep->desc) ||
+-                              usb_endpoint_xfer_bulk(&ep->desc))
++                  usb_endpoint_xfer_bulk(&ep->desc)) {
+                       interval = ep->desc.bInterval;
++                      break;
++              }
+               /* Fall through - SS and HS isoc/int have same decoding */
++
+       case USB_SPEED_SUPER:
+               if (usb_endpoint_xfer_int(&ep->desc) ||
+-                              usb_endpoint_xfer_isoc(&ep->desc)) {
+-                      if (ep->desc.bInterval == 0)
+-                              interval = 0;
+-                      else
+-                              interval = ep->desc.bInterval - 1;
+-                      if (interval > 15)
+-                              interval = 15;
+-                      if (interval != ep->desc.bInterval + 1)
+-                              dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n",
+-                                              ep->desc.bEndpointAddress, 1 << interval);
++                  usb_endpoint_xfer_isoc(&ep->desc)) {
++                      interval = xhci_parse_exponent_interval(udev, ep);
+               }
+               break;
+-      /* Convert bInterval (in 1-255 frames) to microframes and round down to
+-       * nearest power of 2.
+-       */
++
+       case USB_SPEED_FULL:
++              if (usb_endpoint_xfer_int(&ep->desc)) {
++                      interval = xhci_parse_exponent_interval(udev, ep);
++                      break;
++              }
++              /*
++               * Fall through for isochronous endpoint interval decoding
++               * since it uses the same rules as low speed interrupt
++               * endpoints.
++               */
++
+       case USB_SPEED_LOW:
+               if (usb_endpoint_xfer_int(&ep->desc) ||
+-                              usb_endpoint_xfer_isoc(&ep->desc)) {
+-                      interval = fls(8*ep->desc.bInterval) - 1;
+-                      if (interval > 10)
+-                              interval = 10;
+-                      if (interval < 3)
+-                              interval = 3;
+-                      if ((1 << interval) != 8*ep->desc.bInterval)
+-                              dev_warn(&udev->dev,
+-                                              "ep %#x - rounding interval"
+-                                              " to %d microframes, "
+-                                              "ep desc says %d microframes\n",
+-                                              ep->desc.bEndpointAddress,
+-                                              1 << interval,
+-                                              8*ep->desc.bInterval);
++                  usb_endpoint_xfer_isoc(&ep->desc)) {
++
++                      interval = xhci_parse_frame_interval(udev, ep);
+               }
+               break;
++
+       default:
+               BUG();
+       }
diff --git a/queue-2.6.38/usb-xhci-fix-unsafe-macro-definitions.patch b/queue-2.6.38/usb-xhci-fix-unsafe-macro-definitions.patch
new file mode 100644 (file)
index 0000000..b2e3659
--- /dev/null
@@ -0,0 +1,47 @@
+From 5a6c2f3ff039154872ce597952f8b8900ea0d732 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dtor@vmware.com>
+Date: Sun, 20 Mar 2011 02:15:17 -0700
+Subject: USB: xhci - fix unsafe macro definitions
+
+From: Dmitry Torokhov <dtor@vmware.com>
+
+commit 5a6c2f3ff039154872ce597952f8b8900ea0d732 upstream.
+
+Macro arguments used in expressions need to be enclosed in parenthesis
+to avoid unpleasant surprises.
+
+This should be queued for kernels back to 2.6.31
+
+Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci.h |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -232,7 +232,7 @@ struct xhci_op_regs {
+  * notification type that matches a bit set in this bit field.
+  */
+ #define       DEV_NOTE_MASK           (0xffff)
+-#define ENABLE_DEV_NOTE(x)    (1 << x)
++#define ENABLE_DEV_NOTE(x)    (1 << (x))
+ /* Most of the device notification types should only be used for debug.
+  * SW does need to pay attention to function wake notifications.
+  */
+@@ -601,11 +601,11 @@ struct xhci_ep_ctx {
+ #define EP_STATE_STOPPED      3
+ #define EP_STATE_ERROR                4
+ /* Mult - Max number of burtst within an interval, in EP companion desc. */
+-#define EP_MULT(p)            ((p & 0x3) << 8)
++#define EP_MULT(p)            (((p) & 0x3) << 8)
+ /* bits 10:14 are Max Primary Streams */
+ /* bit 15 is Linear Stream Array */
+ /* Interval - period between requests to an endpoint - 125u increments. */
+-#define EP_INTERVAL(p)                ((p & 0xff) << 16)
++#define EP_INTERVAL(p)                (((p) & 0xff) << 16)
+ #define EP_INTERVAL_TO_UFRAMES(p)             (1 << (((p) >> 16) & 0xff))
+ #define EP_MAXPSTREAMS_MASK   (0x1f << 10)
+ #define EP_MAXPSTREAMS(p)     (((p) << 10) & EP_MAXPSTREAMS_MASK)