Commit 6c6f4783 authored by Christian König's avatar Christian König Committed by Dave Airlie

drm/radeon: rework recursive gpu reset handling

Instead of all this humpy pumpy with recursive
mutex (which also fixes only halve of the problem)
move the actual gpu reset out of the fence code,
return -EDEADLK and then reset the gpu in the
calling ioctl function.

v2: Split removal of radeon_mutex into separate patch.
    Return -EAGAIN if reset is successful.
Signed-off-by: default avatarChristian König <deathsimple@vodafone.de>
Reviewed-by: default avatarJerome Glisse <jglisse@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 8f676c4c
...@@ -496,6 +496,16 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, ...@@ -496,6 +496,16 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
return r; return r;
} }
static int radeon_cs_handle_lockup(struct radeon_device *rdev, int r)
{
if (r == -EDEADLK) {
r = radeon_gpu_reset(rdev);
if (!r)
r = -EAGAIN;
}
return r;
}
int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -517,6 +527,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) ...@@ -517,6 +527,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
if (r) { if (r) {
DRM_ERROR("Failed to initialize parser !\n"); DRM_ERROR("Failed to initialize parser !\n");
radeon_cs_parser_fini(&parser, r); radeon_cs_parser_fini(&parser, r);
r = radeon_cs_handle_lockup(rdev, r);
radeon_mutex_unlock(&rdev->cs_mutex); radeon_mutex_unlock(&rdev->cs_mutex);
return r; return r;
} }
...@@ -525,6 +536,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) ...@@ -525,6 +536,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
if (r != -ERESTARTSYS) if (r != -ERESTARTSYS)
DRM_ERROR("Failed to parse relocation %d!\n", r); DRM_ERROR("Failed to parse relocation %d!\n", r);
radeon_cs_parser_fini(&parser, r); radeon_cs_parser_fini(&parser, r);
r = radeon_cs_handle_lockup(rdev, r);
radeon_mutex_unlock(&rdev->cs_mutex); radeon_mutex_unlock(&rdev->cs_mutex);
return r; return r;
} }
...@@ -538,6 +550,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) ...@@ -538,6 +550,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
} }
out: out:
radeon_cs_parser_fini(&parser, r); radeon_cs_parser_fini(&parser, r);
r = radeon_cs_handle_lockup(rdev, r);
radeon_mutex_unlock(&rdev->cs_mutex); radeon_mutex_unlock(&rdev->cs_mutex);
return r; return r;
} }
......
...@@ -986,9 +986,6 @@ int radeon_gpu_reset(struct radeon_device *rdev) ...@@ -986,9 +986,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
int r; int r;
int resched; int resched;
/* Prevent CS ioctl from interfering */
radeon_mutex_lock(&rdev->cs_mutex);
radeon_save_bios_scratch_regs(rdev); radeon_save_bios_scratch_regs(rdev);
/* block TTM */ /* block TTM */
resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
...@@ -1003,8 +1000,6 @@ int radeon_gpu_reset(struct radeon_device *rdev) ...@@ -1003,8 +1000,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
} }
radeon_mutex_unlock(&rdev->cs_mutex);
if (r) { if (r) {
/* bad news, how to tell it to userspace ? */ /* bad news, how to tell it to userspace ? */
dev_info(rdev->dev, "GPU reset failed\n"); dev_info(rdev->dev, "GPU reset failed\n");
......
...@@ -244,6 +244,8 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) ...@@ -244,6 +244,8 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr)
/* change sequence value on all rings, so nobody else things there is a lockup */ /* change sequence value on all rings, so nobody else things there is a lockup */
for (i = 0; i < RADEON_NUM_RINGS; ++i) for (i = 0; i < RADEON_NUM_RINGS; ++i)
rdev->fence_drv[i].last_seq -= 0x10000; rdev->fence_drv[i].last_seq -= 0x10000;
rdev->fence_drv[fence->ring].last_activity = jiffies;
write_unlock_irqrestore(&rdev->fence_lock, irq_flags); write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
if (radeon_ring_is_lockup(rdev, fence->ring, &rdev->ring[fence->ring])) { if (radeon_ring_is_lockup(rdev, fence->ring, &rdev->ring[fence->ring])) {
...@@ -254,13 +256,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) ...@@ -254,13 +256,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr)
/* mark the ring as not ready any more */ /* mark the ring as not ready any more */
rdev->ring[fence->ring].ready = false; rdev->ring[fence->ring].ready = false;
r = radeon_gpu_reset(rdev); return -EDEADLK;
if (r)
return r;
write_lock_irqsave(&rdev->fence_lock, irq_flags);
rdev->fence_drv[fence->ring].last_activity = jiffies;
write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
} }
} }
} }
......
...@@ -154,6 +154,17 @@ void radeon_gem_object_close(struct drm_gem_object *obj, ...@@ -154,6 +154,17 @@ void radeon_gem_object_close(struct drm_gem_object *obj,
radeon_bo_unreserve(rbo); radeon_bo_unreserve(rbo);
} }
static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r)
{
if (r == -EDEADLK) {
radeon_mutex_lock(&rdev->cs_mutex);
r = radeon_gpu_reset(rdev);
if (!r)
r = -EAGAIN;
radeon_mutex_unlock(&rdev->cs_mutex);
}
return r;
}
/* /*
* GEM ioctls. * GEM ioctls.
...@@ -210,12 +221,14 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, ...@@ -210,12 +221,14 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
args->initial_domain, false, args->initial_domain, false,
false, &gobj); false, &gobj);
if (r) { if (r) {
r = radeon_gem_handle_lockup(rdev, r);
return r; return r;
} }
r = drm_gem_handle_create(filp, gobj, &handle); r = drm_gem_handle_create(filp, gobj, &handle);
/* drop reference from allocate - handle holds it now */ /* drop reference from allocate - handle holds it now */
drm_gem_object_unreference_unlocked(gobj); drm_gem_object_unreference_unlocked(gobj);
if (r) { if (r) {
r = radeon_gem_handle_lockup(rdev, r);
return r; return r;
} }
args->handle = handle; args->handle = handle;
...@@ -245,6 +258,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, ...@@ -245,6 +258,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
drm_gem_object_unreference_unlocked(gobj); drm_gem_object_unreference_unlocked(gobj);
r = radeon_gem_handle_lockup(robj->rdev, r);
return r; return r;
} }
...@@ -301,6 +315,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, ...@@ -301,6 +315,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
break; break;
} }
drm_gem_object_unreference_unlocked(gobj); drm_gem_object_unreference_unlocked(gobj);
r = radeon_gem_handle_lockup(robj->rdev, r);
return r; return r;
} }
...@@ -322,6 +337,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, ...@@ -322,6 +337,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
if (robj->rdev->asic->ioctl_wait_idle) if (robj->rdev->asic->ioctl_wait_idle)
robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj); robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj);
drm_gem_object_unreference_unlocked(gobj); drm_gem_object_unreference_unlocked(gobj);
r = radeon_gem_handle_lockup(robj->rdev, r);
return r; return r;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment