diff options
-rw-r--r-- | Documentation/usb/power-management.txt | 60 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 31 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 45 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 25 | ||||
-rw-r--r-- | include/linux/usb.h | 26 |
5 files changed, 74 insertions, 113 deletions
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt index 8817368203d6..c7c1dc2f8017 100644 --- a/Documentation/usb/power-management.txt +++ b/Documentation/usb/power-management.txt | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | Alan Stern <stern@rowland.harvard.edu> | 3 | Alan Stern <stern@rowland.harvard.edu> |
4 | 4 | ||
5 | October 5, 2007 | 5 | November 10, 2009 |
6 | 6 | ||
7 | 7 | ||
8 | 8 | ||
@@ -123,9 +123,9 @@ relevant attribute files are: wakeup, level, and autosuspend. | |||
123 | 123 | ||
124 | power/level | 124 | power/level |
125 | 125 | ||
126 | This file contains one of three words: "on", "auto", | 126 | This file contains one of two words: "on" or "auto". |
127 | or "suspend". You can write those words to the file | 127 | You can write those words to the file to change the |
128 | to change the device's setting. | 128 | device's setting. |
129 | 129 | ||
130 | "on" means that the device should be resumed and | 130 | "on" means that the device should be resumed and |
131 | autosuspend is not allowed. (Of course, system | 131 | autosuspend is not allowed. (Of course, system |
@@ -134,10 +134,10 @@ relevant attribute files are: wakeup, level, and autosuspend. | |||
134 | "auto" is the normal state in which the kernel is | 134 | "auto" is the normal state in which the kernel is |
135 | allowed to autosuspend and autoresume the device. | 135 | allowed to autosuspend and autoresume the device. |
136 | 136 | ||
137 | "suspend" means that the device should remain | 137 | (In kernels up to 2.6.32, you could also specify |
138 | suspended, and autoresume is not allowed. (But remote | 138 | "suspend", meaning that the device should remain |
139 | wakeup may still be allowed, since it is controlled | 139 | suspended and autoresume was not allowed. This |
140 | separately by the power/wakeup attribute.) | 140 | setting is no longer supported.) |
141 | 141 | ||
142 | power/autosuspend | 142 | power/autosuspend |
143 | 143 | ||
@@ -313,13 +313,14 @@ three of the methods listed above. In addition, a driver indicates | |||
313 | that it supports autosuspend by setting the .supports_autosuspend flag | 313 | that it supports autosuspend by setting the .supports_autosuspend flag |
314 | in its usb_driver structure. It is then responsible for informing the | 314 | in its usb_driver structure. It is then responsible for informing the |
315 | USB core whenever one of its interfaces becomes busy or idle. The | 315 | USB core whenever one of its interfaces becomes busy or idle. The |
316 | driver does so by calling these five functions: | 316 | driver does so by calling these six functions: |
317 | 317 | ||
318 | int usb_autopm_get_interface(struct usb_interface *intf); | 318 | int usb_autopm_get_interface(struct usb_interface *intf); |
319 | void usb_autopm_put_interface(struct usb_interface *intf); | 319 | void usb_autopm_put_interface(struct usb_interface *intf); |
320 | int usb_autopm_set_interface(struct usb_interface *intf); | ||
321 | int usb_autopm_get_interface_async(struct usb_interface *intf); | 320 | int usb_autopm_get_interface_async(struct usb_interface *intf); |
322 | void usb_autopm_put_interface_async(struct usb_interface *intf); | 321 | void usb_autopm_put_interface_async(struct usb_interface *intf); |
322 | void usb_autopm_get_interface_no_resume(struct usb_interface *intf); | ||
323 | void usb_autopm_put_interface_no_suspend(struct usb_interface *intf); | ||
323 | 324 | ||
324 | The functions work by maintaining a counter in the usb_interface | 325 | The functions work by maintaining a counter in the usb_interface |
325 | structure. When intf->pm_usage_count is > 0 then the interface is | 326 | structure. When intf->pm_usage_count is > 0 then the interface is |
@@ -331,11 +332,13 @@ considered to be idle, and the kernel may autosuspend the device. | |||
331 | associated with the device itself rather than any of its interfaces. | 332 | associated with the device itself rather than any of its interfaces. |
332 | This field is used only by the USB core.) | 333 | This field is used only by the USB core.) |
333 | 334 | ||
334 | The driver owns intf->pm_usage_count; it can modify the value however | 335 | Drivers must not modify intf->pm_usage_count directly; its value |
335 | and whenever it likes. A nice aspect of the non-async usb_autopm_* | 336 | should be changed only be using the functions listed above. Drivers |
336 | routines is that the changes they make are protected by the usb_device | 337 | are responsible for insuring that the overall change to pm_usage_count |
337 | structure's PM mutex (udev->pm_mutex); however drivers may change | 338 | during their lifetime balances out to 0 (it may be necessary for the |
338 | pm_usage_count without holding the mutex. Drivers using the async | 339 | disconnect method to call usb_autopm_put_interface() one or more times |
340 | to fulfill this requirement). The first two routines use the PM mutex | ||
341 | in struct usb_device for mutual exclusion; drivers using the async | ||
339 | routines are responsible for their own synchronization and mutual | 342 | routines are responsible for their own synchronization and mutual |
340 | exclusion. | 343 | exclusion. |
341 | 344 | ||
@@ -347,11 +350,6 @@ exclusion. | |||
347 | attempts an autosuspend if the new value is <= 0 and the | 350 | attempts an autosuspend if the new value is <= 0 and the |
348 | device isn't suspended. | 351 | device isn't suspended. |
349 | 352 | ||
350 | usb_autopm_set_interface() leaves pm_usage_count alone. | ||
351 | It attempts an autoresume if the value is > 0 and the device | ||
352 | is suspended, and it attempts an autosuspend if the value is | ||
353 | <= 0 and the device isn't suspended. | ||
354 | |||
355 | usb_autopm_get_interface_async() and | 353 | usb_autopm_get_interface_async() and |
356 | usb_autopm_put_interface_async() do almost the same things as | 354 | usb_autopm_put_interface_async() do almost the same things as |
357 | their non-async counterparts. The differences are: they do | 355 | their non-async counterparts. The differences are: they do |
@@ -360,13 +358,11 @@ exclusion. | |||
360 | such as an URB's completion handler, but when they return the | 358 | such as an URB's completion handler, but when they return the |
361 | device will not generally not yet be in the desired state. | 359 | device will not generally not yet be in the desired state. |
362 | 360 | ||
363 | There also are a couple of utility routines drivers can use: | 361 | usb_autopm_get_interface_no_resume() and |
364 | 362 | usb_autopm_put_interface_no_suspend() merely increment or | |
365 | usb_autopm_enable() sets pm_usage_cnt to 0 and then calls | 363 | decrement the pm_usage_count value; they do not attempt to |
366 | usb_autopm_set_interface(), which will attempt an autosuspend. | 364 | carry out an autoresume or an autosuspend. Hence they can be |
367 | 365 | called in an atomic context. | |
368 | usb_autopm_disable() sets pm_usage_cnt to 1 and then calls | ||
369 | usb_autopm_set_interface(), which will attempt an autoresume. | ||
370 | 366 | ||
371 | The conventional usage pattern is that a driver calls | 367 | The conventional usage pattern is that a driver calls |
372 | usb_autopm_get_interface() in its open routine and | 368 | usb_autopm_get_interface() in its open routine and |
@@ -400,11 +396,11 @@ though, setting this flag won't cause the kernel to autoresume it. | |||
400 | Normally a driver would set this flag in its probe method, at which | 396 | Normally a driver would set this flag in its probe method, at which |
401 | time the device is guaranteed not to be autosuspended.) | 397 | time the device is guaranteed not to be autosuspended.) |
402 | 398 | ||
403 | The usb_autopm_* routines have to run in a sleepable process context; | 399 | The synchronous usb_autopm_* routines have to run in a sleepable |
404 | they must not be called from an interrupt handler or while holding a | 400 | process context; they must not be called from an interrupt handler or |
405 | spinlock. In fact, the entire autosuspend mechanism is not well geared | 401 | while holding a spinlock. In fact, the entire autosuspend mechanism |
406 | toward interrupt-driven operation. However there is one thing a | 402 | is not well geared toward interrupt-driven operation. However there |
407 | driver can do in an interrupt handler: | 403 | is one thing a driver can do in an interrupt handler: |
408 | 404 | ||
409 | usb_mark_last_busy(struct usb_device *udev); | 405 | usb_mark_last_busy(struct usb_device *udev); |
410 | 406 | ||
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8016a296010e..7a05bab73960 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -948,8 +948,6 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg) | |||
948 | 948 | ||
949 | done: | 949 | done: |
950 | dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); | 950 | dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); |
951 | if (status == 0) | ||
952 | udev->autoresume_disabled = 0; | ||
953 | return status; | 951 | return status; |
954 | } | 952 | } |
955 | 953 | ||
@@ -1280,11 +1278,6 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg) | |||
1280 | 1278 | ||
1281 | /* Propagate the resume up the tree, if necessary */ | 1279 | /* Propagate the resume up the tree, if necessary */ |
1282 | if (udev->state == USB_STATE_SUSPENDED) { | 1280 | if (udev->state == USB_STATE_SUSPENDED) { |
1283 | if ((msg.event & PM_EVENT_AUTO) && | ||
1284 | udev->autoresume_disabled) { | ||
1285 | status = -EPERM; | ||
1286 | goto done; | ||
1287 | } | ||
1288 | if (parent) { | 1281 | if (parent) { |
1289 | status = usb_autoresume_device(parent); | 1282 | status = usb_autoresume_device(parent); |
1290 | if (status == 0) { | 1283 | if (status == 0) { |
@@ -1638,8 +1631,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf) | |||
1638 | 1631 | ||
1639 | if (intf->condition == USB_INTERFACE_UNBOUND) | 1632 | if (intf->condition == USB_INTERFACE_UNBOUND) |
1640 | status = -ENODEV; | 1633 | status = -ENODEV; |
1641 | else if (udev->autoresume_disabled) | ||
1642 | status = -EPERM; | ||
1643 | else { | 1634 | else { |
1644 | atomic_inc(&intf->pm_usage_cnt); | 1635 | atomic_inc(&intf->pm_usage_cnt); |
1645 | if (atomic_read(&intf->pm_usage_cnt) > 0 && | 1636 | if (atomic_read(&intf->pm_usage_cnt) > 0 && |
@@ -1652,28 +1643,6 @@ int usb_autopm_get_interface_async(struct usb_interface *intf) | |||
1652 | } | 1643 | } |
1653 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async); | 1644 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async); |
1654 | 1645 | ||
1655 | /** | ||
1656 | * usb_autopm_set_interface - set a USB interface's autosuspend state | ||
1657 | * @intf: the usb_interface whose state should be set | ||
1658 | * | ||
1659 | * This routine sets the autosuspend state of @intf's device according | ||
1660 | * to @intf's usage counter, which the caller must have set previously. | ||
1661 | * If the counter is <= 0, the device is autosuspended (if it isn't | ||
1662 | * already suspended and if nothing else prevents the autosuspend). If | ||
1663 | * the counter is > 0, the device is autoresumed (if it isn't already | ||
1664 | * awake). | ||
1665 | */ | ||
1666 | int usb_autopm_set_interface(struct usb_interface *intf) | ||
1667 | { | ||
1668 | int status; | ||
1669 | |||
1670 | status = usb_autopm_do_interface(intf, 0); | ||
1671 | dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", | ||
1672 | __func__, status, atomic_read(&intf->pm_usage_cnt)); | ||
1673 | return status; | ||
1674 | } | ||
1675 | EXPORT_SYMBOL_GPL(usb_autopm_set_interface); | ||
1676 | |||
1677 | #else | 1646 | #else |
1678 | 1647 | ||
1679 | void usb_autosuspend_work(struct work_struct *work) | 1648 | void usb_autosuspend_work(struct work_struct *work) |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5413d712cae0..b38fd6730e2a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -71,6 +71,7 @@ struct usb_hub { | |||
71 | 71 | ||
72 | unsigned mA_per_port; /* current for each child */ | 72 | unsigned mA_per_port; /* current for each child */ |
73 | 73 | ||
74 | unsigned init_done:1; | ||
74 | unsigned limited_power:1; | 75 | unsigned limited_power:1; |
75 | unsigned quiescing:1; | 76 | unsigned quiescing:1; |
76 | unsigned disconnected:1; | 77 | unsigned disconnected:1; |
@@ -375,12 +376,13 @@ static void kick_khubd(struct usb_hub *hub) | |||
375 | { | 376 | { |
376 | unsigned long flags; | 377 | unsigned long flags; |
377 | 378 | ||
378 | /* Suppress autosuspend until khubd runs */ | ||
379 | atomic_set(&to_usb_interface(hub->intfdev)->pm_usage_cnt, 1); | ||
380 | |||
381 | spin_lock_irqsave(&hub_event_lock, flags); | 379 | spin_lock_irqsave(&hub_event_lock, flags); |
382 | if (!hub->disconnected && list_empty(&hub->event_list)) { | 380 | if (!hub->disconnected && list_empty(&hub->event_list)) { |
383 | list_add_tail(&hub->event_list, &hub_event_list); | 381 | list_add_tail(&hub->event_list, &hub_event_list); |
382 | |||
383 | /* Suppress autosuspend until khubd runs */ | ||
384 | usb_autopm_get_interface_no_resume( | ||
385 | to_usb_interface(hub->intfdev)); | ||
384 | wake_up(&khubd_wait); | 386 | wake_up(&khubd_wait); |
385 | } | 387 | } |
386 | spin_unlock_irqrestore(&hub_event_lock, flags); | 388 | spin_unlock_irqrestore(&hub_event_lock, flags); |
@@ -665,7 +667,7 @@ int usb_remove_device(struct usb_device *udev) | |||
665 | } | 667 | } |
666 | 668 | ||
667 | enum hub_activation_type { | 669 | enum hub_activation_type { |
668 | HUB_INIT, HUB_INIT2, HUB_INIT3, | 670 | HUB_INIT, HUB_INIT2, HUB_INIT3, /* INITs must come first */ |
669 | HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME, | 671 | HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME, |
670 | }; | 672 | }; |
671 | 673 | ||
@@ -710,8 +712,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
710 | msecs_to_jiffies(delay)); | 712 | msecs_to_jiffies(delay)); |
711 | 713 | ||
712 | /* Suppress autosuspend until init is done */ | 714 | /* Suppress autosuspend until init is done */ |
713 | atomic_set(&to_usb_interface(hub->intfdev)-> | 715 | usb_autopm_get_interface_no_resume( |
714 | pm_usage_cnt, 1); | 716 | to_usb_interface(hub->intfdev)); |
715 | return; /* Continues at init2: below */ | 717 | return; /* Continues at init2: below */ |
716 | } else { | 718 | } else { |
717 | hub_power_on(hub, true); | 719 | hub_power_on(hub, true); |
@@ -818,6 +820,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
818 | } | 820 | } |
819 | init3: | 821 | init3: |
820 | hub->quiescing = 0; | 822 | hub->quiescing = 0; |
823 | hub->init_done = 1; | ||
821 | 824 | ||
822 | status = usb_submit_urb(hub->urb, GFP_NOIO); | 825 | status = usb_submit_urb(hub->urb, GFP_NOIO); |
823 | if (status < 0) | 826 | if (status < 0) |
@@ -827,6 +830,10 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
827 | 830 | ||
828 | /* Scan all ports that need attention */ | 831 | /* Scan all ports that need attention */ |
829 | kick_khubd(hub); | 832 | kick_khubd(hub); |
833 | |||
834 | /* Allow autosuspend if it was suppressed */ | ||
835 | if (type <= HUB_INIT3) | ||
836 | usb_autopm_put_interface_async(to_usb_interface(hub->intfdev)); | ||
830 | } | 837 | } |
831 | 838 | ||
832 | /* Implement the continuations for the delays above */ | 839 | /* Implement the continuations for the delays above */ |
@@ -854,6 +861,11 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) | |||
854 | int i; | 861 | int i; |
855 | 862 | ||
856 | cancel_delayed_work_sync(&hub->init_work); | 863 | cancel_delayed_work_sync(&hub->init_work); |
864 | if (!hub->init_done) { | ||
865 | hub->init_done = 1; | ||
866 | usb_autopm_put_interface_no_suspend( | ||
867 | to_usb_interface(hub->intfdev)); | ||
868 | } | ||
857 | 869 | ||
858 | /* khubd and related activity won't re-trigger */ | 870 | /* khubd and related activity won't re-trigger */ |
859 | hub->quiescing = 1; | 871 | hub->quiescing = 1; |
@@ -1176,7 +1188,10 @@ static void hub_disconnect(struct usb_interface *intf) | |||
1176 | 1188 | ||
1177 | /* Take the hub off the event list and don't let it be added again */ | 1189 | /* Take the hub off the event list and don't let it be added again */ |
1178 | spin_lock_irq(&hub_event_lock); | 1190 | spin_lock_irq(&hub_event_lock); |
1179 | list_del_init(&hub->event_list); | 1191 | if (!list_empty(&hub->event_list)) { |
1192 | list_del_init(&hub->event_list); | ||
1193 | usb_autopm_put_interface_no_suspend(intf); | ||
1194 | } | ||
1180 | hub->disconnected = 1; | 1195 | hub->disconnected = 1; |
1181 | spin_unlock_irq(&hub_event_lock); | 1196 | spin_unlock_irq(&hub_event_lock); |
1182 | 1197 | ||
@@ -3235,7 +3250,7 @@ static void hub_events(void) | |||
3235 | * disconnected while waiting for the lock to succeed. */ | 3250 | * disconnected while waiting for the lock to succeed. */ |
3236 | usb_lock_device(hdev); | 3251 | usb_lock_device(hdev); |
3237 | if (unlikely(hub->disconnected)) | 3252 | if (unlikely(hub->disconnected)) |
3238 | goto loop; | 3253 | goto loop2; |
3239 | 3254 | ||
3240 | /* If the hub has died, clean up after it */ | 3255 | /* If the hub has died, clean up after it */ |
3241 | if (hdev->state == USB_STATE_NOTATTACHED) { | 3256 | if (hdev->state == USB_STATE_NOTATTACHED) { |
@@ -3384,11 +3399,15 @@ static void hub_events(void) | |||
3384 | } | 3399 | } |
3385 | } | 3400 | } |
3386 | 3401 | ||
3387 | loop_autopm: | 3402 | loop_autopm: |
3388 | /* Allow autosuspend if we're not going to run again */ | 3403 | /* Balance the usb_autopm_get_interface() above */ |
3389 | if (list_empty(&hub->event_list)) | 3404 | usb_autopm_put_interface_no_suspend(intf); |
3390 | usb_autopm_enable(intf); | 3405 | loop: |
3391 | loop: | 3406 | /* Balance the usb_autopm_get_interface_no_resume() in |
3407 | * kick_khubd() and allow autosuspend. | ||
3408 | */ | ||
3409 | usb_autopm_put_interface(intf); | ||
3410 | loop2: | ||
3392 | usb_unlock_device(hdev); | 3411 | usb_unlock_device(hdev); |
3393 | kref_put(&hub->kref, hub_release); | 3412 | kref_put(&hub->kref, hub_release); |
3394 | 3413 | ||
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index ae763974be25..15477008b631 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -327,7 +327,6 @@ static DEVICE_ATTR(autosuspend, S_IRUGO | S_IWUSR, | |||
327 | 327 | ||
328 | static const char on_string[] = "on"; | 328 | static const char on_string[] = "on"; |
329 | static const char auto_string[] = "auto"; | 329 | static const char auto_string[] = "auto"; |
330 | static const char suspend_string[] = "suspend"; | ||
331 | 330 | ||
332 | static ssize_t | 331 | static ssize_t |
333 | show_level(struct device *dev, struct device_attribute *attr, char *buf) | 332 | show_level(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -335,13 +334,8 @@ show_level(struct device *dev, struct device_attribute *attr, char *buf) | |||
335 | struct usb_device *udev = to_usb_device(dev); | 334 | struct usb_device *udev = to_usb_device(dev); |
336 | const char *p = auto_string; | 335 | const char *p = auto_string; |
337 | 336 | ||
338 | if (udev->state == USB_STATE_SUSPENDED) { | 337 | if (udev->state != USB_STATE_SUSPENDED && udev->autosuspend_disabled) |
339 | if (udev->autoresume_disabled) | 338 | p = on_string; |
340 | p = suspend_string; | ||
341 | } else { | ||
342 | if (udev->autosuspend_disabled) | ||
343 | p = on_string; | ||
344 | } | ||
345 | return sprintf(buf, "%s\n", p); | 339 | return sprintf(buf, "%s\n", p); |
346 | } | 340 | } |
347 | 341 | ||
@@ -353,7 +347,7 @@ set_level(struct device *dev, struct device_attribute *attr, | |||
353 | int len = count; | 347 | int len = count; |
354 | char *cp; | 348 | char *cp; |
355 | int rc = 0; | 349 | int rc = 0; |
356 | int old_autosuspend_disabled, old_autoresume_disabled; | 350 | int old_autosuspend_disabled; |
357 | 351 | ||
358 | cp = memchr(buf, '\n', count); | 352 | cp = memchr(buf, '\n', count); |
359 | if (cp) | 353 | if (cp) |
@@ -361,7 +355,6 @@ set_level(struct device *dev, struct device_attribute *attr, | |||
361 | 355 | ||
362 | usb_lock_device(udev); | 356 | usb_lock_device(udev); |
363 | old_autosuspend_disabled = udev->autosuspend_disabled; | 357 | old_autosuspend_disabled = udev->autosuspend_disabled; |
364 | old_autoresume_disabled = udev->autoresume_disabled; | ||
365 | 358 | ||
366 | /* Setting the flags without calling usb_pm_lock is a subject to | 359 | /* Setting the flags without calling usb_pm_lock is a subject to |
367 | * races, but who cares... | 360 | * races, but who cares... |
@@ -369,28 +362,18 @@ set_level(struct device *dev, struct device_attribute *attr, | |||
369 | if (len == sizeof on_string - 1 && | 362 | if (len == sizeof on_string - 1 && |
370 | strncmp(buf, on_string, len) == 0) { | 363 | strncmp(buf, on_string, len) == 0) { |
371 | udev->autosuspend_disabled = 1; | 364 | udev->autosuspend_disabled = 1; |
372 | udev->autoresume_disabled = 0; | ||
373 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); | 365 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); |
374 | 366 | ||
375 | } else if (len == sizeof auto_string - 1 && | 367 | } else if (len == sizeof auto_string - 1 && |
376 | strncmp(buf, auto_string, len) == 0) { | 368 | strncmp(buf, auto_string, len) == 0) { |
377 | udev->autosuspend_disabled = 0; | 369 | udev->autosuspend_disabled = 0; |
378 | udev->autoresume_disabled = 0; | ||
379 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); | 370 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); |
380 | 371 | ||
381 | } else if (len == sizeof suspend_string - 1 && | ||
382 | strncmp(buf, suspend_string, len) == 0) { | ||
383 | udev->autosuspend_disabled = 0; | ||
384 | udev->autoresume_disabled = 1; | ||
385 | rc = usb_external_suspend_device(udev, PMSG_USER_SUSPEND); | ||
386 | |||
387 | } else | 372 | } else |
388 | rc = -EINVAL; | 373 | rc = -EINVAL; |
389 | 374 | ||
390 | if (rc) { | 375 | if (rc) |
391 | udev->autosuspend_disabled = old_autosuspend_disabled; | 376 | udev->autosuspend_disabled = old_autosuspend_disabled; |
392 | udev->autoresume_disabled = old_autoresume_disabled; | ||
393 | } | ||
394 | usb_unlock_device(udev); | 377 | usb_unlock_device(udev); |
395 | return (rc < 0 ? rc : count); | 378 | return (rc < 0 ? rc : count); |
396 | } | 379 | } |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 4b6f6db544ee..6af3581e1114 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -432,7 +432,6 @@ struct usb_tt; | |||
432 | * @do_remote_wakeup: remote wakeup should be enabled | 432 | * @do_remote_wakeup: remote wakeup should be enabled |
433 | * @reset_resume: needs reset instead of resume | 433 | * @reset_resume: needs reset instead of resume |
434 | * @autosuspend_disabled: autosuspend disabled by the user | 434 | * @autosuspend_disabled: autosuspend disabled by the user |
435 | * @autoresume_disabled: autoresume disabled by the user | ||
436 | * @skip_sys_resume: skip the next system resume | 435 | * @skip_sys_resume: skip the next system resume |
437 | * @wusb_dev: if this is a Wireless USB device, link to the WUSB | 436 | * @wusb_dev: if this is a Wireless USB device, link to the WUSB |
438 | * specific data for the device. | 437 | * specific data for the device. |
@@ -516,7 +515,6 @@ struct usb_device { | |||
516 | unsigned do_remote_wakeup:1; | 515 | unsigned do_remote_wakeup:1; |
517 | unsigned reset_resume:1; | 516 | unsigned reset_resume:1; |
518 | unsigned autosuspend_disabled:1; | 517 | unsigned autosuspend_disabled:1; |
519 | unsigned autoresume_disabled:1; | ||
520 | unsigned skip_sys_resume:1; | 518 | unsigned skip_sys_resume:1; |
521 | #endif | 519 | #endif |
522 | struct wusb_dev *wusb_dev; | 520 | struct wusb_dev *wusb_dev; |
@@ -542,22 +540,20 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); | |||
542 | 540 | ||
543 | /* USB autosuspend and autoresume */ | 541 | /* USB autosuspend and autoresume */ |
544 | #ifdef CONFIG_USB_SUSPEND | 542 | #ifdef CONFIG_USB_SUSPEND |
545 | extern int usb_autopm_set_interface(struct usb_interface *intf); | ||
546 | extern int usb_autopm_get_interface(struct usb_interface *intf); | 543 | extern int usb_autopm_get_interface(struct usb_interface *intf); |
547 | extern void usb_autopm_put_interface(struct usb_interface *intf); | 544 | extern void usb_autopm_put_interface(struct usb_interface *intf); |
548 | extern int usb_autopm_get_interface_async(struct usb_interface *intf); | 545 | extern int usb_autopm_get_interface_async(struct usb_interface *intf); |
549 | extern void usb_autopm_put_interface_async(struct usb_interface *intf); | 546 | extern void usb_autopm_put_interface_async(struct usb_interface *intf); |
550 | 547 | ||
551 | static inline void usb_autopm_enable(struct usb_interface *intf) | 548 | static inline void usb_autopm_get_interface_no_resume( |
549 | struct usb_interface *intf) | ||
552 | { | 550 | { |
553 | atomic_set(&intf->pm_usage_cnt, 0); | 551 | atomic_inc(&intf->pm_usage_cnt); |
554 | usb_autopm_set_interface(intf); | ||
555 | } | 552 | } |
556 | 553 | static inline void usb_autopm_put_interface_no_suspend( | |
557 | static inline void usb_autopm_disable(struct usb_interface *intf) | 554 | struct usb_interface *intf) |
558 | { | 555 | { |
559 | atomic_set(&intf->pm_usage_cnt, 1); | 556 | atomic_dec(&intf->pm_usage_cnt); |
560 | usb_autopm_set_interface(intf); | ||
561 | } | 557 | } |
562 | 558 | ||
563 | static inline void usb_mark_last_busy(struct usb_device *udev) | 559 | static inline void usb_mark_last_busy(struct usb_device *udev) |
@@ -567,12 +563,8 @@ static inline void usb_mark_last_busy(struct usb_device *udev) | |||
567 | 563 | ||
568 | #else | 564 | #else |
569 | 565 | ||
570 | static inline int usb_autopm_set_interface(struct usb_interface *intf) | ||
571 | { return 0; } | ||
572 | |||
573 | static inline int usb_autopm_get_interface(struct usb_interface *intf) | 566 | static inline int usb_autopm_get_interface(struct usb_interface *intf) |
574 | { return 0; } | 567 | { return 0; } |
575 | |||
576 | static inline int usb_autopm_get_interface_async(struct usb_interface *intf) | 568 | static inline int usb_autopm_get_interface_async(struct usb_interface *intf) |
577 | { return 0; } | 569 | { return 0; } |
578 | 570 | ||
@@ -580,9 +572,11 @@ static inline void usb_autopm_put_interface(struct usb_interface *intf) | |||
580 | { } | 572 | { } |
581 | static inline void usb_autopm_put_interface_async(struct usb_interface *intf) | 573 | static inline void usb_autopm_put_interface_async(struct usb_interface *intf) |
582 | { } | 574 | { } |
583 | static inline void usb_autopm_enable(struct usb_interface *intf) | 575 | static inline void usb_autopm_get_interface_no_resume( |
576 | struct usb_interface *intf) | ||
584 | { } | 577 | { } |
585 | static inline void usb_autopm_disable(struct usb_interface *intf) | 578 | static inline void usb_autopm_put_interface_no_suspend( |
579 | struct usb_interface *intf) | ||
586 | { } | 580 | { } |
587 | static inline void usb_mark_last_busy(struct usb_device *udev) | 581 | static inline void usb_mark_last_busy(struct usb_device *udev) |
588 | { } | 582 | { } |