aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFeng Tang <feng.tang@intel.com>2012-09-28 03:22:00 -0400
committerLen Brown <len.brown@intel.com>2012-10-06 14:53:10 -0400
commita520d52e99b14ba7db135e916348f12f2a6e09be (patch)
tree286c64629a828c802ca25fd92a14322bc74fde02
parenta0d271cbfed1dd50278c6b06bead3d00ba0a88f9 (diff)
ACPI: EC: Make the GPE storm threshold a module parameter
The Linux EC driver includes a mechanism to detect GPE storms, and switch from interrupt-mode to polling mode. However, polling mode sometimes doesn't work, so the workaround is problematic. Also, different systems seem to need the threshold for detecting the GPE storm at different levels. ACPI_EC_STORM_THRESHOLD was initially 20 when it's created, and was changed to 8 in 2.6.28 commit 06cf7d3c7 "ACPI: EC: lower interrupt storm threshold" to fix kernel bug 11892 by forcing the laptop in that bug to work in polling mode. However in bug 45151, it works fine in interrupt mode if we lift the threshold back to 20. This patch makes the threshold a module parameter so that user has a flexible option to debug/workaround this issue. The default is unchanged. This is also a preparation patch to fix specific systems: https://bugzilla.kernel.org/show_bug.cgi?id=45151 Signed-off-by: Feng Tang <feng.tang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com> cc: stable@vger.kernel.org
-rw-r--r--drivers/acpi/ec.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 7edaccce6640..615264c89c31 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -71,9 +71,6 @@ enum ec_command {
71#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ 71#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
72#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ 72#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */
73 73
74#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts
75 per one transaction */
76
77enum { 74enum {
78 EC_FLAGS_QUERY_PENDING, /* Query is pending */ 75 EC_FLAGS_QUERY_PENDING, /* Query is pending */
79 EC_FLAGS_GPE_STORM, /* GPE storm detected */ 76 EC_FLAGS_GPE_STORM, /* GPE storm detected */
@@ -87,6 +84,15 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
87module_param(ec_delay, uint, 0644); 84module_param(ec_delay, uint, 0644);
88MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); 85MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
89 86
87/*
88 * If the number of false interrupts per one transaction exceeds
89 * this threshold, will think there is a GPE storm happened and
90 * will disable the GPE for normal transaction.
91 */
92static unsigned int ec_storm_threshold __read_mostly = 8;
93module_param(ec_storm_threshold, uint, 0644);
94MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
95
90/* If we find an EC via the ECDT, we need to keep a ptr to its context */ 96/* If we find an EC via the ECDT, we need to keep a ptr to its context */
91/* External interfaces use first EC only, so remember */ 97/* External interfaces use first EC only, so remember */
92typedef int (*acpi_ec_query_func) (void *data); 98typedef int (*acpi_ec_query_func) (void *data);
@@ -319,7 +325,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
319 msleep(1); 325 msleep(1);
320 /* It is safe to enable the GPE outside of the transaction. */ 326 /* It is safe to enable the GPE outside of the transaction. */
321 acpi_enable_gpe(NULL, ec->gpe); 327 acpi_enable_gpe(NULL, ec->gpe);
322 } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { 328 } else if (t->irq_count > ec_storm_threshold) {
323 pr_info(PREFIX "GPE storm detected, " 329 pr_info(PREFIX "GPE storm detected, "
324 "transactions will use polling mode\n"); 330 "transactions will use polling mode\n");
325 set_bit(EC_FLAGS_GPE_STORM, &ec->flags); 331 set_bit(EC_FLAGS_GPE_STORM, &ec->flags);