From 1abe11687b55b34c5cb86cd69dba5bc56c4213a9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 21 Jan 2010 14:19:47 -0800 Subject: [PATCH] some more .32 patches --- .../acpi-ec-accelerate-query-execution.patch | 228 ++++++++++++++++++ .../acpi-ec-add-wait-for-irq-storm.patch | 51 ++++ queue-2.6.32/series | 2 + 3 files changed, 281 insertions(+) create mode 100644 queue-2.6.32/acpi-ec-accelerate-query-execution.patch create mode 100644 queue-2.6.32/acpi-ec-add-wait-for-irq-storm.patch diff --git a/queue-2.6.32/acpi-ec-accelerate-query-execution.patch b/queue-2.6.32/acpi-ec-accelerate-query-execution.patch new file mode 100644 index 00000000000..aeaf635fcb7 --- /dev/null +++ b/queue-2.6.32/acpi-ec-accelerate-query-execution.patch @@ -0,0 +1,228 @@ +From a62e8f1978f49e52f87a711ff6711b323d4b12ff Mon Sep 17 00:00:00 2001 +From: Alexey Starikovskiy +Date: Thu, 24 Dec 2009 11:34:16 +0300 +Subject: ACPI: EC: Accelerate query execution + +From: Alexey Starikovskiy + +commit a62e8f1978f49e52f87a711ff6711b323d4b12ff upstream. + +Split EC query handling into acknowledge and execution phase. +This allows much smaller pending query lattency and lowers chances +of EC going "wild" and losing events. + +Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14858 + +Signed-off-by: Alexey Starikovskiy +Signed-off-by: Len Brown +Cc: François Valenduc +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/ec.c | 122 ++++++++++++++++++++++++++++++++++-------------------- + 1 file changed, 77 insertions(+), 45 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -201,14 +201,13 @@ unlock: + spin_unlock_irqrestore(&ec->curr_lock, flags); + } + +-static void acpi_ec_gpe_query(void *ec_cxt); ++static int acpi_ec_sync_query(struct acpi_ec *ec); + +-static int ec_check_sci(struct acpi_ec *ec, u8 state) ++static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) + { + if (state & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) +- return acpi_os_execute(OSL_EC_BURST_HANDLER, +- acpi_ec_gpe_query, ec); ++ return acpi_ec_sync_query(ec); + } + return 0; + } +@@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked( + { + unsigned long tmp; + int ret = 0; +- pr_debug(PREFIX "transaction start\n"); +- /* disable GPE during transaction if storm is detected */ +- if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { +- acpi_disable_gpe(NULL, ec->gpe); +- } + if (EC_FLAGS_MSI) + udelay(ACPI_EC_MSI_UDELAY); + /* start transaction */ +@@ -269,16 +263,6 @@ static int acpi_ec_transaction_unlocked( + spin_lock_irqsave(&ec->curr_lock, tmp); + ec->curr = NULL; + spin_unlock_irqrestore(&ec->curr_lock, tmp); +- if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { +- /* check if we received SCI during transaction */ +- ec_check_sci(ec, acpi_ec_read_status(ec)); +- /* it is safe to enable GPE outside of transaction */ +- acpi_enable_gpe(NULL, ec->gpe); +- } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { +- pr_info(PREFIX "GPE storm detected, " +- "transactions will use polling mode\n"); +- set_bit(EC_FLAGS_GPE_STORM, &ec->flags); +- } + return ret; + } + +@@ -321,7 +305,24 @@ static int acpi_ec_transaction(struct ac + status = -ETIME; + goto end; + } ++ pr_debug(PREFIX "transaction start\n"); ++ /* disable GPE during transaction if storm is detected */ ++ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { ++ 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)) { ++ /* it is safe to enable GPE outside of transaction */ ++ acpi_enable_gpe(NULL, ec->gpe); ++ } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { ++ pr_info(PREFIX "GPE storm detected, " ++ "transactions will use polling mode\n"); ++ set_bit(EC_FLAGS_GPE_STORM, &ec->flags); ++ } + end: + if (ec->global_lock) + acpi_release_global_lock(glk); +@@ -443,7 +444,7 @@ int ec_transaction(u8 command, + + EXPORT_SYMBOL(ec_transaction); + +-static int acpi_ec_query(struct acpi_ec *ec, u8 * data) ++static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) + { + int result; + u8 d; +@@ -452,20 +453,16 @@ static int acpi_ec_query(struct acpi_ec + .wlen = 0, .rlen = 1}; + if (!ec || !data) + return -EINVAL; +- + /* + * Query the EC to find out which _Qxx method we need to evaluate. + * Note that successful completion of the query causes the ACPI_EC_SCI + * bit to be cleared (and thus clearing the interrupt source). + */ +- +- result = acpi_ec_transaction(ec, &t); ++ result = acpi_ec_transaction_unlocked(ec, &t); + if (result) + return result; +- + if (!d) + return -ENODATA; +- + *data = d; + return 0; + } +@@ -509,43 +506,78 @@ void acpi_ec_remove_query_handler(struct + + EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); + +-static void acpi_ec_gpe_query(void *ec_cxt) ++static void acpi_ec_run(void *cxt) + { +- struct acpi_ec *ec = ec_cxt; +- u8 value = 0; +- struct acpi_ec_query_handler *handler, copy; +- +- if (!ec || acpi_ec_query(ec, &value)) ++ struct acpi_ec_query_handler *handler = cxt; ++ if (!handler) + return; +- mutex_lock(&ec->lock); ++ pr_debug(PREFIX "start query execution\n"); ++ if (handler->func) ++ handler->func(handler->data); ++ else if (handler->handle) ++ acpi_evaluate_object(handler->handle, NULL, NULL, NULL); ++ pr_debug(PREFIX "stop query execution\n"); ++ kfree(handler); ++} ++ ++static int acpi_ec_sync_query(struct acpi_ec *ec) ++{ ++ u8 value = 0; ++ int status; ++ struct acpi_ec_query_handler *handler, *copy; ++ if ((status = acpi_ec_query_unlocked(ec, &value))) ++ return status; + list_for_each_entry(handler, &ec->list, node) { + if (value == handler->query_bit) { + /* have custom handler for this bit */ +- memcpy(©, handler, sizeof(copy)); +- mutex_unlock(&ec->lock); +- if (copy.func) { +- copy.func(copy.data); +- } else if (copy.handle) { +- acpi_evaluate_object(copy.handle, NULL, NULL, NULL); +- } +- return; ++ copy = kmalloc(sizeof(*handler), GFP_KERNEL); ++ if (!copy) ++ return -ENOMEM; ++ memcpy(copy, handler, sizeof(*copy)); ++ pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); ++ return acpi_os_execute(OSL_GPE_HANDLER, ++ acpi_ec_run, copy); + } + } ++ return 0; ++} ++ ++static void acpi_ec_gpe_query(void *ec_cxt) ++{ ++ struct acpi_ec *ec = ec_cxt; ++ if (!ec) ++ return; ++ mutex_lock(&ec->lock); ++ acpi_ec_sync_query(ec); + mutex_unlock(&ec->lock); + } + ++static void acpi_ec_gpe_query(void *ec_cxt); ++ ++static int ec_check_sci(struct acpi_ec *ec, u8 state) ++{ ++ if (state & ACPI_EC_FLAG_SCI) { ++ if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { ++ pr_debug(PREFIX "push gpe query to the queue\n"); ++ return acpi_os_execute(OSL_NOTIFY_HANDLER, ++ acpi_ec_gpe_query, ec); ++ } ++ } ++ return 0; ++} ++ + static u32 acpi_ec_gpe_handler(void *data) + { + struct acpi_ec *ec = data; +- u8 status; + + pr_debug(PREFIX "~~~> interrupt\n"); +- status = acpi_ec_read_status(ec); + +- advance_transaction(ec, status); +- if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) ++ advance_transaction(ec, acpi_ec_read_status(ec)); ++ if (ec_transaction_done(ec) && ++ (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { + wake_up(&ec->wait); +- ec_check_sci(ec, status); ++ ec_check_sci(ec, acpi_ec_read_status(ec)); ++ } + return ACPI_INTERRUPT_HANDLED; + } + diff --git a/queue-2.6.32/acpi-ec-add-wait-for-irq-storm.patch b/queue-2.6.32/acpi-ec-add-wait-for-irq-storm.patch new file mode 100644 index 00000000000..eac7fd8b3d3 --- /dev/null +++ b/queue-2.6.32/acpi-ec-add-wait-for-irq-storm.patch @@ -0,0 +1,51 @@ +From 54070101f86ca9a6e9ba243c999d144721ec3db7 Mon Sep 17 00:00:00 2001 +From: Alexey Starikovskiy +Date: Wed, 30 Dec 2009 15:53:10 +0300 +Subject: ACPI: EC: Add wait for irq storm + +From: Alexey Starikovskiy + +commit 54070101f86ca9a6e9ba243c999d144721ec3db7 upstream. + +Merge of poll and irq modes accelerated EC transaction, so +that keyboard starts to suffer again. Add msleep(1) into +transaction path for the storm to allow keyboard controller +to do its job. + +Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14747 + +Signed-off-by: Alexey Starikovskiy +Signed-off-by: Len Brown +Cc: François Valenduc +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/ec.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -259,7 +259,6 @@ static int acpi_ec_transaction_unlocked( + clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); + spin_unlock_irqrestore(&ec->curr_lock, tmp); + ret = ec_poll(ec); +- pr_debug(PREFIX "transaction end\n"); + spin_lock_irqsave(&ec->curr_lock, tmp); + ec->curr = NULL; + spin_unlock_irqrestore(&ec->curr_lock, tmp); +@@ -316,6 +315,7 @@ static int acpi_ec_transaction(struct ac + /* 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 GPE outside of transaction */ + acpi_enable_gpe(NULL, ec->gpe); + } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { +@@ -323,6 +323,7 @@ static int acpi_ec_transaction(struct ac + "transactions will use polling mode\n"); + set_bit(EC_FLAGS_GPE_STORM, &ec->flags); + } ++ pr_debug(PREFIX "transaction end\n"); + end: + if (ec->global_lock) + acpi_release_global_lock(glk); diff --git a/queue-2.6.32/series b/queue-2.6.32/series index 94feae3d94d..87916b3ac6c 100644 --- a/queue-2.6.32/series +++ b/queue-2.6.32/series @@ -14,3 +14,5 @@ usb-ehci-fix-handling-of-unusual-interrupt-intervals.patch usb-ehci-uhci-fix-race-between-root-hub-suspend-and-port-resume.patch usb-add-missing-delay-during-remote-wakeup.patch usb-add-speed-values-for-usb-3.0-and-wireless-controllers.patch +acpi-ec-accelerate-query-execution.patch +acpi-ec-add-wait-for-irq-storm.patch -- 2.47.3