diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 4 | ||||
-rw-r--r-- | drivers/acpi/acpi_apd.c | 7 | ||||
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 8 | ||||
-rw-r--r-- | drivers/acpi/acpi_video.c | 11 | ||||
-rw-r--r-- | drivers/acpi/apei/ghes.c | 7 | ||||
-rw-r--r-- | drivers/acpi/apei/hest.c | 13 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 72 | ||||
-rw-r--r-- | drivers/acpi/blacklist.c | 28 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 10 | ||||
-rw-r--r-- | drivers/acpi/cppc_acpi.c | 16 | ||||
-rw-r--r-- | drivers/acpi/device_sysfs.c | 8 | ||||
-rw-r--r-- | drivers/acpi/event.c | 6 | ||||
-rw-r--r-- | drivers/acpi/nfit/core.c | 55 | ||||
-rw-r--r-- | drivers/acpi/nfit/nfit.h | 2 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 19 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 2 | ||||
-rw-r--r-- | drivers/acpi/processor_perflib.c | 55 | ||||
-rw-r--r-- | drivers/acpi/property.c | 125 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 3 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 37 | ||||
-rw-r--r-- | drivers/acpi/video_detect.c | 20 |
21 files changed, 335 insertions, 173 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 535e7828445a..83e5f7e1a20d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -104,7 +104,7 @@ config ACPI_PROCFS_POWER Say N to delete power /proc/acpi/ directories that have moved to /sys/ config ACPI_REV_OVERRIDE_POSSIBLE - bool "Allow supported ACPI revision to be overriden" + bool "Allow supported ACPI revision to be overridden" depends on X86 default y help @@ -342,7 +342,7 @@ config ACPI_DEBUG Use the acpi.debug_layer and acpi.debug_level kernel command-line parameters documented in Documentation/acpi/debug.txt and - Documentation/kernel-parameters.txt to control the type and + Documentation/admin-guide/kernel-parameters.rst to control the type and amount of debug output. config ACPI_PCI_SLOT diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index 7dd70927991e..26696b693e63 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -77,6 +77,11 @@ static const struct apd_device_desc cz_i2c_desc = { .fixed_clk_rate = 133000000, }; +static const struct apd_device_desc wt_i2c_desc = { + .setup = acpi_apd_setup, + .fixed_clk_rate = 150000000, +}; + static struct property_entry uart_properties[] = { PROPERTY_ENTRY_U32("reg-io-width", 4), PROPERTY_ENTRY_U32("reg-shift", 2), @@ -156,7 +161,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = { /* Generic apd devices */ #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE { "AMD0010", APD_ADDR(cz_i2c_desc) }, - { "AMDI0010", APD_ADDR(cz_i2c_desc) }, + { "AMDI0010", APD_ADDR(wt_i2c_desc) }, { "AMD0020", APD_ADDR(cz_uart_desc) }, { "AMDI0020", APD_ADDR(cz_uart_desc) }, { "AMD0030", }, diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 373657f7e35a..8ea836c046f8 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -718,13 +718,14 @@ static int acpi_lpss_resume_early(struct device *dev) #define LPSS_GPIODEF0_DMA1_D3 BIT(2) #define LPSS_GPIODEF0_DMA2_D3 BIT(3) #define LPSS_GPIODEF0_DMA_D3_MASK GENMASK(3, 2) +#define LPSS_GPIODEF0_DMA_LLP BIT(13) static DEFINE_MUTEX(lpss_iosf_mutex); static void lpss_iosf_enter_d3_state(void) { u32 value1 = 0; - u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK; + u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP; u32 value2 = LPSS_PMCSR_D3hot; u32 mask2 = LPSS_PMCSR_Dx_MASK; /* @@ -768,8 +769,9 @@ exit: static void lpss_iosf_exit_d3_state(void) { - u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3; - u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK; + u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3 | + LPSS_GPIODEF0_DMA_LLP; + u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP; u32 value2 = LPSS_PMCSR_D0; u32 mask2 = LPSS_PMCSR_Dx_MASK; diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index c5557d070954..201292e67ee8 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -43,17 +43,6 @@ #define ACPI_VIDEO_BUS_NAME "Video Bus" #define ACPI_VIDEO_DEVICE_NAME "Video Device" -#define ACPI_VIDEO_NOTIFY_SWITCH 0x80 -#define ACPI_VIDEO_NOTIFY_PROBE 0x81 -#define ACPI_VIDEO_NOTIFY_CYCLE 0x82 -#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83 -#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84 - -#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85 -#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86 -#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 -#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 -#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 #define MAX_NAME_LEN 20 diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 0d099a24f776..e53bef6cf53c 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -852,6 +852,8 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) if (ghes_read_estatus(ghes, 1)) { ghes_clear_estatus(ghes); continue; + } else { + ret = NMI_HANDLED; } sev = ghes_severity(ghes->estatus->error_severity); @@ -863,12 +865,11 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) __process_error(ghes); ghes_clear_estatus(ghes); - - ret = NMI_HANDLED; } #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG - irq_work_queue(&ghes_proc_irq_work); + if (ret == NMI_HANDLED) + irq_work_queue(&ghes_proc_irq_work); #endif atomic_dec(&ghes_in_nmi); return ret; diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 20b3fcf4007c..8f2a98e23bba 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c @@ -123,7 +123,13 @@ EXPORT_SYMBOL_GPL(apei_hest_parse); */ static int __init hest_parse_cmc(struct acpi_hest_header *hest_hdr, void *data) { - return arch_apei_enable_cmcff(hest_hdr, data); + if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK) + return 0; + + if (!acpi_disable_cmcff) + return !arch_apei_enable_cmcff(hest_hdr, data); + + return 0; } struct ghes_arr { @@ -232,8 +238,9 @@ void __init acpi_hest_init(void) goto err; } - if (!acpi_disable_cmcff) - apei_hest_parse(hest_parse_cmc, NULL); + rc = apei_hest_parse(hest_parse_cmc, NULL); + if (rc) + goto err; if (!ghes_disable) { rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count); diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 93ecae55fe6a..05fe9ebfb9b5 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -430,39 +430,24 @@ static int acpi_battery_get_status(struct acpi_battery *battery) return 0; } -static int acpi_battery_get_info(struct acpi_battery *battery) + +static int extract_battery_info(const int use_bix, + struct acpi_battery *battery, + const struct acpi_buffer *buffer) { int result = -EFAULT; - acpi_status status = 0; - char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ? - "_BIX" : "_BIF"; - - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - if (!acpi_battery_present(battery)) - return 0; - mutex_lock(&battery->lock); - status = acpi_evaluate_object(battery->device->handle, name, - NULL, &buffer); - mutex_unlock(&battery->lock); - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name)); - return -ENODEV; - } - - if (battery_bix_broken_package) - result = extract_package(battery, buffer.pointer, + if (use_bix && battery_bix_broken_package) + result = extract_package(battery, buffer->pointer, extended_info_offsets + 1, ARRAY_SIZE(extended_info_offsets) - 1); - else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)) - result = extract_package(battery, buffer.pointer, + else if (use_bix) + result = extract_package(battery, buffer->pointer, extended_info_offsets, ARRAY_SIZE(extended_info_offsets)); else - result = extract_package(battery, buffer.pointer, + result = extract_package(battery, buffer->pointer, info_offsets, ARRAY_SIZE(info_offsets)); - kfree(buffer.pointer); if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) battery->full_charge_capacity = battery->design_capacity; if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && @@ -483,6 +468,45 @@ static int acpi_battery_get_info(struct acpi_battery *battery) return result; } +static int acpi_battery_get_info(struct acpi_battery *battery) +{ + const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); + int use_bix; + int result = -ENODEV; + + if (!acpi_battery_present(battery)) + return 0; + + + for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) { + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status status = AE_ERROR; + + mutex_lock(&battery->lock); + status = acpi_evaluate_object(battery->device->handle, + use_bix ? "_BIX":"_BIF", + NULL, &buffer); + mutex_unlock(&battery->lock); + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", + use_bix ? "_BIX":"_BIF")); + } else { + result = extract_battery_info(use_bix, + battery, + &buffer); + + kfree(buffer.pointer); + break; + } + } + + if (!result && !use_bix && xinfo) + pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n"); + + return result; +} + static int acpi_battery_get_state(struct acpi_battery *battery) { int result = 0; diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index bdc67bad61a7..4421f7c9981c 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -160,6 +160,34 @@ static struct dmi_system_id acpi_rev_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343"), }, }, + { + .callback = dmi_enable_rev_override, + .ident = "DELL Precision 5520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision 5520"), + }, + }, + { + .callback = dmi_enable_rev_override, + .ident = "DELL Precision 3520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3520"), + }, + }, + /* + * Resolves a quirk with the Dell Latitude 3350 that + * causes the ethernet adapter to not function. + */ + { + .callback = dmi_enable_rev_override, + .ident = "DELL Latitude 3350", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 3350"), + }, + }, #endif {} }; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 77468be75b3c..95855cb9d6fb 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -331,6 +331,16 @@ static void acpi_bus_osc_support(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; +#ifdef CONFIG_X86 + if (boot_cpu_has(X86_FEATURE_HWP)) { + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPCV2_SUPPORT; + } +#endif + + if (IS_ENABLED(CONFIG_SCHED_MC_PRIO)) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT; + if (!ghes_disable) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index d0d0504b7c89..3ca0729f7e0e 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -776,21 +776,25 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) init_waitqueue_head(&pcc_data.pcc_write_wait_q); } - /* Plug PSD data into this CPUs CPC descriptor. */ - per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr; - /* Everything looks okay */ pr_debug("Parsed CPC struct for CPU: %d\n", pr->id); /* Add per logical CPU nodes for reading its feedback counters. */ cpu_dev = get_cpu_device(pr->id); - if (!cpu_dev) + if (!cpu_dev) { + ret = -EINVAL; goto out_free; + } + + /* Plug PSD data into this CPUs CPC descriptor. */ + per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr; ret = kobject_init_and_add(&cpc_ptr->kobj, &cppc_ktype, &cpu_dev->kobj, "acpi_cppc"); - if (ret) + if (ret) { + per_cpu(cpc_desc_ptr, pr->id) = NULL; goto out_free; + } kfree(output.pointer); return 0; @@ -824,6 +828,8 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr) void __iomem *addr; cpc_ptr = per_cpu(cpc_desc_ptr, pr->id); + if (!cpc_ptr) + return; /* Free all the mapped sys mem areas for this CPU */ for (i = 2; i < cpc_ptr->num_entries; i++) { diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index 7b2c48fde4e2..24418932612e 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -52,7 +52,7 @@ struct acpi_data_node_attr { static ssize_t data_node_show_path(struct acpi_data_node *dn, char *buf) { - return acpi_object_path(dn->handle, buf); + return dn->handle ? acpi_object_path(dn->handle, buf) : 0; } DATA_NODE_ATTR(path); @@ -105,10 +105,10 @@ static void acpi_expose_nondev_subnodes(struct kobject *kobj, init_completion(&dn->kobj_done); ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype, kobj, "%s", dn->name); - if (ret) - acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret); - else + if (!ret) acpi_expose_nondev_subnodes(&dn->kobj, &dn->data); + else if (dn->handle) + acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret); } } diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index e24ea4e796e4..7fceb3b4691b 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -82,8 +82,8 @@ static const struct genl_multicast_group acpi_event_mcgrps[] = { { .name = ACPI_GENL_MCAST_GROUP_NAME, }, }; -static struct genl_family acpi_event_genl_family = { - .id = GENL_ID_GENERATE, +static struct genl_family acpi_event_genl_family __ro_after_init = { + .module = THIS_MODULE, .name = ACPI_GENL_FAMILY_NAME, .version = ACPI_GENL_VERSION, .maxattr = ACPI_GENL_ATTR_MAX, @@ -144,7 +144,7 @@ int acpi_bus_generate_netlink_event(const char *device_class, EXPORT_SYMBOL(acpi_bus_generate_netlink_event); -static int acpi_event_genetlink_init(void) +static int __init acpi_event_genetlink_init(void) { return genl_register_family(&acpi_event_genl_family); } diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 0efd3fa9a4d8..2f82b8eba360 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -94,7 +94,7 @@ static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc) return to_acpi_device(acpi_desc->dev); } -static int xlat_status(void *buf, unsigned int cmd, u32 status) +static int xlat_bus_status(void *buf, unsigned int cmd, u32 status) { struct nd_cmd_clear_error *clear_err; struct nd_cmd_ars_status *ars_status; @@ -113,7 +113,7 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status) flags = ND_ARS_PERSISTENT | ND_ARS_VOLATILE; if ((status >> 16 & flags) == 0) return -ENOTTY; - break; + return 0; case ND_CMD_ARS_START: /* ARS is in progress */ if ((status & 0xffff) == NFIT_ARS_START_BUSY) @@ -122,7 +122,7 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status) /* Command failed */ if (status & 0xffff) return -EIO; - break; + return 0; case ND_CMD_ARS_STATUS: ars_status = buf; /* Command failed */ @@ -146,7 +146,8 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status) * then just continue with the returned results. */ if (status == NFIT_ARS_STATUS_INTR) { - if (ars_status->flags & NFIT_ARS_F_OVERFLOW) + if (ars_status->out_length >= 40 && (ars_status->flags + & NFIT_ARS_F_OVERFLOW)) return -ENOSPC; return 0; } @@ -154,7 +155,7 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status) /* Unknown status */ if (status >> 16) return -EIO; - break; + return 0; case ND_CMD_CLEAR_ERROR: clear_err = buf; if (status & 0xffff) @@ -163,7 +164,7 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status) return -EIO; if (clear_err->length > clear_err->cleared) return clear_err->cleared; - break; + return 0; default: break; } @@ -174,9 +175,18 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status) return 0; } -static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, - struct nvdimm *nvdimm, unsigned int cmd, void *buf, - unsigned int buf_len, int *cmd_rc) +static int xlat_status(struct nvdimm *nvdimm, void *buf, unsigned int cmd, + u32 status) +{ + if (!nvdimm) + return xlat_bus_status(buf, cmd, status); + if (status) + return -EIO; + return 0; +} + +int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, + unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) { struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); union acpi_object in_obj, in_buf, *out_obj; @@ -298,7 +308,8 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, for (i = 0, offset = 0; i < desc->out_num; i++) { u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf, - (u32 *) out_obj->buffer.pointer); + (u32 *) out_obj->buffer.pointer, + out_obj->buffer.length - offset); if (offset + out_size > out_obj->buffer.length) { dev_dbg(dev, "%s:%s output object underflow cmd: %s field: %d\n", @@ -333,7 +344,8 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, */ rc = buf_len - offset - in_buf.buffer.length; if (cmd_rc) - *cmd_rc = xlat_status(buf, cmd, fw_status); + *cmd_rc = xlat_status(nvdimm, buf, cmd, + fw_status); } else { dev_err(dev, "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n", __func__, dimm_name, cmd_name, buf_len, @@ -343,7 +355,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, } else { rc = 0; if (cmd_rc) - *cmd_rc = xlat_status(buf, cmd, fw_status); + *cmd_rc = xlat_status(nvdimm, buf, cmd, fw_status); } out: @@ -351,6 +363,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, return rc; } +EXPORT_SYMBOL_GPL(acpi_nfit_ctl); static const char *spa_type_name(u16 type) { @@ -2001,19 +2014,32 @@ static int ars_get_status(struct acpi_nfit_desc *acpi_desc) return cmd_rc; } -static int ars_status_process_records(struct nvdimm_bus *nvdimm_bus, +static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc, struct nd_cmd_ars_status *ars_status) { + struct nvdimm_bus *nvdimm_bus = acpi_desc->nvdimm_bus; int rc; u32 i; + /* + * First record starts at 44 byte offset from the start of the + * payload. + */ + if (ars_status->out_length < 44) + return 0; for (i = 0; i < ars_status->num_records; i++) { + /* only process full records */ + if (ars_status->out_length + < 44 + sizeof(struct nd_ars_record) * (i + 1)) + break; rc = nvdimm_bus_add_poison(nvdimm_bus, ars_status->records[i].err_address, ars_status->records[i].length); if (rc) return rc; } + if (i < ars_status->num_records) + dev_warn(acpi_desc->dev, "detected truncated ars results\n"); return 0; } @@ -2266,8 +2292,7 @@ static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc, if (rc < 0 && rc != -ENOSPC) return rc; - if (ars_status_process_records(acpi_desc->nvdimm_bus, - acpi_desc->ars_status)) + if (ars_status_process_records(acpi_desc, acpi_desc->ars_status)) return -ENOMEM; return 0; diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index 14296f5267c8..fc29c2e9832e 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -240,5 +240,7 @@ const u8 *to_nfit_uuid(enum nfit_uuids id); int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz); void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event); void __acpi_nvdimm_notify(struct device *dev, u32 event); +int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, + unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc); void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev); #endif /* __NFIT_H__ */ diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 8a7cab06e271..a404ff4d7151 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -182,15 +182,15 @@ void acpi_os_vprintf(const char *fmt, va_list args) static unsigned long acpi_rsdp; static int __init setup_acpi_rsdp(char *arg) { - if (kstrtoul(arg, 16, &acpi_rsdp)) - return -EINVAL; - return 0; + return kstrtoul(arg, 16, &acpi_rsdp); } early_param("acpi_rsdp", setup_acpi_rsdp); #endif acpi_physical_address __init acpi_os_get_root_pointer(void) { + acpi_physical_address pa = 0; + #ifdef CONFIG_KEXEC if (acpi_rsdp) return acpi_rsdp; @@ -199,21 +199,14 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) return efi.acpi20; - else if (efi.acpi != EFI_INVALID_TABLE_ADDR) + if (efi.acpi != EFI_INVALID_TABLE_ADDR) return efi.acpi; - else { - printk(KERN_ERR PREFIX - "System description tables not found\n"); - return 0; - } + pr_err(PREFIX "System description tables not found\n"); } else if (IS_ENABLED(CONFIG_ACPI_LEGACY_TABLES_LOOKUP)) { - acpi_physical_address pa = 0; - acpi_find_root_pointer(&pa); - return pa; } - return 0; + return pa; } /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2237d3f24f0e..5c8aa9cf62d7 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -141,7 +141,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr, if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) return; - if (amd_e400_c1e_detected) + if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) type = ACPI_STATE_C1; /* diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index bb01dea39fdc..f0b4a981b8d3 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -157,7 +157,7 @@ static void acpi_processor_ppc_ost(acpi_handle handle, int status) status, NULL); } -int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag) +void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag) { int ret; @@ -168,7 +168,7 @@ int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag) */ if (event_flag) acpi_processor_ppc_ost(pr->handle, 1); - return 0; + return; } ret = acpi_processor_get_platform_limit(pr); @@ -182,10 +182,8 @@ int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag) else acpi_processor_ppc_ost(pr->handle, 0); } - if (ret < 0) - return (ret); - else - return cpufreq_update_policy(pr->id); + if (ret >= 0) + cpufreq_update_policy(pr->id); } int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) @@ -465,11 +463,33 @@ int acpi_processor_get_performance_info(struct acpi_processor *pr) return result; } EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info); -int acpi_processor_notify_smm(struct module *calling_module) + +int acpi_processor_pstate_control(void) { acpi_status status; - static int is_done = 0; + if (!acpi_gbl_FADT.smi_command || !acpi_gbl_FADT.pstate_control) + return 0; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Writing pstate_control [0x%x] to smi_command [0x%x]\n", + acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command)); + + status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + (u32)acpi_gbl_FADT.pstate_control, 8); + if (ACPI_SUCCESS(status)) + return 1; + + ACPI_EXCEPTION((AE_INFO, status, + "Failed to write pstate_control [0x%x] to smi_command [0x%x]", + acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command)); + return -EIO; +} + +int acpi_processor_notify_smm(struct module *calling_module) +{ + static int is_done = 0; + int result; if (!(acpi_processor_ppc_status & PPC_REGISTERED)) return -EBUSY; @@ -492,26 +512,15 @@ int acpi_processor_notify_smm(struct module *calling_module) is_done = -EIO; - /* Can't write pstate_control to smi_command if either value is zero */ - if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) { + result = acpi_processor_pstate_control(); + if (!result) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n")); module_put(calling_module); return 0; } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Writing pstate_control [0x%x] to smi_command [0x%x]\n", - acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command)); - - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.pstate_control, 8); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Failed to write pstate_control [0x%x] to " - "smi_command [0x%x]", acpi_gbl_FADT.pstate_control, - acpi_gbl_FADT.smi_command)); + if (result < 0) { module_put(calling_module); - return status; + return result; } /* Success. If there's no _PPC, we need to fear nothing, so diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 03f5ec11ab31..3afddcd834ef 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -41,14 +41,13 @@ static bool acpi_enumerate_nondev_subnodes(acpi_handle scope, static bool acpi_extract_properties(const union acpi_object *desc, struct acpi_device_data *data); -static bool acpi_nondev_subnode_ok(acpi_handle scope, - const union acpi_object *link, - struct list_head *list) +static bool acpi_nondev_subnode_extract(const union acpi_object *desc, + acpi_handle handle, + const union acpi_object *link, + struct list_head *list) { - struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; struct acpi_data_node *dn; - acpi_handle handle; - acpi_status status; + bool result; dn = kzalloc(sizeof(*dn), GFP_KERNEL); if (!dn) @@ -58,43 +57,75 @@ static bool acpi_nondev_subnode_ok(acpi_handle scope, dn->fwnode.type = FWNODE_ACPI_DATA; INIT_LIST_HEAD(&dn->data.subnodes); - status = acpi_get_handle(scope, link->package.elements[1].string.pointer, - &handle); - if (ACPI_FAILURE(status)) - goto fail; + result = acpi_extract_properties(desc, &dn->data); - status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf, - ACPI_TYPE_PACKAGE); - if (ACPI_FAILURE(status)) - goto fail; + if (handle) { + acpi_handle scope; + acpi_status status; - if (acpi_extract_properties(buf.pointer, &dn->data)) - dn->handle = handle; + /* + * The scope for the subnode object lookup is the one of the + * namespace node (device) containing the object that has + * returned the package. That is, it's the scope of that + * object's parent. + */ + status = acpi_get_parent(handle, &scope); + if (ACPI_SUCCESS(status) + && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data)) + result = true; + } else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data)) { + result = true; + } - /* - * The scope for the subnode object lookup is the one of the namespace - * node (device) containing the object that has returned the package. - * That is, it's the scope of that object's parent. - */ - status = acpi_get_parent(handle, &scope); - if (ACPI_SUCCESS(status) - && acpi_enumerate_nondev_subnodes(scope, buf.pointer, &dn->data)) + if (result) { dn->handle = handle; - - if (dn->handle) { - dn->data.pointer = buf.pointer; + dn->data.pointer = desc; list_add_tail(&dn->sibling, list); return true; } + kfree(dn); acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n"); + return false; +} + +static bool acpi_nondev_subnode_data_ok(acpi_handle handle, + const union acpi_object *link, + struct list_head *list) +{ + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; + acpi_status status; + + status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf, + ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(status)) + return false; + + if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list)) + return true; - fail: ACPI_FREE(buf.pointer); - kfree(dn); return false; } +static bool acpi_nondev_subnode_ok(acpi_handle scope, + const union acpi_object *link, + struct list_head *list) +{ + acpi_handle handle; + acpi_status status; + + if (!scope) + return false; + + status = acpi_get_handle(scope, link->package.elements[1].string.pointer, + &handle); + if (ACPI_FAILURE(status)) + return false; + + return acpi_nondev_subnode_data_ok(handle, link, list); +} + static int acpi_add_nondev_subnodes(acpi_handle scope, const union acpi_object *links, struct list_head *list) @@ -103,15 +134,37 @@ static int acpi_add_nondev_subnodes(acpi_handle scope, int i; for (i = 0; i < links->package.count; i++) { - const union acpi_object *link; + const union acpi_object *link, *desc; + acpi_handle handle; + bool result; link = &links->package.elements[i]; - /* Only two elements allowed, both must be strings. */ - if (link->package.count == 2 - && link->package.elements[0].type == ACPI_TYPE_STRING - && link->package.elements[1].type == ACPI_TYPE_STRING - && acpi_nondev_subnode_ok(scope, link, list)) - ret = true; + /* Only two elements allowed. */ + if (link->package.count != 2) + continue; + + /* The first one must be a string. */ + if (link->package.elements[0].type != ACPI_TYPE_STRING) + continue; + + /* The second one may be a string, a reference or a package. */ + switch (link->package.elements[1].type) { + case ACPI_TYPE_STRING: + result = acpi_nondev_subnode_ok(scope, link, list); + break; + case ACPI_TYPE_LOCAL_REFERENCE: + handle = link->package.elements[1].reference.handle; + result = acpi_nondev_subnode_data_ok(handle, link, list); + break; + case ACPI_TYPE_PACKAGE: + desc = &link->package.elements[1]; + result = acpi_nondev_subnode_extract(desc, NULL, link, list); + break; + default: + result = false; + break; + } + ret = ret || result; } return ret; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 3d1856f1f4d0..07aa2e649eb1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1119,9 +1119,6 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " "support\n")); *cap |= ACPI_VIDEO_BACKLIGHT; - if (!acpi_has_method(handle, "_BQC")) - printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, " - "cannot determine initial brightness\n"); /* We have backlight support, no need to scan further */ return AE_CTRL_TERMINATE; } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index deb0ff78eba8..9b6cebe227a0 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -47,32 +47,15 @@ static void acpi_sleep_tts_switch(u32 acpi_state) } } -static void acpi_sleep_pts_switch(u32 acpi_state) -{ - acpi_status status; - - status = acpi_execute_simple_method(NULL, "\\_PTS", acpi_state); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - /* - * OS can't evaluate the _PTS object correctly. Some warning - * message will be printed. But it won't break anything. - */ - printk(KERN_NOTICE "Failure in evaluating _PTS object\n"); - } -} - -static int sleep_notify_reboot(struct notifier_block *this, +static int tts_notify_reboot(struct notifier_block *this, unsigned long code, void *x) { acpi_sleep_tts_switch(ACPI_STATE_S5); - - acpi_sleep_pts_switch(ACPI_STATE_S5); - return NOTIFY_DONE; } -static struct notifier_block sleep_notifier = { - .notifier_call = sleep_notify_reboot, +static struct notifier_block tts_notifier = { + .notifier_call = tts_notify_reboot, .next = NULL, .priority = 0, }; @@ -691,6 +674,14 @@ static void acpi_sleep_suspend_setup(void) if (acpi_sleep_state_supported(i)) sleep_states[i] = 1; + /* + * Use suspend-to-idle by default if ACPI_FADT_LOW_POWER_S0 is set and + * the default suspend mode was not selected from the command line. + */ + if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0 && + mem_sleep_default > PM_SUSPEND_MEM) + mem_sleep_default = PM_SUSPEND_FREEZE; + suspend_set_ops(old_suspend_ordering ? &acpi_suspend_ops_old : &acpi_suspend_ops); freeze_set_ops(&acpi_freeze_ops); @@ -916,9 +907,9 @@ int __init acpi_sleep_init(void) pr_info(PREFIX "(supports%s)\n", supported); /* - * Register the sleep_notifier to reboot notifier list so that the _TTS - * and _PTS object can also be evaluated when the system enters S5. + * Register the tts_notifier to reboot notifier list so that the _TTS + * object can also be evaluated when the system enters S5. */ - register_reboot_notifier(&sleep_notifier); + register_reboot_notifier(&tts_notifier); return 0; } diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index a6b36fc53aec..02ded25c82e4 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -296,6 +296,26 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"), }, }, + { + /* https://bugzilla.redhat.com/show_bug.cgi?id=1123661 */ + .callback = video_detect_force_native, + .ident = "Dell XPS 17 L702X", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"), + }, + }, + { + /* https://bugzilla.redhat.com/show_bug.cgi?id=1204476 */ + /* https://bugs.launchpad.net/ubuntu/+source/linux-lts-trusty/+bug/1416940 */ + .callback = video_detect_force_native, + .ident = "HP Pavilion dv6", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6 Notebook PC"), + }, + }, + { }, }; |