usb: dwc2: gadget: fix clear halt feature handling
authorGregory Herrero <gregory.herrero@intel.com>
Fri, 30 Jan 2015 08:09:27 +0000 (09:09 +0100)
committerFelipe Balbi <balbi@ti.com>
Fri, 30 Jan 2015 16:30:29 +0000 (10:30 -0600)
When clearing HALT on an endpoint, req->complete of in progress
requests must be called with locks off. New request should only be
started if there is not already a pending request on the endpoint.

Tested-by: Robert Baldyga <r.baldyga@samsung.com>
Acked-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Gregory Herrero <gregory.herrero@intel.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/dwc2/gadget.c

index 50ae09648cc17befd2f29abeb474dcc2233061c4..02d0e9af9242329ec8b8a38c3cf27b7d99e4169c 100644 (file)
@@ -1007,16 +1007,22 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
                                        hs_req = ep->req;
                                        ep->req = NULL;
                                        list_del_init(&hs_req->queue);
-                                       usb_gadget_giveback_request(&ep->ep,
-                                                                   &hs_req->req);
+                                       if (hs_req->req.complete) {
+                                               spin_unlock(&hsotg->lock);
+                                               usb_gadget_giveback_request(
+                                                       &ep->ep, &hs_req->req);
+                                               spin_lock(&hsotg->lock);
+                                       }
                                }
 
                                /* If we have pending request, then start it */
-                               restart = !list_empty(&ep->queue);
-                               if (restart) {
-                                       hs_req = get_ep_head(ep);
-                                       s3c_hsotg_start_req(hsotg, ep,
-                                                           hs_req, false);
+                               if (!ep->req) {
+                                       restart = !list_empty(&ep->queue);
+                                       if (restart) {
+                                               hs_req = get_ep_head(ep);
+                                               s3c_hsotg_start_req(hsotg, ep,
+                                                               hs_req, false);
+                                       }
                                }
                        }