svn commit: r290415 - in head: share/man/man9 sys/dev/pci
John Baldwin
jhb at FreeBSD.org
Thu Nov 5 21:27:27 UTC 2015
Author: jhb
Date: Thu Nov 5 21:27:25 2015
New Revision: 290415
URL: https://svnweb.freebsd.org/changeset/base/290415
Log:
Add a new helper function for PCI devices to locate the upstream
PCI-express root port of a given PCI device.
Reviewed by: kib, imp
MFC after: 1 week
Sponsored by: Chelsio
Differential Revision: https://reviews.freebsd.org/D4089
Modified:
head/share/man/man9/Makefile
head/share/man/man9/pci.9
head/sys/dev/pci/pci.c
head/sys/dev/pci/pcivar.h
Modified: head/share/man/man9/Makefile
==============================================================================
--- head/share/man/man9/Makefile Thu Nov 5 21:26:06 2015 (r290414)
+++ head/share/man/man9/Makefile Thu Nov 5 21:27:25 2015 (r290415)
@@ -1274,6 +1274,7 @@ MLINKS+=pci.9 pci_alloc_msi.9 \
pci.9 pci_find_device.9 \
pci.9 pci_find_extcap.9 \
pci.9 pci_find_htcap.9 \
+ pci.9 pci_find_pcie_root_port.9 \
pci.9 pci_get_max_read_req.9 \
pci.9 pci_get_powerstate.9 \
pci.9 pci_get_vpd_ident.9 \
Modified: head/share/man/man9/pci.9
==============================================================================
--- head/share/man/man9/pci.9 Thu Nov 5 21:26:06 2015 (r290414)
+++ head/share/man/man9/pci.9 Thu Nov 5 21:27:25 2015 (r290415)
@@ -42,6 +42,7 @@
.Nm pci_find_device ,
.Nm pci_find_extcap ,
.Nm pci_find_htcap ,
+.Nm pci_find_pcie_root_port ,
.Nm pci_get_max_read_req ,
.Nm pci_get_powerstate ,
.Nm pci_get_vpd_ident ,
@@ -91,6 +92,8 @@
.Fn pci_find_extcap "device_t dev" "int capability" "int *capreg"
.Ft int
.Fn pci_find_htcap "device_t dev" "int capability" "int *capreg"
+.Ft device_t
+.Fn pci_find_pcie_root_port "device_t dev"
.Ft int
.Fn pci_get_max_read_req "device_t dev"
.Ft int
@@ -338,6 +341,16 @@ If the capability is not found or the de
returns an error.
.Pp
The
+.Fn pci_find_pcie_root_port
+function walks up the PCI device hierarchy to locate the PCI-express root
+port upstream of
+.Fa dev .
+If a root port is not found,
+.Fn pci_find_pcie_root_port
+returns
+.Dv NULL .
+.Pp
+The
.Fn pci_get_vpd_ident
function is used to fetch a device's Vital Product Data
.Pq VPD
Modified: head/sys/dev/pci/pci.c
==============================================================================
--- head/sys/dev/pci/pci.c Thu Nov 5 21:26:06 2015 (r290414)
+++ head/sys/dev/pci/pci.c Thu Nov 5 21:27:25 2015 (r290415)
@@ -5431,3 +5431,44 @@ pci_get_rid_method(device_t dev, device_
return (PCIB_GET_RID(device_get_parent(dev), child));
}
+
+/* Find the upstream port of a given PCI device in a root complex. */
+device_t
+pci_find_pcie_root_port(device_t dev)
+{
+ struct pci_devinfo *dinfo;
+ devclass_t pci_class;
+ device_t pcib, bus;
+
+ pci_class = devclass_find("pci");
+ KASSERT(device_get_devclass(device_get_parent(dev)) == pci_class,
+ ("%s: non-pci device %s", __func__, device_get_nameunit(dev)));
+
+ /*
+ * Walk the bridge hierarchy until we find a PCI-e root
+ * port or a non-PCI device.
+ */
+ for (;;) {
+ bus = device_get_parent(dev);
+ KASSERT(bus != NULL, ("%s: null parent of %s", __func__,
+ device_get_nameunit(dev)));
+
+ pcib = device_get_parent(bus);
+ KASSERT(pcib != NULL, ("%s: null bridge of %s", __func__,
+ device_get_nameunit(bus)));
+
+ /*
+ * pcib's parent must be a PCI bus for this to be a
+ * PCI-PCI bridge.
+ */
+ if (device_get_devclass(device_get_parent(pcib)) != pci_class)
+ return (NULL);
+
+ dinfo = device_get_ivars(pcib);
+ if (dinfo->cfg.pcie.pcie_location != 0 &&
+ dinfo->cfg.pcie.pcie_type == PCIEM_TYPE_ROOT_PORT)
+ return (pcib);
+
+ dev = pcib;
+ }
+}
Modified: head/sys/dev/pci/pcivar.h
==============================================================================
--- head/sys/dev/pci/pcivar.h Thu Nov 5 21:26:06 2015 (r290414)
+++ head/sys/dev/pci/pcivar.h Thu Nov 5 21:27:25 2015 (r290415)
@@ -547,6 +547,7 @@ int pci_msix_device_blacklisted(device_t
void pci_ht_map_msi(device_t dev, uint64_t addr);
+device_t pci_find_pcie_root_port(device_t dev);
int pci_get_max_read_req(device_t dev);
void pci_restore_state(device_t dev);
void pci_save_state(device_t dev);
More information about the svn-src-all
mailing list