Commit 5d9efc59 authored by Oliver Neukum's avatar Oliver Neukum Committed by Dmitry Torokhov

Input: usbtouchscreen - implement runtime power management

This implement USB autosuspend while the device is opened for
devices that do remote wakeup with a fallback to open/close for
those devices that don't. Devices that require the host to
constantly poll them are never autosuspended.
Signed-off-by: default avatarOliver Neukum <oneukum@suse.de>
Tested-by: default avatarPetr Štetiar <ynezz@true.cz>
Tested-by: default avatarOndrej Zary <linux@rainbow-software.org>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent ed4299e1
...@@ -1268,6 +1268,7 @@ static void usbtouch_irq(struct urb *urb) ...@@ -1268,6 +1268,7 @@ static void usbtouch_irq(struct urb *urb)
usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length);
exit: exit:
usb_mark_last_busy(interface_to_usbdev(usbtouch->interface));
retval = usb_submit_urb(urb, GFP_ATOMIC); retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval) if (retval)
err("%s - usb_submit_urb failed with result: %d", err("%s - usb_submit_urb failed with result: %d",
...@@ -1277,23 +1278,39 @@ static void usbtouch_irq(struct urb *urb) ...@@ -1277,23 +1278,39 @@ static void usbtouch_irq(struct urb *urb)
static int usbtouch_open(struct input_dev *input) static int usbtouch_open(struct input_dev *input)
{ {
struct usbtouch_usb *usbtouch = input_get_drvdata(input); struct usbtouch_usb *usbtouch = input_get_drvdata(input);
int r;
usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface);
r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0;
if (r < 0)
goto out;
if (!usbtouch->type->irq_always) { if (!usbtouch->type->irq_always) {
if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) {
return -EIO; r = -EIO;
goto out_put;
}
} }
return 0; usbtouch->interface->needs_remote_wakeup = 1;
out_put:
usb_autopm_put_interface(usbtouch->interface);
out:
return r;
} }
static void usbtouch_close(struct input_dev *input) static void usbtouch_close(struct input_dev *input)
{ {
struct usbtouch_usb *usbtouch = input_get_drvdata(input); struct usbtouch_usb *usbtouch = input_get_drvdata(input);
int r;
if (!usbtouch->type->irq_always) if (!usbtouch->type->irq_always)
usb_kill_urb(usbtouch->irq); usb_kill_urb(usbtouch->irq);
r = usb_autopm_get_interface(usbtouch->interface);
usbtouch->interface->needs_remote_wakeup = 0;
if (!r)
usb_autopm_put_interface(usbtouch->interface);
} }
static int usbtouch_suspend static int usbtouch_suspend
...@@ -1457,8 +1474,11 @@ static int usbtouch_probe(struct usb_interface *intf, ...@@ -1457,8 +1474,11 @@ static int usbtouch_probe(struct usb_interface *intf,
usb_set_intfdata(intf, usbtouch); usb_set_intfdata(intf, usbtouch);
if (usbtouch->type->irq_always) { if (usbtouch->type->irq_always) {
/* this can't fail */
usb_autopm_get_interface(intf);
err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); err = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
if (err) { if (err) {
usb_autopm_put_interface(intf);
err("%s - usb_submit_urb failed with result: %d", err("%s - usb_submit_urb failed with result: %d",
__func__, err); __func__, err);
goto out_unregister_input; goto out_unregister_input;
...@@ -1512,6 +1532,7 @@ static struct usb_driver usbtouch_driver = { ...@@ -1512,6 +1532,7 @@ static struct usb_driver usbtouch_driver = {
.suspend = usbtouch_suspend, .suspend = usbtouch_suspend,
.resume = usbtouch_resume, .resume = usbtouch_resume,
.id_table = usbtouch_devices, .id_table = usbtouch_devices,
.supports_autosuspend = 1,
}; };
static int __init usbtouch_init(void) static int __init usbtouch_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment