diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-dbg.c | 56 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 74 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 27 | ||||
-rw-r--r-- | drivers/usb/host/ehci-ixp4xx.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-ppc-soc.c | 201 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 32 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 161 | ||||
-rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 13 | ||||
-rw-r--r-- | drivers/usb/host/isp1760-if.c | 7 | ||||
-rw-r--r-- | drivers/usb/host/ohci-dbg.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 10 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hub.c | 87 | ||||
-rw-r--r-- | drivers/usb/host/ohci-omap.c | 20 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pnx4008.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pxa27x.c | 259 | ||||
-rw-r--r-- | drivers/usb/host/ohci.h | 8 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 101 | ||||
-rw-r--r-- | drivers/usb/host/sl811-hcd.c | 15 | ||||
-rw-r--r-- | drivers/usb/host/sl811_cs.c | 133 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 10 | ||||
-rw-r--r-- | drivers/usb/host/uhci-q.c | 41 |
21 files changed, 568 insertions, 693 deletions
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index b0f8ed5a7fb..0cb53ca8d34 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -358,7 +358,8 @@ struct debug_buffer { struct usb_bus *bus; struct mutex mutex; /* protect filling of buffer */ size_t count; /* number of characters filled into buffer */ - char *page; + char *output_buf; + size_t alloc_size; }; #define speed_char(info1) ({ char tmp; \ @@ -488,8 +489,8 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) hcd = bus_to_hcd(buf->bus); ehci = hcd_to_ehci (hcd); - next = buf->page; - size = PAGE_SIZE; + next = buf->output_buf; + size = buf->alloc_size; *next = 0; @@ -510,7 +511,7 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) } spin_unlock_irqrestore (&ehci->lock, flags); - return strlen(buf->page); + return strlen(buf->output_buf); } #define DBG_SCHED_LIMIT 64 @@ -531,8 +532,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) hcd = bus_to_hcd(buf->bus); ehci = hcd_to_ehci (hcd); - next = buf->page; - size = PAGE_SIZE; + next = buf->output_buf; + size = buf->alloc_size; temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); size -= temp; @@ -568,14 +569,16 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) for (temp = 0; temp < seen_count; temp++) { if (seen [temp].ptr != p.ptr) continue; - if (p.qh->qh_next.ptr) + if (p.qh->qh_next.ptr) { temp = scnprintf (next, size, " ..."); - p.ptr = NULL; + size -= temp; + next += temp; + } break; } /* show more info the first time around */ - if (temp == seen_count && p.ptr) { + if (temp == seen_count) { u32 scratch = hc32_to_cpup(ehci, &p.qh->hw_info1); struct ehci_qtd *qtd; @@ -649,7 +652,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) spin_unlock_irqrestore (&ehci->lock, flags); kfree (seen); - return PAGE_SIZE - size; + return buf->alloc_size - size; } #undef DBG_SCHED_LIMIT @@ -665,14 +668,14 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) hcd = bus_to_hcd(buf->bus); ehci = hcd_to_ehci (hcd); - next = buf->page; - size = PAGE_SIZE; + next = buf->output_buf; + size = buf->alloc_size; spin_lock_irqsave (&ehci->lock, flags); 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, @@ -684,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, @@ -808,7 +811,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) done: spin_unlock_irqrestore (&ehci->lock, flags); - return PAGE_SIZE - size; + return buf->alloc_size - size; } static struct debug_buffer *alloc_buffer(struct usb_bus *bus, @@ -822,6 +825,7 @@ static struct debug_buffer *alloc_buffer(struct usb_bus *bus, buf->bus = bus; buf->fill_func = fill_func; mutex_init(&buf->mutex); + buf->alloc_size = PAGE_SIZE; } return buf; @@ -831,10 +835,10 @@ static int fill_buffer(struct debug_buffer *buf) { int ret = 0; - if (!buf->page) - buf->page = (char *)get_zeroed_page(GFP_KERNEL); + if (!buf->output_buf) + buf->output_buf = (char *)vmalloc(buf->alloc_size); - if (!buf->page) { + if (!buf->output_buf) { ret = -ENOMEM; goto out; } @@ -867,7 +871,7 @@ static ssize_t debug_output(struct file *file, char __user *user_buf, mutex_unlock(&buf->mutex); ret = simple_read_from_buffer(user_buf, len, offset, - buf->page, buf->count); + buf->output_buf, buf->count); out: return ret; @@ -879,8 +883,8 @@ static int debug_close(struct inode *inode, struct file *file) struct debug_buffer *buf = file->private_data; if (buf) { - if (buf->page) - free_page((unsigned long)buf->page); + if (buf->output_buf) + vfree(buf->output_buf); kfree(buf); } @@ -895,10 +899,14 @@ static int debug_async_open(struct inode *inode, struct file *file) static int debug_periodic_open(struct inode *inode, struct file *file) { - file->private_data = alloc_buffer(inode->i_private, - fill_periodic_buffer); + struct debug_buffer *buf; + buf = alloc_buffer(inode->i_private, fill_periodic_buffer); + if (!buf) + return -ENOMEM; - return file->private_data ? 0 : -ENOMEM; + buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; + file->private_data = buf; + return 0; } static int debug_registers_open(struct inode *inode, struct file *file) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d9d53f289ca..d343afacb0b 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -24,6 +24,7 @@ #include <linux/ioport.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/vmalloc.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/timer.h> @@ -59,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" @@ -145,16 +145,6 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, return -ETIMEDOUT; } -static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr, - u32 mask, u32 done, int usec) -{ - int error = handshake(ehci, ptr, mask, done, usec); - if (error) - ehci_to_hcd(ehci)->state = HC_STATE_HALT; - - return error; -} - /* force HC to halt state from unknown (EHCI spec section 2.3) */ static int ehci_halt (struct ehci_hcd *ehci) { @@ -173,6 +163,22 @@ static int ehci_halt (struct ehci_hcd *ehci) STS_HALT, STS_HALT, 16 * 125); } +static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr, + u32 mask, u32 done, int usec) +{ + int error; + + error = handshake(ehci, ptr, mask, done, usec); + if (error) { + ehci_halt(ehci); + ehci_to_hcd(ehci)->state = HC_STATE_HALT; + ehci_err(ehci, "force halt; handhake %p %08x %08x -> %d\n", + ptr, mask, done, error); + } + + return error; +} + /* put TDI/ARC silicon into EHCI mode */ static void tdi_reset (struct ehci_hcd *ehci) { @@ -614,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, @@ -700,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--) { @@ -709,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, @@ -725,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: @@ -988,9 +996,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"); @@ -1014,11 +1020,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 @@ -1043,6 +1044,16 @@ static int __init ehci_hcd_init(void) { int retval = 0; + if (usb_disabled()) + 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), @@ -1050,8 +1061,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 @@ -1099,6 +1112,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); @@ -1120,6 +1135,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/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 740835bb857..218f9660d7e 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-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index f9575c40912..9c32063a0c2 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c @@ -1,7 +1,7 @@ /* * IXP4XX EHCI Host Controller Driver * - * Author: Vladimir Barinov <vbarinov@ru.mvista.com> + * Author: Vladimir Barinov <vbarinov@embeddedalley.com> * * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com> * diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c deleted file mode 100644 index 529590eb403..00000000000 --- 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 <sr@denx.de>, DENX Software Engineering - * - * Bus Glue for PPC On-Chip EHCI driver - * Tested on AMCC 440EPx - * - * Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com> - * - * This file is licenced under the GPL. - */ - -#include <linux/platform_device.h> - -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-sched.c b/drivers/usb/host/ehci-sched.c index b7853c8bac0..4a0c5a78b2e 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -437,6 +437,9 @@ static int enable_periodic (struct ehci_hcd *ehci) u32 cmd; int status; + if (ehci->periodic_sched++) + return 0; + /* did clearing PSE did take effect yet? * takes effect only at frame boundaries... */ @@ -461,6 +464,9 @@ static int disable_periodic (struct ehci_hcd *ehci) u32 cmd; int status; + if (--ehci->periodic_sched) + return 0; + /* did setting PSE not take effect yet? * takes effect only at frame boundaries... */ @@ -544,13 +550,10 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) : (qh->usecs * 8); /* maybe enable periodic schedule processing */ - if (!ehci->periodic_sched++) - return enable_periodic (ehci); - - return 0; + return enable_periodic(ehci); } -static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) +static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) { unsigned i; unsigned period; @@ -586,9 +589,7 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) qh_put (qh); /* maybe turn off periodic schedule */ - ehci->periodic_sched--; - if (!ehci->periodic_sched) - (void) disable_periodic (ehci); + return disable_periodic(ehci); } static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) @@ -1562,9 +1563,7 @@ itd_link_urb ( urb->hcpriv = NULL; timer_action (ehci, TIMER_IO_WATCHDOG); - if (unlikely (!ehci->periodic_sched++)) - return enable_periodic (ehci); - return 0; + return enable_periodic(ehci); } #define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) @@ -1642,7 +1641,7 @@ itd_complete ( ehci_urb_done(ehci, urb, 0); retval = true; urb = NULL; - ehci->periodic_sched--; + (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; if (unlikely (list_empty (&stream->td_list))) { @@ -1951,9 +1950,7 @@ sitd_link_urb ( urb->hcpriv = NULL; timer_action (ehci, TIMER_IO_WATCHDOG); - if (!ehci->periodic_sched++) - return enable_periodic (ehci); - return 0; + return enable_periodic(ehci); } /*-------------------------------------------------------------------------*/ @@ -2019,7 +2016,7 @@ sitd_complete ( ehci_urb_done(ehci, urb, 0); retval = true; urb = NULL; - ehci->periodic_sched--; + (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; if (list_empty (&stream->td_list)) { @@ -2243,8 +2240,7 @@ restart: if (unlikely (modified)) { if (likely(ehci->periodic_sched > 0)) goto restart; - /* maybe we can short-circuit this scan! */ - disable_periodic(ehci); + /* short-circuit this scan */ now_uframe = clock; break; } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 5799298364f..b11798d17ae 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 */ @@ -181,14 +183,16 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) * the async ring; just the I/O watchdog. Note that if a * SHRINK were pending, OFF would never be requested. */ - if (timer_pending(&ehci->watchdog) - && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) - & ehci->actions)) - return; + enum ehci_timer_action oldactions = ehci->actions; if (!test_and_set_bit (action, &ehci->actions)) { unsigned long t; + if (timer_pending(&ehci->watchdog) + && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) + & oldactions)) + return; + switch (action) { case TIMER_IO_WATCHDOG: t = EHCI_IO_JIFFIES; @@ -204,149 +208,13 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; break; } - mod_timer(&ehci->watchdog, t + jiffies); + mod_timer(&ehci->watchdog, round_jiffies(t + jiffies)); } } /*-------------------------------------------------------------------------*/ -/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ - -/* Section 2.2 Host Controller Capability Registers */ -struct ehci_caps { - /* these fields are specified as 8 and 16 bit registers, - * but some hosts can't perform 8 or 16 bit PCI accesses. - */ - u32 hc_capbase; -#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ -#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ - u32 hcs_params; /* HCSPARAMS - offset 0x4 */ -#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ -#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ -#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ -#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ -#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ -#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ -#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ - - u32 hcc_params; /* HCCPARAMS - offset 0x8 */ -#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ -#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ -#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ -#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ -#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ -#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ - u8 portroute [8]; /* nibbles for routing - offset 0xC */ -} __attribute__ ((packed)); - - -/* Section 2.3 Host Controller Operational Registers */ -struct ehci_regs { - - /* USBCMD: offset 0x00 */ - u32 command; -/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ -#define CMD_PARK (1<<11) /* enable "park" on async qh */ -#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ -#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ -#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ -#define CMD_ASE (1<<5) /* async schedule enable */ -#define CMD_PSE (1<<4) /* periodic schedule enable */ -/* 3:2 is periodic frame list size */ -#define CMD_RESET (1<<1) /* reset HC not bus */ -#define CMD_RUN (1<<0) /* start/stop HC */ - - /* USBSTS: offset 0x04 */ - u32 status; -#define STS_ASS (1<<15) /* Async Schedule Status */ -#define STS_PSS (1<<14) /* Periodic Schedule Status */ -#define STS_RECL (1<<13) /* Reclamation */ -#define STS_HALT (1<<12) /* Not running (any reason) */ -/* some bits reserved */ - /* these STS_* flags are also intr_enable bits (USBINTR) */ -#define STS_IAA (1<<5) /* Interrupted on async advance */ -#define STS_FATAL (1<<4) /* such as some PCI access errors */ -#define STS_FLR (1<<3) /* frame list rolled over */ -#define STS_PCD (1<<2) /* port change detect */ -#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ -#define STS_INT (1<<0) /* "normal" completion (short, ...) */ - - /* USBINTR: offset 0x08 */ - u32 intr_enable; - - /* FRINDEX: offset 0x0C */ - u32 frame_index; /* current microframe number */ - /* CTRLDSSEGMENT: offset 0x10 */ - u32 segment; /* address bits 63:32 if needed */ - /* PERIODICLISTBASE: offset 0x14 */ - u32 frame_list; /* points to periodic list */ - /* ASYNCLISTADDR: offset 0x18 */ - u32 async_next; /* address of next async queue head */ - - u32 reserved [9]; - - /* CONFIGFLAG: offset 0x40 */ - u32 configured_flag; -#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ - - /* PORTSC: offset 0x44 */ - u32 port_status [0]; /* up to N_PORTS */ -/* 31:23 reserved */ -#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ -#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ -#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ -/* 19:16 for port testing */ -#define PORT_LED_OFF (0<<14) -#define PORT_LED_AMBER (1<<14) -#define PORT_LED_GREEN (2<<14) -#define PORT_LED_MASK (3<<14) -#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ -#define PORT_POWER (1<<12) /* true: has power (see PPC) */ -#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */ -/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ -/* 9 reserved */ -#define PORT_RESET (1<<8) /* reset port */ -#define PORT_SUSPEND (1<<7) /* suspend port */ -#define PORT_RESUME (1<<6) /* resume it */ -#define PORT_OCC (1<<5) /* over current change */ -#define PORT_OC (1<<4) /* over current active */ -#define PORT_PEC (1<<3) /* port enable change */ -#define PORT_PE (1<<2) /* port enable */ -#define PORT_CSC (1<<1) /* connect status change */ -#define PORT_CONNECT (1<<0) /* device connected */ -#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) -} __attribute__ ((packed)); - -#define USBMODE 0x68 /* USB Device mode */ -#define USBMODE_SDIS (1<<3) /* Stream disable */ -#define USBMODE_BE (1<<2) /* BE/LE endianness select */ -#define USBMODE_CM_HC (3<<0) /* host controller mode */ -#define USBMODE_CM_IDLE (0<<0) /* idle state */ - -/* Appendix C, Debug port ... intended for use with special "debug devices" - * that can help if there's no serial console. (nonstandard enumeration.) - */ -struct ehci_dbg_port { - u32 control; -#define DBGP_OWNER (1<<30) -#define DBGP_ENABLED (1<<28) -#define DBGP_DONE (1<<16) -#define DBGP_INUSE (1<<10) -#define DBGP_ERRCODE(x) (((x)>>7)&0x07) -# define DBGP_ERR_BAD 1 -# define DBGP_ERR_SIGNAL 2 -#define DBGP_ERROR (1<<6) -#define DBGP_GO (1<<5) -#define DBGP_OUT (1<<4) -#define DBGP_LEN(x) (((x)>>0)&0x0f) - u32 pids; -#define DBGP_PID_GET(x) (((x)>>16)&0xff) -#define DBGP_PID_SET(data,tok) (((data)<<8)|(tok)) - u32 data03; - u32 data47; - u32 address; -#define DBGP_EPADDR(dev,ep) (((dev)<<8)|(ep)) -} __attribute__ ((packed)); +#include <linux/usb/ehci_def.h> |