From 895a89e28d0724c8e6c1cb5dd5d30de18bd25c6b Mon Sep 17 00:00:00 2001 From: Alistair Strachan Date: Thu, 25 Nov 2010 17:16:24 +0000 Subject: gpu: pvr: Update to DDK 1.6.16.4046 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: If38412971f275715a47bf200aeebe1139d2620f8 gpu: pvr: Update DDK version number to 1.6.16.4061 This is a version number change only, which is required for compatibility with the user-mode driver. Change-Id: I4e0f59a8f98ea28f9c0862aff76c0bfa2710efe0 gpu: pvr: Update to DDK 1.6.16.4124 Change-Id: Ifbc47f2552f031e92e02b31a9715e3e42cf14b3c gpu: pvr: Update DDK version number to 1.6.16.4131 This is a version number change only, which is required for compatibility with the user-mode driver. Change-Id: I8c4df3ae638ad2d358aa3977ffb7f6e9bdb1de4a gpu: pvr: Update to DDK 1.7.17.4142 Signed-off-by: Simon Wilson gpu: pvr: Update to DDK 1.7.17.4474 Signed-off-by: Simon Wilson gpu: pvr: Update to DDK 1.8.18.380 gpu: pvr: Update to DDK 1.8.18.468 gpu: pvr: Update to DDK 1.8.18.684 Change-Id: I7a4e92add9f1c61862a06e51b68169d93b67a001 Signed-off-by: JP Abgrall gpu: pvr: Update to DDK 1.8.18.726 gpu: pvr: Update to DDK 1.8.18.749 gpu: pvr: Fix to compile on 2.6.39 Change-Id: I79c07b3a0ca219f7e6d8dec97f41adc3fc5a01ff Signed-off-by: Arve Hjønnevåg gpu: pvr: Update to DDK 1.8.18.834 Fix a couple of double frees in PVRSRVSwapToDCBuffer2KM. Fixes for various ION client refcounting issues. gpu: pvr: Update to DDK 1.8.18.844 Various fixes to prevent arbitrary memory corruption with ION: * Remove the per-process ION client - there is now just one "kernel" ION client * Ensure that the mmap mutex is taken before walking the offset struct list * Implement ION cache flush code gpu: pvr: Update to DDK 1.8.18.853 Change-Id: I5e2e1619aae0634ca5036c5ab60e1e4339a35b0d gpu: pvr: Update to DDK 1.8.18.866 Change-Id: I91548bf62aa30ff41814118a3a6d49303fc16bfc gpu: pvr: Update to DDK 1.8.18.877 Change-Id: Id87c6318a7705ad51e5bfd487a9b216f373c0caf gpu: pvr: Update to DDK 1.8.18.891 This is a version number change only, which is required for compatibility with the user-mode driver. Change-Id: I30b11a79973179d7dcb0923d2106a1f072b88a77 gpu: pvr: Update to DDK 1.8.18.919 - Bump CONFIG_FB_S3C_NR_BUFFERS to 6, to increase the display carveout size by 3MB. This is to make space for video-decode buffers. - drivers/gpu/pvr Makefile cleanups. Remove dead build options. - Groundwork for "multiple readers" capability required by HWC. - Merge s3c_lcd and s5pc110 display and system code with latest versions. Add video-decode carveout capability. Change-Id: I8836204451eebf12b030404177cfd6bc4b294489 gpu: pvr: Update to DDK 1.8.18.927 - More work on "multiple reader" capability for HWC. Change-Id: I0fd372b03de5bb86591d4b2be208be3749670248 gpu: pvr: Update to DDK 1.8.18.943 Change-Id: Iae3d13fc82dfa0cffc6bce98a056f1b0d4b1f62a gpu: pvr: Update to DDK 1.8.18.945 - Add ProcessFlip V2 capability to s3c_displayclass.c. - Enables FIMC integration. Change-Id: Ibc1dec9c24f5f55ce1436674b36571f3718b4e96 gpu: pvr: Update to DDK 1.8.18.964 - Add SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS to enable returning of display buffer physical addresses to user-space. Required for C110 HWC. Not enabled on Prime. Change-Id: I5f19c7b1cea193aaca24cceca518d0100171c823 gpu: pvr: Update to DDK 1.8@273945 This is a version number change only, which is required for compatibility with the user-mode driver. gpu: pvr: Update to DDK 1.8@274226 gpu: pvr: Update to DDK 1.8@274836 gpu: pvr: Update to DDK 1.8@275425 This is a version number change only, which is required for compatibility with the user-mode driver. gpu: pvr: Update to DDK 1.8@275540 - Allow userspace to obtain a copy of the current kernel reference count of a MemInfo. Fixes a bug on crespo that allowed a Y/UV swapchain buffer to be incorrectly re-used in another allocation. Change-Id: I6a10d75ad9efb4109b6bfa34b3478dc7b36caac2 gpu: pvr: Update to DDK 1.8@275916 gpu: pvr: Update to DDK 1.8@276629 Merged with upstream s3c_lcd. gpu: pvr: Update to DDK 1.8@278427 - Fix a possible livelock scenario in s3c_lcd, by scheduling the MISR in the vsync handler. Change-Id: If5c57b8a8658159d2912d89074015bb03b3f5ed3 gpu: pvr: Update to DDK 1.8@279068 Also make it possible to build the debug (pdump) driver. Change-Id: I90f9a5c566a9d6205e801302bfb4f881f53e3247 gpu: pvr: Update to DDK 1.8@288777 This is a version number change only, which is required for compatibility with the user-mode driver. Change-Id: Ia22454fd91e280cf35cf798806dfa2b9505d0018 gpu: pvr: Update to DDK 1.8@289037 - Merge with upstream TILER allocation wrap support in preparation for video encoder integration. - Suppress some overly verbose kernel messages. - Remove incorrect/unnecssary VM_PFNMAP sanity check. Change-Id: Ia30a3316e1c9d2dc421afa5068a977b25618c85d gpu: pvr: Update to DDK 1.8@289270 This is a version number change only, which is required for compatibility with the user-mode driver. Change-Id: Ic827cd7f22792c900708e77b0af48d5824790581 gpu: pvr: Update to DDK 1.8@289794 This is a version number change only, which is required for compatibility with the user-mode driver. Change-Id: Iba07b4cb193d87000aacb0408993841b99c8cb3e gpu: pvr: Update to DDK 1.8@291121 - Merged TI heap configuration change - Pass ROC2 devvaddr through to userspace (better debug) Change-Id: Ie43b9af490190adbe0d1e34119af392f1ea420f5 gpu: pvr: Update to DDK 1.8@292125 Change-Id: I2b6e31f950a7ea98ff4db4feb160886c3d6eab7c gpu: pvr: Update to DDK 1.8@292423 Change-Id: I4086ba1f3f3a6e5f7e605b156d1e01151da17223 gpu: pvr: Update to DDK 1.8@293295 Change-Id: Iec7d62292583d6b8e0fa157aa32e3156090a529d gpu: pvr: Update to DDK 1.8@295945 - Make sure buffer IDs propagate to other process mappings. Debug feature only. Change-Id: Id4b360b9e6b76951129791200d1df7e8d42708e9 gpu: pvr: Update to DDK 1.8@297401 - Security fixes. Remove ability to map primary surface in any process. Hide user-accessible path to OSPanic(). Change-Id: Iff7d56b04400625cac6f1f6e123749bdaeb3908c gpu: pvr: Update to DDK 1.8@298138 This is a version number change only, which is required for compatibility with the user-mode driver. Change-Id: I9edf13aaedf0b56c9922c63d84a2d99ec7b6aae3 gpu: pvr: Update to DDK 1.8@300406 This is a version number change only, which is required for compatibility with the user-mode driver. Change-Id: I6cde977c5cfdf13f7ef43e01f2c0dba1bc0659b6 --- drivers/gpu/pvr/buffer_manager.c | 545 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 505 insertions(+), 40 deletions(-) (limited to 'drivers/gpu/pvr/buffer_manager.c') diff --git a/drivers/gpu/pvr/buffer_manager.c b/drivers/gpu/pvr/buffer_manager.c index c5ee8c7..8907e22 100644 --- a/drivers/gpu/pvr/buffer_manager.c +++ b/drivers/gpu/pvr/buffer_manager.c @@ -1,6 +1,6 @@ /********************************************************************** * - * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved. + * Copyright (C) Imagination Technologies Ltd. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -38,8 +38,9 @@ static IMG_VOID BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping); static IMG_BOOL BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize, - IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping, - IMG_UINT32 uFlags, IMG_UINTPTR_T *pBase); + IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping, + IMG_UINT32 uFlags, IMG_PVOID pvPrivData, + IMG_UINT32 ui32PrivDataLength, IMG_UINTPTR_T *pBase); static IMG_BOOL DevMemoryAlloc (BM_CONTEXT *pBMContext, @@ -52,13 +53,15 @@ static IMG_VOID DevMemoryFree (BM_MAPPING *pMapping); static IMG_BOOL -AllocMemory (BM_CONTEXT *pBMContext, - BM_HEAP *psBMHeap, - IMG_DEV_VIRTADDR *psDevVAddr, - IMG_SIZE_T uSize, - IMG_UINT32 uFlags, - IMG_UINT32 uDevVAddrAlignment, - BM_BUF *pBuf) +AllocMemory (BM_CONTEXT *pBMContext, + BM_HEAP *psBMHeap, + IMG_DEV_VIRTADDR *psDevVAddr, + IMG_SIZE_T uSize, + IMG_UINT32 uFlags, + IMG_UINT32 uDevVAddrAlignment, + IMG_PVOID pvPrivData, + IMG_UINT32 ui32PrivDataLength, + BM_BUF *pBuf) { BM_MAPPING *pMapping; IMG_UINTPTR_T uOffset; @@ -105,6 +108,8 @@ AllocMemory (BM_CONTEXT *pBMContext, uFlags, uDevVAddrAlignment, 0, + pvPrivData, + ui32PrivDataLength, (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr))) { PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize)); @@ -175,15 +180,22 @@ AllocMemory (BM_CONTEXT *pBMContext, } else { + IMG_BOOL bResult; - pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap, + bResult = pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap, uSize, IMG_NULL, 0, uDevVAddrAlignment, &pBuf->DevVAddr); + + if(!bResult) + { + PVR_DPF((PVR_DBG_ERROR, "AllocMemory: MMUAlloc failed")); + return IMG_FALSE; + } } @@ -526,6 +538,7 @@ static IMG_VOID FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator) { BM_MAPPING *pMapping; + PVRSRV_DEVICE_NODE *psDeviceNode; PVR_DPF ((PVR_DBG_MESSAGE, "FreeBuf: pBuf=0x%x: DevVAddr=%08X CpuVAddr=0x%x CpuPAddr=%08X", @@ -535,6 +548,12 @@ FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator) pMapping = pBuf->pMapping; + psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode; + if (psDeviceNode->pfnCacheInvalidate) + { + psDeviceNode->pfnCacheInvalidate(psDeviceNode); + } + if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) { @@ -695,7 +714,7 @@ BM_DestroyContext(IMG_HANDLE hBMContext, else { - eError = ResManFreeResByPtr(pBMContext->hResItem); + eError = ResManFreeResByPtr(pBMContext->hResItem, CLEANUP_WITH_POLL); if(eError != PVRSRV_OK) { PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeResByPtr failed %d",eError)); @@ -745,13 +764,15 @@ static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list } -static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam, - IMG_UINT32 ui32Param) +static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam, + IMG_UINT32 ui32Param, + IMG_BOOL bDummy) { BM_CONTEXT *pBMContext = pvParam; PVRSRV_DEVICE_NODE *psDeviceNode; PVRSRV_ERROR eError; PVR_UNREFERENCED_PARAMETER(ui32Param); + PVR_UNREFERENCED_PARAMETER(bDummy); @@ -787,8 +808,11 @@ static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam, } else { - - List_BM_CONTEXT_Remove(pBMContext); + if (pBMContext->ppsThis != IMG_NULL) + { + + List_BM_CONTEXT_Remove(pBMContext); + } } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL); @@ -895,9 +919,9 @@ BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode, goto cleanup; } - if(psDeviceNode->pfnMMUInitialise(psDeviceNode, - &pBMContext->psMMUContext, - psPDDevPAddr) != PVRSRV_OK) + if((IMG_NULL == psDeviceNode->pfnMMUInitialise) || (psDeviceNode->pfnMMUInitialise(psDeviceNode, + &pBMContext->psMMUContext, + psPDDevPAddr) != PVRSRV_OK)) { PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: MMUInitialise failed")); goto cleanup; @@ -966,7 +990,7 @@ BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode, return (IMG_HANDLE)pBMContext; cleanup: - (IMG_VOID)BM_DestroyContextCallBack(pBMContext, 0); + (IMG_VOID)BM_DestroyContextCallBack(pBMContext, 0, CLEANUP_WITH_POLL); return IMG_NULL; } @@ -1006,6 +1030,11 @@ BM_CreateHeap (IMG_HANDLE hBMContext, psDeviceNode = pBMContext->psDeviceNode; + + PVR_ASSERT((psDevMemHeapInfo->ui32HeapSize & (psDevMemHeapInfo->ui32DataPageSize - 1)) == 0); + PVR_ASSERT(psDevMemHeapInfo->ui32HeapSize > 0); + + @@ -1042,6 +1071,9 @@ BM_CreateHeap (IMG_HANDLE hBMContext, psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize; psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo; psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs; +#if defined(SUPPORT_MEMORY_TILING) + psBMHeap->ui32XTileStride = psDevMemHeapInfo->ui32XTileStride; +#endif psBMHeap->pBMContext = pBMContext; @@ -1096,7 +1128,7 @@ ErrorExit: if (psBMHeap->pMMUHeap != IMG_NULL) { psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap); - psDeviceNode->pfnMMUFinalise (pBMContext->psMMUContext); + } @@ -1165,6 +1197,8 @@ BM_Alloc ( IMG_HANDLE hDevMemHeap, IMG_SIZE_T uSize, IMG_UINT32 *pui32Flags, IMG_UINT32 uDevVAddrAlignment, + IMG_PVOID pvPrivData, + IMG_UINT32 ui32PrivDataLength, BM_HANDLE *phBuf) { BM_BUF *pBuf; @@ -1214,6 +1248,8 @@ BM_Alloc ( IMG_HANDLE hDevMemHeap, uSize, uFlags, uDevVAddrAlignment, + pvPrivData, + ui32PrivDataLength, pBuf) != IMG_TRUE) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL); @@ -1379,6 +1415,11 @@ BM_Wrap ( IMG_HANDLE hDevMemHeap, return IMG_TRUE; } + else + { + + HASH_Remove(psBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddress.uiAddr); + } } @@ -1567,7 +1608,7 @@ DevMemoryAlloc (BM_CONTEXT *pBMContext, { PVRSRV_DEVICE_NODE *psDeviceNode; #ifdef PDUMP - IMG_UINT32 ui32PDumpSize = pMapping->uSize; + IMG_UINT32 ui32PDumpSize = (IMG_UINT32)pMapping->uSize; #endif psDeviceNode = pBMContext->psDeviceNode; @@ -1677,41 +1718,337 @@ static IMG_VOID DevMemoryFree (BM_MAPPING *pMapping) { PVRSRV_DEVICE_NODE *psDeviceNode; + IMG_DEV_PHYADDR sDevPAddr; #ifdef PDUMP IMG_UINT32 ui32PSize; #endif + psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode; + sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr); + + if (sDevPAddr.uiAddr != 0) + { #ifdef PDUMP + + if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY) + { + + ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize; + } + else + { + ui32PSize = (IMG_UINT32)pMapping->uSize; + } - if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY) + PDUMPFREEPAGES(pMapping->pBMHeap, + pMapping->DevVAddr, + ui32PSize, + pMapping->pBMHeap->sDevArena.ui32DataPageSize, + (IMG_HANDLE)pMapping, + (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE); +#endif + } + psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize)); +} + +#ifndef XPROC_WORKAROUND_NUM_SHAREABLES +#define XPROC_WORKAROUND_NUM_SHAREABLES 200 +#endif + +#define XPROC_WORKAROUND_BAD_SHAREINDEX 0773407734 + +static IMG_UINT32 gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX; + + +static struct { + IMG_UINT32 ui32RefCount; + IMG_UINT32 ui32AllocFlags; + IMG_UINT32 ui32Size; + IMG_UINT32 ui32PageSize; + RA_ARENA *psArena; + IMG_SYS_PHYADDR sSysPAddr; + IMG_VOID *pvCpuVAddr; + IMG_HANDLE hOSMemHandle; +} gXProcWorkaroundShareData[XPROC_WORKAROUND_NUM_SHAREABLES] = {{0}}; + +PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index) +{ + + + + if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX) { - - ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize; + PVR_DPF((PVR_DBG_ERROR, "No, it's already set!")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + gXProcWorkaroundShareIndex = ui32Index; + + return PVRSRV_OK; +} + +PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index) +{ + + + + if (gXProcWorkaroundShareIndex == XPROC_WORKAROUND_BAD_SHAREINDEX) + { + PVR_DPF((PVR_DBG_ERROR, "huh? how can it be bad??")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + if (gXProcWorkaroundShareIndex != ui32Index) + { + PVR_DPF((PVR_DBG_ERROR, "gXProcWorkaroundShareIndex == 0x%08x != 0x%08x == ui32Index", gXProcWorkaroundShareIndex, ui32Index)); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX; + + return PVRSRV_OK; +} + +PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index) +{ + + + + if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX) + { + return PVRSRV_ERROR_INVALID_PARAMS; + } + + for (*pui32Index = 0; *pui32Index < XPROC_WORKAROUND_NUM_SHAREABLES; (*pui32Index)++) + { + if (gXProcWorkaroundShareData[*pui32Index].ui32RefCount == 0) + { + gXProcWorkaroundShareIndex = *pui32Index; + return PVRSRV_OK; + } + } + + PVR_DPF((PVR_DBG_ERROR, "ran out of shared buffers")); + return PVRSRV_ERROR_OUT_OF_MEMORY; +} + +static PVRSRV_ERROR +XProcWorkaroundAllocShareable(RA_ARENA *psArena, + IMG_UINT32 ui32AllocFlags, + IMG_UINT32 ui32Size, + IMG_UINT32 ui32PageSize, + IMG_PVOID pvPrivData, + IMG_UINT32 ui32PrivDataLength, + IMG_VOID **ppvCpuVAddr, + IMG_HANDLE *phOSMemHandle) +{ + if ((ui32AllocFlags & PVRSRV_MEM_XPROC) == 0) + { + PVR_DPF((PVR_DBG_VERBOSE, "XProcWorkaroundAllocShareable: bad flags")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + if (gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount > 0) + { + PVR_DPF((PVR_DBG_VERBOSE, + "XProcWorkaroundAllocShareable: re-using previously allocated pages")); + + ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK; + ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS; + + if (ui32AllocFlags != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags) + { + PVR_DPF((PVR_DBG_ERROR, + "Can't! Flags don't match! (I had 0x%08x, you gave 0x%08x)", + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags, + ui32AllocFlags)); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + if (ui32Size != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size) + { + PVR_DPF((PVR_DBG_ERROR, + "Can't! Size doesn't match!")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + if (ui32PageSize != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize) + { + PVR_DPF((PVR_DBG_ERROR, + "Can't! Page Size doesn't match!")); + return PVRSRV_ERROR_INVALID_PARAMS; + } + + *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr; + *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle; + + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount ++; + + return PVRSRV_OK; } else { - ui32PSize = pMapping->uSize; + if (psArena != IMG_NULL) + { + IMG_CPU_PHYADDR sCpuPAddr; + IMG_SYS_PHYADDR sSysPAddr; + + PVR_DPF((PVR_DBG_VERBOSE, + "XProcWorkaroundAllocShareable: making a NEW allocation from local mem")); + + if (!RA_Alloc (psArena, + ui32Size, + IMG_NULL, + IMG_NULL, + 0, + ui32PageSize, + 0, + pvPrivData, + ui32PrivDataLength, + (IMG_UINTPTR_T *)&sSysPAddr.uiAddr)) + { + PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: RA_Alloc(0x%x) FAILED", ui32Size)); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + + sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr); + if(OSReservePhys(sCpuPAddr, + ui32Size, + ui32AllocFlags, + (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr, + &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: OSReservePhys failed")); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].sSysPAddr = sSysPAddr; + } + else + { + PVR_DPF((PVR_DBG_VERBOSE, + "XProcWorkaroundAllocShareable: making a NEW allocation from OS")); + + ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK; + ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS; + + + if (OSAllocPages(ui32AllocFlags, + ui32Size, + ui32PageSize, + pvPrivData, + ui32PrivDataLength, + (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr, + &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, + "XProcWorkaroundAllocShareable: OSAllocPages(0x%x) failed", + ui32PageSize)); + return PVRSRV_ERROR_OUT_OF_MEMORY; + } + } + + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].psArena = psArena; + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags = ui32AllocFlags; + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size = ui32Size; + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize = ui32PageSize; + + *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr; + *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle; + + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount ++; + + return PVRSRV_OK; } +} - PDUMPFREEPAGES(pMapping->pBMHeap, - pMapping->DevVAddr, - ui32PSize, - pMapping->pBMHeap->sDevArena.ui32DataPageSize, - (IMG_HANDLE)pMapping, - (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE); -#endif +static PVRSRV_ERROR XProcWorkaroundHandleToSI(IMG_HANDLE hOSMemHandle, IMG_UINT32 *pui32SI) +{ + + IMG_UINT32 ui32SI; + IMG_BOOL bFound; + IMG_BOOL bErrorDups; - psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode; + bFound = IMG_FALSE; + bErrorDups = IMG_FALSE; - psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize)); + for (ui32SI = 0; ui32SI < XPROC_WORKAROUND_NUM_SHAREABLES; ui32SI++) + { + if (gXProcWorkaroundShareData[ui32SI].ui32RefCount>0 && gXProcWorkaroundShareData[ui32SI].hOSMemHandle == hOSMemHandle) + { + if (bFound) + { + bErrorDups = IMG_TRUE; + } + else + { + *pui32SI = ui32SI; + bFound = IMG_TRUE; + } + } + } + + if (bErrorDups || !bFound) + { + return PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE; + } + + return PVRSRV_OK; } +static IMG_VOID XProcWorkaroundFreeShareable(IMG_HANDLE hOSMemHandle) +{ + IMG_UINT32 ui32SI = (IMG_UINT32)((IMG_UINTPTR_T)hOSMemHandle & 0xffffU); + PVRSRV_ERROR eError; + + eError = XProcWorkaroundHandleToSI(hOSMemHandle, &ui32SI); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "bad handle")); + return; + } + + gXProcWorkaroundShareData[ui32SI].ui32RefCount --; + + PVR_DPF((PVR_DBG_VERBOSE, "Reduced refcount of SI[%d] from %d to %d", + ui32SI, gXProcWorkaroundShareData[ui32SI].ui32RefCount+1, gXProcWorkaroundShareData[ui32SI].ui32RefCount)); + + if (gXProcWorkaroundShareData[ui32SI].ui32RefCount == 0) + { + if (gXProcWorkaroundShareData[ui32SI].psArena != IMG_NULL) + { + IMG_SYS_PHYADDR sSysPAddr; + + if (gXProcWorkaroundShareData[ui32SI].pvCpuVAddr != IMG_NULL) + { + OSUnReservePhys(gXProcWorkaroundShareData[ui32SI].pvCpuVAddr, + gXProcWorkaroundShareData[ui32SI].ui32Size, + gXProcWorkaroundShareData[ui32SI].ui32AllocFlags, + gXProcWorkaroundShareData[ui32SI].hOSMemHandle); + } + sSysPAddr = gXProcWorkaroundShareData[ui32SI].sSysPAddr; + RA_Free (gXProcWorkaroundShareData[ui32SI].psArena, + sSysPAddr.uiAddr, + IMG_FALSE); + } + else + { + PVR_DPF((PVR_DBG_VERBOSE, "freeing OS memory")); + OSFreePages(gXProcWorkaroundShareData[ui32SI].ui32AllocFlags, + gXProcWorkaroundShareData[ui32SI].ui32PageSize, + gXProcWorkaroundShareData[ui32SI].pvCpuVAddr, + gXProcWorkaroundShareData[ui32SI].hOSMemHandle); + } + } +} + + static IMG_BOOL BM_ImportMemory (IMG_VOID *pH, IMG_SIZE_T uRequestSize, IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping, IMG_UINT32 uFlags, + IMG_PVOID pvPrivData, + IMG_UINT32 ui32PrivDataLength, IMG_UINTPTR_T *pBase) { BM_MAPPING *pMapping; @@ -1720,7 +2057,7 @@ BM_ImportMemory (IMG_VOID *pH, IMG_BOOL bResult; IMG_SIZE_T uSize; IMG_SIZE_T uPSize; - IMG_UINT32 uDevVAddrAlignment = 0; + IMG_SIZE_T uDevVAddrAlignment = 0; PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory (pBMContext=0x%x, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)", @@ -1771,6 +2108,113 @@ BM_ImportMemory (IMG_VOID *pH, uPSize = pMapping->uSize; } + if (uFlags & PVRSRV_MEM_XPROC) + { + IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs | PVRSRV_MEM_XPROC; + IMG_BOOL bBadBackingStoreType; + + + if(uFlags & PVRSRV_MEM_ION) + { + ui32Attribs |= PVRSRV_MEM_ION; + } + + bBadBackingStoreType = IMG_TRUE; + + if ((ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) != 0) + { +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + uDevVAddrAlignment = MAX(pBMHeap->sDevArena.ui32DataPageSize, HOST_PAGESIZE()); + + + if (uPSize % uDevVAddrAlignment != 0) + { + PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated")); + goto fail_mapping_alloc; + } + uDevVAddrAlignment = 0; + + + if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) + { + ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK; + ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK); + } + + + if (XProcWorkaroundAllocShareable(IMG_NULL, + ui32Attribs, + (IMG_UINT32)uPSize, + pBMHeap->sDevArena.ui32DataPageSize, + pvPrivData, + ui32PrivDataLength, + (IMG_VOID **)&pMapping->CpuVAddr, + &pMapping->hOSMemHandle) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, + "BM_ImportMemory: XProcWorkaroundAllocShareable(0x%x) failed", + uPSize)); + goto fail_mapping_alloc; + } + + + + + pMapping->eCpuMemoryOrigin = hm_env; + bBadBackingStoreType = IMG_FALSE; + } + + if ((ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) != 0) + { + uDevVAddrAlignment = pBMHeap->sDevArena.ui32DataPageSize; + + if (uPSize % uDevVAddrAlignment != 0) + { + PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated")); + goto fail_mapping_alloc; + } + uDevVAddrAlignment = 0; + + + if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) + { + ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK; + ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK); + } + + + if (XProcWorkaroundAllocShareable(pBMHeap->pLocalDevMemArena, + ui32Attribs, + (IMG_UINT32)uPSize, + pBMHeap->sDevArena.ui32DataPageSize, + pvPrivData, + ui32PrivDataLength, + (IMG_VOID **)&pMapping->CpuVAddr, + &pMapping->hOSMemHandle) != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, + "BM_ImportMemory: XProcWorkaroundAllocShareable(0x%x) failed", + uPSize)); + goto fail_mapping_alloc; + } + + + + + pMapping->eCpuMemoryOrigin = hm_env; + bBadBackingStoreType = IMG_FALSE; + } + + if (bBadBackingStoreType) + { + PVR_DPF((PVR_DBG_ERROR, "Cannot use this memory sharing workaround with this type of backing store")); + goto fail_mapping_alloc; + } + } + else + if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) @@ -1783,11 +2227,19 @@ BM_ImportMemory (IMG_VOID *pH, ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK; ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK); } - + + if (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM) + { + ui32Attribs &= ~PVRSRV_MEM_ALLOCATENONCACHEDMEM; + ui32Attribs |= (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM); + } + if (OSAllocPages(ui32Attribs, uPSize, pBMHeap->sDevArena.ui32DataPageSize, + pvPrivData, + ui32PrivDataLength, (IMG_VOID **)&pMapping->CpuVAddr, &pMapping->hOSMemHandle) != PVRSRV_OK) { @@ -1822,6 +2274,8 @@ BM_ImportMemory (IMG_VOID *pH, 0, pBMHeap->sDevArena.ui32DataPageSize, 0, + pvPrivData, + ui32PrivDataLength, (IMG_UINTPTR_T *)&sSysPAddr.uiAddr)) { PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%x) FAILED", uPSize)); @@ -1854,7 +2308,7 @@ BM_ImportMemory (IMG_VOID *pH, pMapping, IMG_NULL, uFlags, - uDevVAddrAlignment, + (IMG_UINT32)uDevVAddrAlignment, &pMapping->DevVAddr); if (!bResult) { @@ -1892,7 +2346,12 @@ fail_dev_mem_alloc: uPSize = pMapping->uSize; } - if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) + if (uFlags & PVRSRV_MEM_XPROC) + { + XProcWorkaroundFreeShareable(pMapping->hOSMemHandle); + } + else + if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) { OSFreePages(pBMHeap->ui32Attribs, uPSize, @@ -1959,7 +2418,12 @@ BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping) uPSize = psMapping->uSize; } - if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) + if (psMapping->ui32Flags & PVRSRV_MEM_XPROC) + { + XProcWorkaroundFreeShareable(psMapping->hOSMemHandle); + } + else + if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) { OSFreePages(pBMHeap->ui32Attribs, uPSize, @@ -2002,6 +2466,7 @@ IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo, PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0); + psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode; *psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap, -- cgit v1.1