summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'sgx_km/eurasia_km/services4/srvkm/env/linux/pvr_counting_timeline.c')
-rw-r--r--sgx_km/eurasia_km/services4/srvkm/env/linux/pvr_counting_timeline.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/sgx_km/eurasia_km/services4/srvkm/env/linux/pvr_counting_timeline.c b/sgx_km/eurasia_km/services4/srvkm/env/linux/pvr_counting_timeline.c
new file mode 100644
index 0000000..c0485a1
--- /dev/null
+++ b/sgx_km/eurasia_km/services4/srvkm/env/linux/pvr_counting_timeline.c
@@ -0,0 +1,158 @@
1/*************************************************************************/ /*!
2@File
3@Title PowerVR Linux software "counting" timeline fence implementation
4@Codingstyle LinuxKernel
5@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
6@License Strictly Confidential.
7*/ /**************************************************************************/
8
9#include <linux/kernel.h>
10#include <linux/slab.h>
11#include <linux/kref.h>
12#include <linux/sync_file.h>
13
14#include "img_types.h"
15#include "services_headers.h"
16#include "servicesext.h"
17#include "pvr_counting_timeline.h"
18#include "pvr_sw_fence.h"
19
20struct PVR_COUNTING_FENCE_TIMELINE {
21 char name[32];
22 struct PVR_SW_FENCE_CONTEXT *psSwFenceCtx;
23
24 spinlock_t sActive_fences_lock;
25 IMG_UINT64 ui64Current_value; /* guarded by active_fences_lock */
26 struct list_head sActive_fences;
27
28 struct kref sRef;
29};
30
31struct PVR_COUNTING_FENCE {
32 IMG_UINT64 ui64Value;
33 struct dma_fence *psFence;
34 struct list_head sActive_list_entry;
35};
36
37struct PVR_COUNTING_FENCE_TIMELINE *pvr_counting_fence_timeline_create(const char *name)
38{
39 struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline = kmalloc(sizeof(*psFenceTimeline), GFP_KERNEL);
40
41 if (!psFenceTimeline)
42 goto err_out;
43
44 strlcpy(psFenceTimeline->name, name, sizeof(psFenceTimeline->name));
45
46 psFenceTimeline->psSwFenceCtx = pvr_sw_fence_context_create(psFenceTimeline->name, "pvr_sw_sync");
47 if (!psFenceTimeline->psSwFenceCtx)
48 goto err_free_timeline;
49
50 psFenceTimeline->ui64Current_value = 0;
51 kref_init(&psFenceTimeline->sRef);
52 spin_lock_init(&psFenceTimeline->sActive_fences_lock);
53 INIT_LIST_HEAD(&psFenceTimeline->sActive_fences);
54
55err_out:
56 return psFenceTimeline;
57
58err_free_timeline:
59 kfree(psFenceTimeline);
60 psFenceTimeline = NULL;
61 goto err_out;
62}
63
64void pvr_counting_fence_timeline_force_complete(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline)
65{
66 struct list_head *entry, *tmp;
67 unsigned long flags;
68
69 spin_lock_irqsave(&psFenceTimeline->sActive_fences_lock, flags);
70
71 list_for_each_safe(entry, tmp, &psFenceTimeline->sActive_fences)
72 {
73 struct PVR_COUNTING_FENCE *psPvrCountingFence = list_entry(entry, struct PVR_COUNTING_FENCE, sActive_list_entry);
74 dma_fence_signal(psPvrCountingFence->psFence);
75 dma_fence_put(psPvrCountingFence->psFence);
76 psPvrCountingFence->psFence = NULL;
77 list_del(&psPvrCountingFence->sActive_list_entry);
78 kfree(psPvrCountingFence);
79 }
80 spin_unlock_irqrestore(&psFenceTimeline->sActive_fences_lock, flags);
81}
82
83static void pvr_counting_fence_timeline_destroy(struct kref *kref)
84{
85 struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline = container_of(kref, struct PVR_COUNTING_FENCE_TIMELINE, sRef);
86
87 WARN_ON(!list_empty(&psFenceTimeline->sActive_fences));
88
89 pvr_sw_fence_context_destroy(psFenceTimeline->psSwFenceCtx);
90 kfree(psFenceTimeline);
91}
92
93void pvr_counting_fence_timeline_put(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline)
94{
95 kref_put(&psFenceTimeline->sRef, pvr_counting_fence_timeline_destroy);
96}
97
98struct PVR_COUNTING_FENCE_TIMELINE *pvr_counting_fence_timeline_get(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline)
99{
100 if (!psFenceTimeline)
101 return NULL;
102 kref_get(&psFenceTimeline->sRef);
103 return psFenceTimeline;
104}
105
106struct dma_fence *pvr_counting_fence_create(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline, IMG_UINT64 ui64Value)
107{
108 unsigned long flags;
109 struct dma_fence *psSwFence;
110 struct PVR_COUNTING_FENCE *psCountFence = kmalloc(sizeof(*psCountFence), GFP_KERNEL);
111
112 if (!psCountFence)
113 return NULL;
114
115 psSwFence = pvr_sw_fence_create(psFenceTimeline->psSwFenceCtx);
116 if (!psSwFence)
117 goto err_free_fence;
118
119 psCountFence->psFence = dma_fence_get(psSwFence);
120 psCountFence->ui64Value = ui64Value;
121
122 spin_lock_irqsave(&psFenceTimeline->sActive_fences_lock, flags);
123
124 list_add_tail(&psCountFence->sActive_list_entry, &psFenceTimeline->sActive_fences);
125
126 spin_unlock_irqrestore(&psFenceTimeline->sActive_fences_lock, flags);
127
128 return psSwFence;
129
130err_free_fence:
131 kfree(psCountFence);
132 return NULL;
133}
134
135void pvr_counting_fence_timeline_inc(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline, IMG_UINT64 ui64Value)
136{
137 struct list_head *entry, *tmp;
138 unsigned long flags;
139
140 spin_lock_irqsave(&psFenceTimeline->sActive_fences_lock, flags);
141
142 psFenceTimeline->ui64Current_value += ui64Value;
143
144 list_for_each_safe(entry, tmp, &psFenceTimeline->sActive_fences)
145 {
146 struct PVR_COUNTING_FENCE *psCountFence = list_entry(entry, struct PVR_COUNTING_FENCE, sActive_list_entry);
147 if (psCountFence->ui64Value <= psFenceTimeline->ui64Current_value)
148 {
149 dma_fence_signal(psCountFence->psFence);
150 dma_fence_put(psCountFence->psFence);
151 psCountFence->psFence = NULL;
152 list_del(&psCountFence->sActive_list_entry);
153 kfree(psCountFence);
154 }
155 }
156
157 spin_unlock_irqrestore(&psFenceTimeline->sActive_fences_lock, flags);
158}