Merge branches 'acpi-pm', 'acpi-sysfs', 'acpi-pci' and 'acpi-resource'

Merge ACPI power management updates, ACPI sysfs interface updates, an
ACPI support update related to PCI, and an ACPI device resources
management update for 6.20-rc1/7.0-rc1:

 - Rework ACPI PM notification setup for PCI root buses and modify the
   ACPI PM setup for devices to register wakeup source objects under
   physical (that is, PCI, platform, etc.) devices instead of doing that
   under their ACPI companions (Rafael Wysocki)

 - Adjust debug messages regarding postponed ACPI PM printed during
   system resume to be more accurate (Rafael Wysocki)

 - Remove dead code from lps0_device_attach() (Gergo Koteles)

 - Start to invoke Microsoft Function 9 (Turn On Display) of the Low-
   Power S0 Idle (LPS0) _DSM in the suspend-to-idle resume flow on
   systems with ACPI LPS0 support to address a functional issue on
   Lenovo Yoga Slim 7i Aura (15ILL9), where system fans and keyboard
   backlights fail to resume after suspend (Jakob Riemenschneider)

 - Add sysfs attribute cid for exposing _CID lists under ACPI device
   objects (Rafael Wysocki)

 - Replace sprintf() with sysfs_emit() in all of the core ACPI sysfs
   interface code (Sumeet Pawnikar)

 - Use acpi_get_local_u64_address() in the code implementing ACPI
   support for PCI to evaluate _ADR instead of evaluating that object
   directly (Andy Shevchenko)

 - Add JWIPC JVC9100 to irq1_level_low_skip_override[] to unbreak
   serial IRQs on that system (Ai Chao)

* acpi-pm:
  ACPI: x86: s2idle: Invoke Microsoft _DSM Function 9 (Turn On Display)
  ACPI: PM: Adjust messages regarding postponed ACPI PM
  ACPI: x86: s2idle: Remove dead code in lps0_device_attach()
  ACPI: PM: Register wakeup sources under physical devices
  ACPI: PCI: PM: Rework root bus notification setup

* acpi-sysfs:
  ACPI: sysfs: Replace sprintf() with sysfs_emit()
  ACPI: sysfs: Add device cid attribute for exposing _CID lists

* acpi-pci:
  ACPI: PCI: simplify code with acpi_get_local_u64_address()

* acpi-resource:
  ACPI: resource: Add JWIPC JVC9100 to irq1_level_low_skip_override[]
This commit is contained in:
Rafael J. Wysocki 2026-02-05 12:49:43 +01:00
9 changed files with 87 additions and 48 deletions

View File

@ -586,8 +586,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
goto out;
mutex_lock(&acpi_pm_notifier_lock);
adev->wakeup.ws = wakeup_source_register(&adev->dev,
dev_name(&adev->dev));
adev->wakeup.ws = wakeup_source_register(dev, dev_name(&adev->dev));
adev->wakeup.context.dev = dev;
adev->wakeup.context.func = func;
adev->wakeup.flags.notifier_present = true;
@ -1252,7 +1251,7 @@ static int acpi_subsys_resume_early(struct device *dev)
return 0;
if (pm && !pm->resume_early) {
dev_dbg(dev, "postponing D0 transition to normal resume stage\n");
dev_dbg(dev, "Postponing ACPI PM to normal resume stage\n");
return 0;
}
@ -1274,7 +1273,7 @@ static int acpi_subsys_resume(struct device *dev)
int ret = 0;
if (!dev_pm_skip_resume(dev) && pm && !pm->resume_early) {
dev_dbg(dev, "executing postponed D0 transition\n");
dev_dbg(dev, "Applying postponed ACPI PM\n");
ret = acpi_dev_resume(dev);
}

View File

@ -27,7 +27,7 @@ static ssize_t acpi_object_path(acpi_handle handle, char *buf)
if (result)
return result;
result = sprintf(buf, "%s\n", (char *)path.pointer);
result = sysfs_emit(buf, "%s\n", (char *)path.pointer);
kfree(path.pointer);
return result;
}
@ -347,7 +347,7 @@ static ssize_t real_power_state_show(struct device *dev,
if (ret)
return ret;
return sprintf(buf, "%s\n", acpi_power_state_string(state));
return sysfs_emit(buf, "%s\n", acpi_power_state_string(state));
}
static DEVICE_ATTR_RO(real_power_state);
@ -357,7 +357,7 @@ static ssize_t power_state_show(struct device *dev,
{
struct acpi_device *adev = to_acpi_device(dev);
return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));
return sysfs_emit(buf, "%s\n", acpi_power_state_string(adev->power.state));
}
static DEVICE_ATTR_RO(power_state);
@ -399,16 +399,43 @@ hid_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct acpi_device *acpi_dev = to_acpi_device(dev);
return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
return sysfs_emit(buf, "%s\n", acpi_device_hid(acpi_dev));
}
static DEVICE_ATTR_RO(hid);
static ssize_t cid_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct acpi_device *acpi_dev = to_acpi_device(dev);
struct acpi_device_info *info = NULL;
ssize_t len = 0;
acpi_get_object_info(acpi_dev->handle, &info);
if (!info)
return 0;
if (info->valid & ACPI_VALID_CID) {
struct acpi_pnp_device_id_list *cid_list = &info->compatible_id_list;
int i;
for (i = 0; i < cid_list->count - 1; i++)
len += sysfs_emit_at(buf, len, "%s,", cid_list->ids[i].string);
len += sysfs_emit_at(buf, len, "%s\n", cid_list->ids[i].string);
}
kfree(info);
return len;
}
static DEVICE_ATTR_RO(cid);
static ssize_t uid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct acpi_device *acpi_dev = to_acpi_device(dev);
return sprintf(buf, "%s\n", acpi_device_uid(acpi_dev));
return sysfs_emit(buf, "%s\n", acpi_device_uid(acpi_dev));
}
static DEVICE_ATTR_RO(uid);
@ -418,9 +445,9 @@ static ssize_t adr_show(struct device *dev,
struct acpi_device *acpi_dev = to_acpi_device(dev);
if (acpi_dev->pnp.bus_address > U32_MAX)
return sprintf(buf, "0x%016llx\n", acpi_dev->pnp.bus_address);
return sysfs_emit(buf, "0x%016llx\n", acpi_dev->pnp.bus_address);
else
return sprintf(buf, "0x%08llx\n", acpi_dev->pnp.bus_address);
return sysfs_emit(buf, "0x%08llx\n", acpi_dev->pnp.bus_address);
}
static DEVICE_ATTR_RO(adr);
@ -482,7 +509,7 @@ sun_show(struct device *dev, struct device_attribute *attr,
if (ACPI_FAILURE(status))
return -EIO;
return sprintf(buf, "%llu\n", sun);
return sysfs_emit(buf, "%llu\n", sun);
}
static DEVICE_ATTR_RO(sun);
@ -498,7 +525,7 @@ hrv_show(struct device *dev, struct device_attribute *attr,
if (ACPI_FAILURE(status))
return -EIO;
return sprintf(buf, "%llu\n", hrv);
return sysfs_emit(buf, "%llu\n", hrv);
}
static DEVICE_ATTR_RO(hrv);
@ -513,13 +540,14 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr,
if (ACPI_FAILURE(status))
return -EIO;
return sprintf(buf, "%llu\n", sta);
return sysfs_emit(buf, "%llu\n", sta);
}
static DEVICE_ATTR_RO(status);
static struct attribute *acpi_attrs[] = {
&dev_attr_path.attr,
&dev_attr_hid.attr,
&dev_attr_cid.attr,
&dev_attr_modalias.attr,
&dev_attr_description.attr,
&dev_attr_adr.attr,
@ -562,6 +590,9 @@ static bool acpi_show_attr(struct acpi_device *dev, const struct device_attribut
if (attr == &dev_attr_status)
return acpi_has_method(dev->handle, "_STA");
if (attr == &dev_attr_cid)
return acpi_has_method(dev->handle, "_CID");
/*
* If device has _EJ0, 'eject' file is created that is used to trigger
* hot-removal function from userland.

View File

@ -738,7 +738,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
if (no_aspm)
pcie_no_aspm();
pci_acpi_add_bus_pm_notifier(device);
pci_acpi_add_root_pm_notifier(device, root);
device_set_wakeup_capable(root->bus->bridge, device->wakeup.flags.valid);
if (hotadd) {

View File

@ -42,8 +42,9 @@ static int
check_slot(acpi_handle handle, unsigned long long *sun)
{
int device = -1;
unsigned long long adr, sta;
unsigned long long sta;
acpi_status status;
u64 adr;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@ -56,10 +57,9 @@ check_slot(acpi_handle handle, unsigned long long *sun)
goto out;
}
status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
if (ACPI_FAILURE(status)) {
pr_debug("_ADR returned %d on %s\n",
status, (char *)buffer.pointer);
if (acpi_get_local_u64_address(handle, &adr)) {
pr_debug("_ADR returned with failure on %s\n",
(char *)buffer.pointer);
goto out;
}

View File

@ -532,6 +532,12 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
DMI_MATCH(DMI_BOARD_NAME, "16T90SP"),
},
},
{
/* JWIPC JVC9100 */
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "JVC9100"),
},
},
{ }
};
@ -706,6 +712,8 @@ struct irq_override_cmp {
static const struct irq_override_cmp override_table[] = {
{ irq1_level_low_skip_override, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
{ irq1_level_low_skip_override, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 1, false },
{ irq1_level_low_skip_override, 11, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 1, false },
{ irq1_edge_low_force_override, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
};

View File

@ -687,7 +687,7 @@ static ssize_t counter_show(struct kobject *kobj,
acpi_irq_not_handled;
all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count =
acpi_gpe_count;
size = sprintf(buf, "%8u", all_counters[index].count);
size = sysfs_emit(buf, "%8u", all_counters[index].count);
/* "gpe_all" or "sci" */
if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
@ -698,29 +698,29 @@ static ssize_t counter_show(struct kobject *kobj,
goto end;
if (status & ACPI_EVENT_FLAG_ENABLE_SET)
size += sprintf(buf + size, " EN");
size += sysfs_emit_at(buf, size, " EN");
else
size += sprintf(buf + size, " ");
size += sysfs_emit_at(buf, size, " ");
if (status & ACPI_EVENT_FLAG_STATUS_SET)
size += sprintf(buf + size, " STS");
size += sysfs_emit_at(buf, size, " STS");
else
size += sprintf(buf + size, " ");
size += sysfs_emit_at(buf, size, " ");
if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER))
size += sprintf(buf + size, " invalid ");
size += sysfs_emit_at(buf, size, " invalid ");
else if (status & ACPI_EVENT_FLAG_ENABLED)
size += sprintf(buf + size, " enabled ");
size += sysfs_emit_at(buf, size, " enabled ");
else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED)
size += sprintf(buf + size, " wake_enabled");
size += sysfs_emit_at(buf, size, " wake_enabled");
else
size += sprintf(buf + size, " disabled ");
size += sysfs_emit_at(buf, size, " disabled ");
if (status & ACPI_EVENT_FLAG_MASKED)
size += sprintf(buf + size, " masked ");
size += sysfs_emit_at(buf, size, " masked ");
else
size += sprintf(buf + size, " unmasked");
size += sysfs_emit_at(buf, size, " unmasked");
end:
size += sprintf(buf + size, "\n");
size += sysfs_emit_at(buf, size, "\n");
return result ? result : size;
}
@ -937,7 +937,7 @@ static void __exit interrupt_stats_exit(void)
static ssize_t pm_profile_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile);
return sysfs_emit(buf, "%d\n", acpi_gbl_FADT.preferred_profile);
}
static const struct kobj_attribute pm_profile_attr = __ATTR_RO(pm_profile);
@ -946,7 +946,7 @@ static ssize_t enabled_show(struct kobject *kobj, struct kobj_attribute *attr, c
{
struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
return sprintf(buf, "%d\n", hotplug->enabled);
return sysfs_emit(buf, "%d\n", hotplug->enabled);
}
static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@ -1000,7 +1000,7 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
static ssize_t force_remove_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", 0);
return sysfs_emit(buf, "%d\n", 0);
}
static ssize_t force_remove_store(struct kobject *kobj,

View File

@ -49,6 +49,7 @@ static const struct acpi_device_id lps0_device_ids[] = {
#define ACPI_LPS0_EXIT 6
#define ACPI_LPS0_MS_ENTRY 7
#define ACPI_LPS0_MS_EXIT 8
#define ACPI_MS_TURN_ON_DISPLAY 9
/* AMD */
#define ACPI_LPS0_DSM_UUID_AMD "e3f32452-febc-43ce-9039-932122d37721"
@ -356,6 +357,8 @@ static const char *acpi_sleep_dsm_state_to_str(unsigned int state)
return "lps0 ms entry";
case ACPI_LPS0_MS_EXIT:
return "lps0 ms exit";
case ACPI_MS_TURN_ON_DISPLAY:
return "lps0 ms turn on display";
}
} else {
switch (state) {
@ -463,9 +466,6 @@ static int lps0_device_attach(struct acpi_device *adev,
lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask);
} else if (lps0_dsm_func_mask_microsoft > 0 && rev_id) {
lps0_dsm_func_mask_microsoft = -EINVAL;
acpi_handle_debug(adev->handle, "_DSM Using AMD method\n");
}
} else {
rev_id = 1;
@ -617,6 +617,9 @@ static void acpi_s2idle_restore_early_lps0(void)
if (lps0_dsm_func_mask_microsoft > 0) {
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
/* Intent to turn on display */
acpi_sleep_run_lps0_dsm(ACPI_MS_TURN_ON_DISPLAY,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
/* Modern Standby exit */
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);

View File

@ -847,12 +847,7 @@ bool shpchp_is_native(struct pci_dev *bridge)
*/
static void pci_acpi_wake_bus(struct acpi_device_wakeup_context *context)
{
struct acpi_device *adev;
struct acpi_pci_root *root;
adev = container_of(context, struct acpi_device, wakeup.context);
root = acpi_driver_data(adev);
pci_pme_wakeup_bus(root->bus);
pci_pme_wakeup_bus(to_pci_host_bridge(context->dev)->bus);
}
/**
@ -885,12 +880,14 @@ static void pci_acpi_wake_dev(struct acpi_device_wakeup_context *context)
}
/**
* pci_acpi_add_bus_pm_notifier - Register PM notifier for root PCI bus.
* pci_acpi_add_root_pm_notifier - Register PM notifier for root PCI bus.
* @dev: PCI root bridge ACPI device.
* @root: PCI root corresponding to @dev.
*/
acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev)
acpi_status pci_acpi_add_root_pm_notifier(struct acpi_device *dev,
struct acpi_pci_root *root)
{
return acpi_add_pm_notifier(dev, NULL, pci_acpi_wake_bus);
return acpi_add_pm_notifier(dev, root->bus->bridge, pci_acpi_wake_bus);
}
/**

View File

@ -12,7 +12,8 @@
#include <linux/acpi.h>
#ifdef CONFIG_ACPI
extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev);
extern acpi_status pci_acpi_add_root_pm_notifier(struct acpi_device *dev,
struct acpi_pci_root *pci_root);
static inline acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
{
return acpi_remove_pm_notifier(dev);