From patchwork Wed Aug 3 08:01:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lv Zheng X-Patchwork-Id: 9260899 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 08D8E60754 for ; Wed, 3 Aug 2016 08:14:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EEF1228402 for ; Wed, 3 Aug 2016 08:14:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E327928562; Wed, 3 Aug 2016 08:14:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6EC4528402 for ; Wed, 3 Aug 2016 08:14:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756979AbcHCIOS (ORCPT ); Wed, 3 Aug 2016 04:14:18 -0400 Received: from mga01.intel.com ([192.55.52.88]:45197 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756321AbcHCIOM (ORCPT ); Wed, 3 Aug 2016 04:14:12 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga101.fm.intel.com with ESMTP; 03 Aug 2016 01:01:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,465,1464678000"; d="scan'208";a="1007521784" Received: from lvzheng-z530.sh.intel.com ([10.239.159.127]) by orsmga001.jf.intel.com with ESMTP; 03 Aug 2016 01:01:30 -0700 From: Lv Zheng To: "Rafael J. Wysocki" , "Rafael J. Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , , linux-acpi@vger.kernel.org Subject: [PATCH v3 1/5] ACPI / EC: Add EC_FLAGS_QUERY_ENABLED to reveal a hidden logic Date: Wed, 3 Aug 2016 16:01:24 +0800 Message-Id: X-Mailer: git-send-email 1.7.10 In-Reply-To: References: Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There is a hidden logic in the EC driver: 1. During boot, EC_FLAGS_QUERY_PENDING is responsible for blocking event handling; 2. During suspend, EC_FLAGS_STARTED is responsible for blocking event handling. This patch uses a new EC_FLAGS_QUERY_ENABLED flag to make this hidden logic explicit and have code cleaned up. No functional change. Signed-off-by: Lv Zheng Tested-by: Todd E Brandt --- drivers/acpi/ec.c | 103 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 32 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 6f6c7d1..4ab34d7 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -104,6 +104,7 @@ enum ec_command { #define ACPI_EC_MAX_QUERIES 16 /* Maximum number of parallel queries */ enum { + EC_FLAGS_QUERY_ENABLED, /* Query is enabled */ EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_QUERY_GUARDING, /* Guard for SCI_EVT check */ EC_FLAGS_GPE_HANDLER_INSTALLED, /* GPE handler installed */ @@ -239,6 +240,22 @@ static bool acpi_ec_started(struct acpi_ec *ec) !test_bit(EC_FLAGS_STOPPED, &ec->flags); } +static bool acpi_ec_event_enabled(struct acpi_ec *ec) +{ + /* + * There is an OSPM early stage logic. During the early stages + * (boot/resume), OSPMs shouldn't enable the event handling, only + * the EC transactions are allowed to be performed. + */ + if (!test_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) + return false; + /* + * The EC event handling is automatically disabled as soon as the + * EC driver is stopped. + */ + return test_bit(EC_FLAGS_STARTED, &ec->flags); +} + static bool acpi_ec_flushed(struct acpi_ec *ec) { return ec->reference_count == 1; @@ -429,7 +446,8 @@ static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec) static void acpi_ec_submit_query(struct acpi_ec *ec) { - if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { + if (acpi_ec_event_enabled(ec) && + !test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { ec_dbg_evt("Command(%s) submitted/blocked", acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); ec->nr_pending_queries++; @@ -446,6 +464,52 @@ static void acpi_ec_complete_query(struct acpi_ec *ec) } } +static inline void __acpi_ec_enable_event(struct acpi_ec *ec) +{ + if (!test_and_set_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) + ec_log_drv("event unblocked"); +} + +static inline void __acpi_ec_disable_event(struct acpi_ec *ec) +{ + if (test_and_clear_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) + ec_log_drv("event blocked"); +} + +/* + * Process _Q events that might have accumulated in the EC. + * Run with locked ec mutex. + */ +static void acpi_ec_clear(struct acpi_ec *ec) +{ + int i, status; + u8 value = 0; + + for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) { + status = acpi_ec_query(ec, &value); + if (status || !value) + break; + } + if (unlikely(i == ACPI_EC_CLEAR_MAX)) + pr_warn("Warning: Maximum of %d stale EC events cleared\n", i); + else + pr_info("%d stale EC events cleared\n", i); +} + +static void acpi_ec_enable_event(struct acpi_ec *ec) +{ + unsigned long flags; + + spin_lock_irqsave(&ec->lock, flags); + if (acpi_ec_started(ec)) + __acpi_ec_enable_event(ec); + spin_unlock_irqrestore(&ec->lock, flags); + + /* Drain additional events if hardware requires that */ + if (EC_FLAGS_CLEAR_ON_RESUME) + acpi_ec_clear(ec); +} + static bool acpi_ec_guard_event(struct acpi_ec *ec) { bool guarded = true; @@ -832,27 +896,6 @@ acpi_handle ec_get_handle(void) } EXPORT_SYMBOL(ec_get_handle); -/* - * Process _Q events that might have accumulated in the EC. - * Run with locked ec mutex. - */ -static void acpi_ec_clear(struct acpi_ec *ec) -{ - int i, status; - u8 value = 0; - - for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) { - status = acpi_ec_query(ec, &value); - if (status || !value) - break; - } - - if (unlikely(i == ACPI_EC_CLEAR_MAX)) - pr_warn("Warning: Maximum of %d stale EC events cleared\n", i); - else - pr_info("%d stale EC events cleared\n", i); -} - static void acpi_ec_start(struct acpi_ec *ec, bool resuming) { unsigned long flags; @@ -864,7 +907,8 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming) if (!resuming) { acpi_ec_submit_request(ec); ec_dbg_ref(ec, "Increase driver"); - } + } else + __acpi_ec_enable_event(ec); ec_log_drv("EC started"); } spin_unlock_irqrestore(&ec->lock, flags); @@ -896,7 +940,8 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending) if (!suspending) { acpi_ec_complete_request(ec); ec_dbg_ref(ec, "Decrease driver"); - } + } else + __acpi_ec_disable_event(ec); clear_bit(EC_FLAGS_STARTED, &ec->flags); clear_bit(EC_FLAGS_STOPPED, &ec->flags); ec_log_drv("EC stopped"); @@ -927,8 +972,7 @@ void acpi_ec_unblock_transactions(void) /* Allow transactions to be carried out again */ acpi_ec_start(ec, true); - if (EC_FLAGS_CLEAR_ON_RESUME) - acpi_ec_clear(ec); + acpi_ec_enable_event(ec); } void acpi_ec_unblock_transactions_early(void) @@ -1234,7 +1278,6 @@ static struct acpi_ec *make_acpi_ec(void) if (!ec) return NULL; - ec->flags = 1 << EC_FLAGS_QUERY_PENDING; mutex_init(&ec->mutex); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); @@ -1421,11 +1464,7 @@ static int acpi_ec_add(struct acpi_device *device) acpi_walk_dep_device_list(ec->handle); /* EC is fully operational, allow queries */ - clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - - /* Clear stale _Q events if hardware might require that */ - if (EC_FLAGS_CLEAR_ON_RESUME) - acpi_ec_clear(ec); + acpi_ec_enable_event(ec); return ret; } From patchwork Wed Aug 3 08:01:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lv Zheng X-Patchwork-Id: 9260873 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1B73460754 for ; Wed, 3 Aug 2016 08:11:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0E4B928562 for ; Wed, 3 Aug 2016 08:11:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0274928565; Wed, 3 Aug 2016 08:11:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6DF2A28562 for ; Wed, 3 Aug 2016 08:11:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755568AbcHCILY (ORCPT ); Wed, 3 Aug 2016 04:11:24 -0400 Received: from mga11.intel.com ([192.55.52.93]:60556 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755215AbcHCILT (ORCPT ); Wed, 3 Aug 2016 04:11:19 -0400 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP; 03 Aug 2016 01:01:38 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,465,1464678000"; d="scan'208";a="1018774246" Received: from lvzheng-z530.sh.intel.com ([10.239.159.127]) by fmsmga001.fm.intel.com with ESMTP; 03 Aug 2016 01:01:35 -0700 From: Lv Zheng To: "Rafael J. Wysocki" , "Rafael J. Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , , linux-acpi@vger.kernel.org Subject: [PATCH v3 2/5] ACPI / EC: Fix an issue that SCI_EVT cannot be detected after event is enabled Date: Wed, 3 Aug 2016 16:01:30 +0800 Message-Id: <061fb2fc7b9e0ca8ff0324afabdfc80bc10582f1.1470205312.git.lv.zheng@intel.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: References: Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP After enabling the EC event handling, Linux is still in the noirq stage, if there is no triggering source (EC transaction, GPE STS status), advance_transaction() will not be invoked and SCI_EVT cannot be detected. This patch adds one more triggering source after enabling the EC event handling to poll the pending SCI_EVT. Known issues: 1. Still no SCI_EVT triggering source There could still be no SCI_EVT triggering source after handling the first SCI_EVT (polled by this patch if any). Because after handling the first SCI_EVT, Linux could still be in noirq stage and there could still be no further triggering source in this stage. Then the second SCI_EVT indicated during this stage still cannot be detected by the EC driver. With this improvement applied, it is then possible to move acpi_ec_enable_event() out of the noirq stage to fix this issue (if the first SCI_EVT is handled out of the noirq stage, the follow-up SCI_EVTs should be able to trigger IRQs). Signed-off-by: Lv Zheng Tested-by: Todd E Brandt --- drivers/acpi/ec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 4ab34d7..79305be 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -468,6 +468,8 @@ static inline void __acpi_ec_enable_event(struct acpi_ec *ec) { if (!test_and_set_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) ec_log_drv("event unblocked"); + if (!test_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) + advance_transaction(ec); } static inline void __acpi_ec_disable_event(struct acpi_ec *ec) From patchwork Wed Aug 3 08:01:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lv Zheng X-Patchwork-Id: 9260877 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 62EC360754 for ; Wed, 3 Aug 2016 08:11:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 561C128560 for ; Wed, 3 Aug 2016 08:11:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4ABF028563; Wed, 3 Aug 2016 08:11:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 35A2728560 for ; Wed, 3 Aug 2016 08:11:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756902AbcHCILm (ORCPT ); Wed, 3 Aug 2016 04:11:42 -0400 Received: from mga09.intel.com ([134.134.136.24]:31535 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755055AbcHCILT (ORCPT ); Wed, 3 Aug 2016 04:11:19 -0400 Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP; 03 Aug 2016 01:01:43 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,465,1464678000"; d="scan'208";a="858827427" Received: from lvzheng-z530.sh.intel.com ([10.239.159.127]) by orsmga003.jf.intel.com with ESMTP; 03 Aug 2016 01:01:41 -0700 From: Lv Zheng To: "Rafael J. Wysocki" , "Rafael J. Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , , linux-acpi@vger.kernel.org Subject: [PATCH v3 3/5] ACPI / EC: Add PM operations to improve event handling for resume process Date: Wed, 3 Aug 2016 16:01:36 +0800 Message-Id: <5c03ecd25ac597f807b2c2dd9935e6a2aca629f8.1470205312.git.lv.zheng@intel.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: References: Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch makes 2 changes: 1. Restore old behavior Originally, EC driver stops handling both events and transactions in acpi_ec_block_transactions(), and restarts to handle transactions in acpi_ec_unblock_transactions_early(), restarts to handle both events and transactions in acpi_ec_unblock_transactions(). While currently, EC driver still stops handling both events and transactions in acpi_ec_block_transactions(), but restarts to handle both events and transactions in acpi_ec_unblock_transactions_early(). This patch tries to restore the old behavior by dropping __acpi_ec_enable_event() from acpi_unblock_transactions_early(). 2. Improve old behavior However this still cannot fix the real issue as both of the acpi_ec_unblock_xxx() functions are invoked in the noirq stage. Since the EC driver actually doesn't implement the event handling in the polling mode, re-enabling the event handling too early in the noirq stage could result in the problem that if there is no triggering source causing advance_transaction() to be invoked, pending SCI_EVT cannot be detected by the EC driver and _Qxx cannot be triggered. It actually makes sense to restart the event handling in any point during resuming after the noirq stage. Just like the boot stage where the event handling is enabled in .add(), this patch further moves acpi_ec_enable_event() to .resume(). After doing that, the following 2 functions can be combined: acpi_ec_unblock_transactions_early()/acpi_ec_unblock_transactions(). The differences of the event handling availability between the old behavior (this patch isn't applied) and the new behavior (this patch is applied) are as follows: !Applied Applied before suspend Y Y suspend before EC Y Y suspend after EC Y Y suspend_late Y Y suspend_noirq Y (actually N) Y (actually N) resume_noirq Y (actually N) Y (actually N) resume_late Y (actually N) Y (actually N) resume before EC Y (actually N) Y (actually N) resume after EC Y (actually N) Y after resume Y (actually N) Y Where "actually N" means if there is no triggering source, the EC driver is actually not able to notice the pending SCI_EVT occurred in the noirq stage. So we can clearly see that this patch has improved the situation. Signed-off-by: Lv Zheng Tested-by: Todd E Brandt --- drivers/acpi/ec.c | 26 +++++++++++--------------- drivers/acpi/internal.h | 1 - drivers/acpi/sleep.c | 4 ++-- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 79305be..8d5444d 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -909,8 +909,7 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming) if (!resuming) { acpi_ec_submit_request(ec); ec_dbg_ref(ec, "Increase driver"); - } else - __acpi_ec_enable_event(ec); + } ec_log_drv("EC started"); } spin_unlock_irqrestore(&ec->lock, flags); @@ -966,19 +965,6 @@ void acpi_ec_block_transactions(void) void acpi_ec_unblock_transactions(void) { - struct acpi_ec *ec = first_ec; - - if (!ec) - return; - - /* Allow transactions to be carried out again */ - acpi_ec_start(ec, true); - - acpi_ec_enable_event(ec); -} - -void acpi_ec_unblock_transactions_early(void) -{ /* * Allow transactions to happen again (this function is called from * atomic context during wakeup, so we don't need to acquire the mutex). @@ -1706,10 +1692,20 @@ static int acpi_ec_resume_noirq(struct device *dev) acpi_ec_leave_noirq(ec); return 0; } + +static int acpi_ec_resume(struct device *dev) +{ + struct acpi_ec *ec = + acpi_driver_data(to_acpi_device(dev)); + + acpi_ec_enable_event(ec); + return 0; +} #endif static const struct dev_pm_ops acpi_ec_pm = { SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend_noirq, acpi_ec_resume_noirq) + SET_SYSTEM_SLEEP_PM_OPS(NULL, acpi_ec_resume) }; static int param_set_event_clearing(const char *val, struct kernel_param *kp) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 6996121..29f2063 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -189,7 +189,6 @@ int acpi_ec_ecdt_probe(void); int acpi_ec_dsdt_probe(void); void acpi_ec_block_transactions(void); void acpi_ec_unblock_transactions(void); -void acpi_ec_unblock_transactions_early(void); int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, acpi_handle handle, acpi_ec_query_func func, void *data); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 9788663..deb0ff7 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -586,7 +586,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) */ acpi_disable_all_gpes(); /* Allow EC transactions to happen. */ - acpi_ec_unblock_transactions_early(); + acpi_ec_unblock_transactions(); suspend_nvs_restore(); @@ -784,7 +784,7 @@ static void acpi_hibernation_leave(void) /* Restore the NVS memory area */ suspend_nvs_restore(); /* Allow EC transactions to happen. */ - acpi_ec_unblock_transactions_early(); + acpi_ec_unblock_transactions(); } static void acpi_pm_thaw(void) From patchwork Wed Aug 3 08:01:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lv Zheng X-Patchwork-Id: 9260937 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 41D0660754 for ; Wed, 3 Aug 2016 08:59:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2ECE428566 for ; Wed, 3 Aug 2016 08:59:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 213272857A; Wed, 3 Aug 2016 08:59:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8EEA228566 for ; Wed, 3 Aug 2016 08:59:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752463AbcHCI7h (ORCPT ); Wed, 3 Aug 2016 04:59:37 -0400 Received: from mga14.intel.com ([192.55.52.115]:14923 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752647AbcHCI7e (ORCPT ); Wed, 3 Aug 2016 04:59:34 -0400 Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP; 03 Aug 2016 01:01:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,465,1464678000"; d="scan'208";a="149821673" Received: from lvzheng-z530.sh.intel.com ([10.239.159.127]) by fmsmga004.fm.intel.com with ESMTP; 03 Aug 2016 01:01:49 -0700 From: Lv Zheng To: "Rafael J. Wysocki" , "Rafael J. Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , , linux-acpi@vger.kernel.org Subject: [PATCH v3 4/5] ACPI / EC: Add PM operations to improve event handling for suspend process Date: Wed, 3 Aug 2016 16:01:43 +0800 Message-Id: X-Mailer: git-send-email 1.7.10 In-Reply-To: References: Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In the original EC driver, though the event handling is not explicitly stopped, the EC driver is actually not able to handle events during the noirq stage as the EC driver is not prepared to handle the EC events in the polling mode. So if there is no advance_transaction() triggered, the EC driver couldn't notice the EC events. However, do we actually need to handle EC events during suspend/resume stage? EC events are mostly useless for the suspend/resume period (key strokes and battery/thermal updates, etc.,), and the useful ones (lid close, power/sleep button press) should have already been delivered to the OSPM to trigger the power saving operations. Thus this patch implements acpi_ec_disable_event() to be a reverse call of acpi_ec_enable_event(), with which, the EC driver is able to stop handling the EC events in a position before entering the noirq stage. Since there are actually 2 choices for us: 1. implement event handling in polling mode; 2. stop event handling before entering noirq stage. And this patch only implements the second choice using .suspend() callback. Thus this is experimental (first choice is better? or different hook position is better?). This patch finally keeps the old behavior by default and prepares a boot parameter to enable this feature. The differences of the event handling availability between the old behavior (this patch is not applied) and the new behavior (this patch is applied) are as follows: !FreezeEvents FreezeEvents before suspend Y Y suspend before EC Y Y suspend after EC Y N suspend_late Y N suspend_noirq Y (actually N) N resume_noirq Y (actually N) N resume_late Y (actually N) N resume before EC Y (actually N) N resume after EC Y Y after resume Y Y Where "actually N" means if there is no EC transactions, the EC driver is actually not able to notice the pending events. We can see that FreezeEvents is the only approach now can actually flush the EC event handling with both query commands and _Qxx evaluations flushed, other modes can only flush the EC event handling with only query commands flushed, _Qxx evaluations occurred after stopping the EC driver may end up failure due to the failure of the EC transaction carried out in the _Qxx control methods. We also can see that this feature should be able to trigger some platform notifications later than resuming other drivers. Signed-off-by: Lv Zheng Tested-by: Todd E Brandt --- drivers/acpi/ec.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 8d5444d..2bec709 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -146,6 +146,10 @@ static unsigned int ec_storm_threshold __read_mostly = 8; module_param(ec_storm_threshold, uint, 0644); MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm"); +static bool ec_freeze_events __read_mostly = false; +module_param(ec_freeze_events, bool, 0644); +MODULE_PARM_DESC(ec_freeze_events, "Disabling event handling during suspend/resume"); + struct acpi_ec_query_handler { struct list_head node; acpi_ec_query_func func; @@ -250,10 +254,18 @@ static bool acpi_ec_event_enabled(struct acpi_ec *ec) if (!test_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) return false; /* - * The EC event handling is automatically disabled as soon as the - * EC driver is stopped. + * However, disabling the event handling is experimental for late + * stage (suspend), and is controlled by the boot parameter of + * "ec_freeze_events": + * 1. true: The EC event handling is disabled before entering + * the noirq stage. + * 2. false: The EC event handling is automatically disabled as + * soon as the EC driver is stopped. */ - return test_bit(EC_FLAGS_STARTED, &ec->flags); + if (ec_freeze_events) + return acpi_ec_started(ec); + else + return test_bit(EC_FLAGS_STARTED, &ec->flags); } static bool acpi_ec_flushed(struct acpi_ec *ec) @@ -512,6 +524,38 @@ static void acpi_ec_enable_event(struct acpi_ec *ec) acpi_ec_clear(ec); } +static bool acpi_ec_query_flushed(struct acpi_ec *ec) +{ + bool flushed; + unsigned long flags; + + spin_lock_irqsave(&ec->lock, flags); + flushed = !ec->nr_pending_queries; + spin_unlock_irqrestore(&ec->lock, flags); + return flushed; +} + +static void __acpi_ec_flush_event(struct acpi_ec *ec) +{ + /* + * When ec_freeze_events is true, we need to flush events in + * the proper position before entering the noirq stage. + */ + wait_event(ec->wait, acpi_ec_query_flushed(ec)); + if (ec_query_wq) + flush_workqueue(ec_query_wq); +} + +static void acpi_ec_disable_event(struct acpi_ec *ec) +{ + unsigned long flags; + + spin_lock_irqsave(&ec->lock, flags); + __acpi_ec_disable_event(ec); + spin_unlock_irqrestore(&ec->lock, flags); + __acpi_ec_flush_event(ec); +} + static bool acpi_ec_guard_event(struct acpi_ec *ec) { bool guarded = true; @@ -941,7 +985,7 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending) if (!suspending) { acpi_ec_complete_request(ec); ec_dbg_ref(ec, "Decrease driver"); - } else + } else if (!ec_freeze_events) __acpi_ec_disable_event(ec); clear_bit(EC_FLAGS_STARTED, &ec->flags); clear_bit(EC_FLAGS_STOPPED, &ec->flags); @@ -1693,6 +1737,16 @@ static int acpi_ec_resume_noirq(struct device *dev) return 0; } +static int acpi_ec_suspend(struct device *dev) +{ + struct acpi_ec *ec = + acpi_driver_data(to_acpi_device(dev)); + + if (ec_freeze_events) + acpi_ec_disable_event(ec); + return 0; +} + static int acpi_ec_resume(struct device *dev) { struct acpi_ec *ec = @@ -1705,7 +1759,7 @@ static int acpi_ec_resume(struct device *dev) static const struct dev_pm_ops acpi_ec_pm = { SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend_noirq, acpi_ec_resume_noirq) - SET_SYSTEM_SLEEP_PM_OPS(NULL, acpi_ec_resume) + SET_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend, acpi_ec_resume) }; static int param_set_event_clearing(const char *val, struct kernel_param *kp) From patchwork Wed Aug 3 08:01:50 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lv Zheng X-Patchwork-Id: 9260891 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 45B3E60754 for ; Wed, 3 Aug 2016 08:14:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 380D328560 for ; Wed, 3 Aug 2016 08:14:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2B42C28563; Wed, 3 Aug 2016 08:14:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A905A28560 for ; Wed, 3 Aug 2016 08:14:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755350AbcHCIOP (ORCPT ); Wed, 3 Aug 2016 04:14:15 -0400 Received: from mga04.intel.com ([192.55.52.120]:22676 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756523AbcHCIOM (ORCPT ); Wed, 3 Aug 2016 04:14:12 -0400 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga104.fm.intel.com with ESMTP; 03 Aug 2016 01:01:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,465,1464678000"; d="scan'208";a="1018774427" Received: from lvzheng-z530.sh.intel.com ([10.239.159.127]) by fmsmga001.fm.intel.com with ESMTP; 03 Aug 2016 01:01:56 -0700 From: Lv Zheng To: "Rafael J. Wysocki" , "Rafael J. Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , , linux-acpi@vger.kernel.org Subject: [PATCH v3 5/5] ACPI / EC: Enable event freeze mode to improve event handling for suspend process Date: Wed, 3 Aug 2016 16:01:50 +0800 Message-Id: X-Mailer: git-send-email 1.7.10 In-Reply-To: References: Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch enables the event freeze mode, flushing the EC event handling in .suspend() callback. This feature is experimental, if it is bisected out to be the cause of the real issues, please report the issues to the kernel bugzilla for further root causing and improvement. This mode eliminates useless _Qxx handling during the power saving operations, thus can help to tune the power saving operations faster. Tests show that this mode can efficiently block flooding _Qxx during the suspend process and tune the speed of the suspend faster. Signed-off-by: Lv Zheng Tested-by: Todd E Brandt --- drivers/acpi/ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 2bec709..1925589 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -146,7 +146,7 @@ static unsigned int ec_storm_threshold __read_mostly = 8; module_param(ec_storm_threshold, uint, 0644); MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm"); -static bool ec_freeze_events __read_mostly = false; +static bool ec_freeze_events __read_mostly = true; module_param(ec_freeze_events, bool, 0644); MODULE_PARM_DESC(ec_freeze_events, "Disabling event handling during suspend/resume");