--- a/sys/dev/acpica/Osd/OsdSchedule.c +++ b/sys/dev/acpica/Osd/OsdSchedule.c @@ -71,6 +71,9 @@ static struct thread *acpi_task_td; struct lwkt_port acpi_afree_rport; +static volatile int acpi_task_pending; + +void acpi_os_wait_events_complete(void); /* * Initialize the ACPI helper thread. @@ -106,6 +109,9 @@ func = at->at_function; func(at->at_context); lwkt_replymsg(&at->at_msg, 0); + atomic_subtract_int(&acpi_task_pending, 1); + if (acpi_task_pending == 0) + wakeup(&acpi_task_pending); } lwkt_reltoken(&acpi_token); } @@ -139,8 +145,27 @@ at->at_function = Function; at->at_context = Context; at->at_type = Type; + atomic_add_int(&acpi_task_pending, 1); lwkt_sendmsg(&acpi_task_td->td_msgport, &at->at_msg); return_ACPI_STATUS (AE_OK); +} + +/* + * Real AcpiOsWaitEventsComplete (was a no-op "XXX TBI"): wait until + * every message already queued for the helper thread has been + * dispatched and replied, so a driver detach cannot free state a + * still-queued callback references (DF-2376/DF-2381/DF-2393). + */ +void +acpi_os_wait_events_complete(void) +{ + int i; + + for (i = 0; i < 120; i++) { + if (acpi_task_pending == 0) + break; + tsleep(&acpi_task_pending, 0, "acpdrn", hz / 20); + } } /* --- a/sys/contrib/dev/acpica/source/include/platform/acdragonfly.h +++ b/sys/contrib/dev/acpica/source/include/platform/acdragonfly.h @@ -217,7 +217,8 @@ /* XXX TBI */ #define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWaitEventsComplete -#define AcpiOsWaitEventsComplete() +void acpi_os_wait_events_complete(void); +#define AcpiOsWaitEventsComplete() acpi_os_wait_events_complete() #define USE_NATIVE_ALLOCATE_ZEROED