summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci/pci.c
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2011-05-30 19:09:46 +0000
committerkettenis <kettenis@openbsd.org>2011-05-30 19:09:46 +0000
commit653b3980470e04e34c4d530e8ac8b064f85a15a2 (patch)
treecf41a00f3e2997aea26b96930696c7b7d4834a80 /sys/dev/pci/pci.c
parentKthread_create is a kernel function so use kprintf format attribute instead. (diff)
downloadwireguard-openbsd-653b3980470e04e34c4d530e8ac8b064f85a15a2.tar.xz
wireguard-openbsd-653b3980470e04e34c4d530e8ac8b064f85a15a2.zip
Enable MSI for HyperTransport devices that have MSI remapping enabled.
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r--sys/dev/pci/pci.c60
1 files changed, 57 insertions, 3 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 79a85a1d92c..3cb6423ce3d 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci.c,v 1.91 2011/05/19 20:14:55 kettenis Exp $ */
+/* $OpenBSD: pci.c,v 1.92 2011/05/30 19:09:46 kettenis Exp $ */
/* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */
/*
@@ -370,8 +370,10 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
struct pci_attach_args pa;
struct pci_dev *pd;
struct device *dev;
- pcireg_t id, class, intr, bhlcr;
- int ret = 0, pin, bus, device, function;
+ pcireg_t id, class, intr, bhlcr, cap;
+ int pin, bus, device, function;
+ int off, ret = 0;
+ uint64_t addr;
pci_decompose_tag(pc, tag, &bus, &device, &function);
@@ -437,6 +439,29 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
}
pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
+ if (pci_get_ht_capability(pc, tag, PCI_HT_CAP_MSI, &off, &cap)) {
+ /*
+ * XXX Should we enable MSI mapping ourselves on
+ * systems that have it disabled?
+ */
+ if (cap & PCI_HT_MSI_ENABLED) {
+ if ((cap & PCI_HT_MSI_FIXED) == 0) {
+ addr = pci_conf_read(pc, tag,
+ off + PCI_HT_MSI_ADDR);
+ addr |= (uint64_t)pci_conf_read(pc, tag,
+ off + PCI_HT_MSI_ADDR_HI32) << 32;
+ } else
+ addr = PCI_HT_MSI_FIXED_ADDR;
+
+ /*
+ * XXX This will fail to enable MSI on systems
+ * that don't use the canonical address.
+ */
+ if (addr == PCI_HT_MSI_FIXED_ADDR)
+ pa.pa_flags |= PCI_FLAGS_MSI_ENABLED;
+ }
+ }
+
if (match != NULL) {
ret = (*match)(&pa);
if (ret != 0 && pap != NULL)
@@ -558,6 +583,35 @@ pci_get_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid,
}
int
+pci_get_ht_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid,
+ int *offset, pcireg_t *value)
+{
+ pcireg_t reg;
+ unsigned int ofs;
+
+ if (pci_get_capability(pc, tag, PCI_CAP_HT, &ofs, NULL) == 0)
+ return (0);
+
+ while (ofs != 0) {
+#ifdef DIAGNOSTIC
+ if ((ofs & 3) || (ofs < 0x40))
+ panic("pci_get_ht_capability");
+#endif
+ reg = pci_conf_read(pc, tag, ofs);
+ if (PCI_HT_CAP(reg) == capid) {
+ if (offset)
+ *offset = ofs;
+ if (value)
+ *value = reg;
+ return (1);
+ }
+ ofs = PCI_CAPLIST_NEXT(reg);
+ }
+
+ return (0);
+}
+
+int
pci_find_device(struct pci_attach_args *pa,
int (*match)(struct pci_attach_args *))
{