For some selftests, we want to issue requests but delay them going to hardware. Furthermore, we don't want those requests to block indefinitely (or else we may hang the driver and block testing) so we want to employ a timeout. So naturally we want a fence that is automatically signaled by a timer. Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_sw_fence.c | 62 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_sw_fence.h | 4 +++ 2 files changed, 66 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 808ea4d5b962..308fbb201d4c 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -506,6 +506,68 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, return ret; } +struct timer_fence { + struct i915_sw_fence base; + struct timer_list timer; + struct kref ref; +}; + +static void timer_fence_wake(unsigned long data) +{ + struct timer_fence *tf = (struct timer_fence *)data; + + i915_sw_fence_complete(&tf->base); +} + +static int __i915_sw_fence_call +timer_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) +{ + if (state == FENCE_FREE) + i915_sw_fence_timer_put(fence); + + return NOTIFY_DONE; +} + +struct i915_sw_fence *i915_sw_fence_create_timer(long timeout, gfp_t gfp) +{ + struct timer_fence *tf; + + tf = kmalloc(sizeof(*tf), gfp); + if (!tf) + return ERR_PTR(-ENOMEM); + + i915_sw_fence_init(&tf->base, timer_fence_notify); + kref_init(&tf->ref); + + setup_timer(&tf->timer, timer_fence_wake, (unsigned long)tf); + mod_timer(&tf->timer, timeout); + + kref_get(&tf->ref); + return &tf->base; +} + +static void i915_sw_fence_timer_free(struct kref *ref) +{ + struct timer_fence *tf = container_of(ref, typeof(*tf), ref); + + kfree(tf); +} + +void i915_sw_fence_timer_flush(struct i915_sw_fence *fence) +{ + struct timer_fence *tf = container_of(fence, typeof(*tf), base); + + if (del_timer_sync(&tf->timer)) + i915_sw_fence_complete(&tf->base); +} + +void i915_sw_fence_timer_put(struct i915_sw_fence *fence) +{ + struct timer_fence *tf = container_of(fence, typeof(*tf), base); + + kref_put(&tf->ref, i915_sw_fence_timer_free); +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/i915_sw_fence.c" #endif diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index fe2ef4dadfc6..eccbee027cb8 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -61,6 +61,10 @@ void i915_sw_fence_fini(struct i915_sw_fence *fence); static inline void i915_sw_fence_fini(struct i915_sw_fence *fence) {} #endif +struct i915_sw_fence *i915_sw_fence_create_timer(long timeout, gfp_t gfp); +void i915_sw_fence_timer_flush(struct i915_sw_fence *fence); +void i915_sw_fence_timer_put(struct i915_sw_fence *fence); + void i915_sw_fence_commit(struct i915_sw_fence *fence); int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, -- 2.15.0.rc0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx