diff options
author | Thomas Renninger <trenn@suse.de> | 2010-10-21 12:24:57 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-10-22 01:21:30 -0400 |
commit | 7a18e96dcbdec3c96876444ae2c7e36ce458e151 (patch) | |
tree | c4a8ed0442eba1035fb7420f8598c955b1735032 /drivers/acpi/ec.c | |
parent | f6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff) |
ACPI: Make Embedded Controller command timeout delay configurable
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>
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r-- | drivers/acpi/ec.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index f31291ba94d0..372ff80b7b0c 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -83,6 +83,11 @@ enum { | |||
83 | EC_FLAGS_BLOCKED, /* Transactions are blocked */ | 83 | EC_FLAGS_BLOCKED, /* Transactions are blocked */ |
84 | }; | 84 | }; |
85 | 85 | ||
86 | /* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */ | ||
87 | static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; | ||
88 | module_param(ec_delay, uint, 0644); | ||
89 | MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); | ||
90 | |||
86 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ | 91 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ |
87 | /* External interfaces use first EC only, so remember */ | 92 | /* External interfaces use first EC only, so remember */ |
88 | typedef int (*acpi_ec_query_func) (void *data); | 93 | typedef int (*acpi_ec_query_func) (void *data); |
@@ -210,7 +215,7 @@ static int ec_poll(struct acpi_ec *ec) | |||
210 | int repeat = 2; /* number of command restarts */ | 215 | int repeat = 2; /* number of command restarts */ |
211 | while (repeat--) { | 216 | while (repeat--) { |
212 | unsigned long delay = jiffies + | 217 | unsigned long delay = jiffies + |
213 | msecs_to_jiffies(ACPI_EC_DELAY); | 218 | msecs_to_jiffies(ec_delay); |
214 | do { | 219 | do { |
215 | /* don't sleep with disabled interrupts */ | 220 | /* don't sleep with disabled interrupts */ |
216 | if (EC_FLAGS_MSI || irqs_disabled()) { | 221 | if (EC_FLAGS_MSI || irqs_disabled()) { |
@@ -265,7 +270,7 @@ static int ec_check_ibf0(struct acpi_ec *ec) | |||
265 | 270 | ||
266 | static int ec_wait_ibf0(struct acpi_ec *ec) | 271 | static int ec_wait_ibf0(struct acpi_ec *ec) |
267 | { | 272 | { |
268 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 273 | unsigned long delay = jiffies + msecs_to_jiffies(ec_delay); |
269 | /* interrupt wait manually if GPE mode is not active */ | 274 | /* interrupt wait manually if GPE mode is not active */ |
270 | while (time_before(jiffies, delay)) | 275 | while (time_before(jiffies, delay)) |
271 | if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), | 276 | if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), |