diff options
Diffstat (limited to 'drivers/hid/hid-wiimote-core.c')
-rw-r--r-- | drivers/hid/hid-wiimote-core.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 00a9b6fa5189..a025d2104d3c 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -58,11 +58,11 @@ static enum power_supply_property wiimote_battery_props[] = { /* output queue handling */ -static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, - size_t count) +static int wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, + size_t count) { __u8 *buf; - ssize_t ret; + int ret; if (!hdev->hid_output_raw_report) return -ENODEV; @@ -84,14 +84,20 @@ static void wiimote_queue_worker(struct work_struct *work) struct wiimote_data *wdata = container_of(queue, struct wiimote_data, queue); unsigned long flags; + int ret; spin_lock_irqsave(&wdata->queue.lock, flags); while (wdata->queue.head != wdata->queue.tail) { spin_unlock_irqrestore(&wdata->queue.lock, flags); - wiimote_hid_send(wdata->hdev, + ret = wiimote_hid_send(wdata->hdev, wdata->queue.outq[wdata->queue.tail].data, wdata->queue.outq[wdata->queue.tail].size); + if (ret < 0) { + spin_lock_irqsave(&wdata->state.lock, flags); + wiimote_cmd_abort(wdata); + spin_unlock_irqrestore(&wdata->state.lock, flags); + } spin_lock_irqsave(&wdata->queue.lock, flags); wdata->queue.tail = (wdata->queue.tail + 1) % WIIMOTE_BUFSIZE; @@ -108,7 +114,9 @@ static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, if (count > HID_MAX_BUFFER_SIZE) { hid_warn(wdata->hdev, "Sending too large output report\n"); - return; + + spin_lock_irqsave(&wdata->queue.lock, flags); + goto out_error; } /* @@ -134,8 +142,14 @@ static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, wdata->queue.head = newhead; } else { hid_warn(wdata->hdev, "Output queue is full"); + goto out_error; } + goto out_unlock; + +out_error: + wiimote_cmd_abort(wdata); +out_unlock: spin_unlock_irqrestore(&wdata->queue.lock, flags); } |