-/* $OpenBSD: agintc.c,v 1.51 2023/07/06 09:40:36 patrick Exp $ */
+/* $OpenBSD: agintc.c,v 1.52 2023/07/07 10:11:39 patrick Exp $ */
/*
* Copyright (c) 2007, 2009, 2011, 2017 Dale Rahn <drahn@dalerahn.com>
* Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
void **mr_mbi;
};
+struct agintc_lpi_info {
+ struct agintc_msi_softc *li_msic;
+ struct cpu_info *li_ci;
+ uint32_t li_deviceid;
+ uint32_t li_eventid;
+ struct intrhand *li_ih;
+};
+
struct agintc_softc {
struct simplebus_softc sc_sbus;
struct intrq *sc_handler;
- struct intrhand **sc_lpi_handler;
+ struct agintc_lpi_info **sc_lpi;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_d_ioh;
bus_space_handle_t *sc_r_ioh;
int agintc_ipi_combined(void *);
void agintc_send_ipi(struct cpu_info *, int);
-void agintc_msi_invall(void);
+void agintc_msi_discard(struct agintc_lpi_info *);
+void agintc_msi_inv(struct agintc_lpi_info *);
const struct cfattach agintc_ca = {
sizeof (struct agintc_softc), agintc_match, agintc_attach
sizeof(*sc->sc_handler), M_DEVBUF, M_ZERO | M_WAITOK);
for (i = 0; i < nintr; i++)
TAILQ_INIT(&sc->sc_handler[i].iq_list);
- sc->sc_lpi_handler = mallocarray(sc->sc_nlpi,
- sizeof(*sc->sc_lpi_handler), M_DEVBUF, M_ZERO | M_WAITOK);
+ sc->sc_lpi = mallocarray(sc->sc_nlpi,
+ sizeof(*sc->sc_lpi), M_DEVBUF, M_ZERO | M_WAITOK);
/* set priority to IPL_HIGH until configure lowers to desired IPL */
agintc_setipl(IPL_HIGH);
}
for (irq = 0; irq < sc->sc_nlpi; irq++) {
- ih = sc->sc_lpi_handler[irq];
- if (ih == NULL || (ih->ih_flags & IPL_WAKEUP))
+ if (sc->sc_lpi[irq] == NULL)
+ continue;
+ ih = sc->sc_lpi[irq]->li_ih;
+ KASSERT(ih != NULL);
+ if (ih->ih_flags & IPL_WAKEUP)
continue;
prop = AGINTC_DMA_KVA(sc->sc_prop);
prop[irq] &= ~GICR_PROP_ENABLE;
cpu_dcache_wb_range((vaddr_t)&prop[irq],
sizeof(*prop));
__asm volatile("dsb sy");
+ /* Invalidate cache */
+ agintc_msi_inv(sc->sc_lpi[irq]);
}
-
- /* Invalidate cache. */
- agintc_msi_invall();
}
void
}
for (irq = 0; irq < sc->sc_nlpi; irq++) {
- ih = sc->sc_lpi_handler[irq];
- if (ih == NULL || (ih->ih_flags & IPL_WAKEUP))
+ if (sc->sc_lpi[irq] == NULL)
+ continue;
+ ih = sc->sc_lpi[irq]->li_ih;
+ KASSERT(ih != NULL);
+ if (ih->ih_flags & IPL_WAKEUP)
continue;
prop = AGINTC_DMA_KVA(sc->sc_prop);
prop[irq] |= GICR_PROP_ENABLE;
cpu_dcache_wb_range((vaddr_t)&prop[irq],
sizeof(*prop));
__asm volatile("dsb sy");
+ /* Invalidate cache */
+ agintc_msi_inv(sc->sc_lpi[irq]);
}
-
- /* Invalidate cache. */
- agintc_msi_invall();
}
void
}
if (irq >= LPI_BASE) {
- ih = sc->sc_lpi_handler[irq - LPI_BASE];
- if (ih == NULL)
+ if (sc->sc_lpi[irq - LPI_BASE] == NULL)
return;
-
+ ih = sc->sc_lpi[irq - LPI_BASE]->li_ih;
+ KASSERT(ih != NULL);
+
s = agintc_splraise(ih->ih_ipl);
intr_enable();
agintc_run_handler(ih, frame, s);
}
TAILQ_INSERT_TAIL(&sc->sc_handler[irqno].iq_list, ih, ih_list);
sc->sc_handler[irqno].iq_ci = ci;
- } else
- sc->sc_lpi_handler[irqno - LPI_BASE] = ih;
+ }
if (name != NULL)
evcount_attach(&ih->ih_count, name, &ih->ih_irq);
} else {
uint8_t *prop = AGINTC_DMA_KVA(sc->sc_prop);
- sc->sc_lpi_handler[irqno - LPI_BASE] = NULL;
prop[irqno - LPI_BASE] = 0;
/* Make globally visible. */
cpu_dcache_wb_range((vaddr_t)&prop[irqno - LPI_BASE],
sizeof(*prop));
__asm volatile("dsb sy");
-
- /* XXX: Invalidate cache? */
}
if (ih->ih_name != NULL)
#define MAPTI 0x0a
#define INV 0x0c
#define INVALL 0x0d
+#define DISCARD 0x0f
#define GITS_CMDQ_SIZE (64 * 1024)
#define GITS_CMDQ_NENTRIES (GITS_CMDQ_SIZE / sizeof(struct gits_cmd))
bus_addr_t sc_msi_addr;
int sc_msi_delta;
- int sc_nlpi;
- void **sc_lpi;
-
struct agintc_dmamem *sc_cmdq;
uint16_t sc_cmdidx;
else
sc->sc_cidbits = 16;
- sc->sc_nlpi = agintc_sc->sc_nlpi;
- sc->sc_lpi = mallocarray(sc->sc_nlpi, sizeof(void *), M_DEVBUF,
- M_WAITOK|M_ZERO);
-
/* Set up command queue. */
sc->sc_cmdq = agintc_dmamem_alloc(sc->sc_dmat,
GITS_CMDQ_SIZE, GITS_CMDQ_SIZE);
if (sc->sc_cmdq)
agintc_dmamem_free(sc->sc_dmat, sc->sc_cmdq);
- if (sc->sc_lpi)
- free(sc->sc_lpi, M_DEVBUF, sc->sc_nlpi * sizeof(void *));
-
bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
}
}
void
-agintc_msi_invall(void)
+agintc_msi_discard(struct agintc_lpi_info *li)
{
- struct cfdriver *cd = &agintcmsi_cd;
struct agintc_msi_softc *sc;
+ struct cpu_info *ci;
struct gits_cmd cmd;
- int i, j;
+ int hwcpu;
- for (i = 0; i < cd->cd_ndevs; i++) {
- if (cd->cd_devs[i] == NULL)
- continue;
- sc = cd->cd_devs[i];
- for (j = 0; j < ncpus; j++) {
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmd = INVALL;
- cmd.dw2 = j;
- agintc_msi_send_cmd(sc, &cmd);
- agintc_msi_wait_cmd(sc);
- }
- }
+ sc = li->li_msic;
+ ci = li->li_ci;
+ hwcpu = agintc_sc->sc_cpuremap[ci->ci_cpuid];
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = DISCARD;
+ cmd.deviceid = li->li_deviceid;
+ cmd.eventid = li->li_eventid;
+ agintc_msi_send_cmd(sc, &cmd);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = SYNC;
+ cmd.dw2 = agintc_sc->sc_processor[hwcpu] << 16;
+ agintc_msi_send_cmd(sc, &cmd);
+ agintc_msi_wait_cmd(sc);
+}
+
+void
+agintc_msi_inv(struct agintc_lpi_info *li)
+{
+ struct agintc_msi_softc *sc;
+ struct cpu_info *ci;
+ struct gits_cmd cmd;
+ int hwcpu;
+
+ sc = li->li_msic;
+ ci = li->li_ci;
+ hwcpu = agintc_sc->sc_cpuremap[ci->ci_cpuid];
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = INV;
+ cmd.deviceid = li->li_deviceid;
+ cmd.eventid = li->li_eventid;
+ agintc_msi_send_cmd(sc, &cmd);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = SYNC;
+ cmd.dw2 = agintc_sc->sc_processor[hwcpu] << 16;
+ agintc_msi_send_cmd(sc, &cmd);
+ agintc_msi_wait_cmd(sc);
}
void *
struct gits_cmd cmd;
uint32_t deviceid = *data;
uint32_t eventid;
- void *cookie;
int i, hwcpu;
if (ci == NULL)
if (eventid >= 32)
return NULL;
- for (i = 0; i < sc->sc_nlpi; i++) {
- if (sc->sc_lpi[i] != NULL)
+ for (i = 0; i < agintc_sc->sc_nlpi; i++) {
+ if (agintc_sc->sc_lpi[i] != NULL)
continue;
- cookie = agintc_intr_establish(LPI_BASE + i,
+ agintc_sc->sc_lpi[i] = malloc(sizeof(struct agintc_lpi_info),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+ agintc_sc->sc_lpi[i]->li_msic = sc;
+ agintc_sc->sc_lpi[i]->li_ci = ci;
+ agintc_sc->sc_lpi[i]->li_deviceid = deviceid;
+ agintc_sc->sc_lpi[i]->li_eventid = eventid;
+ agintc_sc->sc_lpi[i]->li_ih =
+ agintc_intr_establish(LPI_BASE + i,
IST_EDGE_RISING, level, ci, func, arg, name);
- if (cookie == NULL)
+ if (agintc_sc->sc_lpi[i]->li_ih == NULL) {
+ free(agintc_sc->sc_lpi[i], M_DEVBUF,
+ sizeof(struct agintc_lpi_info));
+ agintc_sc->sc_lpi[i] = NULL;
return NULL;
+ }
memset(&cmd, 0, sizeof(cmd));
cmd.cmd = MAPTI;
*addr = sc->sc_msi_addr + deviceid * sc->sc_msi_delta;
*data = eventid;
- sc->sc_lpi[i] = cookie;
- return &sc->sc_lpi[i];
+ return &agintc_sc->sc_lpi[i];
}
return NULL;
void
agintc_intr_disestablish_msi(void *cookie)
{
- agintc_intr_disestablish(*(void **)cookie);
- *(void **)cookie = NULL;
+ struct agintc_lpi_info *li = *(void **)cookie;
+
+ agintc_intr_disestablish(li->li_ih);
+ agintc_msi_discard(li);
+ agintc_msi_inv(li);
- /* Invalidate cache. */
- agintc_msi_invall();
+ free(li, M_DEVBUF, sizeof(*li));
+ *(void **)cookie = NULL;
}
void
agintc_intr_barrier_msi(void *cookie)
{
- agintc_intr_barrier(*(void **)cookie);
+ struct agintc_lpi_info *li = *(void **)cookie;
+
+ agintc_intr_barrier(li->li_ih);
}
struct agintc_dmamem *