Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Jul 2009 09:59:32 +0200
From:      David Naylor <naylor.b.david@gmail.com>
To:        eculp <eculp@encontacto.net>
Cc:        freebsd-current <freebsd-current@freebsd.org>
Subject:   Re: Acer Laptop overheating with ACPI error that I don't understand.
Message-ID:  <200907160959.37024.naylor.b.david@gmail.com>
In-Reply-To: <20090714183503.165415zfkagwfb5w@econet.encontacto.net>
References:  <20090714183503.165415zfkagwfb5w@econet.encontacto.net>

next in thread | previous in thread | raw e-mail | index | archive | help
--nextPart2225410.334euvKaTl
Content-Type: multipart/mixed;
  boundary="Boundary-01=_k3tXK33FiTl0Q0d"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

--Boundary-01=_k3tXK33FiTl0Q0d
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

On Wednesday 15 July 2009 01:35:03 eculp wrote:
> I am having overheating problems with my Acer Aspire laptop.
> # uname -a
> FreeBSD ed.local.net.mx 8.0-BETA1 FreeBSD 8.0-BETA1 #256: Thu Jul  9
> 07:05:20 CDT 2009
> root@ed.local.net.mx:/usr/obj/usr/src/sys/ENCONTACTO  i386
>
> I've been having this problem for several months and compensating by
> reducing dev.cpu.0.freq from 1900 to 1200 and 800 in warm offices.
>
> The errors I'm seeing in the log files are:
>
> +acpi_ec0: EcRead: failed waiting to get data
> +ACPI Exception: AE_NO_HARDWARE_RESPONSE, Returned by Handler for
> [EmbeddedControl] 20090521 evregion-531
> +ACPI Error (psparse-0633): Method parse/execution failed
> [\\_TZ_.THRM._TMP] (Node 0xc4e75960), AE_NO_HARDWARE_RESPONSE
>
> I'm afraid that I don't understand them.
>
> Any suggestions appreciated,
>
> ed

A similar problem has been discussed on freebsd-acpi@.  A patch was created=
=20
that *may* help you.  Here are some of the links:

Start of discussion: http://markmail.org/message/oervuwnjmfmyqwxi
Second patch: http://markmail.org/message/yvd523kg5blvhhab

And attached for the second patch (these mail readers just love eating my=20
homework :) )

Good luck,

David

--Boundary-01=_k3tXK33FiTl0Q0d
Content-Type: text/x-diff;
  charset="iso 8859-15";
  name="acpi_ec.c.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="acpi_ec.c.diff"

=2D-- 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
=20
 /* Default delay in microseconds between each run of the status polling lo=
op. */
=2D#define EC_POLL_DELAY	5
+#define EC_POLL_DELAY	100
=20
 /* 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");
=20
=2Dstatic int	ec_burst_mode;
+static int	ec_burst_mode =3D FALSE;
 TUNABLE_INT("debug.acpi.ec.burst", &ec_burst_mode);
=2DSYSCTL_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, FA=
LSE,
     "Enable use of burst mode (faster for nearly all systems)");
=2Dstatic int	ec_polled_mode;
+static int	ec_delay =3D 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 =3D 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 =3D FALSE;
 TUNABLE_INT("debug.acpi.ec.polled", &ec_polled_mode);
=2DSYSCTL_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, =
=46ALSE,
     "Force use of polled mode (only if interrupt mode doesn't work)");
 static int	ec_timeout =3D EC_TIMEOUT;
 TUNABLE_INT("debug.acpi.ec.timeout", &ec_timeout);
@@ -794,6 +802,7 @@
     EC_STATUS ec_status;
=20
     status =3D AE_NO_HARDWARE_RESPONSE;
+
     ec_status =3D 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;
=2D    int		count, i, slp_ival;
+    int		count, i, req_ticks, cur_ticks;
=20
     ACPI_SERIAL_ASSERT(ec);
     Status =3D AE_NO_HARDWARE_RESPONSE;
     int need_poll =3D cold || rebooting || ec_polled_mode || sc->ec_suspen=
ding;
=2D    /*
=2D     * The main CPU should be much faster than the EC.  So the status sh=
ould
=2D     * be "not ready" when we start waiting.  But if the main CPU is rea=
lly
=2D     * slow, it's possible we see the current "ready" response.  Since t=
hat
=2D     * can't be distinguished from the previous response in polled mode,
=2D     * this is a potential issue.  We really should have interrupts enab=
led
=2D     * during boot so there is no ambiguity in polled mode.
=2D     *
=2D     * If this occurs, we add an additional delay before actually enteri=
ng
=2D     * the status checking loop, hopefully to allow the EC to go to work
=2D     * and produce a non-stale status.
=2D     */
=2D    if (need_poll) {
=2D	static int	once;
=2D
=2D	if (EcCheckStatus(sc, "pre-check", Event) =3D=3D AE_OK) {
=2D	    if (!once) {
=2D		device_printf(sc->ec_dev,
=2D		    "warning: EC done before starting event wait\n");
=2D		once =3D 1;
=2D	    }
=2D	    AcpiOsStall(10);
=2D	}
=2D    }
=20
     /* Wait for event by polling or GPE (interrupt). */
     if (need_poll) {
 	count =3D (ec_timeout * 1000) / EC_POLL_DELAY;
 	if (count =3D=3D 0)
 	    count =3D 1;
+
+	/* The EC is slow, give it some time to catch up to us */
+	AcpiOsStall(100);
 	for (i =3D 0; i < count; i++) {
 	    Status =3D EcCheckStatus(sc, "poll", Event);
 	    if (Status =3D=3D AE_OK)
 		break;
 	    AcpiOsStall(EC_POLL_DELAY);
 	}
+
+	if (Status !=3D AE_OK)
+	    device_printf(sc->ec_dev, "wait timed out [polling mode]\n");
     } else {
=2D	slp_ival =3D hz / 1000;
=2D	if (slp_ival !=3D 0) {
=2D	    count =3D ec_timeout;
=2D	} else {
=2D	    /* hz has less than 1 ms resolution so scale timeout. */
=2D	    slp_ival =3D 1;
=2D	    count =3D ec_timeout / (1000 / hz);
=2D	}
+	/* How many ticks should we sleep for (max) */
+	req_ticks =3D hz < 1000 ? (ec_timeout * hz) / 1000
+	    : (ec_timeout * 1000) / hz;
+	/* Make sure we sleep for at least one tick, from now */
+	cur_ticks =3D (volatile int)ticks;
+	req_ticks =3D cur_ticks + (req_ticks ? req_ticks : 1) + 1;
=20
 	/*
 	 * 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).
 	 */
=2D	for (i =3D 0; i < count; i++) {
=2D	    if (gen_count !=3D sc->ec_gencount) {
=2D		/*
=2D		 * Record new generation count.  It's possible the GPE was
=2D		 * just to notify us that a query is needed and we need to
=2D		 * wait for a second GPE to signal the completion of the
=2D		 * event we are actually waiting for.
=2D		 */
=2D		gen_count =3D sc->ec_gencount;
=2D		Status =3D EcCheckStatus(sc, "sleep", Event);
=2D		if (Status =3D=3D AE_OK)
=2D		    break;
=2D	    }
=2D	    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 =3D=3D 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 =3D sc->ec_gencount;
+	    Status =3D EcCheckStatus(sc, "sleep", Event);
+	    if (Status =3D=3D AE_OK)
+	        break;
+
+	    /* Update current tick (so we always have a consistant value */
+	    cur_ticks =3D (volatile int)ticks;
 	}
=20
 	/*
=2D	 * We finished waiting for the GPE and it never arrived.  Try to
=2D	 * read the register once and trust whatever value we got.  This is
=2D	 * the best we can do at this point.  Then, force polled mode on
=2D	 * 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 !=3D AE_OK) {
=2D	    Status =3D EcCheckStatus(sc, "sleep_end", Event);
=2D	    device_printf(sc->ec_dev,
=2D		"wait timed out (%sresponse), forcing polled mode\n",
=2D		Status =3D=3D AE_OK ? "" : "no ");
=2D	    ec_polled_mode =3D TRUE;
+	    device_printf(sc->ec_dev, "wait timed out [GPE mode]%s\n",
+		ec_gpe_mode ? "" : ", forcing polled mode");
+	    ec_polled_mode =3D TRUE && !ec_gpe_mode;
 	}
     }
     if (Status !=3D 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);
 }
=20

--Boundary-01=_k3tXK33FiTl0Q0d--

--nextPart2225410.334euvKaTl
Content-Type: application/pgp-signature; name=signature.asc 
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (FreeBSD)

iEYEABECAAYFAkpe3egACgkQUaaFgP9pFrKQkACdGnaCZLwWpuzbfJ3UNT+4Qe7k
wx4AnAvi2P+7Oa6NgRUfwIOM7gC7S0pd
=oieh
-----END PGP SIGNATURE-----

--nextPart2225410.334euvKaTl--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907160959.37024.naylor.b.david>