1# SPDX-License-Identifier: GPL-2.0 2# 3# Copyright (c) NXP 2019 4 5import gdb 6 7from linux.utils import CachedType 8from linux.utils import container_of 9from linux.lists import list_for_each_entry 10 11 12device_private_type = CachedType('struct device_private') 13device_type = CachedType('struct device') 14 15subsys_private_type = CachedType('struct subsys_private') 16kobject_type = CachedType('struct kobject') 17kset_type = CachedType('struct kset') 18 19bus_type = CachedType('struct bus_type') 20class_type = CachedType('struct class') 21 22 23def dev_name(dev): 24 dev_init_name = dev['init_name'] 25 if dev_init_name: 26 return dev_init_name.string() 27 return dev['kobj']['name'].string() 28 29 30def kset_for_each_object(kset): 31 return list_for_each_entry(kset['list'], 32 kobject_type.get_type().pointer(), "entry") 33 34 35def for_each_bus(): 36 for kobj in kset_for_each_object(gdb.parse_and_eval('bus_kset')): 37 subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj') 38 subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys') 39 yield subsys_priv 40 41 42def for_each_class(): 43 for kobj in kset_for_each_object(gdb.parse_and_eval('class_kset')): 44 subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj') 45 subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys') 46 yield subsys_priv 47 48 49def get_bus_by_name(name): 50 for item in for_each_bus(): 51 if item['bus']['name'].string() == name: 52 return item 53 raise gdb.GdbError("Can't find bus type {!r}".format(name)) 54 55 56def get_class_by_name(name): 57 for item in for_each_class(): 58 if item['class']['name'].string() == name: 59 return item 60 raise gdb.GdbError("Can't find device class {!r}".format(name)) 61 62 63klist_type = CachedType('struct klist') 64klist_node_type = CachedType('struct klist_node') 65 66 67def klist_for_each(klist): 68 return list_for_each_entry(klist['k_list'], 69 klist_node_type.get_type().pointer(), 'n_node') 70 71 72def bus_for_each_device(bus): 73 for kn in klist_for_each(bus['klist_devices']): 74 dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_bus') 75 yield dp['device'] 76 77 78def class_for_each_device(cls): 79 for kn in klist_for_each(cls['klist_devices']): 80 dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_class') 81 yield dp['device'] 82 83 84def device_for_each_child(dev): 85 for kn in klist_for_each(dev['p']['klist_children']): 86 dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_parent') 87 yield dp['device'] 88 89 90def _show_device(dev, level=0, recursive=False): 91 gdb.write('{}dev {}:\t{}\n'.format('\t' * level, dev_name(dev), dev)) 92 if recursive: 93 for child in device_for_each_child(dev): 94 _show_device(child, level + 1, recursive) 95 96 97class LxDeviceListBus(gdb.Command): 98 '''Print devices on a bus (or all buses if not specified)''' 99 100 def __init__(self): 101 super(LxDeviceListBus, self).__init__('lx-device-list-bus', gdb.COMMAND_DATA) 102 103 def invoke(self, arg, from_tty): 104 if not arg: 105 for bus in for_each_bus(): 106 gdb.write('bus {}:\t{}\n'.format(bus['bus']['name'].string(), bus)) 107 for dev in bus_for_each_device(bus): 108 _show_device(dev, level=1) 109 else: 110 bus = get_bus_by_name(arg) 111 if not bus: 112 raise gdb.GdbError("Can't find bus {!r}".format(arg)) 113 for dev in bus_for_each_device(bus): 114 _show_device(dev) 115 116 117class LxDeviceListClass(gdb.Command): 118 '''Print devices in a class (or all classes if not specified)''' 119 120 def __init__(self): 121 super(LxDeviceListClass, self).__init__('lx-device-list-class', gdb.COMMAND_DATA) 122 123 def invoke(self, arg, from_tty): 124 if not arg: 125 for cls in for_each_class(): 126 gdb.write("class {}:\t{}\n".format(cls['class']['name'].string(), cls)) 127 for dev in class_for_each_device(cls): 128 _show_device(dev, level=1) 129 else: 130 cls = get_class_by_name(arg) 131 for dev in class_for_each_device(cls): 132 _show_device(dev) 133 134 135class LxDeviceListTree(gdb.Command): 136 '''Print a device and its children recursively''' 137 138 def __init__(self): 139 super(LxDeviceListTree, self).__init__('lx-device-list-tree', gdb.COMMAND_DATA) 140 141 def invoke(self, arg, from_tty): 142 if not arg: 143 raise gdb.GdbError('Please provide pointer to struct device') 144 dev = gdb.parse_and_eval(arg) 145 if dev.type != device_type.get_type().pointer(): 146 raise gdb.GdbError('Please provide pointer to struct device') 147 _show_device(dev, level=0, recursive=True) 148 149 150class LxDeviceFindByBusName(gdb.Function): 151 '''Find struct device by bus and name (both strings)''' 152 153 def __init__(self): 154 super(LxDeviceFindByBusName, self).__init__('lx_device_find_by_bus_name') 155 156 def invoke(self, bus, name): 157 name = name.string() 158 bus = get_bus_by_name(bus.string()) 159 for dev in bus_for_each_device(bus): 160 if dev_name(dev) == name: 161 return dev 162 163 164class LxDeviceFindByClassName(gdb.Function): 165 '''Find struct device by class and name (both strings)''' 166 167 def __init__(self): 168 super(LxDeviceFindByClassName, self).__init__('lx_device_find_by_class_name') 169 170 def invoke(self, cls, name): 171 name = name.string() 172 cls = get_class_by_name(cls.string()) 173 for dev in class_for_each_device(cls): 174 if dev_name(dev) == name: 175 return dev 176 177 178LxDeviceListBus() 179LxDeviceListClass() 180LxDeviceListTree() 181LxDeviceFindByBusName() 182LxDeviceFindByClassName() 183