From: Jerome Glisse <jgli...@redhat.com>

After unrecovered GPU lockup avoid any GPU activities to avoid
things like kernel segfault and alike to happen in any of the
path that assume hw is working.

cc: sta...@vger.kernel.org
Signed-off-by: Jerome Glisse <jgli...@redhat.com>
---
 drivers/gpu/drm/radeon/radeon_device.c |    9 ++++---
 drivers/gpu/drm/radeon/radeon_object.c |    7 ++++++
 drivers/gpu/drm/radeon/radeon_ttm.c    |   41 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/ttm/ttm_tt.c           |    1 +
 4 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 066c98b..653f352 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -993,16 +993,19 @@ int radeon_gpu_reset(struct radeon_device *rdev)
        /* block TTM */
        resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
        radeon_suspend(rdev);
+       rdev->accel_working = false;
 
        r = radeon_asic_reset(rdev);
        if (!r) {
                dev_info(rdev->dev, "GPU reset succeed\n");
                radeon_resume(rdev);
-               radeon_restore_bios_scratch_regs(rdev);
-               drm_helper_resume_force_mode(rdev->ddev);
-               ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
        }
 
+       /* no matter what restore video mode */
+       radeon_restore_bios_scratch_regs(rdev);
+       drm_helper_resume_force_mode(rdev->ddev);
+       ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
+
        if (r) {
                /* bad news, how to tell it to userspace ? */
                dev_info(rdev->dev, "GPU reset failed\n");
diff --git a/drivers/gpu/drm/radeon/radeon_object.c 
b/drivers/gpu/drm/radeon/radeon_object.c
index 830f1a7..27e8e53 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -89,6 +89,13 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, 
u32 domain)
        rbo->placement.lpfn = 0;
        rbo->placement.placement = rbo->placements;
        rbo->placement.busy_placement = rbo->placements;
+       if (!rbo->rdev->accel_working) {
+               /* for new bo to system ram when GPU is not working */
+               rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+               rbo->placement.num_placement = c;
+               rbo->placement.num_busy_placement = c;
+               return;
+       }
        if (domain & RADEON_GEM_DOMAIN_VRAM)
                rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
                                        TTM_PL_FLAG_VRAM;
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c 
b/drivers/gpu/drm/radeon/radeon_ttm.c
index c94a225..0994d1e 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -215,6 +215,25 @@ static void radeon_move_null(struct ttm_buffer_object *bo,
        new_mem->mm_node = NULL;
 }
 
+static void radeon_move_noop(struct ttm_buffer_object *bo,
+                            struct ttm_mem_reg *new_mem)
+{
+       struct ttm_bo_device *bdev = bo->bdev;
+       struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type];
+       struct ttm_mem_reg *old_mem = &bo->mem;
+       struct ttm_mem_reg old_copy = *old_mem;
+
+       *old_mem = *new_mem;
+       new_mem->mm_node = NULL;
+
+       if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && (bo->ttm != NULL)) {
+               ttm_tt_destroy(bo->ttm);
+               bo->ttm = NULL;
+       }
+
+       ttm_bo_mem_put(bo, &old_copy);
+}
+
 static int radeon_move_blit(struct ttm_buffer_object *bo,
                        bool evict, int no_wait_reserve, bool no_wait_gpu,
                        struct ttm_mem_reg *new_mem,
@@ -399,6 +418,14 @@ static int radeon_bo_move(struct ttm_buffer_object *bo,
                radeon_move_null(bo, new_mem);
                return 0;
        }
+       if (!rdev->accel_working) {
+               /* when accel is not working GPU is in broken state just
+                * do nothing for any ttm operation to avoid making the
+                * situation worst than it's
+                */
+               radeon_move_noop(bo, new_mem);
+               return 0;
+       }
        if ((old_mem->mem_type == TTM_PL_TT &&
             new_mem->mem_type == TTM_PL_SYSTEM) ||
            (old_mem->mem_type == TTM_PL_SYSTEM &&
@@ -545,6 +572,13 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm,
                WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n",
                     ttm->num_pages, bo_mem, ttm);
        }
+       if (!gtt->rdev->accel_working) {
+               /* when accel is not working GPU is in broken state just
+                * do nothing for any ttm operation to avoid making the
+                * situation worst than it's
+                */
+               return 0;
+       }
        r = radeon_gart_bind(gtt->rdev, gtt->offset,
                             ttm->num_pages, ttm->pages, gtt->ttm.dma_address);
        if (r) {
@@ -559,6 +593,13 @@ static int radeon_ttm_backend_unbind(struct ttm_tt *ttm)
 {
        struct radeon_ttm_tt *gtt = (void *)ttm;
 
+       if (!gtt->rdev->accel_working) {
+               /* when accel is not working GPU is in broken state just
+                * do nothing for any ttm operation to avoid making the
+                * situation worst than it's
+                */
+               return 0;
+       }
        radeon_gart_unbind(gtt->rdev, gtt->offset, ttm->num_pages);
        return 0;
 }
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index fa09daf..f7bdb04 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -181,6 +181,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
        ttm->swap_storage = NULL;
        ttm->func->destroy(ttm);
 }
+EXPORT_SYMBOL(ttm_tt_destroy);
 
 int ttm_tt_init(struct ttm_tt *ttm, struct ttm_bo_device *bdev,
                unsigned long size, uint32_t page_flags,
-- 
1.7.10.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to