diff options
Diffstat (limited to 'drivers/hid/usbhid/hid-core.c')
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 105 |
1 files changed, 42 insertions, 63 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 5489eab..b336dd8 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 " * 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); @@ -136,10 +135,10 @@ static void hid_reset(struct work_struct *work) hid_io_error(hid); break; default: - err_hid("can't reset device, %s-%s/input%d, status %d", - hid_to_usb_dev(hid)->bus->bus_name, - hid_to_usb_dev(hid)->devpath, - usbhid->ifnum, rc); + hid_err(hid, "can't reset device, %s-%s/input%d, status %d\n", + hid_to_usb_dev(hid)->bus->bus_name, + hid_to_usb_dev(hid)->devpath, + usbhid->ifnum, rc); /* FALLTHROUGH */ case -EHOSTUNREACH: case -ENODEV: @@ -278,18 +277,18 @@ static void hid_irq_in(struct urb *urb) hid_io_error(hid); return; default: /* error */ - dev_warn(&urb->dev->dev, "input irq status %d " - "received\n", urb->status); + hid_warn(urb->dev, "input irq status %d received\n", + urb->status); } status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { clear_bit(HID_IN_RUNNING, &usbhid->iofl); if (status != -EPERM) { - err_hid("can't resubmit intr, %s-%s/input%d, status %d", - hid_to_usb_dev(hid)->bus->bus_name, - hid_to_usb_dev(hid)->devpath, - usbhid->ifnum, status); + hid_err(hid, "can't resubmit intr, %s-%s/input%d, status %d\n", + hid_to_usb_dev(hid)->bus->bus_name, + hid_to_usb_dev(hid)->devpath, + usbhid->ifnum, status); hid_io_error(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); @@ -313,17 +321,11 @@ static int hid_submit_out(struct hid_device *hid) dbg_hid("submitting out urb\n"); if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { - err_hid("usb_submit_urb(out) failed"); + 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)) { - err_hid("usb_submit_urb(ctrl) failed"); + 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; @@ -413,8 +412,8 @@ static void hid_irq_out(struct urb *urb) case -ENOENT: break; default: /* error */ - dev_warn(&urb->dev->dev, "output irq status %d " - "received\n", urb->status); + hid_warn(urb->dev, "output irq status %d received\n", + urb->status); } spin_lock_irqsave(&usbhid->lock, flags); @@ -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); } @@ -466,8 +466,7 @@ static void hid_ctrl(struct urb *urb) case -EPIPE: /* report not available */ break; default: /* error */ - dev_warn(&urb->dev->dev, "ctrl urb status %d " - "received\n", status); + hid_warn(urb->dev, "ctrl urb status %d received\n", status); } if (unplug) @@ -481,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); } @@ -501,13 +502,13 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { - dev_warn(&hid->dev, "output queue full\n"); + hid_warn(hid, "output queue full\n"); return; } usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); if (!usbhid->out[usbhid->outhead].raw_report) { - dev_warn(&hid->dev, "output queueing failed\n"); + hid_warn(hid, "output queueing failed\n"); return; } hid_output_report(report, usbhid->out[usbhid->outhead].raw_report); @@ -532,14 +533,14 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re } if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { - dev_warn(&hid->dev, "control queue full\n"); + hid_warn(hid, "control queue full\n"); return; } if (dir == USB_DIR_OUT) { usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { - dev_warn(&hid->dev, "control queueing failed\n"); + hid_warn(hid, "control queueing failed\n"); return; } hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report); @@ -590,7 +591,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un return -1; if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { - dev_warn(&dev->dev, "event field not found\n"); + hid_warn(dev, "event field not found\n"); return -1; } @@ -656,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); @@ -722,7 +723,7 @@ void usbhid_init_reports(struct hid_device *hid) } if (err) - dev_warn(&hid->dev, "timeout initializing reports\n"); + hid_warn(hid, "timeout initializing reports\n"); } /* @@ -857,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; @@ -1140,8 +1129,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * if (usb_endpoint_is_int_in(&interface->endpoint[n].desc)) has_in++; if (!has_in) { - dev_err(&intf->dev, "couldn't find an input interrupt " - "endpoint\n"); + hid_err(intf, "couldn't find an input interrupt endpoint\n"); return -ENODEV; } @@ -1206,14 +1194,13 @@ 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); ret = hid_add_device(hid); if (ret) { if (ret != -ENODEV) - dev_err(&intf->dev, "can't add hid device: %d\n", ret); + hid_err(intf, "can't add hid device: %d\n", ret); goto err_free; } @@ -1241,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); } @@ -1262,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; @@ -1461,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; @@ -1481,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; } @@ -1491,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); |