diff options
-rw-r--r-- | Documentation/acpi/apei/einj.txt | 19 | ||||
-rw-r--r-- | drivers/acpi/apei/einj.c | 39 |
2 files changed, 52 insertions, 6 deletions
diff --git a/Documentation/acpi/apei/einj.txt b/Documentation/acpi/apei/einj.txt index a58b63da1a36..f51861bcb07b 100644 --- a/Documentation/acpi/apei/einj.txt +++ b/Documentation/acpi/apei/einj.txt | |||
@@ -45,11 +45,22 @@ directory apei/einj. The following files are provided. | |||
45 | injection. Before this, please specify all necessary error | 45 | injection. Before this, please specify all necessary error |
46 | parameters. | 46 | parameters. |
47 | 47 | ||
48 | - flags | ||
49 | Present for kernel version 3.13 and above. Used to specify which | ||
50 | of param{1..4} are valid and should be used by BIOS during injection. | ||
51 | Value is a bitmask as specified in ACPI5.0 spec for the | ||
52 | SET_ERROR_TYPE_WITH_ADDRESS data structure: | ||
53 | Bit 0 - Processor APIC field valid (see param3 below) | ||
54 | Bit 1 - Memory address and mask valid (param1 and param2) | ||
55 | Bit 2 - PCIe (seg,bus,dev,fn) valid (param4 below) | ||
56 | If set to zero, legacy behaviour is used where the type of injection | ||
57 | specifies just one bit set, and param1 is multiplexed. | ||
58 | |||
48 | - param1 | 59 | - param1 |
49 | This file is used to set the first error parameter value. Effect of | 60 | This file is used to set the first error parameter value. Effect of |
50 | parameter depends on error_type specified. For example, if error | 61 | parameter depends on error_type specified. For example, if error |
51 | type is memory related type, the param1 should be a valid physical | 62 | type is memory related type, the param1 should be a valid physical |
52 | memory address. | 63 | memory address. [Unless "flag" is set - see above] |
53 | 64 | ||
54 | - param2 | 65 | - param2 |
55 | This file is used to set the second error parameter value. Effect of | 66 | This file is used to set the second error parameter value. Effect of |
@@ -58,6 +69,12 @@ directory apei/einj. The following files are provided. | |||
58 | address mask. Linux requires page or narrower granularity, say, | 69 | address mask. Linux requires page or narrower granularity, say, |
59 | 0xfffffffffffff000. | 70 | 0xfffffffffffff000. |
60 | 71 | ||
72 | - param3 | ||
73 | Used when the 0x1 bit is set in "flag" to specify the APIC id | ||
74 | |||
75 | - param4 | ||
76 | Used when the 0x4 bit is set in "flag" to specify target PCIe device | ||
77 | |||
61 | - notrigger | 78 | - notrigger |
62 | The EINJ mechanism is a two step process. First inject the error, then | 79 | The EINJ mechanism is a two step process. First inject the error, then |
63 | perform some actions to trigger it. Setting "notrigger" to 1 skips the | 80 | perform some actions to trigger it. Setting "notrigger" to 1 skips the |
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index fb57d03e698b..c76674e2a01f 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -416,7 +416,8 @@ out: | |||
416 | return rc; | 416 | return rc; |
417 | } | 417 | } |
418 | 418 | ||
419 | static int __einj_error_inject(u32 type, u64 param1, u64 param2) | 419 | static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, |
420 | u64 param3, u64 param4) | ||
420 | { | 421 | { |
421 | struct apei_exec_context ctx; | 422 | struct apei_exec_context ctx; |
422 | u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT; | 423 | u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT; |
@@ -446,6 +447,12 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) | |||
446 | break; | 447 | break; |
447 | } | 448 | } |
448 | v5param->flags = vendor_flags; | 449 | v5param->flags = vendor_flags; |
450 | } else if (flags) { | ||
451 | v5param->flags = flags; | ||
452 | v5param->memory_address = param1; | ||
453 | v5param->memory_address_range = param2; | ||
454 | v5param->apicid = param3; | ||
455 | v5param->pcie_sbdf = param4; | ||
449 | } else { | 456 | } else { |
450 | switch (type) { | 457 | switch (type) { |
451 | case ACPI_EINJ_PROCESSOR_CORRECTABLE: | 458 | case ACPI_EINJ_PROCESSOR_CORRECTABLE: |
@@ -514,11 +521,17 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) | |||
514 | } | 521 | } |
515 | 522 | ||
516 | /* Inject the specified hardware error */ | 523 | /* Inject the specified hardware error */ |
517 | static int einj_error_inject(u32 type, u64 param1, u64 param2) | 524 | static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, |
525 | u64 param3, u64 param4) | ||
518 | { | 526 | { |
519 | int rc; | 527 | int rc; |
520 | unsigned long pfn; | 528 | unsigned long pfn; |
521 | 529 | ||
530 | /* If user manually set "flags", make sure it is legal */ | ||
531 | if (flags && (flags & | ||
532 | ~(SETWA_FLAGS_APICID|SETWA_FLAGS_MEM|SETWA_FLAGS_PCIE_SBDF))) | ||
533 | return -EINVAL; | ||
534 | |||
522 | /* | 535 | /* |
523 | * We need extra sanity checks for memory errors. | 536 | * We need extra sanity checks for memory errors. |
524 | * Other types leap directly to injection. | 537 | * Other types leap directly to injection. |
@@ -532,7 +545,7 @@ static int einj_error_inject(u32 type, u64 param1, u64 param2) | |||
532 | if (type & ACPI5_VENDOR_BIT) { | 545 | if (type & ACPI5_VENDOR_BIT) { |
533 | if (vendor_flags != SETWA_FLAGS_MEM) | 546 | if (vendor_flags != SETWA_FLAGS_MEM) |
534 | goto inject; | 547 | goto inject; |
535 | } else if (!(type & MEM_ERROR_MASK)) | 548 | } else if (!(type & MEM_ERROR_MASK) && !(flags & SETWA_FLAGS_MEM)) |
536 | goto inject; | 549 | goto inject; |
537 | 550 | ||
538 | /* | 551 | /* |
@@ -546,15 +559,18 @@ static int einj_error_inject(u32 type, u64 param1, u64 param2) | |||
546 | 559 | ||
547 | inject: | 560 | inject: |
548 | mutex_lock(&einj_mutex); | 561 | mutex_lock(&einj_mutex); |
549 | rc = __einj_error_inject(type, param1, param2); | 562 | rc = __einj_error_inject(type, flags, param1, param2, param3, param4); |
550 | mutex_unlock(&einj_mutex); | 563 | mutex_unlock(&einj_mutex); |
551 | 564 | ||
552 | return rc; | 565 | return rc; |
553 | } | 566 | } |
554 | 567 | ||
555 | static u32 error_type; | 568 | static u32 error_type; |
569 | static u32 error_flags; | ||
556 | static u64 error_param1; | 570 | static u64 error_param1; |
557 | static u64 error_param2; | 571 | static u64 error_param2; |
572 | static u64 error_param3; | ||
573 | static u64 error_param4; | ||
558 | static struct dentry *einj_debug_dir; | 574 | static struct dentry *einj_debug_dir; |
559 | 575 | ||
560 | static int available_error_type_show(struct seq_file *m, void *v) | 576 | static int available_error_type_show(struct seq_file *m, void *v) |
@@ -648,7 +664,8 @@ static int error_inject_set(void *data, u64 val) | |||
648 | if (!error_type) | 664 | if (!error_type) |
649 | return -EINVAL; | 665 | return -EINVAL; |
650 | 666 | ||
651 | return einj_error_inject(error_type, error_param1, error_param2); | 667 | return einj_error_inject(error_type, error_flags, error_param1, error_param2, |
668 | error_param3, error_param4); | ||
652 | } | 669 | } |
653 | 670 | ||
654 | DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, | 671 | DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, |
@@ -729,6 +746,10 @@ static int __init einj_init(void) | |||
729 | rc = -ENOMEM; | 746 | rc = -ENOMEM; |
730 | einj_param = einj_get_parameter_address(); | 747 | einj_param = einj_get_parameter_address(); |
731 | if ((param_extension || acpi5) && einj_param) { | 748 | if ((param_extension || acpi5) && einj_param) { |
749 | fentry = debugfs_create_x32("flags", S_IRUSR | S_IWUSR, | ||
750 | einj_debug_dir, &error_flags); | ||
751 | if (!fentry) | ||
752 | goto err_unmap; | ||
732 | fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR, | 753 | fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR, |
733 | einj_debug_dir, &error_param1); | 754 | einj_debug_dir, &error_param1); |
734 | if (!fentry) | 755 | if (!fentry) |
@@ -737,6 +758,14 @@ static int __init einj_init(void) | |||
737 | einj_debug_dir, &error_param2); | 758 | einj_debug_dir, &error_param2); |
738 | if (!fentry) | 759 | if (!fentry) |
739 | goto err_unmap; | 760 | goto err_unmap; |
761 | fentry = debugfs_create_x64("param3", S_IRUSR | S_IWUSR, | ||
762 | einj_debug_dir, &error_param3); | ||
763 | if (!fentry) | ||
764 | goto err_unmap; | ||
765 | fentry = debugfs_create_x64("param4", S_IRUSR | S_IWUSR, | ||
766 | einj_debug_dir, &error_param4); | ||
767 | if (!fentry) | ||
768 | goto err_unmap; | ||
740 | 769 | ||
741 | fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR, | 770 | fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR, |
742 | einj_debug_dir, ¬rigger); | 771 | einj_debug_dir, ¬rigger); |