diff options
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.c | 158 |
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 | |||
20 | struct 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 | |||
31 | struct PVR_COUNTING_FENCE { | ||
32 | IMG_UINT64 ui64Value; | ||
33 | struct dma_fence *psFence; | ||
34 | struct list_head sActive_list_entry; | ||
35 | }; | ||
36 | |||
37 | struct 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 | |||
55 | err_out: | ||
56 | return psFenceTimeline; | ||
57 | |||
58 | err_free_timeline: | ||
59 | kfree(psFenceTimeline); | ||
60 | psFenceTimeline = NULL; | ||
61 | goto err_out; | ||
62 | } | ||
63 | |||
64 | void 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 | |||
83 | static 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 | |||
93 | void pvr_counting_fence_timeline_put(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline) | ||
94 | { | ||
95 | kref_put(&psFenceTimeline->sRef, pvr_counting_fence_timeline_destroy); | ||
96 | } | ||
97 | |||
98 | struct 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 | |||
106 | struct 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 | |||
130 | err_free_fence: | ||
131 | kfree(psCountFence); | ||
132 | return NULL; | ||
133 | } | ||
134 | |||
135 | void 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 | } | ||