Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Mar 2012 18:08:57 +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: r232472 - in head/sys/dev: pci siba
Message-ID:  <201203031808.q23I8vPV093886@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Sat Mar  3 18:08:57 2012
New Revision: 232472
URL: http://svn.freebsd.org/changeset/base/232472

Log:
  Expand the set of APIs available for locating PCI capabilities:
  - pci_find_extcap() is repurposed to be used for fetching PCI-express
    extended capabilities (PCIZ_* constants in <dev/pci/pcireg.h>).
  - pci_find_htcap() can be used to locate a specific HyperTransport
    capability (PCIM_HTCAP_* constants in <dev/pci/pcireg.h>).
  - Cache the starting location of the PCI-express capability for PCI-express
    devices in PCI device ivars.

Modified:
  head/sys/dev/pci/hostb_pci.c
  head/sys/dev/pci/pci.c
  head/sys/dev/pci/pci_if.m
  head/sys/dev/pci/pci_private.h
  head/sys/dev/pci/pcivar.h
  head/sys/dev/pci/vga_pci.c
  head/sys/dev/siba/siba_bwn.c

Modified: head/sys/dev/pci/hostb_pci.c
==============================================================================
--- head/sys/dev/pci/hostb_pci.c	Sat Mar  3 18:07:53 2012	(r232471)
+++ head/sys/dev/pci/hostb_pci.c	Sat Mar  3 18:08:57 2012	(r232472)
@@ -197,6 +197,14 @@ pci_hostb_assign_interrupt(device_t dev,
 }
 
 static int
+pci_hostb_find_cap(device_t dev, device_t child, int capability,
+    int *capreg)
+{
+
+	return (pci_find_cap(dev, capability, capreg));
+}
+
+static int
 pci_hostb_find_extcap(device_t dev, device_t child, int capability,
     int *capreg)
 {
@@ -204,6 +212,14 @@ pci_hostb_find_extcap(device_t dev, devi
 	return (pci_find_extcap(dev, capability, capreg));
 }
 
+static int
+pci_hostb_find_htcap(device_t dev, device_t child, int capability,
+    int *capreg)
+{
+
+	return (pci_find_htcap(dev, capability, capreg));
+}
+
 static device_method_t pci_hostb_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		pci_hostb_probe),
@@ -233,7 +249,9 @@ static device_method_t pci_hostb_methods
 	DEVMETHOD(pci_get_powerstate,	pci_hostb_get_powerstate),
 	DEVMETHOD(pci_set_powerstate,	pci_hostb_set_powerstate),
 	DEVMETHOD(pci_assign_interrupt,	pci_hostb_assign_interrupt),
+	DEVMETHOD(pci_find_cap,		pci_hostb_find_cap),
 	DEVMETHOD(pci_find_extcap,	pci_hostb_find_extcap),
+	DEVMETHOD(pci_find_htcap,	pci_hostb_find_htcap),
 
 	{ 0, 0 }
 };

Modified: head/sys/dev/pci/pci.c
==============================================================================
--- head/sys/dev/pci/pci.c	Sat Mar  3 18:07:53 2012	(r232471)
+++ head/sys/dev/pci/pci.c	Sat Mar  3 18:08:57 2012	(r232472)
@@ -177,7 +177,9 @@ static device_method_t pci_methods[] = {
 	DEVMETHOD(pci_get_powerstate,	pci_get_powerstate_method),
 	DEVMETHOD(pci_set_powerstate,	pci_set_powerstate_method),
 	DEVMETHOD(pci_assign_interrupt,	pci_assign_interrupt_method),
+	DEVMETHOD(pci_find_cap,		pci_find_cap_method),
 	DEVMETHOD(pci_find_extcap,	pci_find_extcap_method),
+	DEVMETHOD(pci_find_htcap,	pci_find_htcap_method),
 	DEVMETHOD(pci_alloc_msi,	pci_alloc_msi_method),
 	DEVMETHOD(pci_alloc_msix,	pci_alloc_msix_method),
 	DEVMETHOD(pci_remap_msix,	pci_remap_msix_method),
@@ -737,6 +739,9 @@ pci_read_cap(device_t pcib, pcicfgregs *
 			 * at least one PCI-express device.
 			 */
 			pcie_chipset = 1;
+			cfg->pcie.pcie_location = ptr;
+			val = REG(ptr + PCIR_EXPRESS_FLAGS, 2);
+			cfg->pcie.pcie_type = val & PCIM_EXP_FLAGS_TYPE;
 			break;
 		default:
 			break;
@@ -1154,12 +1159,55 @@ pci_get_vpd_readonly_method(device_t dev
 }
 
 /*
- * Find the requested extended capability and return the offset in
- * configuration space via the pointer provided. The function returns
- * 0 on success and error code otherwise.
+ * Find the requested HyperTransport capability and return the offset
+ * in configuration space via the pointer provided.  The function
+ * returns 0 on success and an error code otherwise.
  */
 int
-pci_find_extcap_method(device_t dev, device_t child, int capability,
+pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg)
+{
+	int ptr, error;
+	uint16_t val;
+
+	error = pci_find_cap(child, PCIY_HT, &ptr);
+	if (error)
+		return (error);
+
+	/*
+	 * Traverse the capabilities list checking each HT capability
+	 * to see if it matches the requested HT capability.
+	 */
+	while (ptr != 0) {
+		val = pci_read_config(child, ptr + PCIR_HT_COMMAND, 2);
+		if (capability == PCIM_HTCAP_SLAVE ||
+		    capability == PCIM_HTCAP_HOST)
+			val &= 0xe000;
+		else
+			val &= PCIM_HTCMD_CAP_MASK;
+		if (val == capability) {
+			if (capreg != NULL)
+				*capreg = ptr;
+			return (0);
+		}
+
+		/* Skip to the next HT capability. */
+		while (ptr != 0) {
+			ptr = pci_read_config(child, ptr + PCICAP_NEXTPTR, 1);
+			if (pci_read_config(child, ptr + PCICAP_ID, 1) ==
+			    PCIY_HT)
+				break;
+		}
+	}
+	return (ENOENT);
+}
+
+/*
+ * Find the requested capability and return the offset in
+ * configuration space via the pointer provided.  The function returns
+ * 0 on success and an error code otherwise.
+ */
+int
+pci_find_cap_method(device_t dev, device_t child, int capability,
     int *capreg)
 {
 	struct pci_devinfo *dinfo = device_get_ivars(child);
@@ -1207,6 +1255,43 @@ pci_find_extcap_method(device_t dev, dev
 }
 
 /*
+ * Find the requested extended capability and return the offset in
+ * configuration space via the pointer provided.  The function returns
+ * 0 on success and an error code otherwise.
+ */
+int
+pci_find_extcap_method(device_t dev, device_t child, int capability,
+    int *capreg)
+{
+	struct pci_devinfo *dinfo = device_get_ivars(child);
+	pcicfgregs *cfg = &dinfo->cfg;
+	uint32_t ecap;
+	uint16_t ptr;
+
+	/* Only supported for PCI-express devices. */
+	if (cfg->pcie.pcie_location == 0)
+		return (ENXIO);
+
+	ptr = PCIR_EXTCAP;
+	ecap = pci_read_config(child, ptr, 4);
+	if (ecap == 0xffffffff || ecap == 0)
+		return (ENOENT);
+	for (;;) {
+		if (PCI_EXTCAP_ID(ecap) == capability) {
+			if (capreg != NULL)
+				*capreg = ptr;
+			return (0);
+		}
+		ptr = PCI_EXTCAP_NEXTPTR(ecap);
+		if (ptr == 0)
+			break;
+		ecap = pci_read_config(child, ptr, 4);
+	}
+
+	return (ENOENT);
+}
+
+/*
  * Support for MSI-X message interrupts.
  */
 void
@@ -1696,10 +1781,12 @@ pci_ht_map_msi(device_t dev, uint64_t ad
 int
 pci_get_max_read_req(device_t dev)
 {
+	struct pci_devinfo *dinfo = device_get_ivars(dev);
 	int cap;
 	uint16_t val;
 
-	if (pci_find_cap(dev, PCIY_EXPRESS, &cap) != 0)
+	cap = dinfo->cfg.pcie.pcie_location;
+	if (cap == 0)
 		return (0);
 	val = pci_read_config(dev, cap + PCIR_EXPRESS_DEVICE_CTL, 2);
 	val &= PCIM_EXP_CTL_MAX_READ_REQUEST;
@@ -1710,10 +1797,12 @@ pci_get_max_read_req(device_t dev)
 int
 pci_set_max_read_req(device_t dev, int size)
 {
+	struct pci_devinfo *dinfo = device_get_ivars(dev);
 	int cap;
 	uint16_t val;
 
-	if (pci_find_cap(dev, PCIY_EXPRESS, &cap) != 0)
+	cap = dinfo->cfg.pcie.pcie_location;
+	if (cap == 0)
 		return (0);
 	if (size < 128)
 		size = 128;

Modified: head/sys/dev/pci/pci_if.m
==============================================================================
--- head/sys/dev/pci/pci_if.m	Sat Mar  3 18:07:53 2012	(r232471)
+++ head/sys/dev/pci/pci_if.m	Sat Mar  3 18:08:57 2012	(r232472)
@@ -105,6 +105,13 @@ METHOD int assign_interrupt {
 	device_t	child;
 };
 
+METHOD int find_cap {
+	device_t	dev;
+	device_t	child;
+	int		capability;
+	int		*capreg;
+};
+
 METHOD int find_extcap {
 	device_t	dev;
 	device_t	child;
@@ -112,6 +119,13 @@ METHOD int find_extcap {
 	int		*capreg;
 };
 
+METHOD int find_htcap {
+	device_t	dev;
+	device_t	child;
+	int		capability;
+	int		*capreg;
+};
+
 METHOD int alloc_msi {
 	device_t	dev;
 	device_t	child;

Modified: head/sys/dev/pci/pci_private.h
==============================================================================
--- head/sys/dev/pci/pci_private.h	Sat Mar  3 18:07:53 2012	(r232471)
+++ head/sys/dev/pci/pci_private.h	Sat Mar  3 18:08:57 2012	(r232472)
@@ -80,8 +80,12 @@ int		pci_enable_busmaster_method(device_
 int		pci_disable_busmaster_method(device_t dev, device_t child);
 int		pci_enable_io_method(device_t dev, device_t child, int space);
 int		pci_disable_io_method(device_t dev, device_t child, int space);
+int		pci_find_cap_method(device_t dev, device_t child,
+		    int capability, int *capreg);
 int		pci_find_extcap_method(device_t dev, device_t child,
 		    int capability, int *capreg);
+int		pci_find_htcap_method(device_t dev, device_t child,
+		    int capability, int *capreg);
 int		pci_alloc_msi_method(device_t dev, device_t child, int *count);
 int		pci_alloc_msix_method(device_t dev, device_t child, int *count);
 int		pci_remap_msix_method(device_t dev, device_t child,

Modified: head/sys/dev/pci/pcivar.h
==============================================================================
--- head/sys/dev/pci/pcivar.h	Sat Mar  3 18:07:53 2012	(r232471)
+++ head/sys/dev/pci/pcivar.h	Sat Mar  3 18:08:57 2012	(r232472)
@@ -123,6 +123,12 @@ struct pcicfg_ht {
     uint64_t	ht_msiaddr;	/* MSI mapping base address */
 };
 
+/* Interesting values for PCI-express */
+struct pcicfg_pcie {
+    uint8_t	pcie_location;	/* Offset of PCI-e capability registers. */
+    uint8_t	pcie_type;	/* Device type. */
+};
+
 /* config header information common to all header types */
 typedef struct pcicfg {
     struct device *dev;		/* device which owns this */
@@ -164,6 +170,7 @@ typedef struct pcicfg {
     struct pcicfg_msi msi;	/* PCI MSI */
     struct pcicfg_msix msix;	/* PCI MSI-X */
     struct pcicfg_ht ht;	/* HyperTransport */
+    struct pcicfg_pcie pcie;	/* PCI Express */
 } pcicfgregs;
 
 /* additional type 1 device config header information (PCI to PCI bridge) */
@@ -409,7 +416,7 @@ pci_get_powerstate(device_t dev)
 static __inline int
 pci_find_cap(device_t dev, int capability, int *capreg)
 {
-    return (PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg));
+    return (PCI_FIND_CAP(device_get_parent(dev), dev, capability, capreg));
 }
 
 static __inline int
@@ -419,6 +426,12 @@ pci_find_extcap(device_t dev, int capabi
 }
 
 static __inline int
+pci_find_htcap(device_t dev, int capability, int *capreg)
+{
+    return (PCI_FIND_HTCAP(device_get_parent(dev), dev, capability, capreg));
+}
+
+static __inline int
 pci_alloc_msi(device_t dev, int *count)
 {
     return (PCI_ALLOC_MSI(device_get_parent(dev), dev, count));

Modified: head/sys/dev/pci/vga_pci.c
==============================================================================
--- head/sys/dev/pci/vga_pci.c	Sat Mar  3 18:07:53 2012	(r232471)
+++ head/sys/dev/pci/vga_pci.c	Sat Mar  3 18:08:57 2012	(r232472)
@@ -314,6 +314,14 @@ vga_pci_assign_interrupt(device_t dev, d
 }
 
 static int
+vga_pci_find_cap(device_t dev, device_t child, int capability,
+    int *capreg)
+{
+
+	return (pci_find_cap(dev, capability, capreg));
+}
+
+static int
 vga_pci_find_extcap(device_t dev, device_t child, int capability,
     int *capreg)
 {
@@ -322,6 +330,14 @@ vga_pci_find_extcap(device_t dev, device
 }
 
 static int
+vga_pci_find_htcap(device_t dev, device_t child, int capability,
+    int *capreg)
+{
+
+	return (pci_find_htcap(dev, capability, capreg));
+}
+
+static int
 vga_pci_alloc_msi(device_t dev, device_t child, int *count)
 {
 	struct vga_pci_softc *sc;
@@ -422,7 +438,9 @@ static device_method_t vga_pci_methods[]
 	DEVMETHOD(pci_get_powerstate,	vga_pci_get_powerstate),
 	DEVMETHOD(pci_set_powerstate,	vga_pci_set_powerstate),
 	DEVMETHOD(pci_assign_interrupt,	vga_pci_assign_interrupt),
+	DEVMETHOD(pci_find_cap,		vga_pci_find_cap),
 	DEVMETHOD(pci_find_extcap,	vga_pci_find_extcap),
+	DEVMETHOD(pci_find_htcap,	vga_pci_find_htcap),
 	DEVMETHOD(pci_alloc_msi,	vga_pci_alloc_msi),
 	DEVMETHOD(pci_alloc_msix,	vga_pci_alloc_msix),
 	DEVMETHOD(pci_remap_msix,	vga_pci_remap_msix),

Modified: head/sys/dev/siba/siba_bwn.c
==============================================================================
--- head/sys/dev/siba/siba_bwn.c	Sat Mar  3 18:07:53 2012	(r232471)
+++ head/sys/dev/siba/siba_bwn.c	Sat Mar  3 18:08:57 2012	(r232472)
@@ -279,6 +279,14 @@ siba_bwn_teardown_intr(device_t dev, dev
 }
 
 static int
+siba_bwn_find_cap(device_t dev, device_t child, int capability,
+    int *capreg)
+{
+
+	return (pci_find_cap(dev, capability, capreg));
+}
+
+static int
 siba_bwn_find_extcap(device_t dev, device_t child, int capability,
     int *capreg)
 {
@@ -287,6 +295,14 @@ siba_bwn_find_extcap(device_t dev, devic
 }
 
 static int
+siba_bwn_find_htcap(device_t dev, device_t child, int capability,
+    int *capreg)
+{
+
+	return (pci_find_htcap(dev, capability, capreg));
+}
+
+static int
 siba_bwn_alloc_msi(device_t dev, device_t child, int *count)
 {
 	struct siba_bwn_softc *ssc;
@@ -405,7 +421,9 @@ static device_method_t siba_bwn_methods[
 	DEVMETHOD(bus_teardown_intr,    siba_bwn_teardown_intr),
 
 	/* PCI interface */
+	DEVMETHOD(pci_find_cap,		siba_bwn_find_cap),
 	DEVMETHOD(pci_find_extcap,	siba_bwn_find_extcap),
+	DEVMETHOD(pci_find_htcap,	siba_bwn_find_htcap),
 	DEVMETHOD(pci_alloc_msi,	siba_bwn_alloc_msi),
 	DEVMETHOD(pci_release_msi,	siba_bwn_release_msi),
 	DEVMETHOD(pci_msi_count,	siba_bwn_msi_count),



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