diff options
author | 2019-05-31 10:35:49 +0000 | |
---|---|---|
committer | 2019-05-31 10:35:49 +0000 | |
commit | e33d8a25524438b0dca5bd1d06e1737a57adbbe8 (patch) | |
tree | e52b3ad9715d97e50d750c2dad12fc3a8ed3b681 /sys/dev | |
parent | Exit the attribute loop early if there are no unknown attributes left (diff) | |
download | wireguard-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.c | 68 |
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, ®) == 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, ®) == 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]; |