summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrzysztof Opasiak <kopasiak90@gmail.com>2017-01-19 18:55:27 +0100
committerGerrit - the friendly Code Review server <code-review@localhost>2019-01-09 05:56:22 -0800
commit712a014d96f49a0463ae0721c34df419b5915b19 (patch)
treea72ca4cd07b70037d3a30a010d763026ca72aac7
parentc059ef285c7fd4fb0643d3d22d494d49f6c07a76 (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. Change-Id: Ifeab1eff6223e6380b7a1f6db6900ca33ade9de1 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> Git-commit: b6092a57150c1641dffb6bfeebbe2cbde7275d1f Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git Signed-off-by: Ajay Agarwal <ajaya@codeaurora.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 a99ae39daed4..08b1dd4caeb3 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -383,20 +383,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)
{
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;
unsigned long flags;
- req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
- if (!req_list)
- return;
+ switch (req->status) {
+ case 0:
+ 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);
- list_add_tail(&req_list->list, &hidg->completed_out_req);
- spin_unlock_irqrestore(&hidg->spinlock, flags);
+ spin_lock_irqsave(&hidg->spinlock, flags);
+ list_add_tail(&req_list->list, &hidg->completed_out_req);
+ 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,