|
@@ -67,7 +67,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
|
|
|
* Input submission and I/O error handler.
|
|
|
*/
|
|
|
static DEFINE_MUTEX(hid_open_mut);
|
|
|
-static struct workqueue_struct *resumption_waker;
|
|
|
|
|
|
static void hid_io_error(struct hid_device *hid);
|
|
|
static int hid_submit_out(struct hid_device *hid);
|
|
@@ -300,10 +299,19 @@ static int hid_submit_out(struct hid_device *hid)
|
|
|
struct hid_report *report;
|
|
|
char *raw_report;
|
|
|
struct usbhid_device *usbhid = hid->driver_data;
|
|
|
+ int r;
|
|
|
|
|
|
report = usbhid->out[usbhid->outtail].report;
|
|
|
raw_report = usbhid->out[usbhid->outtail].raw_report;
|
|
|
|
|
|
+ r = usb_autopm_get_interface_async(usbhid->intf);
|
|
|
+ if (r < 0)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * if the device hasn't been woken, we leave the output
|
|
|
+ * to resume()
|
|
|
+ */
|
|
|
if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
|
|
|
usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
|
|
|
usbhid->urbout->dev = hid_to_usb_dev(hid);
|
|
@@ -314,16 +322,10 @@ static int hid_submit_out(struct hid_device *hid)
|
|
|
|
|
|
if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
|
|
|
hid_err(hid, "usb_submit_urb(out) failed\n");
|
|
|
+ usb_autopm_put_interface_async(usbhid->intf);
|
|
|
return -1;
|
|
|
}
|
|
|
usbhid->last_out = jiffies;
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * queue work to wake up the device.
|
|
|
- * as the work queue is freezeable, this is safe
|
|
|
- * with respect to STD and STR
|
|
|
- */
|
|
|
- queue_work(resumption_waker, &usbhid->restart_work);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -334,13 +336,16 @@ static int hid_submit_ctrl(struct hid_device *hid)
|
|
|
struct hid_report *report;
|
|
|
unsigned char dir;
|
|
|
char *raw_report;
|
|
|
- int len;
|
|
|
+ int len, r;
|
|
|
struct usbhid_device *usbhid = hid->driver_data;
|
|
|
|
|
|
report = usbhid->ctrl[usbhid->ctrltail].report;
|
|
|
raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report;
|
|
|
dir = usbhid->ctrl[usbhid->ctrltail].dir;
|
|
|
|
|
|
+ r = usb_autopm_get_interface_async(usbhid->intf);
|
|
|
+ if (r < 0)
|
|
|
+ return -1;
|
|
|
if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
|
|
|
len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
|
|
|
if (dir == USB_DIR_OUT) {
|
|
@@ -375,17 +380,11 @@ static int hid_submit_ctrl(struct hid_device *hid)
|
|
|
usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
|
|
|
|
|
|
if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
|
|
|
+ usb_autopm_put_interface_async(usbhid->intf);
|
|
|
hid_err(hid, "usb_submit_urb(ctrl) failed\n");
|
|
|
return -1;
|
|
|
}
|
|
|
usbhid->last_ctrl = jiffies;
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * queue work to wake up the device.
|
|
|
- * as the work queue is freezeable, this is safe
|
|
|
- * with respect to STD and STR
|
|
|
- */
|
|
|
- queue_work(resumption_waker, &usbhid->restart_work);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -435,6 +434,7 @@ static void hid_irq_out(struct urb *urb)
|
|
|
|
|
|
clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
|
|
|
spin_unlock_irqrestore(&usbhid->lock, flags);
|
|
|
+ usb_autopm_put_interface_async(usbhid->intf);
|
|
|
wake_up(&usbhid->wait);
|
|
|
}
|
|
|
|
|
@@ -480,11 +480,13 @@ static void hid_ctrl(struct urb *urb)
|
|
|
wake_up(&usbhid->wait);
|
|
|
}
|
|
|
spin_unlock(&usbhid->lock);
|
|
|
+ usb_autopm_put_interface_async(usbhid->intf);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
|
|
|
spin_unlock(&usbhid->lock);
|
|
|
+ usb_autopm_put_interface_async(usbhid->intf);
|
|
|
wake_up(&usbhid->wait);
|
|
|
}
|
|
|
|
|
@@ -655,7 +657,7 @@ int usbhid_open(struct hid_device *hid)
|
|
|
mutex_lock(&hid_open_mut);
|
|
|
if (!hid->open++) {
|
|
|
res = usb_autopm_get_interface(usbhid->intf);
|
|
|
- /* the device must be awake to reliable request remote wakeup */
|
|
|
+ /* the device must be awake to reliably request remote wakeup */
|
|
|
if (res < 0) {
|
|
|
hid->open--;
|
|
|
mutex_unlock(&hid_open_mut);
|
|
@@ -856,18 +858,6 @@ static void usbhid_restart_queues(struct usbhid_device *usbhid)
|
|
|
usbhid_restart_ctrl_queue(usbhid);
|
|
|
}
|
|
|
|
|
|
-static void __usbhid_restart_queues(struct work_struct *work)
|
|
|
-{
|
|
|
- struct usbhid_device *usbhid =
|
|
|
- container_of(work, struct usbhid_device, restart_work);
|
|
|
- int r;
|
|
|
-
|
|
|
- r = usb_autopm_get_interface(usbhid->intf);
|
|
|
- if (r < 0)
|
|
|
- return;
|
|
|
- usb_autopm_put_interface(usbhid->intf);
|
|
|
-}
|
|
|
-
|
|
|
static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
|
|
|
{
|
|
|
struct usbhid_device *usbhid = hid->driver_data;
|
|
@@ -1204,7 +1194,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
|
|
|
|
|
|
init_waitqueue_head(&usbhid->wait);
|
|
|
INIT_WORK(&usbhid->reset_work, hid_reset);
|
|
|
- INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
|
|
|
setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
|
|
|
spin_lock_init(&usbhid->lock);
|
|
|
|
|
@@ -1239,7 +1228,6 @@ static void usbhid_disconnect(struct usb_interface *intf)
|
|
|
static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid)
|
|
|
{
|
|
|
del_timer_sync(&usbhid->io_retry);
|
|
|
- cancel_work_sync(&usbhid->restart_work);
|
|
|
cancel_work_sync(&usbhid->reset_work);
|
|
|
}
|
|
|
|
|
@@ -1260,7 +1248,6 @@ static int hid_pre_reset(struct usb_interface *intf)
|
|
|
spin_lock_irq(&usbhid->lock);
|
|
|
set_bit(HID_RESET_PENDING, &usbhid->iofl);
|
|
|
spin_unlock_irq(&usbhid->lock);
|
|
|
- cancel_work_sync(&usbhid->restart_work);
|
|
|
hid_cease_io(usbhid);
|
|
|
|
|
|
return 0;
|
|
@@ -1459,9 +1446,6 @@ static int __init hid_init(void)
|
|
|
{
|
|
|
int retval = -ENOMEM;
|
|
|
|
|
|
- resumption_waker = create_freezeable_workqueue("usbhid_resumer");
|
|
|
- if (!resumption_waker)
|
|
|
- goto no_queue;
|
|
|
retval = hid_register_driver(&hid_usb_driver);
|
|
|
if (retval)
|
|
|
goto hid_register_fail;
|
|
@@ -1479,8 +1463,6 @@ usb_register_fail:
|
|
|
usbhid_quirks_init_fail:
|
|
|
hid_unregister_driver(&hid_usb_driver);
|
|
|
hid_register_fail:
|
|
|
- destroy_workqueue(resumption_waker);
|
|
|
-no_queue:
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
@@ -1489,7 +1471,6 @@ static void __exit hid_exit(void)
|
|
|
usb_deregister(&hid_driver);
|
|
|
usbhid_quirks_exit();
|
|
|
hid_unregister_driver(&hid_usb_driver);
|
|
|
- destroy_workqueue(resumption_waker);
|
|
|
}
|
|
|
|
|
|
module_init(hid_init);
|