aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/power/domain.c205
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
2362static int pm_genpd_summary_show(struct seq_file *s, void *data) 2362static 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
2385static int pm_genpd_summary_open(struct inode *inode, struct file *file) 2385static 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]);
2407exit:
2408 genpd_unlock(genpd);
2409 return ret;
2388} 2410}
2389 2411
2390static const struct file_operations pm_genpd_summary_fops = { 2412static 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
2429static 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
2458static 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
2478static 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
2506static 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) \
2533static int genpd_##name##_open(struct inode *inode, struct file *file) \
2534{ \
2535 return single_open(file, genpd_##name##_show, inode->i_private); \
2536}
2537
2538define_genpd_open_function(summary);
2539define_genpd_open_function(status);
2540define_genpd_open_function(sub_domains);
2541define_genpd_open_function(idle_states);
2542define_genpd_open_function(active_time);
2543define_genpd_open_function(total_idle_time);
2544define_genpd_open_function(devices);
2545
2546#define define_genpd_debugfs_fops(name) \
2547static 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
2554define_genpd_debugfs_fops(summary);
2555define_genpd_debugfs_fops(status);
2556define_genpd_debugfs_fops(sub_domains);
2557define_genpd_debugfs_fops(idle_states);
2558define_genpd_debugfs_fops(active_time);
2559define_genpd_debugfs_fops(total_idle_time);
2560define_genpd_debugfs_fops(devices);
2396 2561
2397static int __init pm_genpd_debug_init(void) 2562static 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}
2413late_initcall(pm_genpd_debug_init); 2598late_initcall(pm_genpd_debug_init);