IMG_INTERNAL void PVRSRVBMXProcDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index) { if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC)) goto skip; PVRSRV_LOCK_CCB(); gsRefCountCCB[giOffset].pszFile = pszFile; gsRefCountCCB[giOffset].iLine = iLine; gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); snprintf(gsRefCountCCB[giOffset].pcMesg, PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, PVRSRV_REFCOUNT_CCB_FMT_STRING, "BM_XPROC", NULL, NULL, gXProcWorkaroundShareData[ui32Index].hOSMemHandle, (IMG_VOID *) ui32Index, gXProcWorkaroundShareData[ui32Index].ui32RefCount, gXProcWorkaroundShareData[ui32Index].ui32RefCount - 1, gXProcWorkaroundShareData[ui32Index].ui32Size); gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; PVRSRV_UNLOCK_CCB(); skip: gXProcWorkaroundShareData[ui32Index].ui32RefCount--; }
IMG_INTERNAL void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) { if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO)) goto skip; PVRSRV_LOCK_CCB(); gsRefCountCCB[giOffset].pszFile = pszFile; gsRefCountCCB[giOffset].iLine = iLine; gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); snprintf(gsRefCountCCB[giOffset].pcMesg, PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, PVRSRV_REFCOUNT_CCB_FMT_STRING, "MEMINFO", psKernelMemInfo->psKernelSyncInfo, psKernelMemInfo, psKernelMemInfo->sMemBlk.hOSMemHandle, NULL, psKernelMemInfo->ui32RefCount, psKernelMemInfo->ui32RefCount - 1, psKernelMemInfo->uAllocSize); gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; PVRSRV_UNLOCK_CCB(); skip: psKernelMemInfo->ui32RefCount--; }
IMG_INTERNAL void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo, PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) { IMG_UINT32 ui32RefValue = OSAtomicRead(psKernelSyncInfo->pvRefCount); if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO)) goto skip; PVRSRV_LOCK_CCB(); gsRefCountCCB[giOffset].pszFile = pszFile; gsRefCountCCB[giOffset].iLine = iLine; gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); snprintf(gsRefCountCCB[giOffset].pcMesg, PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, PVRSRV_REFCOUNT_CCB_FMT_STRING, "SYNCINFO", psKernelSyncInfo, psKernelMemInfo, (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL, NULL, ui32RefValue, ui32RefValue - 1, (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0); gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; PVRSRV_UNLOCK_CCB(); skip: PVRSRVReleaseSyncInfoKM(psKernelSyncInfo); }
IMG_INTERNAL void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf) { if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2)) goto skip; PVRSRV_LOCK_CCB(); gsRefCountCCB[giOffset].pszFile = pszFile; gsRefCountCCB[giOffset].iLine = iLine; gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); snprintf(gsRefCountCCB[giOffset].pcMesg, PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, PVRSRV_REFCOUNT_CCB_FMT_STRING, "BM_BUF2", NULL, NULL, BM_HandleToOSMemHandle(pBuf), pBuf, pBuf->ui32ExportCount, pBuf->ui32ExportCount - 1, (pBuf->pMapping) ? pBuf->pMapping->uSize : 0); gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; PVRSRV_UNLOCK_CCB(); skip: pBuf->ui32ExportCount--; }
void SystraceTAKick(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FrameNum, IMG_UINT32 ui32RTData, IMG_BOOL bIsFirstKick) { IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); IMG_UINT32 ui32JobID = 0; IMG_UINT32 ui32CtxID = 0; PVRSRV_SYSTRACE_ERROR eError = PVRSRV_SYSTRACE_OK; if(psDevInfo->bSystraceInitialised) { if(bIsFirstKick) { eError = CreateJob(psDevInfo->psSystraceData, ui32PID, ui32FrameNum, ui32RTData); if(eError != PVRSRV_SYSTRACE_OK) { PVR_DPF((PVR_DBG_WARNING,"Systrace: Error creating a Job")); } } eError = GetCtxAndJobID(psDevInfo->psSystraceData, ui32PID, ui32FrameNum, ui32RTData, &ui32CtxID, &ui32JobID); if(eError != PVRSRV_SYSTRACE_OK) { PVR_DPF((PVR_DBG_WARNING,"Systrace: Job not found")); } trace_gpu_job_enqueue(ui32CtxID, ui32JobID, "TA"); } }
IMG_INTERNAL void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine, PKV_OFFSET_STRUCT psOffsetStruct) { if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2)) goto skip; PVRSRV_LOCK_CCB(); gsRefCountCCB[giOffset].pszFile = pszFile; gsRefCountCCB[giOffset].iLine = iLine; gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); snprintf(gsRefCountCCB[giOffset].pcMesg, PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, PVRSRV_REFCOUNT_CCB_FMT_STRING, "MMAP2", NULL, NULL, psOffsetStruct->psLinuxMemArea, psOffsetStruct, psOffsetStruct->ui32Mapped, psOffsetStruct->ui32Mapped - 1, psOffsetStruct->ui32RealByteSize); gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; PVRSRV_UNLOCK_CCB(); skip: psOffsetStruct->ui32Mapped--; }
int CreatePerProcessProcEntry(const char *name, read_proc_t rhandler, write_proc_t whandler, void *data) { struct PVRSRV_ENV_PER_PROCESS_DATA *psPerProc; u32 ui32PID; if (!dir) { PVR_DPF(PVR_DBG_ERROR, "CreatePerProcessProcEntries: /proc/%s doesn't exist", PVRProcDirRoot); return -ENOMEM; } ui32PID = OSGetCurrentProcessIDKM(); psPerProc = PVRSRVPerProcessPrivateData(ui32PID); if (!psPerProc) { PVR_DPF(PVR_DBG_ERROR, "CreatePerProcessProcEntries: no per process data"); return -ENOMEM; } if (!psPerProc->psProcDir) { char dirname[16]; int ret; ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID); if (ret <= 0 || ret >= sizeof(dirname)) { PVR_DPF(PVR_DBG_ERROR, "CreatePerProcessProcEntries: " "couldn't generate per process proc " "directory name \"%u\"", ui32PID); return -ENOMEM; } else { psPerProc->psProcDir = proc_mkdir(dirname, dir); if (!psPerProc->psProcDir) { PVR_DPF(PVR_DBG_ERROR, "CreatePerProcessProcEntries: " "couldn't create per process proc " "directory /proc/%s/%u", PVRProcDirRoot, ui32PID); return -ENOMEM; } } } return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler, whandler, data); }
static int PVRSRVRelease(struct inode unref__ * pInode, struct file unref__ * pFile) { int Ret = 0; LinuxLockMutex(&gPVRSRVLock); PVRSRVProcessDisconnect(OSGetCurrentProcessIDKM()); LinuxUnLockMutex(&gPVRSRVLock); return Ret; }
static int PVRSRVOpen(struct inode unref__ * pInode, struct file unref__ * pFile) { int Ret = 0; LinuxLockMutex(&gPVRSRVLock); if (PVRSRVProcessConnect(OSGetCurrentProcessIDKM()) != PVRSRV_OK) Ret = -ENOMEM; LinuxUnLockMutex(&gPVRSRVLock); return Ret; }
/*! ****************************************************************************** @Function LinuxEventObjectAdd @Description Linux wait object addition @Input hOSEventObjectList : Event object list handle @Output phOSEventObject : Pointer to the event object handle @Return PVRSRV_ERROR : Error code ******************************************************************************/ PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject) { PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject; PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); PVRSRV_PER_PROCESS_DATA *psPerProc; unsigned long ulLockFlags; psPerProc = PVRSRVPerProcessData(ui32PID); if (psPerProc == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data")); return PVRSRV_ERROR_OUT_OF_MEMORY; } /* allocate completion variable */ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), (IMG_VOID **)&psLinuxEventObject, IMG_NULL, "Linux Event Object") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory ")); return PVRSRV_ERROR_OUT_OF_MEMORY; } INIT_LIST_HEAD(&psLinuxEventObject->sList); atomic_set(&psLinuxEventObject->sTimeStamp, 0); psLinuxEventObject->ui32TimeStampPrevious = 0; #if defined(DEBUG) psLinuxEventObject->ui32Stats = 0; #endif init_waitqueue_head(&psLinuxEventObject->sWait); psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList; psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_EVENT_OBJECT, psLinuxEventObject, 0, &LinuxEventObjectDeleteCallback); write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags); list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList); write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags); *phOSEventObject = psLinuxEventObject; return PVRSRV_OK; }
int msvdx_preinit_mmu(unsigned long hmemcxt) { PVRSRV_ERROR err; PVRSRV_PER_PROCESS_DATA *ps_data = NULL; IMG_HANDLE hmem = (IMG_HANDLE) hmemcxt; IMG_HANDLE hmemkm; IMG_DEV_PHYADDR addr; IMG_UINT32 pid = OSGetCurrentProcessIDKM(); int ret; drm_emgd_priv_t *priv = gpDrmDevice->dev_private; igd_context_t *context = priv->context; platform_context_plb_t *platform = (platform_context_plb_t *) context->platform_context; ps_data = PVRSRVPerProcessData(pid); if (!ps_data) { printk(KERN_ERR "MSVDX: Cannot get process data information"); return -1; } err = PVRSRVLookupHandle(ps_data->psHandleBase, &hmemkm, hmem, PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT); if(err != PVRSRV_OK) { printk(KERN_ERR "MSVDX: Cannot get memory context from process data"); return -1; } addr = BM_GetDeviceNode(hmemkm)->pfnMMUGetPDDevPAddr(BM_GetMMUContextFromMemContext(hmemkm)); msvdx_init_compositor_mmu(addr.uiAddr); if (!platform->msvdx_pvr) { ret = msvdx_pvr_init(); if (ret) { printk(KERN_INFO "Failed in msvdx_pvr_init()"); } else { printk(KERN_INFO "Succeed for msvdx_pvr_init()"); } } return 0; }
int psb_get_meminfo_by_handle(IMG_HANDLE hKernelMemInfo, PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo) { PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL; PVRSRV_PER_PROCESS_DATA *psPerProc = IMG_NULL; PVRSRV_ERROR eError; psPerProc = PVRSRVPerProcessData(OSGetCurrentProcessIDKM()); eError = PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID *)&psKernelMemInfo, hKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO); if (eError != PVRSRV_OK) { DRM_ERROR("Cannot find kernel meminfo for handle 0x%x\n", (IMG_UINT32)hKernelMemInfo); return -EINVAL; } *ppsKernelMemInfo = psKernelMemInfo; DRM_DEBUG("Got Kernel MemInfo for handle %x\n", (IMG_UINT32)hKernelMemInfo); return 0; }
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_INT32 PVRSRV_BridgeDispatchKM(struct file *pFile, IMG_UINT unref__ ioctlCmd, IMG_UINT32 arg) #endif { IMG_UINT32 cmd; #if !defined(SUPPORT_DRI_DRM) PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg; PVRSRV_BRIDGE_PACKAGE sBridgePackageKM; #endif PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM; IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); PVRSRV_PER_PROCESS_DATA *psPerProc; IMG_INT err = -EFAULT; LinuxLockMutex(&gPVRSRVLock); #if defined(SUPPORT_DRI_DRM) PVR_UNREFERENCED_PARAMETER(dev); psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg; PVR_ASSERT(psBridgePackageKM != IMG_NULL); #else PVR_UNREFERENCED_PARAMETER(ioctlCmd); psBridgePackageKM = &sBridgePackageKM; if(!OSAccessOK(PVR_VERIFY_WRITE, psBridgePackageUM, sizeof(PVRSRV_BRIDGE_PACKAGE))) { PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments", __FUNCTION__)); goto unlock_and_return; } if(OSCopyFromUser(IMG_NULL, psBridgePackageKM, psBridgePackageUM, sizeof(PVRSRV_BRIDGE_PACKAGE)) != PVRSRV_OK) { goto unlock_and_return; } #endif cmd = psBridgePackageKM->ui32BridgeID; #if defined(MODULE_TEST) switch (cmd) { case PVRSRV_BRIDGE_SERVICES_TEST_MEM1: { PVRSRV_ERROR eError = MemTest1(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; case PVRSRV_BRIDGE_SERVICES_TEST_MEM2: { PVRSRV_ERROR eError = MemTest2(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; case PVRSRV_BRIDGE_SERVICES_TEST_RESOURCE: { PVRSRV_ERROR eError = ResourceTest(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; case PVRSRV_BRIDGE_SERVICES_TEST_EVENTOBJECT: { PVRSRV_ERROR eError = EventObjectTest(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; case PVRSRV_BRIDGE_SERVICES_TEST_MEMMAPPING: { PVRSRV_ERROR eError = MemMappingTest(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; case PVRSRV_BRIDGE_SERVICES_TEST_PROCESSID: { PVRSRV_ERROR eError = ProcessIDTest(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; case PVRSRV_BRIDGE_SERVICES_TEST_CLOCKUSWAITUS: { PVRSRV_ERROR eError = ClockusWaitusTest(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; case PVRSRV_BRIDGE_SERVICES_TEST_TIMER: { PVRSRV_ERROR eError = TimerTest(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; case PVRSRV_BRIDGE_SERVICES_TEST_PRIVSRV: { PVRSRV_ERROR eError = PrivSrvTest(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; case PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA: { IMG_UINT32 ui32PID; PVRSRV_PER_PROCESS_DATA *psPerProc; PVRSRV_ERROR eError; ui32PID = OSGetCurrentProcessIDKM(); PVRSRVTrace("PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA %d", ui32PID); psPerProc = PVRSRVPerProcessData(ui32PID); eError = CopyDataTest(psBridgePackageKM->pvParamIn, psBridgePackageKM->pvParamOut, psPerProc); *(PVRSRV_ERROR*)psBridgePackageKM->pvParamOut = eError; err = 0; goto unlock_and_return; } case PVRSRV_BRIDGE_SERVICES_TEST_POWERMGMT: { PVRSRV_ERROR eError = PowerMgmtTest(); if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN)) { PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ; pReturn->eError = eError; } } err = 0; goto unlock_and_return; } #endif if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES) { PVRSRV_ERROR eError; eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE, (IMG_PVOID *)&psPerProc, psBridgePackageKM->hKernelServices, PVRSRV_HANDLE_TYPE_PERPROC_DATA); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)", __FUNCTION__, eError)); goto unlock_and_return; } if(psPerProc->ui32PID != ui32PID) { PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data " "belonging to process %d", __FUNCTION__, ui32PID, psPerProc->ui32PID)); goto unlock_and_return; } } else { psPerProc = PVRSRVPerProcessData(ui32PID); if(psPerProc == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: " "Couldn't create per-process data area")); goto unlock_and_return; } } psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID); #if defined(PVR_SECURE_FD_EXPORT) switch(cmd) { case PVRSRV_BRIDGE_EXPORT_DEVICEMEM: { PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); if(psPrivateData->hKernelMemInfo) { PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo " "per file descriptor", __FUNCTION__)); err = -EINVAL; goto unlock_and_return; } break; } case PVRSRV_BRIDGE_MAP_DEV_MEMORY: { PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN = (PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamIn; PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); if(!psPrivateData->hKernelMemInfo) { PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no " "associated MemInfo handle", __FUNCTION__)); err = -EINVAL; goto unlock_and_return; } psMapDevMemIN->hKernelMemInfo = psPrivateData->hKernelMemInfo; break; } default: { PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); if(psPrivateData->hKernelMemInfo) { PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried " "to use privileged service", __FUNCTION__)); goto unlock_and_return; } break; } } #endif err = BridgedDispatchKM(psPerProc, psBridgePackageKM); if(err != PVRSRV_OK) goto unlock_and_return; switch(cmd) { #if defined(PVR_SECURE_FD_EXPORT) case PVRSRV_BRIDGE_EXPORT_DEVICEMEM: { PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT = (PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut; PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); psPrivateData->hKernelMemInfo = psExportDeviceMemOUT->hMemInfo; #if defined(SUPPORT_MEMINFO_IDS) psExportDeviceMemOUT->ui64Stamp = psPrivateData->ui64Stamp = ++ui64Stamp; #endif break; } #endif #if defined(SUPPORT_MEMINFO_IDS) case PVRSRV_BRIDGE_MAP_DEV_MEMORY: { PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT = (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut; PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp = psPrivateData->ui64Stamp; break; } case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY: { PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT = (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut; psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp; break; } #endif default: break; } unlock_and_return: LinuxUnLockMutex(&gPVRSRVLock); return err; }
PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateData, IMG_PVOID pvOSData) { ENV_CONNECTION_DATA *psEnvConnection; #if defined(SUPPORT_ION) ENV_ION_CONNECTION_DATA *psIonConnection; #endif *phOsPrivateData = OSAllocMem(sizeof(ENV_CONNECTION_DATA)); if (*phOsPrivateData == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed", __FUNCTION__)); return PVRSRV_ERROR_OUT_OF_MEMORY; } psEnvConnection = (ENV_CONNECTION_DATA *)*phOsPrivateData; OSMemSet(psEnvConnection, 0, sizeof(*psEnvConnection)); /* Save the pointer to our struct file */ psEnvConnection->psFile = pvOSData; #if defined(SUPPORT_ION) psIonConnection = (ENV_ION_CONNECTION_DATA *)OSAllocMem(sizeof(ENV_ION_CONNECTION_DATA)); if (psIonConnection == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed", __FUNCTION__)); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psIonConnection, 0, sizeof(*psIonConnection)); psEnvConnection->psIonData = psIonConnection; /* We can have more then one connection per process so we need more then the PID to have a unique name */ psEnvConnection->psIonData->psIonDev = IonDevAcquire(); OSSNPrintf(psEnvConnection->psIonData->azIonClientName, ION_CLIENT_NAME_SIZE, "pvr_ion_client-%p-%d", *phOsPrivateData, OSGetCurrentProcessIDKM()); psEnvConnection->psIonData->psIonClient = ion_client_create(psEnvConnection->psIonData->psIonDev, psEnvConnection->psIonData->azIonClientName); if (IS_ERR_OR_NULL(psEnvConnection->psIonData->psIonClient)) { PVR_DPF((PVR_DBG_ERROR, "OSConnectionPrivateDataInit: Couldn't create " "ion client for per connection data")); return PVRSRV_ERROR_OUT_OF_MEMORY; } psEnvConnection->psIonData->ui32IonClientRefCount = 1; #endif /* SUPPORT_ION */ return PVRSRV_OK; }
int alloc_ramdec_region(unsigned long *base_addr0, unsigned long *base_addr1, unsigned long size0, unsigned long size1) { unsigned long pid = OSGetCurrentProcessIDKM(); unsigned long num = 10; unsigned long heap_count = 0; void *sgx_cookie = NULL; unsigned long heapIndex = 0, generalHeapIndex = 0; PVRSRV_ERROR err; PVRSRV_KERNEL_MEM_INFO *rendec0MemInfo; PVRSRV_KERNEL_MEM_INFO *rendec1MemInfo; int i; printk(KERN_INFO "Calling PVRSRVPerProcessData()\n"); if (PVRSRVPerProcessDataConnect(200) != PVRSRV_OK) { printk(KERN_ERR "msvdx_init: connect to PVR failed\n"); } psPerProc = PVRSRVPerProcessData(200); if (psPerProc == IMG_NULL) { printk(KERN_ERR "msvdx_init: Couldn't find per process data for pid=%lx\n", pid); } printk(KERN_INFO " TEST: pp_data = 0x%p\n", psPerProc); PVRSRVEnumerateDevicesKM(&num, dev_id_list); printk(KERN_INFO "Calling PVRSRVEnumerateDevicesKM()\n"); if (PVRSRVEnumerateDevicesKM(&num, dev_id_list) != PVRSRV_OK) { printk(KERN_ERR "msvdx_init: PVRSRVEnumerateDevice failed\n"); } else { printk(KERN_INFO " PVRSRVEnumerateDevicesKM() found %ld devices\n", num); for (i = 0 ; i < num ; i++) { PVRSRV_DEVICE_IDENTIFIER *id = dev_id_list + i; unsigned long cookie = 0; printk(KERN_INFO " Device %d has type %d, class %d & index %ld\n", i, id->eDeviceType, id->eDeviceClass, id->ui32DeviceIndex); if (PVRSRV_DEVICE_TYPE_EXT != id->eDeviceType) { // Call PVRSRVAcquireDeviceDataKM(): printk(KERN_INFO "Calling PVRSRVAcquireDeviceDataKM()\n"); err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex, PVRSRV_DEVICE_TYPE_UNKNOWN, (void *) &cookie); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] PVRSRVAcquireDeviceDataKM() " "returned %d\n", err); break; } if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) { printk(KERN_INFO " Found cookie = 0x%lx\n", cookie); // Save this away for later: sgx_cookie = (void *) cookie; } } } } // Enumerate the display class devices to be able to find the 3DD: printk(KERN_INFO "Calling PVRSRVEnumerateDCKM()\n"); err = PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS_DISPLAY, &num, dev_ids); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] PVRSRVEnumerateDCKM() returned %d\n", err); } else { // Find the 3DD: printk(KERN_INFO " PVRSRVEnumerateDCKM() found %ld devices\n", num); for (i = 0 ; i < num ; i++) { printk(KERN_INFO " device %d has ID %ld\n", i, dev_ids[i]); } if (0 == dev_ids[0]) { printk(KERN_ERR "[EMGD] Did not find 3rd-party display driver ID\n"); } } // Call PVRSRVCreateDeviceMemContextKM(): printk(KERN_INFO "Calling PVRSRVCreateDeviceMemContextKM()\n"); err = PVRSRVCreateDeviceMemContextKM(sgx_cookie, psPerProc, &dev_mem_context, &heap_count, heap_info, &mem_created, &dummy); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] PVRSRVCreateDeviceMemContextKM() " "returned %d\n", err); } for (heapIndex=0; heapIndex<heap_count; heapIndex++) { if (HEAP_IDX(heap_info[heapIndex].ui32HeapID) == SGX_GENERAL_HEAP_ID) { generalHeapIndex = heapIndex; break; } } if (PVRSRVAllocDeviceMemKM(sgx_cookie, psPerProc, heap_info[generalHeapIndex].hDevMemHeap, PVRSRV_MEM_READ | PVRSRV_MEM_WRITE, size0, 0, &rendec0MemInfo, "") != PVRSRV_OK) { printk(KERN_ERR "msvdx: PVRSRVAllocDeviceMemKM failed\n"); } if (PVRSRVAllocDeviceMemKM(sgx_cookie, psPerProc, heap_info[generalHeapIndex].hDevMemHeap, PVRSRV_MEM_READ | PVRSRV_MEM_WRITE, size1, 0, &rendec1MemInfo, "") != PVRSRV_OK) { printk(KERN_ERR "msvdx: PVRSRVAllocDeviceMemKM failed\n"); } *base_addr0 = rendec0MemInfo->sDevVAddr.uiAddr; *base_addr1 = rendec1MemInfo->sDevVAddr.uiAddr; //printk(KERN_INFO "pvr size0=%lx, size1=%lx, heap=%ld\n", size0, size1, generalHeapIndex); // return PVRSRV_OK; return 0; }
/*! ****************************************************************************** @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_UINT32 psb_get_tgid(void) { return OSGetCurrentProcessIDKM(); }
/* * Can't call from module initialization, since PVR services are started when * the Xorg server starts. */ int msvdx_pvr_init(void) { drm_emgd_priv_t *priv; igd_context_t *context; platform_context_plb_t *platform; struct msvdx_pvr_info *pvr; PVRSRV_DEVICE_IDENTIFIER dev_id_list[PVRSRV_MAX_DEVICES]; IMG_UINT32 pid; IMG_UINT32 num_devices; IMG_UINT32 i; IMG_BOOL mem_created; PVRSRV_ERROR err; int ret; priv = gpDrmDevice->dev_private; context = priv->context; platform = (platform_context_plb_t *)context->platform_context; if (platform->msvdx_pvr) { printk(KERN_INFO "[EMGD] MSVDX: PVR services already " "initialized\n"); return 0; } pvr = kzalloc(sizeof(*pvr), GFP_KERNEL); if (!pvr) return -ENOMEM; /* * Create a dummy kernel thread so that a persistent PVR per process * data could be created. */ pvr->kthread = kthread_run(msvdx_pvr_kthread, NULL, "msvdx-pvr"); if (IS_ERR(pvr->kthread)) { ret = PTR_ERR(pvr->kthread); printk(KERN_ERR "[EMGD] MSVDX: failed to create MSVDX PVR " "kernel tread, error=%i\n", ret); pvr->kthread = NULL; goto out_free; } ret = -ENODEV; pid = OSGetCurrentProcessIDKM(); //(IMG_UINT32)pvr->kthread->pid; err = PVRSRVPerProcessDataConnect(pid); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] MSVDX: connect to PVR failed (pid=%u), " "error=%i\n", (unsigned int)err, err); goto out_stop_kthread; } pvr->per_proc = PVRSRVPerProcessData(pid); if (pvr->per_proc == IMG_NULL) { printk(KERN_ERR "[EMGD] MSVDX: Couldn't find per process " "data for pid=%u\n", (unsigned int)pid); goto out_stop_kthread; } err = PVRSRVEnumerateDevicesKM(&num_devices, dev_id_list); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] MSVDX: PVRSRVEnumerateDevice() failed, " "error=%u\n", (unsigned int)err); goto out_stop_kthread; } for (i = 0 ; i < num_devices ; i++) { PVRSRV_DEVICE_IDENTIFIER *id; IMG_HANDLE cookie; cookie = IMG_NULL; id = &dev_id_list[i]; if (id->eDeviceType != PVRSRV_DEVICE_TYPE_EXT) { err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex, PVRSRV_DEVICE_TYPE_UNKNOWN, &cookie); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] MSVDX: " "PVRSRVAcquireDeviceDataKM() failed, " "error=%u\n", err); break; } if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) { pvr->sgx_cookie = cookie; break; } } } if (pvr->sgx_cookie == IMG_NULL) goto out_stop_kthread; err = PVRSRVCreateDeviceMemContextKM(pvr->sgx_cookie, pvr->per_proc, &pvr->dev_mem_context, &pvr->heap_count, pvr->heap_info, &mem_created, pvr->heap_shared); if (err != PVRSRV_OK) { printk(KERN_ERR "[EMGD] MSVDX: PVRSRVCreateDeviceMemContextKM()" " failed, error=%u\n", (unsigned int)err); goto out_stop_kthread; } for (i = 0; i < pvr->heap_count; i++) { if (HEAP_IDX(pvr->heap_info[i].ui32HeapID) == SGX_VIDEO_HEAP_ID) { pvr->mapping_heap_index = i; break; } } platform->msvdx_pvr = pvr; pvr->pid = pid; return 0; out_stop_kthread: kthread_stop(pvr->kthread); out_free: kfree(pvr); return ret; }
PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData) { PVRSRV_ERROR eError; IMG_HANDLE hBlockAlloc; PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc; eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_ENV_PER_PROCESS_DATA), phOsPrivateData, &hBlockAlloc, "Environment per Process Data"); if (eError != PVRSRV_OK) { *phOsPrivateData = IMG_NULL; PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError)); return eError; } psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData; OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc)); psEnvPerProc->hBlockAlloc = hBlockAlloc; /* Linux specific mmap processing */ LinuxMMapPerProcessConnect(psEnvPerProc); #if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) /* Linked list of PVRSRV_FILE_PRIVATE_DATA structures */ INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead); #endif #if defined(SUPPORT_ION) OSSNPrintf(psEnvPerProc->azIonClientName, ION_CLIENT_NAME_SIZE, "pvr_ion_client-%d", OSGetCurrentProcessIDKM()); psEnvPerProc->psIONClient = ion_client_create(gpsIonDev, psEnvPerProc->azIonClientName); if (IS_ERR_OR_NULL(psEnvPerProc->psIONClient)) { PVR_DPF((PVR_DBG_ERROR, "OSPerProcessPrivateDataInit: Couldn't create " "ion client for per process data")); return PVRSRV_ERROR_OUT_OF_MEMORY; } #endif /* defined(SUPPORT_ION) */ return PVRSRV_OK; }