diff options
22 files changed, 2130 insertions, 1 deletions
@@ -90,6 +90,8 @@ tty/serial-add-driver-for-the-altera-jtag-uart.patch tty/serial-add-driver-for-the-altera-uart.patch tty/tty-fix-obsolete-comment-on-tty_insert_flip_string_fixed_flag.patch tty/serial-bfin_sport_uart-use-resource-size-to-fix-off-by-one-error.patch +tty/serial-isicomm-handle-running-out-of-slots.patch +tty/serial-apbuart-let-boards-without-apbuart-boot.patch ################################### @@ -258,6 +260,24 @@ usb/usb-gadget-f_fs.c-needs-to-include-pagemap.h.patch usb/usb-xhci-transfer-ring-link-trb-activation-change.patch usb/usb-xhci-fix-wrong-usage-of-macro-trb_type.patch usb/usb-fix-interface-runtime-pm-settings.patch +usb/usb-ehci-omap-fix-resume-failures-after-bus-suspend.patch +usb/usb-add-missing-in-map_urb_for_dma.patch +usb/usb-gadget-f_mass_storage-fix-in-error-recovery.patch +usb/usb-remove-usb_find_device.patch +usb/usb-xhci-remove-the-arbitrary-limit-of-15-xhci-ports.patch +usb/usb-fix-functionfs-for-config_net-disabled.patch +usb/usb-ehci-clear-phcd-before-resuming.patch +usb/usb-ehci-fix-controller-wakeup-flag-settings-during-suspend.patch +usb/usb-ir-usb-fix-double-free.patch +usb/usb-ir-usb-allow-custom-bulk-buffer-size-without-reallocation.patch +usb/usb-ir-usb-fix-set_termios-race.patch +usb/usb-ir-usb-reimplement-using-generic-framework.patch +usb/usb-ipw-clean-up-dtr-rts-handling.patch +usb/usb-ipw-remove-dummy-port_probe-and-port_remove.patch +usb/usb-ipw-reimplement-using-generic-framework.patch +usb/usb-io_edgeport-use-kzalloc.patch +usb/usb-cp210x-remove-redundant-disconnect.patch +usb/usb-fhci-cq_get-should-check-kfifo_out-s-return-value.patch # this goes in last. usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch diff --git a/tty/serial-apbuart-let-boards-without-apbuart-boot.patch b/tty/serial-apbuart-let-boards-without-apbuart-boot.patch new file mode 100644 index 00000000000000..a1acb9e93dceae --- /dev/null +++ b/tty/serial-apbuart-let-boards-without-apbuart-boot.patch @@ -0,0 +1,130 @@ +From avorontsov@mvista.com Fri May 14 12:17:06 2010 +From: Anton Vorontsov <avorontsov@mvista.com> +Date: Fri, 14 May 2010 18:19:49 +0400 +Subject: serial: apbuart: Let boards without apbuart boot +To: David Miller <davem@davemloft.net>, Greg Kroah-Hartman <gregkh@suse.de> +Cc: Kristoffer Glembo <kristoffer@gaisler.com>, linux-kernel@vger.kernel.org +Message-ID: <20100514141949.GA9244@oksana.dev.rtsoft.ru> +Content-Disposition: inline + + +This patch fixes the following oops: + + Unable to handle kernel paging request for data at address 0x00000000 + Faulting instruction address: 0xc016dea8 + Oops: Kernel access of bad area, sig: 11 [#1] + P1020 RDB + last sysfs file: + NIP: c016dea8 LR: c016dea0 CTR: c0010948 + REGS: c033fea0 TRAP: 0300 Not tainted (2.6.34-rc7-00108-g83b5177-dirty) + [...] + NIP [c016dea8] grlib_apbuart_configure+0xd0/0x3bc + LR [c016dea0] grlib_apbuart_configure+0xc8/0x3bc + Call Trace: + [c033ff50] [c016dea0] grlib_apbuart_configure+0xc8/0x3bc (unreliable) + [c033ffa0] [c0316144] apbuart_console_init+0x10/0x34 + [c033ffb0] [c0314a10] console_init+0x40/0x5c + +There's no apbuart on P1020 boards, and what's worse, there's no +clock-frequency property for it. The driver didn't handle this +case, which resulted in the oops above. Once we fix this, the +next oops pops up: + + Unable to handle kernel paging request for data at address 0x00000030 + Faulting instruction address: 0xc0166ecc + Oops: Kernel access of bad area, sig: 11 [#1] + P1020 RDB + [...] + NIP [c0166ecc] uart_set_options+0xd0/0x164 + LR [c0166e38] uart_set_options+0x3c/0x164 + Call Trace: + [c033fef0] [c0330000] 0xc0330000 (unreliable) + [c033ff50] [c03160dc] apbuart_console_setup+0xa8/0x100 + [c033ff70] [c003d668] register_console+0x338/0x3ec + [c033ffa0] [c0316154] apbuart_console_init+0x20/0x34 + [c033ffb0] [c0314a10] console_init+0x40/0x5c + [c033ffc0] [c0300968] start_kernel+0x12c/0x234 + [c033fff0] [c0000398] skpinv+0x2b0/0x2ec + +And that one is because the driver tries to register the console +even if there were no matches in grlib_apbuart_configure(). + +While at it, also annotate grlib_apbuart_configure() with __init, +that fixes several section mismatches: + + Section mismatch in reference from the function + grlib_apbuart_configure() to the variable .init.data:apbuart_match + The function grlib_apbuart_configure() references the variable + __initdata apbuart_match. + +Signed-off-by: Anton Vorontsov <avorontsov@mvista.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/serial/apbuart.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +--- a/drivers/serial/apbuart.c ++++ b/drivers/serial/apbuart.c +@@ -520,11 +520,16 @@ static struct console grlib_apbuart_cons + }; + + +-static void grlib_apbuart_configure(void); ++static int __init grlib_apbuart_configure(void); + + static int __init apbuart_console_init(void) + { +- grlib_apbuart_configure(); ++ int ret; ++ ++ ret = grlib_apbuart_configure(); ++ if (ret) ++ return ret; ++ + register_console(&grlib_apbuart_console); + return 0; + } +@@ -593,7 +598,7 @@ static struct of_platform_driver grlib_a + }; + + +-static void grlib_apbuart_configure(void) ++static int __init grlib_apbuart_configure(void) + { + static int enum_done; + struct device_node *np, *rp; +@@ -606,12 +611,14 @@ static void grlib_apbuart_configure(void + struct amba_prom_registers *regs; + + if (enum_done) +- return; ++ return -ENODEV; + + /* Get bus frequency */ + rp = of_find_node_by_path("/"); + rp = of_get_next_child(rp, NULL); + prop = of_get_property(rp, "clock-frequency", NULL); ++ if (!prop) ++ return -ENODEV; + freq_khz = *prop; + + line = 0; +@@ -629,7 +636,7 @@ static void grlib_apbuart_configure(void + d = *device; + + if (!irqs || !regs) +- return; ++ return -ENODEV; + + grlib_apbuart_nodes[line] = np; + +@@ -658,6 +665,8 @@ static void grlib_apbuart_configure(void + enum_done = 1; + + grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line; ++ ++ return line ? 0 : -ENODEV; + } + + static int __init grlib_apbuart_init(void) diff --git a/tty/serial-isicomm-handle-running-out-of-slots.patch b/tty/serial-isicomm-handle-running-out-of-slots.patch new file mode 100644 index 00000000000000..3495882381d85b --- /dev/null +++ b/tty/serial-isicomm-handle-running-out-of-slots.patch @@ -0,0 +1,49 @@ +From error27@gmail.com Fri May 14 12:00:10 2010 +From: Dan Carpenter <error27@gmail.com> +Date: Fri, 7 May 2010 10:30:41 +0200 +Subject: serial: isicomm: handle running out of slots +To: Jiri Slaby <jirislaby@gmail.com> +Cc: Alan Cox <alan@linux.intel.com>, Greg Kroah-Hartman <gregkh@suse.de>, linux-kernel@vger.kernel.org, kernel-janitors@vger.kernel.org +Message-ID: <20100507083041.GU27064@bicker> +Content-Disposition: inline + + +This patch makes it return -ENODEV if we run out of empty slots in the +probe function. It's unlikely to happen, but it makes the static +checkers happy. + +Signed-off-by: Dan Carpenter <error27@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/char/isicom.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/char/isicom.c ++++ b/drivers/char/isicom.c +@@ -1573,11 +1573,16 @@ static int __devinit isicom_probe(struct + dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device); + + /* allot the first empty slot in the array */ +- for (index = 0; index < BOARD_COUNT; index++) ++ for (index = 0; index < BOARD_COUNT; index++) { + if (isi_card[index].base == 0) { + board = &isi_card[index]; + break; + } ++ } ++ if (index == BOARD_COUNT) { ++ retval = -ENODEV; ++ goto err_disable; ++ } + + board->index = index; + board->base = pci_resource_start(pdev, 3); +@@ -1624,6 +1629,7 @@ errunrr: + errdec: + board->base = 0; + card_count--; ++err_disable: + pci_disable_device(pdev); + err: + return retval; diff --git a/usb/usb-add-missing-in-map_urb_for_dma.patch b/usb/usb-add-missing-in-map_urb_for_dma.patch new file mode 100644 index 00000000000000..9a6f985ac57f52 --- /dev/null +++ b/usb/usb-add-missing-in-map_urb_for_dma.patch @@ -0,0 +1,43 @@ +From tom.leiming@gmail.com Fri May 14 12:02:26 2010 +From: tom.leiming@gmail.com +Date: Wed, 12 May 2010 23:38:12 +0800 +Subject: USB: add missing "{}" in map_urb_for_dma +To: greg@kroah.com, stern@rowland.harvard.edu +Cc: linux-usb@vger.kernel.org, Ming Lei <tom.leiming@gmail.com> +Message-ID: <1273678692-19602-1-git-send-email-tom.leiming@gmail.com> + + +From: Ming Lei <tom.leiming@gmail.com> + +Obviously, {} is needed in the branch of + "else if (hcd->driver->flags & HCD_LOCAL_MEM)" +for handling of setup packet mapping. + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hcd.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -1327,7 +1327,7 @@ static int map_urb_for_dma(struct usb_hc + urb->setup_dma)) + return -EAGAIN; + urb->transfer_flags |= URB_SETUP_MAP_SINGLE; +- } else if (hcd->driver->flags & HCD_LOCAL_MEM) ++ } else if (hcd->driver->flags & HCD_LOCAL_MEM) { + ret = hcd_alloc_coherent( + urb->dev->bus, mem_flags, + &urb->setup_dma, +@@ -1337,6 +1337,7 @@ static int map_urb_for_dma(struct usb_hc + if (ret) + return ret; + urb->transfer_flags |= URB_SETUP_MAP_LOCAL; ++ } + } + + dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; diff --git a/usb/usb-cp210x-remove-redundant-disconnect.patch b/usb/usb-cp210x-remove-redundant-disconnect.patch new file mode 100644 index 00000000000000..4b5a8e4aa4c8ac --- /dev/null +++ b/usb/usb-cp210x-remove-redundant-disconnect.patch @@ -0,0 +1,85 @@ +From jhovold@gmail.com Fri May 14 12:15:54 2010 +From: Johan Hovold <jhovold@gmail.com> +Date: Thu, 13 May 2010 22:25:09 +0200 +Subject: USB: cp210x: remove redundant disconnect() +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com> +Message-ID: <1273782309-18670-1-git-send-email-jhovold@gmail.com> + + +Remove cp210x_disconnect which is used to kill traffic although this is +already handled by the generic framework. + +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/cp210x.c | 29 ----------------------------- + 1 file changed, 29 deletions(-) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -34,7 +34,6 @@ + * Function Prototypes + */ + static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *); +-static void cp210x_cleanup(struct usb_serial_port *); + static void cp210x_close(struct usb_serial_port *); + static void cp210x_get_termios(struct tty_struct *, + struct usb_serial_port *port); +@@ -49,7 +48,6 @@ static int cp210x_tiocmset_port(struct u + unsigned int, unsigned int); + static void cp210x_break_ctl(struct tty_struct *, int); + static int cp210x_startup(struct usb_serial *); +-static void cp210x_disconnect(struct usb_serial *); + static void cp210x_dtr_rts(struct usb_serial_port *p, int on); + static int cp210x_carrier_raised(struct usb_serial_port *p); + +@@ -147,7 +145,6 @@ static struct usb_serial_driver cp210x_d + .tiocmget = cp210x_tiocmget, + .tiocmset = cp210x_tiocmset, + .attach = cp210x_startup, +- .disconnect = cp210x_disconnect, + .dtr_rts = cp210x_dtr_rts, + .carrier_raised = cp210x_carrier_raised + }; +@@ -391,21 +388,6 @@ static int cp210x_open(struct tty_struct + return 0; + } + +-static void cp210x_cleanup(struct usb_serial_port *port) +-{ +- struct usb_serial *serial = port->serial; +- +- dbg("%s - port %d", __func__, port->number); +- +- if (serial->dev) { +- /* shutdown any bulk reads that might be going on */ +- if (serial->num_bulk_out) +- usb_kill_urb(port->write_urb); +- if (serial->num_bulk_in) +- usb_kill_urb(port->read_urb); +- } +-} +- + static void cp210x_close(struct usb_serial_port *port) + { + dbg("%s - port %d", __func__, port->number); +@@ -794,17 +776,6 @@ static int cp210x_startup(struct usb_ser + return 0; + } + +-static void cp210x_disconnect(struct usb_serial *serial) +-{ +- int i; +- +- dbg("%s", __func__); +- +- /* Stop reads and writes on all ports */ +- for (i = 0; i < serial->num_ports; ++i) +- cp210x_cleanup(serial->port[i]); +-} +- + static int __init cp210x_init(void) + { + int retval; diff --git a/usb/usb-ehci-clear-phcd-before-resuming.patch b/usb/usb-ehci-clear-phcd-before-resuming.patch new file mode 100644 index 00000000000000..c7c4e71bcce302 --- /dev/null +++ b/usb/usb-ehci-clear-phcd-before-resuming.patch @@ -0,0 +1,57 @@ +From alek.du@intel.com Fri May 14 12:11:52 2010 +From: "Du, Alek" <alek.du@intel.com> +Date: Mon, 10 May 2010 11:17:49 +0800 +Subject: USB: EHCI: clear PHCD before resuming +Cc: Alan Stern <stern@rowland.harvard.edu> +Message-ID: <20100510111749.6c8c7df8@dxy2> + + +From: Alek Du <alek.du@intel.com> + +This is a bug fix for PHCD (phy clock disable) low power feature: +After PHCD is set, any write to PORTSC register is illegal, so when +resume ports, clear PHCD bit first. + +Signed-off-by: Alek Du <alek.du@intel.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Alan Stern <stern@rowland.harvard.edu> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/ehci-hub.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -294,6 +294,16 @@ static int ehci_bus_resume (struct usb_h + /* manually resume the ports we suspended during bus_suspend() */ + i = HCS_N_PORTS (ehci->hcs_params); + while (i--) { ++ /* clear phy low power mode before resume */ ++ if (ehci->has_hostpc) { ++ u32 __iomem *hostpc_reg = ++ (u32 __iomem *)((u8 *)ehci->regs ++ + HOSTPC0 + 4 * (i & 0xff)); ++ temp = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, temp & ~HOSTPC_PHCD, ++ hostpc_reg); ++ mdelay(5); ++ } + temp = ehci_readl(ehci, &ehci->regs->port_status [i]); + temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + if (test_bit(i, &ehci->bus_suspended) && +@@ -678,6 +688,13 @@ static int ehci_hub_control ( + if (temp & PORT_SUSPEND) { + if ((temp & PORT_PE) == 0) + goto error; ++ /* clear phy low power mode before resume */ ++ if (hostpc_reg) { ++ temp1 = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, ++ hostpc_reg); ++ mdelay(5); ++ } + /* resume signaling for 20 msec */ + temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + ehci_writel(ehci, temp | PORT_RESUME, diff --git a/usb/usb-ehci-fix-controller-wakeup-flag-settings-during-suspend.patch b/usb/usb-ehci-fix-controller-wakeup-flag-settings-during-suspend.patch new file mode 100644 index 00000000000000..9a1d0af1f37221 --- /dev/null +++ b/usb/usb-ehci-fix-controller-wakeup-flag-settings-during-suspend.patch @@ -0,0 +1,392 @@ +From stern@rowland.harvard.edu Fri May 14 12:12:30 2010 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Wed, 12 May 2010 18:21:35 -0400 (EDT) +Subject: USB: EHCI: fix controller wakeup flag settings during suspend +To: Greg KH <greg@kroah.com> +Cc: Ondrej Zary <linux@rainbow-software.org>, Alek Du <alek.du@intel.com>, USB list <linux-usb@vger.kernel.org> +Message-ID: <Pine.LNX.4.44L0.1005121818360.1353-100000@iolanthe.rowland.org> + + +This patch (as1380) fixes a bug in the wakeup settings for EHCI host +controllers. When the controller is suspended, if it isn't enabled +for remote wakeup then we have to turn off all the port wakeup flags. +Disabling PCI PME# isn't good enough, because some systems (Intel) +evidently use alternate wakeup signalling paths. + +In addition, the patch improves the handling of the Intel Moorestown +hardware by performing various power-up and power-down delays just +once instead of once for each port (i.e., the delays are moved outside +of the port loops). This requires extra code, but the total delay +time is reduced. + +There are also a few additional minor cleanups. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Reported-by: Ondrej Zary <linux@rainbow-software.org> +CC: Alek Du <alek.du@intel.com> +CC: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/ehci-au1xxx.c | 16 --- + drivers/usb/host/ehci-fsl.c | 2 + drivers/usb/host/ehci-hub.c | 173 +++++++++++++++++++++++++++++------------ + drivers/usb/host/ehci-pci.c | 15 --- + drivers/usb/host/ehci.h | 10 ++ + 5 files changed, 145 insertions(+), 71 deletions(-) + +--- a/drivers/usb/host/ehci-au1xxx.c ++++ b/drivers/usb/host/ehci-au1xxx.c +@@ -224,26 +224,17 @@ static int ehci_hcd_au1xxx_drv_suspend(s + msleep(10); + + /* Root hub was already suspended. Disable irq emission and +- * mark HW unaccessible, bail out if RH has been resumed. Use +- * the spinlock to properly synchronize with possible pending +- * RH suspend or resume activity. +- * +- * This is still racy as hcd->state is manipulated outside of +- * any locks =P But that will be a different fix. ++ * mark HW unaccessible. The PM and USB cores make sure that ++ * the root hub is either suspended or stopped. + */ + spin_lock_irqsave(&ehci->lock, flags); +- if (hcd->state != HC_STATE_SUSPENDED) { +- rc = -EINVAL; +- goto bail; +- } ++ ehci_prepare_ports_for_controller_suspend(ehci); + ehci_writel(ehci, 0, &ehci->regs->intr_enable); + (void)ehci_readl(ehci, &ehci->regs->intr_enable); + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + au1xxx_stop_ehc(); +- +-bail: + spin_unlock_irqrestore(&ehci->lock, flags); + + // could save FLADJ in case of Vaux power loss +@@ -273,6 +264,7 @@ static int ehci_hcd_au1xxx_drv_resume(st + if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { + int mask = INTR_MASK; + ++ ehci_prepare_ports_for_controller_resume(ehci); + if (!hcd->self.root_hub->do_remote_wakeup) + mask &= ~STS_PCD; + ehci_writel(ehci, mask, &ehci->regs->intr_enable); +--- a/drivers/usb/host/ehci-fsl.c ++++ b/drivers/usb/host/ehci-fsl.c +@@ -313,6 +313,7 @@ static int ehci_fsl_drv_suspend(struct d + struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); + void __iomem *non_ehci = hcd->regs; + ++ ehci_prepare_ports_for_controller_suspend(ehci); + if (!fsl_deep_sleep()) + return 0; + +@@ -327,6 +328,7 @@ static int ehci_fsl_drv_resume(struct de + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + void __iomem *non_ehci = hcd->regs; + ++ ehci_prepare_ports_for_controller_resume(ehci); + if (!fsl_deep_sleep()) + return 0; + +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -106,12 +106,75 @@ static void ehci_handover_companion_port + ehci->owned_ports = 0; + } + ++static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, ++ bool suspending) ++{ ++ int port; ++ u32 temp; ++ ++ /* If remote wakeup is enabled for the root hub but disabled ++ * for the controller, we must adjust all the port wakeup flags ++ * when the controller is suspended or resumed. In all other ++ * cases they don't need to be changed. ++ */ ++ if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || ++ device_may_wakeup(ehci_to_hcd(ehci)->self.controller)) ++ return; ++ ++ /* clear phy low-power mode before changing wakeup flags */ ++ if (ehci->has_hostpc) { ++ port = HCS_N_PORTS(ehci->hcs_params); ++ while (port--) { ++ u32 __iomem *hostpc_reg; ++ ++ hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs ++ + HOSTPC0 + 4 * port); ++ temp = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); ++ } ++ msleep(5); ++ } ++ ++ port = HCS_N_PORTS(ehci->hcs_params); ++ while (port--) { ++ u32 __iomem *reg = &ehci->regs->port_status[port]; ++ u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; ++ u32 t2 = t1 & ~PORT_WAKE_BITS; ++ ++ /* If we are suspending the controller, clear the flags. ++ * If we are resuming the controller, set the wakeup flags. ++ */ ++ if (!suspending) { ++ if (t1 & PORT_CONNECT) ++ t2 |= PORT_WKOC_E | PORT_WKDISC_E; ++ else ++ t2 |= PORT_WKOC_E | PORT_WKCONN_E; ++ } ++ ehci_vdbg(ehci, "port %d, %08x -> %08x\n", ++ port + 1, t1, t2); ++ ehci_writel(ehci, t2, reg); ++ } ++ ++ /* enter phy low-power mode again */ ++ if (ehci->has_hostpc) { ++ port = HCS_N_PORTS(ehci->hcs_params); ++ while (port--) { ++ u32 __iomem *hostpc_reg; ++ ++ hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs ++ + HOSTPC0 + 4 * port); ++ temp = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); ++ } ++ } ++} ++ + static int ehci_bus_suspend (struct usb_hcd *hcd) + { + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + int port; + int mask; +- u32 __iomem *hostpc_reg = NULL; ++ int changed; + + ehci_dbg(ehci, "suspend root hub\n"); + +@@ -155,15 +218,13 @@ static int ehci_bus_suspend (struct usb_ + */ + ehci->bus_suspended = 0; + ehci->owned_ports = 0; ++ changed = 0; + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { + u32 __iomem *reg = &ehci->regs->port_status [port]; + u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; +- u32 t2 = t1; ++ u32 t2 = t1 & ~PORT_WAKE_BITS; + +- if (ehci->has_hostpc) +- hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs +- + HOSTPC0 + 4 * (port & 0xff)); + /* keep track of which ports we suspend */ + if (t1 & PORT_OWNER) + set_bit(port, &ehci->owned_ports); +@@ -172,40 +233,45 @@ static int ehci_bus_suspend (struct usb_ + set_bit(port, &ehci->bus_suspended); + } + +- /* enable remote wakeup on all ports */ ++ /* enable remote wakeup on all ports, if told to do so */ + if (hcd->self.root_hub->do_remote_wakeup) { + /* only enable appropriate wake bits, otherwise the + * hardware can not go phy low power mode. If a race + * condition happens here(connection change during bits + * set), the port change detection will finally fix it. + */ +- if (t1 & PORT_CONNECT) { ++ if (t1 & PORT_CONNECT) + t2 |= PORT_WKOC_E | PORT_WKDISC_E; +- t2 &= ~PORT_WKCONN_E; +- } else { ++ else + t2 |= PORT_WKOC_E | PORT_WKCONN_E; +- t2 &= ~PORT_WKDISC_E; +- } +- } else +- t2 &= ~PORT_WAKE_BITS; ++ } + + if (t1 != t2) { + ehci_vdbg (ehci, "port %d, %08x -> %08x\n", + port + 1, t1, t2); + ehci_writel(ehci, t2, reg); +- if (hostpc_reg) { +- u32 t3; ++ changed = 1; ++ } ++ } + +- spin_unlock_irq(&ehci->lock); +- msleep(5);/* 5ms for HCD enter low pwr mode */ +- spin_lock_irq(&ehci->lock); +- t3 = ehci_readl(ehci, hostpc_reg); +- ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); +- t3 = ehci_readl(ehci, hostpc_reg); +- ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", ++ if (changed && ehci->has_hostpc) { ++ spin_unlock_irq(&ehci->lock); ++ msleep(5); /* 5 ms for HCD to enter low-power mode */ ++ spin_lock_irq(&ehci->lock); ++ ++ port = HCS_N_PORTS(ehci->hcs_params); ++ while (port--) { ++ u32 __iomem *hostpc_reg; ++ u32 t3; ++ ++ hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs ++ + HOSTPC0 + 4 * port); ++ t3 = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); ++ t3 = ehci_readl(ehci, hostpc_reg); ++ ehci_dbg(ehci, "Port %d phy low-power mode %s\n", + port, (t3 & HOSTPC_PHCD) ? + "succeeded" : "failed"); +- } + } + } + +@@ -291,19 +357,28 @@ static int ehci_bus_resume (struct usb_h + msleep(8); + spin_lock_irq(&ehci->lock); + ++ /* clear phy low-power mode before resume */ ++ if (ehci->bus_suspended && ehci->has_hostpc) { ++ i = HCS_N_PORTS(ehci->hcs_params); ++ while (i--) { ++ if (test_bit(i, &ehci->bus_suspended)) { ++ u32 __iomem *hostpc_reg; ++ ++ hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs ++ + HOSTPC0 + 4 * i); ++ temp = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, temp & ~HOSTPC_PHCD, ++ hostpc_reg); ++ } ++ } ++ spin_unlock_irq(&ehci->lock); ++ msleep(5); ++ spin_lock_irq(&ehci->lock); ++ } ++ + /* manually resume the ports we suspended during bus_suspend() */ + i = HCS_N_PORTS (ehci->hcs_params); + while (i--) { +- /* clear phy low power mode before resume */ +- if (ehci->has_hostpc) { +- u32 __iomem *hostpc_reg = +- (u32 __iomem *)((u8 *)ehci->regs +- + HOSTPC0 + 4 * (i & 0xff)); +- temp = ehci_readl(ehci, hostpc_reg); +- ehci_writel(ehci, temp & ~HOSTPC_PHCD, +- hostpc_reg); +- mdelay(5); +- } + temp = ehci_readl(ehci, &ehci->regs->port_status [i]); + temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + if (test_bit(i, &ehci->bus_suspended) && +@@ -685,23 +760,25 @@ static int ehci_hub_control ( + goto error; + if (ehci->no_selective_suspend) + break; +- if (temp & PORT_SUSPEND) { +- if ((temp & PORT_PE) == 0) +- goto error; +- /* clear phy low power mode before resume */ +- if (hostpc_reg) { +- temp1 = ehci_readl(ehci, hostpc_reg); +- ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, ++ if (!(temp & PORT_SUSPEND)) ++ break; ++ if ((temp & PORT_PE) == 0) ++ goto error; ++ ++ /* clear phy low-power mode before resume */ ++ if (hostpc_reg) { ++ temp1 = ehci_readl(ehci, hostpc_reg); ++ ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, + hostpc_reg); +- mdelay(5); +- } +- /* resume signaling for 20 msec */ +- temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); +- ehci_writel(ehci, temp | PORT_RESUME, +- status_reg); +- ehci->reset_done [wIndex] = jiffies +- + msecs_to_jiffies (20); ++ spin_unlock_irqrestore(&ehci->lock, flags); ++ msleep(5);/* wait to leave low-power mode */ ++ spin_lock_irqsave(&ehci->lock, flags); + } ++ /* resume signaling for 20 msec */ ++ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); ++ ehci_writel(ehci, temp | PORT_RESUME, status_reg); ++ ehci->reset_done[wIndex] = jiffies ++ + msecs_to_jiffies(20); + break; + case USB_PORT_FEAT_C_SUSPEND: + clear_bit(wIndex, &ehci->port_c_suspend); +--- a/drivers/usb/host/ehci-pci.c ++++ b/drivers/usb/host/ehci-pci.c +@@ -287,23 +287,15 @@ static int ehci_pci_suspend(struct usb_h + msleep(10); + + /* Root hub was already suspended. Disable irq emission and +- * mark HW unaccessible, bail out if RH has been resumed. Use +- * the spinlock to properly synchronize with possible pending +- * RH suspend or resume activity. +- * +- * This is still racy as hcd->state is manipulated outside of +- * any locks =P But that will be a different fix. ++ * mark HW unaccessible. The PM and USB cores make sure that ++ * the root hub is either suspended or stopped. + */ + spin_lock_irqsave (&ehci->lock, flags); +- if (hcd->state != HC_STATE_SUSPENDED) { +- rc = -EINVAL; +- goto bail; +- } ++ ehci_prepare_ports_for_controller_suspend(ehci); + ehci_writel(ehci, 0, &ehci->regs->intr_enable); + (void)ehci_readl(ehci, &ehci->regs->intr_enable); + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); +- bail: + spin_unlock_irqrestore (&ehci->lock, flags); + + // could save FLADJ in case of Vaux power loss +@@ -333,6 +325,7 @@ static int ehci_pci_resume(struct usb_hc + !hibernated) { + int mask = INTR_MASK; + ++ ehci_prepare_ports_for_controller_resume(ehci); + if (!hcd->self.root_hub->do_remote_wakeup) + mask &= ~STS_PCD; + ehci_writel(ehci, mask, &ehci->regs->intr_enable); +--- a/drivers/usb/host/ehci.h ++++ b/drivers/usb/host/ehci.h +@@ -536,6 +536,16 @@ struct ehci_fstn { + + /*-------------------------------------------------------------------------*/ + ++/* Prepare the PORTSC wakeup flags during controller suspend/resume */ ++ ++#define ehci_prepare_ports_for_controller_suspend(ehci) \ ++ ehci_adjust_port_wakeup_flags(ehci, true); ++ ++#define ehci_prepare_ports_for_controller_resume(ehci) \ ++ ehci_adjust_port_wakeup_flags(ehci, false); ++ ++/*-------------------------------------------------------------------------*/ ++ + #ifdef CONFIG_USB_EHCI_ROOT_HUB_TT + + /* diff --git a/usb/usb-ehci-omap-fix-resume-failures-after-bus-suspend.patch b/usb/usb-ehci-omap-fix-resume-failures-after-bus-suspend.patch new file mode 100644 index 00000000000000..b7406d082f8cd7 --- /dev/null +++ b/usb/usb-ehci-omap-fix-resume-failures-after-bus-suspend.patch @@ -0,0 +1,61 @@ +From gadiyar@ti.com Fri May 14 11:59:46 2010 +From: Anand Gadiyar <gadiyar@ti.com> +Date: Thu, 6 May 2010 20:09:48 +0530 +Subject: USB: ehci-omap: Fix resume failures after bus suspend +To: linux-usb@vger.kernel.org, Greg KH <gregkh@suse.de> +Cc: Anand Gadiyar <gadiyar@ti.com> +Message-ID: <1273156788-22853-1-git-send-email-gadiyar@ti.com> + + +An undocumented "feature" in the OMAP3 EHCI controller causes +suspended ports to be taken out of suspend when the USBCMD.Run/Stop +bit is cleared (this bit is normally cleared when ehci_bus_suspend +is called). + +This "feature" breaks suspend-resume if the root-hub is allowed +to suspend. (The controller thinks it is in resume, and the PHY +thinks it is still in suspend). + +There is an undocumented register bit that can be used to disable +this feature and restore normal behavior. Set this bit so +suspend-resume can work normally. + +Tested on OMAP3 SDPs with the NXP ISP1504 and NXP ISP1703 PHYs. + +Signed-off-by: Anand Gadiyar <gadiyar@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/ehci-omap.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/usb/host/ehci-omap.c ++++ b/drivers/usb/host/ehci-omap.c +@@ -116,6 +116,8 @@ + #define OMAP_UHH_DEBUG_CSR (0x44) + + /* EHCI Register Set */ ++#define EHCI_INSNREG04 (0xA0) ++#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5) + #define EHCI_INSNREG05_ULPI (0xA4) + #define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31 + #define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24 +@@ -382,6 +384,18 @@ static int omap_start_ehc(struct ehci_hc + dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); + + ++ /* ++ * An undocumented "feature" in the OMAP3 EHCI controller, ++ * causes suspended ports to be taken out of suspend when ++ * the USBCMD.Run/Stop bit is cleared (for example when ++ * we do ehci_bus_suspend). ++ * This breaks suspend-resume if the root-hub is allowed ++ * to suspend. Writing 1 to this undocumented register bit ++ * disables this feature and restores normal behavior. ++ */ ++ ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04, ++ EHCI_INSNREG04_DISABLE_UNSUSPEND); ++ + if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) || + (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) || + (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) { diff --git a/usb/usb-fhci-cq_get-should-check-kfifo_out-s-return-value.patch b/usb/usb-fhci-cq_get-should-check-kfifo_out-s-return-value.patch new file mode 100644 index 00000000000000..3eb636f26a5c3a --- /dev/null +++ b/usb/usb-fhci-cq_get-should-check-kfifo_out-s-return-value.patch @@ -0,0 +1,57 @@ +From avorontsov@mvista.com Fri May 14 12:16:13 2010 +From: Anton Vorontsov <avorontsov@mvista.com> +Date: Fri, 14 May 2010 18:33:18 +0400 +Subject: USB: FHCI: cq_get() should check kfifo_out()'s return value +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, linuxppc-dev@ozlabs.org +Message-ID: <20100514143318.GA14034@oksana.dev.rtsoft.ru> +Content-Disposition: inline + + +Since commit 7acd72eb85f1c7a15e8b5eb554994949241737f1 ("kfifo: rename +kfifo_put... into kfifo_in... and kfifo_get... into kfifo_out..."), +kfifo_out() is marked __must_check, and that causes gcc to produce +lots of warnings like this: + + CC drivers/usb/host/fhci-mem.o +In file included from drivers/usb/host/fhci-hcd.c:34: +drivers/usb/host/fhci.h: In function 'cq_get': +drivers/usb/host/fhci.h:520: warning: ignoring return value of 'kfifo_out', declared with attribute warn_unused_result +... + +This patch fixes the issue by properly checking the return value. + +Signed-off-by: Anton Vorontsov <avorontsov@mvista.com> +Cc: stable <stable@kernel.org> [.33 and .34] +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/fhci.h | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/fhci.h ++++ b/drivers/usb/host/fhci.h +@@ -20,6 +20,7 @@ + + #include <linux/kernel.h> + #include <linux/types.h> ++#include <linux/bug.h> + #include <linux/spinlock.h> + #include <linux/interrupt.h> + #include <linux/kfifo.h> +@@ -515,9 +516,13 @@ static inline int cq_put(struct kfifo *k + + static inline void *cq_get(struct kfifo *kfifo) + { +- void *p = NULL; ++ unsigned int sz; ++ void *p; ++ ++ sz = kfifo_out(kfifo, (void *)&p, sizeof(p)); ++ if (sz != sizeof(p)) ++ return NULL; + +- kfifo_out(kfifo, (void *)&p, sizeof(p)); + return p; + } + diff --git a/usb/usb-fix-functionfs-for-config_net-disabled.patch b/usb/usb-fix-functionfs-for-config_net-disabled.patch new file mode 100644 index 00000000000000..9dd4e706bc8078 --- /dev/null +++ b/usb/usb-fix-functionfs-for-config_net-disabled.patch @@ -0,0 +1,64 @@ +From randy.dunlap@oracle.com Fri May 14 12:09:56 2010 +From: Randy Dunlap <randy.dunlap@oracle.com> +Date: Thu, 13 May 2010 09:41:12 -0700 +Subject: USB: fix functionfs for CONFIG_NET disabled +To: Stephen Rothwell <sfr@canb.auug.org.au>, gregkh@suse.de, Michal Nazarewicz <m.nazarewicz@samsung.com> +Message-ID: <20100513094112.86acf7c2.randy.dunlap@oracle.com> + + +From: Randy Dunlap <randy.dunlap@oracle.com> + +Fix functionfs build to handle CONFIG_NET not enabled, to prevent +these build errors: + +ERROR: "netif_carrier_on" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "netif_carrier_off" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "skb_realloc_headroom" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "skb_trim" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "netif_rx" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "alloc_etherdev_mq" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "ethtool_op_get_link" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "free_netdev" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "register_netdev" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "skb_push" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "skb_pull" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "dev_kfree_skb_any" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "skb_queue_tail" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "__alloc_skb" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "eth_type_trans" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "eth_validate_addr" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "skb_dequeue" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "unregister_netdev" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "__netif_schedule" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "skb_put" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "eth_mac_addr" [drivers/usb/gadget/g_ffs.ko] undefined! +ERROR: "dev_get_stats" [drivers/usb/gadget/g_ffs.ko] undefined! + +Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> +Acked-by: Michał Nazarewicz <m.nazarewicz@samsung.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/gadget/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -726,7 +726,7 @@ config USB_FUNCTIONFS + + config USB_FUNCTIONFS_ETH + bool "Include CDC ECM (Ethernet) function" +- depends on USB_FUNCTIONFS ++ depends on USB_FUNCTIONFS && NET + help + Include an CDC ECM (Ethernet) funcion in the CDC ECM (Funcion) + Filesystem. If you also say "y" to the RNDIS query below the +@@ -734,7 +734,7 @@ config USB_FUNCTIONFS_ETH + + config USB_FUNCTIONFS_RNDIS + bool "Include RNDIS (Ethernet) function" +- depends on USB_FUNCTIONFS ++ depends on USB_FUNCTIONFS && NET + help + Include an RNDIS (Ethernet) funcion in the Funcion Filesystem. + If you also say "y" to the CDC ECM query above the gadget will diff --git a/usb/usb-gadget-f_mass_storage-fix-in-error-recovery.patch b/usb/usb-gadget-f_mass_storage-fix-in-error-recovery.patch new file mode 100644 index 00000000000000..b1426e2211d562 --- /dev/null +++ b/usb/usb-gadget-f_mass_storage-fix-in-error-recovery.patch @@ -0,0 +1,114 @@ +From m.nazarewicz@samsung.com Fri May 14 12:03:03 2010 +From: Michal Nazarewicz <m.nazarewicz@samsung.com> +Date: Wed, 12 May 2010 12:51:13 +0200 +Subject: USB: gadget: f_mass_storage: fix in error recovery +To: linux-usb@vger.kernel.org +Cc: Kyungmin Park <kyungmin.park@samsung.com>, Marek Szyprowski <m.szyprowski@samsung.com>, Viral Mehta <Viral.Mehta@lntinfotech.com>, linux-kernel@vger.kernel.org, Michal Nazarewicz <mina86@mina86.com> +Message-ID: <1148fb1fcb3a9864a2a12fbbf2e3444827c9ed4a.1273661077.git.mina86@mina86.com> + + +In to places in fsg_common_init() an unconditional call to kfree() +on common was performed in error recovery which is not a valid +behaviour since fsg_common structure is not always allocated by +fsg_common_init(). + +To fix, the calls has been replaced with a goto to a proper error +recovery which does the correct thing. + +Also, refactored fsg_common_release() function. + +Signed-off-by: Michal Nazarewicz <mina86@mina86.com> +Reviewed-by: Viral Mehta <viral.mehta@lntinfotech.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/gadget/f_mass_storage.c | 55 +++++++++++++++++------------------- + 1 file changed, 27 insertions(+), 28 deletions(-) + +--- a/drivers/usb/gadget/f_mass_storage.c ++++ b/drivers/usb/gadget/f_mass_storage.c +@@ -2742,10 +2742,8 @@ static struct fsg_common *fsg_common_ini + /* Maybe allocate device-global string IDs, and patch descriptors */ + if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { + rc = usb_string_id(cdev); +- if (rc < 0) { +- kfree(common); +- return ERR_PTR(rc); +- } ++ if (unlikely(rc < 0)) ++ goto error_release; + fsg_strings[FSG_STRING_INTERFACE].id = rc; + fsg_intf_desc.iInterface = rc; + } +@@ -2753,9 +2751,9 @@ static struct fsg_common *fsg_common_ini + /* Create the LUNs, open their backing files, and register the + * LUN devices in sysfs. */ + curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL); +- if (!curlun) { +- kfree(common); +- return ERR_PTR(-ENOMEM); ++ if (unlikely(!curlun)) { ++ rc = -ENOMEM; ++ goto error_release; + } + common->luns = curlun; + +@@ -2914,11 +2912,7 @@ error_release: + + static void fsg_common_release(struct kref *ref) + { +- struct fsg_common *common = +- container_of(ref, struct fsg_common, ref); +- unsigned i = common->nluns; +- struct fsg_lun *lun = common->luns; +- struct fsg_buffhd *bh; ++ struct fsg_common *common = container_of(ref, struct fsg_common, ref); + + /* If the thread isn't already dead, tell it to exit now */ + if (common->state != FSG_STATE_TERMINATED) { +@@ -2929,24 +2923,29 @@ static void fsg_common_release(struct kr + complete(&common->thread_notifier); + } + +- /* Beware tempting for -> do-while optimization: when in error +- * recovery nluns may be zero. */ +- +- for (; i; --i, ++lun) { +- device_remove_file(&lun->dev, &dev_attr_ro); +- device_remove_file(&lun->dev, &dev_attr_file); +- fsg_lun_close(lun); +- device_unregister(&lun->dev); ++ if (likely(common->luns)) { ++ struct fsg_lun *lun = common->luns; ++ unsigned i = common->nluns; ++ ++ /* In error recovery common->nluns may be zero. */ ++ for (; i; --i, ++lun) { ++ device_remove_file(&lun->dev, &dev_attr_ro); ++ device_remove_file(&lun->dev, &dev_attr_file); ++ fsg_lun_close(lun); ++ device_unregister(&lun->dev); ++ } ++ ++ kfree(common->luns); ++ } ++ ++ { ++ struct fsg_buffhd *bh = common->buffhds; ++ unsigned i = FSG_NUM_BUFFERS; ++ do { ++ kfree(bh->buf); ++ } while (++bh, --i); + } + +- kfree(common->luns); +- +- i = FSG_NUM_BUFFERS; +- bh = common->buffhds; +- do { +- kfree(bh->buf); +- } while (++bh, --i); +- + if (common->free_storage_on_release) + kfree(common); + } diff --git a/usb/usb-io_edgeport-use-kzalloc.patch b/usb/usb-io_edgeport-use-kzalloc.patch new file mode 100644 index 00000000000000..8618a0acaacdda --- /dev/null +++ b/usb/usb-io_edgeport-use-kzalloc.patch @@ -0,0 +1,54 @@ +From julia@diku.dk Fri May 14 12:15:34 2010 +From: Julia Lawall <julia@diku.dk> +Date: Thu, 13 May 2010 22:00:40 +0200 (CEST) +Subject: USB: io_edgeport: Use kzalloc +To: Greg Kroah-Hartman <gregkh@suse.de>, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, kernel-janitors@vger.kernel.org +Message-ID: <Pine.LNX.4.64.1005132200240.6282@ask.diku.dk> + + +From: Julia Lawall <julia@diku.dk> + +Use kzalloc rather than the combination of kmalloc and memset. + +The semantic patch that makes this change is as follows: +(http://coccinelle.lip6.fr/) + +// <smpl> +@@ +expression x,size,flags; +statement S; +@@ + +-x = kmalloc(size,flags); ++x = kzalloc(size,flags); + if (x == NULL) S +-memset(x, 0, size); +// </smpl> + +Signed-off-by: Julia Lawall <julia@diku.dk> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/serial/io_edgeport.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/usb/serial/io_edgeport.c ++++ b/drivers/usb/serial/io_edgeport.c +@@ -3020,7 +3020,7 @@ static int edge_startup(struct usb_seria + + /* set up our port private structures */ + for (i = 0; i < serial->num_ports; ++i) { +- edge_port = kmalloc(sizeof(struct edgeport_port), GFP_KERNEL); ++ edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); + if (edge_port == NULL) { + dev_err(&serial->dev->dev, "%s - Out of memory\n", + __func__); +@@ -3033,7 +3033,6 @@ static int edge_startup(struct usb_seria + kfree(edge_serial); + return -ENOMEM; + } +- memset(edge_port, 0, sizeof(struct edgeport_port)); + spin_lock_init(&edge_port->ep_lock); + edge_port->port = serial->port[i]; + usb_set_serial_port_data(serial->port[i], edge_port); diff --git a/usb/usb-ipw-clean-up-dtr-rts-handling.patch b/usb/usb-ipw-clean-up-dtr-rts-handling.patch new file mode 100644 index 00000000000000..7c14644eb7b281 --- /dev/null +++ b/usb/usb-ipw-clean-up-dtr-rts-handling.patch @@ -0,0 +1,94 @@ +From jhovold@gmail.com Fri May 14 12:14:47 2010 +From: Johan Hovold <jhovold@gmail.com> +Date: Thu, 13 May 2010 21:33:08 +0200 +Subject: USB: ipw: clean up dtr-rts handling +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com> +Message-ID: <1273779190-8652-2-git-send-email-jhovold@gmail.com> + + +No need to raise dtr/rts in open as this is taken care of by tty layer. + +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ipw.c | 43 ++++++------------------------------------- + 1 file changed, 6 insertions(+), 37 deletions(-) + +--- a/drivers/usb/serial/ipw.c ++++ b/drivers/usb/serial/ipw.c +@@ -267,35 +267,6 @@ static int ipw_open(struct tty_struct *t + dev_err(&port->dev, + "initial flowcontrol failed (error = %d)\n", result); + +- +- /*--5: raise the dtr */ +- dbg("%s:raising dtr", __func__); +- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), +- IPW_SIO_SET_PIN, +- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, +- IPW_PIN_SETDTR, +- 0, +- NULL, +- 0, +- 200000); +- if (result < 0) +- dev_err(&port->dev, +- "setting dtr failed (error = %d)\n", result); +- +- /*--6: raise the rts */ +- dbg("%s:raising rts", __func__); +- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), +- IPW_SIO_SET_PIN, +- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, +- IPW_PIN_SETRTS, +- 0, +- NULL, +- 0, +- 200000); +- if (result < 0) +- dev_err(&port->dev, +- "setting dtr failed (error = %d)\n", result); +- + kfree(buf_flow_init); + return 0; + } +@@ -305,8 +276,8 @@ static void ipw_dtr_rts(struct usb_seria + struct usb_device *dev = port->serial->dev; + int result; + +- /*--1: drop the dtr */ +- dbg("%s:dropping dtr", __func__); ++ dbg("%s: on = %d", __func__, on); ++ + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + IPW_SIO_SET_PIN, + USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, +@@ -316,22 +287,20 @@ static void ipw_dtr_rts(struct usb_seria + 0, + 200000); + if (result < 0) +- dev_err(&port->dev, "dropping dtr failed (error = %d)\n", ++ dev_err(&port->dev, "setting dtr failed (error = %d)\n", + result); + +- /*--2: drop the rts */ +- dbg("%s:dropping rts", __func__); + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + IPW_SIO_SET_PIN, USB_TYPE_VENDOR | +- USB_RECIP_INTERFACE | USB_DIR_OUT, ++ USB_RECIP_INTERFACE | USB_DIR_OUT, + on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS, + 0, + NULL, + 0, + 200000); + if (result < 0) +- dev_err(&port->dev, +- "dropping rts failed (error = %d)\n", result); ++ dev_err(&port->dev, "setting rts failed (error = %d)\n", ++ result); + } + + static void ipw_close(struct usb_serial_port *port) diff --git a/usb/usb-ipw-reimplement-using-generic-framework.patch b/usb/usb-ipw-reimplement-using-generic-framework.patch new file mode 100644 index 00000000000000..5a9b38101ecb66 --- /dev/null +++ b/usb/usb-ipw-reimplement-using-generic-framework.patch @@ -0,0 +1,202 @@ +From jhovold@gmail.com Fri May 14 12:15:10 2010 +From: Johan Hovold <jhovold@gmail.com> +Date: Thu, 13 May 2010 21:33:10 +0200 +Subject: USB: ipw: reimplement using generic framework +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com> +Message-ID: <1273779190-8652-4-git-send-email-jhovold@gmail.com> + + +Compile-only tested. + +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ipw.c | 128 +---------------------------------------------- + 1 file changed, 4 insertions(+), 124 deletions(-) + +--- a/drivers/usb/serial/ipw.c ++++ b/drivers/usb/serial/ipw.c +@@ -34,7 +34,6 @@ + * DCD, DTR, RTS, CTS which are currently faked. + * It's good enough for PPP at this point. It's based off all kinds of + * code found in usb/serial and usb/class +- * + */ + + #include <linux/kernel.h> +@@ -52,7 +51,7 @@ + /* + * Version Information + */ +-#define DRIVER_VERSION "v0.3" ++#define DRIVER_VERSION "v0.4" + #define DRIVER_AUTHOR "Roelf Diedericks" + #define DRIVER_DESC "IPWireless tty driver" + +@@ -65,8 +64,6 @@ + /* Message sizes */ + #define EVENT_BUFFER_SIZE 0xFF + #define CHAR2INT16(c1, c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff)) +-#define NUM_BULK_URBS 24 +-#define NUM_CONTROL_URBS 16 + + /* vendor/product pairs that are known work with this driver*/ + #define IPW_VID 0x0bc3 +@@ -151,47 +148,6 @@ static struct usb_driver usb_ipw_driver + + static int debug; + +-static void ipw_read_bulk_callback(struct urb *urb) +-{ +- struct usb_serial_port *port = urb->context; +- unsigned char *data = urb->transfer_buffer; +- struct tty_struct *tty; +- int result; +- int status = urb->status; +- +- dbg("%s - port %d", __func__, port->number); +- +- if (status) { +- dbg("%s - nonzero read bulk status received: %d", +- __func__, status); +- return; +- } +- +- usb_serial_debug_data(debug, &port->dev, __func__, +- urb->actual_length, data); +- +- tty = tty_port_tty_get(&port->port); +- if (tty && urb->actual_length) { +- tty_insert_flip_string(tty, data, urb->actual_length); +- tty_flip_buffer_push(tty); +- } +- tty_kref_put(tty); +- +- /* Continue trying to always read */ +- usb_fill_bulk_urb(port->read_urb, port->serial->dev, +- usb_rcvbulkpipe(port->serial->dev, +- port->bulk_in_endpointAddress), +- port->read_urb->transfer_buffer, +- port->read_urb->transfer_buffer_length, +- ipw_read_bulk_callback, port); +- result = usb_submit_urb(port->read_urb, GFP_ATOMIC); +- if (result) +- dev_err(&port->dev, +- "%s - failed resubmitting read urb, error %d\n", +- __func__, result); +- return; +-} +- + static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) + { + struct usb_device *dev = port->serial->dev; +@@ -229,15 +185,7 @@ static int ipw_open(struct tty_struct *t + + /*--2: Start reading from the device */ + dbg("%s: setting up bulk read callback", __func__); +- usb_fill_bulk_urb(port->read_urb, dev, +- usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), +- port->bulk_in_buffer, +- port->bulk_in_size, +- ipw_read_bulk_callback, port); +- result = usb_submit_urb(port->read_urb, GFP_KERNEL); +- if (result < 0) +- dbg("%s - usb_submit_urb(read bulk) failed with status %d", +- __func__, result); ++ usb_serial_generic_open(tty, port); + + /*--3: Tell the modem to open the floodgates on the rx bulk channel */ + dbg("%s:asking modem for RxRead (RXBULK_ON)", __func__); +@@ -337,72 +285,7 @@ static void ipw_close(struct usb_serial_ + dev_err(&port->dev, + "Disabling bulk RxRead failed (error = %d)\n", result); + +- /* shutdown any in-flight urbs that we know about */ +- usb_kill_urb(port->read_urb); +- usb_kill_urb(port->write_urb); +-} +- +-static void ipw_write_bulk_callback(struct urb *urb) +-{ +- struct usb_serial_port *port = urb->context; +- int status = urb->status; +- +- dbg("%s", __func__); +- +- port->write_urb_busy = 0; +- +- if (status) +- dbg("%s - nonzero write bulk status received: %d", +- __func__, status); +- +- usb_serial_port_softint(port); +-} +- +-static int ipw_write(struct tty_struct *tty, struct usb_serial_port *port, +- const unsigned char *buf, int count) +-{ +- struct usb_device *dev = port->serial->dev; +- int ret; +- +- dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__, +- count, in_interrupt()); +- +- if (count == 0) { +- dbg("%s - write request of 0 bytes", __func__); +- return 0; +- } +- +- spin_lock_bh(&port->lock); +- if (port->write_urb_busy) { +- spin_unlock_bh(&port->lock); +- dbg("%s - already writing", __func__); +- return 0; +- } +- port->write_urb_busy = 1; +- spin_unlock_bh(&port->lock); +- +- count = min(count, port->bulk_out_size); +- memcpy(port->bulk_out_buffer, buf, count); +- +- dbg("%s count now:%d", __func__, count); +- +- usb_fill_bulk_urb(port->write_urb, dev, +- usb_sndbulkpipe(dev, port->bulk_out_endpointAddress), +- port->write_urb->transfer_buffer, +- count, +- ipw_write_bulk_callback, +- port); +- +- ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); +- if (ret != 0) { +- port->write_urb_busy = 0; +- dbg("%s - usb_submit_urb(write bulk) failed with error = %d", +- __func__, ret); +- return ret; +- } +- +- dbg("%s returning %d", __func__, count); +- return count; ++ usb_serial_generic_close(port); + } + + static struct usb_serial_driver ipw_device = { +@@ -411,15 +294,12 @@ static struct usb_serial_driver ipw_devi + .name = "ipw", + }, + .description = "IPWireless converter", +- .usb_driver = &usb_ipw_driver, ++ .usb_driver = &usb_ipw_driver, + .id_table = usb_ipw_ids, + .num_ports = 1, + .open = ipw_open, + .close = ipw_close, + .dtr_rts = ipw_dtr_rts, +- .write = ipw_write, +- .write_bulk_callback = ipw_write_bulk_callback, +- .read_bulk_callback = ipw_read_bulk_callback, + }; + + diff --git a/usb/usb-ipw-remove-dummy-port_probe-and-port_remove.patch b/usb/usb-ipw-remove-dummy-port_probe-and-port_remove.patch new file mode 100644 index 00000000000000..704c6ae63d0f15 --- /dev/null +++ b/usb/usb-ipw-remove-dummy-port_probe-and-port_remove.patch @@ -0,0 +1,46 @@ +From jhovold@gmail.com Fri May 14 12:14:59 2010 +From: Johan Hovold <jhovold@gmail.com> +Date: Thu, 13 May 2010 21:33:09 +0200 +Subject: USB: ipw: remove dummy port_probe and port_remove +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com> +Message-ID: <1273779190-8652-3-git-send-email-jhovold@gmail.com> + + + +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ipw.c | 13 ------------- + 1 file changed, 13 deletions(-) + +--- a/drivers/usb/serial/ipw.c ++++ b/drivers/usb/serial/ipw.c +@@ -405,17 +405,6 @@ static int ipw_write(struct tty_struct * + return count; + } + +-static int ipw_probe(struct usb_serial_port *port) +-{ +- return 0; +-} +- +-static int ipw_disconnect(struct usb_serial_port *port) +-{ +- usb_set_serial_port_data(port, NULL); +- return 0; +-} +- + static struct usb_serial_driver ipw_device = { + .driver = { + .owner = THIS_MODULE, +@@ -428,8 +417,6 @@ static struct usb_serial_driver ipw_devi + .open = ipw_open, + .close = ipw_close, + .dtr_rts = ipw_dtr_rts, +- .port_probe = ipw_probe, +- .port_remove = ipw_disconnect, + .write = ipw_write, + .write_bulk_callback = ipw_write_bulk_callback, + .read_bulk_callback = ipw_read_bulk_callback, diff --git a/usb/usb-ir-usb-allow-custom-bulk-buffer-size-without-reallocation.patch b/usb/usb-ir-usb-allow-custom-bulk-buffer-size-without-reallocation.patch new file mode 100644 index 00000000000000..4be66aee3c3846 --- /dev/null +++ b/usb/usb-ir-usb-allow-custom-bulk-buffer-size-without-reallocation.patch @@ -0,0 +1,70 @@ +From jhovold@gmail.com Fri May 14 12:13:44 2010 +From: Johan Hovold <jhovold@gmail.com> +Date: Thu, 13 May 2010 21:02:01 +0200 +Subject: USB: ir-usb: allow custom bulk buffer size without reallocation +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com> +Message-ID: <1273777323-32136-3-git-send-email-jhovold@gmail.com> + + +Use usb_serial_driver bulk_in_size and bulk_out_size to make sure +buffers of appropriate sizes are allocated in the first place rather than +reallocating them at every open. + +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ir-usb.c | 30 +++++------------------------- + 1 file changed, 5 insertions(+), 25 deletions(-) + +--- a/drivers/usb/serial/ir-usb.c ++++ b/drivers/usb/serial/ir-usb.c +@@ -297,35 +297,10 @@ static int ir_startup(struct usb_serial + + static int ir_open(struct tty_struct *tty, struct usb_serial_port *port) + { +- char *buffer; + int result = 0; + + dbg("%s - port %d", __func__, port->number); + +- if (buffer_size) { +- /* override the default buffer sizes */ +- buffer = kmalloc(buffer_size, GFP_KERNEL); +- if (!buffer) { +- dev_err(&port->dev, "%s - out of memory.\n", __func__); +- return -ENOMEM; +- } +- kfree(port->read_urb->transfer_buffer); +- port->read_urb->transfer_buffer = buffer; +- port->read_urb->transfer_buffer_length = buffer_size; +- port->bulk_in_buffer = buffer; +- +- buffer = kmalloc(buffer_size, GFP_KERNEL); +- if (!buffer) { +- dev_err(&port->dev, "%s - out of memory.\n", __func__); +- return -ENOMEM; +- } +- kfree(port->write_urb->transfer_buffer); +- port->write_urb->transfer_buffer = buffer; +- port->write_urb->transfer_buffer_length = buffer_size; +- port->bulk_out_buffer = buffer; +- port->bulk_out_size = buffer_size; +- } +- + /* Start reading from the device */ + usb_fill_bulk_urb( + port->read_urb, +@@ -585,6 +560,11 @@ static int __init ir_init(void) + { + int retval; + ++ if (buffer_size) { ++ ir_device.bulk_in_size = buffer_size; ++ ir_device.bulk_out_size = buffer_size; ++ } ++ + retval = usb_serial_register(&ir_device); + if (retval) + goto failed_usb_serial_register; diff --git a/usb/usb-ir-usb-fix-double-free.patch b/usb/usb-ir-usb-fix-double-free.patch new file mode 100644 index 00000000000000..35a1db88587b6a --- /dev/null +++ b/usb/usb-ir-usb-fix-double-free.patch @@ -0,0 +1,38 @@ +From jhovold@gmail.com Fri May 14 12:13:32 2010 +From: Johan Hovold <jhovold@gmail.com> +Date: Thu, 13 May 2010 21:02:00 +0200 +Subject: USB: ir-usb: fix double free +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com>, stable <stable@kernel.org> +Message-ID: <1273777323-32136-2-git-send-email-jhovold@gmail.com> + + +If the user specifies a custom bulk buffer size we get a double free at +port release. + +Cc: stable <stable@kernel.org> +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ir-usb.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/serial/ir-usb.c ++++ b/drivers/usb/serial/ir-usb.c +@@ -312,6 +312,7 @@ static int ir_open(struct tty_struct *tt + kfree(port->read_urb->transfer_buffer); + port->read_urb->transfer_buffer = buffer; + port->read_urb->transfer_buffer_length = buffer_size; ++ port->bulk_in_buffer = buffer; + + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!buffer) { +@@ -321,6 +322,7 @@ static int ir_open(struct tty_struct *tt + kfree(port->write_urb->transfer_buffer); + port->write_urb->transfer_buffer = buffer; + port->write_urb->transfer_buffer_length = buffer_size; ++ port->bulk_out_buffer = buffer; + port->bulk_out_size = buffer_size; + } + diff --git a/usb/usb-ir-usb-fix-set_termios-race.patch b/usb/usb-ir-usb-fix-set_termios-race.patch new file mode 100644 index 00000000000000..672dc765a6b166 --- /dev/null +++ b/usb/usb-ir-usb-fix-set_termios-race.patch @@ -0,0 +1,117 @@ +From jhovold@gmail.com Fri May 14 12:14:20 2010 +From: Johan Hovold <jhovold@gmail.com> +Date: Thu, 13 May 2010 21:02:02 +0200 +Subject: USB: ir-usb: fix set_termios race +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com> +Message-ID: <1273777323-32136-4-git-send-email-jhovold@gmail.com> + + +Use dynamically allocated urb for baudrate changes rather than +unconditionally submitting the port write urb which may already be in +use. + +Compile-only tested. + +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ir-usb.c | 63 ++++++++++++++++++++++++++++++++------------ + 1 file changed, 47 insertions(+), 16 deletions(-) + +--- a/drivers/usb/serial/ir-usb.c ++++ b/drivers/usb/serial/ir-usb.c +@@ -469,9 +469,23 @@ static void ir_read_bulk_callback(struct + return; + } + ++static void ir_set_termios_callback(struct urb *urb) ++{ ++ struct usb_serial_port *port = urb->context; ++ int status = urb->status; ++ ++ dbg("%s - port %d", __func__, port->number); ++ ++ kfree(urb->transfer_buffer); ++ ++ if (status) ++ dbg("%s - non-zero urb status: %d", __func__, status); ++} ++ + static void ir_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) + { ++ struct urb *urb; + unsigned char *transfer_buffer; + int result; + speed_t baud; +@@ -525,35 +539,52 @@ static void ir_set_termios(struct tty_st + else + ir_xbof = ir_xbof_change(xbof) ; + +- /* FIXME need to check to see if our write urb is busy right +- * now, or use a urb pool. +- * ++ /* Only speed changes are supported */ ++ tty_termios_copy_hw(tty->termios, old_termios); ++ tty_encode_baud_rate(tty, baud, baud); ++ ++ /* + * send the baud change out on an "empty" data packet + */ +- transfer_buffer = port->write_urb->transfer_buffer; ++ urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!urb) { ++ dev_err(&port->dev, "%s - no more urbs\n", __func__); ++ return; ++ } ++ transfer_buffer = kmalloc(1, GFP_KERNEL); ++ if (!transfer_buffer) { ++ dev_err(&port->dev, "%s - out of memory\n", __func__); ++ goto err_buf; ++ } ++ + *transfer_buffer = ir_xbof | ir_baud; + + usb_fill_bulk_urb( +- port->write_urb, ++ urb, + port->serial->dev, + usb_sndbulkpipe(port->serial->dev, + port->bulk_out_endpointAddress), +- port->write_urb->transfer_buffer, ++ transfer_buffer, + 1, +- ir_write_bulk_callback, ++ ir_set_termios_callback, + port); + +- port->write_urb->transfer_flags = URB_ZERO_PACKET; ++ urb->transfer_flags = URB_ZERO_PACKET; ++ ++ result = usb_submit_urb(urb, GFP_KERNEL); ++ if (result) { ++ dev_err(&port->dev, "%s - failed to submit urb: %d\n", ++ __func__, result); ++ goto err_subm; ++ } + +- result = usb_submit_urb(port->write_urb, GFP_KERNEL); +- if (result) +- dev_err(&port->dev, +- "%s - failed submitting write urb, error %d\n", +- __func__, result); ++ usb_free_urb(urb); + +- /* Only speed changes are supported */ +- tty_termios_copy_hw(tty->termios, old_termios); +- tty_encode_baud_rate(tty, baud, baud); ++ return; ++err_subm: ++ kfree(transfer_buffer); ++err_buf: ++ usb_free_urb(urb); + } + + static int __init ir_init(void) diff --git a/usb/usb-ir-usb-reimplement-using-generic-framework.patch b/usb/usb-ir-usb-reimplement-using-generic-framework.patch new file mode 100644 index 00000000000000..ee40a8bc2d3916 --- /dev/null +++ b/usb/usb-ir-usb-reimplement-using-generic-framework.patch @@ -0,0 +1,289 @@ +From jhovold@gmail.com Fri May 14 12:14:33 2010 +From: Johan Hovold <jhovold@gmail.com> +Date: Thu, 13 May 2010 21:02:03 +0200 +Subject: USB: ir-usb: reimplement using generic framework +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: linux-usb@vger.kernel.org, Johan Hovold <jhovold@gmail.com> +Message-ID: <1273777323-32136-5-git-send-email-jhovold@gmail.com> + + +Compile-only tested. + +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ir-usb.c | 197 ++++++++------------------------------------ + 1 file changed, 38 insertions(+), 159 deletions(-) + +--- a/drivers/usb/serial/ir-usb.c ++++ b/drivers/usb/serial/ir-usb.c +@@ -3,6 +3,7 @@ + * + * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2002 Gary Brubaker (xavyer@ix.netcom.com) ++ * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -72,8 +73,8 @@ + /* + * Version Information + */ +-#define DRIVER_VERSION "v0.4" +-#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" ++#define DRIVER_VERSION "v0.5" ++#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Johan Hovold <jhovold@gmail.com>" + #define DRIVER_DESC "USB IR Dongle driver" + + static int debug; +@@ -87,11 +88,9 @@ static int xbof = -1; + + static int ir_startup (struct usb_serial *serial); + static int ir_open(struct tty_struct *tty, struct usb_serial_port *port); +-static void ir_close(struct usb_serial_port *port); +-static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, +- const unsigned char *buf, int count); +-static void ir_write_bulk_callback (struct urb *urb); +-static void ir_read_bulk_callback (struct urb *urb); ++static int ir_prepare_write_buffer(struct usb_serial_port *port, ++ void *dest, size_t size); ++static void ir_process_read_urb(struct urb *urb); + static void ir_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios); + +@@ -130,10 +129,8 @@ static struct usb_serial_driver ir_devic + .set_termios = ir_set_termios, + .attach = ir_startup, + .open = ir_open, +- .close = ir_close, +- .write = ir_write, +- .write_bulk_callback = ir_write_bulk_callback, +- .read_bulk_callback = ir_read_bulk_callback, ++ .prepare_write_buffer = ir_prepare_write_buffer, ++ .process_read_urb = ir_process_read_urb, + }; + + static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc) +@@ -198,7 +195,6 @@ error: + return NULL; + } + +- + static u8 ir_xbof_change(u8 xbof) + { + u8 result; +@@ -237,7 +233,6 @@ static u8 ir_xbof_change(u8 xbof) + return(result); + } + +- + static int ir_startup(struct usb_serial *serial) + { + struct usb_irda_cs_descriptor *irda_desc; +@@ -297,60 +292,21 @@ static int ir_startup(struct usb_serial + + static int ir_open(struct tty_struct *tty, struct usb_serial_port *port) + { +- int result = 0; ++ int i; + + dbg("%s - port %d", __func__, port->number); + +- /* Start reading from the device */ +- usb_fill_bulk_urb( +- port->read_urb, +- port->serial->dev, +- usb_rcvbulkpipe(port->serial->dev, +- port->bulk_in_endpointAddress), +- port->read_urb->transfer_buffer, +- port->read_urb->transfer_buffer_length, +- ir_read_bulk_callback, +- port); +- result = usb_submit_urb(port->read_urb, GFP_KERNEL); +- if (result) +- dev_err(&port->dev, +- "%s - failed submitting read urb, error %d\n", +- __func__, result); ++ for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) ++ port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET; + +- return result; ++ /* Start reading from the device */ ++ return usb_serial_generic_open(tty, port); + } + +-static void ir_close(struct usb_serial_port *port) ++static int ir_prepare_write_buffer(struct usb_serial_port *port, ++ void *dest, size_t size) + { +- dbg("%s - port %d", __func__, port->number); +- +- /* shutdown our bulk read */ +- usb_kill_urb(port->read_urb); +-} +- +-static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, +- const unsigned char *buf, int count) +-{ +- unsigned char *transfer_buffer; +- int result; +- int transfer_size; +- +- dbg("%s - port = %d, count = %d", __func__, port->number, count); +- +- if (count == 0) +- return 0; +- +- spin_lock_bh(&port->lock); +- if (port->write_urb_busy) { +- spin_unlock_bh(&port->lock); +- dbg("%s - already writing", __func__); +- return 0; +- } +- port->write_urb_busy = 1; +- spin_unlock_bh(&port->lock); +- +- transfer_buffer = port->write_urb->transfer_buffer; +- transfer_size = min(count, port->bulk_out_size - 1); ++ unsigned char *buf = dest; + + /* + * The first byte of the packet we send to the device contains an +@@ -359,114 +315,37 @@ static int ir_write(struct tty_struct *t + * + * See section 5.4.2.2 of the USB IrDA spec. + */ +- *transfer_buffer = ir_xbof | ir_baud; +- ++transfer_buffer; +- +- memcpy(transfer_buffer, buf, transfer_size); +- +- usb_fill_bulk_urb( +- port->write_urb, +- port->serial->dev, +- usb_sndbulkpipe(port->serial->dev, +- port->bulk_out_endpointAddress), +- port->write_urb->transfer_buffer, +- transfer_size + 1, +- ir_write_bulk_callback, +- port); +- +- port->write_urb->transfer_flags = URB_ZERO_PACKET; +- +- result = usb_submit_urb(port->write_urb, GFP_ATOMIC); +- if (result) { +- port->write_urb_busy = 0; +- dev_err(&port->dev, +- "%s - failed submitting write urb, error %d\n", +- __func__, result); +- } else +- result = transfer_size; ++ *buf = ir_xbof | ir_baud; + +- return result; ++ return kfifo_out_locked(&port->write_fifo, buf + 1, size - 1, ++ &port->lock); + } + +-static void ir_write_bulk_callback(struct urb *urb) ++static void ir_process_read_urb(struct urb *urb) + { + struct usb_serial_port *port = urb->context; +- int status = urb->status; +- +- dbg("%s - port %d", __func__, port->number); ++ unsigned char *data = urb->transfer_buffer; ++ struct tty_struct *tty; + +- port->write_urb_busy = 0; +- if (status) { +- dbg("%s - nonzero write bulk status received: %d", +- __func__, status); ++ if (!urb->actual_length) + return; +- } +- +- usb_serial_debug_data( +- debug, +- &port->dev, +- __func__, +- urb->actual_length, +- urb->transfer_buffer); +- +- usb_serial_port_softint(port); +-} +- +-static void ir_read_bulk_callback(struct urb *urb) +-{ +- struct usb_serial_port *port = urb->context; +- struct tty_struct *tty; +- unsigned char *data = urb->transfer_buffer; +- int result; +- int status = urb->status; ++ /* ++ * The first byte of the packet we get from the device ++ * contains a busy indicator and baud rate change. ++ * See section 5.4.1.2 of the USB IrDA spec. ++ */ ++ if (*data & 0x0f) ++ ir_baud = *data & 0x0f; + +- dbg("%s - port %d", __func__, port->number); ++ if (urb->actual_length == 1) ++ return; + +- switch (status) { +- case 0: /* Successful */ +- /* +- * The first byte of the packet we get from the device +- * contains a busy indicator and baud rate change. +- * See section 5.4.1.2 of the USB IrDA spec. +- */ +- if ((*data & 0x0f) > 0) +- ir_baud = *data & 0x0f; +- usb_serial_debug_data(debug, &port->dev, __func__, +- urb->actual_length, data); +- tty = tty_port_tty_get(&port->port); +- tty_insert_flip_string(tty, data+1, urb->actual_length - 1); +- tty_flip_buffer_push(tty); +- tty_kref_put(tty); +- +- /* +- * No break here. +- * We want to resubmit the urb so we can read +- * again. +- */ +- +- case -EPROTO: /* taking inspiration from pl2303.c */ +- /* Continue trying to always read */ +- usb_fill_bulk_urb( +- port->read_urb, +- port->serial->dev, +- usb_rcvbulkpipe(port->serial->dev, +- port->bulk_in_endpointAddress), +- port->read_urb->transfer_buffer, +- port->read_urb->transfer_buffer_length, +- ir_read_bulk_callback, +- port); +- +- result = usb_submit_urb(port->read_urb, GFP_ATOMIC); +- if (result) +- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", +- __func__, result); +- break ; +- default: +- dbg("%s - nonzero read bulk status received: %d", +- __func__, status); +- break ; +- } +- return; ++ tty = tty_port_tty_get(&port->port); ++ if (!tty) ++ return; ++ tty_insert_flip_string(tty, data + 1, urb->actual_length - 1); ++ tty_flip_buffer_push(tty); ++ tty_kref_put(tty); + } + + static void ir_set_termios_callback(struct urb *urb) diff --git a/usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch b/usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch index 0bce486dbc5af5..6f043bdc7d0313 100644 --- a/usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch +++ b/usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch @@ -16,7 +16,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/include/linux/usb.h +++ b/include/linux/usb.h -@@ -1373,18 +1373,6 @@ void *usb_alloc_coherent(struct usb_devi +@@ -1372,18 +1372,6 @@ void *usb_alloc_coherent(struct usb_devi void usb_free_coherent(struct usb_device *dev, size_t size, void *addr, dma_addr_t dma); diff --git a/usb/usb-remove-usb_find_device.patch b/usb/usb-remove-usb_find_device.patch new file mode 100644 index 00000000000000..4a36c165479885 --- /dev/null +++ b/usb/usb-remove-usb_find_device.patch @@ -0,0 +1,89 @@ +From tom.leiming@gmail.com Fri May 14 12:03:50 2010 +From: tom.leiming@gmail.com +Date: Wed, 12 May 2010 23:38:46 +0800 +Subject: USB: remove usb_find_device +To: greg@kroah.com, stern@rowland.harvard.edu +Cc: linux-usb@vger.kernel.org, Ming Lei <tom.leiming@gmail.com> +Message-ID: <1273678726-19664-1-git-send-email-tom.leiming@gmail.com> + + +From: Ming Lei <tom.leiming@gmail.com> + +Now on one uses this function and it seems useless, +so remove usb_find_device. + +[tom@tom linux-2.6-next]$ grep -r -n -I usb_find_device ./ +drivers/media/dvb/dvb-usb/dvb-usb-init.c:160:static struct +dvb_usb_device_description * dvb_usb_find_device(struct usb_device +*udev,struct dvb_usb_device_properties *props, int *cold) + +drivers/media/dvb/dvb-usb/dvb-usb-init.c:230: if ((desc = +dvb_usb_find_device(udev,props,&cold)) == NULL) { + +drivers/usb/core/usb.c:630: * usb_find_device - find a specific usb device in the system +drivers/usb/core/usb.c:642:struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/usb.c | 37 ------------------------------------- + include/linux/usb.h | 1 - + 2 files changed, 38 deletions(-) + +--- a/drivers/usb/core/usb.c ++++ b/drivers/usb/core/usb.c +@@ -627,43 +627,6 @@ exit: + } + + /** +- * usb_find_device - find a specific usb device in the system +- * @vendor_id: the vendor id of the device to find +- * @product_id: the product id of the device to find +- * +- * Returns a pointer to a struct usb_device if such a specified usb +- * device is present in the system currently. The usage count of the +- * device will be incremented if a device is found. Make sure to call +- * usb_put_dev() when the caller is finished with the device. +- * +- * If a device with the specified vendor and product id is not found, +- * NULL is returned. +- */ +-struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) +-{ +- struct list_head *buslist; +- struct usb_bus *bus; +- struct usb_device *dev = NULL; +- +- mutex_lock(&usb_bus_list_lock); +- for (buslist = usb_bus_list.next; +- buslist != &usb_bus_list; +- buslist = buslist->next) { +- bus = container_of(buslist, struct usb_bus, bus_list); +- if (!bus->root_hub) +- continue; +- usb_lock_device(bus->root_hub); +- dev = match_device(bus->root_hub, vendor_id, product_id); +- usb_unlock_device(bus->root_hub); +- if (dev) +- goto exit; +- } +-exit: +- mutex_unlock(&usb_bus_list_lock); +- return dev; +-} +- +-/** + * usb_get_current_frame_number - return current bus frame number + * @dev: the device whose bus is being queried + * +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -510,7 +510,6 @@ extern int usb_lock_device_for_reset(str + extern int usb_reset_device(struct usb_device *dev); + extern void usb_queue_reset_device(struct usb_interface *dev); + +-extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); + + /* USB autosuspend and autoresume */ + #ifdef CONFIG_USB_SUSPEND diff --git a/usb/usb-xhci-remove-the-arbitrary-limit-of-15-xhci-ports.patch b/usb/usb-xhci-remove-the-arbitrary-limit-of-15-xhci-ports.patch new file mode 100644 index 00000000000000..3a413909bfc695 --- /dev/null +++ b/usb/usb-xhci-remove-the-arbitrary-limit-of-15-xhci-ports.patch @@ -0,0 +1,58 @@ +From wgulland@vmware.com Fri May 14 12:05:05 2010 +From: William Gulland <wgulland@vmware.com> +Date: Wed, 12 May 2010 10:20:34 -0700 +Subject: USB: xhci: Remove the arbitrary limit of 15 xHCI ports +To: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Message-ID: <1273684834.11403.7.camel@wgulland-ubuntu> + + +Our virtual xHCI device can have as many ports as we like - I've tested +this patch with 31. + +Signed-off-by: William Gulland <wgulland@vmware.com> +Cc: 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, 3 insertions(+), 12 deletions(-) + +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -298,7 +298,6 @@ error: + * Returns 0 if the status hasn't changed, or the number of bytes in buf. + * Ports are 0-indexed from the HCD point of view, + * and 1-indexed from the USB core pointer of view. +- * xHCI instances can have up to 127 ports, so FIXME if you see more than 15. + * + * Note that the status change bits will be cleared as soon as a port status + * change event is generated, so we use the saved status from that event. +@@ -315,14 +314,9 @@ int xhci_hub_status_data(struct usb_hcd + ports = HCS_MAX_PORTS(xhci->hcs_params1); + + /* Initial status is no changes */ +- buf[0] = 0; ++ retval = (ports + 8) / 8; ++ memset(buf, 0, retval); + status = 0; +- if (ports > 7) { +- buf[1] = 0; +- retval = 2; +- } else { +- retval = 1; +- } + + spin_lock_irqsave(&xhci->lock, flags); + /* For each port, did anything change? If so, set that bit in buf. */ +@@ -331,10 +325,7 @@ int xhci_hub_status_data(struct usb_hcd + NUM_PORT_REGS*i; + temp = xhci_readl(xhci, addr); + if (temp & (PORT_CSC | PORT_PEC | PORT_OCC)) { +- if (i < 7) +- buf[0] |= 1 << (i + 1); +- else +- buf[1] |= 1 << (i - 7); ++ buf[(i + 1) / 8] |= 1 << (i + 1) % 8; + status = 1; + } + } |
