]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Fri, 26 Aug 2011 22:33:38 +0000 (15:33 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 26 Aug 2011 22:33:38 +0000 (15:33 -0700)
13 files changed:
queue-3.0/series
queue-3.0/usb-ehci-do-not-rely-on-port_suspend-to-stop-usb-resuming-in-ehci_bus_resume.patch [new file with mode: 0644]
queue-3.0/usb-musb-cppi-fix-build-errors-due-to-dbg-and-missing.patch [new file with mode: 0644]
queue-3.0/usb-option-add-yuga-device-id-to-driver.patch [new file with mode: 0644]
queue-3.0/usb-option-driver-add-pid-of-huawei-vodafone-k3806.patch [new file with mode: 0644]
queue-3.0/usb-option-driver-add-pid-of-huawei-vodafone-k4605.patch [new file with mode: 0644]
queue-3.0/usb-option-driver-k3765-k4505-avoid-cdc_data-interface.patch [new file with mode: 0644]
queue-3.0/xhci-fix-failed-enqueue-in-the-middle-of-isoch-td.patch [new file with mode: 0644]
queue-3.0/xhci-fix-memory-leak-during-failed-enqueue.patch [new file with mode: 0644]
queue-3.0/xhci-fix-port-u3-status-check-condition.patch [new file with mode: 0644]
queue-3.0/xhci-handle-zero-length-isochronous-packets.patch [new file with mode: 0644]
queue-3.0/xhci-remove-tds-from-td-lists-when-urbs-are-canceled.patch [new file with mode: 0644]
queue-3.0/xhci-report-usb2-port-in-resuming-as-suspend.patch [new file with mode: 0644]

index 0d226bf4bc3def983d830102f4a90900adc5b095..320a3bfe873c21df051d57824388032e8e492f25 100644 (file)
@@ -13,3 +13,15 @@ tty-add-spi-prefix-for-spi-modalias.patch
 tty-pty-fix-pty-counting.patch
 usb-ftdi_sio-add-calao-reference-board-support.patch
 usb-s5p-ehci-fix-a-null-pointer-deference.patch
+usb-option-driver-add-pid-of-huawei-vodafone-k3806.patch
+usb-option-driver-add-pid-of-huawei-vodafone-k4605.patch
+usb-option-add-yuga-device-id-to-driver.patch
+usb-option-driver-k3765-k4505-avoid-cdc_data-interface.patch
+usb-musb-cppi-fix-build-errors-due-to-dbg-and-missing.patch
+usb-ehci-do-not-rely-on-port_suspend-to-stop-usb-resuming-in-ehci_bus_resume.patch
+xhci-fix-port-u3-status-check-condition.patch
+xhci-report-usb2-port-in-resuming-as-suspend.patch
+xhci-fix-memory-leak-during-failed-enqueue.patch
+xhci-fix-failed-enqueue-in-the-middle-of-isoch-td.patch
+xhci-remove-tds-from-td-lists-when-urbs-are-canceled.patch
+xhci-handle-zero-length-isochronous-packets.patch
diff --git a/queue-3.0/usb-ehci-do-not-rely-on-port_suspend-to-stop-usb-resuming-in-ehci_bus_resume.patch b/queue-3.0/usb-ehci-do-not-rely-on-port_suspend-to-stop-usb-resuming-in-ehci_bus_resume.patch
new file mode 100644 (file)
index 0000000..88b845b
--- /dev/null
@@ -0,0 +1,54 @@
+From d0f2fb2500b1c5fe4967eb45d8c9bc758d7aef80 Mon Sep 17 00:00:00 2001
+From: Wang Zhi <zhi.wang@windriver.com>
+Date: Wed, 17 Aug 2011 10:39:31 +0800
+Subject: USB: EHCI: Do not rely on PORT_SUSPEND to stop USB resuming in ehci_bus_resume().
+
+From: Wang Zhi <zhi.wang@windriver.com>
+
+commit d0f2fb2500b1c5fe4967eb45d8c9bc758d7aef80 upstream.
+
+From EHCI Spec p.28 HC should clear PORT_SUSPEND when SW clears
+PORT_RESUME. In Intel Oaktrail platform, MPH (Multi-Port Host
+Controller) core clears PORT_SUSPEND directly when SW sets PORT_RESUME
+bit. If we rely on PORT_SUSPEND bit to stop USB resume, we will miss
+the action of clearing PORT_RESUME. This will cause unexpected long
+resume signal on USB bus.
+
+Signed-off-by: Wang Zhi <zhi.wang@windriver.com>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-hub.c |    7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -343,7 +343,7 @@ static int ehci_bus_resume (struct usb_h
+       u32                     temp;
+       u32                     power_okay;
+       int                     i;
+-      u8                      resume_needed = 0;
++      unsigned long           resume_needed = 0;
+       if (time_before (jiffies, ehci->next_statechange))
+               msleep(5);
+@@ -416,7 +416,7 @@ static int ehci_bus_resume (struct usb_h
+               if (test_bit(i, &ehci->bus_suspended) &&
+                               (temp & PORT_SUSPEND)) {
+                       temp |= PORT_RESUME;
+-                      resume_needed = 1;
++                      set_bit(i, &resume_needed);
+               }
+               ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
+       }
+@@ -431,8 +431,7 @@ static int ehci_bus_resume (struct usb_h
+       i = HCS_N_PORTS (ehci->hcs_params);
+       while (i--) {
+               temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+-              if (test_bit(i, &ehci->bus_suspended) &&
+-                              (temp & PORT_SUSPEND)) {
++              if (test_bit(i, &resume_needed)) {
+                       temp &= ~(PORT_RWC_BITS | PORT_RESUME);
+                       ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
+                       ehci_vdbg (ehci, "resumed port %d\n", i + 1);
diff --git a/queue-3.0/usb-musb-cppi-fix-build-errors-due-to-dbg-and-missing.patch b/queue-3.0/usb-musb-cppi-fix-build-errors-due-to-dbg-and-missing.patch
new file mode 100644 (file)
index 0000000..b60c1ab
--- /dev/null
@@ -0,0 +1,96 @@
+From f847a79ab3c1faca3022061045cd22e4678c1b1c Mon Sep 17 00:00:00 2001
+From: Per Forlin <per.forlin@linaro.org>
+Date: Wed, 3 Aug 2011 15:39:15 +0200
+Subject: usb: musb: cppi: fix build errors due to DBG and missing
+ musb variable
+
+From: Per Forlin <per.forlin@linaro.org>
+
+commit f847a79ab3c1faca3022061045cd22e4678c1b1c upstream.
+
+Replace DBG with dev_dbg and fix invalid access of musb->controller.
+With this patch cppi_dma builds successfully.
+
+Signed-off-by: Per Forlin <per.forlin@linaro.org>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/musb/cppi_dma.c |   26 +++++++++++++++++---------
+ 1 file changed, 17 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/musb/cppi_dma.c
++++ b/drivers/usb/musb/cppi_dma.c
+@@ -226,8 +226,10 @@ static int cppi_controller_stop(struct d
+       struct cppi             *controller;
+       void __iomem            *tibase;
+       int                     i;
++      struct musb             *musb;
+       controller = container_of(c, struct cppi, controller);
++      musb = controller->musb;
+       tibase = controller->tibase;
+       /* DISABLE INDIVIDUAL CHANNEL Interrupts */
+@@ -289,9 +291,11 @@ cppi_channel_allocate(struct dma_control
+       u8                      index;
+       struct cppi_channel     *cppi_ch;
+       void __iomem            *tibase;
++      struct musb             *musb;
+       controller = container_of(c, struct cppi, controller);
+       tibase = controller->tibase;
++      musb = controller->musb;
+       /* ep0 doesn't use DMA; remember cppi indices are 0..N-1 */
+       index = ep->epnum - 1;
+@@ -339,7 +343,8 @@ static void cppi_channel_release(struct
+       c = container_of(channel, struct cppi_channel, channel);
+       tibase = c->controller->tibase;
+       if (!c->hw_ep)
+-              dev_dbg(musb->controller, "releasing idle DMA channel %p\n", c);
++              dev_dbg(c->controller->musb->controller,
++                      "releasing idle DMA channel %p\n", c);
+       else if (!c->transmit)
+               core_rxirq_enable(tibase, c->index + 1);
+@@ -357,10 +362,11 @@ cppi_dump_rx(int level, struct cppi_chan
+       musb_ep_select(base, c->index + 1);
+-      DBG(level, "RX DMA%d%s: %d left, csr %04x, "
+-                      "%08x H%08x S%08x C%08x, "
+-                      "B%08x L%08x %08x .. %08x"
+-                      "\n",
++      dev_dbg(c->controller->musb->controller,
++              "RX DMA%d%s: %d left, csr %04x, "
++              "%08x H%08x S%08x C%08x, "
++              "B%08x L%08x %08x .. %08x"
++              "\n",
+               c->index, tag,
+               musb_readl(c->controller->tibase,
+                       DAVINCI_RXCPPI_BUFCNT0_REG + 4 * c->index),
+@@ -387,10 +393,11 @@ cppi_dump_tx(int level, struct cppi_chan
+       musb_ep_select(base, c->index + 1);
+-      DBG(level, "TX DMA%d%s: csr %04x, "
+-                      "H%08x S%08x C%08x %08x, "
+-                      "F%08x L%08x .. %08x"
+-                      "\n",
++      dev_dbg(c->controller->musb->controller,
++              "TX DMA%d%s: csr %04x, "
++              "H%08x S%08x C%08x %08x, "
++              "F%08x L%08x .. %08x"
++              "\n",
+               c->index, tag,
+               musb_readw(c->hw_ep->regs, MUSB_TXCSR),
+@@ -1022,6 +1029,7 @@ static bool cppi_rx_scan(struct cppi *cp
+       int                             i;
+       dma_addr_t                      safe2ack;
+       void __iomem                    *regs = rx->hw_ep->regs;
++      struct musb                     *musb = cppi->musb;
+       cppi_dump_rx(6, rx, "/K");
diff --git a/queue-3.0/usb-option-add-yuga-device-id-to-driver.patch b/queue-3.0/usb-option-add-yuga-device-id-to-driver.patch
new file mode 100644 (file)
index 0000000..869a05c
--- /dev/null
@@ -0,0 +1,124 @@
+From c6eb2d75ffcdfafa37ff010bf467de20d468ef79 Mon Sep 17 00:00:00 2001
+From: "Gavin.zhu" <gavin.kx@qq.com>
+Date: Mon, 22 Aug 2011 13:51:53 -0700
+Subject: USB: option: add YUGA device id to driver
+
+From: "Gavin.zhu" <gavin.kx@qq.com>
+
+commit c6eb2d75ffcdfafa37ff010bf467de20d468ef79 upstream.
+
+Signed-off-by: Gavin.zhu <gavin.kx@qq.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c |   92 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 92 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -418,6 +418,56 @@ static void option_instat_callback(struc
+ #define SAMSUNG_VENDOR_ID                       0x04e8
+ #define SAMSUNG_PRODUCT_GT_B3730                0x6889
++/* YUGA products  www.yuga-info.com*/
++#define YUGA_VENDOR_ID                                0x257A
++#define YUGA_PRODUCT_CEM600                   0x1601
++#define YUGA_PRODUCT_CEM610                   0x1602
++#define YUGA_PRODUCT_CEM500                   0x1603
++#define YUGA_PRODUCT_CEM510                   0x1604
++#define YUGA_PRODUCT_CEM800                   0x1605
++#define YUGA_PRODUCT_CEM900                   0x1606
++
++#define YUGA_PRODUCT_CEU818                   0x1607
++#define YUGA_PRODUCT_CEU816                   0x1608
++#define YUGA_PRODUCT_CEU828                   0x1609
++#define YUGA_PRODUCT_CEU826                   0x160A
++#define YUGA_PRODUCT_CEU518                   0x160B
++#define YUGA_PRODUCT_CEU516                   0x160C
++#define YUGA_PRODUCT_CEU528                   0x160D
++#define YUGA_PRODUCT_CEU526                   0x160F
++
++#define YUGA_PRODUCT_CWM600                   0x2601
++#define YUGA_PRODUCT_CWM610                   0x2602
++#define YUGA_PRODUCT_CWM500                   0x2603
++#define YUGA_PRODUCT_CWM510                   0x2604
++#define YUGA_PRODUCT_CWM800                   0x2605
++#define YUGA_PRODUCT_CWM900                   0x2606
++
++#define YUGA_PRODUCT_CWU718                   0x2607
++#define YUGA_PRODUCT_CWU716                   0x2608
++#define YUGA_PRODUCT_CWU728                   0x2609
++#define YUGA_PRODUCT_CWU726                   0x260A
++#define YUGA_PRODUCT_CWU518                   0x260B
++#define YUGA_PRODUCT_CWU516                   0x260C
++#define YUGA_PRODUCT_CWU528                   0x260D
++#define YUGA_PRODUCT_CWU526                   0x260F
++
++#define YUGA_PRODUCT_CLM600                   0x2601
++#define YUGA_PRODUCT_CLM610                   0x2602
++#define YUGA_PRODUCT_CLM500                   0x2603
++#define YUGA_PRODUCT_CLM510                   0x2604
++#define YUGA_PRODUCT_CLM800                   0x2605
++#define YUGA_PRODUCT_CLM900                   0x2606
++
++#define YUGA_PRODUCT_CLU718                   0x2607
++#define YUGA_PRODUCT_CLU716                   0x2608
++#define YUGA_PRODUCT_CLU728                   0x2609
++#define YUGA_PRODUCT_CLU726                   0x260A
++#define YUGA_PRODUCT_CLU518                   0x260B
++#define YUGA_PRODUCT_CLU516                   0x260C
++#define YUGA_PRODUCT_CLU528                   0x260D
++#define YUGA_PRODUCT_CLU526                   0x260F
++
+ /* some devices interfaces need special handling due to a number of reasons */
+ enum option_blacklist_reason {
+               OPTION_BLACKLIST_NONE = 0,
+@@ -1009,6 +1059,48 @@ static const struct usb_device_id option
+       { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
+       { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
+       { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM610) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM500) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM510) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM800) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM900) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU818) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU816) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU828) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU826) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU518) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU516) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU528) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU526) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM600) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM610) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM500) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM510) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM800) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM900) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU718) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU716) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU728) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU726) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU518) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU516) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU528) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU526) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM600) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM610) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM500) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM510) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM800) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM900) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU718) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU716) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU728) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU726) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU518) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) },
++      { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
+       { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/queue-3.0/usb-option-driver-add-pid-of-huawei-vodafone-k3806.patch b/queue-3.0/usb-option-driver-add-pid-of-huawei-vodafone-k3806.patch
new file mode 100644 (file)
index 0000000..4a05fcf
--- /dev/null
@@ -0,0 +1,41 @@
+From 0e69d75ccb2f091757b38d4d6a2ed739e06b615e Mon Sep 17 00:00:00 2001
+From: Andrew Bird <ajb@spheresystems.co.uk>
+Date: Tue, 16 Aug 2011 13:57:14 -0600
+Subject: USB option driver add PID of Huawei Vodafone K3806
+
+From: Andrew Bird <ajb@spheresystems.co.uk>
+
+commit 0e69d75ccb2f091757b38d4d6a2ed739e06b615e upstream.
+
+This patch adds the product ID of Huawei's Vodafone K3806 mobile broadband
+modem to option.c. This is necessary so that the driver gets loaded on
+demand without the intervention of usb_modeswitch. This has the benefit of
+it becoming available faster and also ensures that the option driver is not
+bound to a network interface that should be claimed by cdc_ether.
+
+Signed-off-by: Andrew Bird <ajb@spheresystems.co.uk>
+Signed-off-by: Alex Chiang <achiang@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -148,6 +148,7 @@ static void option_instat_callback(struc
+ #define HUAWEI_PRODUCT_K4505                  0x1464
+ #define HUAWEI_PRODUCT_K3765                  0x1465
+ #define HUAWEI_PRODUCT_E14AC                  0x14AC
++#define HUAWEI_PRODUCT_K3806                  0x14AE
+ #define HUAWEI_PRODUCT_K3770                  0x14C9
+ #define HUAWEI_PRODUCT_K3771                  0x14CA
+ #define HUAWEI_PRODUCT_K4510                  0x14CB
+@@ -551,6 +552,7 @@ static const struct usb_device_id option
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
++      { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) },
diff --git a/queue-3.0/usb-option-driver-add-pid-of-huawei-vodafone-k4605.patch b/queue-3.0/usb-option-driver-add-pid-of-huawei-vodafone-k4605.patch
new file mode 100644 (file)
index 0000000..dcbccec
--- /dev/null
@@ -0,0 +1,56 @@
+From 7e1805844da18a37e6d251d286f93c94b52d791e Mon Sep 17 00:00:00 2001
+From: Andrew Bird <ajb@spheresystems.co.uk>
+Date: Tue, 16 Aug 2011 13:58:21 -0600
+Subject: USB option driver add PID of Huawei Vodafone K4605
+
+From: Andrew Bird <ajb@spheresystems.co.uk>
+
+commit 7e1805844da18a37e6d251d286f93c94b52d791e upstream.
+
+This patch adds the product ID of Huawei's Vodafone K4605 mobile broadband
+modem to option.c. This is necessary so that the driver gets loaded on
+demand without the intervention of usb_modeswitch. This has the benefit of
+it becoming available faster and also ensures that the option driver is not
+bound to a network interface that should be claimed by suitable network
+driver.
+
+Signed-off-by: Andrew Bird <ajb@spheresystems.co.uk>
+Signed-off-by: Alex Chiang <achiang@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -149,6 +149,7 @@ static void option_instat_callback(struc
+ #define HUAWEI_PRODUCT_K3765                  0x1465
+ #define HUAWEI_PRODUCT_E14AC                  0x14AC
+ #define HUAWEI_PRODUCT_K3806                  0x14AE
++#define HUAWEI_PRODUCT_K4605                  0x14C6
+ #define HUAWEI_PRODUCT_K3770                  0x14C9
+ #define HUAWEI_PRODUCT_K3771                  0x14CA
+ #define HUAWEI_PRODUCT_K4510                  0x14CB
+@@ -553,6 +554,7 @@ static const struct usb_device_id option
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) },
++      { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) },
+@@ -1136,10 +1138,11 @@ static int option_probe(struct usb_seria
+               serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff)
+               return -ENODEV;
+-      /* Don't bind network interfaces on Huawei K3765 & K4505 */
++      /* Don't bind network interfaces on Huawei K3765, K4505 & K4605 */
+       if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID &&
+               (serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 ||
+-                      serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) &&
++                      serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505 ||
++                      serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4605) &&
+               serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
+               return -ENODEV;
diff --git a/queue-3.0/usb-option-driver-k3765-k4505-avoid-cdc_data-interface.patch b/queue-3.0/usb-option-driver-k3765-k4505-avoid-cdc_data-interface.patch
new file mode 100644 (file)
index 0000000..933a931
--- /dev/null
@@ -0,0 +1,33 @@
+From 6118514e8749105334f46ccec6faf9a439be6cf9 Mon Sep 17 00:00:00 2001
+From: Andrew Bird <ajb@spheresystems.co.uk>
+Date: Wed, 17 Aug 2011 00:20:03 +0100
+Subject: USB option driver K3765/K4505 avoid CDC_DATA interface
+
+From: Andrew Bird <ajb@spheresystems.co.uk>
+
+commit 6118514e8749105334f46ccec6faf9a439be6cf9 upstream.
+
+Currently the Option driver avoids binding interface 1 on Huawei K3765
+and K4505 broadband modems as it should be handled by the cdc_ether
+driver instead. This patch ensures we don't bind the interface 2
+on those devices as that is CDC_DATA.
+
+Signed-off-by: Andrew Bird <ajb@spheresystems.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1235,7 +1235,8 @@ static int option_probe(struct usb_seria
+               (serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 ||
+                       serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505 ||
+                       serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4605) &&
+-              serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
++              (serial->interface->cur_altsetting->desc.bInterfaceNumber == 1 ||
++                      serial->interface->cur_altsetting->desc.bInterfaceNumber == 2))
+               return -ENODEV;
+       /* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
diff --git a/queue-3.0/xhci-fix-failed-enqueue-in-the-middle-of-isoch-td.patch b/queue-3.0/xhci-fix-failed-enqueue-in-the-middle-of-isoch-td.patch
new file mode 100644 (file)
index 0000000..e4134e6
--- /dev/null
@@ -0,0 +1,165 @@
+From 522989a27c7badb608155b1f1dea3487ed431f74 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 29 Jul 2011 12:44:32 -0700
+Subject: xhci: Fix failed enqueue in the middle of isoch TD.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 522989a27c7badb608155b1f1dea3487ed431f74 upstream.
+
+When an isochronous transfer is enqueued, xhci_queue_isoc_tx_prepare()
+will ensure that there is enough room on the transfer rings for all of the
+isochronous TDs for that URB.  However, when xhci_queue_isoc_tx() is
+enqueueing individual isoc TDs, the prepare_transfer() function can fail
+if the endpoint state has changed to disabled, error, or some other
+unknown state.
+
+With the current code, if Nth TD (not the first TD) fails, the ring is
+left in a sorry state.  The partially enqueued TDs are left on the ring,
+and the first TRB of the TD is not given back to the hardware.  The
+enqueue pointer is left on the TRB after the last successfully enqueued
+TD.  This means the ring is basically useless.  Any new transfers will be
+enqueued after the failed TDs, which the hardware will never read because
+the cycle bit indicates it does not own them.  The ring will fill up with
+untransferred TDs, and the endpoint will be basically unusable.
+
+The untransferred TDs will also remain on the TD list.  Since the td_list
+is a FIFO, this basically means the ring handler will be waiting on TDs
+that will never be completed (or worse, dereference memory that doesn't
+exist any more).
+
+Change the code to clean up the isochronous ring after a failed transfer.
+If the first TD failed, simply return and allow the xhci_urb_enqueue
+function to free the urb_priv.  If the Nth TD failed, first remove the TDs
+from the td_list.  Then convert the TRBs that were enqueued into No-op
+TRBs.  Make sure to flip the cycle bit on all enqueued TRBs (including any
+link TRBs in the middle or between TDs), but leave the cycle bit of the
+first TRB (which will show software-owned) intact.  Then move the ring
+enqueue pointer back to the first TRB and make sure to change the
+xhci_ring's cycle state to what is appropriate for that ring segment.
+
+This ensures that the No-op TRBs will be overwritten by subsequent TDs,
+and the hardware will not start executing random TRBs because the cycle
+bit was left as hardware-owned.
+
+This bug is unlikely to be hit, but it was something I noticed while
+tracking down the watchdog timer issue.  I verified that the fix works by
+injecting some errors on the 250th isochronous URB queued, although I
+could not verify that the ring is in the correct state because uvcvideo
+refused to talk to the device after the first usb_submit_urb() failed.
+Ring debugging shows that the ring looks correct, however.
+
+This patch should be backported to kernels as old as 2.6.36.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |   50 +++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 44 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -516,8 +516,12 @@ void xhci_find_new_dequeue_state(struct
+                       (unsigned long long) addr);
+ }
++/* flip_cycle means flip the cycle bit of all but the first and last TRB.
++ * (The last TRB actually points to the ring enqueue pointer, which is not part
++ * of this TD.)  This is used to remove partially enqueued isoc TDs from a ring.
++ */
+ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
+-              struct xhci_td *cur_td)
++              struct xhci_td *cur_td, bool flip_cycle)
+ {
+       struct xhci_segment *cur_seg;
+       union xhci_trb *cur_trb;
+@@ -531,6 +535,12 @@ static void td_to_noop(struct xhci_hcd *
+                        * leave the pointers intact.
+                        */
+                       cur_trb->generic.field[3] &= cpu_to_le32(~TRB_CHAIN);
++                      /* Flip the cycle bit (link TRBs can't be the first
++                       * or last TRB).
++                       */
++                      if (flip_cycle)
++                              cur_trb->generic.field[3] ^=
++                                      cpu_to_le32(TRB_CYCLE);
+                       xhci_dbg(xhci, "Cancel (unchain) link TRB\n");
+                       xhci_dbg(xhci, "Address = %p (0x%llx dma); "
+                                       "in seg %p (0x%llx dma)\n",
+@@ -544,6 +554,11 @@ static void td_to_noop(struct xhci_hcd *
+                       cur_trb->generic.field[2] = 0;
+                       /* Preserve only the cycle bit of this TRB */
+                       cur_trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE);
++                      /* Flip the cycle bit except on the first or last TRB */
++                      if (flip_cycle && cur_trb != cur_td->first_trb &&
++                                      cur_trb != cur_td->last_trb)
++                              cur_trb->generic.field[3] ^=
++                                      cpu_to_le32(TRB_CYCLE);
+                       cur_trb->generic.field[3] |= cpu_to_le32(
+                               TRB_TYPE(TRB_TR_NOOP));
+                       xhci_dbg(xhci, "Cancel TRB %p (0x%llx dma) "
+@@ -722,7 +737,7 @@ static void handle_stopped_endpoint(stru
+                                       cur_td->urb->stream_id,
+                                       cur_td, &deq_state);
+               else
+-                      td_to_noop(xhci, ep_ring, cur_td);
++                      td_to_noop(xhci, ep_ring, cur_td, false);
+ remove_finished_td:
+               /*
+                * The event handler won't see a completion for this TD anymore,
+@@ -3231,6 +3246,7 @@ static int xhci_queue_isoc_tx(struct xhc
+       start_trb = &ep_ring->enqueue->generic;
+       start_cycle = ep_ring->cycle_state;
++      urb_priv = urb->hcpriv;
+       /* Queue the first TRB, even if it's zero-length */
+       for (i = 0; i < num_tds; i++) {
+               unsigned int total_packet_count;
+@@ -3254,12 +3270,13 @@ static int xhci_queue_isoc_tx(struct xhc
+               ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
+                               urb->stream_id, trbs_per_td, urb, i, mem_flags);
+-              if (ret < 0)
+-                      return ret;
++              if (ret < 0) {
++                      if (i == 0)
++                              return ret;
++                      goto cleanup;
++              }
+-              urb_priv = urb->hcpriv;
+               td = urb_priv->td[i];
+-
+               for (j = 0; j < trbs_per_td; j++) {
+                       u32 remainder = 0;
+                       field = TRB_TBC(burst_count) | TRB_TLBPC(residue);
+@@ -3349,6 +3366,27 @@ static int xhci_queue_isoc_tx(struct xhc
+       giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
+                       start_cycle, start_trb);
+       return 0;
++cleanup:
++      /* Clean up a partially enqueued isoc transfer. */
++
++      for (i--; i >= 0; i--)
++              list_del(&urb_priv->td[i]->td_list);
++
++      /* Use the first TD as a temporary variable to turn the TDs we've queued
++       * into No-ops with a software-owned cycle bit. That way the hardware
++       * won't accidentally start executing bogus TDs when we partially
++       * overwrite them.  td->first_trb and td->start_seg are already set.
++       */
++      urb_priv->td[0]->last_trb = ep_ring->enqueue;
++      /* Every TRB except the first & last will have its cycle bit flipped. */
++      td_to_noop(xhci, ep_ring, urb_priv->td[0], true);
++
++      /* Reset the ring enqueue back to the first TRB and its cycle bit. */
++      ep_ring->enqueue = urb_priv->td[0]->first_trb;
++      ep_ring->enq_seg = urb_priv->td[0]->start_seg;
++      ep_ring->cycle_state = start_cycle;
++      usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
++      return ret;
+ }
+ /*
diff --git a/queue-3.0/xhci-fix-memory-leak-during-failed-enqueue.patch b/queue-3.0/xhci-fix-memory-leak-during-failed-enqueue.patch
new file mode 100644 (file)
index 0000000..b978000
--- /dev/null
@@ -0,0 +1,131 @@
+From d13565c12828ce0cd2a3862bf6260164a0653352 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 22 Jul 2011 14:34:34 -0700
+Subject: xhci: Fix memory leak during failed enqueue.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit d13565c12828ce0cd2a3862bf6260164a0653352 upstream.
+
+When the isochronous transfer support was introduced, and the xHCI driver
+switched to using urb->hcpriv to store an "urb_priv" pointer, a couple of
+memory leaks were introduced into the URB enqueue function in its error
+handling paths.
+
+xhci_urb_enqueue allocates urb_priv, but it doesn't free it if changing
+the control endpoint's max packet size fails or the bulk endpoint is in
+the middle of allocating or deallocating streams.
+
+xhci_urb_enqueue also doesn't free urb_priv if any of the four endpoint
+types' enqueue functions fail.  Instead, it expects those functions to
+free urb_priv if an error occurs.  However, the bulk, control, and
+interrupt enqueue functions do not free urb_priv if the endpoint ring is
+NULL.  It will, however, get freed if prepare_transfer() fails in those
+enqueue functions.
+
+Several of the error paths in the isochronous endpoint enqueue function
+also fail to free it.  xhci_queue_isoc_tx_prepare() doesn't free urb_priv
+if prepare_ring() indicates there is not enough room for all the
+isochronous TDs in this URB.  If individual isochronous TDs fail to be
+queued (perhaps due to an endpoint state change), urb_priv is also leaked.
+
+This argues that the freeing of urb_priv should be done in the function
+that allocated it, xhci_urb_enqueue.
+
+This patch looks rather ugly, but refactoring the code will have to wait
+because this patch needs to be backported to stable kernels.
+
+This patch should be backported to kernels as old as 2.6.36.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |    5 +----
+ drivers/usb/host/xhci.c      |   21 +++++++++++++++++----
+ 2 files changed, 18 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2508,11 +2508,8 @@ static int prepare_transfer(struct xhci_
+       if (td_index == 0) {
+               ret = usb_hcd_link_urb_to_ep(bus_to_hcd(urb->dev->bus), urb);
+-              if (unlikely(ret)) {
+-                      xhci_urb_free_priv(xhci, urb_priv);
+-                      urb->hcpriv = NULL;
++              if (unlikely(ret))
+                       return ret;
+-              }
+       }
+       td->urb = urb;
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1085,8 +1085,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+               if (urb->dev->speed == USB_SPEED_FULL) {
+                       ret = xhci_check_maxpacket(xhci, slot_id,
+                                       ep_index, urb);
+-                      if (ret < 0)
++                      if (ret < 0) {
++                              xhci_urb_free_priv(xhci, urb_priv);
++                              urb->hcpriv = NULL;
+                               return ret;
++                      }
+               }
+               /* We have a spinlock and interrupts disabled, so we must pass
+@@ -1097,6 +1100,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+                       goto dying;
+               ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
+                               slot_id, ep_index);
++              if (ret)
++                      goto free_priv;
+               spin_unlock_irqrestore(&xhci->lock, flags);
+       } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) {
+               spin_lock_irqsave(&xhci->lock, flags);
+@@ -1117,6 +1122,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+                       ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
+                                       slot_id, ep_index);
+               }
++              if (ret)
++                      goto free_priv;
+               spin_unlock_irqrestore(&xhci->lock, flags);
+       } else if (usb_endpoint_xfer_int(&urb->ep->desc)) {
+               spin_lock_irqsave(&xhci->lock, flags);
+@@ -1124,6 +1131,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+                       goto dying;
+               ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,
+                               slot_id, ep_index);
++              if (ret)
++                      goto free_priv;
+               spin_unlock_irqrestore(&xhci->lock, flags);
+       } else {
+               spin_lock_irqsave(&xhci->lock, flags);
+@@ -1131,18 +1140,22 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+                       goto dying;
+               ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb,
+                               slot_id, ep_index);
++              if (ret)
++                      goto free_priv;
+               spin_unlock_irqrestore(&xhci->lock, flags);
+       }
+ exit:
+       return ret;
+ dying:
+-      xhci_urb_free_priv(xhci, urb_priv);
+-      urb->hcpriv = NULL;
+       xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for "
+                       "non-responsive xHCI host.\n",
+                       urb->ep->desc.bEndpointAddress, urb);
++      ret = -ESHUTDOWN;
++free_priv:
++      xhci_urb_free_priv(xhci, urb_priv);
++      urb->hcpriv = NULL;
+       spin_unlock_irqrestore(&xhci->lock, flags);
+-      return -ESHUTDOWN;
++      return ret;
+ }
+ /* Get the right ring for the given URB.
diff --git a/queue-3.0/xhci-fix-port-u3-status-check-condition.patch b/queue-3.0/xhci-fix-port-u3-status-check-condition.patch
new file mode 100644 (file)
index 0000000..00cbe8a
--- /dev/null
@@ -0,0 +1,34 @@
+From 5ac04bf190e6f8b17238aef179ebd7f2bdfec919 Mon Sep 17 00:00:00 2001
+From: Andiry Xu <andiry.xu@amd.com>
+Date: Wed, 3 Aug 2011 16:46:48 +0800
+Subject: xHCI: fix port U3 status check condition
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+commit 5ac04bf190e6f8b17238aef179ebd7f2bdfec919 upstream.
+
+Fix the port U3 status check when Clear PORT_SUSPEND Feature.
+The port status should be masked with PORT_PLS_MASK to check if it's in
+U3 state.
+
+This should be backported to kernels as old as 2.6.37.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.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-hub.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -664,7 +664,7 @@ int xhci_hub_control(struct usb_hcd *hcd
+                       xhci_dbg(xhci, "PORTSC %04x\n", temp);
+                       if (temp & PORT_RESET)
+                               goto error;
+-                      if (temp & XDEV_U3) {
++                      if ((temp & PORT_PLS_MASK) == XDEV_U3) {
+                               if ((temp & PORT_PE) == 0)
+                                       goto error;
diff --git a/queue-3.0/xhci-handle-zero-length-isochronous-packets.patch b/queue-3.0/xhci-handle-zero-length-isochronous-packets.patch
new file mode 100644 (file)
index 0000000..78d66d1
--- /dev/null
@@ -0,0 +1,96 @@
+From 48df4a6fd8c40c0bbcbca2044f5f2bc75dcf6db1 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 12 Aug 2011 10:23:01 -0700
+Subject: xhci: Handle zero-length isochronous packets.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 48df4a6fd8c40c0bbcbca2044f5f2bc75dcf6db1 upstream.
+
+For a long time, the xHCI driver has had this note:
+       /* FIXME: Ignoring zero-length packets, can those happen? */
+
+It turns out that, yes, there are drivers that need to queue zero-length
+transfers for isochronous OUT transfers.  Without this patch, users will
+see kernel hang messages when a driver attempts to enqueue an isochronous
+URB with a zero length transfer (because count_isoc_trbs_needed will return
+zero for that TD, xhci_td->last_trb will never be set, and updating the
+dequeue pointer will cause an infinite loop).
+
+Matěj ran into this issue when using an NI Audio4DJ USB soundcard
+with the snd-usb-caiaq driver.  See
+       https://bugzilla.kernel.org/show_bug.cgi?id=40702
+
+Fix count_isoc_trbs_needed() to return 1 for zero-length transfers (thanks
+Alan on the math help).  Update the various TRB field calculations to deal
+with zero-length transfers.  We're still transferring one packet with a
+zero-length data payload, so the total_packet_count should be 1. The
+Transfer Burst Count (TBC) and Transfer Last Burst Packet Count (TLBPC)
+fields should be set to zero.
+
+This patch should be backported to kernels as old as 2.6.36.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Tested-by: Matěj Laitl <matej@laitl.cz>
+Cc: Daniel Mack <zonque@gmail.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |   21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2692,6 +2692,10 @@ static u32 xhci_v1_0_td_remainder(int ru
+ {
+       int packets_transferred;
++      /* One TRB with a zero-length data packet. */
++      if (running_total == 0 && trb_buff_len == 0)
++              return 0;
++
+       /* All the TRB queueing functions don't count the current TRB in
+        * running_total.
+        */
+@@ -3133,20 +3137,15 @@ static int count_isoc_trbs_needed(struct
+               struct urb *urb, int i)
+ {
+       int num_trbs = 0;
+-      u64 addr, td_len, running_total;
++      u64 addr, td_len;
+       addr = (u64) (urb->transfer_dma + urb->iso_frame_desc[i].offset);
+       td_len = urb->iso_frame_desc[i].length;
+-      running_total = TRB_MAX_BUFF_SIZE - (addr & (TRB_MAX_BUFF_SIZE - 1));
+-      running_total &= TRB_MAX_BUFF_SIZE - 1;
+-      if (running_total != 0)
+-              num_trbs++;
+-
+-      while (running_total < td_len) {
++      num_trbs = DIV_ROUND_UP(td_len + (addr & (TRB_MAX_BUFF_SIZE - 1)),
++                      TRB_MAX_BUFF_SIZE);
++      if (num_trbs == 0)
+               num_trbs++;
+-              running_total += TRB_MAX_BUFF_SIZE;
+-      }
+       return num_trbs;
+ }
+@@ -3258,9 +3257,11 @@ static int xhci_queue_isoc_tx(struct xhc
+               addr = start_addr + urb->iso_frame_desc[i].offset;
+               td_len = urb->iso_frame_desc[i].length;
+               td_remain_len = td_len;
+-              /* FIXME: Ignoring zero-length packets, can those happen? */
+               total_packet_count = roundup(td_len,
+                               le16_to_cpu(urb->ep->desc.wMaxPacketSize));
++              /* A zero-length transfer still involves at least one packet. */
++              if (total_packet_count == 0)
++                      total_packet_count++;
+               burst_count = xhci_get_burst_count(xhci, urb->dev, urb,
+                               total_packet_count);
+               residue = xhci_get_last_burst_packet_count(xhci,
diff --git a/queue-3.0/xhci-remove-tds-from-td-lists-when-urbs-are-canceled.patch b/queue-3.0/xhci-remove-tds-from-td-lists-when-urbs-are-canceled.patch
new file mode 100644 (file)
index 0000000..a81fd0e
--- /dev/null
@@ -0,0 +1,116 @@
+From 585df1d90cb07a02ca6c7a7d339e56e46d50dafb Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Tue, 2 Aug 2011 15:43:40 -0700
+Subject: xhci: Remove TDs from TD lists when URBs are canceled.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 585df1d90cb07a02ca6c7a7d339e56e46d50dafb upstream.
+
+When a driver tries to cancel an URB, and the host controller is dying,
+xhci_urb_dequeue will giveback the URB without removing the xhci_tds
+that comprise that URB from the td_list or the cancelled_td_list.  This
+can cause a race condition between the driver calling URB dequeue and
+the stop endpoint command watchdog timer.
+
+If the timer fires on a dying host, and a driver attempts to resubmit
+while the watchdog timer has dropped the xhci->lock to giveback a
+cancelled URB, URBs may be given back by the xhci_urb_dequeue() function.
+At that point, the URB's priv pointer will be freed and set to NULL, but
+the TDs will remain on the td_list.  This will cause an oops in
+xhci_giveback_urb_in_irq() when the watchdog timer attempts to loop
+through the endpoints' td_lists, giving back killed URBs.
+
+Make sure that xhci_urb_dequeue() removes TDs from the TD lists and
+canceled TD lists before it gives back the URB.
+
+This patch should be backported to kernels as old as 2.6.36.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |   16 ++++++++--------
+ drivers/usb/host/xhci.c      |    7 +++++++
+ 2 files changed, 15 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -744,7 +744,7 @@ remove_finished_td:
+                * so remove it from the endpoint ring's TD list.  Keep it in
+                * the cancelled TD list for URB completion later.
+                */
+-              list_del(&cur_td->td_list);
++              list_del_init(&cur_td->td_list);
+       }
+       last_unlinked_td = cur_td;
+       xhci_stop_watchdog_timer_in_irq(xhci, ep);
+@@ -772,7 +772,7 @@ remove_finished_td:
+       do {
+               cur_td = list_entry(ep->cancelled_td_list.next,
+                               struct xhci_td, cancelled_td_list);
+-              list_del(&cur_td->cancelled_td_list);
++              list_del_init(&cur_td->cancelled_td_list);
+               /* Clean up the cancelled URB */
+               /* Doesn't matter what we pass for status, since the core will
+@@ -880,9 +880,9 @@ void xhci_stop_endpoint_command_watchdog
+                               cur_td = list_first_entry(&ring->td_list,
+                                               struct xhci_td,
+                                               td_list);
+-                              list_del(&cur_td->td_list);
++                              list_del_init(&cur_td->td_list);
+                               if (!list_empty(&cur_td->cancelled_td_list))
+-                                      list_del(&cur_td->cancelled_td_list);
++                                      list_del_init(&cur_td->cancelled_td_list);
+                               xhci_giveback_urb_in_irq(xhci, cur_td,
+                                               -ESHUTDOWN, "killed");
+                       }
+@@ -891,7 +891,7 @@ void xhci_stop_endpoint_command_watchdog
+                                               &temp_ep->cancelled_td_list,
+                                               struct xhci_td,
+                                               cancelled_td_list);
+-                              list_del(&cur_td->cancelled_td_list);
++                              list_del_init(&cur_td->cancelled_td_list);
+                               xhci_giveback_urb_in_irq(xhci, cur_td,
+                                               -ESHUTDOWN, "killed");
+                       }
+@@ -1582,10 +1582,10 @@ td_cleanup:
+                       else
+                               *status = 0;
+               }
+-              list_del(&td->td_list);
++              list_del_init(&td->td_list);
+               /* Was this TD slated to be cancelled but completed anyway? */
+               if (!list_empty(&td->cancelled_td_list))
+-                      list_del(&td->cancelled_td_list);
++                      list_del_init(&td->cancelled_td_list);
+               urb_priv->td_cnt++;
+               /* Giveback the urb when all the tds are completed */
+@@ -3370,7 +3370,7 @@ cleanup:
+       /* Clean up a partially enqueued isoc transfer. */
+       for (i--; i >= 0; i--)
+-              list_del(&urb_priv->td[i]->td_list);
++              list_del_init(&urb_priv->td[i]->td_list);
+       /* Use the first TD as a temporary variable to turn the TDs we've queued
+        * into No-ops with a software-owned cycle bit. That way the hardware
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1252,6 +1252,13 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
+       if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
+               xhci_dbg(xhci, "HW died, freeing TD.\n");
+               urb_priv = urb->hcpriv;
++              for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
++                      td = urb_priv->td[i];
++                      if (!list_empty(&td->td_list))
++                              list_del_init(&td->td_list);
++                      if (!list_empty(&td->cancelled_td_list))
++                              list_del_init(&td->cancelled_td_list);
++              }
+               usb_hcd_unlink_urb_from_ep(hcd, urb);
+               spin_unlock_irqrestore(&xhci->lock, flags);
diff --git a/queue-3.0/xhci-report-usb2-port-in-resuming-as-suspend.patch b/queue-3.0/xhci-report-usb2-port-in-resuming-as-suspend.patch
new file mode 100644 (file)
index 0000000..8139a95
--- /dev/null
@@ -0,0 +1,78 @@
+From 8a8ff2f9399b23b968901f585ccb5a70a537c5ae Mon Sep 17 00:00:00 2001
+From: Andiry Xu <andiry.xu@amd.com>
+Date: Wed, 3 Aug 2011 16:46:49 +0800
+Subject: xHCI: report USB2 port in resuming as suspend
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+commit 8a8ff2f9399b23b968901f585ccb5a70a537c5ae upstream.
+
+When a USB2 port initiate a remote wakeup, software shall ensure that
+resume is signaled for at least 20ms, and then write '0' to the PLS field.
+According to this, xhci driver do the following things:
+
+1. When receive a remote wakeup event in irq_handler, set the resume_done
+   value as jiffies + 20ms, and modify rh_timer to poll root hub status at
+   that time;
+2. When receive a GetPortStatus request, if the jiffies is after the
+   resume_done value, clear the resume signal and resume_done.
+
+However, if usb_port_resume() is called before the rh_timer triggered, it
+will indicate the port as Suspend Cleared and skip the clear resume signal
+part. The device will fail the usb_get_status request in finish_port_resume(),
+and usbcore will try a reset-resume instead. Device will work OK after
+reset-resume, but resume_done value is not cleared in this case, and
+xhci_bus_suspend() will fail because when it finds a non-zero resume_done
+value, it will regard the port as resuming and return -EBUSY.
+
+This causes issue on some platforms that the system fail to suspend
+after remote wakeup from suspend by USB2 devices connected to xHCI port.
+
+To fix this issue, report the port status as suspend if the resume is
+signaling less that 20ms, and usb_port_resume() will wait 25ms and check
+port status again, so xHCI driver can clear the resume signaling and
+resume_done value.
+
+This should be backported to kernels as old as 2.6.37.
+
+Signed-off-by: Andiry Xu <andiry.xu@amd.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-hub.c |   15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -463,11 +463,12 @@ int xhci_hub_control(struct usb_hcd *hcd
+                                       && (temp & PORT_POWER))
+                               status |= USB_PORT_STAT_SUSPEND;
+               }
+-              if ((temp & PORT_PLS_MASK) == XDEV_RESUME) {
++              if ((temp & PORT_PLS_MASK) == XDEV_RESUME &&
++                              !DEV_SUPERSPEED(temp)) {
+                       if ((temp & PORT_RESET) || !(temp & PORT_PE))
+                               goto error;
+-                      if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies,
+-                                              bus_state->resume_done[wIndex])) {
++                      if (time_after_eq(jiffies,
++                                      bus_state->resume_done[wIndex])) {
+                               xhci_dbg(xhci, "Resume USB2 port %d\n",
+                                       wIndex + 1);
+                               bus_state->resume_done[wIndex] = 0;
+@@ -487,6 +488,14 @@ int xhci_hub_control(struct usb_hcd *hcd
+                               xhci_ring_device(xhci, slot_id);
+                               bus_state->port_c_suspend |= 1 << wIndex;
+                               bus_state->suspended_ports &= ~(1 << wIndex);
++                      } else {
++                              /*
++                               * The resume has been signaling for less than
++                               * 20ms. Report the port status as SUSPEND,
++                               * let the usbcore check port status again
++                               * and clear resume signaling later.
++                               */
++                              status |= USB_PORT_STAT_SUSPEND;
+                       }
+               }
+               if ((temp & PORT_PLS_MASK) == XDEV_U0