AMD General Should we add a new API in amdgpu ras_mgr layer for this check? I think we should stop adding RAS functionality for SMU v13 and later products in the legacy ras layer.
Regards, Hawking -----Original Message----- From: amd-gfx <[email protected]> On Behalf Of Stanley.Yang Sent: Wednesday, July 1, 2026 8:08 PM To: [email protected] Cc: Yang, Stanley <[email protected]> Subject: [PATCH 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 via the (sub-block, method) pair; 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. Restrict that check to address-based injections and warn when a non address-based one is given a non-zero address. Other ASICs keep injecting by address. Signed-off-by: Stanley.Yang <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 94 ++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 + .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c | 3 +- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index af48dd2ebd16..c563e2d96809 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -485,6 +485,91 @@ static void amdgpu_ras_instance_mask_check(struct amdgpu_device *adev, inst_mask, data->inject.instance_mask); } +/* + * UMC error injection on MI300-class ASICs is dispatched by the RAS TA +using + * the (sub-block, method) pair passed in struct +ta_ras_trigger_error_input as + * sub_block_index (enum error_sub_block_umc) and value (enum inject_method_umc). + * Only the "coherent" methods program an explicit injection address. + * + * Keep the values below in sync with the RAS TA. + */ +enum umc_error_sub_block { + UMC_ERROR_CRC = 0, + UMC_ERROR_SRAM = 1, + UMC_ERROR_ODECC = 2, + UMC_ERROR_PARITY_DATA = 3, + UMC_ERROR_PARITY_CMD = 4, +}; + +enum umc_inject_method { + UMC_METH_COHERENT = 0, + UMC_METH_SINGLE_SHOT = 1, + UMC_METH_PERSISTENT = 2, + UMC_METH_PERSISTENT_DISABLE = 3, + UMC_METH_COHERENT_NO_DETECTION = 4, + UMC_METH_COHERENT_WR = 5, + UMC_METH_SINGLE_SHOT_WR = 6, + UMC_METH_PERSISTENT_WR = 7, + UMC_METH_SINGLE_SHOT_CLEAN = 8, +}; + +/* + * Return true if a UMC error injection using @sub_block (enum +error_sub_block_umc) + * and @method (enum inject_method_umc) is address-based, i.e. it +programs an + * explicit injection address. On MI300 series the non address-based +methods + * ignore the address; other ASICs always inject by the given address, +so return + * true there to keep validating it. + */ +bool amdgpu_ras_umc_is_address_based(struct amdgpu_device *adev, + u32 sub_block, u64 method) +{ + /* + * The (sub-block, method) classification below follows the MI300 RAS + * TA injection ABI and does not apply to other ASICs. + */ + switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) { + case IP_VERSION(13, 0, 6): + case IP_VERSION(13, 0, 12): + case IP_VERSION(13, 0, 14): + break; + default: + return true; + } + + switch (sub_block) { + case UMC_ERROR_CRC: + return method == UMC_METH_COHERENT || + method == UMC_METH_COHERENT_NO_DETECTION || + method == UMC_METH_COHERENT_WR; + case UMC_ERROR_ODECC: + return method == UMC_METH_COHERENT; + case UMC_ERROR_PARITY_DATA: + return method == UMC_METH_COHERENT || + method == UMC_METH_COHERENT_WR; + default: + return false; + } +} + +/* + * Wrapper for the legacy debugfs inject path: classify @data and warn +when a + * non address-based injection was given a non-zero address (which is ignored). + */ +static bool amdgpu_ras_umc_inject_is_address_based(struct amdgpu_device *adev, + struct ras_debug_if *data) +{ + bool address_based = amdgpu_ras_umc_is_address_based(adev, + data->head.sub_block_index, + data->inject.value); + + if (!address_based && data->inject.address) + dev_warn(adev->dev, + "RAS WARN: non address based injection, ignore the injection address 0x%llx\n", + data->inject.address); + + return address_based; +} + /** * DOC: AMDGPU RAS debugfs control interface * @@ -606,8 +691,13 @@ 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, but + * only address-based injections actually use the address, so + * limit the bad page check to those. + */ + if (data.head.block == AMDGPU_RAS_BLOCK__UMC && + amdgpu_ras_umc_inject_is_address_based(adev, &data)) 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/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index ad24c7cf8936..69a1600ad1a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -917,6 +917,9 @@ int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, int amdgpu_ras_error_inject(struct amdgpu_device *adev, struct ras_inject_if *info); +bool amdgpu_ras_umc_is_address_based(struct amdgpu_device *adev, + u32 sub_block, u64 method); + int amdgpu_ras_interrupt_add_handler(struct amdgpu_device *adev, struct ras_common_if *head); 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..31486ceecc72 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 @@ -90,7 +90,8 @@ static int amdgpu_ras_inject_error(struct ras_core_context *ras_core, (struct ras_cmd_inject_error_req *)cmd->input_buff_raw; int ret = RAS_CMD__ERROR_GENERIC; - if (req->block_id == RAS_BLOCK_ID__UMC) { + if (req->block_id == RAS_BLOCK_ID__UMC && + amdgpu_ras_umc_is_address_based(adev, req->subblock_id, req->method)) +{ 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", -- 2.43.0
