aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/pvr/queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/pvr/queue.c')
-rw-r--r--drivers/gpu/pvr/queue.c1154
1 files changed, 1154 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/queue.c b/drivers/gpu/pvr/queue.c
new file mode 100644
index 00000000000..5340571d64c
--- /dev/null
+++ b/drivers/gpu/pvr/queue.c
@@ -0,0 +1,1154 @@
1/**********************************************************************
2 *
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
20 *
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24 *
25 ******************************************************************************/
26
27#include "services_headers.h"
28
29#include "lists.h"
30
31#if defined(__linux__) && defined(__KERNEL__)
32
33#include "proc.h"
34
35static IMG_INT
36QueuePrintCommands (PVRSRV_QUEUE_INFO * psQueue, IMG_CHAR * buffer, size_t size)
37{
38 off_t off = 0;
39 IMG_INT cmds = 0;
40 IMG_SIZE_T ui32ReadOffset = psQueue->ui32ReadOffset;
41 IMG_SIZE_T ui32WriteOffset = psQueue->ui32WriteOffset;
42 PVRSRV_COMMAND * psCmd;
43
44 while (ui32ReadOffset != ui32WriteOffset)
45 {
46 psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset);
47
48 off = printAppend(buffer, size, off, "%x %x %5u %6u %3u %5u %2u %2u %3u \n",
49 (IMG_UINTPTR_T)psQueue,
50 (IMG_UINTPTR_T)psCmd,
51 psCmd->ui32ProcessID,
52 psCmd->CommandType,
53 psCmd->ui32CmdSize,
54 psCmd->ui32DevIndex,
55 psCmd->ui32DstSyncCount,
56 psCmd->ui32SrcSyncCount,
57 psCmd->ui32DataSize);
58
59 ui32ReadOffset += psCmd->ui32CmdSize;
60 ui32ReadOffset &= psQueue->ui32QueueSize - 1;
61 cmds++;
62 }
63 if (cmds == 0)
64 {
65 off = printAppend(buffer, size, off, "%x <empty>\n", (IMG_UINTPTR_T)psQueue);
66 }
67 return off;
68}
69
70
71
72void ProcSeqShowQueue(struct seq_file *sfile,void* el)
73{
74 PVRSRV_QUEUE_INFO * psQueue = (PVRSRV_QUEUE_INFO*)el;
75 IMG_INT cmds = 0;
76 IMG_SIZE_T ui32ReadOffset;
77 IMG_SIZE_T ui32WriteOffset;
78 PVRSRV_COMMAND * psCmd;
79
80 if(el == PVR_PROC_SEQ_START_TOKEN)
81 {
82 seq_printf( sfile,
83 "Command Queues\n"
84 "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n");
85 return;
86 }
87
88 ui32ReadOffset = psQueue->ui32ReadOffset;
89 ui32WriteOffset = psQueue->ui32WriteOffset;
90
91 while (ui32ReadOffset != ui32WriteOffset)
92 {
93 psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset);
94
95 seq_printf(sfile, "%x %x %5u %6u %3u %5u %2u %2u %3u \n",
96 (IMG_UINTPTR_T)psQueue,
97 (IMG_UINTPTR_T)psCmd,
98 psCmd->ui32ProcessID,
99 psCmd->CommandType,
100 psCmd->ui32CmdSize,
101 psCmd->ui32DevIndex,
102 psCmd->ui32DstSyncCount,
103 psCmd->ui32SrcSyncCount,
104 psCmd->ui32DataSize);
105
106 ui32ReadOffset += psCmd->ui32CmdSize;
107 ui32ReadOffset &= psQueue->ui32QueueSize - 1;
108 cmds++;
109 }
110
111 if (cmds == 0)
112 {
113 seq_printf(sfile, "%x <empty>\n", (IMG_UINTPTR_T)psQueue);
114 }
115}
116
117void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
118{
119 PVRSRV_QUEUE_INFO * psQueue;
120 SYS_DATA * psSysData;
121
122 PVR_UNREFERENCED_PARAMETER(sfile);
123
124 if(!off)
125 {
126 return PVR_PROC_SEQ_START_TOKEN;
127 }
128
129
130 SysAcquireData(&psSysData);
131
132 for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM);
133 return psQueue;
134}
135
136off_t
137QueuePrintQueues (IMG_CHAR * buffer, size_t size, off_t off)
138{
139 SYS_DATA * psSysData;
140 PVRSRV_QUEUE_INFO * psQueue;
141
142 SysAcquireData(&psSysData);
143
144 if (!off)
145 return printAppend (buffer, size, 0,
146 "Command Queues\n"
147 "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n");
148
149
150 for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM)
151 ;
152
153 return psQueue ? QueuePrintCommands (psQueue, buffer, size) : END_OF_FILE;
154}
155#endif
156
157#define GET_SPACE_IN_CMDQ(psQueue) \
158 ((((psQueue)->ui32ReadOffset - (psQueue)->ui32WriteOffset) \
159 + ((psQueue)->ui32QueueSize - 1)) & ((psQueue)->ui32QueueSize - 1))
160
161#define UPDATE_QUEUE_WOFF(psQueue, ui32Size) \
162 (psQueue)->ui32WriteOffset = ((psQueue)->ui32WriteOffset + (ui32Size)) \
163 & ((psQueue)->ui32QueueSize - 1);
164
165#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending) \
166 ((ui32OpsComplete) >= (ui32OpsPending))
167
168
169static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
170 IMG_UINT32 i,
171 IMG_BOOL bIsSrc)
172{
173 PVRSRV_SYNC_OBJECT *psSyncObject;
174
175 psSyncObject = bIsSrc ? psCmdCompleteData->psSrcSync : psCmdCompleteData->psDstSync;
176
177 if (psCmdCompleteData->bInUse)
178 {
179 PVR_LOG(("\t%s %u: ROC DevVAddr:0x%X ROP:0x%x ROC:0x%x, WOC DevVAddr:0x%X WOP:0x%x WOC:0x%x",
180 bIsSrc ? "SRC" : "DEST", i,
181 psSyncObject[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
182 psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsPending,
183 psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete,
184 psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
185 psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending,
186 psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete))
187 }
188 else
189 {
190 PVR_LOG(("\t%s %u: (Not in use)", bIsSrc ? "SRC" : "DEST", i))
191 }
192}
193
194
195static IMG_VOID QueueDumpDebugInfo_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
196{
197 if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
198 {
199 IMG_UINT32 i;
200 SYS_DATA *psSysData;
201 COMMAND_COMPLETE_DATA **ppsCmdCompleteData;
202 COMMAND_COMPLETE_DATA *psCmdCompleteData;
203
204 SysAcquireData(&psSysData);
205
206 ppsCmdCompleteData = psSysData->ppsCmdCompleteData[psDeviceNode->sDevId.ui32DeviceIndex];
207
208 if (ppsCmdCompleteData != IMG_NULL)
209 {
210 psCmdCompleteData = ppsCmdCompleteData[DC_FLIP_COMMAND];
211
212 PVR_LOG(("Command Complete Data for display device %u:", psDeviceNode->sDevId.ui32DeviceIndex))
213
214 for (i = 0; i < psCmdCompleteData->ui32SrcSyncCount; i++)
215 {
216 QueueDumpCmdComplete(psCmdCompleteData, i, IMG_TRUE);
217 }
218
219 for (i = 0; i < psCmdCompleteData->ui32DstSyncCount; i++)
220 {
221 QueueDumpCmdComplete(psCmdCompleteData, i, IMG_FALSE);
222 }
223 }
224 else
225 {
226 PVR_LOG(("There is no Command Complete Data for display device %u", psDeviceNode->sDevId.ui32DeviceIndex))
227 }
228 }
229}
230
231
232IMG_VOID QueueDumpDebugInfo(IMG_VOID)
233{
234 SYS_DATA *psSysData;
235 SysAcquireData(&psSysData);
236 List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, &QueueDumpDebugInfo_ForEachCb);
237}
238
239
240static IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value)
241{
242 IMG_SIZE_T ui32Temp, ui32Result = 1;
243
244 if(!ui32Value)
245 return 0;
246
247 ui32Temp = ui32Value - 1;
248 while(ui32Temp)
249 {
250 ui32Result <<= 1;
251 ui32Temp >>= 1;
252 }
253
254 return ui32Result;
255}
256
257
258IMG_EXPORT
259PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
260 PVRSRV_QUEUE_INFO **ppsQueueInfo)
261{
262 PVRSRV_QUEUE_INFO *psQueueInfo;
263 IMG_SIZE_T ui32Power2QueueSize = NearestPower2(ui32QueueSize);
264 SYS_DATA *psSysData;
265 PVRSRV_ERROR eError;
266 IMG_HANDLE hMemBlock;
267
268 SysAcquireData(&psSysData);
269
270
271 eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
272 sizeof(PVRSRV_QUEUE_INFO),
273 (IMG_VOID **)&psQueueInfo, &hMemBlock,
274 "Queue Info");
275 if (eError != PVRSRV_OK)
276 {
277 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue struct"));
278 goto ErrorExit;
279 }
280 OSMemSet(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO));
281
282 psQueueInfo->hMemBlock[0] = hMemBlock;
283 psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
284
285
286 eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
287 ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
288 &psQueueInfo->pvLinQueueKM, &hMemBlock,
289 "Command Queue");
290 if (eError != PVRSRV_OK)
291 {
292 PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue buffer"));
293 goto ErrorExit;
294 }
295
296 psQueueInfo->hMemBlock[1] = hMemBlock;
297 psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
298
299
300 PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
301 PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
302
303 psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
304
305
306 if (psSysData->psQueueList == IMG_NULL)
307 {
308 eError = OSCreateResource(&psSysData->sQProcessResource);
309 if (eError != PVRSRV_OK)
310 {
311 goto ErrorExit;
312 }
313 }
314
315
316 eError = OSLockResource(&psSysData->sQProcessResource,
317 KERNEL_ID);
318 if (eError != PVRSRV_OK)
319 {
320 goto ErrorExit;
321 }
322
323 psQueueInfo->psNextKM = psSysData->psQueueList;
324 psSysData->psQueueList = psQueueInfo;
325
326 eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
327 if (eError != PVRSRV_OK)
328 {
329 goto ErrorExit;
330 }
331
332 *ppsQueueInfo = psQueueInfo;
333
334 return PVRSRV_OK;
335
336ErrorExit:
337
338 if(psQueueInfo)
339 {
340 if(psQueueInfo->pvLinQueueKM)
341 {
342 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
343 psQueueInfo->ui32QueueSize,
344 psQueueInfo->pvLinQueueKM,
345 psQueueInfo->hMemBlock[1]);
346 psQueueInfo->pvLinQueueKM = IMG_NULL;
347 }
348
349 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
350 sizeof(PVRSRV_QUEUE_INFO),
351 psQueueInfo,
352 psQueueInfo->hMemBlock[0]);
353
354 }
355
356 return eError;
357}
358
359
360IMG_EXPORT
361PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo)
362{
363 PVRSRV_QUEUE_INFO *psQueue;
364 SYS_DATA *psSysData;
365 PVRSRV_ERROR eError;
366 IMG_BOOL bTimeout = IMG_TRUE;
367
368 SysAcquireData(&psSysData);
369
370 psQueue = psSysData->psQueueList;
371
372
373 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
374 {
375 if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
376 {
377 bTimeout = IMG_FALSE;
378 break;
379 }
380 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
381 } END_LOOP_UNTIL_TIMEOUT();
382
383 if (bTimeout)
384 {
385
386 PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
387 eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
388 goto ErrorExit;
389 }
390
391
392 eError = OSLockResource(&psSysData->sQProcessResource,
393 KERNEL_ID);
394 if (eError != PVRSRV_OK)
395 {
396 goto ErrorExit;
397 }
398
399 if(psQueue == psQueueInfo)
400 {
401 psSysData->psQueueList = psQueueInfo->psNextKM;
402
403 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
404 NearestPower2(psQueueInfo->ui32QueueSize) + PVRSRV_MAX_CMD_SIZE,
405 psQueueInfo->pvLinQueueKM,
406 psQueueInfo->hMemBlock[1]);
407 psQueueInfo->pvLinQueueKM = IMG_NULL;
408 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
409 sizeof(PVRSRV_QUEUE_INFO),
410 psQueueInfo,
411 psQueueInfo->hMemBlock[0]);
412
413 psQueueInfo = IMG_NULL;
414 }
415 else
416 {
417 while(psQueue)
418 {
419 if(psQueue->psNextKM == psQueueInfo)
420 {
421 psQueue->psNextKM = psQueueInfo->psNextKM;
422
423 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
424 psQueueInfo->ui32QueueSize,
425 psQueueInfo->pvLinQueueKM,
426 psQueueInfo->hMemBlock[1]);
427 psQueueInfo->pvLinQueueKM = IMG_NULL;
428 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
429 sizeof(PVRSRV_QUEUE_INFO),
430 psQueueInfo,
431 psQueueInfo->hMemBlock[0]);
432
433 psQueueInfo = IMG_NULL;
434 break;
435 }
436 psQueue = psQueue->psNextKM;
437 }
438
439 if(!psQueue)
440 {
441 eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
442 if (eError != PVRSRV_OK)
443 {
444 goto ErrorExit;
445 }
446 eError = PVRSRV_ERROR_INVALID_PARAMS;
447 goto ErrorExit;
448 }
449 }
450
451
452 eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
453 if (eError != PVRSRV_OK)
454 {
455 goto ErrorExit;
456 }
457
458
459 if (psSysData->psQueueList == IMG_NULL)
460 {
461 eError = OSDestroyResource(&psSysData->sQProcessResource);
462 if (eError != PVRSRV_OK)
463 {
464 goto ErrorExit;
465 }
466 }
467
468ErrorExit:
469
470 return eError;
471}
472
473
474IMG_EXPORT
475PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
476 IMG_SIZE_T ui32ParamSize,
477 IMG_VOID **ppvSpace)
478{
479 IMG_BOOL bTimeout = IMG_TRUE;
480
481
482 ui32ParamSize = (ui32ParamSize+3) & 0xFFFFFFFC;
483
484 if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE)
485 {
486 PVR_DPF((PVR_DBG_WARNING,"PVRSRVGetQueueSpace: max command size is %d bytes", PVRSRV_MAX_CMD_SIZE));
487 return PVRSRV_ERROR_CMD_TOO_BIG;
488 }
489
490
491 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
492 {
493 if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize)
494 {
495 bTimeout = IMG_FALSE;
496 break;
497 }
498 OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
499 } END_LOOP_UNTIL_TIMEOUT();
500
501 if (bTimeout == IMG_TRUE)
502 {
503 *ppvSpace = IMG_NULL;
504
505 return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
506 }
507 else
508 {
509 *ppvSpace = (IMG_VOID *)((IMG_UINTPTR_T)psQueue->pvLinQueueUM + psQueue->ui32WriteOffset);
510 }
511
512 return PVRSRV_OK;
513}
514
515
516IMG_EXPORT
517PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
518 PVRSRV_COMMAND **ppsCommand,
519 IMG_UINT32 ui32DevIndex,
520 IMG_UINT16 CommandType,
521 IMG_UINT32 ui32DstSyncCount,
522 PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
523 IMG_UINT32 ui32SrcSyncCount,
524 PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
525 IMG_SIZE_T ui32DataByteSize )
526{
527 PVRSRV_ERROR eError;
528 PVRSRV_COMMAND *psCommand;
529 IMG_SIZE_T ui32CommandSize;
530 IMG_UINT32 i;
531
532
533 ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL;
534
535
536 ui32CommandSize = sizeof(PVRSRV_COMMAND)
537 + ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
538 + ui32DataByteSize;
539
540
541 eError = PVRSRVGetQueueSpaceKM (psQueue, ui32CommandSize, (IMG_VOID**)&psCommand);
542 if(eError != PVRSRV_OK)
543 {
544 return eError;
545 }
546
547 psCommand->ui32ProcessID = OSGetCurrentProcessIDKM();
548
549
550 psCommand->ui32CmdSize = ui32CommandSize;
551 psCommand->ui32DevIndex = ui32DevIndex;
552 psCommand->CommandType = CommandType;
553 psCommand->ui32DstSyncCount = ui32DstSyncCount;
554 psCommand->ui32SrcSyncCount = ui32SrcSyncCount;
555
556
557 psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND));
558
559
560 psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psDstSync)
561 + (ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
562
563 psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync)
564 + (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
565 psCommand->ui32DataSize = ui32DataByteSize;
566
567
568 for (i=0; i<ui32DstSyncCount; i++)
569 {
570 psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
571 psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
572 psCommand->psDstSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
573
574 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
575 i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
576 psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
577 psCommand->psDstSync[i].ui32ReadOpsPending,
578 psCommand->psDstSync[i].ui32WriteOpsPending));
579 }
580
581
582 for (i=0; i<ui32SrcSyncCount; i++)
583 {
584 psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
585 psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
586 psCommand->psSrcSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
587
588 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
589 i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
590 psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
591 psCommand->psSrcSync[i].ui32ReadOpsPending,
592 psCommand->psSrcSync[i].ui32WriteOpsPending));
593 }
594
595
596 *ppsCommand = psCommand;
597
598 return PVRSRV_OK;
599}
600
601
602IMG_EXPORT
603PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
604 PVRSRV_COMMAND *psCommand)
605{
606
607
608
609 if (psCommand->ui32DstSyncCount > 0)
610 {
611 psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
612 + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND));
613 }
614
615 if (psCommand->ui32SrcSyncCount > 0)
616 {
617 psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
618 + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
619 + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
620 }
621
622 psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
623 + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
624 + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))
625 + (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
626
627
628 UPDATE_QUEUE_WOFF(psQueue, psCommand->ui32CmdSize);
629
630 return PVRSRV_OK;
631}
632
633
634
635static
636PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
637 PVRSRV_COMMAND *psCommand,
638 IMG_BOOL bFlush)
639{
640 PVRSRV_SYNC_OBJECT *psWalkerObj;
641 PVRSRV_SYNC_OBJECT *psEndObj;
642 IMG_UINT32 i;
643 COMMAND_COMPLETE_DATA *psCmdCompleteData;
644 PVRSRV_ERROR eError = PVRSRV_OK;
645 IMG_UINT32 ui32WriteOpsComplete;
646 IMG_UINT32 ui32ReadOpsComplete;
647
648
649 psWalkerObj = psCommand->psDstSync;
650 psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
651 while (psWalkerObj < psEndObj)
652 {
653 PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
654
655 ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
656 ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
657
658 if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
659 || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
660 {
661 if (!bFlush ||
662 !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
663 !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
664 {
665 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
666 }
667 }
668
669 psWalkerObj++;
670 }
671
672
673 psWalkerObj = psCommand->psSrcSync;
674 psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
675 while (psWalkerObj < psEndObj)
676 {
677 PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
678
679 ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
680 ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
681
682 if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
683 || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
684 {
685 if (!bFlush &&
686 SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) &&
687 SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
688 {
689 PVR_DPF((PVR_DBG_WARNING,
690 "PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
691 (IMG_UINTPTR_T)psSyncData, ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending));
692 }
693
694 if (!bFlush ||
695 !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
696 !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
697 {
698 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
699 }
700 }
701 psWalkerObj++;
702 }
703
704
705 if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT)
706 {
707 PVR_DPF((PVR_DBG_ERROR,
708 "PVRSRVProcessCommand: invalid DeviceType 0x%x",
709 psCommand->ui32DevIndex));
710 return PVRSRV_ERROR_INVALID_PARAMS;
711 }
712
713
714 psCmdCompleteData = psSysData->ppsCmdCompleteData[psCommand->ui32DevIndex][psCommand->CommandType];
715 if (psCmdCompleteData->bInUse)
716 {
717
718 return PVRSRV_ERROR_FAILED_DEPENDENCIES;
719 }
720
721
722 psCmdCompleteData->bInUse = IMG_TRUE;
723
724
725 psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
726 for (i=0; i<psCommand->ui32DstSyncCount; i++)
727 {
728 psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
729
730 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
731 i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
732 psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
733 psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
734 psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
735 }
736
737
738
739 psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
740 for (i=0; i<psCommand->ui32SrcSyncCount; i++)
741 {
742 psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
743
744 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
745 i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
746 psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
747 psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
748 psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
749 }
750
751
752
753
754
755
756
757
758
759
760
761 if (psSysData->ppfnCmdProcList[psCommand->ui32DevIndex][psCommand->CommandType]((IMG_HANDLE)psCmdCompleteData,
762 psCommand->ui32DataSize,
763 psCommand->pvData) == IMG_FALSE)
764 {
765
766
767
768 psCmdCompleteData->bInUse = IMG_FALSE;
769 eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
770 }
771
772 return eError;
773}
774
775
776static IMG_VOID PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
777{
778 if (psDeviceNode->bReProcessDeviceCommandComplete &&
779 psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
780 {
781 (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
782 }
783}
784
785IMG_EXPORT
786PVRSRV_ERROR PVRSRVProcessQueues(IMG_UINT32 ui32CallerID,
787 IMG_BOOL bFlush)
788{
789 PVRSRV_QUEUE_INFO *psQueue;
790 SYS_DATA *psSysData;
791 PVRSRV_COMMAND *psCommand;
792 PVRSRV_ERROR eError;
793
794 SysAcquireData(&psSysData);
795
796
797 psSysData->bReProcessQueues = IMG_FALSE;
798
799
800 eError = OSLockResource(&psSysData->sQProcessResource,
801 ui32CallerID);
802 if(eError != PVRSRV_OK)
803 {
804
805 psSysData->bReProcessQueues = IMG_TRUE;
806
807
808 if(ui32CallerID == ISR_ID)
809 {
810 if (bFlush)
811 {
812 PVR_DPF((PVR_DBG_ERROR,"PVRSRVProcessQueues: Couldn't acquire queue processing lock for FLUSH"));
813 }
814 else
815 {
816 PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Couldn't acquire queue processing lock"));
817 }
818 }
819 else
820 {
821 PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Queue processing lock-acquire failed when called from the Services driver."));
822 PVR_DPF((PVR_DBG_MESSAGE," This is due to MISR queue processing being interrupted by the Services driver."));
823 }
824
825 return PVRSRV_OK;
826 }
827
828 psQueue = psSysData->psQueueList;
829
830 if(!psQueue)
831 {
832 PVR_DPF((PVR_DBG_MESSAGE,"No Queues installed - cannot process commands"));
833 }
834
835 if (bFlush)
836 {
837 PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
838 }
839
840 while (psQueue)
841 {
842 while (psQueue->ui32ReadOffset != psQueue->ui32WriteOffset)
843 {
844 psCommand = (PVRSRV_COMMAND*)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + psQueue->ui32ReadOffset);
845
846 if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK)
847 {
848
849 UPDATE_QUEUE_ROFF(psQueue, psCommand->ui32CmdSize)
850
851 if (bFlush)
852 {
853 continue;
854 }
855 }
856
857 break;
858 }
859 psQueue = psQueue->psNextKM;
860 }
861
862 if (bFlush)
863 {
864 PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
865 }
866
867
868 List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
869 &PVRSRVProcessQueues_ForEachCb);
870
871
872
873 OSUnlockResource(&psSysData->sQProcessResource, ui32CallerID);
874
875
876 if(psSysData->bReProcessQueues)
877 {
878 return PVRSRV_ERROR_PROCESSING_BLOCKED;
879 }
880
881 return PVRSRV_OK;
882}
883
884#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
885IMG_INTERNAL
886IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
887 IMG_BOOL bScheduleMISR)
888{
889 COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
890 SYS_DATA *psSysData;
891
892 SysAcquireData(&psSysData);
893
894
895 psCmdCompleteData->bInUse = IMG_FALSE;
896
897
898 PVRSRVScheduleDeviceCallbacks();
899
900#if defined(SYS_USING_INTERRUPTS)
901 if(bScheduleMISR)
902 {
903 OSScheduleMISR(psSysData);
904 }
905#else
906 PVR_UNREFERENCED_PARAMETER(bScheduleMISR);
907#endif
908}
909
910#endif
911
912
913IMG_EXPORT
914IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie,
915 IMG_BOOL bScheduleMISR)
916{
917 IMG_UINT32 i;
918 COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
919 SYS_DATA *psSysData;
920
921 SysAcquireData(&psSysData);
922
923
924 for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++)
925 {
926 psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++;
927
928 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
929 i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
930 psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
931 psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
932 psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
933 }
934
935
936 for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++)
937 {
938 psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete++;
939
940 PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
941 i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
942 psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
943 psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
944 psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
945 }
946
947
948 psCmdCompleteData->bInUse = IMG_FALSE;
949
950
951 PVRSRVScheduleDeviceCallbacks();
952
953#if defined(SYS_USING_INTERRUPTS)
954 if(bScheduleMISR)
955 {
956 OSScheduleMISR(psSysData);
957 }
958#else
959 PVR_UNREFERENCED_PARAMETER(bScheduleMISR);
960#endif
961}
962
963
964
965
966IMG_EXPORT
967PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
968 PFN_CMD_PROC *ppfnCmdProcList,
969 IMG_UINT32 ui32MaxSyncsPerCmd[][2],
970 IMG_UINT32 ui32CmdCount)
971{
972 SYS_DATA *psSysData;
973 PVRSRV_ERROR eError;
974 IMG_UINT32 i;
975 IMG_SIZE_T ui32AllocSize;
976 PFN_CMD_PROC *ppfnCmdProc;
977 COMMAND_COMPLETE_DATA *psCmdCompleteData;
978
979
980 if(ui32DevIndex >= SYS_DEVICE_COUNT)
981 {
982 PVR_DPF((PVR_DBG_ERROR,
983 "PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x",
984 ui32DevIndex));
985 return PVRSRV_ERROR_INVALID_PARAMS;
986 }
987
988
989 SysAcquireData(&psSysData);
990
991
992 eError = OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
993 ui32CmdCount * sizeof(PFN_CMD_PROC),
994 (IMG_VOID **)&psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL,
995 "Internal Queue Info structure");
996 if (eError != PVRSRV_OK)
997 {
998 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc queue"));
999 return eError;
1000 }
1001
1002
1003 ppfnCmdProc = psSysData->ppfnCmdProcList[ui32DevIndex];
1004
1005
1006 for (i=0; i<ui32CmdCount; i++)
1007 {
1008 ppfnCmdProc[i] = ppfnCmdProcList[i];
1009 }
1010
1011
1012 ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*);
1013 eError = OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
1014 ui32AllocSize,
1015 (IMG_VOID **)&psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL,
1016 "Array of Pointers for Command Store");
1017 if (eError != PVRSRV_OK)
1018 {
1019 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
1020 goto ErrorExit;
1021 }
1022
1023 for (i=0; i<ui32CmdCount; i++)
1024 {
1025
1026
1027 ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
1028 + ((ui32MaxSyncsPerCmd[i][0]
1029 + ui32MaxSyncsPerCmd[i][1])
1030 * sizeof(PVRSRV_SYNC_OBJECT));
1031
1032 eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
1033 ui32AllocSize,
1034 (IMG_VOID **)&psSysData->ppsCmdCompleteData[ui32DevIndex][i],
1035 IMG_NULL,
1036 "Command Complete Data");
1037 if (eError != PVRSRV_OK)
1038 {
1039 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d",i));
1040 goto ErrorExit;
1041 }
1042
1043
1044 OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex][i], 0x00, ui32AllocSize);
1045
1046 psCmdCompleteData = psSysData->ppsCmdCompleteData[ui32DevIndex][i];
1047
1048
1049 psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*)
1050 (((IMG_UINTPTR_T)psCmdCompleteData)
1051 + sizeof(COMMAND_COMPLETE_DATA));
1052 psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT*)
1053 (((IMG_UINTPTR_T)psCmdCompleteData->psDstSync)
1054 + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[i][0]));
1055
1056 psCmdCompleteData->ui32AllocSize = ui32AllocSize;
1057 }
1058
1059 return PVRSRV_OK;
1060
1061ErrorExit:
1062
1063
1064
1065 if(psSysData->ppsCmdCompleteData[ui32DevIndex] != IMG_NULL)
1066 {
1067 for (i=0; i<ui32CmdCount; i++)
1068 {
1069 if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL)
1070 {
1071 ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
1072 + ((ui32MaxSyncsPerCmd[i][0]
1073 + ui32MaxSyncsPerCmd[i][1])
1074 * sizeof(PVRSRV_SYNC_OBJECT));
1075 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppsCmdCompleteData[ui32DevIndex][i], IMG_NULL);
1076 psSysData->ppsCmdCompleteData[ui32DevIndex][i] = IMG_NULL;
1077 }
1078 }
1079 ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*);
1080 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL);
1081 psSysData->ppsCmdCompleteData[ui32DevIndex] = IMG_NULL;
1082 }
1083
1084 if(psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL)
1085 {
1086 ui32AllocSize = ui32CmdCount * sizeof(PFN_CMD_PROC);
1087 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL);
1088 psSysData->ppfnCmdProcList[ui32DevIndex] = IMG_NULL;
1089 }
1090
1091 return eError;
1092}
1093
1094
1095IMG_EXPORT
1096PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
1097 IMG_UINT32 ui32CmdCount)
1098{
1099 SYS_DATA *psSysData;
1100 IMG_UINT32 i;
1101
1102
1103 if(ui32DevIndex >= SYS_DEVICE_COUNT)
1104 {
1105 PVR_DPF((PVR_DBG_ERROR,
1106 "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
1107 ui32DevIndex));
1108 return PVRSRV_ERROR_INVALID_PARAMS;
1109 }
1110
1111
1112 SysAcquireData(&psSysData);
1113
1114 if(psSysData->ppsCmdCompleteData[ui32DevIndex] == IMG_NULL)
1115 {
1116 PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveCmdProcListKM: Invalid command array"));
1117 return PVRSRV_ERROR_INVALID_PARAMS;
1118 }
1119 else
1120 {
1121 for(i=0; i<ui32CmdCount; i++)
1122 {
1123
1124 if(psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL)
1125 {
1126 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
1127 psSysData->ppsCmdCompleteData[ui32DevIndex][i]->ui32AllocSize,
1128 psSysData->ppsCmdCompleteData[ui32DevIndex][i],
1129 IMG_NULL);
1130 psSysData->ppsCmdCompleteData[ui32DevIndex][i] = IMG_NULL;
1131 }
1132 }
1133
1134
1135 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
1136 ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*),
1137 psSysData->ppsCmdCompleteData[ui32DevIndex],
1138 IMG_NULL);
1139 psSysData->ppsCmdCompleteData[ui32DevIndex] = IMG_NULL;
1140 }
1141
1142
1143 if(psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL)
1144 {
1145 OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
1146 ui32CmdCount * sizeof(PFN_CMD_PROC),
1147 psSysData->ppfnCmdProcList[ui32DevIndex],
1148 IMG_NULL);
1149 psSysData->ppfnCmdProcList[ui32DevIndex] = IMG_NULL;
1150 }
1151
1152 return PVRSRV_OK;
1153}
1154