aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-07-19 16:08:31 -0400
committerJiri Kosina <jkosina@suse.cz>2012-07-20 05:24:24 -0400
commit01a7c984e86fd45b760bb0da8b635059dff602e1 (patch)
tree5dfcbaf8c403825ff04c84be01def864a3e29813 /drivers
parent668160e5a80536251b4931a332dfe34d6ec2aeb7 (diff)
HID: usbhid: fix autosuspend calls
This patch (as1593) fixes some logic errors in the usbhid driver relating to runtime PM. The driver does not balance its calls to usb_autopm_get_interface_async() and usb_autopm_put_interface_async(). For example, when the control queue is restarted the driver does a _get. But the resume won't happen immediately, so the driver leaves the queue stopped. When the resume does occur, the queue is restarted and a second _get occurs, with no balancing _put. The patch fixes the problem by rearranging the logic for restarting the queues. All the _get/_put calls and bitflag settings in __usbhid_submit_report() are moved into the queue-restart routines. A balancing _put call is added for the case where the queue is still suspended. A call to irq_out_pump_restart(), which doesn't take all the right actions for restarting the irq-OUT queue, is replaced by a call to usbhid_restart_out_queue(), which does. Similarly for ctrl_pump_restart(). Finally, new code is added to prevent an autosuspend from happening every time an URB is cancelled, and the comments explaining what happens when an URB needs to be cancelled are expanded and clarified. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: Oliver Neukum <oliver@neukum.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hid/usbhid/hid-core.c146
1 files changed, 72 insertions, 74 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 6b9bad540702..213b3f39753c 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -213,9 +213,20 @@ static int usbhid_restart_out_queue(struct usbhid_device *usbhid)
213 if ((kicked = (usbhid->outhead != usbhid->outtail))) { 213 if ((kicked = (usbhid->outhead != usbhid->outtail))) {
214 hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); 214 hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail);
215 215
216 /* Try to wake up from autosuspend... */
216 r = usb_autopm_get_interface_async(usbhid->intf); 217 r = usb_autopm_get_interface_async(usbhid->intf);
217 if (r < 0) 218 if (r < 0)
218 return r; 219 return r;
220
221 /*
222 * If still suspended, don't submit. Submission will
223 * occur if/when resume drains the queue.
224 */
225 if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
226 usb_autopm_put_interface_no_suspend(usbhid->intf);
227 return r;
228 }
229
219 /* Asynchronously flush queue. */ 230 /* Asynchronously flush queue. */
220 set_bit(HID_OUT_RUNNING, &usbhid->iofl); 231 set_bit(HID_OUT_RUNNING, &usbhid->iofl);
221 if (hid_submit_out(hid)) { 232 if (hid_submit_out(hid)) {
@@ -240,9 +251,20 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid)
240 if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { 251 if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) {
241 hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); 252 hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail);
242 253
254 /* Try to wake up from autosuspend... */
243 r = usb_autopm_get_interface_async(usbhid->intf); 255 r = usb_autopm_get_interface_async(usbhid->intf);
244 if (r < 0) 256 if (r < 0)
245 return r; 257 return r;
258
259 /*
260 * If still suspended, don't submit. Submission will
261 * occur if/when resume drains the queue.
262 */
263 if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
264 usb_autopm_put_interface_no_suspend(usbhid->intf);
265 return r;
266 }
267
246 /* Asynchronously flush queue. */ 268 /* Asynchronously flush queue. */
247 set_bit(HID_CTRL_RUNNING, &usbhid->iofl); 269 set_bit(HID_CTRL_RUNNING, &usbhid->iofl);
248 if (hid_submit_ctrl(hid)) { 270 if (hid_submit_ctrl(hid)) {
@@ -546,49 +568,36 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
546 usbhid->out[usbhid->outhead].report = report; 568 usbhid->out[usbhid->outhead].report = report;
547 usbhid->outhead = head; 569 usbhid->outhead = head;
548 570
549 /* Try to awake from autosuspend... */ 571 /* If the queue isn't running, restart it */
550 if (usb_autopm_get_interface_async(usbhid->intf) < 0) 572 if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
551 return; 573 usbhid_restart_out_queue(usbhid);
552 574
553 /* 575 /* Otherwise see if an earlier request has timed out */
554 * But if still suspended, leave urb enqueued, don't submit. 576 } else if (time_after(jiffies, usbhid->last_out + HZ * 5)) {
555 * Submission will occur if/when resume() drains the queue. 577
556 */ 578 /* Prevent autosuspend following the unlink */
557 if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) 579 usb_autopm_get_interface_no_resume(usbhid->intf);
558 return;
559 580
560 if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
561 if (hid_submit_out(hid)) {
562 clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
563 usb_autopm_put_interface_async(usbhid->intf);
564 }
565 wake_up(&usbhid->wait);
566 } else {
567 /* 581 /*
568 * the queue is known to run 582 * Prevent resubmission in case the URB completes
569 * but an earlier request may be stuck 583 * before we can unlink it. We don't want to cancel
570 * we may need to time out 584 * the wrong transfer!
571 * no race because the URB is blocked under
572 * spinlock
573 */ 585 */
574 if (time_after(jiffies, usbhid->last_out + HZ * 5)) { 586 usb_block_urb(usbhid->urbout);
575 usb_block_urb(usbhid->urbout);
576 /* drop lock to not deadlock if the callback is called */
577 spin_unlock(&usbhid->lock);
578 usb_unlink_urb(usbhid->urbout);
579 spin_lock(&usbhid->lock);
580 usb_unblock_urb(usbhid->urbout);
581 /*
582 * if the unlinking has already completed
583 * the pump will have been stopped
584 * it must be restarted now
585 */
586 if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl))
587 if (!irq_out_pump_restart(hid))
588 set_bit(HID_OUT_RUNNING, &usbhid->iofl);
589 587
588 /* Drop lock to avoid deadlock if the callback runs */
589 spin_unlock(&usbhid->lock);
590 590
591 } 591 usb_unlink_urb(usbhid->urbout);
592 spin_lock(&usbhid->lock);
593 usb_unblock_urb(usbhid->urbout);
594
595 /* Unlink might have stopped the queue */
596 if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl))
597 usbhid_restart_out_queue(usbhid);
598
599 /* Now we can allow autosuspend again */
600 usb_autopm_put_interface_async(usbhid->intf);
592 } 601 }
593 return; 602 return;
594 } 603 }
@@ -610,47 +619,36 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
610 usbhid->ctrl[usbhid->ctrlhead].dir = dir; 619 usbhid->ctrl[usbhid->ctrlhead].dir = dir;
611 usbhid->ctrlhead = head; 620 usbhid->ctrlhead = head;
612 621
613 /* Try to awake from autosuspend... */ 622 /* If the queue isn't running, restart it */
614 if (usb_autopm_get_interface_async(usbhid->intf) < 0) 623 if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
615 return; 624 usbhid_restart_ctrl_queue(usbhid);
616 625
617 /* 626 /* Otherwise see if an earlier request has timed out */
618 * If already suspended, leave urb enqueued, but don't submit. 627 } else if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) {
619 * Submission will occur if/when resume() drains the queue. 628
620 */ 629 /* Prevent autosuspend following the unlink */
621 if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) 630 usb_autopm_get_interface_no_resume(usbhid->intf);
622 return;
623 631
624 if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
625 if (hid_submit_ctrl(hid)) {
626 clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
627 usb_autopm_put_interface_async(usbhid->intf);
628 }
629 wake_up(&usbhid->wait);
630 } else {
631 /* 632 /*
632 * the queue is known to run 633 * Prevent resubmission in case the URB completes
633 * but an earlier request may be stuck 634 * before we can unlink it. We don't want to cancel
634 * we may need to time out 635 * the wrong transfer!
635 * no race because the URB is blocked under
636 * spinlock
637 */ 636 */
638 if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) { 637 usb_block_urb(usbhid->urbctrl);
639 usb_block_urb(usbhid->urbctrl); 638
640 /* drop lock to not deadlock if the callback is called */ 639 /* Drop lock to avoid deadlock if the callback runs */
641 spin_unlock(&usbhid->lock); 640 spin_unlock(&usbhid->lock);
642 usb_unlink_urb(usbhid->urbctrl); 641
643 spin_lock(&usbhid->lock); 642 usb_unlink_urb(usbhid->urbctrl);
644 usb_unblock_urb(usbhid->urbctrl); 643 spin_lock(&usbhid->lock);
645 /* 644 usb_unblock_urb(usbhid->urbctrl);
646 * if the unlinking has already completed 645
647 * the pump will have been stopped 646 /* Unlink might have stopped the queue */
648 * it must be restarted now 647 if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
649 */ 648 usbhid_restart_ctrl_queue(usbhid);
650 if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) 649
651 if (!ctrl_pump_restart(hid)) 650 /* Now we can allow autosuspend again */
652 set_bit(HID_CTRL_RUNNING, &usbhid->iofl); 651 usb_autopm_put_interface_async(usbhid->intf);
653 }
654 } 652 }
655} 653}
656 654