aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4213-drm-amdgpu-psp-add-psp-memory-training-implementatio.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4213-drm-amdgpu-psp-add-psp-memory-training-implementatio.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4213-drm-amdgpu-psp-add-psp-memory-training-implementatio.patch246
1 files changed, 246 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4213-drm-amdgpu-psp-add-psp-memory-training-implementatio.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4213-drm-amdgpu-psp-add-psp-memory-training-implementatio.patch
new file mode 100644
index 00000000..b6a6644f
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4213-drm-amdgpu-psp-add-psp-memory-training-implementatio.patch
@@ -0,0 +1,246 @@
+From 7759546a09a7816345f83d60f9c04ec7ecda191a Mon Sep 17 00:00:00 2001
+From: "Tianci.Yin" <tianci.yin@amd.com>
+Date: Mon, 30 Sep 2019 14:29:33 +0800
+Subject: [PATCH 4213/4736] drm/amdgpu/psp: add psp memory training
+ implementation(v3)
+
+add memory training implementation code to save resume time.
+
+Change-Id: Ib74fec65eb4db1f7343d5ff54e9169e3ade1a882
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Luben Tuikov <luben.tuikov@amd.com>
+Signed-off-by: Tianci.Yin <tianci.yin@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 +
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 ++
+ drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 161 ++++++++++++++++++++++++
+ 3 files changed, 171 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+index 8c5c1833aca7..f1f258a2790a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -156,6 +156,7 @@ extern char *amdgpu_disable_cu;
+ extern char *amdgpu_virtual_display;
+ extern uint amdgpu_pp_feature_mask;
+ extern int amdgpu_ssg_enabled;
++extern uint amdgpu_force_long_training;
+ extern int amdgpu_job_hang_limit;
+ extern int amdgpu_lbpw;
+ extern int amdgpu_compute_multipipe;
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+index 5ab426726849..699cab407158 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -129,6 +129,7 @@ char *amdgpu_disable_cu = NULL;
+ char *amdgpu_virtual_display = NULL;
+ /* OverDrive(bit 14) disabled by default*/
+ uint amdgpu_pp_feature_mask = 0xffffbfff;
++uint amdgpu_force_long_training = 0;
+ int amdgpu_job_hang_limit = 0;
+ int amdgpu_lbpw = -1;
+ int amdgpu_compute_multipipe = -1;
+@@ -403,6 +404,14 @@ module_param_named(direct_gma_size, amdgpu_direct_gma_size, int, 0444);
+ MODULE_PARM_DESC(ssg, "SSG support (1 = enable, 0 = disable (default))");
+ module_param_named(ssg, amdgpu_ssg_enabled, int, 0444);
+
++/**
++ * DOC: forcelongtraining (uint)
++ * Force long memory training in resume.
++ * The default is zero, indicates short training in resume.
++ */
++MODULE_PARM_DESC(forcelongtraining, "force memory long training");
++module_param_named(forcelongtraining, amdgpu_force_long_training, uint, 0444);
++
+ /**
+ * DOC: pcie_gen_cap (uint)
+ * Override PCIE gen speed capabilities. See the CAIL flags in drivers/gpu/drm/amd/include/amd_pcie.h.
+diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+index b52af59079b7..0875ece1bea2 100644
+--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+@@ -57,6 +57,8 @@ MODULE_FIRMWARE("amdgpu/arcturus_ta.bin");
+ #define mmRLC_GPM_UCODE_DATA_NV10 0x5b62
+ #define mmSDMA0_UCODE_ADDR_NV10 0x5880
+ #define mmSDMA0_UCODE_DATA_NV10 0x5881
++/* memory training timeout define */
++#define MEM_TRAIN_SEND_MSG_TIMEOUT_US 3000000
+
+ #define VEGA20_BL_VERSION_VAR_NEW 0xA1
+
+@@ -918,6 +920,162 @@ static int psp_v11_0_rlc_autoload_start(struct psp_context *psp)
+ return psp_rlc_autoload_start(psp);
+ }
+
++static int psp_v11_0_memory_training_send_msg(struct psp_context *psp, int msg)
++{
++ int ret;
++ int i;
++ uint32_t data_32;
++ int max_wait;
++ struct amdgpu_device *adev = psp->adev;
++
++ data_32 = (psp->mem_train_ctx.c2p_train_data_offset >> 20);
++ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, data_32);
++ WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, msg);
++
++ max_wait = MEM_TRAIN_SEND_MSG_TIMEOUT_US / adev->usec_timeout;
++ for (i = 0; i < max_wait; i++) {
++ ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
++ 0x80000000, 0x80000000, false);
++ if (ret == 0)
++ break;
++ }
++ if (i < max_wait)
++ ret = 0;
++ else
++ ret = -ETIME;
++
++ DRM_DEBUG("training %s %s, cost %d @ %d ms\n",
++ (msg == PSP_BL__DRAM_SHORT_TRAIN) ? "short" : "long",
++ (ret == 0) ? "succeed" : "failed",
++ i, adev->usec_timeout/1000);
++ return ret;
++}
++
++static void psp_v11_0_memory_training_fini(struct psp_context *psp)
++{
++ struct psp_memory_training_context *ctx = &psp->mem_train_ctx;
++
++ ctx->init = PSP_MEM_TRAIN_NOT_SUPPORT;
++ kfree(ctx->sys_cache);
++ ctx->sys_cache = NULL;
++}
++
++static int psp_v11_0_memory_training_init(struct psp_context *psp)
++{
++ int ret;
++ struct psp_memory_training_context *ctx = &psp->mem_train_ctx;
++
++ if (ctx->init != PSP_MEM_TRAIN_RESERVE_SUCCESS) {
++ DRM_DEBUG("memory training is not supported!\n");
++ return 0;
++ }
++
++ ctx->sys_cache = kzalloc(ctx->train_data_size, GFP_KERNEL);
++ if (ctx->sys_cache == NULL) {
++ DRM_ERROR("alloc mem_train_ctx.sys_cache failed!\n");
++ ret = -ENOMEM;
++ goto Err_out;
++ }
++
++ DRM_DEBUG("train_data_size:%llx,p2c_train_data_offset:%llx,c2p_train_data_offset:%llx.\n",
++ ctx->train_data_size,
++ ctx->p2c_train_data_offset,
++ ctx->c2p_train_data_offset);
++ ctx->init = PSP_MEM_TRAIN_INIT_SUCCESS;
++ return 0;
++
++Err_out:
++ psp_v11_0_memory_training_fini(psp);
++ return ret;
++}
++
++/*
++ * save and restore proces
++ */
++static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)
++{
++ int ret;
++ uint32_t p2c_header[4];
++ struct psp_memory_training_context *ctx = &psp->mem_train_ctx;
++ uint32_t *pcache = (uint32_t*)ctx->sys_cache;
++
++ if (ctx->init == PSP_MEM_TRAIN_NOT_SUPPORT) {
++ DRM_DEBUG("Memory training is not supported.\n");
++ return 0;
++ } else if (ctx->init != PSP_MEM_TRAIN_INIT_SUCCESS) {
++ DRM_ERROR("Memory training initialization failure.\n");
++ return -EINVAL;
++ }
++
++ if (psp_v11_0_is_sos_alive(psp)) {
++ DRM_DEBUG("SOS is alive, skip memory training.\n");
++ return 0;
++ }
++
++ amdgpu_device_vram_access(psp->adev, ctx->p2c_train_data_offset, p2c_header, sizeof(p2c_header), false);
++ DRM_DEBUG("sys_cache[%08x,%08x,%08x,%08x] p2c_header[%08x,%08x,%08x,%08x]\n",
++ pcache[0], pcache[1], pcache[2], pcache[3],
++ p2c_header[0], p2c_header[1], p2c_header[2], p2c_header[3]);
++
++ if (ops & PSP_MEM_TRAIN_SEND_SHORT_MSG) {
++ DRM_DEBUG("Short training depends on restore.\n");
++ ops |= PSP_MEM_TRAIN_RESTORE;
++ }
++
++ if ((ops & PSP_MEM_TRAIN_RESTORE) &&
++ pcache[0] != MEM_TRAIN_SYSTEM_SIGNATURE) {
++ DRM_DEBUG("sys_cache[0] is invalid, restore depends on save.\n");
++ ops |= PSP_MEM_TRAIN_SAVE;
++ }
++
++ if (p2c_header[0] == MEM_TRAIN_SYSTEM_SIGNATURE &&
++ !(pcache[0] == MEM_TRAIN_SYSTEM_SIGNATURE &&
++ pcache[3] == p2c_header[3])) {
++ DRM_DEBUG("sys_cache is invalid or out-of-date, need save training data to sys_cache.\n");
++ ops |= PSP_MEM_TRAIN_SAVE;
++ }
++
++ if ((ops & PSP_MEM_TRAIN_SAVE) &&
++ p2c_header[0] != MEM_TRAIN_SYSTEM_SIGNATURE) {
++ DRM_DEBUG("p2c_header[0] is invalid, save depends on long training.\n");
++ ops |= PSP_MEM_TRAIN_SEND_LONG_MSG;
++ }
++
++ if (ops & PSP_MEM_TRAIN_SEND_LONG_MSG) {
++ ops &= ~PSP_MEM_TRAIN_SEND_SHORT_MSG;
++ ops |= PSP_MEM_TRAIN_SAVE;
++ }
++
++ DRM_DEBUG("Memory training ops:%x.\n", ops);
++
++ if (ops & PSP_MEM_TRAIN_SEND_LONG_MSG) {
++ ret = psp_v11_0_memory_training_send_msg(psp, PSP_BL__DRAM_LONG_TRAIN);
++ if (ret) {
++ DRM_ERROR("Send long training msg failed.\n");
++ return ret;
++ }
++ }
++
++ if (ops & PSP_MEM_TRAIN_SAVE) {
++ amdgpu_device_vram_access(psp->adev, ctx->p2c_train_data_offset, ctx->sys_cache, ctx->train_data_size, false);
++ }
++
++ if (ops & PSP_MEM_TRAIN_RESTORE) {
++ amdgpu_device_vram_access(psp->adev, ctx->c2p_train_data_offset, ctx->sys_cache, ctx->train_data_size, true);
++ }
++
++ if (ops & PSP_MEM_TRAIN_SEND_SHORT_MSG) {
++ ret = psp_v11_0_memory_training_send_msg(psp, (amdgpu_force_long_training > 0) ?
++ PSP_BL__DRAM_LONG_TRAIN : PSP_BL__DRAM_SHORT_TRAIN);
++ if (ret) {
++ DRM_ERROR("send training msg failed.\n");
++ return ret;
++ }
++ }
++ ctx->training_cnt++;
++ return 0;
++}
++
+ static const struct psp_funcs psp_v11_0_funcs = {
+ .init_microcode = psp_v11_0_init_microcode,
+ .bootloader_load_kdb = psp_v11_0_bootloader_load_kdb,
+@@ -938,6 +1096,9 @@ static const struct psp_funcs psp_v11_0_funcs = {
+ .ras_trigger_error = psp_v11_0_ras_trigger_error,
+ .ras_cure_posion = psp_v11_0_ras_cure_posion,
+ .rlc_autoload_start = psp_v11_0_rlc_autoload_start,
++ .mem_training_init = psp_v11_0_memory_training_init,
++ .mem_training_fini = psp_v11_0_memory_training_fini,
++ .mem_training = psp_v11_0_memory_training,
+ };
+
+ void psp_v11_0_set_psp_funcs(struct psp_context *psp)
+--
+2.17.1
+