Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[cascardo/linux.git] / drivers / gpu / drm / radeon / cik.c
index 8ac82df..ba192a3 100644 (file)
@@ -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);