[PATCH] USB: isp116x-hcd: cleanup

The attached patch makes a cleanup of isp116x-hcd. Most of the volume of
the patch comes from 2 sources: moving the code around to get rid of a
few function prototypes and reworking register dumping functions/macros.
Among other things, switched over from using procfs to debugfs.

Cleanup. The following changes were made:

- Rework register dumping code so it can be used for dumping
  to both syslog and debugfs.
- Switch from procfs to debugfs..
- Die gracefully on Unrecoverable Error interrupt.
- Fix memory leak in isp116x_urb_enqueue(), if HC happens to
  die in a narrow time window.
- Fix a 'sparce' warning (unnecessary cast).
- Report Devices Removable for root hub ports by default
  (was Devices Permanently Attached).
- Move bus suspend/resume functions down in code to get rid of
  a few function prototypes.
- A number of one-line cleanups.
- Add an entry to MAINTAINERS.

Signed-off-by: Olav Kongas <ok@artecdesign.ee>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

 MAINTAINERS                    |    6
 drivers/usb/host/isp116x-hcd.c |  429 ++++++++++++++++-------------------------
 drivers/usb/host/isp116x.h     |   83 +++++--
 3 files changed, 230 insertions(+), 288 deletions(-)
This commit is contained in:
Olav Kongas 2005-11-03 17:38:14 +02:00 committed by Greg Kroah-Hartman
parent 535488fcf1
commit 959eea2191
3 changed files with 230 additions and 288 deletions

View File

@ -2640,6 +2640,12 @@ L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net
S: Maintained S: Maintained
USB ISP116X DRIVER
P: Olav Kongas
M: ok@artecdesign.ee
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
USB KAWASAKI LSI DRIVER USB KAWASAKI LSI DRIVER
P: Oliver Neukum P: Oliver Neukum
M: oliver@neukum.name M: oliver@neukum.name

View File

@ -55,19 +55,13 @@
/* enqueuing/finishing log of urbs */ /* enqueuing/finishing log of urbs */
//#define URB_TRACE //#define URB_TRACE
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ioport.h> #include <linux/debugfs.h>
#include <linux/sched.h> #include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb_isp116x.h> #include <linux/usb_isp116x.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -77,14 +71,10 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#ifndef DEBUG
# define STUB_DEBUG_FILE
#endif
#include "../core/hcd.h" #include "../core/hcd.h"
#include "isp116x.h" #include "isp116x.h"
#define DRIVER_VERSION "05 Aug 2005" #define DRIVER_VERSION "03 Nov 2005"
#define DRIVER_DESC "ISP116x USB Host Controller Driver" #define DRIVER_DESC "ISP116x USB Host Controller Driver"
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
@ -305,9 +295,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
udev = urb->dev; udev = urb->dev;
ptd = &ep->ptd; ptd = &ep->ptd;
cc = PTD_GET_CC(ptd); cc = PTD_GET_CC(ptd);
spin_lock(&urb->lock);
short_not_ok = 1; short_not_ok = 1;
spin_lock(&urb->lock);
/* Data underrun is special. For allowed underrun /* Data underrun is special. For allowed underrun
we clear the error and continue as normal. For we clear the error and continue as normal. For
@ -420,7 +409,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
ep->nextpid = 0; ep->nextpid = 0;
break; break;
default: default:
BUG_ON(1); BUG();
} }
spin_unlock(&urb->lock); spin_unlock(&urb->lock);
} }
@ -628,8 +617,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT); u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
isp116x_write_reg32(isp116x, HCINTSTAT, intstat); isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
if (intstat & HCINT_UE) { if (intstat & HCINT_UE) {
ERR("Unrecoverable error\n"); ERR("Unrecoverable error, HC is dead!\n");
/* What should we do here? Reset? */ /* 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) if (intstat & HCINT_RHSC)
/* When root hub or any of its ports is going /* When root hub or any of its ports is going
@ -640,7 +633,6 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (intstat & HCINT_RD) { if (intstat & HCINT_RD) {
DBG("---- remote wakeup\n"); DBG("---- remote wakeup\n");
usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(hcd);
ret = IRQ_HANDLED;
} }
irqstat &= ~HCuPINT_OPR; irqstat &= ~HCuPINT_OPR;
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
@ -651,6 +643,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
} }
isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
done:
spin_unlock(&isp116x->lock); spin_unlock(&isp116x->lock);
return ret; return ret;
} }
@ -724,6 +717,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
spin_lock_irqsave(&isp116x->lock, flags); spin_lock_irqsave(&isp116x->lock, flags);
if (!HC_IS_RUNNING(hcd->state)) { if (!HC_IS_RUNNING(hcd->state)) {
kfree(ep);
ret = -ENODEV; ret = -ENODEV;
goto fail; goto fail;
} }
@ -888,7 +882,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
struct usb_host_endpoint *hep) struct usb_host_endpoint *hep)
{ {
int i; int i;
struct isp116x_ep *ep = hep->hcpriv;; struct isp116x_ep *ep = hep->hcpriv;
if (!ep) if (!ep)
return; return;
@ -916,8 +910,6 @@ static int isp116x_get_frame(struct usb_hcd *hcd)
return (int)fmnum; return (int)fmnum;
} }
/*----------------------------------------------------------------*/
/* /*
Adapted from ohci-hub.c. Currently we don't support autosuspend. Adapted from ohci-hub.c. Currently we don't support autosuspend.
*/ */
@ -968,11 +960,10 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
desc->bHubContrCurrent = 0; desc->bHubContrCurrent = 0;
desc->bNbrPorts = (u8) (reg & 0x3); desc->bNbrPorts = (u8) (reg & 0x3);
/* Power switching, device type, overcurrent. */ /* Power switching, device type, overcurrent. */
desc->wHubCharacteristics = desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
(__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f));
desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff); desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
/* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ /* 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; desc->bitmap[1] = ~0;
} }
@ -1159,145 +1150,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
return ret; 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;
}
/* Get rid of these declarations later in cleanup */
static int isp116x_reset(struct usb_hcd *hcd);
static int isp116x_start(struct usb_hcd *hcd);
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;
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 #ifdef CONFIG_DEBUG_FS
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>
static void dump_irq(struct seq_file *s, char *label, u16 mask) static void dump_irq(struct seq_file *s, char *label, u16 mask)
{ {
@ -1321,13 +1176,9 @@ static void dump_int(struct seq_file *s, char *label, u32 mask)
mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : ""); 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 *isp116x = s->private;
struct isp116x_ep *ep;
struct urb *urb;
unsigned i;
char *str;
seq_printf(s, "%s\n%s version %s\n", seq_printf(s, "%s\n%s version %s\n",
isp116x_to_hcd(isp116x)->product_desc, hcd_name, isp116x_to_hcd(isp116x)->product_desc, hcd_name,
@ -1343,105 +1194,50 @@ static int proc_isp116x_show(struct seq_file *s, void *unused)
} }
spin_lock_irq(&isp116x->lock); spin_lock_irq(&isp116x->lock);
dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB)); dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB));
dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT)); 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_enable", isp116x_read_reg32(isp116x, HCINTENB));
dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT)); dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT));
isp116x_show_regs_seq(isp116x, s);
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);
}
spin_unlock_irq(&isp116x->lock); spin_unlock_irq(&isp116x->lock);
seq_printf(s, "\n"); seq_printf(s, "\n");
return 0; 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 = { static struct file_operations isp116x_debug_fops = {
.open = proc_isp116x_open, .open = isp116x_open_seq,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = single_release, .release = single_release,
}; };
/* expect just one isp116x per system */ static int create_debug_file(struct isp116x *isp116x)
static const char proc_filename[] = "driver/isp116x";
static void create_debug_file(struct isp116x *isp116x)
{ {
struct proc_dir_entry *pde; isp116x->dentry = debugfs_create_file(hcd_name,
S_IRUGO, NULL, isp116x,
pde = create_proc_entry(proc_filename, 0, NULL); &isp116x_debug_fops);
if (pde == NULL) if (!isp116x->dentry)
return; return -ENOMEM;
return 0;
pde->proc_fops = &proc_ops;
pde->data = isp116x;
isp116x->pde = pde;
} }
static void remove_debug_file(struct isp116x *isp116x) static void remove_debug_file(struct isp116x *isp116x)
{ {
if (isp116x->pde) debugfs_remove(isp116x->dentry);
remove_proc_entry(proc_filename, NULL);
} }
#endif #else
#define create_debug_file(d) 0
#define remove_debug_file(d) do{}while(0)
#endif /* CONFIG_DEBUG_FS */
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
@ -1476,7 +1272,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
struct isp116x *isp116x = hcd_to_isp116x(hcd); struct isp116x *isp116x = hcd_to_isp116x(hcd);
unsigned long t; unsigned long t;
u16 clkrdy = 0; u16 clkrdy = 0;
int ret = 0, timeout = 15 /* ms */ ; int ret, timeout = 15 /* ms */ ;
ret = isp116x_sw_reset(isp116x); ret = isp116x_sw_reset(isp116x);
if (ret) if (ret)
@ -1492,7 +1288,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
break; break;
} }
if (!clkrdy) { 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 /* After sw_reset the clock won't report to be ready, if
H_WAKEUP pin is high. */ H_WAKEUP pin is high. */
ERR("Please make sure that the H_WAKEUP pin is pulled low!\n"); ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
@ -1610,12 +1406,128 @@ static int isp116x_start(struct usb_hcd *hcd)
isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
isp116x_write_reg32(isp116x, HCRHPORT2, 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); spin_unlock_irqrestore(&isp116x->lock, flags);
return 0; 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:
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;
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 = { static struct hc_driver isp116x_hc_driver = {
.description = hcd_name, .description = hcd_name,
@ -1745,12 +1657,19 @@ static int __init isp116x_probe(struct platform_device *pdev)
} }
ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
if (ret != 0) if (ret)
goto err6; goto err6;
create_debug_file(isp116x); ret = create_debug_file(isp116x);
if (ret) {
ERR("Couldn't create debugfs entry\n");
goto err7;
}
return 0; return 0;
err7:
usb_remove_hcd(hcd);
err6: err6:
usb_put_hcd(hcd); usb_put_hcd(hcd);
err5: err5:
@ -1772,13 +1691,9 @@ static int __init isp116x_probe(struct platform_device *pdev)
*/ */
static int isp116x_suspend(struct platform_device *dev, pm_message_t state) static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
{ {
int ret = 0; VDBG("%s: state %x\n", __func__, state.event);
VDBG("%s: state %x\n", __func__, state);
dev->dev.power.power_state = state; dev->dev.power.power_state = state;
return 0;
return ret;
} }
/* /*
@ -1786,13 +1701,9 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
*/ */
static int isp116x_resume(struct platform_device *dev) static int isp116x_resume(struct platform_device *dev)
{ {
int ret = 0; VDBG("%s: state %x\n", __func__, dev->power.power_state.event);
VDBG("%s: state %x\n", __func__, dev->dev.power.power_state);
dev->dev.power.power_state = PMSG_ON; dev->dev.power.power_state = PMSG_ON;
return 0;
return ret;
} }
#else #else

View File

@ -259,7 +259,7 @@ struct isp116x {
struct isp116x_platform_data *board; struct isp116x_platform_data *board;
struct proc_dir_entry *pde; struct dentry *dentry;
unsigned long stat1, stat2, stat4, stat8, stat16; unsigned long stat1, stat2, stat4, stat8, stat16;
/* HC registers */ /* HC registers */
@ -450,7 +450,7 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
isp116x_write_data32(isp116x, (u32) val); isp116x_write_data32(isp116x, (u32) val);
} }
#define isp116x_show_reg(d,r) { \ #define isp116x_show_reg_log(d,r,s) { \
if ((r) < 0x20) { \ if ((r) < 0x20) { \
DBG("%-12s[%02x]: %08x\n", #r, \ DBG("%-12s[%02x]: %08x\n", #r, \
r, isp116x_read_reg32(d, 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)); \ 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_reg(isp116x, HCREVISION); isp116x_show_regs(isp116x, seq, s);
isp116x_show_reg(isp116x, HCCONTROL); }
isp116x_show_reg(isp116x, HCCMDSTAT);
isp116x_show_reg(isp116x, HCINTSTAT); /*
isp116x_show_reg(isp116x, HCINTENB); Dump registers to syslog.
isp116x_show_reg(isp116x, HCFMINTVL); */
isp116x_show_reg(isp116x, HCFMREM); static inline void isp116x_show_regs_log(struct isp116x *isp116x)
isp116x_show_reg(isp116x, HCFMNUM); {
isp116x_show_reg(isp116x, HCLSTHRESH); isp116x_show_regs(isp116x, log, NULL);
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);
} }
#if defined(URB_TRACE) #if defined(URB_TRACE)