summaryrefslogtreecommitdiff
path: root/usr/src/cmd/pcieadm/pcieadm.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/pcieadm/pcieadm.c')
-rw-r--r--usr/src/cmd/pcieadm/pcieadm.c51
1 files changed, 39 insertions, 12 deletions
diff --git a/usr/src/cmd/pcieadm/pcieadm.c b/usr/src/cmd/pcieadm/pcieadm.c
index edcad6e4d8..f1af0da485 100644
--- a/usr/src/cmd/pcieadm/pcieadm.c
+++ b/usr/src/cmd/pcieadm/pcieadm.c
@@ -129,13 +129,49 @@ pcieadm_ofmt_errx(const char *fmt, ...)
verrx(EXIT_FAILURE, fmt, ap);
}
-boolean_t
+/*
+ * We determine if a node is PCI in a two step process. The first is to see if
+ * the node's name starts with pci, and has an additional character that
+ * indicates it's not the synthetic root of the tree. However, the node name
+ * changes for some classes of devices such as GPUs. As such, for those we try
+ * to look at the compatible property and see if we have a pciexclass or
+ * pciclass entry. We look specifically for the class to make sure that we don't
+ * fall for the synthetic nodes that have a compatible property of
+ * 'pciex_root_complex'.
+ *
+ * The compatible property is a single string that is actually a compressed
+ * string. That is, there are multiple strings concatenated together in a single
+ * pointer.
+ */
+static boolean_t
pcieadm_di_node_is_pci(di_node_t node)
{
const char *name;
+ char *compat;
+ int nents;
name = di_node_name(node);
- return (strncmp("pci", name, 3) == 0);
+ if (strncmp("pci", name, 3) == 0) {
+ return (name[3] != '\0');
+ }
+
+ nents = di_prop_lookup_strings(DDI_DEV_T_ANY, node, "compatible",
+ &compat);
+ if (nents <= 0) {
+ return (B_FALSE);
+ }
+
+ for (int i = 0; i < nents; i++) {
+ if (strncmp("pciclass,", compat, strlen("pciclass,")) == 0 ||
+ strncmp("pciexclass,", compat, strlen("pciexclass,")) ==
+ 0) {
+ return (B_TRUE);
+ }
+
+ compat += strlen(compat) + 1;
+ }
+
+ return (B_FALSE);
}
static int
@@ -147,15 +183,6 @@ pcieadm_di_walk_cb(di_node_t node, void *arg)
return (DI_WALK_CONTINUE);
}
- /*
- * We create synthetic nodes for the root of PCIe tree basically
- * functions as all the resources available for one or more bridges.
- * When we encounter that top-level node skip it.
- */
- if (strcmp("pci", di_node_name(node)) == 0) {
- return (DI_WALK_CONTINUE);
- }
-
return (walk->pdw_func(node, walk->pdw_arg));
}
@@ -216,7 +243,7 @@ pcieadm_find_dip_cb(di_node_t node, void *arg)
}
(void) snprintf(bdf, sizeof (bdf), "%x/%x/%x", PCI_REG_BUS_G(regs[0]),
PCI_REG_DEV_G(regs[0]), PCI_REG_FUNC_G(regs[0]));
- (void) snprintf(bdf, sizeof (bdf), "%02x/%02x/%02x",
+ (void) snprintf(altbdf, sizeof (altbdf), "%02x/%02x/%02x",
PCI_REG_BUS_G(regs[0]), PCI_REG_DEV_G(regs[0]),
PCI_REG_FUNC_G(regs[0]));