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