/*!
******************************************************************************

 @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;	 
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
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;

}
Ejemplo n.º 5
0
/*
 * 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;
}
Ejemplo n.º 6
0
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;
}