/*! ****************************************************************************** @Function PVRSRVTimeTraceBufferDestroy @Description Destroy a trace buffer. Note: We assume that this will only be called once per process. @Input ui32PID : PID of the process that is creating the buffer @Return none ******************************************************************************/ PVRSRV_ERROR PVRSRVTimeTraceBufferDestroy(IMG_UINT32 ui32PID) { #if !defined(TTRACE_KEEP_BUFFER_ON_EXIT) sTimeTraceBuffer *psBuffer; #if defined(DUMP_TTRACE_BUFFERS_ON_EXIT) PVRSRVDumpTimeTraceBuffers(); #endif LinuxLockMutex(&g_sTTraceMutex); psBuffer = (sTimeTraceBuffer *) HASH_Retrieve(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); if (psBuffer) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer) + TIME_TRACE_BUFFER_SIZE, psBuffer, NULL); HASH_Remove(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); LinuxUnLockMutex(&g_sTTraceMutex); return PVRSRV_OK; } PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferDestroy: Can't find trace buffer in hash table")); LinuxUnLockMutex(&g_sTTraceMutex); return PVRSRV_ERROR_INVALID_PARAMS; #else return PVRSRV_OK; #endif }
void PVRSRVPerProcessDataDisconnect(u32 ui32PID) { enum PVRSRV_ERROR eError; struct PVRSRV_PER_PROCESS_DATA *psPerProc; PVR_ASSERT(psHashTab != NULL); psPerProc = (struct PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (u32)ui32PID); if (psPerProc == NULL) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: " "Couldn't locate per-process data for PID %u", ui32PID); } else { psPerProc->ui32RefCount--; if (psPerProc->ui32RefCount == 0) { PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: " "Last close from process 0x%x received", ui32PID); PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE); eError = FreePerProcessData(psPerProc); if (eError != PVRSRV_OK) PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: " "Error freeing per-process data"); } } }
/*! ****************************************************************************** @Function PVRSRVPerProcessData @Description Return per-process data area @Input ui32PID - process ID @Return Pointer to per-process data area, or IMG_NULL on error. ******************************************************************************/ PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID) { PVRSRV_PER_PROCESS_DATA *psPerProc; PVR_ASSERT(psHashTab != IMG_NULL); /* Look for existing per-process data area */ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID); return psPerProc; }
PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID) { PVRSRV_PER_PROCESS_DATA *psPerProc; PVR_ASSERT(psHashTab != IMG_NULL); psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID); return psPerProc; }
struct PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(u32 ui32PID) { struct PVRSRV_PER_PROCESS_DATA *psPerProc; PVR_ASSERT(psHashTab != NULL); psPerProc = (struct PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (u32) ui32PID); return psPerProc; }
/*! ****************************************************************************** @Function PVRSRVPerProcessDataDisconnect @Description Decrement refcount for per-process data area, and free the resources if necessary. @Input ui32PID - process ID @Return IMG_VOID ******************************************************************************/ IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID) { PVRSRV_ERROR eError; PVRSRV_PER_PROCESS_DATA *psPerProc; PVR_ASSERT(psHashTab != IMG_NULL); psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID); if (psPerProc == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: Couldn't locate per-process data for PID %u", ui32PID)); } else { psPerProc->ui32RefCount--; if (psPerProc->ui32RefCount == 0) { PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: " "Last close from process 0x%x received", ui32PID)); /* Close the Resource Manager connection */ PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE); #if defined (TTRACE) PVRSRVTimeTraceBufferDestroy(ui32PID); #endif /* Free the per-process data */ eError = FreePerProcessData(psPerProc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Error freeing per-process data")); } } } eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Purge of global handle pool failed (%d)", eError)); } }
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; }
/*! ****************************************************************************** @Function PVRSRVTimeTraceBufferDestroy @Description Destroy a trace buffer. Note: We assume that this will only be called once per process. @Input ui32PID : PID of the process that is creating the buffer @Return none ******************************************************************************/ PVRSRV_ERROR PVRSRVTimeTraceBufferDestroy(IMG_UINT32 ui32PID) { sTimeTraceBuffer *psBuffer; #if defined(DUMP_TTRACE_BUFFERS_ON_EXIT) PVRSRVDumpTimeTraceBuffers(); #endif psBuffer = (sTimeTraceBuffer *) HASH_Retrieve(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); if (psBuffer) { if (psBuffer->pui8Data) OSFreeMem(PVRSRV_PAGEABLE_SELECT, TIME_TRACE_BUFFER_SIZE, psBuffer->pui8Data, NULL); OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer), psBuffer, NULL); HASH_Remove(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); return PVRSRV_OK; } PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferDestroy: Can't find trace buffer in hash table")); return PVRSRV_ERROR_INVALID_PARAMS; }
/*! ****************************************************************************** @Function PVRSRVPerProcessDataConnect @Description Allocate per-process data area, or increment refcount if one already exists for this PID. @Input ui32PID - process ID ppsPerProc - Pointer to per-process data area @Return PVRSRV_ERROR ******************************************************************************/ PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags) { PVRSRV_PER_PROCESS_DATA *psPerProc; IMG_HANDLE hBlockAlloc; PVRSRV_ERROR eError = PVRSRV_OK; if (psHashTab == IMG_NULL) { return PVRSRV_ERROR_INIT_FAILURE; } /* Look for existing per-process data area */ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID); if (psPerProc == IMG_NULL) { /* Allocate per-process data area */ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(*psPerProc), (IMG_PVOID *)&psPerProc, &hBlockAlloc, "Per Process Data"); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)", eError)); return eError; } OSMemSet(psPerProc, 0, sizeof(*psPerProc)); psPerProc->hBlockAlloc = hBlockAlloc; if (!HASH_Insert(psHashTab, (IMG_UINTPTR_T)ui32PID, (IMG_UINTPTR_T)psPerProc)) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table")); eError = PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED; goto failure; } psPerProc->ui32PID = ui32PID; psPerProc->ui32RefCount = 0; #if defined(SUPPORT_PDUMP_MULTI_PROCESS) if (ui32Flags == SRV_FLAGS_PDUMP_ACTIVE) { psPerProc->bPDumpActive = IMG_TRUE; } #else PVR_UNREFERENCED_PARAMETER(ui32Flags); #endif /* Call environment specific per process init function */ eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)", eError)); goto failure; } /* Allocate a handle for the per-process data area */ eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE, &psPerProc->hPerProcData, psPerProc, PVRSRV_HANDLE_TYPE_PERPROC_DATA, PVRSRV_HANDLE_ALLOC_FLAG_NONE); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)", eError)); goto failure; } /* Allocate handle base for this process */ eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)", eError)); goto failure; } /* Set per-process handle options */ eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)", eError)); goto failure; } /* Create a resource manager context for the process */ eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager")); goto failure; } #if defined (TTRACE) PVRSRVTimeTraceBufferCreate(ui32PID); #endif } psPerProc->ui32RefCount++; PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d", ui32PID, psPerProc->ui32RefCount)); return eError; failure: (IMG_VOID)FreePerProcessData(psPerProc); return eError; }
enum PVRSRV_ERROR PVRSRVPerProcessDataConnect(u32 ui32PID) { struct PVRSRV_PER_PROCESS_DATA *psPerProc; void *hBlockAlloc; enum PVRSRV_ERROR eError = PVRSRV_OK; PVR_ASSERT(psHashTab != NULL); psPerProc = (struct PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (u32)ui32PID); if (psPerProc == NULL) { eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(*psPerProc), (void **)&psPerProc, &hBlockAlloc); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: " "Couldn't allocate per-process data (%d)", eError); return eError; } OSMemSet(psPerProc, 0, sizeof(*psPerProc)); psPerProc->hBlockAlloc = hBlockAlloc; if (!HASH_Insert(psHashTab, (u32) ui32PID, (u32)psPerProc)) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: " "Couldn't insert per-process data into hash table"); eError = PVRSRV_ERROR_GENERIC; goto failure; } psPerProc->ui32PID = ui32PID; psPerProc->ui32RefCount = 0; eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: " "OSPerProcessPrivateDataInit failed (%d)", eError); goto failure; } eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE, &psPerProc->hPerProcData, psPerProc, PVRSRV_HANDLE_TYPE_PERPROC_DATA, PVRSRV_HANDLE_ALLOC_FLAG_NONE); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: " "Couldn't allocate handle for per-process data (%d)", eError); goto failure; } eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: " "Couldn't allocate handle base for process (%d)", eError); goto failure; } eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: " "Couldn't set handle options (%d)", eError); goto failure; } eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: " "Couldn't register with the resource manager"); goto failure; } } psPerProc->ui32RefCount++; PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d", ui32PID, psPerProc->ui32RefCount); return eError; failure: (void)FreePerProcessData(psPerProc); return eError; }
PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags) { PVRSRV_PER_PROCESS_DATA *psPerProc; IMG_HANDLE hBlockAlloc; PVRSRV_ERROR eError = PVRSRV_OK; PVR_ASSERT(psHashTab != IMG_NULL); psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID); if (psPerProc == IMG_NULL) { eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(*psPerProc), (IMG_PVOID *)&psPerProc, &hBlockAlloc, "Per Process Data"); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)", eError)); return eError; } OSMemSet(psPerProc, 0, sizeof(*psPerProc)); psPerProc->hBlockAlloc = hBlockAlloc; /* * FIXME: using a hash to retrieve psPerProc makes not much * sense. We always want to have this struct on the IOCTL path * for the current task, so it'd be just a matter of storing * it in the file private object. Until this is resolved and * we get rid of this pid specific lookup make sure the above * assumption holds. */ WARN_ON(OSGetCurrentProcessIDKM() != ui32PID); get_task_comm(psPerProc->name, current); if (!HASH_Insert(psHashTab, (IMG_UINTPTR_T)ui32PID, (IMG_UINTPTR_T)psPerProc)) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table")); eError = PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED; goto failure; } psPerProc->ui32PID = ui32PID; psPerProc->ui32RefCount = 0; #if defined(PERPROC_LIST) List_PVRSRV_PER_PROCESS_DATA_Insert(&psPerProcList, psPerProc); /*PVR_LOG(("MarkTupsperproc %d\n", ui32PID));*/ #endif #if defined(SUPPORT_PDUMP_MULTI_PROCESS) if (ui32Flags == SRV_FLAGS_PDUMP_ACTIVE) { psPerProc->bPDumpActive = IMG_TRUE; } #else PVR_UNREFERENCED_PARAMETER(ui32Flags); #endif eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)", eError)); goto failure; } eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE, &psPerProc->hPerProcData, psPerProc, PVRSRV_HANDLE_TYPE_PERPROC_DATA, PVRSRV_HANDLE_ALLOC_FLAG_NONE); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)", eError)); goto failure; } eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)", eError)); goto failure; } eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)", eError)); goto failure; } eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager")); goto failure; } } psPerProc->ui32RefCount++; PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d", ui32PID, psPerProc->ui32RefCount)); return eError; failure: (IMG_VOID)FreePerProcessData(psPerProc); return eError; }
IMG_BOOL BM_Wrap ( IMG_HANDLE hDevMemHeap, IMG_SIZE_T ui32Size, IMG_SIZE_T ui32Offset, IMG_BOOL bPhysContig, IMG_SYS_PHYADDR *psSysAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 *pui32Flags, BM_HANDLE *phBuf) { BM_BUF *pBuf; BM_CONTEXT *psBMContext; BM_HEAP *psBMHeap; SYS_DATA *psSysData; IMG_SYS_PHYADDR sHashAddress; IMG_UINT32 uFlags; psBMHeap = (BM_HEAP*)hDevMemHeap; psBMContext = psBMHeap->pBMContext; uFlags = psBMHeap->ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK); if ((pui32Flags != IMG_NULL) && ((*pui32Flags & PVRSRV_HAP_CACHETYPE_MASK) != 0)) { uFlags &= ~PVRSRV_HAP_CACHETYPE_MASK; uFlags |= *pui32Flags & PVRSRV_HAP_CACHETYPE_MASK; } PVR_DPF ((PVR_DBG_MESSAGE, "BM_Wrap (uSize=0x%x, uOffset=0x%x, bPhysContig=0x%x, pvCPUVAddr=0x%x, uFlags=0x%x)", ui32Size, ui32Offset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags)); SysAcquireData(&psSysData); #if defined(PVR_LMA) if (bPhysContig) { if (!ValidSysPAddrRangeForDev(psBMContext->psDeviceNode, *psSysAddr, WRAP_MAPPING_SIZE(ui32Size, ui32Offset))) { PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: System address range invalid for device")); return IMG_FALSE; } } else { IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE(); if (!ValidSysPAddrArrayForDev(psBMContext->psDeviceNode, psSysAddr, WRAP_PAGE_COUNT(ui32Size, ui32Offset, ui32HostPageSize), ui32HostPageSize)) { PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: Array of system addresses invalid for device")); return IMG_FALSE; } } #endif sHashAddress = psSysAddr[0]; sHashAddress.uiAddr += ui32Offset; pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, sHashAddress.uiAddr); if(pBuf) { IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset); if(pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)) { PVR_DPF((PVR_DBG_MESSAGE, "BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)", ui32Size, ui32Offset, sHashAddress.uiAddr)); pBuf->ui32RefCount++; *phBuf = (BM_HANDLE)pBuf; if(pui32Flags) *pui32Flags = uFlags; return IMG_TRUE; } } if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), (IMG_PVOID *)&pBuf, IMG_NULL, "Buffer Manager buffer") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED")); return IMG_FALSE; } OSMemSet(pBuf, 0, sizeof (BM_BUF)); if (WrapMemory (psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr, uFlags, pBuf) != IMG_TRUE) { PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED")); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL); return IMG_FALSE; } if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) { PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr); if (!HASH_Insert (psBMContext->pBufferHash, sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf)) { FreeBuf (pBuf, uFlags, IMG_TRUE); PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED")); return IMG_FALSE; } } PVR_DPF ((PVR_DBG_MESSAGE, "BM_Wrap (uSize=0x%x, uFlags=0x%x, devVAddr=%08X)", ui32Size, uFlags, pBuf->DevVAddr.uiAddr)); pBuf->ui32RefCount = 1; *phBuf = (BM_HANDLE)pBuf; if(pui32Flags) { *pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS; } return IMG_TRUE; }
/*! ****************************************************************************** @Function PVRSRVTimeTraceAllocItem @Description Allocate a trace item from the buffer of the current process @Output ppsTraceItem : Pointer to allocated trace item @Input ui32Size : Size of data packet to be allocated @Return none ******************************************************************************/ static IMG_VOID PVRSRVTimeTraceAllocItem(IMG_UINT32 **pui32Item, IMG_UINT32 ui32Size) { IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); IMG_UINT32 ui32AllocOffset; sTimeTraceBuffer *psBuffer = (sTimeTraceBuffer *) HASH_Retrieve(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); /* The caller only asks for extra data space */ ui32Size += PVRSRV_TRACE_ITEM_SIZE; /* Always round to 32-bit */ ui32Size = ((ui32Size - 1) & (~0x3)) + 0x04; if (!psBuffer) { PVRSRV_ERROR eError; PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVTimeTraceAllocItem: Creating buffer for PID %u", (IMG_UINT32) ui32PID)); eError = PVRSRVTimeTraceBufferCreate(ui32PID); if (eError != PVRSRV_OK) { *pui32Item = IMG_NULL; PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceAllocItem: Failed to create buffer")); return; } psBuffer = (sTimeTraceBuffer *) HASH_Retrieve(g_psBufferTable, (IMG_UINTPTR_T) ui32PID); if (psBuffer == IMG_NULL) { *pui32Item = NULL; PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceAllocItem: Failed to retrieve buffer")); return; } } /* Can't allocate more then buffer size */ if (ui32Size >= TIME_TRACE_BUFFER_SIZE) { *pui32Item = NULL; PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceAllocItem: Error trace item too large (%d)", ui32Size)); return; } /* FIXME: Enter critical section? */ /* Always ensure we have enough space to write a padding message */ if ((psBuffer->ui32Woff + ui32Size + PVRSRV_TRACE_ITEM_SIZE) > TIME_TRACE_BUFFER_SIZE) { IMG_UINT32 *ui32WriteEOB = (IMG_UINT32 *) &psBuffer->pui8Data[psBuffer->ui32Woff]; IMG_UINT32 ui32Remain = TIME_TRACE_BUFFER_SIZE - psBuffer->ui32Woff; /* Not enough space at the end of the buffer, back to the start */ *ui32WriteEOB++ = WRITE_HEADER(GROUP, PVRSRV_TRACE_GROUP_PADDING); *ui32WriteEOB++ = 0; /* Don't need timestamp */ *ui32WriteEOB++ = 0; /* Don't need UID */ *ui32WriteEOB = WRITE_HEADER(SIZE, (ui32Remain - PVRSRV_TRACE_ITEM_SIZE)); psBuffer->ui32ByteCount += ui32Remain; psBuffer->ui32Woff = ui32AllocOffset = 0; } else ui32AllocOffset = psBuffer->ui32Woff; psBuffer->ui32Woff = psBuffer->ui32Woff + ui32Size; psBuffer->ui32ByteCount += ui32Size; /* This allocation will start overwritting past our read pointer, move the read pointer along */ while (psBuffer->ui32ByteCount > TIME_TRACE_BUFFER_SIZE) { IMG_UINT32 *psReadItem = (IMG_UINT32 *) &psBuffer->pui8Data[psBuffer->ui32Roff]; IMG_UINT32 ui32ReadSize; ui32ReadSize = PVRSRVTimeTraceItemSize(psReadItem); psBuffer->ui32Roff = (psBuffer->ui32Roff + ui32ReadSize) & (TIME_TRACE_BUFFER_SIZE - 1); psBuffer->ui32ByteCount -= ui32ReadSize; } *pui32Item = (IMG_UINT32 *) &psBuffer->pui8Data[ui32AllocOffset]; /* FIXME: Exit critical section? */ }
IMG_BOOL BM_Wrap(void *hDevMemHeap, u32 ui32Size, u32 ui32Offset, IMG_BOOL bPhysContig, struct IMG_SYS_PHYADDR *psSysAddr, void *pvCPUVAddr, u32 *pui32Flags, void **phBuf) { struct BM_BUF *pBuf; struct BM_CONTEXT *psBMContext; struct BM_HEAP *psBMHeap; struct SYS_DATA *psSysData; struct IMG_SYS_PHYADDR sHashAddress; u32 uFlags; psBMHeap = (struct BM_HEAP *)hDevMemHeap; psBMContext = psBMHeap->pBMContext; uFlags = psBMHeap->ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK); if (pui32Flags) uFlags |= *pui32Flags; PVR_DPF(PVR_DBG_MESSAGE, "BM_Wrap (uSize=0x%x, uOffset=0x%x, " "bPhysContig=0x%x, pvCPUVAddr=0x%x, uFlags=0x%x)", ui32Size, ui32Offset, bPhysContig, pvCPUVAddr, uFlags); if (SysAcquireData(&psSysData) != PVRSRV_OK) return IMG_FALSE; sHashAddress = psSysAddr[0]; sHashAddress.uiAddr += ui32Offset; pBuf = (struct BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, (u32) sHashAddress.uiAddr); if (pBuf) { u32 ui32MappingSize = HOST_PAGEALIGN(ui32Size + ui32Offset); if (pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)) { PVR_DPF(PVR_DBG_MESSAGE, "BM_Wrap " "(Matched previous Wrap! uSize=0x%x, " "uOffset=0x%x, SysAddr=%08X)", ui32Size, ui32Offset, sHashAddress.uiAddr); pBuf->ui32RefCount++; *phBuf = (void *)pBuf; if (pui32Flags) *pui32Flags = uFlags; return IMG_TRUE; } } if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_BUF), (void **)&pBuf, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED"); return IMG_FALSE; } OSMemSet(pBuf, 0, sizeof(struct BM_BUF)); if (WrapMemory(psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr, uFlags, pBuf) != IMG_TRUE) { PVR_DPF(PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED"); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_BUF), pBuf, NULL); return IMG_FALSE; } if (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) { PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr); if (!HASH_Insert(psBMContext->pBufferHash, (u32)sHashAddress.uiAddr, (u32) pBuf)) { FreeBuf(pBuf, uFlags); PVR_DPF(PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED"); return IMG_FALSE; } } PVR_DPF(PVR_DBG_MESSAGE, "BM_Wrap (uSize=0x%x, uFlags=0x%x)=%08X(devVAddr=%08X)", ui32Size, uFlags, pBuf, pBuf->DevVAddr.uiAddr); pBuf->ui32RefCount = 1; pvr_get_ctx(psBMContext); *phBuf = (void *) pBuf; if (pui32Flags) *pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS; return IMG_TRUE; }