Module Name:    src
Committed By:   riastradh
Date:           Fri Jan  7 01:10:58 UTC 2022

Modified Files:
        src/sys/dev/acpi: acpi_bat.c

Log Message:
acpibat(4): Fix race in detach with AcpiOsExecute deferred call.


To generate a diff of this commit:
cvs rdiff -u -r1.120 -r1.121 src/sys/dev/acpi/acpi_bat.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/acpi/acpi_bat.c
diff -u src/sys/dev/acpi/acpi_bat.c:1.120 src/sys/dev/acpi/acpi_bat.c:1.121
--- src/sys/dev/acpi/acpi_bat.c:1.120	Fri Dec 31 14:20:56 2021
+++ src/sys/dev/acpi/acpi_bat.c	Fri Jan  7 01:10:57 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpi_bat.c,v 1.120 2021/12/31 14:20:56 riastradh Exp $	*/
+/*	$NetBSD: acpi_bat.c,v 1.121 2022/01/07 01:10:57 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -75,7 +75,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.120 2021/12/31 14:20:56 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_bat.c,v 1.121 2022/01/07 01:10:57 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/condvar.h>
@@ -157,6 +157,7 @@ struct acpibat_softc {
 	int32_t			 sc_lcapacity;
 	int32_t			 sc_wcapacity;
 	int                      sc_present;
+	bool			 sc_dying;
 };
 
 static const struct device_compatible_entry compat_data[] = {
@@ -262,12 +263,29 @@ acpibat_detach(device_t self, int flags)
 {
 	struct acpibat_softc *sc = device_private(self);
 
+	/* Prevent further use of sc->sc_sme in acpibat_update_info.  */
+	mutex_enter(&sc->sc_mutex);
+	sc->sc_dying = true;
+	mutex_exit(&sc->sc_mutex);
+
+	/* Prevent further calls to acpibat_resume.  */
 	pmf_device_deregister(self);
+
+	/* Prevent further calls to acpibat_notify_handler.  */
 	acpi_deregister_notify(sc->sc_node);
 
+	/* Detach sensors and prevent further calls to acpibat_refresh. */
 	if (sc->sc_sme != NULL)
 		sysmon_envsys_unregister(sc->sc_sme);
 
+	/*
+	 * Wait for calls to acpibat_update_info/status in case sysmon
+	 * envsys refreshed the sensors and queued them but they didn't
+	 * run before sysmon_envsys_unregister.  After this point, no
+	 * asynchronous access to the softc is possible.
+	 */
+	AcpiOsWaitEventsComplete();
+
 	if (sc->sc_sensor != NULL)
 		kmem_free(sc->sc_sensor, ACPIBAT_COUNT *
 		    sizeof(*sc->sc_sensor));
@@ -599,6 +617,10 @@ acpibat_update_info(void *arg)
 
 	mutex_enter(&sc->sc_mutex);
 
+	/* Don't touch sc_sme if we're detaching.  */
+	if (sc->sc_dying)
+		goto out;
+
 	rv = acpibat_get_sta(dv);
 	if (rv > 0) {
 		acpibat_get_info(dv);
@@ -619,7 +641,7 @@ acpibat_update_info(void *arg)
 	}
 
 	sc->sc_present = rv;
-
+out:
 	mutex_exit(&sc->sc_mutex);
 }
 

Reply via email to