IMG_EXPORT PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext) { PVRSRV_ERROR eError = PVRSRV_OK; /* Check if the FW has finished with this resource ... */ eError = RGXFWRequestCommonContextCleanUp(psComputeContext->psDeviceNode, FWCommonContextGetFWAddress(psComputeContext->psServerCommonContext), psComputeContext->psSync, RGXFWIF_DM_CDM); if (eError == PVRSRV_ERROR_RETRY) { return eError; } else if (eError != PVRSRV_OK) { PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError))); } /* ... it has so we can free its resources */ dllist_remove_node(&(psComputeContext->sListNode)); FWCommonContextFree(psComputeContext->psServerCommonContext); DevmemFwFree(psComputeContext->psFWFrameworkMemDesc); DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc); SyncPrimFree(psComputeContext->psSync); OSFreeMem(psComputeContext); return PVRSRV_OK; }
IMG_VOID RGXDestroyCCB(RGX_CLIENT_CCB *psClientCCB) { PDumpUnregisterTransitionCallback(psClientCCB->hTransition); DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc); DevmemFwFree(psClientCCB->psClientCCBCtrlMemDesc); DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBMemDesc); DevmemFwFree(psClientCCB->psClientCCBMemDesc); OSFreeMem(psClientCCB); }
static PVRSRV_ERROR _Destroy3DTransferContext(RGX_SERVER_TQ_3D_DATA *ps3DData, PVRSRV_DEVICE_NODE *psDeviceNode, PVRSRV_CLIENT_SYNC_PRIM *psCleanupSync) { PVRSRV_ERROR eError; /* Check if the FW has finished with this resource ... */ eError = RGXFWRequestCommonContextCleanUp(psDeviceNode, FWCommonContextGetFWAddress(ps3DData->psServerCommonContext), psCleanupSync, RGXFWIF_DM_3D); if (eError == PVRSRV_ERROR_RETRY) { return eError; } else if (eError != PVRSRV_OK) { PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError))); } /* ... it has so we can free it's resources */ DevmemFwFree(ps3DData->psFWContextStateMemDesc); FWCommonContextFree(ps3DData->psServerCommonContext); return PVRSRV_OK; }
IMG_VOID RGXUnregisterMemoryContext(IMG_HANDLE hPrivData) { SERVER_MMU_CONTEXT *psServerMMUContext = hPrivData; PVRSRV_RGXDEV_INFO *psDevInfo = psServerMMUContext->psDevInfo; OSWRLockAcquireWrite(psDevInfo->hMemoryCtxListLock); dllist_remove_node(&psServerMMUContext->sNode); OSWRLockReleaseWrite(psDevInfo->hMemoryCtxListLock); #if defined(SUPPORT_PAGE_FAULT_DEBUG) _RecordUnregisteredMemoryContext(psDevInfo, psServerMMUContext); #endif /* * Release the page catalogue address acquired in RGXRegisterMemoryContext(). */ MMU_ReleaseBaseAddr(IMG_NULL /* FIXME */); /* * Free the firmware memory context. */ DevmemFwFree(psServerMMUContext->psFWMemContextMemDesc); OSFreeMem(psServerMMUContext); }
/* * PVRSRVRGXDestroyTQ2DContextKM */ IMG_EXPORT PVRSRV_ERROR PVRSRVRGXDestroyTQ2DContextKM(RGX_TQ2D_CLEANUP_DATA *psCleanupData) { PVRSRV_ERROR eError = PVRSRV_OK; PRGXFWIF_FWCOMMONCONTEXT psFWComContextFWAddr; RGXSetFirmwareAddress(&psFWComContextFWAddr, psCleanupData->psFWTQ2DContextMemDesc, 0, RFW_FWADDR_NOREF_FLAG); eError = RGXFWRequestCommonContextCleanUp(psCleanupData->psDeviceNode, psFWComContextFWAddr, psCleanupData->psCleanupSync, RGXFWIF_DM_2D); /* If we get retry error then we can't free this resource as it's still in use and we will be called again */ if (eError != PVRSRV_ERROR_RETRY) { eError = RGXDeinitFWCommonContext(&psCleanupData->sFWComContextCleanup); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXDestroyTQ2DContextKM : failed to deinit fw common ctx. Error:%u", eError)); goto e0; } /* Free the framework buffer */ DevmemFwFree(psCleanupData->psFWFrameworkMemDesc); /* * Free the firmware common context. */ DevmemFwFree(psCleanupData->psFWTQ2DContextMemDesc); /* Free the cleanup sync */ SyncPrimFree(psCleanupData->psCleanupSync); OSFreeMem(psCleanupData); } e0: return eError; }
static PVRSRV_ERROR _Create3DTransferContext(CONNECTION_DATA *psConnection, PVRSRV_DEVICE_NODE *psDeviceNode, DEVMEM_MEMDESC *psFWMemContextMemDesc, IMG_UINT32 ui32Priority, RGX_COMMON_CONTEXT_INFO *psInfo, RGX_SERVER_TQ_3D_DATA *ps3DData) { PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; PVRSRV_ERROR eError; /* Allocate device memory for the firmware GPU context suspend state. Note: the FW reads/writes the state to memory by accessing the GPU register interface. */ PDUMPCOMMENT("Allocate RGX firmware TQ/3D context suspend state"); eError = DevmemFwAllocate(psDevInfo, sizeof(RGXFWIF_3DCTX_STATE), RGX_FWCOMCTX_ALLOCFLAGS, "FirmwareTQ3DContext", &ps3DData->psFWContextStateMemDesc); if (eError != PVRSRV_OK) { goto fail_contextswitchstate; } eError = FWCommonContextAllocate(psConnection, psDeviceNode, "TQ_3D", IMG_NULL, 0, psFWMemContextMemDesc, ps3DData->psFWContextStateMemDesc, RGX_CCB_SIZE_LOG2, ui32Priority, psInfo, &ps3DData->psServerCommonContext); if (eError != PVRSRV_OK) { goto fail_contextalloc; } PDUMPCOMMENT("Dump 3D context suspend state buffer"); DevmemPDumpLoadMem(ps3DData->psFWContextStateMemDesc, 0, sizeof(RGXFWIF_3DCTX_STATE), PDUMP_FLAGS_CONTINUOUS); ps3DData->ui32Priority = ui32Priority; return PVRSRV_OK; fail_contextalloc: DevmemFwFree(ps3DData->psFWContextStateMemDesc); fail_contextswitchstate: PVR_ASSERT(eError != PVRSRV_OK); return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext) { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_RGXDEV_INFO *psDevInfo = psComputeContext->psDeviceNode->pvDevice; /* Check if the FW has finished with this resource ... */ eError = RGXFWRequestCommonContextCleanUp(psComputeContext->psDeviceNode, psComputeContext->psServerCommonContext, psComputeContext->psSync, RGXFWIF_DM_CDM); if (eError == PVRSRV_ERROR_RETRY) { return eError; } else if (eError != PVRSRV_OK) { PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)", __FUNCTION__, PVRSRVGetErrorStringKM(eError))); return eError; } /* ... it has so we can free its resources */ OSWRLockAcquireWrite(psDevInfo->hComputeCtxListLock); dllist_remove_node(&(psComputeContext->sListNode)); OSWRLockReleaseWrite(psDevInfo->hComputeCtxListLock); FWCommonContextFree(psComputeContext->psServerCommonContext); DevmemFwFree(psComputeContext->psFWFrameworkMemDesc); DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc); SyncPrimFree(psComputeContext->psSync); SyncAddrListDeinit(&psComputeContext->sSyncAddrListFence); SyncAddrListDeinit(&psComputeContext->sSyncAddrListUpdate); OSFreeMem(psComputeContext); return PVRSRV_OK; }
IMG_EXPORT PVRSRV_ERROR PVRSRVRGXDestroyTransferContextKM(RGX_SERVER_TQ_CONTEXT *psTransferContext) { PVRSRV_ERROR eError; if (psTransferContext->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D) { eError = _Destroy2DTransferContext(&psTransferContext->s2DData, psTransferContext->psDeviceNode, psTransferContext->psCleanupSync); if (eError != PVRSRV_OK) { goto fail_destroy2d; } /* We've freed the 2D context, don't try to free it again */ psTransferContext->ui32Flags &= ~RGX_SERVER_TQ_CONTEXT_FLAGS_2D; } if (psTransferContext->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_3D) { eError = _Destroy3DTransferContext(&psTransferContext->s3DData, psTransferContext->psDeviceNode, psTransferContext->psCleanupSync); if (eError != PVRSRV_OK) { goto fail_destroy3d; } /* We've freed the 3D context, don't try to free it again */ psTransferContext->ui32Flags &= ~RGX_SERVER_TQ_CONTEXT_FLAGS_3D; } dllist_remove_node(&(psTransferContext->sListNode)); DevmemFwFree(psTransferContext->psFWFrameworkMemDesc); SyncPrimFree(psTransferContext->psCleanupSync); OSFreeMem(psTransferContext); return PVRSRV_OK; fail_destroy2d: fail_destroy3d: PVR_ASSERT(eError != PVRSRV_OK); return eError; }
/* * PVRSRVCreateTransferContextKM */ IMG_EXPORT PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA *psConnection, PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32Priority, IMG_DEV_VIRTADDR sMCUFenceAddr, IMG_UINT32 ui32FrameworkCommandSize, IMG_PBYTE pabyFrameworkCommand, IMG_HANDLE hMemCtxPrivData, RGX_SERVER_TQ_CONTEXT **ppsTransferContext) { RGX_SERVER_TQ_CONTEXT *psTransferContext; DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData); RGX_COMMON_CONTEXT_INFO sInfo; PVRSRV_ERROR eError = PVRSRV_OK; /* Allocate the server side structure */ psTransferContext = OSAllocMem(sizeof(*psTransferContext)); if (psTransferContext == IMG_NULL) { return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psTransferContext, 0, sizeof(*psTransferContext)); *ppsTransferContext = psTransferContext; psTransferContext->psDeviceNode = psDeviceNode; /* Allocate cleanup sync */ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psTransferContext->psCleanupSync); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to allocate cleanup sync (0x%x)", eError)); goto fail_syncalloc; } /* * Create the FW framework buffer */ eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode, &psTransferContext->psFWFrameworkMemDesc, ui32FrameworkCommandSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to allocate firmware GPU framework state (%u)", eError)); goto fail_frameworkcreate; } /* Copy the Framework client data into the framework buffer */ eError = PVRSRVRGXFrameworkCopyCommand(psTransferContext->psFWFrameworkMemDesc, pabyFrameworkCommand, ui32FrameworkCommandSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateTransferContextKM: Failed to populate the framework buffer (%u)", eError)); goto fail_frameworkcopy; } sInfo.psFWFrameworkMemDesc = psTransferContext->psFWFrameworkMemDesc; sInfo.psMCUFenceAddr = &sMCUFenceAddr; eError = _Create3DTransferContext(psConnection, psDeviceNode, psFWMemContextMemDesc, ui32Priority, &sInfo, &psTransferContext->s3DData); if (eError != PVRSRV_OK) { goto fail_3dtransfercontext; } psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_3D; eError = _Create2DTransferContext(psConnection, psDeviceNode, psFWMemContextMemDesc, ui32Priority, &sInfo, &psTransferContext->s2DData); if (eError != PVRSRV_OK) { goto fail_2dtransfercontext; } psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_2D; { PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; dllist_add_to_tail(&(psDevInfo->sTransferCtxtListHead), &(psTransferContext->sListNode)); } return PVRSRV_OK; fail_2dtransfercontext: _Destroy3DTransferContext(&psTransferContext->s3DData, psTransferContext->psDeviceNode, psTransferContext->psCleanupSync); fail_3dtransfercontext: fail_frameworkcopy: DevmemFwFree(psTransferContext->psFWFrameworkMemDesc); fail_frameworkcreate: SyncPrimFree(psTransferContext->psCleanupSync); fail_syncalloc: OSFreeMem(psTransferContext); PVR_ASSERT(eError != PVRSRV_OK); return eError; }
PVRSRV_ERROR RGXCreateCCB(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32CCBSizeLog2, CONNECTION_DATA *psConnectionData, const IMG_CHAR *pszName, RGX_SERVER_COMMON_CONTEXT *psServerCommonContext, RGX_CLIENT_CCB **ppsClientCCB, DEVMEM_MEMDESC **ppsClientCCBMemDesc, DEVMEM_MEMDESC **ppsClientCCBCtrlMemDesc) { PVRSRV_ERROR eError; DEVMEM_FLAGS_T uiClientCCBMemAllocFlags, uiClientCCBCtlMemAllocFlags; IMG_UINT32 ui32AllocSize = (1U << ui32CCBSizeLog2); RGX_CLIENT_CCB *psClientCCB; psClientCCB = OSAllocMem(sizeof(*psClientCCB)); if (psClientCCB == IMG_NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto fail_alloc; } psClientCCB->psServerCommonContext = psServerCommonContext; uiClientCCBMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) | PVRSRV_MEMALLOCFLAG_GPU_READABLE | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_UNCACHED | PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE; uiClientCCBCtlMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | PVRSRV_MEMALLOCFLAG_GPU_READABLE | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_UNCACHED | PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE; PDUMPCOMMENT("Allocate RGXFW cCCB"); eError = DevmemFwAllocateExportable(psDeviceNode, ui32AllocSize, uiClientCCBMemAllocFlags, "FirmwareClientCCB", &psClientCCB->psClientCCBMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to allocate RGX client CCB (%s)", PVRSRVGetErrorStringKM(eError))); goto fail_alloc_ccb; } eError = DevmemAcquireCpuVirtAddr(psClientCCB->psClientCCBMemDesc, (IMG_VOID **) &psClientCCB->pui8ClientCCB); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to map RGX client CCB (%s)", PVRSRVGetErrorStringKM(eError))); goto fail_map_ccb; } PDUMPCOMMENT("Allocate RGXFW cCCB control"); eError = DevmemFwAllocateExportable(psDeviceNode, sizeof(RGXFWIF_CCCB_CTL), uiClientCCBCtlMemAllocFlags, "FirmwareClientCCBControl", &psClientCCB->psClientCCBCtrlMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to allocate RGX client CCB control (%s)", PVRSRVGetErrorStringKM(eError))); goto fail_alloc_ccbctrl; } eError = DevmemAcquireCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc, (IMG_VOID **) &psClientCCB->psClientCCBCtrl); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateCCBKM: Failed to map RGX client CCB (%s)", PVRSRVGetErrorStringKM(eError))); goto fail_map_ccbctrl; } psClientCCB->psClientCCBCtrl->ui32WriteOffset = 0; psClientCCB->psClientCCBCtrl->ui32ReadOffset = 0; psClientCCB->psClientCCBCtrl->ui32DepOffset = 0; psClientCCB->psClientCCBCtrl->ui32WrapMask = ui32AllocSize - 1; OSStringCopy(psClientCCB->szName, pszName); PDUMPCOMMENT("cCCB control"); DevmemPDumpLoadMem(psClientCCB->psClientCCBCtrlMemDesc, 0, sizeof(RGXFWIF_CCCB_CTL), PDUMP_FLAGS_CONTINUOUS); PVR_ASSERT(eError == PVRSRV_OK); psClientCCB->ui32HostWriteOffset = 0; psClientCCB->ui32LastPDumpWriteOffset = 0; psClientCCB->ui32Size = ui32AllocSize; #if defined REDUNDANT_SYNCS_DEBUG psClientCCB->ui32UpdateWriteIndex = 0; OSMemSet(psClientCCB->asFenceUpdateList, 0, sizeof(psClientCCB->asFenceUpdateList)); #endif eError = PDumpRegisterTransitionCallback(psConnectionData->psPDumpConnectionData, _RGXCCBPDumpTransition, psClientCCB, &psClientCCB->hTransition); if (eError != PVRSRV_OK) { goto fail_pdumpreg; } /* Note: Due to resman the connection structure could be freed before the client CCB so rather then saving off the connection structure save the PDump specific memory which is refcounted to ensure it's not freed too early */ psClientCCB->psPDumpConnectionData = psConnectionData->psPDumpConnectionData; PDUMPCOMMENT("New RGXFW cCCB(%s@%p) created", psClientCCB->szName, psClientCCB); *ppsClientCCB = psClientCCB; *ppsClientCCBMemDesc = psClientCCB->psClientCCBMemDesc; *ppsClientCCBCtrlMemDesc = psClientCCB->psClientCCBCtrlMemDesc; return PVRSRV_OK; fail_pdumpreg: DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc); fail_map_ccbctrl: DevmemFwFree(psClientCCB->psClientCCBCtrlMemDesc); fail_alloc_ccbctrl: DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBMemDesc); fail_map_ccb: DevmemFwFree(psClientCCB->psClientCCBMemDesc); fail_alloc_ccb: OSFreeMem(psClientCCB); fail_alloc: PVR_ASSERT(eError != PVRSRV_OK); return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA *psConnection, PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32Priority, IMG_DEV_VIRTADDR sMCUFenceAddr, IMG_UINT32 ui32FrameworkCommandSize, IMG_PBYTE pbyFrameworkCommand, IMG_HANDLE hMemCtxPrivData, RGX_SERVER_COMPUTE_CONTEXT **ppsComputeContext) { PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; DEVMEM_MEMDESC *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData); RGX_SERVER_COMPUTE_CONTEXT *psComputeContext; RGX_COMMON_CONTEXT_INFO sInfo; PVRSRV_ERROR eError = PVRSRV_OK; /* Prepare cleanup struct */ *ppsComputeContext = IMG_NULL; psComputeContext = OSAllocMem(sizeof(*psComputeContext)); if (psComputeContext == IMG_NULL) { return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psComputeContext, 0, sizeof(*psComputeContext)); psComputeContext->psDeviceNode = psDeviceNode; /* Allocate cleanup sync */ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psComputeContext->psSync); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate cleanup sync (0x%x)", eError)); goto fail_syncalloc; } /* Allocate device memory for the firmware GPU context suspend state. Note: the FW reads/writes the state to memory by accessing the GPU register interface. */ PDUMPCOMMENT("Allocate RGX firmware compute context suspend state"); eError = DevmemFwAllocate(psDevInfo, sizeof(RGXFWIF_COMPUTECTX_STATE), RGX_FWCOMCTX_ALLOCFLAGS, "ComputeContextState", &psComputeContext->psFWComputeContextStateMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate firmware GPU context suspend state (%u)", eError)); goto fail_contextsuspendalloc; } /* * Create the FW framework buffer */ eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode, &psComputeContext->psFWFrameworkMemDesc, ui32FrameworkCommandSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate firmware GPU framework state (%u)", eError)); goto fail_frameworkcreate; } /* Copy the Framework client data into the framework buffer */ eError = PVRSRVRGXFrameworkCopyCommand(psComputeContext->psFWFrameworkMemDesc, pbyFrameworkCommand, ui32FrameworkCommandSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to populate the framework buffer (%u)", eError)); goto fail_frameworkcopy; } sInfo.psFWFrameworkMemDesc = psComputeContext->psFWFrameworkMemDesc; sInfo.psMCUFenceAddr = &sMCUFenceAddr; eError = FWCommonContextAllocate(psConnection, psDeviceNode, "CDM", IMG_NULL, 0, psFWMemContextMemDesc, psComputeContext->psFWComputeContextStateMemDesc, RGX_CCB_SIZE_LOG2, ui32Priority, &sInfo, &psComputeContext->psServerCommonContext); if (eError != PVRSRV_OK) { goto fail_contextalloc; } { PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; dllist_add_to_tail(&(psDevInfo->sComputeCtxtListHead), &(psComputeContext->sListNode)); } *ppsComputeContext = psComputeContext; return PVRSRV_OK; fail_contextalloc: fail_frameworkcopy: DevmemFwFree(psComputeContext->psFWFrameworkMemDesc); fail_frameworkcreate: DevmemFwFree(psComputeContext->psFWComputeContextStateMemDesc); fail_contextsuspendalloc: SyncPrimFree(psComputeContext->psSync); fail_syncalloc: OSFreeMem(psComputeContext); return eError; }
/* * RGXRegisterMemoryContext */ PVRSRV_ERROR RGXRegisterMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT *psMMUContext, IMG_HANDLE *hPrivData) { PVRSRV_ERROR eError; PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; DEVMEM_FLAGS_T uiFWMemContextMemAllocFlags; RGXFWIF_FWMEMCONTEXT *psFWMemContext; DEVMEM_MEMDESC *psFWMemContextMemDesc; SERVER_MMU_CONTEXT *psServerMMUContext; if (psDevInfo->psKernelMMUCtx == IMG_NULL) { /* * This must be the creation of the Kernel memory context. Take a copy * of the MMU context for use when programming the BIF. */ psDevInfo->psKernelMMUCtx = psMMUContext; } else { psServerMMUContext = OSAllocMem(sizeof(*psServerMMUContext)); if (psServerMMUContext == IMG_NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto fail_alloc_server_ctx; } psServerMMUContext->psDevInfo = psDevInfo; /* * This FW MemContext is only mapped into kernel for initialisation purposes. * Otherwise this allocation is only used by the FW. * Therefore the GPU cache doesn't need coherency, * and write-combine is suffice on the CPU side (WC buffer will be flushed at any kick) */ uiFWMemContextMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(META_CACHED) | PVRSRV_MEMALLOCFLAG_GPU_READABLE | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT | PVRSRV_MEMALLOCFLAG_CPU_READABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | PVRSRV_MEMALLOCFLAG_CPU_WRITE_COMBINE | PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE; /* Allocate device memory for the firmware memory context for the new application. */ PDUMPCOMMENT("Allocate RGX firmware memory context"); /* FIXME: why cache-consistent? */ eError = DevmemFwAllocate(psDevInfo, sizeof(*psFWMemContext), uiFWMemContextMemAllocFlags, "FirmwareMemoryContext", &psFWMemContextMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to allocate firmware memory context (%u)", eError)); goto fail_alloc_fw_ctx; } /* Temporarily map the firmware memory context to the kernel. */ eError = DevmemAcquireCpuVirtAddr(psFWMemContextMemDesc, (IMG_VOID **)&psFWMemContext); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to map firmware memory context (%u)", eError)); goto fail_acquire_cpu_addr; } /* * Write the new memory context's page catalogue into the firmware memory * context for the client. */ eError = MMU_AcquireBaseAddr(psMMUContext, &psFWMemContext->sPCDevPAddr); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to acquire Page Catalogue address (%u)", eError)); DevmemReleaseCpuVirtAddr(psFWMemContextMemDesc); goto fail_acquire_base_addr; } /* * Set default values for the rest of the structure. */ psFWMemContext->uiPageCatBaseRegID = -1; psFWMemContext->uiBreakpointAddr = 0; psFWMemContext->uiBPHandlerAddr = 0; psFWMemContext->uiBreakpointCtl = 0; #if defined(SUPPORT_GPUVIRT_VALIDATION) { IMG_UINT32 ui32OSid = 0, ui32OSidReg = 0; MMU_GetOSids(psMMUContext, &ui32OSid, &ui32OSidReg); psFWMemContext->ui32OSid = ui32OSidReg; } #endif #if defined(PDUMP) { IMG_CHAR aszName[PMR_MAX_MEMSPNAME_SYMB_ADDR_LENGTH_DEFAULT]; IMG_DEVMEM_OFFSET_T uiOffset = 0; /* * Dump the Mem context allocation */ DevmemPDumpLoadMem(psFWMemContextMemDesc, 0, sizeof(*psFWMemContext), PDUMP_FLAGS_CONTINUOUS); /* * Obtain a symbolic addr of the mem context structure */ eError = DevmemPDumpPageCatBaseToSAddr(psFWMemContextMemDesc, &uiOffset, aszName, PMR_MAX_MEMSPNAME_SYMB_ADDR_LENGTH_DEFAULT); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to generate a Dump Page Catalogue address (%u)", eError)); DevmemReleaseCpuVirtAddr(psFWMemContextMemDesc); goto fail_pdump_cat_base_addr; } /* * Dump the Page Cat tag in the mem context (symbolic address) */ eError = MMU_PDumpWritePageCatBase(psMMUContext, aszName, uiOffset, 8, /* 64-bit register write */ 0, 0, 0); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"RGXRegisterMemoryContext: Failed to acquire Page Catalogue address (%u)", eError)); DevmemReleaseCpuVirtAddr(psFWMemContextMemDesc); goto fail_pdump_cat_base; } } #endif /* * Release kernel address acquired above. */ DevmemReleaseCpuVirtAddr(psFWMemContextMemDesc); /* * Store the process information for this device memory context * for use with the host page-fault analysis. */ psServerMMUContext->uiPID = OSGetCurrentProcessID(); psServerMMUContext->psMMUContext = psMMUContext; psServerMMUContext->psFWMemContextMemDesc = psFWMemContextMemDesc; if (OSSNPrintf(psServerMMUContext->szProcessName, RGXMEM_SERVER_MMU_CONTEXT_MAX_NAME, "%s", OSGetCurrentProcessName()) == RGXMEM_SERVER_MMU_CONTEXT_MAX_NAME) { psServerMMUContext->szProcessName[RGXMEM_SERVER_MMU_CONTEXT_MAX_NAME-1] = '\0'; } OSWRLockAcquireWrite(psDevInfo->hMemoryCtxListLock); dllist_add_to_tail(&psDevInfo->sMemoryContextList, &psServerMMUContext->sNode); OSWRLockReleaseWrite(psDevInfo->hMemoryCtxListLock); MMU_SetDeviceData(psMMUContext, psFWMemContextMemDesc); *hPrivData = psServerMMUContext; } return PVRSRV_OK; #if defined(PDUMP) fail_pdump_cat_base: fail_pdump_cat_base_addr: MMU_ReleaseBaseAddr(IMG_NULL); #endif fail_acquire_base_addr: /* Done before jumping to the fail point as the release is done before exit */ fail_acquire_cpu_addr: DevmemFwFree(psServerMMUContext->psFWMemContextMemDesc); fail_alloc_fw_ctx: OSFreeMem(psServerMMUContext); fail_alloc_server_ctx: PVR_ASSERT(eError != PVRSRV_OK); return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVRGXCreateTQ2DContextKM(PVRSRV_DEVICE_NODE *psDeviceNode, DEVMEM_MEMDESC *psTQ2DCCBMemDesc, DEVMEM_MEMDESC *psTQ2DCCBCtlMemDesc, RGX_TQ2D_CLEANUP_DATA **ppsCleanupData, DEVMEM_MEMDESC **ppsFWTQ2DContextMemDesc, IMG_UINT32 ui32Priority, IMG_UINT32 ui32FrameworkRegisterSize, IMG_PBYTE pbyFrameworkRegisters, IMG_HANDLE hMemCtxPrivData) { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; RGXFWIF_FWCOMMONCONTEXT *psFWTQ2DContext; RGX_TQ2D_CLEANUP_DATA *psTmpCleanup; DEVMEM_MEMDESC *psFWFrameworkMemDesc; /* Prepare cleanup struct */ psTmpCleanup = OSAllocMem(sizeof(*psTmpCleanup)); if (psTmpCleanup == IMG_NULL) { return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psTmpCleanup, 0, sizeof(*psTmpCleanup)); *ppsCleanupData = psTmpCleanup; /* Allocate cleanup sync */ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psTmpCleanup->psCleanupSync); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate cleanup sync (0x%x)", eError)); goto fail_syncalloc; } /* Allocate device memory for the firmware TQ 2D context. */ PDUMPCOMMENT("Allocate RGX firmware TQ 2D context"); eError = DevmemFwAllocate(psDevInfo, sizeof(*psFWTQ2DContext), RGX_FWCOMCTX_ALLOCFLAGS, ppsFWTQ2DContextMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ2DContextKM: Failed to allocate firmware TQ 2D context (%u)", eError)); goto fail_contextalloc; } psTmpCleanup->psFWTQ2DContextMemDesc = *ppsFWTQ2DContextMemDesc; psTmpCleanup->psDeviceNode = psDeviceNode; /* Temporarily map the firmware TQ 2D context to the kernel. */ eError = DevmemAcquireCpuVirtAddr(*ppsFWTQ2DContextMemDesc, (IMG_VOID **)&psFWTQ2DContext); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ2DContextKM: Failed to map firmware TQ 2D context (%u)", eError)); goto fail_cpuvirtacquire; } /* * Create the FW framework buffer */ eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode, & psFWFrameworkMemDesc, ui32FrameworkRegisterSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ2DContextKM: Failed to allocate firmware GPU framework state (%u)", eError)); goto fail_frameworkcreate; } psTmpCleanup->psFWFrameworkMemDesc = psFWFrameworkMemDesc; /* Copy the Framework client data into the framework buffer */ eError = PVRSRVRGXFrameworkCopyRegisters(psFWFrameworkMemDesc, pbyFrameworkRegisters, ui32FrameworkRegisterSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ2DContextKM: Failed to populate the framework buffer (%u)", eError)); goto fail_frameworkcopy; } eError = RGXInitFWCommonContext(psFWTQ2DContext, psTQ2DCCBMemDesc, psTQ2DCCBCtlMemDesc, hMemCtxPrivData, psFWFrameworkMemDesc, ui32Priority, IMG_NULL, & psTmpCleanup->sFWComContextCleanup); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ2DContextKM: Failed to init firmware common context (%u)", eError)); goto fail_contextinit; } /* * Dump the TQ2D and the memory contexts */ PDUMPCOMMENT("Dump FWTQ2DContext"); DevmemPDumpLoadMem(*ppsFWTQ2DContextMemDesc, 0, sizeof(*psFWTQ2DContext), PDUMP_FLAGS_CONTINUOUS); /* Release address acquired above. */ DevmemReleaseCpuVirtAddr(*ppsFWTQ2DContextMemDesc); return PVRSRV_OK; fail_contextinit: fail_frameworkcopy: DevmemFwFree(psFWFrameworkMemDesc); fail_frameworkcreate: DevmemReleaseCpuVirtAddr(*ppsFWTQ2DContextMemDesc); fail_cpuvirtacquire: DevmemFwFree(*ppsFWTQ2DContextMemDesc); fail_contextalloc: SyncPrimFree(psTmpCleanup->psCleanupSync); fail_syncalloc: OSFreeMem(psTmpCleanup); return eError; }
/* * PVRSRVRGXDestroyTQ3DContextKM */ IMG_EXPORT PVRSRV_ERROR PVRSRVRGXDestroyTQ3DContextKM(RGX_TQ3D_CLEANUP_DATA *psCleanupData) { PVRSRV_ERROR eError = PVRSRV_OK; PRGXFWIF_FWCOMMONCONTEXT psFWComContextFWAddr; RGXSetFirmwareAddress(&psFWComContextFWAddr, psCleanupData->psFWTQ3DContextMemDesc, 0, RFW_FWADDR_NOREF_FLAG); eError = RGXFWRequestCommonContextCleanUp(psCleanupData->psDeviceNode, psFWComContextFWAddr, psCleanupData->psCleanupSync, RGXFWIF_DM_3D); /* If we get retry error then we can't free this resource as it's still in use and we will be called again */ if (eError != PVRSRV_ERROR_RETRY) { eError = RGXDeinitFWCommonContext(&psCleanupData->sFWComContextCleanup); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXDestroyTQ3DContextKM : failed to deinit fw common ctx. Error:%u", eError)); goto e0; } #if defined(DEBUG) /* Log the number of TQ3D context stores which occurred */ { RGXFWIF_3DCTX_STATE *psFWState; eError = DevmemAcquireCpuVirtAddr(psCleanupData->psFWTQ3DContextStateMemDesc, (IMG_VOID**)&psFWState); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateRenderContextKM: Failed to map firmware render context state (%u)", eError)); } else { PVR_DPF((PVR_DBG_WARNING,"Number of context stores on FW TQ3D context 0x%010x: %u", psFWComContextFWAddr.ui32Addr, psFWState->ui32NumStores)); /* Release the CPU virt addr */ DevmemReleaseCpuVirtAddr(psCleanupData->psFWTQ3DContextStateMemDesc); } } #endif /* * Unmap the TA/3D context state buffer pointers */ RGXUnsetFirmwareAddress(psCleanupData->psFWTQ3DContextStateMemDesc); /* * Free the firmware TQ/3D context state buffer */ DevmemFwFree(psCleanupData->psFWTQ3DContextStateMemDesc); /* Free the framework buffer */ DevmemFwFree(psCleanupData->psFWFrameworkMemDesc); /* * Free the firmware common context. */ DevmemFwFree(psCleanupData->psFWTQ3DContextMemDesc); /* Free the cleanup sync */ SyncPrimFree(psCleanupData->psCleanupSync); OSFreeMem(psCleanupData); } e0: return eError; }
/* * PVRSRVRGXCreateTQ3DContextKM */ IMG_EXPORT PVRSRV_ERROR PVRSRVRGXCreateTQ3DContextKM(PVRSRV_DEVICE_NODE *psDeviceNode, DEVMEM_MEMDESC *psTQ3DCCBMemDesc, DEVMEM_MEMDESC *psTQ3DCCBCtlMemDesc, RGX_TQ3D_CLEANUP_DATA **ppsCleanupData, DEVMEM_MEMDESC **ppsFWTQ3DContextMemDesc, DEVMEM_MEMDESC **ppsFWTQ3DContextStateMemDesc, IMG_UINT32 ui32Priority, IMG_DEV_VIRTADDR sMCUFenceAddr, IMG_UINT32 ui32FrameworkRegisterSize, IMG_PBYTE pbyFrameworkRegisters, IMG_HANDLE hMemCtxPrivData) { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; RGXFWIF_FWCOMMONCONTEXT *psFWTQ3DContext; RGX_TQ3D_CLEANUP_DATA *psTmpCleanup; DEVMEM_MEMDESC *psFWFrameworkMemDesc; /* Prepare cleanup struct */ psTmpCleanup = OSAllocMem(sizeof(*psTmpCleanup)); if (psTmpCleanup == IMG_NULL) { return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psTmpCleanup, 0, sizeof(*psTmpCleanup)); *ppsCleanupData = psTmpCleanup; /* Allocate cleanup sync */ eError = SyncPrimAlloc(psDeviceNode->hSyncPrimContext, &psTmpCleanup->psCleanupSync); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateComputeContextKM: Failed to allocate cleanup sync (0x%x)", eError)); goto fail_syncalloc; } /* Allocate device memory for the firmware TQ 3D context. */ PDUMPCOMMENT("Allocate RGX firmware TQ 3D context"); eError = DevmemFwAllocate(psDevInfo, sizeof(*psFWTQ3DContext), RGX_FWCOMCTX_ALLOCFLAGS, ppsFWTQ3DContextMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ3DContextKM: Failed to allocate firmware TQ 3D context (%u)", eError)); goto fail_contextalloc; } psTmpCleanup->psFWTQ3DContextMemDesc = *ppsFWTQ3DContextMemDesc; psTmpCleanup->psDeviceNode = psDeviceNode; /* Temporarily map the firmware TQ 3D context to the kernel. */ eError = DevmemAcquireCpuVirtAddr(*ppsFWTQ3DContextMemDesc, (IMG_VOID **)&psFWTQ3DContext); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ3DContextKM: Failed to map firmware TQ 3D context (%u)", eError)); goto fail_cpuvirtacquire; } /* Allocate device memory for the firmware GPU context suspend state. Note: the FW reads/writes the state to memory by accessing the GPU register interface. */ PDUMPCOMMENT("Allocate RGX firmware TQ/3D context suspend state"); eError = DevmemFwAllocate(psDevInfo, sizeof(RGXFWIF_3DCTX_STATE), RGX_FWCOMCTX_ALLOCFLAGS, ppsFWTQ3DContextStateMemDesc); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ3DContextKM: Failed to allocate firmware GPU context suspend state (%u)", eError)); goto fail_contextsuspendalloc; } psTmpCleanup->psFWTQ3DContextStateMemDesc = *ppsFWTQ3DContextStateMemDesc; /* * Create the FW framework buffer */ eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode, & psFWFrameworkMemDesc, ui32FrameworkRegisterSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ3DContextKM: Failed to allocate firmware GPU framework state (%u)", eError)); goto fail_frameworkcreate; } psTmpCleanup->psFWFrameworkMemDesc = psFWFrameworkMemDesc; /* Copy the Framework client data into the framework buffer */ eError = PVRSRVRGXFrameworkCopyRegisters(psFWFrameworkMemDesc, pbyFrameworkRegisters, ui32FrameworkRegisterSize); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ3DContextKM: Failed to populate the framework buffer (%u)", eError)); goto fail_frameworkcopy; } /* Init TQ/3D FW common context */ eError = RGXInitFWCommonContext(psFWTQ3DContext, psTQ3DCCBMemDesc, psTQ3DCCBCtlMemDesc, hMemCtxPrivData, psFWFrameworkMemDesc, ui32Priority, &sMCUFenceAddr, &psTmpCleanup->sFWComContextCleanup); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRGXCreateTQ3DContextKM: Failed to init firmware common context (%u)", eError)); goto fail_contextinit; } /* * Set the firmware GPU context state buffer. * * The common context stores a dword pointer (FW) so we can cast the generic buffer to * the correct 3D (3D/TQ = normal 3D) state structure type in the FW. */ RGXSetFirmwareAddress(&psFWTQ3DContext->psContextState, *ppsFWTQ3DContextStateMemDesc, 0, RFW_FWADDR_FLAG_NONE); /* * Dump the TQ3D and the memory contexts */ PDUMPCOMMENT("Dump FWTQ3DContext"); DevmemPDumpLoadMem(*ppsFWTQ3DContextMemDesc, 0, sizeof(*psFWTQ3DContext), PDUMP_FLAGS_CONTINUOUS); /* * Dump the FW TQ/3D context suspend state buffer */ PDUMPCOMMENT("Dump FWTQ3DContextState"); DevmemPDumpLoadMem(*ppsFWTQ3DContextStateMemDesc, 0, sizeof(RGXFWIF_3DCTX_STATE), PDUMP_FLAGS_CONTINUOUS); /* Release address acquired above. */ DevmemReleaseCpuVirtAddr(*ppsFWTQ3DContextMemDesc); return PVRSRV_OK; fail_contextinit: fail_frameworkcopy: DevmemFwFree(psFWFrameworkMemDesc); fail_frameworkcreate: DevmemFwFree(*ppsFWTQ3DContextStateMemDesc); fail_contextsuspendalloc: DevmemReleaseCpuVirtAddr(*ppsFWTQ3DContextMemDesc); fail_cpuvirtacquire: DevmemFwFree(*ppsFWTQ3DContextMemDesc); fail_contextalloc: SyncPrimFree(psTmpCleanup->psCleanupSync); fail_syncalloc: OSFreeMem(psTmpCleanup); return eError; }