summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2020-07-23 08:38:10 +0300
committerDave Airlie <airlied@redhat.com>2020-07-23 08:38:11 +0300
commit206739119508d5ab4b42ab480ff61a7e6cd72d7c (patch)
tree756285714f5b842e223e22a75d17521c9f41ae55 /drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
parent959ed53808d171cf5203cdc74578db55d0c79822 (diff)
parent6e14adea0ac3037d923a9591d1a094c115d7947c (diff)
downloadlinux-206739119508d5ab4b42ab480ff61a7e6cd72d7c.tar.xz
Merge tag 'amd-drm-next-5.9-2020-07-17' of git://people.freedesktop.org/~agd5f/linux into drm-next
amd-drm-next-5.9-2020-07-17: amdgpu: - SI UVD/VCE clock support - Updates for Sienna Cichlid - Expose drm rotation property - Atomfirmware updates for renoir - updates to GPUVM hub handling for different register layouts - swSMU restructuring and cleanups - RAS fixes - DC fixes - mode1 reset support for Sienna Cichlid - Add support for Navy Flounder GPUs amdkfd: - Add SMI events watch interface UAPI: - Add amdkfd SMI events watch interface Userspace which uses this interface: https://github.com/RadeonOpenCompute/rocm_smi_lib/commit/2235ede34c456f1c7d3490f6fe74825d442d272e Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexdeucher@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200717132022.4014-1-alexander.deucher@amd.com
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c172
1 files changed, 166 insertions, 6 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 9342a9e8cadf..aa80cf799e42 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -99,6 +99,7 @@ static int psp_early_init(void *handle)
case CHIP_NAVI14:
case CHIP_NAVI12:
case CHIP_SIENNA_CICHLID:
+ case CHIP_NAVY_FLOUNDER:
psp_v11_0_set_psp_funcs(psp);
psp->autoload_supported = true;
break;
@@ -430,6 +431,52 @@ static int psp_tmr_load(struct psp_context *psp)
return ret;
}
+static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp,
+ struct psp_gfx_cmd_resp *cmd)
+{
+ if (amdgpu_sriov_vf(psp->adev))
+ cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR;
+ else
+ cmd->cmd_id = GFX_CMD_ID_DESTROY_TMR;
+}
+
+static int psp_tmr_unload(struct psp_context *psp)
+{
+ int ret;
+ struct psp_gfx_cmd_resp *cmd;
+
+ cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ psp_prep_tmr_unload_cmd_buf(psp, cmd);
+ DRM_INFO("free PSP TMR buffer\n");
+
+ ret = psp_cmd_submit_buf(psp, NULL, cmd,
+ psp->fence_buf_mc_addr);
+
+ kfree(cmd);
+
+ return ret;
+}
+
+static int psp_tmr_terminate(struct psp_context *psp)
+{
+ int ret;
+ void *tmr_buf;
+ void **pptr;
+
+ ret = psp_tmr_unload(psp);
+ if (ret)
+ return ret;
+
+ /* free TMR memory buffer */
+ pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
+ amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr);
+
+ return 0;
+}
+
static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
uint64_t asd_mc, uint32_t size)
{
@@ -452,7 +499,9 @@ static int psp_asd_load(struct psp_context *psp)
* add workaround to bypass it for sriov now.
* TODO: add version check to make it common
*/
- if (amdgpu_sriov_vf(psp->adev) || (psp->adev->asic_type == CHIP_SIENNA_CICHLID))
+ if (amdgpu_sriov_vf(psp->adev) ||
+ (psp->adev->asic_type == CHIP_SIENNA_CICHLID) ||
+ (psp->adev->asic_type == CHIP_NAVY_FLOUNDER))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
@@ -1717,7 +1766,8 @@ static int psp_np_fw_load(struct psp_context *psp)
continue;
if (psp->autoload_supported &&
- adev->asic_type == CHIP_SIENNA_CICHLID &&
+ (adev->asic_type == CHIP_SIENNA_CICHLID ||
+ adev->asic_type == CHIP_NAVY_FLOUNDER) &&
(ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 ||
ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 ||
ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3))
@@ -1866,8 +1916,6 @@ static int psp_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct psp_context *psp = &adev->psp;
- void *tmr_buf;
- void **pptr;
int ret;
if (psp->adev->psp.ta_fw) {
@@ -1883,10 +1931,9 @@ static int psp_hw_fini(void *handle)
return ret;
}
+ psp_tmr_terminate(psp);
psp_ring_destroy(psp, PSP_RING_TYPE__KM);
- pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
- amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr);
amdgpu_bo_free_kernel(&psp->fw_pri_bo,
&psp->fw_pri_mc_addr, &psp->fw_pri_buf);
amdgpu_bo_free_kernel(&psp->fence_buf_bo,
@@ -1933,6 +1980,18 @@ static int psp_suspend(void *handle)
}
}
+ ret = psp_asd_unload(psp);
+ if (ret) {
+ DRM_ERROR("Failed to unload asd\n");
+ return ret;
+ }
+
+ ret = psp_tmr_terminate(psp);
+ if (ret) {
+ DRM_ERROR("Failed to terminate tmr\n");
+ return ret;
+ }
+
ret = psp_ring_stop(psp, PSP_RING_TYPE__KM);
if (ret) {
DRM_ERROR("PSP ring stop failed\n");
@@ -2222,6 +2281,107 @@ out:
return err;
}
+int parse_ta_bin_descriptor(struct psp_context *psp,
+ const struct ta_fw_bin_desc *desc,
+ const struct ta_firmware_header_v2_0 *ta_hdr)
+{
+ uint8_t *ucode_start_addr = NULL;
+
+ if (!psp || !desc || !ta_hdr)
+ return -EINVAL;
+
+ ucode_start_addr = (uint8_t *)ta_hdr +
+ le32_to_cpu(desc->offset_bytes) +
+ le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+
+ switch (desc->fw_type) {
+ case TA_FW_TYPE_PSP_ASD:
+ psp->asd_fw_version = le32_to_cpu(desc->fw_version);
+ psp->asd_feature_version = le32_to_cpu(desc->fw_version);
+ psp->asd_ucode_size = le32_to_cpu(desc->size_bytes);
+ psp->asd_start_addr = ucode_start_addr;
+ break;
+ case TA_FW_TYPE_PSP_XGMI:
+ psp->ta_xgmi_ucode_version = le32_to_cpu(desc->fw_version);
+ psp->ta_xgmi_ucode_size = le32_to_cpu(desc->size_bytes);
+ psp->ta_xgmi_start_addr = ucode_start_addr;
+ break;
+ case TA_FW_TYPE_PSP_RAS:
+ psp->ta_ras_ucode_version = le32_to_cpu(desc->fw_version);
+ psp->ta_ras_ucode_size = le32_to_cpu(desc->size_bytes);
+ psp->ta_ras_start_addr = ucode_start_addr;
+ break;
+ case TA_FW_TYPE_PSP_HDCP:
+ psp->ta_hdcp_ucode_version = le32_to_cpu(desc->fw_version);
+ psp->ta_hdcp_ucode_size = le32_to_cpu(desc->size_bytes);
+ psp->ta_hdcp_start_addr = ucode_start_addr;
+ break;
+ case TA_FW_TYPE_PSP_DTM:
+ psp->ta_dtm_ucode_version = le32_to_cpu(desc->fw_version);
+ psp->ta_dtm_ucode_size = le32_to_cpu(desc->size_bytes);
+ psp->ta_dtm_start_addr = ucode_start_addr;
+ break;
+ default:
+ dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type);
+ break;
+ }
+
+ return 0;
+}
+
+int psp_init_ta_microcode(struct psp_context *psp,
+ const char *chip_name)
+{
+ struct amdgpu_device *adev = psp->adev;
+ char fw_name[30];
+ const struct ta_firmware_header_v2_0 *ta_hdr;
+ int err = 0;
+ int ta_index = 0;
+
+ if (!chip_name) {
+ dev_err(adev->dev, "invalid chip name for ta microcode\n");
+ return -EINVAL;
+ }
+
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
+ err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
+ if (err)
+ goto out;
+
+ err = amdgpu_ucode_validate(adev->psp.ta_fw);
+ if (err)
+ goto out;
+
+ ta_hdr = (const struct ta_firmware_header_v2_0 *)adev->psp.ta_fw->data;
+
+ if (le16_to_cpu(ta_hdr->header.header_version_major) != 2) {
+ dev_err(adev->dev, "unsupported TA header version\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_TA_PACKAGING) {
+ dev_err(adev->dev, "packed TA count exceeds maximum limit\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr->ta_fw_bin_count); ta_index++) {
+ err = parse_ta_bin_descriptor(psp,
+ &ta_hdr->ta_fw_bin[ta_index],
+ ta_hdr);
+ if (err)
+ goto out;
+ }
+
+ return 0;
+out:
+ dev_err(adev->dev, "fail to initialize ta microcode\n");
+ release_firmware(adev->psp.ta_fw);
+ adev->psp.ta_fw = NULL;
+ return err;
+}
+
static int psp_set_clockgating_state(void *handle,
enum amd_clockgating_state state)
{