137 lines · c
1/*2 * Copyright © 2017 Intel Corporation3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice (including the next12 * paragraph) shall be included in all copies or substantial portions of the13 * Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS21 * IN THE SOFTWARE.22 *23 */24 25#include "lib_sw_fence.h"26 27/* Small library of different fence types useful for writing tests */28 29static int30nop_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)31{32 return NOTIFY_DONE;33}34 35void __onstack_fence_init(struct i915_sw_fence *fence,36 const char *name,37 struct lock_class_key *key)38{39 debug_fence_init_onstack(fence);40 41 __init_waitqueue_head(&fence->wait, name, key);42 atomic_set(&fence->pending, 1);43 fence->error = 0;44 fence->fn = nop_fence_notify;45}46 47void onstack_fence_fini(struct i915_sw_fence *fence)48{49 if (!fence->fn)50 return;51 52 i915_sw_fence_commit(fence);53 i915_sw_fence_fini(fence);54}55 56static void timed_fence_wake(struct timer_list *t)57{58 struct timed_fence *tf = from_timer(tf, t, timer);59 60 i915_sw_fence_commit(&tf->fence);61}62 63void timed_fence_init(struct timed_fence *tf, unsigned long expires)64{65 onstack_fence_init(&tf->fence);66 67 timer_setup_on_stack(&tf->timer, timed_fence_wake, 0);68 69 if (time_after(expires, jiffies))70 mod_timer(&tf->timer, expires);71 else72 i915_sw_fence_commit(&tf->fence);73}74 75void timed_fence_fini(struct timed_fence *tf)76{77 if (del_timer_sync(&tf->timer))78 i915_sw_fence_commit(&tf->fence);79 80 destroy_timer_on_stack(&tf->timer);81 i915_sw_fence_fini(&tf->fence);82}83 84struct heap_fence {85 struct i915_sw_fence fence;86 union {87 struct kref ref;88 struct rcu_head rcu;89 };90};91 92static int93heap_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)94{95 struct heap_fence *h = container_of(fence, typeof(*h), fence);96 97 switch (state) {98 case FENCE_COMPLETE:99 break;100 101 case FENCE_FREE:102 heap_fence_put(&h->fence);103 }104 105 return NOTIFY_DONE;106}107 108struct i915_sw_fence *heap_fence_create(gfp_t gfp)109{110 struct heap_fence *h;111 112 h = kmalloc(sizeof(*h), gfp);113 if (!h)114 return NULL;115 116 i915_sw_fence_init(&h->fence, heap_fence_notify);117 refcount_set(&h->ref.refcount, 2);118 119 return &h->fence;120}121 122static void heap_fence_release(struct kref *ref)123{124 struct heap_fence *h = container_of(ref, typeof(*h), ref);125 126 i915_sw_fence_fini(&h->fence);127 128 kfree_rcu(h, rcu);129}130 131void heap_fence_put(struct i915_sw_fence *fence)132{133 struct heap_fence *h = container_of(fence, typeof(*h), fence);134 135 kref_put(&h->ref, heap_fence_release);136}137