18e458fe2SChris Wilson /* SPDX-License-Identifier: MIT */ 28e458fe2SChris Wilson 38e458fe2SChris Wilson /* 48e458fe2SChris Wilson * Copyright © 2019 Intel Corporation 58e458fe2SChris Wilson */ 68e458fe2SChris Wilson 78e458fe2SChris Wilson #ifndef I915_SW_FENCE_WORK_H 88e458fe2SChris Wilson #define I915_SW_FENCE_WORK_H 98e458fe2SChris Wilson 108e458fe2SChris Wilson #include <linux/dma-fence.h> 118e458fe2SChris Wilson #include <linux/spinlock.h> 128e458fe2SChris Wilson #include <linux/workqueue.h> 138e458fe2SChris Wilson 148e458fe2SChris Wilson #include "i915_sw_fence.h" 158e458fe2SChris Wilson 168e458fe2SChris Wilson struct dma_fence_work; 178e458fe2SChris Wilson 188e458fe2SChris Wilson struct dma_fence_work_ops { 198e458fe2SChris Wilson const char *name; 20*dc194184SJason Ekstrand void (*work)(struct dma_fence_work *f); 218e458fe2SChris Wilson void (*release)(struct dma_fence_work *f); 228e458fe2SChris Wilson }; 238e458fe2SChris Wilson 248e458fe2SChris Wilson struct dma_fence_work { 258e458fe2SChris Wilson struct dma_fence dma; 268e458fe2SChris Wilson spinlock_t lock; 278e458fe2SChris Wilson 288e458fe2SChris Wilson struct i915_sw_fence chain; 298e458fe2SChris Wilson struct i915_sw_dma_fence_cb cb; 308e458fe2SChris Wilson 318e458fe2SChris Wilson struct work_struct work; 328e458fe2SChris Wilson const struct dma_fence_work_ops *ops; 338e458fe2SChris Wilson }; 348e458fe2SChris Wilson 3592581f9fSChris Wilson enum { 3692581f9fSChris Wilson DMA_FENCE_WORK_IMM = DMA_FENCE_FLAG_USER_BITS, 3792581f9fSChris Wilson }; 3892581f9fSChris Wilson 398e458fe2SChris Wilson void dma_fence_work_init(struct dma_fence_work *f, 408e458fe2SChris Wilson const struct dma_fence_work_ops *ops); 418e458fe2SChris Wilson int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal); 428e458fe2SChris Wilson dma_fence_work_commit(struct dma_fence_work * f)438e458fe2SChris Wilsonstatic inline void dma_fence_work_commit(struct dma_fence_work *f) 448e458fe2SChris Wilson { 458e458fe2SChris Wilson i915_sw_fence_commit(&f->chain); 468e458fe2SChris Wilson } 478e458fe2SChris Wilson 4892581f9fSChris Wilson /** 4992581f9fSChris Wilson * dma_fence_work_commit_imm: Commit the fence, and if possible execute locally. 5092581f9fSChris Wilson * @f: the fenced worker 5192581f9fSChris Wilson * 5292581f9fSChris Wilson * Instead of always scheduling a worker to execute the callback (see 5392581f9fSChris Wilson * dma_fence_work_commit()), we try to execute the callback immediately in 5492581f9fSChris Wilson * the local context. It is required that the fence be committed before it 5592581f9fSChris Wilson * is published, and that no other threads try to tamper with the number 5692581f9fSChris Wilson * of asynchronous waits on the fence (or else the callback will be 5792581f9fSChris Wilson * executed in the wrong context, i.e. not the callers). 5892581f9fSChris Wilson */ dma_fence_work_commit_imm(struct dma_fence_work * f)5992581f9fSChris Wilsonstatic inline void dma_fence_work_commit_imm(struct dma_fence_work *f) 6092581f9fSChris Wilson { 6192581f9fSChris Wilson if (atomic_read(&f->chain.pending) <= 1) 6292581f9fSChris Wilson __set_bit(DMA_FENCE_WORK_IMM, &f->dma.flags); 6392581f9fSChris Wilson 6492581f9fSChris Wilson dma_fence_work_commit(f); 6592581f9fSChris Wilson } 6692581f9fSChris Wilson 678e458fe2SChris Wilson #endif /* I915_SW_FENCE_WORK_H */ 68