Dave: A bug in gadgetfs has persisted for quite a while: nested spin_locks when used with net2280. This is because inode.c calls usb_ep_queue() for ep0 while holding the device lock, and ep0_complete() tries to acquire the lock. Since net2280 will call the completion routine directly during submission if the request is small enough to fit entirely in a FIFO, we end up in deadlock. (Dummy_hcd may behave the same way; I haven't checked.) The patch below attempts to fix the problem by dropping the lock around the calls to usb_ep_queue() for ep0, but I don't know whether doing this might lead to other problems. I suppose the places inside gadgetfs_setup() are probably okay, but what about the call inside ep0_read()? There's a possibility that the host might send a new SETUP packet while waiting for the userspace program to get around to reading the OUT data from the previous transfer. Can you look this over and figure out what more (if anything) needs to be done? Thanks, Alan Stern Index: usb-2.6/drivers/usb/gadget/inode.c =================================================================== --- usb-2.6.orig/drivers/usb/gadget/inode.c +++ usb-2.6/drivers/usb/gadget/inode.c @@ -1000,8 +1000,11 @@ ep0_read (struct file *fd, char __user * struct usb_ep *ep = dev->gadget->ep0; struct usb_request *req = dev->req; - if ((retval = setup_req (ep, req, 0)) == 0) + if ((retval = setup_req (ep, req, 0)) == 0) { + spin_unlock(&dev->lock); retval = usb_ep_queue (ep, req, GFP_ATOMIC); + spin_lock(&dev->lock); + } dev->state = STATE_DEV_CONNECTED; /* assume that was SET_CONFIGURATION */ @@ -1535,8 +1538,10 @@ delegate: w_length); if (value < 0) break; + spin_unlock(&dev->lock); value = usb_ep_queue (gadget->ep0, dev->req, GFP_ATOMIC); + spin_lock(&dev->lock); if (value < 0) { clean_req (gadget->ep0, dev->req); break; @@ -1559,7 +1564,9 @@ delegate: if (value >= 0 && dev->state != STATE_DEV_SETUP) { req->length = value; req->zero = value < w_length; + spin_unlock(&dev->lock); value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); + spin_lock(&dev->lock); if (value < 0) { DBG (dev, "ep_queue --> %d\n", value); req->status = 0; -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html