IMG_VOID ServerSyncCompleteOp(SERVER_SYNC_PRIMITIVE *psSync, IMG_UINT32 ui32UpdateValue) { SYNC_UPDATES_PRINT("%s: sync: %p (%d) = %d", __FUNCTION__, psSync, *psSync->psSync->pui32LinAddr, ui32UpdateValue); *psSync->psSync->pui32LinAddr = ui32UpdateValue; _ServerSyncUnref(psSync); }
PVRSRV_ERROR PVRSRVServerSyncQueueSWOpKM(SERVER_SYNC_PRIMITIVE *psSync, IMG_UINT32 *pui32FenceValue, IMG_UINT32 *pui32UpdateValue, IMG_UINT32 ui32SyncRequesterID, IMG_BOOL bUpdate, IMG_BOOL *pbFenceRequired) { /* FIXME: Lock */ _ServerSyncRef(psSync); _ServerSyncTakeOperation(psSync, bUpdate, pui32FenceValue, pui32UpdateValue); /* The caller want to know if a fence command is required i.e. was the last operation done on this sync done by the the same sync requestor */ if (pbFenceRequired) { if (ui32SyncRequesterID == psSync->ui32LastSyncRequesterID) { *pbFenceRequired = IMG_FALSE; } else { *pbFenceRequired = IMG_TRUE; } } /* If we're transitioning from a HW operation to a SW operation we need to save the last update the HW will do so that when we PDump we can issue a POL for it before the next HW operation and then LDB in the last SW fence update */ if (psSync->bSWOperation == IMG_FALSE) { psSync->bSWOperation = IMG_TRUE; psSync->ui32LastHWUpdate = *pui32FenceValue; PDumpIsCaptureFrameKM(&psSync->bSWOpStartedInCaptRange); } if (pbFenceRequired) { if (*pbFenceRequired) { SYNC_UPDATES_PRINT("%s: sync: %p, fence: %d, value: %d", __FUNCTION__, psSync, *pui32FenceValue, *pui32UpdateValue); } } psSync->ui32LastSyncRequesterID = ui32SyncRequesterID; /* FIXME: Unlock */ return PVRSRV_OK; }
PVRSRV_ERROR PVRSRVServerSyncQueueHWOpKM(SERVER_SYNC_PRIMITIVE *psSync, IMG_UINT32 *pui32FenceValue, IMG_UINT32 *pui32UpdateValue) { /* FIXME: Lock */ _ServerSyncTakeOperation(psSync, IMG_TRUE, pui32FenceValue, pui32UpdateValue); /* FIXME: Unlock */ /* Note: We might want to consider optimising the fences that we write for HW operations but for now just clear it back to unknown */ psSync->ui32LastSyncRequesterID = SYNC_REQUESTOR_UNKNOWN; if (psSync->bSWOperation) { IMG_CHAR azTmp[100]; OSSNPrintf(azTmp, sizeof(azTmp), "Wait for HW ops and dummy update for SW ops (%p, FW VAddr = 0x%08x, value = 0x%08x)", psSync, SyncPrimGetFirmwareAddr(psSync->psSync), *pui32FenceValue); PDumpCommentKM(azTmp, 0); if (psSync->bSWOpStartedInCaptRange) { /* Dump a POL for the previous HW operation */ SyncPrimPDumpPol(psSync->psSync, psSync->ui32LastHWUpdate, 0xffffffff, PDUMP_POLL_OPERATOR_EQUAL, 0); } /* Dump the expected value (i.e. the value after all the SW operations) */ SyncPrimPDumpValue(psSync->psSync, *pui32FenceValue); /* Reset the state as we've just done a HW operation */ psSync->bSWOperation = IMG_FALSE; } SYNC_UPDATES_PRINT("%s: sync: %p, fence: %d, value: %d", __FUNCTION__, psSync, *pui32FenceValue, *pui32UpdateValue); return PVRSRV_OK; }
PVRSRV_ERROR PVRSRVServerSyncAllocKM(PVRSRV_DEVICE_NODE *psDevNode, SERVER_SYNC_PRIMITIVE **ppsSync, IMG_UINT32 *pui32SyncPrimVAddr) { SERVER_SYNC_PRIMITIVE *psNewSync; PVRSRV_ERROR eError; psNewSync = OSAllocMem(sizeof(SERVER_SYNC_PRIMITIVE)); if (psNewSync == IMG_NULL) { return PVRSRV_ERROR_OUT_OF_MEMORY; } eError = SyncPrimAlloc(psDevNode->hSyncPrimContext, &psNewSync->psSync); if (eError != PVRSRV_OK) { goto fail_sync_alloc; } SyncPrimSet(psNewSync->psSync, 0); psNewSync->ui32NextOp = 0; psNewSync->ui32RefCount = 0; psNewSync->ui32UID = g_ServerSyncUID++; psNewSync->ui32LastSyncRequesterID = SYNC_REQUESTOR_UNKNOWN; psNewSync->bSWOperation = IMG_FALSE; psNewSync->ui32LastHWUpdate = 0x0bad592c; psNewSync->bPDumped = IMG_FALSE; _ServerSyncRef(psNewSync); *pui32SyncPrimVAddr = SyncPrimGetFirmwareAddr(psNewSync->psSync); SYNC_UPDATES_PRINT("%s: sync: %p, fwaddr: %8.8X", __FUNCTION__, psNewSync, *pui32SyncPrimVAddr); *ppsSync = psNewSync; return PVRSRV_OK; fail_sync_alloc: OSFreeMem(psNewSync); return eError; }
IMG_BOOL ServerSyncFenceIsMeet(SERVER_SYNC_PRIMITIVE *psSync, IMG_UINT32 ui32FenceValue) { SYNC_UPDATES_PRINT("%s: sync: %p, value(%d) == fence(%d)?", __FUNCTION__, psSync, *psSync->psSync->pui32LinAddr, ui32FenceValue); return (*psSync->psSync->pui32LinAddr == ui32FenceValue); }
PVRSRV_ERROR PVRSRVServerSyncQueueHWOpKM(SERVER_SYNC_PRIMITIVE *psSync, IMG_BOOL bUpdate, IMG_UINT32 *pui32FenceValue, IMG_UINT32 *pui32UpdateValue) { /* For HW operations the client is required to ensure the operation has completed before freeing the sync as we no way of dropping the refcount if we where to acquire it here. Take the lock to ensure the state that we're modifying below will be consistent with itself. */ OSLockAcquire(psSync->hLock); _ServerSyncTakeOperation(psSync, bUpdate, pui32FenceValue, pui32UpdateValue); /* Note: We might want to consider optimising the fences that we write for HW operations but for now just clear it back to unknown */ psSync->ui32LastSyncRequesterID = SYNC_REQUESTOR_UNKNOWN; if (psSync->bSWOperation) { IMG_CHAR azTmp[256]; OSSNPrintf(azTmp, sizeof(azTmp), "Wait for HW ops and dummy update for SW ops (0x%p, FW VAddr = 0x%08x, value = 0x%08x)\n", psSync, SyncPrimGetFirmwareAddr(psSync->psSync), *pui32FenceValue); PDumpCommentKM(azTmp, 0); if (psSync->bSWOpStartedInCaptRange) { /* Dump a POL for the previous HW operation */ SyncPrimPDumpPol(psSync->psSync, psSync->ui32LastHWUpdate, 0xffffffff, PDUMP_POLL_OPERATOR_EQUAL, 0); } /* Dump the expected value (i.e. the value after all the SW operations) */ SyncPrimPDumpValue(psSync->psSync, *pui32FenceValue); /* Reset the state as we've just done a HW operation */ psSync->bSWOperation = IMG_FALSE; } OSLockRelease(psSync->hLock); SYNC_UPDATES_PRINT("%s: sync: %p, fence: %d, value: %d", __FUNCTION__, psSync, *pui32FenceValue, *pui32UpdateValue); return PVRSRV_OK; }
PVRSRV_ERROR PVRSRVServerSyncQueueSWOpKM(SERVER_SYNC_PRIMITIVE *psSync, IMG_UINT32 *pui32FenceValue, IMG_UINT32 *pui32UpdateValue, IMG_UINT32 ui32SyncRequesterID, IMG_BOOL bUpdate, IMG_BOOL *pbFenceRequired) { ServerSyncRef(psSync); /* ServerSyncRef will acquire and release the lock but we need to reacquire here to ensure the state that we're modifying below will be consistent with itself. But it doesn't matter if another thread acquires the lock in between as we've ensured the sync wont go away */ OSLockAcquire(psSync->hLock); _ServerSyncTakeOperation(psSync, bUpdate, pui32FenceValue, pui32UpdateValue); /* The caller want to know if a fence command is required i.e. was the last operation done on this sync done by the the same sync requestor */ if (pbFenceRequired) { if (ui32SyncRequesterID == psSync->ui32LastSyncRequesterID) { *pbFenceRequired = IMG_FALSE; } else { *pbFenceRequired = IMG_TRUE; } } /* If we're transitioning from a HW operation to a SW operation we need to save the last update the HW will do so that when we PDump we can issue a POL for it before the next HW operation and then LDB in the last SW fence update */ if (psSync->bSWOperation == IMG_FALSE) { psSync->bSWOperation = IMG_TRUE; psSync->ui32LastHWUpdate = *pui32FenceValue; PDumpIsCaptureFrameKM(&psSync->bSWOpStartedInCaptRange); } if (pbFenceRequired) { if (*pbFenceRequired) { SYNC_UPDATES_PRINT("%s: sync: %p, fence: %d, value: %d", __FUNCTION__, psSync, *pui32FenceValue, *pui32UpdateValue); } } /* Only update the last requester id if we are make changes to this sync * object. */ if (bUpdate) psSync->ui32LastSyncRequesterID = ui32SyncRequesterID; OSLockRelease(psSync->hLock); return PVRSRV_OK; }
PVRSRV_ERROR PVRSRVServerSyncAllocKM(PVRSRV_DEVICE_NODE *psDevNode, SERVER_SYNC_PRIMITIVE **ppsSync, IMG_UINT32 *pui32SyncPrimVAddr, IMG_UINT32 ui32ClassNameSize, const IMG_CHAR *pszClassName) { SERVER_SYNC_PRIMITIVE *psNewSync; PVRSRV_ERROR eError; psNewSync = OSAllocMem(sizeof(SERVER_SYNC_PRIMITIVE)); if (psNewSync == IMG_NULL) { return PVRSRV_ERROR_OUT_OF_MEMORY; } /* szClassName must be setup now and used for the SyncPrimAlloc call because * pszClassName is allocated in the bridge code is not NULL terminated */ if(pszClassName) { if (ui32ClassNameSize >= SYNC_MAX_CLASS_NAME_LEN) ui32ClassNameSize = SYNC_MAX_CLASS_NAME_LEN - 1; /* Copy over the class name annotation */ OSStringNCopy(psNewSync->szClassName, pszClassName, ui32ClassNameSize); psNewSync->szClassName[ui32ClassNameSize] = 0; } else { /* No class name annotation */ psNewSync->szClassName[0] = 0; } eError = SyncPrimAlloc(psDevNode->hSyncPrimContext, &psNewSync->psSync, psNewSync->szClassName); if (eError != PVRSRV_OK) { goto fail_sync_alloc; } eError = OSLockCreate(&psNewSync->hLock, LOCK_TYPE_NONE); if (eError != PVRSRV_OK) { goto fail_lock_create; } SyncPrimSet(psNewSync->psSync, 0); psNewSync->ui32NextOp = 0; psNewSync->ui32RefCount = 1; psNewSync->ui32UID = g_ServerSyncUID++; psNewSync->ui32LastSyncRequesterID = SYNC_REQUESTOR_UNKNOWN; psNewSync->bSWOperation = IMG_FALSE; psNewSync->ui32LastHWUpdate = 0x0bad592c; psNewSync->bPDumped = IMG_FALSE; /* Add the sync to the global list */ OSLockAcquire(g_hListLock); dllist_add_to_head(&g_sAllServerSyncs, &psNewSync->sNode); OSLockRelease(g_hListLock); *pui32SyncPrimVAddr = SyncPrimGetFirmwareAddr(psNewSync->psSync); SYNC_UPDATES_PRINT("%s: sync: %p, fwaddr: %8.8X", __FUNCTION__, psNewSync, *pui32SyncPrimVAddr); *ppsSync = psNewSync; return PVRSRV_OK; fail_lock_create: SyncPrimFree(psNewSync->psSync); fail_sync_alloc: OSFreeMem(psNewSync); return eError; }