xref: /linux-6.15/scripts/gdb/linux/device.py (revision 801a2b1b)
1778c1f5cSLeonard Crestez# SPDX-License-Identifier: GPL-2.0
2778c1f5cSLeonard Crestez#
3778c1f5cSLeonard Crestez# Copyright (c) NXP 2019
4778c1f5cSLeonard Crestez
5778c1f5cSLeonard Crestezimport gdb
6778c1f5cSLeonard Crestez
7778c1f5cSLeonard Crestezfrom linux.utils import CachedType
8778c1f5cSLeonard Crestezfrom linux.utils import container_of
9778c1f5cSLeonard Crestezfrom linux.lists import list_for_each_entry
10778c1f5cSLeonard Crestez
11778c1f5cSLeonard Crestez
12778c1f5cSLeonard Crestezdevice_private_type = CachedType('struct device_private')
13778c1f5cSLeonard Crestezdevice_type = CachedType('struct device')
14778c1f5cSLeonard Crestez
15778c1f5cSLeonard Crestezsubsys_private_type = CachedType('struct subsys_private')
16778c1f5cSLeonard Crestezkobject_type = CachedType('struct kobject')
17778c1f5cSLeonard Crestezkset_type = CachedType('struct kset')
18778c1f5cSLeonard Crestez
19778c1f5cSLeonard Crestezbus_type = CachedType('struct bus_type')
20778c1f5cSLeonard Crestezclass_type = CachedType('struct class')
21778c1f5cSLeonard Crestez
22778c1f5cSLeonard Crestez
23778c1f5cSLeonard Crestezdef dev_name(dev):
24778c1f5cSLeonard Crestez    dev_init_name = dev['init_name']
25778c1f5cSLeonard Crestez    if dev_init_name:
26778c1f5cSLeonard Crestez        return dev_init_name.string()
27778c1f5cSLeonard Crestez    return dev['kobj']['name'].string()
28778c1f5cSLeonard Crestez
29778c1f5cSLeonard Crestez
30778c1f5cSLeonard Crestezdef kset_for_each_object(kset):
31778c1f5cSLeonard Crestez    return list_for_each_entry(kset['list'],
32778c1f5cSLeonard Crestez            kobject_type.get_type().pointer(), "entry")
33778c1f5cSLeonard Crestez
34778c1f5cSLeonard Crestez
35778c1f5cSLeonard Crestezdef for_each_bus():
36778c1f5cSLeonard Crestez    for kobj in kset_for_each_object(gdb.parse_and_eval('bus_kset')):
37778c1f5cSLeonard Crestez        subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
38778c1f5cSLeonard Crestez        subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
39*801a2b1bSFlorian Fainelli        yield subsys_priv
40778c1f5cSLeonard Crestez
41778c1f5cSLeonard Crestez
42778c1f5cSLeonard Crestezdef for_each_class():
43778c1f5cSLeonard Crestez    for kobj in kset_for_each_object(gdb.parse_and_eval('class_kset')):
44778c1f5cSLeonard Crestez        subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
45778c1f5cSLeonard Crestez        subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
46*801a2b1bSFlorian Fainelli        yield subsys_priv
47778c1f5cSLeonard Crestez
48778c1f5cSLeonard Crestez
49778c1f5cSLeonard Crestezdef get_bus_by_name(name):
50778c1f5cSLeonard Crestez    for item in for_each_bus():
51*801a2b1bSFlorian Fainelli        if item['bus']['name'].string() == name:
52778c1f5cSLeonard Crestez            return item
53778c1f5cSLeonard Crestez    raise gdb.GdbError("Can't find bus type {!r}".format(name))
54778c1f5cSLeonard Crestez
55778c1f5cSLeonard Crestez
56778c1f5cSLeonard Crestezdef get_class_by_name(name):
57778c1f5cSLeonard Crestez    for item in for_each_class():
58*801a2b1bSFlorian Fainelli        if item['class']['name'].string() == name:
59778c1f5cSLeonard Crestez            return item
60778c1f5cSLeonard Crestez    raise gdb.GdbError("Can't find device class {!r}".format(name))
61778c1f5cSLeonard Crestez
62778c1f5cSLeonard Crestez
63778c1f5cSLeonard Crestezklist_type = CachedType('struct klist')
64778c1f5cSLeonard Crestezklist_node_type = CachedType('struct klist_node')
65778c1f5cSLeonard Crestez
66778c1f5cSLeonard Crestez
67778c1f5cSLeonard Crestezdef klist_for_each(klist):
68778c1f5cSLeonard Crestez    return list_for_each_entry(klist['k_list'],
69778c1f5cSLeonard Crestez                klist_node_type.get_type().pointer(), 'n_node')
70778c1f5cSLeonard Crestez
71778c1f5cSLeonard Crestez
72778c1f5cSLeonard Crestezdef bus_for_each_device(bus):
73*801a2b1bSFlorian Fainelli    for kn in klist_for_each(bus['klist_devices']):
74778c1f5cSLeonard Crestez        dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_bus')
75778c1f5cSLeonard Crestez        yield dp['device']
76778c1f5cSLeonard Crestez
77778c1f5cSLeonard Crestez
78778c1f5cSLeonard Crestezdef class_for_each_device(cls):
79*801a2b1bSFlorian Fainelli    for kn in klist_for_each(cls['klist_devices']):
80778c1f5cSLeonard Crestez        dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_class')
81778c1f5cSLeonard Crestez        yield dp['device']
82778c1f5cSLeonard Crestez
83778c1f5cSLeonard Crestez
84778c1f5cSLeonard Crestezdef device_for_each_child(dev):
85778c1f5cSLeonard Crestez    for kn in klist_for_each(dev['p']['klist_children']):
86778c1f5cSLeonard Crestez        dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_parent')
87778c1f5cSLeonard Crestez        yield dp['device']
88778c1f5cSLeonard Crestez
89778c1f5cSLeonard Crestez
90778c1f5cSLeonard Crestezdef _show_device(dev, level=0, recursive=False):
91778c1f5cSLeonard Crestez    gdb.write('{}dev {}:\t{}\n'.format('\t' * level, dev_name(dev), dev))
92778c1f5cSLeonard Crestez    if recursive:
93778c1f5cSLeonard Crestez        for child in device_for_each_child(dev):
94778c1f5cSLeonard Crestez            _show_device(child, level + 1, recursive)
95778c1f5cSLeonard Crestez
96778c1f5cSLeonard Crestez
97778c1f5cSLeonard Crestezclass LxDeviceListBus(gdb.Command):
98778c1f5cSLeonard Crestez    '''Print devices on a bus (or all buses if not specified)'''
99778c1f5cSLeonard Crestez
100778c1f5cSLeonard Crestez    def __init__(self):
101778c1f5cSLeonard Crestez        super(LxDeviceListBus, self).__init__('lx-device-list-bus', gdb.COMMAND_DATA)
102778c1f5cSLeonard Crestez
103778c1f5cSLeonard Crestez    def invoke(self, arg, from_tty):
104778c1f5cSLeonard Crestez        if not arg:
105778c1f5cSLeonard Crestez            for bus in for_each_bus():
106*801a2b1bSFlorian Fainelli                gdb.write('bus {}:\t{}\n'.format(bus['bus']['name'].string(), bus))
107778c1f5cSLeonard Crestez                for dev in bus_for_each_device(bus):
108778c1f5cSLeonard Crestez                    _show_device(dev, level=1)
109778c1f5cSLeonard Crestez        else:
110778c1f5cSLeonard Crestez            bus = get_bus_by_name(arg)
111778c1f5cSLeonard Crestez            if not bus:
112778c1f5cSLeonard Crestez                raise gdb.GdbError("Can't find bus {!r}".format(arg))
113778c1f5cSLeonard Crestez            for dev in bus_for_each_device(bus):
114778c1f5cSLeonard Crestez                _show_device(dev)
115778c1f5cSLeonard Crestez
116778c1f5cSLeonard Crestez
117778c1f5cSLeonard Crestezclass LxDeviceListClass(gdb.Command):
118778c1f5cSLeonard Crestez    '''Print devices in a class (or all classes if not specified)'''
119778c1f5cSLeonard Crestez
120778c1f5cSLeonard Crestez    def __init__(self):
121778c1f5cSLeonard Crestez        super(LxDeviceListClass, self).__init__('lx-device-list-class', gdb.COMMAND_DATA)
122778c1f5cSLeonard Crestez
123778c1f5cSLeonard Crestez    def invoke(self, arg, from_tty):
124778c1f5cSLeonard Crestez        if not arg:
125778c1f5cSLeonard Crestez            for cls in for_each_class():
126*801a2b1bSFlorian Fainelli                gdb.write("class {}:\t{}\n".format(cls['class']['name'].string(), cls))
127778c1f5cSLeonard Crestez                for dev in class_for_each_device(cls):
128778c1f5cSLeonard Crestez                    _show_device(dev, level=1)
129778c1f5cSLeonard Crestez        else:
130778c1f5cSLeonard Crestez            cls = get_class_by_name(arg)
131778c1f5cSLeonard Crestez            for dev in class_for_each_device(cls):
132778c1f5cSLeonard Crestez                _show_device(dev)
133778c1f5cSLeonard Crestez
134778c1f5cSLeonard Crestez
135778c1f5cSLeonard Crestezclass LxDeviceListTree(gdb.Command):
136778c1f5cSLeonard Crestez    '''Print a device and its children recursively'''
137778c1f5cSLeonard Crestez
138778c1f5cSLeonard Crestez    def __init__(self):
139778c1f5cSLeonard Crestez        super(LxDeviceListTree, self).__init__('lx-device-list-tree', gdb.COMMAND_DATA)
140778c1f5cSLeonard Crestez
141778c1f5cSLeonard Crestez    def invoke(self, arg, from_tty):
142778c1f5cSLeonard Crestez        if not arg:
143778c1f5cSLeonard Crestez            raise gdb.GdbError('Please provide pointer to struct device')
144778c1f5cSLeonard Crestez        dev = gdb.parse_and_eval(arg)
145778c1f5cSLeonard Crestez        if dev.type != device_type.get_type().pointer():
146778c1f5cSLeonard Crestez            raise gdb.GdbError('Please provide pointer to struct device')
147778c1f5cSLeonard Crestez        _show_device(dev, level=0, recursive=True)
148778c1f5cSLeonard Crestez
149778c1f5cSLeonard Crestez
150778c1f5cSLeonard Crestezclass LxDeviceFindByBusName(gdb.Function):
151778c1f5cSLeonard Crestez    '''Find struct device by bus and name (both strings)'''
152778c1f5cSLeonard Crestez
153778c1f5cSLeonard Crestez    def __init__(self):
154778c1f5cSLeonard Crestez        super(LxDeviceFindByBusName, self).__init__('lx_device_find_by_bus_name')
155778c1f5cSLeonard Crestez
156778c1f5cSLeonard Crestez    def invoke(self, bus, name):
157778c1f5cSLeonard Crestez        name = name.string()
158778c1f5cSLeonard Crestez        bus = get_bus_by_name(bus.string())
159778c1f5cSLeonard Crestez        for dev in bus_for_each_device(bus):
160778c1f5cSLeonard Crestez            if dev_name(dev) == name:
161778c1f5cSLeonard Crestez                return dev
162778c1f5cSLeonard Crestez
163778c1f5cSLeonard Crestez
164778c1f5cSLeonard Crestezclass LxDeviceFindByClassName(gdb.Function):
165778c1f5cSLeonard Crestez    '''Find struct device by class and name (both strings)'''
166778c1f5cSLeonard Crestez
167778c1f5cSLeonard Crestez    def __init__(self):
168778c1f5cSLeonard Crestez        super(LxDeviceFindByClassName, self).__init__('lx_device_find_by_class_name')
169778c1f5cSLeonard Crestez
170778c1f5cSLeonard Crestez    def invoke(self, cls, name):
171778c1f5cSLeonard Crestez        name = name.string()
172778c1f5cSLeonard Crestez        cls = get_class_by_name(cls.string())
173778c1f5cSLeonard Crestez        for dev in class_for_each_device(cls):
174778c1f5cSLeonard Crestez            if dev_name(dev) == name:
175778c1f5cSLeonard Crestez                return dev
176778c1f5cSLeonard Crestez
177778c1f5cSLeonard Crestez
178778c1f5cSLeonard CrestezLxDeviceListBus()
179778c1f5cSLeonard CrestezLxDeviceListClass()
180778c1f5cSLeonard CrestezLxDeviceListTree()
181778c1f5cSLeonard CrestezLxDeviceFindByBusName()
182778c1f5cSLeonard CrestezLxDeviceFindByClassName()
183