aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2008-08-10 22:33:31 -0400
committerAndi Kleen <ak@linux.intel.com>2008-08-14 21:13:06 -0400
commit9d699ed92a459cb408e2577e8bbeabc8ec3989e1 (patch)
tree195dcdb6078df4a8b75d2b5604424571013a76a1 /drivers/acpi
parent2500822bf4eb0179ef80e5b072c1e0fa83037381 (diff)
ACPI: Avoid bogus EC timeout when EC is in Polling mode
When EC is in Polling mode, OS will check the EC status continually by using the following source code: clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) return 0; msleep(1); } But msleep is realized by the function of schedule_timeout. At the same time although one process is already waken up by some events, it won't be scheduled immediately. So maybe there exists the following phenomena: a. The current jiffies is already after the predefined jiffies. But before timeout happens, OS has no chance to check the EC status again. b. If preemptible schedule is enabled, maybe preempt schedule will happen before checking loop. When the process is resumed again, maybe timeout already happens, which means that OS has no chance to check the EC status. In such case maybe EC status is already what OS expects when timeout happens. But OS has no chance to check the EC status and regards it as AE_TIME. So it will be more appropriate that OS will try to check the EC status again when timeout happens. If the EC status is what we expect, it won't be regarded as timeout. Only when the EC status is not what we expect, it will be regarded as timeout, which means that EC controller can't give a response in time. http://bugzilla.kernel.org/show_bug.cgi?id=9823 http://bugzilla.kernel.org/show_bug.cgi?id=11141 Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/ec.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 76784ae7e6a1..13593f9f2197 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -221,6 +221,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
221 return 0; 221 return 0;
222 msleep(1); 222 msleep(1);
223 } 223 }
224 if (acpi_ec_check_status(ec,event))
225 return 0;
224 } 226 }
225 pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", 227 pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n",
226 acpi_ec_read_status(ec), 228 acpi_ec_read_status(ec),