]> git.karo-electronics.de Git - linux-beck.git/commitdiff
USB: gadget: Fix "scheduling while atomic" bugs in ci13xxx_udc
authorPavankumar Kondeti <pkondeti@codeaurora.org>
Tue, 7 Dec 2010 12:24:00 +0000 (17:54 +0530)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 10 Dec 2010 22:23:33 +0000 (14:23 -0800)
dma_pool_alloc() require sleeping context when called with GFP_KERNEL
argument.  Hence release the spin lock before calling dma_pool_alloc().

usb_ep_alloc_request can also be called with non-atomic GFP flags.  Hence
get rid off spin lock while allocation request memory.

Use GFP_ATOMIC flag for allocating request for ep0 in interrupt handler.

Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/gadget/ci13xxx_udc.c

index 4e9ec7d256fdca7c1a46efe5f362a9290d48877e..d19537a0613d3eb1b71bdb547fcbb71403984b2c 100644 (file)
@@ -1626,7 +1626,7 @@ __acquires(udc->lock)
        spin_unlock(udc->lock);
        retval = usb_ep_enable(&mEp->ep, &ctrl_endpt_desc);
        if (!retval) {
-               mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_KERNEL);
+               mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_ATOMIC);
                if (mEp->status == NULL) {
                        usb_ep_disable(&mEp->ep);
                        retval = -ENOMEM;
@@ -2055,7 +2055,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
 {
        struct ci13xxx_ep  *mEp  = container_of(ep, struct ci13xxx_ep, ep);
        struct ci13xxx_req *mReq = NULL;
-       unsigned long flags;
 
        trace("%p, %i", ep, gfp_flags);
 
@@ -2064,8 +2063,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
                return NULL;
        }
 
-       spin_lock_irqsave(mEp->lock, flags);
-
        mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
        if (mReq != NULL) {
                INIT_LIST_HEAD(&mReq->queue);
@@ -2080,8 +2077,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
 
        dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
 
-       spin_unlock_irqrestore(mEp->lock, flags);
-
        return (mReq == NULL) ? NULL : &mReq->req;
 }
 
@@ -2404,9 +2399,11 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
                /* this allocation cannot be random */
                for (k = RX; k <= TX; k++) {
                        INIT_LIST_HEAD(&mEp->qh[k].queue);
+                       spin_unlock_irqrestore(udc->lock, flags);
                        mEp->qh[k].ptr = dma_pool_alloc(udc->qh_pool,
                                                        GFP_KERNEL,
                                                        &mEp->qh[k].dma);
+                       spin_lock_irqsave(udc->lock, flags);
                        if (mEp->qh[k].ptr == NULL)
                                retval = -ENOMEM;
                        else