aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
authorAlexey Starikovskiy <alexey.y.starikovskiy@intel.com>2006-12-07 10:42:16 -0500
committerLen Brown <len.brown@intel.com>2006-12-08 02:56:06 -0500
commitaf3fd1404fd4f0f58ebbb52b22be4f1ca0794cda (patch)
treedddef95d7c36096d3f82983a5261cb4f02477088 /drivers/acpi/ec.c
parentbec5a1e0604d1b829b87b4b7e85f71ccc43dda50 (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/ec.c')
-rw-r--r--drivers/acpi/ec.c84
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
156static int acpi_ec_wait(struct acpi_ec *ec, u8 event) 158static 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
274static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, 276static 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
422struct acpi_ec_query_data {
423 acpi_handle handle;
424 u8 data;
425};
426
427static void acpi_ec_gpe_query(void *ec_cxt) 424static 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 ?