svn commit: r219737 - head/sys/dev/pci

John Baldwin jhb at FreeBSD.org
Fri Mar 18 12:13:04 UTC 2011


Author: jhb
Date: Fri Mar 18 12:13:04 2011
New Revision: 219737
URL: http://svn.freebsd.org/changeset/base/219737

Log:
  Fix a few issues with HyperTransport devices and MSI interrupts:
  - Always enable the HyperTransport MSI mapping window for HyperTransport
    to PCI bridges (these show up as HyperTransport slave devices).
    The mapping windows in PCI-PCI bridges are enabled by existing code
    in the PCI-PCI bridge driver as MSI requests propagate up the device
    tree, but Host-PCI bridges don't really show up in that tree.
  - If the PCI device at domain 0 bus 0 slot 0 function 0 is not a
    HyperTransport device, then blacklist MSI on any other HT devices in
    the system.  Linux has a similar quirk.
  
  PR:		kern/155442
  Tested by:	Zack Dannar  zdannar of gmail
  MFC after:	1 week

Modified:
  head/sys/dev/pci/pci.c
  head/sys/dev/pci/pcivar.h

Modified: head/sys/dev/pci/pci.c
==============================================================================
--- head/sys/dev/pci/pci.c	Fri Mar 18 12:09:27 2011	(r219736)
+++ head/sys/dev/pci/pci.c	Fri Mar 18 12:13:04 2011	(r219737)
@@ -236,7 +236,7 @@ struct pci_quirk pci_quirks[] = {
 struct devlist pci_devq;
 uint32_t pci_generation;
 uint32_t pci_numdevs = 0;
-static int pcie_chipset, pcix_chipset;
+static int ht_chipset, pcie_chipset, pcix_chipset;
 
 /* sysctl vars */
 SYSCTL_NODE(_hw, OID_AUTO, pci, CTLFLAG_RD, 0, "PCI bus tuning parameters");
@@ -612,10 +612,24 @@ pci_read_extcap(device_t pcib, pcicfgreg
 					cfg->pp.pp_data = ptr + PCIR_POWER_DATA;
 			}
 			break;
-#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
 		case PCIY_HT:		/* HyperTransport */
 			/* Determine HT-specific capability type. */
 			val = REG(ptr + PCIR_HT_COMMAND, 2);
+
+			if ((val & 0xe000) == PCIM_HTCAP_SLAVE) {
+				cfg->ht.ht_slave = ptr;
+
+				/*
+				 * If device 0:0:0:0 is an HT slave,
+				 * then this is an HT chipset and MSI
+				 * should be enabled for HT devices.
+				 */
+				if (cfg->domain == 0 && cfg->bus == 0 &&
+				    cfg->slot == 0 && cfg->func == 0)
+					ht_chipset = 1;
+			}
+
+#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
 			switch (val & PCIM_HTCMD_CAP_MASK) {
 			case PCIM_HTCAP_MSI_MAPPING:
 				if (!(val & PCIM_HTCMD_MSI_FIXED)) {
@@ -627,7 +641,7 @@ pci_read_extcap(device_t pcib, pcicfgreg
 					    4);
 					if (addr != MSI_INTEL_ADDR_BASE)
 						device_printf(pcib,
-	    "HT Bridge at pci%d:%d:%d:%d has non-default MSI window 0x%llx\n",
+	    "HT device at pci%d:%d:%d:%d has non-default MSI window 0x%llx\n",
 						    cfg->domain, cfg->bus,
 						    cfg->slot, cfg->func,
 						    (long long)addr);
@@ -639,8 +653,8 @@ pci_read_extcap(device_t pcib, pcicfgreg
 				cfg->ht.ht_msiaddr = addr;
 				break;
 			}
-			break;
 #endif
+			break;
 		case PCIY_MSI:		/* PCI MSI */
 			cfg->msi.msi_location = ptr;
 			cfg->msi.msi_ctrl = REG(ptr + PCIR_MSI_CTRL, 2);
@@ -696,6 +710,24 @@ pci_read_extcap(device_t pcib, pcicfgreg
 			break;
 		}
 	}
+
+	
+#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
+	/*
+	 * Enable the MSI mapping window for all HyperTransport
+	 * slaves.  PCI-PCI bridges have their windows enabled via
+	 * PCIB_MAP_MSI().
+	 */
+	if (cfg->ht.ht_slave != 0 && cfg->ht.ht_msimap != 0 &&
+	    !(cfg->ht.ht_msictrl & PCIM_HTCMD_MSI_ENABLE)) {
+		device_printf(pcib,
+	    "Enabling MSI window for HyperTransport slave at pci%d:%d:%d:%d\n",
+		    cfg->domain, cfg->bus, cfg->slot, cfg->func);
+		 cfg->ht.ht_msictrl |= PCIM_HTCMD_MSI_ENABLE;
+		 WREG(cfg->ht.ht_msimap + PCIR_HT_COMMAND, cfg->ht.ht_msictrl,
+		     2);
+	}
+#endif
 /* REG and WREG use carry through to next functions */
 }
 
@@ -1837,6 +1869,13 @@ pci_msi_device_blacklisted(device_t dev)
 		    q->type == PCI_QUIRK_DISABLE_MSI)
 			return (1);
 	}
+
+	/*
+	 * Blacklist HyperTransport devices if the device at 0:0:0:0
+	 * is not a HyperTransport slave.
+	 */
+	if (!ht_chipset && pci_find_extcap(dev, PCIY_HT, NULL) == 0)
+		return (1);
 	return (0);
 }
 

Modified: head/sys/dev/pci/pcivar.h
==============================================================================
--- head/sys/dev/pci/pcivar.h	Fri Mar 18 12:09:27 2011	(r219736)
+++ head/sys/dev/pci/pcivar.h	Fri Mar 18 12:13:04 2011	(r219737)
@@ -110,6 +110,7 @@ struct pcicfg_msix {
 
 /* Interesting values for HyperTransport */
 struct pcicfg_ht {
+    uint8_t	ht_slave;	/* Non-zero if device is an HT slave. */
     uint8_t	ht_msimap;	/* Offset of MSI mapping cap registers. */
     uint16_t	ht_msictrl;	/* MSI mapping control */
     uint64_t	ht_msiaddr;	/* MSI mapping base address */


More information about the svn-src-head mailing list