Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Nov 2015 21:27:25 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r290415 - in head: share/man/man9 sys/dev/pci
Message-ID:  <201511052127.tA5LRPV8036332@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201511052127.tA5LRPV8036332>