So that they can be shared among different PSP generations. And there is no need to have one copy for each PSP generation. Change-Id: I7a97f410ef5993b25f0ec3cfac4a293073d697c3 Signed-off-by: Evan Quan <evan.quan@xxxxxxx> --- drivers/gpu/drm/amd/amdgpu/Makefile | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 71 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 16 +- drivers/gpu/drm/amd/amdgpu/psp_ring.c | 353 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/psp_ring.h | 43 +++ drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 247 +---------------- drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 278 +------------------ drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 231 +--------------- 8 files changed, 444 insertions(+), 798 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/psp_ring.c create mode 100644 drivers/gpu/drm/amd/amdgpu/psp_ring.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 007478905c7b..bdcf0d4338f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -90,7 +90,8 @@ amdgpu-y += \ amdgpu_psp.o \ psp_v3_1.o \ psp_v10_0.o \ - psp_v11_0.o + psp_v11_0.o \ + psp_ring.o # add SMC block amdgpu-y += \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 8189a90637f7..38398f0c10c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -33,6 +33,21 @@ #include "psp_v10_0.h" #include "psp_v11_0.h" +#define psp_ring_init(psp, type) \ + (psp)->funcs->ring_init((psp), (type)) +#define psp_ring_create(psp, type) \ + (psp)->funcs->ring_create((psp), (type)) +#define psp_ring_stop(psp, type) \ + (psp)->funcs->ring_stop((psp), (type)) +#define psp_ring_destroy(psp, type) \ + ((psp)->funcs->ring_destroy((psp), (type))) +#define psp_prep_cmd_buf(ucode, cmd) \ + (psp)->funcs->prep_cmd_buf((ucode), (cmd)) +#define psp_submit_cmd_buf(psp, ucode, cmd, fence_mc) \ + (psp)->funcs->submit_cmd_buf((psp), (ucode), (cmd), (fence_mc)) +#define psp_support_vmr_ring(psp) \ + ((psp)->funcs->support_vmr_ring ? (psp)->funcs->support_vmr_ring((psp)) : false) + static void psp_set_funcs(struct amdgpu_device *adev); static int psp_early_init(void *handle) @@ -117,50 +132,6 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index, return -ETIME; } -static int -psp_cmd_submit_buf(struct psp_context *psp, - struct amdgpu_firmware_info *ucode, - struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr) -{ - int ret; - int index; - - memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); - - memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); - - index = atomic_inc_return(&psp->fence_value); - ret = psp_cmd_submit(psp, ucode, psp->cmd_buf_mc_addr, - fence_mc_addr, index); - if (ret) { - atomic_dec(&psp->fence_value); - return ret; - } - - while (*((unsigned int *)psp->fence_buf) != index) - msleep(1); - - /* the status field must be 0 after psp command completion */ - if (psp->cmd_buf_mem->resp.status) { - if (ucode) - DRM_ERROR("failed to load ucode id (%d) ", - ucode->ucode_id); - DRM_ERROR("psp command failed and response status is (%d)\n", - psp->cmd_buf_mem->resp.status); - return -EINVAL; - } - - /* get xGMI session id from response buffer */ - cmd->resp.session_id = psp->cmd_buf_mem->resp.session_id; - - if (ucode) { - ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo; - ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi; - } - - return ret; -} - static void psp_prep_tmr_cmd_buf(struct psp_context *psp, struct psp_gfx_cmd_resp *cmd, uint64_t tmr_mc, uint32_t size) @@ -206,7 +177,7 @@ static int psp_tmr_load(struct psp_context *psp) DRM_INFO("reserve 0x%x from 0x%llx for PSP TMR SIZE\n", PSP_TMR_SIZE, psp->tmr_mc_addr); - ret = psp_cmd_submit_buf(psp, NULL, cmd, + ret = psp_submit_cmd_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); if (ret) goto failed; @@ -273,7 +244,7 @@ static int psp_asd_load(struct psp_context *psp) psp_prep_asd_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->asd_shared_mc_addr, psp->asd_ucode_size, PSP_ASD_SHARED_MEM_SIZE); - ret = psp_cmd_submit_buf(psp, NULL, cmd, + ret = psp_submit_cmd_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); kfree(cmd); @@ -334,7 +305,7 @@ static int psp_xgmi_load(struct psp_context *psp) psp->xgmi_context.xgmi_shared_mc_addr, psp->ta_xgmi_ucode_size, PSP_XGMI_SHARED_MEM_SIZE); - ret = psp_cmd_submit_buf(psp, NULL, cmd, + ret = psp_submit_cmd_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); if (!ret) { @@ -371,7 +342,7 @@ static int psp_xgmi_unload(struct psp_context *psp) psp_prep_xgmi_ta_unload_cmd_buf(cmd, psp->xgmi_context.session_id); - ret = psp_cmd_submit_buf(psp, NULL, cmd, + ret = psp_submit_cmd_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); kfree(cmd); @@ -407,7 +378,7 @@ int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id) psp_prep_xgmi_ta_invoke_cmd_buf(cmd, ta_cmd_id, psp->xgmi_context.session_id); - ret = psp_cmd_submit_buf(psp, NULL, cmd, + ret = psp_submit_cmd_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); kfree(cmd); @@ -526,7 +497,7 @@ static int psp_np_fw_load(struct psp_context *psp) if (ret) return ret; - ret = psp_cmd_submit_buf(psp, ucode, psp->cmd, + ret = psp_submit_cmd_buf(psp, ucode, psp->cmd, psp->fence_buf_mc_addr); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 3ee573b4016e..c94fa444f8b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -74,10 +74,9 @@ struct psp_funcs enum psp_ring_type ring_type); int (*ring_destroy)(struct psp_context *psp, enum psp_ring_type ring_type); - int (*cmd_submit)(struct psp_context *psp, - struct amdgpu_firmware_info *ucode, - uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, - int index); + int (*submit_cmd_buf)(struct psp_context *psp, + struct amdgpu_firmware_info *ucode, + struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr); bool (*compare_sram_data)(struct psp_context *psp, struct amdgpu_firmware_info *ucode, enum AMDGPU_UCODE_ID ucode_type); @@ -176,13 +175,6 @@ struct psp_xgmi_topology_info { struct psp_xgmi_node_info nodes[AMDGPU_XGMI_MAX_CONNECTED_NODES]; }; -#define psp_prep_cmd_buf(ucode, type) (psp)->funcs->prep_cmd_buf((ucode), (type)) -#define psp_ring_init(psp, type) (psp)->funcs->ring_init((psp), (type)) -#define psp_ring_create(psp, type) (psp)->funcs->ring_create((psp), (type)) -#define psp_ring_stop(psp, type) (psp)->funcs->ring_stop((psp), (type)) -#define psp_ring_destroy(psp, type) ((psp)->funcs->ring_destroy((psp), (type))) -#define psp_cmd_submit(psp, ucode, cmd_mc, fence_mc, index) \ - (psp)->funcs->cmd_submit((psp), (ucode), (cmd_mc), (fence_mc), (index)) #define psp_compare_sram_data(psp, ucode, type) \ (psp)->funcs->compare_sram_data((psp), (ucode), (type)) #define psp_init_microcode(psp) \ @@ -193,8 +185,6 @@ struct psp_xgmi_topology_info { ((psp)->funcs->bootloader_load_sos ? (psp)->funcs->bootloader_load_sos((psp)) : 0) #define psp_smu_reload_quirk(psp) \ ((psp)->funcs->smu_reload_quirk ? (psp)->funcs->smu_reload_quirk((psp)) : false) -#define psp_support_vmr_ring(psp) \ - ((psp)->funcs->support_vmr_ring ? (psp)->funcs->support_vmr_ring((psp)) : false) #define psp_mode1_reset(psp) \ ((psp)->funcs->mode1_reset ? (psp)->funcs->mode1_reset((psp)) : false) #define psp_xgmi_get_node_id(psp, node_id) \ diff --git a/drivers/gpu/drm/amd/amdgpu/psp_ring.c b/drivers/gpu/drm/amd/amdgpu/psp_ring.c new file mode 100644 index 000000000000..c2f1ade51758 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/psp_ring.c @@ -0,0 +1,353 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "psp_ring.h" +#include "soc15_common.h" +#include "mp/mp_11_0_offset.h" +#include "mp/mp_11_0_sh_mask.h" + +int psp_ring_init_ring(struct psp_context *psp, + enum psp_ring_type ring_type) +{ + int ret = 0; + struct psp_ring *ring; + struct amdgpu_device *adev = psp->adev; + + ring = &psp->km_ring; + + ring->ring_type = ring_type; + + /* allocate 4k Page of Local Frame Buffer memory for ring */ + ring->ring_size = 0x1000; + ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->firmware.rbuf, + &ring->ring_mem_mc_addr, + (void **)&ring->ring_mem); + if (ret) { + ring->ring_size = 0; + return ret; + } + + return 0; +} + +bool psp_ring_support_vmr(struct psp_context *psp) +{ + struct amdgpu_device *adev = psp->adev; + + if ((adev->asic_type == CHIP_VEGA20) && + amdgpu_sriov_vf(adev) && + psp->sos_fw_version > 0x80045) + return true; + + return false; +} + +int psp_ring_create_ring(struct psp_context *psp, + enum psp_ring_type ring_type) +{ + int ret = 0; + unsigned int psp_ring_reg = 0; + struct psp_ring *ring = &psp->km_ring; + struct amdgpu_device *adev = psp->adev; + + if (psp_ring_support_vmr(psp)) { + /* Write low address of the ring to C2PMSG_102 */ + psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg); + /* Write high address of the ring to C2PMSG_103 */ + psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_103, psp_ring_reg); + + /* Write the ring initialization command to C2PMSG_101 */ + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, + GFX_CTRL_CMD_ID_INIT_GPCOM_RING); + + /* there might be handshake issue with hardware which needs delay */ + mdelay(20); + + /* Wait for response flag (bit 31) in C2PMSG_101 */ + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), + 0x80000000, 0x8000FFFF, false); + + } else { + /* Write low address of the ring to C2PMSG_69 */ + psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg); + /* Write high address of the ring to C2PMSG_70 */ + psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg); + /* Write size of ring to C2PMSG_71 */ + psp_ring_reg = ring->ring_size; + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg); + /* Write the ring initialization command to C2PMSG_64 */ + psp_ring_reg = ring_type; + psp_ring_reg = psp_ring_reg << 16; + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); + + /* there might be handshake issue with hardware which needs delay */ + mdelay(20); + + /* Wait for response flag (bit 31) in C2PMSG_64 */ + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), + 0x80000000, 0x8000FFFF, false); + } + + return ret; +} + +int psp_ring_stop_ring(struct psp_context *psp, + enum psp_ring_type ring_type) +{ + int ret = 0; + struct amdgpu_device *adev = psp->adev; + + /* Write the ring destroy command*/ + if (psp_ring_support_vmr(psp)) + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, + GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING); + else + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, + GFX_CTRL_CMD_ID_DESTROY_RINGS); + + /* there might be handshake issue with hardware which needs delay */ + mdelay(20); + + /* Wait for response flag (bit 31) */ + if (psp_ring_support_vmr(psp)) + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), + 0x80000000, 0x80000000, false); + else + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), + 0x80000000, 0x80000000, false); + + return ret; +} + +int psp_ring_destroy_ring(struct psp_context *psp, + enum psp_ring_type ring_type) +{ + int ret = 0; + struct psp_ring *ring = &psp->km_ring; + struct amdgpu_device *adev = psp->adev; + + ret = psp_ring_stop_ring(psp, ring_type); + if (ret) + DRM_ERROR("Fail to stop psp ring\n"); + + amdgpu_bo_free_kernel(&adev->firmware.rbuf, + &ring->ring_mem_mc_addr, + (void **)&ring->ring_mem); + + return ret; +} + +static int +psp_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type) +{ + switch (ucode->ucode_id) { + case AMDGPU_UCODE_ID_SDMA0: + *type = GFX_FW_TYPE_SDMA0; + break; + case AMDGPU_UCODE_ID_SDMA1: + *type = GFX_FW_TYPE_SDMA1; + break; + case AMDGPU_UCODE_ID_CP_CE: + *type = GFX_FW_TYPE_CP_CE; + break; + case AMDGPU_UCODE_ID_CP_PFP: + *type = GFX_FW_TYPE_CP_PFP; + break; + case AMDGPU_UCODE_ID_CP_ME: + *type = GFX_FW_TYPE_CP_ME; + break; + case AMDGPU_UCODE_ID_CP_MEC1: + *type = GFX_FW_TYPE_CP_MEC; + break; + case AMDGPU_UCODE_ID_CP_MEC1_JT: + *type = GFX_FW_TYPE_CP_MEC_ME1; + break; + case AMDGPU_UCODE_ID_CP_MEC2: + *type = GFX_FW_TYPE_CP_MEC; + break; + case AMDGPU_UCODE_ID_CP_MEC2_JT: + *type = GFX_FW_TYPE_CP_MEC_ME2; + break; + case AMDGPU_UCODE_ID_RLC_G: + *type = GFX_FW_TYPE_RLC_G; + break; + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL: + *type = GFX_FW_TYPE_RLC_RESTORE_LIST_CNTL; + break; + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM: + *type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM; + break; + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: + *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM; + break; + case AMDGPU_UCODE_ID_SMC: + *type = GFX_FW_TYPE_SMU; + break; + case AMDGPU_UCODE_ID_UVD: + *type = GFX_FW_TYPE_UVD; + break; + case AMDGPU_UCODE_ID_UVD1: + *type = GFX_FW_TYPE_UVD1; + break; + case AMDGPU_UCODE_ID_VCE: + *type = GFX_FW_TYPE_VCE; + break; + case AMDGPU_UCODE_ID_VCN: + *type = GFX_FW_TYPE_VCN; + break; + case AMDGPU_UCODE_ID_DMCU_ERAM: + *type = GFX_FW_TYPE_DMCU_ERAM; + break; + case AMDGPU_UCODE_ID_DMCU_INTV: + *type = GFX_FW_TYPE_DMCU_ISR; + break; + case AMDGPU_UCODE_ID_MAXIMUM: + default: + return -EINVAL; + } + + return 0; +} + +int psp_ring_prep_cmd_buf(struct amdgpu_firmware_info *ucode, + struct psp_gfx_cmd_resp *cmd) +{ + int ret; + uint64_t fw_mem_mc_addr = ucode->mc_addr; + + memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); + + cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; + cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); + cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); + cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size; + + ret = psp_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); + if (ret) + DRM_ERROR("Unknown firmware type\n"); + + return ret; +} + +static int psp_cmd_submit(struct psp_context *psp, + struct amdgpu_firmware_info *ucode, + uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, + int index) +{ + unsigned int psp_write_ptr_reg = 0; + struct psp_gfx_rb_frame *write_frame = psp->km_ring.ring_mem; + struct psp_ring *ring = &psp->km_ring; + struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem; + struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start + + ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1; + struct amdgpu_device *adev = psp->adev; + uint32_t ring_size_dw = ring->ring_size / 4; + uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; + + /* KM (GPCOM) prepare write pointer */ + if (psp_ring_support_vmr(psp)) + psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102); + else + psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67); + + /* Update KM RB frame pointer to new frame */ + /* write_frame ptr increments by size of rb_frame in bytes */ + /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */ + if ((psp_write_ptr_reg % ring_size_dw) == 0) + write_frame = ring_buffer_start; + else + write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw); + /* Check invalid write_frame ptr address */ + if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) { + DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n", + ring_buffer_start, ring_buffer_end, write_frame); + DRM_ERROR("write_frame is pointing to address out of bounds\n"); + return -EINVAL; + } + + /* Initialize KM RB frame */ + memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); + + /* Update KM RB frame */ + write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr); + write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr); + write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr); + write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr); + write_frame->fence_value = index; + + /* Update the write Pointer in DWORDs */ + psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; + if (psp_ring_support_vmr(psp)) { + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_write_ptr_reg); + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, GFX_CTRL_CMD_ID_CONSUME_CMD); + } else + WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg); + + return 0; +} + +int +psp_ring_submit_cmd_buf(struct psp_context *psp, + struct amdgpu_firmware_info *ucode, + struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr) +{ + int ret; + int index; + + memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); + + memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); + + index = atomic_inc_return(&psp->fence_value); + ret = psp_cmd_submit(psp, ucode, psp->cmd_buf_mc_addr, + fence_mc_addr, index); + if (ret) { + atomic_dec(&psp->fence_value); + return ret; + } + + while (*((unsigned int *)psp->fence_buf) != index) + msleep(1); + + /* the status field must be 0 after FW is loaded */ + if (ucode && psp->cmd_buf_mem->resp.status) { + DRM_ERROR("failed loading with status (%d) and ucode id (%d)\n", + psp->cmd_buf_mem->resp.status, ucode->ucode_id); + return -EINVAL; + } + + /* get xGMI session id from response buffer */ + cmd->resp.session_id = psp->cmd_buf_mem->resp.session_id; + + if (ucode) { + ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo; + ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi; + } + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/psp_ring.h b/drivers/gpu/drm/amd/amdgpu/psp_ring.h new file mode 100644 index 000000000000..ff7d988f175d --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/psp_ring.h @@ -0,0 +1,43 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __PSP_RING_H +#define __PSP_RING_H + +#include "amdgpu_psp.h" + +int psp_ring_init_ring(struct psp_context *psp, + enum psp_ring_type ring_type); +int psp_ring_create_ring(struct psp_context *psp, + enum psp_ring_type ring_type); +int psp_ring_stop_ring(struct psp_context *psp, + enum psp_ring_type ring_type); +int psp_ring_destroy_ring(struct psp_context *psp, + enum psp_ring_type ring_type); +int psp_ring_prep_cmd_buf(struct amdgpu_firmware_info *ucode, + struct psp_gfx_cmd_resp *cmd); +int psp_ring_submit_cmd_buf(struct psp_context *psp, + struct amdgpu_firmware_info *ucode, + struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr); +bool psp_ring_support_vmr(struct psp_context *psp); + +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c index d78b4306a36f..700a766751fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c @@ -33,80 +33,12 @@ #include "mp/mp_10_0_offset.h" #include "gc/gc_9_1_offset.h" #include "sdma0/sdma0_4_1_offset.h" +#include "psp_ring.h" MODULE_FIRMWARE("amdgpu/raven_asd.bin"); MODULE_FIRMWARE("amdgpu/picasso_asd.bin"); MODULE_FIRMWARE("amdgpu/raven2_asd.bin"); -static int -psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type) -{ - switch(ucode->ucode_id) { - case AMDGPU_UCODE_ID_SDMA0: - *type = GFX_FW_TYPE_SDMA0; - break; - case AMDGPU_UCODE_ID_SDMA1: - *type = GFX_FW_TYPE_SDMA1; - break; - case AMDGPU_UCODE_ID_CP_CE: - *type = GFX_FW_TYPE_CP_CE; - break; - case AMDGPU_UCODE_ID_CP_PFP: - *type = GFX_FW_TYPE_CP_PFP; - break; - case AMDGPU_UCODE_ID_CP_ME: - *type = GFX_FW_TYPE_CP_ME; - break; - case AMDGPU_UCODE_ID_CP_MEC1: - *type = GFX_FW_TYPE_CP_MEC; - break; - case AMDGPU_UCODE_ID_CP_MEC1_JT: - *type = GFX_FW_TYPE_CP_MEC_ME1; - break; - case AMDGPU_UCODE_ID_CP_MEC2: - *type = GFX_FW_TYPE_CP_MEC; - break; - case AMDGPU_UCODE_ID_CP_MEC2_JT: - *type = GFX_FW_TYPE_CP_MEC_ME2; - break; - case AMDGPU_UCODE_ID_RLC_G: - *type = GFX_FW_TYPE_RLC_G; - break; - case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL: - *type = GFX_FW_TYPE_RLC_RESTORE_LIST_CNTL; - break; - case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM: - *type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM; - break; - case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: - *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM; - break; - case AMDGPU_UCODE_ID_SMC: - *type = GFX_FW_TYPE_SMU; - break; - case AMDGPU_UCODE_ID_UVD: - *type = GFX_FW_TYPE_UVD; - break; - case AMDGPU_UCODE_ID_VCE: - *type = GFX_FW_TYPE_VCE; - break; - case AMDGPU_UCODE_ID_VCN: - *type = GFX_FW_TYPE_VCN; - break; - case AMDGPU_UCODE_ID_DMCU_ERAM: - *type = GFX_FW_TYPE_DMCU_ERAM; - break; - case AMDGPU_UCODE_ID_DMCU_INTV: - *type = GFX_FW_TYPE_DMCU_ISR; - break; - case AMDGPU_UCODE_ID_MAXIMUM: - default: - return -EINVAL; - } - - return 0; -} - static int psp_v10_0_init_microcode(struct psp_context *psp) { struct amdgpu_device *adev = psp->adev; @@ -158,171 +90,6 @@ static int psp_v10_0_init_microcode(struct psp_context *psp) return err; } -static int psp_v10_0_prep_cmd_buf(struct amdgpu_firmware_info *ucode, - struct psp_gfx_cmd_resp *cmd) -{ - int ret; - uint64_t fw_mem_mc_addr = ucode->mc_addr; - - memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); - - cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; - cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); - cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); - cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size; - - ret = psp_v10_0_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); - if (ret) - DRM_ERROR("Unknown firmware type\n"); - - return ret; -} - -static int psp_v10_0_ring_init(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - struct psp_ring *ring; - struct amdgpu_device *adev = psp->adev; - - ring = &psp->km_ring; - - ring->ring_type = ring_type; - - /* allocate 4k Page of Local Frame Buffer memory for ring */ - ring->ring_size = 0x1000; - ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->firmware.rbuf, - &ring->ring_mem_mc_addr, - (void **)&ring->ring_mem); - if (ret) { - ring->ring_size = 0; - return ret; - } - - return 0; -} - -static int psp_v10_0_ring_create(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - unsigned int psp_ring_reg = 0; - struct psp_ring *ring = &psp->km_ring; - struct amdgpu_device *adev = psp->adev; - - /* Write low address of the ring to C2PMSG_69 */ - psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg); - /* Write high address of the ring to C2PMSG_70 */ - psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg); - /* Write size of ring to C2PMSG_71 */ - psp_ring_reg = ring->ring_size; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg); - /* Write the ring initialization command to C2PMSG_64 */ - psp_ring_reg = ring_type; - psp_ring_reg = psp_ring_reg << 16; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); - - /* There might be handshake issue with hardware which needs delay */ - mdelay(20); - - /* Wait for response flag (bit 31) in C2PMSG_64 */ - ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), - 0x80000000, 0x8000FFFF, false); - - return ret; -} - -static int psp_v10_0_ring_stop(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - unsigned int psp_ring_reg = 0; - struct amdgpu_device *adev = psp->adev; - - /* Write the ring destroy command to C2PMSG_64 */ - psp_ring_reg = 3 << 16; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); - - /* There might be handshake issue with hardware which needs delay */ - mdelay(20); - - /* Wait for response flag (bit 31) in C2PMSG_64 */ - ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), - 0x80000000, 0x80000000, false); - - return ret; -} - -static int psp_v10_0_ring_destroy(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - struct psp_ring *ring = &psp->km_ring; - struct amdgpu_device *adev = psp->adev; - - ret = psp_v10_0_ring_stop(psp, ring_type); - if (ret) - DRM_ERROR("Fail to stop psp ring\n"); - - amdgpu_bo_free_kernel(&adev->firmware.rbuf, - &ring->ring_mem_mc_addr, - (void **)&ring->ring_mem); - - return ret; -} - -static int psp_v10_0_cmd_submit(struct psp_context *psp, - struct amdgpu_firmware_info *ucode, - uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, - int index) -{ - unsigned int psp_write_ptr_reg = 0; - struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem; - struct psp_ring *ring = &psp->km_ring; - struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem; - struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start + - ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1; - struct amdgpu_device *adev = psp->adev; - uint32_t ring_size_dw = ring->ring_size / 4; - uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; - - /* KM (GPCOM) prepare write pointer */ - psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67); - - /* Update KM RB frame pointer to new frame */ - if ((psp_write_ptr_reg % ring_size_dw) == 0) - write_frame = ring_buffer_start; - else - write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw); - /* Check invalid write_frame ptr address */ - if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) { - DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n", - ring_buffer_start, ring_buffer_end, write_frame); - DRM_ERROR("write_frame is pointing to address out of bounds\n"); - return -EINVAL; - } - - /* Initialize KM RB frame */ - memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); - - /* Update KM RB frame */ - write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr); - write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr); - write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr); - write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr); - write_frame->fence_value = index; - - /* Update the write Pointer in DWORDs */ - psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg); - - return 0; -} - static int psp_v10_0_sram_map(struct amdgpu_device *adev, unsigned int *sram_offset, unsigned int *sram_addr_reg_offset, @@ -454,12 +221,12 @@ static int psp_v10_0_mode1_reset(struct psp_context *psp) static const struct psp_funcs psp_v10_0_funcs = { .init_microcode = psp_v10_0_init_microcode, - .prep_cmd_buf = psp_v10_0_prep_cmd_buf, - .ring_init = psp_v10_0_ring_init, - .ring_create = psp_v10_0_ring_create, - .ring_stop = psp_v10_0_ring_stop, - .ring_destroy = psp_v10_0_ring_destroy, - .cmd_submit = psp_v10_0_cmd_submit, + .ring_init = psp_ring_init_ring, + .ring_create = psp_ring_create_ring, + .ring_stop = psp_ring_stop_ring, + .ring_destroy = psp_ring_destroy_ring, + .prep_cmd_buf = psp_ring_prep_cmd_buf, + .submit_cmd_buf = psp_ring_submit_cmd_buf, .compare_sram_data = psp_v10_0_compare_sram_data, .mode1_reset = psp_v10_0_mode1_reset, }; diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index 0c6e7f9b143f..43487d97a0cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -32,6 +32,7 @@ #include "gc/gc_9_0_offset.h" #include "sdma0/sdma0_4_0_offset.h" #include "nbio/nbio_7_4_offset.h" +#include "psp_ring.h" MODULE_FIRMWARE("amdgpu/vega20_sos.bin"); MODULE_FIRMWARE("amdgpu/vega20_asd.bin"); @@ -40,60 +41,6 @@ MODULE_FIRMWARE("amdgpu/vega20_ta.bin"); /* address block */ #define smnMP1_FIRMWARE_FLAGS 0x3010024 -static int -psp_v11_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type) -{ - switch (ucode->ucode_id) { - case AMDGPU_UCODE_ID_SDMA0: - *type = GFX_FW_TYPE_SDMA0; - break; - case AMDGPU_UCODE_ID_SDMA1: - *type = GFX_FW_TYPE_SDMA1; - break; - case AMDGPU_UCODE_ID_CP_CE: - *type = GFX_FW_TYPE_CP_CE; - break; - case AMDGPU_UCODE_ID_CP_PFP: - *type = GFX_FW_TYPE_CP_PFP; - break; - case AMDGPU_UCODE_ID_CP_ME: - *type = GFX_FW_TYPE_CP_ME; - break; - case AMDGPU_UCODE_ID_CP_MEC1: - *type = GFX_FW_TYPE_CP_MEC; - break; - case AMDGPU_UCODE_ID_CP_MEC1_JT: - *type = GFX_FW_TYPE_CP_MEC_ME1; - break; - case AMDGPU_UCODE_ID_CP_MEC2: - *type = GFX_FW_TYPE_CP_MEC; - break; - case AMDGPU_UCODE_ID_CP_MEC2_JT: - *type = GFX_FW_TYPE_CP_MEC_ME2; - break; - case AMDGPU_UCODE_ID_RLC_G: - *type = GFX_FW_TYPE_RLC_G; - break; - case AMDGPU_UCODE_ID_SMC: - *type = GFX_FW_TYPE_SMU; - break; - case AMDGPU_UCODE_ID_UVD: - *type = GFX_FW_TYPE_UVD; - break; - case AMDGPU_UCODE_ID_VCE: - *type = GFX_FW_TYPE_VCE; - break; - case AMDGPU_UCODE_ID_UVD1: - *type = GFX_FW_TYPE_UVD1; - break; - case AMDGPU_UCODE_ID_MAXIMUM: - default: - return -EINVAL; - } - - return 0; -} - static int psp_v11_0_init_microcode(struct psp_context *psp) { struct amdgpu_device *adev = psp->adev; @@ -267,215 +214,6 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp) return ret; } -static int psp_v11_0_prep_cmd_buf(struct amdgpu_firmware_info *ucode, - struct psp_gfx_cmd_resp *cmd) -{ - int ret; - uint64_t fw_mem_mc_addr = ucode->mc_addr; - - memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); - - cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; - cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); - cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); - cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size; - - ret = psp_v11_0_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); - if (ret) - DRM_ERROR("Unknown firmware type\n"); - - return ret; -} - -static int psp_v11_0_ring_init(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - struct psp_ring *ring; - struct amdgpu_device *adev = psp->adev; - - ring = &psp->km_ring; - - ring->ring_type = ring_type; - - /* allocate 4k Page of Local Frame Buffer memory for ring */ - ring->ring_size = 0x1000; - ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->firmware.rbuf, - &ring->ring_mem_mc_addr, - (void **)&ring->ring_mem); - if (ret) { - ring->ring_size = 0; - return ret; - } - - return 0; -} - -static bool psp_v11_0_support_vmr_ring(struct psp_context *psp) -{ - if (amdgpu_sriov_vf(psp->adev) && psp->sos_fw_version > 0x80045) - return true; - return false; -} - -static int psp_v11_0_ring_create(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - unsigned int psp_ring_reg = 0; - struct psp_ring *ring = &psp->km_ring; - struct amdgpu_device *adev = psp->adev; - - if (psp_v11_0_support_vmr_ring(psp)) { - /* Write low address of the ring to C2PMSG_102 */ - psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg); - /* Write high address of the ring to C2PMSG_103 */ - psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_103, psp_ring_reg); - - /* Write the ring initialization command to C2PMSG_101 */ - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, - GFX_CTRL_CMD_ID_INIT_GPCOM_RING); - - /* there might be handshake issue with hardware which needs delay */ - mdelay(20); - - /* Wait for response flag (bit 31) in C2PMSG_101 */ - ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), - 0x80000000, 0x8000FFFF, false); - - } else { - /* Write low address of the ring to C2PMSG_69 */ - psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg); - /* Write high address of the ring to C2PMSG_70 */ - psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg); - /* Write size of ring to C2PMSG_71 */ - psp_ring_reg = ring->ring_size; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg); - /* Write the ring initialization command to C2PMSG_64 */ - psp_ring_reg = ring_type; - psp_ring_reg = psp_ring_reg << 16; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); - - /* there might be handshake issue with hardware which needs delay */ - mdelay(20); - - /* Wait for response flag (bit 31) in C2PMSG_64 */ - ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), - 0x80000000, 0x8000FFFF, false); - } - - return ret; -} - -static int psp_v11_0_ring_stop(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - struct amdgpu_device *adev = psp->adev; - - /* Write the ring destroy command*/ - if (psp_v11_0_support_vmr_ring(psp)) - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, - GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING); - else - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, - GFX_CTRL_CMD_ID_DESTROY_RINGS); - - /* there might be handshake issue with hardware which needs delay */ - mdelay(20); - - /* Wait for response flag (bit 31) */ - if (psp_v11_0_support_vmr_ring(psp)) - ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), - 0x80000000, 0x80000000, false); - else - ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), - 0x80000000, 0x80000000, false); - - return ret; -} - -static int psp_v11_0_ring_destroy(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - struct psp_ring *ring = &psp->km_ring; - struct amdgpu_device *adev = psp->adev; - - ret = psp_v11_0_ring_stop(psp, ring_type); - if (ret) - DRM_ERROR("Fail to stop psp ring\n"); - - amdgpu_bo_free_kernel(&adev->firmware.rbuf, - &ring->ring_mem_mc_addr, - (void **)&ring->ring_mem); - - return ret; -} - -static int psp_v11_0_cmd_submit(struct psp_context *psp, - struct amdgpu_firmware_info *ucode, - uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, - int index) -{ - unsigned int psp_write_ptr_reg = 0; - struct psp_gfx_rb_frame *write_frame = psp->km_ring.ring_mem; - struct psp_ring *ring = &psp->km_ring; - struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem; - struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start + - ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1; - struct amdgpu_device *adev = psp->adev; - uint32_t ring_size_dw = ring->ring_size / 4; - uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; - - /* KM (GPCOM) prepare write pointer */ - if (psp_v11_0_support_vmr_ring(psp)) - psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102); - else - psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67); - - /* Update KM RB frame pointer to new frame */ - /* write_frame ptr increments by size of rb_frame in bytes */ - /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */ - if ((psp_write_ptr_reg % ring_size_dw) == 0) - write_frame = ring_buffer_start; - else - write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw); - /* Check invalid write_frame ptr address */ - if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) { - DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n", - ring_buffer_start, ring_buffer_end, write_frame); - DRM_ERROR("write_frame is pointing to address out of bounds\n"); - return -EINVAL; - } - - /* Initialize KM RB frame */ - memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); - - /* Update KM RB frame */ - write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr); - write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr); - write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr); - write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr); - write_frame->fence_value = index; - - /* Update the write Pointer in DWORDs */ - psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; - if (psp_v11_0_support_vmr_ring(psp)) { - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_write_ptr_reg); - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, GFX_CTRL_CMD_ID_CONSUME_CMD); - } else - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg); - - return 0; -} - static int psp_v11_0_sram_map(struct amdgpu_device *adev, unsigned int *sram_offset, unsigned int *sram_addr_reg_offset, @@ -753,19 +491,19 @@ static const struct psp_funcs psp_v11_0_funcs = { .init_microcode = psp_v11_0_init_microcode, .bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv, .bootloader_load_sos = psp_v11_0_bootloader_load_sos, - .prep_cmd_buf = psp_v11_0_prep_cmd_buf, - .ring_init = psp_v11_0_ring_init, - .ring_create = psp_v11_0_ring_create, - .ring_stop = psp_v11_0_ring_stop, - .ring_destroy = psp_v11_0_ring_destroy, - .cmd_submit = psp_v11_0_cmd_submit, + .ring_init = psp_ring_init_ring, + .ring_create = psp_ring_create_ring, + .ring_stop = psp_ring_stop_ring, + .ring_destroy = psp_ring_destroy_ring, + .prep_cmd_buf = psp_ring_prep_cmd_buf, + .submit_cmd_buf = psp_ring_submit_cmd_buf, + .support_vmr_ring = psp_ring_support_vmr, .compare_sram_data = psp_v11_0_compare_sram_data, .mode1_reset = psp_v11_0_mode1_reset, .xgmi_get_topology_info = psp_v11_0_xgmi_get_topology_info, .xgmi_set_topology_info = psp_v11_0_xgmi_set_topology_info, .xgmi_get_hive_id = psp_v11_0_xgmi_get_hive_id, .xgmi_get_node_id = psp_v11_0_xgmi_get_node_id, - .support_vmr_ring = psp_v11_0_support_vmr_ring, }; void psp_v11_0_set_psp_funcs(struct psp_context *psp) diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c index 79694ff16969..b74dd556a573 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c @@ -36,6 +36,7 @@ #include "gc/gc_9_0_offset.h" #include "sdma0/sdma0_4_0_offset.h" #include "nbio/nbio_6_1_offset.h" +#include "psp_ring.h" MODULE_FIRMWARE("amdgpu/vega10_sos.bin"); MODULE_FIRMWARE("amdgpu/vega10_asd.bin"); @@ -47,57 +48,6 @@ MODULE_FIRMWARE("amdgpu/vega12_asd.bin"); static uint32_t sos_old_versions[] = {1517616, 1510592, 1448594, 1446554}; -static int -psp_v3_1_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type) -{ - switch(ucode->ucode_id) { - case AMDGPU_UCODE_ID_SDMA0: - *type = GFX_FW_TYPE_SDMA0; - break; - case AMDGPU_UCODE_ID_SDMA1: - *type = GFX_FW_TYPE_SDMA1; - break; - case AMDGPU_UCODE_ID_CP_CE: - *type = GFX_FW_TYPE_CP_CE; - break; - case AMDGPU_UCODE_ID_CP_PFP: - *type = GFX_FW_TYPE_CP_PFP; - break; - case AMDGPU_UCODE_ID_CP_ME: - *type = GFX_FW_TYPE_CP_ME; - break; - case AMDGPU_UCODE_ID_CP_MEC1: - *type = GFX_FW_TYPE_CP_MEC; - break; - case AMDGPU_UCODE_ID_CP_MEC1_JT: - *type = GFX_FW_TYPE_CP_MEC_ME1; - break; - case AMDGPU_UCODE_ID_CP_MEC2: - *type = GFX_FW_TYPE_CP_MEC; - break; - case AMDGPU_UCODE_ID_CP_MEC2_JT: - *type = GFX_FW_TYPE_CP_MEC_ME2; - break; - case AMDGPU_UCODE_ID_RLC_G: - *type = GFX_FW_TYPE_RLC_G; - break; - case AMDGPU_UCODE_ID_SMC: - *type = GFX_FW_TYPE_SMU; - break; - case AMDGPU_UCODE_ID_UVD: - *type = GFX_FW_TYPE_UVD; - break; - case AMDGPU_UCODE_ID_VCE: - *type = GFX_FW_TYPE_VCE; - break; - case AMDGPU_UCODE_ID_MAXIMUM: - default: - return -EINVAL; - } - - return 0; -} - static int psp_v3_1_init_microcode(struct psp_context *psp) { struct amdgpu_device *adev = psp->adev; @@ -277,173 +227,6 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp) return ret; } -static int psp_v3_1_prep_cmd_buf(struct amdgpu_firmware_info *ucode, - struct psp_gfx_cmd_resp *cmd) -{ - int ret; - uint64_t fw_mem_mc_addr = ucode->mc_addr; - - memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); - - cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; - cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); - cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); - cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size; - - ret = psp_v3_1_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); - if (ret) - DRM_ERROR("Unknown firmware type\n"); - - return ret; -} - -static int psp_v3_1_ring_init(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - struct psp_ring *ring; - struct amdgpu_device *adev = psp->adev; - - ring = &psp->km_ring; - - ring->ring_type = ring_type; - - /* allocate 4k Page of Local Frame Buffer memory for ring */ - ring->ring_size = 0x1000; - ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->firmware.rbuf, - &ring->ring_mem_mc_addr, - (void **)&ring->ring_mem); - if (ret) { - ring->ring_size = 0; - return ret; - } - - return 0; -} - -static int psp_v3_1_ring_create(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - unsigned int psp_ring_reg = 0; - struct psp_ring *ring = &psp->km_ring; - struct amdgpu_device *adev = psp->adev; - - /* Write low address of the ring to C2PMSG_69 */ - psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg); - /* Write high address of the ring to C2PMSG_70 */ - psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg); - /* Write size of ring to C2PMSG_71 */ - psp_ring_reg = ring->ring_size; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg); - /* Write the ring initialization command to C2PMSG_64 */ - psp_ring_reg = ring_type; - psp_ring_reg = psp_ring_reg << 16; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); - - /* there might be handshake issue with hardware which needs delay */ - mdelay(20); - - /* Wait for response flag (bit 31) in C2PMSG_64 */ - ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), - 0x80000000, 0x8000FFFF, false); - - return ret; -} - -static int psp_v3_1_ring_stop(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - unsigned int psp_ring_reg = 0; - struct amdgpu_device *adev = psp->adev; - - /* Write the ring destroy command to C2PMSG_64 */ - psp_ring_reg = 3 << 16; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); - - /* there might be handshake issue with hardware which needs delay */ - mdelay(20); - - /* Wait for response flag (bit 31) in C2PMSG_64 */ - ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), - 0x80000000, 0x80000000, false); - - return ret; -} - -static int psp_v3_1_ring_destroy(struct psp_context *psp, - enum psp_ring_type ring_type) -{ - int ret = 0; - struct psp_ring *ring = &psp->km_ring; - struct amdgpu_device *adev = psp->adev; - - ret = psp_v3_1_ring_stop(psp, ring_type); - if (ret) - DRM_ERROR("Fail to stop psp ring\n"); - - amdgpu_bo_free_kernel(&adev->firmware.rbuf, - &ring->ring_mem_mc_addr, - (void **)&ring->ring_mem); - - return ret; -} - -static int psp_v3_1_cmd_submit(struct psp_context *psp, - struct amdgpu_firmware_info *ucode, - uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, - int index) -{ - unsigned int psp_write_ptr_reg = 0; - struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem; - struct psp_ring *ring = &psp->km_ring; - struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem; - struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start + - ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1; - struct amdgpu_device *adev = psp->adev; - uint32_t ring_size_dw = ring->ring_size / 4; - uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; - - /* KM (GPCOM) prepare write pointer */ - psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67); - - /* Update KM RB frame pointer to new frame */ - /* write_frame ptr increments by size of rb_frame in bytes */ - /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */ - if ((psp_write_ptr_reg % ring_size_dw) == 0) - write_frame = ring_buffer_start; - else - write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw); - /* Check invalid write_frame ptr address */ - if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) { - DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n", - ring_buffer_start, ring_buffer_end, write_frame); - DRM_ERROR("write_frame is pointing to address out of bounds\n"); - return -EINVAL; - } - - /* Initialize KM RB frame */ - memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); - - /* Update KM RB frame */ - write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr); - write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr); - write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr); - write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr); - write_frame->fence_value = index; - - /* Update the write Pointer in DWORDs */ - psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; - WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg); - - return 0; -} - static int psp_v3_1_sram_map(struct amdgpu_device *adev, unsigned int *sram_offset, unsigned int *sram_addr_reg_offset, @@ -615,12 +398,12 @@ static const struct psp_funcs psp_v3_1_funcs = { .init_microcode = psp_v3_1_init_microcode, .bootloader_load_sysdrv = psp_v3_1_bootloader_load_sysdrv, .bootloader_load_sos = psp_v3_1_bootloader_load_sos, - .prep_cmd_buf = psp_v3_1_prep_cmd_buf, - .ring_init = psp_v3_1_ring_init, - .ring_create = psp_v3_1_ring_create, - .ring_stop = psp_v3_1_ring_stop, - .ring_destroy = psp_v3_1_ring_destroy, - .cmd_submit = psp_v3_1_cmd_submit, + .ring_init = psp_ring_init_ring, + .ring_create = psp_ring_create_ring, + .ring_stop = psp_ring_stop_ring, + .ring_destroy = psp_ring_destroy_ring, + .prep_cmd_buf = psp_ring_prep_cmd_buf, + .submit_cmd_buf = psp_ring_submit_cmd_buf, .compare_sram_data = psp_v3_1_compare_sram_data, .smu_reload_quirk = psp_v3_1_smu_reload_quirk, .mode1_reset = psp_v3_1_mode1_reset, -- 2.20.1 _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx