From owner-freebsd-acpi@FreeBSD.ORG Tue Jan 19 20:38:34 2010 Return-Path: Delivered-To: acpi@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 65D1A1065670 for ; Tue, 19 Jan 2010 20:38:34 +0000 (UTC) (envelope-from peter.piggybox@virgin.net) Received: from queueout02-winn.ispmail.ntl.com (queueout02-winn.ispmail.ntl.com [81.103.221.56]) by mx1.freebsd.org (Postfix) with ESMTP id DDF398FC17 for ; Tue, 19 Jan 2010 20:38:33 +0000 (UTC) Received: from know-smtpout-1.server.virginmedia.net ([62.254.123.1]) by mtaout03-winn.ispmail.ntl.com (InterMail vM.7.08.04.00 201-2186-134-20080326) with ESMTP id <20100119202417.BHYP17277.mtaout03-winn.ispmail.ntl.com@know-smtpout-1.server.virginmedia.net> for ; Tue, 19 Jan 2010 20:24:17 +0000 Received: from [81.105.213.236] (helo=ideapad.piggybox) by know-smtpout-1.server.virginmedia.net with esmtp (Exim 4.63) (envelope-from ) id 1NXKcb-0005Uh-87 for acpi@freebsd.org; Tue, 19 Jan 2010 20:24:17 +0000 Received: from ideapad.piggybox (localhost [127.0.0.1]) by ideapad.piggybox (8.14.3/8.14.3) with ESMTP id o0JKNLFD001371 for ; Tue, 19 Jan 2010 20:23:21 GMT (envelope-from peter@ideapad.piggybox) Received: (from peter@localhost) by ideapad.piggybox (8.14.3/8.14.3/Submit) id o0JKNLjY001370 for acpi@freebsd.org; Tue, 19 Jan 2010 20:23:21 GMT (envelope-from peter) Date: Tue, 19 Jan 2010 20:23:20 +0000 From: Peter Harrison To: acpi@freebsd.org Message-ID: <20100119202320.GA1311@ideapad.piggybox> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="fUYQa+Pmc3FrFX/N" Content-Disposition: inline User-Agent: Mutt/1.4.2.3i X-Cloudmark-Analysis: v=1.1 cv=1ggfb5FlKZQUfF3vzm9UBYZ2uTfLsbs/8dSljwg5+mE= c=1 sm=0 a=glaGrEw0-H8A:10 a=XJWaWzYWCtRG6mKeWUoA:9 a=ZBAaz0AXCIGBHyf3o0UA:7 a=2cbXx2w5ho2ugdpFCXZi6_n5Vp4A:4 a=Fy70mjEB83qxtY1XEKoA:9 a=-pVLZ1-B_-c4BlJ6i576sRO7u9MA:4 a=NCTbfDvCfKiAX7Mq:21 a=5RRhA-ipWWKELhen:21 a=HpAAvcLHHh0Zw7uRqdWCyQ==:117 Cc: Subject: Problem installing patched acpi... X-BeenThere: freebsd-acpi@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: ACPI and power management development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Jan 2010 20:38:34 -0000 --fUYQa+Pmc3FrFX/N Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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. --fUYQa+Pmc3FrFX/N Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="acpi_ec.c.diff.new" --- 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); } --fUYQa+Pmc3FrFX/N--