Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Jun 2004 12:49:18 -0700 (PDT)
From:      Nate Lawson <nate@root.org>
To:        Andrew Thompson <andy@fud.org.nz>
Cc:        brooks@freebsd.org
Subject:   Re: AE_NO_HARDWARE_RESPONSE problems
Message-ID:  <20040630124817.M41697@root.org>
In-Reply-To: <20040628220257.GA21946@thingy.tbd.co.nz>
References:  <20040628004724.GA4071@fire.masaclaw.co.nz> <20040628124854.X27408@root.org> <20040628220257.GA21946@thingy.tbd.co.nz>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 29 Jun 2004, Andrew Thompson wrote:
> On Mon, Jun 28, 2004 at 01:44:47PM -0700, Nate Lawson wrote:
> > On Mon, 28 Jun 2004, Andrew Thompson wrote:
> > > On my HP Omnibook 6000 I get the following right after boot
> > >
> > > etc... I changed the loop on line 829 of acpi_ec.c from 1000 to 10000 and
> > > everything seems to be working fine. Is this a valid fix or will it cause
> > > problems elsewhere? One issue I can see is holding Giant for this length of
> > > time.
> > >
> >
> > Try the code I just committed instead.
> >
>
> It doesnt seem to have changed. Here is the tail of the dmesg, link to
> full one below. Thanks.

Ok, I think I found one other problem.  Please try this patch (booted,
tested):

Index: sys/dev/acpica/acpi_ec.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi_ec.c,v
retrieving revision 1.55
diff -u -r1.55 acpi_ec.c
--- sys/dev/acpica/acpi_ec.c	30 Jun 2004 16:00:20 -0000	1.55
+++ sys/dev/acpica/acpi_ec.c	30 Jun 2004 12:36:04 -0000
@@ -142,9 +142,10 @@
 #include "opt_acpi.h"
 #include <sys/param.h>
 #include <sys/kernel.h>
-#include <sys/module.h>
 #include <sys/bus.h>
 #include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/sx.h>

 #include <machine/bus.h>
 #include <machine/resource.h>
@@ -269,8 +270,7 @@

     int			ec_glk;
     int			ec_glkhandle;
-    struct mtx		ec_mtx;
-    int			ec_polldelay;
+    struct sx		ec_sxlock;
 };

 /*
@@ -280,11 +280,8 @@
  */
 #define EC_LOCK_TIMEOUT	1000

-/*
- * Start with an interval of 1 us for status poll loop.  This delay
- * will be dynamically adjusted based on the actual time waited.
- */
-#define EC_POLL_DELAY	1
+/* Default interval in microseconds for the status polling loop. */
+#define EC_POLL_DELAY	10

 /* Total time in ms spent in the poll loop waiting for a response. */
 #define EC_POLL_TIMEOUT	100
@@ -304,13 +301,13 @@
     ACPI_STATUS	status = AE_OK;

     /* Always acquire this EC's mutex. */
-    mtx_lock(&sc->ec_mtx);
+    sx_xlock(&sc->ec_sxlock);

     /* If _GLK is non-zero, also acquire the global lock. */
     if (sc->ec_glk) {
 	status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
 	if (ACPI_FAILURE(status))
-	    mtx_unlock(&sc->ec_mtx);
+	    sx_xunlock(&sc->ec_sxlock);
     }

     return (status);
@@ -321,7 +318,7 @@
 {
     if (sc->ec_glk)
 	AcpiReleaseGlobalLock(sc->ec_glkhandle);
-    mtx_unlock(&sc->ec_mtx);
+    sx_xunlock(&sc->ec_sxlock);
 }

 static uint32_t		EcGpeHandler(void *Context);
@@ -553,8 +550,7 @@
     params = acpi_get_private(dev);
     sc->ec_dev = dev;
     sc->ec_handle = acpi_get_handle(dev);
-    sc->ec_polldelay = EC_POLL_DELAY;
-    mtx_init(&sc->ec_mtx, "ACPI embedded controller", NULL, MTX_DEF);
+    sx_init(&sc->ec_sxlock, "ACPI embedded controller");

     /* Retrieve previously probed values via device ivars. */
     sc->ec_glk = params->glk;
@@ -637,7 +633,7 @@
     if (sc->ec_data_res)
 	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
 			     sc->ec_data_res);
-    mtx_destroy(&sc->ec_mtx);
+    sx_destroy(&sc->ec_sxlock);
     return (ENXIO);
 }

@@ -823,10 +819,10 @@
 {
     EC_STATUS	EcStatus;
     ACPI_STATUS	Status;
-    int		i, period, retval;
+    int		count, i, period, retval, slp_ival;
     static int	EcDbgMaxDelay;

-    mtx_assert(&sc->ec_mtx, MA_OWNED);
+    sx_assert(&sc->ec_sxlock, SX_XLOCKED);
     Status = AE_NO_HARDWARE_RESPONSE;

     /*
@@ -837,44 +833,33 @@
     AcpiOsStall(1);

     /*
-     * If we're up and running, wait up to 1 ms.  Otherwise, burn the entire
-     * timeout value with delays since msleep() is a no-op.
-     */
-    period = 1000 / sc->ec_polldelay;
-    if (cold)
-	period *= ec_poll_timeout;
-
-    /*
-     * Poll the EC status register to detect completion of the last
-     * command in chunks of ec_polldelay.
+     * Poll the EC status register for up to 1 ms in chunks of 10 us
+     * to detect completion of the last command.
      */
-    for (i = 0; i < period; i++) {
+    for (i = 0; i < 1000 / EC_POLL_DELAY; i++) {
 	EcStatus = EC_GET_CSR(sc);
 	if (EVENT_READY(Event, EcStatus)) {
 	    Status = AE_OK;
 	    break;
 	}
-	AcpiOsStall(sc->ec_polldelay);
+	AcpiOsStall(EC_POLL_DELAY);
     }
-
-    /* Scale poll delay by the amount of time actually waited. */
-    period = i * sc->ec_polldelay;
-    if (period <= 5)
-	sc->ec_polldelay = 1;
-    else if (period <= 20)
-	sc->ec_polldelay = 5;
-    else if (period <= 100)
-	sc->ec_polldelay = 10;
-    else
-	sc->ec_polldelay = 100;
+    period = i * EC_POLL_DELAY;

     /*
      * If we still don't have a response and we're up and running, wait up
      * to ec_poll_timeout ms for completion, sleeping for chunks of 10 ms.
      */
-    if (!cold && Status != AE_OK) {
-	retval = -1;
-	for (i = 0; i < ec_poll_timeout / 10; i++) {
+    slp_ival = 0;
+    if (Status != AE_OK) {
+	retval = ENXIO;
+	count = ec_poll_timeout / 10;
+	if (count == 0)
+	    count = 1;
+	slp_ival = hz / 100;
+	if (slp_ival == 0)
+	    slp_ival = 1;
+	for (i = 0; i < count; i++) {
 	    if (retval != 0)
 		EcStatus = EC_GET_CSR(sc);
 	    else
@@ -883,13 +868,15 @@
 		Status = AE_OK;
 		break;
 	    }
-	    retval = msleep(&sc->ec_csrvalue, &sc->ec_mtx, PZERO, "ecpoll",
-			    10/*ms*/);
+	    if (!cold)
+		retval = tsleep(&sc->ec_csrvalue, PZERO, "ecpoll", slp_ival);
+	    else
+		AcpiOsStall(10000);
 	}
     }

     /* Calculate new delay and print it if it exceeds the max. */
-    if (period == 1000)
+    if (slp_ival > 0)
 	period += i * 10000;
     if (period > EcDbgMaxDelay) {
 	EcDbgMaxDelay = period;
@@ -906,7 +893,7 @@
     ACPI_STATUS	Status;
     EC_EVENT	Event;

-    mtx_assert(&sc->ec_mtx, MA_OWNED);
+    sx_assert(&sc->ec_sxlock, SX_XLOCKED);

     /* Decide what to wait for based on command type. */
     switch (cmd) {
@@ -941,7 +928,7 @@
 {
     ACPI_STATUS	Status;

-    mtx_assert(&sc->ec_mtx, MA_OWNED);
+    sx_assert(&sc->ec_sxlock, SX_XLOCKED);

 #ifdef notyet
     /* If we can't start burst mode, continue anyway. */
@@ -978,7 +965,7 @@
 {
     ACPI_STATUS	Status;

-    mtx_assert(&sc->ec_mtx, MA_OWNED);
+    sx_assert(&sc->ec_sxlock, SX_XLOCKED);

 #ifdef notyet
     /* If we can't start burst mode, continue anyway. */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040630124817.M41697>