From a93ab8494873a88622bf74be861a93f875643524 Mon Sep 17 00:00:00 2001 From: Bruno Prémont Date: Mon, 30 Jul 2012 21:38:57 +0200 Subject: HID: picoLCD: Improve unplug handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop earlier attempting to submit new reports/URBs (though locking and usbhid still prevents to bail out early enough to not produce multiple hid-picolcd 0003:04D8:C002.0003: usb_submit_urb(out) failed: -19 messages in kernel log. Strengthen framebuffer removal to be less racy. Signed-off-by: Bruno Prémont Signed-off-by: Jiri Kosina --- drivers/hid/hid-picolcd_core.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/hid/hid-picolcd_core.c') diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c index 8d5d341adeab..2d7ef688d66e 100644 --- a/drivers/hid/hid-picolcd_core.c +++ b/drivers/hid/hid-picolcd_core.c @@ -105,12 +105,17 @@ struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0); k++; } - data->pending = work; - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); - spin_unlock_irqrestore(&data->lock, flags); - wait_for_completion_interruptible_timeout(&work->ready, HZ*2); - spin_lock_irqsave(&data->lock, flags); - data->pending = NULL; + if (data->status & PICOLCD_FAILED) { + kfree(work); + work = NULL; + } else { + data->pending = work; + usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + spin_unlock_irqrestore(&data->lock, flags); + wait_for_completion_interruptible_timeout(&work->ready, HZ*2); + spin_lock_irqsave(&data->lock, flags); + data->pending = NULL; + } spin_unlock_irqrestore(&data->lock, flags); mutex_unlock(&data->mutex); return work; @@ -235,6 +240,10 @@ int picolcd_reset(struct hid_device *hdev) /* perform the reset */ hid_set_field(report->field[0], 0, 1); + if (data->status & PICOLCD_FAILED) { + spin_unlock_irqrestore(&data->lock, flags); + return -ENODEV; + } usbhid_submit_report(hdev, report, USB_DIR_OUT); spin_unlock_irqrestore(&data->lock, flags); -- cgit v1.2.3