diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-08-18 10:10:20 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2018-08-18 10:10:20 +0000 |
commit | 88dd41732e45e7562f160843007fb76faece0a3f (patch) | |
tree | e1aa9c281328ebb0c79cb0a8baf904a7fdc6be10 | |
parent | 43164441137d18c8ca9d93dfe95e9d88c09d6613 (diff) |
Support arbitrary number of redistributors.
Inspired by an earlier diff from drahn@
ok patrick@, jsg@
-rw-r--r-- | sys/arch/arm64/dev/agintc.c | 68 |
1 files changed, 44 insertions, 24 deletions
diff --git a/sys/arch/arm64/dev/agintc.c b/sys/arch/arm64/dev/agintc.c index 6be7ca13077..2d9afa9016d 100644 --- a/sys/arch/arm64/dev/agintc.c +++ b/sys/arch/arm64/dev/agintc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: agintc.c,v 1.13 2018/08/15 21:46:29 kettenis Exp $ */ +/* $OpenBSD: agintc.c,v 1.14 2018/08/18 10:10:19 kettenis Exp $ */ /* * Copyright (c) 2007, 2009, 2011, 2017 Dale Rahn <drahn@dalerahn.com> * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org> @@ -132,24 +132,16 @@ #define IRQ_ENABLE 1 #define IRQ_DISABLE 0 -/* - * This is not a true hard limit, but until bigger machines are supported - * there is no need for this to be 96+, which the interrupt controller - * does support. It may make sense to move to dynamic allocation of these 3 - * fields in the future, eg when hardware with 96 cores are supported. - */ -#define MAX_CORES 24 - struct agintc_softc { struct simplebus_softc sc_sbus; struct intrq *sc_handler; struct intrhand **sc_lpi_handler; bus_space_tag_t sc_iot; bus_space_handle_t sc_d_ioh; - bus_space_handle_t sc_r_ioh[MAX_CORES]; + bus_space_handle_t *sc_r_ioh; bus_space_handle_t sc_redist_base; bus_dma_tag_t sc_dmat; - uint64_t sc_affinity[MAX_CORES]; + uint64_t *sc_affinity; int sc_cpuremap[MAXCPUS]; int sc_nintr; int sc_nlpi; @@ -354,7 +346,7 @@ agintc_attach(struct device *parent, struct device *self, void *aux) agintc_sc = sc; /* save this for global access */ - /* find and submap the redistributors. */ + /* find the redistributors. */ offset = 0; for (nredist = 0; ; nredist++) { int32_t sz = (64 * 1024 * 2); @@ -366,17 +358,43 @@ agintc_attach(struct device *parent, struct device *self, void *aux) if (typer & GICR_TYPER_VLPIS) sz += (64 * 1024 * 2); +#ifdef DEBUG_AGINTC + printf("probing redistributor %d %x\n", nredist, offset); +#endif + + offset += sz; + + if (typer & GICR_TYPER_LAST) { + sc->sc_num_redist = nredist + 1; + break; + } + } + + printf(" nirq %d, nredist %d", nintr, sc->sc_num_redist); + + sc->sc_r_ioh = mallocarray(sc->sc_num_redist, + sizeof(*sc->sc_r_ioh), M_DEVBUF, M_WAITOK); + sc->sc_affinity = mallocarray(sc->sc_num_redist, + sizeof(*sc->sc_affinity), M_DEVBUF, M_WAITOK); + + /* submap and configure the redistributors. */ + offset = 0; + for (nredist = 0; nredist < sc->sc_num_redist; nredist++) { + int32_t sz = (64 * 1024 * 2); + uint64_t typer; + + typer = bus_space_read_8(sc->sc_iot, sc->sc_redist_base, + offset + GICR_TYPER); + + if (typer & GICR_TYPER_VLPIS) + sz += (64 * 1024 * 2); + sc->sc_affinity[nredist] = bus_space_read_8(sc->sc_iot, sc->sc_redist_base, offset + GICR_TYPER) >> 32; bus_space_subregion(sc->sc_iot, sc->sc_redist_base, offset, sz, &sc->sc_r_ioh[nredist]); -#ifdef DEBUG_AGINTC - printf("probing redistributor %d %x %p\n", nredist, offset, - sc->sc_r_ioh[nredist]); -#endif - if (sc->sc_nlpi > 0) { bus_space_write_8(sc->sc_iot, sc->sc_redist_base, offset + GICR_PROPBASER, @@ -393,15 +411,8 @@ agintc_attach(struct device *parent, struct device *self, void *aux) } offset += sz; - - if (typer & GICR_TYPER_LAST) { - sc->sc_num_redist = nredist + 1; - break; - } } - printf(" nirq %d, nredist %d", nintr, sc->sc_num_redist); - /* Disable all interrupts, clear all pending */ for (i = 1; i < nintr / 32; i++) { bus_space_write_4(sc->sc_iot, sc->sc_d_ioh, @@ -535,6 +546,15 @@ agintc_attach(struct device *parent, struct device *self, void *aux) return; unmap: + if (sc->sc_r_ioh) { + free(sc->sc_r_ioh, M_DEVBUF, + sc->sc_num_redist * sizeof(*sc->sc_r_ioh)); + } + if (sc->sc_affinity) { + free(sc->sc_affinity, M_DEVBUF, + sc->sc_num_redist * sizeof(*sc->sc_affinity)); + } + if (sc->sc_pend) agintc_dmamem_free(sc->sc_dmat, sc->sc_pend); if (sc->sc_prop) |