]> git.openpandora.org Git - sgx.git/commitdiff
gpu: pvr: Reuse the same syncobject across all wraps
authorMark Underwood <mark.underwood@imgtec.com>
Fri, 14 May 2010 16:08:23 +0000 (18:08 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Sun, 20 May 2012 18:09:41 +0000 (21:09 +0300)
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 <mark.underwood@imgtec.com>
Signed-off-by: Imre Deak <imre.deak@nokia.com>
pvr/device.h
pvr/devicemem.c
pvr/pvrsrv.c
pvr/servicesint.h

index a5240c47c970af985a0c62552059d581c5625618..43a37e00d0777f5eb4770d9c61160498a45b643e 100644 (file)
@@ -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;
 };
 
index 6cbcf2ce5cd0373f971021b17fd125e9bc2c4c72..72ebe6b9a0302447ad29fd304b073465c9a320d8 100644 (file)
@@ -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;
 
index f0c9efebdb7808ee703e796debfd560ea288b529..65fdbc6f5b7437923a19755c397af5c68d842d8a 100644 (file)
@@ -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,
index d18adecbde3657bc6d2f4142bb2c21402f885c47..a81adff8f49bf58ff6480b8c358b5e27c3bbb0a8 100644 (file)
@@ -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 {