Merge branches 'acpi-ec', 'acpi-apei', 'acpi-soc' and 'acpi-misc'

* 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
This commit is contained in:
Rafael J. Wysocki 2021-06-29 15:51:25 +02:00
12 changed files with 131 additions and 55 deletions

View File

@ -13,9 +13,6 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/security.h> #include <linux/security.h>
#include "acpica/accommon.h"
#include "acpica/actables.h"
static struct config_group *acpi_table_group; static struct config_group *acpi_table_group;
struct acpi_table { 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); 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); acpi_unload_table(table->index);
config_item_put(cfg); config_item_put(cfg);
} }

View File

@ -597,9 +597,14 @@ static int __init acpi_ipmi_init(void)
pr_warn("Can't register IPMI opregion space handle\n"); pr_warn("Can't register IPMI opregion space handle\n");
return -EINVAL; return -EINVAL;
} }
result = ipmi_smi_watcher_register(&driver_data.bmc_events); 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"); pr_err("Can't register IPMI system interface watcher\n");
}
return result; return result;
} }

View File

@ -186,13 +186,12 @@ static void byt_i2c_setup(struct lpss_private_data *pdata)
long uid = 0; long uid = 0;
/* Expected to always be true, but better safe then sorry */ /* Expected to always be true, but better safe then sorry */
if (uid_str) if (uid_str && !kstrtol(uid_str, 10, &uid) && uid) {
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);
/* Detect I2C bus shared with PUNIT and ignore its d3 status */ if (ACPI_SUCCESS(status) && shared_host)
status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host); pmc_atom_d3_mask &= ~(BIT_LPSS2_F1_I2C1 << (uid - 1));
if (ACPI_SUCCESS(status) && shared_host && uid) }
pmc_atom_d3_mask &= ~(BIT_LPSS2_F1_I2C1 << (uid - 1));
lpss_deassert_reset(pdata); lpss_deassert_reset(pdata);

View File

@ -673,7 +673,7 @@ static int __init einj_init(void)
struct apei_exec_context ctx; struct apei_exec_context ctx;
if (acpi_disabled) { if (acpi_disabled) {
pr_warn("ACPI disabled.\n"); pr_info("ACPI disabled.\n");
return -ENODEV; return -ENODEV;
} }

View 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); gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node, node_len);
} }
static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, static bool ghes_do_memory_failure(u64 physical_addr, int flags)
int sev)
{ {
unsigned long pfn; 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)) if (!IS_ENABLED(CONFIG_ACPI_APEI_MEMORY_FAILURE))
return false; return false;
if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) pfn = PHYS_PFN(physical_addr);
return false;
pfn = mem_err->physical_addr >> PAGE_SHIFT;
if (!pfn_valid(pfn)) { if (!pfn_valid(pfn)) {
pr_warn_ratelimited(FW_WARN GHES_PFX pr_warn_ratelimited(FW_WARN GHES_PFX
"Invalid address in generic error data: %#llx\n", "Invalid address in generic error data: %#llx\n",
mem_err->physical_addr); physical_addr);
return false; 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 */ /* iff following two events can be handled properly by now */
if (sec_sev == GHES_SEV_CORRECTED && if (sec_sev == GHES_SEV_CORRECTED &&
(gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED)) (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) if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE)
flags = 0; flags = 0;
if (flags != -1) { if (flags != -1)
memory_failure_queue(pfn, flags); return ghes_do_memory_failure(mem_err->physical_addr, flags);
return true;
}
return false; 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 * 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 * 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); ghes_handle_aer(gdata);
} }
else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata); queued = ghes_handle_arm_hw_error(gdata, sev);
log_arm_hw_error(err);
} else { } else {
void *err = acpi_hest_get_payload(gdata); void *err = acpi_hest_get_payload(gdata);

View File

@ -1315,14 +1315,13 @@ static int __init acpi_init(void)
} }
acpi_kobj = kobject_create_and_add("acpi", firmware_kobj); acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
if (!acpi_kobj) { if (!acpi_kobj)
pr_debug("%s: kset create error\n", __func__); pr_debug("%s: kset create error\n", __func__);
acpi_kobj = NULL;
}
init_prmt(); init_prmt();
result = acpi_bus_init(); result = acpi_bus_init();
if (result) { if (result) {
kobject_put(acpi_kobj);
disable_acpi(); disable_acpi();
return result; return result;
} }

View 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_CORRECT_ECDT; /* Needs ECDT port address correction */
static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */ 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 */ 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 && 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 * Trust PNP0C09 namespace location rather than
* ECDT ID. But trust ECDT GPE rather than _GPE * 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; 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. * Some DSDTs contain wrong GPE setting.
* Asus FX502VD/VE, GL702VMK, X550VXK, X580VD * 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_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "GL702VMK"),}, NULL}, 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", { ec_honor_ecdt_gpe, "ASUS X550VXK", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X550VXK"),}, NULL}, 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_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL}, 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", { ec_clear_on_resume, "Samsung hardware", {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
{}, {},

View File

@ -167,7 +167,7 @@ static int acpi_event_genetlink_init(void)
static int __init acpi_event_init(void) static int __init acpi_event_init(void)
{ {
int error = 0; int error;
if (acpi_disabled) if (acpi_disabled)
return 0; return 0;

View File

@ -84,13 +84,13 @@ struct nvs_page {
static LIST_HEAD(nvs_list); static LIST_HEAD(nvs_list);
/** /**
* suspend_nvs_register - register platform NVS memory region to save * suspend_nvs_register - register platform NVS memory region to save
* @start - physical address of the region * @start: Physical address of the region.
* @size - size of the region * @size: Size of the region.
* *
* The NVS region need not be page-aligned (both ends) and we arrange * 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 * things so that the data from page-aligned addresses in this region will
* be copied into separate RAM pages. * be copied into separate RAM pages.
*/ */
static int suspend_nvs_register(unsigned long start, unsigned long size) 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) 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) 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) 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 * This function is going to be called with interrupts disabled, so it
* cannot iounmap the virtual addresses used to access the NVS region. * cannot iounmap the virtual addresses used to access the NVS region.
*/ */
void suspend_nvs_restore(void) void suspend_nvs_restore(void)
{ {

View File

@ -1487,12 +1487,7 @@ EXPORT_SYMBOL(acpi_check_resource_conflict);
int acpi_check_region(resource_size_t start, resource_size_t n, int acpi_check_region(resource_size_t start, resource_size_t n,
const char *name) const char *name)
{ {
struct resource res = { struct resource res = DEFINE_RES_IO_NAMED(start, n, name);
.start = start,
.end = start + n - 1,
.name = name,
.flags = IORESOURCE_IO,
};
return acpi_check_resource_conflict(&res); return acpi_check_resource_conflict(&res);
} }

View File

@ -231,7 +231,6 @@ static int smbus_alarm(void *context)
case ACPI_SBS_BATTERY: case ACPI_SBS_BATTERY:
acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_os_execute(OSL_NOTIFY_HANDLER,
acpi_smbus_callback, hc); acpi_smbus_callback, hc);
default:;
} }
mutex_unlock(&hc->lock); mutex_unlock(&hc->lock);
return 0; return 0;

View File

@ -43,4 +43,4 @@ static inline void disable_hmat(void)
{ {
} }
#endif /* CONFIG_ACPI_HMAT */ #endif /* CONFIG_ACPI_HMAT */
#endif /* __ACP_NUMA_H */ #endif /* __ACPI_NUMA_H */