[PATCH V3 06/11] USB: gadget: Fix "scheduling while atomic" bugs in ci13xxx_udc

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxx>
---
 drivers/usb/gadget/ci13xxx_udc.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 4e9ec7d..d19537a 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -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
-- 
1.7.1
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux