git: 79dd9ddb1d8c - stable/13 - Keep per-timer interrupt data together

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Mon, 15 May 2023 15:45:57 UTC
The branch stable/13 has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=79dd9ddb1d8c51c2de097d76875c5009668fa788

commit 79dd9ddb1d8c51c2de097d76875c5009668fa788
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2023-03-14 09:27:23 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2023-05-15 07:59:43 +0000

    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
    
    (cherry picked from commit b71ef90ec28fdb731733afde495ac74ae59d6196)
---
 sys/arm/arm/generic_timer.c | 118 +++++++++++++++++++++++---------------------
 1 file changed, 63 insertions(+), 55 deletions(-)

diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c
index e0ec6281e402..01ec46977a4e 100644
--- a/sys/arm/arm/generic_timer.c
+++ b/sys/arm/arm/generic_timer.c
@@ -93,9 +93,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;
@@ -104,16 +111,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;
@@ -356,6 +353,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)
@@ -433,42 +453,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);
 			}
 		}
 	}
@@ -532,18 +528,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
@@ -597,13 +604,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;
@@ -621,24 +628,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;