diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/acpi/ac.c | 19 | ||||
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 13 | ||||
-rw-r--r-- | drivers/acpi/acpi_pnp.c | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/acglobal.h | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwesleep.c | 8 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwsleep.c | 11 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwxfsleep.c | 7 | ||||
-rw-r--r-- | drivers/acpi/acpica/utosi.c | 1 | ||||
-rw-r--r-- | drivers/acpi/arm64/gtdt.c | 2 | ||||
-rw-r--r-- | drivers/acpi/dock.c | 8 | ||||
-rw-r--r-- | drivers/acpi/glue.c | 66 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/power.c | 104 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 3 | ||||
-rw-r--r-- | drivers/acpi/resource.c | 56 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 6 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 10 | ||||
-rw-r--r-- | drivers/acpi/tables.c | 3 | ||||
-rw-r--r-- | drivers/acpi/x86/s2idle.c | 3 |
20 files changed, 214 insertions, 113 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 1da360c51d66..cdbdf68bd98f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -71,7 +71,7 @@ config ACPI_DEBUGGER if ACPI_DEBUGGER config ACPI_DEBUGGER_USER - tristate "Userspace debugger accessiblity" + tristate "Userspace debugger accessibility" depends on DEBUG_FS help Export /sys/kernel/debug/acpi/acpidbg for userspace utilities diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index b0cb662233f1..81aff651a0d4 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -61,6 +61,7 @@ static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); static int ac_sleep_before_get_state_ms; static int ac_check_pmic = 1; +static int ac_only; static struct acpi_driver acpi_ac_driver = { .name = "ac", @@ -93,6 +94,11 @@ static int acpi_ac_get_state(struct acpi_ac *ac) if (!ac) return -EINVAL; + if (ac_only) { + ac->state = 1; + return 0; + } + status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); if (ACPI_FAILURE(status)) { @@ -200,6 +206,12 @@ static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d) return 0; } +static int __init ac_only_quirk(const struct dmi_system_id *d) +{ + ac_only = 1; + return 0; +} + /* Please keep this list alphabetically sorted */ static const struct dmi_system_id ac_dmi_table[] __initconst = { { @@ -210,6 +222,13 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = { }, }, { + /* Kodlix GK45 returning incorrect state */ + .callback = ac_only_quirk, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "GK45"), + }, + }, + { /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ .callback = ac_do_not_check_pmic_quirk, .matches = { diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 30b1f511c2af..bcae0f03572b 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -712,14 +712,13 @@ static void __lpss_reg_write(u32 val, struct lpss_private_data *pdata, static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val) { - struct acpi_device *adev; + struct acpi_device *adev = ACPI_COMPANION(dev); struct lpss_private_data *pdata; unsigned long flags; int ret; - ret = acpi_bus_get_device(ACPI_HANDLE(dev), &adev); - if (WARN_ON(ret)) - return ret; + if (WARN_ON(!adev)) + return -ENODEV; spin_lock_irqsave(&dev->power.lock, flags); if (pm_runtime_suspended(dev)) { @@ -732,6 +731,7 @@ static int lpss_reg_read(struct device *dev, unsigned int reg, u32 *val) goto out; } *val = __lpss_reg_read(pdata, reg); + ret = 0; out: spin_unlock_irqrestore(&dev->power.lock, flags); @@ -750,7 +750,7 @@ static ssize_t lpss_ltr_show(struct device *dev, struct device_attribute *attr, if (ret) return ret; - return snprintf(buf, PAGE_SIZE, "%08x\n", ltr_value); + return sysfs_emit(buf, "%08x\n", ltr_value); } static ssize_t lpss_ltr_mode_show(struct device *dev, @@ -1266,7 +1266,8 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, if (!id || !id->driver_data) return 0; - if (acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev)) + adev = ACPI_COMPANION(&pdev->dev); + if (!adev) return 0; pdata = acpi_driver_data(adev); diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 8f2dc176bb41..ffdcfcd4a10d 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -156,8 +156,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { {"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */ {"BRI1400"}, /* Boca Research 33,600 ACF Modem */ {"BRI3400"}, /* Boca 33.6 Kbps Internal FD34FSVD */ - {"BRI0A49"}, /* Boca 33.6 Kbps Internal FD34FSVD */ - {"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */ {"CPI4050"}, /* Computer Peripherals Inc. EuroViVa CommCenter-33.6 SP PnP */ {"CTL3001"}, /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */ {"CTL3011"}, /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index d41b810e367c..4366d36ef119 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -226,6 +226,8 @@ extern struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG]; ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a); ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b); +ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a_s0); +ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b_s0); /***************************************************************************** * diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 803402aefaeb..808fdf54aeeb 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -147,17 +147,13 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) { - acpi_status status; u8 sleep_type_value; ACPI_FUNCTION_TRACE(hw_extended_wake_prep); - status = acpi_get_sleep_type_data(ACPI_STATE_S0, - &acpi_gbl_sleep_type_a, - &acpi_gbl_sleep_type_b); - if (ACPI_SUCCESS(status)) { + if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) { sleep_type_value = - ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & + ((acpi_gbl_sleep_type_a_s0 << ACPI_X_SLEEP_TYPE_POSITION) & ACPI_X_SLEEP_TYPE_MASK); (void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 14baa13bf848..34a3825f25d3 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -179,7 +179,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) { - acpi_status status; + acpi_status status = AE_OK; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; u32 pm1a_control; @@ -192,10 +192,7 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) * This is unclear from the ACPI Spec, but it is required * by some machines. */ - status = acpi_get_sleep_type_data(ACPI_STATE_S0, - &acpi_gbl_sleep_type_a, - &acpi_gbl_sleep_type_b); - if (ACPI_SUCCESS(status)) { + if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) { sleep_type_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); sleep_enable_reg_info = @@ -216,9 +213,9 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) /* Insert the SLP_TYP bits */ - pm1a_control |= (acpi_gbl_sleep_type_a << + pm1a_control |= (acpi_gbl_sleep_type_a_s0 << sleep_type_reg_info->bit_position); - pm1b_control |= (acpi_gbl_sleep_type_b << + pm1b_control |= (acpi_gbl_sleep_type_b_s0 << sleep_type_reg_info->bit_position); /* Write the control registers and ignore any errors */ diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index 89b12afed564..e4cde23a2906 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -217,6 +217,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) return_ACPI_STATUS(status); } + status = acpi_get_sleep_type_data(ACPI_STATE_S0, + &acpi_gbl_sleep_type_a_s0, + &acpi_gbl_sleep_type_b_s0); + if (ACPI_FAILURE(status)) { + acpi_gbl_sleep_type_a_s0 = ACPI_SLEEP_TYPE_INVALID; + } + /* Execute the _PTS method (Prepare To Sleep) */ arg_list.count = 1; diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index 7b8e8bf1e824..8afa1ccaf12e 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -73,6 +73,7 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = { {"Windows 2018", NULL, 0, ACPI_OSI_WIN_10_RS4}, /* Windows 10 version 1803 - Added 11/2018 */ {"Windows 2018.2", NULL, 0, ACPI_OSI_WIN_10_RS5}, /* Windows 10 version 1809 - Added 11/2018 */ {"Windows 2019", NULL, 0, ACPI_OSI_WIN_10_19H1}, /* Windows 10 version 1903 - Added 08/2019 */ + {"Windows 2020", NULL, 0, ACPI_OSI_WIN_10_20H1}, /* Windows 10 version 2004 - Added 08/2021 */ /* Feature Group Strings */ diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c index 0a0a982f9c28..c0e77c1c8e09 100644 --- a/drivers/acpi/arm64/gtdt.c +++ b/drivers/acpi/arm64/gtdt.c @@ -36,7 +36,7 @@ struct acpi_gtdt_descriptor { static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata; -static inline void *next_platform_timer(void *platform_timer) +static inline __init void *next_platform_timer(void *platform_timer) { struct acpi_gtdt_header *gh = platform_timer; diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 7cf92158008f..c8e9b962e18c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -492,7 +492,7 @@ static ssize_t docked_show(struct device *dev, struct acpi_device *adev = NULL; acpi_bus_get_device(dock_station->handle, &adev); - return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev)); + return sysfs_emit(buf, "%u\n", acpi_device_enumerated(adev)); } static DEVICE_ATTR_RO(docked); @@ -504,7 +504,7 @@ static ssize_t flags_show(struct device *dev, { struct dock_station *dock_station = dev->platform_data; - return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); + return sysfs_emit(buf, "%d\n", dock_station->flags); } static DEVICE_ATTR_RO(flags); @@ -543,7 +543,7 @@ static ssize_t uid_show(struct device *dev, if (ACPI_FAILURE(status)) return 0; - return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf); + return sysfs_emit(buf, "%llx\n", lbuf); } static DEVICE_ATTR_RO(uid); @@ -562,7 +562,7 @@ static ssize_t type_show(struct device *dev, else type = "unknown"; - return snprintf(buf, PAGE_SIZE, "%s\n", type); + return sysfs_emit(buf, "%s\n", type); } static DEVICE_ATTR_RO(type); diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 7a33a6d985f8..7cd0009e7ff3 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -17,6 +17,8 @@ #include <linux/rwsem.h> #include <linux/acpi.h> #include <linux/dma-mapping.h> +#include <linux/pci.h> +#include <linux/pci-acpi.h> #include <linux/platform_device.h> #include "internal.h" @@ -111,13 +113,10 @@ struct acpi_device *acpi_find_child_device(struct acpi_device *parent, return NULL; list_for_each_entry(adev, &parent->children, node) { - unsigned long long addr; - acpi_status status; + acpi_bus_address addr = acpi_device_adr(adev); int score; - status = acpi_evaluate_integer(adev->handle, METHOD_NAME__ADR, - NULL, &addr); - if (ACPI_FAILURE(status) || addr != address) + if (!adev->pnp.type.bus_address || addr != address) continue; if (!ret) { @@ -287,12 +286,13 @@ EXPORT_SYMBOL_GPL(acpi_unbind_one); void acpi_device_notify(struct device *dev) { - struct acpi_bus_type *type = acpi_get_bus_type(dev); struct acpi_device *adev; int ret; ret = acpi_bind_one(dev, NULL); if (ret) { + struct acpi_bus_type *type = acpi_get_bus_type(dev); + if (!type) goto err; @@ -304,17 +304,26 @@ void acpi_device_notify(struct device *dev) ret = acpi_bind_one(dev, adev); if (ret) goto err; - } - adev = ACPI_COMPANION(dev); - if (dev_is_platform(dev)) - acpi_configure_pmsi_domain(dev); + if (type->setup) { + type->setup(dev); + goto done; + } + } else { + adev = ACPI_COMPANION(dev); + + if (dev_is_pci(dev)) { + pci_acpi_setup(dev, adev); + goto done; + } else if (dev_is_platform(dev)) { + acpi_configure_pmsi_domain(dev); + } + } - if (type && type->setup) - type->setup(dev); - else if (adev->handler && adev->handler->bind) + if (adev->handler && adev->handler->bind) adev->handler->bind(dev); +done: acpi_handle_debug(ACPI_HANDLE(dev), "Bound to device %s\n", dev_name(dev)); @@ -327,16 +336,39 @@ err: void acpi_device_notify_remove(struct device *dev) { struct acpi_device *adev = ACPI_COMPANION(dev); - struct acpi_bus_type *type; if (!adev) return; - type = acpi_get_bus_type(dev); - if (type && type->cleanup) - type->cleanup(dev); + if (dev_is_pci(dev)) + pci_acpi_cleanup(dev, adev); else if (adev->handler && adev->handler->unbind) adev->handler->unbind(dev); acpi_unbind_one(dev); } + +int acpi_dev_turn_off_if_unused(struct device *dev, void *not_used) +{ + struct acpi_device *adev = to_acpi_device(dev); + + /* + * Skip device objects with device IDs, because they may be in use even + * if they are not companions of any physical device objects. + */ + if (adev->pnp.type.hardware_id) + return 0; + + mutex_lock(&adev->physical_node_lock); + + /* + * Device objects without device IDs are not in use if they have no + * corresponding physical device objects. + */ + if (list_empty(&adev->physical_node_list)) + acpi_device_set_power(adev, ACPI_STATE_D3_COLD); + + mutex_unlock(&adev->physical_node_lock); + + return 0; +} diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index d91b560e8867..8fbdc172864b 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -117,6 +117,7 @@ bool acpi_device_is_battery(struct acpi_device *adev); bool acpi_device_is_first_physical_node(struct acpi_device *adev, const struct device *dev); int acpi_bus_register_early_device(int type); +int acpi_dev_turn_off_if_unused(struct device *dev, void *not_used); /* -------------------------------------------------------------------------- Device Matching and Notification diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index b9863e22b952..112256154880 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -52,7 +52,6 @@ struct acpi_power_resource { u32 order; unsigned int ref_count; u8 state; - bool wakeup_enabled; struct mutex resource_lock; struct list_head dependents; }; @@ -615,20 +614,19 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p) list_for_each_entry(entry, list, node) { struct acpi_power_resource *resource = entry->resource; - int result; u8 state; mutex_lock(&resource->resource_lock); - result = acpi_power_get_state(resource, &state); - if (result) { - mutex_unlock(&resource->resource_lock); - return result; - } - if (state == ACPI_POWER_RESOURCE_STATE_ON) { - resource->ref_count++; - resource->wakeup_enabled = true; - } + /* + * Make sure that the power resource state and its reference + * counter value are consistent with each other. + */ + if (!resource->ref_count && + !acpi_power_get_state(resource, &state) && + state == ACPI_POWER_RESOURCE_STATE_ON) + __acpi_power_off(resource); + if (system_level > resource->system_level) system_level = resource->system_level; @@ -711,7 +709,6 @@ int acpi_device_sleep_wake(struct acpi_device *dev, */ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) { - struct acpi_power_resource_entry *entry; int err = 0; if (!dev || !dev->wakeup.flags.valid) @@ -722,33 +719,22 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) if (dev->wakeup.prepare_count++) goto out; - list_for_each_entry(entry, &dev->wakeup.resources, node) { - struct acpi_power_resource *resource = entry->resource; - - mutex_lock(&resource->resource_lock); - - if (!resource->wakeup_enabled) { - err = acpi_power_on_unlocked(resource); - if (!err) - resource->wakeup_enabled = true; - } - - mutex_unlock(&resource->resource_lock); - - if (err) { - dev_err(&dev->dev, - "Cannot turn wakeup power resources on\n"); - dev->wakeup.flags.valid = 0; - goto out; - } + err = acpi_power_on_list(&dev->wakeup.resources); + if (err) { + dev_err(&dev->dev, "Cannot turn on wakeup power resources\n"); + dev->wakeup.flags.valid = 0; + goto out; } + /* * Passing 3 as the third argument below means the device may be * put into arbitrary power state afterward. */ err = acpi_device_sleep_wake(dev, 1, sleep_state, 3); - if (err) + if (err) { + acpi_power_off_list(&dev->wakeup.resources); dev->wakeup.prepare_count = 0; + } out: mutex_unlock(&acpi_device_lock); @@ -771,39 +757,33 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) mutex_lock(&acpi_device_lock); - if (--dev->wakeup.prepare_count > 0) + if (dev->wakeup.prepare_count > 1) { + dev->wakeup.prepare_count--; goto out; + } - /* - * Executing the code below even if prepare_count is already zero when - * the function is called may be useful, for example for initialisation. - */ - if (dev->wakeup.prepare_count < 0) - dev->wakeup.prepare_count = 0; + /* Do nothing if wakeup power has not been enabled for this device. */ + if (!dev->wakeup.prepare_count) + goto out; err = acpi_device_sleep_wake(dev, 0, 0, 0); if (err) goto out; + /* + * All of the power resources in the list need to be turned off even if + * there are errors. + */ list_for_each_entry(entry, &dev->wakeup.resources, node) { - struct acpi_power_resource *resource = entry->resource; - - mutex_lock(&resource->resource_lock); - - if (resource->wakeup_enabled) { - err = acpi_power_off_unlocked(resource); - if (!err) - resource->wakeup_enabled = false; - } - - mutex_unlock(&resource->resource_lock); + int ret; - if (err) { - dev_err(&dev->dev, - "Cannot turn wakeup power resources off\n"); - dev->wakeup.flags.valid = 0; - break; - } + ret = acpi_power_off(entry->resource); + if (ret && !err) + err = ret; + } + if (err) { + dev_err(&dev->dev, "Cannot turn off wakeup power resources\n"); + dev->wakeup.flags.valid = 0; } out: @@ -943,6 +923,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) union acpi_object acpi_object; struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object }; acpi_status status; + u8 state_dummy; int result; acpi_bus_get_device(handle, &device); @@ -971,6 +952,10 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) resource->order = acpi_object.power_resource.resource_order; resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN; + /* Get the initial state or just flip it on if that fails. */ + if (acpi_power_get_state(resource, &state_dummy)) + __acpi_power_on(resource); + pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device)); device->flags.match_driver = true; @@ -1035,13 +1020,8 @@ void acpi_turn_off_unused_power_resources(void) list_for_each_entry_reverse(resource, &acpi_power_resource_list, list_node) { mutex_lock(&resource->resource_lock); - /* - * Turn off power resources in an unknown state too, because the - * platform firmware on some system expects the OS to turn off - * power resources without any users unconditionally. - */ if (!resource->ref_count && - resource->state != ACPI_POWER_RESOURCE_STATE_OFF) { + resource->state == ACPI_POWER_RESOURCE_STATE_ON) { acpi_handle_debug(resource->device.handle, "Turning OFF\n"); __acpi_power_off(resource); } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f37fba9e5ba0..76ef1bcc8848 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -789,7 +789,8 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr) state->enter = acpi_idle_enter; state->flags = 0; - if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2) { + if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2 || + cx->type == ACPI_STATE_C3) { state->enter_dead = acpi_idle_play_dead; drv->safe_state_index = count; } diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index ee78a210c606..3c25ce8c95ba 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -16,6 +16,7 @@ #include <linux/ioport.h> #include <linux/slab.h> #include <linux/irq.h> +#include <linux/dmi.h> #ifdef CONFIG_X86 #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) @@ -380,9 +381,58 @@ unsigned int acpi_dev_get_irq_type(int triggering, int polarity) } EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type); +static const struct dmi_system_id medion_laptop[] = { + { + .ident = "MEDION P15651", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_BOARD_NAME, "M15T"), + }, + }, + { + .ident = "MEDION S17405", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_BOARD_NAME, "M17T"), + }, + }, + { } +}; + +struct irq_override_cmp { + const struct dmi_system_id *system; + unsigned char irq; + unsigned char triggering; + unsigned char polarity; + unsigned char shareable; +}; + +static const struct irq_override_cmp skip_override_table[] = { + { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 }, +}; + +static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, + u8 shareable) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(skip_override_table); i++) { + const struct irq_override_cmp *entry = &skip_override_table[i]; + + if (dmi_check_system(entry->system) && + entry->irq == gsi && + entry->triggering == triggering && + entry->polarity == polarity && + entry->shareable == shareable) + return false; + } + + return true; +} + static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, u8 triggering, u8 polarity, u8 shareable, - bool legacy) + bool check_override) { int irq, p, t; @@ -401,7 +451,9 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, * using extended IRQ descriptors we take the IRQ configuration * from _CRS directly. */ - if (legacy && !acpi_get_override_irq(gsi, &t, &p)) { + if (check_override && + acpi_dev_irq_override(gsi, triggering, polarity, shareable) && + !acpi_get_override_irq(gsi, &t, &p)) { u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5b54c80b9d32..770b82483d74 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2559,6 +2559,12 @@ int __init acpi_scan_init(void) } } + /* + * Make sure that power management resources are not blocked by ACPI + * device objects with no users. + */ + bus_for_each_dev(&acpi_bus_type, NULL, NULL, acpi_dev_turn_off_if_unused); + acpi_turn_off_unused_power_resources(); acpi_scan_initialized = true; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3023224515ab..eaa47753b758 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -815,14 +815,18 @@ void __weak acpi_s2idle_setup(void) static void acpi_sleep_suspend_setup(void) { + bool suspend_ops_needed = false; int i; for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) - if (acpi_sleep_state_supported(i)) + if (acpi_sleep_state_supported(i)) { sleep_states[i] = 1; + suspend_ops_needed = true; + } - suspend_set_ops(old_suspend_ordering ? - &acpi_suspend_ops_old : &acpi_suspend_ops); + if (suspend_ops_needed) + suspend_set_ops(old_suspend_ordering ? + &acpi_suspend_ops_old : &acpi_suspend_ops); acpi_s2idle_setup(); } diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index f9383736fa0f..71419eb16e09 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -21,6 +21,7 @@ #include <linux/earlycpio.h> #include <linux/initrd.h> #include <linux/security.h> +#include <linux/kmemleak.h> #include "internal.h" #ifdef CONFIG_ACPI_CUSTOM_DSDT @@ -601,6 +602,8 @@ void __init acpi_table_upgrade(void) */ arch_reserve_mem_area(acpi_tables_addr, all_tables_size); + kmemleak_ignore_phys(acpi_tables_addr); + /* * early_ioremap only can remap 256k one time. If we map all * tables one time, we will hit the limit. Need to map chunks diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index bd92b549fd5a..1c48358b43ba 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -371,7 +371,7 @@ static int lps0_device_attach(struct acpi_device *adev, return 0; if (acpi_s2idle_vendor_amd()) { - /* AMD0004, AMDI0005: + /* AMD0004, AMD0005, AMDI0005: * - Should use rev_id 0x0 * - function mask > 0x3: Should use AMD method, but has off by one bug * - function mask = 0x3: Should use Microsoft method @@ -390,6 +390,7 @@ static int lps0_device_attach(struct acpi_device *adev, ACPI_LPS0_DSM_UUID_MICROSOFT, 0, &lps0_dsm_guid_microsoft); if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") || + !strcmp(hid, "AMD0005") || !strcmp(hid, "AMDI0005"))) { lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1; acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n", |