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 index) { int ret; memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); ret = psp_cmd_submit(psp, ucode, psp->cmd_buf_mc_addr, fence_mc_addr, index); 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; } 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 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; int timeout = 2000; 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) { if (--timeout == 0) break; msleep(1); } /* In some cases, psp response status is not 0 even there is no * problem while the command is submitted. Some version of PSP FW * doesn't write 0 to that field. * So here we would like to only print a warning instead of an error * during psp initialization to avoid breaking hw_init and it doesn't * return -EINVAL. */ if (psp->cmd_buf_mem->resp.status || !timeout) { if (ucode) DRM_WARN("failed to load ucode id (%d) ", ucode->ucode_id); DRM_WARN("psp command failed and response status is (%d)\n", psp->cmd_buf_mem->resp.status); if (!timeout) 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 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 index) { int ret; struct amdgpu_bo *cmd_buf_bo; uint64_t cmd_buf_mc_addr; struct psp_gfx_cmd_resp *cmd_buf_mem; struct amdgpu_device *adev = psp->adev; ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, &cmd_buf_bo, &cmd_buf_mc_addr, (void **)&cmd_buf_mem); if (ret) return ret; memset(cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); memcpy(cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); ret = psp_cmd_submit(psp, ucode, cmd_buf_mc_addr, fence_mc_addr, index); while (*((unsigned int *)psp->fence_buf) != index) { msleep(1); } amdgpu_bo_free_kernel(&cmd_buf_bo, &cmd_buf_mc_addr, (void **)&cmd_buf_mem); return ret; }