diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 14 | ||||
-rw-r--r-- | drivers/acpi/acpica/aclocal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwsleep.c | 15 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsaccess.c | 7 | ||||
-rw-r--r-- | drivers/acpi/acpica/nssearch.c | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/psloop.c | 31 | ||||
-rw-r--r-- | drivers/acpi/acpica/uterror.c | 6 | ||||
-rw-r--r-- | drivers/acpi/arm64/iort.c | 48 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 78 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 40 | ||||
-rw-r--r-- | drivers/acpi/button.c | 17 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 34 | ||||
-rw-r--r-- | drivers/acpi/nfit/core.c | 48 | ||||
-rw-r--r-- | drivers/acpi/nfit/nfit.h | 1 | ||||
-rw-r--r-- | drivers/acpi/osi.c | 8 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 72 | ||||
-rw-r--r-- | drivers/acpi/pptt.c | 10 | ||||
-rw-r--r-- | drivers/acpi/property.c | 209 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 23 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 30 | ||||
-rw-r--r-- | drivers/acpi/x86/utils.c | 22 |
22 files changed, 467 insertions, 256 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b533eeb6139d..4a46344bf0e3 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -5,11 +5,10 @@ menuconfig ACPI bool "ACPI (Advanced Configuration and Power Interface) Support" - depends on !IA64_HP_SIM - depends on IA64 || X86 || ARM64 + depends on ARCH_SUPPORTS_ACPI depends on PCI select PNP - default y if (IA64 || X86) + default y if X86 help Advanced Configuration and Power Interface (ACPI) support for Linux requires an ACPI-compliant platform (hardware/firmware), @@ -41,6 +40,9 @@ menuconfig ACPI <http://www.acpi.info> <http://www.uefi.org/acpi/specs> +config ARCH_SUPPORTS_ACPI + bool + if ACPI config ACPI_LEGACY_TABLES_LOOKUP diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 38a286975c31..9706613eecf9 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -22,6 +22,7 @@ #include <linux/pm_domain.h> #include <linux/pm_runtime.h> #include <linux/pwm.h> +#include <linux/suspend.h> #include <linux/delay.h> #include "internal.h" @@ -878,6 +879,7 @@ static void acpi_lpss_dismiss(struct device *dev) #define LPSS_GPIODEF0_DMA_LLP BIT(13) static DEFINE_MUTEX(lpss_iosf_mutex); +static bool lpss_iosf_d3_entered; static void lpss_iosf_enter_d3_state(void) { @@ -920,6 +922,9 @@ static void lpss_iosf_enter_d3_state(void) iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE, LPSS_IOSF_GPIODEF0, value1, mask1); + + lpss_iosf_d3_entered = true; + exit: mutex_unlock(&lpss_iosf_mutex); } @@ -934,6 +939,11 @@ static void lpss_iosf_exit_d3_state(void) mutex_lock(&lpss_iosf_mutex); + if (!lpss_iosf_d3_entered) + goto exit; + + lpss_iosf_d3_entered = false; + iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE, LPSS_IOSF_GPIODEF0, value1, mask1); @@ -943,6 +953,7 @@ static void lpss_iosf_exit_d3_state(void) iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE, LPSS_IOSF_PMCSR, value2, mask2); +exit: mutex_unlock(&lpss_iosf_mutex); } @@ -961,7 +972,8 @@ static int acpi_lpss_suspend(struct device *dev, bool wakeup) * wrong status for devices being about to be powered off. See * lpss_iosf_enter_d3_state() for further information. */ - if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) + if (acpi_target_system_state() == ACPI_STATE_S0 && + lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) lpss_iosf_enter_d3_state(); return ret; diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 51c386bf230d..c5367bf5487f 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -165,7 +165,6 @@ struct acpi_namespace_node { #define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */ #define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (install_method) */ -#define IMPLICIT_EXTERNAL 0x02 /* iASL only: This object created implicitly via External */ #define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */ #define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */ #define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* iASL only: Method has at least one return value */ diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index fc0c2e2328cd..fe9d46d81750 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -51,16 +51,23 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) return_ACPI_STATUS(status); } - /* - * 1) Disable all GPEs - * 2) Enable all wakeup GPEs - */ + /* Disable all GPEs */ status = acpi_hw_disable_all_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + /* + * If the target sleep state is S5, clear all GPEs and fixed events too + */ + if (sleep_state == ACPI_STATE_S5) { + status = acpi_hw_clear_acpi_status(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } acpi_gbl_system_awake_and_running = FALSE; + /* Enable all wakeup GPEs */ status = acpi_hw_enable_all_wakeup_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 220a718fbce9..83a593e2155d 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -613,13 +613,6 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* Special handling for the last segment (num_segments == 0) */ else { -#ifdef ACPI_ASL_COMPILER - if (!acpi_gbl_disasm_flag - && (this_node->flags & ANOBJ_IS_EXTERNAL)) { - this_node->flags &= ~IMPLICIT_EXTERNAL; - } -#endif - /* * Sanity typecheck of the target object: * diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index e9c9a63bb6a4..f594ab75a5fe 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -381,7 +381,6 @@ acpi_ns_search_and_enter(u32 target_name, if (flags & ACPI_NS_EXTERNAL || (walk_state && walk_state->opcode == AML_SCOPE_OP)) { new_node->flags |= ANOBJ_IS_EXTERNAL; - new_node->flags |= IMPLICIT_EXTERNAL; } #endif diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index bc5f05906bd1..44f35ab3347d 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -497,6 +497,18 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) status = acpi_ps_create_op(walk_state, aml_op_start, &op); if (ACPI_FAILURE(status)) { + /* + * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by + * executing it as a control method. However, if we encounter + * an error while loading the table, we need to keep trying to + * load the table rather than aborting the table load. Set the + * status to AE_OK to proceed with the table load. + */ + if ((walk_state-> + parse_flags & ACPI_PARSE_MODULE_LEVEL) + && status == AE_ALREADY_EXISTS) { + status = AE_OK; + } if (status == AE_CTRL_PARSE_CONTINUE) { continue; } @@ -694,6 +706,25 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_OK; + } else + if ((walk_state-> + parse_flags & ACPI_PARSE_MODULE_LEVEL) + && status != AE_CTRL_TRANSFER + && ACPI_FAILURE(status)) { + /* + * ACPI_PARSE_MODULE_LEVEL flag means that we are currently + * loading a table by executing it as a control method. + * However, if we encounter an error while loading the table, + * we need to keep trying to load the table rather than + * aborting the table load (setting the status to AE_OK + * continues the table load). If we get a failure at this + * point, it means that the dispatcher got an error while + * processing Op (most likely an AML operand error) or a + * control method was called from module level and the + * dispatcher returned AE_CTRL_TRANSFER. In the latter case, + * leave the status alone, there's nothing wrong with it. + */ + status = AE_OK; } } diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c index 5a64ddaed8a3..e47430272692 100644 --- a/drivers/acpi/acpica/uterror.c +++ b/drivers/acpi/acpica/uterror.c @@ -182,19 +182,19 @@ acpi_ut_prefixed_namespace_error(const char *module_name, switch (lookup_status) { case AE_ALREADY_EXISTS: - acpi_os_printf("\n" ACPI_MSG_BIOS_ERROR); + acpi_os_printf(ACPI_MSG_BIOS_ERROR); message = "Failure creating"; break; case AE_NOT_FOUND: - acpi_os_printf("\n" ACPI_MSG_BIOS_ERROR); + acpi_os_printf(ACPI_MSG_BIOS_ERROR); message = "Could not resolve"; break; default: - acpi_os_printf("\n" ACPI_MSG_ERROR); + acpi_os_printf(ACPI_MSG_ERROR); message = "Failure resolving"; break; } diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index 7a3a541046ed..08f26db2da7e 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -947,6 +947,24 @@ static int nc_dma_get_range(struct device *dev, u64 *size) return 0; } +static int rc_dma_get_range(struct device *dev, u64 *size) +{ + struct acpi_iort_node *node; + struct acpi_iort_root_complex *rc; + + node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX, + iort_match_node_callback, dev); + if (!node || node->revision < 1) + return -ENODEV; + + rc = (struct acpi_iort_root_complex *)node->node_data; + + *size = rc->memory_address_limit >= 64 ? U64_MAX : + 1ULL<<rc->memory_address_limit; + + return 0; +} + /** * iort_dma_setup() - Set-up device DMA parameters. * @@ -960,25 +978,28 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size) int ret, msb; /* - * Set default coherent_dma_mask to 32 bit. Drivers are expected to - * setup the correct supported mask. + * If @dev is expected to be DMA-capable then the bus code that created + * it should have initialised its dma_mask pointer by this point. For + * now, we'll continue the legacy behaviour of coercing it to the + * coherent mask if not, but we'll no longer do so quietly. */ - if (!dev->coherent_dma_mask) - dev->coherent_dma_mask = DMA_BIT_MASK(32); - - /* - * Set it to coherent_dma_mask by default if the architecture - * code has not set it. - */ - if (!dev->dma_mask) + if (!dev->dma_mask) { + dev_warn(dev, "DMA mask not set\n"); dev->dma_mask = &dev->coherent_dma_mask; + } - size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1); + if (dev->coherent_dma_mask) + size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1); + else + size = 1ULL << 32; - if (dev_is_pci(dev)) + if (dev_is_pci(dev)) { ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size); - else + if (ret == -ENODEV) + ret = rc_dma_get_range(dev, &size); + } else { ret = nc_dma_get_range(dev, &size); + } if (!ret) { msb = fls64(dmaaddr + size - 1); @@ -993,6 +1014,7 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size) * Limit coherent and dma mask based on size * retrieved from firmware. */ + dev->bus_dma_mask = mask; dev->coherent_dma_mask = mask; *dev->dma_mask = mask; } diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b0113a5802a3..cb97b6105f52 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -23,18 +23,18 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/async.h> +#include <linux/delay.h> +#include <linux/dmi.h> +#include <linux/jiffies.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/jiffies.h> -#include <linux/async.h> -#include <linux/dmi.h> -#include <linux/delay.h> #include <linux/slab.h> #include <linux/suspend.h> +#include <linux/types.h> + #include <asm/unaligned.h> #ifdef CONFIG_ACPI_PROCFS_POWER @@ -364,6 +364,20 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_SERIAL_NUMBER, }; +static enum power_supply_property energy_battery_full_cap_broken_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CYCLE_COUNT, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_POWER_NOW, + POWER_SUPPLY_PROP_ENERGY_NOW, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_SERIAL_NUMBER, +}; + /* -------------------------------------------------------------------------- Battery Management -------------------------------------------------------------------------- */ @@ -577,8 +591,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery) battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN && (s16)(battery->rate_now) < 0) { battery->rate_now = abs((s16)battery->rate_now); - printk_once(KERN_WARNING FW_BUG - "battery: (dis)charge rate invalid.\n"); + pr_warn_once(FW_BUG "battery: (dis)charge rate invalid.\n"); } if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) @@ -717,10 +730,11 @@ void battery_hook_register(struct acpi_battery_hook *hook) */ pr_err("extension failed to load: %s", hook->name); __battery_hook_unregister(hook, 0); - return; + goto end; } } pr_info("new extension: %s\n", hook->name); +end: mutex_unlock(&hook_mutex); } EXPORT_SYMBOL_GPL(battery_hook_register); @@ -732,7 +746,7 @@ EXPORT_SYMBOL_GPL(battery_hook_register); */ static void battery_hook_add_battery(struct acpi_battery *battery) { - struct acpi_battery_hook *hook_node; + struct acpi_battery_hook *hook_node, *tmp; mutex_lock(&hook_mutex); INIT_LIST_HEAD(&battery->list); @@ -744,15 +758,15 @@ static void battery_hook_add_battery(struct acpi_battery *battery) * when a battery gets hotplugged or initialized * during the battery module initialization. */ - list_for_each_entry(hook_node, &battery_hook_list, list) { + list_for_each_entry_safe(hook_node, tmp, &battery_hook_list, list) { if (hook_node->add_battery(battery->bat)) { /* * The notification of the extensions has failed, to * prevent further errors we will unload the extension. */ - __battery_hook_unregister(hook_node, 0); pr_err("error in extension, unloading: %s", hook_node->name); + __battery_hook_unregister(hook_node, 0); } } mutex_unlock(&hook_mutex); @@ -798,6 +812,11 @@ static int sysfs_add_battery(struct acpi_battery *battery) battery->bat_desc.properties = charge_battery_props; battery->bat_desc.num_properties = ARRAY_SIZE(charge_battery_props); + } else if (battery->full_charge_capacity == 0) { + battery->bat_desc.properties = + energy_battery_full_cap_broken_props; + battery->bat_desc.num_properties = + ARRAY_SIZE(energy_battery_full_cap_broken_props); } else { battery->bat_desc.properties = energy_battery_props; battery->bat_desc.num_properties = @@ -917,10 +936,11 @@ static void acpi_battery_quirks(struct acpi_battery *battery) static int acpi_battery_update(struct acpi_battery *battery, bool resume) { - int result, old_present = acpi_battery_present(battery); - result = acpi_battery_get_status(battery); + int result = acpi_battery_get_status(battery); + if (result) return result; + if (!acpi_battery_present(battery)) { sysfs_remove_battery(battery); battery->update_time = 0; @@ -930,8 +950,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume) if (resume) return 0; - if (!battery->update_time || - old_present != acpi_battery_present(battery)) { + if (!battery->update_time) { result = acpi_battery_get_info(battery); if (result) return result; @@ -1020,7 +1039,7 @@ static int acpi_battery_info_proc_show(struct seq_file *seq, void *offset) acpi_battery_units(battery)); seq_printf(seq, "battery technology: %srechargeable\n", - (!battery->technology)?"non-":""); + battery->technology ? "" : "non-"); if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "design voltage: unknown\n"); @@ -1111,11 +1130,12 @@ static int acpi_battery_alarm_proc_show(struct seq_file *seq, void *offset) goto end; } seq_printf(seq, "alarm: "); - if (!battery->alarm) - seq_printf(seq, "unsupported\n"); - else + if (battery->alarm) { seq_printf(seq, "%u %sh\n", battery->alarm, acpi_battery_units(battery)); + } else { + seq_printf(seq, "unsupported\n"); + } end: if (result) seq_printf(seq, "ERROR: Unable to read battery alarm\n"); @@ -1148,9 +1168,9 @@ static ssize_t acpi_battery_write_alarm(struct file *file, } result = acpi_battery_set_alarm(battery); end: - if (!result) - return count; - return result; + if (result) + return result; + return count; } static int acpi_battery_alarm_proc_open(struct inode *inode, struct file *file) @@ -1169,8 +1189,7 @@ static const struct file_operations acpi_battery_alarm_fops = { static int acpi_battery_add_fs(struct acpi_device *device) { - printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded," - " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); + pr_warning(PREFIX "Deprecated procfs I/F for battery is loaded, please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_battery_dir); @@ -1246,7 +1265,9 @@ static int battery_notify(struct notifier_block *nb, if (!acpi_battery_present(battery)) return 0; - if (!battery->bat) { + if (battery->bat) { + acpi_battery_refresh(battery); + } else { result = acpi_battery_get_info(battery); if (result) return result; @@ -1254,8 +1275,7 @@ static int battery_notify(struct notifier_block *nb, result = sysfs_add_battery(battery); if (result) return result; - } else - acpi_battery_refresh(battery); + } acpi_battery_init_alarm(battery); acpi_battery_get_state(battery); @@ -1397,7 +1417,7 @@ static int acpi_battery_add(struct acpi_device *device) } #endif - printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", + pr_info(PREFIX "%s Slot [%s] (battery %s)\n", ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), device->status.battery_present ? "present" : "absent"); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 84b4a62018eb..292088fcc624 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -66,37 +66,10 @@ static int set_copy_dsdt(const struct dmi_system_id *id) return 0; } #endif -static int set_gbl_term_list(const struct dmi_system_id *id) -{ - acpi_gbl_execute_tables_as_methods = 1; - return 0; -} -static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = { - /* - * Touchpad on Dell XPS 9570/Precision M5530 doesn't work under I2C - * mode. - * https://bugzilla.kernel.org/show_bug.cgi?id=198515 - */ - { - .callback = set_gbl_term_list, - .ident = "Dell Precision M5530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Precision M5530"), - }, - }, - { - .callback = set_gbl_term_list, - .ident = "Dell XPS 15 9570", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9570"), - }, - }, +static const struct dmi_system_id dsdt_dmi_table[] __initconst = { /* * Invoke DSDT corruption work-around on all Toshiba Satellite. - * DSDT will be copied to memory. * https://bugzilla.kernel.org/show_bug.cgi?id=14679 */ { @@ -110,7 +83,7 @@ static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = { {} }; #else -static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = { +static const struct dmi_system_id dsdt_dmi_table[] __initconst = { {} }; #endif @@ -962,7 +935,7 @@ static int acpi_device_probe(struct device *dev) return 0; } -static int acpi_device_remove(struct device * dev) +static int acpi_device_remove(struct device *dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = acpi_dev->driver; @@ -1060,8 +1033,11 @@ void __init acpi_early_init(void) acpi_permanent_mmap = true; - /* Check machine-specific quirks */ - dmi_check_system(acpi_quirks_dmi_table); + /* + * If the machine falls into the DMI check table, + * DSDT will be copied to memory + */ + dmi_check_system(dsdt_dmi_table); status = acpi_reallocate_root_table(); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 2345a5ee2dbb..a19ff3977ac4 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -21,6 +21,7 @@ #define pr_fmt(fmt) "ACPI: button: " fmt +#include <linux/compiler.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -235,9 +236,6 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state) button->last_time = ktime_get(); } - if (state) - acpi_pm_wakeup_event(&device->dev); - ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); if (ret == NOTIFY_DONE) ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, @@ -252,7 +250,8 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state) return ret; } -static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) +static int __maybe_unused acpi_button_state_seq_show(struct seq_file *seq, + void *offset) { struct acpi_device *device = seq->private; int state; @@ -366,7 +365,8 @@ int acpi_lid_open(void) } EXPORT_SYMBOL(acpi_lid_open); -static int acpi_lid_update_state(struct acpi_device *device) +static int acpi_lid_update_state(struct acpi_device *device, + bool signal_wakeup) { int state; @@ -374,6 +374,9 @@ static int acpi_lid_update_state(struct acpi_device *device) if (state < 0) return state; + if (state && signal_wakeup) + acpi_pm_wakeup_event(&device->dev); + return acpi_lid_notify_state(device, state); } @@ -384,7 +387,7 @@ static void acpi_lid_initialize_state(struct acpi_device *device) (void)acpi_lid_notify_state(device, 1); break; case ACPI_BUTTON_LID_INIT_METHOD: - (void)acpi_lid_update_state(device); + (void)acpi_lid_update_state(device, false); break; case ACPI_BUTTON_LID_INIT_IGNORE: default: @@ -409,7 +412,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) users = button->input->users; mutex_unlock(&button->input->mutex); if (users) - acpi_lid_update_state(device); + acpi_lid_update_state(device, true); } else { int keycode; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index bb94cf0731fe..d4e5610e09c5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -2037,6 +2037,31 @@ static inline void acpi_ec_query_exit(void) } } +static const struct dmi_system_id acpi_ec_no_wakeup[] = { + { + .ident = "Thinkpad X1 Carbon 6th", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_FAMILY, "Thinkpad X1 Carbon 6th"), + }, + }, + { + .ident = "ThinkPad X1 Carbon 6th", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Carbon 6th"), + }, + }, + { + .ident = "ThinkPad X1 Yoga 3rd", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Yoga 3rd"), + }, + }, + { }, +}; + int __init acpi_ec_init(void) { int result; @@ -2047,6 +2072,15 @@ int __init acpi_ec_init(void) if (result) return result; + /* + * Disable EC wakeup on following systems to prevent periodic + * wakeup from EC GPE. + */ + if (dmi_check_system(acpi_ec_no_wakeup)) { + ec_no_wakeup = true; + pr_debug("Disabling EC wakeup on suspend-to-idle\n"); + } + /* Drivers must be started after acpi_ec_query_init() */ dsdt_fail = acpi_bus_register_driver(&acpi_ec_driver); /* diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index d15814e1727f..7c479002e798 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -408,6 +408,8 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, const guid_t *guid; int rc, i; + if (cmd_rc) + *cmd_rc = -EINVAL; func = cmd; if (cmd == ND_CMD_CALL) { call_pkg = buf; @@ -518,6 +520,8 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, * If we return an error (like elsewhere) then caller wouldn't * be able to rely upon data returned to make calculation. */ + if (cmd_rc) + *cmd_rc = 0; return 0; } @@ -1273,7 +1277,7 @@ static ssize_t scrub_show(struct device *dev, mutex_lock(&acpi_desc->init_mutex); rc = sprintf(buf, "%d%s", acpi_desc->scrub_count, - work_busy(&acpi_desc->dwork.work) + acpi_desc->scrub_busy && !acpi_desc->cancel ? "+\n" : "\n"); mutex_unlock(&acpi_desc->init_mutex); } @@ -2939,6 +2943,32 @@ static unsigned int __acpi_nfit_scrub(struct acpi_nfit_desc *acpi_desc, return 0; } +static void __sched_ars(struct acpi_nfit_desc *acpi_desc, unsigned int tmo) +{ + lockdep_assert_held(&acpi_desc->init_mutex); + + acpi_desc->scrub_busy = 1; + /* note this should only be set from within the workqueue */ + if (tmo) + acpi_desc->scrub_tmo = tmo; + queue_delayed_work(nfit_wq, &acpi_desc->dwork, tmo * HZ); +} + +static void sched_ars(struct acpi_nfit_desc *acpi_desc) +{ + __sched_ars(acpi_desc, 0); +} + +static void notify_ars_done(struct acpi_nfit_desc *acpi_desc) +{ + lockdep_assert_held(&acpi_desc->init_mutex); + + acpi_desc->scrub_busy = 0; + acpi_desc->scrub_count++; + if (acpi_desc->scrub_count_state) + sysfs_notify_dirent(acpi_desc->scrub_count_state); +} + static void acpi_nfit_scrub(struct work_struct *work) { struct acpi_nfit_desc *acpi_desc; @@ -2949,14 +2979,10 @@ static void acpi_nfit_scrub(struct work_struct *work) mutex_lock(&acpi_desc->init_mutex); query_rc = acpi_nfit_query_poison(acpi_desc); tmo = __acpi_nfit_scrub(acpi_desc, query_rc); - if (tmo) { - queue_delayed_work(nfit_wq, &acpi_desc->dwork, tmo * HZ); - acpi_desc->scrub_tmo = tmo; - } else { - acpi_desc->scrub_count++; - if (acpi_desc->scrub_count_state) - sysfs_notify_dirent(acpi_desc->scrub_count_state); - } + if (tmo) + __sched_ars(acpi_desc, tmo); + else + notify_ars_done(acpi_desc); memset(acpi_desc->ars_status, 0, acpi_desc->max_ars); mutex_unlock(&acpi_desc->init_mutex); } @@ -3037,7 +3063,7 @@ static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc) break; } - queue_delayed_work(nfit_wq, &acpi_desc->dwork, 0); + sched_ars(acpi_desc); return 0; } @@ -3239,7 +3265,7 @@ int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, unsigned long flags) } } if (scheduled) { - queue_delayed_work(nfit_wq, &acpi_desc->dwork, 0); + sched_ars(acpi_desc); dev_dbg(dev, "ars_scan triggered\n"); } mutex_unlock(&acpi_desc->init_mutex); diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index 7d15856a739f..a97ff42fe311 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -203,6 +203,7 @@ struct acpi_nfit_desc { unsigned int max_ars; unsigned int scrub_count; unsigned int scrub_mode; + unsigned int scrub_busy:1; unsigned int cancel:1; unsigned long dimm_cmd_force_en; unsigned long bus_cmd_force_en; diff --git a/drivers/acpi/osi.c b/drivers/acpi/osi.c index 8a8f43568510..b2a16ed7e81a 100644 --- a/drivers/acpi/osi.c +++ b/drivers/acpi/osi.c @@ -66,6 +66,14 @@ osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = { * be removed if both new and old graphics cards are supported. */ {"Linux-Dell-Video", true}, + /* + * Linux-Lenovo-NV-HDMI-Audio is used by BIOS to power on NVidia's HDMI + * audio device which is turned off for power-saving in Windows OS. + * This power management feature observed on some Lenovo Thinkpad + * systems which will not be able to output audio via HDMI without + * a BIOS workaround. + */ + {"Linux-Lenovo-NV-HDMI-Audio", true}, }; static u32 acpi_osi_handler(acpi_string interface, u32 supported) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 7ca41bf023c9..8df9abfa947b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -45,6 +45,8 @@ #include <linux/uaccess.h> #include <linux/io-64-nonatomic-lo-hi.h> +#include "acpica/accommon.h" +#include "acpica/acnamesp.h" #include "internal.h" #define _COMPONENT ACPI_OS_SERVICES @@ -1490,6 +1492,76 @@ int acpi_check_region(resource_size_t start, resource_size_t n, } EXPORT_SYMBOL(acpi_check_region); +static acpi_status acpi_deactivate_mem_region(acpi_handle handle, u32 level, + void *_res, void **return_value) +{ + struct acpi_mem_space_context **mem_ctx; + union acpi_operand_object *handler_obj; + union acpi_operand_object *region_obj2; + union acpi_operand_object *region_obj; + struct resource *res = _res; + acpi_status status; + + region_obj = acpi_ns_get_attached_object(handle); + if (!region_obj) + return AE_OK; + + handler_obj = region_obj->region.handler; + if (!handler_obj) + return AE_OK; + + if (region_obj->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) + return AE_OK; + + if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) + return AE_OK; + + region_obj2 = acpi_ns_get_secondary_object(region_obj); + if (!region_obj2) + return AE_OK; + + mem_ctx = (void *)®ion_obj2->extra.region_context; + + if (!(mem_ctx[0]->address >= res->start && + mem_ctx[0]->address < res->end)) + return AE_OK; + + status = handler_obj->address_space.setup(region_obj, + ACPI_REGION_DEACTIVATE, + NULL, (void **)mem_ctx); + if (ACPI_SUCCESS(status)) + region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE); + + return status; +} + +/** + * acpi_release_memory - Release any mappings done to a memory region + * @handle: Handle to namespace node + * @res: Memory resource + * @level: A level that terminates the search + * + * Walks through @handle and unmaps all SystemMemory Operation Regions that + * overlap with @res and that have already been activated (mapped). + * + * This is a helper that allows drivers to place special requirements on memory + * region that may overlap with operation regions, primarily allowing them to + * safely map the region as non-cached memory. + * + * The unmapped Operation Regions will be automatically remapped next time they + * are called, so the drivers do not need to do anything else. + */ +acpi_status acpi_release_memory(acpi_handle handle, struct resource *res, + u32 level) +{ + if (!(res->flags & IORESOURCE_MEM)) + return AE_TYPE; + + return acpi_walk_namespace(ACPI_TYPE_REGION, handle, level, + acpi_deactivate_mem_region, NULL, res, NULL); +} +EXPORT_SYMBOL_GPL(acpi_release_memory); + /* * Let drivers know whether the resource checks are effective */ diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index e5ea1974d1e3..d1e26cb599bf 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -481,8 +481,14 @@ static int topology_get_acpi_cpu_tag(struct acpi_table_header *table, if (cpu_node) { cpu_node = acpi_find_processor_package_id(table, cpu_node, level, flag); - /* Only the first level has a guaranteed id */ - if (level == 0) + /* + * As per specification if the processor structure represents + * an actual processor, then ACPI processor ID must be valid. + * For processor containers ACPI_PPTT_ACPI_PROCESSOR_ID_VALID + * should be set if the UID is valid + */ + if (level == 0 || + cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID) return cpu_node->acpi_processor_id; return ACPI_PTR_DIFF(cpu_node, table); } diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 5815356ea6ad..693cf05b0cc4 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -542,6 +542,23 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data, return 0; } +static struct fwnode_handle * +acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode, + const char *childname) +{ + struct fwnode_handle *child; + + /* + * Find first matching named child node of this fwnode. + * For ACPI this will be a data only sub-node. + */ + fwnode_for_each_child_node(fwnode, child) + if (acpi_data_node_match(child, childname)) + return child; + + return NULL; +} + /** * __acpi_node_get_property_reference - returns handle to the referenced object * @fwnode: Firmware node to get the property from @@ -579,7 +596,7 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data, */ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, const char *propname, size_t index, size_t num_args, - struct acpi_reference_args *args) + struct fwnode_reference_args *args) { const union acpi_object *element, *end; const union acpi_object *obj; @@ -607,7 +624,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, if (ret) return ret == -ENODEV ? -EINVAL : ret; - args->adev = device; + args->fwnode = acpi_fwnode_handle(device); args->nargs = 0; return 0; } @@ -633,6 +650,8 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, u32 nargs, i; if (element->type == ACPI_TYPE_LOCAL_REFERENCE) { + struct fwnode_handle *ref_fwnode; + ret = acpi_bus_get_device(element->reference.handle, &device); if (ret) @@ -641,6 +660,19 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, nargs = 0; element++; + /* + * Find the referred data extension node under the + * referred device node. + */ + for (ref_fwnode = acpi_fwnode_handle(device); + element < end && element->type == ACPI_TYPE_STRING; + element++) { + ref_fwnode = acpi_fwnode_get_named_child_node( + ref_fwnode, element->string.pointer); + if (!ref_fwnode) + return -EINVAL; + } + /* assume following integer elements are all args */ for (i = 0; element + i < end && i < num_args; i++) { int type = element[i].type; @@ -653,11 +685,11 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, return -EINVAL; } - if (nargs > MAX_ACPI_REFERENCE_ARGS) + if (nargs > NR_FWNODE_REFERENCE_ARGS) return -EINVAL; if (idx == index) { - args->adev = device; + args->fwnode = ref_fwnode; args->nargs = nargs; for (i = 0; i < nargs; i++) args->args[i] = element[i].integer.value; @@ -995,16 +1027,36 @@ struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode) return NULL; } +/* + * Return true if the node is an ACPI graph node. Called on either ports + * or endpoints. + */ +static bool is_acpi_graph_node(struct fwnode_handle *fwnode, + const char *str) +{ + unsigned int len = strlen(str); + const char *name; + + if (!len || !is_acpi_data_node(fwnode)) + return false; + + name = to_acpi_data_node(fwnode)->name; + + return (fwnode_property_present(fwnode, "reg") && + !strncmp(name, str, len) && name[len] == '@') || + fwnode_property_present(fwnode, str); +} + /** * acpi_graph_get_next_endpoint - Get next endpoint ACPI firmware node * @fwnode: Pointer to the parent firmware node * @prev: Previous endpoint node or %NULL to get the first * * Looks up next endpoint ACPI firmware node below a given @fwnode. Returns - * %NULL if there is no next endpoint, ERR_PTR() in case of error. In case - * of success the next endpoint is returned. + * %NULL if there is no next endpoint or in case of error. In case of success + * the next endpoint is returned. */ -struct fwnode_handle *acpi_graph_get_next_endpoint( +static struct fwnode_handle *acpi_graph_get_next_endpoint( const struct fwnode_handle *fwnode, struct fwnode_handle *prev) { struct fwnode_handle *port = NULL; @@ -1013,8 +1065,14 @@ struct fwnode_handle *acpi_graph_get_next_endpoint( if (!prev) { do { port = fwnode_get_next_child_node(fwnode, port); - /* Ports must have port property */ - if (fwnode_property_present(port, "port")) + /* + * The names of the port nodes begin with "port@" + * followed by the number of the port node and they also + * have a "reg" property that also has the number of the + * port node. For compatibility reasons a node is also + * recognised as a port node from the "port" property. + */ + if (is_acpi_graph_node(port, "port")) break; } while (port); } else { @@ -1029,15 +1087,19 @@ struct fwnode_handle *acpi_graph_get_next_endpoint( port = fwnode_get_next_child_node(fwnode, port); if (!port) break; - if (fwnode_property_present(port, "port")) + if (is_acpi_graph_node(port, "port")) endpoint = fwnode_get_next_child_node(port, NULL); } - if (endpoint) { - /* Endpoints must have "endpoint" property */ - if (!fwnode_property_present(endpoint, "endpoint")) - return ERR_PTR(-EPROTO); - } + /* + * The names of the endpoint nodes begin with "endpoint@" followed by + * the number of the endpoint node and they also have a "reg" property + * that also has the number of the endpoint node. For compatibility + * reasons a node is also recognised as an endpoint node from the + * "endpoint" property. + */ + if (!is_acpi_graph_node(endpoint, "endpoint")) + return NULL; return endpoint; } @@ -1074,65 +1136,42 @@ static struct fwnode_handle *acpi_graph_get_child_prop_value( /** * acpi_graph_get_remote_enpoint - Parses and returns remote end of an endpoint * @fwnode: Endpoint firmware node pointing to a remote device - * @parent: Firmware node of remote port parent is filled here if not %NULL - * @port: Firmware node of remote port is filled here if not %NULL * @endpoint: Firmware node of remote endpoint is filled here if not %NULL * - * Function parses remote end of ACPI firmware remote endpoint and fills in - * fields requested by the caller. Returns %0 in case of success and - * negative errno otherwise. + * Returns the remote endpoint corresponding to @__fwnode. NULL on error. */ -int acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode, - struct fwnode_handle **parent, - struct fwnode_handle **port, - struct fwnode_handle **endpoint) +static struct fwnode_handle * +acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode) { struct fwnode_handle *fwnode; unsigned int port_nr, endpoint_nr; - struct acpi_reference_args args; + struct fwnode_reference_args args; int ret; memset(&args, 0, sizeof(args)); ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0, &args); if (ret) - return ret; + return NULL; + + /* Direct endpoint reference? */ + if (!is_acpi_device_node(args.fwnode)) + return args.nargs ? NULL : args.fwnode; /* * Always require two arguments with the reference: port and * endpoint indices. */ if (args.nargs != 2) - return -EPROTO; + return NULL; - fwnode = acpi_fwnode_handle(args.adev); + fwnode = args.fwnode; port_nr = args.args[0]; endpoint_nr = args.args[1]; - if (parent) - *parent = fwnode; - - if (!port && !endpoint) - return 0; - fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr); - if (!fwnode) - return -EPROTO; - - if (port) - *port = fwnode; - - if (!endpoint) - return 0; - fwnode = acpi_graph_get_child_prop_value(fwnode, "endpoint", - endpoint_nr); - if (!fwnode) - return -EPROTO; - - *endpoint = fwnode; - - return 0; + return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr); } static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode) @@ -1186,70 +1225,14 @@ acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode, val, nval); } -static struct fwnode_handle * -acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode, - const char *childname) -{ - struct fwnode_handle *child; - - /* - * Find first matching named child node of this fwnode. - * For ACPI this will be a data only sub-node. - */ - fwnode_for_each_child_node(fwnode, child) - if (acpi_data_node_match(child, childname)) - return child; - - return NULL; -} - static int acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode, const char *prop, const char *nargs_prop, unsigned int args_count, unsigned int index, struct fwnode_reference_args *args) { - struct acpi_reference_args acpi_args; - unsigned int i; - int ret; - - ret = __acpi_node_get_property_reference(fwnode, prop, index, - args_count, &acpi_args); - if (ret < 0) - return ret; - if (!args) - return 0; - - args->nargs = acpi_args.nargs; - args->fwnode = acpi_fwnode_handle(acpi_args.adev); - - for (i = 0; i < NR_FWNODE_REFERENCE_ARGS; i++) - args->args[i] = i < acpi_args.nargs ? acpi_args.args[i] : 0; - - return 0; -} - -static struct fwnode_handle * -acpi_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, - struct fwnode_handle *prev) -{ - struct fwnode_handle *endpoint; - - endpoint = acpi_graph_get_next_endpoint(fwnode, prev); - if (IS_ERR(endpoint)) - return NULL; - - return endpoint; -} - -static struct fwnode_handle * -acpi_fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode) -{ - struct fwnode_handle *endpoint = NULL; - - acpi_graph_get_remote_endpoint(fwnode, NULL, NULL, &endpoint); - - return endpoint; + return __acpi_node_get_property_reference(fwnode, prop, index, + args_count, args); } static struct fwnode_handle * @@ -1265,8 +1248,10 @@ static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, endpoint->local_fwnode = fwnode; - fwnode_property_read_u32(port_fwnode, "port", &endpoint->port); - fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id); + if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port)) + fwnode_property_read_u32(port_fwnode, "port", &endpoint->port); + if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id)) + fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id); return 0; } @@ -1292,9 +1277,9 @@ acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode, .get_named_child_node = acpi_fwnode_get_named_child_node, \ .get_reference_args = acpi_fwnode_get_reference_args, \ .graph_get_next_endpoint = \ - acpi_fwnode_graph_get_next_endpoint, \ + acpi_graph_get_next_endpoint, \ .graph_get_remote_endpoint = \ - acpi_fwnode_graph_get_remote_endpoint, \ + acpi_graph_get_remote_endpoint, \ .graph_get_port_parent = acpi_fwnode_get_parent, \ .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \ }; \ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 970dd87d347c..e1b6231cfa1c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1528,7 +1528,7 @@ static int acpi_check_serial_bus_slave(struct acpi_resource *ares, void *data) static bool acpi_is_indirect_io_slave(struct acpi_device *device) { struct acpi_device *parent = device->parent; - const struct acpi_device_id indirect_io_hosts[] = { + static const struct acpi_device_id indirect_io_hosts[] = { {"HISI0191", 0}, {} }; @@ -1540,6 +1540,18 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) { struct list_head resource_list; bool is_serial_bus_slave = false; + /* + * These devices have multiple I2cSerialBus resources and an i2c-client + * must be instantiated for each, each with its own i2c_device_id. + * Normally we only instantiate an i2c-client for the first resource, + * using the ACPI HID as id. These special cases are handled by the + * drivers/platform/x86/i2c-multi-instantiate.c driver, which knows + * which i2c_device_id to use for each resource. + */ + static const struct acpi_device_id i2c_multi_instantiate_ids[] = { + {"BSG1160", }, + {} + }; if (acpi_is_indirect_io_slave(device)) return true; @@ -1551,6 +1563,10 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) fwnode_property_present(&device->fwnode, "baud"))) return true; + /* Instantiate a pdev for the i2c-multi-instantiate drv to bind to */ + if (!acpi_match_device_ids(device, i2c_multi_instantiate_ids)) + return false; + INIT_LIST_HEAD(&resource_list); acpi_dev_get_resources(device, &resource_list, acpi_check_serial_bus_slave, @@ -1612,7 +1628,8 @@ static int acpi_add_single_object(struct acpi_device **child, * Note this must be done before the get power-/wakeup_dev-flags calls. */ if (type == ACPI_BUS_TYPE_DEVICE) - acpi_bus_get_status(device); + if (acpi_bus_get_status(device) < 0) + acpi_set_device_status(device, 0); acpi_bus_get_power_flags(device); acpi_bus_get_wakeup_device_flags(device); @@ -1690,7 +1707,7 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, * acpi_add_single_object updates this once we've an acpi_device * so that acpi_bus_get_status' quirk handling can be used. */ - *sta = 0; + *sta = ACPI_STA_DEFAULT; break; case ACPI_TYPE_PROCESSOR: *type = ACPI_BUS_TYPE_PROCESSOR; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 5d0486f1cfcd..754d59f95500 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -338,6 +338,14 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"), }, }, + { + .callback = init_nvs_save_s3, + .ident = "Asus 1025C", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "1025C"), + }, + }, /* * https://bugzilla.kernel.org/show_bug.cgi?id=189431 * Lenovo G50-45 is a platform later than 2012, but needs nvs memory @@ -718,9 +726,6 @@ static const struct acpi_device_id lps0_device_ids[] = { #define ACPI_LPS0_ENTRY 5 #define ACPI_LPS0_EXIT 6 -#define ACPI_LPS0_SCREEN_MASK ((1 << ACPI_LPS0_SCREEN_OFF) | (1 << ACPI_LPS0_SCREEN_ON)) -#define ACPI_LPS0_PLATFORM_MASK ((1 << ACPI_LPS0_ENTRY) | (1 << ACPI_LPS0_EXIT)) - static acpi_handle lps0_device_handle; static guid_t lps0_dsm_guid; static char lps0_dsm_func_mask; @@ -924,17 +929,14 @@ static int lps0_device_attach(struct acpi_device *adev, if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) { char bitmask = *(char *)out_obj->buffer.pointer; - if ((bitmask & ACPI_LPS0_PLATFORM_MASK) == ACPI_LPS0_PLATFORM_MASK || - (bitmask & ACPI_LPS0_SCREEN_MASK) == ACPI_LPS0_SCREEN_MASK) { - lps0_dsm_func_mask = bitmask; - lps0_device_handle = adev->handle; - /* - * Use suspend-to-idle by default if the default - * suspend mode was not set from the command line. - */ - if (mem_sleep_default > PM_SUSPEND_MEM) - mem_sleep_current = PM_SUSPEND_TO_IDLE; - } + lps0_dsm_func_mask = bitmask; + lps0_device_handle = adev->handle; + /* + * Use suspend-to-idle by default if the default + * suspend mode was not set from the command line. + */ + if (mem_sleep_default > PM_SUSPEND_MEM) + mem_sleep_current = PM_SUSPEND_TO_IDLE; acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n", bitmask); diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index ec5b0f190231..06c31ec3cc70 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -62,14 +62,20 @@ static const struct always_present_id always_present_ids[] = { */ ENTRY("INT0002", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}), /* - * On the Dell Venue 11 Pro 7130 the DSDT hides the touchscreen ACPI - * device until a certain time after _SB.PCI0.GFX0.LCD.LCD1._ON gets - * called has passed *and* _STA has been called at least 3 times since. + * On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides + * the touchscreen ACPI device until a certain time + * after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed + * *and* _STA has been called at least 3 times since. */ ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"), }), + ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"), + }), + /* * The GPD win BIOS dated 20170221 has disabled the accelerometer, the * drivers sometimes cause crashes under Windows and this is how the @@ -103,13 +109,9 @@ static const struct always_present_id always_present_ids[] = { bool acpi_device_always_present(struct acpi_device *adev) { - u32 *status = (u32 *)&adev->status; - u32 old_status = *status; bool ret = false; unsigned int i; - /* acpi_match_device_ids checks status, so set it to default */ - *status = ACPI_STA_DEFAULT; for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) { if (acpi_match_device_ids(adev, always_present_ids[i].hid)) continue; @@ -125,15 +127,9 @@ bool acpi_device_always_present(struct acpi_device *adev) !dmi_check_system(always_present_ids[i].dmi_ids)) continue; - if (old_status != ACPI_STA_DEFAULT) /* Log only once */ - dev_info(&adev->dev, - "Device [%s] is in always present list\n", - adev->pnp.bus_id); - ret = true; break; } - *status = old_status; return ret; } |