diff options
author | Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> | 2006-12-07 10:42:16 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-12-08 02:56:06 -0500 |
commit | af3fd1404fd4f0f58ebbb52b22be4f1ca0794cda (patch) | |
tree | dddef95d7c36096d3f82983a5261cb4f02477088 /drivers/acpi | |
parent | bec5a1e0604d1b829b87b4b7e85f71ccc43dda50 (diff) |
ACPI: ec: Remove expect_event and all races around it.
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/ec.c | 84 |
1 files changed, 38 insertions, 46 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 94b983b9cfba..1514e71b723d 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -46,6 +46,9 @@ ACPI_MODULE_NAME("acpi_ec") | |||
46 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" | 46 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" |
47 | #define ACPI_EC_FILE_INFO "info" | 47 | #define ACPI_EC_FILE_INFO "info" |
48 | 48 | ||
49 | #undef PREFIX | ||
50 | #define PREFIX "ACPI: EC: " | ||
51 | |||
49 | /* EC status register */ | 52 | /* EC status register */ |
50 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ | 53 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ |
51 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ | 54 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ |
@@ -101,7 +104,6 @@ struct acpi_ec { | |||
101 | unsigned long data_addr; | 104 | unsigned long data_addr; |
102 | unsigned long global_lock; | 105 | unsigned long global_lock; |
103 | struct semaphore sem; | 106 | struct semaphore sem; |
104 | unsigned int expect_event; | ||
105 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ | 107 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ |
106 | wait_queue_head_t wait; | 108 | wait_queue_head_t wait; |
107 | } *ec_ecdt; | 109 | } *ec_ecdt; |
@@ -155,34 +157,25 @@ static int acpi_ec_check_status(struct acpi_ec *ec, u8 event) | |||
155 | 157 | ||
156 | static int acpi_ec_wait(struct acpi_ec *ec, u8 event) | 158 | static int acpi_ec_wait(struct acpi_ec *ec, u8 event) |
157 | { | 159 | { |
158 | int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0; | 160 | if (acpi_ec_mode == EC_POLL) { |
159 | long time_left; | 161 | int i; |
160 | 162 | for (i = 0; i < ACPI_EC_UDELAY_COUNT; ++i) { | |
161 | ec->expect_event = event; | 163 | if (acpi_ec_check_status(ec, event)) |
162 | if (acpi_ec_check_status(ec, event)) { | ||
163 | ec->expect_event = 0; | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | do { | ||
168 | if (acpi_ec_mode == EC_POLL) { | ||
169 | udelay(ACPI_EC_UDELAY); | ||
170 | } else { | ||
171 | time_left = wait_event_timeout(ec->wait, | ||
172 | !ec->expect_event, | ||
173 | msecs_to_jiffies(ACPI_EC_DELAY)); | ||
174 | if (time_left > 0) { | ||
175 | ec->expect_event = 0; | ||
176 | return 0; | 164 | return 0; |
177 | } | 165 | udelay(ACPI_EC_UDELAY); |
178 | } | 166 | } |
179 | if (acpi_ec_check_status(ec, event)) { | 167 | } else { |
180 | ec->expect_event = 0; | 168 | if (wait_event_timeout(ec->wait, |
169 | acpi_ec_check_status(ec, event), | ||
170 | msecs_to_jiffies(ACPI_EC_DELAY)) || | ||
171 | acpi_ec_check_status(ec, event)) { | ||
181 | return 0; | 172 | return 0; |
173 | } else { | ||
174 | printk(KERN_ERR PREFIX "acpi_ec_wait timeout," | ||
175 | " status = %d, expect_event = %d\n", | ||
176 | acpi_ec_read_status(ec), event); | ||
182 | } | 177 | } |
183 | } while (--i > 0); | 178 | } |
184 | |||
185 | ec->expect_event = 0; | ||
186 | 179 | ||
187 | return -ETIME; | 180 | return -ETIME; |
188 | } | 181 | } |
@@ -243,32 +236,41 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
243 | const u8 *wdata, unsigned wdata_len, | 236 | const u8 *wdata, unsigned wdata_len, |
244 | u8 *rdata, unsigned rdata_len) | 237 | u8 *rdata, unsigned rdata_len) |
245 | { | 238 | { |
246 | int result; | 239 | int result = 0; |
247 | 240 | ||
248 | acpi_ec_write_cmd(ec, command); | 241 | acpi_ec_write_cmd(ec, command); |
249 | 242 | ||
250 | for (; wdata_len > 0; wdata_len --) { | 243 | for (; wdata_len > 0; wdata_len --) { |
251 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 244 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); |
252 | if (result) | 245 | if (result) { |
253 | return result; | 246 | printk(KERN_ERR PREFIX "write_cmd timeout, command = %d\n", |
247 | command); | ||
248 | goto end; | ||
249 | } | ||
254 | acpi_ec_write_data(ec, *(wdata++)); | 250 | acpi_ec_write_data(ec, *(wdata++)); |
255 | } | 251 | } |
256 | 252 | ||
257 | if (!rdata_len) { | 253 | if (!rdata_len) { |
258 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 254 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); |
259 | if (result) | 255 | if (result) { |
260 | return result; | 256 | printk(KERN_ERR PREFIX "finish-write timeout, command = %d\n", |
257 | command); | ||
258 | goto end; | ||
259 | } | ||
261 | } | 260 | } |
262 | 261 | ||
263 | for (; rdata_len > 0; rdata_len --) { | 262 | for (; rdata_len > 0; rdata_len --) { |
264 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); | 263 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); |
265 | if (result) | 264 | if (result) { |
266 | return result; | 265 | printk(KERN_ERR PREFIX "read timeout, command = %d\n", |
266 | command); | ||
267 | goto end; | ||
268 | } | ||
267 | 269 | ||
268 | *(rdata++) = acpi_ec_read_data(ec); | 270 | *(rdata++) = acpi_ec_read_data(ec); |
269 | } | 271 | } |
270 | 272 | end: | |
271 | return 0; | 273 | return result; |
272 | } | 274 | } |
273 | 275 | ||
274 | static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, | 276 | static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, |
@@ -419,11 +421,6 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data) | |||
419 | Event Management | 421 | Event Management |
420 | -------------------------------------------------------------------------- */ | 422 | -------------------------------------------------------------------------- */ |
421 | 423 | ||
422 | struct acpi_ec_query_data { | ||
423 | acpi_handle handle; | ||
424 | u8 data; | ||
425 | }; | ||
426 | |||
427 | static void acpi_ec_gpe_query(void *ec_cxt) | 424 | static void acpi_ec_gpe_query(void *ec_cxt) |
428 | { | 425 | { |
429 | struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; | 426 | struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; |
@@ -443,7 +440,7 @@ static void acpi_ec_gpe_query(void *ec_cxt) | |||
443 | 440 | ||
444 | snprintf(object_name, 8, "_Q%2.2X", value); | 441 | snprintf(object_name, 8, "_Q%2.2X", value); |
445 | 442 | ||
446 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); | 443 | printk(KERN_INFO PREFIX "evaluating %s\n", object_name); |
447 | 444 | ||
448 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); | 445 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); |
449 | 446 | ||
@@ -460,17 +457,12 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
460 | acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); | 457 | acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); |
461 | 458 | ||
462 | if (acpi_ec_mode == EC_INTR) { | 459 | if (acpi_ec_mode == EC_INTR) { |
463 | if (acpi_ec_check_status(ec, ec->expect_event)) { | 460 | wake_up(&ec->wait); |
464 | ec->expect_event = 0; | ||
465 | wake_up(&ec->wait); | ||
466 | } | ||
467 | } | 461 | } |
468 | 462 | ||
469 | value = acpi_ec_read_status(ec); | 463 | value = acpi_ec_read_status(ec); |
470 | if (value & ACPI_EC_FLAG_SCI) { | 464 | if (value & ACPI_EC_FLAG_SCI) { |
471 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); | 465 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); |
472 | return status == AE_OK ? | ||
473 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | ||
474 | } | 466 | } |
475 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); | 467 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); |
476 | return status == AE_OK ? | 468 | return status == AE_OK ? |