Commit afa9556b authored by Krzysztof Opasiak's avatar Krzysztof Opasiak Committed by Greg Kroah-Hartman

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>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6be8bf7c
...@@ -425,20 +425,36 @@ static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, ...@@ -425,20 +425,36 @@ 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;
req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC); switch (req->status) {
if (!req_list) case 0:
return; req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
if (!req_list) {
ERROR(cdev, "Unable to allocate mem for req_list\n");
goto free_req;
}
req_list->req = req; req_list->req = req;
spin_lock_irqsave(&hidg->spinlock, flags); spin_lock_irqsave(&hidg->spinlock, flags);
list_add_tail(&req_list->list, &hidg->completed_out_req); list_add_tail(&req_list->list, &hidg->completed_out_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