aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2015-02-05 19:57:52 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-02-06 09:48:09 -0500
commitad479e7f47ca09c3f3190603ead4d01cf8fe6fa8 (patch)
treeb9a5d11f9b458363e610c28ad83f98e886a3b2b5 /drivers/acpi/ec.c
parenta8d4fc227f312edea06bb4ebbeeb6db89c798e91 (diff)
ACPI / EC: Introduce STARTED/STOPPED flags to replace BLOCKED flag
By using the 2 flags, we can indicate an inter-mediate state where the current transactions should be completed while the new transactions should be dropped. The comparison of the old flag and the new flags: Old New about to set BLOCKED STOPPED set / STARTED set BLOCKED set STOPPED clear / STARTED clear BLOCKED clear STOPPED clear / STARTED set A new period can be indicated by the 2 flags. The new period is between the point where we are about to set BLOCKED and the point when the BLOCKED is set. The new flags facilitate us with acpi_ec_started() check to allow the EC transaction to be submitted during the new period. This period thus can be used as a grace period for the EC transaction flushing. The only functional change after applying this patch is: 1. The GPE enabling/disabling is protected by the EC specific lock. We can do this because of recent ACPICA GPE API enhancement. This is reasonable as the GPE disabling/enabling state should only be determined by the EC driver's state machine which is protected by the EC spinlock. Signed-off-by: Lv Zheng <lv.zheng@intel.com> Tested-by: Ortwin Glück <odi@odi.ch> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c65
1 files changed, 54 insertions, 11 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 55632539392d..a6179b71c573 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -80,7 +80,8 @@ enum {
80 EC_FLAGS_GPE_STORM, /* GPE storm detected */ 80 EC_FLAGS_GPE_STORM, /* GPE storm detected */
81 EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and 81 EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and
82 * OpReg are installed */ 82 * OpReg are installed */
83 EC_FLAGS_BLOCKED, /* Transactions are blocked */ 83 EC_FLAGS_STARTED, /* Driver is started */
84 EC_FLAGS_STOPPED, /* Driver is stopped */
84}; 85};
85 86
86#define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */ 87#define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */
@@ -135,6 +136,16 @@ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
135static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */ 136static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
136 137
137/* -------------------------------------------------------------------------- 138/* --------------------------------------------------------------------------
139 * Device Flags
140 * -------------------------------------------------------------------------- */
141
142static bool acpi_ec_started(struct acpi_ec *ec)
143{
144 return test_bit(EC_FLAGS_STARTED, &ec->flags) &&
145 !test_bit(EC_FLAGS_STOPPED, &ec->flags);
146}
147
148/* --------------------------------------------------------------------------
138 * EC Registers 149 * EC Registers
139 * -------------------------------------------------------------------------- */ 150 * -------------------------------------------------------------------------- */
140 151
@@ -415,6 +426,10 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
415 udelay(ACPI_EC_MSI_UDELAY); 426 udelay(ACPI_EC_MSI_UDELAY);
416 /* start transaction */ 427 /* start transaction */
417 spin_lock_irqsave(&ec->lock, tmp); 428 spin_lock_irqsave(&ec->lock, tmp);
429 if (!acpi_ec_started(ec)) {
430 ret = -EINVAL;
431 goto unlock;
432 }
418 /* following two actions should be kept atomic */ 433 /* following two actions should be kept atomic */
419 ec->curr = t; 434 ec->curr = t;
420 pr_debug("***** Command(%s) started *****\n", 435 pr_debug("***** Command(%s) started *****\n",
@@ -426,6 +441,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
426 pr_debug("***** Command(%s) stopped *****\n", 441 pr_debug("***** Command(%s) stopped *****\n",
427 acpi_ec_cmd_string(t->command)); 442 acpi_ec_cmd_string(t->command));
428 ec->curr = NULL; 443 ec->curr = NULL;
444unlock:
429 spin_unlock_irqrestore(&ec->lock, tmp); 445 spin_unlock_irqrestore(&ec->lock, tmp);
430 return ret; 446 return ret;
431} 447}
@@ -440,10 +456,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
440 if (t->rdata) 456 if (t->rdata)
441 memset(t->rdata, 0, t->rlen); 457 memset(t->rdata, 0, t->rlen);
442 mutex_lock(&ec->mutex); 458 mutex_lock(&ec->mutex);
443 if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) {
444 status = -EINVAL;
445 goto unlock;
446 }
447 if (ec->global_lock) { 459 if (ec->global_lock) {
448 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); 460 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
449 if (ACPI_FAILURE(status)) { 461 if (ACPI_FAILURE(status)) {
@@ -595,6 +607,37 @@ static void acpi_ec_clear(struct acpi_ec *ec)
595 pr_info("%d stale EC events cleared\n", i); 607 pr_info("%d stale EC events cleared\n", i);
596} 608}
597 609
610static void acpi_ec_start(struct acpi_ec *ec, bool resuming)
611{
612 unsigned long flags;
613
614 spin_lock_irqsave(&ec->lock, flags);
615 if (!test_and_set_bit(EC_FLAGS_STARTED, &ec->flags)) {
616 pr_debug("+++++ Starting EC +++++\n");
617 if (!resuming)
618 acpi_ec_enable_gpe(ec, true);
619 pr_info("+++++ EC started +++++\n");
620 }
621 spin_unlock_irqrestore(&ec->lock, flags);
622}
623
624static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
625{
626 unsigned long flags;
627
628 spin_lock_irqsave(&ec->lock, flags);
629 if (acpi_ec_started(ec)) {
630 pr_debug("+++++ Stopping EC +++++\n");
631 set_bit(EC_FLAGS_STOPPED, &ec->flags);
632 if (!suspending)
633 acpi_ec_disable_gpe(ec, true);
634 clear_bit(EC_FLAGS_STARTED, &ec->flags);
635 clear_bit(EC_FLAGS_STOPPED, &ec->flags);
636 pr_info("+++++ EC stopped +++++\n");
637 }
638 spin_unlock_irqrestore(&ec->lock, flags);
639}
640
598void acpi_ec_block_transactions(void) 641void acpi_ec_block_transactions(void)
599{ 642{
600 struct acpi_ec *ec = first_ec; 643 struct acpi_ec *ec = first_ec;
@@ -604,7 +647,7 @@ void acpi_ec_block_transactions(void)
604 647
605 mutex_lock(&ec->mutex); 648 mutex_lock(&ec->mutex);
606 /* Prevent transactions from being carried out */ 649 /* Prevent transactions from being carried out */
607 set_bit(EC_FLAGS_BLOCKED, &ec->flags); 650 acpi_ec_stop(ec, true);
608 mutex_unlock(&ec->mutex); 651 mutex_unlock(&ec->mutex);
609} 652}
610 653
@@ -616,7 +659,7 @@ void acpi_ec_unblock_transactions(void)
616 return; 659 return;
617 660
618 /* Allow transactions to be carried out again */ 661 /* Allow transactions to be carried out again */
619 clear_bit(EC_FLAGS_BLOCKED, &ec->flags); 662 acpi_ec_start(ec, true);
620 663
621 if (EC_FLAGS_CLEAR_ON_RESUME) 664 if (EC_FLAGS_CLEAR_ON_RESUME)
622 acpi_ec_clear(ec); 665 acpi_ec_clear(ec);
@@ -629,7 +672,7 @@ void acpi_ec_unblock_transactions_early(void)
629 * atomic context during wakeup, so we don't need to acquire the mutex). 672 * atomic context during wakeup, so we don't need to acquire the mutex).
630 */ 673 */
631 if (first_ec) 674 if (first_ec)
632 clear_bit(EC_FLAGS_BLOCKED, &first_ec->flags); 675 acpi_ec_start(first_ec, true);
633} 676}
634 677
635/* -------------------------------------------------------------------------- 678/* --------------------------------------------------------------------------
@@ -894,7 +937,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
894 if (ACPI_FAILURE(status)) 937 if (ACPI_FAILURE(status))
895 return -ENODEV; 938 return -ENODEV;
896 939
897 acpi_ec_enable_gpe(ec, true); 940 acpi_ec_start(ec, false);
898 status = acpi_install_address_space_handler(ec->handle, 941 status = acpi_install_address_space_handler(ec->handle,
899 ACPI_ADR_SPACE_EC, 942 ACPI_ADR_SPACE_EC,
900 &acpi_ec_space_handler, 943 &acpi_ec_space_handler,
@@ -909,7 +952,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
909 pr_err("Fail in evaluating the _REG object" 952 pr_err("Fail in evaluating the _REG object"
910 " of EC device. Broken bios is suspected.\n"); 953 " of EC device. Broken bios is suspected.\n");
911 } else { 954 } else {
912 acpi_ec_disable_gpe(ec, true); 955 acpi_ec_stop(ec, false);
913 acpi_remove_gpe_handler(NULL, ec->gpe, 956 acpi_remove_gpe_handler(NULL, ec->gpe,
914 &acpi_ec_gpe_handler); 957 &acpi_ec_gpe_handler);
915 return -ENODEV; 958 return -ENODEV;
@@ -924,7 +967,7 @@ static void ec_remove_handlers(struct acpi_ec *ec)
924{ 967{
925 if (!test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) 968 if (!test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
926 return; 969 return;
927 acpi_ec_disable_gpe(ec, true); 970 acpi_ec_stop(ec, false);
928 if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, 971 if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
929 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) 972 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
930 pr_err("failed to remove space handler\n"); 973 pr_err("failed to remove space handler\n");