aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c69
1 files changed, 42 insertions, 27 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index d7a6bbbb834c..f2234db85da0 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -39,6 +39,7 @@
39#include <linux/interrupt.h> 39#include <linux/interrupt.h>
40#include <linux/list.h> 40#include <linux/list.h>
41#include <linux/spinlock.h> 41#include <linux/spinlock.h>
42#include <linux/slab.h>
42#include <asm/io.h> 43#include <asm/io.h>
43#include <acpi/acpi_bus.h> 44#include <acpi/acpi_bus.h>
44#include <acpi/acpi_drivers.h> 45#include <acpi/acpi_drivers.h>
@@ -76,8 +77,9 @@ enum ec_command {
76enum { 77enum {
77 EC_FLAGS_QUERY_PENDING, /* Query is pending */ 78 EC_FLAGS_QUERY_PENDING, /* Query is pending */
78 EC_FLAGS_GPE_STORM, /* GPE storm detected */ 79 EC_FLAGS_GPE_STORM, /* GPE storm detected */
79 EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and 80 EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and
80 * OpReg are installed */ 81 * OpReg are installed */
82 EC_FLAGS_FROZEN, /* Transactions are suspended */
81}; 83};
82 84
83/* If we find an EC via the ECDT, we need to keep a ptr to its context */ 85/* If we find an EC via the ECDT, we need to keep a ptr to its context */
@@ -291,6 +293,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
291 if (t->rdata) 293 if (t->rdata)
292 memset(t->rdata, 0, t->rlen); 294 memset(t->rdata, 0, t->rlen);
293 mutex_lock(&ec->lock); 295 mutex_lock(&ec->lock);
296 if (test_bit(EC_FLAGS_FROZEN, &ec->flags)) {
297 status = -EINVAL;
298 goto unlock;
299 }
294 if (ec->global_lock) { 300 if (ec->global_lock) {
295 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); 301 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
296 if (ACPI_FAILURE(status)) { 302 if (ACPI_FAILURE(status)) {
@@ -453,6 +459,32 @@ int ec_transaction(u8 command,
453 459
454EXPORT_SYMBOL(ec_transaction); 460EXPORT_SYMBOL(ec_transaction);
455 461
462void acpi_ec_suspend_transactions(void)
463{
464 struct acpi_ec *ec = first_ec;
465
466 if (!ec)
467 return;
468
469 mutex_lock(&ec->lock);
470 /* Prevent transactions from being carried out */
471 set_bit(EC_FLAGS_FROZEN, &ec->flags);
472 mutex_unlock(&ec->lock);
473}
474
475void acpi_ec_resume_transactions(void)
476{
477 struct acpi_ec *ec = first_ec;
478
479 if (!ec)
480 return;
481
482 mutex_lock(&ec->lock);
483 /* Allow transactions to be carried out again */
484 clear_bit(EC_FLAGS_FROZEN, &ec->flags);
485 mutex_unlock(&ec->lock);
486}
487
456static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) 488static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
457{ 489{
458 int result; 490 int result;
@@ -597,12 +629,12 @@ static u32 acpi_ec_gpe_handler(void *data)
597 629
598static acpi_status 630static acpi_status
599acpi_ec_space_handler(u32 function, acpi_physical_address address, 631acpi_ec_space_handler(u32 function, acpi_physical_address address,
600 u32 bits, u64 *value, 632 u32 bits, u64 *value64,
601 void *handler_context, void *region_context) 633 void *handler_context, void *region_context)
602{ 634{
603 struct acpi_ec *ec = handler_context; 635 struct acpi_ec *ec = handler_context;
604 int result = 0, i; 636 int result = 0, i, bytes = bits / 8;
605 u8 temp = 0; 637 u8 *value = (u8 *)value64;
606 638
607 if ((address > 0xFF) || !value || !handler_context) 639 if ((address > 0xFF) || !value || !handler_context)
608 return AE_BAD_PARAMETER; 640 return AE_BAD_PARAMETER;
@@ -610,32 +642,15 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
610 if (function != ACPI_READ && function != ACPI_WRITE) 642 if (function != ACPI_READ && function != ACPI_WRITE)
611 return AE_BAD_PARAMETER; 643 return AE_BAD_PARAMETER;
612 644
613 if (bits != 8 && acpi_strict) 645 if (EC_FLAGS_MSI || bits > 8)
614 return AE_BAD_PARAMETER;
615
616 if (EC_FLAGS_MSI)
617 acpi_ec_burst_enable(ec); 646 acpi_ec_burst_enable(ec);
618 647
619 if (function == ACPI_READ) { 648 for (i = 0; i < bytes; ++i, ++address, ++value)
620 result = acpi_ec_read(ec, address, &temp); 649 result = (function == ACPI_READ) ?
621 *value = temp; 650 acpi_ec_read(ec, address, value) :
622 } else { 651 acpi_ec_write(ec, address, *value);
623 temp = 0xff & (*value);
624 result = acpi_ec_write(ec, address, temp);
625 }
626 652
627 for (i = 8; unlikely(bits - i > 0); i += 8) { 653 if (EC_FLAGS_MSI || bits > 8)
628 ++address;
629 if (function == ACPI_READ) {
630 result = acpi_ec_read(ec, address, &temp);
631 (*value) |= ((u64)temp) << i;
632 } else {
633 temp = 0xff & ((*value) >> i);
634 result = acpi_ec_write(ec, address, temp);
635 }
636 }
637
638 if (EC_FLAGS_MSI)
639 acpi_ec_burst_disable(ec); 654 acpi_ec_burst_disable(ec);
640 655
641 switch (result) { 656 switch (result) {