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:
commit
4aa8c70cb0
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
-------------------------------------------------------------------------- */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue