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>