drm/amdgpu: Guard against write accesses after device removal
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / amdgpu / psp_v11_0.c
index 589410c..2cec71e 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/firmware.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
+#include <drm/drm_drv.h>
 
 #include "amdgpu.h"
 #include "amdgpu_psp.h"
@@ -269,10 +270,8 @@ static int psp_v11_0_bootloader_load_kdb(struct psp_context *psp)
        if (ret)
                return ret;
 
-       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
        /* Copy PSP KDB binary to memory */
-       memcpy(psp->fw_pri_buf, psp->kdb_start_addr, psp->kdb_bin_size);
+       psp_copy_fw(psp, psp->kdb_start_addr, psp->kdb_bin_size);
 
        /* Provide the PSP KDB to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -302,10 +301,8 @@ static int psp_v11_0_bootloader_load_spl(struct psp_context *psp)
        if (ret)
                return ret;
 
-       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
        /* Copy PSP SPL binary to memory */
-       memcpy(psp->fw_pri_buf, psp->spl_start_addr, psp->spl_bin_size);
+       psp_copy_fw(psp, psp->spl_start_addr, psp->spl_bin_size);
 
        /* Provide the PSP SPL to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -335,10 +332,8 @@ static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp)
        if (ret)
                return ret;
 
-       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
        /* Copy PSP System Driver binary to memory */
-       memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size);
+       psp_copy_fw(psp, psp->sys_start_addr, psp->sys_bin_size);
 
        /* Provide the sys driver to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -371,10 +366,8 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
        if (ret)
                return ret;
 
-       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
-
        /* Copy Secure OS binary to PSP memory */
-       memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size);
+       psp_copy_fw(psp, psp->sos_start_addr, psp->sos_bin_size);
 
        /* Provide the PSP secure OS to bootloader */
        WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
@@ -608,7 +601,7 @@ static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)
        uint32_t p2c_header[4];
        uint32_t sz;
        void *buf;
-       int ret;
+       int ret, idx;
 
        if (ctx->init == PSP_MEM_TRAIN_NOT_SUPPORT) {
                DRM_DEBUG("Memory training is not supported.\n");
@@ -681,17 +674,24 @@ static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)
                        return -ENOMEM;
                }
 
-               memcpy_fromio(buf, adev->mman.aper_base_kaddr, sz);
-               ret = psp_v11_0_memory_training_send_msg(psp, PSP_BL__DRAM_LONG_TRAIN);
-               if (ret) {
-                       DRM_ERROR("Send long training msg failed.\n");
+               if (drm_dev_enter(&adev->ddev, &idx)) {
+                       memcpy_fromio(buf, adev->mman.aper_base_kaddr, sz);
+                       ret = psp_v11_0_memory_training_send_msg(psp, PSP_BL__DRAM_LONG_TRAIN);
+                       if (ret) {
+                               DRM_ERROR("Send long training msg failed.\n");
+                               vfree(buf);
+                               drm_dev_exit(idx);
+                               return ret;
+                       }
+
+                       memcpy_toio(adev->mman.aper_base_kaddr, buf, sz);
+                       adev->hdp.funcs->flush_hdp(adev, NULL);
                        vfree(buf);
-                       return ret;
+                       drm_dev_exit(idx);
+               } else {
+                       vfree(buf);
+                       return -ENODEV;
                }
-
-               memcpy_toio(adev->mman.aper_base_kaddr, buf, sz);
-               adev->hdp.funcs->flush_hdp(adev, NULL);
-               vfree(buf);
        }
 
        if (ops & PSP_MEM_TRAIN_SAVE) {