drm/radeon: drop doing resets in a work item
[linux-2.6-block.git] / drivers / gpu / drm / radeon / radeon_device.c
index b6aee40e6ef34abeacb5895ed7a9da3b44d73369..d30f1cc1aa12be2998495064bf265cbb23c7fd0b 100644 (file)
@@ -1488,7 +1488,6 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
        struct drm_crtc *crtc;
        struct drm_connector *connector;
        int i, r;
-       bool force_completion = false;
 
        if (dev == NULL || dev->dev_private == NULL) {
                return -ENODEV;
@@ -1532,12 +1531,9 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
                r = radeon_fence_wait_empty(rdev, i);
                if (r) {
                        /* delay GPU reset to resume */
-                       force_completion = true;
+                       radeon_fence_driver_force_completion(rdev, i);
                }
        }
-       if (force_completion) {
-               radeon_fence_driver_force_completion(rdev);
-       }
 
        radeon_save_bios_scratch_regs(rdev);
 
@@ -1677,8 +1673,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
                return 0;
        }
 
-       rdev->needs_reset = false;
-
        radeon_save_bios_scratch_regs(rdev);
        /* block TTM */
        resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
@@ -1695,7 +1689,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
                }
        }
 
-retry:
        r = radeon_asic_reset(rdev);
        if (!r) {
                dev_info(rdev->dev, "GPU reset succeeded, trying to resume\n");
@@ -1704,26 +1697,12 @@ retry:
 
        radeon_restore_bios_scratch_regs(rdev);
 
-       if (!r) {
-               for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+               if (!r && ring_data[i]) {
                        radeon_ring_restore(rdev, &rdev->ring[i],
                                            ring_sizes[i], ring_data[i]);
-                       ring_sizes[i] = 0;
-                       ring_data[i] = NULL;
-               }
-
-               r = radeon_ib_ring_tests(rdev);
-               if (r) {
-                       dev_err(rdev->dev, "ib ring test failed (%d).\n", r);
-                       if (saved) {
-                               saved = false;
-                               radeon_suspend(rdev);
-                               goto retry;
-                       }
-               }
-       } else {
-               radeon_fence_driver_force_completion(rdev);
-               for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+               } else {
+                       radeon_fence_driver_force_completion(rdev, i);
                        kfree(ring_data[i]);
                }
        }
@@ -1755,19 +1734,32 @@ retry:
        /* reset hpd state */
        radeon_hpd_init(rdev);
 
+       ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
+
+       rdev->in_reset = true;
+       rdev->needs_reset = false;
+
+       downgrade_write(&rdev->exclusive_lock);
+
        drm_helper_resume_force_mode(rdev->ddev);
 
        /* set the power state here in case we are a PX system or headless */
        if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
                radeon_pm_compute_clocks(rdev);
 
-       ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-       if (r) {
+       if (!r) {
+               r = radeon_ib_ring_tests(rdev);
+               if (r && saved)
+                       r = -EAGAIN;
+       } else {
                /* bad news, how to tell it to userspace ? */
                dev_info(rdev->dev, "GPU reset failed\n");
        }
 
-       up_write(&rdev->exclusive_lock);
+       rdev->needs_reset = r == -EAGAIN;
+       rdev->in_reset = false;
+
+       up_read(&rdev->exclusive_lock);
        return r;
 }