diff options
-rw-r--r-- | Documentation/power/runtime_pm.txt | 2 | ||||
-rw-r--r-- | Documentation/usb/power-management.txt | 8 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 94 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-picolcd.c | 2 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 7 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 2 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/usb.c | 4 | ||||
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 2 | ||||
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 6 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 9 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 9 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 15 | ||||
-rw-r--r-- | drivers/usb/serial/sierra.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/usb_wwan.c | 2 | ||||
-rw-r--r-- | include/linux/pm.h | 2 | ||||
-rw-r--r-- | include/trace/events/rpm.h | 99 | ||||
-rw-r--r-- | kernel/trace/Makefile | 3 | ||||
-rw-r--r-- | kernel/trace/rpm-traces.c | 20 | ||||
-rw-r--r-- | sound/usb/card.c | 2 |
20 files changed, 226 insertions, 66 deletions
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 6066e3a6b9a9..1f054046bc76 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt | |||
@@ -477,12 +477,14 @@ pm_runtime_autosuspend_expiration() | |||
477 | If pm_runtime_irq_safe() has been called for a device then the following helper | 477 | If pm_runtime_irq_safe() has been called for a device then the following helper |
478 | functions may also be used in interrupt context: | 478 | functions may also be used in interrupt context: |
479 | 479 | ||
480 | pm_runtime_idle() | ||
480 | pm_runtime_suspend() | 481 | pm_runtime_suspend() |
481 | pm_runtime_autosuspend() | 482 | pm_runtime_autosuspend() |
482 | pm_runtime_resume() | 483 | pm_runtime_resume() |
483 | pm_runtime_get_sync() | 484 | pm_runtime_get_sync() |
484 | pm_runtime_put_sync() | 485 | pm_runtime_put_sync() |
485 | pm_runtime_put_sync_suspend() | 486 | pm_runtime_put_sync_suspend() |
487 | pm_runtime_put_sync_autosuspend() | ||
486 | 488 | ||
487 | 5. Runtime PM Initialization, Device Probing and Removal | 489 | 5. Runtime PM Initialization, Device Probing and Removal |
488 | 490 | ||
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt index c9ffa9ced7ee..e8662a5fbc5d 100644 --- a/Documentation/usb/power-management.txt +++ b/Documentation/usb/power-management.txt | |||
@@ -439,10 +439,10 @@ cause autosuspends to fail with -EBUSY if the driver needs to use the | |||
439 | device. | 439 | device. |
440 | 440 | ||
441 | External suspend calls should never be allowed to fail in this way, | 441 | External suspend calls should never be allowed to fail in this way, |
442 | only autosuspend calls. The driver can tell them apart by checking | 442 | only autosuspend calls. The driver can tell them apart by applying |
443 | the PM_EVENT_AUTO bit in the message.event argument to the suspend | 443 | the PMSG_IS_AUTO() macro to the message argument to the suspend |
444 | method; this bit will be set for internal PM events (autosuspend) and | 444 | method; it will return True for internal PM events (autosuspend) and |
445 | clear for external PM events. | 445 | False for external PM events. |
446 | 446 | ||
447 | 447 | ||
448 | Mutual exclusion | 448 | Mutual exclusion |
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index acb3f83b8079..7a6fb5e34a0e 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
11 | #include <linux/pm_runtime.h> | 11 | #include <linux/pm_runtime.h> |
12 | #include <trace/events/rpm.h> | ||
12 | #include "power.h" | 13 | #include "power.h" |
13 | 14 | ||
14 | static int rpm_resume(struct device *dev, int rpmflags); | 15 | static int rpm_resume(struct device *dev, int rpmflags); |
@@ -155,6 +156,31 @@ static int rpm_check_suspend_allowed(struct device *dev) | |||
155 | } | 156 | } |
156 | 157 | ||
157 | /** | 158 | /** |
159 | * __rpm_callback - Run a given runtime PM callback for a given device. | ||
160 | * @cb: Runtime PM callback to run. | ||
161 | * @dev: Device to run the callback for. | ||
162 | */ | ||
163 | static int __rpm_callback(int (*cb)(struct device *), struct device *dev) | ||
164 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | ||
165 | { | ||
166 | int retval; | ||
167 | |||
168 | if (dev->power.irq_safe) | ||
169 | spin_unlock(&dev->power.lock); | ||
170 | else | ||
171 | spin_unlock_irq(&dev->power.lock); | ||
172 | |||
173 | retval = cb(dev); | ||
174 | |||
175 | if (dev->power.irq_safe) | ||
176 | spin_lock(&dev->power.lock); | ||
177 | else | ||
178 | spin_lock_irq(&dev->power.lock); | ||
179 | |||
180 | return retval; | ||
181 | } | ||
182 | |||
183 | /** | ||
158 | * rpm_idle - Notify device bus type if the device can be suspended. | 184 | * rpm_idle - Notify device bus type if the device can be suspended. |
159 | * @dev: Device to notify the bus type about. | 185 | * @dev: Device to notify the bus type about. |
160 | * @rpmflags: Flag bits. | 186 | * @rpmflags: Flag bits. |
@@ -171,6 +197,7 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
171 | int (*callback)(struct device *); | 197 | int (*callback)(struct device *); |
172 | int retval; | 198 | int retval; |
173 | 199 | ||
200 | trace_rpm_idle(dev, rpmflags); | ||
174 | retval = rpm_check_suspend_allowed(dev); | 201 | retval = rpm_check_suspend_allowed(dev); |
175 | if (retval < 0) | 202 | if (retval < 0) |
176 | ; /* Conditions are wrong. */ | 203 | ; /* Conditions are wrong. */ |
@@ -225,24 +252,14 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
225 | else | 252 | else |
226 | callback = NULL; | 253 | callback = NULL; |
227 | 254 | ||
228 | if (callback) { | 255 | if (callback) |
229 | if (dev->power.irq_safe) | 256 | __rpm_callback(callback, dev); |
230 | spin_unlock(&dev->power.lock); | ||
231 | else | ||
232 | spin_unlock_irq(&dev->power.lock); | ||
233 | |||
234 | callback(dev); | ||
235 | |||
236 | if (dev->power.irq_safe) | ||
237 | spin_lock(&dev->power.lock); | ||
238 | else | ||
239 | spin_lock_irq(&dev->power.lock); | ||
240 | } | ||
241 | 257 | ||
242 | dev->power.idle_notification = false; | 258 | dev->power.idle_notification = false; |
243 | wake_up_all(&dev->power.wait_queue); | 259 | wake_up_all(&dev->power.wait_queue); |
244 | 260 | ||
245 | out: | 261 | out: |
262 | trace_rpm_return_int(dev, _THIS_IP_, retval); | ||
246 | return retval; | 263 | return retval; |
247 | } | 264 | } |
248 | 265 | ||
@@ -252,22 +269,14 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
252 | * @dev: Device to run the callback for. | 269 | * @dev: Device to run the callback for. |
253 | */ | 270 | */ |
254 | static int rpm_callback(int (*cb)(struct device *), struct device *dev) | 271 | static int rpm_callback(int (*cb)(struct device *), struct device *dev) |
255 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | ||
256 | { | 272 | { |
257 | int retval; | 273 | int retval; |
258 | 274 | ||
259 | if (!cb) | 275 | if (!cb) |
260 | return -ENOSYS; | 276 | return -ENOSYS; |
261 | 277 | ||
262 | if (dev->power.irq_safe) { | 278 | retval = __rpm_callback(cb, dev); |
263 | retval = cb(dev); | ||
264 | } else { | ||
265 | spin_unlock_irq(&dev->power.lock); | ||
266 | |||
267 | retval = cb(dev); | ||
268 | 279 | ||
269 | spin_lock_irq(&dev->power.lock); | ||
270 | } | ||
271 | dev->power.runtime_error = retval; | 280 | dev->power.runtime_error = retval; |
272 | return retval != -EACCES ? retval : -EIO; | 281 | return retval != -EACCES ? retval : -EIO; |
273 | } | 282 | } |
@@ -295,7 +304,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
295 | struct device *parent = NULL; | 304 | struct device *parent = NULL; |
296 | int retval; | 305 | int retval; |
297 | 306 | ||
298 | dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags); | 307 | trace_rpm_suspend(dev, rpmflags); |
299 | 308 | ||
300 | repeat: | 309 | repeat: |
301 | retval = rpm_check_suspend_allowed(dev); | 310 | retval = rpm_check_suspend_allowed(dev); |
@@ -347,6 +356,15 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
347 | goto out; | 356 | goto out; |
348 | } | 357 | } |
349 | 358 | ||
359 | if (dev->power.irq_safe) { | ||
360 | spin_unlock(&dev->power.lock); | ||
361 | |||
362 | cpu_relax(); | ||
363 | |||
364 | spin_lock(&dev->power.lock); | ||
365 | goto repeat; | ||
366 | } | ||
367 | |||
350 | /* Wait for the other suspend running in parallel with us. */ | 368 | /* Wait for the other suspend running in parallel with us. */ |
351 | for (;;) { | 369 | for (;;) { |
352 | prepare_to_wait(&dev->power.wait_queue, &wait, | 370 | prepare_to_wait(&dev->power.wait_queue, &wait, |
@@ -430,7 +448,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
430 | } | 448 | } |
431 | 449 | ||
432 | out: | 450 | out: |
433 | dev_dbg(dev, "%s returns %d\n", __func__, retval); | 451 | trace_rpm_return_int(dev, _THIS_IP_, retval); |
434 | 452 | ||
435 | return retval; | 453 | return retval; |
436 | } | 454 | } |
@@ -459,7 +477,7 @@ static int rpm_resume(struct device *dev, int rpmflags) | |||
459 | struct device *parent = NULL; | 477 | struct device *parent = NULL; |
460 | int retval = 0; | 478 | int retval = 0; |
461 | 479 | ||
462 | dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags); | 480 | trace_rpm_resume(dev, rpmflags); |
463 | 481 | ||
464 | repeat: | 482 | repeat: |
465 | if (dev->power.runtime_error) | 483 | if (dev->power.runtime_error) |
@@ -496,6 +514,15 @@ static int rpm_resume(struct device *dev, int rpmflags) | |||
496 | goto out; | 514 | goto out; |
497 | } | 515 | } |
498 | 516 | ||
517 | if (dev->power.irq_safe) { | ||
518 | spin_unlock(&dev->power.lock); | ||
519 | |||
520 | cpu_relax(); | ||
521 | |||
522 | spin_lock(&dev->power.lock); | ||
523 | goto repeat; | ||
524 | } | ||
525 | |||
499 | /* Wait for the operation carried out in parallel with us. */ | 526 | /* Wait for the operation carried out in parallel with us. */ |
500 | for (;;) { | 527 | for (;;) { |
501 | prepare_to_wait(&dev->power.wait_queue, &wait, | 528 | prepare_to_wait(&dev->power.wait_queue, &wait, |
@@ -615,7 +642,7 @@ static int rpm_resume(struct device *dev, int rpmflags) | |||
615 | spin_lock_irq(&dev->power.lock); | 642 | spin_lock_irq(&dev->power.lock); |
616 | } | 643 | } |
617 | 644 | ||
618 | dev_dbg(dev, "%s returns %d\n", __func__, retval); | 645 | trace_rpm_return_int(dev, _THIS_IP_, retval); |
619 | 646 | ||
620 | return retval; | 647 | return retval; |
621 | } | 648 | } |
@@ -732,13 +759,16 @@ EXPORT_SYMBOL_GPL(pm_schedule_suspend); | |||
732 | * return immediately if it is larger than zero. Then carry out an idle | 759 | * return immediately if it is larger than zero. Then carry out an idle |
733 | * notification, either synchronous or asynchronous. | 760 | * notification, either synchronous or asynchronous. |
734 | * | 761 | * |
735 | * This routine may be called in atomic context if the RPM_ASYNC flag is set. | 762 | * This routine may be called in atomic context if the RPM_ASYNC flag is set, |
763 | * or if pm_runtime_irq_safe() has been called. | ||
736 | */ | 764 | */ |
737 | int __pm_runtime_idle(struct device *dev, int rpmflags) | 765 | int __pm_runtime_idle(struct device *dev, int rpmflags) |
738 | { | 766 | { |
739 | unsigned long flags; | 767 | unsigned long flags; |
740 | int retval; | 768 | int retval; |
741 | 769 | ||
770 | might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); | ||
771 | |||
742 | if (rpmflags & RPM_GET_PUT) { | 772 | if (rpmflags & RPM_GET_PUT) { |
743 | if (!atomic_dec_and_test(&dev->power.usage_count)) | 773 | if (!atomic_dec_and_test(&dev->power.usage_count)) |
744 | return 0; | 774 | return 0; |
@@ -761,13 +791,16 @@ EXPORT_SYMBOL_GPL(__pm_runtime_idle); | |||
761 | * return immediately if it is larger than zero. Then carry out a suspend, | 791 | * return immediately if it is larger than zero. Then carry out a suspend, |
762 | * either synchronous or asynchronous. | 792 | * either synchronous or asynchronous. |
763 | * | 793 | * |
764 | * This routine may be called in atomic context if the RPM_ASYNC flag is set. | 794 | * This routine may be called in atomic context if the RPM_ASYNC flag is set, |
795 | * or if pm_runtime_irq_safe() has been called. | ||
765 | */ | 796 | */ |
766 | int __pm_runtime_suspend(struct device *dev, int rpmflags) | 797 | int __pm_runtime_suspend(struct device *dev, int rpmflags) |
767 | { | 798 | { |
768 | unsigned long flags; | 799 | unsigned long flags; |
769 | int retval; | 800 | int retval; |
770 | 801 | ||
802 | might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); | ||
803 | |||
771 | if (rpmflags & RPM_GET_PUT) { | 804 | if (rpmflags & RPM_GET_PUT) { |
772 | if (!atomic_dec_and_test(&dev->power.usage_count)) | 805 | if (!atomic_dec_and_test(&dev->power.usage_count)) |
773 | return 0; | 806 | return 0; |
@@ -789,13 +822,16 @@ EXPORT_SYMBOL_GPL(__pm_runtime_suspend); | |||
789 | * If the RPM_GET_PUT flag is set, increment the device's usage count. Then | 822 | * If the RPM_GET_PUT flag is set, increment the device's usage count. Then |
790 | * carry out a resume, either synchronous or asynchronous. | 823 | * carry out a resume, either synchronous or asynchronous. |
791 | * | 824 | * |
792 | * This routine may be called in atomic context if the RPM_ASYNC flag is set. | 825 | * This routine may be called in atomic context if the RPM_ASYNC flag is set, |
826 | * or if pm_runtime_irq_safe() has been called. | ||
793 | */ | 827 | */ |
794 | int __pm_runtime_resume(struct device *dev, int rpmflags) | 828 | int __pm_runtime_resume(struct device *dev, int rpmflags) |
795 | { | 829 | { |
796 | unsigned long flags; | 830 | unsigned long flags; |
797 | int retval; | 831 | int retval; |
798 | 832 | ||
833 | might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); | ||
834 | |||
799 | if (rpmflags & RPM_GET_PUT) | 835 | if (rpmflags & RPM_GET_PUT) |
800 | atomic_inc(&dev->power.usage_count); | 836 | atomic_inc(&dev->power.usage_count); |
801 | 837 | ||
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 9cbac6b445e1..6767b4a3d48a 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -1116,7 +1116,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) | |||
1116 | return 0; | 1116 | return 0; |
1117 | 1117 | ||
1118 | spin_lock_irq(&data->txlock); | 1118 | spin_lock_irq(&data->txlock); |
1119 | if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) { | 1119 | if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) { |
1120 | set_bit(BTUSB_SUSPENDING, &data->flags); | 1120 | set_bit(BTUSB_SUSPENDING, &data->flags); |
1121 | spin_unlock_irq(&data->txlock); | 1121 | spin_unlock_irq(&data->txlock); |
1122 | } else { | 1122 | } else { |
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 9d8710f8bc79..1782693819f3 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c | |||
@@ -2409,7 +2409,7 @@ static int picolcd_raw_event(struct hid_device *hdev, | |||
2409 | #ifdef CONFIG_PM | 2409 | #ifdef CONFIG_PM |
2410 | static int picolcd_suspend(struct hid_device *hdev, pm_message_t message) | 2410 | static int picolcd_suspend(struct hid_device *hdev, pm_message_t message) |
2411 | { | 2411 | { |
2412 | if (message.event & PM_EVENT_AUTO) | 2412 | if (PMSG_IS_AUTO(message)) |
2413 | return 0; | 2413 | return 0; |
2414 | 2414 | ||
2415 | picolcd_suspend_backlight(hid_get_drvdata(hdev)); | 2415 | picolcd_suspend_backlight(hid_get_drvdata(hdev)); |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index ad978f5748d3..a9fa294ee7d3 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -1332,7 +1332,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1332 | struct usbhid_device *usbhid = hid->driver_data; | 1332 | struct usbhid_device *usbhid = hid->driver_data; |
1333 | int status; | 1333 | int status; |
1334 | 1334 | ||
1335 | if (message.event & PM_EVENT_AUTO) { | 1335 | if (PMSG_IS_AUTO(message)) { |
1336 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ | 1336 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ |
1337 | if (!test_bit(HID_RESET_PENDING, &usbhid->iofl) | 1337 | if (!test_bit(HID_RESET_PENDING, &usbhid->iofl) |
1338 | && !test_bit(HID_CLEAR_HALT, &usbhid->iofl) | 1338 | && !test_bit(HID_CLEAR_HALT, &usbhid->iofl) |
@@ -1367,7 +1367,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1367 | return -EIO; | 1367 | return -EIO; |
1368 | } | 1368 | } |
1369 | 1369 | ||
1370 | if (!ignoreled && (message.event & PM_EVENT_AUTO)) { | 1370 | if (!ignoreled && PMSG_IS_AUTO(message)) { |
1371 | spin_lock_irq(&usbhid->lock); | 1371 | spin_lock_irq(&usbhid->lock); |
1372 | if (test_bit(HID_LED_ON, &usbhid->iofl)) { | 1372 | if (test_bit(HID_LED_ON, &usbhid->iofl)) { |
1373 | spin_unlock_irq(&usbhid->lock); | 1373 | spin_unlock_irq(&usbhid->lock); |
@@ -1380,8 +1380,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1380 | hid_cancel_delayed_stuff(usbhid); | 1380 | hid_cancel_delayed_stuff(usbhid); |
1381 | hid_cease_io(usbhid); | 1381 | hid_cease_io(usbhid); |
1382 | 1382 | ||
1383 | if ((message.event & PM_EVENT_AUTO) && | 1383 | if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { |
1384 | test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { | ||
1385 | /* lost race against keypresses */ | 1384 | /* lost race against keypresses */ |
1386 | status = hid_start_in(hid); | 1385 | status = hid_start_in(hid); |
1387 | if (status < 0) | 1386 | if (status < 0) |
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index ce395fe5de26..f1c435ba5284 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -1470,7 +1470,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message) | |||
1470 | if (!dev->suspend_count++) { | 1470 | if (!dev->suspend_count++) { |
1471 | spin_lock_irq(&dev->txq.lock); | 1471 | spin_lock_irq(&dev->txq.lock); |
1472 | /* don't autosuspend while transmitting */ | 1472 | /* don't autosuspend while transmitting */ |
1473 | if (dev->txq.qlen && (message.event & PM_EVENT_AUTO)) { | 1473 | if (dev->txq.qlen && PMSG_IS_AUTO(message)) { |
1474 | spin_unlock_irq(&dev->txq.lock); | 1474 | spin_unlock_irq(&dev->txq.lock); |
1475 | return -EBUSY; | 1475 | return -EBUSY; |
1476 | } else { | 1476 | } else { |
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 298f2b0b6311..9a644d052f1e 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c | |||
@@ -599,7 +599,7 @@ void i2400mu_disconnect(struct usb_interface *iface) | |||
599 | * | 599 | * |
600 | * As well, the device might refuse going to sleep for whichever | 600 | * As well, the device might refuse going to sleep for whichever |
601 | * reason. In this case we just fail. For system suspend/hibernate, | 601 | * reason. In this case we just fail. For system suspend/hibernate, |
602 | * we *can't* fail. We check PM_EVENT_AUTO to see if the | 602 | * we *can't* fail. We check PMSG_IS_AUTO to see if the |
603 | * suspend call comes from the USB stack or from the system and act | 603 | * suspend call comes from the USB stack or from the system and act |
604 | * in consequence. | 604 | * in consequence. |
605 | * | 605 | * |
@@ -615,7 +615,7 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg) | |||
615 | struct i2400m *i2400m = &i2400mu->i2400m; | 615 | struct i2400m *i2400m = &i2400mu->i2400m; |
616 | 616 | ||
617 | #ifdef CONFIG_PM | 617 | #ifdef CONFIG_PM |
618 | if (pm_msg.event & PM_EVENT_AUTO) | 618 | if (PMSG_IS_AUTO(pm_msg)) |
619 | is_autosuspend = 1; | 619 | is_autosuspend = 1; |
620 | #endif | 620 | #endif |
621 | 621 | ||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index dac7676ce21b..94e6c5c09dd8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -1305,7 +1305,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
1305 | struct acm *acm = usb_get_intfdata(intf); | 1305 | struct acm *acm = usb_get_intfdata(intf); |
1306 | int cnt; | 1306 | int cnt; |
1307 | 1307 | ||
1308 | if (message.event & PM_EVENT_AUTO) { | 1308 | if (PMSG_IS_AUTO(message)) { |
1309 | int b; | 1309 | int b; |
1310 | 1310 | ||
1311 | spin_lock_irq(&acm->write_lock); | 1311 | spin_lock_irq(&acm->write_lock); |
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 2b9ff518b509..42f180aca3fb 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -798,11 +798,11 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | |||
798 | dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); | 798 | dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); |
799 | 799 | ||
800 | /* if this is an autosuspend the caller does the locking */ | 800 | /* if this is an autosuspend the caller does the locking */ |
801 | if (!(message.event & PM_EVENT_AUTO)) | 801 | if (!PMSG_IS_AUTO(message)) |
802 | mutex_lock(&desc->lock); | 802 | mutex_lock(&desc->lock); |
803 | spin_lock_irq(&desc->iuspin); | 803 | spin_lock_irq(&desc->iuspin); |
804 | 804 | ||
805 | if ((message.event & PM_EVENT_AUTO) && | 805 | if (PMSG_IS_AUTO(message) && |
806 | (test_bit(WDM_IN_USE, &desc->flags) | 806 | (test_bit(WDM_IN_USE, &desc->flags) |
807 | || test_bit(WDM_RESPONDING, &desc->flags))) { | 807 | || test_bit(WDM_RESPONDING, &desc->flags))) { |
808 | spin_unlock_irq(&desc->iuspin); | 808 | spin_unlock_irq(&desc->iuspin); |
@@ -815,7 +815,7 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | |||
815 | kill_urbs(desc); | 815 | kill_urbs(desc); |
816 | cancel_work_sync(&desc->rxwork); | 816 | cancel_work_sync(&desc->rxwork); |
817 | } | 817 | } |
818 | if (!(message.event & PM_EVENT_AUTO)) | 818 | if (!PMSG_IS_AUTO(message)) |
819 | mutex_unlock(&desc->lock); | 819 | mutex_unlock(&desc->lock); |
820 | 820 | ||
821 | return rv; | 821 | return rv; |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 34e3da5aa72a..e03042883c68 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -1046,8 +1046,7 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg) | |||
1046 | /* Non-root devices on a full/low-speed bus must wait for their | 1046 | /* Non-root devices on a full/low-speed bus must wait for their |
1047 | * companion high-speed root hub, in case a handoff is needed. | 1047 | * companion high-speed root hub, in case a handoff is needed. |
1048 | */ | 1048 | */ |
1049 | if (!(msg.event & PM_EVENT_AUTO) && udev->parent && | 1049 | if (!PMSG_IS_AUTO(msg) && udev->parent && udev->bus->hs_companion) |
1050 | udev->bus->hs_companion) | ||
1051 | device_pm_wait_for_dev(&udev->dev, | 1050 | device_pm_wait_for_dev(&udev->dev, |
1052 | &udev->bus->hs_companion->root_hub->dev); | 1051 | &udev->bus->hs_companion->root_hub->dev); |
1053 | 1052 | ||
@@ -1075,7 +1074,7 @@ static int usb_suspend_interface(struct usb_device *udev, | |||
1075 | 1074 | ||
1076 | if (driver->suspend) { | 1075 | if (driver->suspend) { |
1077 | status = driver->suspend(intf, msg); | 1076 | status = driver->suspend(intf, msg); |
1078 | if (status && !(msg.event & PM_EVENT_AUTO)) | 1077 | if (status && !PMSG_IS_AUTO(msg)) |
1079 | dev_err(&intf->dev, "%s error %d\n", | 1078 | dev_err(&intf->dev, "%s error %d\n", |
1080 | "suspend", status); | 1079 | "suspend", status); |
1081 | } else { | 1080 | } else { |
@@ -1189,7 +1188,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1189 | status = usb_suspend_interface(udev, intf, msg); | 1188 | status = usb_suspend_interface(udev, intf, msg); |
1190 | 1189 | ||
1191 | /* Ignore errors during system sleep transitions */ | 1190 | /* Ignore errors during system sleep transitions */ |
1192 | if (!(msg.event & PM_EVENT_AUTO)) | 1191 | if (!PMSG_IS_AUTO(msg)) |
1193 | status = 0; | 1192 | status = 0; |
1194 | if (status != 0) | 1193 | if (status != 0) |
1195 | break; | 1194 | break; |
@@ -1199,7 +1198,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1199 | status = usb_suspend_device(udev, msg); | 1198 | status = usb_suspend_device(udev, msg); |
1200 | 1199 | ||
1201 | /* Again, ignore errors during system sleep transitions */ | 1200 | /* Again, ignore errors during system sleep transitions */ |
1202 | if (!(msg.event & PM_EVENT_AUTO)) | 1201 | if (!PMSG_IS_AUTO(msg)) |
1203 | status = 0; | 1202 | status = 0; |
1204 | } | 1203 | } |
1205 | 1204 | ||
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 73cbbd85219f..3b9d906339ef 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1961,8 +1961,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) | |||
1961 | int status; | 1961 | int status; |
1962 | int old_state = hcd->state; | 1962 | int old_state = hcd->state; |
1963 | 1963 | ||
1964 | dev_dbg(&rhdev->dev, "bus %s%s\n", | 1964 | dev_dbg(&rhdev->dev, "bus %ssuspend, wakeup %d\n", |
1965 | (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend"); | 1965 | (PMSG_IS_AUTO(msg) ? "auto-" : ""), |
1966 | rhdev->do_remote_wakeup); | ||
1966 | if (HCD_DEAD(hcd)) { | 1967 | if (HCD_DEAD(hcd)) { |
1967 | dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend"); | 1968 | dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend"); |
1968 | return 0; | 1969 | return 0; |
@@ -1997,8 +1998,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) | |||
1997 | int status; | 1998 | int status; |
1998 | int old_state = hcd->state; | 1999 | int old_state = hcd->state; |
1999 | 2000 | ||
2000 | dev_dbg(&rhdev->dev, "usb %s%s\n", | 2001 | dev_dbg(&rhdev->dev, "usb %sresume\n", |
2001 | (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume"); | 2002 | (PMSG_IS_AUTO(msg) ? "auto-" : "")); |
2002 | if (HCD_DEAD(hcd)) { | 2003 | if (HCD_DEAD(hcd)) { |
2003 | dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume"); | 2004 | dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume"); |
2004 | return 0; | 2005 | return 0; |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a428aa080a36..13bc83240adb 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -2324,8 +2324,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2324 | int port1 = udev->portnum; | 2324 | int port1 = udev->portnum; |
2325 | int status; | 2325 | int status; |
2326 | 2326 | ||
2327 | // dev_dbg(hub->intfdev, "suspend port %d\n", port1); | ||
2328 | |||
2329 | /* enable remote wakeup when appropriate; this lets the device | 2327 | /* enable remote wakeup when appropriate; this lets the device |
2330 | * wake up the upstream hub (including maybe the root hub). | 2328 | * wake up the upstream hub (including maybe the root hub). |
2331 | * | 2329 | * |
@@ -2342,7 +2340,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2342 | dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", | 2340 | dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", |
2343 | status); | 2341 | status); |
2344 | /* bail if autosuspend is requested */ | 2342 | /* bail if autosuspend is requested */ |
2345 | if (msg.event & PM_EVENT_AUTO) | 2343 | if (PMSG_IS_AUTO(msg)) |
2346 | return status; | 2344 | return status; |
2347 | } | 2345 | } |
2348 | } | 2346 | } |
@@ -2367,12 +2365,13 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2367 | USB_CTRL_SET_TIMEOUT); | 2365 | USB_CTRL_SET_TIMEOUT); |
2368 | 2366 | ||
2369 | /* System sleep transitions should never fail */ | 2367 | /* System sleep transitions should never fail */ |
2370 | if (!(msg.event & PM_EVENT_AUTO)) | 2368 | if (!PMSG_IS_AUTO(msg)) |
2371 | status = 0; | 2369 | status = 0; |
2372 | } else { | 2370 | } else { |
2373 | /* device has up to 10 msec to fully suspend */ | 2371 | /* device has up to 10 msec to fully suspend */ |
2374 | dev_dbg(&udev->dev, "usb %ssuspend\n", | 2372 | dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n", |
2375 | (msg.event & PM_EVENT_AUTO ? "auto-" : "")); | 2373 | (PMSG_IS_AUTO(msg) ? "auto-" : ""), |
2374 | udev->do_remote_wakeup); | ||
2376 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | 2375 | usb_set_device_state(udev, USB_STATE_SUSPENDED); |
2377 | msleep(10); | 2376 | msleep(10); |
2378 | } | 2377 | } |
@@ -2523,7 +2522,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
2523 | } else { | 2522 | } else { |
2524 | /* drive resume for at least 20 msec */ | 2523 | /* drive resume for at least 20 msec */ |
2525 | dev_dbg(&udev->dev, "usb %sresume\n", | 2524 | dev_dbg(&udev->dev, "usb %sresume\n", |
2526 | (msg.event & PM_EVENT_AUTO ? "auto-" : "")); | 2525 | (PMSG_IS_AUTO(msg) ? "auto-" : "")); |
2527 | msleep(25); | 2526 | msleep(25); |
2528 | 2527 | ||
2529 | /* Virtual root hubs can trigger on GET_PORT_STATUS to | 2528 | /* Virtual root hubs can trigger on GET_PORT_STATUS to |
@@ -2625,7 +2624,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
2625 | udev = hdev->children [port1-1]; | 2624 | udev = hdev->children [port1-1]; |
2626 | if (udev && udev->can_submit) { | 2625 | if (udev && udev->can_submit) { |
2627 | dev_warn(&intf->dev, "port %d nyet suspended\n", port1); | 2626 | dev_warn(&intf->dev, "port %d nyet suspended\n", port1); |
2628 | if (msg.event & PM_EVENT_AUTO) | 2627 | if (PMSG_IS_AUTO(msg)) |
2629 | return -EBUSY; | 2628 | return -EBUSY; |
2630 | } | 2629 | } |
2631 | } | 2630 | } |
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index d5d136a53b61..b18179bda0d8 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -1009,7 +1009,7 @@ static int sierra_suspend(struct usb_serial *serial, pm_message_t message) | |||
1009 | struct sierra_intf_private *intfdata; | 1009 | struct sierra_intf_private *intfdata; |
1010 | int b; | 1010 | int b; |
1011 | 1011 | ||
1012 | if (message.event & PM_EVENT_AUTO) { | 1012 | if (PMSG_IS_AUTO(message)) { |
1013 | intfdata = serial->private; | 1013 | intfdata = serial->private; |
1014 | spin_lock_irq(&intfdata->susp_lock); | 1014 | spin_lock_irq(&intfdata->susp_lock); |
1015 | b = intfdata->in_flight; | 1015 | b = intfdata->in_flight; |
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index e4fad5e643d7..d555ca9567b8 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c | |||
@@ -651,7 +651,7 @@ int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message) | |||
651 | 651 | ||
652 | dbg("%s entered", __func__); | 652 | dbg("%s entered", __func__); |
653 | 653 | ||
654 | if (message.event & PM_EVENT_AUTO) { | 654 | if (PMSG_IS_AUTO(message)) { |
655 | spin_lock_irq(&intfdata->susp_lock); | 655 | spin_lock_irq(&intfdata->susp_lock); |
656 | b = intfdata->in_flight; | 656 | b = intfdata->in_flight; |
657 | spin_unlock_irq(&intfdata->susp_lock); | 657 | spin_unlock_irq(&intfdata->susp_lock); |
diff --git a/include/linux/pm.h b/include/linux/pm.h index f7c84c9abd30..18de9f893497 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -366,6 +366,8 @@ extern struct dev_pm_ops generic_subsys_pm_ops; | |||
366 | #define PMSG_AUTO_RESUME ((struct pm_message) \ | 366 | #define PMSG_AUTO_RESUME ((struct pm_message) \ |
367 | { .event = PM_EVENT_AUTO_RESUME, }) | 367 | { .event = PM_EVENT_AUTO_RESUME, }) |
368 | 368 | ||
369 | #define PMSG_IS_AUTO(msg) (((msg).event & PM_EVENT_AUTO) != 0) | ||
370 | |||
369 | /** | 371 | /** |
370 | * Device run-time power management status. | 372 | * Device run-time power management status. |
371 | * | 373 | * |
diff --git a/include/trace/events/rpm.h b/include/trace/events/rpm.h new file mode 100644 index 000000000000..d62c558bf64b --- /dev/null +++ b/include/trace/events/rpm.h | |||
@@ -0,0 +1,99 @@ | |||
1 | |||
2 | #undef TRACE_SYSTEM | ||
3 | #define TRACE_SYSTEM rpm | ||
4 | |||
5 | #if !defined(_TRACE_RUNTIME_POWER_H) || defined(TRACE_HEADER_MULTI_READ) | ||
6 | #define _TRACE_RUNTIME_POWER_H | ||
7 | |||
8 | #include <linux/ktime.h> | ||
9 | #include <linux/tracepoint.h> | ||
10 | #include <linux/device.h> | ||
11 | |||
12 | /* | ||
13 | * The rpm_internal events are used for tracing some important | ||
14 | * runtime pm internal functions. | ||
15 | */ | ||
16 | DECLARE_EVENT_CLASS(rpm_internal, | ||
17 | |||
18 | TP_PROTO(struct device *dev, int flags), | ||
19 | |||
20 | TP_ARGS(dev, flags), | ||
21 | |||
22 | TP_STRUCT__entry( | ||
23 | __string( name, dev_name(dev) ) | ||
24 | __field( int, flags ) | ||
25 | __field( int , usage_count ) | ||
26 | __field( int , disable_depth ) | ||
27 | __field( int , runtime_auto ) | ||
28 | __field( int , request_pending ) | ||
29 | __field( int , irq_safe ) | ||
30 | __field( int , child_count ) | ||
31 | ), | ||
32 | |||
33 | TP_fast_assign( | ||
34 | __assign_str(name, dev_name(dev)); | ||
35 | __entry->flags = flags; | ||
36 | __entry->usage_count = atomic_read( | ||
37 | &dev->power.usage_count); | ||
38 | __entry->disable_depth = dev->power.disable_depth; | ||
39 | __entry->runtime_auto = dev->power.runtime_auto; | ||
40 | __entry->request_pending = dev->power.request_pending; | ||
41 | __entry->irq_safe = dev->power.irq_safe; | ||
42 | __entry->child_count = atomic_read( | ||
43 | &dev->power.child_count); | ||
44 | ), | ||
45 | |||
46 | TP_printk("%s flags-%x cnt-%-2d dep-%-2d auto-%-1d p-%-1d" | ||
47 | " irq-%-1d child-%d", | ||
48 | __get_str(name), __entry->flags, | ||
49 | __entry->usage_count, | ||
50 | __entry->disable_depth, | ||
51 | __entry->runtime_auto, | ||
52 | __entry->request_pending, | ||
53 | __entry->irq_safe, | ||
54 | __entry->child_count | ||
55 | ) | ||
56 | ); | ||
57 | DEFINE_EVENT(rpm_internal, rpm_suspend, | ||
58 | |||
59 | TP_PROTO(struct device *dev, int flags), | ||
60 | |||
61 | TP_ARGS(dev, flags) | ||
62 | ); | ||
63 | DEFINE_EVENT(rpm_internal, rpm_resume, | ||
64 | |||
65 | TP_PROTO(struct device *dev, int flags), | ||
66 | |||
67 | TP_ARGS(dev, flags) | ||
68 | ); | ||
69 | DEFINE_EVENT(rpm_internal, rpm_idle, | ||
70 | |||
71 | TP_PROTO(struct device *dev, int flags), | ||
72 | |||
73 | TP_ARGS(dev, flags) | ||
74 | ); | ||
75 | |||
76 | TRACE_EVENT(rpm_return_int, | ||
77 | TP_PROTO(struct device *dev, unsigned long ip, int ret), | ||
78 | TP_ARGS(dev, ip, ret), | ||
79 | |||
80 | TP_STRUCT__entry( | ||
81 | __string( name, dev_name(dev)) | ||
82 | __field( unsigned long, ip ) | ||
83 | __field( int, ret ) | ||
84 | ), | ||
85 | |||
86 | TP_fast_assign( | ||
87 | __assign_str(name, dev_name(dev)); | ||
88 | __entry->ip = ip; | ||
89 | __entry->ret = ret; | ||
90 | ), | ||
91 | |||
92 | TP_printk("%pS:%s ret=%d", (void *)__entry->ip, __get_str(name), | ||
93 | __entry->ret) | ||
94 | ); | ||
95 | |||
96 | #endif /* _TRACE_RUNTIME_POWER_H */ | ||
97 | |||
98 | /* This part must be outside protection */ | ||
99 | #include <trace/define_trace.h> | ||
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index 761c510a06c5..f49405f842f4 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile | |||
@@ -53,6 +53,9 @@ endif | |||
53 | obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o | 53 | obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o |
54 | obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o | 54 | obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o |
55 | obj-$(CONFIG_TRACEPOINTS) += power-traces.o | 55 | obj-$(CONFIG_TRACEPOINTS) += power-traces.o |
56 | ifeq ($(CONFIG_PM_RUNTIME),y) | ||
57 | obj-$(CONFIG_TRACEPOINTS) += rpm-traces.o | ||
58 | endif | ||
56 | ifeq ($(CONFIG_TRACING),y) | 59 | ifeq ($(CONFIG_TRACING),y) |
57 | obj-$(CONFIG_KGDB_KDB) += trace_kdb.o | 60 | obj-$(CONFIG_KGDB_KDB) += trace_kdb.o |
58 | endif | 61 | endif |
diff --git a/kernel/trace/rpm-traces.c b/kernel/trace/rpm-traces.c new file mode 100644 index 000000000000..4b3b5eaf94d1 --- /dev/null +++ b/kernel/trace/rpm-traces.c | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * Power trace points | ||
3 | * | ||
4 | * Copyright (C) 2009 Ming Lei <ming.lei@canonical.com> | ||
5 | */ | ||
6 | |||
7 | #include <linux/string.h> | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/workqueue.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/usb.h> | ||
13 | |||
14 | #define CREATE_TRACE_POINTS | ||
15 | #include <trace/events/rpm.h> | ||
16 | |||
17 | EXPORT_TRACEPOINT_SYMBOL_GPL(rpm_return_int); | ||
18 | EXPORT_TRACEPOINT_SYMBOL_GPL(rpm_idle); | ||
19 | EXPORT_TRACEPOINT_SYMBOL_GPL(rpm_suspend); | ||
20 | EXPORT_TRACEPOINT_SYMBOL_GPL(rpm_resume); | ||
diff --git a/sound/usb/card.c b/sound/usb/card.c index d8f2bf401458..3068f043099a 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c | |||
@@ -631,7 +631,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) | |||
631 | if (chip == (void *)-1L) | 631 | if (chip == (void *)-1L) |
632 | return 0; | 632 | return 0; |
633 | 633 | ||
634 | if (!(message.event & PM_EVENT_AUTO)) { | 634 | if (!PMSG_IS_AUTO(message)) { |
635 | snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); | 635 | snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); |
636 | if (!chip->num_suspended_intf++) { | 636 | if (!chip->num_suspended_intf++) { |
637 | list_for_each(p, &chip->pcm_list) { | 637 | list_for_each(p, &chip->pcm_list) { |