svn commit: r357324 - head/sys/arm64/arm64
Andrew Turner
andrew at FreeBSD.org
Fri Jan 31 10:30:13 UTC 2020
Author: andrew
Date: Fri Jan 31 10:30:13 2020
New Revision: 357324
URL: https://svnweb.freebsd.org/changeset/base/357324
Log:
Only create one ITS configuration table
When there are multiple ITS devices in the system we would allocate a
configuration table for each, however only one table is needed as all the
ITS devices share this.
Allocate a table only when the global table is unset.
While here fix the type of this to be a pointer to a uint8_t array as the
entries are all 8 bits wide.
MFC after: 2 weeks
Sponsored by: DARPA, AFRL
Modified:
head/sys/arm64/arm64/gicv3_its.c
Modified: head/sys/arm64/arm64/gicv3_its.c
==============================================================================
--- head/sys/arm64/arm64/gicv3_its.c Fri Jan 31 09:51:38 2020 (r357323)
+++ head/sys/arm64/arm64/gicv3_its.c Fri Jan 31 10:30:13 2020 (r357324)
@@ -224,6 +224,7 @@ struct its_col {
struct gicv3_its_irqsrc {
struct intr_irqsrc gi_isrc;
u_int gi_irq;
+ u_int gi_lpi;
struct its_dev *gi_its_dev;
};
@@ -241,7 +242,7 @@ struct gicv3_its_softc {
* TODO: We should get these from the parent as we only want a
* single copy of each across the interrupt controller.
*/
- vm_offset_t sc_conf_base;
+ uint8_t *sc_conf_base;
vm_offset_t sc_pend_base[MAXCPU];
/* Command handling */
@@ -263,6 +264,8 @@ struct gicv3_its_softc {
u_int sc_its_flags;
};
+static void *conf_base;
+
typedef void (its_quirk_func_t)(device_t);
static its_quirk_func_t its_quirk_cavium_22375;
@@ -542,17 +545,29 @@ gicv3_its_table_init(device_t dev, struct gicv3_its_so
static void
gicv3_its_conftable_init(struct gicv3_its_softc *sc)
{
+ void *conf_table;
- sc->sc_conf_base = (vm_offset_t)contigmalloc(LPI_CONFTAB_SIZE,
- M_GICV3_ITS, M_WAITOK, 0, LPI_CONFTAB_MAX_ADDR, LPI_CONFTAB_ALIGN,
- 0);
+ conf_table = (void *)atomic_load_ptr((uintptr_t *)&conf_base);
+ if (conf_table == NULL) {
+ conf_table = contigmalloc(LPI_CONFTAB_SIZE,
+ M_GICV3_ITS, M_WAITOK, 0, LPI_CONFTAB_MAX_ADDR,
+ LPI_CONFTAB_ALIGN, 0);
+ if (atomic_cmpset_ptr((uintptr_t *)&conf_base,
+ (uintptr_t)NULL, (uintptr_t)conf_table) == 0) {
+ contigfree(conf_table, LPI_CONFTAB_SIZE, M_GICV3_ITS);
+ conf_table =
+ (void *)atomic_load_ptr((uintptr_t *)&conf_base);
+ }
+ }
+ sc->sc_conf_base = conf_table;
+
/* Set the default configuration */
- memset((void *)sc->sc_conf_base, GIC_PRIORITY_MAX | LPI_CONF_GROUP1,
+ memset(sc->sc_conf_base, GIC_PRIORITY_MAX | LPI_CONF_GROUP1,
LPI_CONFTAB_SIZE);
/* Flush the table to memory */
- cpu_dcache_wb_range(sc->sc_conf_base, LPI_CONFTAB_SIZE);
+ cpu_dcache_wb_range((vm_offset_t)sc->sc_conf_base, LPI_CONFTAB_SIZE);
}
static void
@@ -792,6 +807,7 @@ gicv3_its_attach(device_t dev)
name = device_get_nameunit(dev);
for (i = 0; i < sc->sc_irq_length; i++) {
sc->sc_irqs[i].gi_irq = i;
+ sc->sc_irqs[i].gi_lpi = i + sc->sc_irq_base - GIC_FIRST_LPI;
err = intr_isrc_register(&sc->sc_irqs[i].gi_isrc, dev, 0,
"%s,%u", name, i);
}
@@ -824,13 +840,13 @@ gicv3_its_disable_intr(device_t dev, struct intr_irqsr
sc = device_get_softc(dev);
girq = (struct gicv3_its_irqsrc *)isrc;
- conf = (uint8_t *)sc->sc_conf_base;
+ conf = sc->sc_conf_base;
- conf[girq->gi_irq] &= ~LPI_CONF_ENABLE;
+ conf[girq->gi_lpi] &= ~LPI_CONF_ENABLE;
if ((sc->sc_its_flags & ITS_FLAGS_LPI_CONF_FLUSH) != 0) {
/* Clean D-cache under command. */
- cpu_dcache_wb_range((vm_offset_t)&conf[girq->gi_irq], 1);
+ cpu_dcache_wb_range((vm_offset_t)&conf[girq->gi_lpi], 1);
} else {
/* DSB inner shareable, store */
dsb(ishst);
@@ -848,13 +864,13 @@ gicv3_its_enable_intr(device_t dev, struct intr_irqsrc
sc = device_get_softc(dev);
girq = (struct gicv3_its_irqsrc *)isrc;
- conf = (uint8_t *)sc->sc_conf_base;
+ conf = sc->sc_conf_base;
- conf[girq->gi_irq] |= LPI_CONF_ENABLE;
+ conf[girq->gi_lpi] |= LPI_CONF_ENABLE;
if ((sc->sc_its_flags & ITS_FLAGS_LPI_CONF_FLUSH) != 0) {
/* Clean D-cache under command. */
- cpu_dcache_wb_range((vm_offset_t)&conf[girq->gi_irq], 1);
+ cpu_dcache_wb_range((vm_offset_t)&conf[girq->gi_lpi], 1);
} else {
/* DSB inner shareable, store */
dsb(ishst);
More information about the svn-src-all
mailing list