diff options
| author | Len Brown <len.brown@intel.com> | 2007-03-09 23:19:25 -0500 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2007-03-09 23:19:25 -0500 |
| commit | 51e7fff1c2b763da910db3a875eac5b992df91d9 (patch) | |
| tree | d7198ca0f3cd319c340b4c6547a6da16500a4867 | |
| parent | bdf3aaf9519ddd8a026b5e04e713d2fa673532e5 (diff) | |
| parent | 9e197219605513c14d3eae41039ecf1b82d1920d (diff) | |
Pull bugzilla-8110 into release branch
| -rw-r--r-- | drivers/acpi/ec.c | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ab6888373795..a802962ff2b4 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -100,6 +100,7 @@ static struct acpi_ec { | |||
| 100 | unsigned long global_lock; | 100 | unsigned long global_lock; |
| 101 | struct mutex lock; | 101 | struct mutex lock; |
| 102 | atomic_t query_pending; | 102 | atomic_t query_pending; |
| 103 | atomic_t event_count; | ||
| 103 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ | 104 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ |
| 104 | wait_queue_head_t wait; | 105 | wait_queue_head_t wait; |
| 105 | } *ec_ecdt; | 106 | } *ec_ecdt; |
| @@ -131,10 +132,12 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) | |||
| 131 | outb(data, ec->data_addr); | 132 | outb(data, ec->data_addr); |
| 132 | } | 133 | } |
| 133 | 134 | ||
| 134 | static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) | 135 | static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event, |
| 136 | unsigned old_count) | ||
| 135 | { | 137 | { |
| 136 | u8 status = acpi_ec_read_status(ec); | 138 | u8 status = acpi_ec_read_status(ec); |
| 137 | 139 | if (old_count == atomic_read(&ec->event_count)) | |
| 140 | return 0; | ||
| 138 | if (event == ACPI_EC_EVENT_OBF_1) { | 141 | if (event == ACPI_EC_EVENT_OBF_1) { |
| 139 | if (status & ACPI_EC_FLAG_OBF) | 142 | if (status & ACPI_EC_FLAG_OBF) |
| 140 | return 1; | 143 | return 1; |
| @@ -146,19 +149,19 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) | |||
| 146 | return 0; | 149 | return 0; |
| 147 | } | 150 | } |
| 148 | 151 | ||
| 149 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event) | 152 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count) |
| 150 | { | 153 | { |
| 151 | if (acpi_ec_mode == EC_POLL) { | 154 | if (acpi_ec_mode == EC_POLL) { |
| 152 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 155 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); |
| 153 | while (time_before(jiffies, delay)) { | 156 | while (time_before(jiffies, delay)) { |
| 154 | if (acpi_ec_check_status(ec, event)) | 157 | if (acpi_ec_check_status(ec, event, 0)) |
| 155 | return 0; | 158 | return 0; |
| 156 | } | 159 | } |
| 157 | } else { | 160 | } else { |
| 158 | if (wait_event_timeout(ec->wait, | 161 | if (wait_event_timeout(ec->wait, |
| 159 | acpi_ec_check_status(ec, event), | 162 | acpi_ec_check_status(ec, event, count), |
| 160 | msecs_to_jiffies(ACPI_EC_DELAY)) || | 163 | msecs_to_jiffies(ACPI_EC_DELAY)) || |
| 161 | acpi_ec_check_status(ec, event)) { | 164 | acpi_ec_check_status(ec, event, 0)) { |
| 162 | return 0; | 165 | return 0; |
| 163 | } else { | 166 | } else { |
| 164 | printk(KERN_ERR PREFIX "acpi_ec_wait timeout," | 167 | printk(KERN_ERR PREFIX "acpi_ec_wait timeout," |
| @@ -225,21 +228,22 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
| 225 | u8 * rdata, unsigned rdata_len) | 228 | u8 * rdata, unsigned rdata_len) |
| 226 | { | 229 | { |
| 227 | int result = 0; | 230 | int result = 0; |
| 228 | 231 | unsigned count = atomic_read(&ec->event_count); | |
| 229 | acpi_ec_write_cmd(ec, command); | 232 | acpi_ec_write_cmd(ec, command); |
| 230 | 233 | ||
| 231 | for (; wdata_len > 0; --wdata_len) { | 234 | for (; wdata_len > 0; --wdata_len) { |
| 232 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 235 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); |
| 233 | if (result) { | 236 | if (result) { |
| 234 | printk(KERN_ERR PREFIX | 237 | printk(KERN_ERR PREFIX |
| 235 | "write_cmd timeout, command = %d\n", command); | 238 | "write_cmd timeout, command = %d\n", command); |
| 236 | goto end; | 239 | goto end; |
| 237 | } | 240 | } |
| 241 | count = atomic_read(&ec->event_count); | ||
| 238 | acpi_ec_write_data(ec, *(wdata++)); | 242 | acpi_ec_write_data(ec, *(wdata++)); |
| 239 | } | 243 | } |
| 240 | 244 | ||
| 241 | if (!rdata_len) { | 245 | if (!rdata_len) { |
| 242 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 246 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); |
| 243 | if (result) { | 247 | if (result) { |
| 244 | printk(KERN_ERR PREFIX | 248 | printk(KERN_ERR PREFIX |
| 245 | "finish-write timeout, command = %d\n", command); | 249 | "finish-write timeout, command = %d\n", command); |
| @@ -250,13 +254,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
| 250 | } | 254 | } |
| 251 | 255 | ||
| 252 | for (; rdata_len > 0; --rdata_len) { | 256 | for (; rdata_len > 0; --rdata_len) { |
| 253 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); | 257 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count); |
| 254 | if (result) { | 258 | if (result) { |
| 255 | printk(KERN_ERR PREFIX "read timeout, command = %d\n", | 259 | printk(KERN_ERR PREFIX "read timeout, command = %d\n", |
| 256 | command); | 260 | command); |
| 257 | goto end; | 261 | goto end; |
| 258 | } | 262 | } |
| 259 | 263 | count = atomic_read(&ec->event_count); | |
| 260 | *(rdata++) = acpi_ec_read_data(ec); | 264 | *(rdata++) = acpi_ec_read_data(ec); |
| 261 | } | 265 | } |
| 262 | end: | 266 | end: |
| @@ -288,7 +292,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, | |||
| 288 | /* Make sure GPE is enabled before doing transaction */ | 292 | /* Make sure GPE is enabled before doing transaction */ |
| 289 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 293 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); |
| 290 | 294 | ||
| 291 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); | 295 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); |
| 292 | if (status) { | 296 | if (status) { |
| 293 | printk(KERN_DEBUG PREFIX | 297 | printk(KERN_DEBUG PREFIX |
| 294 | "input buffer is not empty, aborting transaction\n"); | 298 | "input buffer is not empty, aborting transaction\n"); |
| @@ -369,8 +373,8 @@ int ec_write(u8 addr, u8 val) | |||
| 369 | EXPORT_SYMBOL(ec_write); | 373 | EXPORT_SYMBOL(ec_write); |
| 370 | 374 | ||
| 371 | int ec_transaction(u8 command, | 375 | int ec_transaction(u8 command, |
| 372 | const u8 * wdata, unsigned wdata_len, | 376 | const u8 * wdata, unsigned wdata_len, |
| 373 | u8 * rdata, unsigned rdata_len) | 377 | u8 * rdata, unsigned rdata_len) |
| 374 | { | 378 | { |
| 375 | struct acpi_ec *ec; | 379 | struct acpi_ec *ec; |
| 376 | 380 | ||
| @@ -435,7 +439,7 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
| 435 | acpi_status status = AE_OK; | 439 | acpi_status status = AE_OK; |
| 436 | u8 value; | 440 | u8 value; |
| 437 | struct acpi_ec *ec = (struct acpi_ec *)data; | 441 | struct acpi_ec *ec = (struct acpi_ec *)data; |
| 438 | 442 | atomic_inc(&ec->event_count); | |
| 439 | if (acpi_ec_mode == EC_INTR) { | 443 | if (acpi_ec_mode == EC_INTR) { |
| 440 | wake_up(&ec->wait); | 444 | wake_up(&ec->wait); |
| 441 | } | 445 | } |
| @@ -633,6 +637,7 @@ static int acpi_ec_add(struct acpi_device *device) | |||
| 633 | ec->uid = -1; | 637 | ec->uid = -1; |
| 634 | mutex_init(&ec->lock); | 638 | mutex_init(&ec->lock); |
| 635 | atomic_set(&ec->query_pending, 0); | 639 | atomic_set(&ec->query_pending, 0); |
| 640 | atomic_set(&ec->event_count, 1); | ||
| 636 | if (acpi_ec_mode == EC_INTR) { | 641 | if (acpi_ec_mode == EC_INTR) { |
| 637 | atomic_set(&ec->leaving_burst, 1); | 642 | atomic_set(&ec->leaving_burst, 1); |
| 638 | init_waitqueue_head(&ec->wait); | 643 | init_waitqueue_head(&ec->wait); |
| @@ -807,6 +812,7 @@ acpi_fake_ecdt_callback(acpi_handle handle, | |||
| 807 | acpi_status status; | 812 | acpi_status status; |
| 808 | 813 | ||
| 809 | mutex_init(&ec_ecdt->lock); | 814 | mutex_init(&ec_ecdt->lock); |
| 815 | atomic_set(&ec_ecdt->event_count, 1); | ||
| 810 | if (acpi_ec_mode == EC_INTR) { | 816 | if (acpi_ec_mode == EC_INTR) { |
| 811 | init_waitqueue_head(&ec_ecdt->wait); | 817 | init_waitqueue_head(&ec_ecdt->wait); |
| 812 | } | 818 | } |
| @@ -888,6 +894,7 @@ static int __init acpi_ec_get_real_ecdt(void) | |||
| 888 | return -ENOMEM; | 894 | return -ENOMEM; |
| 889 | 895 | ||
| 890 | mutex_init(&ec_ecdt->lock); | 896 | mutex_init(&ec_ecdt->lock); |
| 897 | atomic_set(&ec_ecdt->event_count, 1); | ||
| 891 | if (acpi_ec_mode == EC_INTR) { | 898 | if (acpi_ec_mode == EC_INTR) { |
| 892 | init_waitqueue_head(&ec_ecdt->wait); | 899 | init_waitqueue_head(&ec_ecdt->wait); |
| 893 | } | 900 | } |
| @@ -1016,8 +1023,7 @@ static int __init acpi_ec_set_intr_mode(char *str) | |||
| 1016 | acpi_ec_mode = EC_POLL; | 1023 | acpi_ec_mode = EC_POLL; |
| 1017 | } | 1024 | } |
| 1018 | acpi_ec_driver.ops.add = acpi_ec_add; | 1025 | acpi_ec_driver.ops.add = acpi_ec_add; |
| 1019 | printk(KERN_NOTICE PREFIX "%s mode.\n", | 1026 | printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling"); |
| 1020 | intr ? "interrupt" : "polling"); | ||
| 1021 | 1027 | ||
| 1022 | return 1; | 1028 | return 1; |
| 1023 | } | 1029 | } |
