summaryrefslogtreecommitdiff
path: root/sys/arch/arm64
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2022-03-07 11:08:14 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2022-03-07 11:08:14 +0000
commitd329ac1b02771340f8bed210e6287feb0f14f1df (patch)
tree5794adfd9b2acee3588291476b17ababf035f830 /sys/arch/arm64
parentbebde137097676dfab3927f1509a7af3fba75bf0 (diff)
Since AIC2 uses 4 interrupt cells we need to adjust the code that handles
the "msi-ranges" property and converts it into a proper interrupt descriptor for MSIs. ok jsg@
Diffstat (limited to 'sys/arch/arm64')
-rw-r--r--sys/arch/arm64/dev/aplpcie.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/sys/arch/arm64/dev/aplpcie.c b/sys/arch/arm64/dev/aplpcie.c
index e64ba3ccb9a..e2d6cc773b7 100644
--- a/sys/arch/arm64/dev/aplpcie.c
+++ b/sys/arch/arm64/dev/aplpcie.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aplpcie.c,v 1.11 2022/02/13 12:02:21 kettenis Exp $ */
+/* $OpenBSD: aplpcie.c,v 1.12 2022/03/07 11:08:13 kettenis Exp $ */
/*
* Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
*
@@ -127,7 +127,8 @@ struct aplpcie_softc {
int sc_msi;
bus_addr_t sc_msi_doorbell;
- uint32_t sc_msi_range[5];
+ uint32_t sc_msi_range[6];
+ int sc_msi_rangelen;
struct interrupt_controller sc_msi_ic;
};
@@ -229,8 +230,12 @@ aplpcie_attach(struct device *parent, struct device *self, void *aux)
sc->sc_msi_doorbell =
OF_getpropint64(sc->sc_node, "msi-doorbell", 0xffff000ULL);
- if (OF_getpropintarray(sc->sc_node, "msi-ranges", sc->sc_msi_range,
- sizeof(sc->sc_msi_range)) != sizeof(sc->sc_msi_range)) {
+ sc->sc_msi_rangelen = OF_getpropintarray(sc->sc_node, "msi-ranges",
+ sc->sc_msi_range, sizeof(sc->sc_msi_range));
+ if (sc->sc_msi_rangelen <= 0 ||
+ (sc->sc_msi_rangelen % sizeof(uint32_t)) ||
+ (sc->sc_msi_rangelen / sizeof(uint32_t)) < 5 ||
+ (sc->sc_msi_rangelen / sizeof(uint32_t) > 6)) {
printf(": invalid msi-ranges property\n");
return;
}
@@ -665,17 +670,18 @@ aplpcie_intr_establish_msi(void *cookie, uint64_t *addr, uint64_t *data,
int level, struct cpu_info *ci, int (*func)(void *), void *arg, char *name)
{
struct aplpcie_softc *sc = cookie;
- uint32_t cells[3];
+ uint32_t cells[4];
+ int ncells;
- if (sc->sc_msi >= sc->sc_msi_range[4])
+ ncells = sc->sc_msi_rangelen / sizeof(uint32_t);
+ if (sc->sc_msi >= sc->sc_msi_range[ncells - 1])
return NULL;
*addr = sc->sc_msi_doorbell;
*data = sc->sc_msi++;
- cells[0] = sc->sc_msi_range[1];
- cells[1] = sc->sc_msi_range[2] + *data;
- cells[2] = sc->sc_msi_range[3];
+ memcpy(cells, &sc->sc_msi_range[1], sizeof(cells));
+ cells[ncells - 4] += *data;
return fdt_intr_parent_establish(&sc->sc_msi_ic, cells,
level, ci, func, arg, name);