1 /* 2 * Copyright (c) 2019 Jonathan Gray <jsg@openbsd.org> 3 * Copyright (c) 2020 François Tigeot <ftigeot@wolfpond.org> 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #ifndef _LINUX_DMA_FENCE_H_ 26 #define _LINUX_DMA_FENCE_H_ 27 28 #include <linux/err.h> 29 #include <linux/wait.h> 30 #include <linux/list.h> 31 #include <linux/bitops.h> 32 #include <linux/kref.h> 33 #include <linux/sched.h> 34 #include <linux/printk.h> 35 #include <linux/rcupdate.h> 36 37 #define DMA_FENCE_TRACE(fence, fmt, args...) do {} while(0) 38 39 struct dma_fence_cb; 40 41 struct dma_fence { 42 struct kref refcount; 43 struct lock *lock; 44 const struct dma_fence_ops *ops; 45 struct rcu_head rcu; 46 struct list_head cb_list; 47 u64 context; 48 unsigned seqno; 49 unsigned long flags; 50 ktime_t timestamp; 51 int error; 52 }; 53 54 enum dma_fence_flag_bits { 55 DMA_FENCE_FLAG_SIGNALED_BIT, 56 DMA_FENCE_FLAG_TIMESTAMP_BIT, 57 DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, 58 DMA_FENCE_FLAG_USER_BITS, /* must always be last member */ 59 }; 60 61 typedef void (*dma_fence_func_t)(struct dma_fence *fence, 62 struct dma_fence_cb *cb); 63 64 struct dma_fence_cb { 65 struct list_head node; 66 dma_fence_func_t func; 67 }; 68 69 struct dma_fence_ops { 70 const char * (*get_driver_name)(struct dma_fence *fence); 71 const char * (*get_timeline_name)(struct dma_fence *fence); 72 bool (*enable_signaling)(struct dma_fence *fence); 73 bool (*signaled)(struct dma_fence *fence); 74 signed long (*wait)(struct dma_fence *fence, 75 bool intr, signed long timeout); 76 void (*release)(struct dma_fence *fence); 77 78 int (*fill_driver_data)(struct dma_fence *fence, void *data, int size); 79 void (*fence_value_str)(struct dma_fence *fence, char *str, int size); 80 void (*timeline_value_str)(struct dma_fence *fence, 81 char *str, int size); 82 }; 83 84 void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, 85 spinlock_t *lock, u64 context, unsigned seqno); 86 87 void dma_fence_release(struct kref *kref); 88 89 static inline struct dma_fence * 90 dma_fence_get(struct dma_fence *fence) 91 { 92 if (fence) 93 kref_get(&fence->refcount); 94 return fence; 95 } 96 97 static inline struct dma_fence * 98 dma_fence_get_rcu(struct dma_fence *fence) 99 { 100 if (fence) 101 kref_get(&fence->refcount); 102 return fence; 103 } 104 105 static inline void 106 dma_fence_put(struct dma_fence *fence) 107 { 108 if (fence) 109 kref_put(&fence->refcount, dma_fence_release); 110 } 111 112 int dma_fence_signal(struct dma_fence *fence); 113 int dma_fence_signal_locked(struct dma_fence *fence); 114 115 static inline bool 116 dma_fence_is_signaled(struct dma_fence *fence) 117 { 118 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) 119 return true; 120 121 if (fence->ops->signaled && fence->ops->signaled(fence)) { 122 dma_fence_signal(fence); 123 return true; 124 } 125 126 return false; 127 } 128 129 void dma_fence_enable_sw_signaling(struct dma_fence *fence); 130 131 signed long dma_fence_default_wait(struct dma_fence *fence, 132 bool intr, signed long timeout); 133 signed long dma_fence_wait_timeout(struct dma_fence *, 134 bool intr, signed long timeout); 135 signed long dma_fence_wait_any_timeout(struct dma_fence **fences, 136 uint32_t count, 137 bool intr, signed long timeout, uint32_t *idx); 138 139 static inline signed long 140 dma_fence_wait(struct dma_fence *fence, bool intr) 141 { 142 signed long ret; 143 144 ret = dma_fence_wait_timeout(fence, intr, MAX_SCHEDULE_TIMEOUT); 145 146 if (ret < 0) 147 return ret; 148 149 return 0; 150 } 151 152 int dma_fence_add_callback(struct dma_fence *fence, 153 struct dma_fence_cb *cb, 154 dma_fence_func_t func); 155 156 bool dma_fence_remove_callback(struct dma_fence *fence, 157 struct dma_fence_cb *cb); 158 159 u64 dma_fence_context_alloc(unsigned num); 160 161 static inline bool 162 dma_fence_is_later(struct dma_fence *a, struct dma_fence *b) 163 { 164 return (a->seqno > b->seqno); 165 } 166 167 static inline void 168 dma_fence_set_error(struct dma_fence *fence, int error) 169 { 170 fence->error = error; 171 } 172 173 static inline struct dma_fence * 174 dma_fence_get_rcu_safe(struct dma_fence **dfp) 175 { 176 struct dma_fence *fence; 177 if (dfp == NULL) 178 return NULL; 179 fence = *dfp; 180 if (fence) 181 kref_get(&fence->refcount); 182 return fence; 183 } 184 185 void dma_fence_free(struct dma_fence *fence); 186 187 #endif /* _LINUX_DMA_FENCE_H_ */ 188