svn commit: r323327 - head/sys/x86/pci

Konstantin Belousov kib at FreeBSD.org
Fri Sep 8 19:51:04 UTC 2017


Author: kib
Date: Fri Sep  8 19:51:03 2017
New Revision: 323327
URL: https://svnweb.freebsd.org/changeset/base/323327

Log:
  Enhance qpi.c to make it usable on all Core-microarchitecture Xeons.
  
  Scan all buses for CSR bus, not stopping on the first failed
  match. Scan all slots for function 0 on the found bus, for instance on
  IvyBridge the slot 0 is not decoded at all. Since the scan is quite
  unsafe, and access to the buses is mostly useful for developers,
  enable the csr buses scan with the tunable.
  
  Current qpi.c makes too many assumptions about the uncore
  configuration buses location and about slots occupied.  Also it
  restricts itself only to Nehalem CPUs.  It is needed on all Core-based
  Xeons.  On the 2600 v2 (IvyBridge) machine I have access to, the CSR
  buses have numbers 31 (BSP socket) and 63 (second socket), and there
  is no functions pci0.31.0.0 or pci0.63.0.0.  According to the CPU
  datasheet, all devices on the uncore bus occupy slots >= 8.
  
  Practically, the attach to config buses is required for the intel-pcm
  pcm-memory.x tool to work, for instance.
  
  Reviewed by:	jhb (previous version)
  Sponsored by:	Mellanox Technologies
  MFC after:	1 week
  Differential revision:	https://reviews.freebsd.org/D12268

Modified:
  head/sys/x86/pci/qpi.c

Modified: head/sys/x86/pci/qpi.c
==============================================================================
--- head/sys/x86/pci/qpi.c	Fri Sep  8 19:45:37 2017	(r323326)
+++ head/sys/x86/pci/qpi.c	Fri Sep  8 19:51:03 2017	(r323327)
@@ -63,13 +63,19 @@ static MALLOC_DEFINE(M_QPI, "qpidrv", "qpi system devi
 static void
 qpi_identify(driver_t *driver, device_t parent)
 {
+	int do_qpi;
 
 	/* Check CPUID to ensure this is an i7 CPU of some sort. */
-	if (!(cpu_vendor_id == CPU_VENDOR_INTEL &&
-	    CPUID_TO_FAMILY(cpu_id) == 0x6 &&
-	    (CPUID_TO_MODEL(cpu_id) == 0x1a || CPUID_TO_MODEL(cpu_id) == 0x2c)))
+	if (cpu_vendor_id != CPU_VENDOR_INTEL ||
+	    CPUID_TO_FAMILY(cpu_id) != 0x6)
 		return;
 
+	/* Only discover buses with configuration devices if allowed by user */
+	do_qpi = 0;
+	TUNABLE_INT_FETCH("hw.attach_intel_csr_pci", &do_qpi);
+	if (!do_qpi)
+		return;
+
 	/* PCI config register access is required. */
 	if (pci_cfgregopen() == 0)
 		return;
@@ -97,6 +103,7 @@ qpi_probe_pcib(device_t dev, int bus)
 	struct qpi_device *qdev;
 	device_t child;
 	uint32_t devid;
+	int s;
 
 	/*
 	 * If a PCI bus already exists for this bus number, then
@@ -106,18 +113,23 @@ qpi_probe_pcib(device_t dev, int bus)
 		return (EEXIST);
 
 	/*
-	 * Attempt to read the device id for device 0, function 0 on
-	 * the bus.  A value of 0xffffffff means that the bus is not
-	 * present.
+	 * Attempt to read the device id for every slot, function 0 on
+	 * the bus.  If all read values are 0xffffffff this means that
+	 * the bus is not present.
 	 */
-	devid = pci_cfgregread(bus, 0, 0, PCIR_DEVVENDOR, 4);
+	for (s = 0; s <= PCI_SLOTMAX; s++) {
+		devid = pci_cfgregread(bus, s, 0, PCIR_DEVVENDOR, 4);
+		if (devid != 0xffffffff)
+			break;
+	}
 	if (devid == 0xffffffff)
 		return (ENOENT);
 
 	if ((devid & 0xffff) != 0x8086) {
-		device_printf(dev,
-		    "Device at pci%d.0.0 has non-Intel vendor 0x%x\n", bus,
-		    devid & 0xffff);
+		if (bootverbose)
+			device_printf(dev,
+			    "Device at pci%d.%d.0 has non-Intel vendor 0x%x\n",
+			    bus, s, devid & 0xffff);
 		return (ENXIO);
 	}
 
@@ -137,12 +149,12 @@ qpi_attach(device_t dev)
 	int bus;
 
 	/*
-	 * Each processor socket has a dedicated PCI bus counting down from
-	 * 255.  We keep probing buses until one fails.
+	 * Each processor socket has a dedicated PCI bus, sometimes
+	 * not enumerated by ACPI.  Probe all unattached buses from 0
+	 * to 255.
 	 */
-	for (bus = 255;; bus--)
-		if (qpi_probe_pcib(dev, bus) != 0)
-			break;
+	for (bus = PCI_BUSMAX; bus >= 0; bus--)
+		qpi_probe_pcib(dev, bus);
 
 	return (bus_generic_attach(dev));
 }


More information about the svn-src-all mailing list