diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-30 16:21:36 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-30 16:21:36 -0700 |
commit | dc49a952fd6cbbdce6aacd9f1efb3ace6f64c4bc (patch) | |
tree | 1ce208bd0a9c4a02596da4b95b6272625dd669b7 /usb | |
parent | a5363843f6fde193b61d6b06779229390eb4071c (diff) | |
download | patches-dc49a952fd6cbbdce6aacd9f1efb3ace6f64c4bc.tar.gz |
loads of new patches
Diffstat (limited to 'usb')
17 files changed, 2623 insertions, 1 deletions
diff --git a/usb/usb-add-driver-for-non-composite-sierra-wireless-devices.patch b/usb/usb-add-driver-for-non-composite-sierra-wireless-devices.patch new file mode 100644 index 0000000000000..08036c7b0f3dd --- /dev/null +++ b/usb/usb-add-driver-for-non-composite-sierra-wireless-devices.patch @@ -0,0 +1,132 @@ +From klloyd@airprime.com Fri Jun 30 11:18:46 2006 +From: "Kevin Lloyd" <klloyd@sierrawireless.com> +Subject: USB: add driver for non-composite Sierra Wireless devices +Date: Fri, 30 Jun 2006 11:17:55 -0700 +Message-ID: <3415E2A2AB26944B9159CDB22001004D2C90EC@nestea.sierrawireless.local> +To: "Greg KH" <gregkh@suse.de> +Cc: "Kevin Lloyd" <klloyd@sierrawireless.com> + +From: Kevin Lloyd <linux@sierrawireless.com> + +This patch creates a new driver, sierra.c, that supports the new +non-composite Sierra Wireless WWAN devices. The older Sierra +Wireless and Airprime devices are supported in airprime.c. + +Signed-off-by: Kevin Lloyd <linux@sierrawireless.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/serial/Kconfig | 11 ++++++ + drivers/usb/serial/Makefile | 1 + drivers/usb/serial/sierra.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 87 insertions(+) + +--- gregkh-2.6.orig/drivers/usb/serial/Kconfig ++++ gregkh-2.6/drivers/usb/serial/Kconfig +@@ -456,6 +456,17 @@ config USB_SERIAL_SAFE_PADDED + bool "USB Secure Encapsulated Driver - Padded" + depends on USB_SERIAL_SAFE + ++config USB_SERIAL_SIERRAWIRELESS ++ tristate "USB Sierra Wireless Driver" ++ depends on USB_SERIAL ++ help ++ Say M here if you want to use a Sierra Wireless device (if ++ using an PC 5220 or AC580 please use the Airprime driver ++ instead). ++ ++ To compile this driver as a module, choose M here: the ++ module will be called sierra. ++ + config USB_SERIAL_TI + tristate "USB TI 3410/5052 Serial Driver" + depends on USB_SERIAL +--- gregkh-2.6.orig/drivers/usb/serial/Makefile ++++ gregkh-2.6/drivers/usb/serial/Makefile +@@ -39,6 +39,7 @@ obj-$(CONFIG_USB_SERIAL_OMNINET) += omn + obj-$(CONFIG_USB_SERIAL_OPTION) += option.o + obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o + obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o ++obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o + obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o + obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o + obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o +--- /dev/null ++++ gregkh-2.6/drivers/usb/serial/sierra.c +@@ -0,0 +1,75 @@ ++/* ++ * Sierra Wireless CDMA Wireless Serial USB driver ++ * ++ * Current Copy modified by: Kevin Lloyd <linux@sierrawireless.com> ++ * Original Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License version ++ * 2 as published by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/tty.h> ++#include <linux/module.h> ++#include <linux/usb.h> ++#include "usb-serial.h" ++ ++static struct usb_device_id id_table [] = { ++ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ ++ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ ++ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ ++ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ ++ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ ++ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ ++ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ ++ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ ++ /* Following devices are supported in the airprime.c driver */ ++ /* { USB_DEVICE(0x1199, 0x0112) }, */ /* Sierra Wireless AirCard 580 */ ++ /* { USB_DEVICE(0x0F3D, 0x0112) }, */ /* AirPrime/Sierra PC 5220 */ ++ { } ++}; ++MODULE_DEVICE_TABLE(usb, id_table); ++ ++static struct usb_driver sierra_driver = { ++ .name = "sierra_wireless", ++ .probe = usb_serial_probe, ++ .disconnect = usb_serial_disconnect, ++ .id_table = id_table, ++}; ++ ++static struct usb_serial_driver sierra_device = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "Sierra_Wireless", ++ }, ++ .id_table = id_table, ++ .num_interrupt_in = NUM_DONT_CARE, ++ .num_bulk_in = NUM_DONT_CARE, ++ .num_bulk_out = NUM_DONT_CARE, ++ .num_ports = 3, ++}; ++ ++static int __init sierra_init(void) ++{ ++ int retval; ++ ++ retval = usb_serial_register(&sierra_device); ++ if (retval) ++ return retval; ++ retval = usb_register(&sierra_driver); ++ if (retval) ++ usb_serial_deregister(&sierra_device); ++ return retval; ++} ++ ++static void __exit sierra_exit(void) ++{ ++ usb_deregister(&sierra_driver); ++ usb_serial_deregister(&sierra_device); ++} ++ ++module_init(sierra_init); ++module_exit(sierra_exit); ++MODULE_LICENSE("GPL"); diff --git a/usb/usb-allow-compile-in-g_ether-fix-typo.patch b/usb/usb-allow-compile-in-g_ether-fix-typo.patch new file mode 100644 index 0000000000000..023fb1713c590 --- /dev/null +++ b/usb/usb-allow-compile-in-g_ether-fix-typo.patch @@ -0,0 +1,40 @@ +From david-b@pacbell.net Thu Jun 29 22:27:40 2006 +From: Tony Lindgren <tony@atomide.com> +Subject: USB: Allow compile in g_ether, fix typo +Date: Thu, 29 Jun 2006 22:27:36 -0700 +To: Greg KH <greg@kroah.com> +Cc: Tony Lindgren <tony@atomide.com> +Message-Id: <200606292227.36598.david-b@pacbell.net> + +From: Tony Lindgren <tony@atomide.com> + +Allows compiling g_ether in and fixes a typo with MUSB_HDRC + +Signed-off-by: Tony Lindgren <tony@atomide.com> +Cc: David Brownell <david-b@pacbell.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/gadget/ether.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/gadget/ether.c ++++ gregkh-2.6/drivers/usb/gadget/ether.c +@@ -261,7 +261,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethern + #define DEV_CONFIG_CDC + #endif + +-#ifdef CONFIG_USB_GADGET_MUSBHDRC ++#ifdef CONFIG_USB_GADGET_MUSB_HDRC + #define DEV_CONFIG_CDC + #endif + +@@ -2548,7 +2548,7 @@ static struct usb_gadget_driver eth_driv + + .function = (char *) driver_desc, + .bind = eth_bind, +- .unbind = __exit_p(eth_unbind), ++ .unbind = eth_unbind, + + .setup = eth_setup, + .disconnect = eth_disconnect, diff --git a/usb/usb-at91-ohci-updates-mostly-power-management.patch b/usb/usb-at91-ohci-updates-mostly-power-management.patch new file mode 100644 index 0000000000000..9d8b0efb3ad0b --- /dev/null +++ b/usb/usb-at91-ohci-updates-mostly-power-management.patch @@ -0,0 +1,299 @@ +From david-b@pacbell.net Mon Jun 19 14:31:06 2006 +From: David Brownell <david-b@pacbell.net> +To: Greg KH <greg@kroah.com> +Subject: USB: AT91 OHCI updates, mostly power management +Date: Mon, 19 Jun 2006 14:27:20 -0700 +Cc: Andrew Victor <andrew@sanpeople.com> +Message-Id: <200606191427.20871.david-b@pacbell.net> + +OHCI updates for AT91 series processors: + + - Get ready for at91sam926x processors (ARMv5tej not ARMv4t) + + - Suspend/resume support now behaves properly + + - In "standby" mode, OHCI can be a source of system wakeup events + (remote wakeup, device connect/disconnect, etc) + +And minor cleanups. + +Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> +Signed-off-by: Andrew Victor <andrew@sanpeople.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/Kconfig | 2 + drivers/usb/host/ohci-at91.c | 88 ++++++++++++++++++++++++++++--------------- + drivers/usb/host/ohci-hcd.c | 3 - + 3 files changed, 62 insertions(+), 31 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/Kconfig ++++ gregkh-2.6/drivers/usb/Kconfig +@@ -24,7 +24,7 @@ config USB_ARCH_HAS_OHCI + default y if ARCH_S3C2410 + default y if PXA27x + default y if ARCH_EP93XX +- default y if ARCH_AT91RM9200 ++ default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) + # PPC: + default y if STB03xxx + default y if PPC_MPC52xx +--- gregkh-2.6.orig/drivers/usb/host/ohci-at91.c ++++ gregkh-2.6/drivers/usb/host/ohci-at91.c +@@ -4,7 +4,7 @@ + * Copyright (C) 2004 SAN People (Pty) Ltd. + * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> + * +- * AT91RM9200 Bus Glue ++ * AT91 Bus Glue + * + * Based on fragments of 2.4 driver by Rick Bronson. + * Based on ohci-omap.c +@@ -19,12 +19,13 @@ + #include <asm/hardware.h> + #include <asm/arch/board.h> + +-#ifndef CONFIG_ARCH_AT91RM9200 +-#error "CONFIG_ARCH_AT91RM9200 must be defined." ++#ifndef CONFIG_ARCH_AT91 ++#error "CONFIG_ARCH_AT91 must be defined." + #endif + + /* interface and function clocks */ + static struct clk *iclk, *fclk; ++static int clocked; + + extern int usb_disabled(void); + +@@ -35,13 +36,14 @@ static void at91_start_hc(struct platfor + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_regs __iomem *regs = hcd->regs; + +- dev_dbg(&pdev->dev, "starting AT91RM9200 OHCI USB Controller\n"); ++ dev_dbg(&pdev->dev, "start\n"); + + /* + * Start the USB clocks. + */ + clk_enable(iclk); + clk_enable(fclk); ++ clocked = 1; + + /* + * The USB host controller must remain in reset. +@@ -54,7 +56,7 @@ static void at91_stop_hc(struct platform + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_regs __iomem *regs = hcd->regs; + +- dev_dbg(&pdev->dev, "stopping AT91RM9200 OHCI USB Controller\n"); ++ dev_dbg(&pdev->dev, "stop\n"); + + /* + * Put the USB host controller into reset. +@@ -66,6 +68,7 @@ static void at91_stop_hc(struct platform + */ + clk_disable(fclk); + clk_disable(iclk); ++ clocked = 0; + } + + +@@ -78,14 +81,15 @@ static int usb_hcd_at91_remove (struct u + + + /** +- * usb_hcd_at91_probe - initialize AT91RM9200-based HCDs ++ * usb_hcd_at91_probe - initialize AT91-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + */ +-int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev) ++static int usb_hcd_at91_probe(const struct hc_driver *driver, ++ struct platform_device *pdev) + { + int retval; + struct usb_hcd *hcd = NULL; +@@ -95,12 +99,13 @@ int usb_hcd_at91_probe (const struct hc_ + return -ENODEV; + } + +- if ((pdev->resource[0].flags != IORESOURCE_MEM) || (pdev->resource[1].flags != IORESOURCE_IRQ)) { ++ if ((pdev->resource[0].flags != IORESOURCE_MEM) ++ || (pdev->resource[1].flags != IORESOURCE_IRQ)) { + pr_debug("hcd probe: invalid resource type\n"); + return -ENODEV; + } + +- hcd = usb_create_hcd(driver, &pdev->dev, "at91rm9200"); ++ hcd = usb_create_hcd(driver, &pdev->dev, "at91"); + if (!hcd) + return -ENOMEM; + hcd->rsrc_start = pdev->resource[0].start; +@@ -149,21 +154,23 @@ int usb_hcd_at91_probe (const struct hc_ + /* may be called with controller, bus, and devices active */ + + /** +- * usb_hcd_at91_remove - shutdown processing for AT91RM9200-based HCDs ++ * usb_hcd_at91_remove - shutdown processing for AT91-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_at91_probe(), first invoking + * the HCD's stop() method. It is always called from a thread +- * context, normally "rmmod", "apmd", or something similar. ++ * context, "rmmod" or something similar. + * + */ +-static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pdev) ++static int usb_hcd_at91_remove(struct usb_hcd *hcd, ++ struct platform_device *pdev) + { + usb_remove_hcd(hcd); + at91_stop_hc(pdev); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); ++ disable_irq_wake(hcd->irq); + + clk_put(fclk); + clk_put(iclk); +@@ -178,19 +185,21 @@ static int usb_hcd_at91_remove (struct u + static int __devinit + ohci_at91_start (struct usb_hcd *hcd) + { +-// struct at91_ohci_data *board = hcd->self.controller->platform_data; ++ struct at91_usbh_data *board = hcd->self.controller->platform_data; + struct ohci_hcd *ohci = hcd_to_ohci (hcd); ++ struct usb_device *root = hcd->self.root_hub; + int ret; + + if ((ret = ohci_init(ohci)) < 0) + return ret; + ++ root->maxchild = board->ports; ++ + if ((ret = ohci_run(ohci)) < 0) { + err("can't start %s", hcd->self.bus_name); + ohci_stop(hcd); + return ret; + } +-// hcd->self.root_hub->maxchild = board->ports; + return 0; + } + +@@ -198,7 +207,7 @@ ohci_at91_start (struct usb_hcd *hcd) + + static const struct hc_driver ohci_at91_hc_driver = { + .description = hcd_name, +- .product_desc = "AT91RM9200 OHCI", ++ .product_desc = "AT91 OHCI", + .hcd_priv_size = sizeof(struct ohci_hcd), + + /* +@@ -240,33 +249,54 @@ static const struct hc_driver ohci_at91_ + + /*-------------------------------------------------------------------------*/ + +-static int ohci_hcd_at91_drv_probe(struct platform_device *dev) ++static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) + { +- return usb_hcd_at91_probe(&ohci_at91_hc_driver, dev); ++ device_init_wakeup(&pdev->dev, 1); ++ return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); + } + +-static int ohci_hcd_at91_drv_remove(struct platform_device *dev) ++static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) + { +- return usb_hcd_at91_remove(platform_get_drvdata(dev), dev); ++ device_init_wakeup(&pdev->dev, 0); ++ return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev); + } + + #ifdef CONFIG_PM + +-/* REVISIT suspend/resume look "too" simple here */ +- + static int +-ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg) ++ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) + { +- clk_disable(fclk); +- clk_disable(iclk); ++ struct usb_hcd *hcd = platform_get_drvdata(pdev); ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ ++ if (device_may_wakeup(&pdev->dev)) ++ enable_irq_wake(hcd->irq); ++ else ++ disable_irq_wake(hcd->irq); ++ ++ /* ++ * The integrated transceivers seem unable to notice disconnect, ++ * reconnect, or wakeup without the 48 MHz clock active. so for ++ * correctness, always discard connection state (using reset). ++ * ++ * REVISIT: some boards will be able to turn VBUS off... ++ */ ++ if (at91_suspend_entering_slow_clock()) { ++ ohci_usb_reset (ohci); ++ clk_disable(fclk); ++ clk_disable(iclk); ++ clocked = 0; ++ } + + return 0; + } + +-static int ohci_hcd_at91_drv_resume(struct platform_device *dev) ++static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) + { +- clk_enable(iclk); +- clk_enable(fclk); ++ if (!clocked) { ++ clk_enable(iclk); ++ clk_enable(fclk); ++ } + + return 0; + } +@@ -275,7 +305,7 @@ static int ohci_hcd_at91_drv_resume(stru + #define ohci_hcd_at91_drv_resume NULL + #endif + +-MODULE_ALIAS("at91rm9200-ohci"); ++MODULE_ALIAS("at91_ohci"); + + static struct platform_driver ohci_hcd_at91_driver = { + .probe = ohci_hcd_at91_drv_probe, +@@ -283,7 +313,7 @@ static struct platform_driver ohci_hcd_a + .suspend = ohci_hcd_at91_drv_suspend, + .resume = ohci_hcd_at91_drv_resume, + .driver = { +- .name = "at91rm9200-ohci", ++ .name = "at91_ohci", + .owner = THIS_MODULE, + }, + }; +--- gregkh-2.6.orig/drivers/usb/host/ohci-hcd.c ++++ gregkh-2.6/drivers/usb/host/ohci-hcd.c +@@ -924,7 +924,7 @@ MODULE_LICENSE ("GPL"); + #include "ohci-ppc-soc.c" + #endif + +-#ifdef CONFIG_ARCH_AT91RM9200 ++#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261) + #include "ohci-at91.c" + #endif + +@@ -938,6 +938,7 @@ MODULE_LICENSE ("GPL"); + || defined (CONFIG_SOC_AU1X00) \ + || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ + || defined (CONFIG_ARCH_AT91RM9200) \ ++ || defined (CONFIG_ARCH_AT91SAM9261) \ + ) + #error "missing bus glue for ohci-hcd" + #endif diff --git a/usb/usb-at91-udc-updates-mostly-power-management.patch b/usb/usb-at91-udc-updates-mostly-power-management.patch new file mode 100644 index 0000000000000..1d0a3bc25adc4 --- /dev/null +++ b/usb/usb-at91-udc-updates-mostly-power-management.patch @@ -0,0 +1,405 @@ +From david-b@pacbell.net Mon Jun 19 14:31:06 2006 +From: David Brownell <david-b@pacbell.net> +To: Greg KH <greg@kroah.com> +Subject: USB: AT91 UDC updates, mostly power management +Date: Mon, 19 Jun 2006 14:25:11 -0700 +Cc: Andrew Victor <andrew@sanpeople.com> +Message-Id: <200606191425.11737.david-b@pacbell.net> + + +UDC updates for AT91 series processors: + + - Get ready for at91sam926x processors (ARMv5tej not ARMv4t) + + - Suspend/resume support now behaves properly + + - In "standby" mode, UDC can be a source of system wakeup events + (host resume, device connect/disconnect, etc) + + - Fix a startup problem that crept in with the initial merge + +And minor cleanups, especially whitespace. + +Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> +Signed-off-by: Andrew Victor <andrew@sanpeople.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/gadget/at91_udc.c | 157 +++++++++++++++++++++++++----------------- + drivers/usb/gadget/at91_udc.h | 1 + 2 files changed, 98 insertions(+), 60 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/gadget/at91_udc.c ++++ gregkh-2.6/drivers/usb/gadget/at91_udc.c +@@ -70,7 +70,7 @@ + * power. During USB suspend, the 48 MHz clock is gated off. + */ + +-#define DRIVER_VERSION "8 March 2005" ++#define DRIVER_VERSION "3 May 2006" + + static const char driver_name [] = "at91_udc"; + static const char ep0name[] = "ep0"; +@@ -319,7 +319,8 @@ static void done(struct at91_ep *ep, str + * that shouldn't normally be changed. + */ + #define SET_FX (AT91_UDP_TXPKTRDY) +-#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) ++#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP \ ++ | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) + + /* pull OUT packet data from the endpoint's fifo */ + static int read_fifo (struct at91_ep *ep, struct at91_request *req) +@@ -473,7 +474,8 @@ static void nuke(struct at91_ep *ep, int + + /*-------------------------------------------------------------------------*/ + +-static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ++static int at91_ep_enable(struct usb_ep *_ep, ++ const struct usb_endpoint_descriptor *desc) + { + struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); + struct at91_udc *dev = ep->udc; +@@ -583,11 +585,12 @@ static int at91_ep_disable (struct usb_e + * interesting for request or buffer allocation. + */ + +-static struct usb_request *at91_ep_alloc_request (struct usb_ep *_ep, unsigned int gfp_flags) ++static struct usb_request * ++at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags) + { + struct at91_request *req; + +- req = kcalloc(1, sizeof (struct at91_request), SLAB_KERNEL); ++ req = kcalloc(1, sizeof (struct at91_request), gfp_flags); + if (!req) + return NULL; + +@@ -890,8 +893,8 @@ static void clk_off(struct at91_udc *udc + return; + udc->clocked = 0; + udc->gadget.speed = USB_SPEED_UNKNOWN; +- clk_disable(udc->iclk); + clk_disable(udc->fclk); ++ clk_disable(udc->iclk); + } + + /* +@@ -912,9 +915,6 @@ static void pullup(struct at91_udc *udc, + at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); + at91_set_gpio_value(udc->board.pullup_pin, 0); + clk_off(udc); +- +- // REVISIT: with transceiver disabled, will D- float +- // so that a host would falsely detect a device? + } + } + +@@ -1291,7 +1291,8 @@ static void handle_ep0(struct at91_udc * + if (udc->wait_for_addr_ack) { + u32 tmp; + +- at91_udp_write(AT91_UDP_FADDR, AT91_UDP_FEN | udc->addr); ++ at91_udp_write(AT91_UDP_FADDR, ++ AT91_UDP_FEN | udc->addr); + tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp &= ~AT91_UDP_FADDEN; + if (udc->addr) +@@ -1362,9 +1363,10 @@ static irqreturn_t at91_udc_irq (int irq + u32 rescans = 5; + + while (rescans--) { +- u32 status = at91_udp_read(AT91_UDP_ISR); ++ u32 status; + +- status &= at91_udp_read(AT91_UDP_IMR); ++ status = at91_udp_read(AT91_UDP_ISR) ++ & at91_udp_read(AT91_UDP_IMR); + if (!status) + break; + +@@ -1380,18 +1382,17 @@ static irqreturn_t at91_udc_irq (int irq + stop_activity(udc); + + /* enable ep0 */ +- at91_udp_write(AT91_UDP_CSR(0), AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); ++ at91_udp_write(AT91_UDP_CSR(0), ++ AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); + udc->gadget.speed = USB_SPEED_FULL; + udc->suspended = 0; + at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0)); + + /* + * NOTE: this driver keeps clocks off unless the +- * USB host is present. That saves power, and also +- * eliminates IRQs (reset, resume, suspend) that can +- * otherwise flood from the controller. If your +- * board doesn't support VBUS detection, suspend and +- * resume irq logic may need more attention... ++ * USB host is present. That saves power, but for ++ * boards that don't support VBUS detection, both ++ * clocks need to be active most of the time. + */ + + /* host initiated suspend (3+ms bus idle) */ +@@ -1453,13 +1454,19 @@ static irqreturn_t at91_udc_irq (int irq + + /*-------------------------------------------------------------------------*/ + ++static void nop_release(struct device *dev) ++{ ++ /* nothing to free */ ++} ++ + static struct at91_udc controller = { + .gadget = { +- .ops = &at91_udc_ops, +- .ep0 = &controller.ep[0].ep, +- .name = driver_name, +- .dev = { +- .bus_id = "gadget" ++ .ops = &at91_udc_ops, ++ .ep0 = &controller.ep[0].ep, ++ .name = driver_name, ++ .dev = { ++ .bus_id = "gadget", ++ .release = nop_release, + } + }, + .ep[0] = { +@@ -1469,7 +1476,8 @@ static struct at91_udc controller = { + }, + .udc = &controller, + .maxpacket = 8, +- .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(0)), ++ .creg = (void __iomem *)(AT91_VA_BASE_UDP ++ + AT91_UDP_CSR(0)), + .int_mask = 1 << 0, + }, + .ep[1] = { +@@ -1480,7 +1488,8 @@ static struct at91_udc controller = { + .udc = &controller, + .is_pingpong = 1, + .maxpacket = 64, +- .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(1)), ++ .creg = (void __iomem *)(AT91_VA_BASE_UDP ++ + AT91_UDP_CSR(1)), + .int_mask = 1 << 1, + }, + .ep[2] = { +@@ -1491,7 +1500,8 @@ static struct at91_udc controller = { + .udc = &controller, + .is_pingpong = 1, + .maxpacket = 64, +- .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(2)), ++ .creg = (void __iomem *)(AT91_VA_BASE_UDP ++ + AT91_UDP_CSR(2)), + .int_mask = 1 << 2, + }, + .ep[3] = { +@@ -1502,7 +1512,8 @@ static struct at91_udc controller = { + }, + .udc = &controller, + .maxpacket = 8, +- .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(3)), ++ .creg = (void __iomem *)(AT91_VA_BASE_UDP ++ + AT91_UDP_CSR(3)), + .int_mask = 1 << 3, + }, + .ep[4] = { +@@ -1513,7 +1524,8 @@ static struct at91_udc controller = { + .udc = &controller, + .is_pingpong = 1, + .maxpacket = 256, +- .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(4)), ++ .creg = (void __iomem *)(AT91_VA_BASE_UDP ++ + AT91_UDP_CSR(4)), + .int_mask = 1 << 4, + }, + .ep[5] = { +@@ -1524,10 +1536,11 @@ static struct at91_udc controller = { + .udc = &controller, + .is_pingpong = 1, + .maxpacket = 256, +- .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(5)), ++ .creg = (void __iomem *)(AT91_VA_BASE_UDP ++ + AT91_UDP_CSR(5)), + .int_mask = 1 << 5, + }, +- /* ep6 and ep7 are also reserved */ ++ /* ep6 and ep7 are also reserved (custom silicon might use them) */ + }; + + static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r) +@@ -1625,6 +1638,16 @@ static int __devinit at91udc_probe(struc + return -ENODEV; + } + ++ if (pdev->num_resources != 2) { ++ DBG("invalid num_resources"); ++ return -ENODEV; ++ } ++ if ((pdev->resource[0].flags != IORESOURCE_MEM) ++ || (pdev->resource[1].flags != IORESOURCE_IRQ)) { ++ DBG("invalid resource type"); ++ return -ENODEV; ++ } ++ + if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) { + DBG("someone's using UDC memory\n"); + return -EBUSY; +@@ -1650,19 +1673,26 @@ static int __devinit at91udc_probe(struc + if (retval < 0) + goto fail0; + +- /* disable everything until there's a gadget driver and vbus */ +- pullup(udc, 0); ++ /* don't do anything until we have both gadget driver and VBUS */ ++ clk_enable(udc->iclk); ++ at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); ++ at91_udp_write(AT91_UDP_IDR, 0xffffffff); ++ clk_disable(udc->iclk); + + /* request UDC and maybe VBUS irqs */ +- if (request_irq(AT91_ID_UDP, at91_udc_irq, SA_INTERRUPT, driver_name, udc)) { +- DBG("request irq %d failed\n", AT91_ID_UDP); ++ udc->udp_irq = platform_get_irq(pdev, 0); ++ if (request_irq(udc->udp_irq, at91_udc_irq, ++ SA_INTERRUPT, driver_name, udc)) { ++ DBG("request irq %d failed\n", udc->udp_irq); + retval = -EBUSY; + goto fail1; + } + if (udc->board.vbus_pin > 0) { +- if (request_irq(udc->board.vbus_pin, at91_vbus_irq, SA_INTERRUPT, driver_name, udc)) { +- DBG("request vbus irq %d failed\n", udc->board.vbus_pin); +- free_irq(AT91_ID_UDP, udc); ++ if (request_irq(udc->board.vbus_pin, at91_vbus_irq, ++ SA_INTERRUPT, driver_name, udc)) { ++ DBG("request vbus irq %d failed\n", ++ udc->board.vbus_pin); ++ free_irq(udc->udp_irq, udc); + retval = -EBUSY; + goto fail1; + } +@@ -1671,6 +1701,7 @@ static int __devinit at91udc_probe(struc + udc->vbus = 1; + } + dev_set_drvdata(dev, udc); ++ device_init_wakeup(dev, 1); + create_debug_file(udc); + + INFO("%s version %s\n", driver_name, DRIVER_VERSION); +@@ -1679,14 +1710,14 @@ static int __devinit at91udc_probe(struc + fail1: + device_unregister(&udc->gadget.dev); + fail0: +- release_mem_region(AT91_VA_BASE_UDP, SZ_16K); ++ release_mem_region(AT91_BASE_UDP, SZ_16K); + DBG("%s probe failed, %d\n", driver_name, retval); + return retval; + } + +-static int __devexit at91udc_remove(struct platform_device *dev) ++static int __devexit at91udc_remove(struct platform_device *pdev) + { +- struct at91_udc *udc = platform_get_drvdata(dev); ++ struct at91_udc *udc = platform_get_drvdata(pdev); + + DBG("remove\n"); + +@@ -1695,10 +1726,11 @@ static int __devexit at91udc_remove(stru + if (udc->driver != 0) + usb_gadget_unregister_driver(udc->driver); + ++ device_init_wakeup(&pdev->dev, 0); + remove_debug_file(udc); + if (udc->board.vbus_pin > 0) + free_irq(udc->board.vbus_pin, udc); +- free_irq(AT91_ID_UDP, udc); ++ free_irq(udc->udp_irq, udc); + device_unregister(&udc->gadget.dev); + release_mem_region(AT91_BASE_UDP, SZ_16K); + +@@ -1709,31 +1741,36 @@ static int __devexit at91udc_remove(stru + } + + #ifdef CONFIG_PM +-static int at91udc_suspend(struct platform_device *dev, pm_message_t mesg) ++static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg) + { +- struct at91_udc *udc = platform_get_drvdata(dev); ++ struct at91_udc *udc = platform_get_drvdata(pdev); ++ int wake = udc->driver && device_may_wakeup(&pdev->dev); + +- /* +- * The "safe" suspend transitions are opportunistic ... e.g. when +- * the USB link is suspended (48MHz clock autogated off), or when +- * it's disconnected (programmatically gated off, elsewhere). +- * Then we can suspend, and the chip can enter slow clock mode. +- * +- * The problem case is some component (user mode?) suspending this +- * device while it's active, with the 48 MHz clock in use. There +- * are two basic approaches: (a) veto suspend levels involving slow +- * clock mode, (b) disconnect, so 48 MHz will no longer be in use +- * and we can enter slow clock mode. This uses (b) for now, since +- * it's simplest until AT91 PM exists and supports the other option. ++ /* Unless we can act normally to the host (letting it wake us up ++ * whenever it has work for us) force disconnect. Wakeup requires ++ * PLLB for USB events (signaling for reset, wakeup, or incoming ++ * tokens) and VBUS irqs (on systems which support them). + */ +- if (udc->vbus && !udc->suspended) ++ if ((!udc->suspended && udc->addr) ++ || !wake ++ || at91_suspend_entering_slow_clock()) { + pullup(udc, 0); ++ disable_irq_wake(udc->udp_irq); ++ } else ++ enable_irq_wake(udc->udp_irq); ++ ++ if (udc->board.vbus_pin > 0) { ++ if (wake) ++ enable_irq_wake(udc->board.vbus_pin); ++ else ++ disable_irq_wake(udc->board.vbus_pin); ++ } + return 0; + } + +-static int at91udc_resume(struct platform_device *dev) ++static int at91udc_resume(struct platform_device *pdev) + { +- struct at91_udc *udc = platform_get_drvdata(dev); ++ struct at91_udc *udc = platform_get_drvdata(pdev); + + /* maybe reconnect to host; if so, clocks on */ + pullup(udc, 1); +@@ -1749,7 +1786,7 @@ static struct platform_driver at91_udc = + .remove = __devexit_p(at91udc_remove), + .shutdown = at91udc_shutdown, + .suspend = at91udc_suspend, +- .resume = at91udc_resume, ++ .resume = at91udc_resume, + .driver = { + .name = (char *) driver_name, + .owner = THIS_MODULE, +@@ -1768,6 +1805,6 @@ static void __devexit udc_exit_module(vo + } + module_exit(udc_exit_module); + +-MODULE_DESCRIPTION("AT91RM9200 udc driver"); ++MODULE_DESCRIPTION("AT91 udc driver"); + MODULE_AUTHOR("Thomas Rathbone, David Brownell"); + MODULE_LICENSE("GPL"); +--- gregkh-2.6.orig/drivers/usb/gadget/at91_udc.h ++++ gregkh-2.6/drivers/usb/gadget/at91_udc.h +@@ -141,6 +141,7 @@ struct at91_udc { + struct clk *iclk, *fclk; + struct platform_device *pdev; + struct proc_dir_entry *pde; ++ int udp_irq; + }; + + static inline struct at91_udc *to_udc(struct usb_gadget *g) diff --git a/usb/usb-fix-pointer-dereference-in-drivers-usb-misc-usblcd.patch b/usb/usb-fix-pointer-dereference-in-drivers-usb-misc-usblcd.patch new file mode 100644 index 0000000000000..d4c86c4c4ddd3 --- /dev/null +++ b/usb/usb-fix-pointer-dereference-in-drivers-usb-misc-usblcd.patch @@ -0,0 +1,32 @@ +From linux-kernel-owner+greg=40kroah.com-S933309AbWFZW6V@vger.kernel.org Mon Jun 26 16:19:13 2006 +From: Eric Sesterhenn <snakebyte@gmx.de> +Subject: USB: fix pointer dereference in drivers/usb/misc/usblcd +Cc: <g.toth@e-biz.lu> +Date: Tue, 27 Jun 2006 00:57:42 +0200 +Message-Id: <1151362662.15204.7.camel@alice> + +coverity spotted (id #185) that we still use urb, if the allocation +fails in the error path. This patch fixes this by returning directly. + +Signed-off-by: Eric Sesterhenn <snakebyte@gmx.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/misc/usblcd.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/misc/usblcd.c ++++ gregkh-2.6/drivers/usb/misc/usblcd.c +@@ -200,10 +200,8 @@ static ssize_t lcd_write(struct file *fi + + /* create a urb, and a buffer for it, and copy the data to the urb */ + urb = usb_alloc_urb(0, GFP_KERNEL); +- if (!urb) { +- retval = -ENOMEM; +- goto error; +- } ++ if (!urb) ++ return -ENOMEM; + + buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); + if (!buf) { diff --git a/usb/usb-kill-compiler-warning-in-quirk_usb_handoff_ohci.patch b/usb/usb-kill-compiler-warning-in-quirk_usb_handoff_ohci.patch new file mode 100644 index 0000000000000..e290f4ce265f3 --- /dev/null +++ b/usb/usb-kill-compiler-warning-in-quirk_usb_handoff_ohci.patch @@ -0,0 +1,53 @@ +From kyle@athena.road.mcmartin.ca Tue Jun 27 09:11:48 2006 +Date: Sun, 25 Jun 2006 18:45:29 -0400 +From: Kyle McMartin <kyle@mcmartin.ca> +To: gregkh@suse.de +Subject: USB: Kill compiler warning in quirk_usb_handoff_ohci +Message-ID: <20060625224529.GB2837@athena.road.mcmartin.ca> +Content-Disposition: inline + +From: Kyle McMartin <kyle@parisc-linux.org> + +Move variables only used on !__hppa__ into that #ifndef section. This +cleans up a compiler warning on parisc. Problem pointed out by +Joel Soete. + +Signed-off-by: Kyle McMartin <kyle@parisc-linux.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/pci-quirks.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/host/pci-quirks.c ++++ gregkh-2.6/drivers/usb/host/pci-quirks.c +@@ -168,8 +168,6 @@ static int __devinit mmio_resource_enabl + static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) + { + void __iomem *base; +- int wait_time; +- u32 control; + + if (!mmio_resource_enabled(pdev, 0)) + return; +@@ -180,9 +178,10 @@ static void __devinit quirk_usb_handoff_ + + /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ + #ifndef __hppa__ +- control = readl(base + OHCI_CONTROL); ++{ ++ u32 control = readl(base + OHCI_CONTROL); + if (control & OHCI_CTRL_IR) { +- wait_time = 500; /* arbitrary; 5 seconds */ ++ int wait_time = 500; /* arbitrary; 5 seconds */ + writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); + writel(OHCI_OCR, base + OHCI_CMDSTATUS); + while (wait_time > 0 && +@@ -199,6 +198,7 @@ static void __devinit quirk_usb_handoff_ + /* reset controller, preserving RWC */ + writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL); + } ++} + #endif + + /* diff --git a/usb/usb-move-linux-usb_otg.h-to-linux-usb-otg.h.patch b/usb/usb-move-linux-usb_otg.h-to-linux-usb-otg.h.patch new file mode 100644 index 0000000000000..b07d5522c46b9 --- /dev/null +++ b/usb/usb-move-linux-usb_otg.h-to-linux-usb-otg.h.patch @@ -0,0 +1,333 @@ +From david-b@pacbell.net Thu Jun 29 14:02:38 2006 +From: David Brownell <david-b@pacbell.net> +To: Greg KH <greg@kroah.com> +Subject: USB: move <linux/usb_otg.h> to <linux/usb/otg.h> +Date: Thu, 29 Jun 2006 12:27:23 -0700 +Message-Id: <200606291227.24267.david-b@pacbell.net> + +Move <linux/usb_otg.h> to <linux/usb/otg.h>. + +Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + arch/arm/plat-omap/usb.c | 2 + drivers/i2c/chips/isp1301_omap.c | 2 + drivers/usb/gadget/omap_udc.c | 2 + drivers/usb/host/ohci-hcd.c | 2 + include/linux/usb/otg.h | 131 +++++++++++++++++++++++++++++++++++++++ + include/linux/usb_otg.h | 131 --------------------------------------- + 6 files changed, 135 insertions(+), 135 deletions(-) + +--- gregkh-2.6.orig/arch/arm/plat-omap/usb.c ++++ gregkh-2.6/arch/arm/plat-omap/usb.c +@@ -27,7 +27,7 @@ + #include <linux/errno.h> + #include <linux/init.h> + #include <linux/platform_device.h> +-#include <linux/usb_otg.h> ++#include <linux/usb/otg.h> + + #include <asm/io.h> + #include <asm/irq.h> +--- gregkh-2.6.orig/drivers/i2c/chips/isp1301_omap.c ++++ gregkh-2.6/drivers/i2c/chips/isp1301_omap.c +@@ -31,7 +31,7 @@ + #include <linux/usb_ch9.h> + #include <linux/usb_gadget.h> + #include <linux/usb.h> +-#include <linux/usb_otg.h> ++#include <linux/usb/otg.h> + #include <linux/i2c.h> + #include <linux/workqueue.h> + +--- gregkh-2.6.orig/drivers/usb/gadget/omap_udc.c ++++ gregkh-2.6/drivers/usb/gadget/omap_udc.c +@@ -41,7 +41,7 @@ + #include <linux/platform_device.h> + #include <linux/usb_ch9.h> + #include <linux/usb_gadget.h> +-#include <linux/usb_otg.h> ++#include <linux/usb/otg.h> + #include <linux/dma-mapping.h> + + #include <asm/byteorder.h> +--- gregkh-2.6.orig/drivers/usb/host/ohci-hcd.c ++++ gregkh-2.6/drivers/usb/host/ohci-hcd.c +@@ -89,7 +89,7 @@ + #include <linux/timer.h> + #include <linux/list.h> + #include <linux/usb.h> +-#include <linux/usb_otg.h> ++#include <linux/usb/otg.h> + #include <linux/dma-mapping.h> + #include <linux/dmapool.h> + #include <linux/reboot.h> +--- /dev/null ++++ gregkh-2.6/include/linux/usb/otg.h +@@ -0,0 +1,131 @@ ++// include/linux/usb/otg.h ++ ++/* ++ * These APIs may be used between USB controllers. USB device drivers ++ * (for either host or peripheral roles) don't use these calls; they ++ * continue to use just usb_device and usb_gadget. ++ */ ++ ++ ++/* OTG defines lots of enumeration states before device reset */ ++enum usb_otg_state { ++ OTG_STATE_UNDEFINED = 0, ++ ++ /* single-role peripheral, and dual-role default-b */ ++ OTG_STATE_B_IDLE, ++ OTG_STATE_B_SRP_INIT, ++ OTG_STATE_B_PERIPHERAL, ++ ++ /* extra dual-role default-b states */ ++ OTG_STATE_B_WAIT_ACON, ++ OTG_STATE_B_HOST, ++ ++ /* dual-role default-a */ ++ OTG_STATE_A_IDLE, ++ OTG_STATE_A_WAIT_VRISE, ++ OTG_STATE_A_WAIT_BCON, ++ OTG_STATE_A_HOST, ++ OTG_STATE_A_SUSPEND, ++ OTG_STATE_A_PERIPHERAL, ++ OTG_STATE_A_WAIT_VFALL, ++ OTG_STATE_A_VBUS_ERR, ++}; ++ ++/* ++ * the otg driver needs to interact with both device side and host side ++ * usb controllers. it decides which controller is active at a given ++ * moment, using the transceiver, ID signal, HNP and sometimes static ++ * configuration information (including "board isn't wired for otg"). ++ */ ++struct otg_transceiver { ++ struct device *dev; ++ const char *label; ++ ++ u8 default_a; ++ enum usb_otg_state state; ++ ++ struct usb_bus *host; ++ struct usb_gadget *gadget; ++ ++ /* to pass extra port status to the root hub */ ++ u16 port_status; ++ u16 port_change; ++ ++ /* bind/unbind the host controller */ ++ int (*set_host)(struct otg_transceiver *otg, ++ struct usb_bus *host); ++ ++ /* bind/unbind the peripheral controller */ ++ int (*set_peripheral)(struct otg_transceiver *otg, ++ struct usb_gadget *gadget); ++ ++ /* effective for B devices, ignored for A-peripheral */ ++ int (*set_power)(struct otg_transceiver *otg, ++ unsigned mA); ++ ++ /* for non-OTG B devices: set transceiver into suspend mode */ ++ int (*set_suspend)(struct otg_transceiver *otg, ++ int suspend); ++ ++ /* for B devices only: start session with A-Host */ ++ int (*start_srp)(struct otg_transceiver *otg); ++ ++ /* start or continue HNP role switch */ ++ int (*start_hnp)(struct otg_transceiver *otg); ++ ++}; ++ ++ ++/* for board-specific init logic */ ++extern int otg_set_transceiver(struct otg_transceiver *); ++ ++ ++/* for usb host and peripheral controller drivers */ ++extern struct otg_transceiver *otg_get_transceiver(void); ++ ++static inline int ++otg_start_hnp(struct otg_transceiver *otg) ++{ ++ return otg->start_hnp(otg); ++} ++ ++ ++/* for HCDs */ ++static inline int ++otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) ++{ ++ return otg->set_host(otg, host); ++} ++ ++ ++/* for usb peripheral controller drivers */ ++static inline int ++otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph) ++{ ++ return otg->set_peripheral(otg, periph); ++} ++ ++static inline int ++otg_set_power(struct otg_transceiver *otg, unsigned mA) ++{ ++ return otg->set_power(otg, mA); ++} ++ ++static inline int ++otg_set_suspend(struct otg_transceiver *otg, int suspend) ++{ ++ if (otg->set_suspend != NULL) ++ return otg->set_suspend(otg, suspend); ++ else ++ return 0; ++} ++ ++static inline int ++otg_start_srp(struct otg_transceiver *otg) ++{ ++ return otg->start_srp(otg); ++} ++ ++ ++/* for OTG controller drivers (and maybe other stuff) */ ++extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num); +--- gregkh-2.6.orig/include/linux/usb_otg.h ++++ /dev/null +@@ -1,131 +0,0 @@ +-// include/linux/usb_otg.h +- +-/* +- * These APIs may be used between USB controllers. USB device drivers +- * (for either host or peripheral roles) don't use these calls; they +- * continue to use just usb_device and usb_gadget. +- */ +- +- +-/* OTG defines lots of enumeration states before device reset */ +-enum usb_otg_state { +- OTG_STATE_UNDEFINED = 0, +- +- /* single-role peripheral, and dual-role default-b */ +- OTG_STATE_B_IDLE, +- OTG_STATE_B_SRP_INIT, +- OTG_STATE_B_PERIPHERAL, +- +- /* extra dual-role default-b states */ +- OTG_STATE_B_WAIT_ACON, +- OTG_STATE_B_HOST, +- +- /* dual-role default-a */ +- OTG_STATE_A_IDLE, +- OTG_STATE_A_WAIT_VRISE, +- OTG_STATE_A_WAIT_BCON, +- OTG_STATE_A_HOST, +- OTG_STATE_A_SUSPEND, +- OTG_STATE_A_PERIPHERAL, +- OTG_STATE_A_WAIT_VFALL, +- OTG_STATE_A_VBUS_ERR, +-}; +- +-/* +- * the otg driver needs to interact with both device side and host side +- * usb controllers. it decides which controller is active at a given +- * moment, using the transceiver, ID signal, HNP and sometimes static +- * configuration information (including "board isn't wired for otg"). +- */ +-struct otg_transceiver { +- struct device *dev; +- const char *label; +- +- u8 default_a; +- enum usb_otg_state state; +- +- struct usb_bus *host; +- struct usb_gadget *gadget; +- +- /* to pass extra port status to the root hub */ +- u16 port_status; +- u16 port_change; +- +- /* bind/unbind the host controller */ +- int (*set_host)(struct otg_transceiver *otg, +- struct usb_bus *host); +- +- /* bind/unbind the peripheral controller */ +- int (*set_peripheral)(struct otg_transceiver *otg, +- struct usb_gadget *gadget); +- +- /* effective for B devices, ignored for A-peripheral */ +- int (*set_power)(struct otg_transceiver *otg, +- unsigned mA); +- +- /* for non-OTG B devices: set transceiver into suspend mode */ +- int (*set_suspend)(struct otg_transceiver *otg, +- int suspend); +- +- /* for B devices only: start session with A-Host */ +- int (*start_srp)(struct otg_transceiver *otg); +- +- /* start or continue HNP role switch */ +- int (*start_hnp)(struct otg_transceiver *otg); +- +-}; +- +- +-/* for board-specific init logic */ +-extern int otg_set_transceiver(struct otg_transceiver *); +- +- +-/* for usb host and peripheral controller drivers */ +-extern struct otg_transceiver *otg_get_transceiver(void); +- +-static inline int +-otg_start_hnp(struct otg_transceiver *otg) +-{ +- return otg->start_hnp(otg); +-} +- +- +-/* for HCDs */ +-static inline int +-otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) +-{ +- return otg->set_host(otg, host); +-} +- +- +-/* for usb peripheral controller drivers */ +-static inline int +-otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph) +-{ +- return otg->set_peripheral(otg, periph); +-} +- +-static inline int +-otg_set_power(struct otg_transceiver *otg, unsigned mA) +-{ +- return otg->set_power(otg, mA); +-} +- +-static inline int +-otg_set_suspend(struct otg_transceiver *otg, int suspend) +-{ +- if (otg->set_suspend != NULL) +- return otg->set_suspend(otg, suspend); +- else +- return 0; +-} +- +-static inline int +-otg_start_srp(struct otg_transceiver *otg) +-{ +- return otg->start_srp(otg); +-} +- +- +-/* for OTG controller drivers (and maybe other stuff) */ +-extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num); diff --git a/usb/usb-ohci-controller-support-for-pnx4008.patch b/usb/usb-ohci-controller-support-for-pnx4008.patch new file mode 100644 index 0000000000000..dd604573d993c --- /dev/null +++ b/usb/usb-ohci-controller-support-for-pnx4008.patch @@ -0,0 +1,545 @@ +From linux-usb-devel-bounces@lists.sourceforge.net Thu Jun 29 07:28:31 2006 +Date: Thu, 29 Jun 2006 18:28:18 +0400 +From: Vitaly Wool <vwool@ru.mvista.com> +Message-Id: <20060629182818.bc0f77f8.vwool@ru.mvista.com> +Subject: USB OHCI controller support for PNX4008 + + +inlined is the patch that adds basic support for USB OHCI controller +support for PNX4008 Philips PNX4008 ARM board. Due to HW design, it +depends on I2C driver for PNX4008 which I've recetnly posted to LKML and +i2c at lm-sensors. + +Signed-off-by: Vitaly Wool <vitalywool@gmail.com> +Cc: David Brownell <david-b@pacbell.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/Kconfig | 1 + drivers/usb/host/Kconfig | 2 + drivers/usb/host/ohci-hcd.c | 5 + drivers/usb/host/ohci-pnx4008.c | 476 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 484 insertions(+) + +--- gregkh-2.6.orig/drivers/usb/Kconfig ++++ gregkh-2.6/drivers/usb/Kconfig +@@ -25,6 +25,7 @@ config USB_ARCH_HAS_OHCI + default y if PXA27x + default y if ARCH_EP93XX + default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) ++ default y if ARCH_PNX4008 + # PPC: + default y if STB03xxx + default y if PPC_MPC52xx +--- gregkh-2.6.orig/drivers/usb/host/Kconfig ++++ gregkh-2.6/drivers/usb/host/Kconfig +@@ -83,6 +83,8 @@ config USB_OHCI_HCD + tristate "OHCI HCD support" + depends on USB && USB_ARCH_HAS_OHCI + select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 ++ select I2C if ARCH_PNX4008 ++ select I2C_PNX if ARCH_PNX4008 + ---help--- + The Open Host Controller Interface (OHCI) is a standard for accessing + USB 1.1 host controller hardware. It does more in hardware than Intel's +--- gregkh-2.6.orig/drivers/usb/host/ohci-hcd.c ++++ gregkh-2.6/drivers/usb/host/ohci-hcd.c +@@ -928,6 +928,10 @@ MODULE_LICENSE ("GPL"); + #include "ohci-at91.c" + #endif + ++#ifdef CONFIG_ARCH_PNX4008 ++#include "ohci-pnx4008.c" ++#endif ++ + #if !(defined(CONFIG_PCI) \ + || defined(CONFIG_SA1111) \ + || defined(CONFIG_ARCH_S3C2410) \ +@@ -939,6 +943,7 @@ MODULE_LICENSE ("GPL"); + || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ + || defined (CONFIG_ARCH_AT91RM9200) \ + || defined (CONFIG_ARCH_AT91SAM9261) \ ++ || defined (CONFIG_ARCH_PNX4008) \ + ) + #error "missing bus glue for ohci-hcd" + #endif +--- /dev/null ++++ gregkh-2.6/drivers/usb/host/ohci-pnx4008.c +@@ -0,0 +1,476 @@ ++/* ++ * drivers/usb/host/ohci-pnx4008.c ++ * ++ * driver for Philips PNX4008 USB Host ++ * ++ * Authors: Dmitry Chigirev <source@mvista.com> ++ * Vitaly Wool <vitalywool@gmail.com> ++ * ++ * register initialization is based on code examples provided by Philips ++ * Copyright (c) 2005 Koninklijke Philips Electronics N.V. ++ * ++ * NOTE: This driver does not have suspend/resume functionality ++ * This driver is intended for engineering development purposes only ++ * ++ * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under ++ * the terms of the GNU General Public License version 2. This program ++ * is licensed "as is" without any warranty of any kind, whether express ++ * or implied. ++ */ ++#include <linux/clk.h> ++#include <linux/platform_device.h> ++#include <linux/i2c.h> ++ ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/mach-types.h> ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/irqs.h> ++#include <asm/arch/gpio.h> ++ ++#define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64) ++ ++/* USB_CTRL bit defines */ ++#define USB_SLAVE_HCLK_EN (1 << 24) ++#define USB_HOST_NEED_CLK_EN (1 << 21) ++ ++#define USB_OTG_CLK_CTRL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF4) ++#define USB_OTG_CLK_STAT IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF8) ++ ++/* USB_OTG_CLK_CTRL bit defines */ ++#define AHB_M_CLOCK_ON (1 << 4) ++#define OTG_CLOCK_ON (1 << 3) ++#define I2C_CLOCK_ON (1 << 2) ++#define DEV_CLOCK_ON (1 << 1) ++#define HOST_CLOCK_ON (1 << 0) ++ ++#define USB_OTG_STAT_CONTROL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x110) ++ ++/* USB_OTG_STAT_CONTROL bit defines */ ++#define TRANSPARENT_I2C_EN (1 << 7) ++#define HOST_EN (1 << 0) ++ ++/* ISP1301 USB transceiver I2C registers */ ++#define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */ ++ ++#define MC1_SPEED_REG (1 << 0) ++#define MC1_SUSPEND_REG (1 << 1) ++#define MC1_DAT_SE0 (1 << 2) ++#define MC1_TRANSPARENT (1 << 3) ++#define MC1_BDIS_ACON_EN (1 << 4) ++#define MC1_OE_INT_EN (1 << 5) ++#define MC1_UART_EN (1 << 6) ++#define MC1_MASK 0x7f ++ ++#define ISP1301_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */ ++ ++#define MC2_GLOBAL_PWR_DN (1 << 0) ++#define MC2_SPD_SUSP_CTRL (1 << 1) ++#define MC2_BI_DI (1 << 2) ++#define MC2_TRANSP_BDIR0 (1 << 3) ++#define MC2_TRANSP_BDIR1 (1 << 4) ++#define MC2_AUDIO_EN (1 << 5) ++#define MC2_PSW_EN (1 << 6) ++#define MC2_EN2V7 (1 << 7) ++ ++#define ISP1301_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */ ++# define OTG1_DP_PULLUP (1 << 0) ++# define OTG1_DM_PULLUP (1 << 1) ++# define OTG1_DP_PULLDOWN (1 << 2) ++# define OTG1_DM_PULLDOWN (1 << 3) ++# define OTG1_ID_PULLDOWN (1 << 4) ++# define OTG1_VBUS_DRV (1 << 5) ++# define OTG1_VBUS_DISCHRG (1 << 6) ++# define OTG1_VBUS_CHRG (1 << 7) ++#define ISP1301_OTG_STATUS 0x10 /* u8 readonly */ ++# define OTG_B_SESS_END (1 << 6) ++# define OTG_B_SESS_VLD (1 << 7) ++ ++#define ISP1301_I2C_ADDR 0x2C ++ ++#define ISP1301_I2C_MODE_CONTROL_1 0x4 ++#define ISP1301_I2C_MODE_CONTROL_2 0x12 ++#define ISP1301_I2C_OTG_CONTROL_1 0x6 ++#define ISP1301_I2C_OTG_CONTROL_2 0x10 ++#define ISP1301_I2C_INTERRUPT_SOURCE 0x8 ++#define ISP1301_I2C_INTERRUPT_LATCH 0xA ++#define ISP1301_I2C_INTERRUPT_FALLING 0xC ++#define ISP1301_I2C_INTERRUPT_RISING 0xE ++#define ISP1301_I2C_REG_CLEAR_ADDR 1 ++ ++struct i2c_driver isp1301_driver; ++struct i2c_client *isp1301_i2c_client; ++ ++extern int usb_disabled(void); ++extern int ocpi_enable(void); ++ ++static struct clk *usb_clk; ++ ++static int isp1301_probe(struct i2c_adapter *adap); ++static int isp1301_detach(struct i2c_client *client); ++static int isp1301_command(struct i2c_client *client, unsigned int cmd, ++ void *arg); ++ ++static unsigned short normal_i2c[] = ++ { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END }; ++static unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END }; ++ ++static struct i2c_client_address_data addr_data = { ++ .normal_i2c = normal_i2c, ++ .probe = dummy_i2c_addrlist, ++ .ignore = dummy_i2c_addrlist, ++}; ++ ++struct i2c_driver isp1301_driver = { ++ .id = I2C_DRIVERID_I2CDEV, /* Fake Id */ ++ .class = I2C_CLASS_HWMON, ++ .attach_adapter = isp1301_probe, ++ .detach_client = isp1301_detach, ++ .command = isp1301_command ++}; ++ ++static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind) ++{ ++ struct i2c_client *c; ++ ++ c = (struct i2c_client *)kzalloc(sizeof(*c), SLAB_KERNEL); ++ ++ if (!c) ++ return -ENOMEM; ++ ++ strcpy(c->name, "isp1301"); ++ c->flags = 0; ++ c->addr = addr; ++ c->adapter = adap; ++ c->driver = &isp1301_driver; ++ ++ isp1301_i2c_client = c; ++ ++ return i2c_attach_client(c); ++} ++ ++static int isp1301_probe(struct i2c_adapter *adap) ++{ ++ return i2c_probe(adap, &addr_data, isp1301_attach); ++} ++ ++static int isp1301_detach(struct i2c_client *client) ++{ ++ i2c_detach_client(client); ++ kfree(isp1301_i2c_client); ++ return 0; ++} ++ ++/* No commands defined */ ++static int isp1301_command(struct i2c_client *client, unsigned int cmd, ++ void *arg) ++{ ++ return 0; ++} ++ ++static void i2c_write(u8 buf, u8 subaddr) ++{ ++ char tmpbuf[2]; ++ ++ tmpbuf[0] = subaddr; /*register number */ ++ tmpbuf[1] = buf; /*register data */ ++ i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2); ++} ++ ++static void isp1301_configure(void) ++{ ++ /* PNX4008 only supports DAT_SE0 USB mode */ ++ /* PNX4008 R2A requires setting the MAX603 to output 3.6V */ ++ /* Power up externel charge-pump */ ++ ++ i2c_write(MC1_DAT_SE0 | MC1_SPEED_REG, ISP1301_I2C_MODE_CONTROL_1); ++ i2c_write(~(MC1_DAT_SE0 | MC1_SPEED_REG), ++ ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); ++ i2c_write(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL, ++ ISP1301_I2C_MODE_CONTROL_2); ++ i2c_write(~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL), ++ ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR); ++ i2c_write(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN, ++ ISP1301_I2C_OTG_CONTROL_1); ++ i2c_write(~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN), ++ ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); ++ i2c_write(0xFF, ++ ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR); ++ i2c_write(0xFF, ++ ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR); ++ i2c_write(0xFF, ++ ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR); ++ ++} ++ ++static inline void isp1301_vbus_on(void) ++{ ++ i2c_write(OTG1_VBUS_DRV, ISP1301_I2C_OTG_CONTROL_1); ++} ++ ++static inline void isp1301_vbus_off(void) ++{ ++ i2c_write(OTG1_VBUS_DRV, ++ ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); ++} ++ ++static void pnx4008_start_hc(void) ++{ ++ unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN; ++ __raw_writel(tmp, USB_OTG_STAT_CONTROL); ++ isp1301_vbus_on(); ++} ++ ++static void pnx4008_stop_hc(void) ++{ ++ unsigned long tmp; ++ isp1301_vbus_off(); ++ tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN; ++ __raw_writel(tmp, USB_OTG_STAT_CONTROL); ++} ++ ++static int __devinit ohci_pnx4008_start(struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ int ret; ++ ++ if ((ret = ohci_init(ohci)) < 0) ++ return ret; ++ ++ if ((ret = ohci_run(ohci)) < 0) { ++ dev_err(hcd->self.controller, "can't start\n"); ++ ohci_stop(hcd); ++ return ret; ++ } ++ return 0; ++} ++ ++static const struct hc_driver ohci_pnx4008_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "pnx4008 OHCI", ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ohci_irq, ++ .flags = HCD_USB11 | HCD_MEMORY, ++ ++ .hcd_priv_size = sizeof(struct ohci_hcd), ++ /* ++ * basic lifecycle operations ++ */ ++ .start = ohci_pnx4008_start, ++ .stop = ohci_stop, ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ohci_urb_enqueue, ++ .urb_dequeue = ohci_urb_dequeue, ++ .endpoint_disable = ohci_endpoint_disable, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ohci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ohci_hub_status_data, ++ .hub_control = ohci_hub_control, ++ ++ .start_port_reset = ohci_start_port_reset, ++}; ++ ++#define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON) ++ ++static void pnx4008_set_usb_bits(void) ++{ ++ start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N); ++ start_int_ack(SE_USB_OTG_ATX_INT_N); ++ start_int_umask(SE_USB_OTG_ATX_INT_N); ++ ++ start_int_set_rising_edge(SE_USB_OTG_TIMER_INT); ++ start_int_ack(SE_USB_OTG_TIMER_INT); ++ start_int_umask(SE_USB_OTG_TIMER_INT); ++ ++ start_int_set_rising_edge(SE_USB_I2C_INT); ++ start_int_ack(SE_USB_I2C_INT); ++ start_int_umask(SE_USB_I2C_INT); ++ ++ start_int_set_rising_edge(SE_USB_INT); ++ start_int_ack(SE_USB_INT); ++ start_int_umask(SE_USB_INT); ++ ++ start_int_set_rising_edge(SE_USB_NEED_CLK_INT); ++ start_int_ack(SE_USB_NEED_CLK_INT); ++ start_int_umask(SE_USB_NEED_CLK_INT); ++ ++ start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT); ++ start_int_ack(SE_USB_AHB_NEED_CLK_INT); ++ start_int_umask(SE_USB_AHB_NEED_CLK_INT); ++} ++ ++static void pnx4008_unset_usb_bits(void) ++{ ++ start_int_mask(SE_USB_OTG_ATX_INT_N); ++ start_int_mask(SE_USB_OTG_TIMER_INT); ++ start_int_mask(SE_USB_I2C_INT); ++ start_int_mask(SE_USB_INT); ++ start_int_mask(SE_USB_NEED_CLK_INT); ++ start_int_mask(SE_USB_AHB_NEED_CLK_INT); ++} ++ ++static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) ++{ ++ struct usb_hcd *hcd = 0; ++ struct ohci_hcd *ohci; ++ const struct hc_driver *driver = &ohci_pnx4008_hc_driver; ++ ++ int ret = 0, irq; ++ ++ dev_dbg(&pdev->dev, "%s: " DRIVER_INFO " (pnx4008)\n", hcd_name); ++ if (usb_disabled()) { ++ err("USB is disabled"); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ if (pdev->num_resources != 2 ++ || pdev->resource[0].flags != IORESOURCE_MEM ++ || pdev->resource[1].flags != IORESOURCE_IRQ) { ++ err("Invalid resource configuration"); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ /* Enable AHB slave USB clock, needed for further USB clock control */ ++ __raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL); ++ ++ ret = i2c_add_driver(&isp1301_driver); ++ if (ret < 0) { ++ err("failed to connect I2C to ISP1301 USB Transceiver"); ++ goto out; ++ } ++ ++ isp1301_configure(); ++ ++ /* Enable USB PLL */ ++ usb_clk = clk_get(&pdev->dev, "ck_pll5"); ++ if (IS_ERR(usb_clk)) { ++ err("failed to acquire USB PLL"); ++ ret = PTR_ERR(usb_clk); ++ goto out1; ++ } ++ ++ ret = clk_enable(usb_clk); ++ if (ret < 0) { ++ err("failed to start USB PLL"); ++ goto out2; ++ } ++ ++ ret = clk_set_rate(usb_clk, 48000); ++ if (ret < 0) { ++ err("failed to set USB clock rate"); ++ goto out3; ++ } ++ ++ __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL); ++ ++ /* Set to enable all needed USB clocks */ ++ __raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL); ++ ++ while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) != ++ USB_CLOCK_MASK) ; ++ ++ hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id); ++ if (!hcd) { ++ err("Failed to allocate HC buffer"); ++ ret = -ENOMEM; ++ goto out3; ++ } ++ ++ /* Set all USB bits in the Start Enable register */ ++ pnx4008_set_usb_bits(); ++ ++ hcd->rsrc_start = pdev->resource[0].start; ++ hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; ++ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { ++ dev_dbg(&pdev->dev, "request_mem_region failed\n"); ++ ret = -ENOMEM; ++ goto out4; ++ } ++ hcd->regs = (void __iomem *)pdev->resource[0].start; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ ret = -ENXIO; ++ goto out4; ++ } ++ ++ hcd->self.hcpriv = (void *)hcd; ++ ++ pnx4008_start_hc(); ++ platform_set_drvdata(pdev, hcd); ++ ohci = hcd_to_ohci(hcd); ++ ohci_hcd_init(ohci); ++ ++ dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq); ++ ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); ++ if (ret == 0) ++ return ret; ++ ++ pnx4008_stop_hc(); ++out4: ++ pnx4008_unset_usb_bits(); ++ usb_put_hcd(hcd); ++out3: ++ clk_disable(usb_clk); ++out2: ++ clk_put(usb_clk); ++out1: ++ i2c_del_driver(&isp1301_driver); ++out: ++ return ret; ++} ++ ++static int usb_hcd_pnx4008_remove(struct platform_device *pdev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(pdev); ++ ++ usb_remove_hcd(hcd); ++ pnx4008_stop_hc(); ++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); ++ usb_put_hcd(hcd); ++ pnx4008_unset_usb_bits(); ++ clk_disable(usb_clk); ++ clk_put(usb_clk); ++ i2c_del_driver(&isp1301_driver); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static struct platform_driver usb_hcd_pnx4008_driver = { ++ .driver = { ++ .name = "usb-ohci", ++ }, ++ .probe = usb_hcd_pnx4008_probe, ++ .remove = usb_hcd_pnx4008_remove, ++}; ++ ++static int __init usb_hcd_pnx4008_init(void) ++{ ++ return platform_driver_register(&usb_hcd_pnx4008_driver); ++} ++ ++static void __exit usb_hcd_pnx4008_cleanup(void) ++{ ++ return platform_driver_unregister(&usb_hcd_pnx4008_driver); ++} ++ ++module_init(usb_hcd_pnx4008_init); ++module_exit(usb_hcd_pnx4008_cleanup); diff --git a/usb/usb-ohci-s3c2410.c-clock-now-usb-bus-host.patch b/usb/usb-ohci-s3c2410.c-clock-now-usb-bus-host.patch new file mode 100644 index 0000000000000..c13c05a65b142 --- /dev/null +++ b/usb/usb-ohci-s3c2410.c-clock-now-usb-bus-host.patch @@ -0,0 +1,40 @@ +From ben@fluff.org.uk Mon Jun 26 15:37:21 2006 +Date: Mon, 26 Jun 2006 23:36:07 +0100 +From: Ben Dooks <ben-linux@fluff.org> +Cc: gregkh@suse.de +Subject: USB: ohci-s3c2410.c: clock now usb-bus-host +Message-ID: <20060626223607.GA1788@home.fluff.org> +Content-Disposition: inline + +With the newer Samsung S3C2412 and S3C2413 SoC devices, +the 48MHz USB clock has been given an individual gate +into the USB OHCI and gadget blocks. + +This clock is called usb-bus-clock, and we need to +replace the old use of the USB PLL (upll) directly +with the new usb-bus-host. + +The S3C2410 clock driver has been updated already to +provide a virtual clock which is a child of the UPLL +to maintain compatibility. The S3C2412 clock driver +correctly enables the PLL when either usb-bus clock +is active. + +Signed-off-by: Ben Dooks <ben-linux@fluff.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/ohci-s3c2410.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- gregkh-2.6.orig/drivers/usb/host/ohci-s3c2410.c ++++ gregkh-2.6/drivers/usb/host/ohci-s3c2410.c +@@ -370,7 +370,7 @@ static int usb_hcd_s3c2410_probe (const + goto err_mem; + } + +- usb_clk = clk_get(&dev->dev, "upll"); ++ usb_clk = clk_get(&dev->dev, "usb-bus-host"); + if (IS_ERR(usb_clk)) { + dev_err(&dev->dev, "cannot get usb-host clock\n"); + retval = -ENOENT; diff --git a/usb/usb-pxa2xx_udc-understands-gpio-based-vbus-sensing.patch b/usb/usb-pxa2xx_udc-understands-gpio-based-vbus-sensing.patch new file mode 100644 index 0000000000000..70896d80002f0 --- /dev/null +++ b/usb/usb-pxa2xx_udc-understands-gpio-based-vbus-sensing.patch @@ -0,0 +1,231 @@ +From david-b@pacbell.net Thu Jun 29 14:02:38 2006 +From: David Brownell <david-b@pacbell.net> +To: Greg KH <greg@kroah.com> +Subject: USB: pxa2xx_udc understands GPIO based VBUS sensing +Date: Thu, 29 Jun 2006 12:25:39 -0700 +Cc: linux-usb-devel@lists.sourceforge.net, Dave Hylands <dhylands@gmail.com> +Message-Id: <200606291225.39983.david-b@pacbell.net> + +This updates the PXA 25x UDC board-independent infrastructure for VBUS sensing +and the D+ pullup. The original code evolved from rather bizarre support on +Intel's "Lubbock" reference hardware, so that on more sensible hardware it +doesn't work as well as it could/should. + +The change is just to teach the UDC driver how to use built-in PXA GPIO pins +directly. This reduces the amount of board-specfic object code needed, and +enables the use of a VBUS sensing IRQ on boards (like Gumstix) that have one. +With VBUS sensing, the UDC is unclocked until a host is actually connected. + +Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + arch/arm/mach-pxa/corgi.c | 15 -------- + drivers/usb/gadget/pxa2xx_udc.c | 70 ++++++++++++++++++++++++++++++++++++++-- + drivers/usb/gadget/pxa2xx_udc.h | 24 ++++--------- + include/asm-arm/arch-pxa/udc.h | 8 ++++ + 4 files changed, 85 insertions(+), 32 deletions(-) + +--- gregkh-2.6.orig/arch/arm/mach-pxa/corgi.c ++++ gregkh-2.6/arch/arm/mach-pxa/corgi.c +@@ -284,21 +284,9 @@ static struct pxaficp_platform_data corg + /* + * USB Device Controller + */ +-static void corgi_udc_command(int cmd) +-{ +- switch(cmd) { +- case PXA2XX_UDC_CMD_CONNECT: +- GPSR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP); +- break; +- case PXA2XX_UDC_CMD_DISCONNECT: +- GPCR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP); +- break; +- } +-} +- + static struct pxa2xx_udc_mach_info udc_info __initdata = { + /* no connect GPIO; corgi can't tell connection status */ +- .udc_command = corgi_udc_command, ++ .gpio_pullup = CORGI_GPIO_USB_PULLUP, + }; + + +@@ -350,7 +338,6 @@ static void __init corgi_init(void) + corgi_ssp_set_machinfo(&corgi_ssp_machinfo); + + pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT); +- pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT); + pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN); + + pxa_set_udc_info(&udc_info); +--- gregkh-2.6.orig/drivers/usb/gadget/pxa2xx_udc.c ++++ gregkh-2.6/drivers/usb/gadget/pxa2xx_udc.c +@@ -151,6 +151,39 @@ MODULE_PARM_DESC (fifo_mode, "pxa2xx udc + static void pxa2xx_ep_fifo_flush (struct usb_ep *ep); + static void nuke (struct pxa2xx_ep *, int status); + ++/* one GPIO should be used to detect VBUS from the host */ ++static int is_vbus_present(void) ++{ ++ struct pxa2xx_udc_mach_info *mach = the_controller->mach; ++ ++ if (mach->gpio_vbus) ++ return pxa_gpio_get(mach->gpio_vbus); ++ if (mach->udc_is_connected) ++ return mach->udc_is_connected(); ++ return 1; ++} ++ ++/* one GPIO should control a D+ pullup, so host sees this device (or not) */ ++static void pullup_off(void) ++{ ++ struct pxa2xx_udc_mach_info *mach = the_controller->mach; ++ ++ if (mach->gpio_pullup) ++ pxa_gpio_set(mach->gpio_pullup, 0); ++ else if (mach->udc_command) ++ mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); ++} ++ ++static void pullup_on(void) ++{ ++ struct pxa2xx_udc_mach_info *mach = the_controller->mach; ++ ++ if (mach->gpio_pullup) ++ pxa_gpio_set(mach->gpio_pullup, 1); ++ else if (mach->udc_command) ++ mach->udc_command(PXA2XX_UDC_CMD_CONNECT); ++} ++ + static void pio_irq_enable(int bEndpointAddress) + { + bEndpointAddress &= 0xf; +@@ -1722,6 +1755,16 @@ lubbock_vbus_irq(int irq, void *_dev, st + + #endif + ++static irqreturn_t ++udc_vbus_irq(int irq, void *_dev, struct pt_regs *r) ++{ ++ struct pxa2xx_udc *dev = _dev; ++ int vbus = pxa_gpio_get(dev->mach->gpio_vbus); ++ ++ pxa2xx_udc_vbus_session(&dev->gadget, vbus); ++ return IRQ_HANDLED; ++} ++ + + /*-------------------------------------------------------------------------*/ + +@@ -2439,7 +2482,7 @@ static struct pxa2xx_udc memory = { + static int __init pxa2xx_udc_probe(struct platform_device *pdev) + { + struct pxa2xx_udc *dev = &memory; +- int retval, out_dma = 1; ++ int retval, out_dma = 1, vbus_irq; + u32 chiprev; + + /* insist on Intel/ARM/XScale */ +@@ -2503,6 +2546,16 @@ static int __init pxa2xx_udc_probe(struc + /* other non-static parts of init */ + dev->dev = &pdev->dev; + dev->mach = pdev->dev.platform_data; ++ if (dev->mach->gpio_vbus) { ++ vbus_irq = IRQ_GPIO(dev->mach->gpio_vbus & GPIO_MD_MASK_NR); ++ pxa_gpio_mode((dev->mach->gpio_vbus & GPIO_MD_MASK_NR) ++ | GPIO_IN); ++ set_irq_type(vbus_irq, IRQT_BOTHEDGE); ++ } else ++ vbus_irq = 0; ++ if (dev->mach->gpio_pullup) ++ pxa_gpio_mode((dev->mach->gpio_pullup & GPIO_MD_MASK_NR) ++ | GPIO_OUT | GPIO_DFLT_LOW); + + init_timer(&dev->timer); + dev->timer.function = udc_watchdog; +@@ -2558,8 +2611,19 @@ lubbock_fail0: + HEX_DISPLAY(dev->stats.irqs); + LUB_DISC_BLNK_LED &= 0xff; + #endif +- } ++ } else + #endif ++ if (vbus_irq) { ++ retval = request_irq(vbus_irq, udc_vbus_irq, ++ SA_INTERRUPT | SA_SAMPLE_RANDOM, ++ driver_name, dev); ++ if (retval != 0) { ++ printk(KERN_ERR "%s: can't get irq %i, err %d\n", ++ driver_name, vbus_irq, retval); ++ free_irq(IRQ_USB, dev); ++ return -EBUSY; ++ } ++ } + create_proc_files(); + + return 0; +@@ -2588,6 +2652,8 @@ static int __exit pxa2xx_udc_remove(stru + free_irq(LUBBOCK_USB_IRQ, dev); + } + #endif ++ if (dev->mach->gpio_vbus) ++ free_irq(IRQ_GPIO(dev->mach->gpio_vbus), dev); + platform_set_drvdata(pdev, NULL); + the_controller = NULL; + return 0; +--- gregkh-2.6.orig/drivers/usb/gadget/pxa2xx_udc.h ++++ gregkh-2.6/drivers/usb/gadget/pxa2xx_udc.h +@@ -177,27 +177,19 @@ struct pxa2xx_udc { + + static struct pxa2xx_udc *the_controller; + +-/* one GPIO should be used to detect VBUS from the host */ +-static inline int is_vbus_present(void) ++static inline int pxa_gpio_get(unsigned gpio) + { +- if (!the_controller->mach->udc_is_connected) +- return 1; +- return the_controller->mach->udc_is_connected(); ++ return (GPLR(gpio) & GPIO_bit(gpio)) != 0; + } + +-/* one GPIO should control a D+ pullup, so host sees this device (or not) */ +-static inline void pullup_off(void) ++static inline void pxa_gpio_set(unsigned gpio, int is_on) + { +- if (!the_controller->mach->udc_command) +- return; +- the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); +-} ++ int mask = GPIO_bit(gpio); + +-static inline void pullup_on(void) +-{ +- if (!the_controller->mach->udc_command) +- return; +- the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); ++ if (is_on) ++ GPSR(gpio) = mask; ++ else ++ GPCR(gpio) = mask; + } + + /*-------------------------------------------------------------------------*/ +--- gregkh-2.6.orig/include/asm-arm/arch-pxa/udc.h ++++ gregkh-2.6/include/asm-arm/arch-pxa/udc.h +@@ -12,6 +12,14 @@ struct pxa2xx_udc_mach_info { + void (*udc_command)(int cmd); + #define PXA2XX_UDC_CMD_CONNECT 0 /* let host see us */ + #define PXA2XX_UDC_CMD_DISCONNECT 1 /* so host won't see us */ ++ ++ /* Boards following the design guidelines in the developer's manual, ++ * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane ++ * VBUS IRQ and omit the methods above. Store the GPIO number ++ * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits. ++ */ ++ u16 gpio_vbus; /* high == vbus present */ ++ u16 gpio_pullup; /* high == pullup activated */ + }; + + extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info); diff --git a/usb/usb-serial-ftdi_sio-prevent-userspace-dos.patch b/usb/usb-serial-ftdi_sio-prevent-userspace-dos.patch new file mode 100644 index 0000000000000..a61e99ce6349a --- /dev/null +++ b/usb/usb-serial-ftdi_sio-prevent-userspace-dos.patch @@ -0,0 +1,234 @@ +From ian.abbott@mev.co.uk Mon Jun 26 04:59:49 2006 +Message-ID: <449FCC15.3020903@mev.co.uk> +Date: Mon, 26 Jun 2006 12:59:17 +0100 +From: Ian Abbott <abbotti@mev.co.uk> +To: linux-usb-devel@lists.sourceforge.net +Cc: Greg KH <greg@kroah.com>, Guillaume Autran <gautran@mrv.com> +Subject: USB serial ftdi_sio: Prevent userspace DoS + +From: Ian Abbott <abbotti@mev.co.uk> + +This patch limits the amount of outstanding 'write' data that can be +queued up for the ftdi_sio driver, to prevent userspace DoS attacks (or +simple accidents) that use up all the system memory by writing lots of +data to the serial port. + +The original patch was by Guillaume Autran, who in turn based it on the +same mechanism implemented in the 'visor' driver. I (Ian Abbott) +re-targeted the patch to the latest sources, fixed a couple of errors, +renamed his new structure members, and updated the implementations of +the 'write_room' and 'chars_in_buffer' methods to take account of the +number of outstanding 'write' bytes. It seems to work fine, though at +low baud rates it is still possible to queue up an amount of data that +takes an age to shift (a job for another day!). + +Signed-off-by: Ian Abbott <abbotti@mev.co.uk> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/ftdi_sio.c | 103 ++++++++++++++++++++++++++++++++++++------ + 1 file changed, 90 insertions(+), 13 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/serial/ftdi_sio.c ++++ gregkh-2.6/drivers/usb/serial/ftdi_sio.c +@@ -551,11 +551,17 @@ struct ftdi_private { + spinlock_t rx_lock; /* spinlock for receive state */ + struct work_struct rx_work; + int rx_processed; ++ unsigned long rx_bytes; + + __u16 interface; /* FT2232C port interface (0 for FT232/245) */ + + int force_baud; /* if non-zero, force the baud rate to this value */ + int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ ++ ++ spinlock_t tx_lock; /* spinlock for transmit state */ ++ unsigned long tx_bytes; ++ unsigned long tx_outstanding_bytes; ++ unsigned long tx_outstanding_urbs; + }; + + /* Used for TIOCMIWAIT */ +@@ -629,6 +635,9 @@ static struct usb_serial_driver ftdi_sio + #define HIGH 1 + #define LOW 0 + ++/* number of outstanding urbs to prevent userspace DoS from happening */ ++#define URB_UPPER_LIMIT 42 ++ + /* + * *************************************************************************** + * Utlity functions +@@ -1159,6 +1168,7 @@ static int ftdi_sio_attach (struct usb_s + } + + spin_lock_init(&priv->rx_lock); ++ spin_lock_init(&priv->tx_lock); + init_waitqueue_head(&priv->delta_msr_wait); + /* This will push the characters through immediately rather + than queue a task to deliver them */ +@@ -1273,6 +1283,13 @@ static int ftdi_open (struct usb_serial + + dbg("%s", __FUNCTION__); + ++ spin_lock_irqsave(&priv->tx_lock, flags); ++ priv->tx_bytes = 0; ++ spin_unlock_irqrestore(&priv->tx_lock, flags); ++ spin_lock_irqsave(&priv->rx_lock, flags); ++ priv->rx_bytes = 0; ++ spin_unlock_irqrestore(&priv->rx_lock, flags); ++ + if (port->tty) + port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + +@@ -1375,6 +1392,7 @@ static int ftdi_write (struct usb_serial + int data_offset ; /* will be 1 for the SIO and 0 otherwise */ + int status; + int transfer_size; ++ unsigned long flags; + + dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count); + +@@ -1382,6 +1400,13 @@ static int ftdi_write (struct usb_serial + dbg("write request of 0 bytes"); + return 0; + } ++ spin_lock_irqsave(&priv->tx_lock, flags); ++ if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) { ++ spin_unlock_irqrestore(&priv->tx_lock, flags); ++ dbg("%s - write limit hit\n", __FUNCTION__); ++ return 0; ++ } ++ spin_unlock_irqrestore(&priv->tx_lock, flags); + + data_offset = priv->write_offset; + dbg("data_offset set to %d",data_offset); +@@ -1448,6 +1473,12 @@ static int ftdi_write (struct usb_serial + err("%s - failed submitting write urb, error %d", __FUNCTION__, status); + count = status; + kfree (buffer); ++ } else { ++ spin_lock_irqsave(&priv->tx_lock, flags); ++ ++priv->tx_outstanding_urbs; ++ priv->tx_outstanding_bytes += count; ++ priv->tx_bytes += count; ++ spin_unlock_irqrestore(&priv->tx_lock, flags); + } + + /* we are done with this urb, so let the host driver +@@ -1463,7 +1494,11 @@ static int ftdi_write (struct usb_serial + + static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) + { ++ unsigned long flags; + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; ++ struct ftdi_private *priv; ++ int data_offset; /* will be 1 for the SIO and 0 otherwise */ ++ unsigned long countback; + + /* free up the transfer buffer, as usb_free_urb() does not do this */ + kfree (urb->transfer_buffer); +@@ -1475,34 +1510,67 @@ static void ftdi_write_bulk_callback (st + return; + } + ++ priv = usb_get_serial_port_data(port); ++ if (!priv) { ++ dbg("%s - bad port private data pointer - exiting", __FUNCTION__); ++ return; ++ } ++ /* account for transferred data */ ++ countback = urb->actual_length; ++ data_offset = priv->write_offset; ++ if (data_offset > 0) { ++ /* Subtract the control bytes */ ++ countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ)); ++ } ++ spin_lock_irqsave(&priv->tx_lock, flags); ++ --priv->tx_outstanding_urbs; ++ priv->tx_outstanding_bytes -= countback; ++ spin_unlock_irqrestore(&priv->tx_lock, flags); ++ + usb_serial_port_softint(port); + } /* ftdi_write_bulk_callback */ + + + static int ftdi_write_room( struct usb_serial_port *port ) + { ++ struct ftdi_private *priv = usb_get_serial_port_data(port); ++ int room; ++ unsigned long flags; ++ + dbg("%s - port %d", __FUNCTION__, port->number); + +- /* +- * We really can take anything the user throws at us +- * but let's pick a nice big number to tell the tty +- * layer that we have lots of free space +- */ +- return 2048; ++ spin_lock_irqsave(&priv->tx_lock, flags); ++ if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) { ++ /* ++ * We really can take anything the user throws at us ++ * but let's pick a nice big number to tell the tty ++ * layer that we have lots of free space ++ */ ++ room = 2048; ++ } else { ++ room = 0; ++ } ++ spin_unlock_irqrestore(&priv->tx_lock, flags); ++ return room; + } /* ftdi_write_room */ + + + static int ftdi_chars_in_buffer (struct usb_serial_port *port) + { /* ftdi_chars_in_buffer */ ++ struct ftdi_private *priv = usb_get_serial_port_data(port); ++ int buffered; ++ unsigned long flags; ++ + dbg("%s - port %d", __FUNCTION__, port->number); + +- /* +- * We can't really account for how much data we +- * have sent out, but hasn't made it through to the +- * device, so just tell the tty layer that everything +- * is flushed. +- */ +- return 0; ++ spin_lock_irqsave(&priv->tx_lock, flags); ++ buffered = (int)priv->tx_outstanding_bytes; ++ spin_unlock_irqrestore(&priv->tx_lock, flags); ++ if (buffered < 0) { ++ err("%s outstanding tx bytes is negative!", __FUNCTION__); ++ buffered = 0; ++ } ++ return buffered; + } /* ftdi_chars_in_buffer */ + + +@@ -1512,6 +1580,8 @@ static void ftdi_read_bulk_callback (str + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct tty_struct *tty; + struct ftdi_private *priv; ++ unsigned long countread; ++ unsigned long flags; + + if (urb->number_of_packets > 0) { + err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, +@@ -1546,6 +1616,13 @@ static void ftdi_read_bulk_callback (str + return; + } + ++ /* count data bytes, but not status bytes */ ++ countread = urb->actual_length; ++ countread -= 2 * ((countread + (PKTSZ - 1)) / PKTSZ); ++ spin_lock_irqsave(&priv->rx_lock, flags); ++ priv->rx_bytes += countread; ++ spin_unlock_irqrestore(&priv->rx_lock, flags); ++ + ftdi_process_read(port); + + } /* ftdi_read_bulk_callback */ diff --git a/usb/usb-serial-visor-fix-race-in-open-close.patch b/usb/usb-serial-visor-fix-race-in-open-close.patch new file mode 100644 index 0000000000000..c6482430c49d1 --- /dev/null +++ b/usb/usb-serial-visor-fix-race-in-open-close.patch @@ -0,0 +1,45 @@ +From ian.abbott@mev.co.uk Mon Jun 26 03:44:29 2006 +Message-ID: <449FBA86.5070800@mev.co.uk> +Date: Mon, 26 Jun 2006 11:44:22 +0100 +From: Ian Abbott <abbotti@mev.co.uk> +Cc: Greg KH <greg@kroah.com> +Subject: USB serial visor: fix race in open/close + +From: Ian Abbott <abbotti@mev.co.uk> + +The anti user-DoS mechanism in the USB serial 'visor' driver can fail in +the following way: + +visor_open: priv->outstanding_urbs = 0 +visor_write: ++priv->outstanding_urbs +visor_close: +visor_open: priv->outstanding_urbs = 0 +visor_write_bulk_callback: --priv->outstanding_urbs + +So priv->outstanding_urbs ends up as (unsigned long)(-1). Not good! + +I haven't seen this happen with the visor driver as I don't have the +hardware, but I have seen it while testing a patch to implement the same +functionality in the ftdi_sio driver (patch not yet submitted). + +The fix is pretty simple: don't reinitialize outstanding_urbs in +visor_open. (Again, I haven't tested the fix in visor, but I have +tested it in ftdi_sio.) + +Signed-off-by: Ian Abbott <abbotti@mev.co.uk> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/visor.c | 1 - + 1 file changed, 1 deletion(-) + +--- gregkh-2.6.orig/drivers/usb/serial/visor.c ++++ gregkh-2.6/drivers/usb/serial/visor.c +@@ -303,7 +303,6 @@ static int visor_open (struct usb_serial + spin_lock_irqsave(&priv->lock, flags); + priv->bytes_in = 0; + priv->bytes_out = 0; +- priv->outstanding_urbs = 0; + priv->throttled = 0; + spin_unlock_irqrestore(&priv->lock, flags); + diff --git a/usb/usb-storage-uname-in-pr-sc-unneeded-message.patch b/usb/usb-storage-uname-in-pr-sc-unneeded-message.patch new file mode 100644 index 0000000000000..a28d047e25cba --- /dev/null +++ b/usb/usb-storage-uname-in-pr-sc-unneeded-message.patch @@ -0,0 +1,48 @@ +From phil@ipom.com Sat Jun 24 17:27:58 2006 +Message-ID: <449DD88A.8040003@ipom.com> +Date: Sat, 24 Jun 2006 17:27:54 -0700 +From: Phil Dibowitz <phil@ipom.com> +To: Greg KH <greg@kroah.com> +Subject: USB Storage: Uname in PR/SC Unneeded message + +This patch adds the kernel version to the usb-storage Protocol/SubClass +unneeded message in order to help us troubleshoot such problems. + +Signed-off-by: Phil Dibowitz <phil@ipom.com> +Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/storage/usb.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/storage/usb.c ++++ gregkh-2.6/drivers/usb/storage/usb.c +@@ -47,6 +47,7 @@ + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + ++#include <linux/version.h> + #include <linux/config.h> + #include <linux/sched.h> + #include <linux/errno.h> +@@ -529,7 +530,8 @@ static void get_device_info(struct us_da + if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE)) + printk(KERN_NOTICE USB_STORAGE "This device " + "(%04x,%04x,%04x S %02x P %02x)" +- " has %s in unusual_devs.h\n" ++ " has %s in unusual_devs.h (kernel" ++ " %s)\n" + " Please send a copy of this message to " + "<linux-usb-devel@lists.sourceforge.net>\n", + le16_to_cpu(ddesc->idVendor), +@@ -537,7 +539,8 @@ static void get_device_info(struct us_da + le16_to_cpu(ddesc->bcdDevice), + idesc->bInterfaceSubClass, + idesc->bInterfaceProtocol, +- msgs[msg]); ++ msgs[msg], ++ UTS_RELEASE); + } + } + diff --git a/usb/usb-storage-us_fl_max_sectors_64-flag.patch b/usb/usb-storage-us_fl_max_sectors_64-flag.patch new file mode 100644 index 0000000000000..59811c57f4f42 --- /dev/null +++ b/usb/usb-storage-us_fl_max_sectors_64-flag.patch @@ -0,0 +1,109 @@ +From phil@ipom.com Sat Jun 24 17:27:17 2006 +Message-ID: <449DD85E.7080503@ipom.com> +Date: Sat, 24 Jun 2006 17:27:10 -0700 +From: Phil Dibowitz <phil@ipom.com> +To: Greg KH <greg@kroah.com> +Subject: USB Storage: US_FL_MAX_SECTORS_64 flag + + +This patch adds a US_FL_MAX_SECTORS_64 and removes the Genesys special-cases +for this that were in scsiglue.c. It also adds the flag to other devices +reported to need it. + +Signed-off-by: Phil Dibowitz <phil@ipom.com> +Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + + +--- + drivers/usb/storage/scsiglue.c | 12 +++++------- + drivers/usb/storage/unusual_devs.h | 16 ++++++++++++++-- + drivers/usb/storage/usb.h | 4 ---- + include/linux/usb_usual.h | 2 ++ + 4 files changed, 21 insertions(+), 13 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/storage/scsiglue.c ++++ gregkh-2.6/drivers/usb/storage/scsiglue.c +@@ -112,13 +112,11 @@ static int slave_configure(struct scsi_d + if (sdev->scsi_level < SCSI_2) + sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2; + +- /* According to the technical support people at Genesys Logic, +- * devices using their chips have problems transferring more than +- * 32 KB at a time. In practice people have found that 64 KB +- * works okay and that's what Windows does. But we'll be +- * conservative; people can always use the sysfs interface to +- * increase max_sectors. */ +- if (le16_to_cpu(us->pusb_dev->descriptor.idVendor) == USB_VENDOR_ID_GENESYS && ++ /* Many devices have trouble transfering more than 32KB at a time, ++ * while others have trouble with more than 64K. At this time we ++ * are limiting both to 32K (64 sectores). ++ */ ++ if ((us->flags & US_FL_MAX_SECTORS_64) && + sdev->request_queue->max_sectors > 64) + blk_queue_max_sectors(sdev->request_queue, 64); + +--- gregkh-2.6.orig/drivers/usb/storage/unusual_devs.h ++++ gregkh-2.6/drivers/usb/storage/unusual_devs.h +@@ -716,18 +716,22 @@ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x + * They were originally reported by Alexander Oltu + * <alexander@all-2.com> and Peter Marks <peter.marks@turner.com> + * respectively. ++ * ++ * US_FL_GO_SLOW and US_FL_MAX_SECTORS_64 added by Phil Dibowitz ++ * <phil@ipom.com> as these flags were made and hard-coded ++ * special-cases were pulled from scsiglue.c. + */ + UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff, + "Genesys Logic", + "USB to IDE Optical", + US_SC_DEVICE, US_PR_DEVICE, NULL, +- US_FL_GO_SLOW ), ++ US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ), + + UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff, + "Genesys Logic", + "USB to IDE Disk", + US_SC_DEVICE, US_PR_DEVICE, NULL, +- US_FL_GO_SLOW ), ++ US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ), + + /* Reported by Hanno Boeck <hanno@gmx.de> + * Taken from the Lycoris Kernel */ +@@ -1204,6 +1208,14 @@ UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + ++/* Reported by Benjamin Schiller <sbenni@gmx.de> ++ * It is also sold by Easylite as DJ 20 */ ++UNUSUAL_DEV( 0x0ed1, 0x7636, 0x0103, 0x0103, ++ "Typhoon", ++ "My DJ 1820", ++ US_SC_DEVICE, US_PR_DEVICE, NULL, ++ US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64), ++ + /* Reported by Michael Stattmann <michael@stattmann.com> */ + UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, + "Sony Ericsson", +--- gregkh-2.6.orig/drivers/usb/storage/usb.h ++++ gregkh-2.6/drivers/usb/storage/usb.h +@@ -176,8 +176,4 @@ extern void fill_inquiry_response(struct + #define scsi_unlock(host) spin_unlock_irq(host->host_lock) + #define scsi_lock(host) spin_lock_irq(host->host_lock) + +- +-/* Vendor ID list for devices that require special handling */ +-#define USB_VENDOR_ID_GENESYS 0x05e3 /* Genesys Logic */ +- + #endif +--- gregkh-2.6.orig/include/linux/usb_usual.h ++++ gregkh-2.6/include/linux/usb_usual.h +@@ -43,6 +43,8 @@ + /* Need delay after Command phase */ \ + US_FLAG(NO_WP_DETECT, 0x00000200) \ + /* Don't check for write-protect */ \ ++ US_FLAG(MAX_SECTORS_64, 0x00000400) \ ++ /* Sets max_sectors to 64 */ + + #define US_FLAG(name, value) US_FL_##name = value , + enum { US_DO_ALL_FLAGS }; diff --git a/usb/usb-unusual_devs-entry-for-samsung-mp3-player.patch b/usb/usb-unusual_devs-entry-for-samsung-mp3-player.patch new file mode 100644 index 0000000000000..36cc096f352df --- /dev/null +++ b/usb/usb-unusual_devs-entry-for-samsung-mp3-player.patch @@ -0,0 +1,39 @@ +From stern@rowland.harvard.edu Mon Jun 26 13:02:49 2006 +Date: Mon, 26 Jun 2006 16:02:43 -0400 (EDT) +From: Alan Stern <stern@rowland.harvard.edu> +To: Greg KH <greg@kroah.com> +cc: Ernis <ernisv@gmail.com>, Phil Dibowitz <phil@ipom.com>, USB Storage list <usb-storage@lists.one-eyed-alien.net> +Subject: USB: unusual_devs entry for Samsung MP3 player +Message-ID: <Pine.LNX.4.44L0.0606261559590.14025-100000@iolanthe.rowland.org> + +From: Ernis <ernisv@gmail.com> + +This patch (as730) contains an unusual_devs entry for a Samsung MP3 +device. + +From: Ernis <ernisv@gmail.com> +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + +--- + drivers/usb/storage/unusual_devs.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- gregkh-2.6.orig/drivers/usb/storage/unusual_devs.h ++++ gregkh-2.6/drivers/usb/storage/unusual_devs.h +@@ -113,6 +113,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY ), + ++/* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */ ++UNUSUAL_DEV( 0x0419, 0x0100, 0x0100, 0x0100, ++ "Samsung Info. Systems America, Inc.", ++ "MP3 Player", ++ US_SC_DEVICE, US_PR_DEVICE, NULL, ++ US_FL_IGNORE_RESIDUE ), ++ + /* Reported by Christian Leber <christian@leber.de> */ + UNUSUAL_DEV( 0x0419, 0xaaf5, 0x0100, 0x0100, + "TrekStor", diff --git a/usb/usbcore-fixes-for-hub_port_resume.patch b/usb/usbcore-fixes-for-hub_port_resume.patch new file mode 100644 index 0000000000000..cb7b77b8fb52f --- /dev/null +++ b/usb/usbcore-fixes-for-hub_port_resume.patch @@ -0,0 +1,37 @@ +From stern@rowland.harvard.edu Wed Jun 28 08:20:42 2006 +Date: Wed, 28 Jun 2006 11:20:41 -0400 (EDT) +From: Alan Stern <stern@rowland.harvard.edu> +To: Greg KH <greg@kroah.com> +Subject: usbcore: fixes for hub_port_resume +Message-ID: <Pine.LNX.4.44L0.0606281116010.6790-100000@iolanthe.rowland.org> + +This patch (as731) makes a couple of small fixes to the hub_port_resume +routine: + + Don't return status >= 0 when an error occurs; + + Clear the port-change-suspend status indicator after + resuming a device. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hub.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- gregkh-2.6.orig/drivers/usb/core/hub.c ++++ gregkh-2.6/drivers/usb/core/hub.c +@@ -1883,7 +1883,12 @@ hub_port_resume(struct usb_hub *hub, int + dev_dbg(hub->intfdev, + "port %d status %04x.%04x after resume, %d\n", + port1, portchange, devstatus, status); ++ if (status >= 0) ++ status = -ENODEV; + } else { ++ if (portchange & USB_PORT_STAT_C_SUSPEND) ++ clear_port_feature(hub->hdev, port1, ++ USB_PORT_FEAT_C_SUSPEND); + /* TRSMRCY = 10 msec */ + msleep(10); + if (udev) diff --git a/usb/usbip.patch b/usb/usbip.patch index 215db582687ed..78da15bd294dc 100644 --- a/usb/usbip.patch +++ b/usb/usbip.patch @@ -29,7 +29,7 @@ a link to the userspace tools needed to get this to work. --- gregkh-2.6.orig/drivers/usb/Kconfig +++ gregkh-2.6/drivers/usb/Kconfig -@@ -80,6 +80,8 @@ source "drivers/usb/core/Kconfig" +@@ -81,6 +81,8 @@ source "drivers/usb/core/Kconfig" source "drivers/usb/host/Kconfig" |