diff options
Diffstat (limited to 'jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/event.c')
-rw-r--r-- | jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/event.c | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/event.c b/jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/event.c new file mode 100644 index 0000000..c335640 --- /dev/null +++ b/jacinto6/sgx_src/eurasia_km/services4/srvkm/env/linux/event.c | |||
@@ -0,0 +1,414 @@ | |||
1 | /*************************************************************************/ /*! | ||
2 | @Title Event Object | ||
3 | @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved | ||
4 | @License Dual MIT/GPLv2 | ||
5 | |||
6 | The contents of this file are subject to the MIT license as set out below. | ||
7 | |||
8 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
9 | of this software and associated documentation files (the "Software"), to deal | ||
10 | in the Software without restriction, including without limitation the rights | ||
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
12 | copies of the Software, and to permit persons to whom the Software is | ||
13 | furnished to do so, subject to the following conditions: | ||
14 | |||
15 | The above copyright notice and this permission notice shall be included in | ||
16 | all copies or substantial portions of the Software. | ||
17 | |||
18 | Alternatively, the contents of this file may be used under the terms of | ||
19 | the GNU General Public License Version 2 ("GPL") in which case the provisions | ||
20 | of GPL are applicable instead of those above. | ||
21 | |||
22 | If you wish to allow use of your version of this file only under the terms of | ||
23 | GPL, and not to allow others to use your version of this file under the terms | ||
24 | of the MIT license, indicate your decision by deleting the provisions above | ||
25 | and replace them with the notice and other provisions required by GPL as set | ||
26 | out in the file called "GPL-COPYING" included in this distribution. If you do | ||
27 | not delete the provisions above, a recipient may use your version of this file | ||
28 | under the terms of either the MIT license or GPL. | ||
29 | |||
30 | This License is also included in this distribution in the file called | ||
31 | "MIT-COPYING". | ||
32 | |||
33 | EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS | ||
34 | PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | ||
35 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
36 | PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR | ||
37 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
38 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
39 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
40 | */ /**************************************************************************/ | ||
41 | |||
42 | #include <linux/version.h> | ||
43 | |||
44 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) | ||
45 | #ifndef AUTOCONF_INCLUDED | ||
46 | #include <linux/config.h> | ||
47 | #endif | ||
48 | #endif | ||
49 | |||
50 | #include <asm/io.h> | ||
51 | #include <asm/page.h> | ||
52 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) | ||
53 | #include <asm/system.h> | ||
54 | #endif | ||
55 | #include <linux/mm.h> | ||
56 | #include <linux/slab.h> | ||
57 | #include <linux/vmalloc.h> | ||
58 | #include <linux/delay.h> | ||
59 | #include <linux/pci.h> | ||
60 | |||
61 | #include <linux/string.h> | ||
62 | #include <linux/sched.h> | ||
63 | #include <linux/interrupt.h> | ||
64 | #include <asm/hardirq.h> | ||
65 | #include <linux/spinlock.h> | ||
66 | #include <linux/timer.h> | ||
67 | #include <linux/capability.h> | ||
68 | #include <linux/sched.h> | ||
69 | #include <asm/uaccess.h> | ||
70 | |||
71 | #include "img_types.h" | ||
72 | #include "services_headers.h" | ||
73 | #include "mm.h" | ||
74 | #include "pvrmmap.h" | ||
75 | #include "mmap.h" | ||
76 | #include "env_data.h" | ||
77 | #include "proc.h" | ||
78 | #include "mutex.h" | ||
79 | #include "lock.h" | ||
80 | #include "event.h" | ||
81 | |||
82 | typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG | ||
83 | { | ||
84 | rwlock_t sLock; | ||
85 | struct list_head sList; | ||
86 | |||
87 | } PVRSRV_LINUX_EVENT_OBJECT_LIST; | ||
88 | |||
89 | |||
90 | typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG | ||
91 | { | ||
92 | atomic_t sTimeStamp; | ||
93 | IMG_UINT32 ui32TimeStampPrevious; | ||
94 | #if defined(DEBUG) | ||
95 | IMG_UINT ui32Stats; | ||
96 | #endif | ||
97 | wait_queue_head_t sWait; | ||
98 | struct list_head sList; | ||
99 | IMG_HANDLE hResItem; | ||
100 | PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList; | ||
101 | } PVRSRV_LINUX_EVENT_OBJECT; | ||
102 | |||
103 | /*! | ||
104 | ****************************************************************************** | ||
105 | |||
106 | @Function LinuxEventObjectListCreate | ||
107 | |||
108 | @Description | ||
109 | |||
110 | Linux wait object list creation | ||
111 | |||
112 | @Output hOSEventKM : Pointer to the event object list handle | ||
113 | |||
114 | @Return PVRSRV_ERROR : Error code | ||
115 | |||
116 | ******************************************************************************/ | ||
117 | PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList) | ||
118 | { | ||
119 | PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList; | ||
120 | |||
121 | if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), | ||
122 | (IMG_VOID **)&psEventObjectList, IMG_NULL, | ||
123 | "Linux Event Object List") != PVRSRV_OK) | ||
124 | { | ||
125 | PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list")); | ||
126 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
127 | } | ||
128 | |||
129 | INIT_LIST_HEAD(&psEventObjectList->sList); | ||
130 | |||
131 | rwlock_init(&psEventObjectList->sLock); | ||
132 | |||
133 | *phEventObjectList = (IMG_HANDLE *) psEventObjectList; | ||
134 | |||
135 | return PVRSRV_OK; | ||
136 | } | ||
137 | |||
138 | /*! | ||
139 | ****************************************************************************** | ||
140 | |||
141 | @Function LinuxEventObjectListDestroy | ||
142 | |||
143 | @Description | ||
144 | |||
145 | Linux wait object list destruction | ||
146 | |||
147 | @Input hOSEventKM : Event object list handle | ||
148 | |||
149 | @Return PVRSRV_ERROR : Error code | ||
150 | |||
151 | ******************************************************************************/ | ||
152 | PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList) | ||
153 | { | ||
154 | |||
155 | PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ; | ||
156 | |||
157 | if(psEventObjectList) | ||
158 | { | ||
159 | IMG_BOOL bListEmpty; | ||
160 | |||
161 | read_lock(&psEventObjectList->sLock); | ||
162 | bListEmpty = list_empty(&psEventObjectList->sList); | ||
163 | read_unlock(&psEventObjectList->sLock); | ||
164 | |||
165 | if (!bListEmpty) | ||
166 | { | ||
167 | PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty")); | ||
168 | return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT; | ||
169 | } | ||
170 | |||
171 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEventObjectList, IMG_NULL); | ||
172 | /*not nulling pointer, copy on stack*/ | ||
173 | } | ||
174 | |||
175 | return PVRSRV_OK; | ||
176 | } | ||
177 | |||
178 | |||
179 | /*! | ||
180 | ****************************************************************************** | ||
181 | |||
182 | @Function LinuxEventObjectDelete | ||
183 | |||
184 | @Description | ||
185 | |||
186 | Linux wait object removal | ||
187 | |||
188 | @Input hOSEventObjectList : Event object list handle | ||
189 | @Input hOSEventObject : Event object handle | ||
190 | @Input bResManCallback : Called from the resman | ||
191 | |||
192 | @Return PVRSRV_ERROR : Error code | ||
193 | |||
194 | ******************************************************************************/ | ||
195 | PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject) | ||
196 | { | ||
197 | if(hOSEventObjectList) | ||
198 | { | ||
199 | if(hOSEventObject) | ||
200 | { | ||
201 | PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject; | ||
202 | #if defined(DEBUG) | ||
203 | PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %u", psLinuxEventObject->ui32Stats)); | ||
204 | #endif | ||
205 | if(ResManFreeResByPtr(psLinuxEventObject->hResItem, CLEANUP_WITH_POLL) != PVRSRV_OK) | ||
206 | { | ||
207 | return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT; | ||
208 | } | ||
209 | |||
210 | return PVRSRV_OK; | ||
211 | } | ||
212 | } | ||
213 | return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT; | ||
214 | |||
215 | } | ||
216 | |||
217 | /*! | ||
218 | ****************************************************************************** | ||
219 | |||
220 | @Function LinuxEventObjectDeleteCallback | ||
221 | |||
222 | @Description | ||
223 | |||
224 | Linux wait object removal | ||
225 | |||
226 | @Input hOSEventObject : Event object handle | ||
227 | |||
228 | @Return PVRSRV_ERROR : Error code | ||
229 | |||
230 | ******************************************************************************/ | ||
231 | static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup) | ||
232 | { | ||
233 | PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam; | ||
234 | PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList; | ||
235 | unsigned long ulLockFlags; | ||
236 | |||
237 | PVR_UNREFERENCED_PARAMETER(ui32Param); | ||
238 | PVR_UNREFERENCED_PARAMETER(bForceCleanup); | ||
239 | |||
240 | write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags); | ||
241 | list_del(&psLinuxEventObject->sList); | ||
242 | write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags); | ||
243 | |||
244 | #if defined(DEBUG) | ||
245 | PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %u", psLinuxEventObject->ui32Stats)); | ||
246 | #endif | ||
247 | |||
248 | OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL); | ||
249 | /*not nulling pointer, copy on stack*/ | ||
250 | |||
251 | return PVRSRV_OK; | ||
252 | } | ||
253 | /*! | ||
254 | ****************************************************************************** | ||
255 | |||
256 | @Function LinuxEventObjectAdd | ||
257 | |||
258 | @Description | ||
259 | |||
260 | Linux wait object addition | ||
261 | |||
262 | @Input hOSEventObjectList : Event object list handle | ||
263 | @Output phOSEventObject : Pointer to the event object handle | ||
264 | |||
265 | @Return PVRSRV_ERROR : Error code | ||
266 | |||
267 | ******************************************************************************/ | ||
268 | PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject) | ||
269 | { | ||
270 | PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject; | ||
271 | PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; | ||
272 | IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); | ||
273 | PVRSRV_PER_PROCESS_DATA *psPerProc; | ||
274 | unsigned long ulLockFlags; | ||
275 | |||
276 | psPerProc = PVRSRVPerProcessData(ui32PID); | ||
277 | if (psPerProc == IMG_NULL) | ||
278 | { | ||
279 | PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data")); | ||
280 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
281 | } | ||
282 | |||
283 | /* allocate completion variable */ | ||
284 | if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), | ||
285 | (IMG_VOID **)&psLinuxEventObject, IMG_NULL, | ||
286 | "Linux Event Object") != PVRSRV_OK) | ||
287 | { | ||
288 | PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory ")); | ||
289 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
290 | } | ||
291 | |||
292 | INIT_LIST_HEAD(&psLinuxEventObject->sList); | ||
293 | |||
294 | atomic_set(&psLinuxEventObject->sTimeStamp, 0); | ||
295 | psLinuxEventObject->ui32TimeStampPrevious = 0; | ||
296 | |||
297 | #if defined(DEBUG) | ||
298 | psLinuxEventObject->ui32Stats = 0; | ||
299 | #endif | ||
300 | init_waitqueue_head(&psLinuxEventObject->sWait); | ||
301 | |||
302 | psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList; | ||
303 | |||
304 | psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext, | ||
305 | RESMAN_TYPE_EVENT_OBJECT, | ||
306 | psLinuxEventObject, | ||
307 | 0, | ||
308 | &LinuxEventObjectDeleteCallback); | ||
309 | |||
310 | write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags); | ||
311 | list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList); | ||
312 | write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags); | ||
313 | |||
314 | *phOSEventObject = psLinuxEventObject; | ||
315 | |||
316 | return PVRSRV_OK; | ||
317 | } | ||
318 | |||
319 | /*! | ||
320 | ****************************************************************************** | ||
321 | |||
322 | @Function LinuxEventObjectSignal | ||
323 | |||
324 | @Description | ||
325 | |||
326 | Linux wait object signaling function | ||
327 | |||
328 | @Input hOSEventObjectList : Event object list handle | ||
329 | |||
330 | @Return PVRSRV_ERROR : Error code | ||
331 | |||
332 | ******************************************************************************/ | ||
333 | PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList) | ||
334 | { | ||
335 | PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject; | ||
336 | PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; | ||
337 | struct list_head *psListEntry, *psList; | ||
338 | |||
339 | psList = &psLinuxEventObjectList->sList; | ||
340 | |||
341 | /* | ||
342 | * We don't take the write lock in interrupt context, so we don't | ||
343 | * need to use read_lock_irqsave. | ||
344 | */ | ||
345 | read_lock(&psLinuxEventObjectList->sLock); | ||
346 | list_for_each(psListEntry, psList) | ||
347 | { | ||
348 | |||
349 | psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList); | ||
350 | |||
351 | atomic_inc(&psLinuxEventObject->sTimeStamp); | ||
352 | wake_up_interruptible(&psLinuxEventObject->sWait); | ||
353 | } | ||
354 | read_unlock(&psLinuxEventObjectList->sLock); | ||
355 | |||
356 | return PVRSRV_OK; | ||
357 | |||
358 | } | ||
359 | |||
360 | /*! | ||
361 | ****************************************************************************** | ||
362 | |||
363 | @Function LinuxEventObjectWait | ||
364 | |||
365 | @Description | ||
366 | |||
367 | Linux wait object routine | ||
368 | |||
369 | @Input hOSEventObject : Event object handle | ||
370 | |||
371 | @Input ui32MSTimeout : Time out value in msec | ||
372 | |||
373 | @Return PVRSRV_ERROR : Error code | ||
374 | |||
375 | ******************************************************************************/ | ||
376 | PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout) | ||
377 | { | ||
378 | IMG_UINT32 ui32TimeStamp; | ||
379 | DEFINE_WAIT(sWait); | ||
380 | |||
381 | PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject; | ||
382 | |||
383 | IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout); | ||
384 | |||
385 | do | ||
386 | { | ||
387 | prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE); | ||
388 | ui32TimeStamp = (IMG_UINT32)atomic_read(&psLinuxEventObject->sTimeStamp); | ||
389 | |||
390 | if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp) | ||
391 | { | ||
392 | break; | ||
393 | } | ||
394 | |||
395 | LinuxUnLockMutex(&gPVRSRVLock); | ||
396 | |||
397 | ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies); | ||
398 | |||
399 | LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); | ||
400 | #if defined(DEBUG) | ||
401 | psLinuxEventObject->ui32Stats++; | ||
402 | #endif | ||
403 | |||
404 | |||
405 | } while (ui32TimeOutJiffies); | ||
406 | |||
407 | finish_wait(&psLinuxEventObject->sWait, &sWait); | ||
408 | |||
409 | psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp; | ||
410 | |||
411 | return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT; | ||
412 | |||
413 | } | ||
414 | |||