public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* USBDEVFS_RESET deadlocks USB bus.
@ 2004-06-04 19:39 Zephaniah E. Hull
  2004-06-04 19:52 ` Greg KH
  0 siblings, 1 reply; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-06-04 19:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: Greg KH, David A. Desrosiers

[-- Attachment #1: Type: text/plain, Size: 898 bytes --]

Starting at 2.6.7-rc1 or so (that is when we first noticed it) the new
pilot-link libusb back end started deadlocking the entire USB bus that
the palm device was on.

I have finally tracked it down to happening when we make the
USBDEVFS_RESET ioctl, we never return from it and from that point on the
bus in question is completely dead, no processing is done, no
notifications of devices being plugged in or unplugged.

This is still happening in 2.6.7-rc2-mm1.

It seems to happen with both the UHCI and OHCI back ends, so it is
probably above that.

Given that there were heavy locking changes, I suspect that the case in
question got screwed up somehow.

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

Perl == Being
  -- Descartes (paraphrased).

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-04 19:39 USBDEVFS_RESET deadlocks USB bus Zephaniah E. Hull
@ 2004-06-04 19:52 ` Greg KH
  2004-06-04 20:02   ` Zephaniah E. Hull
  0 siblings, 1 reply; 22+ messages in thread
From: Greg KH @ 2004-06-04 19:52 UTC (permalink / raw)
  To: linux-kernel, David A. Desrosiers; +Cc: linux-usb-devel

On Fri, Jun 04, 2004 at 03:39:11PM -0400, Zephaniah E. Hull wrote:
> Starting at 2.6.7-rc1 or so (that is when we first noticed it) the new
> pilot-link libusb back end started deadlocking the entire USB bus that
> the palm device was on.
> 
> I have finally tracked it down to happening when we make the
> USBDEVFS_RESET ioctl, we never return from it and from that point on the
> bus in question is completely dead, no processing is done, no
> notifications of devices being plugged in or unplugged.
> 
> This is still happening in 2.6.7-rc2-mm1.
> 
> It seems to happen with both the UHCI and OHCI back ends, so it is
> probably above that.
> 
> Given that there were heavy locking changes, I suspect that the case in
> question got screwed up somehow.

This needs to go to the linux-usb-devel list, now CC:

Anyway, can you look at the output of SysRq-T and see where the
processes are hung?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-04 19:52 ` Greg KH
@ 2004-06-04 20:02   ` Zephaniah E. Hull
  2004-06-04 20:05     ` Zephaniah E. Hull
                       ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-06-04 20:02 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, David A. Desrosiers, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 2055 bytes --]

On Fri, Jun 04, 2004 at 12:52:47PM -0700, Greg KH wrote:
> On Fri, Jun 04, 2004 at 03:39:11PM -0400, Zephaniah E. Hull wrote:
> > Starting at 2.6.7-rc1 or so (that is when we first noticed it) the new
> > pilot-link libusb back end started deadlocking the entire USB bus that
> > the palm device was on.
> > 
> > I have finally tracked it down to happening when we make the
> > USBDEVFS_RESET ioctl, we never return from it and from that point on the
> > bus in question is completely dead, no processing is done, no
> > notifications of devices being plugged in or unplugged.
> > 
> > This is still happening in 2.6.7-rc2-mm1.
> > 
> > It seems to happen with both the UHCI and OHCI back ends, so it is
> > probably above that.
> > 
> > Given that there were heavy locking changes, I suspect that the case in
> > question got screwed up somehow.
> 
> This needs to go to the linux-usb-devel list, now CC:

Whoops.
> 
> Anyway, can you look at the output of SysRq-T and see where the
> processes are hung?

lt-pilot-xfer D 00000000     0 11415   2709                     (NOTLB)
d2ad3eb0 00000086 c022391a 00000000 3231203a 000a2e35 00000001 d2ad3ea7
       d4edd000 d7fc8a00 c8449790 00000000 abb31900 000f447a c4bae4b8 c977d824
       00000246 d2ad2000 d2ad3eec c0336735 c977d82c c4bae310 00000001 c4bae310
Call Trace:
 [<c0336735>] __down+0x85/0x120
 [<c033692f>] __down_failed+0xb/0x14
 [<c026af27>] .text.lock.hub+0x69/0x82
 [<c0272b7f>] usbdev_ioctl+0x19f/0x710
 [<c015a45d>] file_ioctl+0x5d/0x170
 [<c015a686>] sys_ioctl+0x116/0x250
 [<c0103f8f>] syscall_call+0x7/0xb

This is on 2.6.7-rc2-mm1.

Please keep me in the reply list if we are pulled off of linux-kernel,
as I am not currently on linux-usb-devel.

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

<cas> well there ya go.  say something stupid in irc and have it
      immortalised forever in someone's .sig file

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-04 20:02   ` Zephaniah E. Hull
@ 2004-06-04 20:05     ` Zephaniah E. Hull
  2004-06-04 20:07     ` Greg KH
  2004-06-04 20:40     ` [linux-usb-devel] " Duncan Sands
  2 siblings, 0 replies; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-06-04 20:05 UTC (permalink / raw)
  To: Greg KH, linux-kernel, David A. Desrosiers, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 1493 bytes --]

On Fri, Jun 04, 2004 at 04:02:11PM -0400, Zephaniah E. Hull wrote:
> On Fri, Jun 04, 2004 at 12:52:47PM -0700, Greg KH wrote:
> > On Fri, Jun 04, 2004 at 03:39:11PM -0400, Zephaniah E. Hull wrote:
> > > Starting at 2.6.7-rc1 or so (that is when we first noticed it) the new
> > > pilot-link libusb back end started deadlocking the entire USB bus that
> > > the palm device was on.
> > > 
> > > I have finally tracked it down to happening when we make the
> > > USBDEVFS_RESET ioctl, we never return from it and from that point on the
> > > bus in question is completely dead, no processing is done, no
> > > notifications of devices being plugged in or unplugged.
> > > 
> > > This is still happening in 2.6.7-rc2-mm1.
> > > 
> > > It seems to happen with both the UHCI and OHCI back ends, so it is
> > > probably above that.
> > > 
> > > Given that there were heavy locking changes, I suspect that the case in
> > > question got screwed up somehow.

Further details, existing links with devices remain functional (IE, the
HID layer continues to get data from already connected mice), however
all processing or new devices or removed devices seems to be just gone,
on all USB busses.

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

"And now, little kittens, we're going to run across red-hot
motherboards, with our bare feet." -- Buzh.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-04 20:02   ` Zephaniah E. Hull
  2004-06-04 20:05     ` Zephaniah E. Hull
@ 2004-06-04 20:07     ` Greg KH
  2004-06-04 20:28       ` David A. Desrosiers
  2004-06-04 21:06       ` Zephaniah E. Hull
  2004-06-04 20:40     ` [linux-usb-devel] " Duncan Sands
  2 siblings, 2 replies; 22+ messages in thread
From: Greg KH @ 2004-06-04 20:07 UTC (permalink / raw)
  To: linux-kernel, David A. Desrosiers, linux-usb-devel

On Fri, Jun 04, 2004 at 04:02:11PM -0400, Zephaniah E. Hull wrote:
> 
> lt-pilot-xfer D 00000000     0 11415   2709                     (NOTLB)
> d2ad3eb0 00000086 c022391a 00000000 3231203a 000a2e35 00000001 d2ad3ea7
>        d4edd000 d7fc8a00 c8449790 00000000 abb31900 000f447a c4bae4b8 c977d824
>        00000246 d2ad2000 d2ad3eec c0336735 c977d82c c4bae310 00000001 c4bae310
> Call Trace:
>  [<c0336735>] __down+0x85/0x120
>  [<c033692f>] __down_failed+0xb/0x14
>  [<c026af27>] .text.lock.hub+0x69/0x82
>  [<c0272b7f>] usbdev_ioctl+0x19f/0x710
>  [<c015a45d>] file_ioctl+0x5d/0x170
>  [<c015a686>] sys_ioctl+0x116/0x250
>  [<c0103f8f>] syscall_call+0x7/0xb
> 
> This is on 2.6.7-rc2-mm1.

Ah, can you not try the -mm1 kernel?  This problem should not be in the
mainline kernel.  There was a locking issue in the last bk-usb patch
that made it into the -mm1 kernel that was fixed yesterday.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-04 20:07     ` Greg KH
@ 2004-06-04 20:28       ` David A. Desrosiers
  2004-06-04 21:06       ` Zephaniah E. Hull
  1 sibling, 0 replies; 22+ messages in thread
From: David A. Desrosiers @ 2004-06-04 20:28 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, linux-usb-devel


> Ah, can you not try the -mm1 kernel?  This problem should not be in the
> mainline kernel.  There was a locking issue in the last bk-usb patch that
> made it into the -mm1 kernel that was fixed yesterday.

	I can confirm that the last kernel this worked with was 2.6.6. We
can't get libusb working at all in 2.4 for the device detection (as you
know). I've now tried everything from 2.6.6 up to 2.6.7-rc2-mm2, including
all "official" (non-akpm) kernels in-between. Same issue.

	What I see in the logs, which may be of use, is:

May 31 21:38:08 wrath kernel: uhci_hcd 0000:00:1d.1: suspend_hc
May 31 21:38:08 wrath kernel: uhci_hcd 0000:00:1d.1: wakeup_hc
May 31 21:38:11 wrath kernel: uhci_hcd 0000:00:1d.1: suspend_hc
May 31 21:38:11 wrath kernel: uhci_hcd 0000:00:1d.1: wakeup_hc
May 31 21:38:13 wrath kernel: uhci_hcd 0000:00:1d.1: suspend_hc
May 31 21:38:13 wrath kernel: uhci_hcd 0000:00:1d.1: wakeup_hc

	..over and over and over, taking the system load gradually up, until
it no longer responds, and has to be rebooted forcibly.

d.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-04 20:02   ` Zephaniah E. Hull
  2004-06-04 20:05     ` Zephaniah E. Hull
  2004-06-04 20:07     ` Greg KH
@ 2004-06-04 20:40     ` Duncan Sands
  2004-06-04 21:30       ` Zephaniah E. Hull
  2 siblings, 1 reply; 22+ messages in thread
From: Duncan Sands @ 2004-06-04 20:40 UTC (permalink / raw)
  To: Zephaniah E. Hull, Greg KH
  Cc: linux-kernel, David A. Desrosiers, linux-usb-devel

> c4bae310 Call Trace:
>  [<c0336735>] __down+0x85/0x120
>  [<c033692f>] __down_failed+0xb/0x14
>  [<c026af27>] .text.lock.hub+0x69/0x82
>  [<c0272b7f>] usbdev_ioctl+0x19f/0x710
>  [<c015a45d>] file_ioctl+0x5d/0x170
>  [<c015a686>] sys_ioctl+0x116/0x250
>  [<c0103f8f>] syscall_call+0x7/0xb

Does this help?

Ciao,

Duncan.

--- linux-2.5/drivers/usb/core/devio.c.orig	2004-06-04 22:29:28.000000000 +0200
+++ linux-2.5/drivers/usb/core/devio.c	2004-06-04 22:40:22.000000000 +0200
@@ -50,6 +50,8 @@
 #include "hcd.h"	/* for usbcore internals */
 #include "usb.h"
 
+extern int __usb_reset_device(struct usb_device *udev);
+
 struct async {
 	struct list_head asynclist;
 	struct dev_state *ps;
@@ -719,7 +721,7 @@
 
 static int proc_resetdevice(struct dev_state *ps)
 {
-	return usb_reset_device(ps->dev);
+	return __usb_reset_device(ps->dev);
 
 }
 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-04 20:07     ` Greg KH
  2004-06-04 20:28       ` David A. Desrosiers
@ 2004-06-04 21:06       ` Zephaniah E. Hull
  1 sibling, 0 replies; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-06-04 21:06 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, David A. Desrosiers, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 2120 bytes --]

On Fri, Jun 04, 2004 at 01:07:48PM -0700, Greg KH wrote:
> On Fri, Jun 04, 2004 at 04:02:11PM -0400, Zephaniah E. Hull wrote:
> > 
> > lt-pilot-xfer D 00000000     0 11415   2709                     (NOTLB)
> > d2ad3eb0 00000086 c022391a 00000000 3231203a 000a2e35 00000001 d2ad3ea7
> >        d4edd000 d7fc8a00 c8449790 00000000 abb31900 000f447a c4bae4b8 c977d824
> >        00000246 d2ad2000 d2ad3eec c0336735 c977d82c c4bae310 00000001 c4bae310
> > Call Trace:
> >  [<c0336735>] __down+0x85/0x120
> >  [<c033692f>] __down_failed+0xb/0x14
> >  [<c026af27>] .text.lock.hub+0x69/0x82
> >  [<c0272b7f>] usbdev_ioctl+0x19f/0x710
> >  [<c015a45d>] file_ioctl+0x5d/0x170
> >  [<c015a686>] sys_ioctl+0x116/0x250
> >  [<c0103f8f>] syscall_call+0x7/0xb
> > 
> > This is on 2.6.7-rc2-mm1.
> 
> Ah, can you not try the -mm1 kernel?  This problem should not be in the
> mainline kernel.  There was a locking issue in the last bk-usb patch
> that made it into the -mm1 kernel that was fixed yesterday.

This is from -rc2.

lt-pilot-xfer D 00000000     0  3034   2981                     (NOTLB)
c3701eb0 00000082 c022039a 00000000 3231203a 300a2e35 00000001 c3701ea7
       1a1e0e40 000f4264 c6e0cc30 00000000 1a1e0e40 000f4264 c50cf3b8 d6cc1824
       00000246 c3700000 c3701eec c032eb35 d6cc182c c50cf210 00000001 c50cf210
Call Trace:
 [<c032eb35>] __down+0x85/0x100
 [<c032ece7>] __down_failed+0xb/0x14
 [<c02663f7>] .text.lock.hub+0x69/0x72
 [<c026dfff>] usbdev_ioctl+0x19f/0x710
 [<c015951d>] file_ioctl+0x5d/0x170
 [<c0159746>] sys_ioctl+0x116/0x250
 [<c0103f0f>] syscall_call+0x7/0xb

I'll next try with the patch from Duncan Sands, but if things are as bad
as Alan Stern says, then we should at least make the ioctl fail for now
instead of killing USB.

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

"Delivery anywhere in the world within thirty minutes or the second one's
 free." - "pizza box" art atop a Minuteman ICBM silo, Paul A. Suhler, RHF

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-04 20:40     ` [linux-usb-devel] " Duncan Sands
@ 2004-06-04 21:30       ` Zephaniah E. Hull
  2004-06-05  7:55         ` Duncan Sands
  0 siblings, 1 reply; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-06-04 21:30 UTC (permalink / raw)
  To: Duncan Sands; +Cc: Greg KH, linux-kernel, David A. Desrosiers, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 860 bytes --]

On Fri, Jun 04, 2004 at 10:40:43PM +0200, Duncan Sands wrote:
> > c4bae310 Call Trace:
> >  [<c0336735>] __down+0x85/0x120
> >  [<c033692f>] __down_failed+0xb/0x14
> >  [<c026af27>] .text.lock.hub+0x69/0x82
> >  [<c0272b7f>] usbdev_ioctl+0x19f/0x710
> >  [<c015a45d>] file_ioctl+0x5d/0x170
> >  [<c015a686>] sys_ioctl+0x116/0x250
> >  [<c0103f8f>] syscall_call+0x7/0xb
> 
> Does this help?

I'm afraid not.

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

I still do not understand why manglement believes that cutting off the
oxygen flow to the brain will INCREASE productivity. The reason they
made that decision is probably because they couldn't think clearly due
to wearing neckties.
  -- Paul Tomko on ASR.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-04 21:30       ` Zephaniah E. Hull
@ 2004-06-05  7:55         ` Duncan Sands
  2004-06-06  6:35           ` Zephaniah E. Hull
  0 siblings, 1 reply; 22+ messages in thread
From: Duncan Sands @ 2004-06-05  7:55 UTC (permalink / raw)
  To: Zephaniah E. Hull
  Cc: Greg KH, linux-kernel, David A. Desrosiers, linux-usb-devel

On Friday 04 June 2004 23:30, Zephaniah E. Hull wrote:
> On Fri, Jun 04, 2004 at 10:40:43PM +0200, Duncan Sands wrote:
> > > c4bae310 Call Trace:
> > >  [<c0336735>] __down+0x85/0x120
> > >  [<c033692f>] __down_failed+0xb/0x14
> > >  [<c026af27>] .text.lock.hub+0x69/0x82
> > >  [<c0272b7f>] usbdev_ioctl+0x19f/0x710
> > >  [<c015a45d>] file_ioctl+0x5d/0x170
> > >  [<c015a686>] sys_ioctl+0x116/0x250
> > >  [<c0103f8f>] syscall_call+0x7/0xb
> >
> > Does this help?
>
> I'm afraid not.

Are you sure?  That seems impossible to me!  Can you
get a new call trace please.

Thanks,

Duncan.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-05  7:55         ` Duncan Sands
@ 2004-06-06  6:35           ` Zephaniah E. Hull
  2004-06-07  7:05             ` Duncan Sands
  0 siblings, 1 reply; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-06-06  6:35 UTC (permalink / raw)
  To: Duncan Sands; +Cc: Greg KH, linux-kernel, David A. Desrosiers, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 1427 bytes --]

On Sat, Jun 05, 2004 at 09:55:01AM +0200, Duncan Sands wrote:
> On Friday 04 June 2004 23:30, Zephaniah E. Hull wrote:
> > On Fri, Jun 04, 2004 at 10:40:43PM +0200, Duncan Sands wrote:
> > > > c4bae310 Call Trace:
> > > >  [<c0336735>] __down+0x85/0x120
> > > >  [<c033692f>] __down_failed+0xb/0x14
> > > >  [<c026af27>] .text.lock.hub+0x69/0x82
> > > >  [<c0272b7f>] usbdev_ioctl+0x19f/0x710
> > > >  [<c015a45d>] file_ioctl+0x5d/0x170
> > > >  [<c015a686>] sys_ioctl+0x116/0x250
> > > >  [<c0103f8f>] syscall_call+0x7/0xb
> > >
> > > Does this help?
> >
> > I'm afraid not.
> 
> Are you sure?  That seems impossible to me!  Can you
> get a new call trace please.

Hrm, I could have sworn that the kernel I tested with was rebuilt with
the patch, but now that I am trying it on rc2-mm1 with the patch, it
does in fact seem to be working, mostly.

Thanks a lot, and sorry for the previous report.

I seem to be seeing a locking related race condition on bulk reads and
writes as well, should I start a new thread for those?

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

* james would be more impressed if netgod's magic powers could stop the
splits in the first place...
* netgod notes debian developers are notoriously hard to impress
        -- Seen on #Debian

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-06  6:35           ` Zephaniah E. Hull
@ 2004-06-07  7:05             ` Duncan Sands
  2004-06-07 15:43               ` Zephaniah E. Hull
  0 siblings, 1 reply; 22+ messages in thread
From: Duncan Sands @ 2004-06-07  7:05 UTC (permalink / raw)
  To: Zephaniah E. Hull
  Cc: Greg KH, linux-kernel, David A. Desrosiers, linux-usb-devel

> > Are you sure?  That seems impossible to me!  Can you
> > get a new call trace please.
> 
> Hrm, I could have sworn that the kernel I tested with was rebuilt with
> the patch, but now that I am trying it on rc2-mm1 with the patch, it
> does in fact seem to be working, mostly.
> 
> Thanks a lot, and sorry for the previous report.
> 
> I seem to be seeing a locking related race condition on bulk reads and
> writes as well, should I start a new thread for those?

I don't think it matters much whether you start a new thread or not.  What
problem are you seeing?

Ciao,

Duncan.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-07  7:05             ` Duncan Sands
@ 2004-06-07 15:43               ` Zephaniah E. Hull
  2004-06-07 19:11                 ` Duncan Sands
  0 siblings, 1 reply; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-06-07 15:43 UTC (permalink / raw)
  To: Duncan Sands; +Cc: Greg KH, linux-kernel, David A. Desrosiers, linux-usb-devel

[-- Attachment #1: Type: text/plain, Size: 2940 bytes --]

On Mon, Jun 07, 2004 at 09:05:41AM +0200, Duncan Sands wrote:
> > > Are you sure?  That seems impossible to me!  Can you
> > > get a new call trace please.
> > 
> > Hrm, I could have sworn that the kernel I tested with was rebuilt with
> > the patch, but now that I am trying it on rc2-mm1 with the patch, it
> > does in fact seem to be working, mostly.
> > 
> > Thanks a lot, and sorry for the previous report.
> > 
> > I seem to be seeing a locking related race condition on bulk reads and
> > writes as well, should I start a new thread for those?
> 
> I don't think it matters much whether you start a new thread or not.  What
> problem are you seeing?

To give some background, the libusb backend of pilot-link is a slightly
odd design, we do the init work, reset the device, and then setup a read
thread, which basicly does a continuous loop of bulk no-timeout reads
from USB.

In the primary thread we do most of the work, including doing the USB
bulk writes to do things like ask the pilot for information.

Which, once I had things working again, sometimes resulted in the
following issue:

lt-pilot-xfer D 00000010     0  3351   3097  3398               (NOTLB)
ca93dec0 00000082 00000001 00000010 cdaa434c caac11e8 cdaa43ec caac11a0
       ca93ded4 ce8b4318 c03a2fc0 00000000 3904f0c0 000f42ec cb7fe398 ca913c24
       00000246 ca93c000 ca93defc c0336735 ca913c2c cb7fe1f0 00000001 cb7fe1f0
Call Trace:
 [<c0336735>] __down+0x85/0x120
 [<c033692f>] __down_failed+0xb/0x14
 [<c0273245>] .text.lock.devio+0xe5/0x120
 [<c015a45d>] file_ioctl+0x5d/0x170
 [<c015a686>] sys_ioctl+0x116/0x250
 [<c0103f8f>] syscall_call+0x7/0xb

lt-pilot-xfer D 00000001     0  3398   3351                     (NOTLB)
ca8ebe1c 00000082 00000000 00000001 0ca97854 ce5bca08 d7d85000 00000001
       ce5bca08 00000246 ca8ebe2c 00000000 38200f00 000f42ec cb7fe938 ca8ebeac
       ca8ea000 ca8ea000 ca8ebe70 c0336eb8 00000000 cb7fe790 c01146a0 00000000
Call Trace:
 [<c0336eb8>] wait_for_completion+0x78/0xf0
 [<c026cc0a>] usb_start_wait_urb+0x7a/0xc0
 [<c0271866>] proc_bulk+0x116/0x220
 [<c0272f61>] usbdev_ioctl+0x581/0x710
 [<c015a45d>] file_ioctl+0x5d/0x170
 [<c015a686>] sys_ioctl+0x116/0x250
 [<c0103f8f>] syscall_call+0x7/0xb

With the device not sending us any more data until it receives the
write, and the write not getting to send until the bulk read finishes or
the device goes away.

With the predictable annoyance this causes, of course.

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

  Yes, Java is so bulletproofed that to a C programmer it feels like
being in a straightjacket, but it's a really comfy and warm
straightjacket, and the world would be a safer place if everyone was
straightjacketed most of the time.        -- Overheard in the SDM.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-07 15:43               ` Zephaniah E. Hull
@ 2004-06-07 19:11                 ` Duncan Sands
  2004-06-07 23:13                   ` Zephaniah E. Hull
  0 siblings, 1 reply; 22+ messages in thread
From: Duncan Sands @ 2004-06-07 19:11 UTC (permalink / raw)
  To: linux-usb-devel
  Cc: Zephaniah E. Hull, Greg KH, linux-kernel, David A. Desrosiers

> To give some background, the libusb backend of pilot-link is a slightly
> odd design, we do the init work, reset the device, and then setup a read
> thread, which basicly does a continuous loop of bulk no-timeout reads
> from USB.
> 
> In the primary thread we do most of the work, including doing the USB
> bulk writes to do things like ask the pilot for information.
> 
> Which, once I had things working again, sometimes resulted in the
> following issue:
> 
> lt-pilot-xfer D 00000010     0  3351   3097  3398               (NOTLB)
> ca93dec0 00000082 00000001 00000010 cdaa434c caac11e8 cdaa43ec caac11a0
>        ca93ded4 ce8b4318 c03a2fc0 00000000 3904f0c0 000f42ec cb7fe398 ca913c24
>        00000246 ca93c000 ca93defc c0336735 ca913c2c cb7fe1f0 00000001 cb7fe1f0
> Call Trace:
>  [<c0336735>] __down+0x85/0x120
>  [<c033692f>] __down_failed+0xb/0x14
>  [<c0273245>] .text.lock.devio+0xe5/0x120
>  [<c015a45d>] file_ioctl+0x5d/0x170
>  [<c015a686>] sys_ioctl+0x116/0x250
>  [<c0103f8f>] syscall_call+0x7/0xb
> 
> lt-pilot-xfer D 00000001     0  3398   3351                     (NOTLB)
> ca8ebe1c 00000082 00000000 00000001 0ca97854 ce5bca08 d7d85000 00000001
>        ce5bca08 00000246 ca8ebe2c 00000000 38200f00 000f42ec cb7fe938 ca8ebeac
>        ca8ea000 ca8ea000 ca8ebe70 c0336eb8 00000000 cb7fe790 c01146a0 00000000
> Call Trace:
>  [<c0336eb8>] wait_for_completion+0x78/0xf0
>  [<c026cc0a>] usb_start_wait_urb+0x7a/0xc0
>  [<c0271866>] proc_bulk+0x116/0x220
>  [<c0272f61>] usbdev_ioctl+0x581/0x710
>  [<c015a45d>] file_ioctl+0x5d/0x170
>  [<c015a686>] sys_ioctl+0x116/0x250
>  [<c0103f8f>] syscall_call+0x7/0xb
> 
> With the device not sending us any more data until it receives the
> write, and the write not getting to send until the bulk read finishes or
> the device goes away.
> 
> With the predictable annoyance this causes, of course.

This is my fault.  I will fix it.

Ciao,

Duncan.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-07 19:11                 ` Duncan Sands
@ 2004-06-07 23:13                   ` Zephaniah E. Hull
  2004-06-08 20:19                     ` Duncan Sands
  0 siblings, 1 reply; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-06-07 23:13 UTC (permalink / raw)
  To: Duncan Sands; +Cc: linux-usb-devel, Greg KH, linux-kernel, David A. Desrosiers

[-- Attachment #1: Type: text/plain, Size: 846 bytes --]

On Mon, Jun 07, 2004 at 09:11:32PM +0200, Duncan Sands wrote:
> > With the device not sending us any more data until it receives the
> > write, and the write not getting to send until the bulk read finishes or
> > the device goes away.
> > 
> > With the predictable annoyance this causes, of course.
> 
> This is my fault.  I will fix it.

Great, could you send me the patch? (So I have something usable until it
gets into mainline and a kernel is released with it.)
> 
> Ciao,
> 
> Duncan.
> 

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

<nonlinear> .net is microsofts perverted version of a java networked
             environment uglified for windows-specific crap
	-- nonlinear in #opengl

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-07 23:13                   ` Zephaniah E. Hull
@ 2004-06-08 20:19                     ` Duncan Sands
  2004-06-18 20:02                       ` Ian Morgan
  2004-07-02 20:47                       ` Zephaniah E. Hull
  0 siblings, 2 replies; 22+ messages in thread
From: Duncan Sands @ 2004-06-08 20:19 UTC (permalink / raw)
  To: linux-usb-devel
  Cc: Zephaniah E. Hull, Greg KH, linux-kernel, David A. Desrosiers

> Great, could you send me the patch? (So I have something usable until it
> gets into mainline and a kernel is released with it.)

Sure - I just have to write it first!  It's a bit tricky to do right...

Duncan.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-08 20:19                     ` Duncan Sands
@ 2004-06-18 20:02                       ` Ian Morgan
  2004-06-19 13:48                         ` Duncan Sands
  2004-07-02 20:47                       ` Zephaniah E. Hull
  1 sibling, 1 reply; 22+ messages in thread
From: Ian Morgan @ 2004-06-18 20:02 UTC (permalink / raw)
  To: Duncan Sands
  Cc: linux-usb-devel, Zephaniah E. Hull, Greg KH,
	Linux Kernel Mailing List, David A. Desrosiers

On Tue, 8 Jun 2004, Duncan Sands wrote:

>> Great, could you send me the patch? (So I have something usable until it
>> gets into mainline and a kernel is released with it.)
>
> Sure - I just have to write it first!  It's a bit tricky to do right...

Any further status on this?

I don't know for sure that the problem I'm having is related, but it sure
sound like it:

I've tried these kernels:
 	2.6.6
 	2.6.7
 	2.6.7 + 2.6.7-rc3-mm2's big USB patch
all both with and witout kernel pre-emption enabled.

I have 3 Addonics 4-slot PCMCIA card reader attached via two 7-port D-Link
hub. All units are USB 2.0 (reported in /proc/bus/usb/devices as 480Mbps).
The problem occurs even with just one slot connected by one hub and
everything else disconncted. All readers and hubs are powered by extrernal
AC adapters, so power draw from the bus should not be an issue.

I can insert a PCMCIA card and, w/ usb-storage, see it as /dev/sda. But here
is the problem: I can only do this (roughly) twice. After ejecting it the
2nd time, and inserting it the 3rd time, the USB subsystem seems to hang,
and rather than detecting the card, goes into an infinite cycle of
attempting and failing to reset the bus. The 3 insertion cycles is almost
always constant, but it has once allowed me 6 cycles before it locked up.
During that one 6-cycle count, the same hang appeard after the 3rd
insertion, but the bus actually recovered after one reset attempt, but then
locked up after the 6th insertion never to recover again.

The kernel processes [usb-storage] and [scsi_eh_n] appear locked, with the
[scsi_eh_n] in D state:

root      4297  0.0  0.0     0    0 ?        SW   15:21   0:00 [usb-storage]
root      4298  0.0  0.0     0    0 ?        DW   15:21   0:00 [scsi_eh_6]

Here is a stack trace of usb-storage and scsi_eh_6:

Jun 18 15:27:05 light kernel: usb-storage   S C03A1C40     0  4297      1       4298  2515 (L-TLB)
Jun 18 15:27:05 light kernel: d5b43f58 00000046 d737e0b0 c03a1c40 00000001 d5b43f48 c0117575 df892b30 
Jun 18 15:27:05 light kernel:        00000001 00000000 d5d86030 00002274 32de0b8e 0000006f d737e258 c158dd04 
Jun 18 15:27:05 light kernel:        00000286 d5b42000 d737e0b0 c02a9512 c158dd0c 00000000 00000001 d737e0b0 
Jun 18 15:27:05 light kernel: Call Trace:
Jun 18 15:27:05 light kernel:  [<c0117575>] __wake_up_common+0x38/0x57
Jun 18 15:27:05 light kernel:  [<c02a9512>] __down_interruptible+0x9b/0x101
Jun 18 15:27:05 light kernel:  [<c011752b>] default_wake_function+0x0/0x12
Jun 18 15:27:05 light kernel:  [<c011a559>] printk+0xef/0x12c
Jun 18 15:27:05 light kernel:  [<c02a958b>] __down_failed_interruptible+0x7/0xc
Jun 18 15:27:05 light kernel:  [<e0ddd29e>] .text.lock.usb+0x5/0x5b [usb_storage]
Jun 18 15:27:05 light kernel:  [<c0105d4e>] ret_from_fork+0x6/0x14
Jun 18 15:27:05 light kernel:  [<e0ddc4b9>] usb_stor_control_thread+0x0/0x2b5 [usb_storage]
Jun 18 15:27:05 light kernel:  [<e0ddc4b9>] usb_stor_control_thread+0x0/0x2b5 [usb_storage]
Jun 18 15:27:05 light kernel:  [<c0104291>] kernel_thread_helper+0x5/0xb
Jun 18 15:27:05 light kernel: 
Jun 18 15:27:05 light kernel: scsi_eh_6     D C03A20E8     0  4298      1       4297 (L-TLB)
Jun 18 15:27:05 light kernel: d5eabed0 00000046 df892b30 c03a20e8 00000073 00000000 c02f76b8 00000001 
Jun 18 15:27:05 light kernel:        d9c03e01 00000073 df892b30 000024bb d9c04dd3 00000073 d5d861d8 df8ff424 
Jun 18 15:27:05 light kernel:        00000286 d5d86030 df8ff42c c02a942c 00000001 d5d86030 c011752b df8ff42c 
Jun 18 15:27:05 light kernel: Call Trace:
Jun 18 15:27:05 light kernel:  [<c02a942c>] __down+0x7c/0xc7
Jun 18 15:27:05 light kernel:  [<c011752b>] default_wake_function+0x0/0x12
Jun 18 15:27:05 light kernel:  [<c011a674>] release_console_sem+0x9a/0x9c
Jun 18 15:27:05 light kernel:  [<c02a9580>] __down_failed+0x8/0xc
Jun 18 15:27:05 light kernel:  [<e08dd6ff>] .text.lock.hub+0x87/0x98 [usbcore]
Jun 18 15:27:05 light kernel:  [<e0dda35e>] bus_reset+0xc9/0xeb [usb_storage]
Jun 18 15:27:05 light kernel:  [<e0dcb146>] scsi_try_bus_reset+0x54/0x8a [scsi_mod]
Jun 18 15:27:05 light kernel:  [<e0dcb265>] scsi_eh_bus_reset+0x5f/0x101 [scsi_mod]
Jun 18 15:27:05 light kernel:  [<e0dcb095>] scsi_eh_bus_device_reset+0x75/0xd2 [scsi_mod]
Jun 18 15:27:05 light kernel:  [<e0dcb7a0>] scsi_eh_ready_devs+0x63/0x93 [scsi_mod]
Jun 18 15:27:05 light kernel:  [<e0dcb8f4>] scsi_unjam_host+0xa1/0xa3 [scsi_mod]
Jun 18 15:27:05 light kernel:  [<e0dcb994>] scsi_error_handler+0x9e/0xc6 [scsi_mod]
Jun 18 15:27:05 light kernel:  [<e0dcb8f6>] scsi_error_handler+0x0/0xc6 [scsi_mod]
Jun 18 15:27:05 light kernel:  [<c0104291>] kernel_thread_helper+0x5/0xb

And here are the debug logs leading up the the lockup:

Jun 18 15:21:17 light kernel: hub 1-1:1.0: port 2, status 0101, change 0001, 12 Mb/s
Jun 18 15:21:17 light kernel: hub 1-1:1.0: debounce: port 2: total 100ms stable 100ms status 0x101
Jun 18 15:21:17 light kernel: usb 1-1.2: new full speed USB device using address 17
Jun 18 15:21:17 light kernel: usb 1-1.2: new device strings: Mfr=73, Product=82, SerialNumber=99
Jun 18 15:21:17 light kernel: usb 1-1.2: default language 0x0409
Jun 18 15:21:17 light kernel: usb 1-1.2: Product: USB to IDE Cable
Jun 18 15:21:17 light kernel: usb 1-1.2: Manufacturer: Addonics
Jun 18 15:21:17 light kernel: usb 1-1.2: SerialNumber: 0123456789AB
Jun 18 15:21:17 light kernel: usb 1-1.2: hotplug
Jun 18 15:21:17 light kernel: usb 1-1.2: adding 1-1.2:2.0 (config #2, interface 0)
Jun 18 15:21:17 light kernel: usb 1-1.2:2.0: hotplug
Jun 18 15:21:17 light kernel: usb-storage 1-1.2:2.0: usb_probe_interface
Jun 18 15:21:17 light kernel: usb-storage 1-1.2:2.0: usb_probe_interface - got id
Jun 18 15:21:17 light kernel: usb-storage: USB Mass Storage device detected
Jun 18 15:21:17 light kernel: usb-storage: altsetting is 0, id_index is 92
Jun 18 15:21:17 light kernel: usb-storage: -- associate_dev
Jun 18 15:21:18 light kernel: usb-storage: Transport: Bulk
Jun 18 15:21:18 light kernel: usb-storage: Protocol: Transparent SCSI
Jun 18 15:21:18 light kernel: usb-storage: Endpoints: In: 0xd6c4ba54 Out: 0xd6c4ba68 Int: 0xd6c4ba7c (Period 32)
Jun 18 15:21:18 light kernel: usb-storage: usb_stor_control_msg: rq=fe rqtype=a1 value=0000 index=00 len=1
Jun 18 15:21:18 light kernel: usb-storage: GetMaxLUN command result is 1, data is 0
Jun 18 15:21:18 light kernel: usb-storage: *** thread sleeping.
Jun 18 15:21:18 light kernel: scsi6 : SCSI emulation for USB Mass Storage devices
Jun 18 15:21:18 light kernel: usb-storage: queuecommand called
Jun 18 15:21:18 light kernel: usb-storage: *** thread awakened.
Jun 18 15:21:18 light kernel: usb-storage: Command INQUIRY (6 bytes)
Jun 18 15:21:18 light kernel: usb-storage:  12 00 00 00 24 00
Jun 18 15:21:18 light kernel: usb-storage: Bulk Command S 0x43425355 T 0xd1 L 36 F 128 Trg 0 LUN 0 CL 6
Jun 18 15:21:18 light kernel: usb-storage: usb_stor_bulk_transfer_buf: xfer 31 bytes
Jun 18 15:21:18 light kernel: usb-storage: Status code 0; transferred 31/31
Jun 18 15:21:18 light kernel: usb-storage: -- transfer complete
Jun 18 15:21:18 light kernel: usb-storage: Bulk command transfer result=0
Jun 18 15:21:18 light kernel: usb-storage: usb_stor_bulk_transfer_buf: xfer 36 bytes
Jun 18 15:21:23 light kernel: usb-storage: command_abort called
Jun 18 15:21:23 light kernel: usb-storage: usb_stor_stop_transport called
Jun 18 15:21:23 light kernel: usb-storage: -- cancelling URB
Jun 18 15:21:23 light kernel: usb-storage: Status code -104; transferred 0/36
Jun 18 15:21:23 light kernel: usb-storage: -- transfer cancelled
Jun 18 15:21:23 light kernel: usb-storage: Bulk data transfer result 0x4
Jun 18 15:21:23 light kernel: usb-storage: -- command was aborted
Jun 18 15:21:23 light kernel: usb-storage: usb_stor_Bulk_reset called
Jun 18 15:21:23 light kernel: usb-storage: usb_stor_control_msg: rq=ff rqtype=21 value=0000 index=00 len=0
Jun 18 15:21:43 light kernel: usb-storage: Timeout -- cancelling URB
Jun 18 15:21:43 light kernel: usb-storage: Soft reset failed: -104
Jun 18 15:21:43 light kernel: usb-storage: scsi command aborted
Jun 18 15:21:43 light kernel: usb-storage: *** thread sleeping.
Jun 18 15:21:43 light kernel: usb-storage: queuecommand called
Jun 18 15:21:43 light kernel: usb-storage: *** thread awakened.
Jun 18 15:21:43 light kernel: usb-storage: Command TEST_UNIT_READY (6 bytes)
Jun 18 15:21:43 light kernel: usb-storage:  00 00 00 00 00 00
Jun 18 15:21:43 light kernel: usb-storage: Bulk Command S 0x43425355 T 0xd1 L 0 F 0 Trg 0 LUN 0 CL 6
Jun 18 15:21:43 light kernel: usb-storage: usb_stor_bulk_transfer_buf: xfer 31 bytes
Jun 18 15:21:43 light kernel: usb-storage: Status code 0; transferred 31/31
Jun 18 15:21:43 light kernel: usb-storage: -- transfer complete
Jun 18 15:21:43 light kernel: usb-storage: Bulk command transfer result=0
Jun 18 15:21:43 light kernel: usb-storage: Attempting to get CSW...
Jun 18 15:21:43 light kernel: usb-storage: usb_stor_bulk_transfer_buf: xfer 13 bytes
Jun 18 15:21:53 light kernel: usb-storage: command_abort called
Jun 18 15:21:53 light kernel: usb-storage: usb_stor_stop_transport called
Jun 18 15:21:53 light kernel: usb-storage: -- cancelling URB
Jun 18 15:21:53 light kernel: usb-storage: Status code -104; transferred 0/13
Jun 18 15:21:53 light kernel: usb-storage: -- transfer cancelled
Jun 18 15:21:53 light kernel: usb-storage: Bulk status result = 4
Jun 18 15:21:53 light kernel: usb-storage: -- command was aborted
Jun 18 15:21:53 light kernel: usb-storage: usb_stor_Bulk_reset called
Jun 18 15:21:53 light kernel: usb-storage: usb_stor_control_msg: rq=ff rqtype=21 value=0000 index=00 len=0
Jun 18 15:22:13 light kernel: usb-storage: Timeout -- cancelling URB
Jun 18 15:22:13 light kernel: usb-storage: Soft reset failed: -104
Jun 18 15:22:13 light kernel: usb-storage: scsi command aborted
Jun 18 15:22:13 light kernel: usb-storage: *** thread sleeping.
Jun 18 15:22:13 light kernel: usb-storage: device_reset called
Jun 18 15:22:13 light kernel: usb-storage: usb_stor_Bulk_reset called
Jun 18 15:22:13 light kernel: usb-storage: usb_stor_control_msg: rq=ff rqtype=21 value=0000 index=00 len=0
Jun 18 15:22:33 light kernel: usb-storage: Timeout -- cancelling URB
Jun 18 15:22:33 light kernel: usb-storage: Soft reset failed: -104
Jun 18 15:22:33 light kernel: usb-storage: bus_reset called
Jun 18 15:24:02 light kernel: hub 1-1:1.0: transfer --> -84
Jun 18 15:24:33 light last message repeated 79 times
Jun 18 15:25:00 light last message repeated 71 times

Notice that after several bus reset timeouts, the "-84" error repeats ad-
infinitum.

This particular test was with only uhci_hcd, but the same deadlock occurs
with ehci_hcd as well, though the end result is different only in the
reported error over and over:

Jun 18 14:42:04 light kernel: ehci_hcd 0000:00:1d.7: devpath 2 ep1in 3strikes
Jun 18 14:42:04 light kernel: hub 4-2:1.0: transfer --> -71

Can anyone help, or at least tell me that this is the same problem seen in the
earlier parts of this thread?

Regards,
Ian Morgan

-- 
-------------------------------------------------------------------
  Ian E. Morgan          Vice President & C.O.O.       Webcon, Inc.
  imorgan at webcon dot ca       PGP: #2DA40D07       www.webcon.ca
     *  Customized Linux Network Solutions for your Business  *
-------------------------------------------------------------------

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-18 20:02                       ` Ian Morgan
@ 2004-06-19 13:48                         ` Duncan Sands
  0 siblings, 0 replies; 22+ messages in thread
From: Duncan Sands @ 2004-06-19 13:48 UTC (permalink / raw)
  To: Ian Morgan
  Cc: linux-usb-devel, Zephaniah E. Hull, Greg KH,
	Linux Kernel Mailing List, David A. Desrosiers

> I don't know for sure that the problem I'm having is related, but it sure
> sound like it:

Hi Ian, I was talking about the problem in usbfs where only one bulk or
control message can be in flight at any one time.  Your problem seems
quite different to this, sorry!

All the best,

Duncan.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-06-08 20:19                     ` Duncan Sands
  2004-06-18 20:02                       ` Ian Morgan
@ 2004-07-02 20:47                       ` Zephaniah E. Hull
  2004-07-02 21:11                         ` Alan Stern
  1 sibling, 1 reply; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-07-02 20:47 UTC (permalink / raw)
  To: Duncan Sands; +Cc: linux-usb-devel, Greg KH, linux-kernel, David A. Desrosiers

[-- Attachment #1: Type: text/plain, Size: 754 bytes --]

On Tue, Jun 08, 2004 at 10:19:40PM +0200, Duncan Sands wrote:
> > Great, could you send me the patch? (So I have something usable until it
> > gets into mainline and a kernel is released with it.)
> 
> Sure - I just have to write it first!  It's a bit tricky to do right...

Has there been any progress on this?

I have been looking at the code in question and I am curious as to what
events we are attempting to protect against with the serialize spinlock?

Thanks.

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

Stubborness will get you where self-esteem won't let you go.
  -- Queen Of Swords in the SDM.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-07-02 20:47                       ` Zephaniah E. Hull
@ 2004-07-02 21:11                         ` Alan Stern
  2004-07-02 21:52                           ` Zephaniah E. Hull
  0 siblings, 1 reply; 22+ messages in thread
From: Alan Stern @ 2004-07-02 21:11 UTC (permalink / raw)
  To: Zephaniah E. Hull
  Cc: Duncan Sands, linux-usb-devel, Greg KH, linux-kernel,
	David A. Desrosiers

On Fri, 2 Jul 2004, Zephaniah E. Hull wrote:

> On Tue, Jun 08, 2004 at 10:19:40PM +0200, Duncan Sands wrote:
> > > Great, could you send me the patch? (So I have something usable until it
> > > gets into mainline and a kernel is released with it.)
> > 
> > Sure - I just have to write it first!  It's a bit tricky to do right...
> 
> Has there been any progress on this?
> 
> I have been looking at the code in question and I am curious as to what
> events we are attempting to protect against with the serialize spinlock?
> 
> Thanks.

There has been progress.  If you start with the latest 2.6.7 kernels 
(vanilla or -mm) and apply these two patches:

http://marc.theaimsgroup.com/?l=linux-usb-devel&m=108810394203966&q=raw
http://marc.theaimsgroup.com/?l=linux-usb-devel&m=108810535225278&q=raw

the deadlock problems should be solved.  Although those patches haven't 
yet been merged, I'm pretty sure they will be.

To answer your other question...  The serialize semaphore (not spinlock) 
prevents the system from trying to do several incompatible things to a USB 
device at the same time.  For example, reset the device while a driver is 
probing it.  Or reset it while it is being suspended.

Alan Stern


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-07-02 21:11                         ` Alan Stern
@ 2004-07-02 21:52                           ` Zephaniah E. Hull
  2004-07-03  8:28                             ` Duncan Sands
  0 siblings, 1 reply; 22+ messages in thread
From: Zephaniah E. Hull @ 2004-07-02 21:52 UTC (permalink / raw)
  To: Alan Stern
  Cc: Duncan Sands, linux-usb-devel, Greg KH, linux-kernel,
	David A. Desrosiers

[-- Attachment #1: Type: text/plain, Size: 2899 bytes --]

On Fri, Jul 02, 2004 at 05:11:52PM -0400, Alan Stern wrote:
> On Fri, 2 Jul 2004, Zephaniah E. Hull wrote:
> 
> > On Tue, Jun 08, 2004 at 10:19:40PM +0200, Duncan Sands wrote:
> > > > Great, could you send me the patch? (So I have something usable until it
> > > > gets into mainline and a kernel is released with it.)
> > > 
> > > Sure - I just have to write it first!  It's a bit tricky to do right...
> > 
> > Has there been any progress on this?
> > 
> > I have been looking at the code in question and I am curious as to what
> > events we are attempting to protect against with the serialize spinlock?
> > 
> > Thanks.
> 
> There has been progress.  If you start with the latest 2.6.7 kernels 
> (vanilla or -mm) and apply these two patches:
> 
> http://marc.theaimsgroup.com/?l=linux-usb-devel&m=108810394203966&q=raw
> http://marc.theaimsgroup.com/?l=linux-usb-devel&m=108810535225278&q=raw
> 
> the deadlock problems should be solved.  Although those patches haven't 
> yet been merged, I'm pretty sure they will be.

Actually, there is still one remaining from looking at the patches I am
afraid.

Admittedly, it is due to the use of a somewhat, unelegant approach,
however it worked quite well (very nice speed bonuses) before the
locking patches.

Specificly, if you have a thread doing bulk reads on a USB device in a
loop, and the device stops talking to you (for instance, waiting for you
to reply), it becomes impossible to take any action on the device,
including aborting the read or issuing a write to the device to tell it
to keep talking until such a time as the read times out, the device
speaks to us, or the device is physically disconnected.

Using timeouts can mediate this, but at the cost of being far less
responsive unless you use a very short timeout.

I am unsure if the kernel provides the locking infrastructure to allow
us to keep us from reading/writing while doing the various events, while
also allowing us to read and write at the same time.

> To answer your other question...  The serialize semaphore (not spinlock) 
> prevents the system from trying to do several incompatible things to a USB 
> device at the same time.  For example, reset the device while a driver is 
> probing it.  Or reset it while it is being suspended.

Ah, my mistake.

-- 
	1024D/E65A7801 Zephaniah E. Hull <warp@babylon.d2dc.net>
	   92ED 94E4 B1E6 3624 226D  5727 4453 008B E65A 7801
	    CCs of replies from mailing lists are requested.

> Is there an API or other means to determine what video
> card, namely the chipset, that the user has installed
> on his machine?

On a modern X86 machine use the PCI/AGP bus data. On a PS/2 use the MCA bus
data. On nubus use the nubus probe data. On old style ISA bus PCs done a large
pointy hat and spend several years reading arcane and forbidden scrolls

 -- Alan Cox

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [linux-usb-devel] Re: USBDEVFS_RESET deadlocks USB bus.
  2004-07-02 21:52                           ` Zephaniah E. Hull
@ 2004-07-03  8:28                             ` Duncan Sands
  0 siblings, 0 replies; 22+ messages in thread
From: Duncan Sands @ 2004-07-03  8:28 UTC (permalink / raw)
  To: Zephaniah E. Hull
  Cc: Alan Stern, linux-usb-devel, Greg KH, linux-kernel,
	David A. Desrosiers

> Specificly, if you have a thread doing bulk reads on a USB device in a
> loop, and the device stops talking to you (for instance, waiting for you
> to reply), it becomes impossible to take any action on the device,
> including aborting the read or issuing a write to the device to tell it
> to keep talking until such a time as the read times out, the device
> speaks to us, or the device is physically disconnected.
> 
> Using timeouts can mediate this, but at the cost of being far less
> responsive unless you use a very short timeout.
> 
> I am unsure if the kernel provides the locking infrastructure to allow
> us to keep us from reading/writing while doing the various events, while
> also allowing us to read and write at the same time.

Hi Zephaniah, I've written a patch to do this, but I haven't finished testing
it yet.  I've put the current version below.  It doesn't (yet) fix the problem
of not being able to interrupt a read/write by sending a signal.  However
it brings things back to where they were before the extra locking went in.
It's against Greg's tree from a little while ago, so may need some fiddling
with before it applies.

Ciao,

Duncan.

===== drivers/usb/core/devio.c 1.77 vs edited =====
--- 1.77/drivers/usb/core/devio.c	2004-05-13 17:39:48 +02:00
+++ edited/drivers/usb/core/devio.c	2004-06-27 21:40:36 +02:00
@@ -45,6 +45,7 @@
 #include <linux/usbdevice_fs.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
+#include <linux/moduleparam.h>
 
 #include "hcd.h"	/* for usbcore internals */
 #include "usb.h"
@@ -70,6 +71,7 @@
 			dev_info( dev , format , ## arg);	\
 	} while (0)
 
+#define MAX_BUFFER_LENGTH	16384
 
 static inline int connected (struct usb_device *dev)
 {
@@ -180,29 +182,12 @@
  * async list handling
  */
 
-static struct async *alloc_async(unsigned int numisoframes)
-{
-        unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
-        struct async *as = kmalloc(assize, GFP_KERNEL);
-        if (!as)
-                return NULL;
-        memset(as, 0, assize);
-	as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
-	if (!as->urb) {
-		kfree(as);
-		return NULL;
-	}
-        return as;
-}
-
 static void free_async(struct async *as)
 {
-        if (as->urb->transfer_buffer)
-                kfree(as->urb->transfer_buffer);
-        if (as->urb->setup_packet)
-                kfree(as->urb->setup_packet);
+	kfree(as->urb->transfer_buffer);
+	kfree(as->urb->setup_packet);
 	usb_free_urb(as->urb);
-        kfree(as);
+	kfree(as);
 }
 
 static inline void async_newpending(struct async *as)
@@ -526,225 +511,378 @@
         return 0;
 }
 
+static void wakeup_completion(struct urb *urb, struct pt_regs *regs)
+{
+	        complete((struct completion *)urb->context);
+}
+
+static void timeout_kill(unsigned long data)
+{
+	struct urb *urb = (struct urb *) data;
+        usb_unlink_urb(urb);
+}
+
+static int start_wait_urb(struct usb_device *dev, struct urb *urb, int timeout, int* actual_length)
+{
+	struct completion done;
+	struct timer_list timer;
+	int status;
+
+	init_completion(&done);
+	urb->context = &done;
+	urb->complete = wakeup_completion;
+	urb->transfer_flags |= URB_ASYNC_UNLINK;
+	urb->actual_length = 0;
+	status = usb_submit_urb(urb, GFP_NOIO);
+
+	if (status == 0) {
+		if (timeout > 0) {
+			init_timer(&timer);
+			timer.expires = jiffies + timeout;
+			timer.data = (unsigned long)urb;
+			timer.function = timeout_kill;
+			/* grr.  timeout _should_ include submit delays. */
+			add_timer(&timer);
+		}
+		up(&dev->serialize);
+		wait_for_completion(&done);
+		down(&dev->serialize);
+		status = urb->status;
+		/* note:  HCDs return ETIMEDOUT for other reasons too */
+		if (status == -ECONNRESET)
+			status = -ETIMEDOUT;
+		if (timeout > 0)
+			del_timer_sync(&timer);
+	}
+
+	if (actual_length)
+		*actual_length = urb->actual_length;
+	return status;
+}
+
 static int proc_control(struct dev_state *ps, void __user *arg)
 {
-	struct usb_device *dev = ps->dev;
 	struct usbdevfs_ctrltransfer ctrl;
-	unsigned int tmo;
-	unsigned char *tbuf;
-	int i, j, ret;
+	struct usb_device *dev = ps->dev;
+	struct usb_ctrlrequest *dr = NULL;
+	unsigned char *tbuf = NULL;
+	struct urb *urb = NULL;
+	int dir_in, j, length, ret;
+	unsigned int pipe, timeout;
 
 	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
 		return -EFAULT;
-	if ((ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex)))
-		return ret;
-	if (ctrl.wLength > PAGE_SIZE)
+	length = ctrl.wLength;
+	if (length < 0 || length > PAGE_SIZE)
 		return -EINVAL;
 	if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
 		return -ENOMEM;
-	tmo = (ctrl.timeout * HZ + 999) / 1000;
-	if (ctrl.bRequestType & 0x80) {
-		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.wLength)) {
-			free_page((unsigned long)tbuf);
-			return -EINVAL;
-		}
-		snoop(&dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", 
-			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex);
-
-		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
-				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
-		if ((i > 0) && ctrl.wLength) {
-			if (usbfs_snoop) {
-				dev_info(&dev->dev, "control read: data ");
-				for (j = 0; j < ctrl.wLength; ++j)
-					printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]);
-				printk("\n");
-			}
-			if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) {
-				free_page((unsigned long)tbuf);
-				return -EFAULT;
-			}
+	dir_in = ctrl.bRequestType & USB_DIR_IN;
+	if (dir_in) {
+		if (length && !access_ok(VERIFY_WRITE, ctrl.data, length)) {
+			ret = -EINVAL;
+			goto out_free;
 		}
 	} else {
-		if (ctrl.wLength) {
-			if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) {
-				free_page((unsigned long)tbuf);
-				return -EFAULT;
+		if (length) {
+			if (copy_from_user(tbuf, ctrl.data, length)) {
+				ret = -EFAULT;
+				goto out_free;
 			}
 		}
-		snoop(&dev->dev, "control write: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", 
-			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex);
+	}
+	snoop(&dev->dev, "control %s: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x wLength=%04x\n", 
+		dir_in ? "read" : "write", ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, ctrl.wLength);
+	if (usbfs_snoop && !dir_in) {
+		dev_info(&dev->dev, "control write: data: ");
+		for (j = 0; j < length; ++j)
+			printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]);
+		printk("\n");
+	}
+	if (!(urb = usb_alloc_urb(0, GFP_KERNEL))) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+	if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL))) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		ret = -ENODEV;
+		goto out_release;
+	}
+	if ((ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex)))
+		goto out_release;
+	if (dir_in)
+		pipe = usb_rcvctrlpipe(dev, 0);
+	else
+		pipe = usb_sndctrlpipe(dev, 0);
+	timeout = (ctrl.timeout * HZ + 999) / 1000;
+	dr->bRequestType= ctrl.bRequestType;
+	dr->bRequest = ctrl.bRequest;
+	dr->wValue = cpu_to_le16p(&ctrl.wValue);
+	dr->wIndex = cpu_to_le16p(&ctrl.wIndex);
+	dr->wLength = cpu_to_le16p(&ctrl.wLength);
+	usb_fill_control_urb(urb, dev, pipe, (unsigned char*)dr, tbuf, length, NULL, 0);
+	ret = start_wait_urb(dev, urb, timeout, &length);
+	up(&dev->serialize);
+	if (ret < 0) {
+		dev_warn(&dev->dev, "usbfs: USBDEVFS_CONTROL failed "
+			   "cmd %s rqt %u rq %u len %u ret %d\n",
+			   current->comm, ctrl.bRequestType, ctrl.bRequest,
+			   ctrl.wLength, ret);
+		goto out_free;
+	}
+	if (dir_in && length) {
 		if (usbfs_snoop) {
-			dev_info(&dev->dev, "control write: data: ");
-			for (j = 0; j < ctrl.wLength; ++j)
-				printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]);
+			dev_info(&dev->dev, "control read: data ");
+			for (j = 0; j < length; ++j)
+				printk ("%02x ", tbuf[j]);
 			printk("\n");
 		}
-		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
-				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		if (copy_to_user(ctrl.data, tbuf, length)) {
+			ret = -EFAULT;
+			goto out_free;
+		}
 	}
+	kfree(dr);
+	usb_free_urb(urb);
 	free_page((unsigned long)tbuf);
-	if (i<0) {
-		dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
-			   "failed cmd %s rqt %u rq %u len %u ret %d\n",
-			   current->comm, ctrl.bRequestType, ctrl.bRequest,
-			   ctrl.wLength, i);
-	}
-	return i;
+	return ret;
+out_release:
+	up(&dev->serialize);
+out_free:
+	kfree(dr);
+	usb_free_urb(urb);
+	free_page((unsigned long)tbuf);
+	return ret;
 }
 
 static int proc_bulk(struct dev_state *ps, void __user *arg)
 {
-	struct usb_device *dev = ps->dev;
 	struct usbdevfs_bulktransfer bulk;
-	unsigned int tmo, len1, pipe;
-	int len2;
-	unsigned char *tbuf;
-	int i, ret;
+	struct usb_device *dev = ps->dev;
+	unsigned char *tbuf = NULL;
+	struct urb *urb = NULL;
+	int dir_in, length, ret;
+	unsigned int pipe, timeout;
 
 	if (copy_from_user(&bulk, arg, sizeof(bulk)))
 		return -EFAULT;
-	if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
-		return ret;
-	if ((ret = checkintf(ps, ret)))
-		return ret;
-	if (bulk.ep & USB_DIR_IN)
-		pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
-	else
-		pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
-	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
+	length = bulk.len;
+	if (length < 0 || length > MAX_BUFFER_LENGTH)
 		return -EINVAL;
-	len1 = bulk.len;
-	if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
+	if (!(tbuf = kmalloc(length, GFP_KERNEL)))
 		return -ENOMEM;
-	tmo = (bulk.timeout * HZ + 999) / 1000;
-	if (bulk.ep & 0x80) {
-		if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
-			kfree(tbuf);
-			return -EINVAL;
-		}
-		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
-		if (!i && len2) {
-			if (copy_to_user(bulk.data, tbuf, len2)) {
-				kfree(tbuf);
-				return -EFAULT;
-			}
+	dir_in = bulk.ep & USB_DIR_IN;
+	if (dir_in) {
+		if (length && !access_ok(VERIFY_WRITE, bulk.data, length)) {
+			ret = -EINVAL;
+			goto out_free;
 		}
 	} else {
-		if (len1) {
-			if (copy_from_user(tbuf, bulk.data, len1)) {
-				kfree(tbuf);
-				return -EFAULT;
+		if (length) {
+			if (copy_from_user(tbuf, bulk.data, length)) {
+				ret = -EFAULT;
+				goto out_free;
 			}
 		}
-		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
 	}
-	kfree(tbuf);
-	if (i < 0) {
+	if (!(urb = usb_alloc_urb(0, GFP_KERNEL))) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		ret = -ENODEV;
+		goto out_release;
+	}
+	if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
+		goto out_release;
+	if ((ret = checkintf(ps, ret)))
+		goto out_release;
+	if (dir_in)
+		pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
+	else
+		pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
+	if (!usb_maxpacket(dev, pipe, !dir_in)) {
+		ret = -EINVAL;
+		goto out_release;
+	}
+	timeout = (bulk.timeout * HZ + 999) / 1000;
+	usb_fill_bulk_urb(urb, dev, pipe, tbuf, length, NULL, NULL);
+	ret = start_wait_urb(dev, urb, timeout, &length);
+	up(&dev->serialize);
+	if (ret < 0) {
 		dev_warn(&dev->dev, "usbfs: USBDEVFS_BULK failed "
-			 "ep 0x%x len %u ret %d\n", bulk.ep, bulk.len, i);
-		return i;
+			 "ep 0x%x len %u ret %d\n", bulk.ep, bulk.len, ret);
+		goto out_free;
+	}
+	if (dir_in && length) {
+		if (copy_to_user(bulk.data, tbuf, length)) {
+			ret = -EFAULT;
+			goto out_free;
+		}
 	}
-	return len2;
+	usb_free_urb(urb);
+	kfree(tbuf);
+	return length;
+out_release:
+	up(&dev->serialize);
+out_free:
+	usb_free_urb(urb);
+	kfree(tbuf);
+	return ret;
 }
 
 static int proc_resetep(struct dev_state *ps, void __user *arg)
 {
+	struct usb_device *dev = ps->dev;
 	unsigned int ep;
 	int ret;
 
 	if (get_user(ep, (unsigned int __user *)arg))
 		return -EFAULT;
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
 	if ((ret = findintfep(ps->dev, ep)) < 0)
-		return ret;
+		goto out;
 	if ((ret = checkintf(ps, ret)))
-		return ret;
+		goto out;
 	usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
-	return 0;
+out:
+	up(&dev->serialize);
+	return ret;
 }
 
 static int proc_clearhalt(struct dev_state *ps, void __user *arg)
 {
+	struct usb_device *dev = ps->dev;
 	unsigned int ep;
 	int pipe;
 	int ret;
 
 	if (get_user(ep, (unsigned int __user *)arg))
 		return -EFAULT;
-	if ((ret = findintfep(ps->dev, ep)) < 0)
-		return ret;
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+	if ((ret = findintfep(dev, ep)) < 0)
+		goto out;
 	if ((ret = checkintf(ps, ret)))
-		return ret;
+		goto out;
 	if (ep & USB_DIR_IN)
-                pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);
+                pipe = usb_rcvbulkpipe(dev, ep & 0x7f);
         else
-                pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f);
+                pipe = usb_sndbulkpipe(dev, ep & 0x7f);
 
-	return usb_clear_halt(ps->dev, pipe);
+	ret = usb_clear_halt(dev, pipe);
+out:
+	up(&dev->serialize);
+	return ret;
 }
 		
 
 static int proc_getdriver(struct dev_state *ps, void __user *arg)
 {
 	struct usbdevfs_getdriver gd;
+	struct usb_device *dev = ps->dev;
 	struct usb_interface *intf;
-	int ret;
+	int ret = 0;
 
 	if (copy_from_user(&gd, arg, sizeof(gd)))
 		return -EFAULT;
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		up(&dev->serialize);
+		return -ENODEV;
+	}
 	down_read(&usb_bus_type.subsys.rwsem);
-	intf = usb_ifnum_to_if(ps->dev, gd.interface);
+	intf = usb_ifnum_to_if(dev, gd.interface);
 	if (!intf || !intf->dev.driver)
 		ret = -ENODATA;
-	else {
-		strncpy(gd.driver, intf->dev.driver->name,
-				sizeof(gd.driver));
-		ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0);
-	}
+	else
+		strncpy(gd.driver, intf->dev.driver->name, sizeof(gd.driver));
 	up_read(&usb_bus_type.subsys.rwsem);
+	up(&dev->serialize);
+	if (!ret)
+		ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0);
 	return ret;
 }
 
 static int proc_connectinfo(struct dev_state *ps, void __user *arg)
 {
 	struct usbdevfs_connectinfo ci;
+	struct usb_device *dev = ps->dev;
 
-	ci.devnum = ps->dev->devnum;
-	ci.slow = ps->dev->speed == USB_SPEED_LOW;
-	if (copy_to_user(arg, &ci, sizeof(ci)))
-		return -EFAULT;
-	return 0;
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		up(&dev->serialize);
+		return -ENODEV;
+	}
+	ci.devnum = dev->devnum;
+	ci.slow = dev->speed == USB_SPEED_LOW;
+	up(&dev->serialize);
+	return copy_to_user(arg, &ci, sizeof(ci)) ? -EFAULT : 0;
 }
 
 static int proc_resetdevice(struct dev_state *ps)
 {
-	return usb_reset_device(ps->dev);
+	struct usb_device *dev = ps->dev;
+	int ret;
 
+	down(&dev->serialize);
+	if (!connected(dev))
+		ret = -ENODEV;
+	else
+		ret = usb_reset_device(dev);
+	up(&dev->serialize);
+	return ret;
 }
 
 static int proc_setintf(struct dev_state *ps, void __user *arg)
 {
 	struct usbdevfs_setinterface setintf;
+	struct usb_device *dev = ps->dev;
 	int ret;
 
 	if (copy_from_user(&setintf, arg, sizeof(setintf)))
 		return -EFAULT;
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
 	if ((ret = checkintf(ps, setintf.interface)))
-		return ret;
-	return usb_set_interface(ps->dev, setintf.interface,
-			setintf.altsetting);
+		goto out;
+	ret = usb_set_interface(dev, setintf.interface, setintf.altsetting);
+out:
+	up(&dev->serialize);
+	return ret;
 }
 
 static int proc_setconfig(struct dev_state *ps, void __user *arg)
 {
-	unsigned int u;
-	int status = 0;
+	struct usb_device *dev = ps->dev;
  	struct usb_host_config *actconfig;
+	int ret;
+	unsigned int u;
 
 	if (get_user(u, (unsigned int __user *)arg))
 		return -EFAULT;
 
- 	actconfig = ps->dev->actconfig;
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+ 	actconfig = dev->actconfig;
  
  	/* Don't touch the device if any interfaces are claimed.
  	 * It could interfere with other drivers' operations, and if
@@ -755,7 +893,7 @@
  
  		for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) {
  			if (usb_interface_claimed(actconfig->interface[i])) {
-				dev_warn (&ps->dev->dev,
+				dev_warn (&dev->dev,
 					"usbfs: interface %d claimed "
 					"while '%s' sets config #%d\n",
 					actconfig->interface[i]
@@ -763,8 +901,8 @@
 						->desc.bInterfaceNumber,
 					current->comm, u);
 #if 0	/* FIXME:  enable in 2.6.10 or so */
- 				status = -EBUSY;
-				break;
+ 				ret = -EBUSY;
+				goto out;
 #endif
 			}
  		}
@@ -773,23 +911,24 @@
 	/* SET_CONFIGURATION is often abused as a "cheap" driver reset,
 	 * so avoid usb_set_configuration()'s kick to sysfs
 	 */
-	if (status == 0) {
-		if (actconfig && actconfig->desc.bConfigurationValue == u)
-			status = usb_reset_configuration(ps->dev);
-		else
-			status = usb_set_configuration(ps->dev, u);
-	}
+	if (actconfig && actconfig->desc.bConfigurationValue == u)
+		ret = usb_reset_configuration(dev);
+	else
+		ret = usb_set_configuration(dev, u);
 
-	return status;
+out:
+	up(&dev->serialize);
+	return ret;
 }
 
 static int proc_submiturb(struct dev_state *ps, void __user *arg)
 {
 	struct usbdevfs_urb uurb;
-	struct usbdevfs_iso_packet_desc *isopkt = NULL;
-	struct usb_endpoint_descriptor *ep_desc;
-	struct async *as;
+	struct async *as = NULL;
+	struct usb_device *dev = ps->dev;
 	struct usb_ctrlrequest *dr = NULL;
+	struct usb_endpoint_descriptor *ep_desc;
+	struct usbdevfs_iso_packet_desc *isopkt = NULL;
 	unsigned int u, totlen, isofrmlen;
 	int ret, interval = 0, ifnum = -1;
 
@@ -802,50 +941,35 @@
 		return -EINVAL;
 	if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
 		return -EINVAL;
-	if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
-		if ((ifnum = findintfep(ps->dev, uurb.endpoint)) < 0)
-			return ifnum;
-		if ((ret = checkintf(ps, ifnum)))
-			return ret;
-	}
+
 	switch(uurb.type) {
 	case USBDEVFS_URB_TYPE_CONTROL:
-		if ((uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) != 0) {
-			if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
-				return -ENOENT;
-			if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL)
-				return -EINVAL;
-		}
 		/* min 8 byte setup packet, max arbitrary */
 		if (uurb.buffer_length < 8 || uurb.buffer_length > PAGE_SIZE)
 			return -EINVAL;
 		if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
 			return -ENOMEM;
 		if (copy_from_user(dr, uurb.buffer, 8)) {
-			kfree(dr);
-			return -EFAULT;
+			ret = -EFAULT;
+			goto out_free;
 		}
 		if (uurb.buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
-			kfree(dr);
-			return -EINVAL;
-		}
-		if ((ret = check_ctrlrecip(ps, dr->bRequestType, le16_to_cpup(&dr->wIndex)))) {
-			kfree(dr);
-			return ret;
+			ret = -EINVAL;
+			goto out_free;
 		}
 		uurb.endpoint = (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
 		uurb.number_of_packets = 0;
 		uurb.buffer_length = le16_to_cpup(&dr->wLength);
 		uurb.buffer += 8;
 		if (!access_ok((uurb.endpoint & USB_DIR_IN) ?  VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) {
-			kfree(dr);
-			return -EFAULT;
+			ret = -EFAULT;
+			goto out_free;
 		}
 		break;
 
 	case USBDEVFS_URB_TYPE_BULK:
 		uurb.number_of_packets = 0;
-		if (uurb.buffer_length > 16384)
+		if (uurb.buffer_length > MAX_BUFFER_LENGTH)
 			return -EINVAL;
 		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
 			return -EFAULT;
@@ -855,39 +979,30 @@
 		/* arbitrary limit */
 		if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)
 			return -EINVAL;
-		if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
-			return -ENOENT;
-		interval = 1 << min (15, ep_desc->bInterval - 1);
 		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;
 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
 			return -ENOMEM;
 		if (copy_from_user(isopkt, &((struct usbdevfs_urb *)arg)->iso_frame_desc, isofrmlen)) {
-			kfree(isopkt);
-			return -EFAULT;
+			ret = -EFAULT;
+			goto out_free;
 		}
 		for (totlen = u = 0; u < uurb.number_of_packets; u++) {
 			if (isopkt[u].length > 1023) {
-				kfree(isopkt);
-				return -EINVAL;
+				ret = -EINVAL;
+				goto out_free;
 			}
 			totlen += isopkt[u].length;
 		}
 		if (totlen > 32768) {
-			kfree(isopkt);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out_free;
 		}
 		uurb.buffer_length = totlen;
 		break;
 
 	case USBDEVFS_URB_TYPE_INTERRUPT:
 		uurb.number_of_packets = 0;
-		if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
-			return -ENOENT;
-		if (ps->dev->speed == USB_SPEED_HIGH)
-			interval = 1 << min (15, ep_desc->bInterval - 1);
-		else
-			interval = ep_desc->bInterval;
-		if (uurb.buffer_length > 16384)
+		if (uurb.buffer_length > MAX_BUFFER_LENGTH)
 			return -EINVAL;
 		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
 			return -EFAULT;
@@ -896,21 +1011,88 @@
 	default:
 		return -EINVAL;
 	}
-	if (!(as = alloc_async(uurb.number_of_packets))) {
-		if (isopkt)
-			kfree(isopkt);
-		if (dr)
-			kfree(dr);
-		return -ENOMEM;
+
+	{
+	        unsigned int assize = sizeof(struct async) + uurb.number_of_packets * sizeof(struct usb_iso_packet_descriptor);
+
+        	if (!(as = kmalloc(assize, GFP_KERNEL))) {
+			ret = -ENOMEM;
+			goto out_free;
+		}
+        	memset(as, 0, assize);
+	}
+
+	if (!(as->urb = usb_alloc_urb(uurb.number_of_packets, GFP_KERNEL))) {
+		ret = -ENOMEM;
+		goto out_free;
 	}
+
 	if (!(as->urb->transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
-		if (isopkt)
-			kfree(isopkt);
-		if (dr)
-			kfree(dr);
-		free_async(as);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out_free;
 	}
+
+	if (!(uurb.endpoint & USB_DIR_IN)) {
+		if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, uurb.buffer_length)) {
+			ret = -EFAULT;
+			goto out_free;
+		}
+	}
+
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		ret = -ENODEV;
+		goto out_release;
+	}
+
+	if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
+		if ((ifnum = findintfep(ps->dev, uurb.endpoint)) < 0) {
+			ret = ifnum;
+			goto out_release;
+		}
+		if ((ret = checkintf(ps, ifnum)))
+			goto out_release;
+	}
+
+	switch(uurb.type) {
+	case USBDEVFS_URB_TYPE_CONTROL:
+		if ((uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) != 0) {
+			if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint))) {
+				ret = -ENOENT;
+				goto out_release;
+			}
+			if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL) {
+				ret = -EINVAL;
+				goto out_release;
+			}
+		}
+		if ((ret = check_ctrlrecip(ps, dr->bRequestType, le16_to_cpup(&dr->wIndex))))
+			goto out_release;
+		break;
+
+	case USBDEVFS_URB_TYPE_ISO:
+		if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint))) {
+			ret = -ENOENT;
+			goto out_release;
+		}
+		interval = 1 << min (15, ep_desc->bInterval - 1);
+		break;
+
+	case USBDEVFS_URB_TYPE_INTERRUPT:
+		if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint))) {
+			ret = -ENOENT;
+			goto out_release;
+		}
+		if (ps->dev->speed == USB_SPEED_HIGH)
+			interval = 1 << min (15, ep_desc->bInterval - 1);
+		else
+			interval = ep_desc->bInterval;
+		break;
+
+	default:
+		break;
+	}
+
         as->urb->dev = ps->dev;
         as->urb->pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
         as->urb->transfer_flags = uurb.flags;
@@ -926,8 +1108,8 @@
 		as->urb->iso_frame_desc[u].length = isopkt[u].length;
 		totlen += isopkt[u].length;
 	}
-	if (isopkt)
-		kfree(isopkt);
+	kfree(isopkt);
+	isopkt = NULL;
 	as->ps = ps;
         as->userurb = arg;
 	if (uurb.endpoint & USB_DIR_IN)
@@ -937,31 +1119,47 @@
 	as->signr = uurb.signr;
 	as->ifnum = ifnum;
 	as->task = current;
-	if (!(uurb.endpoint & USB_DIR_IN)) {
-		if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) {
-			free_async(as);
-			return -EFAULT;
-		}
-	}
         async_newpending(as);
         if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
 		dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret);
                 async_removepending(as);
-                free_async(as);
-                return ret;
+		goto out_release;
         }
+	up(&dev->serialize);
         return 0;
+
+out_release:
+	up(&dev->serialize);
+out_free:
+	if (as) {
+		if (as->urb) {
+			kfree(as->urb->transfer_buffer);
+			usb_free_urb(as->urb);
+		}
+		kfree(as);
+	}
+	kfree(isopkt);
+	kfree(dr);
+	return ret;
 }
 
 static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
 {
 	struct async *as;
+	int ret = 0;
 
-	as = async_getpending(ps, arg);
-	if (!as)
-		return -EINVAL;
-	usb_unlink_urb(as->urb);
-	return 0;
+	down(&ps->dev->serialize);
+	if (!connected(ps->dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+	if ((as = async_getpending(ps, arg)))
+		usb_unlink_urb(as->urb);
+	else
+		ret = -EINVAL;
+out:
+	up(&ps->dev->serialize);
+	return ret;
 }
 
 static int processcompl(struct async *as)
@@ -1003,6 +1201,11 @@
 	struct usb_device *dev = ps->dev;
 	int ret;
 
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		ret = -ENODEV;
+		goto fail;
+	}
 	add_wait_queue(&ps->wait, &wait);
 	while (connected(dev)) {
 		__set_current_state(TASK_INTERRUPTIBLE);
@@ -1016,19 +1219,20 @@
 	}
 	remove_wait_queue(&ps->wait, &wait);
 	set_current_state(TASK_RUNNING);
-	if (as) {
-		ret = processcompl(as);
-		addr = as->userurb;
-		free_async(as);
-		if (ret)
-			return ret;
-		if (put_user(addr, (void **)arg))
-			return -EFAULT;
-		return 0;
+	if (!as) {
+		ret = signal_pending(current) ? -EINTR : -EIO;
+		goto fail;
 	}
-	if (signal_pending(current))
-		return -EINTR;
-	return -EIO;
+	ret = processcompl(as);
+	addr = as->userurb;
+	free_async(as);
+	if (ret)
+		goto fail;
+	up(&dev->serialize);
+	return put_user(addr, (void **)arg) ? -EFAULT : 0;
+fail:
+	up(&dev->serialize);
+	return ret;
 }
 
 static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
@@ -1037,16 +1241,25 @@
 	void __user *addr;
 	int ret;
 
-	if (!(as = async_getcompleted(ps)))
-		return -EAGAIN;
+	down(&ps->dev->serialize);
+	if (!connected(ps->dev)) {
+		ret = -ENODEV;
+		goto fail;
+	}
+	if (!(as = async_getcompleted(ps))) {
+		ret = -EAGAIN;
+		goto fail;
+	}
 	ret = processcompl(as);
 	addr = as->userurb;
 	free_async(as);
 	if (ret)
-		return ret;
-	if (put_user(addr, (void **)arg))
-		return -EFAULT;
-	return 0;
+		goto fail;
+	up(&ps->dev->serialize);
+	return put_user(addr, (void **)arg) ? -EFAULT : 0;
+fail:
+	up(&ps->dev->serialize);
+	return ret;
 }
 
 static int proc_disconnectsignal(struct dev_state *ps, void __user *arg)
@@ -1057,18 +1270,33 @@
 		return -EFAULT;
 	if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX))
 		return -EINVAL;
+	down(&ps->dev->serialize);
+	if (!connected(ps->dev)) {
+		up(&ps->dev->serialize);
+		return -ENODEV;
+	}
 	ps->discsignr = ds.signr;
 	ps->disccontext = ds.context;
+	up(&ps->dev->serialize);
 	return 0;
 }
 
 static int proc_claiminterface(struct dev_state *ps, void __user *arg)
 {
 	unsigned int ifnum;
+	int ret;
 
 	if (get_user(ifnum, (unsigned int __user *)arg))
 		return -EFAULT;
-	return claimintf(ps, ifnum);
+	down(&ps->dev->serialize);
+	if (!connected(ps->dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+	ret = claimintf(ps, ifnum);
+out:
+	up(&ps->dev->serialize);
+	return ret;
 }
 
 static int proc_releaseinterface(struct dev_state *ps, void __user *arg)
@@ -1078,20 +1306,28 @@
 
 	if (get_user(ifnum, (unsigned int __user *)arg))
 		return -EFAULT;
-	if ((ret = releaseintf(ps, ifnum)) < 0)
-		return ret;
+	down(&ps->dev->serialize);
+	if (!connected(ps->dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+	if ((ret = releaseintf(ps, ifnum)))
+		goto out;
 	destroy_async_on_interface (ps, ifnum);
-	return 0;
+out:
+	up(&ps->dev->serialize);
+	return ret;
 }
 
 static int proc_ioctl (struct dev_state *ps, void __user *arg)
 {
 	struct usbdevfs_ioctl	ctrl;
+	void			*buf = NULL;
+	struct usb_device	*dev = ps->dev;
+	struct usb_driver       *driver = NULL;
+	struct usb_interface    *intf = NULL;
+	int			ret = 0;
 	int			size;
-	void			*buf = 0;
-	int			retval = 0;
-	struct usb_interface    *intf = 0;
-	struct usb_driver       *driver = 0;
 
 	/* get input parameters and alloc buffer */
 	if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
@@ -1109,17 +1345,23 @@
 		}
 	}
 
-	if (!connected(ps->dev)) {
-		if (buf)
-			kfree(buf);
-		return -ENODEV;
+	down(&dev->serialize);
+	if (!connected(dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (dev->state != USB_STATE_CONFIGURED) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (!(intf = usb_ifnum_to_if (dev, ctrl.ifno))) {
+               ret = -EINVAL;
+	       goto out;
 	}
 
-	if (ps->dev->state != USB_STATE_CONFIGURED)
-		retval = -ENODEV;
-	else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
-               retval = -EINVAL;
-	else switch (ctrl.ioctl_code) {
+	switch (ctrl.ioctl_code) {
 
 	/* disconnect kernel driver from interface */
 	case USBDEVFS_DISCONNECT:
@@ -1129,7 +1371,7 @@
 			dev_dbg (&intf->dev, "disconnect by usbfs\n");
 			usb_driver_release_interface(driver, intf);
 		} else
-			retval = -ENODATA;
+			ret = -ENODATA;
 		up_write(&usb_bus_type.subsys.rwsem);
 		break;
 
@@ -1144,24 +1386,25 @@
 		if (intf->dev.driver)
 			driver = to_usb_driver(intf->dev.driver);
 		if (driver == 0 || driver->ioctl == 0) {
-			retval = -ENOTTY;
+			ret = -ENOTTY;
 		} else {
-			retval = driver->ioctl (intf, ctrl.ioctl_code, buf);
-			if (retval == -ENOIOCTLCMD)
-				retval = -ENOTTY;
+			ret = driver->ioctl (intf, ctrl.ioctl_code, buf);
+			if (ret == -ENOIOCTLCMD)
+				ret = -ENOTTY;
 		}
 		up_read(&usb_bus_type.subsys.rwsem);
 	}
 
+	if (ret < 0)
+		goto out;
+
 	/* cleanup and return */
-	if (retval >= 0
-			&& (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0
-			&& size > 0
-			&& copy_to_user (ctrl.data, buf, size) != 0)
-		retval = -EFAULT;
-	if (buf != 0)
-		kfree (buf);
-	return retval;
+	if ((_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0 && size > 0)
+	    ret = copy_to_user (ctrl.data, buf, size) ? -EFAULT : 0;
+out:
+	kfree (buf);
+	up(&dev->serialize);
+	return ret;
 }
 
 /*
@@ -1177,11 +1420,6 @@
 
 	if (!(file->f_mode & FMODE_WRITE))
 		return -EPERM;
-	down(&dev->serialize);
-	if (!connected(dev)) {
-		up(&dev->serialize);
-		return -ENODEV;
-	}
 
 	switch (cmd) {
 	case USBDEVFS_CONTROL:
@@ -1279,7 +1517,6 @@
 		ret = proc_ioctl(ps, (void __user *) arg);
 		break;
 	}
-	up(&dev->serialize);
 	if (ret >= 0)
 		inode->i_atime = CURRENT_TIME;
 	return ret;

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2004-07-03  8:32 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-06-04 19:39 USBDEVFS_RESET deadlocks USB bus Zephaniah E. Hull
2004-06-04 19:52 ` Greg KH
2004-06-04 20:02   ` Zephaniah E. Hull
2004-06-04 20:05     ` Zephaniah E. Hull
2004-06-04 20:07     ` Greg KH
2004-06-04 20:28       ` David A. Desrosiers
2004-06-04 21:06       ` Zephaniah E. Hull
2004-06-04 20:40     ` [linux-usb-devel] " Duncan Sands
2004-06-04 21:30       ` Zephaniah E. Hull
2004-06-05  7:55         ` Duncan Sands
2004-06-06  6:35           ` Zephaniah E. Hull
2004-06-07  7:05             ` Duncan Sands
2004-06-07 15:43               ` Zephaniah E. Hull
2004-06-07 19:11                 ` Duncan Sands
2004-06-07 23:13                   ` Zephaniah E. Hull
2004-06-08 20:19                     ` Duncan Sands
2004-06-18 20:02                       ` Ian Morgan
2004-06-19 13:48                         ` Duncan Sands
2004-07-02 20:47                       ` Zephaniah E. Hull
2004-07-02 21:11                         ` Alan Stern
2004-07-02 21:52                           ` Zephaniah E. Hull
2004-07-03  8:28                             ` Duncan Sands

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox