aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/acpi/apei/einj.txt19
-rw-r--r--drivers/acpi/apei/einj.c39
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
419static int __einj_error_inject(u32 type, u64 param1, u64 param2) 419static 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 */
517static int einj_error_inject(u32 type, u64 param1, u64 param2) 524static 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
547inject: 560inject:
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
555static u32 error_type; 568static u32 error_type;
569static u32 error_flags;
556static u64 error_param1; 570static u64 error_param1;
557static u64 error_param2; 571static u64 error_param2;
572static u64 error_param3;
573static u64 error_param4;
558static struct dentry *einj_debug_dir; 574static struct dentry *einj_debug_dir;
559 575
560static int available_error_type_show(struct seq_file *m, void *v) 576static 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
654DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, 671DEFINE_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, &notrigger); 771 einj_debug_dir, &notrigger);