|
@@ -195,7 +195,8 @@ static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
|
|
}
|
|
}
|
|
|
|
|
|
/* Execute instructions in trigger error action table */
|
|
/* Execute instructions in trigger error action table */
|
|
-static int __einj_error_trigger(u64 trigger_paddr)
|
|
|
|
|
|
+static int __einj_error_trigger(u64 trigger_paddr, u32 type,
|
|
|
|
+ u64 param1, u64 param2)
|
|
{
|
|
{
|
|
struct acpi_einj_trigger *trigger_tab = NULL;
|
|
struct acpi_einj_trigger *trigger_tab = NULL;
|
|
struct apei_exec_context trigger_ctx;
|
|
struct apei_exec_context trigger_ctx;
|
|
@@ -256,6 +257,25 @@ static int __einj_error_trigger(u64 trigger_paddr)
|
|
rc = apei_resources_sub(&trigger_resources, &einj_resources);
|
|
rc = apei_resources_sub(&trigger_resources, &einj_resources);
|
|
if (rc)
|
|
if (rc)
|
|
goto out_fini;
|
|
goto out_fini;
|
|
|
|
+ /*
|
|
|
|
+ * Some firmware will access target address specified in
|
|
|
|
+ * param1 to trigger the error when injecting memory error.
|
|
|
|
+ * This will cause resource conflict with regular memory. So
|
|
|
|
+ * remove it from trigger table resources.
|
|
|
|
+ */
|
|
|
|
+ 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);
|
|
|
|
+ apei_resources_fini(&addr_resources);
|
|
|
|
+ if (rc)
|
|
|
|
+ goto out_fini;
|
|
|
|
+ }
|
|
rc = apei_resources_request(&trigger_resources, "APEI EINJ Trigger");
|
|
rc = apei_resources_request(&trigger_resources, "APEI EINJ Trigger");
|
|
if (rc)
|
|
if (rc)
|
|
goto out_fini;
|
|
goto out_fini;
|
|
@@ -325,7 +345,7 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
trigger_paddr = apei_exec_ctx_get_output(&ctx);
|
|
trigger_paddr = apei_exec_ctx_get_output(&ctx);
|
|
- rc = __einj_error_trigger(trigger_paddr);
|
|
|
|
|
|
+ rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
|
|
rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
|