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

Merge power management, PCI and sysfs-related material and changes
related to handling ACPI tables for 5.19-rc1:

 - Improve debug messages in the ACPI device PM code (Rafael Wysocki).

 - Block ASUS B1400CEAE from suspend to idle by default (Mario
   Limonciello).

 - Improve handling of PCI devices that are in D3cold during system
   initialization (Rafael Wysocki).

 - Fix BERT error region memory mapping (Lorenzo Pieralisi).

 - Add support for NVIDIA 16550-compatible port subtype to the SPCR
   parsing code (Jeff Brasen).

 - Use static for BGRT_SHOW kobj_attribute defines (Tom Rix).

 - Fix missing prototype warning for acpi_agdi_init() (Ilkka Koskinen).

* acpi-pm:
  ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
  ACPI: PM: Always print final debug message in acpi_device_set_power()
  ACPI: PM: Unify debug messages in acpi_device_set_power()
  ACPI: PM: Change pr_fmt() in device_pm.c
  ACPI: PM: Convert debug message in acpi_device_get_power()

* acpi-pci:
  ACPI: bus: Avoid non-ACPI device objects in walks over children
  PCI: ACPI: PM: Power up devices in D3cold before scanning them
  ACPI: PM: Introduce acpi_dev_power_up_children_with_adr()
  ACPI: bus: Introduce acpi_dev_for_each_child()

* acpi-sysfs:
  ACPI: sysfs: Fix BERT error region memory mapping

* acpi-tables:
  ACPI: AGDI: Fix missing prototype warning for acpi_agdi_init()
  ACPI: BGRT: use static for BGRT_SHOW kobj_attribute defines
  ACPI: SPCR: Add support for NVIDIA 16550-compatible port subtype
This commit is contained in:
Rafael J. Wysocki 2022-05-23 18:29:20 +02:00
10 changed files with 124 additions and 34 deletions

View File

@ -9,6 +9,7 @@
#define pr_fmt(fmt) "ACPI: AGDI: " fmt
#include <linux/acpi.h>
#include <linux/acpi_agdi.h>
#include <linux/arm_sdei.h>
#include <linux/io.h>
#include <linux/kernel.h>

View File

@ -21,7 +21,7 @@ static struct kobject *bgrt_kobj;
{ \
return sysfs_emit(buf, "%d\n", bgrt_tab._member); \
} \
struct kobj_attribute bgrt_attr_##_name = __ATTR_RO(_name)
static struct kobj_attribute bgrt_attr_##_name = __ATTR_RO(_name)
BGRT_SHOW(version, version);
BGRT_SHOW(status, status);

View File

@ -1070,6 +1070,32 @@ int acpi_bus_for_each_dev(int (*fn)(struct device *, void *), void *data)
}
EXPORT_SYMBOL_GPL(acpi_bus_for_each_dev);
struct acpi_dev_walk_context {
int (*fn)(struct acpi_device *, void *);
void *data;
};
static int acpi_dev_for_one_check(struct device *dev, void *context)
{
struct acpi_dev_walk_context *adwc = context;
if (dev->bus != &acpi_bus_type)
return 0;
return adwc->fn(to_acpi_device(dev), adwc->data);
}
int acpi_dev_for_each_child(struct acpi_device *adev,
int (*fn)(struct acpi_device *, void *), void *data)
{
struct acpi_dev_walk_context adwc = {
.fn = fn,
.data = data,
};
return device_for_each_child(&adev->dev, &adwc, acpi_dev_for_one_check);
}
/* --------------------------------------------------------------------------
Initialization/Cleanup
-------------------------------------------------------------------------- */

View File

@ -10,7 +10,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#define pr_fmt(fmt) "ACPI: PM: " fmt
#define pr_fmt(fmt) "PM: " fmt
#include <linux/acpi.h>
#include <linux/export.h>
@ -130,8 +130,8 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
*state = result;
out:
dev_dbg(&device->dev, "Device power state is %s\n",
acpi_power_state_string(*state));
acpi_handle_debug(device->handle, "Power state: %s\n",
acpi_power_state_string(*state));
return 0;
}
@ -173,11 +173,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
/* Make sure this is a valid target state */
/* There is a special case for D0 addressed below. */
if (state > ACPI_STATE_D0 && state == device->power.state) {
dev_dbg(&device->dev, "Device already in %s\n",
acpi_power_state_string(state));
return 0;
}
if (state > ACPI_STATE_D0 && state == device->power.state)
goto no_change;
if (state == ACPI_STATE_D3_COLD) {
/*
@ -189,17 +186,17 @@ int acpi_device_set_power(struct acpi_device *device, int state)
if (!device->power.states[ACPI_STATE_D3_COLD].flags.valid)
target_state = state;
} else if (!device->power.states[state].flags.valid) {
dev_warn(&device->dev, "Power state %s not supported\n",
acpi_power_state_string(state));
acpi_handle_debug(device->handle, "Power state %s not supported\n",
acpi_power_state_string(state));
return -ENODEV;
}
if (!device->power.flags.ignore_parent &&
device->parent && (state < device->parent->power.state)) {
dev_warn(&device->dev,
"Cannot transition to power state %s for parent in %s\n",
acpi_power_state_string(state),
acpi_power_state_string(device->parent->power.state));
if (!device->power.flags.ignore_parent && device->parent &&
state < device->parent->power.state) {
acpi_handle_debug(device->handle,
"Cannot transition to %s for parent in %s\n",
acpi_power_state_string(state),
acpi_power_state_string(device->parent->power.state));
return -ENODEV;
}
@ -216,9 +213,10 @@ int acpi_device_set_power(struct acpi_device *device, int state)
* (deeper) states to higher-power (shallower) states.
*/
if (state < device->power.state) {
dev_warn(&device->dev, "Cannot transition from %s to %s\n",
acpi_power_state_string(device->power.state),
acpi_power_state_string(state));
acpi_handle_debug(device->handle,
"Cannot transition from %s to %s\n",
acpi_power_state_string(device->power.state),
acpi_power_state_string(state));
return -ENODEV;
}
@ -248,7 +246,7 @@ int acpi_device_set_power(struct acpi_device *device, int state)
/* Nothing to do here if _PSC is not present. */
if (!device->power.flags.explicit_get)
return 0;
goto no_change;
/*
* The power state of the device was set to D0 last
@ -263,23 +261,29 @@ int acpi_device_set_power(struct acpi_device *device, int state)
*/
result = acpi_dev_pm_explicit_get(device, &psc);
if (result || psc == ACPI_STATE_D0)
return 0;
goto no_change;
}
result = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0);
}
end:
end:
if (result) {
dev_warn(&device->dev, "Failed to change power state to %s\n",
acpi_power_state_string(target_state));
acpi_handle_debug(device->handle,
"Failed to change power state to %s\n",
acpi_power_state_string(target_state));
} else {
device->power.state = target_state;
dev_dbg(&device->dev, "Power state changed to %s\n",
acpi_power_state_string(target_state));
acpi_handle_debug(device->handle, "Power state changed to %s\n",
acpi_power_state_string(target_state));
}
return result;
no_change:
acpi_handle_debug(device->handle, "Already in %s\n",
acpi_power_state_string(state));
return 0;
}
EXPORT_SYMBOL(acpi_device_set_power);
@ -425,6 +429,33 @@ bool acpi_bus_power_manageable(acpi_handle handle)
}
EXPORT_SYMBOL(acpi_bus_power_manageable);
static int acpi_power_up_if_adr_present(struct acpi_device *adev, void *not_used)
{
if (!(adev->flags.power_manageable && adev->pnp.type.bus_address))
return 0;
acpi_handle_debug(adev->handle, "Power state: %s\n",
acpi_power_state_string(adev->power.state));
if (adev->power.state == ACPI_STATE_D3_COLD)
return acpi_device_set_power(adev, ACPI_STATE_D0);
return 0;
}
/**
* acpi_dev_power_up_children_with_adr - Power up childres with valid _ADR
* @adev: Parent ACPI device object.
*
* Change the power states of the direct children of @adev that are in D3cold
* and hold valid _ADR objects to D0 in order to allow bus (e.g. PCI)
* enumeration code to access them.
*/
void acpi_dev_power_up_children_with_adr(struct acpi_device *adev)
{
acpi_dev_for_each_child(adev, acpi_power_up_if_adr_present, NULL);
}
#ifdef CONFIG_PM
static DEFINE_MUTEX(acpi_pm_notifier_lock);
static DEFINE_MUTEX(acpi_pm_notifier_install_lock);

View File

@ -927,6 +927,8 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
host_bridge->preserve_config = 1;
ACPI_FREE(obj);
acpi_dev_power_up_children_with_adr(device);
pci_scan_child_bus(bus);
pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info,
info);

View File

@ -373,6 +373,18 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "20GGA00L00"),
},
},
/*
* ASUS B1400CEAE hangs on resume from suspend (see
* https://bugzilla.kernel.org/show_bug.cgi?id=215742).
*/
{
.callback = init_default_s3,
.ident = "ASUS B1400CEAE",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK B1400CEAE"),
},
},
{},
};

View File

@ -142,6 +142,7 @@ int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console)
case ACPI_DBG2_16550_COMPATIBLE:
case ACPI_DBG2_16550_SUBSET:
case ACPI_DBG2_16550_WITH_GAS:
case ACPI_DBG2_16550_NVIDIA:
uart = "uart";
break;
default:

View File

@ -415,19 +415,30 @@ static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj,
loff_t offset, size_t count)
{
struct acpi_data_attr *data_attr;
void *base;
ssize_t rc;
void __iomem *base;
ssize_t size;
data_attr = container_of(bin_attr, struct acpi_data_attr, attr);
size = data_attr->attr.size;
base = acpi_os_map_memory(data_attr->addr, data_attr->attr.size);
if (offset < 0)
return -EINVAL;
if (offset >= size)
return 0;
if (count > size - offset)
count = size - offset;
base = acpi_os_map_iomem(data_attr->addr, size);
if (!base)
return -ENOMEM;
rc = memory_read_from_buffer(buf, count, &offset, base,
data_attr->attr.size);
acpi_os_unmap_memory(base, data_attr->attr.size);
return rc;
memcpy_fromio(buf, base + offset, count);
acpi_os_unmap_iomem(base, size);
return count;
}
static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr)

View File

@ -1374,6 +1374,9 @@ void pci_acpi_setup(struct device *dev, struct acpi_device *adev)
acpi_pci_wakeup(pci_dev, false);
acpi_device_power_add_dependent(adev, dev);
if (pci_is_bridge(pci_dev))
acpi_dev_power_up_children_with_adr(adev);
}
void pci_acpi_cleanup(struct device *dev, struct acpi_device *adev)

View File

@ -481,6 +481,8 @@ void acpi_initialize_hp_context(struct acpi_device *adev,
extern struct bus_type acpi_bus_type;
int acpi_bus_for_each_dev(int (*fn)(struct device *, void *), void *data);
int acpi_dev_for_each_child(struct acpi_device *adev,
int (*fn)(struct acpi_device *, void *), void *data);
/*
* Events
@ -522,6 +524,7 @@ int acpi_device_fix_up_power(struct acpi_device *device);
int acpi_bus_update_power(acpi_handle handle, int *state_p);
int acpi_device_update_power(struct acpi_device *device, int *state_p);
bool acpi_bus_power_manageable(acpi_handle handle);
void acpi_dev_power_up_children_with_adr(struct acpi_device *adev);
int acpi_device_power_add_dependent(struct acpi_device *adev,
struct device *dev);
void acpi_device_power_remove_dependent(struct acpi_device *adev,