From patchwork Wed Jun 21 08:55:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lv Zheng X-Patchwork-Id: 9801223 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 9925D60329 for ; Wed, 21 Jun 2017 08:57:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8765026E16 for ; Wed, 21 Jun 2017 08:57:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7B74B28516; Wed, 21 Jun 2017 08:57:07 +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 E356726E16 for ; Wed, 21 Jun 2017 08:57:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752604AbdFUI4p (ORCPT ); Wed, 21 Jun 2017 04:56:45 -0400 Received: from mga01.intel.com ([192.55.52.88]:47840 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752839AbdFUIz1 (ORCPT ); Wed, 21 Jun 2017 04:55:27 -0400 Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 21 Jun 2017 01:55:26 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.39,368,1493708400"; d="scan'208";a="100046941" Received: from unknown (HELO lvzheng-MOBLsp3.sh.intel.com) ([10.239.159.55]) by orsmga004.jf.intel.com with ESMTP; 21 Jun 2017 01:55:24 -0700 From: Lv Zheng To: "Rafael J . Wysocki" , "Rafael J . Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, Benjamin Tissoires Subject: [RFC PATCH v6 4/5] ACPI: button: extract input creation/destruction helpers Date: Wed, 21 Jun 2017 16:55:23 +0800 Message-Id: X-Mailer: git-send-email 2.7.4 In-Reply-To: References: <2a779ae8c280c968b3237ac4a3d9580df7262a46.1493951798.git.lv.zheng@intel.com> 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 From: Benjamin Tissoires When the LID switch ACPI implementation is unreliable, we might want to remove the device when we are not sure about the state. This should prevent any suspend/resume loops given that in that case, there will be no more LID switch input node. This patch prepares the dynamic creation/destruction of the input node. Signed-off-by: Benjamin Tissoires Signed-off-by: Lv Zheng --- drivers/acpi/button.c | 86 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 1256a8c..91c9989 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -302,6 +302,54 @@ int acpi_lid_open(void) } EXPORT_SYMBOL(acpi_lid_open); +static void acpi_button_remove_input(struct acpi_device *device) +{ + struct acpi_button *button = acpi_driver_data(device); + + input_unregister_device(button->input); + button->input = NULL; +} + +static int acpi_button_add_input(struct acpi_device *device) +{ + struct acpi_button *button = acpi_driver_data(device); + struct input_dev *input; + int error; + + input = input_allocate_device(); + if (!input) { + error = -ENOMEM; + goto err; + } + + input->name = acpi_device_name(device); + input->phys = button->phys; + input->id.bustype = BUS_HOST; + input->id.product = button->type; + input->dev.parent = &device->dev; + switch (button->type) { + case ACPI_BUTTON_TYPE_POWER: + input_set_capability(input, EV_KEY, KEY_POWER); + break; + case ACPI_BUTTON_TYPE_SLEEP: + input_set_capability(input, EV_KEY, KEY_SLEEP); + break; + case ACPI_BUTTON_TYPE_LID: + input_set_capability(input, EV_SW, SW_LID); + break; + } + + error = input_register_device(input); + if (error) + goto err; + + button->input = input; + return 0; + err: + input_free_device(input); + return error; +} + static int acpi_lid_update_state(struct acpi_device *device) { int state; @@ -414,7 +462,6 @@ static int acpi_button_resume(struct device *dev) static int acpi_button_add(struct acpi_device *device) { struct acpi_button *button; - struct input_dev *input; const char *hid = acpi_device_hid(device); char *name, *class; int error; @@ -425,12 +472,6 @@ static int acpi_button_add(struct acpi_device *device) device->driver_data = button; - button->input = input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto err_free_button; - } - name = acpi_device_name(device); class = acpi_device_class(device); @@ -457,38 +498,19 @@ static int acpi_button_add(struct acpi_device *device) } else { printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid); error = -ENODEV; - goto err_free_input; + goto err_free_button; } error = acpi_button_add_fs(device); if (error) - goto err_free_input; + goto err_free_button; snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid); - input->name = name; - input->phys = button->phys; - input->id.bustype = BUS_HOST; - input->id.product = button->type; - input->dev.parent = &device->dev; - - switch (button->type) { - case ACPI_BUTTON_TYPE_POWER: - input_set_capability(input, EV_KEY, KEY_POWER); - break; - - case ACPI_BUTTON_TYPE_SLEEP: - input_set_capability(input, EV_KEY, KEY_SLEEP); - break; - - case ACPI_BUTTON_TYPE_LID: - input_set_capability(input, EV_SW, SW_LID); - break; - } - - error = input_register_device(input); + error = acpi_button_add_input(device); if (error) goto err_remove_fs; + if (button->type == ACPI_BUTTON_TYPE_LID) { /* * This assumes there's only one lid device, or if there are @@ -507,8 +529,6 @@ static int acpi_button_add(struct acpi_device *device) err_remove_fs: acpi_button_remove_fs(device); - err_free_input: - input_free_device(input); err_free_button: kfree(button); return error; @@ -521,7 +541,7 @@ static int acpi_button_remove(struct acpi_device *device) acpi_button_remove_fs(device); if (button->type == ACPI_BUTTON_TYPE_LID) del_timer_sync(&button->lid_timer); - input_unregister_device(button->input); + acpi_button_remove_input(device); kfree(button); return 0; }