Project import generated by Copybara. GitOrigin-RevId: f7ea1bca60e4f562866b25311fb12d178513d252
diff --git a/device.bazelrc b/device.bazelrc index c678743..d52a4df 100644 --- a/device.bazelrc +++ b/device.bazelrc
@@ -1,6 +1,6 @@ build:download_gki --use_prebuilt_gki build:download_gki --use_signed_prebuilts -build:download_gki --action_env=KLEAF_DOWNLOAD_BUILD_NUMBER_MAP="gki_prebuilts=12637676" +build:download_gki --action_env=KLEAF_DOWNLOAD_BUILD_NUMBER_MAP="gki_prebuilts=12916019" build:no_download_gki --use_prebuilt_gki=false # disable GKI prebuilts by default
diff --git a/drivers/gpu/img-rogue/23.2/build/linux/config/core.mk b/drivers/gpu/img-rogue/23.2/build/linux/config/core.mk index 5460ca7..7b7b8ab 100644 --- a/drivers/gpu/img-rogue/23.2/build/linux/config/core.mk +++ b/drivers/gpu/img-rogue/23.2/build/linux/config/core.mk
@@ -2248,6 +2248,27 @@ $(eval $(call TunableBothConfigC,SUPPORT_PMR_DEFERRED_FREE,1,\ Free device mapped PMRs asynchronously from KMD pvr_defer_free thread._\ )) + + $(eval $(call TunableBothConfigC,SUPPORT_PMR_PAGES_DEFERRED_FREE,1,\ + Support deferred freeing of PMR pages freed as a result of PMR_ChangeSparseMem._\ + )) + + ifeq ($(SUPPORT_PMR_PAGES_DEFERRED_FREE),1) + ifeq ($(SUPPORT_PMR_DEFERRED_FREE),0) + $(error SUPPORT_PMR_PAGES_DEFERRED_FREE requires SUPPORT_PMR_DEFERRED_FREE) + endif + endif + + $(eval $(call TunableBothConfigC,SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE,1,\ + Support deferred freeing of PMRs used by multiple devices._\ + )) + + ifeq ($(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE),1) + ifeq ($(SUPPORT_PMR_DEFERRED_FREE),0) + $(error SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE requires SUPPORT_PMR_DEFERRED_FREE) + endif + endif + $(eval $(call TunableBothConfigC,SUPPORT_MMU_DEFERRED_FREE,1,\ Free MMU mappings asynchronously from KMD pvr_defer_free thread._\ ))
diff --git a/drivers/gpu/img-rogue/23.2/build/linux/config/core_volcanic.mk b/drivers/gpu/img-rogue/23.2/build/linux/config/core_volcanic.mk index c711f13..6db6dbd 100644 --- a/drivers/gpu/img-rogue/23.2/build/linux/config/core_volcanic.mk +++ b/drivers/gpu/img-rogue/23.2/build/linux/config/core_volcanic.mk
@@ -2089,6 +2089,17 @@ $(eval $(call TunableBothConfigC,SUPPORT_PMR_DEFERRED_FREE,1,\ Free device mapped PMRs asynchronously from KMD pvr_defer_free thread._\ )) + + $(eval $(call TunableBothConfigC,SUPPORT_PMR_PAGES_DEFERRED_FREE,1,\ + Support deferred freeing of PMR pages freed as a result of PMR_ChangeSparseMem._\ + )) + + ifeq ($(SUPPORT_PMR_PAGES_DEFERRED_FREE),1) + ifeq ($(SUPPORT_PMR_DEFERRED_FREE),0) + $(error SUPPORT_PMR_PAGES_DEFERRED_FREE requires SUPPORT_PMR_DEFERRED_FREE) + endif + endif + $(eval $(call TunableBothConfigC,SUPPORT_MMU_DEFERRED_FREE,1,\ Free MMU mappings asynchronously from KMD pvr_defer_free thread._\ ))
diff --git a/drivers/gpu/img-rogue/23.2/include/img_types.h b/drivers/gpu/img-rogue/23.2/include/img_types.h index 7b4eb64..ed852ea 100644 --- a/drivers/gpu/img-rogue/23.2/include/img_types.h +++ b/drivers/gpu/img-rogue/23.2/include/img_types.h
@@ -256,6 +256,14 @@ typedef int IMG_OS_CONNECTION; #define IMG_DEVMEM_ALIGN_FMTSPEC "0x%010" IMG_UINT64_FMTSPECX #define IMG_DEVMEM_OFFSET_FMTSPEC "0x%010" IMG_UINT64_FMTSPECX +#if defined(__KERNEL__) + #if !defined(DEBUG) && defined(__linux__) + #define IMG_KM_PTR_FMTSPEC "%pK" + #else + #define IMG_KM_PTR_FMTSPEC "%p" + #endif +#endif + /* cpu physical address */ typedef struct {
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/connection_server.c b/drivers/gpu/img-rogue/23.2/services/server/common/connection_server.c index efb0a97..f017ba8 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/connection_server.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/connection_server.c
@@ -100,7 +100,7 @@ static PVRSRV_ERROR ConnectionDataDestroy(CONNECTION_DATA *psConnection) * doesn't even call pfnReleaseData() callback. * Process handles can potentially return RETRY hence additional check * below. */ - eError = PVRSRVReleaseProcessHandleBase(psProcessHandleBase, psConnection->pid, + eError = PVRSRVReleaseProcessHandleBase(psProcessHandleBase, ui64MaxBridgeTime); if (PVRSRVIsRetryError(eError)) { @@ -249,8 +249,8 @@ PVRSRV_ERROR PVRSRVCommonConnectionConnect(void **ppvPrivData, void *pvOSData) PVRSRV_HANDLE_BASE_TYPE_CONNECTION); PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVAllocHandleBase", failure); - /* get process handle base (if it doesn't exist it will be allocated) */ - eError = PVRSRVAcquireProcessHandleBase(psConnection->pid, &psProcessHandleBase); + /* get process handle base for the current process (if it doesn't exist it will be allocated) */ + eError = PVRSRVAcquireProcessHandleBase(&psProcessHandleBase); PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVAcquireProcessHandleBase", failure); /* hConnectionsLock now resides in PVRSRV_DEVICE_NODE */
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/devicemem_server.c b/drivers/gpu/img-rogue/23.2/services/server/common/devicemem_server.c index 42c35f9..b9035b1 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/devicemem_server.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/devicemem_server.c
@@ -983,6 +983,13 @@ DevmemValidateFlags(PMR *psPMR, PVRSRV_MEMALLOCFLAGS_T uiMapFlags) PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_INVALID_FLAGS, ErrorReturnError); } + if ((uiMapFlags & PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK) != + (uiPMRFlags & PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK)) + { + PVR_DPF((PVR_DBG_ERROR, "%s: PMR's device specific flags don't match mapping flags.", __func__)); + PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_INVALID_FLAGS, ErrorReturnError); + } + ErrorReturnError: return eError; } @@ -1012,6 +1019,10 @@ DevmemXIntMapPages(DEVMEMXINT_RESERVATION *psRsrv, "mapping offset out of range", PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE); PVR_LOG_RETURN_IF_FALSE((uiFlags & ~PVRSRV_MEMALLOCFLAGS_DEVMEMX_VIRTUAL_MASK) == 0, "invalid flags", PVRSRV_ERROR_INVALID_FLAGS); + PVR_LOG_RETURN_IF_FALSE(!PMR_IsSparse(psPMR), + "PMR is Sparse, devmemx PMRs should be non-sparse", PVRSRV_ERROR_INVALID_FLAGS); + PVR_LOG_RETURN_IF_FALSE(!(PMR_Flags(psPMR) & PVRSRV_MEMALLOCFLAG_DEFER_PHYS_ALLOC), + "PMR allocation is deferred, devmemx PMRs can not be deferred", PVRSRV_ERROR_INVALID_FLAGS); if (uiLog2PageSize > PMR_GetLog2Contiguity(psPMR)) { @@ -1089,14 +1100,6 @@ DevmemXIntUnmapPages(DEVMEMXINT_RESERVATION *psRsrv, { if (psRsrv->ppsPMR[i] != NULL) { -#if defined(SUPPORT_PMR_DEFERRED_FREE) - /* If PMR is allocated on demand the backing memory is freed by - * pfnUnlockPhysAddresses(). */ - if (!PVRSRV_CHECK_ON_DEMAND(PMR_Flags(psRsrv->ppsPMR[i]))) - { - PMRMarkForDeferFree(psRsrv->ppsPMR[i]); - } -#endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ PMRUnrefPMR2(psRsrv->ppsPMR[i]); psRsrv->ppsPMR[i] = NULL; } @@ -1221,7 +1224,7 @@ DevmemIntMapPMR2(DEVMEMINT_HEAP *psDevmemHeap, if (!DevmemIntReservationAcquireUnlocked(psReservation)) { - PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_REFCOUNT_OVERFLOW, ErrorReturnError); + PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_REFCOUNT_OVERFLOW, ErrorReleaseResLock); } uiAllocationSize = psReservation->uiLength; @@ -1232,6 +1235,13 @@ DevmemIntMapPMR2(DEVMEMINT_HEAP *psDevmemHeap, eError = PMRLockSysPhysAddresses(psPMR); PVR_GOTO_IF_ERROR(eError, ErrorUnreference); + PMRLockPMR(psPMR); + + /* Increase reservation association count so we know if multiple mappings have been created + * on the PMR + */ + PMRGpuResCountIncr(psPMR); + sAllocationDevVAddr = psReservation->sBase; /*Check if the PMR that needs to be mapped is sparse */ @@ -1300,6 +1310,7 @@ DevmemIntMapPMR2(DEVMEMINT_HEAP *psDevmemHeap, psReservation->psMappedPMR = psPMR; + PMRUnlockPMR(psPMR); OSLockRelease(psReservation->hLock); return PVRSRV_OK; @@ -1314,7 +1325,11 @@ DevmemIntMapPMR2(DEVMEMINT_HEAP *psDevmemHeap, 0); ErrorFreeSparseTmpBuf: OSFreeMem(pvTmpBuf); + ErrorUnlockPhysAddr: + PMRGpuResCountDecr(psPMR); + PMRUnlockPMR(psPMR); + { PVRSRV_ERROR eError1 = PVRSRV_OK; eError1 = PMRUnlockSysPhysAddresses(psPMR); @@ -1325,6 +1340,7 @@ DevmemIntMapPMR2(DEVMEMINT_HEAP *psDevmemHeap, /* if fails there's not much to do (the function will print an error) */ DevmemIntReservationReleaseUnlocked(psReservation); +ErrorReleaseResLock: OSLockRelease(psReservation->hLock); ErrorReturnError: @@ -1444,6 +1460,8 @@ DevmemIntUnmapPMR2(DEVMEMINT_RESERVATION2 *psReservation) sAllocationDevVAddr = psReservation->sBase; OSLockAcquire(psReservation->hLock); + PMRLockPMR(psReservation->psMappedPMR); + bIsSparse = PMR_IsSparse(psReservation->psMappedPMR); if (bIsSparse) @@ -1478,14 +1496,10 @@ DevmemIntUnmapPMR2(DEVMEMINT_RESERVATION2 *psReservation) PVR_LOG_GOTO_IF_ERROR(eError, "MMU_UnmapPMRFast", ErrUnlock); } -#if defined(SUPPORT_PMR_DEFERRED_FREE) - /* If PMR is allocated on demand the backing memory is freed by - * pfnUnlockPhysAddresses(). */ - if (!PVRSRV_CHECK_ON_DEMAND(PMR_Flags(psReservation->psMappedPMR))) - { - PMRMarkForDeferFree(psReservation->psMappedPMR); - } -#endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ + + PMRGpuResCountDecr(psReservation->psMappedPMR); + + PMRUnlockPMR(psReservation->psMappedPMR); eError = PMRUnlockSysPhysAddresses(psReservation->psMappedPMR); PVR_ASSERT(eError == PVRSRV_OK); @@ -1499,6 +1513,7 @@ DevmemIntUnmapPMR2(DEVMEMINT_RESERVATION2 *psReservation) return PVRSRV_OK; ErrUnlock: + PMRUnlockPMR(psReservation->psMappedPMR); OSLockRelease(psReservation->hLock); return eError; @@ -1731,6 +1746,57 @@ DevmemIntChangeSparse(DEVMEMINT_HEAP *psDevmemHeap, } static PVRSRV_ERROR +DevmemIntChangeSparseValidateParams(PMR *psPMR, + IMG_UINT32 ui32AllocPageCount, + IMG_UINT32 ui32FreePageCount, + IMG_UINT32 ui32LogicalChunkCount, + SPARSE_MEM_RESIZE_FLAGS uiSparseFlags) +{ + /* Ensure a PMR has been mapped to this reservation. */ + PVR_LOG_RETURN_IF_INVALID_PARAM(uiSparseFlags & SPARSE_RESIZE_BOTH, "uiSparseFlags"); + + if (!PMR_IsSparse(psPMR) || PMR_IsMemLayoutFixed(psPMR) || + PMR_IsCpuMapped(psPMR)) + { + PVR_DPF((PVR_DBG_ERROR, + "%s: PMR cannot be changed because one or more of the following" + " were true: !PMR_IsSparse() = %s, PMR_IsMemLayoutFixed() = %s," + " PMR_IsCpuMapped() = %s", + __func__, + !PMR_IsSparse(psPMR) ? "true" : "false", + PMR_IsMemLayoutFixed(psPMR) ? "true" : "false", + PMR_IsCpuMapped(psPMR) ? "true" : "false")); + return PVRSRV_ERROR_PMR_NOT_PERMITTED; + } + + if (PMR_IsGpuMultiMapped(psPMR)) + { + PVR_DPF((PVR_DBG_ERROR, + "%s: PMR cannot be changed because PMR_IsGpuMultiMapped() = true", + __func__)); + return PVRSRV_ERROR_PMR_NOT_PERMITTED; + } + + if (uiSparseFlags & SPARSE_RESIZE_ALLOC) + { + PVR_LOG_RETURN_IF_INVALID_PARAM(ui32AllocPageCount != 0, "ui32AllocPageCount"); + PVR_LOG_RETURN_IF_FALSE(ui32AllocPageCount <= ui32LogicalChunkCount, + "ui32AllocPageCount is invalid", + PVRSRV_ERROR_PMR_BAD_MAPPINGTABLE_SIZE); + } + + if (uiSparseFlags & SPARSE_RESIZE_FREE) + { + PVR_LOG_RETURN_IF_INVALID_PARAM(ui32FreePageCount != 0, "ui32FreePageCount"); + PVR_LOG_RETURN_IF_FALSE(ui32FreePageCount <= ui32LogicalChunkCount, + "ui32FreePageCount is invalid", + PVRSRV_ERROR_PMR_BAD_MAPPINGTABLE_SIZE); + } + + return PVRSRV_OK; +} + +static PVRSRV_ERROR DevmemIntValidateSparsePMRIndices(IMG_UINT32 ui32PMRLogicalChunkCount, IMG_UINT32 *paui32LogicalIndices, IMG_UINT32 ui32LogicalIndiceCount) @@ -1802,8 +1868,8 @@ DevmemIntChangeSparse2(DEVMEMINT_HEAP *psDevmemHeap, { PVRSRV_ERROR eError = PVRSRV_OK; - IMG_UINT32 uiLog2PMRContiguity; - IMG_UINT32 uiLog2HeapContiguity; + IMG_UINT32 ui32Log2PMRContiguity; + IMG_UINT32 ui32Log2HeapContiguity; IMG_UINT32 uiOrderDiff; PVRSRV_MEMALLOCFLAGS_T uiFlags; @@ -1815,13 +1881,14 @@ DevmemIntChangeSparse2(DEVMEMINT_HEAP *psDevmemHeap, IMG_UINT64 ui64PMRLogicalSize; IMG_UINT32 ui32LogicalChunkCount; + OSLockAcquire(psReservation->hLock); + + uiFlags = psReservation->uiFlags; + + PVR_LOG_GOTO_IF_INVALID_PARAM(psReservation->psMappedPMR != NULL, eError, InvalidPMRErr); + PVR_UNREFERENCED_PARAMETER(psDevmemHeap); - PMR_LogicalSize(psPMR, &ui64PMRLogicalSize); - ui32LogicalChunkCount = ui64PMRLogicalSize >> PMR_GetLog2Contiguity(psPMR); - - /* Ensure a PMR has been mapped to this reservation. */ - PVR_LOG_RETURN_IF_INVALID_PARAM(psReservation->psMappedPMR != NULL, "psReservation"); { IMG_UINT64 ui64PMRUID; @@ -1835,63 +1902,38 @@ DevmemIntChangeSparse2(DEVMEMINT_HEAP *psDevmemHeap, PVR_DPF((PVR_DBG_ERROR, "%s: Reservation doesn't represent virtual range associated" " with given mapped PMR", __func__)); - return PVRSRV_ERROR_INVALID_PARAMS; + PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_INVALID_PARAMS, InvalidPMRErr); } } psPMR = psReservation->psMappedPMR; + PMRLockPMR(psPMR); - if (!PMR_IsSparse(psPMR)) - { - PVR_DPF((PVR_DBG_ERROR, - "%s: Given PMR is not Sparse", - __func__)); - return PVRSRV_ERROR_INVALID_PARAMS; - } + ui32Log2PMRContiguity = PMR_GetLog2Contiguity(psPMR); - uiLog2PMRContiguity = PMR_GetLog2Contiguity(psPMR); - uiLog2HeapContiguity = psReservation->psDevmemHeap->uiLog2PageSize; + PMR_LogicalSize(psPMR, &ui64PMRLogicalSize); + ui32LogicalChunkCount = ui64PMRLogicalSize >> ui32Log2PMRContiguity; - /* This is check is made in DevmemIntMapPMR - no need to do it again in release. */ - PVR_ASSERT(uiLog2HeapContiguity <= uiLog2PMRContiguity); + ui32Log2HeapContiguity = psReservation->psDevmemHeap->uiLog2PageSize; - if (uiSparseFlags & SPARSE_RESIZE_ALLOC) - { - PVR_LOG_RETURN_IF_INVALID_PARAM(ui32AllocPageCount != 0, "ui32AllocPageCount"); - PVR_LOG_RETURN_IF_FALSE(ui32AllocPageCount <= ui32LogicalChunkCount, - "ui32AllocPageCount is invalid", - PVRSRV_ERROR_PMR_BAD_MAPPINGTABLE_SIZE); - } + eError = DevmemIntChangeSparseValidateParams(psPMR, + ui32AllocPageCount, + ui32FreePageCount, + ui32LogicalChunkCount, + uiSparseFlags); + PVR_LOG_GOTO_IF_ERROR(eError, "DevmemIntChangeSparseValidateParams", e0); - if (uiSparseFlags & SPARSE_RESIZE_FREE) - { - PVR_LOG_RETURN_IF_INVALID_PARAM(ui32FreePageCount != 0, "ui32FreePageCount"); - PVR_LOG_RETURN_IF_FALSE(ui32FreePageCount <= ui32LogicalChunkCount, - "ui32FreePageCount is invalid", - PVRSRV_ERROR_PMR_BAD_MAPPINGTABLE_SIZE); - } - - if (PMR_IsMemLayoutFixed(psPMR) || PMR_IsCpuMapped(psPMR)) - { - PVR_DPF((PVR_DBG_ERROR, - "%s: This PMR layout cannot be changed - PMR_IsMemLayoutFixed()=%c, _PMR_IsMapped()=%c", - __func__, - PMR_IsMemLayoutFixed(psPMR) ? 'Y' : 'n', - PMR_IsCpuMapped(psPMR) ? 'Y' : 'n')); - return PVRSRV_ERROR_PMR_NOT_PERMITTED; - } - - uiFlags = psReservation->uiFlags; eError = DevmemValidateFlags(psPMR, uiFlags); PVR_LOG_GOTO_IF_ERROR(eError, "DevmemValidateFlags", e0); + /* This is check is made in DevmemIntMapPMR - no need to do it again in release. */ + PVR_ASSERT(ui32Log2HeapContiguity <= ui32Log2PMRContiguity); + pai32MapIndices = pai32AllocIndices; pai32UnmapIndices = pai32FreeIndices; uiMapPageCount = ui32AllocPageCount; uiUnmapPageCount = ui32FreePageCount; - OSLockAcquire(psReservation->hLock); - /* * The order of steps in which this request is done is given below. The order of * operations is very important in this case: @@ -1929,7 +1971,7 @@ DevmemIntChangeSparse2(DEVMEMINT_HEAP *psDevmemHeap, PVR_LOG_GOTO_IF_ERROR(eError, "DevmemIntValidateSparsePMRIndices", e0); } - uiOrderDiff = uiLog2PMRContiguity - uiLog2HeapContiguity; + uiOrderDiff = ui32Log2PMRContiguity - ui32Log2HeapContiguity; /* Special case: * Adjust indices if we map into a heap that uses smaller page sizes @@ -2032,7 +2074,7 @@ DevmemIntChangeSparse2(DEVMEMINT_HEAP *psDevmemHeap, psReservation->sBase, uiUnmapPageCount, pai32UnmapIndices, - uiLog2HeapContiguity, + ui32Log2HeapContiguity, uiPMRFlags); PVR_LOG_GOTO_IF_ERROR(eError, "MMU_UnmapPages", e1); @@ -2051,12 +2093,12 @@ DevmemIntChangeSparse2(DEVMEMINT_HEAP *psDevmemHeap, } /* Do the PMR specific changes */ - eError = PMR_ChangeSparseMem(psPMR, - ui32AllocPageCount, - pai32AllocIndices, - ui32FreePageCount, - pai32FreeIndices, - uiSparseFlags); + eError = PMR_ChangeSparseMemUnlocked(psPMR, + ui32AllocPageCount, + pai32AllocIndices, + ui32FreePageCount, + pai32FreeIndices, + uiSparseFlags); if (PVRSRV_OK != eError) { PVR_DPF((PVR_DBG_MESSAGE, @@ -2077,7 +2119,7 @@ DevmemIntChangeSparse2(DEVMEMINT_HEAP *psDevmemHeap, 0, uiMapPageCount, pai32MapIndices, - uiLog2HeapContiguity); + ui32Log2HeapContiguity); if (PVRSRV_OK != eError) { PVR_DPF((PVR_DBG_MESSAGE, @@ -2134,6 +2176,8 @@ DevmemIntChangeSparse2(DEVMEMINT_HEAP *psDevmemHeap, OSFreeMem(pai32UnmapIndices); } e0: + PMRUnlockPMR(psPMR); +InvalidPMRErr: OSLockRelease(psReservation->hLock); return eError; }
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/handle.c b/drivers/gpu/img-rogue/23.2/services/server/common/handle.c index 7d0b48d..3761897 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/handle.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/handle.c
@@ -1764,6 +1764,7 @@ PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase, return PVRSRV_OK; ErrorDestroyHandleBase: + eError = PVRSRV_ERROR_INVALID_PARAMS; (void)gpsHandleFuncs->pfnDestroyHandleBase(psBase->psImplBase); ErrorUnlock: @@ -2109,6 +2110,8 @@ PVRSRV_ERROR PVRSRVFreeKernelHandles(PVRSRV_HANDLE_BASE *psBase) return eError; } +/* Only called from sync_fallback_server.c */ +#if defined(SUPPORT_FALLBACK_FENCE_SYNC) /*! ******************************************************************************* @Function PVRSRVRetrieveProcessHandleBase @@ -2148,8 +2151,13 @@ PVRSRV_HANDLE_BASE *PVRSRVRetrieveProcessHandleBase(void) /* Not being called from the cleanup thread, so return the process * handle base for the current process. */ + uintptr_t uiHashKey; + + uiHashKey = OSAcquireCurrentPPIDResourceRefKM(); + OSReleasePPIDResourceRefKM(uiHashKey); + psProcHandleBase = (PROCESS_HANDLE_BASE *) - HASH_Retrieve(g_psProcessHandleBaseTable, OSGetCurrentClientProcessIDKM()); + HASH_Retrieve(g_psProcessHandleBaseTable, uiHashKey); } OSLockRelease(g_hProcessHandleBaseLock); @@ -2160,26 +2168,30 @@ PVRSRV_HANDLE_BASE *PVRSRVRetrieveProcessHandleBase(void) } return psHandleBase; } +#endif /*! ******************************************************************************* @Function PVRSRVAcquireProcessHandleBase - @Description Increments reference count on a process handle base identified - by uiPid and returns pointer to the base. If the handle base - does not exist it will be allocated. - @Inout uiPid - PID of a process - @Output ppsBase - pointer to a handle base for the process identified by - uiPid + @Description Increments reference count on the process handle base for the + current process and returns pointer to the base. If the handle + base does not exist it will be allocated. + @Output ppsBase - pointer to a handle base for the current process @Return Error code or PVRSRV_OK ******************************************************************************/ -PVRSRV_ERROR PVRSRVAcquireProcessHandleBase(IMG_PID uiPid, PROCESS_HANDLE_BASE **ppsBase) +PVRSRV_ERROR PVRSRVAcquireProcessHandleBase(PROCESS_HANDLE_BASE **ppsBase) { PROCESS_HANDLE_BASE *psBase; PVRSRV_ERROR eError; + uintptr_t uiHashKey; OSLockAcquire(g_hProcessHandleBaseLock); - psBase = (PROCESS_HANDLE_BASE*) HASH_Retrieve(g_psProcessHandleBaseTable, uiPid); + /* Acquire the process resource hash key (and take ref) */ + uiHashKey = OSAcquireCurrentPPIDResourceRefKM(); + PVR_ASSERT(uiHashKey != 0); + + psBase = (PROCESS_HANDLE_BASE*) HASH_Retrieve(g_psProcessHandleBaseTable, uiHashKey); /* In case there is none we are going to allocate one */ if (psBase == NULL) @@ -2194,7 +2206,8 @@ PVRSRV_ERROR PVRSRVAcquireProcessHandleBase(IMG_PID uiPid, PROCESS_HANDLE_BASE * PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVAllocHandleBase", ErrorFreeProcessHandleBase); /* Insert the handle base into the global hash table */ - bSuccess = HASH_Insert(g_psProcessHandleBaseTable, uiPid, (uintptr_t) psBase); + psBase->uiHashKey = uiHashKey; + bSuccess = HASH_Insert(g_psProcessHandleBaseTable, uiHashKey, (uintptr_t)psBase); PVR_LOG_GOTO_IF_FALSE(bSuccess, "HASH_Insert failed", ErrorFreeHandleBase); } @@ -2207,10 +2220,12 @@ PVRSRV_ERROR PVRSRVAcquireProcessHandleBase(IMG_PID uiPid, PROCESS_HANDLE_BASE * return PVRSRV_OK; ErrorFreeHandleBase: + eError = PVRSRV_ERROR_INVALID_PARAMS; PVRSRVFreeHandleBase(psBase->psHandleBase, 0); ErrorFreeProcessHandleBase: OSFreeMem(psBase); ErrorUnlock: + OSReleasePPIDResourceRefKM(uiHashKey); OSLockRelease(g_hProcessHandleBaseLock); return eError; @@ -2220,22 +2235,21 @@ PVRSRV_ERROR PVRSRVAcquireProcessHandleBase(IMG_PID uiPid, PROCESS_HANDLE_BASE * ******************************************************************************* @Function PVRSRVReleaseProcessHandleBase @Description Decrements reference count on a process handle base psBase - for a process identified by uiPid. If the reference count - reaches 0 the handle base will be freed.. + for the current process. If the reference count reaches 0 the + process handle base will be freed. @Input psBase - pointer to a process handle base - @Inout uiPid - PID of a process @Inout ui64MaxBridgeTime - maximum time a handle destroy operation can hold the handle base lock (after that time a lock will be release and reacquired for another time slice) @Return Error code or PVRSRV_OK ******************************************************************************/ -PVRSRV_ERROR PVRSRVReleaseProcessHandleBase(PROCESS_HANDLE_BASE *psBase, IMG_PID uiPid, +PVRSRV_ERROR PVRSRVReleaseProcessHandleBase(PROCESS_HANDLE_BASE *psBase, IMG_UINT64 ui64MaxBridgeTime) { PVRSRV_ERROR eError; IMG_INT iRefCount; - uintptr_t uiHashValue; + uintptr_t uiHashValue = 0; OSLockAcquire(g_hProcessHandleBaseLock); @@ -2243,6 +2257,8 @@ PVRSRV_ERROR PVRSRVReleaseProcessHandleBase(PROCESS_HANDLE_BASE *psBase, IMG_PID if (iRefCount != 0) { + /* Release the process resource hash key (drop ref) */ + OSReleasePPIDResourceRefKM(psBase->uiHashKey); OSLockRelease(g_hProcessHandleBaseLock); return PVRSRV_OK; } @@ -2250,7 +2266,10 @@ PVRSRV_ERROR PVRSRVReleaseProcessHandleBase(PROCESS_HANDLE_BASE *psBase, IMG_PID /* in case the refcount becomes 0 we can remove the process handle base * and all related objects */ - uiHashValue = HASH_Remove(g_psProcessHandleBaseTable, uiPid); + uiHashValue = HASH_Remove(g_psProcessHandleBaseTable, psBase->uiHashKey); + /* Release the process resource hash key (drop ref) */ + OSReleasePPIDResourceRefKM(psBase->uiHashKey); + psBase->uiHashKey = 0; OSLockRelease(g_hProcessHandleBaseLock); PVR_LOG_RETURN_IF_FALSE(uiHashValue != 0, "HASH_Remove failed",
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/mmu_common.c b/drivers/gpu/img-rogue/23.2/services/server/common/mmu_common.c index 7269673..cabc077 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/mmu_common.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/mmu_common.c
@@ -3205,6 +3205,10 @@ MMU_MapPages(MMU_CONTEXT *psMMUContext, } } +#if defined(SUPPORT_PMR_DEFERRED_FREE) + PMRMarkForDeferFree(psPMR); +#endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ + OSLockAcquire(psMMUContext->hLock); for (uiLoop = 0; uiLoop < ui32MapPageCount; uiLoop++) @@ -3892,7 +3896,7 @@ MMUX_MapVRangeToBackingPage(MMU_CONTEXT *psMMUContext, PVRSRV_ERROR MMU_MapPMRFast(MMU_CONTEXT *psMMUContext, IMG_DEV_VIRTADDR sDevVAddrBase, - const PMR *psPMR, + PMR *psPMR, IMG_DEVMEM_SIZE_T uiSizeBytes, PVRSRV_MEMALLOCFLAGS_T uiMappingFlags, IMG_UINT32 uiLog2HeapPageSize) @@ -3969,6 +3973,10 @@ MMU_MapPMRFast(MMU_CONTEXT *psMMUContext, PVR_LOG_GOTO_WITH_ERROR("psConfig->uiBytesPerEntry", eError, PVRSRV_ERROR_MMU_CONFIG_IS_WRONG, put_mmu_context); } +#if defined(SUPPORT_PMR_DEFERRED_FREE) + PMRMarkForDeferFree(psPMR); +#endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ + OSLockAcquire(psMMUContext->hLock); do
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/pdump_server.c b/drivers/gpu/img-rogue/23.2/services/server/common/pdump_server.c index 48f6dbe..45dac0f 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/pdump_server.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/pdump_server.c
@@ -3950,7 +3950,7 @@ PVRSRV_ERROR PDumpCommentWithFlagsVA(PVRSRV_DEVICE_NODE *psDeviceNode, const IMG_CHAR * pszFormat, va_list args) { IMG_INT32 iCount; - PVRSRV_ERROR eErr = PVRSRV_OK; + PVRSRV_ERROR eErr = PVRSRV_ERROR_INVALID_PARAMS; PDUMP_GET_MSG_STRING(); /* Construct the string */
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/physheap.c b/drivers/gpu/img-rogue/23.2/services/server/common/physheap.c index 4b57898..ff72f5e 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/physheap.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/physheap.c
@@ -370,7 +370,7 @@ static PVRSRV_ERROR PhysHeapCreatePropertiesString(PHYS_HEAP *psPhysHeap, iCount = OSSNPrintf(pszPhysHeapString, ui32Size, - "0x%p -> PdMs: %s, Type: %s, " + "0x"IMG_KM_PTR_FMTSPEC" -> PdMs: %s, Type: %s, " "CPU PA Base: " CPUPHYADDR_UINT_FMTSPEC", " "GPU PA Base: 0x%08"IMG_UINT64_FMTSPECx", " "Usage Flags: 0x%08x (%s), Refs: %d, " @@ -391,7 +391,7 @@ static PVRSRV_ERROR PhysHeapCreatePropertiesString(PHYS_HEAP *psPhysHeap, { iCount = OSSNPrintf(pszPhysHeapString, ui32Size, - "0x%p -> PdMs: %s, Type: %s, " + "0x"IMG_KM_PTR_FMTSPEC" -> PdMs: %s, Type: %s, " "Usage Flags: 0x%08x (%s), Refs: %d, " "Free Size: %"IMG_UINT64_FMTSPEC"B, " "Total Size: %"IMG_UINT64_FMTSPEC"B",
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/physmem.c b/drivers/gpu/img-rogue/23.2/services/server/common/physmem.c index ed2f2f5..e729683 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/physmem.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/physmem.c
@@ -354,6 +354,16 @@ PVRSRV_ERROR PhysMemValidateParams(IMG_UINT32 ui32NumPhysChunks, return PVRSRV_ERROR_INVALID_FLAGS; } + /* Sparse allocations must be backed immediately as the requested + * pui32MappingTable is not retained in any structure if not immediately + * actioned on allocation. + */ + if (PVRSRV_CHECK_ON_DEMAND(uiFlags) && bIsSparse) + { + PVR_DPF((PVR_DBG_ERROR, "%s: Invalid to specify ON_DEMAND for a sparse allocation: 0x%" IMG_UINT64_FMTSPECX, __func__, uiFlags)); + return PVRSRV_ERROR_INVALID_FLAGS; + } + if (ui32NumVirtChunks == 0) { PVR_DPF((PVR_DBG_ERROR, "%s: Number of virtual chunks cannot be 0",
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/physmem_lma.c b/drivers/gpu/img-rogue/23.2/services/server/common/physmem_lma.c index 4a5cf61..cbbc44b 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/physmem_lma.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/physmem_lma.c
@@ -162,6 +162,11 @@ typedef struct _PMR_LMALLOCARRAY_DATA_ { } PMR_LMALLOCARRAY_DATA; +static PVRSRV_ERROR +_FreeLMPages(PMR_LMALLOCARRAY_DATA *psPageArrayData, + IMG_UINT32 *pui32FreeIndices, + IMG_UINT32 ui32FreeChunkCount); + #if defined(DEBUG) && defined(SUPPORT_VALIDATION) && defined(__linux__) /* Global structure to manage GPU memory leak */ static DEFINE_MUTEX(g_sLMALeakMutex); @@ -1881,6 +1886,130 @@ _FreeLMPagesSparse(PMR_LMALLOCARRAY_DATA *psPageArrayData, return PVRSRV_OK; } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +static PVRSRV_ERROR PMRFreeZombiePagesRAMem(PMR_IMPL_ZOMBIEPAGES pvPriv) +{ + PVRSRV_ERROR eError; + PMR_LMALLOCARRAY_DATA *psZombiePageArray = pvPriv; + + eError = _FreeLMPages(psZombiePageArray, NULL, 0); + PVR_GOTO_IF_ERROR(eError, e0); + + _FreeLMPageArray(psZombiePageArray); + return PVRSRV_OK; +e0: + return eError; +} + +/* Allocates a new PMR_LMALLOCARRAY_DATA object and fills it with + * pages to be extracted from psSrcPageArrayData. + */ +static PVRSRV_ERROR +_ExtractPages(PMR_LMALLOCARRAY_DATA *psSrcPageArrayData, + IMG_UINT32 *pai32ExtractIndices, + IMG_UINT32 ui32ExtractPageCount, + PMR_LMALLOCARRAY_DATA **psOutPageArrayData) +{ + PVRSRV_ERROR eError; + IMG_UINT32 ui32ExtractPageCountSaved; + PMR_LMALLOCARRAY_DATA* psDstPageArrayData; + + /* Alloc PMR_LMALLOCARRAY_DATA for the extracted pages */ + eError = _AllocLMPageArray((IMG_UINT64)ui32ExtractPageCount << psSrcPageArrayData->uiLog2ChunkSize, + ui32ExtractPageCount, + ui32ExtractPageCount, + psSrcPageArrayData->uiLog2ChunkSize, + psSrcPageArrayData->ui32Flags, + psSrcPageArrayData->psPhysHeap, + psSrcPageArrayData->uiAllocFlags, + psSrcPageArrayData->uiPid, + &psDstPageArrayData, + psSrcPageArrayData->psConnection); + PVR_LOG_GOTO_IF_ERROR(eError, "_AllocLMPageArray", alloc_error); + + psDstPageArrayData->psArena = psSrcPageArrayData->psArena; + + ui32ExtractPageCountSaved = ui32ExtractPageCount; + /* Transfer pages from source base array to newly allocated page array */ + eError = RA_TransferMultiSparseIndices(psSrcPageArrayData->psArena, + psSrcPageArrayData->aBaseArray, + psSrcPageArrayData->uiTotalNumChunks, + psDstPageArrayData->aBaseArray, + psDstPageArrayData->uiTotalNumChunks, + psSrcPageArrayData->uiLog2ChunkSize, + pai32ExtractIndices, + &ui32ExtractPageCountSaved); + PVR_LOG_GOTO_IF_FALSE((eError == PVRSRV_OK) && (ui32ExtractPageCountSaved == ui32ExtractPageCount), + "RA_TransferMultiSparseIndices failed", + transfer_error); + + + /* Update page counts */ + psSrcPageArrayData->iNumChunksAllocated -= ui32ExtractPageCount; + psDstPageArrayData->iNumChunksAllocated += ui32ExtractPageCount; + + *psOutPageArrayData = psDstPageArrayData; + + return PVRSRV_OK; +transfer_error: + _FreeLMPageArray(psDstPageArrayData); +alloc_error: + return eError; +} + +/* Extracts all allocated pages referenced psSrcPageArrayData + * Allocates a new PMR_OSPAGEARRAY_DATA object and fills it with the extracted + * pages information. + */ +static PVRSRV_ERROR +_ExtractAllPages(PMR_LMALLOCARRAY_DATA *psSrcPageArrayData, + PMR_LMALLOCARRAY_DATA **psOutPageArrayData) +{ + PVRSRV_ERROR eError; + PMR_LMALLOCARRAY_DATA* psDstPageArrayData; + IMG_UINT32 ui32IdxSrc, ui32IdxDst; + + if (psSrcPageArrayData->iNumChunksAllocated == 0) + { + /* Do nothing if psSrcPageArrayData contains no allocated pages */ + return PVRSRV_OK; + } + + /* Alloc PMR_LMALLOCARRAY_DATA for the extracted pages */ + eError = _AllocLMPageArray((IMG_UINT64)psSrcPageArrayData->iNumChunksAllocated << psSrcPageArrayData->uiLog2ChunkSize, + psSrcPageArrayData->iNumChunksAllocated, + psSrcPageArrayData->uiTotalNumChunks, + psSrcPageArrayData->uiLog2ChunkSize, + psSrcPageArrayData->ui32Flags, + psSrcPageArrayData->psPhysHeap, + psSrcPageArrayData->uiAllocFlags, + psSrcPageArrayData->uiPid, + &psDstPageArrayData, + psSrcPageArrayData->psConnection); + PVR_LOG_RETURN_IF_ERROR_VA(eError, "_AllocLMPageArray failed in %s", __func__); + + /* Now do the transfer */ + ui32IdxDst=0; + for (ui32IdxSrc=0; ((ui32IdxDst<psSrcPageArrayData->iNumChunksAllocated) && + (psDstPageArrayData->iNumChunksAllocated<psSrcPageArrayData->iNumChunksAllocated)); ui32IdxSrc++) + { + if (psSrcPageArrayData->aBaseArray[ui32IdxSrc] != INVALID_BASE_ADDR) + { + psDstPageArrayData->aBaseArray[ui32IdxDst++] = psSrcPageArrayData->aBaseArray[ui32IdxSrc]; + psSrcPageArrayData->aBaseArray[ui32IdxSrc] = INVALID_BASE_ADDR; + psDstPageArrayData->iNumChunksAllocated++; + } + } + + /* Update src page count */ + psSrcPageArrayData->iNumChunksAllocated = 0; + + *psOutPageArrayData = psDstPageArrayData; + + return PVRSRV_OK; +} +#endif /* defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) */ + static PVRSRV_ERROR _FreeLMPages(PMR_LMALLOCARRAY_DATA *psPageArrayData, IMG_UINT32 *pui32FreeIndices, @@ -2088,21 +2217,53 @@ PMRLockSysPhysAddressesLocalMem(PMR_IMPL_PRIVDATA pvPriv) return PVRSRV_OK; } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +static PVRSRV_ERROR +PMRUnlockSysPhysAddressesLocalMem(PMR_IMPL_PRIVDATA pvPriv, + PMR_IMPL_ZOMBIEPAGES *ppvZombiePages) +#else static PVRSRV_ERROR PMRUnlockSysPhysAddressesLocalMem(PMR_IMPL_PRIVDATA pvPriv) +#endif { PVRSRV_ERROR eError = PVRSRV_OK; - PMR_LMALLOCARRAY_DATA *psLMAllocArrayData; + PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = pvPriv; +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_LMALLOCARRAY_DATA *psExtractedPagesPageArray = NULL; - psLMAllocArrayData = pvPriv; + *ppvZombiePages = NULL; +#endif if (BIT_ISSET(psLMAllocArrayData->ui32Flags, FLAG_ONDEMAND)) { +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + if (psLMAllocArrayData->iNumChunksAllocated == 0) + { + *ppvZombiePages = NULL; + return PVRSRV_OK; + } + + eError = _ExtractAllPages(psLMAllocArrayData, + &psExtractedPagesPageArray); + PVR_LOG_GOTO_IF_ERROR(eError, "_ExtractAllPages", e0); + + if (psExtractedPagesPageArray) + { + /* Zombify pages to get proper stats */ + eError = PMRZombifyLocalMem(psExtractedPagesPageArray, NULL); + PVR_WARN_IF_ERROR(eError, "PMRZombifyLocalMem"); + } + *ppvZombiePages = psExtractedPagesPageArray; +#else /* Free Memory for deferred allocation */ eError = _FreeLMPages(psLMAllocArrayData, NULL, 0); PVR_RETURN_IF_ERROR(eError); +#endif } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +e0: +#endif PVR_ASSERT(eError == PVRSRV_OK); return eError; } @@ -2481,6 +2642,9 @@ PMRChangeSparseMemLocalMem(PMR_IMPL_PRIVDATA pPriv, IMG_UINT32 *pai32AllocIndices, IMG_UINT32 ui32FreePageCount, IMG_UINT32 *pai32FreeIndices, +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_IMPL_ZOMBIEPAGES *ppvZombiePages, +#endif IMG_UINT32 uiFlags) { PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS; @@ -2506,6 +2670,10 @@ PMRChangeSparseMemLocalMem(PMR_IMPL_PRIVDATA pPriv, RA_BASE_T *paBaseArray = psPMRPageArrayData->aBaseArray; PMR_MAPPING_TABLE *psPMRMapTable = PMR_GetMappingTable(psPMR); +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + *ppvZombiePages = NULL; +#endif + /* The incoming request is classified into two operations independent of * each other: alloc & free chunks. * These operations can be combined with two mapping operations as well @@ -2678,13 +2846,25 @@ PMRChangeSparseMemLocalMem(PMR_IMPL_PRIVDATA pPriv, } } - /* Free the additional free chunks */ + /* Free or zombie the additional free chunks */ if (0 != ui32AdtnlFreePages) { - ui32Index = ui32Loop; +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_LMALLOCARRAY_DATA *psExtractedPagesPageArray = NULL; + + eError = _ExtractPages(psPMRPageArrayData, &pai32FreeIndices[ui32Loop], ui32AdtnlFreePages, &psExtractedPagesPageArray); + PVR_LOG_GOTO_IF_ERROR(eError, "_ExtractPages", e0); + + /* Zombify pages to get proper stats */ + eError = PMRZombifyLocalMem(psExtractedPagesPageArray, NULL); + PVR_LOG_IF_ERROR(eError, "PMRZombifyLocalMem"); + + *ppvZombiePages = psExtractedPagesPageArray; +#else eError = _FreeLMPages(psPMRPageArrayData, &pai32FreeIndices[ui32Loop], ui32AdtnlFreePages); PVR_LOG_GOTO_IF_ERROR(eError, "_FreeLMPages", e0); - +#endif /* SUPPORT_PMR_PAGES_DEFERRED_FREE */ + ui32Index = ui32Loop; ui32Loop = 0; while (ui32Loop++ < ui32AdtnlFreePages) @@ -2796,6 +2976,9 @@ static PMR_IMPL_FUNCTAB _sPMRLMAFuncTab = { .pfnChangeSparseMemCPUMap = &PMRChangeSparseMemCPUMapLocalMem, .pfnMMap = NULL, .pfnFinalize = &PMRFinalizeLocalMem, +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + .pfnFreeZombiePages = &PMRFreeZombiePagesRAMem, +#endif #if defined(SUPPORT_PMR_DEFERRED_FREE) .pfnZombify = &PMRZombifyLocalMem, #endif
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/pmr.c b/drivers/gpu/img-rogue/23.2/services/server/common/pmr.c index c3cc242..3126fd1 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/pmr.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/pmr.c
@@ -147,6 +147,49 @@ static struct _PMR_CTX_ IMG_BOOL bModuleInitialised; } _gsSingletonPMRContext = { 1, 0, {0}, NULL, IMG_FALSE }; +#if defined(SUPPORT_PMR_DEFERRED_FREE) +typedef enum _PMR_ZOMBIE_TYPE_ { + PMR_ZOMBIE_TYPE_PMR, +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_ZOMBIE_TYPE_PAGES, +#endif /* defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) */ +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + PMR_ZOMBIE_TYPE_DEVICE_IMPORT, +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ +} PMR_ZOMBIE_TYPE; + +typedef struct _PMR_HEADER_ +{ + /* List node used to put the header on the zombie list + * (psDevNode->sPMRZombieList). */ + DLLIST_NODE sZombieNode; + + PMR_ZOMBIE_TYPE eZombieType; +} PMR_HEADER; +#endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ + +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +/* + * A structure describing zombie pages. + */ +typedef struct _PMR_ZOMBIE_PAGES_ +{ + PMR_HEADER sHeader; + PMR_IMPL_ZOMBIEPAGES pvFactoryPages; + PFN_FREE_ZOMBIE_PAGES_FN pfnFactoryFreeZombies; +} PMR_ZOMBIE_PAGES; +#endif + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) +typedef struct _PMR_DEVICE_IMPORT_ +{ + PMR_HEADER sHeader; /* psDevNode zombie queue list node. */ + DLLIST_NODE sNext; /* PMR::sXDeviceImports list node. */ + PVRSRV_DEVICE_NODE *psDevNode; /* Device this import is representing. */ + PMR *psParent; /* PMR the import belongs to. */ +} PMR_DEVICE_IMPORT; +#endif + /* A PMR. One per physical allocation. May be "shared". * * "shared" is ambiguous. We need to be careful with terminology. @@ -164,9 +207,8 @@ static struct _PMR_CTX_ struct _PMR_ { #if defined(SUPPORT_PMR_DEFERRED_FREE) - /* List node used to put the PMR on the zombie list - * (psDevNode->sPMRZombieList). */ - DLLIST_NODE sZombieNode; + /* A Common header structure shared between PMR and PMR-like PMR_ZOMBIE_PAGES object */ + PMR_HEADER sHeader; #endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ /* This object is strictly refcounted. References include: @@ -193,6 +235,12 @@ struct _PMR_ */ ATOMIC_T iCpuMapCount; + /* Count of how many reservations refer to this + * PMR as a part of a GPU mapping. Must be protected + * by PMR lock. + */ + IMG_INT32 iAssociatedResCount; + /* Lock count - this is the number of times PMRLockSysPhysAddresses() * has been called, less the number of PMRUnlockSysPhysAddresses() * calls. This is arguably here for debug reasons only, as the refcount @@ -205,6 +253,16 @@ struct _PMR_ /* Lock for this structure */ POS_LOCK hLock; + /* Protects: `uiInternalFlags` & `uiDevImportBitmap` */ + POS_SPINLOCK hBitmapLock; + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + /* See PMR_ImportedDevicesMask() + * Protected by hBitmapLock. */ + IMG_UINT64 uiDevImportBitmap; + /* List of PMR_DEVICE_IMPORT's */ + DLLIST_NODE sXDeviceImports; +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ /* Incrementing serial number to each allocation. */ IMG_UINT64 uiSerialNum; @@ -484,9 +542,18 @@ _PMRCreate(PMR_SIZE_T uiLogicalSize, return eError; } + eError = OSSpinLockCreate(&psPMR->hBitmapLock); + if (eError != PVRSRV_OK) + { + OSLockDestroy(psPMR->hLock); + OSFreeMem(psPMR); + return eError; + } + /* Setup the PMR */ OSAtomicWrite(&psPMR->iRefCount, 0); OSAtomicWrite(&psPMR->iCpuMapCount, 0); + psPMR->iAssociatedResCount = 0; /* If allocation is not made on demand, it will be backed now and * backing will not be removed until the PMR is destroyed, therefore @@ -502,8 +569,16 @@ _PMRCreate(PMR_SIZE_T uiLogicalSize, psPMR->uiInternalFlags = bSparse ? PMR_FLAG_INTERNAL_SPARSE_ALLOC : 0; psPMR->szAnnotation[0] = '\0'; +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + psPMR->uiDevImportBitmap = 0; +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + #if defined(SUPPORT_PMR_DEFERRED_FREE) - dllist_init(&psPMR->sZombieNode); + psPMR->sHeader.eZombieType = PMR_ZOMBIE_TYPE_PMR; + dllist_init(&psPMR->sHeader.sZombieNode); +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + dllist_init(&psPMR->sXDeviceImports); +#endif /* defined(SUPPORT_DEVICE_IMPORT_DEFERRED_FREE) */ #endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) @@ -566,6 +641,36 @@ PMRUnlockPMR(PMR *psPMR) OSLockRelease(psPMR->hLock); /* Uses same lock as PhysAddresses */ } +static INLINE void _IntFlagSet(PMR *psPMR, const IMG_UINT32 uiValue) +{ + OS_SPINLOCK_FLAGS uiLockingFlags; + + OSSpinLockAcquire(psPMR->hBitmapLock, uiLockingFlags); + BITMASK_SET(psPMR->uiInternalFlags, uiValue); + OSSpinLockRelease(psPMR->hBitmapLock, uiLockingFlags); +} + +static INLINE void _IntFlagClr(PMR *psPMR, const IMG_UINT32 uiValue) +{ + OS_SPINLOCK_FLAGS uiLockingFlags; + + OSSpinLockAcquire(psPMR->hBitmapLock, uiLockingFlags); + BITMASK_UNSET(psPMR->uiInternalFlags, uiValue); + OSSpinLockRelease(psPMR->hBitmapLock, uiLockingFlags); +} + +static INLINE IMG_BOOL _IntFlagIsSet(const PMR *psPMR, const IMG_UINT32 uiValue) +{ + OS_SPINLOCK_FLAGS uiLockingFlags; + IMG_BOOL bIsSet; + + OSSpinLockAcquire(psPMR->hBitmapLock, uiLockingFlags); + bIsSet = BITMASK_HAS(psPMR->uiInternalFlags, uiValue); + OSSpinLockRelease(psPMR->hBitmapLock, uiLockingFlags); + + return bIsSet; +} + static INLINE void _FactoryLock(const PMR_IMPL_FUNCTAB *psFuncTable) { @@ -584,6 +689,243 @@ _FactoryUnlock(const PMR_IMPL_FUNCTAB *psFuncTable) } } +#if defined(SUPPORT_PMR_DEFERRED_FREE) +/* Protects: + * - `psDevNode->sPMRZombieList` + * - `uiPMRZombieCount` + * - `uiPMRZombieCountInCleanup` + * + * and all `PMR_ZOMBIE_CLEANUP_ITEM::sZombieList` where + * `PMR_ZOMBIE_CLEANUP_ITEM::psDevNode == psDevNode` */ +static INLINE void +_ZombieListLock(PPVRSRV_DEVICE_NODE psDevNode) +{ + OSLockAcquire(psDevNode->hPMRZombieListLock); +} + +static INLINE void +_ZombieListUnlock(PPVRSRV_DEVICE_NODE psDevNode) +{ + OSLockRelease(psDevNode->hPMRZombieListLock); +} + +static IMG_BOOL _IsDeviceOnAndOperating(PVRSRV_DEVICE_NODE *psDevNode) +{ + PVRSRV_ERROR eError; + PVRSRV_DEV_POWER_STATE ePowerState; + + eError = PVRSRVGetDevicePowerState(psDevNode, &ePowerState); + if (eError != PVRSRV_OK) + { + /* Treat unknown power state as ON. */ + ePowerState = PVRSRV_DEV_POWER_STATE_ON; + } + + /* The device does not accept zombies when its power is OFF as + * the cache invalidation comes as a given. */ + return !( ePowerState == PVRSRV_DEV_POWER_STATE_OFF + || psDevNode->eDevState == PVRSRV_DEVICE_STATE_PCI_ERROR); +} +#endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) +static IMG_UINT64 +_DeviceImportBitmapGet(const PMR *psPMR) +{ + OS_SPINLOCK_FLAGS uiLockingFlags; + IMG_UINT64 uiDevImportBitmap; + + OSSpinLockAcquire(psPMR->hBitmapLock, uiLockingFlags); + uiDevImportBitmap = psPMR->uiDevImportBitmap; + OSSpinLockRelease(psPMR->hBitmapLock, uiLockingFlags); + + return uiDevImportBitmap; +} + +static void +_DeviceImportBitmapClr(PMR *psPMR, const PPVRSRV_DEVICE_NODE psDevNode) +{ + OS_SPINLOCK_FLAGS uiLockingFlags; + + OSSpinLockAcquire(psPMR->hBitmapLock, uiLockingFlags); + BITMASK_UNSET(psPMR->uiDevImportBitmap, IMG_UINT64_C(1) << psDevNode->sDevId.ui32InternalID); + OSSpinLockRelease(psPMR->hBitmapLock, uiLockingFlags); +} + +static IMG_BOOL +_DeviceImportBitmapIsSet(const PMR *psPMR, const PPVRSRV_DEVICE_NODE psDevNode) +{ + OS_SPINLOCK_FLAGS uiLockingFlags; + IMG_BOOL bIsSet; + + OSSpinLockAcquire(psPMR->hBitmapLock, uiLockingFlags); + bIsSet = BITMASK_HAS(psPMR->uiDevImportBitmap, + IMG_UINT64_C(1) << psDevNode->sDevId.ui32InternalID); + OSSpinLockRelease(psPMR->hBitmapLock, uiLockingFlags); + + return bIsSet; +} + +static IMG_BOOL +/* Atomically, return if the `psDevNode` is set in the bitmap and then set it. */ +_DeviceImportBitmapFetchAndSet(PMR *psPMR, const PPVRSRV_DEVICE_NODE psDevNode) +{ + OS_SPINLOCK_FLAGS uiLockingFlags; + IMG_BOOL bIsSet; + + OSSpinLockAcquire(psPMR->hBitmapLock, uiLockingFlags); + bIsSet = BITMASK_HAS(psPMR->uiDevImportBitmap, + IMG_UINT64_C(1) << psDevNode->sDevId.ui32InternalID); + BITMASK_SET(psPMR->uiDevImportBitmap, + IMG_UINT64_C(1) << psDevNode->sDevId.ui32InternalID); + OSSpinLockRelease(psPMR->hBitmapLock, uiLockingFlags); + + return bIsSet; +} + +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) +static PVRSRV_ERROR +_DeviceImportRegister(PMR *psPMR, PPVRSRV_DEVICE_NODE psDevNode) +{ + PVRSRV_ERROR eError = PVRSRV_OK; + PMR_DEVICE_IMPORT *psImport; + + PVR_ASSERT(psPMR); + PVR_ASSERT(psDevNode); + PVR_ASSERT(PMR_DeviceNode(psPMR) != psDevNode); + + /* Explicitly reject: + * - PVRSRV_MEMALLOCFLAG_DEFER_PHYS_ALLOC + * - !PMR_FLAG_INTERNAL_NO_LAYOUT_CHANGE + * as XD PMRs don't have support for + * SUPPORT_PMR_PAGES_DEFERRED_FREE. */ + if (PVRSRV_CHECK_ON_DEMAND(psPMR->uiFlags) || + !_IntFlagIsSet(psPMR, PMR_FLAG_INTERNAL_NO_LAYOUT_CHANGE)) + { + eError = PVRSRV_ERROR_PMR_NOT_PERMITTED; + PVR_LOG_ERROR(eError, + "PVRSRV_CHECK_ON_DEMAND || !PMR_FLAG_INTERNAL_NO_LAYOUT_CHANGE"); + return eError; + } + + /* Check if the device is already imported */ + if (_DeviceImportBitmapFetchAndSet(psPMR, psDevNode)) + { + return PVRSRV_OK; + } + + psImport = OSAllocMem(sizeof(*psImport)); + PVR_LOG_RETURN_IF_NOMEM(psImport, "PMR_DEVICE_IMPORT"); + + psImport->psParent = psPMR; + psImport->psDevNode = psDevNode; + dllist_init(&psImport->sHeader.sZombieNode); + psImport->sHeader.eZombieType = PMR_ZOMBIE_TYPE_DEVICE_IMPORT; + + PMRLockPMR(psPMR); + dllist_add_to_tail(&psPMR->sXDeviceImports, &psImport->sNext); + PMRUnlockPMR(psPMR); + + return eError; +} + +static void +_DeviceImportFreeImportZombie(PMR_DEVICE_IMPORT *psImport) +{ + PVR_ASSERT(_DeviceImportBitmapIsSet(psImport->psParent, psImport->psDevNode)); + _DeviceImportBitmapClr(psImport->psParent, psImport->psDevNode); + + PMRLockPMR(psImport->psParent); + dllist_remove_node(&psImport->sNext); + PMRUnlockPMR(psImport->psParent); + + OSFreeMem(psImport); +} + +static IMG_BOOL +_DeviceImportEnqueueZombie(PMR_DEVICE_IMPORT *psImport) +{ + PVR_ASSERT(_DeviceImportBitmapIsSet(psImport->psParent, psImport->psDevNode)); + + if (!_IsDeviceOnAndOperating(psImport->psDevNode)) + { + _DeviceImportFreeImportZombie(psImport); + return IMG_FALSE; + } + + _ZombieListLock(psImport->psDevNode); + dllist_add_to_tail(&psImport->psDevNode->sPMRZombieList, + &psImport->sHeader.sZombieNode); + psImport->psDevNode->uiPMRZombieCount++; + _ZombieListUnlock(psImport->psDevNode); + + return IMG_TRUE; +} + +static void +_DeviceImportsReviveZombies(PMR *psPMR) +{ + PDLLIST_NODE psNode, psNext; + PMR_DEVICE_IMPORT *psImport; + + dllist_foreach_node(&psPMR->sXDeviceImports, psNode, psNext) + { + psImport = IMG_CONTAINER_OF(psNode, PMR_DEVICE_IMPORT, sNext); + _ZombieListLock(psImport->psDevNode); + if (!dllist_is_empty(&psImport->sHeader.sZombieNode)) + { + dllist_remove_node(&psImport->sHeader.sZombieNode); + psImport->psDevNode->uiPMRZombieCount--; + } + _ZombieListUnlock(psImport->psDevNode); + } +} + +static IMG_BOOL +_DeviceImportsEnqueueZombies(PMR *psPMR) +{ + PDLLIST_NODE psNode, psNext; + PMR_DEVICE_IMPORT *psImport; + IMG_BOOL bEnqueued = IMG_FALSE; + + PMRLockPMR(psPMR); + + dllist_foreach_node(&psPMR->sXDeviceImports, psNode, psNext) + { + psImport = IMG_CONTAINER_OF(psNode, PMR_DEVICE_IMPORT, sNext); + bEnqueued |= _DeviceImportEnqueueZombie(psImport); + } + + PMRUnlockPMR(psPMR); + + return bEnqueued; +} + +static void +_DeviceImportsUnregisterAll(PMR *psPMR) +{ + OS_SPINLOCK_FLAGS uiLockingFlags; + PDLLIST_NODE psNode, psNext; + + PMRLockPMR(psPMR); + dllist_foreach_node(&psPMR->sXDeviceImports, psNode, psNext) + { + PMR_DEVICE_IMPORT *psImport = IMG_CONTAINER_OF(psNode, PMR_DEVICE_IMPORT, sNext); + PVR_ASSERT(_DeviceImportBitmapIsSet(psPMR, psImport->psDevNode)); + OSFreeMem(psImport); + } + dllist_init(&psPMR->sXDeviceImports); + + OSSpinLockAcquire(psPMR->hBitmapLock, uiLockingFlags); + psPMR->uiDevImportBitmap = 0; + OSSpinLockRelease(psPMR->hBitmapLock, uiLockingFlags); + PMRUnlockPMR(psPMR); +} +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + static void _PMRDestroy(PMR *psPMR) { @@ -630,6 +972,10 @@ _PMRDestroy(PMR *psPMR) } #endif /* if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) */ +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + _DeviceImportsUnregisterAll(psPMR); +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + /* Decrement live PMR count. Probably only of interest for debugging */ PVR_ASSERT(OSAtomicRead(&psPMR->psContext->uiNumLivePMRs) > 0); OSAtomicDecrement(&psPMR->psContext->uiNumLivePMRs); @@ -637,19 +983,57 @@ _PMRDestroy(PMR *psPMR) PVR_DPF((PVR_DBG_MESSAGE, "%s: 0x%p, key:0x%016" IMG_UINT64_FMTSPECX ", numLive:%d", __func__, psPMR, psPMR->uiKey, OSAtomicRead(&psPMR->psContext->uiNumLivePMRs))); + OSSpinLockDestroy(psPMR->hBitmapLock); OSLockDestroy(psPMR->hLock); OSFreeMem(psPMR); } +#if defined(SUPPORT_PMR_DEFERRED_FREE) +static INLINE PMR_ZOMBIE_TYPE +PMR_GetZombieTypeFromNode(const DLLIST_NODE *psNode) +{ + PMR_HEADER *psPMRHeader = IMG_CONTAINER_OF(psNode, PMR_HEADER, sZombieNode); + PVR_ASSERT(psPMRHeader != NULL); + return psPMRHeader->eZombieType; +} + +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +static INLINE PMR_ZOMBIE_PAGES* +PMR_GetZombiePagesFromNode(const DLLIST_NODE *psNode) +{ + PMR_HEADER *psPMRHeader = IMG_CONTAINER_OF(psNode, PMR_HEADER, sZombieNode); + PVR_ASSERT(psPMRHeader != NULL); + return IMG_CONTAINER_OF(psPMRHeader, PMR_ZOMBIE_PAGES, sHeader); +} +#endif /* defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) */ + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) +static INLINE PMR_DEVICE_IMPORT* +PMR_GetDeviceImportFromNode(const DLLIST_NODE *psNode) +{ + PMR_HEADER *psPMRHeader = IMG_CONTAINER_OF(psNode, PMR_HEADER, sZombieNode); + PVR_ASSERT(psPMRHeader != NULL); + return IMG_CONTAINER_OF(psPMRHeader, PMR_DEVICE_IMPORT, sHeader); +} +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + +static INLINE PMR* +PMR_GetPMRFromNode(const DLLIST_NODE *psNode) +{ + PMR_HEADER *psPMRHeader = IMG_CONTAINER_OF(psNode, PMR_HEADER, sZombieNode); + PVR_ASSERT(psPMRHeader != NULL); + return IMG_CONTAINER_OF(psPMRHeader, PMR, sHeader); +} +#endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ + static void _UnrefAndMaybeDestroy(PMR *psPMR) { const PMR_IMPL_FUNCTAB *psFuncTable; IMG_INT iRefCount; #if defined(SUPPORT_PMR_DEFERRED_FREE) - PVRSRV_DEV_POWER_STATE ePowerState; PVRSRV_DEVICE_NODE *psDevNode; - PVRSRV_ERROR eError; + IMG_BOOL bQueuedDeviceImports = IMG_FALSE; #endif PVR_ASSERT(psPMR != NULL); @@ -672,32 +1056,34 @@ _UnrefAndMaybeDestroy(PMR *psPMR) #else /* !defined(SUPPORT_PMR_DEFERRED_FREE) */ psDevNode = PhysHeapDeviceNode(psPMR->psPhysHeap); - eError = PVRSRVGetDevicePowerState(psDevNode, &ePowerState); - if (eError != PVRSRV_OK) + /* PMRs that are not marked for deferred free can be freed right away. + * Those are the PMRs that have not been mapped to the device. + * All PMRs that have been mapped to the device need to go through + * the defer free path unless the power is OFF for the PMR's device + * and for all of the device imports. If power is OFF + * the cache invalidation comes as a given. */ + if (!_IntFlagIsSet(psPMR, PMR_FLAG_INTERNAL_DEFER_FREE)) { - /* Treat unknown power state as ON. */ - ePowerState = PVRSRV_DEV_POWER_STATE_ON; + _PMRDestroy(psPMR); + goto exit_; } - /* PMRs that are not marked for deferred free can be freed right away. - * Those are the PMRs that are not device mappable (so only CPU - * readable/writeable). - * All PMRs that are device mappable need to go through the defer free - * path unless the power is OFF. If power is OFF the cache invalidation - * comes as a given. */ - if (!BITMASK_HAS(psPMR->uiInternalFlags, PMR_FLAG_INTERNAL_DEFER_FREE) || - ePowerState == PVRSRV_DEV_POWER_STATE_OFF || - psDevNode->eDevState == PVRSRV_DEVICE_STATE_PCI_ERROR) +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + bQueuedDeviceImports = _DeviceImportsEnqueueZombies(psPMR); +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + + if (!bQueuedDeviceImports && !_IsDeviceOnAndOperating(psDevNode)) { _PMRDestroy(psPMR); } else { /* Defer freeing the PMR until the Firmware invalidates the caches. */ - OSLockAcquire(psDevNode->hPMRZombieListLock); + _ZombieListLock(psDevNode); - BITMASK_SET(psPMR->uiInternalFlags, PMR_FLAG_INTERNAL_IS_ZOMBIE); - dllist_add_to_tail(&psDevNode->sPMRZombieList, &psPMR->sZombieNode); + _IntFlagSet(psPMR, PMR_FLAG_INTERNAL_IS_ZOMBIE); + + dllist_add_to_tail(&psDevNode->sPMRZombieList, &psPMR->sHeader.sZombieNode); psDevNode->uiPMRZombieCount++; /* PMR pages are accounted by the driver/process stats. Those stats @@ -712,8 +1098,9 @@ _UnrefAndMaybeDestroy(PMR *psPMR) PVR_LOG_IF_ERROR(eError, "pfnZombify"); } - OSLockRelease(psDevNode->hPMRZombieListLock); + _ZombieListUnlock(psDevNode); } +exit_: #endif /* !defined(SUPPORT_PMR_DEFERRED_FREE) */ _FactoryUnlock(psFuncTable); @@ -723,25 +1110,13 @@ _UnrefAndMaybeDestroy(PMR *psPMR) typedef struct _PMR_ZOMBIE_CLEANUP_ITEM_ { PVRSRV_CLEANUP_THREAD_WORK sCleanupThreadFn; - DLLIST_NODE sZombieList; + DLLIST_NODE sZombieList; /*!< See _ZombieListLock */ PPVRSRV_DEVICE_NODE psDevNode; PVRSRV_CLIENT_SYNC_PRIM *psSync; IMG_UINT32 uiRequiredSyncValue; IMG_UINT32 uiRequiredPowerOffCounter; } PMR_ZOMBIE_CLEANUP_ITEM; -static INLINE void -_ZombieListLock(PMR_ZOMBIE_CLEANUP_ITEM *psCleanupItem) -{ - OSLockAcquire(psCleanupItem->psDevNode->hPMRZombieListLock); -} - -static INLINE void -_ZombieListUnlock(PMR_ZOMBIE_CLEANUP_ITEM *psCleanupItem) -{ - OSLockRelease(psCleanupItem->psDevNode->hPMRZombieListLock); -} - static INLINE IMG_BOOL _CanNotFreeZombies(const PMR_ZOMBIE_CLEANUP_ITEM *psCleanupItem) { @@ -760,17 +1135,18 @@ static PVRSRV_ERROR _PmrZombieCleanup(void *pvData) { PMR_ZOMBIE_CLEANUP_ITEM *psCleanupItem = pvData; DLLIST_NODE *psNode; + DLLIST_NODE sRetryHead; + IMG_UINT32 uiRetryCount = 0; + PVRSRV_ERROR eError = PVRSRV_OK; if (_CanNotFreeZombies(psCleanupItem)) { return PVRSRV_ERROR_RETRY; } + dllist_init(&sRetryHead); do { - PMR *psPMR; - const PMR_IMPL_FUNCTAB *psFuncTable; - /* hPMRZombieListLock will prevent removing a node while the list is * processed. If the lock is already acquired by other process which * intends to remove an item from the list it'll assure the list @@ -778,43 +1154,125 @@ static PVRSRV_ERROR _PmrZombieCleanup(void *pvData) * If this thread acquires the lock first it's possible that another * thread might be holding PMR factory lock. */ - _ZombieListLock(psCleanupItem); + _ZombieListLock(psCleanupItem->psDevNode); psNode = dllist_get_next_node(&psCleanupItem->sZombieList); - _ZombieListUnlock(psCleanupItem); + _ZombieListUnlock(psCleanupItem->psDevNode); - if (psNode != NULL) + if (psNode == NULL) { - psPMR = IMG_CONTAINER_OF(psNode, PMR, sZombieNode); - psFuncTable = psPMR->psFuncTab; + continue; + } - _FactoryLock(psFuncTable); - _ZombieListLock(psCleanupItem); - - /* It is possible that the element might have been removed so - * we have to check if the PMR is still a zombie. */ - - if (PMR_IsZombie(psPMR)) + switch (PMR_GetZombieTypeFromNode(psNode)) + { +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + case PMR_ZOMBIE_TYPE_PAGES: { + PMR_ZOMBIE_PAGES* psZombiePages = PMR_GetZombiePagesFromNode(psNode); + eError = psZombiePages->pfnFactoryFreeZombies(psZombiePages->pvFactoryPages); + _ZombieListLock(psCleanupItem->psDevNode); dllist_remove_node(psNode); psCleanupItem->psDevNode->uiPMRZombieCountInCleanup--; - /* Unlock here to avoid locking dependency with the power lock. - * It's okay to do it here since the factory lock is the one - * that needs to be held during PMR destruction. */ - _ZombieListUnlock(psCleanupItem); + _ZombieListUnlock(psCleanupItem->psDevNode); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "Cannot free zombie pages! Skipping object %p", psZombiePages)); + dllist_add_to_tail(&sRetryHead, psNode); + uiRetryCount++; + } + else + { + OSFreeMem(psZombiePages); + } + break; + } +#endif - _PMRDestroy(psPMR); - } - else +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + case PMR_ZOMBIE_TYPE_DEVICE_IMPORT: { - _ZombieListUnlock(psCleanupItem); + PMR_DEVICE_IMPORT *psImport = PMR_GetDeviceImportFromNode(psNode); + _ZombieListLock(psCleanupItem->psDevNode); + dllist_remove_node(psNode); + psCleanupItem->psDevNode->uiPMRZombieCountInCleanup--; + _ZombieListUnlock(psCleanupItem->psDevNode); + _DeviceImportFreeImportZombie(psImport); + break; } - _FactoryUnlock(psFuncTable); +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + + case PMR_ZOMBIE_TYPE_PMR: + { + PMR* psPMR = PMR_GetPMRFromNode(psNode); + const PMR_IMPL_FUNCTAB *psFuncTable = psPMR->psFuncTab; + + _FactoryLock(psFuncTable); + _ZombieListLock(psCleanupItem->psDevNode); + /* It is possible that the element might have been removed so + * we have to check if the PMR is still a zombie. + * It's also possible that the PMR has been revived + * (PMRReviveZombieAndRef()), mapped, unmapped and zombified + * again while the lock was not held. + * Considering above only immediately free the PMR if the + * PMR is still a part of this cleanup item. */ + if (psNode == dllist_get_next_node(&psCleanupItem->sZombieList)) + { + dllist_remove_node(psNode); + psCleanupItem->psDevNode->uiPMRZombieCountInCleanup--; + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + /* The PMR cannot be freed if other devices are + * still waiting for the cache flush. */ + if (_DeviceImportBitmapGet(psPMR) != 0) + { + /* Request it to be retried and continue + * to the next zombie item. */ + dllist_add_to_tail(&sRetryHead, psNode); + uiRetryCount++; + _ZombieListUnlock(psCleanupItem->psDevNode); + _FactoryUnlock(psFuncTable); + continue; + } +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + + /* Unlock here to avoid locking dependency with the power lock. + * It's okay to do it here since the factory lock is the one + * that needs to be held during PMR destruction. */ + _ZombieListUnlock(psCleanupItem->psDevNode); + _PMRDestroy(psPMR); + } + else + { + _ZombieListUnlock(psCleanupItem->psDevNode); + } + _FactoryUnlock(psFuncTable); + break; + } + + default: + PVR_ASSERT(!"Unknown Zombie Type!"); + break; } } while (psNode != NULL); - OSFreeMem(psCleanupItem); + if (uiRetryCount) + { + eError = PVRSRV_ERROR_RETRY; + _ZombieListLock(psCleanupItem->psDevNode); + /* Add the retry items back to this cleanup item for when the + * cleanup item is retried. Oldest items will reside at the head of + * the list. The cleanup item will be placed at the back of the cleanup + * queue to process other dependencies first. */ + dllist_insert_list_at_head(&psCleanupItem->sZombieList, &sRetryHead); + psCleanupItem->psDevNode->uiPMRZombieCountInCleanup += uiRetryCount; + _ZombieListUnlock(psCleanupItem->psDevNode); + } + else + { + OSFreeMem(psCleanupItem); + } - return PVRSRV_OK; + return eError; } IMG_BOOL PMRQueueZombiesForCleanup(PPVRSRV_DEVICE_NODE psDevNode) @@ -829,18 +1287,18 @@ IMG_BOOL PMRQueueZombiesForCleanup(PPVRSRV_DEVICE_NODE psDevNode) return IMG_FALSE; } - OSLockAcquire(psDevNode->hPMRZombieListLock); + _ZombieListLock(psDevNode); if (dllist_is_empty(&psDevNode->sPMRZombieList)) { - OSLockRelease(psDevNode->hPMRZombieListLock); + _ZombieListUnlock(psDevNode); return IMG_FALSE; } psCleanupItem = OSAllocMem(sizeof(*psCleanupItem)); if (psCleanupItem == NULL) { - OSLockRelease(psDevNode->hPMRZombieListLock); + _ZombieListUnlock(psDevNode); return IMG_FALSE; } @@ -869,10 +1327,18 @@ IMG_BOOL PMRQueueZombiesForCleanup(PPVRSRV_DEVICE_NODE psDevNode) } void -PMRDequeueZombieAndRef(PMR *psPMR) +PMRReviveZombieAndRef(PMR *psPMR) { + PVRSRV_DEVICE_NODE *psDeviceNode; + DLLIST_NODE *psThis, *psNext; + IMG_BOOL bIsOnZombieList = IMG_FALSE; + + PVR_ASSERT(psPMR != NULL); + + psDeviceNode = PhysHeapDeviceNode(psPMR->psPhysHeap); + /* If this was on a list then it's brought back to life. */ - OSLockAcquire(PhysHeapDeviceNode(psPMR->psPhysHeap)->hPMRZombieListLock); + _ZombieListLock(psDeviceNode); /* Need to reference this PMR since it was about to be destroyed and its * reference count must be 0 (can't use _Ref() due to the warning). */ @@ -885,15 +1351,41 @@ PMRDequeueZombieAndRef(PMR *psPMR) /* If we got to this point the PMR must be on a list. If it's not * it should mean a race of some sort. */ - PVR_ASSERT(!dllist_is_empty(&psPMR->sZombieNode)); + PVR_ASSERT(!dllist_is_empty(&psPMR->sHeader.sZombieNode)); + + /* For the sake of correct accounting check if the PMR is in the zombie + * list or in the cleanup item. */ + dllist_foreach_node(&psDeviceNode->sPMRZombieList, psThis, psNext) + { + if (psThis == &psPMR->sHeader.sZombieNode) + { + bIsOnZombieList = IMG_TRUE; + break; + } + } +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + if (_DeviceImportBitmapGet(psPMR) != 0) { + PMRLockPMR(psPMR); + _DeviceImportsReviveZombies(psPMR); + PMRUnlockPMR(psPMR); + } +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ /* Revive the PMR (remove it from the zombie list) and therefore * prevent it's destruction. */ - dllist_remove_node(&psPMR->sZombieNode); - BITMASK_UNSET(psPMR->uiInternalFlags, PMR_FLAG_INTERNAL_IS_ZOMBIE); - PhysHeapDeviceNode(psPMR->psPhysHeap)->uiPMRZombieCountInCleanup--; + dllist_remove_node(&psPMR->sHeader.sZombieNode); + _IntFlagClr(psPMR, PMR_FLAG_INTERNAL_IS_ZOMBIE); - OSLockRelease(PhysHeapDeviceNode(psPMR->psPhysHeap)->hPMRZombieListLock); + if (bIsOnZombieList) + { + psDeviceNode->uiPMRZombieCount--; + } + else + { + psDeviceNode->uiPMRZombieCountInCleanup--; + } + + _ZombieListUnlock(psDeviceNode); } void @@ -901,13 +1393,21 @@ PMRMarkForDeferFree(PMR *psPMR) { PVR_ASSERT(psPMR != NULL); - BITMASK_SET(psPMR->uiInternalFlags, PMR_FLAG_INTERNAL_DEFER_FREE); + if (PVRSRV_CHECK_ON_DEMAND(psPMR->uiFlags)) + { + /* If PMR pages are allocated on demand the freeing is handled + * by `SUPPORT_PMR_PAGES_DEFERRED_FREE` path in + * `PMRUnlockSysPhysAddressesNested()`. */ + return; + } + + _IntFlagSet(psPMR, PMR_FLAG_INTERNAL_DEFER_FREE); } #endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ static INLINE IMG_BOOL _PMRIsSparse(const PMR *psPMR) { - return BITMASK_HAS(psPMR->uiInternalFlags, PMR_FLAG_INTERNAL_SPARSE_ALLOC); + return _IntFlagIsSet(psPMR, PMR_FLAG_INTERNAL_SPARSE_ALLOC); } PVRSRV_ERROR @@ -1058,9 +1558,19 @@ PVRSRV_ERROR PMRUnlockSysPhysAddressesNested(PMR *psPMR, IMG_UINT32 ui32NestingLevel) { PVRSRV_ERROR eError; +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_IMPL_ZOMBIEPAGES pvZombiePages = NULL; + PMR_ZOMBIE_PAGES* psPMRZombiePages = NULL; +#endif PVR_ASSERT(psPMR != NULL); +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + /* Speculatively preallocate in order to simplify error handling later */ + psPMRZombiePages = OSAllocZMem(sizeof(PMR_ZOMBIE_PAGES)); + PVR_GOTO_IF_NOMEM(psPMRZombiePages, eError, e0); +#endif + /* Acquiring the lock here, as well as during the Lock operation ensures * the lock count hitting zero and the unlocking of the phys addresses is * an atomic operation @@ -1074,7 +1584,13 @@ PMRUnlockSysPhysAddressesNested(PMR *psPMR, IMG_UINT32 ui32NestingLevel) { PVR_ASSERT(psPMR->psFuncTab->pfnLockPhysAddresses != NULL); +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + eError = psPMR->psFuncTab->pfnUnlockPhysAddresses(psPMR->pvFlavourData, + &pvZombiePages); +#else eError = psPMR->psFuncTab->pfnUnlockPhysAddresses(psPMR->pvFlavourData); +#endif + /* must never fail */ PVR_ASSERT(eError == PVRSRV_OK); } @@ -1082,12 +1598,59 @@ PMRUnlockSysPhysAddressesNested(PMR *psPMR, IMG_UINT32 ui32NestingLevel) OSLockRelease(psPMR->hLock); +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + if (pvZombiePages != NULL) + { + PVRSRV_DEV_POWER_STATE ePowerState; + PVRSRV_DEVICE_NODE *psDevNode; + + psDevNode = PhysHeapDeviceNode(psPMR->psPhysHeap); + eError = PVRSRVGetDevicePowerState(psDevNode, &ePowerState); + if (eError != PVRSRV_OK) + { + /* Treat unknown power state as ON. */ + ePowerState = PVRSRV_DEV_POWER_STATE_ON; + } + + if (ePowerState == PVRSRV_DEV_POWER_STATE_OFF || + psDevNode->eDevState == PVRSRV_DEVICE_STATE_PCI_ERROR) + { + /* Free preallocated psPMRZombiePages as these won't be used*/ + OSFreeMem(psPMRZombiePages); + + eError = psPMR->psFuncTab->pfnFreeZombiePages(pvZombiePages); + PVR_LOG_GOTO_IF_ERROR(eError, "Error when trying to free zombies immediately.", e0); + } + else + { + PVR_ASSERT(psPMRZombiePages != NULL); + psPMRZombiePages->sHeader.eZombieType = PMR_ZOMBIE_TYPE_PAGES; + psPMRZombiePages->pfnFactoryFreeZombies = psPMR->psFuncTab->pfnFreeZombiePages; + psPMRZombiePages->pvFactoryPages = pvZombiePages; + + _ZombieListLock(psDevNode); + dllist_add_to_tail(&psDevNode->sPMRZombieList, &psPMRZombiePages->sHeader.sZombieNode); + psDevNode->uiPMRZombieCount++; + _ZombieListUnlock(psDevNode); + } + } + else + { + OSFreeMem(psPMRZombiePages); + } +#endif + /* We also count the locks as references, so that the PMR is not * freed while someone is using a physical address. */ _UnrefAndMaybeDestroy(psPMR); return PVRSRV_OK; + +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +e0: +#endif + return eError; } PVRSRV_ERROR @@ -1960,6 +2523,47 @@ PMR_IsCpuMapped(PMR *psPMR) return (OSAtomicRead(&psPMR->iCpuMapCount) > 0); } +void +PMRGpuResCountIncr(PMR *psPMR) +{ + if (psPMR->iAssociatedResCount == PMR_MAPCOUNT_MAX) + { + PVR_DPF((PVR_DBG_ERROR, "%s: iAssociatedResCount for PMR: @0x%p (%s) has overflowed.", + __func__, + psPMR, + psPMR->szAnnotation)); + OSWarnOn(1); + return; + } + + psPMR->iAssociatedResCount++; +} + +void +PMRGpuResCountDecr(PMR *psPMR) +{ + if (psPMR->iAssociatedResCount == PMR_MAPCOUNT_MIN) + { + PVR_DPF((PVR_DBG_ERROR, "%s: iAssociatedResCount (now %d) for PMR: @0x%p (%s) has underflowed.", + __func__, + psPMR->iAssociatedResCount, + psPMR, + psPMR->szAnnotation)); + OSWarnOn(1); + return; + } + + psPMR->iAssociatedResCount--; +} + +IMG_BOOL +PMR_IsGpuMultiMapped(PMR *psPMR) +{ + PVR_ASSERT(psPMR != NULL); + + return psPMR->iAssociatedResCount > 1; +} + PVRSRV_DEVICE_NODE * PMR_DeviceNode(const PMR *psPMR) { @@ -1990,7 +2594,7 @@ PMR_IsZombie(const PMR *psPMR) { PVR_ASSERT(psPMR != NULL); - return BITMASK_HAS(psPMR->uiInternalFlags, PMR_FLAG_INTERNAL_IS_ZOMBIE); + return _IntFlagIsSet(psPMR, PMR_FLAG_INTERNAL_IS_ZOMBIE); } #endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ @@ -2005,19 +2609,20 @@ PMR_SetLayoutFixed(PMR *psPMR, IMG_BOOL bFlag) if (bFlag) { - BITMASK_SET(psPMR->uiInternalFlags, PMR_FLAG_INTERNAL_NO_LAYOUT_CHANGE); + _IntFlagSet(psPMR, PMR_FLAG_INTERNAL_NO_LAYOUT_CHANGE); } else { - BITMASK_UNSET(psPMR->uiInternalFlags, PMR_FLAG_INTERNAL_NO_LAYOUT_CHANGE); + _IntFlagClr(psPMR, PMR_FLAG_INTERNAL_NO_LAYOUT_CHANGE); } } IMG_BOOL PMR_IsMemLayoutFixed(PMR *psPMR) { + PVR_ASSERT(psPMR != NULL); - return BITMASK_HAS(psPMR->uiInternalFlags, PMR_FLAG_INTERNAL_NO_LAYOUT_CHANGE); + return _IntFlagIsSet(psPMR, PMR_FLAG_INTERNAL_NO_LAYOUT_CHANGE); } void @@ -2445,9 +3050,33 @@ PVRSRV_ERROR PMR_ChangeSparseMem(PMR *psPMR, IMG_UINT32 uiSparseFlags) { PVRSRV_ERROR eError; - PMRLockPMR(psPMR); + eError = PMR_ChangeSparseMemUnlocked(psPMR, + ui32AllocPageCount, + pai32AllocIndices, + ui32FreePageCount, + pai32FreeIndices, + uiSparseFlags); + + PMRUnlockPMR(psPMR); + + return eError; +} + +PVRSRV_ERROR PMR_ChangeSparseMemUnlocked(PMR *psPMR, + IMG_UINT32 ui32AllocPageCount, + IMG_UINT32 *pai32AllocIndices, + IMG_UINT32 ui32FreePageCount, + IMG_UINT32 *pai32FreeIndices, + IMG_UINT32 uiSparseFlags) +{ + PVRSRV_ERROR eError; +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_IMPL_ZOMBIEPAGES pvZombiePages = NULL; + PMR_ZOMBIE_PAGES* psPMRZombiePages = NULL; +#endif + if (PMR_IsMemLayoutFixed(psPMR) || PMR_IsCpuMapped(psPMR)) { PVR_DPF((PVR_DBG_ERROR, @@ -2455,7 +3084,6 @@ PVRSRV_ERROR PMR_ChangeSparseMem(PMR *psPMR, __func__, PMR_IsMemLayoutFixed(psPMR) ? 'Y' : 'n', PMR_IsCpuMapped(psPMR) ? 'Y' : 'n')); - PMRUnlockPMR(psPMR); return PVRSRV_ERROR_PMR_NOT_PERMITTED; } @@ -2464,16 +3092,27 @@ PVRSRV_ERROR PMR_ChangeSparseMem(PMR *psPMR, PVR_DPF((PVR_DBG_ERROR, "%s: This type of sparse PMR cannot be changed.", __func__)); - PMRUnlockPMR(psPMR); return PVRSRV_ERROR_NOT_IMPLEMENTED; } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + if (uiSparseFlags & SPARSE_RESIZE_FREE) + { + /* Speculatively preallocate in order to simplify error handling later */ + psPMRZombiePages = OSAllocZMem(sizeof(PMR_ZOMBIE_PAGES)); + PVR_GOTO_IF_NOMEM(psPMRZombiePages, eError, e0); + } +#endif + eError = psPMR->psFuncTab->pfnChangeSparseMem(psPMR->pvFlavourData, psPMR, ui32AllocPageCount, pai32AllocIndices, ui32FreePageCount, pai32FreeIndices, +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + &pvZombiePages, +#endif uiSparseFlags); if (eError != PVRSRV_OK) { @@ -2486,9 +3125,52 @@ PVRSRV_ERROR PMR_ChangeSparseMem(PMR *psPMR, OSGetCurrentClientProcessIDKM()); } #endif - goto e0; + goto e1; } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + if (pvZombiePages != NULL) + { + PVRSRV_DEV_POWER_STATE ePowerState; + PVRSRV_DEVICE_NODE *psDevNode; + + psDevNode = PhysHeapDeviceNode(psPMR->psPhysHeap); + eError = PVRSRVGetDevicePowerState(psDevNode, &ePowerState); + if (eError != PVRSRV_OK) + { + /* Treat unknown power state as ON. */ + ePowerState = PVRSRV_DEV_POWER_STATE_ON; + } + + if (ePowerState == PVRSRV_DEV_POWER_STATE_OFF || + psDevNode->eDevState == PVRSRV_DEVICE_STATE_PCI_ERROR) + { + /* Free preallocated psPMRZombiePages as these won't be used*/ + OSFreeMem(psPMRZombiePages); + + eError = psPMR->psFuncTab->pfnFreeZombiePages(pvZombiePages); + PVR_LOG_GOTO_IF_ERROR(eError, "Error when trying to free zombies immediately.", e0); + } + else + { + PVR_ASSERT(psPMRZombiePages != NULL); + psPMRZombiePages->sHeader.eZombieType = PMR_ZOMBIE_TYPE_PAGES; + psPMRZombiePages->pfnFactoryFreeZombies = psPMR->psFuncTab->pfnFreeZombiePages; + psPMRZombiePages->pvFactoryPages = pvZombiePages; + + _ZombieListLock(psDevNode); + dllist_add_to_tail(&psDevNode->sPMRZombieList, &psPMRZombiePages->sHeader.sZombieNode); + psDevNode->uiPMRZombieCount++; + _ZombieListUnlock(psDevNode); + } + } + else + { + /* Free psPMRZombiePages as change sparse has not produced zombie pages */ + OSFreeMem(psPMRZombiePages); + } +#endif + #if defined(PDUMP) { IMG_BOOL bInitialise = IMG_FALSE; @@ -2517,8 +3199,15 @@ PVRSRV_ERROR PMR_ChangeSparseMem(PMR *psPMR, #endif + return PVRSRV_OK; +e1: +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + if (uiSparseFlags & SPARSE_RESIZE_FREE) + { + OSFreeMem(psPMRZombiePages); + } e0: - PMRUnlockPMR(psPMR); +#endif return eError; } @@ -4170,23 +4859,91 @@ PMRFreeZombies(PPVRSRV_DEVICE_NODE psDeviceNode) DLLIST_NODE *psThis, *psNext; IMG_INT32 uiZombieCount; - OSLockAcquire(psDeviceNode->hPMRZombieListLock); + _ZombieListLock(psDeviceNode); /* Move the zombie list to a local copy. The original list will become * an empty list. This will allow us to process the list without holding * the list lock. */ dllist_replace_head(&psDeviceNode->sPMRZombieList, &sZombieList); uiZombieCount = psDeviceNode->uiPMRZombieCount; psDeviceNode->uiPMRZombieCount = 0; - OSLockRelease(psDeviceNode->hPMRZombieListLock); + _ZombieListUnlock(psDeviceNode); dllist_foreach_node(&sZombieList, psThis, psNext) { - PMR *psPMR = IMG_CONTAINER_OF(psThis, PMR, sZombieNode); + dllist_remove_node(psThis); + switch (PMR_GetZombieTypeFromNode(psThis)) + { +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + case PMR_ZOMBIE_TYPE_PAGES: + { + PVRSRV_ERROR eError; + PMR_ZOMBIE_PAGES* psZombiePages = PMR_GetZombiePagesFromNode(psThis); - dllist_remove_node(&psPMR->sZombieNode); + eError = psZombiePages->pfnFactoryFreeZombies(psZombiePages->pvFactoryPages); + if (eError != PVRSRV_OK) + { + /* In case of failure to free zombie pages, remove it from + * the sZombieList and add back to the original list. */ + _ZombieListLock(psDeviceNode); + dllist_add_to_tail(&psDeviceNode->sPMRZombieList, psThis); + psDeviceNode->uiPMRZombieCount++; + _ZombieListUnlock(psDeviceNode); - _PMRDestroy(psPMR); + PVR_DPF((PVR_DBG_ERROR, "Cannot free zombie pages!")); + continue; + } + OSFreeMem(psZombiePages); + break; + } +#endif + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + case PMR_ZOMBIE_TYPE_DEVICE_IMPORT: + { + PMR_DEVICE_IMPORT *psImport = PMR_GetDeviceImportFromNode(psThis); + _DeviceImportFreeImportZombie(psImport); + break; + } +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + + case PMR_ZOMBIE_TYPE_PMR: + { + PMR *psPMR = PMR_GetPMRFromNode(psThis); + const PMR_IMPL_FUNCTAB *psFuncTable = psPMR->psFuncTab; + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + /* The PMR cannot be freed as other devices are + * still waiting for the cache flush. */ + PMRLockPMR(psPMR); + if (_DeviceImportBitmapGet(psPMR) != 0) + { + PDLLIST_NODE psNodeImport; + PMR_DEVICE_IMPORT *psImport; + /* Transfer the ownership to a different + * device queue that has not been processed yet. + * There will be a PMR_DEVICE_IMPORT on the same + * queue, however, this doesn't have any knock on affects as + * it will be freed before the PMR is reached again. */ + psNodeImport = dllist_get_next_node(&psPMR->sXDeviceImports); + PVR_ASSERT(psNodeImport); + psImport = IMG_CONTAINER_OF(psNodeImport, PMR_DEVICE_IMPORT, sNext); + _ZombieListLock(psImport->psDevNode); + dllist_add_to_tail(&psImport->psDevNode->sPMRZombieList, psThis); + psImport->psDevNode->uiPMRZombieCount++; + _ZombieListUnlock(psImport->psDevNode); + PMRUnlockPMR(psPMR); + break; + } + PMRUnlockPMR(psPMR); +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + + _FactoryLock(psFuncTable); + _PMRDestroy(psPMR); + _FactoryUnlock(psFuncTable); + break; + } + } uiZombieCount--; } @@ -4198,20 +4955,48 @@ PMRDumpZombies(PPVRSRV_DEVICE_NODE psDeviceNode) { DLLIST_NODE *psThis, *psNext; - OSLockAcquire(psDeviceNode->hPMRZombieListLock); + _ZombieListLock(psDeviceNode); PVR_DPF((PVR_DBG_ERROR, "Items in zombie list: %u", psDeviceNode->uiPMRZombieCount)); dllist_foreach_node(&psDeviceNode->sPMRZombieList, psThis, psNext) { - PMR *psPMR = IMG_CONTAINER_OF(psThis, PMR, sZombieNode); + switch (PMR_GetZombieTypeFromNode(psThis)) + { +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + case PMR_ZOMBIE_TYPE_PAGES: + { + PMR_ZOMBIE_PAGES* psZombiePages = PMR_GetZombiePagesFromNode(psThis); + PVR_DPF((PVR_DBG_ERROR, "Zombie Pages = %p", psZombiePages)); + break; + } +#endif - PVR_DPF((PVR_DBG_ERROR, "PMR = %px, Flavour = %s, Annotation: %s", - psPMR, PMR_GetTypeStr(psPMR), PMR_GetAnnotation(psPMR))); +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + case PMR_ZOMBIE_TYPE_DEVICE_IMPORT: + { + PMR_DEVICE_IMPORT* psImport = PMR_GetDeviceImportFromNode(psThis); + PVR_DPF((PVR_DBG_ERROR, "Device Import = %p, DevID = %u, PMR = %px (%s)", + psImport, + psImport->psDevNode->sDevId.ui32InternalID, + psImport->psParent, + PMR_GetAnnotation(psImport->psParent))); + break; + } +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + + case PMR_ZOMBIE_TYPE_PMR: + { + PMR *psPMR = PMR_GetPMRFromNode(psThis); + PVR_DPF((PVR_DBG_ERROR, "PMR = %px, Flavour = %s, Annotation: %s", + psPMR, PMR_GetTypeStr(psPMR), PMR_GetAnnotation(psPMR))); + break; + } + } } - OSLockRelease(psDeviceNode->hPMRZombieListLock); + _ZombieListUnlock(psDeviceNode); } void @@ -4222,3 +5007,23 @@ PMRDeInitDevice(PPVRSRV_DEVICE_NODE psDeviceNode) OSLockDestroy(psDeviceNode->hPMRZombieListLock); } #endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) +PVRSRV_ERROR +PMR_RegisterDeviceImport(PMR* psPMR, PPVRSRV_DEVICE_NODE psDevNode) +{ + PVR_ASSERT(!PMR_IsZombie(psPMR)); + + if (PMR_DeviceNode(psPMR) != psDevNode) + { + PVRSRV_ERROR eError = _DeviceImportRegister(psPMR, psDevNode); + PVR_LOG_RETURN_IF_ERROR(eError, "_DeviceImportRegister"); + } + /* else: We explicitly don't add the PMR's dev node to the list because + * this bitmask lets us know if the PMR is cross device. It's not + * an error to register with the original dev node, as the user is + * declaring "The PMR is using `psDevNode`", not that it's a new + * devnode. */ + return PVRSRV_OK; +} +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/pvrsrv.c b/drivers/gpu/img-rogue/23.2/services/server/common/pvrsrv.c index afa7f6a..86be6ff 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/pvrsrv.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/pvrsrv.c
@@ -2219,15 +2219,6 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice, } #endif - /* Initialise the paravirtualised connection */ - if (!PVRSRV_VZ_MODE_IS(NATIVE)) - { - PvzConnectionInit(); - PVR_GOTO_IF_ERROR(eError, ErrorSysDevDeInit); - } - - BIT_SET(psDevConfig->psDevNode->ui32VmState, RGXFW_HOST_DRIVER_ID); - /* Next update value will be 0xFFFFFFF7 since sync prim starts with 0xFFFFFFF6. * Has to be set before call to PMRInitDevice(). */ psDeviceNode->ui32NextMMUInvalidateUpdate = 0xFFFFFFF7U; @@ -2237,7 +2228,7 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice, #endif eError = PVRSRVRegisterDeviceDbgTable(psDeviceNode); - PVR_GOTO_IF_ERROR(eError, ErrorPvzConnectionDeInit); + PVR_GOTO_IF_ERROR(eError, ErrorSysDevDeInit); eError = PVRSRVPowerLockInit(psDeviceNode); PVR_GOTO_IF_ERROR(eError, ErrorUnregisterDbgTable); @@ -2373,12 +2364,21 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice, psPVRSRVData->ui32RegisteredDevices++; OSWRLockReleaseWrite(psPVRSRVData->hDeviceNodeListLock); + /* Initialise the paravirtualised connection */ + if (!PVRSRV_VZ_MODE_IS(NATIVE)) + { + PvzConnectionInit(); + PVR_GOTO_IF_ERROR(eError, ErrorRegisterDVFSDeviceFail); + } + + BIT_SET(psDevConfig->psDevNode->ui32VmState, RGXFW_HOST_DRIVER_ID); + *ppsDeviceNode = psDeviceNode; #if defined(SUPPORT_LINUX_DVFS) && !defined(NO_HARDWARE) /* Register the DVFS device now the device node is present in the dev-list */ eError = RegisterDVFSDevice(psDeviceNode); - PVR_LOG_GOTO_IF_ERROR(eError, "RegisterDVFSDevice", ErrorRegisterDVFSDeviceFail); + PVR_LOG_GOTO_IF_ERROR(eError, "RegisterDVFSDevice", ErrorPvzConnectionDeInit); #endif #if defined(PVRSRV_ENABLE_PROCESS_STATS) @@ -2395,7 +2395,15 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice, return PVRSRV_OK; #if defined(SUPPORT_LINUX_DVFS) && !defined(NO_HARDWARE) +ErrorPvzConnectionDeInit: +#endif + psDevConfig->psDevNode = NULL; + if (!PVRSRV_VZ_MODE_IS(NATIVE)) + { + PvzConnectionDeInit(); + } ErrorRegisterDVFSDeviceFail: +#if defined(SUPPORT_LINUX_DVFS) && !defined(NO_HARDWARE) /* Remove the device from the list */ OSWRLockAcquireWrite(psPVRSRVData->hDeviceNodeListLock); List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode); @@ -2455,12 +2463,6 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice, PVRSRVPowerLockDeInit(psDeviceNode); ErrorUnregisterDbgTable: PVRSRVUnregisterDeviceDbgTable(psDeviceNode); -ErrorPvzConnectionDeInit: - psDevConfig->psDevNode = NULL; - if (!PVRSRV_VZ_MODE_IS(NATIVE)) - { - PvzConnectionDeInit(); - } ErrorSysDevDeInit: SysDevDeInit(psDevConfig); ErrorDeregisterStats:
diff --git a/drivers/gpu/img-rogue/23.2/services/server/common/sync_server.c b/drivers/gpu/img-rogue/23.2/services/server/common/sync_server.c index 12a7d1e..1e9a0ec 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/common/sync_server.c +++ b/drivers/gpu/img-rogue/23.2/services/server/common/sync_server.c
@@ -546,6 +546,12 @@ PVRSRVSyncRecordAddKM(CONNECTION_DATA *psConnection, PVR_UNREFERENCED_PARAMETER(psConnection); + if (!(GetInfoPageDebugFlagsKM() & DEBUG_FEATURE_FULL_SYNC_TRACKING_ENABLED)) + { + PVR_DPF((PVR_DBG_ERROR, "%s: Full sync tracking debug feature not enabled!", __func__)); + return PVRSRV_ERROR_NOT_SUPPORTED; + } + RGXSRV_HWPERF_ALLOC(psDevNode, SYNC, ui32FwBlockAddr + ui32SyncOffset, pszClassName, @@ -616,6 +622,12 @@ PVRSRVSyncRecordRemoveByHandleKM( struct SYNC_RECORD *pSync = (struct SYNC_RECORD*)hRecord; PVRSRV_DEVICE_NODE *psDevNode; + if (!(GetInfoPageDebugFlagsKM() & DEBUG_FEATURE_FULL_SYNC_TRACKING_ENABLED)) + { + PVR_DPF((PVR_DBG_ERROR, "%s: Full sync tracking debug feature not enabled!", __func__)); + return PVRSRV_ERROR_NOT_SUPPORTED; + } + PVR_RETURN_IF_INVALID_PARAM(hRecord); psDevNode = pSync->psDevNode;
diff --git a/drivers/gpu/img-rogue/23.2/services/server/devices/rgxdebug_common.c b/drivers/gpu/img-rogue/23.2/services/server/devices/rgxdebug_common.c index 8684309..9657e0a 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/devices/rgxdebug_common.c +++ b/drivers/gpu/img-rogue/23.2/services/server/devices/rgxdebug_common.c
@@ -811,7 +811,7 @@ static PVRSRV_ERROR _ValidateWithFWModule(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPri if (pui32FWCode[i] != ui32Value) { - PVR_DUMPDEBUG_LOG("%s: Mismatch while validating %s at offset 0x%x: CPU 0x%08x (%p), FW 0x%08x (%x)", + PVR_DUMPDEBUG_LOG("%s: Mismatch while validating %s at offset 0x%x: CPU 0x%08x ("IMG_KM_PTR_FMTSPEC"), FW 0x%08x (%x)", __func__, pszDesc, (i * 4) + ui32StartOffset, pui32FWCode[i], pui32FWCode, ui32Value, ui32FWCodeDevVAAddr); return PVRSRV_ERROR_FW_IMAGE_MISMATCH; @@ -1844,7 +1844,7 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, bRGXPoweredON = (ePowerState == PVRSRV_DEV_POWER_STATE_ON); PVR_DUMPDEBUG_LOG("------[ RGX Info ]------"); - PVR_DUMPDEBUG_LOG("Device Node (Info): %p (%p)", psDevInfo->psDeviceNode, psDevInfo); + PVR_DUMPDEBUG_LOG("Device Node (Info): "IMG_KM_PTR_FMTSPEC" ("IMG_KM_PTR_FMTSPEC")", psDevInfo->psDeviceNode, psDevInfo); DevicememHistoryDumpRecordStats(psDevInfo->psDeviceNode, pfnDumpDebugPrintf, pvDumpDebugFile); PVR_DUMPDEBUG_LOG("RGX BVNC: %d.%d.%d.%d (%s)", psDevInfo->sDevFeatureCfg.ui32B, psDevInfo->sDevFeatureCfg.ui32V,
diff --git a/drivers/gpu/img-rogue/23.2/services/server/devices/rogue/rgxdebug.c b/drivers/gpu/img-rogue/23.2/services/server/devices/rogue/rgxdebug.c index 23382dc..1f5e93a 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/devices/rogue/rgxdebug.c +++ b/drivers/gpu/img-rogue/23.2/services/server/devices/rogue/rgxdebug.c
@@ -3643,13 +3643,13 @@ PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, PVRSRV_ERROR eError; PVR_DUMPDEBUG_LOG("------[ RGX registers ]------"); - PVR_DUMPDEBUG_LOG("RGX Register Base Address (Linear): 0x%p", psDevInfo->pvRegsBaseKM); + PVR_DUMPDEBUG_LOG("RGX Register Base Address (Linear): 0x"IMG_KM_PTR_FMTSPEC, psDevInfo->pvRegsBaseKM); PVR_DUMPDEBUG_LOG("RGX Register Base Address (Physical): 0x%08lX", (unsigned long)psDevInfo->sRegsPhysBase.uiAddr); #if defined(RGX_FEATURE_HOST_SECURITY_VERSION_MAX_VALUE_IDX) if (RGX_GET_FEATURE_VALUE(psDevInfo, HOST_SECURITY_VERSION) > 1) { - PVR_DUMPDEBUG_LOG("RGX Host Secure Register Base Address (Linear): 0x%p", + PVR_DUMPDEBUG_LOG("RGX Host Secure Register Base Address (Linear): 0x"IMG_KM_PTR_FMTSPEC, psDevInfo->pvSecureRegsBaseKM); PVR_DUMPDEBUG_LOG("RGX Host Secure Register Base Address (Physical): 0x%08lX", (unsigned long)psDevInfo->sRegsPhysBase.uiAddr + RGX_HOST_SECURE_REGBANK_OFFSET);
diff --git a/drivers/gpu/img-rogue/23.2/services/server/devices/rogue/rgxinit.c b/drivers/gpu/img-rogue/23.2/services/server/devices/rogue/rgxinit.c index 391a67c..b10712b 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/devices/rogue/rgxinit.c +++ b/drivers/gpu/img-rogue/23.2/services/server/devices/rogue/rgxinit.c
@@ -4356,7 +4356,7 @@ static PVRSRV_ERROR RGXInitPrivateFwPhysHeaps(PVRSRV_DEVICE_NODE *psDeviceNode) PVR_LOG_GOTO_IF_FALSE((psFwCodeHeapCfg != NULL) && (psFwDataHeapCfg != NULL), "Security support requires Fw code and data memory be" - " separate from the heap shared with the kernel driver.", ErrorDeinit); + " separate from the heap shared with the kernel driver.", FailDeinit); if (psFwCodeHeapCfg != psFwDataHeapCfg) { @@ -4371,8 +4371,8 @@ static PVRSRV_ERROR RGXInitPrivateFwPhysHeaps(PVRSRV_DEVICE_NODE *psDeviceNode) PVR_LOG_GOTO_IF_FALSE((psFwSharedHeapCfg->uiSize + ui64FwPrivateHeapSize) == - RGX_FIRMWARE_RAW_HEAP_SIZE, - "Invalid firmware physical heap size.", ErrorDeinit); + RGX_FIRMWARE_RAW_HEAP_SIZE, + "Invalid firmware physical heap size.", FailDeinit); } #endif @@ -4386,6 +4386,10 @@ static PVRSRV_ERROR RGXInitPrivateFwPhysHeaps(PVRSRV_DEVICE_NODE *psDeviceNode) return eError; +#if defined(RGX_PREMAP_FW_HEAPS) && defined(SUPPORT_TRUSTED_DEVICE) +FailDeinit: + eError = PVRSRV_ERROR_INVALID_PARAMS; +#endif ErrorDeinit: PVR_ASSERT(IMG_FALSE);
diff --git a/drivers/gpu/img-rogue/23.2/services/server/devices/volcanic/rgxdebug.c b/drivers/gpu/img-rogue/23.2/services/server/devices/volcanic/rgxdebug.c index 9d391cb..928716e 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/devices/volcanic/rgxdebug.c +++ b/drivers/gpu/img-rogue/23.2/services/server/devices/volcanic/rgxdebug.c
@@ -2416,13 +2416,13 @@ PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, PVRSRV_ERROR eError; PVR_DUMPDEBUG_LOG("------[ RGX registers ]------"); - PVR_DUMPDEBUG_LOG("RGX Register Base Address (Linear): 0x%p", psDevInfo->pvRegsBaseKM); + PVR_DUMPDEBUG_LOG("RGX Register Base Address (Linear): 0x"IMG_KM_PTR_FMTSPEC, psDevInfo->pvRegsBaseKM); PVR_DUMPDEBUG_LOG("RGX Register Base Address (Physical): 0x%08lX", (unsigned long)psDevInfo->sRegsPhysBase.uiAddr); #if defined(RGX_FEATURE_HOST_SECURITY_VERSION_MAX_VALUE_IDX) if (RGX_GET_FEATURE_VALUE(psDevInfo, HOST_SECURITY_VERSION) > 1) { - PVR_DUMPDEBUG_LOG("RGX Host Secure Register Base Address (Linear): 0x%p", + PVR_DUMPDEBUG_LOG("RGX Host Secure Register Base Address (Linear): 0x"IMG_KM_PTR_FMTSPEC, psDevInfo->pvSecureRegsBaseKM); PVR_DUMPDEBUG_LOG("RGX Host Secure Register Base Address (Physical): 0x%08lX", (unsigned long)psDevInfo->sRegsPhysBase.uiAddr + RGX_HOST_SECURE_REGBANK_OFFSET);
diff --git a/drivers/gpu/img-rogue/23.2/services/server/devices/volcanic/rgxinit.c b/drivers/gpu/img-rogue/23.2/services/server/devices/volcanic/rgxinit.c index 1f15c7b..73cb05d 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/devices/volcanic/rgxinit.c +++ b/drivers/gpu/img-rogue/23.2/services/server/devices/volcanic/rgxinit.c
@@ -4267,7 +4267,7 @@ static PVRSRV_ERROR RGXInitPrivateFwPhysHeaps(PVRSRV_DEVICE_NODE *psDeviceNode) PVR_LOG_GOTO_IF_FALSE((psFwCodeHeapCfg != NULL) && (psFwDataHeapCfg != NULL), "Security support requires Fw code and data memory be" - " separate from the heap shared with the kernel driver.", ErrorDeinit); + " separate from the heap shared with the kernel driver.", FailDeinit); if (psFwCodeHeapCfg != psFwDataHeapCfg) { @@ -4282,8 +4282,8 @@ static PVRSRV_ERROR RGXInitPrivateFwPhysHeaps(PVRSRV_DEVICE_NODE *psDeviceNode) PVR_LOG_GOTO_IF_FALSE((psFwSharedHeapCfg->uiSize + ui64FwPrivateHeapSize) == - RGX_FIRMWARE_RAW_HEAP_SIZE, - "Invalid firmware physical heap size.", ErrorDeinit); + RGX_FIRMWARE_RAW_HEAP_SIZE, + "Invalid firmware physical heap size.", FailDeinit); } #endif @@ -4297,6 +4297,10 @@ static PVRSRV_ERROR RGXInitPrivateFwPhysHeaps(PVRSRV_DEVICE_NODE *psDeviceNode) return eError; +#if defined(RGX_PREMAP_FW_HEAPS) && defined(SUPPORT_TRUSTED_DEVICE) +FailDeinit: + eError = PVRSRV_ERROR_INVALID_PARAMS; +#endif ErrorDeinit: PVR_ASSERT(IMG_FALSE);
diff --git a/drivers/gpu/img-rogue/23.2/services/server/env/linux/osfunc.c b/drivers/gpu/img-rogue/23.2/services/server/env/linux/osfunc.c index f45bef4..ddf0332 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/env/linux/osfunc.c +++ b/drivers/gpu/img-rogue/23.2/services/server/env/linux/osfunc.c
@@ -68,6 +68,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <linux/kthread.h> #include <linux/utsname.h> #include <linux/scatterlist.h> +#include <linux/pid.h> #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) #include <linux/pfn_t.h> #include <linux/pfn.h> @@ -78,6 +79,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #else #include <linux/sched.h> #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) */ + #if defined(SUPPORT_SECURE_ALLOC_KM) #if defined(PVR_ANDROID_HAS_DMA_HEAP_FIND) #include <linux/dma-heap.h> @@ -837,6 +839,22 @@ IMG_CHAR *OSGetCurrentClientProcessNameKM(void) return OSGetCurrentProcessName(); } +uintptr_t OSAcquireCurrentPPIDResourceRefKM(void) +{ + struct pid *psPPIDResource = find_pid_ns(OSGetCurrentClientProcessIDKM(), &init_pid_ns); + + PVR_ASSERT(psPPIDResource != NULL); + /* Take ref on pPid */ + get_pid(psPPIDResource); + return (uintptr_t)psPPIDResource; +} + +void OSReleasePPIDResourceRefKM(uintptr_t psPPIDResource) +{ + /* Drop ref on uiProc */ + put_pid((struct pid*)psPPIDResource); +} + uintptr_t OSGetCurrentClientThreadIDKM(void) { return OSGetCurrentThreadID();
diff --git a/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_dmabuf.c b/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_dmabuf.c index 9c84219..1fbddd7 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_dmabuf.c +++ b/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_dmabuf.c
@@ -165,6 +165,7 @@ typedef struct _PMR_DMA_BUF_DATA_ struct dma_buf_attachment *psAttachment; PFN_DESTROY_DMABUF_PMR pfnDestroy; IMG_BOOL bPoisonOnFree; + IMG_PID uiOriginPID; /* Mapping information. */ struct iosys_map sMap; @@ -305,14 +306,14 @@ static void PMRFinalizeDmaBuf(PMR_IMPL_PRIVDATA pvPriv) { PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_DMA_BUF_ZOMBIE, psPrivData->ui32PhysPageCount << PAGE_SHIFT, - OSGetCurrentClientProcessIDKM()); + psPrivData->uiOriginPID); } else #endif { PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_DMA_BUF_IMPORT, psPrivData->ui32PhysPageCount << PAGE_SHIFT, - OSGetCurrentClientProcessIDKM()); + psPrivData->uiOriginPID); } #endif @@ -358,12 +359,10 @@ static PVRSRV_ERROR PMRZombifyDmaBufMem(PMR_IMPL_PRIVDATA pvPriv, PMR *psPMR) #if defined(PVRSRV_ENABLE_PROCESS_STATS) PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_DMA_BUF_IMPORT, psPrivData->ui32PhysPageCount << PAGE_SHIFT, - OSGetCurrentClientProcessIDKM()); + psPrivData->uiOriginPID); PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_DMA_BUF_ZOMBIE, psPrivData->ui32PhysPageCount << PAGE_SHIFT, - OSGetCurrentClientProcessIDKM()); -#else - PVR_UNREFERENCED_PARAMETER(pvPriv); + psPrivData->uiOriginPID); #endif PVRSRVIonZombifyMemAllocRecord(psDmaBuf); @@ -378,9 +377,17 @@ static PVRSRV_ERROR PMRLockPhysAddressesDmaBuf(PMR_IMPL_PRIVDATA pvPriv) return PVRSRV_OK; } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +static PVRSRV_ERROR PMRUnlockPhysAddressesDmaBuf(PMR_IMPL_PRIVDATA pvPriv, + PMR_IMPL_ZOMBIEPAGES *ppvZombiePages) +#else static PVRSRV_ERROR PMRUnlockPhysAddressesDmaBuf(PMR_IMPL_PRIVDATA pvPriv) +#endif { PVR_UNREFERENCED_PARAMETER(pvPriv); +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + *ppvZombiePages = NULL; +#endif return PVRSRV_OK; } @@ -620,6 +627,7 @@ PhysmemCreateNewDmaBufBackedPMR(PHYS_HEAP *psHeap, psPrivData->psAttachment = psAttachment; psPrivData->pfnDestroy = pfnDestroy; psPrivData->bPoisonOnFree = bPoisonOnFree; + psPrivData->uiOriginPID = OSGetCurrentClientProcessIDKM(); psPrivData->ui32VirtPageCount = (ui32NumVirtChunks * uiChunkSize) >> PAGE_SHIFT; @@ -752,7 +760,7 @@ PhysmemCreateNewDmaBufBackedPMR(PHYS_HEAP *psHeap, #if defined(PVRSRV_ENABLE_PROCESS_STATS) PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_DMA_BUF_IMPORT, psPrivData->ui32PhysPageCount << PAGE_SHIFT, - OSGetCurrentClientProcessIDKM()); + psPrivData->uiOriginPID); #endif uiPMRFlags = (PMR_FLAGS_T)(uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK); @@ -1079,7 +1087,25 @@ PhysmemImportSparseDmaBuf(CONNECTION_DATA *psConnection, #if defined(SUPPORT_PMR_DEFERRED_FREE) if (PMR_IsZombie(psPMR)) { - PMRDequeueZombieAndRef(psPMR); +#if defined(PVRSRV_ENABLE_PROCESS_STATS) + PMR_DMA_BUF_DATA *psPrivData = PMRGetPrivateData(psPMR, &_sPMRDmaBufFuncTab); +#endif + + PMRReviveZombieAndRef(psPMR); + +#if defined(PVRSRV_ENABLE_PROCESS_STATS) + if (psPrivData != NULL) + { + PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_DMA_BUF_IMPORT, + psPrivData->ui32PhysPageCount << PAGE_SHIFT, + psPrivData->uiOriginPID); + PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_DMA_BUF_ZOMBIE, + psPrivData->ui32PhysPageCount << PAGE_SHIFT, + psPrivData->uiOriginPID); + } +#endif + + PVRSRVIonReviveMemAllocRecord(psDmaBuf); } else #endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ @@ -1089,13 +1115,31 @@ PhysmemImportSparseDmaBuf(CONNECTION_DATA *psConnection, PMRRefPMR(psPMR); } + /* If an existing PMR is found, the table wasn't created by this func + * call, so the error path can be safely ignored allowing for + * the factory lock can be dropped. */ + PVR_ASSERT(bHashTableCreated == IMG_FALSE); + dma_buf_put(psDmaBuf); + PMRFactoryUnlock(); + +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) + /* The device import can only be registered on an alive & healthy PMR + * therefore we wait for the potential zombie to be dequeued first. */ + eError = PMR_RegisterDeviceImport(psPMR, psDevNode); + if (eError != PVRSRV_OK) + { + /* The factory lock might be taken in PMRUnrefPMR. */ + (void) PMRUnrefPMR(psPMR); + PVR_DPF((PVR_DBG_ERROR, "%s: Failed to register PMR with device: %u", + __func__, psDevNode->sDevId.ui32InternalID)); + goto errReturn; + } +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + *ppsPMRPtr = psPMR; PMR_LogicalSize(psPMR, puiSize); *puiAlign = PAGE_SIZE; - PMRFactoryUnlock(); - dma_buf_put(psDmaBuf); - /* We expect a PMR to be immutable at this point. * But its explicitly set here to cover a corner case * where a PMR created through non-DMA interface could be
diff --git a/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_extmem_linux.c b/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_extmem_linux.c index 8ae96a6..7de1200 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_extmem_linux.c +++ b/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_extmem_linux.c
@@ -611,6 +611,15 @@ PMRWriteBytesExtMem(PMR_IMPL_PRIVDATA pvPriv, size_t uiBufSz, size_t *puiNumBytes) { + PMR_WRAP_DATA *psWrapData = (PMR_WRAP_DATA*) pvPriv; + + if (!BITMASK_HAS(psWrapData->psVMArea->vm_flags, VM_WRITE)) + { + PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to write to read only vma.", + __func__)); + return PVRSRV_ERROR_PMR_NOT_PERMITTED; + } + return _CopyBytesExtMem(pvPriv, uiOffset, pcBuffer, @@ -883,6 +892,14 @@ static inline PVRSRV_ERROR PhysmemValidateParam( IMG_DEVMEM_SIZE_T uiSize, return PVRSRV_ERROR_UNSUPPORTED_CACHE_MODE; } + if (uiFlags & PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK) + { + PVR_DPF((PVR_DBG_ERROR, "%s: Device specific flags not supported. " + "Passed Flags: 0x%"PVRSRV_MEMALLOCFLAGS_FMTSPEC, + __func__, uiFlags)); + return PVRSRV_ERROR_INVALID_FLAGS; + } + #if !defined(PVRSRV_WRAP_EXTMEM_WRITE_ATTRIB_ENABLE) if (uiFlags & (PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
diff --git a/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_osmem_linux.c b/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_osmem_linux.c index 21a0f98..62e1071 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_osmem_linux.c +++ b/drivers/gpu/img-rogue/23.2/services/server/env/linux/physmem_osmem_linux.c
@@ -2927,6 +2927,168 @@ _FreeOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData) return PVRSRV_OK; } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +static PVRSRV_ERROR PMRFreeZombiePagesOSMem(PMR_IMPL_ZOMBIEPAGES pvPriv) +{ + PVRSRV_ERROR eError; + PMR_OSPAGEARRAY_DATA *psZombiePageArray = pvPriv; + + eError = _FreeOSPages(psZombiePageArray, + NULL, + 0 /* Unused */); + + if (eError != PVRSRV_OK) + { + goto e0; + } + + _FreeOSPagesArray(psZombiePageArray); + + return PVRSRV_OK; +e0: + return eError; +} + +/* Extracts ui32ExtractPageCount of pages referenced in pai32ExtractIndices from the psSrcPageArrayData + * Allocates a new PMR_OSPAGEARRAY_DATA object and fills it with the extracted pages information. + * Pages in this context are dev page size and are handled as such. + */ +static PVRSRV_ERROR +_ExtractPages(PMR_OSPAGEARRAY_DATA *psSrcPageArrayData, + IMG_UINT32 *pai32ExtractIndices, + IMG_UINT32 ui32ExtractPageCount, + PMR_OSPAGEARRAY_DATA** psOutPageArrayData) +{ + PVRSRV_ERROR eError; + IMG_UINT32 i; + PMR_OSPAGEARRAY_DATA* psDstPageArrayData; + IMG_UINT32 uiOrder; + + /* Alloc PMR_OSPAGEARRAY_DATA for the extracted pages */ + eError = _AllocOSPageArray(psSrcPageArrayData->psDevNode, + (IMG_UINT64)ui32ExtractPageCount << psSrcPageArrayData->uiLog2AllocPageSize, + ui32ExtractPageCount, + ui32ExtractPageCount, + psSrcPageArrayData->uiLog2AllocPageSize, + psSrcPageArrayData->ui32AllocFlags, + psSrcPageArrayData->ui32CPUCacheFlags, + psSrcPageArrayData->uiPid, + &psDstPageArrayData); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "_AllocOSPageArray failed in _ExtractPages")); + return eError; + } + + uiOrder = psSrcPageArrayData->uiLog2AllocPageSize - PAGE_SHIFT; + + /* Transfer from src pagearray to dst pagearray */ + for (i = 0; i < ui32ExtractPageCount; i++) + { + IMG_UINT32 idxSrc = pai32ExtractIndices[i]; + + if (psSrcPageArrayData->pagearray[idxSrc] != NULL) + { + psDstPageArrayData->pagearray[i] = psSrcPageArrayData->pagearray[idxSrc]; + psSrcPageArrayData->pagearray[idxSrc] = NULL; + } + } + + /* Do the same for dmaphysarray and dmavirtarray if allocated with CMA */ + if (BIT_ISSET(psSrcPageArrayData->ui32AllocFlags, FLAG_IS_CMA)) + { + for (i = 0; i < ui32ExtractPageCount; i++) + { + IMG_UINT32 idxSrc = pai32ExtractIndices[i]; + + if (psSrcPageArrayData->dmaphysarray[idxSrc] != (dma_addr_t)0 || + psSrcPageArrayData->dmavirtarray[idxSrc] != NULL) + { + psDstPageArrayData->dmaphysarray[i] = psSrcPageArrayData->dmaphysarray[idxSrc]; + psDstPageArrayData->dmavirtarray[i] = psSrcPageArrayData->dmavirtarray[idxSrc]; + + psSrcPageArrayData->dmaphysarray[idxSrc] = (dma_addr_t)0; + psSrcPageArrayData->dmavirtarray[idxSrc] = NULL; + } + } + } + + /* Update page counts */ + psSrcPageArrayData->iNumOSPagesAllocated -= ui32ExtractPageCount << uiOrder; + psDstPageArrayData->iNumOSPagesAllocated += ui32ExtractPageCount << uiOrder; + + *psOutPageArrayData = psDstPageArrayData; + return PVRSRV_OK; +} + +/* Extracts all allocated pages referenced psSrcPageArrayData + * Allocates a new PMR_OSPAGEARRAY_DATA object and fills it with the extracted + * pages information. + */ +static PVRSRV_ERROR +_ExtractAllPages(PMR_OSPAGEARRAY_DATA *psSrcPageArrayData, + PMR_OSPAGEARRAY_DATA **psOutPageArrayData) +{ + PVRSRV_ERROR eError; + IMG_UINT32 i; + PMR_OSPAGEARRAY_DATA* psDstPageArrayData; + IMG_UINT32 uiPagesCopied = 0; + + /* Alloc PMR_OSPAGEARRAY_DATA for the extracted pages */ + eError = _AllocOSPageArray(psSrcPageArrayData->psDevNode, + (IMG_UINT64)psSrcPageArrayData->uiTotalNumOSPages << psSrcPageArrayData->uiLog2AllocPageSize, + psSrcPageArrayData->iNumOSPagesAllocated, + psSrcPageArrayData->uiTotalNumOSPages, + psSrcPageArrayData->uiLog2AllocPageSize, + psSrcPageArrayData->ui32AllocFlags, + psSrcPageArrayData->ui32CPUCacheFlags, + psSrcPageArrayData->uiPid, + &psDstPageArrayData); + if (eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR, "_AllocOSPageArray failed in _ExtractPages")); + return eError; + } + + /* Transfer from src pagearray to dst pagearray */ + /* Iterate through all pages in psSrcPageArrayData but stop once + * we have copied psSrcPageArrayData->iNumOSPagesAllocated pages to + * psDstPageArrayData. + */ + for (i = 0; ((i < psSrcPageArrayData->uiTotalNumOSPages) && + (uiPagesCopied < psSrcPageArrayData->iNumOSPagesAllocated)); i++) + { + if (psSrcPageArrayData->pagearray[i] != NULL) + { + psDstPageArrayData->pagearray[uiPagesCopied] = + psSrcPageArrayData->pagearray[i]; + + psSrcPageArrayData->pagearray[i] = NULL; + + if (BIT_ISSET(psSrcPageArrayData->ui32AllocFlags, FLAG_IS_CMA) && + (psSrcPageArrayData->dmaphysarray[i] != (dma_addr_t)0 || + psSrcPageArrayData->dmavirtarray[i] != NULL)) + { + psDstPageArrayData->dmaphysarray[uiPagesCopied] = + psSrcPageArrayData->dmaphysarray[i]; + psDstPageArrayData->dmavirtarray[uiPagesCopied] = + psSrcPageArrayData->dmavirtarray[i]; + + psSrcPageArrayData->dmaphysarray[i] = (dma_addr_t)0; + psSrcPageArrayData->dmavirtarray[i] = NULL; + } + uiPagesCopied++; + } + } + /* Update page counts */ + psDstPageArrayData->iNumOSPagesAllocated = psSrcPageArrayData->iNumOSPagesAllocated; + psSrcPageArrayData->iNumOSPagesAllocated = 0; + + *psOutPageArrayData = psDstPageArrayData; + return PVRSRV_OK; +} +#endif /* defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) */ + /* Free pages from a page array. * Takes care of mem stats and chooses correct free path depending on parameters. */ static PVRSRV_ERROR @@ -3124,15 +3286,45 @@ PMRLockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv) return eError; } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +static PVRSRV_ERROR +PMRUnlockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv, + PMR_IMPL_ZOMBIEPAGES *ppvZombiePages) +#else static PVRSRV_ERROR PMRUnlockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv) +#endif { /* Just drops the refcount. */ PVRSRV_ERROR eError = PVRSRV_OK; PMR_OSPAGEARRAY_DATA *psOSPageArrayData = pvPriv; +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_OSPAGEARRAY_DATA *psExtractedPagesPageArray = NULL; + + *ppvZombiePages = NULL; +#endif if (BIT_ISSET(psOSPageArrayData->ui32AllocFlags, FLAG_ONDEMAND)) { +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + if (psOSPageArrayData->iNumOSPagesAllocated == 0) + { + *ppvZombiePages = NULL; + return PVRSRV_OK; + } + + eError = _ExtractAllPages(psOSPageArrayData, + &psExtractedPagesPageArray); + PVR_LOG_GOTO_IF_ERROR(eError, "_ExtractAllPages", e0); + + if (psExtractedPagesPageArray) + { + /* Zombify pages to get proper stats */ + eError = PMRZombifyOSMem(psExtractedPagesPageArray, NULL); + PVR_WARN_IF_ERROR(eError, "PMRZombifyOSMem"); + } + *ppvZombiePages = psExtractedPagesPageArray; +#else /* Free Memory for deferred allocation */ eError = _FreeOSPages(psOSPageArrayData, NULL, @@ -3141,8 +3333,12 @@ PMRUnlockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv) { return eError; } +#endif } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +e0: +#endif PVR_ASSERT(eError == PVRSRV_OK); return eError; } @@ -3460,6 +3656,9 @@ PMRChangeSparseMemOSMem(PMR_IMPL_PRIVDATA pPriv, IMG_UINT32 *pai32AllocIndices, IMG_UINT32 ui32FreePageCount, IMG_UINT32 *pai32FreeIndices, +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_IMPL_ZOMBIEPAGES *ppvZombiePages, +#endif IMG_UINT32 uiFlags) { PVRSRV_ERROR eError; @@ -3512,6 +3711,10 @@ PMRChangeSparseMemOSMem(PMR_IMPL_PRIVDATA pPriv, ui32FreePageCount = 0; } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + *ppvZombiePages = NULL; +#endif + if (0 == (ui32CommonRequestCount || ui32AdtnlAllocPages || ui32AdtnlFreePages)) { eError = PVRSRV_ERROR_INVALID_PARAMS; @@ -3647,9 +3850,27 @@ PMRChangeSparseMemOSMem(PMR_IMPL_PRIVDATA pPriv, } } - /* Free the additional free pages */ + /* Free or zombie the additional free pages */ if (0 != ui32AdtnlFreePages) { +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_OSPAGEARRAY_DATA *psExtractedPagesPageArray = NULL; + + eError = _ExtractPages(psPMRPageArrayData, + &pai32FreeIndices[ui32Loop], + ui32AdtnlFreePages, + &psExtractedPagesPageArray); + if (eError != PVRSRV_OK) + { + goto e0; + } + + /* Zombify pages to get proper stats */ + eError = PMRZombifyOSMem(psExtractedPagesPageArray, NULL); + PVR_LOG_IF_ERROR(eError, "psExtractedPagesPageArray"); + + *ppvZombiePages = psExtractedPagesPageArray; +#else eError = _FreeOSPages(psPMRPageArrayData, &pai32FreeIndices[ui32Loop], ui32AdtnlFreePages); @@ -3657,6 +3878,7 @@ PMRChangeSparseMemOSMem(PMR_IMPL_PRIVDATA pPriv, { goto e0; } +#endif /* SUPPORT_PMR_PAGES_DEFERRED_FREE */ psPMRMapTable->ui32NumPhysChunks -= ui32AdtnlFreePages; while (ui32Loop < ui32FreePageCount) { @@ -3713,6 +3935,9 @@ static PMR_IMPL_FUNCTAB _sPMROSPFuncTab = { .pfnChangeSparseMem = &PMRChangeSparseMemOSMem, .pfnChangeSparseMemCPUMap = &PMRChangeSparseMemCPUMapOSMem, .pfnFinalize = &PMRFinalizeOSMem, +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + .pfnFreeZombiePages = &PMRFreeZombiePagesOSMem, +#endif #if defined(SUPPORT_PMR_DEFERRED_FREE) .pfnZombify = &PMRZombifyOSMem, #endif
diff --git a/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_fence.c b/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_fence.c index 5638dad..07c149a 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_fence.c +++ b/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_fence.c
@@ -1139,7 +1139,7 @@ u32 pvr_fence_dump_info_on_stalled_ufos(struct pvr_fence_context *fctx, /* Dump sync info */ PVR_DUMPDEBUG_LOG(pfnDummy, NULL, - "\tSyncID = %d, FWAddr = 0x%08x: TLID = %d (Foreign Fence - [%p] %s)", + "\tSyncID = %d, FWAddr = 0x%08x: TLID = %d (Foreign Fence - ["IMG_KM_PTR_FMTSPEC"] %s)", SyncCheckpointGetId(checkpoint), fence_ufo_addr, SyncCheckpointGetTimeline(checkpoint),
diff --git a/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_ion_stats.c b/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_ion_stats.c index b145c93..6b5ad15 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_ion_stats.c +++ b/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_ion_stats.c
@@ -587,4 +587,31 @@ void PVRSRVIonZombifyMemAllocRecord(const struct dma_buf *psDmaBuf) out: OSLockRelease(psState->hBuffersLock); } + +void PVRSRVIonReviveMemAllocRecord(const struct dma_buf *psDmaBuf) +{ + PVR_ION_STATS_STATE *psState = &gPvrIonStatsState; + PVR_ION_STATS_BUF *psBuf; + + if (!psDmaBuf) { + PVR_DPF((PVR_DBG_ERROR, "Invalid dma buffer")); + return; + } + + /* We're only interested in ION buffers */ + if (isIonBuf(psDmaBuf) == IMG_FALSE) + return; + + OSLockAcquire(psState->hBuffersLock); + psBuf = GetBuf(&psState->buffers, (uintptr_t)psDmaBuf); + if (!psBuf) { + PVR_DPF((PVR_DBG_ERROR, "Failed to find dma buffer")); + goto out; + } + + psBuf->bZombie = IMG_FALSE; + +out: + OSLockRelease(psState->hBuffersLock); +} #endif
diff --git a/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_ion_stats.h b/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_ion_stats.h index 1c0d44a..c474813 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_ion_stats.h +++ b/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_ion_stats.h
@@ -59,6 +59,7 @@ void PVRSRVIonRemoveMemAllocRecord(struct dma_buf *psDmaBuf); #if defined(SUPPORT_PMR_DEFERRED_FREE) void PVRSRVIonZombifyMemAllocRecord(const struct dma_buf *psDmaBuf); +void PVRSRVIonReviveMemAllocRecord(const struct dma_buf *psDmaBuf); #endif #else static INLINE PVRSRV_ERROR PVRSRVIonStatsInitialise(void) @@ -85,6 +86,10 @@ static INLINE void PVRSRVIonZombifyMemAllocRecord(const struct dma_buf *psDmaBuf { PVR_UNREFERENCED_PARAMETER(psDmaBuf); } +static INLINE void PVRSRVIonReviveMemAllocRecord(const struct dma_buf *psDmaBuf) +{ + PVR_UNREFERENCED_PARAMETER(psDmaBuf); +} #endif #endif /* defined(PVRSRV_ENABLE_PVR_ION_STATS) */
diff --git a/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_sync_file.c b/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_sync_file.c index e365610..385872d 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_sync_file.c +++ b/drivers/gpu/img-rogue/23.2/services/server/env/linux/pvr_sync_file.c
@@ -1036,7 +1036,7 @@ static void _dump_sync_point(struct dma_fence *fence, PVR_DUMPDEBUG_LOG(dump_debug_printf, dump_debug_file, - "<%p> Seq#=%llu TS=%s State=%s TLN=%s", + "<"IMG_KM_PTR_FMTSPEC"> Seq#=%llu TS=%s State=%s TLN=%s", fence, (u64) fence->seqno, time, @@ -1055,7 +1055,7 @@ static void _dump_fence(struct dma_fence *fence, if (fence_array) { PVR_DUMPDEBUG_LOG(dump_debug_printf, dump_debug_file, - "Fence: [%p] Sync Points:\n", + "Fence: ["IMG_KM_PTR_FMTSPEC"] Sync Points:\n", fence_array); for (i = 0; i < fence_array->num_fences; i++)
diff --git a/drivers/gpu/img-rogue/23.2/services/server/include/handle.h b/drivers/gpu/img-rogue/23.2/services/server/include/handle.h index 92946b6..7ce28a5 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/include/handle.h +++ b/drivers/gpu/img-rogue/23.2/services/server/include/handle.h
@@ -152,6 +152,7 @@ typedef struct _PROCESS_HANDLE_BASE_ { PVRSRV_HANDLE_BASE *psHandleBase; ATOMIC_T iRefCount; + uintptr_t uiHashKey; } PROCESS_HANDLE_BASE; extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase; @@ -195,10 +196,13 @@ PVRSRV_ERROR PVRSRVHandleInit(void); PVRSRV_ERROR PVRSRVHandleDeInit(void); +/* Only called from sync_fallback_server.c */ +#if defined(SUPPORT_FALLBACK_FENCE_SYNC) PVRSRV_HANDLE_BASE *PVRSRVRetrieveProcessHandleBase(void); +#endif -PVRSRV_ERROR PVRSRVAcquireProcessHandleBase(IMG_PID uiPid, PROCESS_HANDLE_BASE **ppsBase); -PVRSRV_ERROR PVRSRVReleaseProcessHandleBase(PROCESS_HANDLE_BASE *psBase, IMG_PID uiPid, IMG_UINT64 ui64MaxBridgeTime); +PVRSRV_ERROR PVRSRVAcquireProcessHandleBase(PROCESS_HANDLE_BASE **ppsBase); +PVRSRV_ERROR PVRSRVReleaseProcessHandleBase(PROCESS_HANDLE_BASE *psBase, IMG_UINT64 ui64MaxBridgeTime); void LockHandle(PVRSRV_HANDLE_BASE *psBase); void UnlockHandle(PVRSRV_HANDLE_BASE *psBase);
diff --git a/drivers/gpu/img-rogue/23.2/services/server/include/mmu_common.h b/drivers/gpu/img-rogue/23.2/services/server/include/mmu_common.h index b14046d..797ce6e 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/include/mmu_common.h +++ b/drivers/gpu/img-rogue/23.2/services/server/include/mmu_common.h
@@ -512,7 +512,7 @@ MMUX_MapVRangeToBackingPage(MMU_CONTEXT *psMMUContext, PVRSRV_ERROR MMU_MapPMRFast(MMU_CONTEXT *psMMUContext, IMG_DEV_VIRTADDR sDevVAddr, - const PMR *psPMR, + PMR *psPMR, IMG_DEVMEM_SIZE_T uiSizeBytes, PVRSRV_MEMALLOCFLAGS_T uiMappingFlags, IMG_UINT32 uiLog2PageSize);
diff --git a/drivers/gpu/img-rogue/23.2/services/server/include/osfunc.h b/drivers/gpu/img-rogue/23.2/services/server/include/osfunc.h index 07e8a4d..d2b67d3 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/include/osfunc.h +++ b/drivers/gpu/img-rogue/23.2/services/server/include/osfunc.h
@@ -684,6 +684,32 @@ IMG_PID OSGetCurrentClientProcessIDKM(void); IMG_CHAR *OSGetCurrentClientProcessNameKM(void); /*************************************************************************/ /*! +@Function OSAcquireCurrentPPIDResourceRefKM +@Description Returns a unique process identifier for the current client + parent process (thread group) and takes a reference on it + (if required) to prevent it being freed/re-allocated. + This value may then be used as a unique reference to the + process rather than using the PID value which might be + reallocated to represent a further process on process + destruction. + Note that the value to be returned is an address relating to + the parent process (thread group) and not to just one thread. + It is the caller's responsibility to ensure the reference is + subsequently dropped (by calling OSReleasePPIDResourceRefKM()) + to allow it to be freed when no longer required. +@Return Address of a kernel resource allocated for the current client + parent process (thread group) +*****************************************************************************/ +uintptr_t OSAcquireCurrentPPIDResourceRefKM(void); + +/*************************************************************************/ /*! +@Function OSReleasePPIDResourceRefKM +@Description Drops a reference on the unique process identifier provided. +@Return None +*****************************************************************************/ +void OSReleasePPIDResourceRefKM(uintptr_t psPPIDResource); + +/*************************************************************************/ /*! @Function OSGetCurrentClientThreadIDKM @Description Returns ID for current client thread For some operating systems, this may simply be the current
diff --git a/drivers/gpu/img-rogue/23.2/services/server/include/pmr.h b/drivers/gpu/img-rogue/23.2/services/server/include/pmr.h index ac331ba..e4d64ea 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/include/pmr.h +++ b/drivers/gpu/img-rogue/23.2/services/server/include/pmr.h
@@ -531,6 +531,34 @@ PMRCpuMapCountDecr(PMR *psPMR); IMG_BOOL PMR_IsCpuMapped(PMR *psPMR); +/* + * PMRGpuResCountIncr() + * + * Increment count of the number of current GPU reservations associated with the PMR. + * Must be protected by PMR lock. + */ +void +PMRGpuResCountIncr(PMR *psPMR); + +/* + * PMRGpuResCountDecr() + * + * Decrement count of the number of current GPU reservations associated with the PMR. + * Must be protected by PMR lock. + * + */ +void +PMRGpuResCountDecr(PMR *psPMR); + +/* + * PMR_IsGpuMultiMapped() + * + * Must be protected by PMR lock. + * + */ +IMG_BOOL +PMR_IsGpuMultiMapped(PMR *psPMR); + PPVRSRV_DEVICE_NODE PMR_DeviceNode(const PMR *psPMR); @@ -685,16 +713,32 @@ IMG_BOOL PMRQueueZombiesForCleanup(PPVRSRV_DEVICE_NODE psDevNode); /* - * PMRDequeueZombieAndRef + * PMRReviveZombieAndRef * * Removed the PMR either form zombie list or cleanup item's list * and references it. */ void -PMRDequeueZombieAndRef(PMR *psPMR); +PMRReviveZombieAndRef(PMR *psPMR); #endif /* defined(SUPPORT_PMR_DEFERRED_FREE) */ /* + * PMR_ChangeSparseMemUnlocked() + * + * See note above about Lock/Unlock semantics. + * + * This function alters the memory map of the given PMR in device space by + * adding/deleting the pages as requested. PMR lock must be taken + * before calling this function. + * + */ +PVRSRV_ERROR PMR_ChangeSparseMemUnlocked(PMR *psPMR, + IMG_UINT32 ui32AllocPageCount, + IMG_UINT32 *pai32AllocIndices, + IMG_UINT32 ui32FreePageCount, + IMG_UINT32 *pai32FreeIndices, + IMG_UINT32 uiSparseFlags); +/* * PMR_ChangeSparseMem() * * See note above about Lock/Unlock semantics. @@ -1155,4 +1199,17 @@ PMRGetIPAInfo(PMR *psPMR, IMG_UINT32 *pui32IPAPolicy, IMG_UINT32 *pui32IPAShift, IMG_UINT32 *pui32IPAMask, IMG_UINT32 *pui32IPAFlagsValue); #endif +#if defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) +/* + * + * PMR_RegisterDeviceImport() + * + * Register the PMR with the device node. + * This is required for the PMR to be marked as a XD PMR. + * Silently handles if the PMR is already registered with the device. + */ +PVRSRV_ERROR +PMR_RegisterDeviceImport(PMR* psPMR, PPVRSRV_DEVICE_NODE psDevNode); +#endif /* defined(SUPPORT_PMR_DEVICE_IMPORT_DEFERRED_FREE) */ + #endif /* #ifdef SRVSRV_PMR_H */
diff --git a/drivers/gpu/img-rogue/23.2/services/server/include/pmr_impl.h b/drivers/gpu/img-rogue/23.2/services/server/include/pmr_impl.h index 68089dd..3fc7949 100644 --- a/drivers/gpu/img-rogue/23.2/services/server/include/pmr_impl.h +++ b/drivers/gpu/img-rogue/23.2/services/server/include/pmr_impl.h
@@ -79,6 +79,10 @@ typedef struct _PMR_MAPPING_TABLE_ PMR_MAPPING_TABLE; */ typedef void *PMR_MMAP_DATA; +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +typedef void *PMR_IMPL_ZOMBIEPAGES; +#endif + #define PMR_IMPL_TYPES \ X(NONE), \ X(OSMEM), \ @@ -135,11 +139,22 @@ typedef PVRSRV_ERROR (*PFN_LOCK_PHYS_ADDRESSES_FN)(PMR_IMPL_PRIVDATA pvPriv); @Input pvPriv Private data (which was generated by the PMR factory when PMR was created) +@Output ppvZombiePages Zombie pages object. If non-null is returned + caller is obligated to call pfnFreeZombiePages + at an appropriate time to prevent memory leaks. + If support for deferred freeing of pages is not + provided, the implementation must set + *ppvZombiePages to NULL. @Return PVRSRV_OK if the operation was successful, an error code otherwise. */ /**************************************************************************/ +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +typedef PVRSRV_ERROR (*PFN_UNLOCK_PHYS_ADDRESSES_FN)(PMR_IMPL_PRIVDATA pvPriv, + PMR_IMPL_ZOMBIEPAGES *ppvZombiePages); +#else typedef PVRSRV_ERROR (*PFN_UNLOCK_PHYS_ADDRESSES_FN)(PMR_IMPL_PRIVDATA pvPriv); +#endif #if defined(PVRSRV_SUPPORT_IPA_FEATURE) /*************************************************************************/ /*! @@ -365,6 +380,9 @@ typedef PVRSRV_ERROR (*PFN_WRITE_BYTES_FN)(PMR_IMPL_PRIVDATA pvPriv, allocation that do not require a physical allocation. @Input ui32Flags Allocation flags +@Output ppvZombiePages Zombie pages object. If non-null is returned + caller is obligated to call pfnFreeZombiePages + at an appropriate time to prevent memory leaks @Return PVRSRV_OK if the sparse allocation physical backing was updated successfully, an error code otherwise. @@ -375,6 +393,9 @@ typedef PVRSRV_ERROR (*PFN_CHANGE_SPARSE_MEM_FN)(PMR_IMPL_PRIVDATA pPriv, IMG_UINT32 *pai32AllocIndices, IMG_UINT32 ui32FreePageCount, IMG_UINT32 *pai32FreeIndices, +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) + PMR_IMPL_ZOMBIEPAGES *ppvZombiePages, +#endif IMG_UINT32 uiFlags); /*************************************************************************/ /*! @@ -507,6 +528,29 @@ typedef PVRSRV_ERROR (*PFN_ZOMBIFY_FN)(PMR_IMPL_PRIVDATA pvPriv, PMR *psPMR); #endif +#ifdef SUPPORT_PMR_PAGES_DEFERRED_FREE +/*************************************************************************/ /*! +@Brief Callback function type PFN_FREE_ZOMBIE_PAGES_FN + +@Description Called to perform factory actions to free zombie pages object + previously returned by PFN_CHANGE_SPARSE_MEM_FN. + + This function should free the pages described in the + pvZombiePages parameter and do any associated actions related + to freeing such as poisoning or returning to the page pool. + + Implementation of this callback is required when + SUPPORT_PMR_PAGES_DEFERRED_FREE=1. + +@Return PVRSRV_OK if the operation was successful, an error code + otherwise. If error is returned, the PMR layer might retry. + On error, factory implementations should modify the contents + of the PMR_IMPL_ZOMBIEPAGES object reflecting any changes in + underlying memory as a result of the initial (failed) call. +*/ /**************************************************************************/ +typedef PVRSRV_ERROR (*PFN_FREE_ZOMBIE_PAGES_FN)(PMR_IMPL_ZOMBIEPAGES pvZombiePages); +#endif + /*! PMR factory callback table. */ struct _PMR_IMPL_FUNCTAB_ { @@ -533,6 +577,11 @@ struct _PMR_IMPL_FUNCTAB_ { /*! Callback function pointer, see ::PFN_CHANGE_SPARSE_MEM_CPU_MAP_FN */ PFN_CHANGE_SPARSE_MEM_CPU_MAP_FN pfnChangeSparseMemCPUMap; +#ifdef SUPPORT_PMR_PAGES_DEFERRED_FREE + /*! Callback function pointer, see ::PFN_FREE_ZOMBIE_PAGES_FN */ + PFN_FREE_ZOMBIE_PAGES_FN pfnFreeZombiePages; +#endif + /*! Callback function pointer, see ::PFN_MMAP_FN */ PFN_MMAP_FN pfnMMap;
diff --git a/drivers/gpu/img-rogue/23.2/services/shared/common/ra.c b/drivers/gpu/img-rogue/23.2/services/shared/common/ra.c index dc4df4b..e792c1c 100644 --- a/drivers/gpu/img-rogue/23.2/services/shared/common/ra.c +++ b/drivers/gpu/img-rogue/23.2/services/shared/common/ra.c
@@ -215,6 +215,12 @@ struct _RA_ARENA_ITERATOR_ IMG_BOOL bIncludeFreeSegments; }; +/* Enum for selecting behaviour of _ConvertAndFree* functions*/ +typedef enum { + CONVERT_AND_FREE = 0, + CONVERT_DONT_FREE = 1 +} RA_CONVERT_AND_FREE_BEHAVIOUR; + static PVRSRV_ERROR _RA_FreeMultiUnlocked(RA_ARENA *pArena, RA_BASE_ARRAY_T aBaseArray, RA_BASE_ARRAY_SIZE_T uiBaseArraySize); @@ -1146,28 +1152,32 @@ _ConvertGhostBaseToReal(RA_ARENA *pArena, } /*************************************************************************/ /*! - * @Function _FreeGhostBasesFromReal + * @Function _ConvertAndFreeStartFromGhost * - * @Description Given a ghost base and size, free the contiguous ghost bases from the - * real base. This has the effect of shrinking the size of the real base. - * If ghost pages remain after the free region, a new Real base will be + * @Description Given a ghost base and size, convert and free contiguous + * ghost bases. This has the effect of shrinking the size of + * the real base holding the range to free. If ghost pages + * remain after the free region, a new Real base will be * created to host them. + * * @Input pArena - The RA Arena to free the Ghost Bases from. * @Input aBaseArray - The array to remove bases from * @Input uiBaseArraySize - The size of the Base array to free from. * @Input uiChunkSize - The chunk size used to generate the Ghost Bases. * @Input ui32GhostBaseIndex - The index into the array of the initial Ghost base to free * @Input ui32FreeCount - The number of Ghost bases to free from the Real base. + * @Input eBehaviour - Specifies if the function should convert and free or only convert. * * @Return PVRSRV_OK on Success, PVRSRV_ERROR code on Failure. */ /**************************************************************************/ static PVRSRV_ERROR -_FreeGhostBasesFromReal(RA_ARENA *pArena, - RA_BASE_ARRAY_T aBaseArray, - RA_BASE_ARRAY_SIZE_T uiBaseArraySize, - RA_LENGTH_T uiChunkSize, - IMG_UINT32 ui32GhostBaseIndex, - IMG_UINT32 ui32FreeCount) +_ConvertAndFreeStartFromGhost(RA_ARENA *pArena, + RA_BASE_ARRAY_T aBaseArray, + RA_BASE_ARRAY_SIZE_T uiBaseArraySize, + RA_LENGTH_T uiChunkSize, + IMG_UINT32 ui32GhostBaseIndex, + IMG_UINT32 ui32FreeCount, + RA_CONVERT_AND_FREE_BEHAVIOUR eBehaviour) { PVRSRV_ERROR eError; RA_BASE_T uiRealBase; @@ -1207,17 +1217,20 @@ _FreeGhostBasesFromReal(RA_ARENA *pArena, PVR_LOG_RETURN_IF_ERROR(eError, "_ConvertGhostBaseToReal"); } - /* Free the region calculated */ - eError = _FreeSingleBaseArray(pArena, - &aBaseArray[ui32GhostBaseIndex], - ui32FreeCount); - PVR_LOG_RETURN_IF_ERROR(eError, "_ConvertGhostBaseToReal"); + if (eBehaviour == CONVERT_AND_FREE) + { + /* Free the region calculated */ + eError = _FreeSingleBaseArray(pArena, + &aBaseArray[ui32GhostBaseIndex], + ui32FreeCount); + PVR_LOG_RETURN_IF_ERROR(eError, "_ConvertGhostBaseToReal"); + } return eError; } /*************************************************************************/ /*! - * @Function _ConvertGhostBaseFreeReal + * @Function _ConvertAndFreeStartFromReal * * @Description Used in the case that we want to keep some indices that are ghost pages * but the indices to free start with the real base. In this case we can @@ -1228,15 +1241,17 @@ _FreeGhostBasesFromReal(RA_ARENA *pArena, * @Input aBaseArray - The Base array to free from. * @Input uiChunkSize - The chunk size used to generate the Ghost bases. * @Input uiGhostBaseIndex - The index into the array of the Ghost base to convert. + * @Input eBehaviour - Specifies if the function should convert and free or only convert. * * @Return PVRSRV_OK on Success, PVRSRV_ERROR code on Failure. */ /**************************************************************************/ static PVRSRV_ERROR -_ConvertGhostBaseFreeReal(RA_ARENA *pArena, - RA_BASE_ARRAY_T aBaseArray, - RA_LENGTH_T uiChunkSize, - IMG_UINT32 uiRealBaseIndex, - IMG_UINT32 uiGhostBaseIndex) +_ConvertAndFreeStartFromReal(RA_ARENA *pArena, + RA_BASE_ARRAY_T aBaseArray, + RA_LENGTH_T uiChunkSize, + IMG_UINT32 uiRealBaseIndex, + IMG_UINT32 uiGhostBaseIndex, + RA_CONVERT_AND_FREE_BEHAVIOUR eBehaviour) { PVRSRV_ERROR eError; RA_BASE_T uiRealBase = aBaseArray[uiRealBaseIndex]; @@ -1249,18 +1264,22 @@ _ConvertGhostBaseFreeReal(RA_ARENA *pArena, uiChunkSize); PVR_LOG_RETURN_IF_ERROR(eError, "_ConvertGhostBaseToReal"); - eError = _FreeSingleBaseArray(pArena, - &aBaseArray[uiRealBaseIndex], - uiGhostBaseIndex - uiRealBaseIndex); - PVR_LOG_RETURN_IF_ERROR(eError, "_FreeBaseArray"); + if (eBehaviour == CONVERT_AND_FREE) + { + eError = _FreeSingleBaseArray(pArena, + &aBaseArray[uiRealBaseIndex], + uiGhostBaseIndex - uiRealBaseIndex); + PVR_LOG_RETURN_IF_ERROR(eError, "_FreeBaseArray"); + } return eError; } /*************************************************************************/ /*! - * @Function _FreeBaseArraySlice + * @Function _ConvertAndFreeBaseArraySlice * - * @Description Free Bases in an Array Slice. + * @Description Convert and maybe free Bases in an Array Slice. + * This function might convert some ghosts into real bases. * This function assumes that the slice is within a single Real base alloc. * i.e the uiFreeStartIndex and uiFreeCount remain fully within a single real * base alloc and do not cross into another Real base region. @@ -1271,16 +1290,18 @@ _ConvertGhostBaseFreeReal(RA_ARENA *pArena, * @Input uiChunkSize - The base chunk size used to generate the Ghost bases. * @Input uiFreeStartIndex - The index in the array to start freeing from * @Input uiFreeCount - The number of bases to free. + * @Input eBehaviour - Specifies if the function should convert and free or only convert. * * @Return PVRSRV_OK on Success, PVRSRV_ERROR code on Failure. */ /**************************************************************************/ static PVRSRV_ERROR -_FreeBaseArraySlice(RA_ARENA *pArena, - RA_BASE_ARRAY_T aBaseArray, - RA_BASE_ARRAY_SIZE_T uiBaseArraySize, - RA_LENGTH_T uiChunkSize, - IMG_UINT32 uiFreeStartIndex, - IMG_UINT32 uiFreeCount) +_ConvertAndFreeBaseArraySlice(RA_ARENA *pArena, + RA_BASE_ARRAY_T aBaseArray, + RA_BASE_ARRAY_SIZE_T uiBaseArraySize, + RA_LENGTH_T uiChunkSize, + IMG_UINT32 uiFreeStartIndex, + IMG_UINT32 uiFreeCount, + RA_CONVERT_AND_FREE_BEHAVIOUR eBehaviour) { /*3 cases: * Key: () = Region to Free @@ -1322,32 +1343,37 @@ _FreeBaseArraySlice(RA_ARENA *pArena, RA_BASE_IS_REAL(aBaseArray[uiFreeStartIndex + uiFreeCount]) || RA_BASE_IS_INVALID(aBaseArray[uiFreeStartIndex + uiFreeCount])) { - eError = _FreeSingleBaseArray(pArena, - &aBaseArray[uiFreeStartIndex], - uiFreeCount); - PVR_LOG_RETURN_IF_ERROR(eError, "_FreeBaseArray"); + if (eBehaviour == CONVERT_AND_FREE) + { + eError = _FreeSingleBaseArray(pArena, + &aBaseArray[uiFreeStartIndex], + uiFreeCount); + PVR_LOG_RETURN_IF_ERROR(eError, "_FreeBaseArray"); + } } /* Case 2*/ else { - eError = _ConvertGhostBaseFreeReal(pArena, - aBaseArray, - uiChunkSize, - uiFreeStartIndex, - uiFreeStartIndex + uiFreeCount); - PVR_LOG_RETURN_IF_ERROR(eError, "_ConvertGhostBaseToReal"); + eError = _ConvertAndFreeStartFromReal(pArena, + aBaseArray, + uiChunkSize, + uiFreeStartIndex, + uiFreeStartIndex + uiFreeCount, + eBehaviour); + PVR_LOG_RETURN_IF_ERROR(eError, "_ConvertAndFreeStartFromReal"); } } /* Case 3 */ else if (RA_BASE_IS_GHOST(aBaseArray[uiFreeStartIndex])) { - eError = _FreeGhostBasesFromReal(pArena, - aBaseArray, - uiBaseArraySize, - uiChunkSize, - uiFreeStartIndex, - uiFreeCount); - PVR_LOG_RETURN_IF_ERROR(eError, "_FreeGhostBasesFromReal"); + eError = _ConvertAndFreeStartFromGhost(pArena, + aBaseArray, + uiBaseArraySize, + uiChunkSize, + uiFreeStartIndex, + uiFreeCount, + eBehaviour); + PVR_LOG_RETURN_IF_ERROR(eError, "_ConvertAndFreeStartFromGhost"); } /* Attempt to free an invalid base, this could be a duplicated * value in the free sparse index array */ @@ -2802,13 +2828,14 @@ _RA_FreeMultiUnlockedSparse(RA_ARENA *pArena, /* Handle case where we only have 1 base to free. */ if (uiFreeCount == 1) { - eError = _FreeBaseArraySlice(pArena, - aBaseArray, - uiBaseArraySize, - uiChunkSize, - puiFreeIndices[0], - 1); - PVR_LOG_IF_ERROR(eError, "_FreeBaseArraySlice"); + eError = _ConvertAndFreeBaseArraySlice(pArena, + aBaseArray, + uiBaseArraySize, + uiChunkSize, + puiFreeIndices[0], + 1, + CONVERT_AND_FREE); + PVR_LOG_IF_ERROR(eError, "_ConvertAndFreeBaseArraySlice"); if (eError == PVRSRV_OK) { *puiFreeCount = uiFreeCount; @@ -2832,13 +2859,14 @@ _RA_FreeMultiUnlockedSparse(RA_ARENA *pArena, uiConsolidate++; } - eError = _FreeBaseArraySlice(pArena, - aBaseArray, - uiBaseArraySize, - uiChunkSize, - puiFreeIndices[i], - uiConsolidate); - PVR_LOG_RETURN_IF_ERROR(eError, "_FreeBaseArraySlice"); + eError = _ConvertAndFreeBaseArraySlice(pArena, + aBaseArray, + uiBaseArraySize, + uiChunkSize, + puiFreeIndices[i], + uiConsolidate, + CONVERT_AND_FREE); + PVR_LOG_RETURN_IF_ERROR(eError, "_ConvertAndFreeBaseArraySlice"); i += uiConsolidate; *puiFreeCount += uiConsolidate; @@ -2887,6 +2915,151 @@ RA_FreeMultiSparse(RA_ARENA *pArena, return eError; } +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +/*************************************************************************/ /*! + * @Function _RA_RealiseMultiSparseIndicesUnlocked + * + * @Description Given an array of indices to extract, prepares the base + * array so that the indices in puiExtractIndices can be + * moved to another base array. + * Called when some pages of the base array need to be + * transferred to another base array. As a result of this call, + * some ghost addresses in aBaseArray might be converted to + * real addresses. + * + * @Input pArena - The RA Arena to free the bases on. + * @Input aBaseArray - The Base array to free from + * @Input uiBaseArraySize - The Size of the base array to free. + * @Input uiChunkSize - The Base chunk size used to generate ghost entries + * @Input puiExtractIndices - Array of indices to extract + * @Input puiExtractCount - Number of indices to extract + * + * @Return PVRSRV_OK on Success, PVRSRV_ERROR code otherwise. +*/ /**************************************************************************/ +static PVRSRV_ERROR +_RA_RealiseMultiSparseIndicesUnlocked(RA_ARENA *pArena, + RA_BASE_ARRAY_T aBaseArray, + RA_BASE_ARRAY_SIZE_T uiBaseArraySize, + RA_LENGTH_T uiChunkSize, + IMG_UINT32 *puiExtractIndices, + IMG_UINT32 *puiExtractCount) +{ + IMG_UINT32 i; + PVRSRV_ERROR eError; + IMG_UINT32 uiExtractCount = *puiExtractCount; + *puiExtractCount = 0; + + /* Handle case where we only have 1 base to extract. */ + if (uiExtractCount == 1) + { + eError = _ConvertAndFreeBaseArraySlice(pArena, + aBaseArray, + uiBaseArraySize, + uiChunkSize, + puiExtractIndices[0], + 1, + CONVERT_DONT_FREE); + PVR_LOG_IF_ERROR(eError, "_ConvertAndFreeBaseArraySlice"); + if (eError == PVRSRV_OK) + { + *puiExtractCount = uiExtractCount; + } + return eError; + } + + for (i = 0; i < uiExtractCount;) + { + IMG_UINT32 j; + IMG_UINT32 uiConsolidate = 1; + + PVR_ASSERT(RA_BASE_IS_REAL(aBaseArray[i])); + + for (j = i; + puiExtractIndices[j + 1] == puiExtractIndices[j] + 1 && + RA_BASE_IS_GHOST(aBaseArray[puiExtractIndices[j + 1]]) && + j + 1 < uiExtractCount; + j++) + { + uiConsolidate++; + } + + eError = _ConvertAndFreeBaseArraySlice(pArena, + aBaseArray, + uiBaseArraySize, + uiChunkSize, + puiExtractIndices[i], + uiConsolidate, + CONVERT_DONT_FREE); + PVR_LOG_RETURN_IF_ERROR(eError, "_ConvertAndFreeBaseArraySlice"); + + i += uiConsolidate; + *puiExtractCount += uiConsolidate; + } + + return PVRSRV_OK; +} + +IMG_INTERNAL PVRSRV_ERROR +RA_TransferMultiSparseIndices(RA_ARENA *pArena, + RA_BASE_ARRAY_T aSrcBaseArray, + RA_BASE_ARRAY_SIZE_T uiSrcBaseArraySize, + RA_BASE_ARRAY_T aDstBaseArray, + RA_BASE_ARRAY_SIZE_T uiDstBaseArraySize, + IMG_UINT32 uiLog2ChunkSize, + IMG_UINT32 *puiTransferIndices, + IMG_UINT32 *puiTransferCount) +{ + PVRSRV_ERROR eError; + IMG_UINT32 i; + + PVR_LOG_RETURN_IF_FALSE(puiTransferCount != NULL, + "puiTransferCount Required", + PVRSRV_ERROR_INVALID_PARAMS); + + /* Ensure source Base Array is large enough for intended extract */ + PVR_LOG_RETURN_IF_FALSE(uiSrcBaseArraySize >= *puiTransferCount, + "Attempt to transfer more bases than src array holds", + PVRSRV_ERROR_INVALID_PARAMS); + + /* Ensure dst Base Array is large enough for intended extract */ + PVR_LOG_RETURN_IF_FALSE(uiDstBaseArraySize <= *puiTransferCount, + "Attempt to transfer more bases than dst array holds", + PVRSRV_ERROR_INVALID_PARAMS); + + PVR_LOG_RETURN_IF_FALSE(puiTransferIndices != NULL, + "puiTransferIndices Required", + PVRSRV_ERROR_INVALID_PARAMS); + + PVR_LOG_RETURN_IF_FALSE(uiLog2ChunkSize >= RA_BASE_FLAGS_LOG2 && + uiLog2ChunkSize <= RA_BASE_CHUNK_LOG2_MAX, + "Log2 chunk size must be 12-64", + PVRSRV_ERROR_INVALID_PARAMS); + + OSLockAcquireNested(pArena->hLock, pArena->ui32LockClass); + /* First prepare the base array for subsequent transfer */ + eError = _RA_RealiseMultiSparseIndicesUnlocked(pArena, + aSrcBaseArray, + uiSrcBaseArraySize, + 1ULL << uiLog2ChunkSize, + puiTransferIndices, + puiTransferCount); + OSLockRelease(pArena->hLock); + PVR_GOTO_IF_ERROR(eError, e0); + + /* Now do the transfer */ + for (i=0; i<*puiTransferCount; i++) + { + IMG_UINT32 idxSrc = puiTransferIndices[i]; + aDstBaseArray[i] = aSrcBaseArray[idxSrc]; + aSrcBaseArray[idxSrc] = INVALID_BASE_ADDR; + } + + return PVRSRV_OK; +e0: + return eError; +} +#endif /* defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) */ + static PVRSRV_ERROR _TrimBlockMakeReal(RA_ARENA *pArena, RA_BASE_ARRAY_T aBaseArray,
diff --git a/drivers/gpu/img-rogue/23.2/services/shared/include/ra.h b/drivers/gpu/img-rogue/23.2/services/shared/include/ra.h index 654c24d..d62df6d 100644 --- a/drivers/gpu/img-rogue/23.2/services/shared/include/ra.h +++ b/drivers/gpu/img-rogue/23.2/services/shared/include/ra.h
@@ -70,7 +70,7 @@ typedef struct _RA_ITERATOR_DATA_ { typedef struct _RA_USAGE_STATS { IMG_UINT64 ui64TotalArenaSize; IMG_UINT64 ui64FreeArenaSize; -}RA_USAGE_STATS, *PRA_USAGE_STATS; +} RA_USAGE_STATS, *PRA_USAGE_STATS; /* * Per-Arena handle - this is private data for the caller of the RA. @@ -521,6 +521,39 @@ RA_FreeMultiSparse(RA_ARENA *pArena, IMG_UINT32 *puiFreeIndices, IMG_UINT32 *puiFreeCount); +#if defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) +/** + * @Function RA_TransferMultiSparseIndices + * + * @Description Transfers a set of indices specified in puiTransferIndices from + * aSrcBaseArray to aDstBaseArray. + * Called when some pages of the base array need to be + * transfered to another base array. As a result of this call, + * some ghost addresses in aBaseArray might be converted to + * real addresses before being transferred.. + * + * @Input pArena - The arena the segment was originally allocated from. + * @Input aSrcBaseArray - The array to transfer bases from. + * @Input uiSrcBaseArraySize - Size of the array to transfer bases from. + * @Input aDstBaseArray - The array to transfer bases to. + * @Input uiDstBaseArraySize - Size of the array to transfer bases to. + * @Input uiLog2ChunkSize - The log2 chunk size used to generate the Ghost bases. + * @Input puiTransferIndices - The indices into the array to be extracted. + * @InOut puiTransferCount - The number of bases to prepare for extraction. + * + * @Return PVRSRV_OK - success + */ +PVRSRV_ERROR +RA_TransferMultiSparseIndices(RA_ARENA *pArena, + RA_BASE_ARRAY_T aSrcBaseArray, + RA_BASE_ARRAY_SIZE_T uiSrcBaseArraySize, + RA_BASE_ARRAY_T aDstBaseArray, + RA_BASE_ARRAY_SIZE_T uiDstBaseArraySize, + IMG_UINT32 uiLog2ChunkSize, + IMG_UINT32 *puiTransferIndices, + IMG_UINT32 *puiTransferCount); +#endif /* defined(SUPPORT_PMR_PAGES_DEFERRED_FREE) */ + /** * @Function RA_Alloc_Range *
diff --git a/drivers/misc/mediatek/hdmi/hdmitx/mt8696/hdmicmd.c b/drivers/misc/mediatek/hdmi/hdmitx/mt8696/hdmicmd.c index 6f1b798..4d80714 100644 --- a/drivers/misc/mediatek/hdmi/hdmitx/mt8696/hdmicmd.c +++ b/drivers/misc/mediatek/hdmi/hdmitx/mt8696/hdmicmd.c
@@ -1716,6 +1716,82 @@ void mt_hdmi_set_edid(int en, char *file_name, int len) HDMI_ATTR_SPRINTF("set test edid done\n"); } +void mt_hdmi_load_denylist(int en, char *file_name) +{ + const struct firmware *fw_entry = NULL; + int ret; + unsigned int i = 0; + unsigned char _all0xFF[sizeof(struct DenyList_DATA)]; + + HDMI_ATTR_SPRINTF("filename %s and enable %d\n", file_name, en); + + if (!en) { + goto NotUse; + } + + /* read file from /vendor/firmware */ + ret = request_firmware(&fw_entry, file_name, &(hdmi_pdev->dev)); + if (ret != 0) { + HDMI_ATTR_SPRINTF("request %s file fail(%d)!!!\n", file_name, ret); + if (fw_entry) + release_firmware(fw_entry); + goto NotUse; + } + + HDMI_ATTR_SPRINTF("filename %s len %lu\n", file_name, fw_entry->size); + + if (fw_entry->size > DENYLIST_FILE_MAX_LEN) { + HDMI_ATTR_SPRINTF("invalid content size 0x%lx\n", fw_entry->size); + HDMI_ATTR_SPRINTF("The maximun file size is 0x%d\n", DENYLIST_FILE_MAX_LEN); + release_firmware(fw_entry); + goto NotUse; + } + + memset(_all0xFF, 0xFF, sizeof(_all0xFF)); + + if (memcmp(fw_entry->data, _all0xFF, sizeof(_all0xFF)) == 0) { + HDMI_ATTR_SPRINTF("First 32 bytes are all 0xFF, not use the file as deny list\n"); + release_firmware(fw_entry); + goto NotUse; + } + + memcpy(gDenyList.DL_DATA, fw_entry->data, fw_entry->size); + gDenyList.u1NumSize = fw_entry->size / sizeof(struct DenyList_DATA); + gDenyList.u1DataFromFile = true; + release_firmware(fw_entry); + + for (i = 0; i < gDenyList.u1NumSize; i++) { + HDMI_ATTR_SPRINTF("deny list %d u1OpType: 0x%x\n", + i, gDenyList.DL_DATA[i].u1OpType); + HDMI_ATTR_SPRINTF("deny list %d valid.u1CheckIdManufacturerName: 0x%x\n", + i, gDenyList.DL_DATA[i].valid.u1CheckIdManufacturerName); + HDMI_ATTR_SPRINTF("deny list %d valid.u1CheckIdProductCode: 0x%x\n", + i, gDenyList.DL_DATA[i].valid.u1CheckIdProductCode); + HDMI_ATTR_SPRINTF("deny list %d valid.u1CheckYearOfManufacturer: 0x%x\n", + i, gDenyList.DL_DATA[i].valid.u1CheckYearOfManufacturer); + HDMI_ATTR_SPRINTF("deny list %d valid.u1CheckDolbyTrueHdChType192: 0x%x\n", + i, gDenyList.DL_DATA[i].valid.u1CheckDolbyTrueHdChType192); + HDMI_ATTR_SPRINTF("deny list %d u1IdManufacturerName[0]: 0x%x\n", + i, gDenyList.DL_DATA[i].u1IdManufacturerName[0]); + HDMI_ATTR_SPRINTF("deny list %d u1IdManufacturerName[1]: 0x%x\n", + i, gDenyList.DL_DATA[i].u1IdManufacturerName[1]); + HDMI_ATTR_SPRINTF("deny list %d u1IdProductCode[0]: 0x%x\n", + i, gDenyList.DL_DATA[i].u1IdProductCode[0]); + HDMI_ATTR_SPRINTF("deny list %d u1IdProductCode[1]: 0x%x\n", + i, gDenyList.DL_DATA[i].u1IdProductCode[1]); + HDMI_ATTR_SPRINTF("deny list %d u1YearOfManufacturer: 0x%x\n", + i, gDenyList.DL_DATA[i].u1YearOfManufacturer); + HDMI_ATTR_SPRINTF("deny list %d u1DolbyTrueHdChType192: 0x%x\n", + i, gDenyList.DL_DATA[i].u1DolbyTrueHdChType192); + } + + HDMI_ATTR_SPRINTF("load deny list done\n"); + return; +NotUse: + gDenyList.u1DataFromFile = false; + HDMI_ATTR_SPRINTF("Not use the file as deny list data\n"); +} + void mt_hdmi_show_edid_info(void) { unsigned int u4Res = 0; @@ -4574,7 +4650,7 @@ static void process_dbg_cmd(char *opt) { char *oprand; int ret, i, size, en; - char testbuf[500] = {0}; + char testbuf[CMD_TEST_BUF_MAX_LEN] = {0}; struct VID_PLA_HDR_METADATA_INFO_T hdr_metadata; if (strncmp(opt, "r:", 2) == 0) @@ -5125,6 +5201,24 @@ static void process_dbg_cmd(char *opt) fgCaHDMIGetContentStreamManage(&ui4mode); TX_DEF_LOG("get content stream manage: %x\n", ui4mode); + } else if (strncmp(opt, "denylist:", 9) == 0) { + char *arg = NULL; + + opt = opt + 9; + // input file name + arg = strsep(&opt, ","); + if (arg == NULL || strlen(arg) > (CMD_TEST_BUF_MAX_LEN-1)) + goto Error; + strncpy(testbuf, arg, (CMD_TEST_BUF_MAX_LEN-1)); + testbuf[CMD_TEST_BUF_MAX_LEN-1] = '\0'; + + arg = strsep(&opt, ","); + if (arg == NULL) + goto Error; + if (kstrtoint(arg, DECIMAL_CONVERT, &en)) + goto Error; + + mt_hdmi_load_denylist(en, testbuf); } else goto Error; return;
diff --git a/drivers/misc/mediatek/hdmi/hdmitx/mt8696/hdmiedid.c b/drivers/misc/mediatek/hdmi/hdmitx/mt8696/hdmiedid.c index 324cf46..d453ee3 100644 --- a/drivers/misc/mediatek/hdmi/hdmitx/mt8696/hdmiedid.c +++ b/drivers/misc/mediatek/hdmi/hdmitx/mt8696/hdmiedid.c
@@ -140,6 +140,8 @@ const unsigned char _cBitdeepStr[][7] = { {"16bit "}, unsigned char cDstStr[60]; unsigned char cDstBitStr[30]; +struct DenyList gDenyList = {0}; + bool isBadYUV420Sink(void); bool fgIsHdmiNoEDIDCheck(void) @@ -3916,113 +3918,193 @@ long long hdmi_DispGetEdidInfo(void) return u4Resolution; } -bool isThomsonUD9_India_TV(void) +bool isDenyListSink(enum DenyList_Operation_T OpCode) { - /* THOMSON UD9 43TH6000 TV (India only TV) has Dolby audio playback issue. - * hide Dolby audio capability of this TV based on Manufacturer ID - * and Manufacturer product code. - * 00 ff ff ff ff ff ff 00 0e 96 03 b1 01 00 00 00 - */ - if ((_bEdidData[0x08] == 0x0e) && (_bEdidData[0x09] == 0x96) && - (_bEdidData[0x0a] == 0x03) && (_bEdidData[0x0b] == 0xb1)) - return true; + unsigned int i = 0; + bool bRet = false; + unsigned int ui4_hdmi_dv_truehd_ch_type = + ((_HdmiSinkAvCap.ui1_sink_mat_mlp_ch_sampling[0]) | + (_HdmiSinkAvCap.ui1_sink_mat_mlp_ch_sampling[4] << 8) | + (_HdmiSinkAvCap.ui1_sink_mat_mlp_ch_sampling[6] << 16)); + HDMI_PLUG_LOG("ui4_hdmi_dv_truehd_ch_type %d\n", ui4_hdmi_dv_truehd_ch_type); + + for (i = 0; i < gDenyList.u1NumSize; i++) { + if (gDenyList.DL_DATA[i].u1OpType == OpCode) { + bRet = true; + if (gDenyList.DL_DATA[i].valid.u1CheckIdManufacturerName) { + if ((_bEdidData[0x08] != gDenyList.DL_DATA[i].u1IdManufacturerName[0]) || + (_bEdidData[0x09] != gDenyList.DL_DATA[i].u1IdManufacturerName[1])) { + bRet = false; + continue; + } + } + + if (gDenyList.DL_DATA[i].valid.u1CheckIdProductCode) { + if ((_bEdidData[0x0a] != gDenyList.DL_DATA[i].u1IdProductCode[0]) || + (_bEdidData[0x0b] != gDenyList.DL_DATA[i].u1IdProductCode[1])) { + bRet = false; + continue; + } + } + + if (gDenyList.DL_DATA[i].valid.u1CheckYearOfManufacturer) { + if (_bEdidData[0x11] != gDenyList.DL_DATA[i].u1YearOfManufacturer) { + bRet = false; + continue; + } + } + + if (gDenyList.DL_DATA[i].valid.u1CheckDolbyTrueHdChType192){ + if ((ui4_hdmi_dv_truehd_ch_type & (1 << 6)) != + (gDenyList.DL_DATA[i].u1DolbyTrueHdChType192 << 6)) { + bRet = false; + continue; + } + } + + break; + } + } + return bRet; +} + +bool isBadDolbyAudioSink(void) +{ + if (!gDenyList.u1DataFromFile) { + /* THOMSON UD9 43TH6000 TV (India only TV) has Dolby audio playback issue. + * hide Dolby audio capability of this TV based on Manufacturer ID + * and Manufacturer product code. + * 00 ff ff ff ff ff ff 00 0e 96 03 b1 01 00 00 00 + */ + if ((_bEdidData[0x08] == 0x0e) && (_bEdidData[0x09] == 0x96) && + (_bEdidData[0x0a] == 0x03) && (_bEdidData[0x0b] == 0xb1)) { + HDMI_AUDIO_LOG( + "THOMSON UD9 43TH6000 TV (India only TV) remove Dolby audio capability\n"); + return true; + } + } else { + if (isDenyListSink(DENYLIST_OP_REMOVE_DOLBY_AUDIO)) { + HDMI_AUDIO_LOG("isBadDolbyAudioSink\n"); + return true; + } + } return false; } bool isBadDDPlusSink(struct HDMI_EDID_T *pv_get_info) { - /* Sony - 2009 model DD+ TV (Sony KDL 40S5600 TV) - * 00 FF FF FF FF FF FF 00 4D D9 01 C9 01 01 01 01 - * Note: The official document states that this sink does not support DD+. - */ - if ((_bEdidData[0x08] == 0x4d) && (_bEdidData[0x09] == 0xd9) && - (_bEdidData[0x0a] == 0x01) && (_bEdidData[0x0b] == 0xc9)) - return true; + if (!gDenyList.u1DataFromFile) { + /* Sony - 2009 model DD+ TV (Sony KDL 40S5600 TV) + * 00 FF FF FF FF FF FF 00 4D D9 01 C9 01 01 01 01 + * Note: The official document states that this sink does not support DD+. + */ + if ((_bEdidData[0x08] == 0x4d) && (_bEdidData[0x09] == 0xd9) && + (_bEdidData[0x0a] == 0x01) && (_bEdidData[0x0b] == 0xc9)) + return true; + } else { + if (isDenyListSink(DENYLIST_OP_REMOVE_DOLBY_DIGITAL_PLUS)) { + HDMI_AUDIO_LOG("isBadDDPlusSink\n"); + return true; + } + } return false; } bool isBadMATSink(struct HDMI_EDID_T *pv_get_info) { - /* Sony - G/H model MAT TV's has MAT implementation issue - * confirmed by their SoC vendor MTK and DOLBY. - * This leads no audio for MAT input. - * Disable MAT audio capability of these Sony TV model without - * impacting Sony Soundbar or AVR of those year using sampling rate - * as differentiator. - * Note: This sink has no 192kHz Sampleing Rates in MAT audio format. - */ - if (((_bEdidData[0x08] == 0x4d) && (_bEdidData[0x09] == 0xd9)) && - ((_bEdidData[0x11] == 0x1d) || (_bEdidData[0x11] == 0x1e)) && - ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == 0x0)) - return true; - /* Philips - 2019/2020 model Dolby MAT TV - * Note: This sink has no 192kHz Sampleing Rates in MAT audio format. - */ - if (((_bEdidData[0x08] == 0x41) && (_bEdidData[0x09] == 0x0c)) && - ((_bEdidData[0x11] == 0x1d) || (_bEdidData[0x11] == 0x1e)) && - ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == 0x0)) - return true; - /* Panasonic - 2019/2020 model Dolby MAT TV - * Note: This sink has no 192kHz Sampleing Rates in MAT audio format. - */ - if (((_bEdidData[0x08] == 0x34) && (_bEdidData[0x09] == 0xa9)) && - ((_bEdidData[0x11] == 0x1d) || (_bEdidData[0x11] == 0x1e)) && - ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == 0x0)) - return true; - /* Hisense - 2018/2019/2020 model Dolby MAT TV - * Note: This sink has no 192kHz Sampleing Rates in MAT audio format. - */ - if (((_bEdidData[0x08] == 0x20) && (_bEdidData[0x09] == 0xa3)) && - ((_bEdidData[0x11] == 0x1c) || (_bEdidData[0x11] == 0x1d) || (_bEdidData[0x11] == 0x1e)) && - ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == 0x0)) - return true; - /* AMBEO - 2020 model Dolby MAT TV - * 00 FF FF FF FF FF FF 00 63 18 15 96 00 00 01 00 - * Note: This sink has 192kHz Sampleing Rates in MAT audio format. - */ - if ((_bEdidData[0x08] == 0x63) && (_bEdidData[0x09] == 0x18) && - (_bEdidData[0x0a] == 0x15) && (_bEdidData[0x0b] == 0x96) && - ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == (0x1 << 6))) - return true; - /* MRX 520 - 2015 model AVR - * 00 FF FF FF FF FF FF 00 06 8d 01 00 7b 03 1e 41 - * Note: Official site presents this sink does not support MAT. - */ - if ((_bEdidData[0x08] == 0x06) && (_bEdidData[0x09] == 0x8d) && - (_bEdidData[0x0a] == 0x01) && (_bEdidData[0x0b] == 0x00) && - ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == (0x1 << 6))) - return true; - /* Samsung 32J590UQN with ViewHD VHD-UHAE2 audio extractor - * 00 ff ff ff ff ff ff 00 4c 2d 34 0f 45 32 39 30 - * Note: This sink does not support MAT audio. - */ - if ((_bEdidData[0x08] == 0x4c) && (_bEdidData[0x09] == 0x2d) && - (_bEdidData[0x0a] == 0x34) && (_bEdidData[0x0b] == 0x0f) && - ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == (0x1 << 6))) - return true; - /* Onkyo NR747 - 2015 model AVR - * 00 FF FF FF FF FF FF 00 3D CB 71 0F 00 00 00 00 - * Note: This sink does not support MAT audio. - */ - if ((_bEdidData[0x08] == 0x3D) && (_bEdidData[0x09] == 0xCB) && - (_bEdidData[0x0a] == 0x71) && (_bEdidData[0x0b] == 0x0F) && - ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == (0x1 << 6))) - return true; - + if (!gDenyList.u1DataFromFile) { + /* Sony - G/H model MAT TV's has MAT implementation issue + * confirmed by their SoC vendor MTK and DOLBY. + * This leads no audio for MAT input. + * Disable MAT audio capability of these Sony TV model without + * impacting Sony Soundbar or AVR of those year using sampling rate + * as differentiator. + * Note: This sink has no 192kHz Sampleing Rates in MAT audio format. + */ + if (((_bEdidData[0x08] == 0x4d) && (_bEdidData[0x09] == 0xd9)) && + ((_bEdidData[0x11] == 0x1d) || (_bEdidData[0x11] == 0x1e)) && + ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == 0x0)) + return true; + /* Philips - 2019/2020 model Dolby MAT TV + * Note: This sink has no 192kHz Sampleing Rates in MAT audio format. + */ + if (((_bEdidData[0x08] == 0x41) && (_bEdidData[0x09] == 0x0c)) && + ((_bEdidData[0x11] == 0x1d) || (_bEdidData[0x11] == 0x1e)) && + ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == 0x0)) + return true; + /* Panasonic - 2019/2020 model Dolby MAT TV + * Note: This sink has no 192kHz Sampleing Rates in MAT audio format. + */ + if (((_bEdidData[0x08] == 0x34) && (_bEdidData[0x09] == 0xa9)) && + ((_bEdidData[0x11] == 0x1d) || (_bEdidData[0x11] == 0x1e)) && + ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == 0x0)) + return true; + /* Hisense - 2018/2019/2020 model Dolby MAT TV + * Note: This sink has no 192kHz Sampleing Rates in MAT audio format. + */ + if (((_bEdidData[0x08] == 0x20) && (_bEdidData[0x09] == 0xa3)) && + ((_bEdidData[0x11] == 0x1c) || (_bEdidData[0x11] == 0x1d) || (_bEdidData[0x11] == 0x1e)) && + ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == 0x0)) + return true; + /* AMBEO - 2020 model Dolby MAT TV + * 00 FF FF FF FF FF FF 00 63 18 15 96 00 00 01 00 + * Note: This sink has 192kHz Sampleing Rates in MAT audio format. + */ + if ((_bEdidData[0x08] == 0x63) && (_bEdidData[0x09] == 0x18) && + (_bEdidData[0x0a] == 0x15) && (_bEdidData[0x0b] == 0x96) && + ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == (0x1 << 6))) + return true; + /* MRX 520 - 2015 model AVR + * 00 FF FF FF FF FF FF 00 06 8d 01 00 7b 03 1e 41 + * Note: Official site presents this sink does not support MAT. + */ + if ((_bEdidData[0x08] == 0x06) && (_bEdidData[0x09] == 0x8d) && + (_bEdidData[0x0a] == 0x01) && (_bEdidData[0x0b] == 0x00) && + ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == (0x1 << 6))) + return true; + /* Samsung 32J590UQN with ViewHD VHD-UHAE2 audio extractor + * 00 ff ff ff ff ff ff 00 4c 2d 34 0f 45 32 39 30 + * Note: This sink does not support MAT audio. + */ + if ((_bEdidData[0x08] == 0x4c) && (_bEdidData[0x09] == 0x2d) && + (_bEdidData[0x0a] == 0x34) && (_bEdidData[0x0b] == 0x0f) && + ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == (0x1 << 6))) + return true; + /* Onkyo NR747 - 2015 model AVR + * 00 FF FF FF FF FF FF 00 3D CB 71 0F 00 00 00 00 + * Note: This sink does not support MAT audio. + */ + if ((_bEdidData[0x08] == 0x3D) && (_bEdidData[0x09] == 0xCB) && + (_bEdidData[0x0a] == 0x71) && (_bEdidData[0x0b] == 0x0F) && + ((pv_get_info->ui4_hdmi_dolby_truehd_ch_type & (1 << 6)) == (0x1 << 6))) + return true; + } else { + if (isDenyListSink(DENYLIST_OP_REMOVE_DOLBY_MAT)) { + HDMI_AUDIO_LOG("isBadMATSink\n"); + return true; + } + } return false; } bool isBadYUV420Sink(void) { - /* Sony - 2018 model Samsung UN50NU6900B TV - * 00 FF FF FF FF FF FF 00 4C 2D 14 0F 00 0E 00 01 - * Note: When open UHD, the TV not support YUV420, disable YUV420 mode. - */ - if ((_bEdidData[0x08] == 0x4C) && (_bEdidData[0x09] == 0x2D) && - (_bEdidData[0x0a] == 0x14) && (_bEdidData[0x0b] == 0x0F)) - return true; + if (!gDenyList.u1DataFromFile) { + /* Sony - 2018 model Samsung UN50NU6900B TV + * 00 FF FF FF FF FF FF 00 4C 2D 14 0F 00 0E 00 01 + * Note: When open UHD, the TV not support YUV420, disable YUV420 mode. + */ + if ((_bEdidData[0x08] == 0x4C) && (_bEdidData[0x09] == 0x2D) && + (_bEdidData[0x0a] == 0x14) && (_bEdidData[0x0b] == 0x0F)) + return true; + } else { + if (isDenyListSink(DENYLIST_OP_REMOVE_YUV420)) { + HDMI_VIDEO_LOG("isBadYUV420Sink\n"); + return true; + } + } return false; } @@ -4384,9 +4466,8 @@ void hdmi_AppGetEdidInfo( for (i = 0; i < EDID_LENGTH_MISC; i++) pv_get_info->ui1rawdata_edid[i] = _bEdidData[i]; - if (isThomsonUD9_India_TV()) { - HDMI_AUDIO_LOG( -"THOMSON UD9 43TH6000 TV (India only TV) remove Dolby audio capability\n"); + if (isBadDolbyAudioSink()) { + HDMI_AUDIO_LOG("Known bad Dolby Audio Sink, remove Dolby audio capability\n"); pv_get_info->ui4_hdmi_ac3_ch_type = 0x00; pv_get_info->ui4_hdmi_ac3_ch3ch4ch5ch7_type = 0x00; pv_get_info->ui4_hdmi_ec3_ch_type = 0x00;
diff --git a/drivers/misc/mediatek/hdmi/hdmitx/mt8696/inc/hdmicmd.h b/drivers/misc/mediatek/hdmi/hdmitx/mt8696/inc/hdmicmd.h index 1864e21..ca98908 100644 --- a/drivers/misc/mediatek/hdmi/hdmitx/mt8696/inc/hdmicmd.h +++ b/drivers/misc/mediatek/hdmi/hdmitx/mt8696/inc/hdmicmd.h
@@ -12,6 +12,8 @@ #define DEBUG_SHIFT_NUM_8 8 #define DECIMAL_CONVERT 10 +#define CMD_TEST_BUF_MAX_LEN 500 + extern struct platform_device *hdmi_pdev; extern char debug_buffer[4095]; extern int temp_len;
diff --git a/drivers/misc/mediatek/hdmi/hdmitx/mt8696/inc/hdmiedid.h b/drivers/misc/mediatek/hdmi/hdmitx/mt8696/inc/hdmiedid.h index 5a55538..9153e46 100644 --- a/drivers/misc/mediatek/hdmi/hdmitx/mt8696/inc/hdmiedid.h +++ b/drivers/misc/mediatek/hdmi/hdmitx/mt8696/inc/hdmiedid.h
@@ -309,6 +309,40 @@ struct HDMI_SINK_AV_CAP_T { extern unsigned char drm_bEdidData[256]; +/* Deny List Declaration */ +#define DENYLIST_FILE_MAX_LEN 0x400 //0x20's sizeof(struct DenyList_DATA) + +enum DenyList_Operation_T { + DENYLIST_OP_REMOVE_DOLBY_AUDIO = 0, + DENYLIST_OP_REMOVE_DOLBY_DIGITAL_PLUS, + DENYLIST_OP_REMOVE_DOLBY_MAT, + DENYLIST_OP_REMOVE_YUV420, +}; + +struct DenyList_DATA { + unsigned char u1OpType; //DenyList_Operation_T + struct type2check { + unsigned char u1CheckIdManufacturerName : 1; + unsigned char u1CheckIdProductCode : 1; + unsigned char u1CheckYearOfManufacturer : 1; + unsigned char u1CheckDolbyTrueHdChType192 : 1; + unsigned char u1CheckReserve : 4; + } valid; + unsigned char u1IdManufacturerName[2]; + unsigned char u1IdProductCode[2]; + unsigned char u1YearOfManufacturer; + unsigned char u1DolbyTrueHdChType192; + unsigned char u1Reserve[24]; +}; + +struct DenyList { + bool u1DataFromFile; + struct DenyList_DATA DL_DATA[DENYLIST_FILE_MAX_LEN]; + unsigned char u1NumSize; +}; + +extern struct DenyList gDenyList; + extern void hdmi_checkedid(unsigned char i1noedid); extern struct QMS_DEBUG_T qms_debug; extern unsigned char hdmi_fgreadedid(unsigned char i1noedid);