From 7eb8744984a8b7ed52d35a291ff5ed6373e93499 Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Sat, 22 Apr 2023 11:47:24 +0200 Subject: ls-tree: Fix parsing devices on multidomain PCI system Represent each domain as domain bridge under the &host_bridge and put root bus of each domain under the domain bridge. With this change lspci in tree view does not show zero bus on domain 0 in the output if this bus does not exist at all. Root bus in PCIe hierarchy does not have to be zero and on Freescale PowerPC systems it is common. Also with this change are separate domain showed in the output separately. --- ls-tree.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/ls-tree.c b/ls-tree.c index 6fa6d51..43ff9b1 100644 --- a/ls-tree.c +++ b/ls-tree.c @@ -73,6 +73,15 @@ insert_dev(struct device *d, struct bridge *b) bus = new_bus(parent->bridge, p->domain, p->bus); } + if (!bus && b == &host_bridge) + { + for (b=b->child; b; b=b->prev) + if (b->domain == (unsigned)p->domain) + break; + if (!b) + b = &host_bridge; + } + if (!bus && ! (bus = find_bus(b, p->domain, p->bus))) { struct bridge *c; @@ -100,9 +109,34 @@ grow_tree(void) struct device *d; struct bridge **last_br, *b; + last_br = &host_bridge.chain; + + /* Build list of top level domain bridges */ + + for (d=first_dev; d; d=d->next) + { + for (b=host_bridge.chain; b; b=b->chain) + if (b->domain == (unsigned)d->dev->domain) + break; + if (b) + continue; + b = xmalloc(sizeof(struct bridge)); + b->domain = d->dev->domain; + b->primary = ~0; + b->secondary = 0; + b->subordinate = ~0; + *last_br = b; + last_br = &b->chain; + b->prev = b->child = NULL; + b->first_bus = NULL; + b->last_bus = NULL; + b->br_dev = NULL; + b->chain = NULL; + pacc->debug("Tree: domain %04x\n", b->domain); + } + /* Build list of bridges */ - last_br = &host_bridge.chain; for (d=first_dev; d; d=d->next) { struct pci_dev *dd = d->dev; @@ -166,7 +200,7 @@ grow_tree(void) /* Create a bridge tree */ - for (b=&host_bridge; b; b=b->chain) + for (b=host_bridge.chain; b; b=b->chain) { struct device *br_dev = b->br_dev; struct bridge *c, *best = NULL; @@ -180,7 +214,7 @@ grow_tree(void) for (c=&host_bridge; c; c=c->chain) if (c != b && (c == &host_bridge || b->domain == c->domain) && b->primary >= c->secondary && b->primary <= c->subordinate && - (!best || best->subordinate - best->primary > c->subordinate - c->primary)) + (!best || best == &host_bridge || best->subordinate - best->primary > c->subordinate - c->primary)) best = c; if (best) { @@ -191,8 +225,8 @@ grow_tree(void) /* Insert secondary bus for each bridge */ - for (b=&host_bridge; b; b=b->chain) - if (!find_bus(b, b->domain, b->secondary)) + for (b=host_bridge.chain; b; b=b->chain) + if (b->br_dev && !find_bus(b, b->domain, b->secondary)) new_bus(b, b->domain, b->secondary); /* Create bus structs and link devices */ @@ -258,7 +292,7 @@ show_tree_dev(struct pci_filter *filter, struct device *d, char *line, char *p) char namebuf[256]; p = tree_printf(line, p, "%02x.%x", q->dev, q->func); - for (b=&host_bridge; b; b=b->chain) + for (b=host_bridge.chain; b; b=b->chain) if (b->br_dev == d) { if (b->secondary == 0) @@ -305,7 +339,7 @@ check_dev_filter(struct pci_filter *filter, struct device *d) if (pci_filter_match(filter, d->dev)) return 1; - for (br = &host_bridge; br; br = br->chain) + for (br = host_bridge.chain; br; br = br->chain) if (br->br_dev == d) { for (b = br->first_bus; b; b = b->sibling) @@ -382,8 +416,8 @@ show_tree_bridge(struct pci_filter *filter, struct bridge *b, char *line, char * { if (check_bus_filter(filter, b->first_bus)) { - if (b == &host_bridge) - p = tree_printf(line, p, "[%04x:%02x]-", b->domain, b->first_bus->number); + if (!b->br_dev) + p = tree_printf(line, p, "[%04x:%02x]-", b->first_bus->domain, b->first_bus->number); show_tree_bus(filter, b->first_bus, line, p); } else @@ -421,5 +455,10 @@ void show_forest(struct pci_filter *filter) { char line[LINE_BUF_SIZE]; - show_tree_bridge(filter, &host_bridge, line, line); + struct bridge *b; + if (host_bridge.child) + { + for (b=host_bridge.child; b->prev; b=b->prev) + show_tree_bridge(filter, b, line, line); + } } -- cgit 1.2.3-korg