AMD General Reviewed-by: Hawking Zhang <[email protected]>
Regards, Hawking -----Original Message----- From: amd-gfx <[email protected]> On Behalf Of Stanley.Yang Sent: Wednesday, July 8, 2026 8:04 PM To: [email protected] Cc: Zhang, Hawking <[email protected]>; Russell, Kent <[email protected]>; Yang, Stanley <[email protected]> Subject: [PATCH V3 1/1] drm/amdgpu/ras: only check bad page for address-based UMC injection UMC error injection on MI300 series is dispatched by the RAS TA using the injection method; only the "coherent" methods are address based, the single-shot/persistent/ac-parity ones ignore the address. The debugfs control path validated the injection address against the bad page list for every UMC injection. On uniras (SMU v13+) devices the address is now validated by the ras_mgr inject handler, so the legacy debugfs bad page check only runs on the legacy RAS path; other ASICs keep injecting by address. In the ras_mgr handler an injection is treated as non address-based only when userspace passes the U64_MAX sentinel address and the method is a non-address method. In that case the address is cleared to 0 and the bad page / range validation is skipped; otherwise the injection address is validated as before. Changed from V1: move address based checking to uniras layer Changed from V2: Check umc injection address setting flag, simplify non address based injection judgment Signed-off-by: Stanley.Yang <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 10 ++- .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c | 83 +++++++++++++++---- 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index af48dd2ebd16..f280a312b0a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -606,8 +606,14 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, ret = amdgpu_ras_feature_enable(adev, &data.head, 1); break; case 2: - /* umc ce/ue error injection for a bad page is not allowed */ - if (data.head.block == AMDGPU_RAS_BLOCK__UMC) + /* + * UMC ce/ue error injection for a bad page is not allowed. For + * uniras (SMU v13+) devices the injection address is validated by + * the ras_mgr inject handler, so only run the legacy bad page + * check for the legacy RAS path. + */ + if (data.head.block == AMDGPU_RAS_BLOCK__UMC && + !amdgpu_uniras_enabled(adev)) ret = amdgpu_ras_check_bad_page(adev, data.inject.address); if (ret == -EINVAL) { dev_warn(adev->dev, "RAS WARN: input address 0x%llx is invalid.", diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c index bfbfdffbfbe6..c2285fde8b3c 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c @@ -82,6 +82,43 @@ static uint64_t local_addr_to_xgmi_global_addr(struct ras_core_context *ras_core return (addr + xgmi->physical_node_id * xgmi->node_segment_size); } +/* + * UMC error injection is dispatched by the RAS TA using the injection +method + * carried in struct ras_cmd_inject_error_req. Only the "coherent" +methods + * program an explicit injection address and are therefore +address-based; the + * single-shot, persistent and ac-parity methods ignore the address. + * + * Keep these values in sync with the RAS TA. + */ +enum umc_inject_method { + UMC_METHOD_COHERENT = 0, + UMC_METHOD_SINGLE_SHOT = 1, + UMC_METHOD_PERSISTENT = 2, + UMC_METHOD_PERSISTENT_DISABLE = 3, + UMC_METHOD_COHERENT_NO_DETECTION = 4, + UMC_METHOD_COHERENT_WR = 5, + UMC_METHOD_SINGLE_SHOT_WR = 6, + UMC_METHOD_PERSISTENT_WR = 7, + UMC_METHOD_SINGLE_SHOT_CLEAN = 8, +}; + +/* + * Return true when @method does not program an explicit injection address. + * Only the coherent methods are address-based; every other method +ignores the + * address, so userspace signals them by setting the address to U64_MAX. + */ +static bool amdgpu_ras_mgr_is_non_address_injection(u64 method) { + switch (method) { + case UMC_METHOD_COHERENT: + case UMC_METHOD_COHERENT_NO_DETECTION: + case UMC_METHOD_COHERENT_WR: + return false; + default: + return true; + } +} + static int amdgpu_ras_inject_error(struct ras_core_context *ras_core, struct ras_cmd_ctx *cmd, void *data) { @@ -91,25 +128,35 @@ static int amdgpu_ras_inject_error(struct ras_core_context *ras_core, int ret = RAS_CMD__ERROR_GENERIC; if (req->block_id == RAS_BLOCK_ID__UMC) { - if (amdgpu_ras_mgr_check_retired_addr(adev, req->address)) { - RAS_DEV_WARN(ras_core->dev, - "RAS WARN: inject: 0x%llx has already been marked as bad!\n", - req->address); - return RAS_CMD__ERROR_ACCESS_DENIED; - } - - if ((req->address >= adev->gmc.mc_vram_size && - adev->gmc.mc_vram_size) || - (req->address >= RAS_UMC_INJECT_ADDR_LIMIT)) { - RAS_DEV_WARN(adev, "RAS WARN: input address 0x%llx is invalid.", + /* + * Only address-based UMC injections carry an explicit injection + * address that has to be validated. A non address-based method + * ignores the address, and userspace flags such an injection by + * setting the address to U64_MAX. When both the sentinel and the + * method agree, clear the address so the RAS TA ignores it and + * skip the validation; otherwise validate the injection address. + */ + if (req->address == U64_MAX && amdgpu_ras_mgr_is_non_address_injection(req->method)) { + req->address = 0x0; + } else { + if (amdgpu_ras_mgr_check_retired_addr(adev, req->address)) { + RAS_DEV_WARN(ras_core->dev, + "RAS WARN: inject: 0x%llx has already been marked as bad!\n", req->address); - return RAS_CMD__ERROR_INVALID_INPUT_DATA; - } - - /* Calculate XGMI relative offset */ - if (adev->gmc.xgmi.num_physical_nodes > 1 && - req->block_id != RAS_BLOCK_ID__GFX) { - req->address = local_addr_to_xgmi_global_addr(ras_core, req->address); + return RAS_CMD__ERROR_ACCESS_DENIED; + } + + if ((req->address >= adev->gmc.mc_vram_size && + adev->gmc.mc_vram_size) || + (req->address >= RAS_UMC_INJECT_ADDR_LIMIT)) { + RAS_DEV_WARN(adev, "RAS WARN: input address 0x%llx is invalid.", + req->address); + return RAS_CMD__ERROR_INVALID_INPUT_DATA; + } + + /* Calculate XGMI relative offset */ + if (adev->gmc.xgmi.num_physical_nodes > 1) + req->address = local_addr_to_xgmi_global_addr(ras_core, +req->address); } } -- 2.43.0
