diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 17:53:17 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 17:53:17 -0400 |
| commit | a8cbf22559ceefdcdfac00701e8e6da7518b7e8e (patch) | |
| tree | 63ebd5779a37f809f7daed77dbf27aa3f1e1110c /drivers/base/power/sysfs.c | |
| parent | e36f561a2c88394ef2708f1ab300fe8a79e9f651 (diff) | |
| parent | 9c034392533f3e9f00656d5c58478cff2560ef81 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6: (26 commits)
PM / Wakeup: Show wakeup sources statistics in debugfs
PM: Introduce library for device-specific OPPs (v7)
PM: Add sysfs attr for rechecking dev hash from PM trace
PM: Lock PM device list mutex in show_dev_hash()
PM / Runtime: Remove idle notification after failing suspend
PM / Hibernate: Modify signature used to mark swap
PM / Runtime: Reduce code duplication in core helper functions
PM: Allow wakeup events to abort freezing of tasks
PM: runtime: add missed pm_request_autosuspend
PM / Hibernate: Make some boot messages look less scary
PM / Runtime: Implement autosuspend support
PM / Runtime: Add no_callbacks flag
PM / Runtime: Combine runtime PM entry points
PM / Runtime: Merge synchronous and async runtime routines
PM / Runtime: Replace boolean arguments with bitflags
PM / Runtime: Move code in drivers/base/power/runtime.c
sysfs: Add sysfs_merge_group() and sysfs_unmerge_group()
PM: Fix potential issue with failing asynchronous suspend
PM / Wakeup: Introduce wakeup source objects and event statistics (v3)
PM: Fix signed/unsigned warning in dpm_show_time()
...
Diffstat (limited to 'drivers/base/power/sysfs.c')
| -rw-r--r-- | drivers/base/power/sysfs.c | 217 |
1 files changed, 208 insertions, 9 deletions
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index e56b4388fe61..0b1e46bf3e56 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
| @@ -75,12 +75,27 @@ | |||
| 75 | * attribute is set to "enabled" by bus type code or device drivers and in | 75 | * attribute is set to "enabled" by bus type code or device drivers and in |
| 76 | * that cases it should be safe to leave the default value. | 76 | * that cases it should be safe to leave the default value. |
| 77 | * | 77 | * |
| 78 | * autosuspend_delay_ms - Report/change a device's autosuspend_delay value | ||
| 79 | * | ||
| 80 | * Some drivers don't want to carry out a runtime suspend as soon as a | ||
| 81 | * device becomes idle; they want it always to remain idle for some period | ||
| 82 | * of time before suspending it. This period is the autosuspend_delay | ||
| 83 | * value (expressed in milliseconds) and it can be controlled by the user. | ||
| 84 | * If the value is negative then the device will never be runtime | ||
| 85 | * suspended. | ||
| 86 | * | ||
| 87 | * NOTE: The autosuspend_delay_ms attribute and the autosuspend_delay | ||
| 88 | * value are used only if the driver calls pm_runtime_use_autosuspend(). | ||
| 89 | * | ||
| 78 | * wakeup_count - Report the number of wakeup events related to the device | 90 | * wakeup_count - Report the number of wakeup events related to the device |
| 79 | */ | 91 | */ |
| 80 | 92 | ||
| 81 | static const char enabled[] = "enabled"; | 93 | static const char enabled[] = "enabled"; |
| 82 | static const char disabled[] = "disabled"; | 94 | static const char disabled[] = "disabled"; |
| 83 | 95 | ||
| 96 | const char power_group_name[] = "power"; | ||
| 97 | EXPORT_SYMBOL_GPL(power_group_name); | ||
| 98 | |||
| 84 | #ifdef CONFIG_PM_RUNTIME | 99 | #ifdef CONFIG_PM_RUNTIME |
| 85 | static const char ctrl_auto[] = "auto"; | 100 | static const char ctrl_auto[] = "auto"; |
| 86 | static const char ctrl_on[] = "on"; | 101 | static const char ctrl_on[] = "on"; |
| @@ -170,6 +185,33 @@ static ssize_t rtpm_status_show(struct device *dev, | |||
| 170 | } | 185 | } |
| 171 | 186 | ||
| 172 | static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL); | 187 | static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL); |
| 188 | |||
| 189 | static ssize_t autosuspend_delay_ms_show(struct device *dev, | ||
| 190 | struct device_attribute *attr, char *buf) | ||
| 191 | { | ||
| 192 | if (!dev->power.use_autosuspend) | ||
| 193 | return -EIO; | ||
| 194 | return sprintf(buf, "%d\n", dev->power.autosuspend_delay); | ||
| 195 | } | ||
| 196 | |||
| 197 | static ssize_t autosuspend_delay_ms_store(struct device *dev, | ||
| 198 | struct device_attribute *attr, const char *buf, size_t n) | ||
| 199 | { | ||
| 200 | long delay; | ||
| 201 | |||
| 202 | if (!dev->power.use_autosuspend) | ||
| 203 | return -EIO; | ||
| 204 | |||
| 205 | if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay) | ||
| 206 | return -EINVAL; | ||
| 207 | |||
| 208 | pm_runtime_set_autosuspend_delay(dev, delay); | ||
| 209 | return n; | ||
| 210 | } | ||
| 211 | |||
| 212 | static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show, | ||
| 213 | autosuspend_delay_ms_store); | ||
| 214 | |||
| 173 | #endif | 215 | #endif |
| 174 | 216 | ||
| 175 | static ssize_t | 217 | static ssize_t |
| @@ -210,11 +252,122 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store); | |||
| 210 | static ssize_t wakeup_count_show(struct device *dev, | 252 | static ssize_t wakeup_count_show(struct device *dev, |
| 211 | struct device_attribute *attr, char *buf) | 253 | struct device_attribute *attr, char *buf) |
| 212 | { | 254 | { |
| 213 | return sprintf(buf, "%lu\n", dev->power.wakeup_count); | 255 | unsigned long count = 0; |
| 256 | bool enabled = false; | ||
| 257 | |||
| 258 | spin_lock_irq(&dev->power.lock); | ||
| 259 | if (dev->power.wakeup) { | ||
| 260 | count = dev->power.wakeup->event_count; | ||
| 261 | enabled = true; | ||
| 262 | } | ||
| 263 | spin_unlock_irq(&dev->power.lock); | ||
| 264 | return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n"); | ||
| 214 | } | 265 | } |
| 215 | 266 | ||
| 216 | static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL); | 267 | static DEVICE_ATTR(wakeup_count, 0444, wakeup_count_show, NULL); |
| 217 | #endif | 268 | |
| 269 | static ssize_t wakeup_active_count_show(struct device *dev, | ||
| 270 | struct device_attribute *attr, char *buf) | ||
| 271 | { | ||
| 272 | unsigned long count = 0; | ||
| 273 | bool enabled = false; | ||
| 274 | |||
| 275 | spin_lock_irq(&dev->power.lock); | ||
| 276 | if (dev->power.wakeup) { | ||
| 277 | count = dev->power.wakeup->active_count; | ||
| 278 | enabled = true; | ||
| 279 | } | ||
| 280 | spin_unlock_irq(&dev->power.lock); | ||
| 281 | return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n"); | ||
| 282 | } | ||
| 283 | |||
| 284 | static DEVICE_ATTR(wakeup_active_count, 0444, wakeup_active_count_show, NULL); | ||
| 285 | |||
| 286 | static ssize_t wakeup_hit_count_show(struct device *dev, | ||
| 287 | struct device_attribute *attr, char *buf) | ||
| 288 | { | ||
| 289 | unsigned long count = 0; | ||
| 290 | bool enabled = false; | ||
| 291 | |||
| 292 | spin_lock_irq(&dev->power.lock); | ||
| 293 | if (dev->power.wakeup) { | ||
| 294 | count = dev->power.wakeup->hit_count; | ||
| 295 | enabled = true; | ||
| 296 | } | ||
| 297 | spin_unlock_irq(&dev->power.lock); | ||
| 298 | return enabled ? sprintf(buf, "%lu\n", count) : sprintf(buf, "\n"); | ||
| 299 | } | ||
| 300 | |||
| 301 | static DEVICE_ATTR(wakeup_hit_count, 0444, wakeup_hit_count_show, NULL); | ||
| 302 | |||
| 303 | static ssize_t wakeup_active_show(struct device *dev, | ||
| 304 | struct device_attribute *attr, char *buf) | ||
| 305 | { | ||
| 306 | unsigned int active = 0; | ||
| 307 | bool enabled = false; | ||
| 308 | |||
| 309 | spin_lock_irq(&dev->power.lock); | ||
| 310 | if (dev->power.wakeup) { | ||
| 311 | active = dev->power.wakeup->active; | ||
| 312 | enabled = true; | ||
| 313 | } | ||
| 314 | spin_unlock_irq(&dev->power.lock); | ||
| 315 | return enabled ? sprintf(buf, "%u\n", active) : sprintf(buf, "\n"); | ||
| 316 | } | ||
| 317 | |||
| 318 | static DEVICE_ATTR(wakeup_active, 0444, wakeup_active_show, NULL); | ||
| 319 | |||
| 320 | static ssize_t wakeup_total_time_show(struct device *dev, | ||
| 321 | struct device_attribute *attr, char *buf) | ||
| 322 | { | ||
| 323 | s64 msec = 0; | ||
| 324 | bool enabled = false; | ||
| 325 | |||
| 326 | spin_lock_irq(&dev->power.lock); | ||
| 327 | if (dev->power.wakeup) { | ||
| 328 | msec = ktime_to_ms(dev->power.wakeup->total_time); | ||
| 329 | enabled = true; | ||
| 330 | } | ||
| 331 | spin_unlock_irq(&dev->power.lock); | ||
| 332 | return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n"); | ||
| 333 | } | ||
| 334 | |||
| 335 | static DEVICE_ATTR(wakeup_total_time_ms, 0444, wakeup_total_time_show, NULL); | ||
| 336 | |||
| 337 | static ssize_t wakeup_max_time_show(struct device *dev, | ||
| 338 | struct device_attribute *attr, char *buf) | ||
| 339 | { | ||
| 340 | s64 msec = 0; | ||
| 341 | bool enabled = false; | ||
| 342 | |||
| 343 | spin_lock_irq(&dev->power.lock); | ||
| 344 | if (dev->power.wakeup) { | ||
| 345 | msec = ktime_to_ms(dev->power.wakeup->max_time); | ||
| 346 | enabled = true; | ||
| 347 | } | ||
| 348 | spin_unlock_irq(&dev->power.lock); | ||
| 349 | return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n"); | ||
| 350 | } | ||
| 351 | |||
| 352 | static DEVICE_ATTR(wakeup_max_time_ms, 0444, wakeup_max_time_show, NULL); | ||
| 353 | |||
| 354 | static ssize_t wakeup_last_time_show(struct device *dev, | ||
| 355 | struct device_attribute *attr, char *buf) | ||
| 356 | { | ||
| 357 | s64 msec = 0; | ||
| 358 | bool enabled = false; | ||
| 359 | |||
| 360 | spin_lock_irq(&dev->power.lock); | ||
| 361 | if (dev->power.wakeup) { | ||
| 362 | msec = ktime_to_ms(dev->power.wakeup->last_time); | ||
| 363 | enabled = true; | ||
| 364 | } | ||
| 365 | spin_unlock_irq(&dev->power.lock); | ||
| 366 | return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n"); | ||
| 367 | } | ||
| 368 | |||
| 369 | static DEVICE_ATTR(wakeup_last_time_ms, 0444, wakeup_last_time_show, NULL); | ||
| 370 | #endif /* CONFIG_PM_SLEEP */ | ||
| 218 | 371 | ||
| 219 | #ifdef CONFIG_PM_ADVANCED_DEBUG | 372 | #ifdef CONFIG_PM_ADVANCED_DEBUG |
| 220 | #ifdef CONFIG_PM_RUNTIME | 373 | #ifdef CONFIG_PM_RUNTIME |
| @@ -279,19 +432,20 @@ static DEVICE_ATTR(async, 0644, async_show, async_store); | |||
| 279 | #endif /* CONFIG_PM_ADVANCED_DEBUG */ | 432 | #endif /* CONFIG_PM_ADVANCED_DEBUG */ |
| 280 | 433 | ||
| 281 | static struct attribute * power_attrs[] = { | 434 | static struct attribute * power_attrs[] = { |
| 282 | #ifdef CONFIG_PM_RUNTIME | ||
| 283 | &dev_attr_control.attr, | ||
| 284 | &dev_attr_runtime_status.attr, | ||
| 285 | &dev_attr_runtime_suspended_time.attr, | ||
| 286 | &dev_attr_runtime_active_time.attr, | ||
| 287 | #endif | ||
| 288 | &dev_attr_wakeup.attr, | 435 | &dev_attr_wakeup.attr, |
| 289 | #ifdef CONFIG_PM_SLEEP | 436 | #ifdef CONFIG_PM_SLEEP |
| 290 | &dev_attr_wakeup_count.attr, | 437 | &dev_attr_wakeup_count.attr, |
| 438 | &dev_attr_wakeup_active_count.attr, | ||
| 439 | &dev_attr_wakeup_hit_count.attr, | ||
| 440 | &dev_attr_wakeup_active.attr, | ||
| 441 | &dev_attr_wakeup_total_time_ms.attr, | ||
| 442 | &dev_attr_wakeup_max_time_ms.attr, | ||
| 443 | &dev_attr_wakeup_last_time_ms.attr, | ||
| 291 | #endif | 444 | #endif |
| 292 | #ifdef CONFIG_PM_ADVANCED_DEBUG | 445 | #ifdef CONFIG_PM_ADVANCED_DEBUG |
| 293 | &dev_attr_async.attr, | 446 | &dev_attr_async.attr, |
| 294 | #ifdef CONFIG_PM_RUNTIME | 447 | #ifdef CONFIG_PM_RUNTIME |
| 448 | &dev_attr_runtime_status.attr, | ||
| 295 | &dev_attr_runtime_usage.attr, | 449 | &dev_attr_runtime_usage.attr, |
| 296 | &dev_attr_runtime_active_kids.attr, | 450 | &dev_attr_runtime_active_kids.attr, |
| 297 | &dev_attr_runtime_enabled.attr, | 451 | &dev_attr_runtime_enabled.attr, |
| @@ -300,10 +454,53 @@ static struct attribute * power_attrs[] = { | |||
| 300 | NULL, | 454 | NULL, |
| 301 | }; | 455 | }; |
| 302 | static struct attribute_group pm_attr_group = { | 456 | static struct attribute_group pm_attr_group = { |
| 303 | .name = "power", | 457 | .name = power_group_name, |
| 304 | .attrs = power_attrs, | 458 | .attrs = power_attrs, |
| 305 | }; | 459 | }; |
| 306 | 460 | ||
| 461 | #ifdef CONFIG_PM_RUNTIME | ||
| 462 | |||
| 463 | static struct attribute *runtime_attrs[] = { | ||
| 464 | #ifndef CONFIG_PM_ADVANCED_DEBUG | ||
| 465 | &dev_attr_runtime_status.attr, | ||
| 466 | #endif | ||
| 467 | &dev_attr_control.attr, | ||
| 468 | &dev_attr_runtime_suspended_time.attr, | ||
| 469 | &dev_attr_runtime_active_time.attr, | ||
| 470 | &dev_attr_autosuspend_delay_ms.attr, | ||
| 471 | NULL, | ||
| 472 | }; | ||
| 473 | static struct attribute_group pm_runtime_attr_group = { | ||
| 474 | .name = power_group_name, | ||
| 475 | .attrs = runtime_attrs, | ||
| 476 | }; | ||
| 477 | |||
| 478 | int dpm_sysfs_add(struct device *dev) | ||
| 479 | { | ||
| 480 | int rc; | ||
| 481 | |||
| 482 | rc = sysfs_create_group(&dev->kobj, &pm_attr_group); | ||
| 483 | if (rc == 0 && !dev->power.no_callbacks) { | ||
| 484 | rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group); | ||
| 485 | if (rc) | ||
| 486 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | ||
| 487 | } | ||
| 488 | return rc; | ||
| 489 | } | ||
| 490 | |||
| 491 | void rpm_sysfs_remove(struct device *dev) | ||
| 492 | { | ||
| 493 | sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group); | ||
| 494 | } | ||
| 495 | |||
| 496 | void dpm_sysfs_remove(struct device *dev) | ||
| 497 | { | ||
| 498 | rpm_sysfs_remove(dev); | ||
| 499 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | ||
| 500 | } | ||
| 501 | |||
| 502 | #else /* CONFIG_PM_RUNTIME */ | ||
| 503 | |||
| 307 | int dpm_sysfs_add(struct device * dev) | 504 | int dpm_sysfs_add(struct device * dev) |
| 308 | { | 505 | { |
| 309 | return sysfs_create_group(&dev->kobj, &pm_attr_group); | 506 | return sysfs_create_group(&dev->kobj, &pm_attr_group); |
| @@ -313,3 +510,5 @@ void dpm_sysfs_remove(struct device * dev) | |||
| 313 | { | 510 | { |
| 314 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | 511 | sysfs_remove_group(&dev->kobj, &pm_attr_group); |
| 315 | } | 512 | } |
| 513 | |||
| 514 | #endif | ||
