Commit 6ecc5f5c authored by Krzysztof Opasiak's avatar Krzysztof Opasiak Committed by Ben Hutchings

usb: gadget: f_hid: fix: Free out requests

commit 20d2ca95 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: 99c51500 ("usb: gadget: hidg: register OUT INT endpoint for SET_REPORT")
Tested-by: default avatarDavid Lechner <david@lechnology.com>
Signed-off-by: default avatarKrzysztof Opasiak <k.opasiak@samsung.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
[bwh: Backported to 3.16: adjust filename]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 208542e4
...@@ -345,12 +345,17 @@ static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, ...@@ -345,12 +345,17 @@ static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep,
static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
{ {
struct f_hidg *hidg = (struct f_hidg *) req->context; struct f_hidg *hidg = (struct f_hidg *) req->context;
struct usb_composite_dev *cdev = hidg->func.config->cdev;
struct f_hidg_req_list *req_list; struct f_hidg_req_list *req_list;
unsigned long flags; unsigned long flags;
switch (req->status) {
case 0:
req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC); req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
if (!req_list) if (!req_list) {
return; ERROR(cdev, "Unable to allocate mem for req_list\n");
goto free_req;
}
req_list->req = req; req_list->req = req;
...@@ -359,6 +364,17 @@ static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -359,6 +364,17 @@ static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
spin_unlock_irqrestore(&hidg->spinlock, flags); spin_unlock_irqrestore(&hidg->spinlock, flags);
wake_up(&hidg->read_queue); wake_up(&hidg->read_queue);
break;
default:
ERROR(cdev, "Set report failed %d\n", req->status);
/* FALLTHROUGH */
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
free_req:
free_ep_req(ep, req);
return;
}
} }
static int hidg_setup(struct usb_function *f, static int hidg_setup(struct usb_function *f,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment