Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115845063
D31767.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D31767.diff
View Options
diff --git a/sys/arm/arm/gic.h b/sys/arm/arm/gic.h
--- a/sys/arm/arm/gic.h
+++ b/sys/arm/arm/gic.h
@@ -63,17 +63,17 @@
int nranges;
struct arm_gic_range * ranges;
+
+ u_int sc_spi_start;
+ u_int sc_spi_end;
+ u_int sc_spi_count;
};
DECLARE_CLASS(arm_gic_driver);
struct arm_gicv2m_softc {
struct resource *sc_mem;
- struct mtx sc_mutex;
uintptr_t sc_xref;
- u_int sc_spi_start;
- u_int sc_spi_end;
- u_int sc_spi_count;
};
DECLARE_CLASS(arm_gicv2m_driver);
diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c
--- a/sys/arm/arm/gic.c
+++ b/sys/arm/arm/gic.c
@@ -501,6 +501,56 @@
("arm_gic_read_ivar: Invalid bus type %u", sc->gic_bus));
*result = sc->gic_bus;
return (0);
+ case GIC_IVAR_MBI_START:
+ *result = sc->sc_spi_start;
+ return (0);
+ case GIC_IVAR_MBI_COUNT:
+ *result = sc->sc_spi_count;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static int
+arm_gic_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct arm_gic_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ switch(which) {
+ case GIC_IVAR_HW_REV:
+ case GIC_IVAR_BUS:
+ return (EINVAL);
+ case GIC_IVAR_MBI_START:
+ /*
+ * GIC_IVAR_MBI_START must be set once and first. This allows
+ * us to reserve the registers when GIC_IVAR_MBI_COUNT is set.
+ */
+ MPASS(sc->sc_spi_start == 0);
+ MPASS(sc->sc_spi_count == 0);
+ MPASS(value >= GIC_FIRST_SPI);
+ MPASS(value < sc->nirqs);
+
+ sc->sc_spi_start = value;
+ return (0);
+ case GIC_IVAR_MBI_COUNT:
+ MPASS(sc->sc_spi_start != 0);
+ MPASS(sc->sc_spi_count == 0);
+ MPASS(value >= sc->sc_spi_start);
+ MPASS(value >= GIC_FIRST_SPI);
+
+ sc->sc_spi_count = value;
+ sc->sc_spi_end = sc->sc_spi_start + sc->sc_spi_count;
+
+ MPASS(sc->sc_spi_end <= sc->nirqs);
+
+ /* Reserve these interrupts for MSI/MSI-X use */
+ arm_gic_reserve_msi_range(dev, sc->sc_spi_start,
+ sc->sc_spi_count);
+
+ return (0);
}
return (ENOENT);
@@ -995,99 +1045,20 @@
}
#endif
-static device_method_t arm_gic_methods[] = {
- /* Bus interface */
- DEVMETHOD(bus_print_child, arm_gic_print_child),
- DEVMETHOD(bus_add_child, bus_generic_add_child),
- DEVMETHOD(bus_alloc_resource, arm_gic_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_release_resource),
- DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
- DEVMETHOD(bus_read_ivar, arm_gic_read_ivar),
-
- /* Interrupt controller interface */
- DEVMETHOD(pic_disable_intr, arm_gic_disable_intr),
- DEVMETHOD(pic_enable_intr, arm_gic_enable_intr),
- DEVMETHOD(pic_map_intr, arm_gic_map_intr),
- DEVMETHOD(pic_setup_intr, arm_gic_setup_intr),
- DEVMETHOD(pic_teardown_intr, arm_gic_teardown_intr),
- DEVMETHOD(pic_post_filter, arm_gic_post_filter),
- DEVMETHOD(pic_post_ithread, arm_gic_post_ithread),
- DEVMETHOD(pic_pre_ithread, arm_gic_pre_ithread),
-#ifdef SMP
- DEVMETHOD(pic_bind_intr, arm_gic_bind_intr),
- DEVMETHOD(pic_init_secondary, arm_gic_init_secondary),
- DEVMETHOD(pic_ipi_send, arm_gic_ipi_send),
- DEVMETHOD(pic_ipi_setup, arm_gic_ipi_setup),
-#endif
- { 0, 0 }
-};
-
-DEFINE_CLASS_0(gic, arm_gic_driver, arm_gic_methods,
- sizeof(struct arm_gic_softc));
-
-/*
- * GICv2m support -- the GICv2 MSI/MSI-X controller.
- */
-
-#define GICV2M_MSI_TYPER 0x008
-#define MSI_TYPER_SPI_BASE(x) (((x) >> 16) & 0x3ff)
-#define MSI_TYPER_SPI_COUNT(x) (((x) >> 0) & 0x3ff)
-#define GICv2M_MSI_SETSPI_NS 0x040
-#define GICV2M_MSI_IIDR 0xFCC
-
-int
-arm_gicv2m_attach(device_t dev)
-{
- struct arm_gicv2m_softc *sc;
- uint32_t typer;
- int rid;
-
- sc = device_get_softc(dev);
-
- rid = 0;
- sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
- RF_ACTIVE);
- if (sc->sc_mem == NULL) {
- device_printf(dev, "Unable to allocate resources\n");
- return (ENXIO);
- }
-
- typer = bus_read_4(sc->sc_mem, GICV2M_MSI_TYPER);
- sc->sc_spi_start = MSI_TYPER_SPI_BASE(typer);
- sc->sc_spi_count = MSI_TYPER_SPI_COUNT(typer);
- sc->sc_spi_end = sc->sc_spi_start + sc->sc_spi_count;
-
- /* Reserve these interrupts for MSI/MSI-X use */
- arm_gic_reserve_msi_range(device_get_parent(dev), sc->sc_spi_start,
- sc->sc_spi_count);
-
- mtx_init(&sc->sc_mutex, "GICv2m lock", NULL, MTX_DEF);
-
- intr_msi_register(dev, sc->sc_xref);
-
- if (bootverbose)
- device_printf(dev, "using spi %u to %u\n", sc->sc_spi_start,
- sc->sc_spi_start + sc->sc_spi_count - 1);
-
- return (0);
-}
-
static int
-arm_gicv2m_alloc_msi(device_t dev, device_t child, int count, int maxcount,
+arm_gic_alloc_msi(device_t dev, device_t child, int count, int maxcount,
device_t *pic, struct intr_irqsrc **srcs)
{
- struct arm_gic_softc *psc;
- struct arm_gicv2m_softc *sc;
+ struct arm_gic_softc *sc;
int i, irq, end_irq;
bool found;
KASSERT(powerof2(count), ("%s: bad count", __func__));
KASSERT(powerof2(maxcount), ("%s: bad maxcount", __func__));
- psc = device_get_softc(device_get_parent(dev));
sc = device_get_softc(dev);
- mtx_lock(&sc->sc_mutex);
+ mtx_lock(&sc->mutex);
found = false;
for (irq = sc->sc_spi_start; irq < sc->sc_spi_end; irq++) {
@@ -1106,11 +1077,11 @@
break;
}
- KASSERT((psc->gic_irqs[end_irq].gi_flags & GI_FLAG_MSI)!= 0,
+ KASSERT((sc->gic_irqs[end_irq].gi_flags & GI_FLAG_MSI)!= 0,
("%s: Non-MSI interrupt found", __func__));
/* This is already used */
- if ((psc->gic_irqs[end_irq].gi_flags & GI_FLAG_MSI_USED) ==
+ if ((sc->gic_irqs[end_irq].gi_flags & GI_FLAG_MSI_USED) ==
GI_FLAG_MSI_USED) {
found = false;
break;
@@ -1122,34 +1093,34 @@
/* Not enough interrupts were found */
if (!found || irq == sc->sc_spi_end) {
- mtx_unlock(&sc->sc_mutex);
+ mtx_unlock(&sc->mutex);
return (ENXIO);
}
for (i = 0; i < count; i++) {
/* Mark the interrupt as used */
- psc->gic_irqs[irq + i].gi_flags |= GI_FLAG_MSI_USED;
+ sc->gic_irqs[irq + i].gi_flags |= GI_FLAG_MSI_USED;
}
- mtx_unlock(&sc->sc_mutex);
+ mtx_unlock(&sc->mutex);
for (i = 0; i < count; i++)
- srcs[i] = (struct intr_irqsrc *)&psc->gic_irqs[irq + i];
- *pic = device_get_parent(dev);
+ srcs[i] = (struct intr_irqsrc *)&sc->gic_irqs[irq + i];
+ *pic = dev;
return (0);
}
static int
-arm_gicv2m_release_msi(device_t dev, device_t child, int count,
+arm_gic_release_msi(device_t dev, device_t child, int count,
struct intr_irqsrc **isrc)
{
- struct arm_gicv2m_softc *sc;
+ struct arm_gic_softc *sc;
struct gic_irqsrc *gi;
int i;
sc = device_get_softc(dev);
- mtx_lock(&sc->sc_mutex);
+ mtx_lock(&sc->mutex);
for (i = 0; i < count; i++) {
gi = (struct gic_irqsrc *)isrc[i];
@@ -1159,50 +1130,48 @@
gi->gi_flags &= ~GI_FLAG_MSI_USED;
}
- mtx_unlock(&sc->sc_mutex);
+ mtx_unlock(&sc->mutex);
return (0);
}
static int
-arm_gicv2m_alloc_msix(device_t dev, device_t child, device_t *pic,
+arm_gic_alloc_msix(device_t dev, device_t child, device_t *pic,
struct intr_irqsrc **isrcp)
{
- struct arm_gicv2m_softc *sc;
- struct arm_gic_softc *psc;
+ struct arm_gic_softc *sc;
int irq;
- psc = device_get_softc(device_get_parent(dev));
sc = device_get_softc(dev);
- mtx_lock(&sc->sc_mutex);
+ mtx_lock(&sc->mutex);
/* Find an unused interrupt */
for (irq = sc->sc_spi_start; irq < sc->sc_spi_end; irq++) {
- KASSERT((psc->gic_irqs[irq].gi_flags & GI_FLAG_MSI) != 0,
+ KASSERT((sc->gic_irqs[irq].gi_flags & GI_FLAG_MSI) != 0,
("%s: Non-MSI interrupt found", __func__));
- if ((psc->gic_irqs[irq].gi_flags & GI_FLAG_MSI_USED) == 0)
+ if ((sc->gic_irqs[irq].gi_flags & GI_FLAG_MSI_USED) == 0)
break;
}
/* No free interrupt was found */
if (irq == sc->sc_spi_end) {
- mtx_unlock(&sc->sc_mutex);
+ mtx_unlock(&sc->mutex);
return (ENXIO);
}
/* Mark the interrupt as used */
- psc->gic_irqs[irq].gi_flags |= GI_FLAG_MSI_USED;
- mtx_unlock(&sc->sc_mutex);
+ sc->gic_irqs[irq].gi_flags |= GI_FLAG_MSI_USED;
+ mtx_unlock(&sc->mutex);
- *isrcp = (struct intr_irqsrc *)&psc->gic_irqs[irq];
- *pic = device_get_parent(dev);
+ *isrcp = (struct intr_irqsrc *)&sc->gic_irqs[irq];
+ *pic = dev;
return (0);
}
static int
-arm_gicv2m_release_msix(device_t dev, device_t child, struct intr_irqsrc *isrc)
+arm_gic_release_msix(device_t dev, device_t child, struct intr_irqsrc *isrc)
{
- struct arm_gicv2m_softc *sc;
+ struct arm_gic_softc *sc;
struct gic_irqsrc *gi;
sc = device_get_softc(dev);
@@ -1211,13 +1180,122 @@
KASSERT((gi->gi_flags & GI_FLAG_MSI_USED) == GI_FLAG_MSI_USED,
("%s: Trying to release an unused MSI-X interrupt", __func__));
- mtx_lock(&sc->sc_mutex);
+ mtx_lock(&sc->mutex);
gi->gi_flags &= ~GI_FLAG_MSI_USED;
- mtx_unlock(&sc->sc_mutex);
+ mtx_unlock(&sc->mutex);
return (0);
}
+static device_method_t arm_gic_methods[] = {
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, arm_gic_print_child),
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
+ DEVMETHOD(bus_alloc_resource, arm_gic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
+ DEVMETHOD(bus_read_ivar, arm_gic_read_ivar),
+ DEVMETHOD(bus_write_ivar, arm_gic_write_ivar),
+
+ /* Interrupt controller interface */
+ DEVMETHOD(pic_disable_intr, arm_gic_disable_intr),
+ DEVMETHOD(pic_enable_intr, arm_gic_enable_intr),
+ DEVMETHOD(pic_map_intr, arm_gic_map_intr),
+ DEVMETHOD(pic_setup_intr, arm_gic_setup_intr),
+ DEVMETHOD(pic_teardown_intr, arm_gic_teardown_intr),
+ DEVMETHOD(pic_post_filter, arm_gic_post_filter),
+ DEVMETHOD(pic_post_ithread, arm_gic_post_ithread),
+ DEVMETHOD(pic_pre_ithread, arm_gic_pre_ithread),
+#ifdef SMP
+ DEVMETHOD(pic_bind_intr, arm_gic_bind_intr),
+ DEVMETHOD(pic_init_secondary, arm_gic_init_secondary),
+ DEVMETHOD(pic_ipi_send, arm_gic_ipi_send),
+ DEVMETHOD(pic_ipi_setup, arm_gic_ipi_setup),
+#endif
+
+ /* MSI/MSI-X */
+ DEVMETHOD(msi_alloc_msi, arm_gic_alloc_msi),
+ DEVMETHOD(msi_release_msi, arm_gic_release_msi),
+ DEVMETHOD(msi_alloc_msix, arm_gic_alloc_msix),
+ DEVMETHOD(msi_release_msix, arm_gic_release_msix),
+
+ { 0, 0 }
+};
+
+DEFINE_CLASS_0(gic, arm_gic_driver, arm_gic_methods,
+ sizeof(struct arm_gic_softc));
+
+/*
+ * GICv2m support -- the GICv2 MSI/MSI-X controller.
+ */
+
+#define GICV2M_MSI_TYPER 0x008
+#define MSI_TYPER_SPI_BASE(x) (((x) >> 16) & 0x3ff)
+#define MSI_TYPER_SPI_COUNT(x) (((x) >> 0) & 0x3ff)
+#define GICv2M_MSI_SETSPI_NS 0x040
+#define GICV2M_MSI_IIDR 0xFCC
+
+int
+arm_gicv2m_attach(device_t dev)
+{
+ struct arm_gicv2m_softc *sc;
+ uint32_t typer;
+ u_int spi_start, spi_count;
+ int rid;
+
+ sc = device_get_softc(dev);
+
+ rid = 0;
+ sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->sc_mem == NULL) {
+ device_printf(dev, "Unable to allocate resources\n");
+ return (ENXIO);
+ }
+
+ typer = bus_read_4(sc->sc_mem, GICV2M_MSI_TYPER);
+ spi_start = MSI_TYPER_SPI_BASE(typer);
+ spi_count = MSI_TYPER_SPI_COUNT(typer);
+ gic_set_mbi_start(dev, spi_start);
+ gic_set_mbi_count(dev, spi_count);
+
+ intr_msi_register(dev, sc->sc_xref);
+
+ if (bootverbose)
+ device_printf(dev, "using spi %u to %u\n", spi_start,
+ spi_start + spi_count - 1);
+
+ return (0);
+}
+
+static int
+arm_gicv2m_alloc_msi(device_t dev, device_t child, int count, int maxcount,
+ device_t *pic, struct intr_irqsrc **srcs)
+{
+ return (MSI_ALLOC_MSI(device_get_parent(dev), child, count, maxcount,
+ pic, srcs));
+}
+
+static int
+arm_gicv2m_release_msi(device_t dev, device_t child, int count,
+ struct intr_irqsrc **isrc)
+{
+ return (MSI_RELEASE_MSI(device_get_parent(dev), child, count, isrc));
+}
+
+static int
+arm_gicv2m_alloc_msix(device_t dev, device_t child, device_t *pic,
+ struct intr_irqsrc **isrcp)
+{
+ return (MSI_ALLOC_MSIX(device_get_parent(dev), child, pic, isrcp));
+}
+
+static int
+arm_gicv2m_release_msix(device_t dev, device_t child, struct intr_irqsrc *isrc)
+{
+ return (MSI_RELEASE_MSIX(device_get_parent(dev), child, isrc));
+}
+
static int
arm_gicv2m_map_msi(device_t dev, device_t child, struct intr_irqsrc *isrc,
uint64_t *addr, uint32_t *data)
diff --git a/sys/arm/arm/gic_common.h b/sys/arm/arm/gic_common.h
--- a/sys/arm/arm/gic_common.h
+++ b/sys/arm/arm/gic_common.h
@@ -33,6 +33,8 @@
#define GIC_IVAR_HW_REV 500
#define GIC_IVAR_BUS 501
+#define GIC_IVAR_MBI_START 510
+#define GIC_IVAR_MBI_COUNT 511
/* GIC_IVAR_BUS values */
#define GIC_BUS_UNKNOWN 0
@@ -42,6 +44,8 @@
__BUS_ACCESSOR(gic, hw_rev, GIC, HW_REV, u_int);
__BUS_ACCESSOR(gic, bus, GIC, BUS, u_int);
+__BUS_ACCESSOR(gic, mbi_start, GIC, MBI_START, u_int);
+__BUS_ACCESSOR(gic, mbi_count, GIC, MBI_COUNT, u_int);
/* Software Generated Interrupts */
#define GIC_FIRST_SGI 0 /* Irqs 0-15 are SGIs/IPIs. */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 30, 11:26 AM (11 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17854487
Default Alt Text
D31767.diff (12 KB)
Attached To
Mode
D31767: Move the GICv2m msi handling to the parent
Attached
Detach File
Event Timeline
Log In to Comment