aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-12 11:48:26 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-12 11:48:26 -0700
commita34ab101a9d27a2995142b47f9857fb46fcb072a (patch)
treea9d5237a5706d5993c78d4f53232ddff86cdf9d1 /drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
parentMerge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending (diff)
parentdrm/i915: Make vblank evade warnings optional (diff)
downloadlinux-dev-a34ab101a9d27a2995142b47f9857fb46fcb072a.tar.xz
linux-dev-a34ab101a9d27a2995142b47f9857fb46fcb072a.zip
Merge tag 'drm-fixes-for-v4.12-rc1' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie: "AMD, nouveau, one i915, and one EDID fix for v4.12-rc1 Some fixes that it would be good to have in rc1. It contains the i915 quiet fix that you reported. It also has an amdgpu fixes pull, with lots of ongoing work on Vega10 which is new in this kernel and is preliminary support so may have a fair bit of movement. Otherwise a few non-Vega10 AMD fixes, one EDID fix and some nouveau regression fixers" * tag 'drm-fixes-for-v4.12-rc1' of git://people.freedesktop.org/~airlied/linux: (144 commits) drm/i915: Make vblank evade warnings optional drm/nouveau/therm: remove ineffective workarounds for alarm bugs drm/nouveau/tmr: avoid processing completed alarms when adding a new one drm/nouveau/tmr: fix corruption of the pending list when rescheduling an alarm drm/nouveau/tmr: handle races with hw when updating the next alarm time drm/nouveau/tmr: ack interrupt before processing alarms drm/nouveau/core: fix static checker warning drm/nouveau/fb/ram/gf100-: remove 0x10f200 read drm/nouveau/kms/nv50: skip core channel cursor update on position-only changes drm/nouveau/kms/nv50: fix source-rect-only plane updates drm/nouveau/kms/nv50: remove pointless argument to window atomic_check_acquire() drm/amd/powerplay: refine pwm1_enable callback functions for CI. drm/amd/powerplay: refine pwm1_enable callback functions for vi. drm/amd/powerplay: refine pwm1_enable callback functions for Vega10. drm/amdgpu: refine amdgpu pwm1_enable sysfs interface. drm/amdgpu: add amd fan ctrl mode enums. drm/amd/powerplay: add more smu message on Vega10. drm/amdgpu: fix dependency issue drm/amd: fix init order of sched job drm/amdgpu: add some additional vega10 pci ids ...
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c229
1 files changed, 146 insertions, 83 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index ed6e5799016e..ac5e92e5d59d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -55,6 +55,8 @@ static int psp_sw_init(void *handle)
psp->bootloader_load_sos = psp_v3_1_bootloader_load_sos;
psp->prep_cmd_buf = psp_v3_1_prep_cmd_buf;
psp->ring_init = psp_v3_1_ring_init;
+ psp->ring_create = psp_v3_1_ring_create;
+ psp->ring_destroy = psp_v3_1_ring_destroy;
psp->cmd_submit = psp_v3_1_cmd_submit;
psp->compare_sram_data = psp_v3_1_compare_sram_data;
psp->smu_reload_quirk = psp_v3_1_smu_reload_quirk;
@@ -152,11 +154,6 @@ static void psp_prep_tmr_cmd_buf(struct psp_gfx_cmd_resp *cmd,
static int psp_tmr_init(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;
/*
* Allocate 3M memory aligned to 1M from Frame Buffer (local
@@ -168,22 +165,30 @@ static int psp_tmr_init(struct psp_context *psp)
ret = amdgpu_bo_create_kernel(psp->adev, 0x300000, 0x100000,
AMDGPU_GEM_DOMAIN_VRAM,
&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
- if (ret)
- goto failed;
+
+ return ret;
+}
+
+static int psp_tmr_load(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_cmd_buf(cmd, psp->tmr_mc_addr, 0x300000);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr, 1);
if (ret)
- goto failed_mem;
+ goto failed;
kfree(cmd);
return 0;
-failed_mem:
- amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
failed:
kfree(cmd);
return ret;
@@ -203,104 +208,78 @@ static void psp_prep_asd_cmd_buf(struct psp_gfx_cmd_resp *cmd,
cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size;
}
-static int psp_asd_load(struct psp_context *psp)
+static int psp_asd_init(struct psp_context *psp)
{
int ret;
- struct amdgpu_bo *asd_bo, *asd_shared_bo;
- uint64_t asd_mc_addr, asd_shared_mc_addr;
- void *asd_buf, *asd_shared_buf;
- struct psp_gfx_cmd_resp *cmd;
-
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
/*
* Allocate 16k memory aligned to 4k from Frame Buffer (local
* physical) for shared ASD <-> Driver
*/
- ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &asd_shared_bo, &asd_shared_mc_addr, &asd_buf);
- if (ret)
- goto failed;
+ ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
+ &psp->asd_shared_bo,
+ &psp->asd_shared_mc_addr,
+ &psp->asd_shared_buf);
- /*
- * Allocate 256k memory aligned to 4k from Frame Buffer (local
- * physical) for ASD firmware
- */
- ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_BIN_SIZE, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &asd_bo, &asd_mc_addr, &asd_buf);
- if (ret)
- goto failed_mem;
+ return ret;
+}
+
+static int psp_asd_load(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;
- memcpy(asd_buf, psp->asd_start_addr, psp->asd_ucode_size);
+ memset(psp->fw_pri_buf, 0, PSP_1_MEG);
+ memcpy(psp->fw_pri_buf, psp->asd_start_addr, psp->asd_ucode_size);
- psp_prep_asd_cmd_buf(cmd, asd_mc_addr, asd_shared_mc_addr,
+ 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,
psp->fence_buf_mc_addr, 2);
- if (ret)
- goto failed_mem1;
- amdgpu_bo_free_kernel(&asd_bo, &asd_mc_addr, &asd_buf);
- amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf);
kfree(cmd);
- return 0;
-
-failed_mem1:
- amdgpu_bo_free_kernel(&asd_bo, &asd_mc_addr, &asd_buf);
-failed_mem:
- amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf);
-failed:
- kfree(cmd);
return ret;
}
-static int psp_load_fw(struct amdgpu_device *adev)
+static int psp_hw_start(struct psp_context *psp)
{
int ret;
- struct psp_gfx_cmd_resp *cmd;
- int i;
- struct amdgpu_firmware_info *ucode;
- struct psp_context *psp = &adev->psp;
-
- cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
ret = psp_bootloader_load_sysdrv(psp);
if (ret)
- goto failed;
+ return ret;
ret = psp_bootloader_load_sos(psp);
if (ret)
- goto failed;
-
- ret = psp_ring_init(psp, PSP_RING_TYPE__KM);
- if (ret)
- goto failed;
+ return ret;
- ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &psp->fence_buf_bo,
- &psp->fence_buf_mc_addr,
- &psp->fence_buf);
+ ret = psp_ring_create(psp, PSP_RING_TYPE__KM);
if (ret)
- goto failed;
-
- memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE);
+ return ret;
- ret = psp_tmr_init(psp);
+ ret = psp_tmr_load(psp);
if (ret)
- goto failed_mem;
+ return ret;
ret = psp_asd_load(psp);
if (ret)
- goto failed_mem;
+ return ret;
+
+ return 0;
+}
+
+static int psp_np_fw_load(struct psp_context *psp)
+{
+ int i, ret;
+ struct amdgpu_firmware_info *ucode;
+ struct amdgpu_device* adev = psp->adev;
for (i = 0; i < adev->firmware.max_ucodes; i++) {
ucode = &adev->firmware.ucode[i];
@@ -310,15 +289,21 @@ static int psp_load_fw(struct amdgpu_device *adev)
if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC &&
psp_smu_reload_quirk(psp))
continue;
+ if (amdgpu_sriov_vf(adev) &&
+ (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA0
+ || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1
+ || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_G))
+ /*skip ucode loading in SRIOV VF */
+ continue;
- ret = psp_prep_cmd_buf(ucode, cmd);
+ ret = psp_prep_cmd_buf(ucode, psp->cmd);
if (ret)
- goto failed_mem;
+ return ret;
- ret = psp_cmd_submit_buf(psp, ucode, cmd,
+ ret = psp_cmd_submit_buf(psp, ucode, psp->cmd,
psp->fence_buf_mc_addr, i + 3);
if (ret)
- goto failed_mem;
+ return ret;
#if 0
/* check if firmware loaded sucessfully */
@@ -327,8 +312,59 @@ static int psp_load_fw(struct amdgpu_device *adev)
#endif
}
- amdgpu_bo_free_kernel(&psp->fence_buf_bo,
- &psp->fence_buf_mc_addr, &psp->fence_buf);
+ return 0;
+}
+
+static int psp_load_fw(struct amdgpu_device *adev)
+{
+ int ret;
+ struct psp_context *psp = &adev->psp;
+ struct psp_gfx_cmd_resp *cmd;
+
+ cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ psp->cmd = cmd;
+
+ ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG,
+ AMDGPU_GEM_DOMAIN_GTT,
+ &psp->fw_pri_bo,
+ &psp->fw_pri_mc_addr,
+ &psp->fw_pri_buf);
+ if (ret)
+ goto failed;
+
+ ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &psp->fence_buf_bo,
+ &psp->fence_buf_mc_addr,
+ &psp->fence_buf);
+ if (ret)
+ goto failed_mem1;
+
+ memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE);
+
+ ret = psp_ring_init(psp, PSP_RING_TYPE__KM);
+ if (ret)
+ goto failed_mem1;
+
+ ret = psp_tmr_init(psp);
+ if (ret)
+ goto failed_mem;
+
+ ret = psp_asd_init(psp);
+ if (ret)
+ goto failed_mem;
+
+ ret = psp_hw_start(psp);
+ if (ret)
+ goto failed_mem;
+
+ ret = psp_np_fw_load(psp);
+ if (ret)
+ goto failed_mem;
+
kfree(cmd);
return 0;
@@ -336,6 +372,9 @@ static int psp_load_fw(struct amdgpu_device *adev)
failed_mem:
amdgpu_bo_free_kernel(&psp->fence_buf_bo,
&psp->fence_buf_mc_addr, &psp->fence_buf);
+failed_mem1:
+ amdgpu_bo_free_kernel(&psp->fw_pri_bo,
+ &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
failed:
kfree(cmd);
return ret;
@@ -379,12 +418,24 @@ static int psp_hw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct psp_context *psp = &adev->psp;
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
- amdgpu_ucode_fini_bo(adev);
+ if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
+ return 0;
+
+ amdgpu_ucode_fini_bo(adev);
+
+ psp_ring_destroy(psp, PSP_RING_TYPE__KM);
if (psp->tmr_buf)
amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
+ if (psp->fw_pri_buf)
+ amdgpu_bo_free_kernel(&psp->fw_pri_bo,
+ &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
+
+ if (psp->fence_buf_bo)
+ amdgpu_bo_free_kernel(&psp->fence_buf_bo,
+ &psp->fence_buf_mc_addr, &psp->fence_buf);
+
return 0;
}
@@ -397,18 +448,30 @@ static int psp_resume(void *handle)
{
int ret;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct psp_context *psp = &adev->psp;
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
return 0;
+ DRM_INFO("PSP is resuming...\n");
+
mutex_lock(&adev->firmware.mutex);
- ret = psp_load_fw(adev);
+ ret = psp_hw_start(psp);
if (ret)
- DRM_ERROR("PSP resume failed\n");
+ goto failed;
+
+ ret = psp_np_fw_load(psp);
+ if (ret)
+ goto failed;
mutex_unlock(&adev->firmware.mutex);
+ return 0;
+
+failed:
+ DRM_ERROR("PSP resume failed\n");
+ mutex_unlock(&adev->firmware.mutex);
return ret;
}