Problem installing patched acpi...
Peter Harrison
peter.piggybox at virgin.net
Tue Jan 19 20:38:34 UTC 2010
Hi list,
I'm running FreeBSD on a Lenovo S10e - successfully in the main on 7.2-RELEASE. The biggest issue was with the acpi, where it spams /var/log/messages continually (ie. several times a second):
Jan 19 20:14:32 ideapad kernel: ACPI Error (psparse-0633): Method parse/execution failed [\_TZ_.TZ00._TMP] (Node 0xc46c39a0), AE_NOT_EXIST
Jan 19 20:14:42 ideapad kernel: ACPI Error: No handler for Region [ERAM] (0xc46c5780) [EmbeddedControl] 20090521 evregion-430
Jan 19 20:14:42 ideapad kernel: ACPI Error: Region EmbeddedControl(3) has no handler 20090521 exfldio-382
Jan 19 20:14:42 ideapad kernel: ACPI Error (psparse-0633): Method parse/execution failed [\_TZ_.TZ00._TMP] (Node 0xc46c39a0), AE_NOT_EXIST
David Naylor on this list gave me the attached patch for acpi_ec.c which worked around this on 7.2-R, and which he told me applied OK to the then 8-CURRENT too.
I've now moved to 8.0-RELEASE and the patch still applies cleanly (cd /usr/src/sys/dev/acpica && patch < ~/acpi_ec.c.diff).
I can then rebuild acpi.ko (make clean; make depend; make; make install) successfully.
But it seems not to be included on boot - ie. I don't get the new sysctls and I still get the acpi errors in /var/log/messages.
What's changed in 8? Can anyone offer me some advice on how to resolve this?
Please copy me in as I'm not subscribed, and thanks for your help.
Peter Harrison.
-------------- next part --------------
--- acpi_ec.c~ 2009-06-17 21:14:48.000000000 +0200
+++ acpi_ec.c 2009-06-19 14:40:02.000000000 +0200
@@ -168,7 +168,7 @@
#define EC_LOCK_TIMEOUT 1000
/* Default delay in microseconds between each run of the status polling loop. */
-#define EC_POLL_DELAY 5
+#define EC_POLL_DELAY 100
/* Total time in ms spent waiting for a response from EC. */
#define EC_TIMEOUT 750
@@ -184,13 +184,21 @@
SYSCTL_DECL(_debug_acpi);
SYSCTL_NODE(_debug_acpi, OID_AUTO, ec, CTLFLAG_RD, NULL, "EC debugging");
-static int ec_burst_mode;
+static int ec_burst_mode = FALSE;
TUNABLE_INT("debug.acpi.ec.burst", &ec_burst_mode);
-SYSCTL_INT(_debug_acpi_ec, OID_AUTO, burst, CTLFLAG_RW, &ec_burst_mode, 0,
+SYSCTL_INT(_debug_acpi_ec, OID_AUTO, burst, CTLFLAG_RW, &ec_burst_mode, FALSE,
"Enable use of burst mode (faster for nearly all systems)");
-static int ec_polled_mode;
+static int ec_delay = 0;
+TUNABLE_INT("debug.acpi.ec.delay", &ec_delay);
+SYSCTL_INT(_debug_acpi_ec, OID_AUTO, delay, CTLFLAG_RW, &ec_delay, 0,
+ "Delay after waiting for responce (GPE and polled mode)");
+static int ec_gpe_mode = FALSE;
+TUNABLE_INT("debug.acpi.ec.gpe", &ec_gpe_mode);
+SYSCTL_INT(_debug_acpi_ec, OID_AUTO, gpe, CTLFLAG_RW, &ec_gpe_mode, FALSE,
+ "Disable adaptive GPE switching (to polled mode)");
+static int ec_polled_mode = FALSE;
TUNABLE_INT("debug.acpi.ec.polled", &ec_polled_mode);
-SYSCTL_INT(_debug_acpi_ec, OID_AUTO, polled, CTLFLAG_RW, &ec_polled_mode, 0,
+SYSCTL_INT(_debug_acpi_ec, OID_AUTO, polled, CTLFLAG_RW, &ec_polled_mode, FALSE,
"Force use of polled mode (only if interrupt mode doesn't work)");
static int ec_timeout = EC_TIMEOUT;
TUNABLE_INT("debug.acpi.ec.timeout", &ec_timeout);
@@ -794,6 +802,7 @@
EC_STATUS ec_status;
status = AE_NO_HARDWARE_RESPONSE;
+
ec_status = EC_GET_CSR(sc);
if (sc->ec_burstactive && !(ec_status & EC_FLAG_BURST_MODE)) {
CTR1(KTR_ACPI, "ec burst disabled in waitevent (%s)", msg);
@@ -810,56 +819,36 @@
EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event, u_int gen_count)
{
ACPI_STATUS Status;
- int count, i, slp_ival;
+ int count, i, req_ticks, cur_ticks;
ACPI_SERIAL_ASSERT(ec);
Status = AE_NO_HARDWARE_RESPONSE;
int need_poll = cold || rebooting || ec_polled_mode || sc->ec_suspending;
- /*
- * The main CPU should be much faster than the EC. So the status should
- * be "not ready" when we start waiting. But if the main CPU is really
- * slow, it's possible we see the current "ready" response. Since that
- * can't be distinguished from the previous response in polled mode,
- * this is a potential issue. We really should have interrupts enabled
- * during boot so there is no ambiguity in polled mode.
- *
- * If this occurs, we add an additional delay before actually entering
- * the status checking loop, hopefully to allow the EC to go to work
- * and produce a non-stale status.
- */
- if (need_poll) {
- static int once;
-
- if (EcCheckStatus(sc, "pre-check", Event) == AE_OK) {
- if (!once) {
- device_printf(sc->ec_dev,
- "warning: EC done before starting event wait\n");
- once = 1;
- }
- AcpiOsStall(10);
- }
- }
/* Wait for event by polling or GPE (interrupt). */
if (need_poll) {
count = (ec_timeout * 1000) / EC_POLL_DELAY;
if (count == 0)
count = 1;
+
+ /* The EC is slow, give it some time to catch up to us */
+ AcpiOsStall(100);
for (i = 0; i < count; i++) {
Status = EcCheckStatus(sc, "poll", Event);
if (Status == AE_OK)
break;
AcpiOsStall(EC_POLL_DELAY);
}
+
+ if (Status != AE_OK)
+ device_printf(sc->ec_dev, "wait timed out [polling mode]\n");
} else {
- slp_ival = hz / 1000;
- if (slp_ival != 0) {
- count = ec_timeout;
- } else {
- /* hz has less than 1 ms resolution so scale timeout. */
- slp_ival = 1;
- count = ec_timeout / (1000 / hz);
- }
+ /* How many ticks should we sleep for (max) */
+ req_ticks = hz < 1000 ? (ec_timeout * hz) / 1000
+ : (ec_timeout * 1000) / hz;
+ /* Make sure we sleep for at least one tick, from now */
+ cur_ticks = (volatile int)ticks;
+ req_ticks = cur_ticks + (req_ticks ? req_ticks : 1) + 1;
/*
* Wait for the GPE to signal the status changed, checking the
@@ -867,38 +856,42 @@
* GPE for an event we're not interested in here (i.e., SCI for
* EC query).
*/
- for (i = 0; i < count; i++) {
- if (gen_count != sc->ec_gencount) {
- /*
- * Record new generation count. It's possible the GPE was
- * just to notify us that a query is needed and we need to
- * wait for a second GPE to signal the completion of the
- * event we are actually waiting for.
- */
- gen_count = sc->ec_gencount;
- Status = EcCheckStatus(sc, "sleep", Event);
- if (Status == AE_OK)
- break;
- }
- tsleep(&sc->ec_gencount, PZERO, "ecgpe", slp_ival);
+ while ((int)(req_ticks - cur_ticks) > 0) {
+ /* If we have not received a signal then wait for one */
+ if (gen_count == sc->ec_gencount)
+ tsleep(&sc->ec_gencount, PZERO, "ecgpe", req_ticks - cur_ticks);
+
+ /*
+ * Record new generation count. It's possible the GPE was
+ * just to notify us that a query is needed and we need to
+ * wait for a second GPE to signal the completion of the
+ * event we are actually waiting for.
+ */
+ gen_count = sc->ec_gencount;
+ Status = EcCheckStatus(sc, "sleep", Event);
+ if (Status == AE_OK)
+ break;
+
+ /* Update current tick (so we always have a consistant value */
+ cur_ticks = (volatile int)ticks;
}
/*
- * We finished waiting for the GPE and it never arrived. Try to
- * read the register once and trust whatever value we got. This is
- * the best we can do at this point. Then, force polled mode on
- * since this system doesn't appear to generate GPEs.
+ * We finished waiting for the GPE and it never arrived. The register
+ * has been read on a timeout so no need to re-read it. Force polled
+ * mode on since this system doesn't appear to generate GPEs.
*/
if (Status != AE_OK) {
- Status = EcCheckStatus(sc, "sleep_end", Event);
- device_printf(sc->ec_dev,
- "wait timed out (%sresponse), forcing polled mode\n",
- Status == AE_OK ? "" : "no ");
- ec_polled_mode = TRUE;
+ device_printf(sc->ec_dev, "wait timed out [GPE mode]%s\n",
+ ec_gpe_mode ? "" : ", forcing polled mode");
+ ec_polled_mode = TRUE && !ec_gpe_mode;
}
}
if (Status != AE_OK)
CTR0(KTR_ACPI, "error: ec wait timed out");
+ else if (ec_delay);
+ /* Give the EC a chance to recover from all its hard work!!! */
+ AcpiOsStall(ec_delay);
return (Status);
}
More information about the freebsd-acpi
mailing list