Commit fac475aa authored by Jeshua Smith's avatar Jeshua Smith Committed by Rafael J. Wysocki

ACPI: APEI: Use ERST timeout for slow devices

Slow devices such as flash may not meet the default 1ms timeout value,
so use the ERST max execution time value that they provide as the
timeout if it is larger.
Signed-off-by: default avatarJeshua Smith <jeshuas@nvidia.com>
Reviewed-by: default avatarTony Luck <tony.luck@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent e2abc47a
...@@ -59,6 +59,10 @@ static struct acpi_table_erst *erst_tab; ...@@ -59,6 +59,10 @@ static struct acpi_table_erst *erst_tab;
#define ERST_RANGE_NVRAM 0x0002 #define ERST_RANGE_NVRAM 0x0002
#define ERST_RANGE_SLOW 0x0004 #define ERST_RANGE_SLOW 0x0004
/* ERST Exec max timings */
#define ERST_EXEC_TIMING_MAX_MASK 0xFFFFFFFF00000000
#define ERST_EXEC_TIMING_MAX_SHIFT 32
/* /*
* ERST Error Log Address Range, used as buffer for reading/writing * ERST Error Log Address Range, used as buffer for reading/writing
* error records. * error records.
...@@ -68,6 +72,7 @@ static struct erst_erange { ...@@ -68,6 +72,7 @@ static struct erst_erange {
u64 size; u64 size;
void __iomem *vaddr; void __iomem *vaddr;
u32 attr; u32 attr;
u64 timings;
} erst_erange; } erst_erange;
/* /*
...@@ -97,6 +102,19 @@ static inline int erst_errno(int command_status) ...@@ -97,6 +102,19 @@ static inline int erst_errno(int command_status)
} }
} }
static inline u64 erst_get_timeout(void)
{
u64 timeout = FIRMWARE_TIMEOUT;
if (erst_erange.attr & ERST_RANGE_SLOW) {
timeout = ((erst_erange.timings & ERST_EXEC_TIMING_MAX_MASK) >>
ERST_EXEC_TIMING_MAX_SHIFT) * NSEC_PER_MSEC;
if (timeout < FIRMWARE_TIMEOUT)
timeout = FIRMWARE_TIMEOUT;
}
return timeout;
}
static int erst_timedout(u64 *t, u64 spin_unit) static int erst_timedout(u64 *t, u64 spin_unit)
{ {
if ((s64)*t < spin_unit) { if ((s64)*t < spin_unit) {
...@@ -191,9 +209,11 @@ static int erst_exec_stall_while_true(struct apei_exec_context *ctx, ...@@ -191,9 +209,11 @@ static int erst_exec_stall_while_true(struct apei_exec_context *ctx,
{ {
int rc; int rc;
u64 val; u64 val;
u64 timeout = FIRMWARE_TIMEOUT; u64 timeout;
u64 stall_time; u64 stall_time;
timeout = erst_get_timeout();
if (ctx->var1 > FIRMWARE_MAX_STALL) { if (ctx->var1 > FIRMWARE_MAX_STALL) {
if (!in_nmi()) if (!in_nmi())
pr_warn(FW_WARN pr_warn(FW_WARN
...@@ -389,6 +409,13 @@ static int erst_get_erange(struct erst_erange *range) ...@@ -389,6 +409,13 @@ static int erst_get_erange(struct erst_erange *range)
if (rc) if (rc)
return rc; return rc;
range->attr = apei_exec_ctx_get_output(&ctx); range->attr = apei_exec_ctx_get_output(&ctx);
rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_TIMINGS);
if (rc == 0)
range->timings = apei_exec_ctx_get_output(&ctx);
else if (rc == -ENOENT)
range->timings = 0;
else
return rc;
return 0; return 0;
} }
...@@ -621,10 +648,12 @@ EXPORT_SYMBOL_GPL(erst_get_record_id_end); ...@@ -621,10 +648,12 @@ EXPORT_SYMBOL_GPL(erst_get_record_id_end);
static int __erst_write_to_storage(u64 offset) static int __erst_write_to_storage(u64 offset)
{ {
struct apei_exec_context ctx; struct apei_exec_context ctx;
u64 timeout = FIRMWARE_TIMEOUT; u64 timeout;
u64 val; u64 val;
int rc; int rc;
timeout = erst_get_timeout();
erst_exec_ctx_init(&ctx); erst_exec_ctx_init(&ctx);
rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_WRITE); rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_WRITE);
if (rc) if (rc)
...@@ -660,10 +689,12 @@ static int __erst_write_to_storage(u64 offset) ...@@ -660,10 +689,12 @@ static int __erst_write_to_storage(u64 offset)
static int __erst_read_from_storage(u64 record_id, u64 offset) static int __erst_read_from_storage(u64 record_id, u64 offset)
{ {
struct apei_exec_context ctx; struct apei_exec_context ctx;
u64 timeout = FIRMWARE_TIMEOUT; u64 timeout;
u64 val; u64 val;
int rc; int rc;
timeout = erst_get_timeout();
erst_exec_ctx_init(&ctx); erst_exec_ctx_init(&ctx);
rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_READ); rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_READ);
if (rc) if (rc)
...@@ -703,10 +734,12 @@ static int __erst_read_from_storage(u64 record_id, u64 offset) ...@@ -703,10 +734,12 @@ static int __erst_read_from_storage(u64 record_id, u64 offset)
static int __erst_clear_from_storage(u64 record_id) static int __erst_clear_from_storage(u64 record_id)
{ {
struct apei_exec_context ctx; struct apei_exec_context ctx;
u64 timeout = FIRMWARE_TIMEOUT; u64 timeout;
u64 val; u64 val;
int rc; int rc;
timeout = erst_get_timeout();
erst_exec_ctx_init(&ctx); erst_exec_ctx_init(&ctx);
rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_CLEAR); rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_CLEAR);
if (rc) if (rc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment