1 /* SPDX-License-Identifier: MIT */ 2 3 /* 4 * Copyright © 2019 Intel Corporation 5 */ 6 7 #ifndef I915_SW_FENCE_WORK_H 8 #define I915_SW_FENCE_WORK_H 9 10 #include <linux/dma-fence.h> 11 #include <linux/spinlock.h> 12 #include <linux/workqueue.h> 13 14 #include "i915_sw_fence.h" 15 16 struct dma_fence_work; 17 18 struct dma_fence_work_ops { 19 const char *name; 20 int (*work)(struct dma_fence_work *f); 21 void (*release)(struct dma_fence_work *f); 22 }; 23 24 struct dma_fence_work { 25 struct dma_fence dma; 26 spinlock_t lock; 27 28 struct i915_sw_fence chain; 29 struct i915_sw_dma_fence_cb cb; 30 31 struct work_struct work; 32 const struct dma_fence_work_ops *ops; 33 }; 34 35 enum { 36 DMA_FENCE_WORK_IMM = DMA_FENCE_FLAG_USER_BITS, 37 }; 38 39 void dma_fence_work_init(struct dma_fence_work *f, 40 const struct dma_fence_work_ops *ops); 41 int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal); 42 43 static inline void dma_fence_work_commit(struct dma_fence_work *f) 44 { 45 i915_sw_fence_commit(&f->chain); 46 } 47 48 /** 49 * dma_fence_work_commit_imm: Commit the fence, and if possible execute locally. 50 * @f: the fenced worker 51 * 52 * Instead of always scheduling a worker to execute the callback (see 53 * dma_fence_work_commit()), we try to execute the callback immediately in 54 * the local context. It is required that the fence be committed before it 55 * is published, and that no other threads try to tamper with the number 56 * of asynchronous waits on the fence (or else the callback will be 57 * executed in the wrong context, i.e. not the callers). 58 */ 59 static inline void dma_fence_work_commit_imm(struct dma_fence_work *f) 60 { 61 if (atomic_read(&f->chain.pending) <= 1) 62 __set_bit(DMA_FENCE_WORK_IMM, &f->dma.flags); 63 64 dma_fence_work_commit(f); 65 } 66 67 #endif /* I915_SW_FENCE_WORK_H */ 68