1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* fence-chain: chain fences together in a timeline
*
* Copyright (C) 2018 Advanced Micro Devices, Inc.
* Authors:
* Christian König <christian.koenig@amd.com>
*/
#ifndef __LINUX_DMA_FENCE_CHAIN_H
#define __LINUX_DMA_FENCE_CHAIN_H
#include <linux/dma-fence.h>
#include <linux/irq_work.h>
#include <linux/slab.h>
/**
* struct dma_fence_chain - fence to represent an node of a fence chain
* @base: fence base class
* @prev: previous fence of the chain
* @prev_seqno: original previous seqno before garbage collection
* @fence: encapsulated fence
* @lock: spinlock for fence handling
*/
struct dma_fence_chain {
struct dma_fence base;
struct dma_fence __rcu *prev;
u64 prev_seqno;
struct dma_fence *fence;
union {
/**
* @cb: callback for signaling
*
* This is used to add the callback for signaling the
* complection of the fence chain. Never used at the same time
* as the irq work.
*/
struct dma_fence_cb cb;
/**
* @work: irq work item for signaling
*
* Irq work structure to allow us to add the callback without
* running into lock inversion. Never used at the same time as
* the callback.
*/
struct irq_work work;
};
spinlock_t lock;
};
/**
* to_dma_fence_chain - cast a fence to a dma_fence_chain
* @fence: fence to cast to a dma_fence_array
*
* Returns NULL if the fence is not a dma_fence_chain,
* or the dma_fence_chain otherwise.
*/
static inline struct dma_fence_chain *
to_dma_fence_chain(struct dma_fence *fence)
{
if (!fence || !dma_fence_is_chain(fence))
return NULL;
return container_of(fence, struct dma_fence_chain, base);
}
/**
* dma_fence_chain_contained - return the contained fence
* @fence: the fence to test
*
* If the fence is a dma_fence_chain the function returns the fence contained
* inside the chain object, otherwise it returns the fence itself.
*/
static inline struct dma_fence *
dma_fence_chain_contained(struct dma_fence *fence)
{
struct dma_fence_chain *chain = to_dma_fence_chain(fence);
return chain ? chain->fence : fence;
}
/**
* dma_fence_chain_alloc
*
* Returns a new struct dma_fence_chain object or NULL on failure.
*
* This specialized allocator has to be a macro for its allocations to be
* accounted separately (to have a separate alloc_tag). The typecast is
* intentional to enforce typesafety.
*/
#define dma_fence_chain_alloc() \
((struct dma_fence_chain *)kmalloc(sizeof(struct dma_fence_chain), GFP_KERNEL))
/**
* dma_fence_chain_free
* @chain: chain node to free
*
* Frees up an allocated but not used struct dma_fence_chain object. This
* doesn't need an RCU grace period since the fence was never initialized nor
* published. After dma_fence_chain_init() has been called the fence must be
* released by calling dma_fence_put(), and not through this function.
*/
static inline void dma_fence_chain_free(struct dma_fence_chain *chain)
{
kfree(chain);
};
/**
* dma_fence_chain_for_each - iterate over all fences in chain
* @iter: current fence
* @head: starting point
*
* Iterate over all fences in the chain. We keep a reference to the current
* fence while inside the loop which must be dropped when breaking out.
*
* For a deep dive iterator see dma_fence_unwrap_for_each().
*/
#define dma_fence_chain_for_each(iter, head) \
for (iter = dma_fence_get(head); iter; \
iter = dma_fence_chain_walk(iter))
struct dma_fence *dma_fence_chain_walk(struct dma_fence *fence);
int dma_fence_chain_find_seqno(struct dma_fence **pfence, uint64_t seqno);
void dma_fence_chain_init(struct dma_fence_chain *chain,
struct dma_fence *prev,
struct dma_fence *fence,
uint64_t seqno);
#endif /* __LINUX_DMA_FENCE_CHAIN_H */
|