From patchwork Thu Mar 24 02:42:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lv Zheng X-Patchwork-Id: 8656631 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id DF8969F3D1 for ; Thu, 24 Mar 2016 02:43:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E13F5202B8 for ; Thu, 24 Mar 2016 02:43:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 228DC20374 for ; Thu, 24 Mar 2016 02:43:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932148AbcCXCmu (ORCPT ); Wed, 23 Mar 2016 22:42:50 -0400 Received: from mga14.intel.com ([192.55.52.115]:37332 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755524AbcCXCmt (ORCPT ); Wed, 23 Mar 2016 22:42:49 -0400 Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP; 23 Mar 2016 19:42:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.24,383,1455004800"; d="scan'208";a="72207122" Received: from lvzheng-z530.sh.intel.com ([10.239.159.153]) by fmsmga004.fm.intel.com with ESMTP; 23 Mar 2016 19:42:47 -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 1/4] ACPI 2.0 / ECDT: Split EC_FLAGS_HANDLERS_INSTALLED Date: Thu, 24 Mar 2016 10:42:47 +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-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch splits EC_FLAGS_HANDLERS_INSTALLED so that address space handler can be installed when it is not possible to install GPE handler during early stage. This patch also tunes address space handler installation, making it happening earlier than GPE handler installation for the same purpose. Since acpi_ec_start()/acpi_ec_stop() will be entered multiple times after applying this change, it is also required to protect acpi_enable_gpe()/ acpi_disable_gpe() invocations. Link: https://bugzilla.kernel.org/show_bug.cgi?id=112911 Signed-off-by: Lv Zheng Tested-by: Chris Bainbridge --- drivers/acpi/ec.c | 96 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index b420fb4..b8f474b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -105,8 +105,8 @@ enum ec_command { enum { EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_QUERY_GUARDING, /* Guard for SCI_EVT check */ - EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and - * OpReg are installed */ + EC_FLAGS_GPE_HANDLER_INSTALLED, /* GPE handler installed */ + EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */ EC_FLAGS_STARTED, /* Driver is started */ EC_FLAGS_STOPPED, /* Driver is stopped */ EC_FLAGS_COMMAND_STORM, /* GPE storms occurred to the @@ -367,7 +367,8 @@ static inline void acpi_ec_clear_gpe(struct acpi_ec *ec) static void acpi_ec_submit_request(struct acpi_ec *ec) { ec->reference_count++; - if (ec->reference_count == 1) + if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) && + ec->reference_count == 1) acpi_ec_enable_gpe(ec, true); } @@ -376,7 +377,8 @@ static void acpi_ec_complete_request(struct acpi_ec *ec) bool flushed = false; ec->reference_count--; - if (ec->reference_count == 0) + if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) && + ec->reference_count == 0) acpi_ec_disable_gpe(ec, true); flushed = acpi_ec_flushed(ec); if (flushed) @@ -1287,52 +1289,64 @@ static int ec_install_handlers(struct acpi_ec *ec) { acpi_status status; - if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) - return 0; - status = acpi_install_gpe_raw_handler(NULL, ec->gpe, - ACPI_GPE_EDGE_TRIGGERED, - &acpi_ec_gpe_handler, ec); - if (ACPI_FAILURE(status)) - return -ENODEV; - acpi_ec_start(ec, false); - status = acpi_install_address_space_handler(ec->handle, - ACPI_ADR_SPACE_EC, - &acpi_ec_space_handler, - NULL, ec); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_FOUND) { - /* - * Maybe OS fails in evaluating the _REG object. - * The AE_NOT_FOUND error will be ignored and OS - * continue to initialize EC. - */ - pr_err("Fail in evaluating the _REG object" - " of EC device. Broken bios is suspected.\n"); - } else { - acpi_ec_stop(ec, false); - acpi_remove_gpe_handler(NULL, ec->gpe, - &acpi_ec_gpe_handler); - return -ENODEV; + + if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { + status = acpi_install_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, + &acpi_ec_space_handler, + NULL, ec); + if (ACPI_FAILURE(status)) { + if (status == AE_NOT_FOUND) { + /* + * Maybe OS fails in evaluating the _REG + * object. The AE_NOT_FOUND error will be + * ignored and OS * continue to initialize + * EC. + */ + pr_err("Fail in evaluating the _REG object" + " of EC device. Broken bios is suspected.\n"); + } else { + acpi_ec_stop(ec, false); + return -ENODEV; + } + } + set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags); + } + + if (!test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) { + status = acpi_install_gpe_raw_handler(NULL, ec->gpe, + ACPI_GPE_EDGE_TRIGGERED, + &acpi_ec_gpe_handler, ec); + /* This is not fatal as we can poll EC events */ + if (ACPI_SUCCESS(status)) { + set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags); + if (test_bit(EC_FLAGS_STARTED, &ec->flags) && + ec->reference_count >= 1) + acpi_ec_enable_gpe(ec, true); } } - set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); return 0; } static void ec_remove_handlers(struct acpi_ec *ec) { - if (!test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) - return; acpi_ec_stop(ec, false); - if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, - ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) - pr_err("failed to remove space handler\n"); - if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, - &acpi_ec_gpe_handler))) - pr_err("failed to remove gpe handler\n"); - clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); + + if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { + if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) + pr_err("failed to remove space handler\n"); + clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags); + } + + if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) { + if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, + &acpi_ec_gpe_handler))) + pr_err("failed to remove gpe handler\n"); + clear_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags); + } } static int acpi_ec_add(struct acpi_device *device) @@ -1434,7 +1448,7 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context) int __init acpi_boot_ec_enable(void) { - if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags)) + if (!boot_ec) return 0; if (!ec_install_handlers(boot_ec)) { first_ec = boot_ec;