* [PATCH 1/3] drm/amd/ras: request GFX RAS features through ras_mgr
@ 2026-08-20 14:04 Xiang Liu
2026-08-20 14:04 ` [PATCH 2/3] drm/amd/ras: use the per-ASIC reserved VRAM size for the bad page threshold Xiang Liu
2026-08-20 14:04 ` [PATCH 3/3] drm/amd/ras: keep reporting the socket id in the RAS feature mask Xiang Liu
0 siblings, 2 replies; 4+ messages in thread
From: Xiang Liu @ 2026-08-20 14:04 UTC (permalink / raw)
To: amd-gfx; +Cc: Hawking.Zhang, Tao.Zhou1, Stanley.Yang, YiPeng.Chai, Xiang Liu
psp_ras_enable_features() returns 0 without sending anything once the
RAS TA is loaded by ras_mgr, and nothing on that path sends
ENABLE_FEATURES either. GFX RAS features therefore end up enabled by no
one, silently, because the helper still reports success.
This is harmless at boot, where the TA is loaded with poison_mode_en set
while GFX is freshly initialized. It is not harmless across a reset: a
mode2 reset clears the GFX side, amdgpu_gfx_ras_late_init() re-runs from
the reset handler but its enable request goes nowhere, and GFX stops
raising SQ EDC_FED. The visible effect is that only the first poison
injection after boot is ever consumed. Every later one creates the
poison in HBM and is never reported, since the first injection triggers
the reset that breaks reporting.
Add ras_psp_enable_features() to send ENABLE_FEATURES/DISABLE_FEATURES
to the TA owned by ras_mgr, and route amdgpu_ras_feature_enable()
through it. Newer parts arm RAS features inside the TA and must not be
toggled by the driver, so restrict the request to GFX IP versions below
12.1.0.
Fixes: c8a0dcadcec6 ("drm/amdgpu: add switch to select firmware loading path for RAS RL and TA")
Signed-off-by: Xiang Liu <xiang.liu@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 9 ++++++-
drivers/gpu/drm/amd/ras/core/ras_psp.c | 19 +++++++++++++
drivers/gpu/drm/amd/ras/core/ras_psp.h | 2 ++
.../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c | 27 +++++++++++++++++++
.../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h | 2 ++
5 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 572403cb6121..d168e5d54d87 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -933,7 +933,14 @@ int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
};
}
- ret = psp_ras_enable_features(&adev->psp, info, enable);
+ if (amdgpu_uniras_enabled(adev))
+ ret = amdgpu_ras_mgr_enable_feature(adev,
+ amdgpu_ras_block_to_ta(head->block),
+ amdgpu_ras_error_to_ta(head->type),
+ enable);
+ else
+ ret = psp_ras_enable_features(&adev->psp, info, enable);
+
if (ret) {
dev_err(adev->dev, "ras %s %s failed poison:%d ret:%d\n",
enable ? "enable":"disable",
diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp.c b/drivers/gpu/drm/amd/ras/core/ras_psp.c
index 102dffe9d498..ed53cd25d6bd 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_psp.c
+++ b/drivers/gpu/drm/amd/ras/core/ras_psp.c
@@ -797,6 +797,25 @@ int ras_psp_reload_firmwares(struct ras_core_context *ras_core,
return load_ras_all_fw(ras_core);
}
+int ras_psp_enable_features(struct ras_core_context *ras_core,
+ struct ras_ta_enable_features_input *info, bool enable)
+{
+ struct ras_ta_ctx *ta_ctx = &ras_core->ras_psp.ta_ctx;
+
+ if (!info)
+ return -EINVAL;
+
+ if (!ta_ctx->ras_ta_initialized) {
+ RAS_DEV_ERR(ras_core->dev, "RAS: ras firmware not initialized!");
+ return -ENOEXEC;
+ }
+
+ return send_ras_ta_runtime_cmd(ras_core,
+ enable ? RAS_TA_CMD_ID__ENABLE_FEATURES :
+ RAS_TA_CMD_ID__DISABLE_FEATURES,
+ info, sizeof(*info), NULL, 0);
+}
+
int ras_psp_trigger_error(struct ras_core_context *ras_core,
struct ras_ta_trigger_error_input *info, uint32_t instance_mask)
{
diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp.h b/drivers/gpu/drm/amd/ras/core/ras_psp.h
index 041d46eee3f4..4cc133c6a6d3 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_psp.h
+++ b/drivers/gpu/drm/amd/ras/core/ras_psp.h
@@ -196,6 +196,8 @@ int ras_psp_sideload_ras_ta(struct ras_core_context *ras_core,
struct ras_psp_ta_load *ta_load);
int ras_psp_unsideload_ras_ta(struct ras_core_context *ras_core,
struct ras_psp_ta_unload *ras_ta_unload);
+int ras_psp_enable_features(struct ras_core_context *ras_core,
+ struct ras_ta_enable_features_input *info, bool enable);
int ras_psp_trigger_error(struct ras_core_context *ras_core,
struct ras_ta_trigger_error_input *info, uint32_t instance_mask);
int ras_psp_query_address(struct ras_core_context *ras_core,
diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c
index e6941de46787..3d806e35382a 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c
@@ -772,6 +772,33 @@ int amdgpu_ras_mgr_post_reset(struct amdgpu_device *adev)
return 0;
}
+int amdgpu_ras_mgr_enable_feature(struct amdgpu_device *adev,
+ uint32_t ta_block_id, uint32_t ta_error_type, bool enable)
+{
+ struct amdgpu_ras_mgr *ras_mgr = amdgpu_ras_mgr_get_context(adev);
+ struct ras_ta_enable_features_input info = {
+ .block_id = (enum ras_ta_block)ta_block_id,
+ .error_type = (enum ras_ta_error_type)ta_error_type,
+ };
+ uint32_t gfx_ip_version;
+
+ if (!ras_mgr || !ras_mgr->ras_core)
+ return -EINVAL;
+
+ if (ras_core_get_ip_version(ras_mgr->ras_core,
+ RAS_UNIT_ID_GFX, &gfx_ip_version))
+ return -EPERM;
+
+ /* Newer parts arm RAS features inside the TA, so the driver must not
+ * toggle them. Older ones still need an explicit request after every
+ * GPU reset, otherwise GFX stops reporting poison consumption.
+ */
+ if (gfx_ip_version >= IP_VERSION(12, 1, 0))
+ return 0;
+
+ return ras_psp_enable_features(ras_mgr->ras_core, &info, enable);
+}
+
int amdgpu_ras_mgr_lookup_bad_pages_in_a_row(struct amdgpu_device *adev,
uint64_t addr, uint64_t *nps_page_addr, uint32_t max_page_count)
{
diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h
index 442d628ccfec..99b3e6995e12 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.h
@@ -85,6 +85,8 @@ int amdgpu_ras_mgr_handle_ras_cmd(struct amdgpu_device *adev,
void *output, uint32_t out_size);
int amdgpu_ras_mgr_pre_reset(struct amdgpu_device *adev);
int amdgpu_ras_mgr_post_reset(struct amdgpu_device *adev);
+int amdgpu_ras_mgr_enable_feature(struct amdgpu_device *adev,
+ uint32_t ta_block_id, uint32_t ta_error_type, bool enable);
int amdgpu_ras_mgr_resume_after_reset(struct amdgpu_device *adev);
int amdgpu_ras_mgr_lookup_bad_pages_in_a_row(struct amdgpu_device *adev,
uint64_t addr, uint64_t *nps_page_addr, uint32_t max_page_count);
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/3] drm/amd/ras: use the per-ASIC reserved VRAM size for the bad page threshold
2026-08-20 14:04 [PATCH 1/3] drm/amd/ras: request GFX RAS features through ras_mgr Xiang Liu
@ 2026-08-20 14:04 ` Xiang Liu
2026-08-20 14:04 ` [PATCH 3/3] drm/amd/ras: keep reporting the socket id in the RAS feature mask Xiang Liu
1 sibling, 0 replies; 4+ messages in thread
From: Xiang Liu @ 2026-08-20 14:04 UTC (permalink / raw)
To: amd-gfx; +Cc: Hawking.Zhang, Tao.Zhou1, Stanley.Yang, YiPeng.Chai, Xiang Liu
The default bad page threshold is derived from the VRAM reserved for
retirement, but ras_eeprom_i2c_config() hardcodes
RAS_RESERVED_VRAM_SIZE_DEFAULT. amdgpu_ras_validate_threshold() instead
derives it from con->reserved_pages_in_bytes, which
amdgpu_ras_init_reserved_vram_size() doubles on MP0 v13.0.14.
That part therefore ends up with a 128 bad page threshold where it
should have 256, and reaches the limit after half as many retirements
as intended.
Reuse the value already computed for con->reserved_pages_in_bytes
rather than deriving it again, so the two cannot drift apart.
Fixes: e383baf88f7d ("drm/amd/ras: Refactor EEPROM parameter config to support multiple ras EEPROMs")
Signed-off-by: Xiang Liu <xiang.liu@amd.com>
---
.../drm/amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c
index d2c9fc525af5..a56d3116c5fd 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_eeprom_i2c.c
@@ -77,6 +77,19 @@
#define BAD_PAGE_NUM_PER_EEPROM_RECORD_V13 16
#define BAD_PAGE_NUM_PER_EEPROM_RECORD_V15 128
+static u64 ras_eeprom_reserved_vram_size(struct amdgpu_device *adev)
+{
+ struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
+
+ /* Set by amdgpu_ras_init_reserved_vram_size(); 0 means that path
+ * does not cover this ASIC.
+ */
+ if (con && con->reserved_pages_in_bytes)
+ return con->reserved_pages_in_bytes;
+
+ return RAS_RESERVED_VRAM_SIZE_DEFAULT;
+}
+
static int ras_eeprom_i2c_config(struct ras_core_context *ras_core,
struct ras_eeprom_param_config *cfg)
{
@@ -168,7 +181,7 @@ static int ras_eeprom_i2c_config(struct ras_core_context *ras_core,
badpages = ESTIMATE_BAD_PAGE_THRESHOLD(adev->gmc.mc_vram_size);
} else if (badpage_threshold == WARN_NONSTOP_OVER_THRESHOLD) {
cfg->work_mode_over_thresh = RAS_WORK_MODE_OVER_THRESH_STRICT;
- badpages = COUNT_BAD_PAGE_THRESHOLD(RAS_RESERVED_VRAM_SIZE_DEFAULT);
+ badpages = COUNT_BAD_PAGE_THRESHOLD(ras_eeprom_reserved_vram_size(adev));
} else if (!badpage_threshold) {
cfg->work_mode_over_thresh = RAS_WORK_MODE_OVER_THRESH_DEBUG;
badpages = 128;
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 3/3] drm/amd/ras: keep reporting the socket id in the RAS feature mask
2026-08-20 14:04 [PATCH 1/3] drm/amd/ras: request GFX RAS features through ras_mgr Xiang Liu
2026-08-20 14:04 ` [PATCH 2/3] drm/amd/ras: use the per-ASIC reserved VRAM size for the bad page threshold Xiang Liu
@ 2026-08-20 14:04 ` Xiang Liu
2026-08-20 16:08 ` Zhang, Hawking
1 sibling, 1 reply; 4+ messages in thread
From: Xiang Liu @ 2026-08-20 14:04 UTC (permalink / raw)
To: amd-gfx; +Cc: Hawking.Zhang, Tao.Zhou1, Stanley.Yang, YiPeng.Chai, Xiang Liu
The socket id of a device is exported through the ras "features" sysfs
node, where con->features carries it in bits[31:29].
Reporting the RAS capability mask there instead changes that layout: it
spends bits[55:0] on block bits and so carries the socket id in
bits[62:60]. Tools that decode bits[31:29] then read block capability
bits, which are identical on every device of a hive.
XGMI error injection depends on this. The tool resolves a WAFL sub block
to its destination socket, looks up the device carrying that socket id
and injects there. Once every device claims the same socket id the
lookup silently falls back to the first device and to instance mask 0,
so the injection lands on the wrong device and the RAS TA rejects it
with RAS_TA_STATUS__ERROR_PCS_STATE_HANG.
Only report the capability mask on parts whose tools decode the wider
layout, and keep reporting con->features on the others.
Fixes: 6ae383bdf282 ("drm/amdgpu: Support obtaining ras capabilities")
Signed-off-by: Xiang Liu <xiang.liu@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index d168e5d54d87..0dec6da3f1d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1845,10 +1845,19 @@ static ssize_t amdgpu_ras_sysfs_features_read(struct device *dev,
{
struct amdgpu_ras *con =
container_of(attr, struct amdgpu_ras, features_attr);
+ struct amdgpu_device *adev = con->adev;
u64 ras_features;
- ras_features = amdgpu_uniras_enabled(con->adev) ?
- amdgpu_uniras_get_ras_caps(con->adev) : con->features;
+ /* The wide capability mask needs bits[31:29] for block bits and so
+ * reports the socket id in bits[62:60] instead. Only newer parts may
+ * use it: on older ones tools still decode bits[31:29], and without a
+ * socket id there they cannot tell the devices of a hive apart.
+ */
+ if (amdgpu_uniras_enabled(adev) &&
+ amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 1, 0))
+ ras_features = amdgpu_uniras_get_ras_caps(adev);
+ else
+ ras_features = con->features;
return sysfs_emit(buf, "feature mask: 0x%llx\n", ras_features);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* RE: [PATCH 3/3] drm/amd/ras: keep reporting the socket id in the RAS feature mask
2026-08-20 14:04 ` [PATCH 3/3] drm/amd/ras: keep reporting the socket id in the RAS feature mask Xiang Liu
@ 2026-08-20 16:08 ` Zhang, Hawking
0 siblings, 0 replies; 4+ messages in thread
From: Zhang, Hawking @ 2026-08-20 16:08 UTC (permalink / raw)
To: Liu, Xiang(Dean), amd-gfx@lists.freedesktop.org
Cc: Zhou1, Tao, Yang, Stanley, Chai, Thomas, Liu, Xiang(Dean)
AMD General
Patch # 1 ~ 2 are
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Patch #3 is not needed.
Regards,
Hawking
-----Original Message-----
From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Xiang Liu
Sent: Thursday, August 20, 2026 10:05 PM
To: amd-gfx@lists.freedesktop.org
Cc: Zhang, Hawking <Hawking.Zhang@amd.com>; Zhou1, Tao <Tao.Zhou1@amd.com>; Yang, Stanley <Stanley.Yang@amd.com>; Chai, Thomas <YiPeng.Chai@amd.com>; Liu, Xiang(Dean) <Xiang.Liu@amd.com>
Subject: [PATCH 3/3] drm/amd/ras: keep reporting the socket id in the RAS feature mask
The socket id of a device is exported through the ras "features" sysfs node, where con->features carries it in bits[31:29].
Reporting the RAS capability mask there instead changes that layout: it spends bits[55:0] on block bits and so carries the socket id in bits[62:60]. Tools that decode bits[31:29] then read block capability bits, which are identical on every device of a hive.
XGMI error injection depends on this. The tool resolves a WAFL sub block to its destination socket, looks up the device carrying that socket id and injects there. Once every device claims the same socket id the lookup silently falls back to the first device and to instance mask 0, so the injection lands on the wrong device and the RAS TA rejects it with RAS_TA_STATUS__ERROR_PCS_STATE_HANG.
Only report the capability mask on parts whose tools decode the wider layout, and keep reporting con->features on the others.
Fixes: 6ae383bdf282 ("drm/amdgpu: Support obtaining ras capabilities")
Signed-off-by: Xiang Liu <xiang.liu@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index d168e5d54d87..0dec6da3f1d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1845,10 +1845,19 @@ static ssize_t amdgpu_ras_sysfs_features_read(struct device *dev, {
struct amdgpu_ras *con =
container_of(attr, struct amdgpu_ras, features_attr);
+ struct amdgpu_device *adev = con->adev;
u64 ras_features;
- ras_features = amdgpu_uniras_enabled(con->adev) ?
- amdgpu_uniras_get_ras_caps(con->adev) : con->features;
+ /* The wide capability mask needs bits[31:29] for block bits and so
+ * reports the socket id in bits[62:60] instead. Only newer parts may
+ * use it: on older ones tools still decode bits[31:29], and without a
+ * socket id there they cannot tell the devices of a hive apart.
+ */
+ if (amdgpu_uniras_enabled(adev) &&
+ amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 1, 0))
+ ras_features = amdgpu_uniras_get_ras_caps(adev);
+ else
+ ras_features = con->features;
return sysfs_emit(buf, "feature mask: 0x%llx\n", ras_features); }
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-20 16:08 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 14:04 [PATCH 1/3] drm/amd/ras: request GFX RAS features through ras_mgr Xiang Liu
2026-08-20 14:04 ` [PATCH 2/3] drm/amd/ras: use the per-ASIC reserved VRAM size for the bad page threshold Xiang Liu
2026-08-20 14:04 ` [PATCH 3/3] drm/amd/ras: keep reporting the socket id in the RAS feature mask Xiang Liu
2026-08-20 16:08 ` Zhang, Hawking
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.