Keep per-timer interrupt data together
Eliminate a redundant resource array allow possible use by bhyve later. Reviewed by: kevans Sponsored by: Arm Ltd Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D37424
This commit is contained in:
parent
559e41a11b
commit
b71ef90ec2
@ -97,9 +97,16 @@ __FBSDID("$FreeBSD$");
|
||||
#define GT_CNTKCTL_PL0VCTEN (1 << 1) /* PL0 CNTVCT and CNTFRQ access */
|
||||
#define GT_CNTKCTL_PL0PCTEN (1 << 0) /* PL0 CNTPCT and CNTFRQ access */
|
||||
|
||||
struct arm_tmr_softc;
|
||||
|
||||
struct arm_tmr_irq {
|
||||
struct resource *res;
|
||||
void *ihl;
|
||||
int rid;
|
||||
};
|
||||
|
||||
struct arm_tmr_softc {
|
||||
struct resource *res[GT_IRQ_COUNT];
|
||||
void *ihl[GT_IRQ_COUNT];
|
||||
struct arm_tmr_irq irqs[GT_IRQ_COUNT];
|
||||
uint64_t (*get_cntxct)(bool);
|
||||
uint32_t clkfreq;
|
||||
struct eventtimer et;
|
||||
@ -108,16 +115,6 @@ struct arm_tmr_softc {
|
||||
|
||||
static struct arm_tmr_softc *arm_tmr_sc = NULL;
|
||||
|
||||
#ifdef DEV_ACPI
|
||||
static struct resource_spec timer_acpi_spec[] = {
|
||||
{ SYS_RES_IRQ, GT_PHYS_SECURE, RF_ACTIVE | RF_OPTIONAL },
|
||||
{ SYS_RES_IRQ, GT_PHYS_NONSECURE, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, GT_VIRT, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, GT_HYP_PHYS, RF_ACTIVE | RF_OPTIONAL },
|
||||
{ -1, 0 }
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct arm_tmr_irq_defs {
|
||||
int idx;
|
||||
const char *name;
|
||||
@ -402,6 +399,29 @@ arm_tmr_intr(void *arg)
|
||||
return (FILTER_HANDLED);
|
||||
}
|
||||
|
||||
static int
|
||||
arm_tmr_attach_irq(device_t dev, struct arm_tmr_softc *sc,
|
||||
const struct arm_tmr_irq_defs *irq_def, int rid, int flags)
|
||||
{
|
||||
sc->irqs[irq_def->idx].res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
|
||||
&rid, flags);
|
||||
if (sc->irqs[irq_def->idx].res == NULL) {
|
||||
if (bootverbose || (flags & RF_OPTIONAL) == 0) {
|
||||
device_printf(dev,
|
||||
"could not allocate irq for %s interrupt '%s'\n",
|
||||
(flags & RF_OPTIONAL) != 0 ? "optional" :
|
||||
"required", irq_def->name);
|
||||
}
|
||||
|
||||
if ((flags & RF_OPTIONAL) == 0)
|
||||
return (ENXIO);
|
||||
} else if (bootverbose) {
|
||||
device_printf(dev, "allocated irq for '%s'\n", irq_def->name);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef FDT
|
||||
static int
|
||||
arm_tmr_fdt_probe(device_t dev)
|
||||
@ -479,42 +499,18 @@ arm_tmr_fdt_attach(device_t dev)
|
||||
flags &= ~RF_OPTIONAL;
|
||||
}
|
||||
|
||||
sc->res[irq_def->idx] = bus_alloc_resource_any(dev,
|
||||
SYS_RES_IRQ, &rid, flags);
|
||||
|
||||
if (sc->res[irq_def->idx] == NULL) {
|
||||
device_printf(dev,
|
||||
"could not allocate irq for %s interrupt '%s'\n",
|
||||
(flags & RF_OPTIONAL) != 0 ? "optional" :
|
||||
"required", irq_def->name);
|
||||
|
||||
if ((flags & RF_OPTIONAL) == 0) {
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bootverbose) {
|
||||
device_printf(dev,
|
||||
"allocated irq for '%s'\n", irq_def->name);
|
||||
}
|
||||
error = arm_tmr_attach_irq(dev, sc, irq_def, rid, flags);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = arm_tmr_attach(dev);
|
||||
out:
|
||||
if (error != 0) {
|
||||
for (i = 0; i < GT_IRQ_COUNT; i++) {
|
||||
if (sc->res[i] != NULL) {
|
||||
/*
|
||||
* rid may not match the index into sc->res in
|
||||
* a number of cases; e.g., optional sec-phys or
|
||||
* interrupt-names specifying them in a
|
||||
* different order than expected.
|
||||
*/
|
||||
if (sc->irqs[i].res != NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
rman_get_rid(sc->res[i]), sc->res[i]);
|
||||
sc->irqs[i].rid, sc->irqs[i].res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -578,18 +574,29 @@ arm_tmr_acpi_probe(device_t dev)
|
||||
static int
|
||||
arm_tmr_acpi_attach(device_t dev)
|
||||
{
|
||||
const struct arm_tmr_irq_defs *irq_def;
|
||||
struct arm_tmr_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
if (bus_alloc_resources(dev, timer_acpi_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
for (int i = 0; i < nitems(arm_tmr_irq_defs); i++) {
|
||||
irq_def = &arm_tmr_irq_defs[i];
|
||||
error = arm_tmr_attach_irq(dev, sc, irq_def, irq_def->idx,
|
||||
irq_def->flags);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = arm_tmr_attach(dev);
|
||||
if (error != 0)
|
||||
bus_release_resources(dev, timer_acpi_spec, sc->res);
|
||||
out:
|
||||
if (error != 0) {
|
||||
for (int i = 0; i < GT_IRQ_COUNT; i++) {
|
||||
if (sc->irqs[i].res != NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
sc->irqs[i].rid, sc->irqs[i].res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
@ -643,13 +650,13 @@ arm_tmr_attach(device_t dev)
|
||||
for (i = 0; i < nitems(arm_tmr_irq_defs); i++) {
|
||||
irq_def = &arm_tmr_irq_defs[i];
|
||||
|
||||
MPASS(sc->res[irq_def->idx] != NULL ||
|
||||
MPASS(sc->irqs[irq_def->idx].res != NULL ||
|
||||
(irq_def->flags & RF_OPTIONAL) != 0);
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
/* Use the virtual timer if we have one. */
|
||||
if (sc->res[GT_VIRT] != NULL) {
|
||||
if (sc->irqs[GT_VIRT].res != NULL) {
|
||||
sc->physical = false;
|
||||
first_timer = GT_VIRT;
|
||||
last_timer = GT_VIRT;
|
||||
@ -667,24 +674,25 @@ arm_tmr_attach(device_t dev)
|
||||
/* Setup secure, non-secure and virtual IRQs handler */
|
||||
for (i = first_timer; i <= last_timer; i++) {
|
||||
/* If we do not have the interrupt, skip it. */
|
||||
if (sc->res[i] == NULL)
|
||||
if (sc->irqs[i].res == NULL)
|
||||
continue;
|
||||
error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK,
|
||||
arm_tmr_intr, NULL, sc, &sc->ihl[i]);
|
||||
error = bus_setup_intr(dev, sc->irqs[i].res, INTR_TYPE_CLK,
|
||||
arm_tmr_intr, NULL, sc, &sc->irqs[i].ihl);
|
||||
if (error) {
|
||||
device_printf(dev, "Unable to alloc int resource.\n");
|
||||
for (int j = first_timer; j < i; j++)
|
||||
bus_teardown_intr(dev, sc->res[j], &sc->ihl[j]);
|
||||
bus_teardown_intr(dev, sc->irqs[j].res,
|
||||
&sc->irqs[j].ihl);
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the virtual timer until we are ready */
|
||||
if (sc->res[GT_VIRT] != NULL)
|
||||
if (sc->irqs[GT_VIRT].res != NULL)
|
||||
arm_tmr_disable(false);
|
||||
/* And the physical */
|
||||
if ((sc->res[GT_PHYS_SECURE] != NULL ||
|
||||
sc->res[GT_PHYS_NONSECURE] != NULL) && HAS_PHYS)
|
||||
if ((sc->irqs[GT_PHYS_SECURE].res != NULL ||
|
||||
sc->irqs[GT_PHYS_NONSECURE].res != NULL) && HAS_PHYS)
|
||||
arm_tmr_disable(true);
|
||||
|
||||
arm_tmr_timecount.tc_frequency = sc->clkfreq;
|
||||
|
Loading…
Reference in New Issue
Block a user