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