ChangeSet 1.1002.3.16, 2003/02/25 11:32:31-08:00, david-b@pacbell.net

[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.


 drivers/usb/host/ohci-dbg.c |  248 +++++++++++++++++++++++++++++++++-----------
 drivers/usb/host/ohci-hcd.c |   18 ++-
 drivers/usb/host/ohci-pci.c |    2 
 drivers/usb/host/ohci-q.c   |   21 +--
 4 files changed, 212 insertions(+), 77 deletions(-)


diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c	Fri Feb 28 14:50:17 2003
+++ b/drivers/usb/host/ohci-dbg.c	Fri Feb 28 14:50:17 2003
@@ -1,50 +1,50 @@
 /*
  * OHCI HCD (Host Controller Driver) for USB.
- * 
+ *
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
  * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * 
+ *
  * This file is licenced under the GPL.
  */
- 
+
 /*-------------------------------------------------------------------------*/
 
 #ifdef DEBUG
 
 #define edstring(ed_type) ({ char *temp; \
 	switch (ed_type) { \
-	case PIPE_CONTROL:	temp = "CTRL"; break; \
-	case PIPE_BULK:		temp = "BULK"; break; \
-	case PIPE_INTERRUPT:	temp = "INTR"; break; \
-	default: 		temp = "ISOC"; break; \
+	case PIPE_CONTROL:	temp = "ctrl"; break; \
+	case PIPE_BULK:		temp = "bulk"; break; \
+	case PIPE_INTERRUPT:	temp = "intr"; break; \
+	default: 		temp = "isoc"; break; \
 	}; temp;})
 #define pipestring(pipe) edstring(usb_pipetype(pipe))
 
-/* debug| print the main components of an URB     
+/* debug| print the main components of an URB
  * small: 0) header + data packets 1) just header
  */
 static void __attribute__((unused))
 urb_print (struct urb * urb, char * str, int small)
 {
 	unsigned int pipe= urb->pipe;
-	
+
 	if (!urb->dev || !urb->dev->bus) {
 		dbg("%s URB: no dev", str);
 		return;
 	}
-	
+
 #ifndef	OHCI_VERBOSE_DEBUG
 	if (urb->status != 0)
 #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,
 		    urb,
 		    usb_pipedevice (pipe),
-		    usb_pipeendpoint (pipe), 
-		    usb_pipeout (pipe)? 'O': 'I',
+		    usb_pipeendpoint (pipe),
+		    usb_pipeout (pipe)? "out" : "in",
 		    pipestring (pipe),
-		    urb->transfer_flags, 
-		    urb->actual_length, 
+		    urb->transfer_flags,
+		    urb->actual_length,
 		    urb->transfer_buffer_length,
 		    urb->status);
 
@@ -54,27 +54,43 @@
 
 		if (usb_pipecontrol (pipe)) {
 			printk (KERN_DEBUG __FILE__ ": setup(8):");
-			for (i = 0; i < 8 ; i++) 
+			for (i = 0; i < 8 ; i++)
 				printk (" %02x", ((__u8 *) urb->setup_packet) [i]);
 			printk ("\n");
 		}
 		if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
-			printk (KERN_DEBUG __FILE__ ": data(%d/%d):", 
-				urb->actual_length, 
+			printk (KERN_DEBUG __FILE__ ": data(%d/%d):",
+				urb->actual_length,
 				urb->transfer_buffer_length);
-			len = usb_pipeout (pipe)? 
+			len = usb_pipeout (pipe)?
 						urb->transfer_buffer_length: urb->actual_length;
-			for (i = 0; i < 16 && i < len; i++) 
+			for (i = 0; i < 16 && i < len; i++)
 				printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]);
 			printk ("%s stat:%d\n", i < len? "...": "", urb->status);
 		}
-	} 
+	}
 #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,
 		mask,
 		(mask & OHCI_INTR_MIE) ? " MIE" : "",
@@ -89,10 +105,15 @@
 		);
 }
 
-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)
-		ohci_dbg (ohci, "%s %08x\n", label, value);
+		ohci_dbg_sw (ohci, next, size, "%s %08x\n", label, value);
 }
 
 static char *hcfs2string (int state)
@@ -107,19 +128,22 @@
 }
 
 // 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;
-	__u32			temp;
+	u32			temp;
 
 	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),
 		(temp & 0x10) ? "with" : "NO");
 
 	temp = readl (&regs->control);
-	ohci_dbg (controller,
-		"control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", temp,
+	ohci_dbg_sw (controller, next, size,
+		"control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
+		temp,
 		(temp & OHCI_CTRL_RWE) ? " RWE" : "",
 		(temp & OHCI_CTRL_RWC) ? " RWC" : "",
 		(temp & OHCI_CTRL_IR) ? " IR" : "",
@@ -132,7 +156,8 @@
 		);
 
 	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_OCR) ? " OCR" : "",
 		(temp & OHCI_BLF) ? " BLF" : "",
@@ -140,24 +165,59 @@
 		(temp & OHCI_HCR) ? " HCR" : ""
 		);
 
-	ohci_dump_intr_mask (controller, "intrstatus", readl (&regs->intrstatus));
-	ohci_dump_intr_mask (controller, "intrenable", readl (&regs->intrenable));
+	ohci_dump_intr_mask (controller, "intrstatus",
+			readl (&regs->intrstatus), next, size);
+	ohci_dump_intr_mask (controller, "intrenable",
+			readl (&regs->intrenable), next, size);
 	// intrdisable always same as intrenable
 
-	maybe_print_eds (controller, "ed_periodcurrent", readl (&regs->ed_periodcurrent));
-
-	maybe_print_eds (controller, "ed_controlhead", readl (&regs->ed_controlhead));
-	maybe_print_eds (controller, "ed_controlcurrent", readl (&regs->ed_controlcurrent));
+	maybe_print_eds (controller, "ed_periodcurrent",
+			readl (&regs->ed_periodcurrent), next, size);
 
-	maybe_print_eds (controller, "ed_bulkhead", readl (&regs->ed_bulkhead));
-	maybe_print_eds (controller, "ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+	maybe_print_eds (controller, "ed_controlhead",
+			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), next, size);
+	maybe_print_eds (controller, "ed_bulkcurrent",
+			readl (&regs->ed_bulkcurrent), next, size);
+
+	maybe_print_eds (controller, "donehead",
+			readl (&regs->donehead), next, size);
+}
+
+#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" : "" \
+		);
 
-	maybe_print_eds (controller, "donehead", readl (&regs->donehead));
-}
 
-static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
+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);
 	if (temp == ~(u32)0)
@@ -165,8 +225,8 @@
 	ndp = (temp & RH_A_NDP);
 
 	if (verbose) {
-		ohci_dbg (controller,
-			"roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
+		ohci_dbg_sw (controller, next, size,
+			"roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
 			((temp & RH_A_POTPGT) >> 24) & 0xff,
 			(temp & RH_A_NOCP) ? " NOCP" : "",
 			(temp & RH_A_OCPM) ? " OCPM" : "",
@@ -176,15 +236,15 @@
 			ndp
 			);
 		temp = roothub_b (controller);
-		ohci_dbg (controller,
-			"roothub.b: %08x PPCM=%04x DR=%04x\n",
+		ohci_dbg_sw (controller, next, size,
+			"roothub.b %08x PPCM=%04x DR=%04x\n",
 			temp,
 			(temp & RH_B_PPCM) >> 16,
 			(temp & RH_B_DR)
 			);
 		temp = roothub_status (controller);
-		ohci_dbg (controller,
-			"roothub.status: %08x%s%s%s%s%s%s\n",
+		ohci_dbg_sw (controller, next, size,
+			"roothub.status %08x%s%s%s%s%s%s\n",
 			temp,
 			(temp & RH_HS_CRWE) ? " CRWE" : "",
 			(temp & RH_HS_OCIC) ? " OCIC" : "",
@@ -194,10 +254,10 @@
 			(temp & RH_HS_LPS) ? " LPS" : ""
 			);
 	}
-	
+
 	for (i = 0; i < ndp; i++) {
 		temp = roothub_portstatus (controller, i);
-		dbg_port (controller, "", i, temp);
+		dbg_port_sw (controller, i, temp, next, size);
 	}
 }
 
@@ -206,11 +266,11 @@
 	ohci_dbg (controller, "OHCI controller state\n");
 
 	// dumps some of the state we know about
-	ohci_dump_status (controller);
+	ohci_dump_status (controller, NULL, 0);
 	if (controller->hcca)
 		ohci_dbg (controller,
 			"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";
@@ -277,8 +337,7 @@
 	u32	tmp = ed->hwINFO;
 	char	*type = "";
 
-	ohci_dbg (ohci,
-		"%s, ed %p state 0x%x type %s; next ed %08x\n",
+	ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x",
 		label,
 		ed, ed->state, edstring (ed->type),
 		le32_to_cpup (&ed->hwNextED));
@@ -297,8 +356,7 @@
 		0x000f & (le32_to_cpu (tmp) >> 7),
 		type,
 		0x007f & le32_to_cpu (tmp));
-	ohci_dbg (ohci,
-		"  tds: head %08x %s%s tail %08x%s",
+	ohci_dbg (ohci, "  tds: head %08x %s%s tail %08x%s",
 		tmp = le32_to_cpup (&ed->hwHeadP),
 		(ed->hwHeadP & ED_C) ? data1 : data0,
 		(ed->hwHeadP & ED_H) ? " HALT" : "",
@@ -321,6 +379,8 @@
 #else
 static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {}
 
+#undef OHCI_VERBOSE_DEBUG
+
 #endif /* DEBUG */
 
 /*-------------------------------------------------------------------------*/
@@ -359,7 +419,7 @@
 		struct td		*td;
 
 		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,
 			(info & ED_LOWSPEED) ? 'l' : 'f',
 			scratch & 0x7f,
@@ -475,7 +535,7 @@
 				u32	scratch = cpu_to_le32p (&ed->hwINFO);
 
 				temp = snprintf (next, size,
-					" (%cs dev%d%s ep%d-%s"
+					" (%cs dev%d%s ep%d%s"
 					" max %d %08x%s%s)",
 					(info & ED_LOWSPEED) ? 'l' : 'f',
 					scratch & 0x7f,
@@ -518,11 +578,78 @@
 
 #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)
 {
 	device_create_file (bus->hcd.controller, &dev_attr_async);
 	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");
 }
 
@@ -530,6 +657,7 @@
 {
 	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_registers);
 }
 
 #endif
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	Fri Feb 28 14:50:17 2003
+++ b/drivers/usb/host/ohci-hcd.c	Fri Feb 28 14:50:17 2003
@@ -17,6 +17,8 @@
  *
  * History:
  * 
+ * 2003/02/24 show registers in sysfs (Kevin Brosius)
+ *
  * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
  * 	bandwidth accounting; if debugging, show schedules in driverfs
  * 2002/07/19 fixes to management of ED and schedule state.
@@ -105,11 +107,10 @@
  * TO DO:
  *
  *	- "disabled" and "sleeping" should be in hcd->state
- *	- bandwidth alloc to generic code
  *	- lots more testing!!
  */
 
-#define DRIVER_VERSION "2002-Sep-17"
+#define DRIVER_VERSION "2003 Feb 24"
 #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
 #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
 
@@ -277,6 +278,7 @@
 	urb_print (urb, "UNLINK", 1);
 #endif		  
 
+	spin_lock_irqsave (&ohci->lock, flags);
 	if (!ohci->disabled) {
 		urb_priv_t  *urb_priv;
 
@@ -284,21 +286,24 @@
 		 * handed to us, flag it for unlink and giveback, and force
 		 * some upcoming INTR_SF to call finish_unlinks()
 		 */
-		spin_lock_irqsave (&ohci->lock, flags);
 		urb_priv = urb->hcpriv;
 		if (urb_priv) {
 			urb_priv->state = URB_DEL; 
 			if (urb_priv->ed->state == ED_OPER)
 				start_urb_unlink (ohci, urb_priv->ed);
 		}
-		spin_unlock_irqrestore (&ohci->lock, flags);
 	} else {
 		/*
 		 * with HC dead, we won't respect hc queue pointers
 		 * any more ... just clean up every urb's memory.
 		 */
-		finish_urb (ohci, urb, NULL);
+		if (urb->hcpriv) {
+			spin_unlock (&ohci->lock);
+			finish_urb (ohci, urb, NULL);
+			spin_lock (&ohci->lock);
+		}
 	}
+	spin_unlock_irqrestore (&ohci->lock, flags);
 	return 0;
 }
 
@@ -598,7 +603,8 @@
 	 */
 	spin_lock (&ohci->lock);
 	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)
 		writel (OHCI_INTR_SF, &regs->intrdisable);	
 	spin_unlock (&ohci->lock);
diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
--- a/drivers/usb/host/ohci-pci.c	Fri Feb 28 14:50:17 2003
+++ b/drivers/usb/host/ohci-pci.c	Fri Feb 28 14:50:17 2003
@@ -214,7 +214,7 @@
 
 #ifdef DEBUG
 	/* the registers may look crazy here */
-	ohci_dump_status (ohci);
+	ohci_dump_status (ohci, 0, 0);
 #endif
 
 	/* Re-enable bus mastering */
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Fri Feb 28 14:50:17 2003
+++ b/drivers/usb/host/ohci-q.c	Fri Feb 28 14:50:17 2003
@@ -30,21 +30,20 @@
 /*
  * URB goes back to driver, and isn't reissued.
  * 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);
 
 	urb_free_priv (ohci, urb->hcpriv);
 	urb->hcpriv = NULL;
 
-	spin_lock_irqsave (&urb->lock, flags);
+	spin_lock (&urb->lock);
 	if (likely (urb->status == -EINPROGRESS))
 		urb->status = 0;
-	spin_unlock_irqrestore (&urb->lock, flags);
+	spin_unlock (&urb->lock);
 
 	// what lock protects these?
 	switch (usb_pipetype (urb->pipe)) {
@@ -850,7 +849,8 @@
 #define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
 
 /* 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;
 
@@ -978,7 +978,8 @@
  * path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of
  * 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;
 
@@ -995,9 +996,9 @@
 
 		/* If all this urb's TDs are done, call complete() */
   		if (urb_priv->td_cnt == urb_priv->length) {
-     			spin_unlock_irqrestore (&ohci->lock, flags);
+     			spin_unlock (&ohci->lock);
   			finish_urb (ohci, urb, regs);
-  			spin_lock_irqsave (&ohci->lock, flags);
+  			spin_lock (&ohci->lock);
   		}
 
 		/* clean schedule:  unlink EDs that are no longer busy */