mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
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. Signed-off-by: Stanley.Yang <Stanley.Yang@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
a8880289fd
commit
bf65973e5f
|
|
@ -596,8 +596,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.",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
return RAS_CMD__ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user