[PATCH 057/109] drm/amdgpu/ras: prepare ras_psp for ras_mgr-owned TA reload

Alex Deucher <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Xiang Liu <[email protected]>

Stop deriving RAS TA session state from the legacy PSP status query and
switch ras_psp over to locally tracked TA lifetime. Delegate TA init
parameters and fini cleanup through ras_psp sys callbacks, update the
load and unload flow to keep firmware metadata in rascore, and add a
skip_lock load path that can be used after PSP reinitialization.

This prepares ras_psp for a later ras_mgr resume hook that reloads the
TA without relying on legacy PSP-managed session ownership.

Signed-off-by: Jinzhou Su <[email protected]>
Signed-off-by: Xiang Liu <[email protected]>
Reviewed-by: Hawking Zhang <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/ras/core/ras.h            |   1 +
 drivers/gpu/drm/amd/ras/core/ras_psp.c        | 149 ++++++++++--------
 drivers/gpu/drm/amd/ras/core/ras_psp.h        |  15 +-
 .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c  |   3 -
 4 files changed, 89 insertions(+), 79 deletions(-)

diff --git a/drivers/gpu/drm/amd/ras/core/ras.h b/drivers/gpu/drm/amd/ras/core/ras.h
index 4cee407c36595..3faf16c850da3 100644
--- a/drivers/gpu/drm/amd/ras/core/ras.h
+++ b/drivers/gpu/drm/amd/ras/core/ras.h
@@ -269,6 +269,7 @@ struct ras_psp_sys_func {
 		struct ras_psp_sys_status *status);
 	int (*get_ras_ta_init_param)(struct ras_core_context *ras_core,
 		struct ras_ta_init_param *ras_ta_param);
+	void (*put_ras_ta_fini_param)(struct ras_core_context *ras_core);
 };
 
 struct ras_sys_func {
diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp.c b/drivers/gpu/drm/amd/ras/core/ras_psp.c
index 30d22c51758a3..b7af0f2dd6ac6 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_psp.c
+++ b/drivers/gpu/drm/amd/ras/core/ras_psp.c
@@ -55,7 +55,6 @@ static const struct ras_psp_ip_func *ras_psp_get_ip_funcs(
 static int ras_psp_sync_system_ras_psp_status(struct ras_core_context *ras_core)
 {
 	struct ras_psp *psp = &ras_core->ras_psp;
-	struct ras_ta_ctx *ta_ctx = &ras_core->ras_psp.ta_ctx;
 	struct ras_psp_ctx *psp_ctx = &ras_core->ras_psp.psp_ctx;
 	struct ras_psp_sys_status status = {0};
 	int ret;
@@ -65,12 +64,6 @@ static int ras_psp_sync_system_ras_psp_status(struct ras_core_context *ras_core)
 		if (ret)
 			return ret;
 
-		if (status.initialized) {
-			ta_ctx->preload_ras_ta_enabled = true;
-			ta_ctx->ras_ta_initialized = status.initialized;
-			ta_ctx->session_id = status.session_id;
-		}
-
 		psp_ctx->external_mutex = status.psp_cmd_mutex;
 	}
 
@@ -81,22 +74,20 @@ static int ras_psp_get_ras_ta_init_param(struct ras_core_context *ras_core,
 	struct ras_ta_init_param *ras_ta_param)
 {
 	struct ras_psp *psp = &ras_core->ras_psp;
-	int ret;
 
-	if (!psp->sys_func || !psp->sys_func->get_ras_ta_init_param) {
-		RAS_DEV_ERR(ras_core->dev, "Not config get_ras_ta_init_param API!!\n");
-		return -EINVAL;
-	}
+	if (psp->sys_func && psp->sys_func->get_ras_ta_init_param)
+		return psp->sys_func->get_ras_ta_init_param(ras_core, ras_ta_param);
 
-	ret = psp->sys_func->get_ras_ta_init_param(ras_core, ras_ta_param);
-	if (ret)
-		return ret;
+	RAS_DEV_ERR(ras_core->dev, "Not config get_ras_ta_init_param API!!\n");
+	return -EACCES;
+}
 
-	ras_ta_param->nps_mode = ras_core_get_curr_nps_mode(ras_core);
-	ras_ta_param->vram_type = ras_core_get_vram_type(ras_core);
-	ras_ta_param->poison_mode_en = ras_core_poison_supported(ras_core) ? 1 : 0;
+static void ras_psp_put_ras_ta_fini_param(struct ras_core_context *ras_core)
+{
+	struct ras_psp *psp = &ras_core->ras_psp;
 
-	return 0;
+	if (psp->sys_func && psp->sys_func->put_ras_ta_fini_param)
+		psp->sys_func->put_ras_ta_fini_param(ras_core);
 }
 
 static struct gpu_mem_block *ras_psp_get_gpu_mem(struct ras_core_context *ras_core,
@@ -384,7 +375,10 @@ static int send_ras_ta_runtime_cmd(struct ras_core_context *ras_core,
 		return -EINVAL;
 	}
 
-	ras_psp_sync_system_ras_psp_status(ras_core);
+	if (!ta_ctx->ras_ta_initialized) {
+		RAS_DEV_ERR(ras_core->dev, "RAS TA is not initialized, cmd_id: %u\n", cmd_id);
+		return -EACCES;
+	}
 
 	cmd_mem = ras_psp_get_gpu_mem(ras_core, GPU_MEM_TYPE_RAS_TA_CMD);
 	if (!cmd_mem)
@@ -479,11 +473,11 @@ static int trigger_ras_ta_error(struct ras_core_context *ras_core,
 }
 
 static int send_load_ta_fw_cmd(struct ras_core_context *ras_core,
-				struct ras_ta_ctx *ta_ctx)
+				struct ras_ta_ctx *ta_ctx, bool skip_lock)
 {
 	struct ras_ta_fw_bin  *fw_bin = &ta_ctx->fw_bin;
-	struct gpu_mem_block *fw_mem;
-	struct gpu_mem_block *cmd_mem;
+	struct gpu_mem_block *fw_mem = NULL;
+	struct gpu_mem_block *cmd_mem = NULL;
 	struct ras_ta_cmd *ta_cmd;
 	struct ras_ta_init_flags *ta_init_flags;
 	struct psp_gfx_cmd_load_ta  psp_load_ta_cmd;
@@ -491,6 +485,10 @@ static int send_load_ta_fw_cmd(struct ras_core_context *ras_core,
 	struct ras_ta_image_header *fw_hdr = NULL;
 	int ret;
 
+	ret = ras_psp_get_ras_ta_init_param(ras_core, &ta_ctx->init_param);
+	if (ret)
+		goto err;
+
 	fw_mem = ras_psp_get_gpu_mem(ras_core, GPU_MEM_TYPE_RAS_TA_FW);
 	if (!fw_mem)
 		return -ENOMEM;
@@ -501,11 +499,12 @@ static int send_load_ta_fw_cmd(struct ras_core_context *ras_core,
 		goto err;
 	}
 
-	ret = ras_psp_get_ras_ta_init_param(ras_core, &ta_ctx->init_param);
-	if (ret)
-		goto err;
-
-	if (!ras_core_down_trylock_gpu_reset_lock(ras_core)) {
+	/*
+	 * When skip_lock is true (called from .resume), the PSP has already
+	 * been re-initialized and it is safe to proceed without the read lock
+	 * (GPU reset holds write lock; S3/S4 has no lock to acquire).
+	 */
+	if (!skip_lock && !ras_core_down_trylock_gpu_reset_lock(ras_core)) {
 		ret = -EACCES;
 		goto err;
 	}
@@ -552,7 +551,8 @@ static int send_load_ta_fw_cmd(struct ras_core_context *ras_core,
 			"Failed to load RAS TA! ret:%d, status:%d\n", ret, resp.status);
 	}
 
-	ras_core_up_gpu_reset_lock(ras_core);
+	if (!skip_lock)
+		ras_core_up_gpu_reset_lock(ras_core);
 
 err:
 	ras_psp_put_gpu_mem(ras_core, fw_mem);
@@ -560,24 +560,12 @@ static int send_load_ta_fw_cmd(struct ras_core_context *ras_core,
 	return ret;
 }
 
-static int load_ras_ta_firmware(struct ras_core_context *ras_core,
-		struct ras_psp_ta_load *ras_ta_load)
+static int load_ras_ta_firmware(struct ras_core_context *ras_core, bool skip_lock)
 {
 	struct ras_ta_ctx *ta_ctx = &ras_core->ras_psp.ta_ctx;
-	struct ras_ta_fw_bin  *fw_bin = &ta_ctx->fw_bin;
 	int ret;
 
-	fw_bin->bin_addr = ras_ta_load->bin_addr;
-	fw_bin->bin_size = ras_ta_load->bin_size;
-	fw_bin->fw_version = ras_ta_load->fw_version;
-	fw_bin->feature_version = ras_ta_load->feature_version;
-
-	ret = send_load_ta_fw_cmd(ras_core, ta_ctx);
-	if (!ret) {
-		ras_ta_load->out_session_id = ta_ctx->session_id;
-		ras_ta_load->out_loaded_ta_version = ta_ctx->ta_version;
-	}
-
+	ret = send_load_ta_fw_cmd(ras_core, ta_ctx, skip_lock);
 	return ret;
 }
 
@@ -602,12 +590,13 @@ static int unload_ras_ta_firmware(struct ras_core_context *ras_core,
 		goto unlock;
 	}
 
-	kfree(ta_ctx->fw_bin.bin_addr);
-	memset(&ta_ctx->fw_bin, 0, sizeof(ta_ctx->fw_bin));
+	RAS_DEV_INFO(ras_core->dev,
+		     "Successfully to unload RAS TA! ret:%d, status:%u\n",
+			ret, resp.status);
+
 	ta_ctx->ta_version = 0;
 	ta_ctx->ras_ta_initialized = false;
 	ta_ctx->session_id = 0;
-
 unlock:
 	ras_core_up_gpu_reset_lock(ras_core);
 
@@ -615,26 +604,42 @@ static int unload_ras_ta_firmware(struct ras_core_context *ras_core,
 }
 
 int ras_psp_load_firmware(struct ras_core_context *ras_core,
-	struct ras_psp_ta_load *ras_ta_load)
+		bool skip_lock)
 {
 	struct ras_ta_ctx *ta_ctx = &ras_core->ras_psp.ta_ctx;
 	struct ras_psp_ta_unload ras_ta_unload = {0};
-	int ret;
-
-	if (ta_ctx->preload_ras_ta_enabled)
-		return 0;
+	int ret = 0;
 
-	if (!ras_ta_load)
-		return -EINVAL;
+	if (skip_lock) {
+		/*
+		 * Called from .resume: PSP has been re-initialized after a GPU
+		 * reset or S3/S4, so any previous TA session is gone. Clear
+		 * stale state and proceed directly to a fresh load, bypassing
+		 * both the unload step and the reset read-lock acquisition
+		 * (which would deadlock inside a GPU reset).
+		 */
+		ta_ctx->preload_ras_ta_enabled = false;
+		ta_ctx->ras_ta_initialized = false;
+		ta_ctx->session_id = 0;
+		ta_ctx->ta_version = 0;
+	} else {
+		/*
+		 * Normal path: only skip a reload when the current TA session is
+		 * known to be alive. Firmware metadata may already be cached even
+		 * when the TA is not loaded, so that must not suppress a reload.
+		 */
+		if (ta_ctx->preload_ras_ta_enabled && ta_ctx->ras_ta_initialized)
+			return 0;
 
-	if (ta_ctx->ras_ta_initialized) {
-		ras_ta_unload.ras_session_id = ta_ctx->session_id;
-		ret = unload_ras_ta_firmware(ras_core, &ras_ta_unload);
-		if (ret)
-			return ret;
+		if (ta_ctx->ras_ta_initialized) {
+			ras_ta_unload.ras_session_id = ta_ctx->session_id;
+			ret = unload_ras_ta_firmware(ras_core, &ras_ta_unload);
+			if (ret)
+				return ret;
+		}
 	}
 
-	return load_ras_ta_firmware(ras_core, ras_ta_load);
+	return load_ras_ta_firmware(ras_core, skip_lock);
 }
 
 int ras_psp_unload_firmware(struct ras_core_context *ras_core,
@@ -642,9 +647,6 @@ int ras_psp_unload_firmware(struct ras_core_context *ras_core,
 {
 	struct ras_ta_ctx *ta_ctx = &ras_core->ras_psp.ta_ctx;
 
-	if (ta_ctx->preload_ras_ta_enabled)
-		return 0;
-
 	if ((!ras_ta_unload) ||
 	    (ras_ta_unload->ras_session_id != ta_ctx->session_id))
 		return -EINVAL;
@@ -719,7 +721,9 @@ int ras_psp_sw_fini(struct ras_core_context *ras_core)
 
 int ras_psp_hw_init(struct ras_core_context *ras_core)
 {
+	int ret = 0;
 	struct ras_psp *psp = &ras_core->ras_psp;
+	struct ras_ta_ctx *ta_ctx = &ras_core->ras_psp.ta_ctx;
 
 	psp->psp_ip_version = ras_core->config->psp_ip_version;
 
@@ -741,11 +745,30 @@ int ras_psp_hw_init(struct ras_core_context *ras_core)
 	 */
 	ras_psp_sync_system_ras_psp_status(ras_core);
 
-	return 0;
+	if (!ta_ctx->preload_ras_ta_enabled && !ta_ctx->ras_ta_initialized)
+		ret = ras_psp_load_firmware(ras_core, false);
+
+	return ret;
 }
 
 int ras_psp_hw_fini(struct ras_core_context *ras_core)
 {
+	struct ras_ta_ctx *ta_ctx = &ras_core->ras_psp.ta_ctx;
+	struct ras_psp_ta_unload ras_ta_unload = {0};
+
+	if (ta_ctx->ras_ta_initialized) {
+		ras_ta_unload.ras_session_id = ta_ctx->session_id;
+		ras_psp_unload_firmware(ras_core, &ras_ta_unload);
+	}
+
+	ta_ctx->ta_version = 0;
+	ta_ctx->ras_ta_initialized = false;
+	ta_ctx->preload_ras_ta_enabled = false;
+	ta_ctx->session_id = 0;
+
+	/* Free shared BO only on hw_fini, not on suspend */
+	ras_psp_put_ras_ta_fini_param(ras_core);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp.h b/drivers/gpu/drm/amd/ras/core/ras_psp.h
index f1d32f31a64ee..cb564b532ac9e 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_psp.h
+++ b/drivers/gpu/drm/amd/ras/core/ras_psp.h
@@ -41,8 +41,6 @@ struct ras_ta_image_header {
 };
 
 struct ras_psp_sys_status {
-	bool  initialized;
-	uint32_t session_id;
 	void *psp_cmd_mutex;
 };
 
@@ -146,15 +144,6 @@ struct ras_psp {
 	const struct ras_psp_sys_func *sys_func;
 };
 
-struct ras_psp_ta_load {
-	uint32_t fw_version;
-	uint32_t feature_version;
-	uint32_t bin_size;
-	uint8_t *bin_addr;
-	uint64_t out_session_id;
-	uint32_t out_loaded_ta_version;
-};
-
 struct ras_psp_ta_unload {
 	uint64_t ras_session_id;
 };
@@ -163,8 +152,8 @@ int ras_psp_sw_init(struct ras_core_context *ras_core);
 int ras_psp_sw_fini(struct ras_core_context *ras_core);
 int ras_psp_hw_init(struct ras_core_context *ras_core);
 int ras_psp_hw_fini(struct ras_core_context *ras_core);
-int ras_psp_load_firmware(struct ras_core_context *ras_core,
-		struct ras_psp_ta_load *ras_ta_load);
+
+int ras_psp_load_firmware(struct ras_core_context *ras_core, bool skip_lock);
 int ras_psp_unload_firmware(struct ras_core_context *ras_core,
 		struct ras_psp_ta_unload *ras_ta_unload);
 int ras_psp_trigger_error(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 525abb7e05474..29558888832c1 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
@@ -188,10 +188,7 @@ static int amdgpu_ras_mgr_get_ras_psp_system_status(struct ras_core_context *ras
 			struct ras_psp_sys_status *status)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev;
-	struct ta_context *context = &adev->psp.ras_context.context;
 
-	status->initialized = context->initialized;
-	status->session_id = context->session_id;
 	status->psp_cmd_mutex = &adev->psp.mutex;
 
 	return 0;
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.