From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lv Zheng Subject: [RFC PATCH v3 4/5] ACPI: button: Fix lid notification Date: Sat, 27 May 2017 07:42:49 +0800 Message-ID: References: <2a779ae8c280c968b3237ac4a3d9580df7262a46.1493951798.git.lv.zheng@intel.com> Return-path: Received: from mga01.intel.com ([192.55.52.88]:50118 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1948848AbdEZXkn (ORCPT ); Fri, 26 May 2017 19:40:43 -0400 In-Reply-To: <2a779ae8c280c968b3237ac4a3d9580df7262a46.1493951798.git.lv.zheng@intel.com> Sender: linux-acpi-owner@vger.kernel.org List-Id: linux-acpi@vger.kernel.org To: "Rafael J. Wysocki" , "Rafael J. Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, Peter Hutterer , Benjamin Tissoires In acpi_lid_notify_state(), it now contains logic to avoid frequently replayed events which originally was ensured by using blocking notifier. On the contrary, using blocking notifier is wrong as it could keep on returning NOTIFY_DONE, causing events lost. This patch thus changes lid notification to raw notifier in order not to have events lost. Cc: Peter Hutterer Cc: Benjamin Tissoires Signed-off-by: Lv Zheng --- drivers/acpi/button.c | 53 ++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index d3f90c6..4abf8ae 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -112,7 +112,7 @@ struct acpi_button { bool suspended; }; -static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); +static RAW_NOTIFIER_HEAD(acpi_lid_notifier); static struct acpi_device *lid_device; static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN; @@ -139,11 +139,16 @@ static int acpi_lid_evaluate_state(struct acpi_device *device) return lid_state ? 1 : 0; } -static int acpi_lid_notify_state(struct acpi_device *device, +static inline void acpi_lid_notifier_call(struct acpi_device *device, + int state) +{ + (void)raw_notifier_call_chain(&acpi_lid_notifier, state, device); +} + +static void acpi_lid_notify_state(struct acpi_device *device, int state, bool bios_notify) { struct acpi_button *button = acpi_driver_data(device); - int ret; ktime_t next_report; /* @@ -161,7 +166,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, ms_to_ktime(lid_report_interval)); if (button->last_is_bios && button->last_state == !!state && !ktime_after(ktime_get(), next_report)) - return 0; + return; /* * Send the unreliable complement switch event: @@ -219,18 +224,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, if (state) pm_wakeup_event(&device->dev, 0); - ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); - if (ret == NOTIFY_DONE) - ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, - device); - if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { - /* - * It is also regarded as success if the notifier_chain - * returns NOTIFY_OK or NOTIFY_DONE. - */ - ret = 0; - } - return ret; + acpi_lid_notifier_call(device, state); } static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) @@ -341,13 +335,24 @@ static int acpi_button_remove_fs(struct acpi_device *device) -------------------------------------------------------------------------- */ int acpi_lid_notifier_register(struct notifier_block *nb) { - return blocking_notifier_chain_register(&acpi_lid_notifier, nb); + return raw_notifier_chain_register(&acpi_lid_notifier, nb); } EXPORT_SYMBOL(acpi_lid_notifier_register); +static inline int __acpi_lid_notifier_unregister(struct notifier_block *nb, + bool sync) +{ + int ret; + + ret = raw_notifier_chain_unregister(&acpi_lid_notifier, nb); + if (sync) + synchronize_rcu(); + return ret; +} + int acpi_lid_notifier_unregister(struct notifier_block *nb) { - return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb); + return __acpi_lid_notifier_unregister(nb, false); } EXPORT_SYMBOL(acpi_lid_notifier_unregister); @@ -360,26 +365,26 @@ int acpi_lid_open(void) } EXPORT_SYMBOL(acpi_lid_open); -static int acpi_lid_update_state(struct acpi_device *device, - bool bios_notify) +static void acpi_lid_update_state(struct acpi_device *device, + bool bios_notify) { int state; state = acpi_lid_evaluate_state(device); if (state < 0) - return state; + return; - return acpi_lid_notify_state(device, state, bios_notify); + acpi_lid_notify_state(device, state, bios_notify); } static void acpi_lid_initialize_state(struct acpi_device *device) { switch (lid_init_state) { case ACPI_BUTTON_LID_INIT_OPEN: - (void)acpi_lid_notify_state(device, 1, false); + acpi_lid_notify_state(device, 1, false); break; case ACPI_BUTTON_LID_INIT_METHOD: - (void)acpi_lid_update_state(device, false); + acpi_lid_update_state(device, false); break; case ACPI_BUTTON_LID_INIT_IGNORE: default: -- 2.7.4 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S945242AbdE0BUY (ORCPT ); Fri, 26 May 2017 21:20:24 -0400 Received: from mga01.intel.com ([192.55.52.88]:50118 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1948848AbdEZXkn (ORCPT ); Fri, 26 May 2017 19:40:43 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.38,399,1491289200"; d="scan'208";a="1174914630" From: Lv Zheng To: "Rafael J. Wysocki" , "Rafael J. Wysocki" , Len Brown Cc: Lv Zheng , Lv Zheng , , linux-acpi@vger.kernel.org, Peter Hutterer , Benjamin Tissoires Subject: [RFC PATCH v3 4/5] ACPI: button: Fix lid notification Date: Sat, 27 May 2017 07:42:49 +0800 Message-Id: X-Mailer: git-send-email 2.5.0 In-Reply-To: <2a779ae8c280c968b3237ac4a3d9580df7262a46.1493951798.git.lv.zheng@intel.com> References: <2a779ae8c280c968b3237ac4a3d9580df7262a46.1493951798.git.lv.zheng@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In acpi_lid_notify_state(), it now contains logic to avoid frequently replayed events which originally was ensured by using blocking notifier. On the contrary, using blocking notifier is wrong as it could keep on returning NOTIFY_DONE, causing events lost. This patch thus changes lid notification to raw notifier in order not to have events lost. Cc: Peter Hutterer Cc: Benjamin Tissoires Signed-off-by: Lv Zheng --- drivers/acpi/button.c | 53 ++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index d3f90c6..4abf8ae 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -112,7 +112,7 @@ struct acpi_button { bool suspended; }; -static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); +static RAW_NOTIFIER_HEAD(acpi_lid_notifier); static struct acpi_device *lid_device; static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN; @@ -139,11 +139,16 @@ static int acpi_lid_evaluate_state(struct acpi_device *device) return lid_state ? 1 : 0; } -static int acpi_lid_notify_state(struct acpi_device *device, +static inline void acpi_lid_notifier_call(struct acpi_device *device, + int state) +{ + (void)raw_notifier_call_chain(&acpi_lid_notifier, state, device); +} + +static void acpi_lid_notify_state(struct acpi_device *device, int state, bool bios_notify) { struct acpi_button *button = acpi_driver_data(device); - int ret; ktime_t next_report; /* @@ -161,7 +166,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, ms_to_ktime(lid_report_interval)); if (button->last_is_bios && button->last_state == !!state && !ktime_after(ktime_get(), next_report)) - return 0; + return; /* * Send the unreliable complement switch event: @@ -219,18 +224,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, if (state) pm_wakeup_event(&device->dev, 0); - ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); - if (ret == NOTIFY_DONE) - ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, - device); - if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { - /* - * It is also regarded as success if the notifier_chain - * returns NOTIFY_OK or NOTIFY_DONE. - */ - ret = 0; - } - return ret; + acpi_lid_notifier_call(device, state); } static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) @@ -341,13 +335,24 @@ static int acpi_button_remove_fs(struct acpi_device *device) -------------------------------------------------------------------------- */ int acpi_lid_notifier_register(struct notifier_block *nb) { - return blocking_notifier_chain_register(&acpi_lid_notifier, nb); + return raw_notifier_chain_register(&acpi_lid_notifier, nb); } EXPORT_SYMBOL(acpi_lid_notifier_register); +static inline int __acpi_lid_notifier_unregister(struct notifier_block *nb, + bool sync) +{ + int ret; + + ret = raw_notifier_chain_unregister(&acpi_lid_notifier, nb); + if (sync) + synchronize_rcu(); + return ret; +} + int acpi_lid_notifier_unregister(struct notifier_block *nb) { - return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb); + return __acpi_lid_notifier_unregister(nb, false); } EXPORT_SYMBOL(acpi_lid_notifier_unregister); @@ -360,26 +365,26 @@ int acpi_lid_open(void) } EXPORT_SYMBOL(acpi_lid_open); -static int acpi_lid_update_state(struct acpi_device *device, - bool bios_notify) +static void acpi_lid_update_state(struct acpi_device *device, + bool bios_notify) { int state; state = acpi_lid_evaluate_state(device); if (state < 0) - return state; + return; - return acpi_lid_notify_state(device, state, bios_notify); + acpi_lid_notify_state(device, state, bios_notify); } static void acpi_lid_initialize_state(struct acpi_device *device) { switch (lid_init_state) { case ACPI_BUTTON_LID_INIT_OPEN: - (void)acpi_lid_notify_state(device, 1, false); + acpi_lid_notify_state(device, 1, false); break; case ACPI_BUTTON_LID_INIT_METHOD: - (void)acpi_lid_update_state(device, false); + acpi_lid_update_state(device, false); break; case ACPI_BUTTON_LID_INIT_IGNORE: default: -- 2.7.4