Commit 328a5259 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB ohci: "registers" sysfs file

This is a slightly cleaned up version of Kevin's patch to
add a "registers" sysfs debug file.  Minor style and whitespace
fixups, prints the other register, resolved config/build
issues (minor).

It also has two minor tweaks: a fix for a potential assertion
violation on a "dead-hc" cleanup path (rare), and wasting less
time blocking irqs when they're already blocked.
parent 72344df4
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
#define edstring(ed_type) ({ char *temp; \ #define edstring(ed_type) ({ char *temp; \
switch (ed_type) { \ switch (ed_type) { \
case PIPE_CONTROL: temp = "CTRL"; break; \ case PIPE_CONTROL: temp = "ctrl"; break; \
case PIPE_BULK: temp = "BULK"; break; \ case PIPE_BULK: temp = "bulk"; break; \
case PIPE_INTERRUPT: temp = "INTR"; break; \ case PIPE_INTERRUPT: temp = "intr"; break; \
default: temp = "ISOC"; break; \ default: temp = "isoc"; break; \
}; temp;}) }; temp;})
#define pipestring(pipe) edstring(usb_pipetype(pipe)) #define pipestring(pipe) edstring(usb_pipetype(pipe))
...@@ -36,12 +36,12 @@ urb_print (struct urb * urb, char * str, int small) ...@@ -36,12 +36,12 @@ urb_print (struct urb * urb, char * str, int small)
#ifndef OHCI_VERBOSE_DEBUG #ifndef OHCI_VERBOSE_DEBUG
if (urb->status != 0) if (urb->status != 0)
#endif #endif
dbg("%s %p dev:%d,ep=%d-%c,%s,flags:%x,len:%d/%d,stat:%d", dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d",
str, str,
urb, urb,
usb_pipedevice (pipe), usb_pipedevice (pipe),
usb_pipeendpoint (pipe), usb_pipeendpoint (pipe),
usb_pipeout (pipe)? 'O': 'I', usb_pipeout (pipe)? "out" : "in",
pipestring (pipe), pipestring (pipe),
urb->transfer_flags, urb->transfer_flags,
urb->actual_length, urb->actual_length,
...@@ -72,9 +72,25 @@ urb_print (struct urb * urb, char * str, int small) ...@@ -72,9 +72,25 @@ urb_print (struct urb * urb, char * str, int small)
#endif #endif
} }
static void ohci_dump_intr_mask (struct ohci_hcd *ohci, char *label, __u32 mask) #define ohci_dbg_sw(ohci, next, size, format, arg...) \
do { \
if (next) { \
unsigned s_len; \
s_len = snprintf (*next, *size, format, ## arg ); \
*size -= s_len; *next += s_len; \
} else \
ohci_dbg(ohci,format, ## arg ); \
} while (0);
static void ohci_dump_intr_mask (
struct ohci_hcd *ohci,
char *label,
u32 mask,
char **next,
unsigned *size)
{ {
ohci_dbg (ohci, "%s: 0x%08x%s%s%s%s%s%s%s%s%s\n", ohci_dbg_sw (ohci, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s\n",
label, label,
mask, mask,
(mask & OHCI_INTR_MIE) ? " MIE" : "", (mask & OHCI_INTR_MIE) ? " MIE" : "",
...@@ -89,10 +105,15 @@ static void ohci_dump_intr_mask (struct ohci_hcd *ohci, char *label, __u32 mask) ...@@ -89,10 +105,15 @@ static void ohci_dump_intr_mask (struct ohci_hcd *ohci, char *label, __u32 mask)
); );
} }
static void maybe_print_eds (struct ohci_hcd *ohci, char *label, __u32 value) static void maybe_print_eds (
struct ohci_hcd *ohci,
char *label,
u32 value,
char **next,
unsigned *size)
{ {
if (value) if (value)
ohci_dbg (ohci, "%s %08x\n", label, value); ohci_dbg_sw (ohci, next, size, "%s %08x\n", label, value);
} }
static char *hcfs2string (int state) static char *hcfs2string (int state)
...@@ -107,19 +128,22 @@ static char *hcfs2string (int state) ...@@ -107,19 +128,22 @@ static char *hcfs2string (int state)
} }
// dump control and status registers // dump control and status registers
static void ohci_dump_status (struct ohci_hcd *controller) static void
ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
{ {
struct ohci_regs *regs = controller->regs; struct ohci_regs *regs = controller->regs;
__u32 temp; u32 temp;
temp = readl (&regs->revision) & 0xff; temp = readl (&regs->revision) & 0xff;
ohci_dbg (controller, "OHCI %d.%d, %s legacy support registers\n", ohci_dbg_sw (controller, next, size,
"OHCI %d.%d, %s legacy support registers\n",
0x03 & (temp >> 4), (temp & 0x0f), 0x03 & (temp >> 4), (temp & 0x0f),
(temp & 0x10) ? "with" : "NO"); (temp & 0x10) ? "with" : "NO");
temp = readl (&regs->control); temp = readl (&regs->control);
ohci_dbg (controller, ohci_dbg_sw (controller, next, size,
"control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", temp, "control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
temp,
(temp & OHCI_CTRL_RWE) ? " RWE" : "", (temp & OHCI_CTRL_RWE) ? " RWE" : "",
(temp & OHCI_CTRL_RWC) ? " RWC" : "", (temp & OHCI_CTRL_RWC) ? " RWC" : "",
(temp & OHCI_CTRL_IR) ? " IR" : "", (temp & OHCI_CTRL_IR) ? " IR" : "",
...@@ -132,7 +156,8 @@ static void ohci_dump_status (struct ohci_hcd *controller) ...@@ -132,7 +156,8 @@ static void ohci_dump_status (struct ohci_hcd *controller)
); );
temp = readl (&regs->cmdstatus); temp = readl (&regs->cmdstatus);
ohci_dbg (controller, "cmdstatus: 0x%08x SOC=%d%s%s%s%s\n", temp, ohci_dbg_sw (controller, next, size,
"cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
(temp & OHCI_SOC) >> 16, (temp & OHCI_SOC) >> 16,
(temp & OHCI_OCR) ? " OCR" : "", (temp & OHCI_OCR) ? " OCR" : "",
(temp & OHCI_BLF) ? " BLF" : "", (temp & OHCI_BLF) ? " BLF" : "",
...@@ -140,24 +165,59 @@ static void ohci_dump_status (struct ohci_hcd *controller) ...@@ -140,24 +165,59 @@ static void ohci_dump_status (struct ohci_hcd *controller)
(temp & OHCI_HCR) ? " HCR" : "" (temp & OHCI_HCR) ? " HCR" : ""
); );
ohci_dump_intr_mask (controller, "intrstatus", readl (&regs->intrstatus)); ohci_dump_intr_mask (controller, "intrstatus",
ohci_dump_intr_mask (controller, "intrenable", readl (&regs->intrenable)); readl (&regs->intrstatus), next, size);
ohci_dump_intr_mask (controller, "intrenable",
readl (&regs->intrenable), next, size);
// intrdisable always same as intrenable // intrdisable always same as intrenable
maybe_print_eds (controller, "ed_periodcurrent", readl (&regs->ed_periodcurrent)); maybe_print_eds (controller, "ed_periodcurrent",
readl (&regs->ed_periodcurrent), next, size);
maybe_print_eds (controller, "ed_controlhead", readl (&regs->ed_controlhead)); maybe_print_eds (controller, "ed_controlhead",
maybe_print_eds (controller, "ed_controlcurrent", readl (&regs->ed_controlcurrent)); readl (&regs->ed_controlhead), next, size);
maybe_print_eds (controller, "ed_controlcurrent",
readl (&regs->ed_controlcurrent), next, size);
maybe_print_eds (controller, "ed_bulkhead", readl (&regs->ed_bulkhead)); maybe_print_eds (controller, "ed_bulkhead",
maybe_print_eds (controller, "ed_bulkcurrent", readl (&regs->ed_bulkcurrent)); readl (&regs->ed_bulkhead), next, size);
maybe_print_eds (controller, "ed_bulkcurrent",
readl (&regs->ed_bulkcurrent), next, size);
maybe_print_eds (controller, "donehead", readl (&regs->donehead)); maybe_print_eds (controller, "donehead",
readl (&regs->donehead), next, size);
} }
static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) #define dbg_port_sw(hc,num,value,next,size) \
ohci_dbg_sw (hc, next, size, \
"roothub.portstatus [%d] " \
"0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
num, temp, \
(temp & RH_PS_PRSC) ? " PRSC" : "", \
(temp & RH_PS_OCIC) ? " OCIC" : "", \
(temp & RH_PS_PSSC) ? " PSSC" : "", \
(temp & RH_PS_PESC) ? " PESC" : "", \
(temp & RH_PS_CSC) ? " CSC" : "", \
\
(temp & RH_PS_LSDA) ? " LSDA" : "", \
(temp & RH_PS_PPS) ? " PPS" : "", \
(temp & RH_PS_PRS) ? " PRS" : "", \
(temp & RH_PS_POCI) ? " POCI" : "", \
(temp & RH_PS_PSS) ? " PSS" : "", \
\
(temp & RH_PS_PES) ? " PES" : "", \
(temp & RH_PS_CCS) ? " CCS" : "" \
);
static void
ohci_dump_roothub (
struct ohci_hcd *controller,
int verbose,
char **next,
unsigned *size)
{ {
__u32 temp, ndp, i; u32 temp, ndp, i;
temp = roothub_a (controller); temp = roothub_a (controller);
if (temp == ~(u32)0) if (temp == ~(u32)0)
...@@ -165,8 +225,8 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) ...@@ -165,8 +225,8 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
ndp = (temp & RH_A_NDP); ndp = (temp & RH_A_NDP);
if (verbose) { if (verbose) {
ohci_dbg (controller, ohci_dbg_sw (controller, next, size,
"roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp, "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
((temp & RH_A_POTPGT) >> 24) & 0xff, ((temp & RH_A_POTPGT) >> 24) & 0xff,
(temp & RH_A_NOCP) ? " NOCP" : "", (temp & RH_A_NOCP) ? " NOCP" : "",
(temp & RH_A_OCPM) ? " OCPM" : "", (temp & RH_A_OCPM) ? " OCPM" : "",
...@@ -176,15 +236,15 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) ...@@ -176,15 +236,15 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
ndp ndp
); );
temp = roothub_b (controller); temp = roothub_b (controller);
ohci_dbg (controller, ohci_dbg_sw (controller, next, size,
"roothub.b: %08x PPCM=%04x DR=%04x\n", "roothub.b %08x PPCM=%04x DR=%04x\n",
temp, temp,
(temp & RH_B_PPCM) >> 16, (temp & RH_B_PPCM) >> 16,
(temp & RH_B_DR) (temp & RH_B_DR)
); );
temp = roothub_status (controller); temp = roothub_status (controller);
ohci_dbg (controller, ohci_dbg_sw (controller, next, size,
"roothub.status: %08x%s%s%s%s%s%s\n", "roothub.status %08x%s%s%s%s%s%s\n",
temp, temp,
(temp & RH_HS_CRWE) ? " CRWE" : "", (temp & RH_HS_CRWE) ? " CRWE" : "",
(temp & RH_HS_OCIC) ? " OCIC" : "", (temp & RH_HS_OCIC) ? " OCIC" : "",
...@@ -197,7 +257,7 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) ...@@ -197,7 +257,7 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
for (i = 0; i < ndp; i++) { for (i = 0; i < ndp; i++) {
temp = roothub_portstatus (controller, i); temp = roothub_portstatus (controller, i);
dbg_port (controller, "", i, temp); dbg_port_sw (controller, i, temp, next, size);
} }
} }
...@@ -206,11 +266,11 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose) ...@@ -206,11 +266,11 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose)
ohci_dbg (controller, "OHCI controller state\n"); ohci_dbg (controller, "OHCI controller state\n");
// dumps some of the state we know about // dumps some of the state we know about
ohci_dump_status (controller); ohci_dump_status (controller, NULL, 0);
if (controller->hcca) if (controller->hcca)
ohci_dbg (controller, ohci_dbg (controller,
"hcca frame #%04x\n", controller->hcca->frame_no); "hcca frame #%04x\n", controller->hcca->frame_no);
ohci_dump_roothub (controller, 1); ohci_dump_roothub (controller, 1, NULL, 0);
} }
static const char data0 [] = "DATA0"; static const char data0 [] = "DATA0";
...@@ -277,8 +337,7 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) ...@@ -277,8 +337,7 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
u32 tmp = ed->hwINFO; u32 tmp = ed->hwINFO;
char *type = ""; char *type = "";
ohci_dbg (ohci, ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x",
"%s, ed %p state 0x%x type %s; next ed %08x\n",
label, label,
ed, ed->state, edstring (ed->type), ed, ed->state, edstring (ed->type),
le32_to_cpup (&ed->hwNextED)); le32_to_cpup (&ed->hwNextED));
...@@ -297,8 +356,7 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) ...@@ -297,8 +356,7 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
0x000f & (le32_to_cpu (tmp) >> 7), 0x000f & (le32_to_cpu (tmp) >> 7),
type, type,
0x007f & le32_to_cpu (tmp)); 0x007f & le32_to_cpu (tmp));
ohci_dbg (ohci, ohci_dbg (ohci, " tds: head %08x %s%s tail %08x%s",
" tds: head %08x %s%s tail %08x%s",
tmp = le32_to_cpup (&ed->hwHeadP), tmp = le32_to_cpup (&ed->hwHeadP),
(ed->hwHeadP & ED_C) ? data1 : data0, (ed->hwHeadP & ED_C) ? data1 : data0,
(ed->hwHeadP & ED_H) ? " HALT" : "", (ed->hwHeadP & ED_H) ? " HALT" : "",
...@@ -321,6 +379,8 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) ...@@ -321,6 +379,8 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
#else #else
static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {} static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {}
#undef OHCI_VERBOSE_DEBUG
#endif /* DEBUG */ #endif /* DEBUG */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -359,7 +419,7 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) ...@@ -359,7 +419,7 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
struct td *td; struct td *td;
temp = snprintf (buf, size, temp = snprintf (buf, size,
"ed/%p %cs dev%d ep%d-%s max %d %08x%s%s %s", "ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s",
ed, ed,
(info & ED_LOWSPEED) ? 'l' : 'f', (info & ED_LOWSPEED) ? 'l' : 'f',
scratch & 0x7f, scratch & 0x7f,
...@@ -475,7 +535,7 @@ show_periodic (struct device *dev, char *buf) ...@@ -475,7 +535,7 @@ show_periodic (struct device *dev, char *buf)
u32 scratch = cpu_to_le32p (&ed->hwINFO); u32 scratch = cpu_to_le32p (&ed->hwINFO);
temp = snprintf (next, size, temp = snprintf (next, size,
" (%cs dev%d%s ep%d-%s" " (%cs dev%d%s ep%d%s"
" max %d %08x%s%s)", " max %d %08x%s%s)",
(info & ED_LOWSPEED) ? 'l' : 'f', (info & ED_LOWSPEED) ? 'l' : 'f',
scratch & 0x7f, scratch & 0x7f,
...@@ -518,11 +578,78 @@ static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); ...@@ -518,11 +578,78 @@ static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
#undef DBG_SCHED_LIMIT #undef DBG_SCHED_LIMIT
static ssize_t
show_registers (struct device *dev, char *buf)
{
struct ohci_hcd *ohci;
struct ohci_regs *regs;
unsigned long flags;
unsigned temp, size;
char *next;
u32 rdata;
ohci = dev_to_ohci(dev);
regs = ohci->regs;
next = buf;
size = PAGE_SIZE;
spin_lock_irqsave (&ohci->lock, flags);
/* dump driver info, then registers in spec order */
ohci_dbg_sw (ohci, &next, &size,
"%s version " DRIVER_VERSION "\n", hcd_name);
ohci_dump_status(ohci, &next, &size);
/* hcca */
if (ohci->hcca)
ohci_dbg_sw (ohci, &next, &size,
"hcca frame 0x%04x\n", ohci->hcca->frame_no);
/* other registers mostly affect frame timings */
rdata = readl (&regs->fminterval);
temp = snprintf (next, size,
"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
rdata, (rdata >> 31) ? " FIT" : "",
(rdata >> 16) & 0xefff, rdata & 0xffff);
size -= temp;
next += temp;
rdata = readl (&regs->fmremaining);
temp = snprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
rdata, (rdata >> 31) ? " FRT" : "",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = readl (&regs->periodicstart);
temp = snprintf (next, size, "periodicstart 0x%04x\n",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = readl (&regs->lsthresh);
temp = snprintf (next, size, "lsthresh 0x%04x\n",
rdata & 0x3fff);
size -= temp;
next += temp;
/* roothub */
ohci_dump_roothub (ohci, 1, &next, &size);
spin_unlock_irqrestore (&ohci->lock, flags);
return PAGE_SIZE - size;
}
static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
static inline void create_debug_files (struct ohci_hcd *bus) static inline void create_debug_files (struct ohci_hcd *bus)
{ {
device_create_file (bus->hcd.controller, &dev_attr_async); device_create_file (bus->hcd.controller, &dev_attr_async);
device_create_file (bus->hcd.controller, &dev_attr_periodic); device_create_file (bus->hcd.controller, &dev_attr_periodic);
// registers device_create_file (bus->hcd.controller, &dev_attr_registers);
ohci_dbg (bus, "created debug files\n"); ohci_dbg (bus, "created debug files\n");
} }
...@@ -530,6 +657,7 @@ static inline void remove_debug_files (struct ohci_hcd *bus) ...@@ -530,6 +657,7 @@ static inline void remove_debug_files (struct ohci_hcd *bus)
{ {
device_remove_file (bus->hcd.controller, &dev_attr_async); device_remove_file (bus->hcd.controller, &dev_attr_async);
device_remove_file (bus->hcd.controller, &dev_attr_periodic); device_remove_file (bus->hcd.controller, &dev_attr_periodic);
device_remove_file (bus->hcd.controller, &dev_attr_registers);
} }
#endif #endif
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
* *
* History: * History:
* *
* 2003/02/24 show registers in sysfs (Kevin Brosius)
*
* 2002/09/03 get rid of ed hashtables, rework periodic scheduling and * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
* bandwidth accounting; if debugging, show schedules in driverfs * bandwidth accounting; if debugging, show schedules in driverfs
* 2002/07/19 fixes to management of ED and schedule state. * 2002/07/19 fixes to management of ED and schedule state.
...@@ -105,11 +107,10 @@ ...@@ -105,11 +107,10 @@
* TO DO: * TO DO:
* *
* - "disabled" and "sleeping" should be in hcd->state * - "disabled" and "sleeping" should be in hcd->state
* - bandwidth alloc to generic code
* - lots more testing!! * - lots more testing!!
*/ */
#define DRIVER_VERSION "2002-Sep-17" #define DRIVER_VERSION "2003 Feb 24"
#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
...@@ -277,6 +278,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -277,6 +278,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
urb_print (urb, "UNLINK", 1); urb_print (urb, "UNLINK", 1);
#endif #endif
spin_lock_irqsave (&ohci->lock, flags);
if (!ohci->disabled) { if (!ohci->disabled) {
urb_priv_t *urb_priv; urb_priv_t *urb_priv;
...@@ -284,21 +286,24 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -284,21 +286,24 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
* handed to us, flag it for unlink and giveback, and force * handed to us, flag it for unlink and giveback, and force
* some upcoming INTR_SF to call finish_unlinks() * some upcoming INTR_SF to call finish_unlinks()
*/ */
spin_lock_irqsave (&ohci->lock, flags);
urb_priv = urb->hcpriv; urb_priv = urb->hcpriv;
if (urb_priv) { if (urb_priv) {
urb_priv->state = URB_DEL; urb_priv->state = URB_DEL;
if (urb_priv->ed->state == ED_OPER) if (urb_priv->ed->state == ED_OPER)
start_urb_unlink (ohci, urb_priv->ed); start_urb_unlink (ohci, urb_priv->ed);
} }
spin_unlock_irqrestore (&ohci->lock, flags);
} else { } else {
/* /*
* with HC dead, we won't respect hc queue pointers * with HC dead, we won't respect hc queue pointers
* any more ... just clean up every urb's memory. * any more ... just clean up every urb's memory.
*/ */
if (urb->hcpriv) {
spin_unlock (&ohci->lock);
finish_urb (ohci, urb, NULL); finish_urb (ohci, urb, NULL);
spin_lock (&ohci->lock);
} }
}
spin_unlock_irqrestore (&ohci->lock, flags);
return 0; return 0;
} }
...@@ -598,7 +603,8 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -598,7 +603,8 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
*/ */
spin_lock (&ohci->lock); spin_lock (&ohci->lock);
if (ohci->ed_rm_list) if (ohci->ed_rm_list)
finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no), ptregs); finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no),
ptregs);
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list) if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list)
writel (OHCI_INTR_SF, &regs->intrdisable); writel (OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock); spin_unlock (&ohci->lock);
......
...@@ -214,7 +214,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd) ...@@ -214,7 +214,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
#ifdef DEBUG #ifdef DEBUG
/* the registers may look crazy here */ /* the registers may look crazy here */
ohci_dump_status (ohci); ohci_dump_status (ohci, 0, 0);
#endif #endif
/* Re-enable bus mastering */ /* Re-enable bus mastering */
......
...@@ -30,21 +30,20 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv) ...@@ -30,21 +30,20 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
/* /*
* URB goes back to driver, and isn't reissued. * URB goes back to driver, and isn't reissued.
* It's completely gone from HC data structures. * It's completely gone from HC data structures.
* PRECONDITION: no locks held (Giveback can call into HCD.) * PRECONDITION: no locks held, irqs blocked (Giveback can call into HCD.)
*/ */
static void finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs) static void
finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs)
{ {
unsigned long flags;
// ASSERT (urb->hcpriv != 0); // ASSERT (urb->hcpriv != 0);
urb_free_priv (ohci, urb->hcpriv); urb_free_priv (ohci, urb->hcpriv);
urb->hcpriv = NULL; urb->hcpriv = NULL;
spin_lock_irqsave (&urb->lock, flags); spin_lock (&urb->lock);
if (likely (urb->status == -EINPROGRESS)) if (likely (urb->status == -EINPROGRESS))
urb->status = 0; urb->status = 0;
spin_unlock_irqrestore (&urb->lock, flags); spin_unlock (&urb->lock);
// what lock protects these? // what lock protects these?
switch (usb_pipetype (urb->pipe)) { switch (usb_pipetype (urb->pipe)) {
...@@ -850,7 +849,8 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) ...@@ -850,7 +849,8 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0) #define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */ /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
static void finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) static void
finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
{ {
struct ed *ed, **last; struct ed *ed, **last;
...@@ -978,7 +978,8 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *reg ...@@ -978,7 +978,8 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *reg
* path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of * path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of
* scanning the (re-reversed) donelist as this does. * scanning the (re-reversed) donelist as this does.
*/ */
static void dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *regs) static void
dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *regs)
{ {
unsigned long flags; unsigned long flags;
...@@ -995,9 +996,9 @@ static void dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs * ...@@ -995,9 +996,9 @@ static void dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *
/* If all this urb's TDs are done, call complete() */ /* If all this urb's TDs are done, call complete() */
if (urb_priv->td_cnt == urb_priv->length) { if (urb_priv->td_cnt == urb_priv->length) {
spin_unlock_irqrestore (&ohci->lock, flags); spin_unlock (&ohci->lock);
finish_urb (ohci, urb, regs); finish_urb (ohci, urb, regs);
spin_lock_irqsave (&ohci->lock, flags); spin_lock (&ohci->lock);
} }
/* clean schedule: unlink EDs that are no longer busy */ /* clean schedule: unlink EDs that are no longer busy */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment