From 3c04e20ea95f9a8555456000e0ff340bdc46dea8 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 18 Sep 2008 23:06:21 +0800 Subject: USB: ehci-dbg: increase debug buffer size for periodic file This patch is based on the following ideas: 1. Some usb devices (such as usb video class) have endpoints of high interval attribute, so reading "periodic" file need more debug buffer to accommodate the qh or itd schedule information. For example, 4KB buffer is not enough for a single interrupt qh of 2ms period. 2. print a %p need 16 byte buffer on 64-bits arch, but 8 byte on 32-bits arch. Add a extra bonus for 64-bits arch. Signed-off-by: Ming Lei Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/host/ehci-hcd.c') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 8409e0705d63..7378aa137a4a 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From cede969fe21adece300300a455580635590deb47 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 22 Sep 2008 15:00:07 -0700 Subject: usb: remove code associated with !CONFIG_PPC_MERGE Now that arch/ppc is gone we don't need CONFIG_PPC_MERGE anymore remove the dead code associated with !CONFIG_PPC_MERGE. Signed-off-by: Kumar Gala Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 5 - drivers/usb/host/ehci-ppc-soc.c | 201 ---------------------------------------- drivers/usb/host/ehci.h | 9 -- drivers/usb/host/ohci.h | 8 -- 4 files changed, 223 deletions(-) delete mode 100644 drivers/usb/host/ehci-ppc-soc.c (limited to 'drivers/usb/host/ehci-hcd.c') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 7378aa137a4a..c6f9961eed3c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1021,11 +1021,6 @@ MODULE_LICENSE ("GPL"); #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver #endif -#if defined(CONFIG_440EPX) && !defined(CONFIG_PPC_MERGE) -#include "ehci-ppc-soc.c" -#define PLATFORM_DRIVER ehci_ppc_soc_driver -#endif - #ifdef CONFIG_USB_EHCI_HCD_PPC_OF #include "ehci-ppc-of.c" #define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c deleted file mode 100644 index 529590eb4037..000000000000 --- a/drivers/usb/host/ehci-ppc-soc.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * EHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 2006-2007 Stefan Roese , DENX Software Engineering - * - * Bus Glue for PPC On-Chip EHCI driver - * Tested on AMCC 440EPx - * - * Based on "ehci-au1xxx.c" by K.Boge - * - * This file is licenced under the GPL. - */ - -#include - -extern int usb_disabled(void); - -/* called during probe() after chip reset completes */ -static int ehci_ppc_soc_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - retval = ehci_halt(ehci); - if (retval) - return retval; - - retval = ehci_init(hcd); - if (retval) - return retval; - - ehci->sbrn = 0x20; - return ehci_reset(ehci); -} - -/** - * usb_ehci_ppc_soc_probe - initialize PPC-SoC-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_ehci_ppc_soc_probe(const struct hc_driver *driver, - struct usb_hcd **hcd_out, - struct platform_device *dev) -{ - int retval; - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - - if (dev->resource[1].flags != IORESOURCE_IRQ) { - pr_debug("resource[1] is not IORESOURCE_IRQ"); - retval = -ENOMEM; - } - hcd = usb_create_hcd(driver, &dev->dev, "PPC-SOC EHCI"); - if (!hcd) - return -ENOMEM; - hcd->rsrc_start = dev->resource[0].start; - hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed"); - retval = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - pr_debug("ioremap failed"); - retval = -ENOMEM; - goto err2; - } - - ehci = hcd_to_ehci(hcd); - ehci->big_endian_mmio = 1; - ehci->big_endian_desc = 1; - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - -#if defined(CONFIG_440EPX) - /* - * 440EPx Errata USBH_3 - * Fix: Enable Break Memory Transfer (BMT) in INSNREG3 - */ - out_be32((void *)((ulong)(&ehci->regs->command) + 0x8c), (1 << 0)); - ehci_dbg(ehci, "Break Memory Transfer (BMT) has beed enabled!\n"); -#endif - - retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED); - if (retval == 0) - return retval; - - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: - usb_put_hcd(hcd); - return retval; -} - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_ehci_hcd_ppc_soc_remove - shutdown processing for PPC-SoC-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_ehci_hcd_ppc_soc_probe(), first invoking - * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - */ -void usb_ehci_ppc_soc_remove(struct usb_hcd *hcd, struct platform_device *dev) -{ - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); -} - -static const struct hc_driver ehci_ppc_soc_hc_driver = { - .description = hcd_name, - .product_desc = "PPC-SOC EHCI", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = ehci_ppc_soc_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, -}; - -static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd = NULL; - int ret; - - pr_debug("In ehci_hcd_ppc_soc_drv_probe\n"); - - if (usb_disabled()) - return -ENODEV; - - /* FIXME we only want one one probe() not two */ - ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev); - return ret; -} - -static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - /* FIXME we only want one one remove() not two */ - usb_ehci_ppc_soc_remove(hcd, pdev); - return 0; -} - -MODULE_ALIAS("platform:ppc-soc-ehci"); -static struct platform_driver ehci_ppc_soc_driver = { - .probe = ehci_hcd_ppc_soc_drv_probe, - .remove = ehci_hcd_ppc_soc_drv_remove, - .shutdown = usb_hcd_platform_shutdown, - .driver = { - .name = "ppc-soc-ehci", - } -}; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index b697a13364ec..fb1770d6e200 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -604,16 +604,7 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) /* * Big-endian read/write functions are arch-specific. * Other arches can be added if/when they're needed. - * - * REVISIT: arch/powerpc now has readl/writel_be, so the - * definition below can die once the 4xx support is - * finally ported over. */ -#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE) -#define readl_be(addr) in_be32((__force unsigned *)addr) -#define writel_be(val, addr) out_be32((__force unsigned *)addr, val) -#endif - #if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX) #define readl_be(addr) __raw_readl((__force unsigned *)addr) #define writel_be(val, addr) __raw_writel(val, (__force unsigned *)addr) diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index faf622eafce7..222011f6172c 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -540,15 +540,7 @@ static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci) * Big-endian read/write functions are arch-specific. * Other arches can be added if/when they're needed. * - * REVISIT: arch/powerpc now has readl/writel_be, so the - * definition below can die once the STB04xxx support is - * finally ported over. */ -#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE) -#define readl_be(addr) in_be32((__force unsigned *)addr) -#define writel_be(val, addr) out_be32((__force unsigned *)addr, val) -#endif - static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs) { -- cgit v1.2.3 From 2b70f07343389cb474235def00b021a645ede916 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 2 Oct 2008 11:47:15 -0400 Subject: USB: EHCI, OHCI, UHCI: remove version numbers This patch (as1145) removes the essentially useless driver-version strings from ehci-hcd, ohci-hcd, and uhci-hcd. It also unifies the form of the banner lines they display upon loading and adds a missing test for usb_disabled() to ehci-hcd. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 4 ++-- drivers/usb/host/ehci-hcd.c | 13 +++++++------ drivers/usb/host/ohci-dbg.c | 2 +- drivers/usb/host/ohci-hcd.c | 7 ++----- drivers/usb/host/ohci-pnx4008.c | 2 +- drivers/usb/host/uhci-hcd.c | 7 +++---- 6 files changed, 16 insertions(+), 19 deletions(-) (limited to 'drivers/usb/host/ehci-hcd.c') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 5d57773e730e..0cb53ca8d343 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -675,7 +675,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { size = scnprintf (next, size, - "bus %s, device %s (driver " DRIVER_VERSION ")\n" + "bus %s, device %s\n" "%s\n" "SUSPENDED (no register access)\n", hcd->self.controller->bus->name, @@ -687,7 +687,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* Capability Registers */ i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); temp = scnprintf (next, size, - "bus %s, device %s (driver " DRIVER_VERSION ")\n" + "bus %s, device %s\n" "%s\n" "EHCI %x.%02x, hcd state %d\n", hcd->self.controller->bus->name, diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c6f9961eed3c..fcbc1f2b2377 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -60,7 +60,6 @@ * providing early devices for those host controllers to talk to! */ -#define DRIVER_VERSION "10 Dec 2004" #define DRIVER_AUTHOR "David Brownell" #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" @@ -621,9 +620,9 @@ static int ehci_run (struct usb_hcd *hcd) temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); ehci_info (ehci, - "USB %x.%x started, EHCI %x.%02x, driver %s%s\n", + "USB %x.%x started, EHCI %x.%02x%s\n", ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), - temp >> 8, temp & 0xff, DRIVER_VERSION, + temp >> 8, temp & 0xff, ignore_oc ? ", overcurrent ignored" : ""); ehci_writel(ehci, INTR_MASK, @@ -995,9 +994,7 @@ static int ehci_get_frame (struct usb_hcd *hcd) /*-------------------------------------------------------------------------*/ -#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC - -MODULE_DESCRIPTION (DRIVER_INFO); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_LICENSE ("GPL"); @@ -1045,6 +1042,10 @@ static int __init ehci_hcd_init(void) { int retval = 0; + if (usb_disabled()) + return -ENODEV; + + printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", hcd_name, sizeof(struct ehci_qh), sizeof(struct ehci_qtd), diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 7cef1d2f7ccc..d3269656aa4d 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -649,7 +649,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) ohci_dbg_sw (ohci, &next, &size, "bus %s, device %s\n" "%s\n" - "%s version " DRIVER_VERSION "\n", + "%s\n", hcd->self.controller->bus->name, dev_name(hcd->self.controller), hcd->product_desc, diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 89901962cbfd..0afeda836df3 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -46,7 +46,6 @@ #include "../core/hcd.h" -#define DRIVER_VERSION "2006 August 04" #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" @@ -984,10 +983,8 @@ static int ohci_restart (struct ohci_hcd *ohci) /*-------------------------------------------------------------------------*/ -#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC - MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_DESCRIPTION (DRIVER_INFO); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE ("GPL"); #ifdef CONFIG_PCI @@ -1095,7 +1092,7 @@ static int __init ohci_hcd_mod_init(void) if (usb_disabled()) return -ENODEV; - printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name); + printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, sizeof (struct ed), sizeof (struct td)); diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index 658a2a978c32..e306ca6aef3d 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -331,7 +331,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) int ret = 0, irq; - dev_dbg(&pdev->dev, "%s: " DRIVER_INFO " (pnx4008)\n", hcd_name); + dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (pnx4008)\n", hcd_name); if (usb_disabled()) { err("USB is disabled"); ret = -ENODEV; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 3a7bfe7a8874..2dddb258b0db 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -53,7 +53,6 @@ /* * Version Information */ -#define DRIVER_VERSION "v3.0" #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ Alan Stern" @@ -951,12 +950,12 @@ static int __init uhci_hcd_init(void) { int retval = -ENOMEM; - printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n", - ignore_oc ? ", overcurrent ignored" : ""); - if (usb_disabled()) return -ENODEV; + printk(KERN_INFO "uhci_hcd: " DRIVER_DESC "%s\n", + ignore_oc ? ", overcurrent ignored" : ""); + if (DEBUG_CONFIGURED) { errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); if (!errbuf) -- cgit v1.2.3 From 9beeee6584b9aa4f9192055512411484a2a624df Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 2 Oct 2008 11:48:13 -0400 Subject: USB: EHCI: log a warning if ehci-hcd is not loaded first This patch (as1139) adds a warning to the system log whenever ehci-hcd is loaded after ohci-hcd or uhci-hcd. Nowadays most distributions are pretty good about not doing this; maybe the warning will help convince anyone still doing it wrong. Signed-off-by: Alan Stern Cc: stable [2.6.27] Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 4 ++++ drivers/usb/core/hcd.h | 6 ++++++ drivers/usb/host/ehci-hcd.c | 15 +++++++++++++-- drivers/usb/host/ohci-hcd.c | 3 +++ drivers/usb/host/uhci-hcd.c | 3 +++ 5 files changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers/usb/host/ehci-hcd.c') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index c8035a8216bd..fc9018e72a09 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -81,6 +81,10 @@ /*-------------------------------------------------------------------------*/ +/* Keep track of which host controller drivers are loaded */ +unsigned long usb_hcds_loaded; +EXPORT_SYMBOL_GPL(usb_hcds_loaded); + /* host controllers we manage */ LIST_HEAD (usb_bus_list); EXPORT_SYMBOL_GPL (usb_bus_list); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index e710ce04e228..2dcde61c465e 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -482,4 +482,10 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, */ extern struct rw_semaphore ehci_cf_port_reset_rwsem; +/* Keep track of which host controller drivers are loaded */ +#define USB_UHCI_LOADED 0 +#define USB_OHCI_LOADED 1 +#define USB_EHCI_LOADED 2 +extern unsigned long usb_hcds_loaded; + #endif /* __KERNEL__ */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index fcbc1f2b2377..358df2a6c396 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1046,6 +1046,12 @@ static int __init ehci_hcd_init(void) return -ENODEV; printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); + set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); + if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || + test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) + printk(KERN_WARNING "Warning! ehci_hcd should always be loaded" + " before uhci_hcd and ohci_hcd, not after\n"); + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", hcd_name, sizeof(struct ehci_qh), sizeof(struct ehci_qtd), @@ -1053,8 +1059,10 @@ static int __init ehci_hcd_init(void) #ifdef DEBUG ehci_debug_root = debugfs_create_dir("ehci", NULL); - if (!ehci_debug_root) - return -ENOENT; + if (!ehci_debug_root) { + retval = -ENOENT; + goto err_debug; + } #endif #ifdef PLATFORM_DRIVER @@ -1102,6 +1110,8 @@ clean0: debugfs_remove(ehci_debug_root); ehci_debug_root = NULL; #endif +err_debug: + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); return retval; } module_init(ehci_hcd_init); @@ -1123,6 +1133,7 @@ static void __exit ehci_hcd_cleanup(void) #ifdef DEBUG debugfs_remove(ehci_debug_root); #endif + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); } module_exit(ehci_hcd_cleanup); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 0afeda836df3..8647dab0d7f9 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1095,6 +1095,7 @@ static int __init ohci_hcd_mod_init(void) printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, sizeof (struct ed), sizeof (struct td)); + set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); #ifdef DEBUG ohci_debug_root = debugfs_create_dir("ohci", NULL); @@ -1181,6 +1182,7 @@ static int __init ohci_hcd_mod_init(void) error_debug: #endif + clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); return retval; } module_init(ohci_hcd_mod_init); @@ -1211,6 +1213,7 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef DEBUG debugfs_remove(ohci_debug_root); #endif + clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); } module_exit(ohci_hcd_mod_exit); diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 2dddb258b0db..cf5e4cf7ea42 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -955,6 +955,7 @@ static int __init uhci_hcd_init(void) printk(KERN_INFO "uhci_hcd: " DRIVER_DESC "%s\n", ignore_oc ? ", overcurrent ignored" : ""); + set_bit(USB_UHCI_LOADED, &usb_hcds_loaded); if (DEBUG_CONFIGURED) { errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); @@ -987,6 +988,7 @@ debug_failed: errbuf_failed: + clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); return retval; } @@ -996,6 +998,7 @@ static void __exit uhci_hcd_cleanup(void) kmem_cache_destroy(uhci_up_cachep); debugfs_remove(uhci_debugfs_root); kfree(errbuf); + clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); } module_init(uhci_hcd_init); -- cgit v1.2.3 From eafe5b99f2135488b21cf17a262c54997c44f784 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 6 Oct 2008 11:25:53 -0400 Subject: USB: EHCI: fix remote-wakeup support for ARC/TDI core This patch (as1147) fixes the remote-wakeup support for EHCI controllers using the ARC/TDI "embedded-TT" core. These controllers turn off the RESUME bit by themselves when a port resume is complete; hence we need to keep separate track of which ports are suspended or in the process of resuming. The patch also makes a couple of small improvements in ehci_irq(), replacing reads of the command register with the value already stored in a local variable. Signed-off-by: Alan Stern Tested-by: Thomas Reitmayr CC: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 14 ++++++++------ drivers/usb/host/ehci-hub.c | 27 +++++++++++++++++++-------- drivers/usb/host/ehci.h | 2 ++ 3 files changed, 29 insertions(+), 14 deletions(-) (limited to 'drivers/usb/host/ehci-hcd.c') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 358df2a6c396..d343afacb0b0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -706,7 +706,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) pcd_status = status; /* resume root hub? */ - if (!(ehci_readl(ehci, &ehci->regs->command) & CMD_RUN)) + if (!(cmd & CMD_RUN)) usb_hcd_resume_root_hub(hcd); while (i--) { @@ -715,8 +715,11 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) if (pstatus & PORT_OWNER) continue; - if (!(pstatus & PORT_RESUME) - || ehci->reset_done [i] != 0) + if (!(test_bit(i, &ehci->suspended_ports) && + ((pstatus & PORT_RESUME) || + !(pstatus & PORT_SUSPEND)) && + (pstatus & PORT_PE) && + ehci->reset_done[i] == 0)) continue; /* start 20 msec resume signaling from this port, @@ -731,9 +734,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* PCI errors [4.15.2.4] */ if (unlikely ((status & STS_FATAL) != 0)) { - dbg_cmd (ehci, "fatal", ehci_readl(ehci, - &ehci->regs->command)); - dbg_status (ehci, "fatal", status); + dbg_cmd(ehci, "fatal", cmd); + dbg_status(ehci, "fatal", status); if (status & STS_HALT) { ehci_err (ehci, "fatal error\n"); dead: diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 740835bb8575..218f9660d7ee 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -236,10 +236,8 @@ static int ehci_bus_resume (struct usb_hcd *hcd) temp = ehci_readl(ehci, &ehci->regs->port_status [i]); temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); if (test_bit(i, &ehci->bus_suspended) && - (temp & PORT_SUSPEND)) { - ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); + (temp & PORT_SUSPEND)) temp |= PORT_RESUME; - } ehci_writel(ehci, temp, &ehci->regs->port_status [i]); } i = HCS_N_PORTS (ehci->hcs_params); @@ -482,10 +480,9 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) * controller by the user. */ - if ((temp & mask) != 0 - || ((temp & PORT_RESUME) != 0 - && time_after_eq(jiffies, - ehci->reset_done[i]))) { + if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend) + || (ehci->reset_done[i] && time_after_eq( + jiffies, ehci->reset_done[i]))) { if (i < 7) buf [0] |= 1 << (i + 1); else @@ -688,6 +685,7 @@ static int ehci_hub_control ( /* resume completed? */ else if (time_after_eq(jiffies, ehci->reset_done[wIndex])) { + clear_bit(wIndex, &ehci->suspended_ports); set_bit(wIndex, &ehci->port_c_suspend); ehci->reset_done[wIndex] = 0; @@ -734,6 +732,9 @@ static int ehci_hub_control ( ehci_readl(ehci, status_reg)); } + if (!(temp & (PORT_RESUME|PORT_RESET))) + ehci->reset_done[wIndex] = 0; + /* transfer dedicated ports to the companion hc */ if ((temp & PORT_CONNECT) && test_bit(wIndex, &ehci->companion_ports)) { @@ -757,8 +758,17 @@ static int ehci_hub_control ( } if (temp & PORT_PE) status |= 1 << USB_PORT_FEAT_ENABLE; - if (temp & (PORT_SUSPEND|PORT_RESUME)) + + /* maybe the port was unsuspended without our knowledge */ + if (temp & (PORT_SUSPEND|PORT_RESUME)) { status |= 1 << USB_PORT_FEAT_SUSPEND; + } else if (test_bit(wIndex, &ehci->suspended_ports)) { + clear_bit(wIndex, &ehci->suspended_ports); + ehci->reset_done[wIndex] = 0; + if (temp & PORT_PE) + set_bit(wIndex, &ehci->port_c_suspend); + } + if (temp & PORT_OC) status |= 1 << USB_PORT_FEAT_OVER_CURRENT; if (temp & PORT_RESET) @@ -803,6 +813,7 @@ static int ehci_hub_control ( || (temp & PORT_RESET) != 0) goto error; ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); + set_bit(wIndex, &ehci->suspended_ports); break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index a6fd550b6903..b11798d17ae5 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -99,6 +99,8 @@ struct ehci_hcd { /* one per controller */ owned by the companion during a bus suspend */ unsigned long port_c_suspend; /* which ports have the change-suspend feature turned on */ + unsigned long suspended_ports; /* which ports are + suspended */ /* per-HC memory pools (could be per-bus, but ...) */ struct dma_pool *qh_pool; /* qh per active urb */ -- cgit v1.2.3