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