Merge branches 'acpi-ec', 'acpi-apei', 'acpi-soc' and 'acpi-misc'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 29 Jun 2021 13:51:25 +0000 (15:51 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 29 Jun 2021 13:51:25 +0000 (15:51 +0200)
* acpi-ec:
  ACPI: EC: trust DSDT GPE for certain HP laptop
  ACPI: EC: Make more Asus laptops use ECDT _GPE

* acpi-apei:
  ACPI: APEI: fix synchronous external aborts in user-mode
  ACPI: APEI: Don't warn if ACPI is disabled

* acpi-soc:
  ACPI: LPSS: Use kstrtol() instead of simple_strtol()

* acpi-misc:
  ACPI: NVS: fix doc warnings in nvs.c
  ACPI: NUMA: fix typo in a comment
  ACPI: OSL: Use DEFINE_RES_IO_NAMED() to simplify code
  ACPI: bus: Call kobject_put() in acpi_init() error path
  ACPI: bus: Remove unneeded assignment
  ACPI: configfs: Replace ACPI_INFO() with pr_debug()
  ACPI: ipmi: Remove address space handler in error path
  ACPI: event: Remove redundant initialization of local variable
  ACPI: sbshc: Fix fall-through warning for Clang

12 files changed:
drivers/acpi/acpi_configfs.c
drivers/acpi/acpi_ipmi.c
drivers/acpi/acpi_lpss.c
drivers/acpi/apei/einj.c
drivers/acpi/apei/ghes.c
drivers/acpi/bus.c
drivers/acpi/ec.c
drivers/acpi/event.c
drivers/acpi/nvs.c
drivers/acpi/osl.c
drivers/acpi/sbshc.c
include/acpi/acpi_numa.h

index 3a14859..76b83b1 100644 (file)
@@ -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);
 }
index bbd00d9..a5fe292 100644 (file)
@@ -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;
 }
index ca742f1..894b7e6 100644 (file)
@@ -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);
 
index 328e8ae..2882450 100644 (file)
@@ -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;
        }
 
index fce7ade..0c8330e 100644 (file)
@@ -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);
 
index 14ec87a..60fb6a8 100644 (file)
@@ -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;
        }
index 3f7680a..e629e89 100644 (file)
@@ -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
@@ -1816,6 +1818,18 @@ static int ec_correct_ecdt(const struct dmi_system_id *id)
        return 0;
 }
 
+/*
+ * 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
@@ -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},
        {},
index df38f3c..d199a19 100644 (file)
@@ -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;
index 7f02e39..a2b1106 100644 (file)
@@ -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)
 {
index 1207490..45c5c0e 100644 (file)
@@ -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);
 }
index d69a2a8..7c62e14 100644 (file)
@@ -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;
index 40a91ce..68e4d80 100644 (file)
@@ -43,4 +43,4 @@ static inline void disable_hmat(void)
 {
 }
 #endif                         /* CONFIG_ACPI_HMAT */
-#endif                         /* __ACP_NUMA_H */
+#endif                         /* __ACPI_NUMA_H */