Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * fence-chain: chain fences together in a timeline
0004  *
0005  * Copyright (C) 2018 Advanced Micro Devices, Inc.
0006  * Authors:
0007  *  Christian König <christian.koenig@amd.com>
0008  */
0009 
0010 #ifndef __LINUX_DMA_FENCE_CHAIN_H
0011 #define __LINUX_DMA_FENCE_CHAIN_H
0012 
0013 #include <linux/dma-fence.h>
0014 #include <linux/irq_work.h>
0015 #include <linux/slab.h>
0016 
0017 /**
0018  * struct dma_fence_chain - fence to represent an node of a fence chain
0019  * @base: fence base class
0020  * @prev: previous fence of the chain
0021  * @prev_seqno: original previous seqno before garbage collection
0022  * @fence: encapsulated fence
0023  * @lock: spinlock for fence handling
0024  */
0025 struct dma_fence_chain {
0026     struct dma_fence base;
0027     struct dma_fence __rcu *prev;
0028     u64 prev_seqno;
0029     struct dma_fence *fence;
0030     union {
0031         /**
0032          * @cb: callback for signaling
0033          *
0034          * This is used to add the callback for signaling the
0035          * complection of the fence chain. Never used at the same time
0036          * as the irq work.
0037          */
0038         struct dma_fence_cb cb;
0039 
0040         /**
0041          * @work: irq work item for signaling
0042          *
0043          * Irq work structure to allow us to add the callback without
0044          * running into lock inversion. Never used at the same time as
0045          * the callback.
0046          */
0047         struct irq_work work;
0048     };
0049     spinlock_t lock;
0050 };
0051 
0052 
0053 /**
0054  * to_dma_fence_chain - cast a fence to a dma_fence_chain
0055  * @fence: fence to cast to a dma_fence_array
0056  *
0057  * Returns NULL if the fence is not a dma_fence_chain,
0058  * or the dma_fence_chain otherwise.
0059  */
0060 static inline struct dma_fence_chain *
0061 to_dma_fence_chain(struct dma_fence *fence)
0062 {
0063     if (!fence || !dma_fence_is_chain(fence))
0064         return NULL;
0065 
0066     return container_of(fence, struct dma_fence_chain, base);
0067 }
0068 
0069 /**
0070  * dma_fence_chain_contained - return the contained fence
0071  * @fence: the fence to test
0072  *
0073  * If the fence is a dma_fence_chain the function returns the fence contained
0074  * inside the chain object, otherwise it returns the fence itself.
0075  */
0076 static inline struct dma_fence *
0077 dma_fence_chain_contained(struct dma_fence *fence)
0078 {
0079     struct dma_fence_chain *chain = to_dma_fence_chain(fence);
0080 
0081     return chain ? chain->fence : fence;
0082 }
0083 
0084 /**
0085  * dma_fence_chain_alloc
0086  *
0087  * Returns a new struct dma_fence_chain object or NULL on failure.
0088  */
0089 static inline struct dma_fence_chain *dma_fence_chain_alloc(void)
0090 {
0091     return kmalloc(sizeof(struct dma_fence_chain), GFP_KERNEL);
0092 };
0093 
0094 /**
0095  * dma_fence_chain_free
0096  * @chain: chain node to free
0097  *
0098  * Frees up an allocated but not used struct dma_fence_chain object. This
0099  * doesn't need an RCU grace period since the fence was never initialized nor
0100  * published. After dma_fence_chain_init() has been called the fence must be
0101  * released by calling dma_fence_put(), and not through this function.
0102  */
0103 static inline void dma_fence_chain_free(struct dma_fence_chain *chain)
0104 {
0105     kfree(chain);
0106 };
0107 
0108 /**
0109  * dma_fence_chain_for_each - iterate over all fences in chain
0110  * @iter: current fence
0111  * @head: starting point
0112  *
0113  * Iterate over all fences in the chain. We keep a reference to the current
0114  * fence while inside the loop which must be dropped when breaking out.
0115  *
0116  * For a deep dive iterator see dma_fence_unwrap_for_each().
0117  */
0118 #define dma_fence_chain_for_each(iter, head)    \
0119     for (iter = dma_fence_get(head); iter; \
0120          iter = dma_fence_chain_walk(iter))
0121 
0122 struct dma_fence *dma_fence_chain_walk(struct dma_fence *fence);
0123 int dma_fence_chain_find_seqno(struct dma_fence **pfence, uint64_t seqno);
0124 void dma_fence_chain_init(struct dma_fence_chain *chain,
0125               struct dma_fence *prev,
0126               struct dma_fence *fence,
0127               uint64_t seqno);
0128 
0129 #endif /* __LINUX_DMA_FENCE_CHAIN_H */