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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to