aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Opasiak <kopasiak90@gmail.com>2017-01-19 12:55:27 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-12 00:41:49 -0500
commitb6092a57150c1641dffb6bfeebbe2cbde7275d1f (patch)
tree255933fa5dfa9a7f49365fe44285ebf3bdf05099
parent92ee9483bc5fe7d4c2e6730515849467d818f8f7 (diff)
usb: gadget: f_hid: fix: Free out requests
commit 20d2ca955bd09639c7b01db5761d157c297aea0a upstream. Requests for out endpoint are allocated in bind() function but never released. This commit ensures that all pending requests are released when we disable out endpoint. Fixes: 99c515005857 ("usb: gadget: hidg: register OUT INT endpoint for SET_REPORT") Tested-by: David Lechner <david@lechnology.com> Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/gadget/function/f_hid.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index e2966f87c860..ceb1d0cc5c90 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -371,20 +371,36 @@ static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep,
371static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) 371static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
372{ 372{
373 struct f_hidg *hidg = (struct f_hidg *) req->context; 373 struct f_hidg *hidg = (struct f_hidg *) req->context;
374 struct usb_composite_dev *cdev = hidg->func.config->cdev;
374 struct f_hidg_req_list *req_list; 375 struct f_hidg_req_list *req_list;
375 unsigned long flags; 376 unsigned long flags;
376 377
377 req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC); 378 switch (req->status) {
378 if (!req_list) 379 case 0:
379 return; 380 req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
381 if (!req_list) {
382 ERROR(cdev, "Unable to allocate mem for req_list\n");
383 goto free_req;
384 }
380 385
381 req_list->req = req; 386 req_list->req = req;
382 387
383 spin_lock_irqsave(&hidg->spinlock, flags); 388 spin_lock_irqsave(&hidg->spinlock, flags);
384 list_add_tail(&req_list->list, &hidg->completed_out_req); 389 list_add_tail(&req_list->list, &hidg->completed_out_req);
385 spin_unlock_irqrestore(&hidg->spinlock, flags); 390 spin_unlock_irqrestore(&hidg->spinlock, flags);
386 391
387 wake_up(&hidg->read_queue); 392 wake_up(&hidg->read_queue);
393 break;
394 default:
395 ERROR(cdev, "Set report failed %d\n", req->status);
396 /* FALLTHROUGH */
397 case -ECONNABORTED: /* hardware forced ep reset */
398 case -ECONNRESET: /* request dequeued */
399 case -ESHUTDOWN: /* disconnect from host */
400free_req:
401 free_ep_req(ep, req);
402 return;
403 }
388} 404}
389 405
390static int hidg_setup(struct usb_function *f, 406static int hidg_setup(struct usb_function *f,