Module Name:    src
Committed By:   riastradh
Date:           Fri Dec 31 14:22:42 UTC 2021

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

Log Message:
acpi(9): Fix memory ordering and completion bugs in notifiers.

1. Guarantee everything which happened before acpi_register_notify
   has also happened before the notifier is actually called.

2. On acpi_deregister_notify, don't return until the notifier is
   definitely not running any more on any CPU, using
   AcpiOsWaitEventsComplete.


To generate a diff of this commit:
cvs rdiff -u -r1.294 -r1.295 src/sys/dev/acpi/acpi.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.c
diff -u src/sys/dev/acpi/acpi.c:1.294 src/sys/dev/acpi/acpi.c:1.295
--- src/sys/dev/acpi/acpi.c:1.294	Mon Dec 20 11:17:40 2021
+++ src/sys/dev/acpi/acpi.c	Fri Dec 31 14:22:42 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpi.c,v 1.294 2021/12/20 11:17:40 skrll Exp $	*/
+/*	$NetBSD: acpi.c,v 1.295 2021/12/31 14:22:42 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@@ -100,13 +100,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.294 2021/12/20 11:17:40 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.295 2021/12/31 14:22:42 riastradh Exp $");
 
 #include "pci.h"
 #include "opt_acpi.h"
 #include "opt_pcifixup.h"
 
 #include <sys/param.h>
+#include <sys/atomic.h>
 #include <sys/device.h>
 #include <sys/kernel.h>
 #include <sys/kmem.h>
@@ -1146,6 +1147,7 @@ acpi_notify_handler(ACPI_HANDLE handle, 
 {
 	struct acpi_softc *sc = acpi_softc;
 	struct acpi_devnode *ad;
+	ACPI_NOTIFY_HANDLER notify;
 
 	KASSERT(sc != NULL);
 	KASSERT(aux == NULL);
@@ -1189,13 +1191,13 @@ acpi_notify_handler(ACPI_HANDLE handle, 
 		if (ad->ad_device == NULL)
 			continue;
 
-		if (ad->ad_notify == NULL)
+		if ((notify = atomic_load_acquire(&ad->ad_notify)) == NULL)
 			continue;
 
 		if (ad->ad_handle != handle)
 			continue;
 
-		(*ad->ad_notify)(ad->ad_handle, event, ad->ad_device);
+		(*notify)(ad->ad_handle, event, ad->ad_device);
 
 		return;
 	}
@@ -1218,7 +1220,7 @@ acpi_register_notify(struct acpi_devnode
 	if (ad == NULL || notify == NULL)
 		goto fail;
 
-	ad->ad_notify = notify;
+	atomic_store_release(&ad->ad_notify, notify);
 
 	return true;
 
@@ -1233,7 +1235,10 @@ void
 acpi_deregister_notify(struct acpi_devnode *ad)
 {
 
-	ad->ad_notify = NULL;
+	atomic_store_relaxed(&ad->ad_notify, NULL);
+
+	/* Wait for any in-flight calls to the notifier to complete.  */
+	AcpiOsWaitEventsComplete();
 }
 
 /*

Reply via email to