RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / services / shared / common / devicemem_utils.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          Device Memory Management internal utility functions
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    Utility functions used internally by device memory management
6                 code.
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 "allocmem.h"
46 #include "img_types.h"
47 #include "pvrsrv_error.h"
48 #include "ra.h"
49 #include "devicemem_utils.h"
50 #include "client_mm_bridge.h"
51
52 #if !defined(__KERNEL__) && defined(SUPPORT_ION)
53 #include <sys/mman.h>
54 #endif
55
56 /*
57         The Devmem import structure is the structure we use
58         to manage memory that is "imported" (which is page
59         granular) from the server into our process, this
60         includes allocations.
61
62         This allows memory to be imported without requiring
63         any CPU or device mapping. Memory can then be mapped
64         into the device or CPU on demand, but neither is
65         required.
66 */
67
68 IMG_INTERNAL
69 IMG_VOID _DevmemImportStructAcquire(DEVMEM_IMPORT *psImport)
70 {
71         IMG_INT iRefCount = OSAtomicIncrement(&psImport->hRefCount);
72         PVR_UNREFERENCED_PARAMETER(iRefCount);
73         PVR_ASSERT(iRefCount != 1);
74
75         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
76                                         __FUNCTION__,
77                                         psImport,
78                                         iRefCount-1,
79                                         iRefCount);
80 }
81
82 IMG_INTERNAL
83 IMG_VOID _DevmemImportStructRelease(DEVMEM_IMPORT *psImport)
84 {
85         IMG_INT iRefCount = OSAtomicDecrement(&psImport->hRefCount);
86         PVR_ASSERT(iRefCount >= 0);
87
88         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
89                                         __FUNCTION__,
90                                         psImport,
91                                         iRefCount+1,
92                                         iRefCount);
93
94         if (iRefCount == 0)
95         {
96                 BridgePMRUnrefPMR(psImport->hBridge,
97                                                   psImport->hPMR);
98                 OSLockDestroy(psImport->sCPUImport.hLock);
99                 OSLockDestroy(psImport->sDeviceImport.hLock);
100                 OSLockDestroy(psImport->hLock);
101                 OSFreeMem(psImport);
102         }
103 }
104
105 IMG_INTERNAL
106 IMG_VOID _DevmemImportDiscard(DEVMEM_IMPORT *psImport)
107 {
108         PVR_ASSERT(OSAtomicRead(&psImport->hRefCount) == 0);
109         OSLockDestroy(psImport->sCPUImport.hLock);
110         OSLockDestroy(psImport->sDeviceImport.hLock);
111         OSLockDestroy(psImport->hLock);
112         OSFreeMem(psImport);
113 }
114
115 IMG_INTERNAL
116 PVRSRV_ERROR _DevmemMemDescAlloc(DEVMEM_MEMDESC **ppsMemDesc)
117 {
118         DEVMEM_MEMDESC *psMemDesc;
119         PVRSRV_ERROR eError;
120
121         psMemDesc = OSAllocMem(sizeof(DEVMEM_MEMDESC));
122
123         if (psMemDesc == IMG_NULL)
124         {
125                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
126                 goto failAlloc;
127         }
128         
129         /* Structure must be zero'd incase it needs to be freed before it is initialised! */
130         OSCachedMemSet(psMemDesc, 0, sizeof(DEVMEM_MEMDESC));
131
132         eError = OSLockCreate(&psMemDesc->hLock, LOCK_TYPE_PASSIVE);
133         if (eError != PVRSRV_OK)
134         {
135                 goto failMDLock;
136         }
137
138         eError = OSLockCreate(&psMemDesc->sDeviceMemDesc.hLock, LOCK_TYPE_PASSIVE);
139         if (eError != PVRSRV_OK)
140         {
141                 goto failDMDLock;
142         }
143
144         eError = OSLockCreate(&psMemDesc->sCPUMemDesc.hLock, LOCK_TYPE_PASSIVE);
145         if (eError != PVRSRV_OK)
146         {
147                 goto failCMDLock;
148         }
149
150         *ppsMemDesc = psMemDesc;
151
152         return PVRSRV_OK;
153
154 failCMDLock:
155         OSLockDestroy(psMemDesc->sDeviceMemDesc.hLock);
156 failDMDLock:
157         OSLockDestroy(psMemDesc->hLock);
158 failMDLock:
159         OSFreeMem(psMemDesc);
160 failAlloc:
161         PVR_ASSERT(eError != PVRSRV_OK);
162
163         return eError;
164 }
165
166 /*
167         Init the MemDesc structure
168 */
169 IMG_INTERNAL
170 IMG_VOID _DevmemMemDescInit(DEVMEM_MEMDESC *psMemDesc,
171                                                                                   IMG_DEVMEM_OFFSET_T uiOffset,
172                                                                                   DEVMEM_IMPORT *psImport)
173 {
174         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
175                                         __FUNCTION__,
176                                         psMemDesc,
177                                         0,
178                                         1);
179
180         psMemDesc->psImport = psImport;
181         psMemDesc->uiOffset = uiOffset;
182
183         psMemDesc->sDeviceMemDesc.ui32RefCount = 0;
184         psMemDesc->sCPUMemDesc.ui32RefCount = 0;
185         OSAtomicWrite(&psMemDesc->hRefCount, 1);
186 }
187
188 IMG_INTERNAL
189 IMG_VOID _DevmemMemDescAcquire(DEVMEM_MEMDESC *psMemDesc)
190 {
191         IMG_INT iRefCount;
192         PVR_UNREFERENCED_PARAMETER(iRefCount);
193
194         iRefCount = OSAtomicIncrement(&psMemDesc->hRefCount);
195         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
196                                         __FUNCTION__,
197                                         psMemDesc,
198                                         iRefCount-1,
199                                         iRefCount);
200 }
201
202 IMG_INTERNAL
203 IMG_VOID _DevmemMemDescRelease(DEVMEM_MEMDESC *psMemDesc)
204 {
205         IMG_INT iRefCount;
206         PVR_ASSERT(psMemDesc != NULL);
207         
208         iRefCount = OSAtomicDecrement(&psMemDesc->hRefCount);
209         PVR_ASSERT(iRefCount >= 0);
210
211         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
212                                         __FUNCTION__,
213                                         psMemDesc,
214                                         iRefCount+1,
215                                         iRefCount);
216
217         if (iRefCount == 0)
218         {
219                 if (!psMemDesc->psImport->bExportable)
220                 {
221                         RA_Free(psMemDesc->psImport->sDeviceImport.psHeap->psSubAllocRA,
222                                         psMemDesc->psImport->sDeviceImport.sDevVAddr.uiAddr +
223                                         psMemDesc->uiOffset);
224                 }
225                 else
226                 {
227                         _DevmemImportStructRelease(psMemDesc->psImport);
228                 }
229
230                 OSLockDestroy(psMemDesc->sCPUMemDesc.hLock);
231                 OSLockDestroy(psMemDesc->sDeviceMemDesc.hLock);
232                 OSLockDestroy(psMemDesc->hLock);
233                 OSFreeMem(psMemDesc);
234         }
235 }
236
237 IMG_INTERNAL
238 IMG_VOID _DevmemMemDescDiscard(DEVMEM_MEMDESC *psMemDesc)
239 {
240         PVR_ASSERT(OSAtomicRead(&psMemDesc->hRefCount) == 0);
241
242         OSLockDestroy(psMemDesc->sCPUMemDesc.hLock);
243         OSLockDestroy(psMemDesc->sDeviceMemDesc.hLock);
244         OSLockDestroy(psMemDesc->hLock);
245         OSFreeMem(psMemDesc);
246 }
247
248
249 IMG_INTERNAL
250 PVRSRV_ERROR _DevmemValidateParams(IMG_DEVMEM_SIZE_T uiSize,
251                                                                    IMG_DEVMEM_ALIGN_T uiAlign,
252                                                                    DEVMEM_FLAGS_T uiFlags)
253 {
254     if (!(uiFlags & PVRSRV_MEMALLOCFLAG_GPU_READABLE))
255     {
256         /* Don't support memory not GPU readable currently */
257         return PVRSRV_ERROR_INVALID_PARAMS;
258     }
259
260     if ((uiFlags & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &&
261         (uiFlags & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
262     {
263         /* Zero on Alloc and Poison on Alloc are mutually exclusive */
264         return PVRSRV_ERROR_INVALID_PARAMS;
265     }
266
267     if (uiAlign & (uiAlign-1))
268     {
269         return PVRSRV_ERROR_INVALID_PARAMS;
270     }
271
272     /* Verify that size is a positive integer multiple of alignment */
273 #if 0 // FIXME
274     if (uiSize & (uiAlign-1))
275     {
276         /* Size not a multiple of alignment */
277         return PVRSRV_ERROR_INVALID_PARAMS;
278     }
279 #endif
280     if (uiSize == 0)
281     {
282         return PVRSRV_ERROR_INVALID_PARAMS;
283     }
284
285     return PVRSRV_OK;
286 }
287
288 /*
289         Allocate and init an import structure
290 */
291 IMG_INTERNAL
292 PVRSRV_ERROR _DevmemImportStructAlloc(IMG_HANDLE hBridge,
293                                                                           IMG_BOOL bExportable,
294                                                                           DEVMEM_IMPORT **ppsImport)
295 {
296         DEVMEM_IMPORT *psImport;
297         PVRSRV_ERROR eError;
298
299     psImport = OSAllocMem(sizeof *psImport);
300     if (psImport == IMG_NULL)
301     {
302         return PVRSRV_ERROR_OUT_OF_MEMORY;
303     }
304
305         /* Setup some known bad values for things we don't have yet */
306         psImport->sDeviceImport.hReservation = LACK_OF_RESERVATION_POISON;
307     psImport->sDeviceImport.hMapping = LACK_OF_MAPPING_POISON;
308     psImport->sDeviceImport.psHeap = IMG_NULL;
309     psImport->sDeviceImport.bMapped = IMG_FALSE;
310
311         eError = OSLockCreate(&psImport->sDeviceImport.hLock, LOCK_TYPE_PASSIVE);
312         if (eError != PVRSRV_OK)
313         {
314                 goto failDIOSLockCreate;
315         }
316
317         psImport->sCPUImport.hOSMMapData = IMG_NULL;
318         psImport->sCPUImport.pvCPUVAddr = IMG_NULL;
319
320         eError = OSLockCreate(&psImport->sCPUImport.hLock, LOCK_TYPE_PASSIVE);
321         if (eError != PVRSRV_OK)
322         {
323                 goto failCIOSLockCreate;
324         }
325
326         /* Set up common elements */
327     psImport->hBridge = hBridge;
328     psImport->bExportable = bExportable;
329
330         /* Setup refcounts */
331     psImport->sDeviceImport.ui32RefCount = 0;
332     psImport->sCPUImport.ui32RefCount = 0;
333     OSAtomicWrite(&psImport->hRefCount, 0);
334
335         /* Create the lock */
336         eError = OSLockCreate(&psImport->hLock, LOCK_TYPE_PASSIVE);
337         if (eError != PVRSRV_OK)
338         {
339                 goto failILockAlloc;
340         }
341
342 #if !defined(__KERNEL__) && defined(SUPPORT_ION)
343         psImport->sCPUImport.iDmaBufFd = -1;
344 #endif
345
346     *ppsImport = psImport;
347     
348     return PVRSRV_OK;
349
350 failILockAlloc:
351         OSLockDestroy(psImport->sCPUImport.hLock);
352 failCIOSLockCreate:
353         OSLockDestroy(psImport->sDeviceImport.hLock);
354 failDIOSLockCreate:
355         OSFreeMem(psImport);
356         PVR_ASSERT(eError != PVRSRV_OK);
357
358         return eError;
359 }
360
361 /*
362         Initialise the import structure
363 */
364 IMG_INTERNAL
365 IMG_VOID _DevmemImportStructInit(DEVMEM_IMPORT *psImport,
366                                                                  IMG_DEVMEM_SIZE_T uiSize,
367                                                                  IMG_DEVMEM_ALIGN_T uiAlign,
368                                                                  DEVMEM_FLAGS_T uiFlags,
369                                                                  IMG_HANDLE hPMR)
370 {
371         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
372                                         __FUNCTION__,
373                                         psImport,
374                                         0,
375                                         1);
376
377         psImport->uiSize = uiSize;
378         psImport->uiAlign = uiAlign;
379         psImport->uiFlags = uiFlags;
380         psImport->hPMR = hPMR;
381         OSAtomicWrite(&psImport->hRefCount, 1);
382 }
383
384 /*
385         Map an import to the device
386 */
387 IMG_INTERNAL
388 PVRSRV_ERROR _DevmemImportStructDevMap(DEVMEM_HEAP *psHeap,
389                                                                            IMG_BOOL bMap,
390                                                                            DEVMEM_IMPORT *psImport)
391 {
392         DEVMEM_DEVICE_IMPORT *psDeviceImport;
393         IMG_BOOL bStatus;
394     RA_BASE_T uiAllocatedAddr;
395     RA_LENGTH_T uiAllocatedSize;
396     IMG_DEV_VIRTADDR sBase;
397     IMG_HANDLE hReservation;
398     PVRSRV_ERROR eError;
399         IMG_UINT uiAlign;
400
401         /* Round the provided import alignment to the configured heap alignment */
402         uiAlign = 1ULL << psHeap->uiLog2ImportAlignment;
403         uiAlign = (psImport->uiAlign + uiAlign - 1) & ~(uiAlign-1);
404
405         psDeviceImport = &psImport->sDeviceImport;
406
407         OSLockAcquire(psDeviceImport->hLock);
408         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
409                                         __FUNCTION__,
410                                         psImport,
411                                         psDeviceImport->ui32RefCount,
412                                         psDeviceImport->ui32RefCount+1);
413
414         if (psDeviceImport->ui32RefCount++ == 0)
415         {
416                 _DevmemImportStructAcquire(psImport);
417
418                 OSAtomicIncrement(&psHeap->hImportCount);
419
420                 if (psHeap->psCtx->hBridge != psImport->hBridge)
421                 {
422                         /*
423                                 The import was done with a different connection then the
424                                 memory context which means they are not compatible.
425                         */
426                         eError = PVRSRV_ERROR_INVALID_PARAMS;
427                         goto failCheck;
428                 }
429
430                 /* Allocate space in the VM */
431             bStatus = RA_Alloc(psHeap->psQuantizedVMRA,
432                                psImport->uiSize,
433                                0, /* flags: this RA doesn't use flags*/
434                                uiAlign,
435                                &uiAllocatedAddr,
436                                &uiAllocatedSize,
437                                IMG_NULL /* don't care about per-import priv data */
438                                );
439             if (!bStatus)
440             {
441                 eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_DEVICE_VM;
442                 goto failVMRAAlloc;
443             }
444         
445             /* No reason for the allocated virtual size to be different from
446                the PMR's size */
447             PVR_ASSERT(uiAllocatedSize == psImport->uiSize);
448         
449             sBase.uiAddr = uiAllocatedAddr;
450         
451                 /* Setup page tables for the allocated VM space */
452             eError = BridgeDevmemIntReserveRange(psHeap->psCtx->hBridge,
453                                                                                          psHeap->hDevMemServerHeap,
454                                                                                          sBase,
455                                                                                          uiAllocatedSize,
456                                                                                          &hReservation);
457             if (eError != PVRSRV_OK)
458             {
459                 goto failReserve;
460             }
461
462                 if (bMap)
463                 {
464                         DEVMEM_FLAGS_T uiMapFlags;
465                         
466                         uiMapFlags = psImport->uiFlags & PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK;
467
468                         /* Actually map the PMR to allocated VM space */
469                         eError = BridgeDevmemIntMapPMR(psHeap->psCtx->hBridge,
470                                                                                    psHeap->hDevMemServerHeap,
471                                                                                    hReservation,
472                                                                                    psImport->hPMR,
473                                                                                    uiMapFlags,
474                                                                                    &psDeviceImport->hMapping);
475                         if (eError != PVRSRV_OK)
476                         {
477                                 goto failMap;
478                         }
479                         psDeviceImport->bMapped = IMG_TRUE;
480                 }
481
482                 /* Setup device mapping specific parts of the mapping info */
483             psDeviceImport->hReservation = hReservation;
484                 psDeviceImport->sDevVAddr.uiAddr = uiAllocatedAddr;
485                 psDeviceImport->psHeap = psHeap;
486         }
487         else
488         {
489                 /*
490                         Check that we've been asked to map it into the
491                         same heap 2nd time around
492                 */
493                 if (psHeap != psDeviceImport->psHeap)
494                 {
495                         eError = PVRSRV_ERROR_INVALID_HEAP;
496                         goto failParams;
497                 }
498         }
499         OSLockRelease(psDeviceImport->hLock);
500
501         return PVRSRV_OK;
502
503 failMap:
504         BridgeDevmemIntUnreserveRange(psHeap->psCtx->hBridge,
505                                                                   hReservation);
506 failReserve:
507         RA_Free(psHeap->psQuantizedVMRA,
508             uiAllocatedAddr);
509 failVMRAAlloc:
510 failCheck:
511         _DevmemImportStructRelease(psImport);
512         OSAtomicDecrement(&psHeap->hImportCount);
513 failParams:
514         OSLockRelease(psDeviceImport->hLock);
515         PVR_ASSERT(eError != PVRSRV_OK);
516         return eError;
517 }
518
519 /*
520         Unmap an import from the Device
521 */
522 IMG_INTERNAL
523 IMG_VOID _DevmemImportStructDevUnmap(DEVMEM_IMPORT *psImport)
524 {
525         PVRSRV_ERROR eError;
526         DEVMEM_DEVICE_IMPORT *psDeviceImport;
527
528         psDeviceImport = &psImport->sDeviceImport;
529
530         OSLockAcquire(psDeviceImport->hLock);
531         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
532                                         __FUNCTION__,
533                                         psImport,
534                                         psDeviceImport->ui32RefCount,
535                                         psDeviceImport->ui32RefCount-1);
536
537         if (--psDeviceImport->ui32RefCount == 0)
538         {
539                 DEVMEM_HEAP *psHeap = psDeviceImport->psHeap;
540
541                 if (psDeviceImport->bMapped)
542                 {
543                         eError = BridgeDevmemIntUnmapPMR(psImport->hBridge,
544                                                                                         psDeviceImport->hMapping);
545                         PVR_ASSERT(eError == PVRSRV_OK);
546                 }
547         
548             eError = BridgeDevmemIntUnreserveRange(psImport->hBridge,
549                                                 psDeviceImport->hReservation);
550             PVR_ASSERT(eError == PVRSRV_OK);
551         
552             RA_Free(psHeap->psQuantizedVMRA,
553                     psDeviceImport->sDevVAddr.uiAddr);
554
555             OSLockRelease(psDeviceImport->hLock);
556
557                 _DevmemImportStructRelease(psImport);
558
559                 OSAtomicDecrement(&psHeap->hImportCount);
560         }
561         else
562         {
563                 OSLockRelease(psDeviceImport->hLock);
564         }
565 }
566
567 /*
568         Map an import into the CPU
569 */
570 IMG_INTERNAL
571 PVRSRV_ERROR _DevmemImportStructCPUMap(DEVMEM_IMPORT *psImport)
572 {
573         PVRSRV_ERROR eError;
574         DEVMEM_CPU_IMPORT *psCPUImport;
575         IMG_SIZE_T uiMappingLength;
576
577         psCPUImport = &psImport->sCPUImport;
578
579         OSLockAcquire(psCPUImport->hLock);
580         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
581                                         __FUNCTION__,
582                                         psImport,
583                                         psCPUImport->ui32RefCount,
584                                         psCPUImport->ui32RefCount+1);
585
586         if (psCPUImport->ui32RefCount++ == 0)
587         {
588                 _DevmemImportStructAcquire(psImport);
589
590 #if !defined(__KERNEL__) && defined(SUPPORT_ION)
591                 if (psImport->sCPUImport.iDmaBufFd >= 0)
592                 {
593                         void *pvCPUVAddr;
594                         int iProt = PROT_READ;
595
596                         iProt |= (psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE) ? PROT_WRITE : 0;
597                         /* For ion imports, use the ion fd and mmap facility to map the
598                          * buffer to user space. We can bypass the services bridge in
599                          * this case and possibly save some time.
600                          */
601                         pvCPUVAddr = mmap(NULL, psImport->uiSize, iProt,
602                                           MAP_SHARED, psImport->sCPUImport.iDmaBufFd, 0);
603
604                         if (pvCPUVAddr == MAP_FAILED)
605                         {
606                                 eError = PVRSRV_ERROR_DEVICEMEM_MAP_FAILED;
607                                 goto failMap;
608                         }
609
610                         psCPUImport->hOSMMapData = pvCPUVAddr;
611                         psCPUImport->pvCPUVAddr = pvCPUVAddr;
612                         uiMappingLength = psImport->uiSize;
613                 }
614                 else
615 #endif
616                 {
617                         eError = OSMMapPMR(psImport->hBridge,
618                                                            psImport->hPMR,
619                                                            psImport->uiSize,
620                                                            psImport->uiFlags,
621                                                            &psCPUImport->hOSMMapData,
622                                                            &psCPUImport->pvCPUVAddr,
623                                                            &uiMappingLength);
624                         if (eError != PVRSRV_OK)
625                         {
626                                 goto failMap;
627                         }
628                 }
629
630                 /* There is no reason the mapping length is different to the size */
631                 PVR_ASSERT(uiMappingLength == psImport->uiSize);
632         }
633         OSLockRelease(psCPUImport->hLock);
634
635         return PVRSRV_OK;
636
637 failMap:
638         psCPUImport->ui32RefCount--;
639         _DevmemImportStructRelease(psImport);
640         OSLockRelease(psCPUImport->hLock);
641         PVR_ASSERT(eError != PVRSRV_OK);
642         return eError;
643 }
644
645 /*
646         Unmap an import from the CPU
647 */
648 IMG_INTERNAL
649 IMG_VOID _DevmemImportStructCPUUnmap(DEVMEM_IMPORT *psImport)
650 {
651         DEVMEM_CPU_IMPORT *psCPUImport;
652
653         psCPUImport = &psImport->sCPUImport;
654
655         OSLockAcquire(psCPUImport->hLock);
656         DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
657                                         __FUNCTION__,
658                                         psImport,
659                                         psCPUImport->ui32RefCount,
660                                         psCPUImport->ui32RefCount-1);
661
662         if (--psCPUImport->ui32RefCount == 0)
663         {
664                 /* FIXME: psImport->uiSize is a 64-bit quantity where as the 5th
665                  * argument to OSUnmapPMR is a 32-bit quantity on 32-bit systems
666                  * hence a compiler warning of implicit cast and loss of data.
667                  * Added explicit cast and assert to remove warning.
668                  */
669 #if (defined(_WIN32) && !defined(_WIN64)) || (defined(LINUX) && defined(__i386__))
670                 PVR_ASSERT(psImport->uiSize<IMG_UINT32_MAX);
671 #endif
672
673 #if !defined(__KERNEL__) && defined(SUPPORT_ION)
674                 if (psImport->sCPUImport.iDmaBufFd >= 0)
675                 {
676                         munmap(psCPUImport->hOSMMapData, psImport->uiSize);
677                 }
678                 else
679 #endif
680                 {
681                         OSMUnmapPMR(psImport->hBridge,
682                                                 psImport->hPMR,
683                                                 psCPUImport->hOSMMapData,
684                                                 psCPUImport->pvCPUVAddr,
685                                                 (IMG_SIZE_T)psImport->uiSize);
686                 }
687
688                 OSLockRelease(psCPUImport->hLock);
689
690                 _DevmemImportStructRelease(psImport);
691         }
692         else
693         {
694                 OSLockRelease(psCPUImport->hLock);
695         }
696 }
697
698