summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2019-05-31 10:35:49 +0000
committerkettenis <kettenis@openbsd.org>2019-05-31 10:35:49 +0000
commite33d8a25524438b0dca5bd1d06e1737a57adbbe8 (patch)
treee52b3ad9715d97e50d750c2dad12fc3a8ed3b681 /sys/dev
parentExit the attribute loop early if there are no unknown attributes left (diff)
downloadwireguard-openbsd-e33d8a25524438b0dca5bd1d06e1737a57adbbe8.tar.xz
wireguard-openbsd-e33d8a25524438b0dca5bd1d06e1737a57adbbe8.zip
Add MSI-X support.
ok patrick@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdt/dwpcie.c68
1 files changed, 39 insertions, 29 deletions
diff --git a/sys/dev/fdt/dwpcie.c b/sys/dev/fdt/dwpcie.c
index cd4ed5c4714..9dae618c925 100644
--- a/sys/dev/fdt/dwpcie.c
+++ b/sys/dev/fdt/dwpcie.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dwpcie.c,v 1.12 2019/01/11 08:03:24 patrick Exp $ */
+/* $OpenBSD: dwpcie.c,v 1.13 2019/05/31 10:35:49 kettenis Exp $ */
/*
* Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
*
@@ -903,11 +903,15 @@ dwpcie_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
sc->sc_io_bus_addr, sc->sc_io_size);
}
+#define PCI_INTX 0
+#define PCI_MSI 1
+#define PCI_MSIX 2
+
struct dwpcie_intr_handle {
pci_chipset_tag_t ih_pc;
pcitag_t ih_tag;
int ih_intrpin;
- int ih_msi;
+ int ih_type;
};
int
@@ -926,7 +930,7 @@ dwpcie_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
ih->ih_pc = pa->pa_pc;
ih->ih_tag = pa->pa_intrtag;
ih->ih_intrpin = pa->pa_intrpin;
- ih->ih_msi = 0;
+ ih->ih_type = PCI_INTX;
*ihp = (pci_intr_handle_t)ih;
return 0;
@@ -946,8 +950,7 @@ dwpcie_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
ih = malloc(sizeof(struct dwpcie_intr_handle), M_DEVBUF, M_WAITOK);
ih->ih_pc = pa->pa_pc;
ih->ih_tag = pa->pa_tag;
- ih->ih_intrpin = pa->pa_intrpin;
- ih->ih_msi = 1;
+ ih->ih_type = PCI_MSI;
*ihp = (pci_intr_handle_t)ih;
return 0;
@@ -957,7 +960,26 @@ int
dwpcie_intr_map_msix(struct pci_attach_args *pa, int vec,
pci_intr_handle_t *ihp)
{
- return -1;
+ pci_chipset_tag_t pc = pa->pa_pc;
+ pcitag_t tag = pa->pa_tag;
+ struct dwpcie_intr_handle *ih;
+ pcireg_t reg;
+
+ if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 ||
+ pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, &reg) == 0)
+ return -1;
+
+ if (vec > PCI_MSIX_MC_TBLSZ(reg))
+ return -1;
+
+ ih = malloc(sizeof(struct dwpcie_intr_handle), M_DEVBUF, M_WAITOK);
+ ih->ih_pc = pa->pa_pc;
+ ih->ih_tag = pa->pa_tag;
+ ih->ih_intrpin = vec;
+ ih->ih_type = PCI_MSIX;
+ *ihp = (pci_intr_handle_t)ih;
+
+ return 0;
}
const char *
@@ -965,8 +987,12 @@ dwpcie_intr_string(void *v, pci_intr_handle_t ihp)
{
struct dwpcie_intr_handle *ih = (struct dwpcie_intr_handle *)ihp;
- if (ih->ih_msi)
+ switch (ih->ih_type) {
+ case PCI_MSI:
return "msi";
+ case PCI_MSIX:
+ return "msix";
+ }
return "intx";
}
@@ -979,10 +1005,8 @@ dwpcie_intr_establish(void *v, pci_intr_handle_t ihp, int level,
struct dwpcie_intr_handle *ih = (struct dwpcie_intr_handle *)ihp;
void *cookie;
- if (ih->ih_msi) {
+ if (ih->ih_type != PCI_INTX) {
uint64_t addr, data;
- pcireg_t reg;
- int off;
/* Assume hardware passes Requester ID as sideband data. */
data = pci_requester_id(ih->ih_pc, ih->ih_tag);
@@ -993,25 +1017,11 @@ dwpcie_intr_establish(void *v, pci_intr_handle_t ihp, int level,
/* TODO: translate address to the PCI device's view */
- if (pci_get_capability(ih->ih_pc, ih->ih_tag, PCI_CAP_MSI,
- &off, &reg) == 0)
- panic("%s: no msi capability", __func__);
-
- if (reg & PCI_MSI_MC_C64) {
- pci_conf_write(ih->ih_pc, ih->ih_tag,
- off + PCI_MSI_MA, addr);
- pci_conf_write(ih->ih_pc, ih->ih_tag,
- off + PCI_MSI_MAU32, addr >> 32);
- pci_conf_write(ih->ih_pc, ih->ih_tag,
- off + PCI_MSI_MD64, data);
- } else {
- pci_conf_write(ih->ih_pc, ih->ih_tag,
- off + PCI_MSI_MA, addr);
- pci_conf_write(ih->ih_pc, ih->ih_tag,
- off + PCI_MSI_MD32, data);
- }
- pci_conf_write(ih->ih_pc, ih->ih_tag,
- off, reg | PCI_MSI_MC_MSIE);
+ if (ih->ih_type == PCI_MSIX) {
+ pci_msix_enable(ih->ih_pc, ih->ih_tag,
+ &sc->sc_bus_memt, ih->ih_intrpin, addr, data);
+ } else
+ pci_msi_enable(ih->ih_pc, ih->ih_tag, addr, data);
} else {
int bus, dev, fn;
uint32_t reg[4];