From: Mark Underwood Date: Fri, 14 May 2010 16:08:23 +0000 (+0200) Subject: gpu: pvr: Reuse the same syncobject across all wraps X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d302900503f0d1414e35d030230210df552892d2;p=sgx.git gpu: pvr: Reuse the same syncobject across all wraps Create a hash table and store all the syncobjects that we create for wrapped memory using the address of the buffer as the key. When a wrap happens we check the hash table to see if the buffer has already been wrapped and if so we retrieve the sync object and reuse it. When the last wrap that is using a syncobject is freed then we remove the syncobject from the hash table and free it. Signed-off-by: Mark Underwood Signed-off-by: Imre Deak --- diff --git a/pvr/device.h b/pvr/device.h index a5240c4..43a37e0 100644 --- a/pvr/device.h +++ b/pvr/device.h @@ -158,6 +158,7 @@ struct PVRSRV_DEVICE_NODE { struct SYS_DATA *psSysData; struct RA_ARENA *psLocalDevMemArena; u32 ui32Flags; + struct HASH_TABLE *sync_table; struct PVRSRV_DEVICE_NODE *psNext; }; diff --git a/pvr/devicemem.c b/pvr/devicemem.c index 6cbcf2c..72ebe6b 100644 --- a/pvr/devicemem.c +++ b/pvr/devicemem.c @@ -425,6 +425,66 @@ enum PVRSRV_ERROR PVRSRVFreeSyncInfoKM( return PVRSRV_OK; } +static inline +void get_syncinfo(struct PVRSRV_KERNEL_SYNC_INFO *syncinfo) +{ + syncinfo->refcount++; +} + +static inline +void put_syncinfo(struct PVRSRV_KERNEL_SYNC_INFO *syncinfo) +{ + struct PVRSRV_DEVICE_NODE *dev = syncinfo->dev_cookie; + + syncinfo->refcount--; + + if (!syncinfo->refcount) { + HASH_Remove(dev->sync_table, + syncinfo->phys_addr.uiAddr); + PVRSRVFreeSyncInfoKM(syncinfo); + } +} + +static inline +enum PVRSRV_ERROR alloc_or_reuse_syncinfo(void *dev_cookie, + void *mem_context_handle, + struct PVRSRV_KERNEL_SYNC_INFO **syncinfo, + struct IMG_SYS_PHYADDR *phys_addr) +{ + enum PVRSRV_ERROR error; + struct PVRSRV_DEVICE_NODE *dev; + + dev = (struct PVRSRV_DEVICE_NODE *) dev_cookie; + + *syncinfo = (struct PVRSRV_KERNEL_SYNC_INFO *) + HASH_Retrieve(dev->sync_table, + phys_addr->uiAddr); + + if (!*syncinfo) { + /* Dont' have one so create one */ + error = PVRSRVAllocSyncInfoKM(dev_cookie, mem_context_handle, + syncinfo); + + if (error != PVRSRV_OK) + return error; + + /* Setup our extra data */ + (*syncinfo)->phys_addr.uiAddr = phys_addr->uiAddr; + (*syncinfo)->dev_cookie = dev_cookie; + (*syncinfo)->refcount = 1; + + if (!HASH_Insert(dev->sync_table, phys_addr->uiAddr, + (u32) *syncinfo)) { + PVR_DPF(PVR_DBG_ERROR, "alloc_or_reuse_syncinfo: " + "Failed to add syncobject to hash table"); + return PVRSRV_ERROR_GENERIC; + } + } else + get_syncinfo(*syncinfo); + + return PVRSRV_OK; +} + static enum PVRSRV_ERROR FreeDeviceMemCallBack(void *pvParam, u32 ui32Param) { enum PVRSRV_ERROR eError = PVRSRV_OK; @@ -601,7 +661,7 @@ static enum PVRSRV_ERROR UnwrapExtMemoryCallBack(void *pvParam, u32 ui32Param) hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem; if (psMemInfo->psKernelSyncInfo) - eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo); + put_syncinfo(psMemInfo->psKernelSyncInfo); if (psMemInfo->sMemBlk.psIntSysPAddr) { int page_count; @@ -754,9 +814,10 @@ enum PVRSRV_ERROR PVRSRVWrapExtMemoryKM(void *hDevCookie, psBMHeap = (struct BM_HEAP *)hDevMemHeap; hDevMemContext = (void *) psBMHeap->pBMContext; - eError = PVRSRVAllocSyncInfoKM(hDevCookie, - hDevMemContext, - &psMemInfo->psKernelSyncInfo); + eError = alloc_or_reuse_syncinfo(hDevCookie, + hDevMemContext, + &psMemInfo->psKernelSyncInfo, + psExtSysPAddr); if (eError != PVRSRV_OK) goto ErrorExitPhase4; diff --git a/pvr/pvrsrv.c b/pvr/pvrsrv.c index f0c9efe..65fdbc6 100644 --- a/pvr/pvrsrv.c +++ b/pvr/pvrsrv.c @@ -36,6 +36,8 @@ #include "pvr_events.h" #include "pvrversion.h" + +#define HASH_TAB_INIT_SIZE 32 enum PVRSRV_ERROR AllocateDeviceID(struct SYS_DATA *psSysData, u32 *pui32DevID) { struct SYS_DEVICE_ID *psDeviceWalker; @@ -287,6 +289,14 @@ FoundDevice: } } + psDeviceNode->sync_table = HASH_Create(HASH_TAB_INIT_SIZE); + if (psDeviceNode->sync_table == NULL) { + PVR_DPF(PVR_DBG_ERROR, "InitDevInfo: " + "Couldn't create syncobject hash table"); + eError = PVRSRV_ERROR_GENERIC; + return eError; + } + return PVRSRV_OK; } @@ -446,6 +456,8 @@ FoundDevice: return eError; } + HASH_Delete(psDeviceNode->sync_table); + ResManFreeResByCriteria(psDeviceNode->hResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, diff --git a/pvr/servicesint.h b/pvr/servicesint.h index d18adec..a81adff 100644 --- a/pvr/servicesint.h +++ b/pvr/servicesint.h @@ -55,6 +55,14 @@ struct PVRSRV_KERNEL_SYNC_INFO { struct IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr; struct IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr; struct PVRSRV_KERNEL_MEM_INFO *psSyncDataMemInfoKM; + + /* + * This stores the physical address of the buffer that + * this syncobject manages (if provided) + */ + struct IMG_SYS_PHYADDR phys_addr; + void *dev_cookie; + u32 refcount; }; struct PVRSRV_DEVICE_SYNC_OBJECT {