diff options
Diffstat (limited to 'drivers/acpi/apei/einj.c')
-rw-r--r-- | drivers/acpi/apei/einj.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index e430cf4caec2..d4326ec12d29 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -28,9 +28,10 @@ #undef pr_fmt #define pr_fmt(fmt) "EINJ: " fmt -#define SPIN_UNIT 100 /* 100ns */ -/* Firmware should respond within 1 milliseconds */ -#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) +#define SLEEP_UNIT_MIN 1000 /* 1ms */ +#define SLEEP_UNIT_MAX 5000 /* 5ms */ +/* Firmware should respond within 1 seconds */ +#define FIRMWARE_TIMEOUT (1 * USEC_PER_SEC) #define ACPI5_VENDOR_BIT BIT(31) #define MEM_ERROR_MASK (ACPI_EINJ_MEMORY_CORRECTABLE | \ ACPI_EINJ_MEMORY_UNCORRECTABLE | \ @@ -171,13 +172,13 @@ static int einj_get_available_error_type(u32 *type) static int einj_timedout(u64 *t) { - if ((s64)*t < SPIN_UNIT) { - pr_warning(FW_WARN "Firmware does not respond in time\n"); + if ((s64)*t < SLEEP_UNIT_MIN) { + pr_warn(FW_WARN "Firmware does not respond in time\n"); return 1; } - *t -= SPIN_UNIT; - ndelay(SPIN_UNIT); - touch_nmi_watchdog(); + *t -= SLEEP_UNIT_MIN; + usleep_range(SLEEP_UNIT_MIN, SLEEP_UNIT_MAX); + return 0; } @@ -312,7 +313,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, } rc = einj_check_trigger_header(trigger_tab); if (rc) { - pr_warning(FW_BUG "Invalid trigger error action table.\n"); + pr_warn(FW_BUG "Invalid trigger error action table.\n"); goto out_rel_header; } @@ -544,9 +545,13 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, ((region_intersects(base_addr, size, IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) != REGION_INTERSECTS) && (region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY) - != REGION_INTERSECTS))) + != REGION_INTERSECTS) && + !arch_is_platform_page(base_addr))) return -EINVAL; + if (is_zero_pfn(base_addr >> PAGE_SHIFT)) + return -EADDRINUSE; + inject: mutex_lock(&einj_mutex); rc = __einj_error_inject(type, flags, param1, param2, param3, param4); @@ -673,7 +678,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; } @@ -692,7 +697,7 @@ static int __init einj_init(void) rc = einj_check_table(einj_tab); if (rc) { pr_warn(FW_BUG "Invalid EINJ table.\n"); - return -EINVAL; + goto err_put_table; } rc = -ENOMEM; @@ -725,7 +730,6 @@ static int __init einj_init(void) goto err_release; } - rc = -ENOMEM; einj_param = einj_get_parameter_address(); if ((param_extension || acpi5) && einj_param) { debugfs_create_x32("flags", S_IRUSR | S_IWUSR, einj_debug_dir, @@ -760,6 +764,8 @@ err_release: err_fini: apei_resources_fini(&einj_resources); debugfs_remove_recursive(einj_debug_dir); +err_put_table: + acpi_put_table((struct acpi_table_header *)einj_tab); return rc; } @@ -780,6 +786,7 @@ static void __exit einj_exit(void) apei_resources_release(&einj_resources); apei_resources_fini(&einj_resources); debugfs_remove_recursive(einj_debug_dir); + acpi_put_table((struct acpi_table_header *)einj_tab); } module_init(einj_init); |