From 656b4e639831a6110dab8cd7e557c41f87514869 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 21 Nov 2019 04:19:12 +0100 Subject: cpuidle: Fix Kconfig indentation Adjust indentation from spaces to tab (+optional two spaces) as in coding style with command like: $ sed -e 's/^ /\t/' -i */Kconfig Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/Kconfig | 16 ++++++++-------- drivers/cpuidle/Kconfig.arm | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 88727b7c0d59..c0aeedd66f02 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -16,7 +16,7 @@ config CPU_IDLE if CPU_IDLE config CPU_IDLE_MULTIPLE_DRIVERS - bool + bool config CPU_IDLE_GOV_LADDER bool "Ladder governor (for periodic timer tick)" @@ -63,13 +63,13 @@ source "drivers/cpuidle/Kconfig.powerpc" endmenu config HALTPOLL_CPUIDLE - tristate "Halt poll cpuidle driver" - depends on X86 && KVM_GUEST - default y - help - This option enables halt poll cpuidle driver, which allows to poll - before halting in the guest (more efficient than polling in the - host via halt_poll_ns for some scenarios). + tristate "Halt poll cpuidle driver" + depends on X86 && KVM_GUEST + default y + help + This option enables halt poll cpuidle driver, which allows to poll + before halting in the guest (more efficient than polling in the + host via halt_poll_ns for some scenarios). endif diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index d8530475493c..e91ab792d14d 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -3,15 +3,15 @@ # ARM CPU Idle drivers # config ARM_CPUIDLE - bool "Generic ARM/ARM64 CPU idle Driver" - select DT_IDLE_STATES + bool "Generic ARM/ARM64 CPU idle Driver" + select DT_IDLE_STATES select CPU_IDLE_MULTIPLE_DRIVERS - help - Select this to enable generic cpuidle driver for ARM. - It provides a generic idle driver whose idle states are configured - at run-time through DT nodes. The CPUidle suspend backend is - initialized by calling the CPU operations init idle hook - provided by architecture code. + help + Select this to enable generic cpuidle driver for ARM. + It provides a generic idle driver whose idle states are configured + at run-time through DT nodes. The CPUidle suspend backend is + initialized by calling the CPU operations init idle hook + provided by architecture code. config ARM_PSCI_CPUIDLE bool "PSCI CPU idle Driver" -- cgit v1.2.3-59-g8ed1b From ba1e78a1dc0ca3e92f0be82279e6ba24177af7d6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Nov 2019 19:41:51 +0100 Subject: cpuidle: Drop disabled field from struct cpuidle_state After recent cpuidle updates the "disabled" field in struct cpuidle_state is only used by two drivers (intel_idle and shmobile cpuidle) for marking unusable idle states, but that may as well be achieved with the help of a state flag, so define an "unusable" idle state flag, CPUIDLE_FLAG_UNUSABLE, make the drivers in question use it instead of the "disabled" field and make the core set CPUIDLE_STATE_DISABLED_BY_DRIVER for the idle states with that flag set. After the above changes, the "disabled" field in struct cpuidle_state is not used any more, so drop it. No intentional functional impact. Signed-off-by: Rafael J. Wysocki --- arch/sh/kernel/cpu/shmobile/cpuidle.c | 8 ++++---- drivers/cpuidle/cpuidle.c | 2 +- drivers/cpuidle/poll_state.c | 1 - drivers/idle/intel_idle.c | 6 +++--- include/linux/cpuidle.h | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c index dbd2cdec2ddb..b0f9c8f8fd14 100644 --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c @@ -67,7 +67,7 @@ static struct cpuidle_driver cpuidle_driver = { .enter = cpuidle_sleep_enter, .name = "C2", .desc = "SuperH Sleep Mode [SF]", - .disabled = true, + .flags = CPUIDLE_FLAG_UNUSABLE, }, { .exit_latency = 2300, @@ -76,7 +76,7 @@ static struct cpuidle_driver cpuidle_driver = { .enter = cpuidle_sleep_enter, .name = "C3", .desc = "SuperH Mobile Standby Mode [SF]", - .disabled = true, + .flags = CPUIDLE_FLAG_UNUSABLE, }, }, .safe_state_index = 0, @@ -86,10 +86,10 @@ static struct cpuidle_driver cpuidle_driver = { int __init sh_mobile_setup_cpuidle(void) { if (sh_mobile_sleep_supported & SUSP_SH_SF) - cpuidle_driver.states[1].disabled = false; + cpuidle_driver.states[1].flags = CPUIDLE_FLAG_NONE; if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) - cpuidle_driver.states[2].disabled = false; + cpuidle_driver.states[2].flags = CPUIDLE_FLAG_NONE; return cpuidle_register(&cpuidle_driver, NULL); } diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 569dbac443bd..0005be5ea2b4 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -572,7 +572,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) return -EINVAL; for (i = 0; i < drv->state_count; i++) - if (drv->states[i].disabled) + if (drv->states[i].flags & CPUIDLE_FLAG_UNUSABLE) dev->states_usage[i].disable |= CPUIDLE_STATE_DISABLED_BY_DRIVER; per_cpu(cpuidle_devices, dev->cpu) = dev; diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c index 9f1ace9c53da..f7e83613ae94 100644 --- a/drivers/cpuidle/poll_state.c +++ b/drivers/cpuidle/poll_state.c @@ -53,7 +53,6 @@ void cpuidle_poll_state_init(struct cpuidle_driver *drv) state->target_residency_ns = 0; state->power_usage = -1; state->enter = poll_idle; - state->disabled = false; state->flags = CPUIDLE_FLAG_POLLING; } EXPORT_SYMBOL_GPL(cpuidle_poll_state_init); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 347b08b56042..75fd2a7b0842 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -1291,8 +1291,8 @@ static void sklh_idle_state_table_update(void) return; } - skl_cstates[5].disabled = 1; /* C8-SKL */ - skl_cstates[6].disabled = 1; /* C9-SKL */ + skl_cstates[5].flags |= CPUIDLE_FLAG_UNUSABLE; /* C8-SKL */ + skl_cstates[6].flags |= CPUIDLE_FLAG_UNUSABLE; /* C9-SKL */ } /* * intel_idle_state_table_update() @@ -1355,7 +1355,7 @@ static void __init intel_idle_cpuidle_driver_init(void) continue; /* if state marked as disabled, skip it */ - if (cpuidle_state_table[cstate].disabled != 0) { + if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_UNUSABLE) { pr_debug("state %s is disabled\n", cpuidle_state_table[cstate].name); continue; diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 2dbe46b7c213..1dabe36bd011 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -54,7 +54,6 @@ struct cpuidle_state { unsigned int exit_latency; /* in US */ int power_usage; /* in mW */ unsigned int target_residency; /* in US */ - bool disabled; /* disabled on all CPUs */ int (*enter) (struct cpuidle_device *dev, struct cpuidle_driver *drv, @@ -77,6 +76,7 @@ struct cpuidle_state { #define CPUIDLE_FLAG_POLLING BIT(0) /* polling state */ #define CPUIDLE_FLAG_COUPLED BIT(1) /* state applies to multiple cpus */ #define CPUIDLE_FLAG_TIMER_STOP BIT(2) /* timer is stopped on this state */ +#define CPUIDLE_FLAG_UNUSABLE BIT(3) /* avoid using this state */ struct cpuidle_device_kobj; struct cpuidle_state_kobj; -- cgit v1.2.3-59-g8ed1b From 4d30d4a0441dac4452fcc188cd21536bedaec5df Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 28 Nov 2019 14:38:03 -0800 Subject: cpuidle: minor Kconfig help text fixes End sentences in help text with a period (aka full stop). Signed-off-by: Randy Dunlap Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/Kconfig.arm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index e91ab792d14d..a224d33dda7f 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -65,21 +65,21 @@ config ARM_U8500_CPUIDLE bool "Cpu Idle Driver for the ST-E u8500 processors" depends on ARCH_U8500 && !ARM64 help - Select this to enable cpuidle for ST-E u8500 processors + Select this to enable cpuidle for ST-E u8500 processors. config ARM_AT91_CPUIDLE bool "Cpu Idle Driver for the AT91 processors" default y depends on ARCH_AT91 && !ARM64 help - Select this to enable cpuidle for AT91 processors + Select this to enable cpuidle for AT91 processors. config ARM_EXYNOS_CPUIDLE bool "Cpu Idle Driver for the Exynos processors" depends on ARCH_EXYNOS && !ARM64 select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP help - Select this to enable cpuidle for Exynos processors + Select this to enable cpuidle for Exynos processors. config ARM_MVEBU_V7_CPUIDLE bool "CPU Idle Driver for mvebu v7 family processors" -- cgit v1.2.3-59-g8ed1b From cde10f856a7de191a773d880bb524ea15084e1cc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 21 Nov 2019 04:19:15 +0100 Subject: cpufreq: Fix Kconfig indentation Adjust indentation from spaces to tab (+optional two spaces) as in coding style with command like: $ sed -e 's/^ /\t/' -i */Kconfig Signed-off-by: Krzysztof Kozlowski Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/Kconfig.powerpc | 8 ++++---- drivers/cpufreq/Kconfig.x86 | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc index 35b4f700f054..58151ca56695 100644 --- a/drivers/cpufreq/Kconfig.powerpc +++ b/drivers/cpufreq/Kconfig.powerpc @@ -48,9 +48,9 @@ config PPC_PASEMI_CPUFREQ PWRficient processors. config POWERNV_CPUFREQ - tristate "CPU frequency scaling for IBM POWERNV platform" - depends on PPC_POWERNV - default y - help + tristate "CPU frequency scaling for IBM POWERNV platform" + depends on PPC_POWERNV + default y + help This adds support for CPU frequency switching on IBM POWERNV platform diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index dfa6457deaf6..a6528388952e 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 @@ -4,17 +4,17 @@ # config X86_INTEL_PSTATE - bool "Intel P state control" - depends on X86 - select ACPI_PROCESSOR if ACPI - select ACPI_CPPC_LIB if X86_64 && ACPI && SCHED_MC_PRIO - help - This driver provides a P state for Intel core processors. + bool "Intel P state control" + depends on X86 + select ACPI_PROCESSOR if ACPI + select ACPI_CPPC_LIB if X86_64 && ACPI && SCHED_MC_PRIO + help + This driver provides a P state for Intel core processors. The driver implements an internal governor and will become - the scaling driver and governor for Sandy bridge processors. + the scaling driver and governor for Sandy bridge processors. When this driver is enabled it will become the preferred - scaling driver for Sandy bridge processors. + scaling driver for Sandy bridge processors. If in doubt, say N. -- cgit v1.2.3-59-g8ed1b From 2a0efc77735b48c42aedbe99df1f8f91aa402f57 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 20 Nov 2019 21:40:04 +0800 Subject: power: avs: Fix Kconfig indentation Adjust indentation from spaces to tab (+optional two spaces) as in coding style with command like: $ sed -e 's/^ /\t/' -i */Kconfig Signed-off-by: Krzysztof Kozlowski Acked-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/power/avs/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig index b5a217b828dc..089b6244b716 100644 --- a/drivers/power/avs/Kconfig +++ b/drivers/power/avs/Kconfig @@ -13,9 +13,9 @@ menuconfig POWER_AVS Say Y here to enable Adaptive Voltage Scaling class support. config ROCKCHIP_IODOMAIN - tristate "Rockchip IO domain support" - depends on POWER_AVS && ARCH_ROCKCHIP && OF - help - Say y here to enable support io domains on Rockchip SoCs. It is - necessary for the io domain setting of the SoC to match the - voltage supplied by the regulators. + tristate "Rockchip IO domain support" + depends on POWER_AVS && ARCH_ROCKCHIP && OF + help + Say y here to enable support io domains on Rockchip SoCs. It is + necessary for the io domain setting of the SoC to match the + voltage supplied by the regulators. -- cgit v1.2.3-59-g8ed1b From e1e047ace8cef6d143f38c7d769753f133becbe6 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 12 Nov 2019 11:47:34 +0100 Subject: PM / devfreq: Add missing locking while setting suspend_freq Commit 2abb0d5268ae ("PM / devfreq: Lock devfreq in trans_stat_show") revealed a missing locking while calling devfreq_update_status() function during suspend/resume cycle. Code analysis revealed that devfreq_set_target() function was called without needed locks held for setting device specific suspend_freq if such has been defined. This patch fixes that by adding the needed locking, what fixes following kernel warning on Exynos4412-based OdroidU3 board during system suspend: PM: suspend entry (deep) Filesystems sync: 0.002 seconds Freezing user space processes ... (elapsed 0.001 seconds) done. OOM killer disabled. Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done. ------------[ cut here ]------------ WARNING: CPU: 2 PID: 1385 at drivers/devfreq/devfreq.c:204 devfreq_update_status+0xc0/0x188 Modules linked in: CPU: 2 PID: 1385 Comm: rtcwake Not tainted 5.4.0-rc6-next-20191111 #6848 Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0xb4/0xe0) [] (dump_stack) from [] (__warn+0xf4/0x10c) [] (__warn) from [] (warn_slowpath_fmt+0xb0/0xb8) [] (warn_slowpath_fmt) from [] (devfreq_update_status+0xc0/0x188) [] (devfreq_update_status) from [] (devfreq_set_target+0xb0/0x15c) [] (devfreq_set_target) from [] (devfreq_suspend+0x2c/0x64) [] (devfreq_suspend) from [] (dpm_suspend+0xa4/0x57c) [] (dpm_suspend) from [] (dpm_suspend_start+0x98/0xa0) [] (dpm_suspend_start) from [] (suspend_devices_and_enter+0xec/0xc74) [] (suspend_devices_and_enter) from [] (pm_suspend+0x340/0x410) [] (pm_suspend) from [] (state_store+0x6c/0xc8) [] (state_store) from [] (kernfs_fop_write+0x10c/0x228) [] (kernfs_fop_write) from [] (__vfs_write+0x30/0x1d0) [] (__vfs_write) from [] (vfs_write+0xa4/0x180) [] (vfs_write) from [] (ksys_write+0x60/0xd8) [] (ksys_write) from [] (ret_fast_syscall+0x0/0x28) Exception stack(0xed3d7fa8 to 0xed3d7ff0) ... irq event stamp: 9667 hardirqs last enabled at (9679): [] _raw_spin_unlock_irq+0x20/0x58 hardirqs last disabled at (9698): [] __schedule+0xd8/0x818 softirqs last enabled at (9694): [] __do_softirq+0x4fc/0x5fc softirqs last disabled at (9719): [] irq_exit+0x16c/0x170 ---[ end trace 41ac5b57d046bdbc ]--- ------------[ cut here ]------------ Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Rafael J. Wysocki --- drivers/devfreq/devfreq.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index f840e61e5a27..425149e8bab0 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -921,7 +921,9 @@ int devfreq_suspend_device(struct devfreq *devfreq) } if (devfreq->suspend_freq) { + mutex_lock(&devfreq->lock); ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0); + mutex_unlock(&devfreq->lock); if (ret) return ret; } @@ -949,7 +951,9 @@ int devfreq_resume_device(struct devfreq *devfreq) return 0; if (devfreq->resume_freq) { + mutex_lock(&devfreq->lock); ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0); + mutex_unlock(&devfreq->lock); if (ret) return ret; } -- cgit v1.2.3-59-g8ed1b From 016b87ca5c8c6e9e87db442f04dc99609b11ed36 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 28 Nov 2019 23:47:51 +0100 Subject: ACPI: EC: Rework flushing of pending work There is a race condition in the ACPI EC driver, between __acpi_ec_flush_event() and acpi_ec_event_handler(), that may cause systems to stay in suspended-to-idle forever after a wakeup event coming from the EC. Namely, acpi_s2idle_wake() calls acpi_ec_flush_work() to wait until the delayed work resulting from the handling of the EC GPE in acpi_ec_dispatch_gpe() is processed, and that function invokes __acpi_ec_flush_event() which uses wait_event() to wait for ec->nr_pending_queries to become zero on ec->wait, and that wait queue may be woken up too early. Suppose that acpi_ec_dispatch_gpe() has caused acpi_ec_gpe_handler() to run, so advance_transaction() has been called and it has invoked acpi_ec_submit_query() to queue up an event work item, so ec->nr_pending_queries has been incremented (under ec->lock). The work function of that work item, acpi_ec_event_handler() runs later and calls acpi_ec_query() to process the event. That function calls acpi_ec_transaction() which invokes acpi_ec_transaction_unlocked() and the latter wakes up ec->wait under ec->lock, but it drops that lock before returning. When acpi_ec_query() returns, acpi_ec_event_handler() acquires ec->lock and decrements ec->nr_pending_queries, but at that point __acpi_ec_flush_event() (woken up previously) may already have acquired ec->lock, checked the value of ec->nr_pending_queries (and it would not have been zero then) and decided to go back to sleep. Next, if ec->nr_pending_queries is equal to zero now, the loop in acpi_ec_event_handler() terminates, ec->lock is released and acpi_ec_check_event() is called, but it does nothing unless ec_event_clearing is equal to ACPI_EC_EVT_TIMING_EVENT (which is not the case by default). In the end, if no more event work items have been queued up while executing acpi_ec_transaction_unlocked(), there is nothing to wake up __acpi_ec_flush_event() again and it sleeps forever, so the suspend-to-idle loop cannot make progress and the system is permanently suspended. To avoid this issue, notice that it actually is not necessary to wait for ec->nr_pending_queries to become zero in every case in which __acpi_ec_flush_event() is used. First, during platform-based system suspend (not suspend-to-idle), __acpi_ec_flush_event() is called by acpi_ec_disable_event() after clearing the EC_FLAGS_QUERY_ENABLED flag, which prevents acpi_ec_submit_query() from submitting any new event work items, so calling flush_scheduled_work() and flushing ec_query_wq subsequently (in order to wait until all of the queries in that queue have been processed) would be sufficient to flush all of the pending EC work in that case. Second, the purpose of the flushing of pending EC work while suspended-to-idle described above really is to wait until the first event work item coming from acpi_ec_dispatch_gpe() is complete, because it should produce system wakeup events if that is a valid EC-based system wakeup, so calling flush_scheduled_work() followed by flushing ec_query_wq is also sufficient for that purpose. Rework the code to follow the above observations. Fixes: 56b9918490 ("PM: sleep: Simplify suspend-to-idle control flow") Reported-by: Kenneth R. Crudup Tested-by: Kenneth R. Crudup Cc: 5.4+ # 5.4+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ec.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index da1e5c5ce150..bd75caff8322 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -525,26 +525,10 @@ static void acpi_ec_enable_event(struct acpi_ec *ec) } #ifdef CONFIG_PM_SLEEP -static bool acpi_ec_query_flushed(struct acpi_ec *ec) +static void __acpi_ec_flush_work(void) { - 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); + flush_scheduled_work(); /* flush ec->work */ + flush_workqueue(ec_query_wq); /* flush queries */ } static void acpi_ec_disable_event(struct acpi_ec *ec) @@ -554,15 +538,21 @@ static void acpi_ec_disable_event(struct acpi_ec *ec) spin_lock_irqsave(&ec->lock, flags); __acpi_ec_disable_event(ec); spin_unlock_irqrestore(&ec->lock, flags); - __acpi_ec_flush_event(ec); + + /* + * When ec_freeze_events is true, we need to flush events in + * the proper position before entering the noirq stage. + */ + __acpi_ec_flush_work(); } void acpi_ec_flush_work(void) { - if (first_ec) - __acpi_ec_flush_event(first_ec); + /* Without ec_query_wq there is nothing to flush. */ + if (!ec_query_wq) + return; - flush_scheduled_work(); + __acpi_ec_flush_work(); } #endif /* CONFIG_PM_SLEEP */ -- cgit v1.2.3-59-g8ed1b From 024aa8732acb7d2503eae43c3fe3504d0a8646d0 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 28 Nov 2019 23:50:40 +0100 Subject: ACPI: PM: s2idle: Rework ACPI events synchronization Note that the EC GPE processing need not be synchronized in acpi_s2idle_wake() after invoking acpi_ec_dispatch_gpe(), because that function checks the GPE status and dispatches its handler if need be and the SCI action handler is not going to run anyway at that point. Moreover, it is better to drain all of the pending ACPI events before restoring the working-state configuration of GPEs in acpi_s2idle_restore(), because those events are likely to be related to system wakeup, in which case they will not be relevant going forward. Rework the code to take these observations into account. Tested-by: Kenneth R. Crudup Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 2af937a8b1c5..6747a279621b 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -977,6 +977,16 @@ static int acpi_s2idle_prepare_late(void) return 0; } +static void acpi_s2idle_sync(void) +{ + /* + * The EC driver uses the system workqueue and an additional special + * one, so those need to be flushed too. + */ + acpi_ec_flush_work(); + acpi_os_wait_events_complete(); /* synchronize Notify handling */ +} + static void acpi_s2idle_wake(void) { /* @@ -1001,13 +1011,8 @@ static void acpi_s2idle_wake(void) * should be missed by canceling the wakeup here. */ pm_system_cancel_wakeup(); - /* - * The EC driver uses the system workqueue and an additional - * special one, so those need to be flushed too. - */ - acpi_os_wait_events_complete(); /* synchronize EC GPE processing */ - acpi_ec_flush_work(); - acpi_os_wait_events_complete(); /* synchronize Notify handling */ + + acpi_s2idle_sync(); rearm_wake_irq(acpi_sci_irq); } @@ -1024,6 +1029,13 @@ static void acpi_s2idle_restore_early(void) static void acpi_s2idle_restore(void) { + /* + * Drain pending events before restoring the working-state configuration + * of GPEs. + */ + acpi_os_wait_events_complete(); /* synchronize GPE processing */ + acpi_s2idle_sync(); + s2idle_wakeup = false; acpi_enable_all_runtime_gpes(); -- cgit v1.2.3-59-g8ed1b