On Thu, Jul 14, 2016 at 11:11:02AM +0100, Chris Wilson wrote: > So one solution would be to make vgem fences automatically timeout (with > a flag for root to override for the sake of testing hang detection). diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c index b7da11419ad6..17c63c9a8ea0 100644 --- a/drivers/gpu/drm/vgem/vgem_fence.c +++ b/drivers/gpu/drm/vgem/vgem_fence.c @@ -28,6 +28,7 @@ struct vgem_fence { struct fence base; struct spinlock lock; + struct timer_list timer; }; static const char *vgem_fence_get_driver_name(struct fence *fence) @@ -50,6 +51,14 @@ static bool vgem_fence_enable_signaling(struct fence *fence) return true; } +static void vgem_fence_release(struct fence *base) +{ + struct vgem_fence *fence = container_of(base, typeof(*fence), base); + + del_timer_sync(&fence->timer); + fence_free(&fence->base); +} + static void vgem_fence_value_str(struct fence *fence, char *str, int size) { snprintf(str, size, "%u", fence->seqno); @@ -67,11 +76,21 @@ const struct fence_ops vgem_fence_ops = { .enable_signaling = vgem_fence_enable_signaling, .signaled = vgem_fence_signaled, .wait = fence_default_wait, + .release = vgem_fence_release, + .fence_value_str = vgem_fence_value_str, .timeline_value_str = vgem_fence_timeline_value_str, }; -static struct fence *vgem_fence_create(struct vgem_file *vfile) +static void vgem_fence_timeout(unsigned long data) +{ + struct vgem_fence *fence = (struct vgem_fence *)data; + + fence_signal(&fence->base); +} + +static struct fence *vgem_fence_create(struct vgem_file *vfile, + unsigned int flags) { struct vgem_fence *fence; @@ -83,6 +102,12 @@ static struct fence *vgem_fence_create(struct vgem_file *vfile) fence_init(&fence->base, &vgem_fence_ops, &fence->lock, fence_context_alloc(1), 1); + setup_timer(&fence->timer, vgem_fence_timeout, (unsigned long)fence); + + /* We force the fence to expire within 10s to prevent driver hangs */ + if (!(flags & VGEM_FENCE_NOTIMEOUT)) + mod_timer(&fence->timer, 10*HZ); + return &fence->base; } @@ -114,9 +139,12 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, struct fence *fence; int ret; - if (arg->flags & ~VGEM_FENCE_WRITE) + if (arg->flags & ~(VGEM_FENCE_WRITE | VGEM_FENCE_NOTIMEOUT)) return -EINVAL; + if (arg->flags & VGEM_FENCE_NOTIMEOUT && !capable(CAP_SYS_ADMIN)) + return -EPERM; + if (arg->pad) return -EINVAL; @@ -128,7 +156,7 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, if (ret) goto out; - fence = vgem_fence_create(vfile); + fence = vgem_fence_create(vfile, arg->flags); if (!fence) { ret = -ENOMEM; goto out; diff --git a/include/uapi/drm/vgem_drm.h b/include/uapi/drm/vgem_drm.h index 352d2fae8de9..55fd08750773 100644 --- a/include/uapi/drm/vgem_drm.h +++ b/include/uapi/drm/vgem_drm.h @@ -45,7 +45,8 @@ extern "C" { struct drm_vgem_fence_attach { __u32 handle; __u32 flags; -#define VGEM_FENCE_WRITE 0x1 +#define VGEM_FENCE_WRITE 0x1 +#define VGEM_FENCE_NOTIMEOUT 0x2 __u32 out_fence; __u32 pad; }; -- Chris Wilson, Intel Open Source Technology Centre _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel