git: 7e7a1b61531a - main - pci: Export bus numbers for bridge devices in struct pci_conf
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 10 Mar 2026 16:53:56 UTC
The branch main has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=7e7a1b61531a29b4a0a5cdac66b96f420e6c66e4
commit 7e7a1b61531a29b4a0a5cdac66b96f420e6c66e4
Author: John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2026-03-10 16:49:21 +0000
Commit: John Baldwin <jhb@FreeBSD.org>
CommitDate: 2026-03-10 16:49:21 +0000
pci: Export bus numbers for bridge devices in struct pci_conf
This exports bus information about bridges to userspace via the
less-privileged PCIOCGETCONF ioctl. Previously if userspace wished to
query this information, it had to use direct PCI config register
access which requires higher privilege.
Reviewed by: imp
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D55771
---
share/man/man4/pci.4 | 6 ++++++
sys/dev/pci/pci.c | 3 +++
sys/dev/pci/pci_user.c | 32 +++++++++++++++++++++++++++++++-
sys/sys/pciio.h | 4 +++-
4 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/share/man/man4/pci.4 b/share/man/man4/pci.4
index f5d42efb4f37..38a427e64f4f 100644
--- a/share/man/man4/pci.4
+++ b/share/man/man4/pci.4
@@ -244,6 +244,12 @@ structure.
This should always be equivalent to the offset of the
.Va pc_spare
member.
+.It pc_secbus
+Secondary PCI bus number.
+.Pq Only valid for bridge devices
+.It pc_subbus
+Subordinate PCI bus number.
+.Pq Only valid for bridge devices
.It pc_spare
Reserved for future use.
.El
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index a46813cc155a..0dddd2dd263f 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -798,6 +798,9 @@ pci_fill_devinfo(device_t pcib, device_t bus, int d, int b, int s, int f,
devlist_entry->conf.pc_progif = cfg->progif;
devlist_entry->conf.pc_revid = cfg->revid;
+ devlist_entry->conf.pc_secbus = cfg->bridge.br_secbus;
+ devlist_entry->conf.pc_subbus = cfg->bridge.br_subbus;
+
pci_numdevs++;
pci_generation++;
diff --git a/sys/dev/pci/pci_user.c b/sys/dev/pci/pci_user.c
index 9768030995e7..0e23363fba73 100644
--- a/sys/dev/pci/pci_user.c
+++ b/sys/dev/pci/pci_user.c
@@ -81,7 +81,9 @@ struct pci_conf32 {
u_int32_t pd_unit; /* device unit number */
int pd_numa_domain; /* device NUMA domain */
u_int32_t pc_reported_len;/* length of PCI data reported */
- char pc_spare[64]; /* space for future fields */
+ uint8_t pc_secbus; /* secondary bus number */
+ uint8_t pc_subbus; /* subordinate bus number */
+ char pc_spare[62]; /* space for future fields */
};
struct pci_match_conf32 {
@@ -889,6 +891,8 @@ pci_conf_for_copyout(const struct pci_conf *pcp, union pci_conf_union *pcup,
pcup->pc32.pd_unit = (uint32_t)pcp->pd_unit;
if (cmd == PCIOCGETCONF32) {
pcup->pc32.pd_numa_domain = pcp->pd_numa_domain;
+ pcup->pc32.pc_secbus = pcp->pc_secbus;
+ pcup->pc32.pc_subbus = pcp->pc_subbus;
pcup->pc32.pc_reported_len =
(uint32_t)offsetof(struct pci_conf32, pc_spare);
}
@@ -1315,6 +1319,32 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t
else
dinfo->conf.pd_numa_domain = 0;
+ if (dinfo->cfg.dev != NULL) {
+ /*
+ * Re-read the values in case a driver
+ * changed them after the device was
+ * initially scanned.
+ */
+ switch (dinfo->conf.pc_hdr) {
+ case PCIM_HDRTYPE_BRIDGE:
+ dinfo->conf.pc_secbus =
+ pci_read_config(dinfo->cfg.dev,
+ PCIR_SECBUS_1, 1);
+ dinfo->conf.pc_subbus =
+ pci_read_config(dinfo->cfg.dev,
+ PCIR_SUBBUS_1, 1);
+ break;
+ case PCIM_HDRTYPE_CARDBUS:
+ dinfo->conf.pc_secbus =
+ pci_read_config(dinfo->cfg.dev,
+ PCIR_SECBUS_2, 1);
+ dinfo->conf.pc_subbus =
+ pci_read_config(dinfo->cfg.dev,
+ PCIR_SUBBUS_2, 1);
+ break;
+ }
+ }
+
if (pattern_buf == NULL ||
pci_conf_match(cmd, pattern_buf, num_patterns,
&dinfo->conf) == 0) {
diff --git a/sys/sys/pciio.h b/sys/sys/pciio.h
index 64c0b32cb8e2..58928544f171 100644
--- a/sys/sys/pciio.h
+++ b/sys/sys/pciio.h
@@ -79,7 +79,9 @@ struct pci_conf {
u_long pd_unit; /* device unit number */
int pd_numa_domain; /* device NUMA domain */
size_t pc_reported_len;/* length of PCI data reported */
- char pc_spare[64]; /* space for future fields */
+ uint8_t pc_secbus; /* secondary bus number */
+ uint8_t pc_subbus; /* subordinate bus number */
+ char pc_spare[62]; /* space for future fields */
};
struct pci_match_conf {