git: e0d2f27825ff - stable/15 - acpi_timer: Add a softc to avoid use of global variables

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 08 Oct 2026 20:44:22 UTC
The branch stable/15 has been updated by jhb:

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

commit e0d2f27825ff6a21da4948177ce4f5f3de343931
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2026-09-30 16:04:59 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2026-10-08 20:42:33 +0000

    acpi_timer: Add a softc to avoid use of global variables
    
    Add a softc and use it to mostly replace the use of global variables
    in this driver.  Simplify the suspend and resume event handlers by
    saving the old timecounter in the softc and passing the softc pointer
    to the handlers.
    
    Differential Revision:  https://reviews.freebsd.org/D59936
    
    (cherry picked from commit 34cf45a93c54ee9a222d2893b97832283a850715)
---
 sys/dev/acpica/acpi_timer.c | 116 ++++++++++++++++++++++++--------------------
 1 file changed, 64 insertions(+), 52 deletions(-)

diff --git a/sys/dev/acpica/acpi_timer.c b/sys/dev/acpica/acpi_timer.c
index c6d015388f2a..dc9e20fd4a8a 100644
--- a/sys/dev/acpica/acpi_timer.c
+++ b/sys/dev/acpica/acpi_timer.c
@@ -55,17 +55,20 @@
 #define _COMPONENT	ACPI_TIMER
 ACPI_MODULE_NAME("TIMER")
 
-static device_t			acpi_timer_dev;
-static struct resource		*acpi_timer_reg;
-static eventhandler_tag		acpi_timer_eh;
+struct acpi_timer_softc {
+	device_t	dev;
+	struct resource *reg;
+	struct timecounter *tc;
+	struct timecounter *old_tc;
+};
 
 #define	ACPI_TIMER_FREQUENCY	(14318182 / 4)
 
 static void	acpi_timer_identify(driver_t *driver, device_t parent);
 static int	acpi_timer_probe(device_t dev);
 static int	acpi_timer_attach(device_t dev);
-static void	acpi_timer_resume_handler(struct timecounter *);
-static void	acpi_timer_suspend_handler(struct timecounter *);
+static void	acpi_timer_resume_handler(struct acpi_timer_softc *);
+static void	acpi_timer_suspend_handler(struct acpi_timer_softc *);
 static u_int	acpi_timer_get_timecount(struct timecounter *tc);
 static int	acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS);
 
@@ -80,7 +83,7 @@ static device_method_t acpi_timer_methods[] = {
 static driver_t acpi_timer_driver = {
     "acpi_timer",
     acpi_timer_methods,
-    0,
+    sizeof(struct acpi_timer_softc),
 };
 
 DRIVER_MODULE(acpi_timer, acpi, acpi_timer_driver, 0, 0);
@@ -97,10 +100,10 @@ static struct timecounter acpi_timer_timecounter = {
 };
 
 static __inline uint32_t
-acpi_timer_read(void)
+acpi_timer_read(struct acpi_timer_softc *sc)
 {
 
-	return (bus_read_4(acpi_timer_reg, 0));
+	return (bus_read_4(sc->reg, 0));
 }
 
 /*
@@ -117,14 +120,14 @@ acpi_timer_identify(driver_t *driver, device_t parent)
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
     if (acpi_disabled("timer") || (acpi_quirks & ACPI_Q_TIMER) ||
-	acpi_timer_dev || AcpiGbl_FADT.PmTimerLength == 0)
+	device_find_child(parent, "acpi_timer", DEVICE_UNIT_ANY) != NULL ||
+	AcpiGbl_FADT.PmTimerLength == 0)
 	return_VOID;
 
     if ((dev = BUS_ADD_CHILD(parent, 2, "acpi_timer", 0)) == NULL) {
 	device_printf(parent, "could not add acpi_timer0\n");
 	return_VOID;
     }
-    acpi_timer_dev = dev;
 
     switch (AcpiGbl_FADT.XPmTimerBlock.SpaceId) {
     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
@@ -149,22 +152,22 @@ acpi_timer_probe(device_t dev)
 {
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
-    if (dev != acpi_timer_dev)
-	return (ENXIO);
-
     device_set_descf(dev, "%d-bit timer at %u.%06uMHz",
 	(AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) != 0 ? 32 : 24,
 	ACPI_TIMER_FREQUENCY / 1000000, ACPI_TIMER_FREQUENCY % 1000000);
-    return (0);
+    return (BUS_PROBE_NOWILDCARD);
 }
 
 static int
 acpi_timer_attach(device_t dev)
 {
+    struct acpi_timer_softc *sc = device_get_softc(dev);
+    eventhandler_tag eh;
     int rtype;
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
+    sc->dev = dev;
     switch (AcpiGbl_FADT.XPmTimerBlock.SpaceId) {
     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
 	rtype = SYS_RES_MEMORY;
@@ -175,15 +178,24 @@ acpi_timer_attach(device_t dev)
     default:
 	return (ENXIO);
     }
-    acpi_timer_reg = bus_alloc_resource_any(dev, rtype, 0, RF_ACTIVE);
-    if (acpi_timer_reg == NULL)
+
+    sc->reg = bus_alloc_resource_any(dev, rtype, 0, RF_ACTIVE);
+    if (sc->reg == NULL)
 	return (ENXIO);
 
-    /* Register suspend event handler. */
-    if (EVENTHANDLER_REGISTER(power_suspend, acpi_timer_suspend_handler,
-	&acpi_timer_timecounter, EVENTHANDLER_PRI_LAST) == NULL) {
+    /* Register resume and suspend event handlers. */
+    eh = EVENTHANDLER_REGISTER(power_suspend, acpi_timer_suspend_handler,
+	sc, EVENTHANDLER_PRI_LAST);
+    if (eh == NULL) {
 	device_printf(dev, "failed to register suspend event handler\n");
-	bus_release_resource(dev, acpi_timer_reg);
+	bus_release_resource(dev, sc->reg);
+	return (ENXIO);
+    }
+    if (EVENTHANDLER_REGISTER(power_resume, acpi_timer_resume_handler,
+	sc, EVENTHANDLER_PRI_LAST) == NULL) {
+	device_printf(dev, "failed to register resume event handler\n");
+	EVENTHANDLER_DEREGISTER(power_suspend, eh);
+	bus_release_resource(dev, sc->reg);
 	return (ENXIO);
     }
 
@@ -192,25 +204,29 @@ acpi_timer_attach(device_t dev)
     else
 	acpi_timer_timecounter.tc_counter_mask = 0x00ffffff;
     acpi_timer_timecounter.tc_frequency = ACPI_TIMER_FREQUENCY;
+    acpi_timer_timecounter.tc_priv = sc;
+    sc->tc = &acpi_timer_timecounter;
 
-    tc_init(&acpi_timer_timecounter);
+    tc_init(sc->tc);
 
     SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_machdep), OID_AUTO,
 	"acpi_timer_freq", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
-	NULL, 0, acpi_timer_sysctl_freq, "I", "ACPI timer frequency");
+	sc->tc, 0, acpi_timer_sysctl_freq, "I", "ACPI timer frequency");
 
     return (0);
 }
 
 static void
-acpi_timer_resume_handler(struct timecounter *newtc)
+acpi_timer_resume_handler(struct acpi_timer_softc *sc)
 {
-	struct timecounter *tc;
+	struct timecounter *newtc, *tc;
 
 	tc = timecounter;
-	if (tc != newtc) {
+	newtc = sc->old_tc;
+	sc->old_tc = NULL;
+	if (newtc != NULL && tc != newtc) {
 		if (bootverbose)
-			device_printf(acpi_timer_dev,
+			device_printf(sc->dev,
 			    "restoring timecounter, %s -> %s\n",
 			    tc->tc_name, newtc->tc_name);
 		(void)newtc->tc_get_timecount(newtc);
@@ -219,17 +235,13 @@ acpi_timer_resume_handler(struct timecounter *newtc)
 }
 
 static void
-acpi_timer_suspend_handler(struct timecounter *newtc)
+acpi_timer_suspend_handler(struct acpi_timer_softc *sc)
 {
 	struct timecounter *tc;
 
-	/* Deregister existing resume event handler. */
-	if (acpi_timer_eh != NULL) {
-		EVENTHANDLER_DEREGISTER(power_resume, acpi_timer_eh);
-		acpi_timer_eh = NULL;
-	}
-
-	if ((timecounter->tc_flags & TC_FLAGS_SUSPEND_SAFE) != 0) {
+	tc = timecounter;
+	sc->old_tc = NULL;
+	if ((tc->tc_flags & TC_FLAGS_SUSPEND_SAFE) != 0) {
 		/*
 		 * If we are using a suspend safe timecounter, don't
 		 * save/restore it across suspend/resume.
@@ -237,27 +249,26 @@ acpi_timer_suspend_handler(struct timecounter *newtc)
 		return;
 	}
 
-	KASSERT(newtc == &acpi_timer_timecounter,
-	    ("acpi_timer_suspend_handler: wrong timecounter"));
-
-	tc = timecounter;
-	if (tc != newtc) {
-		if (bootverbose)
-			device_printf(acpi_timer_dev,
-			    "switching timecounter, %s -> %s\n",
-			    tc->tc_name, newtc->tc_name);
-		(void)acpi_timer_read();
-		(void)acpi_timer_read();
-		timecounter = newtc;
-		acpi_timer_eh = EVENTHANDLER_REGISTER(power_resume,
-		    acpi_timer_resume_handler, tc, EVENTHANDLER_PRI_LAST);
-	}
+	/*
+	  * Our timecounter is suspend safe, so must not be currently
+	  * active.
+	  */
+	MPASS(tc != sc->tc);
+
+	if (bootverbose)
+		device_printf(sc->dev, "switching timecounter, %s -> %s\n",
+		    tc->tc_name, sc->tc->tc_name);
+	(void)acpi_timer_read(sc);
+	(void)acpi_timer_read(sc);
+	timecounter = sc->tc;
+	sc->old_tc = tc;
 }
 
 static u_int
 acpi_timer_get_timecount(struct timecounter *tc)
 {
-    return (acpi_timer_read());
+	struct acpi_timer_softc *sc = tc->tc_priv;
+	return (acpi_timer_read(sc));
 }
 
 /*
@@ -266,13 +277,14 @@ acpi_timer_get_timecount(struct timecounter *tc)
 static int
 acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS)
 {
+    struct timecounter *tc = arg1;
     int error;
     u_int freq;
 
-    freq = acpi_timer_timecounter.tc_frequency;
+    freq = tc->tc_frequency;
     error = sysctl_handle_int(oidp, &freq, 0, req);
     if (error == 0 && req->newptr != NULL) {
-	acpi_timer_timecounter.tc_frequency = freq;
+	tc->tc_frequency = freq;
     }
 
     return (error);