RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / services / shared / common / sync.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Services synchronisation interface
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Implements client side code for services synchronisation
6                 interface
7 @License        Dual MIT/GPLv2
8
9 The contents of this file are subject to the MIT license as set out below.
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
20
21 Alternatively, the contents of this file may be used under the terms of
22 the GNU General Public License Version 2 ("GPL") in which case the provisions
23 of GPL are applicable instead of those above.
24
25 If you wish to allow use of your version of this file only under the terms of
26 GPL, and not to allow others to use your version of this file under the terms
27 of the MIT license, indicate your decision by deleting the provisions above
28 and replace them with the notice and other provisions required by GPL as set
29 out in the file called "GPL-COPYING" included in this distribution. If you do
30 not delete the provisions above, a recipient may use your version of this file
31 under the terms of either the MIT license or GPL.
32
33 This License is also included in this distribution in the file called
34 "MIT-COPYING".
35
36 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
37 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
40 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
41 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
42 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 */ /**************************************************************************/
44
45 #include "img_types.h"
46 #include "client_sync_bridge.h"
47 #include "allocmem.h"
48 #include "osfunc.h"
49 #include "devicemem.h"
50 #include "devicemem_pdump.h"
51 #include "pvr_debug.h"
52 #include "dllist.h"
53 #include "sync.h"
54 #include "sync_internal.h"
55 #include "lock.h"
56 #include "pvr_debug.h"
57 /* FIXME */
58 #if defined(__KERNEL__)
59 #include "pvrsrv.h"
60 #endif
61
62
63 #define SYNC_BLOCK_LIST_CHUNCK_SIZE     10
64 #define LOCAL_SYNC_PRIM_RESET_VALUE 0
65
66 /*
67         This defines the maximum amount of synchronisation memory
68         that can be allocated per SyncPrim context.
69         In reality this number is meaningless as we would run out
70         of synchronisation memory before we reach this limit, but
71         we need to provide a size to the span RA.
72 */
73 #define MAX_SYNC_MEM                            (4 * 1024 * 1024)
74
75 typedef struct _SYNC_BLOCK_LIST_
76 {
77         IMG_UINT32                      ui32BlockCount;                 /*!< Number of contexts in the list */
78         IMG_UINT32                      ui32BlockListSize;              /*!< Size of the array contexts */
79         SYNC_PRIM_BLOCK         **papsSyncPrimBlock;    /*!< Array of syncprim blocks */
80 } SYNC_BLOCK_LIST;
81
82 typedef struct _SYNC_OP_COOKIE_
83 {
84         IMG_UINT32                              ui32SyncCount;
85         IMG_UINT32                              ui32ClientSyncCount;
86         IMG_UINT32                              ui32ServerSyncCount;
87         IMG_BOOL                                bHaveServerSync;
88         IMG_HANDLE                              hBridge;
89         IMG_HANDLE                              hServerCookie;
90
91         SYNC_BLOCK_LIST                 *psSyncBlockList;
92         PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim;
93         /*
94                 Client sync(s) info.
95                 If this changes update the calculation of ui32ClientAllocSize
96         */
97         IMG_UINT32                              *paui32SyncBlockIndex;
98         IMG_UINT32                              *paui32Index;
99         IMG_UINT32                              *paui32Flags;
100         IMG_UINT32                              *paui32FenceValue;
101         IMG_UINT32                              *paui32UpdateValue;
102
103         /*
104                 Server sync(s) info
105                 If this changes update the calculation of ui32ServerAllocSize
106         */
107         IMG_HANDLE                              *pahServerSync;
108         IMG_UINT32              *paui32ServerFlags;
109 } SYNC_OP_COOKIE;
110
111 /* forward declaration */
112 static IMG_VOID
113 _SyncPrimSetValue(SYNC_PRIM *psSyncInt, IMG_UINT32 ui32Value);
114
115 /*
116         Internal interfaces for management of SYNC_PRIM_CONTEXT
117 */
118 static IMG_VOID
119 _SyncPrimContextUnref(SYNC_PRIM_CONTEXT *psContext)
120 {
121         if (!OSAtomicRead(&psContext->hRefCount))
122         {
123                 PVR_DPF((PVR_DBG_ERROR, "_SyncPrimContextUnref context already freed"));
124         }
125         else if (0 == OSAtomicDecrement(&psContext->hRefCount))
126         {
127                 /* SyncPrimContextDestroy only when no longer referenced */
128                 RA_Delete(psContext->psSpanRA);
129                 RA_Delete(psContext->psSubAllocRA);
130                 OSFreeMem(psContext);
131         }
132 }
133
134 static IMG_VOID
135 _SyncPrimContextRef(SYNC_PRIM_CONTEXT *psContext)
136 {
137         if (!OSAtomicRead(&psContext->hRefCount))
138         {
139                 PVR_DPF((PVR_DBG_ERROR, "_SyncPrimContextRef context use after free"));
140         }
141         else
142         {
143                 OSAtomicIncrement(&psContext->hRefCount);
144         }
145 }
146
147 /*
148         Internal interfaces for management of synchronisation block memory
149 */
150 static PVRSRV_ERROR
151 AllocSyncPrimitiveBlock(SYNC_PRIM_CONTEXT *psContext,
152                                                 SYNC_PRIM_BLOCK **ppsSyncBlock)
153 {
154         SYNC_PRIM_BLOCK *psSyncBlk;
155         DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie;
156         DEVMEM_EXPORTCOOKIE sExportCookie;
157         PVRSRV_ERROR eError;
158
159         psSyncBlk = OSAllocMem(sizeof(SYNC_PRIM_BLOCK));
160         if (psSyncBlk == IMG_NULL)
161         {
162                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
163                 goto fail_alloc;
164         }
165         psSyncBlk->psContext = psContext;
166
167         /* Allocate sync prim block */
168         eError = BridgeAllocSyncPrimitiveBlock(psContext->hBridge,
169                                                                                    psContext->hDeviceNode,
170                                                                                    &psSyncBlk->hServerSyncPrimBlock,
171                                                                                    &psSyncBlk->ui32FirmwareAddr,
172                                                                                    &psSyncBlk->ui32SyncBlockSize,
173                                                                                    &hServerExportCookie);
174         if (eError != PVRSRV_OK)
175         {
176                 goto fail_blockalloc;
177         }
178
179         /* Make it mappable by the client */
180         eError = DevmemMakeServerExportClientExport(psContext->hBridge,
181                                                                                                 hServerExportCookie,
182                                                                                                 &sExportCookie);
183         if (eError != PVRSRV_OK)
184         {
185                 goto fail_export;
186         }
187
188         /* Get CPU mapping of the memory block */
189         eError = DevmemImport(psContext->hBridge,
190                                                   &sExportCookie,
191                                                   PVRSRV_MEMALLOCFLAG_CPU_READABLE,
192                                                   &psSyncBlk->hMemDesc);
193
194         /*
195                 Regardless of success or failure we "undo" the export
196         */
197         DevmemUnmakeServerExportClientExport(psContext->hBridge,
198                                                                                  &sExportCookie);
199
200         if (eError != PVRSRV_OK)
201         {
202                 goto fail_import;
203         }
204
205         eError = DevmemAcquireCpuVirtAddr(psSyncBlk->hMemDesc,
206                                                                           (IMG_PVOID *) &psSyncBlk->pui32LinAddr);
207         if (eError != PVRSRV_OK)
208         {
209                 goto fail_cpuvaddr;
210         }
211
212         *ppsSyncBlock = psSyncBlk;
213         return PVRSRV_OK;
214
215 fail_cpuvaddr:
216         DevmemFree(psSyncBlk->hMemDesc);
217 fail_import:
218 fail_export:
219         BridgeFreeSyncPrimitiveBlock(psContext->hBridge,
220                                                                  psSyncBlk->hServerSyncPrimBlock);
221 fail_blockalloc:
222         OSFreeMem(psSyncBlk);
223 fail_alloc:
224         return eError;
225 }
226
227 static IMG_VOID
228 FreeSyncPrimitiveBlock(SYNC_PRIM_BLOCK *psSyncBlk)
229 {
230         SYNC_PRIM_CONTEXT *psContext = psSyncBlk->psContext;
231
232         DevmemReleaseCpuVirtAddr(psSyncBlk->hMemDesc);
233         DevmemFree(psSyncBlk->hMemDesc);
234         BridgeFreeSyncPrimitiveBlock(psContext->hBridge,
235                                                                  psSyncBlk->hServerSyncPrimBlock);
236         OSFreeMem(psSyncBlk);
237 }
238
239 static IMG_BOOL
240 SyncPrimBlockImport(RA_PERARENA_HANDLE hArena,
241                                         RA_LENGTH_T uSize,
242                                         RA_FLAGS_T uFlags,
243                                         RA_BASE_T *puiBase,
244                                         RA_LENGTH_T *puiActualSize,
245                                         RA_PERISPAN_HANDLE *phImport)
246 {
247         SYNC_PRIM_CONTEXT *psContext = hArena;
248         SYNC_PRIM_BLOCK *psSyncBlock = IMG_NULL;
249         RA_LENGTH_T uiSpanSize;
250         PVRSRV_ERROR eError;
251         IMG_BOOL bRet;
252         PVR_UNREFERENCED_PARAMETER(uFlags);
253
254         /* Check we've not be called with an unexpected size */
255         if (!hArena || sizeof(IMG_UINT32) != uSize)
256         {
257                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input params", __FUNCTION__));
258                 goto e0;
259         }
260
261         /*
262                 Ensure the synprim context doesn't go away while we have sync blocks
263                 attached to it
264         */
265         _SyncPrimContextRef(psContext);
266
267         /* Allocate the block of memory */
268         eError = AllocSyncPrimitiveBlock(psContext, &psSyncBlock);
269         if (eError != PVRSRV_OK)
270         {
271                 PVR_DPF((PVR_DBG_ERROR, "Failed to allocation syncprim block (%d)", eError));
272                 goto fail_syncblockalloc;
273         }
274
275         /* Allocate a span for it */
276         bRet = RA_Alloc(psContext->psSpanRA,
277                                         psSyncBlock->ui32SyncBlockSize,
278                                         0,
279                                         psSyncBlock->ui32SyncBlockSize,
280                                         &psSyncBlock->uiSpanBase,
281                                         &uiSpanSize,
282                                         IMG_NULL);
283
284         /*
285                 There is no reason the span RA should return an allocation larger
286                 then we request
287         */
288         if (bRet == IMG_FALSE || uiSpanSize != psSyncBlock->ui32SyncBlockSize)
289         {
290                 goto fail_spanalloc;
291         }
292
293         *puiBase = psSyncBlock->uiSpanBase;
294         *puiActualSize = psSyncBlock->ui32SyncBlockSize;
295         *phImport = psSyncBlock;
296         return IMG_TRUE;
297
298 fail_spanalloc:
299         FreeSyncPrimitiveBlock(psSyncBlock);
300 fail_syncblockalloc:
301         _SyncPrimContextUnref(psContext);
302 e0:
303         return IMG_FALSE;
304 }
305
306 static IMG_VOID
307 SyncPrimBlockUnimport(RA_PERARENA_HANDLE hArena,
308                                           RA_BASE_T uiBase,
309                                           RA_PERISPAN_HANDLE hImport)
310 {
311         SYNC_PRIM_CONTEXT *psContext = hArena;
312         SYNC_PRIM_BLOCK *psSyncBlock = hImport;
313
314         if (!psContext || !psSyncBlock || uiBase != psSyncBlock->uiSpanBase)
315         {
316                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input params", __FUNCTION__));
317                 return;
318         }
319
320         /* Free the span this import is using */
321         RA_Free(psContext->psSpanRA, uiBase);
322
323         /* Free the syncpim block */
324         FreeSyncPrimitiveBlock(psSyncBlock);
325
326         /*      Drop our reference to the syncprim context */
327         _SyncPrimContextUnref(psContext);
328 }
329
330 static INLINE IMG_UINT32 SyncPrimGetOffset(SYNC_PRIM *psSyncInt)
331 {
332         IMG_UINT64 ui64Temp;
333         
334         PVR_ASSERT(psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL);
335
336         /* FIXME: Subtracting a 64-bit address from another and then implicit
337          * cast to 32-bit number. Need to review all call sequences that use this
338          * function, added explicit casting for now.
339          */
340         ui64Temp =  psSyncInt->u.sLocal.uiSpanAddr - psSyncInt->u.sLocal.psSyncBlock->uiSpanBase;
341         PVR_ASSERT(ui64Temp<IMG_UINT32_MAX);
342         return (IMG_UINT32)ui64Temp;
343 }
344
345 static IMG_VOID SyncPrimGetCPULinAddr(SYNC_PRIM *psSyncInt)
346 {
347         SYNC_PRIM_BLOCK *psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
348
349         psSyncInt->sCommon.pui32LinAddr = psSyncBlock->pui32LinAddr +
350                                                                           (SyncPrimGetOffset(psSyncInt)/sizeof(IMG_UINT32));
351 }
352
353 static IMG_VOID SyncPrimLocalFree(SYNC_PRIM *psSyncInt)
354 {
355         SYNC_PRIM_BLOCK *psSyncBlock;
356         SYNC_PRIM_CONTEXT *psContext;
357
358 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
359         {
360                 PVRSRV_ERROR eError;
361                 /* remove this sync record */
362                 eError = BridgeSyncRecordRemoveByHandle(
363                                                 psSyncInt->u.sLocal.psSyncBlock->psContext->hBridge,
364                                                 psSyncInt->u.sLocal.hRecord);
365                 if (PVRSRV_OK != eError)
366                 {
367                         PVR_DPF((PVR_DBG_ERROR, "%s: failed to remove SyncRecord", __FUNCTION__));
368                 }
369         }
370 #endif
371         /* reset the sync prim value as it is freed.
372          * this guarantees the client sync allocated to the client will
373          * have a value of zero and the client does not need to
374          * explicitly initialise the sync value to zero.
375          * the allocation of the backing memory for the sync prim block
376          * is done with ZERO_ON_ALLOC so the memory is initially all zero.
377          */
378          _SyncPrimSetValue(psSyncInt, LOCAL_SYNC_PRIM_RESET_VALUE);
379
380         psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
381         psContext = psSyncBlock->psContext;
382
383         RA_Free(psContext->psSubAllocRA, psSyncInt->u.sLocal.uiSpanAddr);
384         OSFreeMem(psSyncInt);
385         _SyncPrimContextUnref(psContext);
386 }
387
388 static IMG_VOID SyncPrimServerFree(SYNC_PRIM *psSyncInt)
389 {
390         PVRSRV_ERROR eError;
391
392         eError = BridgeServerSyncFree(psSyncInt->u.sServer.hBridge,
393                                                                   psSyncInt->u.sServer.hServerSync);
394         if (eError != PVRSRV_OK)
395         {
396                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimServerFree failed"));
397         }
398         OSFreeMem(psSyncInt);
399 }
400
401 static IMG_VOID SyncPrimLocalUnref(SYNC_PRIM *psSyncInt)
402 {
403         if (!OSAtomicRead(&psSyncInt->u.sLocal.hRefCount))
404         {
405                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimLocalUnref sync already freed"));
406         }
407         else if (0 == OSAtomicDecrement(&psSyncInt->u.sLocal.hRefCount))
408         {
409                 SyncPrimLocalFree(psSyncInt);
410         }
411 }
412
413 static IMG_VOID SyncPrimLocalRef(SYNC_PRIM *psSyncInt)
414 {
415         if (!OSAtomicRead(&psSyncInt->u.sLocal.hRefCount))
416         {
417                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimLocalRef sync use after free"));
418         }
419         else
420         {
421                 OSAtomicIncrement(&psSyncInt->u.sLocal.hRefCount);
422         }
423 }
424
425 static IMG_UINT32 SyncPrimGetFirmwareAddrLocal(SYNC_PRIM *psSyncInt)
426 {
427         SYNC_PRIM_BLOCK *psSyncBlock;
428
429         psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
430         return psSyncBlock->ui32FirmwareAddr + SyncPrimGetOffset(psSyncInt);    
431 }
432
433 static IMG_UINT32 SyncPrimGetFirmwareAddrServer(SYNC_PRIM *psSyncInt)
434 {
435         return psSyncInt->u.sServer.ui32FirmwareAddr;
436 }
437
438 #if !defined(__KERNEL__)
439 static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandleLocal(SYNC_PRIM *psSyncInt)
440 {
441         return psSyncInt->u.sLocal.psSyncBlock->psContext->hBridge;
442 }
443
444 static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandleServer(SYNC_PRIM *psSyncInt)
445 {
446         return psSyncInt->u.sServer.hBridge;
447 }
448
449 static SYNC_BRIDGE_HANDLE _SyncPrimGetBridgeHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync)
450 {
451         SYNC_PRIM *psSyncInt;
452
453         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
454         if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
455         {
456                 return _SyncPrimGetBridgeHandleLocal(psSyncInt);
457         }
458         else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
459         {
460                 return _SyncPrimGetBridgeHandleServer(psSyncInt);
461         }
462         else
463         {
464                 PVR_DPF((PVR_DBG_ERROR, "_SyncPrimGetBridgeHandle: Invalid sync type"));
465                 /*
466                         Either the client has given us a bad pointer or there is an
467                         error in this module
468                 */
469                 return 0;
470         }
471 }
472 #endif
473
474 /*
475         Internal interfaces for management of syncprim block lists
476 */
477 static SYNC_BLOCK_LIST *_SyncPrimBlockListCreate(IMG_VOID)
478 {
479         SYNC_BLOCK_LIST *psBlockList;
480
481         psBlockList = OSAllocMem(sizeof(SYNC_BLOCK_LIST));
482         if (!psBlockList)
483         {
484                 return IMG_NULL;
485         }
486
487         psBlockList->ui32BlockCount = 0;
488         psBlockList->ui32BlockListSize = SYNC_BLOCK_LIST_CHUNCK_SIZE;
489
490         psBlockList->papsSyncPrimBlock = OSAllocMem(sizeof(SYNC_PRIM_BLOCK *)
491                                                                                                         * SYNC_BLOCK_LIST_CHUNCK_SIZE);
492         if (!psBlockList->papsSyncPrimBlock)
493         {
494                 OSFreeMem(psBlockList);
495                 return IMG_NULL;
496         }
497
498         OSCachedMemSet(psBlockList->papsSyncPrimBlock,
499                          0,
500                          sizeof(SYNC_PRIM_BLOCK *) * psBlockList->ui32BlockListSize);
501
502         return psBlockList;
503 }
504
505 static PVRSRV_ERROR _SyncPrimBlockListAdd(SYNC_BLOCK_LIST *psBlockList,
506                                                                                         SYNC_PRIM_BLOCK *psSyncPrimBlock)
507 {
508         IMG_UINT32 i;
509
510         /* Check the context isn't already on the list */
511         for (i=0;i<psBlockList->ui32BlockCount;i++)
512         {
513                 if (psBlockList->papsSyncPrimBlock[i] == psSyncPrimBlock)
514                 {
515                         return PVRSRV_OK;
516                 }
517         }
518
519         /* Check we have space for a new item */
520         if (psBlockList->ui32BlockCount == psBlockList->ui32BlockListSize)
521         {
522                 SYNC_PRIM_BLOCK **papsNewSyncPrimBlock;
523
524                 papsNewSyncPrimBlock = OSAllocMem(sizeof(SYNC_PRIM_BLOCK *) *
525                                                                                         (psBlockList->ui32BlockListSize +
526                                                                                         SYNC_BLOCK_LIST_CHUNCK_SIZE));
527                 if (!papsNewSyncPrimBlock)
528                 {
529                         return PVRSRV_ERROR_OUT_OF_MEMORY;
530                 }
531
532                 OSCachedMemCopy(papsNewSyncPrimBlock,
533                                   psBlockList->papsSyncPrimBlock,
534                                   sizeof(SYNC_PRIM_CONTEXT *) *
535                                   psBlockList->ui32BlockListSize);
536
537                 OSFreeMem(psBlockList->papsSyncPrimBlock);
538
539                 psBlockList->papsSyncPrimBlock = papsNewSyncPrimBlock;
540                 psBlockList->ui32BlockListSize += SYNC_BLOCK_LIST_CHUNCK_SIZE;
541         }
542
543         /* Add the context to the list */
544         psBlockList->papsSyncPrimBlock[psBlockList->ui32BlockCount++] = psSyncPrimBlock;
545         return PVRSRV_OK;
546 }
547
548 static PVRSRV_ERROR _SyncPrimBlockListBlockToIndex(SYNC_BLOCK_LIST *psBlockList,
549                                                                                                    SYNC_PRIM_BLOCK *psSyncPrimBlock,
550                                                                                                    IMG_UINT32 *pui32Index)
551 {
552         IMG_UINT32 i;
553
554         for (i=0;i<psBlockList->ui32BlockCount;i++)
555         {
556                 if (psBlockList->papsSyncPrimBlock[i] == psSyncPrimBlock)
557                 {
558                         *pui32Index = i;
559                         return PVRSRV_OK;
560                 }
561         }
562
563         return PVRSRV_ERROR_INVALID_PARAMS;
564 }
565
566 static PVRSRV_ERROR _SyncPrimBlockListHandleArrayCreate(SYNC_BLOCK_LIST *psBlockList,
567                                                                                                                 IMG_UINT32 *pui32BlockHandleCount,
568                                                                                                                 IMG_HANDLE **ppahHandleList)
569 {
570         IMG_HANDLE *pahHandleList;
571         IMG_UINT32 i;
572
573         pahHandleList = OSAllocMem(sizeof(IMG_HANDLE) *
574                                                            psBlockList->ui32BlockCount);
575         if (!pahHandleList)
576         {
577                 return PVRSRV_ERROR_OUT_OF_MEMORY;
578         }
579
580         for (i=0;i<psBlockList->ui32BlockCount;i++)
581         {
582                 pahHandleList[i] = psBlockList->papsSyncPrimBlock[i]->hServerSyncPrimBlock;
583         }
584
585         *ppahHandleList = pahHandleList;
586         *pui32BlockHandleCount = psBlockList->ui32BlockCount;
587
588         return PVRSRV_OK;
589 }
590
591 static IMG_VOID _SyncPrimBlockListHandleArrayDestroy(IMG_HANDLE *pahHandleList)
592 {
593         OSFreeMem(pahHandleList);
594 }
595
596 static IMG_UINT32 _SyncPrimBlockListGetClientValue(SYNC_BLOCK_LIST *psBlockList,
597                                                                                                    IMG_UINT32 ui32BlockIndex,
598                                                                                                    IMG_UINT32 ui32Index)
599 {
600         return psBlockList->papsSyncPrimBlock[ui32BlockIndex]->pui32LinAddr[ui32Index];
601 }
602
603 static IMG_VOID _SyncPrimBlockListDestroy(SYNC_BLOCK_LIST *psBlockList)
604 {
605         OSFreeMem(psBlockList->papsSyncPrimBlock);
606         OSFreeMem(psBlockList);
607 }
608
609
610 /* TODO: implement _Log2 using __builtin_clz gcc's builtin */
611 /* TODO: factorise the log2 functions (there is a similar one in services/shared/common/ra.c) */
612 static INLINE IMG_UINT32 _Log2(IMG_UINT32 ui32Align)
613 {
614         IMG_UINT32 ui32Log2Align = 0;
615         PVR_ASSERT(ui32Align != 0); /* Log2 isn't defined on 0 (triggers an assert instead of an infinite loop) */
616
617         while (!(ui32Align & 1))
618         {
619                 ui32Log2Align++;
620                 ui32Align = ui32Align >> 1;
621         }
622         PVR_ASSERT(ui32Align == 1);
623
624         return ui32Log2Align;
625 }
626
627 /*
628         External interfaces
629 */
630
631 IMG_INTERNAL PVRSRV_ERROR
632 SyncPrimContextCreate(SYNC_BRIDGE_HANDLE hBridge,
633                                           IMG_HANDLE hDeviceNode,
634                                           PSYNC_PRIM_CONTEXT *phSyncPrimContext)
635 {
636         SYNC_PRIM_CONTEXT *psContext;
637         PVRSRV_ERROR eError;
638
639         psContext = OSAllocMem(sizeof(SYNC_PRIM_CONTEXT));
640         if (psContext == IMG_NULL)
641         {
642                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
643                 goto fail_alloc;
644         }
645
646         psContext->hBridge = hBridge;
647         psContext->hDeviceNode = hDeviceNode;
648
649         OSSNPrintf(psContext->azName, SYNC_PRIM_NAME_SIZE, "Sync Prim RA-%p", psContext);
650         OSSNPrintf(psContext->azSpanName, SYNC_PRIM_NAME_SIZE, "Sync Prim span RA-%p", psContext);
651
652         /*
653                 Create the RA for sub-allocations of the SynPrim's
654
655                 Note:
656                 The import size doesn't matter here as the server will pass
657                 back the blocksize when does the import which overrides
658                 what we specify here.
659         */
660
661         psContext->psSubAllocRA = RA_Create(psContext->azName,
662                                                                                 /* Params for imports */
663                                                                                 _Log2(sizeof(IMG_UINT32)),
664                                                                                 RA_LOCKCLASS_2,
665                                                                                 SyncPrimBlockImport,
666                                                                                 SyncPrimBlockUnimport,
667                                                                                 psContext,
668                                                                                 IMG_FALSE);
669         if (psContext->psSubAllocRA == IMG_NULL)
670         {
671                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
672                 goto fail_suballoc;
673         }
674
675         /*
676                 Create the span-management RA
677
678                 The RA requires that we work with linear spans. For our use
679                 here we don't require this behaviour as we're always working
680                 within offsets of blocks (imports). However, we need to keep
681                 the RA happy so we create the "span" management RA which
682                 ensures that all are imports are added to the RA in a linear
683                 fashion
684         */
685         psContext->psSpanRA = RA_Create(psContext->azSpanName,
686                                                                         /* Params for imports */
687                                                                         0,
688                                                                         RA_LOCKCLASS_1,
689                                                                         IMG_NULL,
690                                                                         IMG_NULL,
691                                                                         IMG_NULL,
692                                                                         IMG_FALSE);
693         if (psContext->psSpanRA == IMG_NULL)
694         {
695                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
696                 goto fail_span;
697         }
698
699         if (!RA_Add(psContext->psSpanRA, 0, MAX_SYNC_MEM, 0, IMG_NULL))
700         {
701                 RA_Delete(psContext->psSpanRA);
702                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
703                 goto fail_span;
704         }
705
706         OSAtomicWrite(&psContext->hRefCount, 1);
707
708         *phSyncPrimContext = psContext;
709         return PVRSRV_OK;
710 fail_span:
711         RA_Delete(psContext->psSubAllocRA);
712 fail_suballoc:
713         OSFreeMem(psContext);
714 fail_alloc:
715         return eError;
716 }
717
718 IMG_INTERNAL IMG_VOID SyncPrimContextDestroy(PSYNC_PRIM_CONTEXT hSyncPrimContext)
719 {
720         SYNC_PRIM_CONTEXT *psContext = hSyncPrimContext;
721         if (1 != OSAtomicRead(&psContext->hRefCount))
722         {
723                 PVR_DPF((PVR_DBG_ERROR, "%s attempted with active references, may be the result of a race", __FUNCTION__));
724         }
725         _SyncPrimContextUnref(psContext);
726 }
727
728 static PVRSRV_ERROR _SyncPrimAlloc(PSYNC_PRIM_CONTEXT hSyncPrimContext,
729                                                                                 PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
730                                                                                 const IMG_CHAR *pszClassName,
731                                                                                 IMG_BOOL bServerSync)
732 {
733         SYNC_PRIM_CONTEXT *psContext = hSyncPrimContext;
734         SYNC_PRIM_BLOCK *psSyncBlock;
735         SYNC_PRIM *psNewSync;
736         PVRSRV_ERROR eError;
737         RA_BASE_T uiSpanAddr;
738
739         psNewSync = OSAllocMem(sizeof(SYNC_PRIM));
740         if (psNewSync == IMG_NULL)
741         {
742                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
743                 goto fail_alloc;
744         }
745
746         if (!RA_Alloc(psContext->psSubAllocRA,
747                                   sizeof(IMG_UINT32),
748                                   0,
749                                   sizeof(IMG_UINT32),
750                                   &uiSpanAddr,
751                                   IMG_NULL,
752                                   (RA_PERISPAN_HANDLE *) &psSyncBlock))
753         {
754                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
755                 goto fail_raalloc;
756         }
757         psNewSync->eType = SYNC_PRIM_TYPE_LOCAL;
758         OSAtomicWrite(&psNewSync->u.sLocal.hRefCount, 1);
759         psNewSync->u.sLocal.uiSpanAddr = uiSpanAddr;
760         psNewSync->u.sLocal.psSyncBlock = psSyncBlock;
761         SyncPrimGetCPULinAddr(psNewSync);
762         *ppsSync = &psNewSync->sCommon;
763         _SyncPrimContextRef(psContext);
764
765 #if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING)
766         {
767                 IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN];
768                 if(pszClassName)
769                 {
770                         /* Copy the class name annotation into a fixed-size array */
771                         OSStringNCopy(szClassName, pszClassName, SYNC_MAX_CLASS_NAME_LEN - 1);
772                         szClassName[SYNC_MAX_CLASS_NAME_LEN - 1] = 0;
773                 }
774                 else
775                 {
776                         /* No class name annotation */
777                         szClassName[0] = 0;
778                 }
779                 /* record this sync */
780                 eError = BridgeSyncRecordAdd(
781                                         psSyncBlock->psContext->hBridge,
782                                         &psNewSync->u.sLocal.hRecord,
783                                         psSyncBlock->hServerSyncPrimBlock,
784                                         psSyncBlock->ui32FirmwareAddr,
785                                         SyncPrimGetOffset(psNewSync),
786                                         bServerSync,
787                                         OSStringNLength(szClassName, SYNC_MAX_CLASS_NAME_LEN),
788                                         szClassName);
789                 if (PVRSRV_OK != eError)
790                 {
791                         PVR_DPF((PVR_DBG_ERROR, "%s: failed to add SyncRecord", __FUNCTION__));
792                 }
793         }
794 #else
795         PVR_UNREFERENCED_PARAMETER(pszClassName);
796         PVR_UNREFERENCED_PARAMETER(bServerSync);
797 #endif /* if defined(PVRSRV_ENABLE_FULL_SYNC_TRACKING) */
798
799         return PVRSRV_OK;
800
801 fail_raalloc:
802         OSFreeMem(psNewSync);
803 fail_alloc:
804         return eError;
805 }
806
807 #if defined(__KERNEL__)
808 IMG_INTERNAL PVRSRV_ERROR SyncPrimAllocForServerSync(PSYNC_PRIM_CONTEXT hSyncPrimContext,
809                                                                                 PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
810                                                                                 const IMG_CHAR *pszClassName)
811 {
812         return _SyncPrimAlloc(hSyncPrimContext,
813                                           ppsSync,
814                                           pszClassName,
815                                           IMG_TRUE);
816 }
817 #endif
818
819 IMG_INTERNAL PVRSRV_ERROR SyncPrimAlloc(PSYNC_PRIM_CONTEXT hSyncPrimContext,
820                                                                                 PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
821                                                                                 const IMG_CHAR *pszClassName)
822 {
823         return _SyncPrimAlloc(hSyncPrimContext,
824                                           ppsSync,
825                                           pszClassName,
826                                           IMG_FALSE);
827 }
828
829 static IMG_VOID
830 _SyncPrimSetValue(SYNC_PRIM *psSyncInt, IMG_UINT32 ui32Value)
831 {
832         PVRSRV_ERROR eError;
833
834         if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
835         {
836                 SYNC_PRIM_BLOCK *psSyncBlock;
837                 SYNC_PRIM_CONTEXT *psContext;
838
839                 psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
840                 psContext = psSyncBlock->psContext;
841
842                 eError = BridgeSyncPrimSet(psContext->hBridge,
843                                                                         psSyncBlock->hServerSyncPrimBlock,
844                                                                         SyncPrimGetOffset(psSyncInt)/sizeof(IMG_UINT32),
845                                                                         ui32Value);
846         }
847         else
848         {
849                 eError = BridgeServerSyncPrimSet(psSyncInt->u.sServer.hBridge,
850                                                                         psSyncInt->u.sServer.hServerSync,
851                                                                         ui32Value);
852         }
853         /* These functions don't actually fail */
854         if (PVRSRV_OK != eError)
855         {
856                 PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
857         }
858 }
859
860 IMG_INTERNAL IMG_VOID SyncPrimFree(PVRSRV_CLIENT_SYNC_PRIM *psSync)
861 {
862         SYNC_PRIM *psSyncInt;
863
864         if (!psSync)
865         {
866                 PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __FUNCTION__));
867                 return;
868         }
869
870         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
871         if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
872         {
873                 SyncPrimLocalUnref(psSyncInt);
874         }
875         else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
876         {
877                 SyncPrimServerFree(psSyncInt);
878         }
879         else
880         {
881                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimFree: Invalid sync type"));
882                 /*
883                         Either the client has given us a bad pointer or there is an
884                         error in this module
885                 */
886                 return;
887         }
888 }
889
890 #if defined(NO_HARDWARE)
891 IMG_INTERNAL IMG_VOID
892 SyncPrimNoHwUpdate(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
893 {
894         SYNC_PRIM *psSyncInt;
895
896         if (!psSync)
897         {
898                 PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __FUNCTION__));
899                 return;
900         }
901         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
902
903         /* There is no check for the psSyncInt to be LOCAL as this call
904            substitutes the Firmware updating a sync and that sync could
905            be a server one */
906
907         _SyncPrimSetValue(psSyncInt, ui32Value);
908 }
909 #endif
910
911 IMG_INTERNAL IMG_VOID
912 SyncPrimSet(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
913 {
914         SYNC_PRIM *psSyncInt;
915
916         if (!psSync)
917         {
918                 PVR_DPF((PVR_DBG_ERROR, "%s: null sync pointer", __FUNCTION__));
919                 return;
920         }
921
922         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
923         if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
924         {
925                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimSet: Invalid sync type"));
926                 return;
927         }
928
929         _SyncPrimSetValue(psSyncInt, ui32Value);
930
931 #if defined(PDUMP)
932         SyncPrimPDump(psSync);
933 #endif
934
935 }
936
937 IMG_INTERNAL PVRSRV_ERROR SyncPrimLocalGetHandleAndOffset(PVRSRV_CLIENT_SYNC_PRIM *psSync,
938                                                         IMG_HANDLE *phBlock,
939                                                         IMG_UINT32 *pui32Offset)
940 {
941         PVRSRV_ERROR eError = PVRSRV_OK;
942         SYNC_PRIM *psSyncInt;
943
944         if(!psSync || !phBlock || !pui32Offset)
945         {
946                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimGetHandleAndOffset: invalid input pointer"));
947                 eError = PVRSRV_ERROR_INVALID_PARAMS;
948                 goto err_out;
949         }
950
951         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
952
953         if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
954         {
955                 *phBlock = psSyncInt->u.sLocal.psSyncBlock->hServerSyncPrimBlock;
956                 *pui32Offset = psSyncInt->u.sLocal.uiSpanAddr - psSyncInt->u.sLocal.psSyncBlock->uiSpanBase;
957         }
958         else
959         {
960                 PVR_DPF((PVR_DBG_ERROR, "%s: psSync not a Local sync prim (%d)",
961                         __FUNCTION__, psSyncInt->eType));
962                 eError = PVRSRV_ERROR_INVALID_PARAMS;
963                 goto err_out;
964         }
965
966 err_out:
967         return eError;
968 }
969
970 IMG_INTERNAL IMG_UINT32 SyncPrimGetFirmwareAddr(PVRSRV_CLIENT_SYNC_PRIM *psSync)
971 {
972         SYNC_PRIM *psSyncInt;
973         if (!psSync)
974         {
975                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
976                 goto err_out;
977         }
978
979         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
980         if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
981         {
982                 return SyncPrimGetFirmwareAddrLocal(psSyncInt);
983         }
984         else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
985         {
986                 return SyncPrimGetFirmwareAddrServer(psSyncInt);
987         }
988         else
989         {
990                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimGetFirmwareAddr: Invalid sync type"));
991                 /*
992                         Either the client has given us a bad pointer or there is an
993                         error in this module
994                 */
995                 goto err_out;
996         }
997 err_out:
998         return 0;
999 }
1000
1001 #if !defined(__KERNEL__)
1002 IMG_INTERNAL PVRSRV_ERROR SyncPrimDumpSyncs(IMG_UINT32 ui32SyncCount, PVRSRV_CLIENT_SYNC_PRIM **papsSync, const IMG_CHAR *pcszExtraInfo)
1003 {
1004 #if defined(PVRSRV_NEED_PVR_DPF)
1005         SYNC_PRIM *psSyncInt;
1006         PVRSRV_CLIENT_SYNC_PRIM **papsServerSync;
1007         IMG_UINT32 ui32ServerSyncs = 0;
1008         IMG_UINT32 *pui32UID = IMG_NULL;
1009         IMG_UINT32 *pui32FWAddr = IMG_NULL;
1010         IMG_UINT32 *pui32CurrentOp = IMG_NULL;
1011         IMG_UINT32 *pui32NextOp = IMG_NULL;
1012         IMG_UINT32 i;
1013         PVRSRV_ERROR eError = PVRSRV_OK;
1014
1015         papsServerSync = OSAllocMem(ui32SyncCount * sizeof(PVRSRV_CLIENT_SYNC_PRIM *));
1016         if (!papsServerSync)
1017         {
1018                 return PVRSRV_ERROR_OUT_OF_MEMORY;
1019         }
1020
1021         for (i = 0; i < ui32SyncCount; i++)
1022         {
1023                 psSyncInt = IMG_CONTAINER_OF(papsSync[i], SYNC_PRIM, sCommon);
1024                 if (psSyncInt->eType == SYNC_PRIM_TYPE_LOCAL)
1025                 {
1026                         PVR_DPF((PVR_DBG_ERROR, "%s: sync=local  fw=0x%x curr=0x%04x",
1027                                          pcszExtraInfo,
1028                                          SyncPrimGetFirmwareAddrLocal(psSyncInt),
1029                                          *psSyncInt->sCommon.pui32LinAddr));
1030                 }
1031                 else if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
1032                 {
1033                         papsServerSync[ui32ServerSyncs++] = papsSync[i];
1034                 }
1035                 else
1036                 {
1037                         PVR_DPF((PVR_DBG_ERROR, "SyncPrimDumpSyncs: Invalid sync type"));
1038                         /*
1039                            Either the client has given us a bad pointer or there is an
1040                            error in this module
1041                            */
1042                         eError = PVRSRV_ERROR_INVALID_PARAMS;
1043                         goto err_free;
1044                 }
1045         }
1046
1047         if (ui32ServerSyncs > 0)
1048         {
1049                 pui32UID = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
1050                 if (!pui32UID)
1051                 {
1052                         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1053                         goto err_free;
1054                 }
1055                 pui32FWAddr = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
1056                 if (!pui32FWAddr)
1057                 {
1058                         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1059                         goto err_free;
1060                 }
1061                 pui32CurrentOp = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
1062                 if (!pui32CurrentOp)
1063                 {
1064                         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1065                         goto err_free;
1066                 }
1067                 pui32NextOp = OSAllocMem(ui32ServerSyncs * sizeof(IMG_UINT32));
1068                 if (!pui32NextOp)
1069                 {
1070                         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1071                         goto err_free;
1072                 }
1073                 eError = SyncPrimServerGetStatus(ui32ServerSyncs, papsServerSync,
1074                                                                                  pui32UID,
1075                                                                                  pui32FWAddr,
1076                                                                                  pui32CurrentOp,
1077                                                                                  pui32NextOp);
1078                 if (eError != PVRSRV_OK)
1079                 {
1080                         PVR_DPF((PVR_DBG_ERROR, "SyncPrimDumpSyncs: Error querying server sync status (%d)",
1081                                          eError));
1082                         goto err_free;
1083                 }
1084                 for (i = 0; i < ui32ServerSyncs; i++)
1085                 {
1086                         PVR_DPF((PVR_DBG_ERROR, "%s: sync=server fw=0x%x curr=0x%04x next=0x%04x id=%u%s",
1087                                          pcszExtraInfo,
1088                                          pui32FWAddr[i],
1089                                          pui32CurrentOp[i],
1090                                          pui32NextOp[i],
1091                                          pui32UID[i],
1092                                          (pui32NextOp[i] - pui32CurrentOp[i] == 1) ? " *" : 
1093                                          (pui32NextOp[i] - pui32CurrentOp[i] >  1) ? " **" : 
1094                                          ""));
1095                 }
1096         }
1097
1098 err_free:
1099         OSFreeMem(papsServerSync);
1100         if (pui32UID)
1101         {
1102                 OSFreeMem(pui32UID);
1103         }
1104         if (pui32FWAddr)
1105         {
1106                 OSFreeMem(pui32FWAddr);
1107         }
1108         if (pui32CurrentOp)
1109         {
1110                 OSFreeMem(pui32CurrentOp);
1111         }
1112         if (pui32NextOp)
1113         {
1114                 OSFreeMem(pui32NextOp);
1115         }
1116         return eError;
1117 #else
1118         PVR_UNREFERENCED_PARAMETER(ui32SyncCount);
1119         PVR_UNREFERENCED_PARAMETER(papsSync);
1120         PVR_UNREFERENCED_PARAMETER(pcszExtraInfo);
1121         return PVRSRV_OK;
1122 #endif
1123 }
1124 #endif
1125
1126 IMG_INTERNAL
1127 PVRSRV_ERROR SyncPrimOpCreate(IMG_UINT32 ui32SyncCount,
1128                                                           PVRSRV_CLIENT_SYNC_PRIM **papsSyncPrim,
1129                                                           PSYNC_OP_COOKIE *ppsCookie)
1130 {
1131         SYNC_OP_COOKIE *psNewCookie;
1132         SYNC_BLOCK_LIST *psSyncBlockList;
1133         IMG_UINT32 ui32ServerSyncCount = 0;
1134         IMG_UINT32 ui32ClientSyncCount = 0;
1135         IMG_UINT32 ui32ServerAllocSize;
1136         IMG_UINT32 ui32ClientAllocSize;
1137         IMG_UINT32 ui32TotalAllocSize;
1138         IMG_UINT32 ui32ServerIndex = 0;
1139         IMG_UINT32 ui32ClientIndex = 0;
1140         IMG_UINT32 i;
1141         IMG_UINT32 ui32SyncBlockCount;
1142         IMG_HANDLE hBridge;
1143         IMG_HANDLE *pahHandleList;
1144         IMG_CHAR *pcPtr;
1145         PVRSRV_ERROR eError;
1146
1147         psSyncBlockList = _SyncPrimBlockListCreate();
1148         
1149         if (!psSyncBlockList)
1150         {
1151                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1152                 goto e0;
1153         }
1154
1155         for (i=0;i<ui32SyncCount;i++)
1156         {
1157                 if (SyncPrimIsServerSync(papsSyncPrim[i]))
1158                 {
1159                         ui32ServerSyncCount++;
1160                 }
1161                 else
1162                 {
1163                         SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[i];
1164
1165                         ui32ClientSyncCount++;
1166                         eError = _SyncPrimBlockListAdd(psSyncBlockList, psSync->u.sLocal.psSyncBlock);
1167                         if (eError != PVRSRV_OK)
1168                         {
1169                                 goto e1;
1170                         }
1171                 }
1172         }
1173
1174         ui32ServerAllocSize = ui32ServerSyncCount * (sizeof(IMG_HANDLE) + sizeof(IMG_UINT32));
1175         ui32ClientAllocSize = ui32ClientSyncCount * (5 * sizeof(IMG_UINT32));
1176         ui32TotalAllocSize = sizeof(SYNC_OP_COOKIE) +
1177                                                          (sizeof(PVRSRV_CLIENT_SYNC_PRIM *) * ui32SyncCount) +
1178                                                          ui32ServerAllocSize + 
1179                                                          ui32ClientAllocSize;
1180
1181         psNewCookie = OSAllocMem(ui32TotalAllocSize);
1182         pcPtr = (IMG_CHAR *) psNewCookie;
1183
1184         if (!psNewCookie)
1185         {
1186                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1187                 goto e1;
1188         }
1189
1190         /* Setup the pointers */
1191         pcPtr += sizeof(SYNC_OP_COOKIE);
1192         psNewCookie->papsSyncPrim = (PVRSRV_CLIENT_SYNC_PRIM **) pcPtr;
1193
1194         pcPtr += sizeof(PVRSRV_CLIENT_SYNC_PRIM *) * ui32SyncCount;
1195         psNewCookie->paui32SyncBlockIndex = (IMG_UINT32 *) pcPtr;
1196
1197         pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1198         psNewCookie->paui32Index = (IMG_UINT32 *) pcPtr;
1199         
1200         pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1201         psNewCookie->paui32Flags = (IMG_UINT32 *) pcPtr;
1202
1203         pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1204         psNewCookie->paui32FenceValue = (IMG_UINT32 *) pcPtr;
1205
1206         pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1207         psNewCookie->paui32UpdateValue = (IMG_UINT32 *) pcPtr;
1208
1209         pcPtr += sizeof(IMG_UINT32) * ui32ClientSyncCount;
1210         psNewCookie->pahServerSync =(IMG_HANDLE *) pcPtr;
1211         pcPtr += sizeof(IMG_HANDLE) * ui32ServerSyncCount;
1212
1213         psNewCookie->paui32ServerFlags =(IMG_UINT32 *) pcPtr;
1214         pcPtr += sizeof(IMG_UINT32) * ui32ServerSyncCount;
1215
1216         /* Check the pointer setup went ok */
1217         if (!(pcPtr == (((IMG_CHAR *) psNewCookie) + ui32TotalAllocSize)))
1218         {
1219                 PVR_DPF((PVR_DBG_ERROR, "%s: cookie setup failed", __FUNCTION__));
1220                 eError = PVRSRV_ERROR_INTERNAL_ERROR;
1221                 goto e1;
1222         }
1223
1224         psNewCookie->ui32SyncCount = ui32SyncCount;
1225         psNewCookie->ui32ServerSyncCount = ui32ServerSyncCount;
1226         psNewCookie->ui32ClientSyncCount = ui32ClientSyncCount;
1227         psNewCookie->psSyncBlockList = psSyncBlockList;
1228
1229         /*
1230                 Get the bridge handle from the 1st sync.
1231
1232                 Note: We assume the all syncs have been created with the same
1233                           services connection.
1234         */
1235         if (SyncPrimIsServerSync(papsSyncPrim[0]))
1236         {
1237                 SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0];
1238
1239                 hBridge = psSync->u.sServer.hBridge;
1240         }
1241         else
1242         {
1243                 SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[0];
1244
1245                 hBridge = psSync->u.sLocal.psSyncBlock->psContext->hBridge;             
1246         }
1247
1248         psNewCookie->hBridge = hBridge;
1249
1250         if (ui32ServerSyncCount)
1251         {
1252                 psNewCookie->bHaveServerSync = IMG_TRUE;
1253         }
1254         else
1255         {
1256                 psNewCookie->bHaveServerSync = IMG_FALSE;
1257         }
1258
1259         /* Fill in the server and client sync data */
1260         for (i=0;i<ui32SyncCount;i++)
1261         {
1262                 SYNC_PRIM *psSync = (SYNC_PRIM *) papsSyncPrim[i];
1263
1264                 if (SyncPrimIsServerSync(papsSyncPrim[i]))
1265                 {
1266                         psNewCookie->pahServerSync[ui32ServerIndex] = psSync->u.sServer.hServerSync;
1267
1268                         ui32ServerIndex++;
1269                 }
1270                 else
1271                 {
1272                         /* Location of sync */
1273                         eError = _SyncPrimBlockListBlockToIndex(psSyncBlockList,
1274                                                                                                         psSync->u.sLocal.psSyncBlock,
1275                                                                                                         &psNewCookie->paui32SyncBlockIndex[ui32ClientIndex]);
1276                         if (eError != PVRSRV_OK)
1277                         {
1278                                 goto e2;
1279                         }
1280
1281                         /* Workout the index to sync */
1282                         psNewCookie->paui32Index[ui32ClientIndex] =
1283                                         SyncPrimGetOffset(psSync)/sizeof(IMG_UINT32);
1284
1285                         ui32ClientIndex++;
1286                 }
1287
1288                 psNewCookie->papsSyncPrim[i] = papsSyncPrim[i];
1289         }
1290
1291         eError = _SyncPrimBlockListHandleArrayCreate(psSyncBlockList,
1292                                                                                                  &ui32SyncBlockCount,
1293                                                                                                  &pahHandleList);
1294         if (eError !=PVRSRV_OK)
1295         {
1296                 goto e2;
1297         }
1298
1299         /*
1300                 Create the server side cookie. Here we pass in all the unchanging
1301                 data so we only need to pass in the minimum at takeop time
1302         */
1303         eError = BridgeSyncPrimOpCreate(hBridge,
1304                                                                         ui32SyncBlockCount,
1305                                                                         pahHandleList,
1306                                                                         psNewCookie->ui32ClientSyncCount,
1307                                                                         psNewCookie->paui32SyncBlockIndex,
1308                                                                         psNewCookie->paui32Index,
1309                                                                         psNewCookie->ui32ServerSyncCount,
1310                                                                         psNewCookie->pahServerSync,
1311                                                                         &psNewCookie->hServerCookie);
1312
1313         /* Free the handle list regardless of error */
1314         _SyncPrimBlockListHandleArrayDestroy(pahHandleList);
1315
1316         if (eError != PVRSRV_OK)
1317         {
1318                 goto e2;
1319         }
1320
1321         /* Increase the reference count on all referenced local sync prims
1322          * so that they cannot be freed until this Op is finished with
1323          */
1324         for (i=0;i<ui32SyncCount;i++)
1325         {
1326                 SYNC_PRIM *psSyncInt;
1327                 psSyncInt = IMG_CONTAINER_OF(papsSyncPrim[i], SYNC_PRIM, sCommon);
1328                 if (SYNC_PRIM_TYPE_LOCAL == psSyncInt->eType)
1329                 {
1330                         SyncPrimLocalRef(psSyncInt);
1331                 }
1332         }
1333
1334         *ppsCookie = psNewCookie;
1335         return PVRSRV_OK;
1336
1337 e2:
1338         OSFreeMem(psNewCookie);
1339 e1:
1340         _SyncPrimBlockListDestroy(psSyncBlockList);
1341 e0:
1342         return eError;
1343 }
1344
1345 IMG_INTERNAL
1346 PVRSRV_ERROR SyncPrimOpTake(PSYNC_OP_COOKIE psCookie,
1347                                                         IMG_UINT32 ui32SyncCount,
1348                                                         PVRSRV_CLIENT_SYNC_PRIM_OP *pasSyncOp)
1349 {
1350         PVRSRV_ERROR eError;
1351         IMG_UINT32 ui32ServerIndex = 0;
1352         IMG_UINT32 ui32ClientIndex = 0;
1353         IMG_UINT32 i;
1354
1355         /* Copy client sync operations */
1356         for (i=0;i<ui32SyncCount;i++)
1357         {
1358                 /*
1359                         Sanity check the client passes in the same syncs as the
1360                         ones we got at create time
1361                 */
1362                 if (psCookie->papsSyncPrim[i] != pasSyncOp[i].psSync)
1363                 {
1364                         return PVRSRV_ERROR_INVALID_PARAMS;
1365                 }
1366
1367                 if (SyncPrimIsServerSync(pasSyncOp[i].psSync))
1368                 {
1369                         psCookie->paui32ServerFlags[ui32ServerIndex] =
1370                                         pasSyncOp[i].ui32Flags;
1371
1372                         ui32ServerIndex++;
1373                 }
1374                 else
1375                 {
1376                         /* Client operation information */
1377                         psCookie->paui32Flags[ui32ClientIndex] =
1378                                         pasSyncOp[i].ui32Flags;
1379                         psCookie->paui32FenceValue[ui32ClientIndex] =
1380                                         pasSyncOp[i].ui32FenceValue;
1381                         psCookie->paui32UpdateValue[ui32ClientIndex] =
1382                                         pasSyncOp[i].ui32UpdateValue;
1383
1384                         ui32ClientIndex++;
1385                 }
1386         }
1387
1388         eError = BridgeSyncPrimOpTake(psCookie->hBridge,
1389                                                                   psCookie->hServerCookie,
1390                                                                   psCookie->ui32ClientSyncCount,
1391                                                                   psCookie->paui32Flags,
1392                                                                   psCookie->paui32FenceValue,
1393                                                                   psCookie->paui32UpdateValue,
1394                                                                   psCookie->ui32ServerSyncCount,
1395                                                                   psCookie->paui32ServerFlags);
1396
1397         return eError;
1398 }
1399
1400 IMG_INTERNAL
1401 PVRSRV_ERROR SyncPrimOpReady(PSYNC_OP_COOKIE psCookie,
1402                                                          IMG_BOOL *pbReady)
1403 {
1404         PVRSRV_ERROR eError;
1405         if (!psCookie)
1406         {
1407                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
1408                 eError = PVRSRV_ERROR_INVALID_PARAMS;
1409                 goto e0;
1410         }
1411
1412         /*
1413                 If we have a server sync we have no choice
1414                 but to do the check in the server
1415         */
1416         if (psCookie->bHaveServerSync)
1417         {
1418                 eError = BridgeSyncPrimOpReady(psCookie->hBridge,
1419                                                                            psCookie->hServerCookie,
1420                                                                            pbReady);
1421                 if (eError != PVRSRV_OK)
1422                 {
1423                         PVR_DPF((PVR_DBG_ERROR,
1424                                          "%s: Failed to do sync check in server (Error = %d)",
1425                                          __FUNCTION__, eError));
1426                         goto e0;
1427                 }
1428         }
1429         else
1430         {
1431                 IMG_UINT32 i;
1432                 IMG_UINT32 ui32SnapShot;
1433                 IMG_BOOL bReady = IMG_TRUE;
1434
1435                 for (i=0;i<psCookie->ui32ClientSyncCount;i++)
1436                 {
1437                         if ((psCookie->paui32Flags[i] & PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK) == 0)
1438                         {
1439                                 continue;
1440                         }
1441
1442                         ui32SnapShot = _SyncPrimBlockListGetClientValue(psCookie->psSyncBlockList,
1443                                                                                                                         psCookie->paui32SyncBlockIndex[i],
1444                                                                                                                         psCookie->paui32Index[i]);
1445                         if (ui32SnapShot != psCookie->paui32FenceValue[i])
1446                         {
1447                                 bReady = IMG_FALSE;
1448                                 break;
1449                         }
1450                 }
1451
1452                 *pbReady = bReady;
1453         }
1454
1455         return PVRSRV_OK;
1456 e0:
1457         return eError;
1458 }
1459
1460 IMG_INTERNAL
1461 PVRSRV_ERROR SyncPrimOpComplete(PSYNC_OP_COOKIE psCookie)
1462 {
1463         PVRSRV_ERROR eError;
1464
1465         eError = BridgeSyncPrimOpComplete(psCookie->hBridge,
1466                                                                           psCookie->hServerCookie);
1467
1468         return eError;
1469 }
1470
1471 IMG_INTERNAL
1472 IMG_VOID SyncPrimOpDestroy(PSYNC_OP_COOKIE psCookie)
1473 {
1474         PVRSRV_ERROR eError;
1475         IMG_UINT32 i;
1476
1477         /* Decrease the reference count on all referenced local sync prims
1478          * so that they can be freed now this Op is finished with
1479          */
1480         for (i=0;i<psCookie->ui32SyncCount;i++)
1481         {
1482                 SYNC_PRIM *psSyncInt;
1483                 psSyncInt = IMG_CONTAINER_OF(psCookie->papsSyncPrim[i], SYNC_PRIM, sCommon);
1484                 if (SYNC_PRIM_TYPE_LOCAL == psSyncInt->eType)
1485                 {
1486                         SyncPrimLocalUnref(psSyncInt);
1487                 }
1488         }
1489
1490         eError = BridgeSyncPrimOpDestroy(psCookie->hBridge, psCookie->hServerCookie);
1491         if (PVRSRV_OK != eError)
1492         {
1493                 PVR_DPF((PVR_DBG_ERROR,
1494                         "%s: Failed to destroy SyncPrimOp (Error = %d)",
1495                          __FUNCTION__, eError));
1496         }
1497
1498         _SyncPrimBlockListDestroy(psCookie->psSyncBlockList);
1499         OSFreeMem(psCookie);
1500 }
1501
1502 IMG_INTERNAL
1503 PVRSRV_ERROR SyncPrimOpResolve(PSYNC_OP_COOKIE psCookie,
1504                                                            IMG_UINT32 *pui32SyncCount,
1505                                                            PVRSRV_CLIENT_SYNC_PRIM_OP **ppsSyncOp)
1506 {
1507         IMG_UINT32 ui32ServerIndex = 0;
1508         IMG_UINT32 ui32ClientIndex = 0;
1509         PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOps;
1510         IMG_UINT32 i;
1511
1512         psSyncOps = OSAllocMem(sizeof(PVRSRV_CLIENT_SYNC_PRIM_OP) * 
1513                                                    psCookie->ui32SyncCount);
1514         if (!psSyncOps)
1515         {
1516                 return PVRSRV_ERROR_OUT_OF_MEMORY;
1517         }
1518         
1519         for (i=0; i<psCookie->ui32SyncCount; i++)
1520         {
1521                 psSyncOps[i].psSync = psCookie->papsSyncPrim[i];
1522                 if (SyncPrimIsServerSync(psCookie->papsSyncPrim[i]))
1523                 {
1524                         psSyncOps[i].ui32FenceValue = 0;
1525                         psSyncOps[i].ui32UpdateValue = 0;
1526                         psSyncOps[i].ui32Flags = psCookie->paui32ServerFlags[ui32ServerIndex];
1527                         ui32ServerIndex++;
1528                 }
1529                 else
1530                 {
1531                         psSyncOps[i].ui32FenceValue = psCookie->paui32FenceValue[ui32ClientIndex]; 
1532                         psSyncOps[i].ui32UpdateValue = psCookie->paui32UpdateValue[ui32ClientIndex]; 
1533                         psSyncOps[i].ui32Flags = psCookie->paui32Flags[ui32ClientIndex];
1534                         ui32ClientIndex++;
1535                 }
1536         }
1537
1538         *ppsSyncOp = psSyncOps;
1539         *pui32SyncCount = psCookie->ui32SyncCount;
1540
1541         return PVRSRV_OK;
1542 }
1543
1544 #if !defined(__KERNEL__)
1545 IMG_INTERNAL
1546 PVRSRV_ERROR SyncPrimServerAlloc(SYNC_BRIDGE_HANDLE hBridge,
1547                                                                  IMG_HANDLE hDeviceNode,
1548                                                                  PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
1549                                                                  const IMG_CHAR *pszClassName
1550                                                                  PVR_DBG_FILELINE_PARAM)
1551 {
1552         IMG_CHAR szClassName[SYNC_MAX_CLASS_NAME_LEN];
1553         SYNC_PRIM *psNewSync;
1554         PVRSRV_ERROR eError;
1555
1556 #if !defined(PVR_SYNC_PRIM_ALLOC_TRACE)
1557         PVR_DBG_FILELINE_UNREF();
1558 #endif
1559         psNewSync = OSAllocMem(sizeof(SYNC_PRIM));
1560         if (psNewSync == IMG_NULL)
1561         {
1562                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1563                 goto e0;
1564         }
1565         OSCachedMemSet(psNewSync, 0, sizeof(SYNC_PRIM));
1566
1567         if(pszClassName)
1568         {
1569                 /* Copy the class name annotation into a fixed-size array */
1570                 OSStringNCopy(szClassName, pszClassName, SYNC_MAX_CLASS_NAME_LEN - 1);
1571                 szClassName[SYNC_MAX_CLASS_NAME_LEN - 1] = 0;
1572         }
1573         else
1574         {
1575                 /* No class name annotation */
1576                 szClassName[0] = 0;
1577         }
1578
1579         eError = BridgeServerSyncAlloc(hBridge,
1580                                                                    hDeviceNode,
1581                                                                    &psNewSync->u.sServer.hServerSync,
1582                                                                    &psNewSync->u.sServer.ui32FirmwareAddr,
1583                                                                    OSStringNLength(szClassName, SYNC_MAX_CLASS_NAME_LEN),
1584                                                                    szClassName);
1585
1586         if (eError != PVRSRV_OK)
1587         {
1588                 goto e1;
1589         }
1590
1591 #if defined(PVR_SYNC_PRIM_ALLOC_TRACE)
1592         PVR_DPF((PVR_DBG_WARNING, "Allocated sync=server fw=0x%x [%p]" PVR_DBG_FILELINE_FMT,
1593                          psNewSync->u.sServer.ui32FirmwareAddr, &psNewSync->sCommon PVR_DBG_FILELINE_ARG));
1594 #endif
1595
1596         psNewSync->eType = SYNC_PRIM_TYPE_SERVER;
1597         psNewSync->u.sServer.hBridge = hBridge;
1598         *ppsSync = &psNewSync->sCommon;
1599
1600         return PVRSRV_OK;
1601 e1:
1602         OSFreeMem(psNewSync);
1603 e0:
1604         return eError;
1605 }
1606
1607 IMG_INTERNAL
1608 PVRSRV_ERROR SyncPrimServerGetStatus(IMG_UINT32 ui32SyncCount,
1609                                                                          PVRSRV_CLIENT_SYNC_PRIM **papsSync,
1610                                                                          IMG_UINT32 *pui32UID,
1611                                                                          IMG_UINT32 *pui32FWAddr,
1612                                                                          IMG_UINT32 *pui32CurrentOp,
1613                                                                          IMG_UINT32 *pui32NextOp)
1614 {
1615         PVRSRV_ERROR eError;
1616         IMG_UINT32 i;
1617         SYNC_BRIDGE_HANDLE hBridge = NULL;
1618         IMG_HANDLE *pahServerHandle;
1619
1620         if (papsSync[0])
1621         {
1622                 hBridge = _SyncPrimGetBridgeHandle(papsSync[0]);
1623         }
1624         if (!hBridge)
1625         {
1626                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid Sync connection\n", __FUNCTION__));
1627                 eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1628                 goto e0;
1629         }
1630
1631         pahServerHandle = OSAllocMem(sizeof(IMG_HANDLE) * ui32SyncCount);
1632         if (pahServerHandle == IMG_NULL)
1633         {
1634                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1635                 goto e0;
1636         }
1637
1638         /*
1639                 Check that all the sync we've been passed are server syncs
1640                 and that they all are on the same connection.
1641         */
1642         for (i=0;i<ui32SyncCount;i++)
1643         {
1644                 SYNC_PRIM *psIntSync = IMG_CONTAINER_OF(papsSync[i], SYNC_PRIM, sCommon);
1645
1646                 if (!SyncPrimIsServerSync(papsSync[i]))
1647                 {
1648                         eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1649                         goto e1;
1650                 }
1651
1652                 if (!papsSync[i] || hBridge != _SyncPrimGetBridgeHandle(papsSync[i]))
1653                 {
1654                         PVR_DPF((PVR_DBG_ERROR, "SyncServerGetStatus: Sync connection is different\n"));
1655                         eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1656                         goto e1;
1657                 }
1658
1659                 pahServerHandle[i] = psIntSync->u.sServer.hServerSync;
1660         }
1661
1662         eError = BridgeServerSyncGetStatus(hBridge,
1663                                                                            ui32SyncCount,
1664                                                                            pahServerHandle,
1665                                                                            pui32UID,
1666                                                                            pui32FWAddr,
1667                                                                            pui32CurrentOp,
1668                                                                            pui32NextOp);
1669         OSFreeMem(pahServerHandle);
1670
1671         if (eError != PVRSRV_OK)
1672         {
1673                 goto e0;
1674         }
1675         return PVRSRV_OK;
1676
1677 e1:
1678         OSFreeMem(pahServerHandle);
1679 e0:
1680         return eError;
1681 }
1682
1683 #endif
1684
1685 IMG_INTERNAL
1686 IMG_BOOL SyncPrimIsServerSync(PVRSRV_CLIENT_SYNC_PRIM *psSync)
1687 {
1688         SYNC_PRIM *psSyncInt;
1689
1690         if (!psSync)
1691         {
1692                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
1693                 goto e0;
1694         }
1695         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1696         if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
1697         {
1698                 return IMG_TRUE;
1699         }
1700
1701 e0:
1702         return IMG_FALSE;
1703 }
1704
1705 IMG_INTERNAL
1706 IMG_HANDLE SyncPrimGetServerHandle(PVRSRV_CLIENT_SYNC_PRIM *psSync)
1707 {
1708         SYNC_PRIM *psSyncInt;
1709
1710         if (!psSync)
1711         {
1712                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
1713                 goto e0;
1714         }
1715         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1716         if (psSyncInt->eType == SYNC_PRIM_TYPE_SERVER)
1717         {
1718                 return psSyncInt->u.sServer.hServerSync;
1719         }
1720         else
1721         {
1722                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid sync type (%d)",
1723                         __FUNCTION__, psSyncInt->eType));
1724                 goto e0;
1725         }
1726 e0:
1727         return 0;
1728 }
1729
1730 IMG_INTERNAL
1731 PVRSRV_ERROR SyncPrimServerQueueOp(PVRSRV_CLIENT_SYNC_PRIM_OP *psSyncOp)
1732 {
1733         SYNC_PRIM *psSyncInt;
1734         IMG_BOOL bUpdate;
1735         PVRSRV_ERROR eError;
1736
1737         if (!psSyncOp)
1738         {
1739                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid input pointer", __FUNCTION__));
1740                 eError = PVRSRV_ERROR_INVALID_PARAMS;
1741                 goto e0;
1742         }
1743
1744         psSyncInt = IMG_CONTAINER_OF(psSyncOp->psSync, SYNC_PRIM, sCommon);
1745         if (psSyncInt->eType != SYNC_PRIM_TYPE_SERVER)
1746         {
1747                 PVR_DPF((PVR_DBG_ERROR, "%s: invalid sync type (%d)",
1748                         __FUNCTION__, psSyncInt->eType));
1749                 eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1750                 goto e0;
1751         }
1752         if (0 == psSyncOp->ui32Flags)
1753         {
1754                 PVR_DPF((PVR_DBG_ERROR, "%s: no sync flags", __FUNCTION__));
1755                 eError = PVRSRV_ERROR_INVALID_SYNC_PRIM;
1756                 goto e0;
1757         }
1758
1759         if (psSyncOp->ui32Flags & PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE)
1760         {
1761                 bUpdate = IMG_TRUE;
1762         }else
1763         {
1764                 bUpdate = IMG_FALSE;
1765         }
1766
1767         eError = BridgeServerSyncQueueHWOp(psSyncInt->u.sServer.hBridge,
1768                                                                               psSyncInt->u.sServer.hServerSync,
1769                                                                                   bUpdate,
1770                                                                               &psSyncOp->ui32FenceValue,
1771                                                                               &psSyncOp->ui32UpdateValue);
1772 e0:
1773         return eError;
1774 }
1775
1776 #if defined(PDUMP)
1777 IMG_INTERNAL IMG_VOID SyncPrimPDump(PVRSRV_CLIENT_SYNC_PRIM *psSync)
1778 {
1779         SYNC_PRIM *psSyncInt;
1780         SYNC_PRIM_BLOCK *psSyncBlock;
1781         SYNC_PRIM_CONTEXT *psContext;
1782         PVRSRV_ERROR eError;
1783
1784         PVR_ASSERT(psSync != IMG_NULL);
1785         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1786
1787         if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
1788         {
1789                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDump: Invalid sync type"));
1790                 PVR_ASSERT(IMG_FALSE);
1791                 return;
1792         }
1793
1794         psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
1795         psContext = psSyncBlock->psContext;
1796
1797         eError = BridgeSyncPrimPDump(psContext->hBridge,
1798                                                                  psSyncBlock->hServerSyncPrimBlock,
1799                                                                  SyncPrimGetOffset(psSyncInt));
1800
1801         if (eError != PVRSRV_OK)
1802         {
1803                 PVR_DPF((PVR_DBG_ERROR,
1804                                 "%s: failed with error %d",
1805                                 __FUNCTION__, eError));
1806         }
1807     PVR_ASSERT(eError == PVRSRV_OK);
1808 }
1809
1810 IMG_INTERNAL IMG_VOID SyncPrimPDumpValue(PVRSRV_CLIENT_SYNC_PRIM *psSync, IMG_UINT32 ui32Value)
1811 {
1812         SYNC_PRIM *psSyncInt;
1813         SYNC_PRIM_BLOCK *psSyncBlock;
1814         SYNC_PRIM_CONTEXT *psContext;
1815         PVRSRV_ERROR eError;
1816
1817         PVR_ASSERT(psSync != IMG_NULL);
1818         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1819
1820         if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
1821         {
1822                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDump: Invalid sync type"));
1823                 PVR_ASSERT(IMG_FALSE);
1824                 return;
1825         }
1826
1827         psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
1828         psContext = psSyncBlock->psContext;
1829
1830         eError = BridgeSyncPrimPDumpValue(psContext->hBridge,
1831                                                                  psSyncBlock->hServerSyncPrimBlock,
1832                                                                  SyncPrimGetOffset(psSyncInt),
1833                                                                  ui32Value);
1834
1835         if (eError != PVRSRV_OK)
1836         {
1837                 PVR_DPF((PVR_DBG_ERROR,
1838                                 "%s: failed with error %d",
1839                                 __FUNCTION__, eError));
1840         }
1841     PVR_ASSERT(eError == PVRSRV_OK);
1842 }
1843
1844 IMG_INTERNAL IMG_VOID SyncPrimPDumpPol(PVRSRV_CLIENT_SYNC_PRIM *psSync,
1845                                                                            IMG_UINT32 ui32Value,
1846                                                                            IMG_UINT32 ui32Mask,
1847                                                                            PDUMP_POLL_OPERATOR eOperator,
1848                                                                            IMG_UINT32 ui32PDumpFlags)
1849 {
1850         SYNC_PRIM *psSyncInt;
1851         SYNC_PRIM_BLOCK *psSyncBlock;
1852         SYNC_PRIM_CONTEXT *psContext;
1853         PVRSRV_ERROR eError;
1854
1855         PVR_ASSERT(psSync != IMG_NULL);
1856         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1857
1858         if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
1859         {
1860                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDumpPol: Invalid sync type (expected SYNC_PRIM_TYPE_LOCAL)"));
1861                 PVR_ASSERT(IMG_FALSE);
1862                 return;
1863         }
1864
1865         psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
1866         psContext = psSyncBlock->psContext;
1867
1868         eError = BridgeSyncPrimPDumpPol(psContext->hBridge,
1869                                                                         psSyncBlock->hServerSyncPrimBlock,
1870                                                                         SyncPrimGetOffset(psSyncInt),
1871                                                                         ui32Value,
1872                                                                         ui32Mask,
1873                                                                         eOperator,
1874                                                                         ui32PDumpFlags);
1875
1876         if (eError != PVRSRV_OK)
1877         {
1878                 PVR_DPF((PVR_DBG_ERROR,
1879                                 "%s: failed with error %d",
1880                                 __FUNCTION__, eError));
1881         }
1882     PVR_ASSERT(eError == PVRSRV_OK);
1883 }
1884
1885 IMG_INTERNAL IMG_VOID SyncPrimOpPDumpPol(PSYNC_OP_COOKIE psCookie,
1886                                                                            PDUMP_POLL_OPERATOR eOperator,
1887                                                                            IMG_UINT32 ui32PDumpFlags)
1888 {
1889         PVRSRV_ERROR eError;
1890
1891         PVR_ASSERT(psCookie != IMG_NULL);
1892
1893         eError = BridgeSyncPrimOpPDumpPol(psCookie->hBridge,
1894                                                                         psCookie->hServerCookie,
1895                                                                         eOperator,
1896                                                                         ui32PDumpFlags);
1897
1898         if (eError != PVRSRV_OK)
1899         {
1900                 PVR_DPF((PVR_DBG_ERROR,
1901                                 "%s: failed with error %d",
1902                                 __FUNCTION__, eError));
1903         }
1904         
1905     PVR_ASSERT(eError == PVRSRV_OK);
1906 }
1907
1908 IMG_INTERNAL IMG_VOID SyncPrimPDumpCBP(PVRSRV_CLIENT_SYNC_PRIM *psSync,
1909                                                                            IMG_UINT64 uiWriteOffset,
1910                                                                            IMG_UINT64 uiPacketSize,
1911                                                                            IMG_UINT64 uiBufferSize)
1912 {
1913         SYNC_PRIM *psSyncInt;
1914         SYNC_PRIM_BLOCK *psSyncBlock;
1915         SYNC_PRIM_CONTEXT *psContext;
1916         PVRSRV_ERROR eError;
1917
1918         PVR_ASSERT(psSync != IMG_NULL);
1919         psSyncInt = IMG_CONTAINER_OF(psSync, SYNC_PRIM, sCommon);
1920
1921         if (psSyncInt->eType != SYNC_PRIM_TYPE_LOCAL)
1922         {
1923                 PVR_DPF((PVR_DBG_ERROR, "SyncPrimPDumpCBP: Invalid sync type"));
1924                 PVR_ASSERT(IMG_FALSE);
1925                 return;
1926         }
1927
1928         psSyncBlock = psSyncInt->u.sLocal.psSyncBlock;
1929         psContext = psSyncBlock->psContext;
1930
1931         /* FIXME: uiWriteOffset, uiPacketSize, uiBufferSize were changed to
1932          * 64-bit quantities to resolve Windows compiler warnings.
1933          * However the bridge is only 32-bit hence compiler warnings
1934          * of implicit cast and loss of data.
1935          * Added explicit cast and assert to remove warning.
1936          */
1937 #if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
1938         PVR_ASSERT(uiWriteOffset<IMG_UINT32_MAX);
1939         PVR_ASSERT(uiPacketSize<IMG_UINT32_MAX);
1940         PVR_ASSERT(uiBufferSize<IMG_UINT32_MAX);
1941 #endif
1942         eError = BridgeSyncPrimPDumpCBP(psContext->hBridge,
1943                                                                         psSyncBlock->hServerSyncPrimBlock,
1944                                                                         SyncPrimGetOffset(psSyncInt),
1945                                                                         (IMG_UINT32)uiWriteOffset,
1946                                                                         (IMG_UINT32)uiPacketSize,
1947                                                                         (IMG_UINT32)uiBufferSize);
1948
1949         if (eError != PVRSRV_OK)
1950         {
1951                 PVR_DPF((PVR_DBG_ERROR,
1952                                 "%s: failed with error %d",
1953                                 __FUNCTION__, eError));
1954         }
1955     PVR_ASSERT(eError == PVRSRV_OK);
1956 }
1957
1958 #endif
1959