summaryrefslogtreecommitdiff
path: root/drivers/usb/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/Makefile4
-rw-r--r--drivers/usb/host/ehci-hcd.c9
-rw-r--r--drivers/usb/host/ehci-hub.c4
-rw-r--r--drivers/usb/host/ehci-pci.c20
-rw-r--r--drivers/usb/host/ehci-q.c14
-rw-r--r--drivers/usb/host/hc_crisv10.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c422
-rw-r--r--drivers/usb/host/isp116x.h83
-rw-r--r--drivers/usb/host/ohci-hcd.c14
-rw-r--r--drivers/usb/host/ohci-hub.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c121
-rw-r--r--drivers/usb/host/pci-quirks.c6
-rw-r--r--drivers/usb/host/sl811-hcd.c14
-rw-r--r--drivers/usb/host/sl811_cs.c5
-rw-r--r--drivers/usb/host/uhci-debug.c14
-rw-r--r--drivers/usb/host/uhci-hcd.c32
-rw-r--r--drivers/usb/host/uhci-hcd.h32
-rw-r--r--drivers/usb/host/uhci-q.c30
18 files changed, 386 insertions, 442 deletions
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 58321d3f314c..e3020f4b17be 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -2,6 +2,10 @@
# Makefile for USB Host Controller Drivers
#
+ifeq ($(CONFIG_USB_DEBUG),y)
+ EXTRA_CFLAGS += -DDEBUG
+endif
+
obj-$(CONFIG_PCI) += pci-quirks.o
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 29f52a44b928..9dd3d14c64f3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -17,13 +17,6 @@
*/
#include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dmapool.h>
@@ -624,7 +617,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
}
/* remote wakeup [4.3.1] */
- if ((status & STS_PCD) && hcd->remote_wakeup) {
+ if (status & STS_PCD) {
unsigned i = HCS_N_PORTS (ehci->hcs_params);
/* resume root hub? */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 82caf336e9b6..69b0b9be7a64 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -59,7 +59,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
t2 |= PORT_SUSPEND;
- if (hcd->remote_wakeup)
+ if (device_may_wakeup(&hcd->self.root_hub->dev))
t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
else
t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
@@ -517,7 +517,7 @@ static int ehci_hub_control (
if ((temp & PORT_PE) == 0
|| (temp & PORT_RESET) != 0)
goto error;
- if (hcd->remote_wakeup)
+ if (device_may_wakeup(&hcd->self.root_hub->dev))
temp |= PORT_WAKE_BITS;
writel (temp | PORT_SUSPEND,
&ehci->regs->port_status [wIndex]);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 13f73a836e45..08ca0f849dab 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -210,7 +210,16 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
/* Serial Bus Release Number is at PCI 0x60 offset */
pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
- /* REVISIT: per-port wake capability (PCI 0x62) currently unused */
+ /* Workaround current PCI init glitch: wakeup bits aren't
+ * being set from PCI PM capability.
+ */
+ if (!device_can_wakeup(&pdev->dev)) {
+ u16 port_wake;
+
+ pci_read_config_word(pdev, 0x62, &port_wake);
+ if (port_wake & 0x0001)
+ device_init_wakeup(&pdev->dev, 1);
+ }
retval = ehci_pci_reinit(ehci, pdev);
done:
@@ -269,7 +278,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
unsigned port;
- struct usb_device *root = hcd->self.root_hub;
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
int retval = -EINVAL;
@@ -303,13 +311,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
restart:
ehci_dbg(ehci, "lost power, restarting\n");
- for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
- port--;
- if (!root->children [port])
- continue;
- usb_set_device_state(root->children[port],
- USB_STATE_NOTATTACHED);
- }
+ usb_root_hub_lost_power(hcd->self.root_hub);
/* Else reset, to cope with power loss or flush-to-storage
* style "resume" having let BIOS kick in during reboot.
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index bf03ec0d8ee2..9b13bf2fa98d 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -514,18 +514,18 @@ qh_urb_transaction (
qtd->urb = urb;
qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
list_add_tail (&qtd->qtd_list, head);
+
+ /* for zero length DATA stages, STATUS is always IN */
+ if (len == 0)
+ token |= (1 /* "in" */ << 8);
}
/*
* data transfer stage: buffer setup
*/
- if (likely (len > 0))
- buf = urb->transfer_dma;
- else
- buf = 0;
+ buf = urb->transfer_dma;
- /* for zero length DATA stages, STATUS is always IN */
- if (!buf || is_input)
+ if (is_input)
token |= (1 /* "in" */ << 8);
/* else it's already initted to "out" pid (0 << 8) */
@@ -572,7 +572,7 @@ qh_urb_transaction (
* control requests may need a terminating data "status" ack;
* bulk ones may need a terminating short packet (zero length).
*/
- if (likely (buf != 0)) {
+ if (likely (urb->transfer_buffer_length != 0)) {
int one_more = 0;
if (usb_pipecontrol (urb->pipe)) {
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 0eaabeb37ac3..641268d7e6f3 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -4397,7 +4397,7 @@ static int __init etrax_usb_hc_init(void)
device_initialize(&fake_device);
kobject_set_name(&fake_device.kobj, "etrax_usb");
kobject_add(&fake_device.kobj);
- kobject_hotplug(&fake_device.kobj, KOBJ_ADD);
+ kobject_uevent(&fake_device.kobj, KOBJ_ADD);
hc->bus->controller = &fake_device;
usb_register_bus(hc->bus);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 82f64986bc22..584b8dc65119 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -55,19 +55,13 @@
/* enqueuing/finishing log of urbs */
//#define URB_TRACE
-#include <linux/config.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/list.h>
-#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/usb_isp116x.h>
#include <linux/platform_device.h>
@@ -77,14 +71,10 @@
#include <asm/system.h>
#include <asm/byteorder.h>
-#ifndef DEBUG
-# define STUB_DEBUG_FILE
-#endif
-
#include "../core/hcd.h"
#include "isp116x.h"
-#define DRIVER_VERSION "05 Aug 2005"
+#define DRIVER_VERSION "03 Nov 2005"
#define DRIVER_DESC "ISP116x USB Host Controller Driver"
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -164,13 +154,11 @@ static void pack_fifo(struct isp116x *isp116x)
struct ptd *ptd;
int buflen = isp116x->atl_last_dir == PTD_DIR_IN
? isp116x->atl_bufshrt : isp116x->atl_buflen;
- int ptd_count = 0;
isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
for (ep = isp116x->atl_active; ep; ep = ep->active) {
- ++ptd_count;
ptd = &ep->ptd;
dump_ptd(ptd);
dump_ptd_out_data(ptd, ep->data);
@@ -305,9 +293,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
udev = urb->dev;
ptd = &ep->ptd;
cc = PTD_GET_CC(ptd);
-
- spin_lock(&urb->lock);
short_not_ok = 1;
+ spin_lock(&urb->lock);
/* Data underrun is special. For allowed underrun
we clear the error and continue as normal. For
@@ -420,7 +407,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
ep->nextpid = 0;
break;
default:
- BUG_ON(1);
+ BUG();
}
spin_unlock(&urb->lock);
}
@@ -628,8 +615,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
if (intstat & HCINT_UE) {
- ERR("Unrecoverable error\n");
- /* What should we do here? Reset? */
+ ERR("Unrecoverable error, HC is dead!\n");
+ /* IRQ's are off, we do no DMA,
+ perfectly ready to die ... */
+ hcd->state = HC_STATE_HALT;
+ ret = IRQ_HANDLED;
+ goto done;
}
if (intstat & HCINT_RHSC)
/* When root hub or any of its ports is going
@@ -640,7 +631,6 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (intstat & HCINT_RD) {
DBG("---- remote wakeup\n");
usb_hcd_resume_root_hub(hcd);
- ret = IRQ_HANDLED;
}
irqstat &= ~HCuPINT_OPR;
ret = IRQ_HANDLED;
@@ -651,6 +641,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
}
isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
+ done:
spin_unlock(&isp116x->lock);
return ret;
}
@@ -724,6 +715,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
spin_lock_irqsave(&isp116x->lock, flags);
if (!HC_IS_RUNNING(hcd->state)) {
+ kfree(ep);
ret = -ENODEV;
goto fail;
}
@@ -888,7 +880,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
struct usb_host_endpoint *hep)
{
int i;
- struct isp116x_ep *ep = hep->hcpriv;;
+ struct isp116x_ep *ep = hep->hcpriv;
if (!ep)
return;
@@ -916,8 +908,6 @@ static int isp116x_get_frame(struct usb_hcd *hcd)
return (int)fmnum;
}
-/*----------------------------------------------------------------*/
-
/*
Adapted from ohci-hub.c. Currently we don't support autosuspend.
*/
@@ -968,11 +958,10 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
desc->bHubContrCurrent = 0;
desc->bNbrPorts = (u8) (reg & 0x3);
/* Power switching, device type, overcurrent. */
- desc->wHubCharacteristics =
- (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f));
+ desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
/* two bitmaps: ports removable, and legacy PortPwrCtrlMask */
- desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
+ desc->bitmap[0] = 0;
desc->bitmap[1] = ~0;
}
@@ -1159,135 +1148,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
return ret;
}
-#ifdef CONFIG_PM
-
-static int isp116x_bus_suspend(struct usb_hcd *hcd)
-{
- struct isp116x *isp116x = hcd_to_isp116x(hcd);
- unsigned long flags;
- u32 val;
- int ret = 0;
-
- spin_lock_irqsave(&isp116x->lock, flags);
-
- val = isp116x_read_reg32(isp116x, HCCONTROL);
- switch (val & HCCONTROL_HCFS) {
- case HCCONTROL_USB_OPER:
- hcd->state = HC_STATE_QUIESCING;
- val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
- val |= HCCONTROL_USB_SUSPEND;
- if (hcd->remote_wakeup)
- val |= HCCONTROL_RWE;
- /* Wait for usb transfers to finish */
- mdelay(2);
- isp116x_write_reg32(isp116x, HCCONTROL, val);
- hcd->state = HC_STATE_SUSPENDED;
- /* Wait for devices to suspend */
- mdelay(5);
- case HCCONTROL_USB_SUSPEND:
- break;
- case HCCONTROL_USB_RESUME:
- isp116x_write_reg32(isp116x, HCCONTROL,
- (val & ~HCCONTROL_HCFS) |
- HCCONTROL_USB_RESET);
- case HCCONTROL_USB_RESET:
- ret = -EBUSY;
- break;
- default:
- ret = -EINVAL;
- }
-
- spin_unlock_irqrestore(&isp116x->lock, flags);
- return ret;
-}
-
-static int isp116x_bus_resume(struct usb_hcd *hcd)
-{
- struct isp116x *isp116x = hcd_to_isp116x(hcd);
- u32 val;
- int ret = -EINPROGRESS;
-
- msleep(5);
- spin_lock_irq(&isp116x->lock);
-
- val = isp116x_read_reg32(isp116x, HCCONTROL);
- switch (val & HCCONTROL_HCFS) {
- case HCCONTROL_USB_SUSPEND:
- val &= ~HCCONTROL_HCFS;
- val |= HCCONTROL_USB_RESUME;
- isp116x_write_reg32(isp116x, HCCONTROL, val);
- case HCCONTROL_USB_RESUME:
- break;
- case HCCONTROL_USB_OPER:
- /* Without setting power_state here the
- SUSPENDED state won't be removed from
- sysfs/usbN/power.state as a response to remote
- wakeup. Maybe in the future. */
- hcd->self.root_hub->dev.power.power_state = PMSG_ON;
- ret = 0;
- break;
- default:
- ret = -EBUSY;
- }
-
- if (ret != -EINPROGRESS) {
- spin_unlock_irq(&isp116x->lock);
- return ret;
- }
-
- val = isp116x->rhdesca & RH_A_NDP;
- while (val--) {
- u32 stat =
- isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
- /* force global, not selective, resume */
- if (!(stat & RH_PS_PSS))
- continue;
- DBG("%s: Resuming port %d\n", __func__, val);
- isp116x_write_reg32(isp116x, RH_PS_POCI, val
- ? HCRHPORT2 : HCRHPORT1);
- }
- spin_unlock_irq(&isp116x->lock);
-
- hcd->state = HC_STATE_RESUMING;
- mdelay(20);
-
- /* Go operational */
- spin_lock_irq(&isp116x->lock);
- val = isp116x_read_reg32(isp116x, HCCONTROL);
- isp116x_write_reg32(isp116x, HCCONTROL,
- (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
- spin_unlock_irq(&isp116x->lock);
- /* see analogous comment above */
- hcd->self.root_hub->dev.power.power_state = PMSG_ON;
- hcd->state = HC_STATE_RUNNING;
-
- return 0;
-}
-
-
-#else
-
-#define isp116x_bus_suspend NULL
-#define isp116x_bus_resume NULL
-
-#endif
-
/*-----------------------------------------------------------------*/
-#ifdef STUB_DEBUG_FILE
-
-static inline void create_debug_file(struct isp116x *isp116x)
-{
-}
-
-static inline void remove_debug_file(struct isp116x *isp116x)
-{
-}
-
-#else
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
+#ifdef CONFIG_DEBUG_FS
static void dump_irq(struct seq_file *s, char *label, u16 mask)
{
@@ -1311,13 +1174,9 @@ static void dump_int(struct seq_file *s, char *label, u32 mask)
mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : "");
}
-static int proc_isp116x_show(struct seq_file *s, void *unused)
+static int isp116x_show_dbg(struct seq_file *s, void *unused)
{
struct isp116x *isp116x = s->private;
- struct isp116x_ep *ep;
- struct urb *urb;
- unsigned i;
- char *str;
seq_printf(s, "%s\n%s version %s\n",
isp116x_to_hcd(isp116x)->product_desc, hcd_name,
@@ -1333,105 +1192,50 @@ static int proc_isp116x_show(struct seq_file *s, void *unused)
}
spin_lock_irq(&isp116x->lock);
-
dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB));
dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT));
dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB));
dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT));
-
- list_for_each_entry(ep, &isp116x->async, schedule) {
-
- switch (ep->nextpid) {
- case USB_PID_IN:
- str = "in";
- break;
- case USB_PID_OUT:
- str = "out";
- break;
- case USB_PID_SETUP:
- str = "setup";
- break;
- case USB_PID_ACK:
- str = "status";
- break;
- default:
- str = "?";
- break;
- };
- seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep,
- ep->epnum, str, ep->maxpacket);
- list_for_each_entry(urb, &ep->hep->urb_list, urb_list) {
- seq_printf(s, " urb%p, %d/%d\n", urb,
- urb->actual_length,
- urb->transfer_buffer_length);
- }
- }
- if (!list_empty(&isp116x->async))
- seq_printf(s, "\n");
-
- seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);
-
- for (i = 0; i < PERIODIC_SIZE; i++) {
- ep = isp116x->periodic[i];
- if (!ep)
- continue;
- seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]);
-
- /* DUMB: prints shared entries multiple times */
- do {
- seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n",
- ep->period, ep,
- (ep->udev->speed ==
- USB_SPEED_FULL) ? "" : "ls ",
- ep->udev->devnum, ep->epnum,
- (ep->epnum ==
- 0) ? "" : ((ep->nextpid ==
- USB_PID_IN) ? "in" : "out"),
- ep->maxpacket);
- ep = ep->next;
- } while (ep);
- }
+ isp116x_show_regs_seq(isp116x, s);
spin_unlock_irq(&isp116x->lock);
seq_printf(s, "\n");
return 0;
}
-static int proc_isp116x_open(struct inode *inode, struct file *file)
+static int isp116x_open_seq(struct inode *inode, struct file *file)
{
- return single_open(file, proc_isp116x_show, PDE(inode)->data);
+ return single_open(file, isp116x_show_dbg, inode->u.generic_ip);
}
-static struct file_operations proc_ops = {
- .open = proc_isp116x_open,
+static struct file_operations isp116x_debug_fops = {
+ .open = isp116x_open_seq,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
-/* expect just one isp116x per system */
-static const char proc_filename[] = "driver/isp116x";
-
-static void create_debug_file(struct isp116x *isp116x)
+static int create_debug_file(struct isp116x *isp116x)
{
- struct proc_dir_entry *pde;
-
- pde = create_proc_entry(proc_filename, 0, NULL);
- if (pde == NULL)
- return;
-
- pde->proc_fops = &proc_ops;
- pde->data = isp116x;
- isp116x->pde = pde;
+ isp116x->dentry = debugfs_create_file(hcd_name,
+ S_IRUGO, NULL, isp116x,
+ &isp116x_debug_fops);
+ if (!isp116x->dentry)
+ return -ENOMEM;
+ return 0;
}
static void remove_debug_file(struct isp116x *isp116x)
{
- if (isp116x->pde)
- remove_proc_entry(proc_filename, NULL);
+ debugfs_remove(isp116x->dentry);
}
-#endif
+#else
+
+#define create_debug_file(d) 0
+#define remove_debug_file(d) do{}while(0)
+
+#endif /* CONFIG_DEBUG_FS */
/*-----------------------------------------------------------------*/
@@ -1466,7 +1270,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
struct isp116x *isp116x = hcd_to_isp116x(hcd);
unsigned long t;
u16 clkrdy = 0;
- int ret = 0, timeout = 15 /* ms */ ;
+ int ret, timeout = 15 /* ms */ ;
ret = isp116x_sw_reset(isp116x);
if (ret)
@@ -1482,7 +1286,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
break;
}
if (!clkrdy) {
- ERR("Clock not ready after 20ms\n");
+ ERR("Clock not ready after %dms\n", timeout);
/* After sw_reset the clock won't report to be ready, if
H_WAKEUP pin is high. */
ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
@@ -1572,7 +1376,8 @@ static int isp116x_start(struct usb_hcd *hcd)
val = 0;
if (board->remote_wakeup_enable) {
- hcd->can_wakeup = 1;
+ if (!device_can_wakeup(hcd->self.controller))
+ device_init_wakeup(hcd->self.controller, 1);
val |= RH_HS_DRWE;
}
isp116x_write_reg32(isp116x, HCRHSTATUS, val);
@@ -1600,12 +1405,126 @@ static int isp116x_start(struct usb_hcd *hcd)
isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
- isp116x_show_regs(isp116x);
+ isp116x_show_regs_log(isp116x);
spin_unlock_irqrestore(&isp116x->lock, flags);
return 0;
}
-/*-----------------------------------------------------------------*/
+#ifdef CONFIG_PM
+
+static int isp116x_bus_suspend(struct usb_hcd *hcd)
+{
+ struct isp116x *isp116x = hcd_to_isp116x(hcd);
+ unsigned long flags;
+ u32 val;
+ int ret = 0;
+
+ spin_lock_irqsave(&isp116x->lock, flags);
+
+ val = isp116x_read_reg32(isp116x, HCCONTROL);
+ switch (val & HCCONTROL_HCFS) {
+ case HCCONTROL_USB_OPER:
+ val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
+ val |= HCCONTROL_USB_SUSPEND;
+ if (device_may_wakeup(&hcd->self.root_hub->dev))
+ val |= HCCONTROL_RWE;
+ /* Wait for usb transfers to finish */
+ mdelay(2);
+ isp116x_write_reg32(isp116x, HCCONTROL, val);
+ /* Wait for devices to suspend */
+ mdelay(5);
+ case HCCONTROL_USB_SUSPEND:
+ break;
+ case HCCONTROL_USB_RESUME:
+ isp116x_write_reg32(isp116x, HCCONTROL,
+ (val & ~HCCONTROL_HCFS) |
+ HCCONTROL_USB_RESET);
+ case HCCONTROL_USB_RESET:
+ ret = -EBUSY;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&isp116x->lock, flags);
+ return ret;
+}
+
+static int isp116x_bus_resume(struct usb_hcd *hcd)
+{
+ struct isp116x *isp116x = hcd_to_isp116x(hcd);
+ u32 val;
+
+ msleep(5);
+ spin_lock_irq(&isp116x->lock);
+
+ val = isp116x_read_reg32(isp116x, HCCONTROL);
+ switch (val & HCCONTROL_HCFS) {
+ case HCCONTROL_USB_SUSPEND:
+ val &= ~HCCONTROL_HCFS;
+ val |= HCCONTROL_USB_RESUME;
+ isp116x_write_reg32(isp116x, HCCONTROL, val);
+ case HCCONTROL_USB_RESUME:
+ break;
+ case HCCONTROL_USB_OPER:
+ spin_unlock_irq(&isp116x->lock);
+ /* Without setting power_state here the
+ SUSPENDED state won't be removed from
+ sysfs/usbN/power.state as a response to remote
+ wakeup. Maybe in the future. */
+ hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ return 0;
+ default:
+ /* HCCONTROL_USB_RESET: this may happen, when during
+ suspension the HC lost power. Reinitialize completely */
+ spin_unlock_irq(&isp116x->lock);
+ DBG("Chip has been reset while suspended. Reinit from scratch.\n");
+ isp116x_reset(hcd);
+ isp116x_start(hcd);
+ isp116x_hub_control(hcd, SetPortFeature,
+ USB_PORT_FEAT_POWER, 1, NULL, 0);
+ if ((isp116x->rhdesca & RH_A_NDP) == 2)
+ isp116x_hub_control(hcd, SetPortFeature,
+ USB_PORT_FEAT_POWER, 2, NULL, 0);
+ hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ return 0;
+ }
+
+ val = isp116x->rhdesca & RH_A_NDP;
+ while (val--) {
+ u32 stat =
+ isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
+ /* force global, not selective, resume */
+ if (!(stat & RH_PS_PSS))
+ continue;
+ DBG("%s: Resuming port %d\n", __func__, val);
+ isp116x_write_reg32(isp116x, RH_PS_POCI, val
+ ? HCRHPORT2 : HCRHPORT1);
+ }
+ spin_unlock_irq(&isp116x->lock);
+
+ hcd->state = HC_STATE_RESUMING;
+ msleep(20);
+
+ /* Go operational */
+ spin_lock_irq(&isp116x->lock);
+ val = isp116x_read_reg32(isp116x, HCCONTROL);
+ isp116x_write_reg32(isp116x, HCCONTROL,
+ (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
+ spin_unlock_irq(&isp116x->lock);
+ /* see analogous comment above */
+ hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ hcd->state = HC_STATE_RUNNING;
+
+ return 0;
+}
+
+#else
+
+#define isp116x_bus_suspend NULL
+#define isp116x_bus_resume NULL
+
+#endif
static struct hc_driver isp116x_hc_driver = {
.description = hcd_name,
@@ -1735,12 +1654,19 @@ static int __init isp116x_probe(struct platform_device *pdev)
}
ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
- if (ret != 0)
+ if (ret)
goto err6;
- create_debug_file(isp116x);
+ ret = create_debug_file(isp116x);
+ if (ret) {
+ ERR("Couldn't create debugfs entry\n");
+ goto err7;
+ }
+
return 0;
+ err7:
+ usb_remove_hcd(hcd);
err6:
usb_put_hcd(hcd);
err5:
@@ -1762,13 +1688,9 @@ static int __init isp116x_probe(struct platform_device *pdev)
*/
static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
{
- int ret = 0;
-
- VDBG("%s: state %x\n", __func__, state);
-
+ VDBG("%s: state %x\n", __func__, state.event);
dev->dev.power.power_state = state;
-
- return ret;
+ return 0;
}
/*
@@ -1776,13 +1698,9 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
*/
static int isp116x_resume(struct platform_device *dev)
{
- int ret = 0;
-
- VDBG("%s: state %x\n", __func__, dev->dev.power.power_state);
-
+ VDBG("%s: state %x\n", __func__, dev->power.power_state.event);
dev->dev.power.power_state = PMSG_ON;
-
- return ret;
+ return 0;
}
#else
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index c6fec96785fe..a1b7c3813d3a 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -259,7 +259,7 @@ struct isp116x {
struct isp116x_platform_data *board;
- struct proc_dir_entry *pde;
+ struct dentry *dentry;
unsigned long stat1, stat2, stat4, stat8, stat16;
/* HC registers */
@@ -450,7 +450,7 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
isp116x_write_data32(isp116x, (u32) val);
}
-#define isp116x_show_reg(d,r) { \
+#define isp116x_show_reg_log(d,r,s) { \
if ((r) < 0x20) { \
DBG("%-12s[%02x]: %08x\n", #r, \
r, isp116x_read_reg32(d, r)); \
@@ -459,35 +459,60 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
r, isp116x_read_reg16(d, r)); \
} \
}
+#define isp116x_show_reg_seq(d,r,s) { \
+ if ((r) < 0x20) { \
+ seq_printf(s, "%-12s[%02x]: %08x\n", #r, \
+ r, isp116x_read_reg32(d, r)); \
+ } else { \
+ seq_printf(s, "%-12s[%02x]: %04x\n", #r, \
+ r, isp116x_read_reg16(d, r)); \
+ } \
+}
-static inline void isp116x_show_regs(struct isp116x *isp116x)
+#define isp116x_show_regs(d,type,s) { \
+ isp116x_show_reg_##type(d, HCREVISION, s); \
+ isp116x_show_reg_##type(d, HCCONTROL, s); \
+ isp116x_show_reg_##type(d, HCCMDSTAT, s); \
+ isp116x_show_reg_##type(d, HCINTSTAT, s); \
+ isp116x_show_reg_##type(d, HCINTENB, s); \
+ isp116x_show_reg_##type(d, HCFMINTVL, s); \
+ isp116x_show_reg_##type(d, HCFMREM, s); \
+ isp116x_show_reg_##type(d, HCFMNUM, s); \
+ isp116x_show_reg_##type(d, HCLSTHRESH, s); \
+ isp116x_show_reg_##type(d, HCRHDESCA, s); \
+ isp116x_show_reg_##type(d, HCRHDESCB, s); \
+ isp116x_show_reg_##type(d, HCRHSTATUS, s); \
+ isp116x_show_reg_##type(d, HCRHPORT1, s); \
+ isp116x_show_reg_##type(d, HCRHPORT2, s); \
+ isp116x_show_reg_##type(d, HCHWCFG, s); \
+ isp116x_show_reg_##type(d, HCDMACFG, s); \
+ isp116x_show_reg_##type(d, HCXFERCTR, s); \
+ isp116x_show_reg_##type(d, HCuPINT, s); \
+ isp116x_show_reg_##type(d, HCuPINTENB, s); \
+ isp116x_show_reg_##type(d, HCCHIPID, s); \
+ isp116x_show_reg_##type(d, HCSCRATCH, s); \
+ isp116x_show_reg_##type(d, HCITLBUFLEN, s); \
+ isp116x_show_reg_##type(d, HCATLBUFLEN, s); \
+ isp116x_show_reg_##type(d, HCBUFSTAT, s); \
+ isp116x_show_reg_##type(d, HCRDITL0LEN, s); \
+ isp116x_show_reg_##type(d, HCRDITL1LEN, s); \
+}
+
+/*
+ Dump registers for debugfs.
+*/
+static inline void isp116x_show_regs_seq(struct isp116x *isp116x,
+ struct seq_file *s)
+{
+ isp116x_show_regs(isp116x, seq, s);
+}
+
+/*
+ Dump registers to syslog.
+*/
+static inline void isp116x_show_regs_log(struct isp116x *isp116x)
{
- isp116x_show_reg(isp116x, HCREVISION);
- isp116x_show_reg(isp116x, HCCONTROL);
- isp116x_show_reg(isp116x, HCCMDSTAT);
- isp116x_show_reg(isp116x, HCINTSTAT);
- isp116x_show_reg(isp116x, HCINTENB);
- isp116x_show_reg(isp116x, HCFMINTVL);
- isp116x_show_reg(isp116x, HCFMREM);
- isp116x_show_reg(isp116x, HCFMNUM);
- isp116x_show_reg(isp116x, HCLSTHRESH);
- isp116x_show_reg(isp116x, HCRHDESCA);
- isp116x_show_reg(isp116x, HCRHDESCB);
- isp116x_show_reg(isp116x, HCRHSTATUS);
- isp116x_show_reg(isp116x, HCRHPORT1);
- isp116x_show_reg(isp116x, HCRHPORT2);
- isp116x_show_reg(isp116x, HCHWCFG);
- isp116x_show_reg(isp116x, HCDMACFG);
- isp116x_show_reg(isp116x, HCXFERCTR);
- isp116x_show_reg(isp116x, HCuPINT);
- isp116x_show_reg(isp116x, HCuPINTENB);
- isp116x_show_reg(isp116x, HCCHIPID);
- isp116x_show_reg(isp116x, HCSCRATCH);
- isp116x_show_reg(isp116x, HCITLBUFLEN);
- isp116x_show_reg(isp116x, HCATLBUFLEN);
- isp116x_show_reg(isp116x, HCBUFSTAT);
- isp116x_show_reg(isp116x, HCRDITL0LEN);
- isp116x_show_reg(isp116x, HCRDITL1LEN);
+ isp116x_show_regs(isp116x, log, NULL);
}
#if defined(URB_TRACE)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index bf1d9abc07ac..a4b12404ae08 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -75,13 +75,6 @@
*/
#include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-# define DEBUG
-#else
-# undef DEBUG
-#endif
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
@@ -802,7 +795,6 @@ static int ohci_restart (struct ohci_hcd *ohci)
int temp;
int i;
struct urb_priv *priv;
- struct usb_device *root = ohci_to_hcd(ohci)->self.root_hub;
/* mark any devices gone, so they do nothing till khubd disconnects.
* recycle any "live" eds/tds (and urbs) right away.
@@ -811,11 +803,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
*/
spin_lock_irq(&ohci->lock);
disable (ohci);
- for (i = 0; i < root->maxchild; i++) {
- if (root->children [i])
- usb_set_device_state (root->children[i],
- USB_STATE_NOTATTACHED);
- }
+ usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
if (!list_empty (&ohci->pending))
ohci_dbg(ohci, "abort schedule...\n");
list_for_each_entry (priv, &ohci->pending, pending) {
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 72e3b12a1926..4b2226d77b34 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -372,7 +372,7 @@ done:
& ohci->hc_control)
== OHCI_USB_OPER
&& time_after (jiffies, ohci->next_statechange)
- && usb_trylock_device (hcd->self.root_hub)
+ && usb_trylock_device (hcd->self.root_hub) == 0
) {
ohci_vdbg (ohci, "autosuspend\n");
(void) ohci_bus_suspend (hcd);
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 9d65ec307990..acde8868da21 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -26,18 +26,12 @@
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
-
-
-#define PMM_NPS_MODE 1
-#define PMM_GLOBAL_MODE 2
-#define PMM_PERPORT_MODE 3
+#include <asm/arch/ohci.h>
#define PXA_UHC_MAX_PORTNUM 3
#define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 )
-static int pxa27x_ohci_pmm_state;
-
/*
PMM_NPS_MODE -- PMM Non-power switching mode
Ports are powered continuously.
@@ -50,8 +44,6 @@ static int pxa27x_ohci_pmm_state;
*/
static int pxa27x_ohci_select_pmm( int mode )
{
- pxa27x_ohci_pmm_state = mode;
-
switch ( mode ) {
case PMM_NPS_MODE:
UHCRHDA |= RH_A_NPS;
@@ -71,7 +63,6 @@ static int pxa27x_ohci_select_pmm( int mode )
"Invalid mode %d, set to non-power switch mode.\n",
mode );
- pxa27x_ohci_pmm_state = PMM_NPS_MODE;
UHCRHDA |= RH_A_NPS;
}
@@ -82,8 +73,13 @@ extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
-static void pxa27x_start_hc(struct platform_device *dev)
+static int pxa27x_start_hc(struct device *dev)
{
+ int retval = 0;
+ struct pxaohci_platform_data *inf;
+
+ inf = dev->platform_data;
+
pxa_set_cken(CKEN10_USBHOST, 1);
UHCHR |= UHCHR_FHR;
@@ -94,21 +90,11 @@ static void pxa27x_start_hc(struct platform_device *dev)
while (UHCHR & UHCHR_FSBIR)
cpu_relax();
- /* This could be properly abstracted away through the
- device data the day more machines are supported and
- their differences can be figured out correctly. */
- if (machine_is_mainstone()) {
- /* setup Port1 GPIO pin. */
- pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
- pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
-
- /* Set the Power Control Polarity Low and Power Sense
- Polarity Low to active low. Supply power to USB ports. */
- UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
- ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+ if (inf->init)
+ retval = inf->init(dev);
- pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
- }
+ if (retval < 0)
+ return retval;
UHCHR &= ~UHCHR_SSE;
@@ -117,10 +103,19 @@ static void pxa27x_start_hc(struct platform_device *dev)
/* Clear any OTG Pin Hold */
if (PSSR & PSSR_OTGPH)
PSSR |= PSSR_OTGPH;
+
+ return 0;
}
-static void pxa27x_stop_hc(struct platform_device *dev)
+static void pxa27x_stop_hc(struct device *dev)
{
+ struct pxaohci_platform_data *inf;
+
+ inf = dev->platform_data;
+
+ if (inf->exit)
+ inf->exit(dev);
+
UHCHR |= UHCHR_FHR;
udelay(11);
UHCHR &= ~UHCHR_FHR;
@@ -147,22 +142,27 @@ static void pxa27x_stop_hc(struct platform_device *dev)
* through the hotplug entry's driver_data.
*
*/
-int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
- struct platform_device *dev)
+int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev)
{
int retval;
struct usb_hcd *hcd;
+ struct pxaohci_platform_data *inf;
- if (dev->resource[1].flags != IORESOURCE_IRQ) {
+ inf = pdev->dev.platform_data;
+
+ if (!inf)
+ return -ENODEV;
+
+ if (pdev->resource[1].flags != IORESOURCE_IRQ) {
pr_debug ("resource[1] is not IORESOURCE_IRQ");
return -ENOMEM;
}
- hcd = usb_create_hcd (driver, &dev->dev, "pxa27x");
+ hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
if (!hcd)
return -ENOMEM;
- hcd->rsrc_start = dev->resource[0].start;
- hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+ 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)) {
pr_debug("request_mem_region failed");
@@ -177,18 +177,22 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
goto err2;
}
- pxa27x_start_hc(dev);
+ if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) {
+ pr_debug("pxa27x_start_hc failed");
+ goto err3;
+ }
/* Select Power Management Mode */
- pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
+ pxa27x_ohci_select_pmm(inf->port_mode);
ohci_hcd_init(hcd_to_ohci(hcd));
- retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+ retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
if (retval == 0)
return retval;
- pxa27x_stop_hc(dev);
+ pxa27x_stop_hc(&pdev->dev);
+ err3:
iounmap(hcd->regs);
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
@@ -211,10 +215,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
* context, normally "rmmod", "apmd", or something similar.
*
*/
-void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev)
+void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
{
usb_remove_hcd(hcd);
- pxa27x_stop_hc(dev);
+ pxa27x_stop_hc(&pdev->dev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
@@ -292,15 +296,12 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev)
{
- int ret;
-
pr_debug ("In ohci_hcd_pxa27x_drv_probe");
if (usb_disabled())
return -ENODEV;
- ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
- return ret;
+ return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
}
static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
@@ -308,31 +309,55 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_hcd_pxa27x_remove(hcd, pdev);
+ platform_set_drvdata(pdev, NULL);
return 0;
}
-static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef CONFIG_PM
+static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state)
{
-// struct usb_hcd *hcd = platform_get_drvdata(dev);
- printk("%s: not implemented yet\n", __FUNCTION__);
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ pxa27x_stop_hc(&pdev->dev);
+ hcd->state = HC_STATE_SUSPENDED;
+ pdev->dev.power.power_state = PMSG_SUSPEND;
return 0;
}
-static int ohci_hcd_pxa27x_drv_resume(struct platform_device *dev)
+static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
{
-// struct usb_hcd *hcd = platform_get_drvdata(dev);
- printk("%s: not implemented yet\n", __FUNCTION__);
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int status;
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
+ return status;
+
+ pdev->dev.power.power_state = PMSG_ON;
+ usb_hcd_resume_root_hub(hcd);
return 0;
}
+#endif
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_drv_probe,
.remove = ohci_hcd_pxa27x_drv_remove,
+#ifdef CONFIG_PM
.suspend = ohci_hcd_pxa27x_drv_suspend,
.resume = ohci_hcd_pxa27x_drv_resume,
+#endif
.driver = {
.name = "pxa27x-ohci",
},
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index e46528c825bf..3ef2c0cdf1db 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -9,12 +9,6 @@
*/
#include <linux/config.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index a7722a6a5a5b..517360b77d8e 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -32,13 +32,6 @@
#undef PACKET_TRACE
#include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-# define DEBUG
-#else
-# undef DEBUG
-#endif
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -1581,7 +1574,9 @@ sl811h_start(struct usb_hcd *hcd)
hcd->state = HC_STATE_RUNNING;
if (sl811->board) {
- hcd->can_wakeup = sl811->board->can_wakeup;
+ if (!device_can_wakeup(hcd->self.controller))
+ device_init_wakeup(hcd->self.controller,
+ sl811->board->can_wakeup);
hcd->power_budget = sl811->board->power * 2;
}
@@ -1805,9 +1800,10 @@ sl811h_resume(struct platform_device *dev)
* let's assume it'd only be powered to enable remote wakeup.
*/
if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND
- || !hcd->can_wakeup) {
+ || !device_can_wakeup(&hcd->self.root_hub->dev)) {
sl811->port1 = 0;
port_power(sl811, 1);
+ usb_root_hub_lost_power(hcd->self.root_hub);
return 0;
}
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index e73faf831b24..5056b7459994 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
/* MACROS */
/*====================================================================*/
-#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG)
+#if defined(DEBUG) || defined(PCMCIA_DEBUG)
static int pc_debug = 0;
module_param(pc_debug, int, 0644);
@@ -129,7 +129,8 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
resources[2].end = base_addr + 1;
/* The driver core will probe for us. We know sl811-hcd has been
- * initialized already because of the link order dependency.
+ * initialized already because of the link order dependency created
+ * by referencing "sl811h_driver".
*/
platform_dev.name = sl811h_driver.name;
return platform_device_register(&platform_dev);
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 151154df37fa..5832953086f8 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -2,8 +2,8 @@
* UHCI-specific debugging code. Invaluable when something
* goes wrong, but don't get in my face.
*
- * Kernel visible pointers are surrounded in []'s and bus
- * visible pointers are surrounded in ()'s
+ * Kernel visible pointers are surrounded in []s and bus
+ * visible pointers are surrounded in ()s
*
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999-2001 Johannes Erdfelt
@@ -19,7 +19,7 @@
static struct dentry *uhci_debugfs_root = NULL;
-/* Handle REALLY large printk's so we don't overflow buffers */
+/* Handle REALLY large printks so we don't overflow buffers */
static inline void lprintk(char *buf)
{
char *p;
@@ -160,7 +160,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
}
if (active && ni > i) {
- out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i);
+ out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i);
tmp = ntmp;
td = ntd;
i = ni;
@@ -173,7 +173,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
if (list_empty(&urbp->queue_list) || urbp->queued)
goto out;
- out += sprintf(out, "%*sQueued QH's:\n", -space, "--");
+ out += sprintf(out, "%*sQueued QHs:\n", -space, "--");
head = &urbp->queue_list;
tmp = head->next;
@@ -197,7 +197,7 @@ out:
}
#ifdef CONFIG_PROC_FS
-static const char *qh_names[] = {
+static const char * const qh_names[] = {
"skel_int128_qh", "skel_int64_qh",
"skel_int32_qh", "skel_int16_qh",
"skel_int8_qh", "skel_int4_qh",
@@ -464,7 +464,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
} while (tmp != head);
}
- out += sprintf(out, "Skeleton QH's\n");
+ out += sprintf(out, "Skeleton QHs\n");
for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
int shown = 0;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 79efaf7d86a3..dfe121d35887 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -23,11 +23,6 @@
*/
#include <linux/config.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
@@ -67,10 +62,10 @@ Alan Stern"
/*
* debug = 0, no debugging messages
- * debug = 1, dump failed URB's except for stalls
- * debug = 2, dump all failed URB's (including stalls)
+ * debug = 1, dump failed URBs except for stalls
+ * debug = 2, dump all failed URBs (including stalls)
* show all queues in /debug/uhci/[pci_addr]
- * debug = 3, show all TD's in URB's when dumping
+ * debug = 3, show all TDs in URBs when dumping
*/
#ifdef DEBUG
static int debug = 1;
@@ -93,7 +88,7 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
#define FSBR_DELAY msecs_to_jiffies(50)
/* When we timeout an idle transfer for FSBR, we'll switch it over to */
-/* depth first traversal. We'll do it in groups of this number of TD's */
+/* depth first traversal. We'll do it in groups of this number of TDs */
/* to make sure it doesn't hog all of the bandwidth */
#define DEPTH_INTERVAL 5
@@ -478,8 +473,6 @@ static int uhci_start(struct usb_hcd *hcd)
struct dentry *dentry;
hcd->uses_new_polling = 1;
- if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
- hcd->can_wakeup = 1; /* Assume it supports PME# */
dentry = debugfs_create_file(hcd->self.bus_name,
S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
@@ -573,7 +566,7 @@ static int uhci_start(struct usb_hcd *hcd)
uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
/* This dummy TD is to work around a bug in Intel PIIX controllers */
- uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
+ uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
@@ -735,8 +728,9 @@ static int uhci_resume(struct usb_hcd *hcd)
dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
- /* We aren't in D3 state anymore, we do that even if dead as I
- * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0
+ /* Since we aren't in D3 any more, it's safe to set this flag
+ * even if the controller was dead. It might not even be dead
+ * any more, if the firmware or quirks code has reset it.
*/
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
mb();
@@ -755,8 +749,12 @@ static int uhci_resume(struct usb_hcd *hcd)
check_and_reset_hc(uhci);
configure_hc(uhci);
- if (uhci->rh_state == UHCI_RH_RESET)
+ if (uhci->rh_state == UHCI_RH_RESET) {
+
+ /* The controller had to be reset */
+ usb_root_hub_lost_power(hcd->self.root_hub);
suspend_rh(uhci, UHCI_RH_SUSPENDED);
+ }
spin_unlock_irq(&uhci->lock);
@@ -882,7 +880,7 @@ static int __init uhci_hcd_init(void)
init_failed:
if (kmem_cache_destroy(uhci_up_cachep))
- warn("not all urb_priv's were freed!");
+ warn("not all urb_privs were freed!");
up_failed:
debugfs_remove(uhci_debugfs_root);
@@ -900,7 +898,7 @@ static void __exit uhci_hcd_cleanup(void)
pci_unregister_driver(&uhci_pci_driver);
if (kmem_cache_destroy(uhci_up_cachep))
- warn("not all urb_priv's were freed!");
+ warn("not all urb_privs were freed!");
debugfs_remove(uhci_debugfs_root);
kfree(errbuf);
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index e576db57a926..8b4b887a7d41 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -71,8 +71,6 @@
#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
-#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */
-
#define UHCI_PTR_BITS cpu_to_le32(0x000F)
#define UHCI_PTR_TERM cpu_to_le32(0x0001)
#define UHCI_PTR_QH cpu_to_le32(0x0002)
@@ -168,9 +166,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */
#define TD_TOKEN_PID_MASK 0xFF
-#define uhci_explen(len) ((len) << TD_TOKEN_EXPLEN_SHIFT)
+#define uhci_explen(len) ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
+ TD_TOKEN_EXPLEN_SHIFT)
-#define uhci_expected_length(token) ((((token) >> 21) + 1) & TD_TOKEN_EXPLEN_MASK)
+#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
+ 1) & TD_TOKEN_EXPLEN_MASK)
#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1)
#define uhci_endpoint(token) (((token) >> 15) & 0xf)
#define uhci_devaddr(token) (((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7f)
@@ -223,10 +223,10 @@ static u32 inline td_status(struct uhci_td *td) {
*/
/*
- * The UHCI driver places Interrupt, Control and Bulk into QH's both
- * to group together TD's for one transfer, and also to faciliate queuing
- * of URB's. To make it easy to insert entries into the schedule, we have
- * a skeleton of QH's for each predefined Interrupt latency, low-speed
+ * The UHCI driver places Interrupt, Control and Bulk into QHs both
+ * to group together TDs for one transfer, and also to facilitate queuing
+ * of URBs. To make it easy to insert entries into the schedule, we have
+ * a skeleton of QHs for each predefined Interrupt latency, low-speed
* control, full-speed control and terminating QH (see explanation for
* the terminating QH below).
*
@@ -257,8 +257,8 @@ static u32 inline td_status(struct uhci_td *td) {
* reclamation.
*
* Isochronous transfers are stored before the start of the skeleton
- * schedule and don't use QH's. While the UHCI spec doesn't forbid the
- * use of QH's for Isochronous, it doesn't use them either. And the spec
+ * schedule and don't use QHs. While the UHCI spec doesn't forbid the
+ * use of QHs for Isochronous, it doesn't use them either. And the spec
* says that queues never advance on an error completion status, which
* makes them totally unsuitable for Isochronous transfers.
*/
@@ -359,7 +359,7 @@ struct uhci_hcd {
struct dma_pool *td_pool;
struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
- struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
+ struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */
spinlock_t lock;
@@ -389,22 +389,22 @@ struct uhci_hcd {
unsigned long resuming_ports;
unsigned long ports_timeout; /* Time to stop signalling */
- /* Main list of URB's currently controlled by this HC */
+ /* Main list of URBs currently controlled by this HC */
struct list_head urb_list;
- /* List of QH's that are done, but waiting to be unlinked (race) */
+ /* List of QHs that are done, but waiting to be unlinked (race) */
struct list_head qh_remove_list;
unsigned int qh_remove_age; /* Age in frames */
- /* List of TD's that are done, but waiting to be freed (race) */
+ /* List of TDs that are done, but waiting to be freed (race) */
struct list_head td_remove_list;
unsigned int td_remove_age; /* Age in frames */
- /* List of asynchronously unlinked URB's */
+ /* List of asynchronously unlinked URBs */
struct list_head urb_remove_list;
unsigned int urb_remove_age; /* Age in frames */
- /* List of URB's awaiting completion callback */
+ /* List of URBs awaiting completion callback */
struct list_head complete_list;
int rh_numports; /* Number of root-hub ports */
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 7e46887d9e12..b6076004a437 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -80,7 +80,7 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status,
}
/*
- * We insert Isochronous URB's directly into the frame list at the beginning
+ * We insert Isochronous URBs directly into the frame list at the beginning
*/
static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
{
@@ -369,7 +369,7 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru
uhci_fixup_toggle(urb,
uhci_toggle(td_token(lltd)) ^ 1));
- /* All qh's in the queue need to link to the next queue */
+ /* All qhs in the queue need to link to the next queue */
urbp->qh->link = eurbp->qh->link;
wmb(); /* Make sure we flush everything */
@@ -502,7 +502,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
}
/* Check to see if the remove list is empty. Set the IOC bit */
- /* to force an interrupt so we can remove the TD's*/
+ /* to force an interrupt so we can remove the TDs*/
if (list_empty(&uhci->td_remove_list))
uhci_set_next_interrupt(uhci);
@@ -596,7 +596,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(7),
+ uhci_fill_td(td, status, destination | uhci_explen(8),
urb->setup_dma);
/*
@@ -612,7 +612,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
}
/*
- * Build the DATA TD's
+ * Build the DATA TDs
*/
while (len > 0) {
int pktsze = len;
@@ -628,7 +628,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
destination ^= TD_TOKEN_TOGGLE;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
+ uhci_fill_td(td, status, destination | uhci_explen(pktsze),
data);
data += pktsze;
@@ -658,7 +658,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status | TD_CTRL_IOC,
- destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
+ destination | uhci_explen(0), 0);
qh = uhci_alloc_qh(uhci);
if (!qh)
@@ -744,7 +744,7 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
urb->actual_length = 0;
- /* The rest of the TD's (but the last) are data */
+ /* The rest of the TDs (but the last) are data */
tmp = tmp->next;
while (tmp != head && tmp->next != head) {
unsigned int ctrlstat;
@@ -848,7 +848,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
status |= TD_CTRL_SPD;
/*
- * Build the DATA TD's
+ * Build the DATA TDs
*/
do { /* Allow zero length packets */
int pktsze = maxsze;
@@ -864,7 +864,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
+ uhci_fill_td(td, status, destination | uhci_explen(pktsze) |
(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
data);
@@ -890,7 +890,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
+ uhci_fill_td(td, status, destination | uhci_explen(0) |
(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
data);
@@ -1025,7 +1025,7 @@ static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsig
list_for_each_entry(up, &uhci->urb_list, urb_list) {
struct urb *u = up->urb;
- /* look for pending URB's with identical pipe handle */
+ /* look for pending URBs with identical pipe handle */
if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
(u->status == -EINPROGRESS) && (u != urb)) {
if (!last_urb)
@@ -1092,7 +1092,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
+ uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length),
urb->transfer_dma + urb->iso_frame_desc[i].offset);
if (i + 1 >= urb->number_of_packets)
@@ -1355,7 +1355,7 @@ static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
uhci_delete_queued_urb(uhci, urb);
- /* The interrupt loop will reclaim the QH's */
+ /* The interrupt loop will reclaim the QHs */
uhci_remove_qh(uhci, urbp->qh);
urbp->qh = NULL;
}
@@ -1413,7 +1413,7 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
list_for_each_entry(td, head, list) {
/*
* Make sure we don't do the last one (since it'll have the
- * TERM bit set) as well as we skip every so many TD's to
+ * TERM bit set) as well as we skip every so many TDs to
* make sure it doesn't hog the bandwidth
*/
if (td->list.next != head && (count % DEPTH_INTERVAL) ==