aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2010-02-12 07:02:28 -0500
committerJiri Kosina <jkosina@suse.cz>2010-02-12 07:07:51 -0500
commit858155fbcc0cd713f6382c527bb1c3abc0ed6d00 (patch)
tree1b7c93ba35985e96b23b3ba0977e3fdd976fc45d /drivers/hid
parentc8a8602b76b6703df1243e31be01cf0e4451e4a6 (diff)
HID: usbhid: introduce timeout for stuck ctrl/out URBs
Some devices do not react to a control request (seen on APC UPS's) resulting in a slow stream of messages, "generic-usb ... control queue full". Therefore request needs a timeout. Cc: stable@kernel.org Signed-off-by: Oliver Neukum <oliver@neukum.org> Signed-off-by: David Fries <david@fries.net> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/usbhid/hid-core.c28
-rw-r--r--drivers/hid/usbhid/usbhid.h2
2 files changed, 28 insertions, 2 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 54060741d45b..74bd3ca220d3 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -316,6 +316,7 @@ static int hid_submit_out(struct hid_device *hid)
316 err_hid("usb_submit_urb(out) failed"); 316 err_hid("usb_submit_urb(out) failed");
317 return -1; 317 return -1;
318 } 318 }
319 usbhid->last_out = jiffies;
319 } else { 320 } else {
320 /* 321 /*
321 * queue work to wake up the device. 322 * queue work to wake up the device.
@@ -377,6 +378,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
377 err_hid("usb_submit_urb(ctrl) failed"); 378 err_hid("usb_submit_urb(ctrl) failed");
378 return -1; 379 return -1;
379 } 380 }
381 usbhid->last_ctrl = jiffies;
380 } else { 382 } else {
381 /* 383 /*
382 * queue work to wake up the device. 384 * queue work to wake up the device.
@@ -512,9 +514,20 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
512 usbhid->out[usbhid->outhead].report = report; 514 usbhid->out[usbhid->outhead].report = report;
513 usbhid->outhead = head; 515 usbhid->outhead = head;
514 516
515 if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) 517 if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
516 if (hid_submit_out(hid)) 518 if (hid_submit_out(hid))
517 clear_bit(HID_OUT_RUNNING, &usbhid->iofl); 519 clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
520 } else {
521 /*
522 * the queue is known to run
523 * but an earlier request may be stuck
524 * we may need to time out
525 * no race because this is called under
526 * spinlock
527 */
528 if (time_after(jiffies, usbhid->last_out + HZ * 5))
529 usb_unlink_urb(usbhid->urbout);
530 }
518 return; 531 return;
519 } 532 }
520 533
@@ -535,9 +548,20 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
535 usbhid->ctrl[usbhid->ctrlhead].dir = dir; 548 usbhid->ctrl[usbhid->ctrlhead].dir = dir;
536 usbhid->ctrlhead = head; 549 usbhid->ctrlhead = head;
537 550
538 if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) 551 if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
539 if (hid_submit_ctrl(hid)) 552 if (hid_submit_ctrl(hid))
540 clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); 553 clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
554 } else {
555 /*
556 * the queue is known to run
557 * but an earlier request may be stuck
558 * we may need to time out
559 * no race because this is called under
560 * spinlock
561 */
562 if (time_after(jiffies, usbhid->last_ctrl + HZ * 5))
563 usb_unlink_urb(usbhid->urbctrl);
564 }
541} 565}
542 566
543void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) 567void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 08f505ca2e3d..ec20400c7f29 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -80,12 +80,14 @@ struct usbhid_device {
80 unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ 80 unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
81 char *ctrlbuf; /* Control buffer */ 81 char *ctrlbuf; /* Control buffer */
82 dma_addr_t ctrlbuf_dma; /* Control buffer dma */ 82 dma_addr_t ctrlbuf_dma; /* Control buffer dma */
83 unsigned long last_ctrl; /* record of last output for timeouts */
83 84
84 struct urb *urbout; /* Output URB */ 85 struct urb *urbout; /* Output URB */
85 struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ 86 struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */
86 unsigned char outhead, outtail; /* Output pipe fifo head & tail */ 87 unsigned char outhead, outtail; /* Output pipe fifo head & tail */
87 char *outbuf; /* Output buffer */ 88 char *outbuf; /* Output buffer */
88 dma_addr_t outbuf_dma; /* Output buffer dma */ 89 dma_addr_t outbuf_dma; /* Output buffer dma */
90 unsigned long last_out; /* record of last output for timeouts */
89 91
90 spinlock_t lock; /* fifo spinlock */ 92 spinlock_t lock; /* fifo spinlock */
91 unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ 93 unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */