Re: Pressing the power button causes the device to freeze completely

From: Evgeny Sagatov

Date: Tue Apr 28 2026 - 15:12:03 EST


Yes, the PC froze when I pressed the power button.

вт, 28 апр. 2026 г. в 20:40, Rafael J. Wysocki <rafael@xxxxxxxxxx>:
>
> On Monday, April 27, 2026 11:49:51 PM CEST Evgeny Sagatov wrote:
> > apr 28 00:48:34 srv kernel: ACPI power button event
> > apr 28 00:48:34 srv kernel: ACPI event status I/O port number: 1024
> >
> > пн, 27 апр. 2026 г. в 23:31, Rafael J. Wysocki <rafael@xxxxxxxxxx>:
> > >
> > > On Monday, April 27, 2026 10:12:33 PM CEST Evgeny Sagatov wrote:
> > > > dmesg | grep "frequency scaling"
> > > > [ 8.552380] acpi_cpufreq: CPU0: Using I/O space for frequency scaling
> > > > [ 8.552386] acpi_cpufreq: CPU0: frequency scaling I/O port number: 2176
> > > > [ 8.552478] acpi_cpufreq: CPU1: Using I/O space for frequency scaling
> > > > [ 8.552480] acpi_cpufreq: CPU1: frequency scaling I/O port number: 2176
> > > > [ 8.552584] acpi_cpufreq: CPU2: Using I/O space for frequency scaling
> > > > [ 8.552586] acpi_cpufreq: CPU2: frequency scaling I/O port number: 2176
> > > > [ 8.552668] acpi_cpufreq: CPU3: Using I/O space for frequency scaling
> > > > [ 8.552670] acpi_cpufreq: CPU3: frequency scaling I/O port number: 2176
>
> The I/O ports that play the role in this issue are separate from each other in
> the address space, but that need not mean that they are physically independent.
>
> My current theory is that accessing one of them while an access to the other
> one is still in progress may cause the platform to lock up, or there is an
> access pattern that causes that to happen.
>
> Let's first test the simplest variant of that theory and see what happens if
> all I/O port accesses in acpi_os_write_port() are serialized, which is done
> in the patch below (it is a replacement for all of the patches sent so far).
>
> In addition, that patch causes schedutil to use the slow path for updating the
> frequency because the I/O space is generally somewhat too slow to be used
> from the scheduler context relatively often, but that should not affect the
> behavior related to I/O space accesses.
>
> Please check if the system still locks up after pressing the power button
> with this patch applied.
>
> ---
> drivers/acpi/osl.c | 9 +++++++--
> drivers/cpufreq/acpi-cpufreq.c | 9 ++++++---
> 2 files changed, 13 insertions(+), 5 deletions(-)
>
> --- a/drivers/acpi/osl.c
> +++ b/drivers/acpi/osl.c
> @@ -700,8 +700,10 @@ EXPORT_SYMBOL(acpi_os_read_port);
>
> acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
> {
> - if (!IS_ENABLED(CONFIG_HAS_IOPORT))
> - return AE_NOT_IMPLEMENTED;
> +#ifdef CONFIG_HAS_IOPORT
> + static DEFINE_RAW_SPINLOCK(acpi_os_write_port_lock);
> +
> + guard(raw_spinlock_irqsave)(&acpi_os_write_port_lock);
>
> if (width <= 8) {
> outb(value, port);
> @@ -715,6 +717,9 @@ acpi_status acpi_os_write_port(acpi_io_a
> }
>
> return AE_OK;
> +#else
> + return AE_NOT_IMPLEMENTED;
> +#endif
> }
>
> EXPORT_SYMBOL(acpi_os_write_port);
> --- a/drivers/cpufreq/acpi-cpufreq.c
> +++ b/drivers/cpufreq/acpi-cpufreq.c
> @@ -878,6 +878,10 @@ static int acpi_cpufreq_cpu_init(struct
> policy->freq_table = freq_table;
> perf->state = 0;
>
> + policy->fast_switch_possible = !acpi_pstate_strict &&
> + !(policy_is_shared(policy) &&
> + policy->shared_type != CPUFREQ_SHARED_TYPE_ANY);
> +
> switch (perf->control_register.space_id) {
> case ACPI_ADR_SPACE_SYSTEM_IO:
> /*
> @@ -887,6 +891,8 @@ static int acpi_cpufreq_cpu_init(struct
> * unknown and not detectable via IO ports.
> */
> policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
> + /* I/O spcase is too slow for fast switching. */
> + policy->fast_switch_possible = false;
> break;
> case ACPI_ADR_SPACE_FIXED_HARDWARE:
> acpi_cpufreq_driver.get = get_cur_freq_on_cpu;
> @@ -912,9 +918,6 @@ static int acpi_cpufreq_cpu_init(struct
> */
> data->resume = 1;
>
> - policy->fast_switch_possible = !acpi_pstate_strict &&
> - !(policy_is_shared(policy) && policy->shared_type != CPUFREQ_SHARED_TYPE_ANY);
> -
> if (perf->states[0].core_frequency * 1000 != freq_table[0].frequency)
> pr_warn(FW_WARN "P-state 0 is not max freq\n");
>
>
>
>