diff options
| -rw-r--r-- | drivers/base/power/domain.c | 205 |
1 files changed, 195 insertions, 10 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 431488914982..43fd08e50ae9 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
| @@ -2359,7 +2359,7 @@ exit: | |||
| 2359 | return 0; | 2359 | return 0; |
| 2360 | } | 2360 | } |
| 2361 | 2361 | ||
| 2362 | static int pm_genpd_summary_show(struct seq_file *s, void *data) | 2362 | static int genpd_summary_show(struct seq_file *s, void *data) |
| 2363 | { | 2363 | { |
| 2364 | struct generic_pm_domain *genpd; | 2364 | struct generic_pm_domain *genpd; |
| 2365 | int ret = 0; | 2365 | int ret = 0; |
| @@ -2382,21 +2382,187 @@ static int pm_genpd_summary_show(struct seq_file *s, void *data) | |||
| 2382 | return ret; | 2382 | return ret; |
| 2383 | } | 2383 | } |
| 2384 | 2384 | ||
| 2385 | static int pm_genpd_summary_open(struct inode *inode, struct file *file) | 2385 | static int genpd_status_show(struct seq_file *s, void *data) |
| 2386 | { | 2386 | { |
| 2387 | return single_open(file, pm_genpd_summary_show, NULL); | 2387 | static const char * const status_lookup[] = { |
| 2388 | [GPD_STATE_ACTIVE] = "on", | ||
| 2389 | [GPD_STATE_POWER_OFF] = "off" | ||
| 2390 | }; | ||
| 2391 | |||
| 2392 | struct generic_pm_domain *genpd = s->private; | ||
| 2393 | int ret = 0; | ||
| 2394 | |||
| 2395 | ret = genpd_lock_interruptible(genpd); | ||
| 2396 | if (ret) | ||
| 2397 | return -ERESTARTSYS; | ||
| 2398 | |||
| 2399 | if (WARN_ON_ONCE(genpd->status >= ARRAY_SIZE(status_lookup))) | ||
| 2400 | goto exit; | ||
| 2401 | |||
| 2402 | if (genpd->status == GPD_STATE_POWER_OFF) | ||
| 2403 | seq_printf(s, "%s-%u\n", status_lookup[genpd->status], | ||
| 2404 | genpd->state_idx); | ||
| 2405 | else | ||
| 2406 | seq_printf(s, "%s\n", status_lookup[genpd->status]); | ||
| 2407 | exit: | ||
| 2408 | genpd_unlock(genpd); | ||
| 2409 | return ret; | ||
| 2388 | } | 2410 | } |
| 2389 | 2411 | ||
| 2390 | static const struct file_operations pm_genpd_summary_fops = { | 2412 | static int genpd_sub_domains_show(struct seq_file *s, void *data) |
| 2391 | .open = pm_genpd_summary_open, | 2413 | { |
| 2392 | .read = seq_read, | 2414 | struct generic_pm_domain *genpd = s->private; |
| 2393 | .llseek = seq_lseek, | 2415 | struct gpd_link *link; |
| 2394 | .release = single_release, | 2416 | int ret = 0; |
| 2395 | }; | 2417 | |
| 2418 | ret = genpd_lock_interruptible(genpd); | ||
| 2419 | if (ret) | ||
| 2420 | return -ERESTARTSYS; | ||
| 2421 | |||
| 2422 | list_for_each_entry(link, &genpd->master_links, master_node) | ||
| 2423 | seq_printf(s, "%s\n", link->slave->name); | ||
| 2424 | |||
| 2425 | genpd_unlock(genpd); | ||
| 2426 | return ret; | ||
| 2427 | } | ||
| 2428 | |||
| 2429 | static int genpd_idle_states_show(struct seq_file *s, void *data) | ||
| 2430 | { | ||
| 2431 | struct generic_pm_domain *genpd = s->private; | ||
| 2432 | unsigned int i; | ||
| 2433 | int ret = 0; | ||
| 2434 | |||
| 2435 | ret = genpd_lock_interruptible(genpd); | ||
| 2436 | if (ret) | ||
| 2437 | return -ERESTARTSYS; | ||
| 2438 | |||
| 2439 | seq_puts(s, "State Time Spent(ms)\n"); | ||
| 2440 | |||
| 2441 | for (i = 0; i < genpd->state_count; i++) { | ||
| 2442 | ktime_t delta = 0; | ||
| 2443 | s64 msecs; | ||
| 2444 | |||
| 2445 | if ((genpd->status == GPD_STATE_POWER_OFF) && | ||
| 2446 | (genpd->state_idx == i)) | ||
| 2447 | delta = ktime_sub(ktime_get(), genpd->accounting_time); | ||
| 2448 | |||
| 2449 | msecs = ktime_to_ms( | ||
| 2450 | ktime_add(genpd->states[i].idle_time, delta)); | ||
| 2451 | seq_printf(s, "S%-13i %lld\n", i, msecs); | ||
| 2452 | } | ||
| 2453 | |||
| 2454 | genpd_unlock(genpd); | ||
| 2455 | return ret; | ||
| 2456 | } | ||
| 2457 | |||
| 2458 | static int genpd_active_time_show(struct seq_file *s, void *data) | ||
| 2459 | { | ||
| 2460 | struct generic_pm_domain *genpd = s->private; | ||
| 2461 | ktime_t delta = 0; | ||
| 2462 | int ret = 0; | ||
| 2463 | |||
| 2464 | ret = genpd_lock_interruptible(genpd); | ||
| 2465 | if (ret) | ||
| 2466 | return -ERESTARTSYS; | ||
| 2467 | |||
| 2468 | if (genpd->status == GPD_STATE_ACTIVE) | ||
| 2469 | delta = ktime_sub(ktime_get(), genpd->accounting_time); | ||
| 2470 | |||
| 2471 | seq_printf(s, "%lld ms\n", ktime_to_ms( | ||
| 2472 | ktime_add(genpd->on_time, delta))); | ||
| 2473 | |||
| 2474 | genpd_unlock(genpd); | ||
| 2475 | return ret; | ||
| 2476 | } | ||
| 2477 | |||
| 2478 | static int genpd_total_idle_time_show(struct seq_file *s, void *data) | ||
| 2479 | { | ||
| 2480 | struct generic_pm_domain *genpd = s->private; | ||
| 2481 | ktime_t delta = 0, total = 0; | ||
| 2482 | unsigned int i; | ||
| 2483 | int ret = 0; | ||
| 2484 | |||
| 2485 | ret = genpd_lock_interruptible(genpd); | ||
| 2486 | if (ret) | ||
| 2487 | return -ERESTARTSYS; | ||
| 2488 | |||
| 2489 | for (i = 0; i < genpd->state_count; i++) { | ||
| 2490 | |||
| 2491 | if ((genpd->status == GPD_STATE_POWER_OFF) && | ||
| 2492 | (genpd->state_idx == i)) | ||
| 2493 | delta = ktime_sub(ktime_get(), genpd->accounting_time); | ||
| 2494 | |||
| 2495 | total = ktime_add(total, genpd->states[i].idle_time); | ||
| 2496 | } | ||
| 2497 | total = ktime_add(total, delta); | ||
| 2498 | |||
| 2499 | seq_printf(s, "%lld ms\n", ktime_to_ms(total)); | ||
| 2500 | |||
| 2501 | genpd_unlock(genpd); | ||
| 2502 | return ret; | ||
| 2503 | } | ||
| 2504 | |||
| 2505 | |||
| 2506 | static int genpd_devices_show(struct seq_file *s, void *data) | ||
| 2507 | { | ||
| 2508 | struct generic_pm_domain *genpd = s->private; | ||
| 2509 | struct pm_domain_data *pm_data; | ||
| 2510 | const char *kobj_path; | ||
| 2511 | int ret = 0; | ||
| 2512 | |||
| 2513 | ret = genpd_lock_interruptible(genpd); | ||
| 2514 | if (ret) | ||
| 2515 | return -ERESTARTSYS; | ||
| 2516 | |||
| 2517 | list_for_each_entry(pm_data, &genpd->dev_list, list_node) { | ||
| 2518 | kobj_path = kobject_get_path(&pm_data->dev->kobj, | ||
| 2519 | genpd_is_irq_safe(genpd) ? | ||
| 2520 | GFP_ATOMIC : GFP_KERNEL); | ||
| 2521 | if (kobj_path == NULL) | ||
| 2522 | continue; | ||
| 2523 | |||
| 2524 | seq_printf(s, "%s\n", kobj_path); | ||
| 2525 | kfree(kobj_path); | ||
| 2526 | } | ||
| 2527 | |||
| 2528 | genpd_unlock(genpd); | ||
| 2529 | return ret; | ||
| 2530 | } | ||
| 2531 | |||
| 2532 | #define define_genpd_open_function(name) \ | ||
| 2533 | static int genpd_##name##_open(struct inode *inode, struct file *file) \ | ||
| 2534 | { \ | ||
| 2535 | return single_open(file, genpd_##name##_show, inode->i_private); \ | ||
| 2536 | } | ||
| 2537 | |||
| 2538 | define_genpd_open_function(summary); | ||
| 2539 | define_genpd_open_function(status); | ||
| 2540 | define_genpd_open_function(sub_domains); | ||
| 2541 | define_genpd_open_function(idle_states); | ||
| 2542 | define_genpd_open_function(active_time); | ||
| 2543 | define_genpd_open_function(total_idle_time); | ||
| 2544 | define_genpd_open_function(devices); | ||
| 2545 | |||
| 2546 | #define define_genpd_debugfs_fops(name) \ | ||
| 2547 | static const struct file_operations genpd_##name##_fops = { \ | ||
| 2548 | .open = genpd_##name##_open, \ | ||
| 2549 | .read = seq_read, \ | ||
| 2550 | .llseek = seq_lseek, \ | ||
| 2551 | .release = single_release, \ | ||
| 2552 | } | ||
| 2553 | |||
| 2554 | define_genpd_debugfs_fops(summary); | ||
| 2555 | define_genpd_debugfs_fops(status); | ||
| 2556 | define_genpd_debugfs_fops(sub_domains); | ||
| 2557 | define_genpd_debugfs_fops(idle_states); | ||
| 2558 | define_genpd_debugfs_fops(active_time); | ||
| 2559 | define_genpd_debugfs_fops(total_idle_time); | ||
| 2560 | define_genpd_debugfs_fops(devices); | ||
| 2396 | 2561 | ||
| 2397 | static int __init pm_genpd_debug_init(void) | 2562 | static int __init pm_genpd_debug_init(void) |
| 2398 | { | 2563 | { |
| 2399 | struct dentry *d; | 2564 | struct dentry *d; |
| 2565 | struct generic_pm_domain *genpd; | ||
| 2400 | 2566 | ||
| 2401 | pm_genpd_debugfs_dir = debugfs_create_dir("pm_genpd", NULL); | 2567 | pm_genpd_debugfs_dir = debugfs_create_dir("pm_genpd", NULL); |
| 2402 | 2568 | ||
| @@ -2404,10 +2570,29 @@ static int __init pm_genpd_debug_init(void) | |||
| 2404 | return -ENOMEM; | 2570 | return -ENOMEM; |
| 2405 | 2571 | ||
| 2406 | d = debugfs_create_file("pm_genpd_summary", S_IRUGO, | 2572 | d = debugfs_create_file("pm_genpd_summary", S_IRUGO, |
| 2407 | pm_genpd_debugfs_dir, NULL, &pm_genpd_summary_fops); | 2573 | pm_genpd_debugfs_dir, NULL, &genpd_summary_fops); |
| 2408 | if (!d) | 2574 | if (!d) |
| 2409 | return -ENOMEM; | 2575 | return -ENOMEM; |
| 2410 | 2576 | ||
| 2577 | list_for_each_entry(genpd, &gpd_list, gpd_list_node) { | ||
| 2578 | d = debugfs_create_dir(genpd->name, pm_genpd_debugfs_dir); | ||
| 2579 | if (!d) | ||
| 2580 | return -ENOMEM; | ||
| 2581 | |||
| 2582 | debugfs_create_file("current_state", 0444, | ||
| 2583 | d, genpd, &genpd_status_fops); | ||
| 2584 | debugfs_create_file("sub_domains", 0444, | ||
| 2585 | d, genpd, &genpd_sub_domains_fops); | ||
| 2586 | debugfs_create_file("idle_states", 0444, | ||
| 2587 | d, genpd, &genpd_idle_states_fops); | ||
| 2588 | debugfs_create_file("active_time", 0444, | ||
| 2589 | d, genpd, &genpd_active_time_fops); | ||
| 2590 | debugfs_create_file("total_idle_time", 0444, | ||
| 2591 | d, genpd, &genpd_total_idle_time_fops); | ||
| 2592 | debugfs_create_file("devices", 0444, | ||
| 2593 | d, genpd, &genpd_devices_fops); | ||
| 2594 | } | ||
| 2595 | |||
| 2411 | return 0; | 2596 | return 0; |
| 2412 | } | 2597 | } |
| 2413 | late_initcall(pm_genpd_debug_init); | 2598 | late_initcall(pm_genpd_debug_init); |
