@@ -209,6 +209,34 @@ static void genpd_sd_counter_inc(struct generic_pm_domain *genpd)
209
209
smp_mb__after_atomic ();
210
210
}
211
211
212
+ #ifdef CONFIG_DEBUG_FS
213
+ static void genpd_update_accounting (struct generic_pm_domain * genpd )
214
+ {
215
+ ktime_t delta , now ;
216
+
217
+ now = ktime_get ();
218
+ delta = ktime_sub (now , genpd -> accounting_time );
219
+
220
+ /*
221
+ * If genpd->status is active, it means we are just
222
+ * out of off and so update the idle time and vice
223
+ * versa.
224
+ */
225
+ if (genpd -> status == GPD_STATE_ACTIVE ) {
226
+ int state_idx = genpd -> state_idx ;
227
+
228
+ genpd -> states [state_idx ].idle_time =
229
+ ktime_add (genpd -> states [state_idx ].idle_time , delta );
230
+ } else {
231
+ genpd -> on_time = ktime_add (genpd -> on_time , delta );
232
+ }
233
+
234
+ genpd -> accounting_time = now ;
235
+ }
236
+ #else
237
+ static inline void genpd_update_accounting (struct generic_pm_domain * genpd ) {}
238
+ #endif
239
+
212
240
static int _genpd_power_on (struct generic_pm_domain * genpd , bool timed )
213
241
{
214
242
unsigned int state_idx = genpd -> state_idx ;
@@ -361,6 +389,7 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
361
389
}
362
390
363
391
genpd -> status = GPD_STATE_POWER_OFF ;
392
+ genpd_update_accounting (genpd );
364
393
365
394
list_for_each_entry (link , & genpd -> slave_links , slave_node ) {
366
395
genpd_sd_counter_dec (link -> master );
@@ -413,6 +442,8 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
413
442
goto err ;
414
443
415
444
genpd -> status = GPD_STATE_ACTIVE ;
445
+ genpd_update_accounting (genpd );
446
+
416
447
return 0 ;
417
448
418
449
err :
@@ -1540,6 +1571,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
1540
1571
genpd -> max_off_time_changed = true;
1541
1572
genpd -> provider = NULL ;
1542
1573
genpd -> has_provider = false;
1574
+ genpd -> accounting_time = ktime_get ();
1543
1575
genpd -> domain .ops .runtime_suspend = genpd_runtime_suspend ;
1544
1576
genpd -> domain .ops .runtime_resume = genpd_runtime_resume ;
1545
1577
genpd -> domain .ops .prepare = pm_genpd_prepare ;
@@ -1743,7 +1775,7 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
1743
1775
mutex_lock (& of_genpd_mutex );
1744
1776
list_add (& cp -> link , & of_genpd_providers );
1745
1777
mutex_unlock (& of_genpd_mutex );
1746
- pr_debug ("Added domain provider from %s \n" , np -> full_name );
1778
+ pr_debug ("Added domain provider from %pOF \n" , np );
1747
1779
1748
1780
return 0 ;
1749
1781
}
@@ -2149,16 +2181,16 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state,
2149
2181
err = of_property_read_u32 (state_node , "entry-latency-us" ,
2150
2182
& entry_latency );
2151
2183
if (err ) {
2152
- pr_debug (" * %s missing entry-latency-us property\n" ,
2153
- state_node -> full_name );
2184
+ pr_debug (" * %pOF missing entry-latency-us property\n" ,
2185
+ state_node );
2154
2186
return - EINVAL ;
2155
2187
}
2156
2188
2157
2189
err = of_property_read_u32 (state_node , "exit-latency-us" ,
2158
2190
& exit_latency );
2159
2191
if (err ) {
2160
- pr_debug (" * %s missing exit-latency-us property\n" ,
2161
- state_node -> full_name );
2192
+ pr_debug (" * %pOF missing exit-latency-us property\n" ,
2193
+ state_node );
2162
2194
return - EINVAL ;
2163
2195
}
2164
2196
@@ -2212,8 +2244,8 @@ int of_genpd_parse_idle_states(struct device_node *dn,
2212
2244
ret = genpd_parse_state (& st [i ++ ], np );
2213
2245
if (ret ) {
2214
2246
pr_err
2215
- ("Parsing idle state node %s failed with err %d\n" ,
2216
- np -> full_name , ret );
2247
+ ("Parsing idle state node %pOF failed with err %d\n" ,
2248
+ np , ret );
2217
2249
of_node_put (np );
2218
2250
kfree (st );
2219
2251
return ret ;
@@ -2327,7 +2359,7 @@ static int pm_genpd_summary_one(struct seq_file *s,
2327
2359
return 0 ;
2328
2360
}
2329
2361
2330
- static int pm_genpd_summary_show (struct seq_file * s , void * data )
2362
+ static int genpd_summary_show (struct seq_file * s , void * data )
2331
2363
{
2332
2364
struct generic_pm_domain * genpd ;
2333
2365
int ret = 0 ;
@@ -2350,32 +2382,217 @@ static int pm_genpd_summary_show(struct seq_file *s, void *data)
2350
2382
return ret ;
2351
2383
}
2352
2384
2353
- static int pm_genpd_summary_open (struct inode * inode , struct file * file )
2385
+ static int genpd_status_show (struct seq_file * s , void * data )
2354
2386
{
2355
- 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 ;
2356
2410
}
2357
2411
2358
- static const struct file_operations pm_genpd_summary_fops = {
2359
- .open = pm_genpd_summary_open ,
2360
- .read = seq_read ,
2361
- .llseek = seq_lseek ,
2362
- .release = single_release ,
2363
- };
2412
+ static int genpd_sub_domains_show (struct seq_file * s , void * data )
2413
+ {
2414
+ struct generic_pm_domain * genpd = s -> private ;
2415
+ struct gpd_link * link ;
2416
+ int ret = 0 ;
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 );
2364
2561
2365
2562
static int __init pm_genpd_debug_init (void )
2366
2563
{
2367
2564
struct dentry * d ;
2565
+ struct generic_pm_domain * genpd ;
2368
2566
2369
2567
pm_genpd_debugfs_dir = debugfs_create_dir ("pm_genpd" , NULL );
2370
2568
2371
2569
if (!pm_genpd_debugfs_dir )
2372
2570
return - ENOMEM ;
2373
2571
2374
2572
d = debugfs_create_file ("pm_genpd_summary" , S_IRUGO ,
2375
- pm_genpd_debugfs_dir , NULL , & pm_genpd_summary_fops );
2573
+ pm_genpd_debugfs_dir , NULL , & genpd_summary_fops );
2376
2574
if (!d )
2377
2575
return - ENOMEM ;
2378
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
+
2379
2596
return 0 ;
2380
2597
}
2381
2598
late_initcall (pm_genpd_debug_init );
0 commit comments