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
This commit is contained in:
parent
ec603c7297
commit
87dd2f95d2
@ -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 \
|
||||
|
@ -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 device is not a HyperTransport device,
|
||||
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
|
||||
|
@ -5431,3 +5431,44 @@ pci_get_rid_method(device_t dev, device_t child)
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -547,6 +547,7 @@ int pci_msix_device_blacklisted(device_t dev);
|
||||
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user