]> err.no Git - linux-2.6/commitdiff
USB: usb serial gadget smp related bug
authorEugeny S. Mints <emints@ru.mvista.com>
Sat, 2 Sep 2006 10:59:19 +0000 (03:59 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 27 Sep 2006 18:58:56 +0000 (11:58 -0700)
Adjust dev->dev_lock spinlock lock/unlock calls to be safe for SMP case.
Otherwise the following sequence may lead to a deadlock in SMP case:

gs_send()->usb_ep_queue()
->(in case a request is satisfied immediatly) gs_write_complete()

for ex for pxa2xx_udc.c:
usb_ep_queue()->pxa2xx_ep_queue()->write_fifo()->done()->gs_write_complete()
(through req.complete pointer)

Signed-off-by: Eugeny S. Mints <emints@ru.mvista.com>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/serial.c

index e762aa19ab0a1c9fef4a87a105b0221b95e3ddad..b893e3118e1be480e9b4d8bbd739152efd718141 100644 (file)
@@ -1120,12 +1120,15 @@ static int gs_send(struct gs_dev *dev)
 gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2));
                        list_del(&req_entry->re_entry);
                        req->length = len;
+                       spin_unlock_irqrestore(&dev->dev_lock, flags);
                        if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
                                printk(KERN_ERR
                                "gs_send: cannot queue read request, ret=%d\n",
                                        ret);
+                               spin_lock_irqsave(&dev->dev_lock, flags);
                                break;
                        }
+                       spin_lock_irqsave(&dev->dev_lock, flags);
                } else {
                        break;
                }