From patchwork Fri Sep 2 07:46:54 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lv Zheng X-Patchwork-Id: 9310513 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 477CA608A0 for ; Fri, 2 Sep 2016 07:50:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3A821296CD for ; Fri, 2 Sep 2016 07:50:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2F116296D3; Fri, 2 Sep 2016 07:50:30 +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 0648F296D4 for ; Fri, 2 Sep 2016 07:50:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751902AbcIBHs2 (ORCPT ); Fri, 2 Sep 2016 03:48:28 -0400 Received: from mga05.intel.com ([192.55.52.43]:5320 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751845AbcIBHrA (ORCPT ); Fri, 2 Sep 2016 03:47:00 -0400 Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP; 02 Sep 2016 00:46:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.30,270,1470726000"; d="scan'208";a="3998088" Received: from lvzheng-z530.sh.intel.com ([10.239.159.35]) by orsmga005.jf.intel.com with ESMTP; 02 Sep 2016 00:46:57 -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 4/4] ACPI / EC: Fix issues related to boot_ec Date: Fri, 2 Sep 2016 15:46:54 +0800 Message-Id: <3a4239fb380e79f9209599ff387ce66e63425baf.1472802172.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 There are issues related to the boot_ec: 1. If acpi_ec_remove() is invoked, boot_ec will also be freed, this is not expected as the boot_ec could be enumerated via ECDT. 2. Address space handler installation/unstallation lead to unexpected _REG evaluations. This patch adds acpi_is_boot_ec() check to be used to fix the above issues. However, since acpi_ec_remove() actually won't be invoked, this patch doesn't handle the reference counting of "struct acpi_ec", it only ensures the correctness of the boot_ec destruction during the boot. Link: https://bugzilla.kernel.org/show_bug.cgi?id=153511 Reported-by: Cc: Signed-off-by: Lv Zheng --- drivers/acpi/ec.c | 63 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 847e665..ab784a6 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1461,6 +1461,37 @@ static int acpi_config_boot_ec(struct acpi_ec *ec, acpi_handle handle, return ret; } +static bool acpi_ec_ecdt_get_handle(acpi_handle *phandle) +{ + struct acpi_table_ecdt *ecdt_ptr; + acpi_status status; + acpi_handle handle; + + status = acpi_get_table(ACPI_SIG_ECDT, 1, + (struct acpi_table_header **)&ecdt_ptr); + if (ACPI_FAILURE(status)) + return false; + + status = acpi_get_handle(NULL, ecdt_ptr->id, &handle); + if (ACPI_FAILURE(status)) + return false; + + *phandle = handle; + return true; +} + +static bool acpi_is_boot_ec(struct acpi_ec *ec) +{ + if (!boot_ec) + return false; + if (ec->handle == boot_ec->handle && + ec->gpe == boot_ec->gpe && + ec->command_addr == boot_ec->command_addr && + ec->data_addr == boot_ec->data_addr) + return true; + return false; +} + static int acpi_ec_add(struct acpi_device *device) { struct acpi_ec *ec = NULL; @@ -1478,7 +1509,14 @@ static int acpi_ec_add(struct acpi_device *device) goto error; } - ret = acpi_config_boot_ec(ec, device->handle, true, false); + if (acpi_is_boot_ec(ec)) { + boot_ec_is_ecdt = false; + acpi_handle_debug(ec->handle, "duplicated.\n"); + acpi_ec_free(ec); + ec = boot_ec; + ret = acpi_config_boot_ec(ec, ec->handle, true, false); + } else + ret = acpi_ec_setup(ec, true); if (ret) goto error; @@ -1496,9 +1534,12 @@ static int acpi_ec_add(struct acpi_device *device) /* Clear stale _Q events if hardware might require that */ if (EC_FLAGS_CLEAR_ON_RESUME) acpi_ec_clear(ec); + acpi_handle_debug(ec->handle, "enumerated.\n"); error: - if (ret) - acpi_ec_free(ec); + if (ret) { + if (ec != boot_ec) + acpi_ec_free(ec); + } return ret; } @@ -1510,11 +1551,13 @@ static int acpi_ec_remove(struct acpi_device *device) return -EINVAL; ec = acpi_driver_data(device); - ec_remove_handlers(ec); release_region(ec->data_addr, 1); release_region(ec->command_addr, 1); device->driver_data = NULL; - acpi_ec_free(ec); + if (ec != boot_ec) { + ec_remove_handlers(ec); + acpi_ec_free(ec); + } return 0; } @@ -1586,8 +1629,6 @@ error: */ int __init acpi_ec_ecdt_start(void) { - struct acpi_table_ecdt *ecdt_ptr; - acpi_status status; acpi_handle handle; if (!boot_ec) @@ -1599,17 +1640,11 @@ int __init acpi_ec_ecdt_start(void) if (!boot_ec_is_ecdt) return -ENODEV; - status = acpi_get_table(ACPI_SIG_ECDT, 1, - (struct acpi_table_header **)&ecdt_ptr); - if (ACPI_FAILURE(status)) - return -ENODEV; - /* * At this point, the namespace and the GPE is initialized, so * start to find the namespace objects and handle the events. */ - status = acpi_get_handle(NULL, ecdt_ptr->id, &handle); - if (ACPI_FAILURE(status)) + if (!acpi_ec_ecdt_get_handle(&handle)) return -ENODEV; return acpi_config_boot_ec(boot_ec, handle, true, true); }