From: Jerome Glisse <jglisse@xxxxxxxxxx> 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: stable@xxxxxxxxxxxxxxx Signed-off-by: Jerome Glisse <jglisse@xxxxxxxxxx> --- 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@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel