diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/cik.c')
-rw-r--r-- | drivers/gpu/drm/radeon/cik.c | 252 |
1 files changed, 177 insertions, 75 deletions
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 8ac82df2efde..ba192a35c607 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -5261,15 +5261,21 @@ static void cik_gpu_pci_config_reset(struct radeon_device *rdev) * cik_asic_reset - soft reset GPU * * @rdev: radeon_device pointer + * @hard: force hard reset * * Look up which blocks are hung and attempt * to reset them. * Returns 0 for success. */ -int cik_asic_reset(struct radeon_device *rdev) +int cik_asic_reset(struct radeon_device *rdev, bool hard) { u32 reset_mask; + if (hard) { + cik_gpu_pci_config_reset(rdev); + return 0; + } + reset_mask = cik_gpu_check_soft_reset(rdev); if (reset_mask) @@ -8137,6 +8143,164 @@ restart_ih: /* * startup/shutdown callbacks */ +static void cik_uvd_init(struct radeon_device *rdev) +{ + int r; + + if (!rdev->has_uvd) + return; + + r = radeon_uvd_init(rdev); + if (r) { + dev_err(rdev->dev, "failed UVD (%d) init.\n", r); + /* + * At this point rdev->uvd.vcpu_bo is NULL which trickles down + * to early fails cik_uvd_start() and thus nothing happens + * there. So it is pointless to try to go through that code + * hence why we disable uvd here. + */ + rdev->has_uvd = 0; + return; + } + rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL; + r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096); +} + +static void cik_uvd_start(struct radeon_device *rdev) +{ + int r; + + if (!rdev->has_uvd) + return; + + r = radeon_uvd_resume(rdev); + if (r) { + dev_err(rdev->dev, "failed UVD resume (%d).\n", r); + goto error; + } + r = uvd_v4_2_resume(rdev); + if (r) { + dev_err(rdev->dev, "failed UVD 4.2 resume (%d).\n", r); + goto error; + } + r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r); + goto error; + } + return; + +error: + rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; +} + +static void cik_uvd_resume(struct radeon_device *rdev) +{ + struct radeon_ring *ring; + int r; + + if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size) + return; + + ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2); + if (r) { + dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r); + return; + } + r = uvd_v1_0_init(rdev); + if (r) { + dev_err(rdev->dev, "failed initializing UVD (%d).\n", r); + return; + } +} + +static void cik_vce_init(struct radeon_device *rdev) +{ + int r; + + if (!rdev->has_vce) + return; + + r = radeon_vce_init(rdev); + if (r) { + dev_err(rdev->dev, "failed VCE (%d) init.\n", r); + /* + * At this point rdev->vce.vcpu_bo is NULL which trickles down + * to early fails cik_vce_start() and thus nothing happens + * there. So it is pointless to try to go through that code + * hence why we disable vce here. + */ + rdev->has_vce = 0; + return; + } + rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_obj = NULL; + r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX], 4096); + rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_obj = NULL; + r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX], 4096); +} + +static void cik_vce_start(struct radeon_device *rdev) +{ + int r; + + if (!rdev->has_vce) + return; + + r = radeon_vce_resume(rdev); + if (r) { + dev_err(rdev->dev, "failed VCE resume (%d).\n", r); + goto error; + } + r = vce_v2_0_resume(rdev); + if (r) { + dev_err(rdev->dev, "failed VCE resume (%d).\n", r); + goto error; + } + r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing VCE1 fences (%d).\n", r); + goto error; + } + r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing VCE2 fences (%d).\n", r); + goto error; + } + return; + +error: + rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0; + rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0; +} + +static void cik_vce_resume(struct radeon_device *rdev) +{ + struct radeon_ring *ring; + int r; + + if (!rdev->has_vce || !rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size) + return; + + ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP); + if (r) { + dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r); + return; + } + ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP); + if (r) { + dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r); + return; + } + r = vce_v1_0_init(rdev); + if (r) { + dev_err(rdev->dev, "failed initializing VCE (%d).\n", r); + return; + } +} + /** * cik_startup - program the asic to a functional state * @@ -8239,34 +8403,8 @@ static int cik_startup(struct radeon_device *rdev) return r; } - r = radeon_uvd_resume(rdev); - if (!r) { - r = uvd_v4_2_resume(rdev); - if (!r) { - r = radeon_fence_driver_start_ring(rdev, - R600_RING_TYPE_UVD_INDEX); - if (r) - dev_err(rdev->dev, "UVD fences init error (%d).\n", r); - } - } - if (r) - rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; - - r = radeon_vce_resume(rdev); - if (!r) { - r = vce_v2_0_resume(rdev); - if (!r) - r = radeon_fence_driver_start_ring(rdev, - TN_RING_TYPE_VCE1_INDEX); - if (!r) - r = radeon_fence_driver_start_ring(rdev, - TN_RING_TYPE_VCE2_INDEX); - } - if (r) { - dev_err(rdev->dev, "VCE init error (%d).\n", r); - rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0; - rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0; - } + cik_uvd_start(rdev); + cik_vce_start(rdev); /* Enable IRQ */ if (!rdev->irq.installed) { @@ -8342,32 +8480,8 @@ static int cik_startup(struct radeon_device *rdev) if (r) return r; - ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; - if (ring->ring_size) { - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, - RADEON_CP_PACKET2); - if (!r) - r = uvd_v1_0_init(rdev); - if (r) - DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); - } - - r = -ENOENT; - - ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; - if (ring->ring_size) - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, - VCE_CMD_NO_OP); - - ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; - if (ring->ring_size) - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, - VCE_CMD_NO_OP); - - if (!r) - r = vce_v1_0_init(rdev); - else if (r != -ENOENT) - DRM_ERROR("radeon: failed initializing VCE (%d).\n", r); + cik_uvd_resume(rdev); + cik_vce_resume(rdev); r = radeon_ib_pool_init(rdev); if (r) { @@ -8443,9 +8557,12 @@ int cik_suspend(struct radeon_device *rdev) radeon_vm_manager_fini(rdev); cik_cp_enable(rdev, false); cik_sdma_enable(rdev, false); - uvd_v1_0_fini(rdev); - radeon_uvd_suspend(rdev); - radeon_vce_suspend(rdev); + if (rdev->has_uvd) { + uvd_v1_0_fini(rdev); + radeon_uvd_suspend(rdev); + } + if (rdev->has_vce) + radeon_vce_suspend(rdev); cik_fini_pg(rdev); cik_fini_cg(rdev); cik_irq_suspend(rdev); @@ -8571,23 +8688,8 @@ int cik_init(struct radeon_device *rdev) ring->ring_obj = NULL; r600_ring_init(rdev, ring, 256 * 1024); - r = radeon_uvd_init(rdev); - if (!r) { - ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; - ring->ring_obj = NULL; - r600_ring_init(rdev, ring, 4096); - } - - r = radeon_vce_init(rdev); - if (!r) { - ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; - ring->ring_obj = NULL; - r600_ring_init(rdev, ring, 4096); - - ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; - ring->ring_obj = NULL; - r600_ring_init(rdev, ring, 4096); - } + cik_uvd_init(rdev); + cik_vce_init(rdev); rdev->ih.ring_obj = NULL; r600_ih_ring_init(rdev, 64 * 1024); |