diff options
-rw-r--r-- | drivers/acpi/ec.c | 59 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 1 |
2 files changed, 26 insertions, 34 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3c97122eacd7..89e89b21dd54 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -120,6 +120,8 @@ struct transaction { | |||
120 | u8 flags; | 120 | u8 flags; |
121 | }; | 121 | }; |
122 | 122 | ||
123 | static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data); | ||
124 | |||
123 | struct acpi_ec *boot_ec, *first_ec; | 125 | struct acpi_ec *boot_ec, *first_ec; |
124 | EXPORT_SYMBOL(first_ec); | 126 | EXPORT_SYMBOL(first_ec); |
125 | 127 | ||
@@ -189,6 +191,22 @@ static const char *acpi_ec_cmd_string(u8 cmd) | |||
189 | #define acpi_ec_cmd_string(cmd) "UNDEF" | 191 | #define acpi_ec_cmd_string(cmd) "UNDEF" |
190 | #endif | 192 | #endif |
191 | 193 | ||
194 | static void acpi_ec_submit_query(struct acpi_ec *ec) | ||
195 | { | ||
196 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { | ||
197 | pr_debug("***** Event started *****\n"); | ||
198 | schedule_work(&ec->work); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | static void acpi_ec_complete_query(struct acpi_ec *ec) | ||
203 | { | ||
204 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { | ||
205 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | ||
206 | pr_debug("***** Event stopped *****\n"); | ||
207 | } | ||
208 | } | ||
209 | |||
192 | static int ec_transaction_completed(struct acpi_ec *ec) | 210 | static int ec_transaction_completed(struct acpi_ec *ec) |
193 | { | 211 | { |
194 | unsigned long flags; | 212 | unsigned long flags; |
@@ -242,6 +260,7 @@ static void advance_transaction(struct acpi_ec *ec) | |||
242 | !(status & ACPI_EC_FLAG_SCI) && | 260 | !(status & ACPI_EC_FLAG_SCI) && |
243 | (t->command == ACPI_EC_COMMAND_QUERY)) { | 261 | (t->command == ACPI_EC_COMMAND_QUERY)) { |
244 | t->flags |= ACPI_EC_COMMAND_POLL; | 262 | t->flags |= ACPI_EC_COMMAND_POLL; |
263 | acpi_ec_complete_query(ec); | ||
245 | t->rdata[t->ri++] = 0x00; | 264 | t->rdata[t->ri++] = 0x00; |
246 | t->flags |= ACPI_EC_COMMAND_COMPLETE; | 265 | t->flags |= ACPI_EC_COMMAND_COMPLETE; |
247 | pr_debug("***** Command(%s) software completion *****\n", | 266 | pr_debug("***** Command(%s) software completion *****\n", |
@@ -250,6 +269,7 @@ static void advance_transaction(struct acpi_ec *ec) | |||
250 | } else if ((status & ACPI_EC_FLAG_IBF) == 0) { | 269 | } else if ((status & ACPI_EC_FLAG_IBF) == 0) { |
251 | acpi_ec_write_cmd(ec, t->command); | 270 | acpi_ec_write_cmd(ec, t->command); |
252 | t->flags |= ACPI_EC_COMMAND_POLL; | 271 | t->flags |= ACPI_EC_COMMAND_POLL; |
272 | acpi_ec_complete_query(ec); | ||
253 | } else | 273 | } else |
254 | goto err; | 274 | goto err; |
255 | goto out; | 275 | goto out; |
@@ -264,6 +284,8 @@ err: | |||
264 | ++t->irq_count; | 284 | ++t->irq_count; |
265 | } | 285 | } |
266 | out: | 286 | out: |
287 | if (status & ACPI_EC_FLAG_SCI) | ||
288 | acpi_ec_submit_query(ec); | ||
267 | if (wakeup && in_interrupt()) | 289 | if (wakeup && in_interrupt()) |
268 | wake_up(&ec->wait); | 290 | wake_up(&ec->wait); |
269 | } | 291 | } |
@@ -275,17 +297,6 @@ static void start_transaction(struct acpi_ec *ec) | |||
275 | advance_transaction(ec); | 297 | advance_transaction(ec); |
276 | } | 298 | } |
277 | 299 | ||
278 | static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data); | ||
279 | |||
280 | static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) | ||
281 | { | ||
282 | if (state & ACPI_EC_FLAG_SCI) { | ||
283 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) | ||
284 | return acpi_ec_sync_query(ec, NULL); | ||
285 | } | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int ec_poll(struct acpi_ec *ec) | 300 | static int ec_poll(struct acpi_ec *ec) |
290 | { | 301 | { |
291 | unsigned long flags; | 302 | unsigned long flags; |
@@ -333,10 +344,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
333 | pr_debug("***** Command(%s) started *****\n", | 344 | pr_debug("***** Command(%s) started *****\n", |
334 | acpi_ec_cmd_string(t->command)); | 345 | acpi_ec_cmd_string(t->command)); |
335 | start_transaction(ec); | 346 | start_transaction(ec); |
336 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { | ||
337 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | ||
338 | pr_debug("***** Event stopped *****\n"); | ||
339 | } | ||
340 | spin_unlock_irqrestore(&ec->lock, tmp); | 347 | spin_unlock_irqrestore(&ec->lock, tmp); |
341 | ret = ec_poll(ec); | 348 | ret = ec_poll(ec); |
342 | spin_lock_irqsave(&ec->lock, tmp); | 349 | spin_lock_irqsave(&ec->lock, tmp); |
@@ -376,8 +383,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | |||
376 | 383 | ||
377 | status = acpi_ec_transaction_unlocked(ec, t); | 384 | status = acpi_ec_transaction_unlocked(ec, t); |
378 | 385 | ||
379 | /* check if we received SCI during transaction */ | ||
380 | ec_check_sci_sync(ec, acpi_ec_read_status(ec)); | ||
381 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | 386 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
382 | msleep(1); | 387 | msleep(1); |
383 | /* It is safe to enable the GPE outside of the transaction. */ | 388 | /* It is safe to enable the GPE outside of the transaction. */ |
@@ -687,14 +692,12 @@ static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data) | |||
687 | return result; | 692 | return result; |
688 | } | 693 | } |
689 | 694 | ||
690 | static void acpi_ec_gpe_query(void *ec_cxt) | 695 | static void acpi_ec_gpe_poller(struct work_struct *work) |
691 | { | 696 | { |
692 | struct acpi_ec *ec = ec_cxt; | ||
693 | acpi_status status; | 697 | acpi_status status; |
694 | u32 glk; | 698 | u32 glk; |
699 | struct acpi_ec *ec = container_of(work, struct acpi_ec, work); | ||
695 | 700 | ||
696 | if (!ec) | ||
697 | return; | ||
698 | mutex_lock(&ec->mutex); | 701 | mutex_lock(&ec->mutex); |
699 | if (ec->global_lock) { | 702 | if (ec->global_lock) { |
700 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 703 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
@@ -708,18 +711,6 @@ unlock: | |||
708 | mutex_unlock(&ec->mutex); | 711 | mutex_unlock(&ec->mutex); |
709 | } | 712 | } |
710 | 713 | ||
711 | static int ec_check_sci(struct acpi_ec *ec, u8 state) | ||
712 | { | ||
713 | if (state & ACPI_EC_FLAG_SCI) { | ||
714 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { | ||
715 | pr_debug("***** Event started *****\n"); | ||
716 | return acpi_os_execute(OSL_NOTIFY_HANDLER, | ||
717 | acpi_ec_gpe_query, ec); | ||
718 | } | ||
719 | } | ||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, | 714 | static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, |
724 | u32 gpe_number, void *data) | 715 | u32 gpe_number, void *data) |
725 | { | 716 | { |
@@ -729,7 +720,6 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, | |||
729 | spin_lock_irqsave(&ec->lock, flags); | 720 | spin_lock_irqsave(&ec->lock, flags); |
730 | advance_transaction(ec); | 721 | advance_transaction(ec); |
731 | spin_unlock_irqrestore(&ec->lock, flags); | 722 | spin_unlock_irqrestore(&ec->lock, flags); |
732 | ec_check_sci(ec, acpi_ec_read_status(ec)); | ||
733 | return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE; | 723 | return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE; |
734 | } | 724 | } |
735 | 725 | ||
@@ -793,6 +783,7 @@ static struct acpi_ec *make_acpi_ec(void) | |||
793 | init_waitqueue_head(&ec->wait); | 783 | init_waitqueue_head(&ec->wait); |
794 | INIT_LIST_HEAD(&ec->list); | 784 | INIT_LIST_HEAD(&ec->list); |
795 | spin_lock_init(&ec->lock); | 785 | spin_lock_init(&ec->lock); |
786 | INIT_WORK(&ec->work, acpi_ec_gpe_poller); | ||
796 | return ec; | 787 | return ec; |
797 | } | 788 | } |
798 | 789 | ||
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 163e82f536fa..dc420787ffcd 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -127,6 +127,7 @@ struct acpi_ec { | |||
127 | struct list_head list; | 127 | struct list_head list; |
128 | struct transaction *curr; | 128 | struct transaction *curr; |
129 | spinlock_t lock; | 129 | spinlock_t lock; |
130 | struct work_struct work; | ||
130 | }; | 131 | }; |
131 | 132 | ||
132 | extern struct acpi_ec *first_ec; | 133 | extern struct acpi_ec *first_ec; |