Merge tag 'mac80211-for-john-2014-11-18' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / gpu / drm / radeon / radeon_device.c
index 12c8329..f41cc15 100644 (file)
@@ -434,7 +434,7 @@ int radeon_wb_init(struct radeon_device *rdev)
 
        if (rdev->wb.wb_obj == NULL) {
                r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
-                                    RADEON_GEM_DOMAIN_GTT, 0, NULL,
+                                    RADEON_GEM_DOMAIN_GTT, 0, NULL, NULL,
                                     &rdev->wb.wb_obj);
                if (r) {
                        dev_warn(rdev->dev, "(%d) create WB bo failed\n", r);
@@ -1257,6 +1257,7 @@ int radeon_device_init(struct radeon_device *rdev,
        for (i = 0; i < RADEON_NUM_RINGS; i++) {
                rdev->ring[i].idx = i;
        }
+       rdev->fence_context = fence_context_alloc(RADEON_NUM_RINGS);
 
        DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
                radeon_family_name[rdev->family], pdev->vendor, pdev->device,
@@ -1274,6 +1275,8 @@ int radeon_device_init(struct radeon_device *rdev,
        init_rwsem(&rdev->pm.mclk_lock);
        init_rwsem(&rdev->exclusive_lock);
        init_waitqueue_head(&rdev->irq.vblank_queue);
+       mutex_init(&rdev->mn_lock);
+       hash_init(rdev->mn_hash);
        r = radeon_gem_init(rdev);
        if (r)
                return r;
@@ -1399,10 +1402,6 @@ int radeon_device_init(struct radeon_device *rdev,
        if (r)
                goto failed;
 
-       r = radeon_ib_ring_tests(rdev);
-       if (r)
-               DRM_ERROR("ib ring test failed (%d).\n", r);
-
        r = radeon_gem_debugfs_init(rdev);
        if (r) {
                DRM_ERROR("registering gem debugfs failed (%d).\n", r);
@@ -1420,6 +1419,10 @@ int radeon_device_init(struct radeon_device *rdev,
                        goto failed;
        }
 
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
+               DRM_ERROR("ib ring test failed (%d).\n", r);
+
        if ((radeon_testing & 1)) {
                if (rdev->accel_working)
                        radeon_test_moves(rdev);
@@ -1497,7 +1500,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;
@@ -1541,12 +1543,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);
 
@@ -1686,8 +1685,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);
@@ -1704,7 +1701,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");
@@ -1713,26 +1709,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]);
                }
        }
@@ -1764,19 +1746,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;
 }