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