diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpi_configfs.c | 5 | ||||
-rw-r--r-- | drivers/acpi/acpi_ipmi.c | 7 | ||||
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 13 | ||||
-rw-r--r-- | drivers/acpi/apei/einj.c | 2 | ||||
-rw-r--r-- | drivers/acpi/apei/ghes.c | 81 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 5 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 37 | ||||
-rw-r--r-- | drivers/acpi/event.c | 2 | ||||
-rw-r--r-- | drivers/acpi/nvs.c | 24 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 7 | ||||
-rw-r--r-- | drivers/acpi/sbshc.c | 1 |
11 files changed, 130 insertions, 54 deletions
diff --git a/drivers/acpi/acpi_configfs.c b/drivers/acpi/acpi_configfs.c index 3a14859dbb75..76b83b181356 100644 --- a/drivers/acpi/acpi_configfs.c +++ b/drivers/acpi/acpi_configfs.c @@ -13,9 +13,6 @@ #include <linux/acpi.h> #include <linux/security.h> -#include "acpica/accommon.h" -#include "acpica/actables.h" - static struct config_group *acpi_table_group; struct acpi_table { @@ -226,7 +223,7 @@ static void acpi_table_drop_item(struct config_group *group, { struct acpi_table *table = container_of(cfg, struct acpi_table, cfg); - ACPI_INFO(("Host-directed Dynamic ACPI Table Unload")); + pr_debug("Host-directed Dynamic ACPI Table Unload\n"); acpi_unload_table(table->index); config_item_put(cfg); } diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index bbd00d96b7a8..a5fe2926bf50 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -597,9 +597,14 @@ static int __init acpi_ipmi_init(void) pr_warn("Can't register IPMI opregion space handle\n"); return -EINVAL; } + result = ipmi_smi_watcher_register(&driver_data.bmc_events); - if (result) + if (result) { + acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_IPMI, + &acpi_ipmi_space_handler); pr_err("Can't register IPMI system interface watcher\n"); + } return result; } diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index ca742f16a507..894b7e6ae144 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -186,13 +186,12 @@ static void byt_i2c_setup(struct lpss_private_data *pdata) long uid = 0; /* Expected to always be true, but better safe then sorry */ - if (uid_str) - uid = simple_strtol(uid_str, NULL, 10); - - /* Detect I2C bus shared with PUNIT and ignore its d3 status */ - status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host); - if (ACPI_SUCCESS(status) && shared_host && uid) - pmc_atom_d3_mask &= ~(BIT_LPSS2_F1_I2C1 << (uid - 1)); + if (uid_str && !kstrtol(uid_str, 10, &uid) && uid) { + /* Detect I2C bus shared with PUNIT and ignore its d3 status */ + status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host); + if (ACPI_SUCCESS(status) && shared_host) + pmc_atom_d3_mask &= ~(BIT_LPSS2_F1_I2C1 << (uid - 1)); + } lpss_deassert_reset(pdata); diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 328e8aeece6c..2882450c443e 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -673,7 +673,7 @@ static int __init einj_init(void) struct apei_exec_context ctx; if (acpi_disabled) { - pr_warn("ACPI disabled.\n"); + pr_info("ACPI disabled.\n"); return -ENODEV; } diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index fce7ade2aba9..0c8330ed1ffd 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -441,28 +441,35 @@ static void ghes_kick_task_work(struct callback_head *head) gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node, node_len); } -static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, - int sev) +static bool ghes_do_memory_failure(u64 physical_addr, int flags) { unsigned long pfn; - int flags = -1; - int sec_sev = ghes_severity(gdata->error_severity); - struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata); if (!IS_ENABLED(CONFIG_ACPI_APEI_MEMORY_FAILURE)) return false; - if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) - return false; - - pfn = mem_err->physical_addr >> PAGE_SHIFT; + pfn = PHYS_PFN(physical_addr); if (!pfn_valid(pfn)) { pr_warn_ratelimited(FW_WARN GHES_PFX "Invalid address in generic error data: %#llx\n", - mem_err->physical_addr); + physical_addr); return false; } + memory_failure_queue(pfn, flags); + return true; +} + +static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, + int sev) +{ + int flags = -1; + int sec_sev = ghes_severity(gdata->error_severity); + struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata); + + if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) + return false; + /* iff following two events can be handled properly by now */ if (sec_sev == GHES_SEV_CORRECTED && (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED)) @@ -470,14 +477,56 @@ static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE) flags = 0; - if (flags != -1) { - memory_failure_queue(pfn, flags); - return true; - } + if (flags != -1) + return ghes_do_memory_failure(mem_err->physical_addr, flags); return false; } +static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata, int sev) +{ + struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata); + bool queued = false; + int sec_sev, i; + char *p; + + log_arm_hw_error(err); + + sec_sev = ghes_severity(gdata->error_severity); + if (sev != GHES_SEV_RECOVERABLE || sec_sev != GHES_SEV_RECOVERABLE) + return false; + + p = (char *)(err + 1); + for (i = 0; i < err->err_info_num; i++) { + struct cper_arm_err_info *err_info = (struct cper_arm_err_info *)p; + bool is_cache = (err_info->type == CPER_ARM_CACHE_ERROR); + bool has_pa = (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR); + const char *error_type = "unknown error"; + + /* + * The field (err_info->error_info & BIT(26)) is fixed to set to + * 1 in some old firmware of HiSilicon Kunpeng920. We assume that + * firmware won't mix corrected errors in an uncorrected section, + * and don't filter out 'corrected' error here. + */ + if (is_cache && has_pa) { + queued = ghes_do_memory_failure(err_info->physical_fault_addr, 0); + p += err_info->length; + continue; + } + + if (err_info->type < ARRAY_SIZE(cper_proc_error_type_strs)) + error_type = cper_proc_error_type_strs[err_info->type]; + + pr_warn_ratelimited(FW_WARN GHES_PFX + "Unhandled processor error type: %s\n", + error_type); + p += err_info->length; + } + + return queued; +} + /* * PCIe AER errors need to be sent to the AER driver for reporting and * recovery. The GHES severities map to the following AER severities and @@ -605,9 +654,7 @@ static bool ghes_do_proc(struct ghes *ghes, ghes_handle_aer(gdata); } else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { - struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata); - - log_arm_hw_error(err); + queued = ghes_handle_arm_hw_error(gdata, sev); } else { void *err = acpi_hest_get_payload(gdata); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 14ec87a76e14..60fb6a843853 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1315,14 +1315,13 @@ static int __init acpi_init(void) } acpi_kobj = kobject_create_and_add("acpi", firmware_kobj); - if (!acpi_kobj) { + if (!acpi_kobj) pr_debug("%s: kset create error\n", __func__); - acpi_kobj = NULL; - } init_prmt(); result = acpi_bus_init(); if (result) { + kobject_put(acpi_kobj); disable_acpi(); return result; } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3f7680a007a3..e629e891d1bb 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -183,6 +183,7 @@ static struct workqueue_struct *ec_query_wq; static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */ static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */ +static int EC_FLAGS_TRUST_DSDT_GPE; /* Needs DSDT GPE as correction setting */ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ /* -------------------------------------------------------------------------- @@ -1593,7 +1594,8 @@ static int acpi_ec_add(struct acpi_device *device) } if (boot_ec && ec->command_addr == boot_ec->command_addr && - ec->data_addr == boot_ec->data_addr) { + ec->data_addr == boot_ec->data_addr && + !EC_FLAGS_TRUST_DSDT_GPE) { /* * Trust PNP0C09 namespace location rather than * ECDT ID. But trust ECDT GPE rather than _GPE @@ -1817,6 +1819,18 @@ static int ec_correct_ecdt(const struct dmi_system_id *id) } /* + * Some ECDTs contain wrong GPE setting, but they share the same port addresses + * with DSDT EC, don't duplicate the DSDT EC with ECDT EC in this case. + * https://bugzilla.kernel.org/show_bug.cgi?id=209989 + */ +static int ec_honor_dsdt_gpe(const struct dmi_system_id *id) +{ + pr_debug("Detected system needing DSDT GPE setting.\n"); + EC_FLAGS_TRUST_DSDT_GPE = 1; + return 0; +} + +/* * Some DSDTs contain wrong GPE setting. * Asus FX502VD/VE, GL702VMK, X550VXK, X580VD * https://bugzilla.kernel.org/show_bug.cgi?id=195651 @@ -1846,6 +1860,22 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "GL702VMK"),}, NULL}, { + ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BA", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X505BA"),}, NULL}, + { + ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BP", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X505BP"),}, NULL}, + { + ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BA", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X542BA"),}, NULL}, + { + ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BP", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X542BP"),}, NULL}, + { ec_honor_ecdt_gpe, "ASUS X550VXK", { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X550VXK"),}, NULL}, @@ -1854,6 +1884,11 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL}, { + /* https://bugzilla.kernel.org/show_bug.cgi?id=209989 */ + ec_honor_dsdt_gpe, "HP Pavilion Gaming Laptop 15-cx0xxx", { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-cx0xxx"),}, NULL}, + { ec_clear_on_resume, "Samsung hardware", { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, {}, diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index df38f3c94861..d199a19bb292 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -167,7 +167,7 @@ static int acpi_event_genetlink_init(void) static int __init acpi_event_init(void) { - int error = 0; + int error; if (acpi_disabled) return 0; diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index 7f02e399047c..a2b11069e792 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c @@ -84,13 +84,13 @@ struct nvs_page { static LIST_HEAD(nvs_list); /** - * suspend_nvs_register - register platform NVS memory region to save - * @start - physical address of the region - * @size - size of the region + * suspend_nvs_register - register platform NVS memory region to save + * @start: Physical address of the region. + * @size: Size of the region. * - * The NVS region need not be page-aligned (both ends) and we arrange - * things so that the data from page-aligned addresses in this region will - * be copied into separate RAM pages. + * The NVS region need not be page-aligned (both ends) and we arrange + * things so that the data from page-aligned addresses in this region will + * be copied into separate RAM pages. */ static int suspend_nvs_register(unsigned long start, unsigned long size) { @@ -125,7 +125,7 @@ static int suspend_nvs_register(unsigned long start, unsigned long size) } /** - * suspend_nvs_free - free data pages allocated for saving NVS regions + * suspend_nvs_free - free data pages allocated for saving NVS regions */ void suspend_nvs_free(void) { @@ -149,7 +149,7 @@ void suspend_nvs_free(void) } /** - * suspend_nvs_alloc - allocate memory necessary for saving NVS regions + * suspend_nvs_alloc - allocate memory necessary for saving NVS regions */ int suspend_nvs_alloc(void) { @@ -166,7 +166,7 @@ int suspend_nvs_alloc(void) } /** - * suspend_nvs_save - save NVS memory regions + * suspend_nvs_save - save NVS memory regions */ int suspend_nvs_save(void) { @@ -195,10 +195,10 @@ int suspend_nvs_save(void) } /** - * suspend_nvs_restore - restore NVS memory regions + * suspend_nvs_restore - restore NVS memory regions * - * This function is going to be called with interrupts disabled, so it - * cannot iounmap the virtual addresses used to access the NVS region. + * This function is going to be called with interrupts disabled, so it + * cannot iounmap the virtual addresses used to access the NVS region. */ void suspend_nvs_restore(void) { diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 1207490b0a50..45c5c0e45e33 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1487,12 +1487,7 @@ EXPORT_SYMBOL(acpi_check_resource_conflict); int acpi_check_region(resource_size_t start, resource_size_t n, const char *name) { - struct resource res = { - .start = start, - .end = start + n - 1, - .name = name, - .flags = IORESOURCE_IO, - }; + struct resource res = DEFINE_RES_IO_NAMED(start, n, name); return acpi_check_resource_conflict(&res); } diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index d69a2a84c83c..7c62e149a7a1 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -231,7 +231,6 @@ static int smbus_alarm(void *context) case ACPI_SBS_BATTERY: acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_smbus_callback, hc); - default:; } mutex_unlock(&hc->lock); return 0; |