diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 4799ea0..92058a1 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -129,6 +129,29 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
 static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
 
 /* --------------------------------------------------------------------------
+                             GPE Enhancement
+   -------------------------------------------------------------------------- */
+
+static bool acpi_gpe_disabled(acpi_handle handle, u32 gpe_number)
+{
+	acpi_event_status event_status = 0;
+
+	(void)acpi_get_gpe_status(NULL, gpe_number, &event_status);
+	return !(event_status & ACPI_EVENT_FLAG_ENABLED);
+}
+
+static bool acpi_ec_disable_gpe(struct acpi_ec *ec)
+{
+	bool disabled;
+
+	acpi_disable_gpe(NULL, ec->gpe);
+	disabled = acpi_gpe_disabled(NULL, ec->gpe);
+	if (disabled)
+		wake_up(&ec->wait);
+	return disabled;
+}
+
+/* --------------------------------------------------------------------------
                              Transaction Management
    -------------------------------------------------------------------------- */
 
@@ -314,16 +337,33 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
 	}
 	/* following two actions should be kept atomic */
 	ec->curr = t;
+	/* Enable GPE for command processing (IBF=0/OBF=1) */
+	acpi_enable_gpe(NULL, ec->gpe);
 	pr_debug("***** Command(%s) started *****\n",
 		 acpi_ec_cmd_string(t->command));
+	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+		pr_debug("+++++ Polling enabled +++++\n");
+		acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
+	}
 	start_transaction(ec);
 	if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
 		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
 	spin_unlock_irqrestore(&ec->lock, tmp);
 	ret = ec_poll(ec);
 	spin_lock_irqsave(&ec->lock, tmp);
+	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+		clear_bit(EC_FLAGS_GPE_STORM, &ec->flags);
+		acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
+		pr_debug("+++++ Polling disabled +++++\n");
+	} else if (t->irq_count > ec_storm_threshold) {
+		pr_debug("+++++ Polling scheduled (%d GPE) +++++\n",
+			 t->irq_count);
+		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
+	}
 	pr_debug("***** Command(%s) stopped *****\n",
 		 acpi_ec_cmd_string(t->command));
+	/* Disable GPE for command processing (IBF=0/OBF=1) */
+	acpi_ec_disable_gpe(ec);
 	ec->curr = NULL;
 unlock:
 	spin_unlock_irqrestore(&ec->lock, tmp);
@@ -346,26 +386,11 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
 			goto unlock;
 		}
 	}
-	/* disable GPE during transaction if storm is detected */
-	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
-		/* It has to be disabled, so that it doesn't trigger. */
-		acpi_disable_gpe(NULL, ec->gpe);
-	}
 
 	status = acpi_ec_transaction_unlocked(ec, t);
 
 	/* check if we received SCI during transaction */
 	ec_check_sci_sync(ec, acpi_ec_read_status(ec));
-	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
-		msleep(1);
-		/* It is safe to enable the GPE outside of the transaction. */
-		acpi_enable_gpe(NULL, ec->gpe);
-	} else if (t->irq_count > ec_storm_threshold) {
-		pr_info("GPE storm detected(%d GPEs), "
-			"transactions will use polling mode\n",
-			t->irq_count);
-		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
-	}
 	if (ec->global_lock)
 		acpi_release_global_lock(glk);
 unlock:
@@ -500,9 +525,25 @@ static void acpi_ec_start(struct acpi_ec *ec)
 	unsigned long flags;
 
 	spin_lock_irqsave(&ec->lock, flags);
-	if (!test_and_set_bit(EC_FLAGS_STARTED, &ec->flags))
+	if (!test_and_set_bit(EC_FLAGS_STARTED, &ec->flags)) {
+		pr_debug("+++++ Starting EC +++++\n");
+		/* Enable GPE for event processing (EVT_SCI=1) */
 		acpi_enable_gpe(NULL, ec->gpe);
+		pr_info("+++++ EC started +++++\n");
+	}
+	spin_unlock_irqrestore(&ec->lock, flags);
+}
+
+static bool acpi_ec_stopped(struct acpi_ec *ec)
+{
+	unsigned long flags;
+	bool disabled = false;
+
+	spin_lock_irqsave(&ec->lock, flags);
+	disabled = acpi_gpe_disabled(NULL, ec->gpe);
 	spin_unlock_irqrestore(&ec->lock, flags);
+
+	return disabled;
 }
 
 static void acpi_ec_stop(struct acpi_ec *ec)
@@ -512,9 +553,16 @@ static void acpi_ec_stop(struct acpi_ec *ec)
 	spin_lock_irqsave(&ec->lock, flags);
 	if (test_bit(EC_FLAGS_STARTED, &ec->flags) &&
 	    !test_and_set_bit(EC_FLAGS_STOPPED, &ec->flags)) {
-		acpi_disable_gpe(NULL, ec->gpe);
+		pr_debug("+++++ Stopping EC +++++\n");
+		/* Disable GPE for event processing (EVT_SCI=1) */
+		if (!acpi_ec_disable_gpe(ec)) {
+			spin_unlock_irqrestore(&ec->lock, flags);
+			wait_event(ec->wait, acpi_ec_stopped(ec));
+			spin_lock_irqsave(&ec->lock, flags);
+		}
 		clear_bit(EC_FLAGS_STARTED, &ec->flags);
 		clear_bit(EC_FLAGS_STOPPED, &ec->flags);
+		pr_info("+++++ EC stopped +++++\n");
 	}
 	spin_unlock_irqrestore(&ec->lock, flags);
 }
