Support arbitrary number of redistributors.
authorkettenis <kettenis@openbsd.org>
Sat, 18 Aug 2018 10:10:19 +0000 (10:10 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 18 Aug 2018 10:10:19 +0000 (10:10 +0000)
Inspired by an earlier diff from drahn@

ok patrick@, jsg@

sys/arch/arm64/dev/agintc.c

index 6be7ca1..2d9afa9 100644 (file)
@@ -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>
 #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)