Skip to content

Commit 883fd0a

Browse files
committed
Merge tag 'acpi-5.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI fixes from Rafael Wysocki: "These revert two commits that turned out to be problematic and fix two issues related to wakeup from suspend-to-idle on x86. Specifics: - Revert a recent change that attempted to avoid issues with conflicting address ranges during PCI initialization, because it turned out to introduce a regression (Hans de Goede). - Revert a change that limited EC GPE wakeups from suspend-to-idle to systems based on Intel hardware, because it turned out that systems based on hardware from other vendors depended on that functionality too (Mario Limonciello). - Fix two issues related to the handling of wakeup interrupts and wakeup events signaled through the EC GPE during suspend-to-idle on x86 (Rafael Wysocki)" * tag 'acpi-5.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: x86/PCI: revert "Ignore E820 reservations for bridge windows on newer systems" PM: s2idle: ACPI: Fix wakeup interrupts handling ACPI: PM: s2idle: Cancel wakeup before dispatching EC GPE ACPI: PM: Revert "Only mark EC GPE for wakeup on Intel systems"
2 parents 8ce964b + 27a98fe commit 883fd0a

File tree

9 files changed

+61
-53
lines changed

9 files changed

+61
-53
lines changed

arch/x86/kernel/resource.c

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// SPDX-License-Identifier: GPL-2.0
2-
#include <linux/dmi.h>
32
#include <linux/ioport.h>
43
#include <asm/e820/api.h>
54

@@ -24,31 +23,11 @@ static void resource_clip(struct resource *res, resource_size_t start,
2423
res->start = end + 1;
2524
}
2625

27-
/*
28-
* Some BIOS-es contain a bug where they add addresses which map to
29-
* system RAM in the PCI host bridge window returned by the ACPI _CRS
30-
* method, see commit 4dc2287c1805 ("x86: avoid E820 regions when
31-
* allocating address space"). To avoid this Linux by default excludes
32-
* E820 reservations when allocating addresses since 2010.
33-
* In 2019 some systems have shown-up with E820 reservations which cover
34-
* the entire _CRS returned PCI host bridge window, causing all attempts
35-
* to assign memory to PCI BARs to fail if Linux uses E820 reservations.
36-
*
37-
* Ideally Linux would fully stop using E820 reservations, but then
38-
* the old systems this was added for will regress.
39-
* Instead keep the old behavior for old systems, while ignoring the
40-
* E820 reservations for any systems from now on.
41-
*/
4226
static void remove_e820_regions(struct resource *avail)
4327
{
44-
int i, year = dmi_get_bios_year();
28+
int i;
4529
struct e820_entry *entry;
4630

47-
if (year >= 2018)
48-
return;
49-
50-
pr_info_once("PCI: Removing E820 reservations from host bridge windows\n");
51-
5231
for (i = 0; i < e820_table->nr_entries; i++) {
5332
entry = &e820_table->entries[i];
5433

drivers/acpi/ec.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,16 @@ bool acpi_ec_dispatch_gpe(void)
20652065
if (acpi_any_gpe_status_set(first_ec->gpe))
20662066
return true;
20672067

2068+
/*
2069+
* Cancel the SCI wakeup and process all pending events in case there
2070+
* are any wakeup ones in there.
2071+
*
2072+
* Note that if any non-EC GPEs are active at this point, the SCI will
2073+
* retrigger after the rearming in acpi_s2idle_wake(), so no events
2074+
* should be missed by canceling the wakeup here.
2075+
*/
2076+
pm_system_cancel_wakeup();
2077+
20682078
/*
20692079
* Dispatch the EC GPE in-band, but do not report wakeup in any case
20702080
* to allow the caller to process events properly after that.

drivers/acpi/sleep.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -736,21 +736,15 @@ bool acpi_s2idle_wake(void)
736736
return true;
737737
}
738738

739-
/* Check non-EC GPE wakeups and dispatch the EC GPE. */
739+
/*
740+
* Check non-EC GPE wakeups and if there are none, cancel the
741+
* SCI-related wakeup and dispatch the EC GPE.
742+
*/
740743
if (acpi_ec_dispatch_gpe()) {
741744
pm_pr_dbg("ACPI non-EC GPE wakeup\n");
742745
return true;
743746
}
744747

745-
/*
746-
* Cancel the SCI wakeup and process all pending events in case
747-
* there are any wakeup ones in there.
748-
*
749-
* Note that if any non-EC GPEs are active at this point, the
750-
* SCI will retrigger after the rearming below, so no events
751-
* should be missed by canceling the wakeup here.
752-
*/
753-
pm_system_cancel_wakeup();
754748
acpi_os_wait_events_complete();
755749

756750
/*
@@ -764,6 +758,7 @@ bool acpi_s2idle_wake(void)
764758
return true;
765759
}
766760

761+
pm_wakeup_clear(acpi_sci_irq);
767762
rearm_wake_irq(acpi_sci_irq);
768763
}
769764

drivers/acpi/x86/s2idle.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -424,15 +424,11 @@ static int lps0_device_attach(struct acpi_device *adev,
424424
mem_sleep_current = PM_SUSPEND_TO_IDLE;
425425

426426
/*
427-
* Some Intel based LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U don't
428-
* use intel-hid or intel-vbtn but require the EC GPE to be enabled while
429-
* suspended for certain wakeup devices to work, so mark it as wakeup-capable.
430-
*
431-
* Only enable on !AMD as enabling this universally causes problems for a number
432-
* of AMD based systems.
427+
* Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
428+
* EC GPE to be enabled while suspended for certain wakeup devices to
429+
* work, so mark it as wakeup-capable.
433430
*/
434-
if (!acpi_s2idle_vendor_amd())
435-
acpi_ec_mark_gpe_for_wake();
431+
acpi_ec_mark_gpe_for_wake();
436432

437433
return 0;
438434
}

drivers/base/power/wakeup.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ suspend_state_t pm_suspend_target_state;
3434
bool events_check_enabled __read_mostly;
3535

3636
/* First wakeup IRQ seen by the kernel in the last cycle. */
37-
unsigned int pm_wakeup_irq __read_mostly;
37+
static unsigned int wakeup_irq[2] __read_mostly;
38+
static DEFINE_RAW_SPINLOCK(wakeup_irq_lock);
3839

3940
/* If greater than 0 and the system is suspending, terminate the suspend. */
4041
static atomic_t pm_abort_suspend __read_mostly;
@@ -942,19 +943,45 @@ void pm_system_cancel_wakeup(void)
942943
atomic_dec_if_positive(&pm_abort_suspend);
943944
}
944945

945-
void pm_wakeup_clear(bool reset)
946+
void pm_wakeup_clear(unsigned int irq_number)
946947
{
947-
pm_wakeup_irq = 0;
948-
if (reset)
948+
raw_spin_lock_irq(&wakeup_irq_lock);
949+
950+
if (irq_number && wakeup_irq[0] == irq_number)
951+
wakeup_irq[0] = wakeup_irq[1];
952+
else
953+
wakeup_irq[0] = 0;
954+
955+
wakeup_irq[1] = 0;
956+
957+
raw_spin_unlock_irq(&wakeup_irq_lock);
958+
959+
if (!irq_number)
949960
atomic_set(&pm_abort_suspend, 0);
950961
}
951962

952963
void pm_system_irq_wakeup(unsigned int irq_number)
953964
{
954-
if (pm_wakeup_irq == 0) {
955-
pm_wakeup_irq = irq_number;
965+
unsigned long flags;
966+
967+
raw_spin_lock_irqsave(&wakeup_irq_lock, flags);
968+
969+
if (wakeup_irq[0] == 0)
970+
wakeup_irq[0] = irq_number;
971+
else if (wakeup_irq[1] == 0)
972+
wakeup_irq[1] = irq_number;
973+
else
974+
irq_number = 0;
975+
976+
raw_spin_unlock_irqrestore(&wakeup_irq_lock, flags);
977+
978+
if (irq_number)
956979
pm_system_wakeup();
957-
}
980+
}
981+
982+
unsigned int pm_wakeup_irq(void)
983+
{
984+
return wakeup_irq[0];
958985
}
959986

960987
/**

include/linux/suspend.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -497,14 +497,14 @@ extern void ksys_sync_helper(void);
497497

498498
/* drivers/base/power/wakeup.c */
499499
extern bool events_check_enabled;
500-
extern unsigned int pm_wakeup_irq;
501500
extern suspend_state_t pm_suspend_target_state;
502501

503502
extern bool pm_wakeup_pending(void);
504503
extern void pm_system_wakeup(void);
505504
extern void pm_system_cancel_wakeup(void);
506-
extern void pm_wakeup_clear(bool reset);
505+
extern void pm_wakeup_clear(unsigned int irq_number);
507506
extern void pm_system_irq_wakeup(unsigned int irq_number);
507+
extern unsigned int pm_wakeup_irq(void);
508508
extern bool pm_get_wakeup_count(unsigned int *count, bool block);
509509
extern bool pm_save_wakeup_count(unsigned int count);
510510
extern void pm_wakep_autosleep_enabled(bool set);

kernel/power/main.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,10 @@ static ssize_t pm_wakeup_irq_show(struct kobject *kobj,
504504
struct kobj_attribute *attr,
505505
char *buf)
506506
{
507-
return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA;
507+
if (!pm_wakeup_irq())
508+
return -ENODATA;
509+
510+
return sprintf(buf, "%u\n", pm_wakeup_irq());
508511
}
509512

510513
power_attr_ro(pm_wakeup_irq);

kernel/power/process.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ int freeze_processes(void)
134134
if (!pm_freezing)
135135
atomic_inc(&system_freezing_cnt);
136136

137-
pm_wakeup_clear(true);
137+
pm_wakeup_clear(0);
138138
pr_info("Freezing user space processes ... ");
139139
pm_freezing = true;
140140
error = try_to_freeze_tasks(true);

kernel/power/suspend.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,6 @@ static void s2idle_loop(void)
136136
break;
137137
}
138138

139-
pm_wakeup_clear(false);
140-
141139
s2idle_enter();
142140
}
143141

0 commit comments

Comments
 (0)