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