From owner-svn-src-all@freebsd.org Thu Nov 5 21:27:27 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 23EDBA2791C; Thu, 5 Nov 2015 21:27:27 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 009A81143; Thu, 5 Nov 2015 21:27:26 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tA5LRQqP036337; Thu, 5 Nov 2015 21:27:26 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tA5LRPV8036332; Thu, 5 Nov 2015 21:27:25 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201511052127.tA5LRPV8036332@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Thu, 5 Nov 2015 21:27:25 +0000 (UTC) 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 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Nov 2015 21:27:27 -0000 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);