Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright © 2017 Intel Corporation
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice (including the next
0012  * paragraph) shall be included in all copies or substantial portions of the
0013  * Software.
0014  *
0015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0018  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0019  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0020  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
0021  * IN THE SOFTWARE.
0022  *
0023  */
0024 
0025 #include "lib_sw_fence.h"
0026 
0027 /* Small library of different fence types useful for writing tests */
0028 
0029 static int
0030 nop_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
0031 {
0032     return NOTIFY_DONE;
0033 }
0034 
0035 void __onstack_fence_init(struct i915_sw_fence *fence,
0036               const char *name,
0037               struct lock_class_key *key)
0038 {
0039     debug_fence_init_onstack(fence);
0040 
0041     __init_waitqueue_head(&fence->wait, name, key);
0042     atomic_set(&fence->pending, 1);
0043     fence->error = 0;
0044     fence->fn = nop_fence_notify;
0045 }
0046 
0047 void onstack_fence_fini(struct i915_sw_fence *fence)
0048 {
0049     if (!fence->fn)
0050         return;
0051 
0052     i915_sw_fence_commit(fence);
0053     i915_sw_fence_fini(fence);
0054 }
0055 
0056 static void timed_fence_wake(struct timer_list *t)
0057 {
0058     struct timed_fence *tf = from_timer(tf, t, timer);
0059 
0060     i915_sw_fence_commit(&tf->fence);
0061 }
0062 
0063 void timed_fence_init(struct timed_fence *tf, unsigned long expires)
0064 {
0065     onstack_fence_init(&tf->fence);
0066 
0067     timer_setup_on_stack(&tf->timer, timed_fence_wake, 0);
0068 
0069     if (time_after(expires, jiffies))
0070         mod_timer(&tf->timer, expires);
0071     else
0072         i915_sw_fence_commit(&tf->fence);
0073 }
0074 
0075 void timed_fence_fini(struct timed_fence *tf)
0076 {
0077     if (del_timer_sync(&tf->timer))
0078         i915_sw_fence_commit(&tf->fence);
0079 
0080     destroy_timer_on_stack(&tf->timer);
0081     i915_sw_fence_fini(&tf->fence);
0082 }
0083 
0084 struct heap_fence {
0085     struct i915_sw_fence fence;
0086     union {
0087         struct kref ref;
0088         struct rcu_head rcu;
0089     };
0090 };
0091 
0092 static int
0093 heap_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
0094 {
0095     struct heap_fence *h = container_of(fence, typeof(*h), fence);
0096 
0097     switch (state) {
0098     case FENCE_COMPLETE:
0099         break;
0100 
0101     case FENCE_FREE:
0102         heap_fence_put(&h->fence);
0103     }
0104 
0105     return NOTIFY_DONE;
0106 }
0107 
0108 struct i915_sw_fence *heap_fence_create(gfp_t gfp)
0109 {
0110     struct heap_fence *h;
0111 
0112     h = kmalloc(sizeof(*h), gfp);
0113     if (!h)
0114         return NULL;
0115 
0116     i915_sw_fence_init(&h->fence, heap_fence_notify);
0117     refcount_set(&h->ref.refcount, 2);
0118 
0119     return &h->fence;
0120 }
0121 
0122 static void heap_fence_release(struct kref *ref)
0123 {
0124     struct heap_fence *h = container_of(ref, typeof(*h), ref);
0125 
0126     i915_sw_fence_fini(&h->fence);
0127 
0128     kfree_rcu(h, rcu);
0129 }
0130 
0131 void heap_fence_put(struct i915_sw_fence *fence)
0132 {
0133     struct heap_fence *h = container_of(fence, typeof(*h), fence);
0134 
0135     kref_put(&h->ref, heap_fence_release);
0136 }