68 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			68 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: MIT */
 | |
| 
 | |
| /*
 | |
|  * Copyright © 2019 Intel Corporation
 | |
|  */
 | |
| 
 | |
| #ifndef I915_SW_FENCE_WORK_H
 | |
| #define I915_SW_FENCE_WORK_H
 | |
| 
 | |
| #include <linux/dma-fence.h>
 | |
| #include <linux/spinlock.h>
 | |
| #include <linux/workqueue.h>
 | |
| 
 | |
| #include "i915_sw_fence.h"
 | |
| 
 | |
| struct dma_fence_work;
 | |
| 
 | |
| struct dma_fence_work_ops {
 | |
| 	const char *name;
 | |
| 	void (*work)(struct dma_fence_work *f);
 | |
| 	void (*release)(struct dma_fence_work *f);
 | |
| };
 | |
| 
 | |
| struct dma_fence_work {
 | |
| 	struct dma_fence dma;
 | |
| 	spinlock_t lock;
 | |
| 
 | |
| 	struct i915_sw_fence chain;
 | |
| 	struct i915_sw_dma_fence_cb cb;
 | |
| 
 | |
| 	struct work_struct work;
 | |
| 	const struct dma_fence_work_ops *ops;
 | |
| };
 | |
| 
 | |
| enum {
 | |
| 	DMA_FENCE_WORK_IMM = DMA_FENCE_FLAG_USER_BITS,
 | |
| };
 | |
| 
 | |
| void dma_fence_work_init(struct dma_fence_work *f,
 | |
| 			 const struct dma_fence_work_ops *ops);
 | |
| int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal);
 | |
| 
 | |
| static inline void dma_fence_work_commit(struct dma_fence_work *f)
 | |
| {
 | |
| 	i915_sw_fence_commit(&f->chain);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * dma_fence_work_commit_imm: Commit the fence, and if possible execute locally.
 | |
|  * @f: the fenced worker
 | |
|  *
 | |
|  * Instead of always scheduling a worker to execute the callback (see
 | |
|  * dma_fence_work_commit()), we try to execute the callback immediately in
 | |
|  * the local context. It is required that the fence be committed before it
 | |
|  * is published, and that no other threads try to tamper with the number
 | |
|  * of asynchronous waits on the fence (or else the callback will be
 | |
|  * executed in the wrong context, i.e. not the callers).
 | |
|  */
 | |
| static inline void dma_fence_work_commit_imm(struct dma_fence_work *f)
 | |
| {
 | |
| 	if (atomic_read(&f->chain.pending) <= 1)
 | |
| 		__set_bit(DMA_FENCE_WORK_IMM, &f->dma.flags);
 | |
| 
 | |
| 	dma_fence_work_commit(f);
 | |
| }
 | |
| 
 | |
| #endif /* I915_SW_FENCE_WORK_H */
 |