1# SPDX-License-Identifier: GPL-2.0
2#
3# Copyright (c) NXP 2019
4
5import gdb
6import sys
7
8from linux.utils import CachedType, gdb_eval_or_none
9from linux.lists import list_for_each_entry
10
11generic_pm_domain_type = CachedType('struct generic_pm_domain')
12pm_domain_data_type = CachedType('struct pm_domain_data')
13device_link_type = CachedType('struct device_link')
14
15
16def kobject_get_path(kobj):
17    path = kobj['name'].string()
18    parent = kobj['parent']
19    if parent:
20        path = kobject_get_path(parent) + '/' + path
21    return path
22
23
24def rtpm_status_str(dev):
25    if dev['power']['runtime_error']:
26        return 'error'
27    if dev['power']['disable_depth']:
28        return 'unsupported'
29    _RPM_STATUS_LOOKUP = [
30        "active",
31        "resuming",
32        "suspended",
33        "suspending"
34    ]
35    return _RPM_STATUS_LOOKUP[dev['power']['runtime_status']]
36
37
38class LxGenPDSummary(gdb.Command):
39    '''Print genpd summary
40
41Output is similar to /sys/kernel/debug/pm_genpd/pm_genpd_summary'''
42
43    def __init__(self):
44        super(LxGenPDSummary, self).__init__('lx-genpd-summary', gdb.COMMAND_DATA)
45
46    def summary_one(self, genpd):
47        if genpd['status'] == 0:
48            status_string = 'on'
49        else:
50            status_string = 'off-{}'.format(genpd['state_idx'])
51
52        child_names = []
53        for link in list_for_each_entry(
54                genpd['parent_links'],
55                device_link_type.get_type().pointer(),
56                'parent_node'):
57            child_names.append(link['child']['name'])
58
59        gdb.write('%-30s  %-15s %s\n' % (
60                genpd['name'].string(),
61                status_string,
62                ', '.join(child_names)))
63
64        # Print devices in domain
65        for pm_data in list_for_each_entry(genpd['dev_list'],
66                        pm_domain_data_type.get_type().pointer(),
67                        'list_node'):
68            dev = pm_data['dev']
69            kobj_path = kobject_get_path(dev['kobj'])
70            gdb.write('    %-50s  %s\n' % (kobj_path, rtpm_status_str(dev)))
71
72    def invoke(self, arg, from_tty):
73        if gdb_eval_or_none("&gpd_list") is None:
74            raise gdb.GdbError("No power domain(s) registered")
75        gdb.write('domain                          status          children\n');
76        gdb.write('    /device                                             runtime status\n');
77        gdb.write('----------------------------------------------------------------------\n');
78        for genpd in list_for_each_entry(
79                gdb.parse_and_eval('&gpd_list'),
80                generic_pm_domain_type.get_type().pointer(),
81                'gpd_list_node'):
82            self.summary_one(genpd)
83
84
85LxGenPDSummary()
86