|
@@ -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)
|
|
|
{
|
|
|
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,
|