7490fe9a31b37f31aebf781a87a37be1e4f9d6ca
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue / services / shared / common / devicemem.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Device Memory Management
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Front End (nominally Client side part, but now invokable
6                 from server too) of device memory management
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 "devicemem.h"
46 #include "img_types.h"
47 #include "pvr_debug.h"
48 #include "pvrsrv_error.h"
49 #include "allocmem.h"
50 #include "ra.h"
51 #include "osfunc.h"
52 #include "devicemem_mmap.h"
53 #include "devicemem_utils.h"
54 #include "client_mm_bridge.h"
55 #if defined(PDUMP)
56 #include "devicemem_pdump.h"
57 #endif
58 #if defined(PVR_RI_DEBUG)
59 #include "client_ri_bridge.h"
60 #endif 
61
62 #if defined(__KERNEL__)
63 #include "pvrsrv.h"
64 #if defined(LINUX)
65 #include "linux/kernel.h"
66 #endif
67 #endif
68
69 /* Storing the page size here so we do not have to hard code it in the code anymore
70    Should be initialised to the correct value at driver init time.
71    Use macros from devicemem.h to access from outside.
72  */
73 IMG_UINT32 g_uiLog2PageSize = 0;
74
75 static PVRSRV_ERROR
76 _Mapping_Export(DEVMEM_IMPORT *psImport,
77                 DEVMEM_EXPORTHANDLE *phPMRExportHandlePtr,
78                 DEVMEM_EXPORTKEY *puiExportKeyPtr,
79                 DEVMEM_SIZE_T *puiSize,
80                 DEVMEM_LOG2ALIGN_T *puiLog2Contig)
81 {
82     /* Gets an export handle and key for the PMR used for this mapping */
83     /* Can only be done if there are no suballocations for this mapping */
84
85     PVRSRV_ERROR eError;
86     DEVMEM_EXPORTHANDLE hPMRExportHandle;
87     DEVMEM_EXPORTKEY uiExportKey;
88     IMG_DEVMEM_SIZE_T uiSize;
89     IMG_DEVMEM_LOG2ALIGN_T uiLog2Contig;
90
91     if (psImport == IMG_NULL)
92     {
93         eError = PVRSRV_ERROR_INVALID_PARAMS;
94         goto failParams;
95     }
96
97     if (!psImport->bExportable)
98     {
99                 eError = PVRSRV_ERROR_DEVICEMEM_CANT_EXPORT_SUBALLOCATION;
100         goto failParams;
101     }
102
103     eError = BridgePMRExportPMR(psImport->hBridge,
104                                 psImport->hPMR,
105                                 &hPMRExportHandle,
106                                 &uiSize,
107                                 &uiLog2Contig,
108                                 &uiExportKey);
109     if (eError != PVRSRV_OK)
110     {
111         goto failExport;
112     }
113
114     PVR_ASSERT(uiSize == psImport->uiSize);
115
116     *phPMRExportHandlePtr = hPMRExportHandle;
117     *puiExportKeyPtr = uiExportKey;
118     *puiSize = uiSize;
119     *puiLog2Contig = uiLog2Contig;
120
121     return PVRSRV_OK;
122
123     /*
124       error exit paths follow
125     */
126
127 failExport:
128 failParams:
129
130     PVR_ASSERT(eError != PVRSRV_OK);
131     return eError;
132
133 }
134
135 static IMG_VOID
136 _Mapping_Unexport(DEVMEM_IMPORT *psImport,
137                   DEVMEM_EXPORTHANDLE hPMRExportHandle)
138 {
139     PVRSRV_ERROR eError;
140
141     PVR_ASSERT (psImport != IMG_NULL);
142
143     eError = BridgePMRUnexportPMR(psImport->hBridge,
144                                   hPMRExportHandle);
145     PVR_ASSERT(eError == PVRSRV_OK);
146 }
147
148 /*****************************************************************************
149  *                    Sub allocation internals                               *
150  *****************************************************************************/
151
152 static PVRSRV_ERROR
153 _AllocateDeviceMemory(IMG_HANDLE hBridge,
154                                           IMG_HANDLE hDeviceNode,
155                                           IMG_UINT32 uiLog2Quantum,
156                                           IMG_DEVMEM_SIZE_T uiSize,
157                                           IMG_DEVMEM_SIZE_T uiChunkSize,
158                                           IMG_UINT32 ui32NumPhysChunks,
159                                           IMG_UINT32 ui32NumVirtChunks,
160                                           IMG_BOOL *pabMappingTable,
161                                           IMG_DEVMEM_ALIGN_T uiAlign,
162                                           DEVMEM_FLAGS_T uiFlags,
163                                           IMG_BOOL bExportable,
164                                           DEVMEM_IMPORT **ppsImport)
165 {
166         DEVMEM_IMPORT *psImport;
167         DEVMEM_FLAGS_T uiPMRFlags;
168         IMG_HANDLE hPMR;
169         PVRSRV_ERROR eError;
170
171         eError = _DevmemImportStructAlloc(hBridge,
172                                                                           bExportable,
173                                                                           &psImport);
174         if (eError != PVRSRV_OK)
175         {
176                 goto failAlloc;
177         }
178
179     /* Check the size is a multiple of the quantum */
180     PVR_ASSERT((uiSize & ((1ULL<<uiLog2Quantum)-1)) == 0);
181
182         /* Pass only the PMR flags down */
183         uiPMRFlags = uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK;
184
185     eError = BridgePhysmemNewRamBackedPMR(hBridge,
186                                           hDeviceNode,
187                                           uiSize,
188                                           uiChunkSize,
189                                           ui32NumPhysChunks,
190                                           ui32NumVirtChunks,
191                                           pabMappingTable,
192                                           uiLog2Quantum,
193                                           uiPMRFlags,
194                                           &hPMR);
195     if (eError != PVRSRV_OK)
196     {
197         /* Our check above should have ensured this the "not page
198            multiple" error never happens */
199         PVR_ASSERT(eError != PVRSRV_ERROR_PMR_NOT_PAGE_MULTIPLE);
200
201         goto failPMR;
202     }
203
204         _DevmemImportStructInit(psImport,
205                                                         uiSize,
206                                                         uiAlign,
207                                                         uiFlags,
208                                                         hPMR);
209
210         *ppsImport = psImport;
211         return PVRSRV_OK;
212
213 failPMR:
214         _DevmemImportDiscard(psImport);
215 failAlloc:
216         PVR_ASSERT(eError != PVRSRV_OK);
217
218         return eError;
219 }
220
221 static IMG_VOID
222 _FreeDeviceMemory(DEVMEM_IMPORT *psImport)
223 {
224         _DevmemImportStructRelease(psImport);
225 }
226
227 static IMG_BOOL
228 _SubAllocImportAlloc(RA_PERARENA_HANDLE hArena,
229                      RA_LENGTH_T uiSize,
230                      RA_FLAGS_T _flags,
231                      /* returned data */
232                      RA_BASE_T *puiBase,
233                      RA_LENGTH_T *puiActualSize,
234                      RA_PERISPAN_HANDLE *phImport)
235 {
236     /* When suballocations need a new lump of memory, the RA calls
237        back here.  Later, in the kernel, we must construct a new PMR
238        and a pairing between the new lump of virtual memory and the
239        PMR (whether or not such PMR is backed by physical memory) */
240     DEVMEM_HEAP *psHeap;
241     DEVMEM_IMPORT *psImport;
242     IMG_DEVMEM_ALIGN_T uiAlign;
243     DEVMEM_FLAGS_T uiFlags;
244     PVRSRV_ERROR eError;
245     IMG_BOOL bMappingTable = IMG_TRUE;
246
247     uiFlags = (DEVMEM_FLAGS_T) _flags;
248
249     /* Per-arena private handle is, for us, the heap */
250     psHeap = hArena;
251
252     /* align to the l.s.b. of the size...  e.g. 96kiB aligned to
253        32kiB. NB: There is an argument to say that the RA should never
254        ask us for Non-power-of-2 size anyway, but I don't want to make
255        that restriction arbitrarily now */
256     uiAlign = uiSize & ~(uiSize-1);
257
258     /* The RA should not have invoked us with a size that is not a
259        multiple of the quantum anyway */
260     PVR_ASSERT((uiSize & ((1ULL<<psHeap->uiLog2Quantum)-1)) == 0);
261
262         eError = _AllocateDeviceMemory(psHeap->psCtx->hBridge,
263                                                                    psHeap->psCtx->hDeviceNode,
264                                                                    psHeap->uiLog2Quantum,
265                                                                    uiSize,
266                                                                    uiSize,
267                                                                    1,
268                                                                    1,
269                                                                    &bMappingTable,
270                                                                    uiAlign,
271                                                                    uiFlags,
272                                                                    IMG_FALSE,
273                                                                    &psImport);
274         if (eError != PVRSRV_OK)
275         {
276                 goto failAlloc;
277         }
278
279 #if defined(PVR_RI_DEBUG)
280         {
281                 eError = BridgeRIWritePMREntry (psImport->hBridge,
282                                                                                 psImport->hPMR,
283                                                                                 sizeof("PMR sub-allocated"),
284                                                                                 "PMR sub-allocated",
285                                                                                 psImport->uiSize);
286                 if( eError != PVRSRV_OK)
287                 {
288                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
289                 }
290         }
291 #endif
292         /*
293                 Suballocations always get mapped into the device was we need to
294                 key the RA off something and as we can't export suballocations
295                 there is no valid reason to request an allocation an not map it
296         */
297         eError = _DevmemImportStructDevMap(psHeap,
298                                                                            IMG_TRUE,
299                                                                            psImport);
300         if (eError != PVRSRV_OK)
301         {
302                 goto failMap;
303         }
304
305         *puiBase = psImport->sDeviceImport.sDevVAddr.uiAddr;
306         *puiActualSize = uiSize;
307         *phImport = psImport;
308
309     return IMG_TRUE;
310
311     /*
312       error exit paths follow
313     */
314 failMap:
315     _FreeDeviceMemory(psImport);
316 failAlloc:
317
318     return IMG_FALSE;
319 }
320
321 static IMG_VOID
322 _SubAllocImportFree(RA_PERARENA_HANDLE hArena,
323                     RA_BASE_T uiBase,
324                     RA_PERISPAN_HANDLE hImport)
325 {
326     DEVMEM_IMPORT *psImport = hImport;
327
328     PVR_ASSERT(psImport != IMG_NULL);
329     PVR_ASSERT(hArena == psImport->sDeviceImport.psHeap);
330     PVR_ASSERT(uiBase == psImport->sDeviceImport.sDevVAddr.uiAddr);
331
332     _DevmemImportStructDevUnmap(psImport);  
333         _DevmemImportStructRelease(psImport);
334 }
335
336 /*****************************************************************************
337  *                    Devmem context internals                               *
338  *****************************************************************************/
339
340 static PVRSRV_ERROR
341 _PopulateContextFromBlueprint(struct _DEVMEM_CONTEXT_ *psCtx,
342                               IMG_HANDLE hDeviceNode,
343                               DEVMEM_HEAPCFGID uiHeapBlueprintID)
344 {
345     PVRSRV_ERROR eError;
346     PVRSRV_ERROR eError2;
347     struct _DEVMEM_HEAP_ **ppsHeapArray;
348     IMG_UINT32 uiNumHeaps;
349     IMG_UINT32 uiHeapsToUnwindOnError;
350     IMG_UINT32 uiHeapIndex;
351     IMG_DEV_VIRTADDR sDevVAddrBase;
352     IMG_CHAR aszHeapName[DEVMEM_HEAPNAME_MAXLENGTH];
353     IMG_DEVMEM_SIZE_T uiHeapLength;
354     IMG_DEVMEM_LOG2ALIGN_T uiLog2DataPageSize;
355
356     eError = DevmemHeapCount(psCtx->hBridge,
357                              hDeviceNode,
358                              uiHeapBlueprintID,
359                              &uiNumHeaps);
360     if (eError != PVRSRV_OK)
361     {
362         goto e0;
363     }
364
365     if (uiNumHeaps == 0)
366     {
367         ppsHeapArray = IMG_NULL;
368     }
369     else
370     {
371         ppsHeapArray = OSAllocMem(sizeof(*ppsHeapArray) * uiNumHeaps);
372         if (ppsHeapArray == IMG_NULL)
373         {
374             eError = PVRSRV_ERROR_OUT_OF_MEMORY;
375             goto e0;
376         }
377     }
378
379     uiHeapsToUnwindOnError = 0;
380
381     for (uiHeapIndex = 0; uiHeapIndex < uiNumHeaps; uiHeapIndex++)
382     {
383         eError = DevmemHeapDetails(psCtx->hBridge,
384                                    hDeviceNode,
385                                    uiHeapBlueprintID,
386                                    uiHeapIndex,
387                                    &aszHeapName[0],
388                                    sizeof(aszHeapName),
389                                    &sDevVAddrBase,
390                                    &uiHeapLength,
391                                    &uiLog2DataPageSize);
392         if (eError != PVRSRV_OK)
393         {
394             goto e1;
395         }
396
397         eError = DevmemCreateHeap(psCtx,
398                                   sDevVAddrBase,
399                                   uiHeapLength,
400                                   uiLog2DataPageSize,
401                                   aszHeapName,
402                                   &ppsHeapArray[uiHeapIndex]);
403         if (eError != PVRSRV_OK)
404         {
405             goto e1;
406         }
407
408         uiHeapsToUnwindOnError = uiHeapIndex + 1;
409     }
410
411     psCtx->uiAutoHeapCount = uiNumHeaps;
412     psCtx->ppsAutoHeapArray = ppsHeapArray;
413
414     PVR_ASSERT(psCtx->uiNumHeaps >= psCtx->uiAutoHeapCount);
415     PVR_ASSERT(psCtx->uiAutoHeapCount == uiNumHeaps);
416
417     return PVRSRV_OK;
418
419     /*
420       error exit paths
421     */
422  e1:
423     for (uiHeapIndex = 0; uiHeapIndex < uiHeapsToUnwindOnError; uiHeapIndex++)
424     {
425         eError2 = DevmemDestroyHeap(ppsHeapArray[uiHeapIndex]);
426         PVR_ASSERT(eError2 == PVRSRV_OK);
427     }
428
429     if (uiNumHeaps != 0)
430     {
431         OSFreeMem(ppsHeapArray);
432     }
433
434  e0:
435     PVR_ASSERT(eError != PVRSRV_OK);
436     return eError;
437 }
438
439 static IMG_VOID
440 _UnpopulateContextFromBlueprint(struct _DEVMEM_CONTEXT_ *psCtx)
441 {
442     PVRSRV_ERROR eError2;
443     IMG_UINT32 uiHeapIndex;
444     IMG_BOOL bDoCheck = IMG_TRUE;
445 #if defined(__KERNEL__)
446     PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
447     if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
448     {
449         bDoCheck = IMG_FALSE;
450     }
451 #endif
452
453     PVR_ASSERT(psCtx->uiNumHeaps >= psCtx->uiAutoHeapCount);
454
455     for (uiHeapIndex = 0; uiHeapIndex < psCtx->uiAutoHeapCount; uiHeapIndex++)
456     {
457         eError2 = DevmemDestroyHeap(psCtx->ppsAutoHeapArray[uiHeapIndex]);
458         if (bDoCheck)
459         {
460                 PVR_ASSERT(eError2 == PVRSRV_OK);
461         }
462     }
463
464     if (psCtx->uiAutoHeapCount != 0)
465     {
466         OSFreeMem(psCtx->ppsAutoHeapArray);
467         psCtx->ppsAutoHeapArray = IMG_NULL;
468     }
469     psCtx->uiAutoHeapCount = 0;
470
471     PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
472     PVR_ASSERT(psCtx->ppsAutoHeapArray == IMG_NULL);
473 }
474
475
476 /*****************************************************************************
477  *                    Devmem context functions                               *
478  *****************************************************************************/
479
480 IMG_INTERNAL PVRSRV_ERROR
481 DevmemCreateContext(DEVMEM_BRIDGE_HANDLE hBridge,
482                     IMG_HANDLE hDeviceNode,
483                     DEVMEM_HEAPCFGID uiHeapBlueprintID,
484                     DEVMEM_CONTEXT **ppsCtxPtr)
485 {
486     PVRSRV_ERROR eError;
487     DEVMEM_CONTEXT *psCtx;
488     /* handle to the server-side counterpart of the device memory
489        context (specifically, for handling mapping to device MMU) */
490     IMG_HANDLE hDevMemServerContext;
491     IMG_HANDLE hPrivData;
492
493
494     if (ppsCtxPtr == IMG_NULL)
495     {
496         eError = PVRSRV_ERROR_INVALID_PARAMS;
497         goto e0;
498     }
499
500     psCtx = OSAllocMem(sizeof *psCtx);
501     if (psCtx == IMG_NULL)
502     {
503         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
504         goto e0;
505     }
506
507     psCtx->uiNumHeaps = 0;
508
509     psCtx->hBridge = hBridge;
510
511     /* Create (server-side) Device Memory context */
512     eError = BridgeDevmemIntCtxCreate(psCtx->hBridge,
513                                    hDeviceNode,
514                                    &hDevMemServerContext,
515                                    &hPrivData);
516     if (eError != PVRSRV_OK)
517     {
518         goto e1;
519     }
520
521     psCtx->hDeviceNode = hDeviceNode;
522     psCtx->hDevMemServerContext = hDevMemServerContext;
523     psCtx->hPrivData = hPrivData;
524
525     /* automagic heap creation */
526     psCtx->uiAutoHeapCount = 0;
527
528     eError = _PopulateContextFromBlueprint(psCtx, hDeviceNode, uiHeapBlueprintID);
529     if (eError != PVRSRV_OK)
530     {
531         goto e2;
532     }
533
534
535     *ppsCtxPtr = psCtx;
536
537
538     PVR_ASSERT(psCtx->uiNumHeaps == psCtx->uiAutoHeapCount);
539     return PVRSRV_OK;
540
541     /*
542       error exit paths follow
543     */
544
545  e2:
546     PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
547     PVR_ASSERT(psCtx->uiNumHeaps == 0);
548     BridgeDevmemIntCtxDestroy(psCtx->hBridge, hDevMemServerContext);
549
550  e1:
551     OSFreeMem(psCtx);
552
553  e0:
554     PVR_ASSERT(eError != PVRSRV_OK);
555     return eError;
556 }
557
558 IMG_INTERNAL PVRSRV_ERROR
559 DevmemAcquireDevPrivData(DEVMEM_CONTEXT *psCtx,
560                          IMG_HANDLE *hPrivData)
561 {
562         PVRSRV_ERROR eError;
563
564         if ((psCtx == IMG_NULL) || (hPrivData == IMG_NULL))
565         {
566                 eError = PVRSRV_ERROR_INVALID_PARAMS;
567                 goto e0;
568         }
569
570         *hPrivData = psCtx->hPrivData;
571         return PVRSRV_OK;
572
573 e0:
574         PVR_ASSERT(eError != PVRSRV_OK);
575         return eError;
576 }
577
578 IMG_INTERNAL PVRSRV_ERROR
579 DevmemReleaseDevPrivData(DEVMEM_CONTEXT *psCtx)
580 {
581         PVRSRV_ERROR eError;
582
583         if (psCtx == IMG_NULL)
584         {
585                 eError = PVRSRV_ERROR_INVALID_PARAMS;
586                 goto e0;
587         }
588         return PVRSRV_OK;
589
590 e0:
591         PVR_ASSERT(eError != PVRSRV_OK);
592         return eError;
593 }
594
595
596 IMG_INTERNAL PVRSRV_ERROR
597 DevmemFindHeapByName(const struct _DEVMEM_CONTEXT_ *psCtx,
598                      const IMG_CHAR *pszHeapName,
599                      struct _DEVMEM_HEAP_ **ppsHeapRet)
600 {
601     IMG_UINT32 uiHeapIndex;
602
603     /* N.B.  This func is only useful for finding "automagic" heaps by name */
604     for (uiHeapIndex = 0;
605          uiHeapIndex < psCtx->uiAutoHeapCount;
606          uiHeapIndex++)
607     {
608         if (!OSStringCompare(psCtx->ppsAutoHeapArray[uiHeapIndex]->pszName, pszHeapName))
609         {
610             *ppsHeapRet = psCtx->ppsAutoHeapArray[uiHeapIndex];
611             return PVRSRV_OK;
612         }
613     }
614
615     return PVRSRV_ERROR_DEVICEMEM_INVALID_HEAP_INDEX;
616 }
617
618 IMG_INTERNAL PVRSRV_ERROR
619 DevmemDestroyContext(DEVMEM_CONTEXT *psCtx)
620 {
621     PVRSRV_ERROR eError;
622     IMG_BOOL bDoCheck = IMG_TRUE;
623
624 #if defined(__KERNEL__)
625     PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
626     if (psPVRSRVData->eServicesState != PVRSRV_SERVICES_STATE_OK)
627     {
628         bDoCheck = IMG_FALSE;
629     }
630 #endif
631
632     if (psCtx == IMG_NULL)
633     {
634         return PVRSRV_ERROR_INVALID_PARAMS;
635     }
636
637     /* should be only the automagically instantiated heaps left */
638     if (psCtx->uiNumHeaps != psCtx->uiAutoHeapCount)
639     {
640         return PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
641     }
642
643     _UnpopulateContextFromBlueprint(psCtx);
644
645     if (bDoCheck)
646     {
647                 PVR_ASSERT(psCtx->uiAutoHeapCount == 0);
648                 PVR_ASSERT(psCtx->uiNumHeaps == 0);
649     }
650     eError = BridgeDevmemIntCtxDestroy(psCtx->hBridge,
651                                       psCtx->hDevMemServerContext);
652     if (bDoCheck)
653     {
654         PVR_ASSERT (eError == PVRSRV_OK);
655     }
656
657     OSFreeMem(psCtx);
658
659     return PVRSRV_OK;
660 }
661
662 /*****************************************************************************
663  *                 Devmem heap query functions                               *
664  *****************************************************************************/
665
666 IMG_INTERNAL PVRSRV_ERROR
667 DevmemHeapConfigCount(DEVMEM_BRIDGE_HANDLE hBridge,
668                       IMG_HANDLE hDeviceNode,
669                       IMG_UINT32 *puiNumHeapConfigsOut)
670 {
671     PVRSRV_ERROR eError;
672
673     eError = BridgeHeapCfgHeapConfigCount(hBridge,
674                                           hDeviceNode,
675                                           puiNumHeapConfigsOut);
676     return eError;
677 }
678
679 IMG_INTERNAL PVRSRV_ERROR
680 DevmemHeapCount(DEVMEM_BRIDGE_HANDLE hBridge,
681                 IMG_HANDLE hDeviceNode,
682                 IMG_UINT32 uiHeapConfigIndex,
683                 IMG_UINT32 *puiNumHeapsOut)
684 {
685     PVRSRV_ERROR eError;
686
687     eError = BridgeHeapCfgHeapCount(hBridge,
688                                     hDeviceNode,
689                                     uiHeapConfigIndex,
690                                     puiNumHeapsOut);
691     return eError;
692 }
693
694 IMG_INTERNAL PVRSRV_ERROR
695 DevmemHeapConfigName(DEVMEM_BRIDGE_HANDLE hBridge,
696                      IMG_HANDLE hDeviceNode,
697                      IMG_UINT32 uiHeapConfigIndex,
698                      IMG_CHAR *pszConfigNameOut,
699                      IMG_UINT32 uiConfigNameBufSz)
700 {
701     PVRSRV_ERROR eError;
702
703     eError = BridgeHeapCfgHeapConfigName(hBridge,
704                                          hDeviceNode,
705                                          uiHeapConfigIndex,
706                                          uiConfigNameBufSz,
707                                          pszConfigNameOut);
708     return eError;
709 }
710
711 IMG_INTERNAL PVRSRV_ERROR
712 DevmemHeapDetails(DEVMEM_BRIDGE_HANDLE hBridge,
713                   IMG_HANDLE hDeviceNode,
714                   IMG_UINT32 uiHeapConfigIndex,
715                   IMG_UINT32 uiHeapIndex,
716                   IMG_CHAR *pszHeapNameOut,
717                   IMG_UINT32 uiHeapNameBufSz,
718                   IMG_DEV_VIRTADDR *psDevVAddrBaseOut,
719                   IMG_DEVMEM_SIZE_T *puiHeapLengthOut,
720                   IMG_UINT32 *puiLog2DataPageSizeOut)
721 {
722     PVRSRV_ERROR eError;
723
724     eError = BridgeHeapCfgHeapDetails(hBridge,
725                                       hDeviceNode,
726                                       uiHeapConfigIndex,
727                                       uiHeapIndex,
728                                       uiHeapNameBufSz,
729                                       pszHeapNameOut,
730                                       psDevVAddrBaseOut,
731                                       puiHeapLengthOut,
732                                       puiLog2DataPageSizeOut);
733
734     VG_MARK_INITIALIZED(pszHeapNameOut,uiHeapNameBufSz);
735
736     return eError;
737 }
738
739 /*****************************************************************************
740  *                    Devmem heap functions                                  *
741  *****************************************************************************/
742  
743 /* See devicemem.h for important notes regarding the arguments
744    to this function */
745 IMG_INTERNAL PVRSRV_ERROR
746 DevmemCreateHeap(DEVMEM_CONTEXT *psCtx,
747                  IMG_DEV_VIRTADDR sBaseAddress,
748                  IMG_DEVMEM_SIZE_T uiLength,
749                  IMG_UINT32 ui32Log2Quantum,
750                  const IMG_CHAR *pszName,
751                  DEVMEM_HEAP **ppsHeapPtr)
752 {
753     PVRSRV_ERROR eError = PVRSRV_OK;
754     PVRSRV_ERROR eError2;
755     DEVMEM_HEAP *psHeap;
756     /* handle to the server-side counterpart of the device memory
757        heap (specifically, for handling mapping to device MMU */
758     IMG_HANDLE hDevMemServerHeap;
759
760     IMG_CHAR aszBuf[100];
761     IMG_CHAR *pszStr;
762
763     if (ppsHeapPtr == IMG_NULL)
764     {
765         eError = PVRSRV_ERROR_INVALID_PARAMS;
766         goto e0;
767     }
768
769     psHeap = OSAllocMem(sizeof *psHeap);
770     if (psHeap == IMG_NULL)
771     {
772         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
773         goto e0;
774     }
775
776     /* Need to keep local copy of heap name, so caller may free
777        theirs */
778     pszStr = OSAllocMem(OSStringLength(pszName)+1);
779     if (pszStr == IMG_NULL)
780     {
781                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
782         goto e1;
783     }
784     OSStringCopy(pszStr, pszName);
785     psHeap->pszName = pszStr;
786
787     psHeap->sBaseAddress = sBaseAddress;
788     psHeap->uiImportCount = 0;
789
790     OSSNPrintf(aszBuf, sizeof(aszBuf),
791                "NDM heap '%s' (suballocs) ctx:%p",
792                pszName, psCtx);
793     pszStr = OSAllocMem(OSStringLength(aszBuf)+1);
794     if (pszStr == IMG_NULL)
795     {
796                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
797         goto e2;
798     }
799     OSStringCopy(pszStr, aszBuf);
800     psHeap->pszSubAllocRAName = pszStr;
801
802     psHeap->psSubAllocRA = RA_Create(psHeap->pszSubAllocRAName,
803                        /* Subsequent imports: */
804                        ui32Log2Quantum,
805                                            RA_LOCKCLASS_2,
806                        _SubAllocImportAlloc,
807                        _SubAllocImportFree,
808                        (RA_PERARENA_HANDLE) psHeap);
809     if (psHeap->psSubAllocRA == IMG_NULL)
810     {
811         eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
812         goto e3;
813     }
814
815     psHeap->uiLog2Quantum = ui32Log2Quantum;
816
817     OSSNPrintf(aszBuf, sizeof(aszBuf),
818                "NDM heap '%s' (QVM) ctx:%p",
819                pszName, psCtx);
820     pszStr = OSAllocMem(OSStringLength(aszBuf)+1);
821     if (pszStr == IMG_NULL)
822     {
823                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
824         goto e4;
825     }
826     OSStringCopy(pszStr, aszBuf);
827     psHeap->pszQuantizedVMRAName = pszStr;
828
829     psHeap->psQuantizedVMRA = RA_Create(psHeap->pszQuantizedVMRAName,
830                        /* Subsequent import: */
831                                        0, RA_LOCKCLASS_1, IMG_NULL, IMG_NULL,
832                        (RA_PERARENA_HANDLE) psHeap);
833
834     if (psHeap->psQuantizedVMRA == IMG_NULL)
835     {
836         eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
837         goto e5;
838     }
839
840         if (!RA_Add(psHeap->psQuantizedVMRA,
841                        (RA_BASE_T)sBaseAddress.uiAddr,
842                        (RA_LENGTH_T)uiLength,
843                        (RA_FLAGS_T)0, /* This RA doesn't use or need flags */
844                                 IMG_NULL /* per ispan handle */))
845         {
846                 RA_Delete(psHeap->psQuantizedVMRA);
847         eError = PVRSRV_ERROR_DEVICEMEM_UNABLE_TO_CREATE_ARENA;
848         goto e5;
849         }
850
851
852     psHeap->psCtx = psCtx;
853
854
855     /* Create server-side counterpart of Device Memory heap */
856     eError = BridgeDevmemIntHeapCreate(psCtx->hBridge,
857                                       psCtx->hDevMemServerContext,
858                                       sBaseAddress,
859                                       uiLength,
860                                       ui32Log2Quantum,
861                                       &hDevMemServerHeap);
862     if (eError != PVRSRV_OK)
863     {
864         goto e6;
865     }
866     psHeap->hDevMemServerHeap = hDevMemServerHeap;
867
868         eError = OSLockCreate(&psHeap->hLock, LOCK_TYPE_PASSIVE);
869         if (eError != PVRSRV_OK)
870         {
871                 goto e7;
872         }
873
874     psHeap->psCtx->uiNumHeaps ++;
875     *ppsHeapPtr = psHeap;
876
877 #if defined PVRSRV_NEWDEVMEM_SUPPORT_MEM_TRACKING
878     psHeap->psMemDescList = IMG_NULL;
879 #endif  /* PVRSRV_NEWDEVMEM_SUPPORT_MEM_TRACKING */
880
881     return PVRSRV_OK;
882
883     /*
884       error exit paths
885     */
886  e7:
887     eError2 = BridgeDevmemIntHeapDestroy(psCtx->hBridge,
888                                        psHeap->hDevMemServerHeap);
889     PVR_ASSERT (eError2 == PVRSRV_OK);
890  e6:
891     RA_Delete(psHeap->psQuantizedVMRA);
892  e5:
893     OSFreeMem(psHeap->pszQuantizedVMRAName);
894  e4:
895     RA_Delete(psHeap->psSubAllocRA);
896  e3:
897     OSFreeMem(psHeap->pszSubAllocRAName);
898  e2:
899     OSFreeMem(psHeap->pszName);
900  e1:
901     OSFreeMem(psHeap);
902  e0:
903     PVR_ASSERT(eError != PVRSRV_OK);
904     return eError;
905 }
906
907 IMG_INTERNAL PVRSRV_ERROR
908 DevmemGetHeapBaseDevVAddr(struct _DEVMEM_HEAP_ *psHeap,
909                           IMG_DEV_VIRTADDR *pDevVAddr)
910 {
911         if (psHeap == IMG_NULL)
912         {
913                 return PVRSRV_ERROR_INVALID_PARAMS;
914         }
915
916         *pDevVAddr = psHeap->sBaseAddress;
917
918         return PVRSRV_OK;
919 }
920
921 IMG_INTERNAL IMG_VOID
922 DevmemExportalignAdjustSizeAndAlign(DEVMEM_HEAP *psHeap, IMG_DEVMEM_SIZE_T *puiSize, IMG_DEVMEM_ALIGN_T *puiAlign)
923 {
924         IMG_DEVMEM_SIZE_T uiSize = *puiSize;
925         IMG_DEVMEM_ALIGN_T uiAlign = *puiAlign;
926         IMG_UINT32 uiLog2Quantum;
927
928         if (psHeap)
929         {
930                 uiLog2Quantum = psHeap->uiLog2Quantum;
931         }
932         else
933         {
934                 uiLog2Quantum = GET_LOG2_PAGESIZE();
935         }
936
937     if ((1ULL << uiLog2Quantum) > uiAlign)
938     {
939                 uiAlign = 1ULL << uiLog2Quantum;
940     }
941     uiSize = (uiSize + uiAlign - 1) & ~(uiAlign - 1);
942
943         *puiSize = uiSize;
944         *puiAlign = uiAlign;
945 }
946
947
948 IMG_INTERNAL PVRSRV_ERROR
949 DevmemDestroyHeap(DEVMEM_HEAP *psHeap)
950 {
951     PVRSRV_ERROR eError;
952
953     if (psHeap == IMG_NULL)
954     {
955         return PVRSRV_ERROR_INVALID_PARAMS;
956     }
957
958     if (psHeap->uiImportCount > 0)
959     {
960         PVR_DPF((PVR_DBG_ERROR, "%d(%s) leaks remain", psHeap->uiImportCount, psHeap->pszName));
961         return PVRSRV_ERROR_DEVICEMEM_ALLOCATIONS_REMAIN_IN_HEAP;
962     }
963
964         OSLockDestroy(psHeap->hLock);
965
966     PVR_ASSERT(psHeap->psCtx->uiNumHeaps > 0);
967     psHeap->psCtx->uiNumHeaps --;
968
969     eError = BridgeDevmemIntHeapDestroy(psHeap->psCtx->hBridge,
970                                        psHeap->hDevMemServerHeap);
971     PVR_ASSERT (eError == PVRSRV_OK);
972
973     RA_Delete(psHeap->psQuantizedVMRA);
974     OSFreeMem(psHeap->pszQuantizedVMRAName);
975
976     RA_Delete(psHeap->psSubAllocRA);
977     OSFreeMem(psHeap->pszSubAllocRAName);
978
979     OSFreeMem(psHeap->pszName);
980
981     OSFreeMem(psHeap);
982
983     return PVRSRV_OK;
984 }
985
986 /*****************************************************************************
987  *                Devmem allocation/free functions                           *
988  *****************************************************************************/
989
990 IMG_INTERNAL PVRSRV_ERROR
991 DevmemAllocate(DEVMEM_HEAP *psHeap,
992                IMG_DEVMEM_SIZE_T uiSize,
993                IMG_DEVMEM_ALIGN_T uiAlign,
994                DEVMEM_FLAGS_T uiFlags,
995                const IMG_PCHAR pszText,
996                            DEVMEM_MEMDESC **ppsMemDescPtr)
997 {
998     IMG_BOOL bStatus; /* eError for RA */
999     RA_BASE_T uiAllocatedAddr;
1000     RA_LENGTH_T uiAllocatedSize;
1001     RA_PERISPAN_HANDLE hImport; /* the "import" from which this sub-allocation came */
1002     RA_FLAGS_T uiFlagsForRA;
1003     PVRSRV_ERROR eError;
1004     DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1005         IMG_DEVMEM_OFFSET_T uiOffset = 0;
1006         DEVMEM_IMPORT *psImport;
1007         IMG_VOID      *pvAddr;
1008
1009         if (uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
1010         {
1011                 /* Deferred Allocation not supported on SubAllocs*/
1012                 eError = PVRSRV_ERROR_INVALID_PARAMS;
1013                 goto failParams;
1014         }
1015
1016     if (psHeap == IMG_NULL || ppsMemDescPtr == IMG_NULL)
1017     {
1018         eError = PVRSRV_ERROR_INVALID_PARAMS;
1019         goto failParams;
1020     }
1021
1022         eError = _DevmemValidateParams(uiSize,
1023                                                                    uiAlign,
1024                                                                    uiFlags);
1025         if (eError != PVRSRV_OK)
1026         {
1027                 goto failParams;
1028         }
1029
1030         eError =_DevmemMemDescAlloc(&psMemDesc);
1031     if (eError != PVRSRV_OK)
1032     {
1033         goto failMemDescAlloc;
1034     }
1035
1036         /*
1037                 No request for exportable memory so use the RA
1038         */
1039     uiFlagsForRA = (RA_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK);
1040     /* Check that the cast didn't lose any flags due to different integer widths */
1041     PVR_ASSERT(uiFlagsForRA == (uiFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK));
1042
1043         /* 
1044            When the RA suballocates memory from a Span it does not zero it. It only zeroes the
1045            memory if it allocates a new Span; but we don't know what is going to happen for this
1046            RA_Alloc call. Therefore, we zero the mem after the allocation below.
1047         */
1048         uiFlagsForRA &= ~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
1049         
1050         bStatus = RA_Alloc(psHeap->psSubAllocRA,
1051                                            uiSize,
1052                                            uiFlagsForRA,
1053                                            uiAlign,
1054                                            &uiAllocatedAddr,
1055                                            &uiAllocatedSize,
1056                                            &hImport);
1057         if (!bStatus)
1058         {
1059                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1060                 goto failDeviceMemAlloc;
1061         }
1062
1063         psImport = hImport;
1064         uiOffset = uiAllocatedAddr - psImport->sDeviceImport.sDevVAddr.uiAddr;
1065
1066         _DevmemMemDescInit(psMemDesc,
1067                                            uiOffset,
1068                                            psImport);
1069
1070         /* zero the memory */
1071         if (uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
1072         {
1073                 eError = DevmemAcquireCpuVirtAddr(psMemDesc, &pvAddr);
1074                 if (eError != PVRSRV_OK)
1075                 {
1076                         goto failZero;
1077                 }
1078
1079                 
1080 #if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
1081                 PVR_ASSERT(uiSize<IMG_UINT32_MAX);
1082 #endif
1083
1084                 OSMemSet(pvAddr, 0x0, (IMG_SIZE_T) uiSize);
1085             
1086                 DevmemReleaseCpuVirtAddr(psMemDesc);
1087
1088 #if defined(PDUMP)
1089                 DevmemPDumpLoadZeroMem(psMemDesc, 0, uiSize, PDUMP_FLAGS_CONTINUOUS);
1090 #endif
1091         }
1092
1093
1094 #if defined(PVR_RI_DEBUG)
1095         {
1096                 /* Attach RI information */
1097                 eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
1098                                                                                         psMemDesc->psImport->hPMR,
1099                                                                                         OSStringNLength(pszText, RI_MAX_TEXT_LEN),
1100                                                                                         pszText,
1101                                                                                         psMemDesc->uiOffset,
1102                                                                                         uiAllocatedSize,
1103                                                                                         IMG_FALSE,
1104                                                                                         IMG_FALSE,
1105                                                                                         &(psMemDesc->hRIHandle));
1106                 if( eError != PVRSRV_OK)
1107                 {
1108                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
1109                 }
1110         }
1111 #else  /* if defined(PVR_RI_DEBUG) */
1112         PVR_UNREFERENCED_PARAMETER (pszText);
1113 #endif /* if defined(PVR_RI_DEBUG) */
1114
1115         *ppsMemDescPtr = psMemDesc;
1116
1117     return PVRSRV_OK;
1118
1119     /*
1120       error exit paths follow
1121     */
1122
1123 failZero:
1124         _DevmemMemDescRelease(psMemDesc);
1125         psMemDesc = IMG_NULL;   /* Make sure we don't do a discard after the release */
1126 failDeviceMemAlloc:
1127         if (psMemDesc)
1128                 _DevmemMemDescDiscard(psMemDesc);
1129 failMemDescAlloc:
1130 failParams:
1131     PVR_ASSERT(eError != PVRSRV_OK);
1132     return eError;
1133 }
1134
1135
1136
1137 IMG_INTERNAL PVRSRV_ERROR
1138 DevmemAllocateExportable(IMG_HANDLE hBridge,
1139                                                  IMG_HANDLE hDeviceNode,
1140                                                  IMG_DEVMEM_SIZE_T uiSize,
1141                                                  IMG_DEVMEM_ALIGN_T uiAlign,
1142                                                  DEVMEM_FLAGS_T uiFlags,
1143                                                  const IMG_PCHAR pszText,
1144                                                  DEVMEM_MEMDESC **ppsMemDescPtr)
1145 {
1146     PVRSRV_ERROR eError;
1147     DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1148         DEVMEM_IMPORT *psImport;
1149         IMG_BOOL bMappingTable = IMG_TRUE;
1150
1151
1152         DevmemExportalignAdjustSizeAndAlign(IMG_NULL,
1153                                                                                 &uiSize,
1154                                                                                 &uiAlign);
1155
1156         eError = _DevmemValidateParams(uiSize,
1157                                                                    uiAlign,
1158                                                                    uiFlags);
1159         if (eError != PVRSRV_OK)
1160         {
1161                 goto failParams;
1162         }
1163
1164
1165         eError =_DevmemMemDescAlloc(&psMemDesc);
1166     if (eError != PVRSRV_OK)
1167     {
1168         goto failMemDescAlloc;
1169     }
1170
1171         /*
1172                 Note:
1173                 In the case of exportable memory we have no heap to
1174                 query the pagesize from, so we assume host pagesize.
1175         */
1176         eError = _AllocateDeviceMemory(hBridge,
1177                                                                    hDeviceNode,
1178                                                                    GET_LOG2_PAGESIZE(),
1179                                                                    uiSize,
1180                                                                    uiSize,
1181                                                                    1,
1182                                                                    1,
1183                                                                    &bMappingTable,
1184                                                                    uiAlign,
1185                                                                    uiFlags,
1186                                                                    IMG_TRUE,
1187                                                                    &psImport);
1188         if (eError != PVRSRV_OK)
1189         {
1190                 goto failDeviceMemAlloc;
1191         }
1192
1193         _DevmemMemDescInit(psMemDesc,
1194                                            0,
1195                                            psImport);
1196
1197     *ppsMemDescPtr = psMemDesc;
1198
1199 #if defined(PVR_RI_DEBUG)
1200         {
1201                 eError = BridgeRIWritePMREntry (psImport->hBridge,
1202                                                                                 psImport->hPMR,
1203                                                                                 OSStringNLength(pszText, RI_MAX_TEXT_LEN),
1204                                                                                 (IMG_CHAR *)pszText,
1205                                                                                 psImport->uiSize);
1206                 if( eError != PVRSRV_OK)
1207                 {
1208                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
1209                 }
1210
1211                  /* Attach RI information */
1212                 eError = BridgeRIWriteMEMDESCEntry (psImport->hBridge,
1213                                                                                         psImport->hPMR,
1214                                                                                         sizeof("^"),
1215                                                                                         "^",
1216                                                                                         psMemDesc->uiOffset,
1217                                                                                         uiSize,
1218                                                                                         IMG_FALSE,
1219                                                                                         IMG_TRUE,
1220                                                                                         &psMemDesc->hRIHandle);
1221                 if( eError != PVRSRV_OK)
1222                 {
1223                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
1224                 }
1225         }
1226 #else  /* if defined(PVR_RI_DEBUG) */
1227         PVR_UNREFERENCED_PARAMETER (pszText);
1228 #endif /* if defined(PVR_RI_DEBUG) */
1229
1230     return PVRSRV_OK;
1231
1232     /*
1233       error exit paths follow
1234     */
1235
1236 failDeviceMemAlloc:
1237     _DevmemMemDescDiscard(psMemDesc);
1238
1239 failMemDescAlloc:
1240 failParams:
1241     PVR_ASSERT(eError != PVRSRV_OK);
1242     return eError;
1243 }
1244
1245 IMG_INTERNAL PVRSRV_ERROR
1246 DevmemAllocateSparse(IMG_HANDLE hBridge,
1247                                          IMG_HANDLE hDeviceNode,
1248                                          IMG_DEVMEM_SIZE_T uiSize,
1249                                          IMG_DEVMEM_SIZE_T uiChunkSize,
1250                                          IMG_UINT32 ui32NumPhysChunks,
1251                                          IMG_UINT32 ui32NumVirtChunks,
1252                                          IMG_BOOL *pabMappingTable,
1253                                          IMG_DEVMEM_ALIGN_T uiAlign,
1254                                          DEVMEM_FLAGS_T uiFlags,
1255                                          const IMG_PCHAR pszText,
1256                                          DEVMEM_MEMDESC **ppsMemDescPtr)
1257 {
1258     PVRSRV_ERROR eError;
1259     DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1260         DEVMEM_IMPORT *psImport;
1261
1262
1263         DevmemExportalignAdjustSizeAndAlign(IMG_NULL,
1264                                                                                 &uiSize,
1265                                                                                 &uiAlign);
1266
1267         eError = _DevmemValidateParams(uiSize,
1268                                                                    uiAlign,
1269                                                                    uiFlags);
1270         if (eError != PVRSRV_OK)
1271         {
1272                 goto failParams;
1273         }
1274
1275
1276         eError =_DevmemMemDescAlloc(&psMemDesc);
1277     if (eError != PVRSRV_OK)
1278     {
1279         goto failMemDescAlloc;
1280     }
1281
1282         /*
1283                 Note:
1284                 In the case of sparse memory we have no heap to
1285                 query the pagesize from, so we assume host pagesize.
1286         */
1287         eError = _AllocateDeviceMemory(hBridge,
1288                                                                    hDeviceNode,
1289                                                                    GET_LOG2_PAGESIZE(),
1290                                                                    uiSize,
1291                                                                    uiChunkSize,
1292                                                                    ui32NumPhysChunks,
1293                                                                    ui32NumVirtChunks,
1294                                                                    pabMappingTable,
1295                                                                    uiAlign,
1296                                                                    uiFlags,
1297                                                                    IMG_TRUE,
1298                                                                    &psImport);
1299         if (eError != PVRSRV_OK)
1300         {
1301                 goto failDeviceMemAlloc;
1302         }
1303
1304         _DevmemMemDescInit(psMemDesc,
1305                                            0,
1306                                            psImport);
1307
1308 #if defined(PVR_RI_DEBUG)
1309         {
1310                 eError = BridgeRIWritePMREntry (psImport->hBridge,
1311                                                                                 psImport->hPMR,
1312                                                                                 OSStringNLength(pszText, RI_MAX_TEXT_LEN),
1313                                                                                 (IMG_CHAR *)pszText,
1314                                                                                 psImport->uiSize);
1315                 if( eError != PVRSRV_OK)
1316                 {
1317                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWritePMREntry failed (eError=%d)", __func__, eError));
1318                 }
1319
1320                 /* Attach RI information */
1321         eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
1322                                                                                         psMemDesc->psImport->hPMR,
1323                                                                                         sizeof("^"),
1324                                                                                         "^",
1325                                                                                         psMemDesc->uiOffset,
1326                                                                                         uiSize,
1327                                                                                         IMG_FALSE,
1328                                                                                         IMG_TRUE,
1329                                                                                         &psMemDesc->hRIHandle);
1330                 if( eError != PVRSRV_OK)
1331                 {
1332                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
1333                 }
1334         }
1335 #else  /* if defined(PVR_RI_DEBUG) */
1336         PVR_UNREFERENCED_PARAMETER (pszText);
1337 #endif /* if defined(PVR_RI_DEBUG) */
1338
1339         *ppsMemDescPtr = psMemDesc;
1340
1341     return PVRSRV_OK;
1342
1343     /*
1344       error exit paths follow
1345     */
1346
1347 failDeviceMemAlloc:
1348     _DevmemMemDescDiscard(psMemDesc);
1349
1350 failMemDescAlloc:
1351 failParams:
1352     PVR_ASSERT(eError != PVRSRV_OK);
1353     return eError;
1354 }
1355
1356 /*****************************************************************************
1357  *                Devmem unsecure export functions                           *
1358  *****************************************************************************/
1359
1360 IMG_INTERNAL PVRSRV_ERROR
1361 DevmemExport(DEVMEM_MEMDESC *psMemDesc,
1362              DEVMEM_EXPORTCOOKIE *psExportCookie)
1363 {
1364     /* Caller to provide storage for export cookie struct */
1365     PVRSRV_ERROR eError;
1366     IMG_HANDLE hPMRExportHandle = 0;
1367     IMG_UINT64 uiPMRExportPassword = 0;
1368     IMG_DEVMEM_SIZE_T uiSize = 0;
1369     IMG_DEVMEM_LOG2ALIGN_T uiLog2Contig = 0;
1370
1371     if (psMemDesc == IMG_NULL || psExportCookie == IMG_NULL)
1372     {
1373         eError = PVRSRV_ERROR_INVALID_PARAMS;
1374         goto e0;
1375     }
1376
1377     eError = _Mapping_Export(psMemDesc->psImport,
1378                              &hPMRExportHandle,
1379                              &uiPMRExportPassword,
1380                              &uiSize,
1381                              &uiLog2Contig);
1382     if (eError != PVRSRV_OK)
1383     {
1384                 psExportCookie->uiSize = 0;
1385         goto e0;
1386     }
1387
1388     psExportCookie->hPMRExportHandle = hPMRExportHandle;
1389     psExportCookie->uiPMRExportPassword = uiPMRExportPassword;
1390     psExportCookie->uiSize = uiSize;
1391     psExportCookie->uiLog2ContiguityGuarantee = uiLog2Contig;
1392
1393     return PVRSRV_OK;
1394
1395     /*
1396       error exit paths follow
1397     */
1398
1399  e0:
1400     PVR_ASSERT(eError != PVRSRV_OK);
1401     return eError;
1402 }
1403
1404 IMG_INTERNAL PVRSRV_ERROR
1405 DevmemMakeServerExportClientExport(DEVMEM_BRIDGE_HANDLE hBridge,
1406                                    DEVMEM_SERVER_EXPORTCOOKIE hServerExportCookie,
1407                                    DEVMEM_EXPORTCOOKIE *psExportCookie)
1408 {
1409         DEVMEM_EXPORTHANDLE hPMRExportHandle;
1410         IMG_DEVMEM_SIZE_T uiPMRSize;
1411         IMG_DEVMEM_LOG2ALIGN_T uiPMRLog2Contig;
1412         DEVMEM_EXPORTKEY uiPMRExportKey;
1413         PVRSRV_ERROR eError = PVRSRV_OK;
1414
1415         eError = BridgePMRMakeServerExportClientExport(hBridge,
1416                                                                                                         hServerExportCookie,
1417                                                                                                         &hPMRExportHandle,
1418                                                                                                         &uiPMRSize,
1419                                                                                                         &uiPMRLog2Contig,
1420                                                                                                         &uiPMRExportKey);
1421
1422         if (eError == PVRSRV_OK)
1423         {
1424                 psExportCookie->hPMRExportHandle = hPMRExportHandle;
1425                 psExportCookie->uiPMRExportPassword = uiPMRExportKey;
1426                 psExportCookie->uiSize = uiPMRSize;
1427                 psExportCookie->uiLog2ContiguityGuarantee = uiPMRLog2Contig;
1428         }
1429
1430         return eError;
1431 }
1432
1433 IMG_INTERNAL PVRSRV_ERROR
1434 DevmemUnmakeServerExportClientExport(DEVMEM_BRIDGE_HANDLE hBridge,
1435                                    DEVMEM_EXPORTCOOKIE *psExportCookie)
1436 {
1437         return BridgePMRUnmakeServerExportClientExport(hBridge, psExportCookie->hPMRExportHandle);
1438 }
1439
1440 IMG_INTERNAL IMG_BOOL
1441 DevmemIsValidExportCookie(DEVMEM_EXPORTCOOKIE *psExportCookie)
1442 {
1443         /* Assume that if the size is set, the export cookie is used */
1444         return (psExportCookie->uiSize != 0x0);
1445 }
1446
1447 IMG_INTERNAL IMG_VOID
1448 DevmemUnexport(DEVMEM_MEMDESC *psMemDesc,
1449                DEVMEM_EXPORTCOOKIE *psExportCookie)
1450 {
1451     _Mapping_Unexport(psMemDesc->psImport,
1452                       psExportCookie->hPMRExportHandle);
1453
1454     psExportCookie->uiSize = 0;
1455 }
1456
1457 IMG_INTERNAL PVRSRV_ERROR
1458 DevmemImport(IMG_HANDLE hBridge,
1459                          DEVMEM_EXPORTCOOKIE *psCookie,
1460                          DEVMEM_FLAGS_T uiFlags,
1461                          DEVMEM_MEMDESC **ppsMemDescPtr)
1462 {
1463     DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1464     DEVMEM_IMPORT *psImport;
1465     IMG_HANDLE hPMR;
1466     PVRSRV_ERROR eError;
1467
1468         if (ppsMemDescPtr == IMG_NULL)
1469     {
1470         eError = PVRSRV_ERROR_INVALID_PARAMS;
1471         goto failParams;
1472     }
1473
1474         eError =_DevmemMemDescAlloc(&psMemDesc);
1475     if (eError != PVRSRV_OK)
1476     {
1477         goto failMemDescAlloc;
1478     }
1479
1480         eError = _DevmemImportStructAlloc(hBridge,
1481                                                                           IMG_TRUE,
1482                                                                           &psImport);
1483     if (eError != PVRSRV_OK)
1484     {
1485         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1486         goto failImportAlloc;
1487     }
1488
1489
1490     /* Get a handle to the PMR (inc refcount, checks authorization) */
1491     eError = BridgePMRImportPMR(hBridge,
1492                                 psCookie->hPMRExportHandle,
1493                                 psCookie->uiPMRExportPassword,
1494                                 psCookie->uiSize, /* not trusted - just for sanity checks */
1495                                 psCookie->uiLog2ContiguityGuarantee, /* not trusted - just for sanity checks */
1496                                 &hPMR);
1497     if (eError != PVRSRV_OK)
1498     {
1499         goto failImport;
1500     }
1501
1502         _DevmemImportStructInit(psImport,
1503                                                         psCookie->uiSize,
1504                                                         1ULL << psCookie->uiLog2ContiguityGuarantee,
1505                                                         uiFlags,
1506                                                         hPMR);
1507
1508         _DevmemMemDescInit(psMemDesc,
1509                                            0,
1510                                            psImport);
1511
1512     *ppsMemDescPtr = psMemDesc;
1513
1514 #if defined(PVR_RI_DEBUG)
1515         {
1516                 /* Attach RI information */
1517                 eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
1518                                                                                         psMemDesc->psImport->hPMR,
1519                                                                                         sizeof("^"),
1520                                                                                         "^",
1521                                                                                         psMemDesc->uiOffset,
1522                                                                                         psMemDesc->psImport->uiSize,
1523                                                                                         IMG_TRUE,
1524                                                                                         IMG_FALSE,
1525                                                                                         &psMemDesc->hRIHandle);
1526                 if( eError != PVRSRV_OK)
1527                 {
1528                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
1529                 }
1530         }
1531 #endif /* if defined(PVR_RI_DEBUG) */
1532
1533         return PVRSRV_OK;
1534
1535     /*
1536       error exit paths follow
1537     */
1538
1539 failImport:
1540     _DevmemImportDiscard(psImport);
1541 failImportAlloc:
1542     _DevmemMemDescDiscard(psMemDesc);
1543 failMemDescAlloc:
1544 failParams:
1545     PVR_ASSERT(eError != PVRSRV_OK);
1546
1547     return eError;
1548 }
1549
1550 /*****************************************************************************
1551  *                   Common MemDesc functions                                *
1552  *****************************************************************************/
1553
1554 /*
1555         This function is called for freeing any class of memory
1556 */
1557 IMG_INTERNAL IMG_VOID
1558 DevmemFree(DEVMEM_MEMDESC *psMemDesc)
1559 {
1560 #if defined(PVR_RI_DEBUG)
1561         if (psMemDesc->hRIHandle)
1562         {
1563             PVRSRV_ERROR eError;
1564
1565             eError = BridgeRIDeleteMEMDESCEntry(psMemDesc->psImport->hBridge,
1566                                                                    psMemDesc->hRIHandle);
1567                 if( eError != PVRSRV_OK)
1568                 {
1569                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIDeleteMEMDESCEntry failed (eError=%d)", __func__, eError));
1570                 }
1571         }
1572 #endif  /* if defined(PVR_RI_DEBUG) */
1573         _DevmemMemDescRelease(psMemDesc);
1574 }
1575
1576 IMG_INTERNAL PVRSRV_ERROR
1577 DevmemMapToDevice(DEVMEM_MEMDESC *psMemDesc,
1578                                   DEVMEM_HEAP *psHeap,
1579                                   IMG_DEV_VIRTADDR *psDevVirtAddr)
1580 {
1581         DEVMEM_IMPORT *psImport;
1582         IMG_DEV_VIRTADDR sDevVAddr;
1583         PVRSRV_ERROR eError;
1584         IMG_BOOL bMap = IMG_TRUE;
1585
1586         OSLockAcquire(psMemDesc->sDeviceMemDesc.hLock);
1587         if (psHeap == IMG_NULL)
1588         {
1589                 eError = PVRSRV_ERROR_INVALID_PARAMS;
1590                 goto failParams;
1591         }
1592
1593         if (psMemDesc->sDeviceMemDesc.ui32RefCount != 0)
1594         {
1595                 eError = PVRSRV_ERROR_DEVICEMEM_ALREADY_MAPPED;
1596                 goto failCheck;
1597         }
1598
1599         /* Don't map memory for deferred allocations */
1600         if (psMemDesc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC)
1601         {
1602                 PVR_ASSERT(psMemDesc->psImport->bExportable);
1603                 bMap = IMG_FALSE;
1604         }
1605
1606         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1607                                         __FUNCTION__,
1608                                         psMemDesc,
1609                                         psMemDesc->sDeviceMemDesc.ui32RefCount,
1610                                         psMemDesc->sDeviceMemDesc.ui32RefCount+1);
1611
1612         psImport = psMemDesc->psImport;
1613         _DevmemMemDescAcquire(psMemDesc);
1614
1615         eError = _DevmemImportStructDevMap(psHeap,
1616                                                                            bMap,
1617                                                                            psImport);
1618         if (eError != PVRSRV_OK)
1619         {
1620                 goto failMap;
1621         }
1622
1623         sDevVAddr.uiAddr = psImport->sDeviceImport.sDevVAddr.uiAddr;
1624         sDevVAddr.uiAddr += psMemDesc->uiOffset;
1625         psMemDesc->sDeviceMemDesc.sDevVAddr = sDevVAddr;
1626         psMemDesc->sDeviceMemDesc.ui32RefCount++;
1627
1628     *psDevVirtAddr = psMemDesc->sDeviceMemDesc.sDevVAddr;
1629
1630     OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1631
1632 #if defined(PVR_RI_DEBUG)
1633         if (psMemDesc->hRIHandle)
1634     {
1635                  eError = BridgeRIUpdateMEMDESCAddr(psImport->hBridge,
1636                                                                            psMemDesc->hRIHandle,
1637                                                                            psImport->sDeviceImport.sDevVAddr);
1638                 if( eError != PVRSRV_OK)
1639                 {
1640                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIUpdateMEMDESCAddr failed (eError=%d)", __func__, eError));
1641                 }
1642         }
1643 #endif
1644
1645     return PVRSRV_OK;
1646
1647 failMap:
1648         _DevmemMemDescRelease(psMemDesc);
1649 failCheck:
1650 failParams:
1651         OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1652         PVR_ASSERT(eError != PVRSRV_OK);
1653
1654         return eError;
1655 }
1656
1657 IMG_INTERNAL PVRSRV_ERROR
1658 DevmemAcquireDevVirtAddr(DEVMEM_MEMDESC *psMemDesc,
1659                          IMG_DEV_VIRTADDR *psDevVirtAddr)
1660 {
1661         PVRSRV_ERROR eError;
1662
1663         OSLockAcquire(psMemDesc->sDeviceMemDesc.hLock);
1664         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1665                                         __FUNCTION__,
1666                                         psMemDesc,
1667                                         psMemDesc->sDeviceMemDesc.ui32RefCount,
1668                                         psMemDesc->sDeviceMemDesc.ui32RefCount+1);
1669
1670         if (psMemDesc->sDeviceMemDesc.ui32RefCount == 0)
1671         {
1672                 eError = PVRSRV_ERROR_DEVICEMEM_NO_MAPPING;
1673                 goto failCheck;
1674         }
1675         psMemDesc->sDeviceMemDesc.ui32RefCount++;
1676
1677     *psDevVirtAddr = psMemDesc->sDeviceMemDesc.sDevVAddr;
1678         OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1679
1680     return PVRSRV_OK;
1681
1682 failCheck:
1683         OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1684         PVR_ASSERT(eError != PVRSRV_OK);
1685
1686         return eError;
1687 }
1688
1689 IMG_INTERNAL IMG_VOID
1690 DevmemReleaseDevVirtAddr(DEVMEM_MEMDESC *psMemDesc)
1691 {
1692         PVR_ASSERT(psMemDesc != IMG_NULL);
1693
1694         OSLockAcquire(psMemDesc->sDeviceMemDesc.hLock);
1695         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1696                                         __FUNCTION__,
1697                                         psMemDesc,
1698                                         psMemDesc->sDeviceMemDesc.ui32RefCount,
1699                                         psMemDesc->sDeviceMemDesc.ui32RefCount-1);
1700
1701         PVR_ASSERT(psMemDesc->sDeviceMemDesc.ui32RefCount != 0);
1702
1703         if (--psMemDesc->sDeviceMemDesc.ui32RefCount == 0)
1704         {
1705                 _DevmemImportStructDevUnmap(psMemDesc->psImport);
1706                 OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1707
1708                 _DevmemMemDescRelease(psMemDesc);
1709         }
1710         else
1711         {
1712                 OSLockRelease(psMemDesc->sDeviceMemDesc.hLock);
1713         }
1714 }
1715
1716 IMG_INTERNAL PVRSRV_ERROR
1717 DevmemAcquireCpuVirtAddr(DEVMEM_MEMDESC *psMemDesc,
1718                          IMG_VOID **ppvCpuVirtAddr)
1719 {
1720         PVRSRV_ERROR eError;
1721
1722         OSLockAcquire(psMemDesc->sCPUMemDesc.hLock);
1723         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1724                                         __FUNCTION__,
1725                                         psMemDesc,
1726                                         psMemDesc->sCPUMemDesc.ui32RefCount,
1727                                         psMemDesc->sCPUMemDesc.ui32RefCount+1);
1728
1729         if (psMemDesc->sCPUMemDesc.ui32RefCount++ == 0)
1730         {
1731                 DEVMEM_IMPORT *psImport = psMemDesc->psImport;
1732                 IMG_UINT8 *pui8CPUVAddr;
1733
1734                 _DevmemMemDescAcquire(psMemDesc);
1735                 eError = _DevmemImportStructCPUMap(psImport);
1736                 if (eError != PVRSRV_OK)
1737                 {
1738                         goto failMap;
1739                 }
1740
1741                 pui8CPUVAddr = psImport->sCPUImport.pvCPUVAddr;
1742                 pui8CPUVAddr += psMemDesc->uiOffset;
1743                 psMemDesc->sCPUMemDesc.pvCPUVAddr = pui8CPUVAddr;
1744         }
1745     *ppvCpuVirtAddr = psMemDesc->sCPUMemDesc.pvCPUVAddr;
1746
1747     VG_MARK_INITIALIZED(*ppvCpuVirtAddr, psMemDesc->psImport->uiSize);
1748
1749     OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
1750
1751     return PVRSRV_OK;
1752
1753 failMap:
1754         PVR_ASSERT(eError != PVRSRV_OK);
1755         psMemDesc->sCPUMemDesc.ui32RefCount--;
1756         _DevmemMemDescRelease(psMemDesc);
1757         OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
1758
1759         return eError;
1760 }
1761
1762 IMG_INTERNAL IMG_VOID
1763 DevmemReleaseCpuVirtAddr(DEVMEM_MEMDESC *psMemDesc)
1764 {
1765         PVR_ASSERT(psMemDesc != IMG_NULL);
1766
1767         OSLockAcquire(psMemDesc->sCPUMemDesc.hLock);
1768         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
1769                                         __FUNCTION__,
1770                                         psMemDesc,
1771                                         psMemDesc->sCPUMemDesc.ui32RefCount,
1772                                         psMemDesc->sCPUMemDesc.ui32RefCount-1);
1773
1774         PVR_ASSERT(psMemDesc->sCPUMemDesc.ui32RefCount != 0);
1775
1776         if (--psMemDesc->sCPUMemDesc.ui32RefCount == 0)
1777         {
1778                 OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
1779                 _DevmemImportStructCPUUnmap(psMemDesc->psImport);
1780                 _DevmemMemDescRelease(psMemDesc);
1781         }
1782         else
1783         {
1784                 OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
1785         }
1786 }
1787
1788 IMG_INTERNAL PVRSRV_ERROR
1789 DevmemGetImportUID(DEVMEM_MEMDESC *psMemDesc,
1790                                                    IMG_UINT64 *pui64UID)
1791 {
1792         DEVMEM_IMPORT *psImport = psMemDesc->psImport;
1793         PVRSRV_ERROR eError;
1794
1795         eError = BridgePMRGetUID(psImport->hBridge,
1796                                                          psImport->hPMR,
1797                                                          pui64UID);
1798
1799         return eError;
1800 }
1801
1802 IMG_INTERNAL PVRSRV_ERROR
1803 DevmemGetReservation(DEVMEM_MEMDESC *psMemDesc,
1804                                 IMG_HANDLE *hReservation)
1805 {
1806         DEVMEM_IMPORT *psImport;
1807
1808         PVR_ASSERT(psMemDesc);
1809         psImport = psMemDesc->psImport;
1810
1811         PVR_ASSERT(psImport);
1812         *hReservation = psImport->sDeviceImport.hReservation;
1813
1814         return PVRSRV_OK;
1815 }
1816
1817 PVRSRV_ERROR
1818 DevmemGetPMRData(DEVMEM_MEMDESC *psMemDesc,
1819                 IMG_HANDLE *phPMR,
1820                 IMG_DEVMEM_OFFSET_T *puiPMROffset)
1821 {
1822         DEVMEM_IMPORT *psImport;
1823
1824         PVR_ASSERT(psMemDesc);
1825         *puiPMROffset = psMemDesc->uiOffset;
1826         psImport = psMemDesc->psImport;
1827
1828         PVR_ASSERT(psImport);
1829         *phPMR = psImport->hPMR;
1830
1831         return PVRSRV_OK;
1832 }
1833
1834 IMG_INTERNAL PVRSRV_ERROR
1835 DevmemGetFlags(DEVMEM_MEMDESC *psMemDesc,
1836                                 DEVMEM_FLAGS_T *puiFlags)
1837 {
1838         DEVMEM_IMPORT *psImport;
1839
1840         PVR_ASSERT(psMemDesc);
1841         psImport = psMemDesc->psImport;
1842
1843         PVR_ASSERT(psImport);
1844         *puiFlags = psImport->uiFlags;
1845
1846         return PVRSRV_OK;
1847 }
1848
1849 IMG_INTERNAL PVRSRV_ERROR
1850 DevmemLocalImport(IMG_HANDLE hBridge,
1851                                   IMG_HANDLE hExtHandle,
1852                                   DEVMEM_FLAGS_T uiFlags,
1853                                   DEVMEM_MEMDESC **ppsMemDescPtr,
1854                                   IMG_DEVMEM_SIZE_T *puiSizePtr)
1855 {
1856     DEVMEM_MEMDESC *psMemDesc = IMG_NULL;
1857     DEVMEM_IMPORT *psImport;
1858     IMG_DEVMEM_SIZE_T uiSize;
1859     IMG_DEVMEM_ALIGN_T uiAlign;
1860     IMG_HANDLE hPMR;
1861     PVRSRV_ERROR eError;
1862
1863     if (ppsMemDescPtr == IMG_NULL)
1864     {
1865         eError = PVRSRV_ERROR_INVALID_PARAMS;
1866         goto failParams;
1867     }   
1868
1869         eError =_DevmemMemDescAlloc(&psMemDesc);
1870     if (eError != PVRSRV_OK)
1871     {
1872         goto failMemDescAlloc;
1873     }
1874
1875         eError = _DevmemImportStructAlloc(hBridge,
1876                                                                           IMG_TRUE,
1877                                                                           &psImport);
1878     if (eError != PVRSRV_OK)
1879     {
1880         eError = PVRSRV_ERROR_OUT_OF_MEMORY;
1881         goto failImportAlloc;
1882     }
1883
1884         /* Get the PMR handle and it's size from the server */
1885         eError = BridgePMRLocalImportPMR(hBridge,
1886                                                                          hExtHandle,
1887                                                                          &hPMR,
1888                                                                          &uiSize,
1889                                                                          &uiAlign);
1890         if (eError != PVRSRV_OK)
1891         {
1892                 goto failImport;
1893         }
1894
1895         _DevmemImportStructInit(psImport,
1896                                                         uiSize,
1897                                                         uiAlign,
1898                                                         uiFlags,
1899                                                         hPMR);
1900
1901         _DevmemMemDescInit(psMemDesc,
1902                                            0,
1903                                            psImport);
1904
1905     *ppsMemDescPtr = psMemDesc;
1906         if (puiSizePtr)
1907                 *puiSizePtr = uiSize;
1908
1909 #if defined(PVR_RI_DEBUG)
1910         {
1911                 /* Attach RI information */
1912                 eError = BridgeRIWriteMEMDESCEntry (psMemDesc->psImport->hBridge,
1913                                                                                         psMemDesc->psImport->hPMR,
1914                                                                                         sizeof("^"),
1915                                                                                         "^",
1916                                                                                         psMemDesc->uiOffset,
1917                                                                                         psMemDesc->psImport->uiSize,
1918                                                                                         IMG_TRUE,
1919                                                                                         IMG_FALSE,
1920                                                                                         &(psMemDesc->hRIHandle));
1921                 if( eError != PVRSRV_OK)
1922                 {
1923                         PVR_DPF((PVR_DBG_ERROR, "%s: call to BridgeRIWriteMEMDESCEntry failed (eError=%d)", __func__, eError));
1924                 }
1925         }
1926 #endif /* if defined(PVR_RI_DEBUG) */
1927         return PVRSRV_OK;
1928
1929 failImport:
1930     _DevmemImportDiscard(psImport);
1931 failImportAlloc:
1932         _DevmemMemDescDiscard(psMemDesc);
1933 failMemDescAlloc:
1934 failParams:
1935         PVR_ASSERT(eError != PVRSRV_OK);
1936
1937         return eError;
1938 }
1939