Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Jeshua Smith <jeshuas@nvidia.com>
Reviewed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Jeshua Smith and committed by
Rafael J. Wysocki
fac475aa e2abc47a

+37 -4
+37 -4
drivers/acpi/apei/erst.c
··· 59 59 #define ERST_RANGE_NVRAM 0x0002 60 60 #define ERST_RANGE_SLOW 0x0004 61 61 62 + /* ERST Exec max timings */ 63 + #define ERST_EXEC_TIMING_MAX_MASK 0xFFFFFFFF00000000 64 + #define ERST_EXEC_TIMING_MAX_SHIFT 32 65 + 62 66 /* 63 67 * ERST Error Log Address Range, used as buffer for reading/writing 64 68 * error records. ··· 72 68 u64 size; 73 69 void __iomem *vaddr; 74 70 u32 attr; 71 + u64 timings; 75 72 } erst_erange; 76 73 77 74 /* ··· 100 95 default: 101 96 return -EINVAL; 102 97 } 98 + } 99 + 100 + static inline u64 erst_get_timeout(void) 101 + { 102 + u64 timeout = FIRMWARE_TIMEOUT; 103 + 104 + if (erst_erange.attr & ERST_RANGE_SLOW) { 105 + timeout = ((erst_erange.timings & ERST_EXEC_TIMING_MAX_MASK) >> 106 + ERST_EXEC_TIMING_MAX_SHIFT) * NSEC_PER_MSEC; 107 + if (timeout < FIRMWARE_TIMEOUT) 108 + timeout = FIRMWARE_TIMEOUT; 109 + } 110 + return timeout; 103 111 } 104 112 105 113 static int erst_timedout(u64 *t, u64 spin_unit) ··· 209 191 { 210 192 int rc; 211 193 u64 val; 212 - u64 timeout = FIRMWARE_TIMEOUT; 194 + u64 timeout; 213 195 u64 stall_time; 196 + 197 + timeout = erst_get_timeout(); 214 198 215 199 if (ctx->var1 > FIRMWARE_MAX_STALL) { 216 200 if (!in_nmi()) ··· 409 389 if (rc) 410 390 return rc; 411 391 range->attr = apei_exec_ctx_get_output(&ctx); 392 + rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_TIMINGS); 393 + if (rc == 0) 394 + range->timings = apei_exec_ctx_get_output(&ctx); 395 + else if (rc == -ENOENT) 396 + range->timings = 0; 397 + else 398 + return rc; 412 399 413 400 return 0; 414 401 } ··· 648 621 static int __erst_write_to_storage(u64 offset) 649 622 { 650 623 struct apei_exec_context ctx; 651 - u64 timeout = FIRMWARE_TIMEOUT; 624 + u64 timeout; 652 625 u64 val; 653 626 int rc; 627 + 628 + timeout = erst_get_timeout(); 654 629 655 630 erst_exec_ctx_init(&ctx); 656 631 rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_WRITE); ··· 689 660 static int __erst_read_from_storage(u64 record_id, u64 offset) 690 661 { 691 662 struct apei_exec_context ctx; 692 - u64 timeout = FIRMWARE_TIMEOUT; 663 + u64 timeout; 693 664 u64 val; 694 665 int rc; 666 + 667 + timeout = erst_get_timeout(); 695 668 696 669 erst_exec_ctx_init(&ctx); 697 670 rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_READ); ··· 734 703 static int __erst_clear_from_storage(u64 record_id) 735 704 { 736 705 struct apei_exec_context ctx; 737 - u64 timeout = FIRMWARE_TIMEOUT; 706 + u64 timeout; 738 707 u64 val; 739 708 int rc; 709 + 710 + timeout = erst_get_timeout(); 740 711 741 712 erst_exec_ctx_init(&ctx); 742 713 rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_CLEAR);