aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@mail.ru>2005-03-19 01:10:05 -0500
committerLen Brown <len.brown@intel.com>2005-07-11 23:52:48 -0400
commit451566f45a2e6cd10ba56e7220a9dd84ba3ef550 (patch)
treeccc6c1018f6bc6c5f3a664e1c28e78fcaae77065
parentb913100d7304ea9596d8d85ab5f3ae04bd2b0ddb (diff)
[ACPI] Enable EC Burst Mode
Fixes several Embedded Controller issues, including button failure and battery status AE_TIME failure. http://bugzilla.kernel.org/show_bug.cgi?id=3851 Based on patch by: Andi Kleen <ak@suse.de> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Luming Yu <luming.yu@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/ec.c390
1 files changed, 276 insertions, 114 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index fdf143b405b..69b04d430f0 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -31,6 +31,7 @@
31#include <linux/delay.h> 31#include <linux/delay.h>
32#include <linux/proc_fs.h> 32#include <linux/proc_fs.h>
33#include <linux/seq_file.h> 33#include <linux/seq_file.h>
34#include <linux/interrupt.h>
34#include <asm/io.h> 35#include <asm/io.h>
35#include <acpi/acpi_bus.h> 36#include <acpi/acpi_bus.h>
36#include <acpi/acpi_drivers.h> 37#include <acpi/acpi_drivers.h>
@@ -49,17 +50,19 @@ ACPI_MODULE_NAME ("acpi_ec")
49 50
50#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ 51#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
51#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ 52#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
53#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */
52#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ 54#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */
53 55
54#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */ 56#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */
55#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */ 57#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */
56 58
57#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ 59#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */
58#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
59#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ 60#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
60 61
61#define ACPI_EC_COMMAND_READ 0x80 62#define ACPI_EC_COMMAND_READ 0x80
62#define ACPI_EC_COMMAND_WRITE 0x81 63#define ACPI_EC_COMMAND_WRITE 0x81
64#define ACPI_EC_BURST_ENABLE 0x82
65#define ACPI_EC_BURST_DISABLE 0x83
63#define ACPI_EC_COMMAND_QUERY 0x84 66#define ACPI_EC_COMMAND_QUERY 0x84
64 67
65static int acpi_ec_add (struct acpi_device *device); 68static int acpi_ec_add (struct acpi_device *device);
@@ -87,7 +90,11 @@ struct acpi_ec {
87 struct acpi_generic_address command_addr; 90 struct acpi_generic_address command_addr;
88 struct acpi_generic_address data_addr; 91 struct acpi_generic_address data_addr;
89 unsigned long global_lock; 92 unsigned long global_lock;
90 spinlock_t lock; 93 unsigned int expect_event;
94 atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/
95 atomic_t pending_gpe;
96 struct semaphore sem;
97 wait_queue_head_t wait;
91}; 98};
92 99
93/* If we find an EC via the ECDT, we need to keep a ptr to its context */ 100/* If we find an EC via the ECDT, we need to keep a ptr to its context */
@@ -100,59 +107,138 @@ static struct acpi_device *first_ec;
100 Transaction Management 107 Transaction Management
101 -------------------------------------------------------------------------- */ 108 -------------------------------------------------------------------------- */
102 109
103static int 110static inline u32 acpi_ec_read_status(struct acpi_ec *ec)
104acpi_ec_wait (
105 struct acpi_ec *ec,
106 u8 event)
107{ 111{
108 u32 acpi_ec_status = 0; 112 u32 status = 0;
109 u32 i = ACPI_EC_UDELAY_COUNT;
110 113
111 if (!ec) 114 acpi_hw_low_level_read(8, &status, &ec->status_addr);
112 return -EINVAL; 115 return status;
116}
117
118static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event)
119{
120 int result = 0;
121
122 ACPI_FUNCTION_TRACE("acpi_ec_wait");
113 123
114 /* Poll the EC status register waiting for the event to occur. */ 124 ec->expect_event = event;
125 smp_mb();
126
127 result = wait_event_interruptible_timeout(ec->wait,
128 !ec->expect_event,
129 msecs_to_jiffies(ACPI_EC_DELAY));
130
131 ec->expect_event = 0;
132 smp_mb();
133
134 if (result < 0){
135 ACPI_DEBUG_PRINT((ACPI_DB_ERROR," result = %d ", result));
136 return_VALUE(result);
137 }
138
139 /*
140 * Verify that the event in question has actually happened by
141 * querying EC status. Do the check even if operation timed-out
142 * to make sure that we did not miss interrupt.
143 */
115 switch (event) { 144 switch (event) {
116 case ACPI_EC_EVENT_OBF: 145 case ACPI_EC_EVENT_OBF:
117 do { 146 if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF)
118 acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); 147 return_VALUE(0);
119 if (acpi_ec_status & ACPI_EC_FLAG_OBF)
120 return 0;
121 udelay(ACPI_EC_UDELAY);
122 } while (--i>0);
123 break; 148 break;
149
124 case ACPI_EC_EVENT_IBE: 150 case ACPI_EC_EVENT_IBE:
125 do { 151 if (~acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)
126 acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); 152 return_VALUE(0);
127 if (!(acpi_ec_status & ACPI_EC_FLAG_IBF))
128 return 0;
129 udelay(ACPI_EC_UDELAY);
130 } while (--i>0);
131 break; 153 break;
132 default:
133 return -EINVAL;
134 } 154 }
135 155
136 return -ETIME; 156 return_VALUE(-ETIME);
137} 157}
138 158
139 159
160
161static int
162acpi_ec_enter_burst_mode (
163 struct acpi_ec *ec)
164{
165 u32 tmp = 0;
166 int status = 0;
167
168 ACPI_FUNCTION_TRACE("acpi_ec_enter_burst_mode");
169
170 status = acpi_ec_read_status(ec);
171 if (status != -EINVAL &&
172 !(status & ACPI_EC_FLAG_BURST)){
173 ACPI_DEBUG_PRINT((ACPI_DB_INFO,"entering burst mode \n"));
174 acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr);
175 status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
176 if (status){
177 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
178 ACPI_DEBUG_PRINT((ACPI_DB_ERROR," status = %d\n", status));
179 return_VALUE(-EINVAL);
180 }
181 acpi_hw_low_level_read(8, &tmp, &ec->data_addr);
182 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
183 if(tmp != 0x90 ) {/* Burst ACK byte*/
184 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"Ack failed \n"));
185 return_VALUE(-EINVAL);
186 }
187 } else
188 ACPI_DEBUG_PRINT((ACPI_DB_INFO,"already be in burst mode \n"));
189 atomic_set(&ec->leaving_burst , 0);
190 return_VALUE(0);
191}
192
193static int
194acpi_ec_leave_burst_mode (
195 struct acpi_ec *ec)
196{
197 int status =0;
198
199 ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode");
200
201 atomic_set(&ec->leaving_burst , 1);
202 status = acpi_ec_read_status(ec);
203 if (status != -EINVAL &&
204 (status & ACPI_EC_FLAG_BURST)){
205 ACPI_DEBUG_PRINT((ACPI_DB_INFO,"leaving burst mode\n"));
206 acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->command_addr);
207 status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
208 if (status){
209 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
210 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n"));
211 return_VALUE(-EINVAL);
212 }
213 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
214 status = acpi_ec_read_status(ec);
215 if (status != -EINVAL &&
216 (status & ACPI_EC_FLAG_BURST)) {
217 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->status fail\n"));
218 return_VALUE(-EINVAL);
219 }
220 }else
221 ACPI_DEBUG_PRINT((ACPI_DB_INFO,"already be in Non-burst mode \n"));
222 ACPI_DEBUG_PRINT((ACPI_DB_INFO,"leaving burst mode\n"));
223
224 return_VALUE(0);
225}
226
140static int 227static int
141acpi_ec_read ( 228acpi_ec_read (
142 struct acpi_ec *ec, 229 struct acpi_ec *ec,
143 u8 address, 230 u8 address,
144 u32 *data) 231 u32 *data)
145{ 232{
146 acpi_status status = AE_OK; 233 int status = 0;
147 int result = 0; 234 u32 glk;
148 unsigned long flags = 0;
149 u32 glk = 0;
150 235
151 ACPI_FUNCTION_TRACE("acpi_ec_read"); 236 ACPI_FUNCTION_TRACE("acpi_ec_read");
152 237
153 if (!ec || !data) 238 if (!ec || !data)
154 return_VALUE(-EINVAL); 239 return_VALUE(-EINVAL);
155 240
241retry:
156 *data = 0; 242 *data = 0;
157 243
158 if (ec->global_lock) { 244 if (ec->global_lock) {
@@ -160,32 +246,50 @@ acpi_ec_read (
160 if (ACPI_FAILURE(status)) 246 if (ACPI_FAILURE(status))
161 return_VALUE(-ENODEV); 247 return_VALUE(-ENODEV);
162 } 248 }
163 249
164 spin_lock_irqsave(&ec->lock, flags); 250 WARN_ON(in_interrupt());
251 down(&ec->sem);
252
253 if(acpi_ec_enter_burst_mode(ec))
254 goto end;
165 255
166 acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr); 256 acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr);
167 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); 257 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
168 if (result) 258 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
259 if (status) {
169 goto end; 260 goto end;
261 }
170 262
171 acpi_hw_low_level_write(8, address, &ec->data_addr); 263 acpi_hw_low_level_write(8, address, &ec->data_addr);
172 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); 264 status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
173 if (result) 265 if (status){
266 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
174 goto end; 267 goto end;
175 268 }
176 269
177 acpi_hw_low_level_read(8, data, &ec->data_addr); 270 acpi_hw_low_level_read(8, data, &ec->data_addr);
271 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
178 272
179 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", 273 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
180 *data, address)); 274 *data, address));
181 275
182end: 276end:
183 spin_unlock_irqrestore(&ec->lock, flags); 277 acpi_ec_leave_burst_mode(ec);
278 up(&ec->sem);
184 279
185 if (ec->global_lock) 280 if (ec->global_lock)
186 acpi_release_global_lock(glk); 281 acpi_release_global_lock(glk);
187 282
188 return_VALUE(result); 283 if(atomic_read(&ec->leaving_burst) == 2){
284 ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
285 while(!atomic_read(&ec->pending_gpe)){
286 msleep(1);
287 }
288 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
289 goto retry;
290 }
291
292 return_VALUE(status);
189} 293}
190 294
191 295
@@ -195,49 +299,80 @@ acpi_ec_write (
195 u8 address, 299 u8 address,
196 u8 data) 300 u8 data)
197{ 301{
198 int result = 0; 302 int status = 0;
199 acpi_status status = AE_OK; 303 u32 glk;
200 unsigned long flags = 0; 304 u32 tmp;
201 u32 glk = 0;
202 305
203 ACPI_FUNCTION_TRACE("acpi_ec_write"); 306 ACPI_FUNCTION_TRACE("acpi_ec_write");
204 307
205 if (!ec) 308 if (!ec)
206 return_VALUE(-EINVAL); 309 return_VALUE(-EINVAL);
207 310retry:
208 if (ec->global_lock) { 311 if (ec->global_lock) {
209 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); 312 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
210 if (ACPI_FAILURE(status)) 313 if (ACPI_FAILURE(status))
211 return_VALUE(-ENODEV); 314 return_VALUE(-ENODEV);
212 } 315 }
213 316
214 spin_lock_irqsave(&ec->lock, flags); 317 WARN_ON(in_interrupt());
318 down(&ec->sem);
319
320 if(acpi_ec_enter_burst_mode(ec))
321 goto end;
322
323 status = acpi_ec_read_status(ec);
324 if (status != -EINVAL &&
325 !(status & ACPI_EC_FLAG_BURST)){
326 acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr);
327 status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
328 if (status)
329 goto end;
330 acpi_hw_low_level_read(8, &tmp, &ec->data_addr);
331 if(tmp != 0x90 ) /* Burst ACK byte*/
332 goto end;
333 }
334 /*Now we are in burst mode*/
215 335
216 acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); 336 acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr);
217 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); 337 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
218 if (result) 338 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
339 if (status){
219 goto end; 340 goto end;
341 }
220 342
221 acpi_hw_low_level_write(8, address, &ec->data_addr); 343 acpi_hw_low_level_write(8, address, &ec->data_addr);
222 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); 344 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
223 if (result) 345 if (status){
346 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
224 goto end; 347 goto end;
348 }
225 349
226 acpi_hw_low_level_write(8, data, &ec->data_addr); 350 acpi_hw_low_level_write(8, data, &ec->data_addr);
227 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); 351 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
228 if (result) 352 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
353 if (status)
229 goto end; 354 goto end;
230 355
231 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", 356 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
232 data, address)); 357 data, address));
233 358
234end: 359end:
235 spin_unlock_irqrestore(&ec->lock, flags); 360 acpi_ec_leave_burst_mode(ec);
361 up(&ec->sem);
236 362
237 if (ec->global_lock) 363 if (ec->global_lock)
238 acpi_release_global_lock(glk); 364 acpi_release_global_lock(glk);
239 365
240 return_VALUE(result); 366 if(atomic_read(&ec->leaving_burst) == 2){
367 ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
368 while(!atomic_read(&ec->pending_gpe)){
369 msleep(1);
370 }
371 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
372 goto retry;
373 }
374
375 return_VALUE(status);
241} 376}
242 377
243/* 378/*
@@ -289,16 +424,14 @@ acpi_ec_query (
289 struct acpi_ec *ec, 424 struct acpi_ec *ec,
290 u32 *data) 425 u32 *data)
291{ 426{
292 int result = 0; 427 int status = 0;
293 acpi_status status = AE_OK; 428 u32 glk;
294 unsigned long flags = 0;
295 u32 glk = 0;
296 429
297 ACPI_FUNCTION_TRACE("acpi_ec_query"); 430 ACPI_FUNCTION_TRACE("acpi_ec_query");
298 431
299 if (!ec || !data) 432 if (!ec || !data)
300 return_VALUE(-EINVAL); 433 return_VALUE(-EINVAL);
301 434retry:
302 *data = 0; 435 *data = 0;
303 436
304 if (ec->global_lock) { 437 if (ec->global_lock) {
@@ -307,29 +440,43 @@ acpi_ec_query (
307 return_VALUE(-ENODEV); 440 return_VALUE(-ENODEV);
308 } 441 }
309 442
443 down(&ec->sem);
444 if(acpi_ec_enter_burst_mode(ec))
445 goto end;
310 /* 446 /*
311 * Query the EC to find out which _Qxx method we need to evaluate. 447 * Query the EC to find out which _Qxx method we need to evaluate.
312 * Note that successful completion of the query causes the ACPI_EC_SCI 448 * Note that successful completion of the query causes the ACPI_EC_SCI
313 * bit to be cleared (and thus clearing the interrupt source). 449 * bit to be cleared (and thus clearing the interrupt source).
314 */ 450 */
315 spin_lock_irqsave(&ec->lock, flags);
316
317 acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); 451 acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr);
318 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); 452 status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
319 if (result) 453 if (status){
454 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
320 goto end; 455 goto end;
321 456 }
457
322 acpi_hw_low_level_read(8, data, &ec->data_addr); 458 acpi_hw_low_level_read(8, data, &ec->data_addr);
459 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
323 if (!*data) 460 if (!*data)
324 result = -ENODATA; 461 status = -ENODATA;
325 462
326end: 463end:
327 spin_unlock_irqrestore(&ec->lock, flags); 464 acpi_ec_leave_burst_mode(ec);
465 up(&ec->sem);
328 466
329 if (ec->global_lock) 467 if (ec->global_lock)
330 acpi_release_global_lock(glk); 468 acpi_release_global_lock(glk);
331 469
332 return_VALUE(result); 470 if(atomic_read(&ec->leaving_burst) == 2){
471 ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n"));
472 while(!atomic_read(&ec->pending_gpe)){
473 msleep(1);
474 }
475 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
476 goto retry;
477 }
478
479 return_VALUE(status);
333} 480}
334 481
335 482
@@ -347,42 +494,29 @@ acpi_ec_gpe_query (
347 void *ec_cxt) 494 void *ec_cxt)
348{ 495{
349 struct acpi_ec *ec = (struct acpi_ec *) ec_cxt; 496 struct acpi_ec *ec = (struct acpi_ec *) ec_cxt;
350 u32 value = 0; 497 u32 value;
351 unsigned long flags = 0; 498 int result = -ENODATA;
352 static char object_name[5] = {'_','Q','0','0','\0'}; 499 static char object_name[5] = {'_','Q','0','0','\0'};
353 const char hex[] = {'0','1','2','3','4','5','6','7', 500 const char hex[] = {'0','1','2','3','4','5','6','7',
354 '8','9','A','B','C','D','E','F'}; 501 '8','9','A','B','C','D','E','F'};
355 502
356 ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); 503 ACPI_FUNCTION_TRACE("acpi_ec_gpe_query");
357 504
358 if (!ec_cxt) 505 if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI)
359 goto end; 506 result = acpi_ec_query(ec, &value);
360 507
361 spin_lock_irqsave(&ec->lock, flags); 508 if (result)
362 acpi_hw_low_level_read(8, &value, &ec->command_addr);
363 spin_unlock_irqrestore(&ec->lock, flags);
364
365 /* TBD: Implement asynch events!
366 * NOTE: All we care about are EC-SCI's. Other EC events are
367 * handled via polling (yuck!). This is because some systems
368 * treat EC-SCIs as level (versus EDGE!) triggered, preventing
369 * a purely interrupt-driven approach (grumble, grumble).
370 */
371 if (!(value & ACPI_EC_FLAG_SCI))
372 goto end; 509 goto end;
373 510
374 if (acpi_ec_query(ec, &value))
375 goto end;
376
377 object_name[2] = hex[((value >> 4) & 0x0F)]; 511 object_name[2] = hex[((value >> 4) & 0x0F)];
378 object_name[3] = hex[(value & 0x0F)]; 512 object_name[3] = hex[(value & 0x0F)];
379 513
380 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); 514 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
381 515
382 acpi_evaluate_object(ec->handle, object_name, NULL, NULL); 516 acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
383 517 atomic_dec(&ec->pending_gpe);
384end: 518end:
385 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); 519 return;
386} 520}
387 521
388static u32 522static u32
@@ -390,6 +524,7 @@ acpi_ec_gpe_handler (
390 void *data) 524 void *data)
391{ 525{
392 acpi_status status = AE_OK; 526 acpi_status status = AE_OK;
527 u32 value;
393 struct acpi_ec *ec = (struct acpi_ec *) data; 528 struct acpi_ec *ec = (struct acpi_ec *) data;
394 529
395 if (!ec) 530 if (!ec)
@@ -397,13 +532,39 @@ acpi_ec_gpe_handler (
397 532
398 acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR); 533 acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
399 534
400 status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, 535 value = acpi_ec_read_status(ec);
401 acpi_ec_gpe_query, ec);
402 536
403 if (status == AE_OK) 537 if((value & ACPI_EC_FLAG_IBF) &&
404 return ACPI_INTERRUPT_HANDLED; 538 !(value & ACPI_EC_FLAG_BURST) &&
405 else 539 (atomic_read(&ec->leaving_burst) == 0)) {
406 return ACPI_INTERRUPT_NOT_HANDLED; 540 /*
541 * the embedded controller disables
542 * burst mode for any reason other
543 * than the burst disable command
544 * to process critical event.
545 */
546 atomic_set(&ec->leaving_burst , 2); /* block current pending transaction
547 and retry */
548 wake_up(&ec->wait);
549 }else {
550 if ((ec->expect_event == ACPI_EC_EVENT_OBF &&
551 (value & ACPI_EC_FLAG_OBF)) ||
552 (ec->expect_event == ACPI_EC_EVENT_IBE &&
553 !(value & ACPI_EC_FLAG_IBF))) {
554 ec->expect_event = 0;
555 wake_up(&ec->wait);
556
557 }
558 }
559
560 if (value & ACPI_EC_FLAG_SCI){
561 atomic_add(1, &ec->pending_gpe) ;
562 status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
563 acpi_ec_gpe_query, ec);
564 }
565
566 return status == AE_OK ?
567 ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
407} 568}
408 569
409/* -------------------------------------------------------------------------- 570/* --------------------------------------------------------------------------
@@ -421,10 +582,8 @@ acpi_ec_space_setup (
421 * The EC object is in the handler context and is needed 582 * The EC object is in the handler context and is needed
422 * when calling the acpi_ec_space_handler. 583 * when calling the acpi_ec_space_handler.
423 */ 584 */
424 if(function == ACPI_REGION_DEACTIVATE) 585 *return_context = (function != ACPI_REGION_DEACTIVATE) ?
425 *return_context = NULL; 586 handler_context : NULL;
426 else
427 *return_context = handler_context;
428 587
429 return AE_OK; 588 return AE_OK;
430} 589}
@@ -555,7 +714,7 @@ static int
555acpi_ec_add_fs ( 714acpi_ec_add_fs (
556 struct acpi_device *device) 715 struct acpi_device *device)
557{ 716{
558 struct proc_dir_entry *entry = NULL; 717 struct proc_dir_entry *entry;
559 718
560 ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); 719 ACPI_FUNCTION_TRACE("acpi_ec_add_fs");
561 720
@@ -606,9 +765,9 @@ static int
606acpi_ec_add ( 765acpi_ec_add (
607 struct acpi_device *device) 766 struct acpi_device *device)
608{ 767{
609 int result = 0; 768 int result;
610 acpi_status status = AE_OK; 769 acpi_status status;
611 struct acpi_ec *ec = NULL; 770 struct acpi_ec *ec;
612 unsigned long uid; 771 unsigned long uid;
613 772
614 ACPI_FUNCTION_TRACE("acpi_ec_add"); 773 ACPI_FUNCTION_TRACE("acpi_ec_add");
@@ -623,7 +782,10 @@ acpi_ec_add (
623 782
624 ec->handle = device->handle; 783 ec->handle = device->handle;
625 ec->uid = -1; 784 ec->uid = -1;
626 spin_lock_init(&ec->lock); 785 atomic_set(&ec->pending_gpe, 0);
786 atomic_set(&ec->leaving_burst , 1);
787 init_MUTEX(&ec->sem);
788 init_waitqueue_head(&ec->wait);
627 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); 789 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
628 strcpy(acpi_device_class(device), ACPI_EC_CLASS); 790 strcpy(acpi_device_class(device), ACPI_EC_CLASS);
629 acpi_driver_data(device) = ec; 791 acpi_driver_data(device) = ec;
@@ -637,7 +799,7 @@ acpi_ec_add (
637 if (ec_ecdt && ec_ecdt->uid == uid) { 799 if (ec_ecdt && ec_ecdt->uid == uid) {
638 acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, 800 acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
639 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); 801 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
640 802
641 acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); 803 acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler);
642 804
643 kfree(ec_ecdt); 805 kfree(ec_ecdt);
@@ -677,7 +839,7 @@ acpi_ec_remove (
677 struct acpi_device *device, 839 struct acpi_device *device,
678 int type) 840 int type)
679{ 841{
680 struct acpi_ec *ec = NULL; 842 struct acpi_ec *ec;
681 843
682 ACPI_FUNCTION_TRACE("acpi_ec_remove"); 844 ACPI_FUNCTION_TRACE("acpi_ec_remove");
683 845
@@ -732,8 +894,8 @@ static int
732acpi_ec_start ( 894acpi_ec_start (
733 struct acpi_device *device) 895 struct acpi_device *device)
734{ 896{
735 acpi_status status = AE_OK; 897 acpi_status status;
736 struct acpi_ec *ec = NULL; 898 struct acpi_ec *ec;
737 899
738 ACPI_FUNCTION_TRACE("acpi_ec_start"); 900 ACPI_FUNCTION_TRACE("acpi_ec_start");
739 901
@@ -789,8 +951,8 @@ acpi_ec_stop (
789 struct acpi_device *device, 951 struct acpi_device *device,
790 int type) 952 int type)
791{ 953{
792 acpi_status status = AE_OK; 954 acpi_status status;
793 struct acpi_ec *ec = NULL; 955 struct acpi_ec *ec;
794 956
795 ACPI_FUNCTION_TRACE("acpi_ec_stop"); 957 ACPI_FUNCTION_TRACE("acpi_ec_stop");
796 958
@@ -832,7 +994,6 @@ acpi_fake_ecdt_callback (
832 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit); 994 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit);
833 if (ACPI_FAILURE(status)) 995 if (ACPI_FAILURE(status))
834 return status; 996 return status;
835 spin_lock_init(&ec_ecdt->lock);
836 ec_ecdt->global_lock = TRUE; 997 ec_ecdt->global_lock = TRUE;
837 ec_ecdt->handle = handle; 998 ec_ecdt->handle = handle;
838 999
@@ -890,7 +1051,7 @@ acpi_ec_get_real_ecdt(void)
890 acpi_status status; 1051 acpi_status status;
891 struct acpi_table_ecdt *ecdt_ptr; 1052 struct acpi_table_ecdt *ecdt_ptr;
892 1053
893 status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, 1054 status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
894 (struct acpi_table_header **) &ecdt_ptr); 1055 (struct acpi_table_header **) &ecdt_ptr);
895 if (ACPI_FAILURE(status)) 1056 if (ACPI_FAILURE(status))
896 return -ENODEV; 1057 return -ENODEV;
@@ -905,11 +1066,12 @@ acpi_ec_get_real_ecdt(void)
905 return -ENOMEM; 1066 return -ENOMEM;
906 memset(ec_ecdt, 0, sizeof(struct acpi_ec)); 1067 memset(ec_ecdt, 0, sizeof(struct acpi_ec));
907 1068
1069 init_MUTEX(&ec_ecdt->sem);
1070 init_waitqueue_head(&ec_ecdt->wait);
908 ec_ecdt->command_addr = ecdt_ptr->ec_control; 1071 ec_ecdt->command_addr = ecdt_ptr->ec_control;
909 ec_ecdt->status_addr = ecdt_ptr->ec_control; 1072 ec_ecdt->status_addr = ecdt_ptr->ec_control;
910 ec_ecdt->data_addr = ecdt_ptr->ec_data; 1073 ec_ecdt->data_addr = ecdt_ptr->ec_data;
911 ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; 1074 ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
912 spin_lock_init(&ec_ecdt->lock);
913 /* use the GL just to be safe */ 1075 /* use the GL just to be safe */
914 ec_ecdt->global_lock = TRUE; 1076 ec_ecdt->global_lock = TRUE;
915 ec_ecdt->uid = ecdt_ptr->uid; 1077 ec_ecdt->uid = ecdt_ptr->uid;
@@ -978,7 +1140,7 @@ error:
978 1140
979static int __init acpi_ec_init (void) 1141static int __init acpi_ec_init (void)
980{ 1142{
981 int result = 0; 1143 int result;
982 1144
983 ACPI_FUNCTION_TRACE("acpi_ec_init"); 1145 ACPI_FUNCTION_TRACE("acpi_ec_init");
984 1146