diff options
author | Oliver Neukum <oneukum@suse.de> | 2010-07-15 12:19:51 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-07-15 12:30:52 -0400 |
commit | 5d9efc59e689445f1f8c4eceb125c1a12898e65c (patch) | |
tree | 21b21794e49de25f728aa0d974722f875fac95cf /drivers/input/touchscreen/usbtouchscreen.c | |
parent | ed4299e1b173f111ac0c40d6617e47fbff02b52f (diff) |
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: Oliver Neukum <oneukum@suse.de>
Tested-by: Petr Štetiar <ynezz@true.cz>
Tested-by: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/touchscreen/usbtouchscreen.c')
-rw-r--r-- | drivers/input/touchscreen/usbtouchscreen.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 9cda660ee7bb..77e671f8f1a4 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -1268,6 +1268,7 @@ static void usbtouch_irq(struct urb *urb) | |||
1268 | usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); | 1268 | usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); |
1269 | 1269 | ||
1270 | exit: | 1270 | exit: |
1271 | usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); | ||
1271 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 1272 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
1272 | if (retval) | 1273 | if (retval) |
1273 | err("%s - usb_submit_urb failed with result: %d", | 1274 | err("%s - usb_submit_urb failed with result: %d", |
@@ -1277,23 +1278,39 @@ exit: | |||
1277 | static int usbtouch_open(struct input_dev *input) | 1278 | static int usbtouch_open(struct input_dev *input) |
1278 | { | 1279 | { |
1279 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | 1280 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); |
1281 | int r; | ||
1280 | 1282 | ||
1281 | usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); | 1283 | usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); |
1282 | 1284 | ||
1285 | r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0; | ||
1286 | if (r < 0) | ||
1287 | goto out; | ||
1288 | |||
1283 | if (!usbtouch->type->irq_always) { | 1289 | if (!usbtouch->type->irq_always) { |
1284 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) | 1290 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) { |
1285 | return -EIO; | 1291 | r = -EIO; |
1292 | goto out_put; | ||
1293 | } | ||
1286 | } | 1294 | } |
1287 | 1295 | ||
1288 | return 0; | 1296 | usbtouch->interface->needs_remote_wakeup = 1; |
1297 | out_put: | ||
1298 | usb_autopm_put_interface(usbtouch->interface); | ||
1299 | out: | ||
1300 | return r; | ||
1289 | } | 1301 | } |
1290 | 1302 | ||
1291 | static void usbtouch_close(struct input_dev *input) | 1303 | static void usbtouch_close(struct input_dev *input) |
1292 | { | 1304 | { |
1293 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | 1305 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); |
1306 | int r; | ||
1294 | 1307 | ||
1295 | if (!usbtouch->type->irq_always) | 1308 | if (!usbtouch->type->irq_always) |
1296 | usb_kill_urb(usbtouch->irq); | 1309 | usb_kill_urb(usbtouch->irq); |
1310 | r = usb_autopm_get_interface(usbtouch->interface); | ||
1311 | usbtouch->interface->needs_remote_wakeup = 0; | ||
1312 | if (!r) | ||
1313 | usb_autopm_put_interface(usbtouch->interface); | ||
1297 | } | 1314 | } |
1298 | 1315 | ||
1299 | static int usbtouch_suspend | 1316 | static int usbtouch_suspend |
@@ -1457,8 +1474,11 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
1457 | usb_set_intfdata(intf, usbtouch); | 1474 | usb_set_intfdata(intf, usbtouch); |
1458 | 1475 | ||
1459 | if (usbtouch->type->irq_always) { | 1476 | if (usbtouch->type->irq_always) { |
1477 | /* this can't fail */ | ||
1478 | usb_autopm_get_interface(intf); | ||
1460 | err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); | 1479 | err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); |
1461 | if (err) { | 1480 | if (err) { |
1481 | usb_autopm_put_interface(intf); | ||
1462 | err("%s - usb_submit_urb failed with result: %d", | 1482 | err("%s - usb_submit_urb failed with result: %d", |
1463 | __func__, err); | 1483 | __func__, err); |
1464 | goto out_unregister_input; | 1484 | goto out_unregister_input; |
@@ -1512,6 +1532,7 @@ static struct usb_driver usbtouch_driver = { | |||
1512 | .suspend = usbtouch_suspend, | 1532 | .suspend = usbtouch_suspend, |
1513 | .resume = usbtouch_resume, | 1533 | .resume = usbtouch_resume, |
1514 | .id_table = usbtouch_devices, | 1534 | .id_table = usbtouch_devices, |
1535 | .supports_autosuspend = 1, | ||
1515 | }; | 1536 | }; |
1516 | 1537 | ||
1517 | static int __init usbtouch_init(void) | 1538 | static int __init usbtouch_init(void) |