Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/fdt Add MSI/MSI-X support.
details: https://anonhg.NetBSD.org/src/rev/5357a19902ba
branches: trunk
changeset: 836897:5357a19902ba
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sun Nov 11 21:24:38 2018 +0000
description:
Add MSI/MSI-X support.
diffstat:
sys/arch/arm/fdt/pcihost_fdt.c | 66 ++++++++++++++++++++++++++++++++++++-----
1 files changed, 58 insertions(+), 8 deletions(-)
diffs (171 lines):
diff -r b1540ddd3403 -r 5357a19902ba sys/arch/arm/fdt/pcihost_fdt.c
--- a/sys/arch/arm/fdt/pcihost_fdt.c Sun Nov 11 21:24:28 2018 +0000
+++ b/sys/arch/arm/fdt/pcihost_fdt.c Sun Nov 11 21:24:38 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pcihost_fdt.c,v 1.2 2018/09/09 13:40:28 jmcneill Exp $ */
+/* $NetBSD: pcihost_fdt.c,v 1.3 2018/11/11 21:24:38 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pcihost_fdt.c,v 1.2 2018/09/09 13:40:28 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pcihost_fdt.c,v 1.3 2018/11/11 21:24:38 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -50,6 +50,8 @@
#include <dev/fdt/fdtvar.h>
+#include <arm/pci/pci_msi_machdep.h>
+
#define IH_INDEX_MASK 0x0000ffff
#define IH_MPSAFE 0x80000000
@@ -72,6 +74,8 @@
#define PHYS_HI_FUNCTION __BITS(10,8)
#define PHYS_HI_REGISTER __BITS(7,0)
+static int pcihost_segment = 0;
+
enum pcihost_type {
PCIHOST_CAM = 1,
PCIHOST_ECAM,
@@ -86,6 +90,7 @@
enum pcihost_type sc_type;
+ u_int sc_seg;
u_int sc_bus_min;
u_int sc_bus_max;
@@ -103,6 +108,7 @@
static int pcihost_bus_maxdevs(void *, int);
static pcitag_t pcihost_make_tag(void *, int, int, int);
static void pcihost_decompose_tag(void *, pcitag_t, int *, int *, int *);
+static u_int pcihost_get_segment(void *);
static pcireg_t pcihost_conf_read(void *, pcitag_t, int);
static void pcihost_conf_write(void *, pcitag_t, int, pcireg_t);
static int pcihost_conf_hook(void *, int, int, int, pcireg_t);
@@ -178,6 +184,15 @@
sc->sc_bus_max = PCIHOST_DEFAULT_BUS_MAX;
}
+ /*
+ * Assign a fixed PCI segment ("domain") number. If the property is not
+ * present, assign one. The binding spec says if this property is used to
+ * assign static segment numbers, all host bridges should have segments
+ * astatic assigned to prevent overlaps.
+ */
+ if (of_getprop_uint32(sc->sc_phandle, "linux,pci-domain", &sc->sc_seg))
+ sc->sc_seg = pcihost_segment++;
+
pcihost_init(&sc->sc_pc, sc);
if (pcihost_config(sc) != 0)
@@ -189,6 +204,12 @@
PCI_FLAGS_MWI_OKAY |
PCI_FLAGS_MEM_OKAY |
PCI_FLAGS_IO_OKAY;
+#ifdef __HAVE_PCI_MSI_MSIX
+ if (sc->sc_type == PCIHOST_ECAM) {
+ pba.pba_flags |= PCI_FLAGS_MSI_OKAY |
+ PCI_FLAGS_MSIX_OKAY;
+ }
+#endif
pba.pba_iot = sc->sc_bst;
pba.pba_memt = sc->sc_bst;
pba.pba_dmat = sc->sc_dmat;
@@ -196,7 +217,7 @@
pba.pba_dmat64 = sc->sc_dmat;
#endif
pba.pba_pc = &sc->sc_pc;
- pba.pba_bus = 0;
+ pba.pba_bus = sc->sc_bus_min;
config_found_ia(self, "pcibus", &pba, pcibusprint);
}
@@ -209,6 +230,7 @@
pc->pc_bus_maxdevs = pcihost_bus_maxdevs;
pc->pc_make_tag = pcihost_make_tag;
pc->pc_decompose_tag = pcihost_decompose_tag;
+ pc->pc_get_segment = pcihost_get_segment;
pc->pc_conf_read = pcihost_conf_read;
pc->pc_conf_write = pcihost_conf_write;
pc->pc_conf_hook = pcihost_conf_hook;
@@ -228,8 +250,17 @@
{
struct extent *ioext = NULL, *memext = NULL, *pmemext = NULL;
const u_int *ranges;
+ u_int probe_only;
int error, len;
+ /*
+ * If this flag is set, skip configuration of the PCI bus and use existing config.
+ */
+ if (of_getprop_uint32(sc->sc_phandle, "linux,pci-probe-only", &probe_only))
+ probe_only = 0;
+ if (probe_only)
+ return 0;
+
ranges = fdtbus_get_prop(sc->sc_phandle, "ranges", &len);
if (ranges == NULL) {
aprint_error_dev(sc->sc_dev, "missing 'ranges' property\n");
@@ -334,6 +365,14 @@
*fp = (tag >> 8) & 0x7;
}
+static u_int
+pcihost_get_segment(void *v)
+{
+ struct pcihost_softc *sc = v;
+
+ return sc->sc_seg;
+}
+
static pcireg_t
pcihost_conf_read(void *v, pcitag_t tag, int offset)
{
@@ -489,16 +528,24 @@
static const char *
pcihost_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len)
{
+ const int irq = __SHIFTOUT(ih, ARM_PCI_INTR_IRQ);
+ const int vec = __SHIFTOUT(ih, ARM_PCI_INTR_MSI_VEC);
struct pcihost_softc *sc = v;
const u_int *specifier;
int ihandle;
- specifier = pcihost_find_intr(sc, ih & IH_INDEX_MASK, &ihandle);
- if (specifier == NULL)
- return NULL;
+ if (ih & ARM_PCI_INTR_MSIX) {
+ snprintf(buf, len, "irq %d (MSI-X vec %d)", irq, vec);
+ } else if (ih & ARM_PCI_INTR_MSI) {
+ snprintf(buf, len, "irq %d (MSI vec %d)", irq, vec);
+ } else {
+ specifier = pcihost_find_intr(sc, ih & IH_INDEX_MASK, &ihandle);
+ if (specifier == NULL)
+ return NULL;
- if (!fdtbus_intr_str_raw(ihandle, specifier, buf, len))
- return NULL;
+ if (!fdtbus_intr_str_raw(ihandle, specifier, buf, len))
+ return NULL;
+ }
return buf;
}
@@ -533,6 +580,9 @@
const u_int *specifier;
int ihandle;
+ if ((ih & (ARM_PCI_INTR_MSI | ARM_PCI_INTR_MSIX)) != 0)
+ return arm_pci_msi_intr_establish(&sc->sc_pc, ih, ipl, callback, arg);
+
specifier = pcihost_find_intr(sc, ih & IH_INDEX_MASK, &ihandle);
if (specifier == NULL)
return NULL;
Home |
Main Index |
Thread Index |
Old Index