|
@@ -194,6 +194,26 @@ static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static struct acpi_generic_address *einj_get_trigger_parameter_region(
|
|
|
+ struct acpi_einj_trigger *trigger_tab, u64 param1, u64 param2)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ struct acpi_whea_header *entry;
|
|
|
+
|
|
|
+ entry = (struct acpi_whea_header *)
|
|
|
+ ((char *)trigger_tab + sizeof(struct acpi_einj_trigger));
|
|
|
+ for (i = 0; i < trigger_tab->entry_count; i++) {
|
|
|
+ if (entry->action == ACPI_EINJ_TRIGGER_ERROR &&
|
|
|
+ entry->instruction == ACPI_EINJ_WRITE_REGISTER_VALUE &&
|
|
|
+ entry->register_region.space_id ==
|
|
|
+ ACPI_ADR_SPACE_SYSTEM_MEMORY &&
|
|
|
+ (entry->register_region.address & param2) == (param1 & param2))
|
|
|
+ return &entry->register_region;
|
|
|
+ entry++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
/* Execute instructions in trigger error action table */
|
|
|
static int __einj_error_trigger(u64 trigger_paddr, u32 type,
|
|
|
u64 param1, u64 param2)
|
|
@@ -205,6 +225,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
|
|
|
struct resource *r;
|
|
|
u32 table_size;
|
|
|
int rc = -EIO;
|
|
|
+ struct acpi_generic_address *trigger_param_region = NULL;
|
|
|
|
|
|
r = request_mem_region(trigger_paddr, sizeof(*trigger_tab),
|
|
|
"APEI EINJ Trigger Table");
|
|
@@ -266,12 +287,17 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
|
|
|
if (param_extension && (type & 0x0038) && param2) {
|
|
|
struct apei_resources addr_resources;
|
|
|
apei_resources_init(&addr_resources);
|
|
|
- rc = apei_resources_add(&addr_resources,
|
|
|
- param1 & param2,
|
|
|
- ~param2 + 1, true);
|
|
|
- if (rc)
|
|
|
- goto out_fini;
|
|
|
- rc = apei_resources_sub(&trigger_resources, &addr_resources);
|
|
|
+ trigger_param_region = einj_get_trigger_parameter_region(
|
|
|
+ trigger_tab, param1, param2);
|
|
|
+ if (trigger_param_region) {
|
|
|
+ rc = apei_resources_add(&addr_resources,
|
|
|
+ trigger_param_region->address,
|
|
|
+ trigger_param_region->bit_width/8, true);
|
|
|
+ if (rc)
|
|
|
+ goto out_fini;
|
|
|
+ rc = apei_resources_sub(&trigger_resources,
|
|
|
+ &addr_resources);
|
|
|
+ }
|
|
|
apei_resources_fini(&addr_resources);
|
|
|
if (rc)
|
|
|
goto out_fini;
|