mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-23 22:14:54 +00:00
dm: core: Support sorting devices with dm tree
Add a -s flag to sort the top-level devices in order of uclass ID. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
c0f19fedaa
commit
3d01254140
5 changed files with 114 additions and 12 deletions
10
cmd/dm.c
10
cmd/dm.c
|
@ -59,7 +59,11 @@ static int do_dm_dump_static_driver_info(struct cmd_tbl *cmdtp, int flag,
|
||||||
static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc,
|
static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
char *const argv[])
|
char *const argv[])
|
||||||
{
|
{
|
||||||
dm_dump_tree();
|
bool sort;
|
||||||
|
|
||||||
|
sort = argc > 1 && !strcmp(argv[1], "-s");
|
||||||
|
|
||||||
|
dm_dump_tree(sort);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +91,7 @@ static char dm_help_text[] =
|
||||||
"dm drivers Dump list of drivers with uclass and instances\n"
|
"dm drivers Dump list of drivers with uclass and instances\n"
|
||||||
DM_MEM_HELP
|
DM_MEM_HELP
|
||||||
"dm static Dump list of drivers with static platform data\n"
|
"dm static Dump list of drivers with static platform data\n"
|
||||||
"dm tree Dump tree of driver model devices ('*' = activated)\n"
|
"dm tree [-s] Dump tree of driver model devices (-s=sort)\n"
|
||||||
"dm uclass Dump list of instances for each uclass"
|
"dm uclass Dump list of instances for each uclass"
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
|
@ -98,5 +102,5 @@ U_BOOT_CMD_WITH_SUBCMDS(dm, "Driver model low level access", dm_help_text,
|
||||||
U_BOOT_SUBCMD_MKENT(drivers, 1, 1, do_dm_dump_drivers),
|
U_BOOT_SUBCMD_MKENT(drivers, 1, 1, do_dm_dump_drivers),
|
||||||
DM_MEM
|
DM_MEM
|
||||||
U_BOOT_SUBCMD_MKENT(static, 1, 1, do_dm_dump_static_driver_info),
|
U_BOOT_SUBCMD_MKENT(static, 1, 1, do_dm_dump_static_driver_info),
|
||||||
U_BOOT_SUBCMD_MKENT(tree, 1, 1, do_dm_dump_tree),
|
U_BOOT_SUBCMD_MKENT(tree, 2, 1, do_dm_dump_tree),
|
||||||
U_BOOT_SUBCMD_MKENT(uclass, 1, 1, do_dm_dump_uclass));
|
U_BOOT_SUBCMD_MKENT(uclass, 1, 1, do_dm_dump_uclass));
|
||||||
|
|
|
@ -12,7 +12,7 @@ Synopis
|
||||||
dm devres
|
dm devres
|
||||||
dm drivers
|
dm drivers
|
||||||
dm static
|
dm static
|
||||||
dm tree
|
dm tree [-s]
|
||||||
dm uclass
|
dm uclass
|
||||||
|
|
||||||
Description
|
Description
|
||||||
|
@ -123,6 +123,9 @@ Name
|
||||||
Shows the device name as well as the tree structure, since child devices are
|
Shows the device name as well as the tree structure, since child devices are
|
||||||
shown attached to their parent.
|
shown attached to their parent.
|
||||||
|
|
||||||
|
If -s is given, the top-level devices (those which are children of the root
|
||||||
|
device) are shown sorted in order of uclass ID, so it is easier to find a
|
||||||
|
particular device type.
|
||||||
|
|
||||||
dm uclass
|
dm uclass
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
|
@ -5,12 +5,34 @@
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <malloc.h>
|
||||||
#include <mapmem.h>
|
#include <mapmem.h>
|
||||||
|
#include <sort.h>
|
||||||
#include <dm/root.h>
|
#include <dm/root.h>
|
||||||
#include <dm/util.h>
|
#include <dm/util.h>
|
||||||
#include <dm/uclass-internal.h>
|
#include <dm/uclass-internal.h>
|
||||||
|
|
||||||
static void show_devices(struct udevice *dev, int depth, int last_flag)
|
/**
|
||||||
|
* struct sort_info - information used for sorting
|
||||||
|
*
|
||||||
|
* @dev: List of devices
|
||||||
|
* @alloced: Maximum number of devices in @dev
|
||||||
|
*/
|
||||||
|
struct sort_info {
|
||||||
|
struct udevice **dev;
|
||||||
|
int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int h_cmp_uclass_id(const void *d1, const void *d2)
|
||||||
|
{
|
||||||
|
const struct udevice *const *dev1 = d1;
|
||||||
|
const struct udevice *const *dev2 = d2;
|
||||||
|
|
||||||
|
return device_get_uclass_id(*dev1) - device_get_uclass_id(*dev2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_devices(struct udevice *dev, int depth, int last_flag,
|
||||||
|
struct udevice **devs)
|
||||||
{
|
{
|
||||||
int i, is_last;
|
int i, is_last;
|
||||||
struct udevice *child;
|
struct udevice *child;
|
||||||
|
@ -39,21 +61,52 @@ static void show_devices(struct udevice *dev, int depth, int last_flag)
|
||||||
|
|
||||||
printf("%s\n", dev->name);
|
printf("%s\n", dev->name);
|
||||||
|
|
||||||
|
if (devs) {
|
||||||
|
int count;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
device_foreach_child(child, dev)
|
||||||
|
devs[count++] = child;
|
||||||
|
qsort(devs, count, sizeof(struct udevice *), h_cmp_uclass_id);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
show_devices(devs[i], depth + 1,
|
||||||
|
(last_flag << 1) | (i == count - 1),
|
||||||
|
devs + count);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
device_foreach_child(child, dev) {
|
device_foreach_child(child, dev) {
|
||||||
is_last = list_is_last(&child->sibling_node, &dev->child_head);
|
is_last = list_is_last(&child->sibling_node,
|
||||||
show_devices(child, depth + 1, (last_flag << 1) | is_last);
|
&dev->child_head);
|
||||||
|
show_devices(child, depth + 1,
|
||||||
|
(last_flag << 1) | is_last, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dm_dump_tree(void)
|
void dm_dump_tree(bool sort)
|
||||||
{
|
{
|
||||||
struct udevice *root;
|
struct udevice *root;
|
||||||
|
|
||||||
root = dm_root();
|
root = dm_root();
|
||||||
if (root) {
|
if (root) {
|
||||||
|
int dev_count, uclasses;
|
||||||
|
struct udevice **devs = NULL;
|
||||||
|
|
||||||
|
dm_get_stats(&dev_count, &uclasses);
|
||||||
|
|
||||||
printf(" Class Index Probed Driver Name\n");
|
printf(" Class Index Probed Driver Name\n");
|
||||||
printf("-----------------------------------------------------------\n");
|
printf("-----------------------------------------------------------\n");
|
||||||
show_devices(root, -1, 0);
|
if (sort) {
|
||||||
|
devs = calloc(dev_count, sizeof(struct udevice *));
|
||||||
|
if (!devs) {
|
||||||
|
printf("(out of memory)\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
show_devices(root, -1, 0, devs);
|
||||||
|
free(devs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,12 @@ struct list_head;
|
||||||
*/
|
*/
|
||||||
int list_count_items(struct list_head *head);
|
int list_count_items(struct list_head *head);
|
||||||
|
|
||||||
/* Dump out a tree of all devices */
|
/**
|
||||||
void dm_dump_tree(void);
|
* Dump out a tree of all devices
|
||||||
|
*
|
||||||
|
* @sort: Sort by uclass name
|
||||||
|
*/
|
||||||
|
void dm_dump_tree(bool sort);
|
||||||
|
|
||||||
/* Dump out a list of uclasses and their devices */
|
/* Dump out a list of uclasses and their devices */
|
||||||
void dm_dump_uclass(void);
|
void dm_dump_uclass(void);
|
||||||
|
|
|
@ -16,6 +16,44 @@ def test_dm_compat(u_boot_console):
|
||||||
for driver in drivers:
|
for driver in drivers:
|
||||||
assert driver in response
|
assert driver in response
|
||||||
|
|
||||||
|
# check sorting - output looks something like this:
|
||||||
|
# testacpi 0 [ ] testacpi_drv |-- acpi-test
|
||||||
|
# testacpi 1 [ ] testacpi_drv | `-- child
|
||||||
|
# pci_emul_p 1 [ ] pci_emul_parent_drv |-- pci-emul2
|
||||||
|
# pci_emul 5 [ ] sandbox_swap_case_em | `-- emul2@1f,0
|
||||||
|
|
||||||
|
# The number of '| ' and '--' matches indicate the indent level. We start
|
||||||
|
# checking sorting only after UCLASS_AXI_EMUL after which the names should
|
||||||
|
# be sorted.
|
||||||
|
|
||||||
|
response = u_boot_console.run_command('dm tree -s')
|
||||||
|
lines = response.split('\n')[2:]
|
||||||
|
stack = [] # holds where we were up to at the previous indent level
|
||||||
|
prev = '' # uclass name of previous line
|
||||||
|
start = False
|
||||||
|
for line in lines:
|
||||||
|
indent = line.count('| ') + ('--' in line)
|
||||||
|
cur = line.split()[0]
|
||||||
|
if not start:
|
||||||
|
if cur != 'axi_emul':
|
||||||
|
continue
|
||||||
|
start = True
|
||||||
|
|
||||||
|
# Handle going up or down an indent level
|
||||||
|
if indent > len(stack):
|
||||||
|
stack.append(prev)
|
||||||
|
prev = ''
|
||||||
|
elif indent < len(stack):
|
||||||
|
prev = stack.pop()
|
||||||
|
|
||||||
|
# Check that the current uclass name is not alphabetically before the
|
||||||
|
# previous one
|
||||||
|
if 'emul' not in cur and cur < prev:
|
||||||
|
print('indent', cur >= prev, indent, prev, cur, stack)
|
||||||
|
assert cur >= prev
|
||||||
|
prev = cur
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.buildconfigspec('cmd_dm')
|
@pytest.mark.buildconfigspec('cmd_dm')
|
||||||
def test_dm_drivers(u_boot_console):
|
def test_dm_drivers(u_boot_console):
|
||||||
"""Test that each driver in `dm compat` is also listed in `dm drivers`."""
|
"""Test that each driver in `dm compat` is also listed in `dm drivers`."""
|
||||||
|
|
Loading…
Add table
Reference in a new issue