diff options
author | Oliver Neukum <oneukum@suse.de> | 2010-12-22 09:33:40 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2010-12-22 13:06:53 -0500 |
commit | 68229689b6dc950bea4b81dd60563884f4a7e1c5 (patch) | |
tree | 492329a1d82af8b4be881da356f4b1f67b13a343 | |
parent | 1874542d952bbea01997191aee868b472555fd9a (diff) |
HID: usbhid: base runtime PM on modern API
This patch doesn't alter functionality, but removes a dedicated kernel
thread.
Signed-off-by: Oliver Neukum <oneukum@suse.de>
Tested-by: Maulik Mankad <x0082077@ti.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 57 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbhid.h | 1 |
2 files changed, 19 insertions, 39 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 276758f53ab5..b336dd84036f 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -67,7 +67,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " | |||
67 | * Input submission and I/O error handler. | 67 | * Input submission and I/O error handler. |
68 | */ | 68 | */ |
69 | static DEFINE_MUTEX(hid_open_mut); | 69 | static DEFINE_MUTEX(hid_open_mut); |
70 | static struct workqueue_struct *resumption_waker; | ||
71 | 70 | ||
72 | static void hid_io_error(struct hid_device *hid); | 71 | static void hid_io_error(struct hid_device *hid); |
73 | static int hid_submit_out(struct hid_device *hid); | 72 | static int hid_submit_out(struct hid_device *hid); |
@@ -300,10 +299,19 @@ static int hid_submit_out(struct hid_device *hid) | |||
300 | struct hid_report *report; | 299 | struct hid_report *report; |
301 | char *raw_report; | 300 | char *raw_report; |
302 | struct usbhid_device *usbhid = hid->driver_data; | 301 | struct usbhid_device *usbhid = hid->driver_data; |
302 | int r; | ||
303 | 303 | ||
304 | report = usbhid->out[usbhid->outtail].report; | 304 | report = usbhid->out[usbhid->outtail].report; |
305 | raw_report = usbhid->out[usbhid->outtail].raw_report; | 305 | raw_report = usbhid->out[usbhid->outtail].raw_report; |
306 | 306 | ||
307 | r = usb_autopm_get_interface_async(usbhid->intf); | ||
308 | if (r < 0) | ||
309 | return -1; | ||
310 | |||
311 | /* | ||
312 | * if the device hasn't been woken, we leave the output | ||
313 | * to resume() | ||
314 | */ | ||
307 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | 315 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { |
308 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 316 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
309 | usbhid->urbout->dev = hid_to_usb_dev(hid); | 317 | usbhid->urbout->dev = hid_to_usb_dev(hid); |
@@ -314,16 +322,10 @@ static int hid_submit_out(struct hid_device *hid) | |||
314 | 322 | ||
315 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { | 323 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { |
316 | hid_err(hid, "usb_submit_urb(out) failed\n"); | 324 | hid_err(hid, "usb_submit_urb(out) failed\n"); |
325 | usb_autopm_put_interface_async(usbhid->intf); | ||
317 | return -1; | 326 | return -1; |
318 | } | 327 | } |
319 | usbhid->last_out = jiffies; | 328 | usbhid->last_out = jiffies; |
320 | } else { | ||
321 | /* | ||
322 | * queue work to wake up the device. | ||
323 | * as the work queue is freezeable, this is safe | ||
324 | * with respect to STD and STR | ||
325 | */ | ||
326 | queue_work(resumption_waker, &usbhid->restart_work); | ||
327 | } | 329 | } |
328 | 330 | ||
329 | return 0; | 331 | return 0; |
@@ -334,13 +336,16 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
334 | struct hid_report *report; | 336 | struct hid_report *report; |
335 | unsigned char dir; | 337 | unsigned char dir; |
336 | char *raw_report; | 338 | char *raw_report; |
337 | int len; | 339 | int len, r; |
338 | struct usbhid_device *usbhid = hid->driver_data; | 340 | struct usbhid_device *usbhid = hid->driver_data; |
339 | 341 | ||
340 | report = usbhid->ctrl[usbhid->ctrltail].report; | 342 | report = usbhid->ctrl[usbhid->ctrltail].report; |
341 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; | 343 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; |
342 | dir = usbhid->ctrl[usbhid->ctrltail].dir; | 344 | dir = usbhid->ctrl[usbhid->ctrltail].dir; |
343 | 345 | ||
346 | r = usb_autopm_get_interface_async(usbhid->intf); | ||
347 | if (r < 0) | ||
348 | return -1; | ||
344 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | 349 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { |
345 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 350 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
346 | if (dir == USB_DIR_OUT) { | 351 | if (dir == USB_DIR_OUT) { |
@@ -375,17 +380,11 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
375 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | 380 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); |
376 | 381 | ||
377 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | 382 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { |
383 | usb_autopm_put_interface_async(usbhid->intf); | ||
378 | hid_err(hid, "usb_submit_urb(ctrl) failed\n"); | 384 | hid_err(hid, "usb_submit_urb(ctrl) failed\n"); |
379 | return -1; | 385 | return -1; |
380 | } | 386 | } |
381 | usbhid->last_ctrl = jiffies; | 387 | usbhid->last_ctrl = jiffies; |
382 | } else { | ||
383 | /* | ||
384 | * queue work to wake up the device. | ||
385 | * as the work queue is freezeable, this is safe | ||
386 | * with respect to STD and STR | ||
387 | */ | ||
388 | queue_work(resumption_waker, &usbhid->restart_work); | ||
389 | } | 388 | } |
390 | 389 | ||
391 | return 0; | 390 | return 0; |
@@ -435,6 +434,7 @@ static void hid_irq_out(struct urb *urb) | |||
435 | 434 | ||
436 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 435 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
437 | spin_unlock_irqrestore(&usbhid->lock, flags); | 436 | spin_unlock_irqrestore(&usbhid->lock, flags); |
437 | usb_autopm_put_interface_async(usbhid->intf); | ||
438 | wake_up(&usbhid->wait); | 438 | wake_up(&usbhid->wait); |
439 | } | 439 | } |
440 | 440 | ||
@@ -480,11 +480,13 @@ static void hid_ctrl(struct urb *urb) | |||
480 | wake_up(&usbhid->wait); | 480 | wake_up(&usbhid->wait); |
481 | } | 481 | } |
482 | spin_unlock(&usbhid->lock); | 482 | spin_unlock(&usbhid->lock); |
483 | usb_autopm_put_interface_async(usbhid->intf); | ||
483 | return; | 484 | return; |
484 | } | 485 | } |
485 | 486 | ||
486 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 487 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
487 | spin_unlock(&usbhid->lock); | 488 | spin_unlock(&usbhid->lock); |
489 | usb_autopm_put_interface_async(usbhid->intf); | ||
488 | wake_up(&usbhid->wait); | 490 | wake_up(&usbhid->wait); |
489 | } | 491 | } |
490 | 492 | ||
@@ -655,7 +657,7 @@ int usbhid_open(struct hid_device *hid) | |||
655 | mutex_lock(&hid_open_mut); | 657 | mutex_lock(&hid_open_mut); |
656 | if (!hid->open++) { | 658 | if (!hid->open++) { |
657 | res = usb_autopm_get_interface(usbhid->intf); | 659 | res = usb_autopm_get_interface(usbhid->intf); |
658 | /* the device must be awake to reliable request remote wakeup */ | 660 | /* the device must be awake to reliably request remote wakeup */ |
659 | if (res < 0) { | 661 | if (res < 0) { |
660 | hid->open--; | 662 | hid->open--; |
661 | mutex_unlock(&hid_open_mut); | 663 | mutex_unlock(&hid_open_mut); |
@@ -856,18 +858,6 @@ static void usbhid_restart_queues(struct usbhid_device *usbhid) | |||
856 | usbhid_restart_ctrl_queue(usbhid); | 858 | usbhid_restart_ctrl_queue(usbhid); |
857 | } | 859 | } |
858 | 860 | ||
859 | static void __usbhid_restart_queues(struct work_struct *work) | ||
860 | { | ||
861 | struct usbhid_device *usbhid = | ||
862 | container_of(work, struct usbhid_device, restart_work); | ||
863 | int r; | ||
864 | |||
865 | r = usb_autopm_get_interface(usbhid->intf); | ||
866 | if (r < 0) | ||
867 | return; | ||
868 | usb_autopm_put_interface(usbhid->intf); | ||
869 | } | ||
870 | |||
871 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | 861 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) |
872 | { | 862 | { |
873 | struct usbhid_device *usbhid = hid->driver_data; | 863 | struct usbhid_device *usbhid = hid->driver_data; |
@@ -1204,7 +1194,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * | |||
1204 | 1194 | ||
1205 | init_waitqueue_head(&usbhid->wait); | 1195 | init_waitqueue_head(&usbhid->wait); |
1206 | INIT_WORK(&usbhid->reset_work, hid_reset); | 1196 | INIT_WORK(&usbhid->reset_work, hid_reset); |
1207 | INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); | ||
1208 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | 1197 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); |
1209 | spin_lock_init(&usbhid->lock); | 1198 | spin_lock_init(&usbhid->lock); |
1210 | 1199 | ||
@@ -1239,7 +1228,6 @@ static void usbhid_disconnect(struct usb_interface *intf) | |||
1239 | static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) | 1228 | static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) |
1240 | { | 1229 | { |
1241 | del_timer_sync(&usbhid->io_retry); | 1230 | del_timer_sync(&usbhid->io_retry); |
1242 | cancel_work_sync(&usbhid->restart_work); | ||
1243 | cancel_work_sync(&usbhid->reset_work); | 1231 | cancel_work_sync(&usbhid->reset_work); |
1244 | } | 1232 | } |
1245 | 1233 | ||
@@ -1260,7 +1248,6 @@ static int hid_pre_reset(struct usb_interface *intf) | |||
1260 | spin_lock_irq(&usbhid->lock); | 1248 | spin_lock_irq(&usbhid->lock); |
1261 | set_bit(HID_RESET_PENDING, &usbhid->iofl); | 1249 | set_bit(HID_RESET_PENDING, &usbhid->iofl); |
1262 | spin_unlock_irq(&usbhid->lock); | 1250 | spin_unlock_irq(&usbhid->lock); |
1263 | cancel_work_sync(&usbhid->restart_work); | ||
1264 | hid_cease_io(usbhid); | 1251 | hid_cease_io(usbhid); |
1265 | 1252 | ||
1266 | return 0; | 1253 | return 0; |
@@ -1459,9 +1446,6 @@ static int __init hid_init(void) | |||
1459 | { | 1446 | { |
1460 | int retval = -ENOMEM; | 1447 | int retval = -ENOMEM; |
1461 | 1448 | ||
1462 | resumption_waker = create_freezeable_workqueue("usbhid_resumer"); | ||
1463 | if (!resumption_waker) | ||
1464 | goto no_queue; | ||
1465 | retval = hid_register_driver(&hid_usb_driver); | 1449 | retval = hid_register_driver(&hid_usb_driver); |
1466 | if (retval) | 1450 | if (retval) |
1467 | goto hid_register_fail; | 1451 | goto hid_register_fail; |
@@ -1479,8 +1463,6 @@ usb_register_fail: | |||
1479 | usbhid_quirks_init_fail: | 1463 | usbhid_quirks_init_fail: |
1480 | hid_unregister_driver(&hid_usb_driver); | 1464 | hid_unregister_driver(&hid_usb_driver); |
1481 | hid_register_fail: | 1465 | hid_register_fail: |
1482 | destroy_workqueue(resumption_waker); | ||
1483 | no_queue: | ||
1484 | return retval; | 1466 | return retval; |
1485 | } | 1467 | } |
1486 | 1468 | ||
@@ -1489,7 +1471,6 @@ static void __exit hid_exit(void) | |||
1489 | usb_deregister(&hid_driver); | 1471 | usb_deregister(&hid_driver); |
1490 | usbhid_quirks_exit(); | 1472 | usbhid_quirks_exit(); |
1491 | hid_unregister_driver(&hid_usb_driver); | 1473 | hid_unregister_driver(&hid_usb_driver); |
1492 | destroy_workqueue(resumption_waker); | ||
1493 | } | 1474 | } |
1494 | 1475 | ||
1495 | module_init(hid_init); | 1476 | module_init(hid_init); |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 89d2e847dcc6..1673cac93d77 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -95,7 +95,6 @@ struct usbhid_device { | |||
95 | unsigned long stop_retry; /* Time to give up, in jiffies */ | 95 | unsigned long stop_retry; /* Time to give up, in jiffies */ |
96 | unsigned int retry_delay; /* Delay length in ms */ | 96 | unsigned int retry_delay; /* Delay length in ms */ |
97 | struct work_struct reset_work; /* Task context for resets */ | 97 | struct work_struct reset_work; /* Task context for resets */ |
98 | struct work_struct restart_work; /* waking up for output to be done in a task */ | ||
99 | wait_queue_head_t wait; /* For sleeping */ | 98 | wait_queue_head_t wait; /* For sleeping */ |
100 | int ledcount; /* counting the number of active leds */ | 99 | int ledcount; /* counting the number of active leds */ |
101 | }; | 100 | }; |