diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-26 15:33:38 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-26 15:33:38 -0700 |
commit | 419e42eb73f7618bc1e08cdd815df3bb114e575b (patch) | |
tree | 4b3625b85a3da8b11d7c0e18c9226cbc626a1402 | |
parent | d9d7239bdd99cea72c95444ce8f0935ec65c6a27 (diff) | |
download | stable-queue-419e42eb73f7618bc1e08cdd815df3bb114e575b.tar.gz |
3.0 patches
13 files changed, 1036 insertions, 0 deletions
diff --git a/queue-3.0/series b/queue-3.0/series index 0d226bf4bc..320a3bfe87 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -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 index 0000000000..88b845bb11 --- /dev/null +++ b/queue-3.0/usb-ehci-do-not-rely-on-port_suspend-to-stop-usb-resuming-in-ehci_bus_resume.patch @@ -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 index 0000000000..b60c1ab619 --- /dev/null +++ b/queue-3.0/usb-musb-cppi-fix-build-errors-due-to-dbg-and-missing.patch @@ -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 index 0000000000..869a05cfc1 --- /dev/null +++ b/queue-3.0/usb-option-add-yuga-device-id-to-driver.patch @@ -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 index 0000000000..4a05fcf6a2 --- /dev/null +++ b/queue-3.0/usb-option-driver-add-pid-of-huawei-vodafone-k3806.patch @@ -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 index 0000000000..dcbccec636 --- /dev/null +++ b/queue-3.0/usb-option-driver-add-pid-of-huawei-vodafone-k4605.patch @@ -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 index 0000000000..933a931303 --- /dev/null +++ b/queue-3.0/usb-option-driver-k3765-k4505-avoid-cdc_data-interface.patch @@ -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 index 0000000000..e4134e6ac4 --- /dev/null +++ b/queue-3.0/xhci-fix-failed-enqueue-in-the-middle-of-isoch-td.patch @@ -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 index 0000000000..b9780008e5 --- /dev/null +++ b/queue-3.0/xhci-fix-memory-leak-during-failed-enqueue.patch @@ -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 index 0000000000..00cbe8a245 --- /dev/null +++ b/queue-3.0/xhci-fix-port-u3-status-check-condition.patch @@ -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 index 0000000000..78d66d1eea --- /dev/null +++ b/queue-3.0/xhci-handle-zero-length-isochronous-packets.patch @@ -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 index 0000000000..a81fd0ee38 --- /dev/null +++ b/queue-3.0/xhci-remove-tds-from-td-lists-when-urbs-are-canceled.patch @@ -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 index 0000000000..8139a95916 --- /dev/null +++ b/queue-3.0/xhci-report-usb2-port-in-resuming-as-suspend.patch @@ -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 |