Skip to content

Commit

Permalink
ACPI: Make Embedded Controller command timeout delay configurable
Browse files Browse the repository at this point in the history
Here and then there show up machines which need higher timeout values.
Finding this on affected machines can be cumbersome, because
ACPI_EC_DELAY is a compile option -> make it configurable via boot param.

This can even be provided writable at runtime via:
/sys/modules/acpi/parameters/ec_delay

Known machines where this helps:
Some HP machines where for whatever reasons specific EC accesses take
very long at resume from S3 (in _WAK function).
The AE_TIME error is passed upwards and the ACPI interpreter will
not execute the rest of the _WAK function which results in not properly
initialized devices/variables with different side-effects.

Afaik, on some MSI machines this helped as well.

If this param is needed there probably are underlying problems like:
  - EC firmware bug
  - A kernel EC driver bug
  - An ACPI interpreter behavior (e.g. timings when specific
    EC accesses happen and how) which the EC does not like
  - ...
which should get evaluated further, but often are nasty or
impossible to fix from OS side.

Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Thomas Renninger authored and Len Brown committed Oct 22, 2010
1 parent f6f94e2 commit 7a18e96
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions drivers/acpi/ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ enum {
EC_FLAGS_BLOCKED, /* Transactions are blocked */
};

/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */
static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
module_param(ec_delay, uint, 0644);
MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");

/* If we find an EC via the ECDT, we need to keep a ptr to its context */
/* External interfaces use first EC only, so remember */
typedef int (*acpi_ec_query_func) (void *data);
Expand Down Expand Up @@ -210,7 +215,7 @@ static int ec_poll(struct acpi_ec *ec)
int repeat = 2; /* number of command restarts */
while (repeat--) {
unsigned long delay = jiffies +
msecs_to_jiffies(ACPI_EC_DELAY);
msecs_to_jiffies(ec_delay);
do {
/* don't sleep with disabled interrupts */
if (EC_FLAGS_MSI || irqs_disabled()) {
Expand Down Expand Up @@ -265,7 +270,7 @@ static int ec_check_ibf0(struct acpi_ec *ec)

static int ec_wait_ibf0(struct acpi_ec *ec)
{
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
unsigned long delay = jiffies + msecs_to_jiffies(ec_delay);
/* interrupt wait manually if GPE mode is not active */
while (time_before(jiffies, delay))
if (wait_event_timeout(ec->wait, ec_check_ibf0(ec),
Expand Down

0 comments on commit 7a18e96

Please sign in to comment.