Skip to content

Commit

Permalink
Merge tag 'please-pull-einj' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/ras/ras into x86/ras

Pull error injection update from Tony Luck:

 * Add more flexibility to the error injection (EINJ) debugfs interface

Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Dec 18, 2013
2 parents 0149522 + 3482fb5 commit cc131ee
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 6 deletions.
19 changes: 18 additions & 1 deletion Documentation/acpi/apei/einj.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,22 @@ directory apei/einj. The following files are provided.
injection. Before this, please specify all necessary error
parameters.

- flags
Present for kernel version 3.13 and above. Used to specify which
of param{1..4} are valid and should be used by BIOS during injection.
Value is a bitmask as specified in ACPI5.0 spec for the
SET_ERROR_TYPE_WITH_ADDRESS data structure:
Bit 0 - Processor APIC field valid (see param3 below)
Bit 1 - Memory address and mask valid (param1 and param2)
Bit 2 - PCIe (seg,bus,dev,fn) valid (param4 below)
If set to zero, legacy behaviour is used where the type of injection
specifies just one bit set, and param1 is multiplexed.

- param1
This file is used to set the first error parameter value. Effect of
parameter depends on error_type specified. For example, if error
type is memory related type, the param1 should be a valid physical
memory address.
memory address. [Unless "flag" is set - see above]

- param2
This file is used to set the second error parameter value. Effect of
Expand All @@ -58,6 +69,12 @@ directory apei/einj. The following files are provided.
address mask. Linux requires page or narrower granularity, say,
0xfffffffffffff000.

- param3
Used when the 0x1 bit is set in "flag" to specify the APIC id

- param4
Used when the 0x4 bit is set in "flag" to specify target PCIe device

- notrigger
The EINJ mechanism is a two step process. First inject the error, then
perform some actions to trigger it. Setting "notrigger" to 1 skips the
Expand Down
39 changes: 34 additions & 5 deletions drivers/acpi/apei/einj.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,8 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
return rc;
}

static int __einj_error_inject(u32 type, u64 param1, u64 param2)
static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
u64 param3, u64 param4)
{
struct apei_exec_context ctx;
u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT;
Expand Down Expand Up @@ -446,6 +447,12 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
break;
}
v5param->flags = vendor_flags;
} else if (flags) {
v5param->flags = flags;
v5param->memory_address = param1;
v5param->memory_address_range = param2;
v5param->apicid = param3;
v5param->pcie_sbdf = param4;
} else {
switch (type) {
case ACPI_EINJ_PROCESSOR_CORRECTABLE:
Expand Down Expand Up @@ -514,11 +521,17 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
}

/* Inject the specified hardware error */
static int einj_error_inject(u32 type, u64 param1, u64 param2)
static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
u64 param3, u64 param4)
{
int rc;
unsigned long pfn;

/* If user manually set "flags", make sure it is legal */
if (flags && (flags &
~(SETWA_FLAGS_APICID|SETWA_FLAGS_MEM|SETWA_FLAGS_PCIE_SBDF)))
return -EINVAL;

/*
* We need extra sanity checks for memory errors.
* Other types leap directly to injection.
Expand All @@ -532,7 +545,7 @@ static int einj_error_inject(u32 type, u64 param1, u64 param2)
if (type & ACPI5_VENDOR_BIT) {
if (vendor_flags != SETWA_FLAGS_MEM)
goto inject;
} else if (!(type & MEM_ERROR_MASK))
} else if (!(type & MEM_ERROR_MASK) && !(flags & SETWA_FLAGS_MEM))
goto inject;

/*
Expand All @@ -546,15 +559,18 @@ static int einj_error_inject(u32 type, u64 param1, u64 param2)

inject:
mutex_lock(&einj_mutex);
rc = __einj_error_inject(type, param1, param2);
rc = __einj_error_inject(type, flags, param1, param2, param3, param4);
mutex_unlock(&einj_mutex);

return rc;
}

static u32 error_type;
static u32 error_flags;
static u64 error_param1;
static u64 error_param2;
static u64 error_param3;
static u64 error_param4;
static struct dentry *einj_debug_dir;

static int available_error_type_show(struct seq_file *m, void *v)
Expand Down Expand Up @@ -648,7 +664,8 @@ static int error_inject_set(void *data, u64 val)
if (!error_type)
return -EINVAL;

return einj_error_inject(error_type, error_param1, error_param2);
return einj_error_inject(error_type, error_flags, error_param1, error_param2,
error_param3, error_param4);
}

DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL,
Expand Down Expand Up @@ -729,6 +746,10 @@ static int __init einj_init(void)
rc = -ENOMEM;
einj_param = einj_get_parameter_address();
if ((param_extension || acpi5) && einj_param) {
fentry = debugfs_create_x32("flags", S_IRUSR | S_IWUSR,
einj_debug_dir, &error_flags);
if (!fentry)
goto err_unmap;
fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
einj_debug_dir, &error_param1);
if (!fentry)
Expand All @@ -737,6 +758,14 @@ static int __init einj_init(void)
einj_debug_dir, &error_param2);
if (!fentry)
goto err_unmap;
fentry = debugfs_create_x64("param3", S_IRUSR | S_IWUSR,
einj_debug_dir, &error_param3);
if (!fentry)
goto err_unmap;
fentry = debugfs_create_x64("param4", S_IRUSR | S_IWUSR,
einj_debug_dir, &error_param4);
if (!fentry)
goto err_unmap;

fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
einj_debug_dir, &notrigger);
Expand Down

0 comments on commit cc131ee

Please sign in to comment.