NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/41112: No ACPI events on HP NC4400
The following reply was made to PR kern/41112; it has been noted by GNATS.
From: Jukka Ruohonen <jruohonen%iki.fi@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc:
Subject: Re: kern/41112: No ACPI events on HP NC4400
Date: Wed, 1 Apr 2009 13:10:37 +0300
> >Fix:
> Solved; see below.
>
I was able to fix this on my own. However, the proposed solution is somewhat
major so I hope someone with more knowledge will look into this.
It seems that the ACPI _GPE-handler ends up in an infinite loop on some
laptops. The current NetBSD implementation has only one thread scheduling
all ACPI notify events. Possibly because the state of some variables is
changed during evaluation, the sysmon-queue gets polluted by repeated notify
requests. The impact is quite critical: due deadlock, no notify events will
get through, causing the _GPE-handler to block. This in turn will eventually
lead to overheating and excessive memory usage.
This behavior is documented to affect several HP laptops.[1] I think FreeBSD
tried to solve similar issue in their 'OsdSchedule.c' by having equal
priorities for OSL_GPE_HANDLER and OSL_NOTIFY_HANDLER. However, this did not
solve the issue for me. It really seems that there needs to be another
thread handling the notify events.
Thus, as a quick "hack", I duplicated the functions in 'sysmon_taskq.c' as
'sysmon_notify_*()' and enabled a separate "sysmon notify queue" in
'init_main.c'. The included diff will give some idea on how these two
separate threads could be possibly scheduled. (As said, this was not really
a serious attempt.)
[1] http://bugzilla.kernel.org/show_bug.cgi?id=5534
* * *
--- OsdSchedule.c.~1.10.~ 2009-04-01 12:05:46.000000000 +0300
+++ OsdSchedule.c 2009-04-01 12:31:22.000000000 +0300
@@ -58,6 +58,10 @@
#include <dev/sysmon/sysmon_taskq.h>
+#ifdef SYSMON_NOTIFYQ
+#include <dev/sysmon/sysmon_notifyq.h>
+#endif
+
extern int acpi_suspended;
#define _COMPONENT ACPI_OS_SERVICES
@@ -78,6 +82,11 @@
ACPI_FUNCTION_TRACE(__func__);
sysmon_task_queue_init();
+
+#ifdef SYSMON_NOTIFYQ
+ sysmon_notify_queue_init();
+#endif
+
mutex_init(&acpi_osd_sleep_mtx, MUTEX_DEFAULT, IPL_NONE);
cv_init(&acpi_osd_sleep_cv, "acpislp");
@@ -97,6 +106,10 @@
sysmon_task_queue_fini();
+#ifdef SYSMON_NOTIFYQ
+ sysmon_notify_queue_fini();
+#endif
+
return_VOID;
}
@@ -120,10 +133,13 @@
AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
void *Context)
{
- int pri;
+ int pri, rv;
+ bool notify;
ACPI_FUNCTION_TRACE(__func__);
+ notify = false;
+
switch (Type) {
case OSL_GPE_HANDLER:
pri = 10;
@@ -134,6 +150,7 @@
pri = 5;
break;
case OSL_NOTIFY_HANDLER:
+ notify = true;
pri = 3;
break;
case OSL_DEBUGGER_THREAD:
@@ -143,7 +160,17 @@
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- switch (sysmon_task_queue_sched(pri, Function, Context)) {
+#ifndef SYSMON_NOTIFYQ
+ rv = sysmon_task_queue_sched(pri, Function, Context);
+#else
+ rv = (notify != false) ?
+ sysmon_notify_queue_sched(pri, Function, Context) :
+ sysmon_task_queue_sched(pri, Function, Context);
+#endif
+
+
+ switch (rv) {
+
case 0:
return_ACPI_STATUS(AE_OK);
Home |
Main Index |
Thread Index |
Old Index