[PATCH] USB: lh7a40x gadget driver: Fixed a dead lock
authorFranck Bui-Huu <vagabon.xyz@gmail.com>
Thu, 23 Feb 2006 08:35:06 +0000 (09:35 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 28 Feb 2006 20:42:06 +0000 (12:42 -0800)
There is a dead lock in lh7a40x udc driver. When the driver receive a
SET_FEATURE HALT request, the dev lock is taken by the interrupt
handler lh7a40x_udc_irq then the handler will call lh7a40x_set_halt
function which in its turn will try to acquire the dev lock.

Signed-off-by: Franck Bui-Huu <franck.bui-huu@innova-card.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/lh7a40x_udc.c

index e02fea5a54339da5de3351927f880a724e7a58e4..1a362c5e7f3d05c88fdfc66af743c30dfc067a91 100644 (file)
@@ -1062,11 +1062,11 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
        ep->pio_irqs = 0;
        ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
 
+       spin_unlock_irqrestore(&ep->dev->lock, flags);
+
        /* Reset halt state (does flush) */
        lh7a40x_set_halt(_ep, 0);
 
-       spin_unlock_irqrestore(&ep->dev->lock, flags);
-
        DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name);
        return 0;
 }
@@ -1775,6 +1775,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
                                        break;
 
                                qep = &dev->ep[ep_num];
+                               spin_unlock(&dev->lock);
                                if (ctrl.bRequest == USB_REQ_SET_FEATURE) {
                                        DEBUG_SETUP("SET_FEATURE (%d)\n",
                                                    ep_num);
@@ -1784,6 +1785,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
                                                    ep_num);
                                        lh7a40x_set_halt(&qep->ep, 0);
                                }
+                               spin_lock(&dev->lock);
                                usb_set_index(0);
 
                                /* Reply with a ZLP on next IN token */