diff options
Diffstat (limited to 'sgx/services4/srvkm/env')
-rwxr-xr-x | sgx/services4/srvkm/env/linux/Kbuild.mk | 2 | ||||
-rw-r--r-- | sgx/services4/srvkm/env/linux/env_perproc.h | 7 | ||||
-rw-r--r-- | sgx/services4/srvkm/env/linux/mm.c | 23 | ||||
-rw-r--r-- | sgx/services4/srvkm/env/linux/mm.h | 6 | ||||
-rw-r--r-- | sgx/services4/srvkm/env/linux/mmap.c | 275 | ||||
-rw-r--r--[-rwxr-xr-x] | sgx/services4/srvkm/env/linux/module.c | 14 | ||||
-rw-r--r-- | sgx/services4/srvkm/env/linux/osfunc.c | 17 | ||||
-rw-r--r-- | sgx/services4/srvkm/env/linux/private_data.h | 32 | ||||
-rw-r--r--[-rwxr-xr-x] | sgx/services4/srvkm/env/linux/pvr_bridge_k.c | 64 | ||||
-rw-r--r--[-rwxr-xr-x] | sgx/services4/srvkm/env/linux/pvr_drm.c | 22 | ||||
-rw-r--r--[-rwxr-xr-x] | sgx/services4/srvkm/env/linux/pvr_drm.h | 0 | ||||
-rw-r--r-- | sgx/services4/srvkm/env/linux/pvr_uaccess.h | 3 |
12 files changed, 402 insertions, 63 deletions
diff --git a/sgx/services4/srvkm/env/linux/Kbuild.mk b/sgx/services4/srvkm/env/linux/Kbuild.mk index 702eadf..95df225 100755 --- a/sgx/services4/srvkm/env/linux/Kbuild.mk +++ b/sgx/services4/srvkm/env/linux/Kbuild.mk @@ -123,6 +123,8 @@ $(PVRSRV_MODNAME)-y += \ ccflags-y += \ -I$(KERNELDIR)/include/drm \ + -I$(KERNELDIR)/drivers/staging/omapdrm \ + -I$(KERNELDIR)/include/linux \ -I$(TOP)/services4/include/env/linux \ ifeq ($(PVR_DRI_DRM_NOT_PCI),1) diff --git a/sgx/services4/srvkm/env/linux/env_perproc.h b/sgx/services4/srvkm/env/linux/env_perproc.h index dabf1e3..58e2c38 100644 --- a/sgx/services4/srvkm/env/linux/env_perproc.h +++ b/sgx/services4/srvkm/env/linux/env_perproc.h @@ -39,6 +39,13 @@ typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_ struct proc_dir_entry *psProcDir; #if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) struct list_head sDRMAuthListHead; +#if defined(SUPPORT_DRI_DRM_EXTERNAL) + /* note: these fields are valid for the duration of a syscall + * or until gPVRSRVLock is released.. + */ + struct drm_file *file; + struct drm_device *dev; +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ #endif } PVRSRV_ENV_PER_PROCESS_DATA; diff --git a/sgx/services4/srvkm/env/linux/mm.c b/sgx/services4/srvkm/env/linux/mm.c index d53d40d..3edbc49 100644 --- a/sgx/services4/srvkm/env/linux/mm.c +++ b/sgx/services4/srvkm/env/linux/mm.c @@ -1262,12 +1262,20 @@ LinuxMemAreaStructAlloc(IMG_VOID) #endif } +#if defined(SUPPORT_DRI_DRM_EXTERNAL) +# include <linux/omap_drv.h> +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ + static IMG_VOID LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea) { +#if defined(SUPPORT_DRI_DRM_EXTERNAL) + if (psLinuxMemArea->buf) + drm_gem_object_unreference_unlocked(psLinuxMemArea->buf); +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea); - + } @@ -1427,6 +1435,10 @@ DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea) IMG_VOID * LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea) { + if (!psLinuxMemArea) + { + return NULL; + } switch(psLinuxMemArea->eAreaType) { case LINUX_MEM_AREA_VMALLOC: @@ -1454,9 +1466,12 @@ LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea) IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset) { - IMG_CPU_PHYADDR CpuPAddr; - - CpuPAddr.uiAddr = 0; + IMG_CPU_PHYADDR CpuPAddr = {0}; + + if (!psLinuxMemArea) + { + return CpuPAddr; + } switch(psLinuxMemArea->eAreaType) { diff --git a/sgx/services4/srvkm/env/linux/mm.h b/sgx/services4/srvkm/env/linux/mm.h index abd97b8..da49083 100644 --- a/sgx/services4/srvkm/env/linux/mm.h +++ b/sgx/services4/srvkm/env/linux/mm.h @@ -149,6 +149,10 @@ struct _LinuxMemArea { struct list_head sMMapOffsetStructList; IMG_HANDLE hSmartCache; + +#if defined(SUPPORT_DRI_DRM_EXTERNAL) + IMG_HANDLE buf; /* external buffer handle, like a GEM or ION buffer */ +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ }; #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)) @@ -330,7 +334,7 @@ LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea) const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType); -#if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS) +#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS) const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags); #endif diff --git a/sgx/services4/srvkm/env/linux/mmap.c b/sgx/services4/srvkm/env/linux/mmap.c index b2794b7..ca38e5d 100644 --- a/sgx/services4/srvkm/env/linux/mmap.c +++ b/sgx/services4/srvkm/env/linux/mmap.c @@ -84,6 +84,7 @@ static IMG_UINT32 g_ui32RegisteredAreas = 0; static IMG_UINT32 g_ui32TotalByteSize = 0; #endif +static inline PKV_OFFSET_STRUCT FindOffsetStructByPID(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32PID); #if defined(DEBUG_LINUX_MMAP_AREAS) static struct proc_dir_entry *g_ProcMMap; @@ -274,6 +275,110 @@ DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea, *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset); } +#if defined(SUPPORT_DRI_DRM_EXTERNAL) +#include <linux/omap_drv.h> +#include "syscommon.h" +static struct omap_gem_vm_ops gem_ops; +static struct drm_gem_object * +create_gem_wrapper(struct drm_device *dev, LinuxMemArea *psLinuxMemArea, + IMG_UINT32 ui32ByteOffset, IMG_UINT32 ui32ByteSize) +{ + /* create a new GEM buffer wrapping this mem-area.. */ + union omap_gem_size gsize; + uint32_t flags; + struct page **pages = NULL; + unsigned long paddr = 0; + int i, npages = PAGE_ALIGN(ui32ByteSize) / PAGE_SIZE; + + + /* from GEM buffer object point of view, we are either mapping + * in terms of an array of struct pages for (potentially) + * discontiguous RAM, or in terms of a physically contiguous + * area (which could be RAM or IO) specified in terms of a + * base physical address. So try and convert the mem-area + * to one of these two types. + * + * TODO double check this.. I don't see any evidence that PVR + * is doing anything like remapping discontiguous IO regions + * into one contiguous virtual user mapping.. + */ + switch(psLinuxMemArea->eAreaType) { + case LINUX_MEM_AREA_IOREMAP: + paddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr.uiAddr; + paddr += ui32ByteOffset; + break; + case LINUX_MEM_AREA_EXTERNAL_KV: + if (psLinuxMemArea->uData.sExternalKV.bPhysContig) { + paddr = SysSysPAddrToCpuPAddr( + psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr).uiAddr; + paddr += ui32ByteOffset; + } else { + IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset); + pages = kmalloc(sizeof(pages) * npages, GFP_KERNEL); + for (i = 0; i < npages; i++) { + IMG_SYS_PHYADDR SysPAddr = + psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageIndex]; + pages[i] = phys_to_page(SysSysPAddrToCpuPAddr(SysPAddr).uiAddr); + } + } + break; + case LINUX_MEM_AREA_IO: + paddr = psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr; + paddr += ui32ByteOffset; + break; + case LINUX_MEM_AREA_VMALLOC: + pages = kmalloc(sizeof(pages) * npages, GFP_KERNEL); + for (i = 0; i < npages; i++) { + char *vaddr = ((char *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress) + + (i * PAGE_SIZE) + ui32ByteOffset; + pages[i] = vmalloc_to_page(vaddr); + } + break; + case LINUX_MEM_AREA_ALLOC_PAGES: + pages = kmalloc(sizeof(pages) * npages, GFP_KERNEL); + for (i = 0; i < npages; i++) { + pages[i] = psLinuxMemArea->uData.sPageList.pvPageList[i + PHYS_TO_PFN(ui32ByteOffset)]; + } + break; + case LINUX_MEM_AREA_SUB_ALLOC: + return create_gem_wrapper(dev, + psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea, + psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset, + ui32ByteSize); + break; + default: + PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n", + __FUNCTION__, psLinuxMemArea->eAreaType)); + return NULL; + } + + /* map PVR cache type flags to GEM.. */ + switch(psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK) { + case PVRSRV_HAP_CACHED: + case PVRSRV_HAP_SMART: + flags = OMAP_BO_CACHED; + break; + case PVRSRV_HAP_WRITECOMBINE: + flags = OMAP_BO_WC; + break; + case PVRSRV_HAP_UNCACHED: + flags = OMAP_BO_UNCACHED; + break; + default: + PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__)); + return NULL; + } + + /* we need to give GEM page aligned address, because that is what will + * be mapped.. userspace will figure out the offset.. + */ + paddr &= ~(PAGE_SIZE-1); + + gsize.bytes = ui32ByteSize; + return omap_gem_new_ext(dev, gsize, flags, paddr, pages, &gem_ops); +} +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ + PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, @@ -291,6 +396,11 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, PKV_OFFSET_STRUCT psOffsetStruct; IMG_HANDLE hOSMemHandle; PVRSRV_ERROR eError; +#if defined(SUPPORT_DRI_DRM_EXTERNAL) + PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc = + (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc); + struct drm_gem_object *buf = NULL; +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ LinuxLockMutex(&g_sMMapMutex); @@ -310,16 +420,35 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; +#if defined(SUPPORT_DRI_DRM_EXTERNAL) + /* if we are using DRM/GEM, then let GEM generate the buffer offset.. + * this is done by creating a wrapper object. + */ + if (psEnvPerProc->dev && psEnvPerProc->file) + { + buf = psLinuxMemArea->buf; + if (!buf) + { + buf = create_gem_wrapper(psEnvPerProc->dev, + psLinuxMemArea, 0, psLinuxMemArea->ui32ByteSize); + if (!buf) + { + PVR_DPF((PVR_DBG_ERROR, "%s: Screw you guys, I'm going home..", __FUNCTION__)); + eError = PVRSRV_ERROR_OUT_OF_MEMORY; + goto exit_unlock; + } + psLinuxMemArea->buf = buf; + } + } +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ + DetermineUsersSizeAndByteOffset(psLinuxMemArea, pui32RealByteSize, pui32ByteOffset); - - list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) + psOffsetStruct = FindOffsetStructByPID(psLinuxMemArea, psPerProc->ui32PID); + if (psOffsetStruct) { - if (psPerProc->ui32PID == psOffsetStruct->ui32PID) - { - PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize); *pui32MMapOffset = psOffsetStruct->ui32MMapOffset; @@ -328,7 +457,6 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, eError = PVRSRV_OK; goto exit_unlock; - } } @@ -349,6 +477,17 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, #endif } +#if defined(SUPPORT_DRI_DRM_EXTERNAL) + if (buf) + { + /* note: omap_gem_mmap_offset() gives us a byte offset that is multiple + * of pages, which can be passed to mmap().. but PVR wants a page offset + * that can be passed to mmap2(). So convert it back to pages: + */ + *pui32MMapOffset = omap_gem_mmap_offset(buf) >> PAGE_SHIFT; + } +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ + psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize); if (psOffsetStruct == IMG_NULL) { @@ -371,6 +510,7 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, *pui32MMapOffset = *pui32MMapOffset << (PAGE_SHIFT - 12); exit_unlock: + LinuxUnLockMutex(&g_sMMapMutex); return eError; @@ -412,11 +552,9 @@ PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - - list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) + psOffsetStruct = FindOffsetStructByPID(psLinuxMemArea, ui32PID); + if (psOffsetStruct) { - if (psOffsetStruct->ui32PID == ui32PID) - { if (psOffsetStruct->ui32RefCount == 0) { PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area %p", __FUNCTION__, psOffsetStruct, psLinuxMemArea)); @@ -433,7 +571,6 @@ PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, eError = PVRSRV_OK; goto exit_unlock; - } } @@ -477,6 +614,19 @@ FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize) return IMG_NULL; } +static inline PKV_OFFSET_STRUCT +FindOffsetStructByPID(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32PID) +{ + PKV_OFFSET_STRUCT psOffsetStruct; + list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) + { + if (psOffsetStruct->ui32PID == ui32PID) + { + return psOffsetStruct; + } + } + return NULL; +} static IMG_BOOL DoMapToUser(LinuxMemArea *psLinuxMemArea, @@ -594,9 +744,8 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea, static IMG_VOID -MMapVOpenNoLock(struct vm_area_struct* ps_vma) +MMapVOpenNoLock(struct vm_area_struct* ps_vma, PKV_OFFSET_STRUCT psOffsetStruct) { - PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data; PVR_ASSERT(psOffsetStruct != IMG_NULL) psOffsetStruct->ui32Mapped++; PVR_ASSERT(!psOffsetStruct->bOnMMapList); @@ -625,17 +774,19 @@ MMapVOpen(struct vm_area_struct* ps_vma) { LinuxLockMutex(&g_sMMapMutex); - MMapVOpenNoLock(ps_vma); + MMapVOpenNoLock(ps_vma, ps_vma->vm_private_data); LinuxUnLockMutex(&g_sMMapMutex); } static IMG_VOID -MMapVCloseNoLock(struct vm_area_struct* ps_vma) +MMapVCloseNoLock(struct vm_area_struct* ps_vma, PKV_OFFSET_STRUCT psOffsetStruct) { - PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data; - PVR_ASSERT(psOffsetStruct != IMG_NULL) + WARN_ON(!psOffsetStruct); + if (!psOffsetStruct) { + return; + } #if defined(DEBUG_LINUX_MMAP_AREAS) PVR_DPF((PVR_DBG_MESSAGE, @@ -667,7 +818,7 @@ MMapVClose(struct vm_area_struct* ps_vma) { LinuxLockMutex(&g_sMMapMutex); - MMapVCloseNoLock(ps_vma); + MMapVCloseNoLock(ps_vma, ps_vma->vm_private_data); LinuxUnLockMutex(&g_sMMapMutex); } @@ -700,10 +851,15 @@ enum { static IMG_VOID PVRMMapUnmapInv(IMG_HANDLE hSmartCache, bool inv); + +#ifndef DBG #define DBG(fmt, ...) do {} while (0) //#define DBG(fmt, ...) printk(KERN_INFO"[%s:%d] "fmt"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif +#ifndef VERB #define VERB(fmt, ...) do {} while (0) //#define VERB(fmt, ...) printk(KERN_INFO"[%s:%d] "fmt"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif #define ERR(fmt, ...) printk(KERN_ERR"ERR: [%s:%d] "fmt"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) static int @@ -1155,7 +1311,7 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma) } - MMapVOpenNoLock(ps_vma); + MMapVOpenNoLock(ps_vma, ps_vma->vm_private_data); PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n", __FUNCTION__, ps_vma->vm_pgoff)); @@ -1171,6 +1327,87 @@ unlock_and_return: return iRetVal; } +#if defined(SUPPORT_DRI_DRM_EXTERNAL) +/* note: currently we stuff memarea struct in bo->private_data.. but there + * must be a better way. Currently PVR's mapper-private data is the + * PVRSRV_KERNEL_SYNC_INFO.. I'm not sure if there is a way to go back + * and forth between this an the offset struct? + */ + +static void +MMapVOpenExt(struct vm_area_struct* ps_vma) +{ + struct drm_gem_object *obj = ps_vma->vm_private_data; + PKV_OFFSET_STRUCT psOffsetStruct = + FindOffsetStructByPID(obj->driver_private, OSGetCurrentProcessIDKM()); + if (WARN_ON(!psOffsetStruct)) + return; + LinuxLockMutex(&g_sMMapMutex); + MMapVOpenNoLock(ps_vma, psOffsetStruct); + LinuxUnLockMutex(&g_sMMapMutex); +} + +static void +MMapVCloseExt(struct vm_area_struct* ps_vma) +{ + struct drm_gem_object *obj = ps_vma->vm_private_data; + PKV_OFFSET_STRUCT psOffsetStruct = + FindOffsetStructByPID(obj->driver_private, OSGetCurrentProcessIDKM()); + if (WARN_ON(!psOffsetStruct)) + return; + LinuxLockMutex(&g_sMMapMutex); + MMapVCloseNoLock(ps_vma, psOffsetStruct); + LinuxUnLockMutex(&g_sMMapMutex); +} + +/* this function doesn't actually handle user mapping.. but does update some + * internal data structures that would otherwise not get updated if we didn't + * have a callback to notify of the user mapping. It is used when something + * outside of the PVR driver (ie. DRM) is handling the userspace mapping + */ +static void +PVRMMapExt(struct file* pFile, struct vm_area_struct* ps_vma) +{ + struct drm_gem_object *obj = ps_vma->vm_private_data; + IMG_UINT32 ui32ByteSize; + PKV_OFFSET_STRUCT psOffsetStruct; + + PVR_UNREFERENCED_PARAMETER(pFile); + + LinuxLockMutex(&g_sMMapMutex); + + ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start; + + ps_vma->vm_flags |= VM_DONTCOPY; + + psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize); + if (psOffsetStruct == IMG_NULL) + { + PVR_DPF((PVR_DBG_WARNING, "%s: No mapped area at offset 0x%08lx, size=%d\n", + __FUNCTION__, ps_vma->vm_pgoff, ui32ByteSize)); + goto unlock_and_return; + } + list_del(&psOffsetStruct->sMMapItem); + psOffsetStruct->bOnMMapList = IMG_FALSE; + + PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0); + + psOffsetStruct->ui32UserVAddr = ps_vma->vm_start; + + obj->driver_private = psOffsetStruct->psLinuxMemArea; + + MMapVOpenNoLock(ps_vma, psOffsetStruct); + +unlock_and_return: + LinuxUnLockMutex(&g_sMMapMutex); +} + +static struct omap_gem_vm_ops gem_ops = { + .open = MMapVOpenExt, + .close = MMapVCloseExt, + .mmap = PVRMMapExt, +}; +#endif #if defined(DEBUG_LINUX_MMAP_AREAS) diff --git a/sgx/services4/srvkm/env/linux/module.c b/sgx/services4/srvkm/env/linux/module.c index 596fe98..cda7c21 100755..100644 --- a/sgx/services4/srvkm/env/linux/module.c +++ b/sgx/services4/srvkm/env/linux/module.c @@ -115,12 +115,6 @@ MODULE_SUPPORTED_DEVICE(DEVNAME); #endif -#if defined(SUPPORT_DRI_DRM) -#define PRIVATE_DATA(pFile) ((pFile)->driver_priv) -#else -#define PRIVATE_DATA(pFile) ((pFile)->private_data) -#endif - #if defined(PVRSRV_NEED_PVR_DPF) #include <linux/moduleparam.h> extern IMG_UINT32 gPVRDebugLevel; @@ -253,7 +247,7 @@ static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device { SYS_DATA *psSysData; - PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice)); + PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p) (%s)", pDevice, pDevice->name)); #if 0 @@ -476,7 +470,7 @@ static int PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile) #endif psPrivateData->ui32OpenPID = ui32PID; psPrivateData->hBlockAlloc = hBlockAlloc; - PRIVATE_DATA(pFile) = psPrivateData; + set_private(pFile, psPrivateData); iRet = 0; err_unlock: LinuxUnLockMutex(&gPVRSRVLock); @@ -497,7 +491,7 @@ static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile) #if defined(SUPPORT_DRI_DRM) psPrivateData = (PVRSRV_FILE_PRIVATE_DATA *)pvPrivData; #else - psPrivateData = PRIVATE_DATA(pFile); + psPrivateData = get_private(pFile); #endif if (psPrivateData != IMG_NULL) { @@ -515,7 +509,7 @@ static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile) psPrivateData, psPrivateData->hBlockAlloc); #if !defined(SUPPORT_DRI_DRM) - PRIVATE_DATA(pFile) = IMG_NULL; + set_private(pFile, IMG_NULL); #endif } diff --git a/sgx/services4/srvkm/env/linux/osfunc.c b/sgx/services4/srvkm/env/linux/osfunc.c index 42ecb05..1fb99f2 100644 --- a/sgx/services4/srvkm/env/linux/osfunc.c +++ b/sgx/services4/srvkm/env/linux/osfunc.c @@ -362,6 +362,23 @@ OSMemHandleUnegisterSmart(IMG_VOID *hOSMemHandle, IMG_HANDLE hSmartCache) } +#if defined(SUPPORT_DRI_DRM_EXTERNAL) +IMG_VOID +OSMemHandleSetGEM(IMG_VOID *hOSMemHandle, IMG_HANDLE buf) +{ + LinuxMemArea *psLinuxMemArea = hOSMemHandle; + psLinuxMemArea->buf = buf; +} + +IMG_HANDLE +OSMemHandleGetGEM(IMG_VOID *hOSMemHandle) +{ + LinuxMemArea *psLinuxMemArea = hOSMemHandle; + return psLinuxMemArea->buf; +} +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ + + IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset) { diff --git a/sgx/services4/srvkm/env/linux/private_data.h b/sgx/services4/srvkm/env/linux/private_data.h index b8751d3..a460798 100644 --- a/sgx/services4/srvkm/env/linux/private_data.h +++ b/sgx/services4/srvkm/env/linux/private_data.h @@ -65,5 +65,37 @@ typedef struct } PVRSRV_FILE_PRIVATE_DATA; +#if defined(SUPPORT_DRI_DRM_EXTERNAL) +#include <linux/omap_drv.h> +extern int pvr_mapper_id; +static inline PVRSRV_FILE_PRIVATE_DATA * get_private(struct drm_file *file) +{ + return omap_drm_file_priv(file, pvr_mapper_id); +} +static inline void set_private(struct drm_file *file, PVRSRV_FILE_PRIVATE_DATA *priv) +{ + omap_drm_file_set_priv(file, pvr_mapper_id, priv); +} +#elif defined(SUPPORT_DRI_DRM) +static inline PVRSRV_FILE_PRIVATE_DATA * get_private(struct drm_file *file) +{ + return file->driver_priv; +} +static inline void set_private(struct drm_file *file, PVRSRV_FILE_PRIVATE_DATA *priv) +{ + file->driver_priv = priv; +} +#else +static inline PVRSRV_FILE_PRIVATE_DATA * get_private(struct file *file) +{ + return file->private_data; +} +static inline void set_private(struct file *file, PVRSRV_FILE_PRIVATE_DATA *priv) +{ + file->private_data = priv; +} +#endif + + #endif diff --git a/sgx/services4/srvkm/env/linux/pvr_bridge_k.c b/sgx/services4/srvkm/env/linux/pvr_bridge_k.c index b1c1124..373b586 100755..100644 --- a/sgx/services4/srvkm/env/linux/pvr_bridge_k.c +++ b/sgx/services4/srvkm/env/linux/pvr_bridge_k.c @@ -35,6 +35,7 @@ #include "private_data.h" #include "linkage.h" #include "pvr_bridge_km.h" +#include "pvr_uaccess.h" #if defined(SUPPORT_DRI_DRM) #include <drm/drmP.h> @@ -54,12 +55,6 @@ #include "bridged_pvr_bridge.h" -#if defined(SUPPORT_DRI_DRM) -#define PRIVATE_DATA(pFile) ((pFile)->driver_priv) -#else -#define PRIVATE_DATA(pFile) ((pFile)->private_data) -#endif - #if defined(DEBUG_BRIDGE_KM) static struct proc_dir_entry *g_ProcBridgeStats =0; @@ -192,10 +187,6 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig #if !defined(SUPPORT_DRI_DRM) PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg; PVRSRV_BRIDGE_PACKAGE sBridgePackageKM; - IMG_VOID *handle = NULL; -#else - IMG_VOID * omap_drm_get_default_fb(struct drm_device *dev); - IMG_VOID *handle = omap_drm_get_default_fb(dev); // XXX handle should come from omaplfb somehow, because it is omaplfb that decided to use the fb_info* as the unique handle.. #endif PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM; IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); @@ -274,7 +265,7 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig { case PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2: { - PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); + PVRSRV_FILE_PRIVATE_DATA *psPrivateData = get_private(pFile); if(psPrivateData->hKernelMemInfo) { @@ -290,7 +281,7 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig { PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN = (PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamIn; - PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); + PVRSRV_FILE_PRIVATE_DATA *psPrivateData = get_private(pFile); if(!psPrivateData->hKernelMemInfo) { @@ -300,13 +291,17 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig goto unlock_and_return; } - psMapDevMemIN->hKernelMemInfo = psPrivateData->hKernelMemInfo; + if (pvr_put_user(psPrivateData->hKernelMemInfo, &psMapDevMemIN->hKernelMemInfo) != 0) + { + err = -EFAULT; + goto unlock_and_return; + } break; } default: { - PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); + PVRSRV_FILE_PRIVATE_DATA *psPrivateData = get_private(pFile); if(psPrivateData->hKernelMemInfo) { @@ -369,7 +364,16 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig } #endif - err = BridgedDispatchKM(psPerProc, psBridgePackageKM, handle); +#if defined(SUPPORT_DRI_DRM_EXTERNAL) + { + PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc = + (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc); + psEnvPerProc->dev = dev; + psEnvPerProc->file = pFile; + } +#endif /* SUPPORT_DRI_DRM_EXTERNAL */ + + err = BridgedDispatchKM(psPerProc, psBridgePackageKM); if(err != PVRSRV_OK) goto unlock_and_return; @@ -379,11 +383,21 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig { PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT = (PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut; - PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); + PVRSRV_FILE_PRIVATE_DATA *psPrivateData = get_private(pFile); - psPrivateData->hKernelMemInfo = psExportDeviceMemOUT->hMemInfo; + if (pvr_get_user(psPrivateData->hKernelMemInfo, &psExportDeviceMemOUT->hMemInfo) != 0) + { + err = -EFAULT; + goto unlock_and_return; + } #if defined(SUPPORT_MEMINFO_IDS) - psExportDeviceMemOUT->ui64Stamp = psPrivateData->ui64Stamp = ++ui64Stamp; + psPrivateData->ui64Stamp = ++ui64Stamp; + + if (pvr_put_user(psPrivateData->ui64Stamp, &psExportDeviceMemOUT->ui64Stamp) != 0) + { + err = -EFAULT; + goto unlock_and_return; + } #endif break; } @@ -393,8 +407,12 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig { 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; + PVRSRV_FILE_PRIVATE_DATA *psPrivateData = get_private(pFile); + if (pvr_put_user(psPrivateData->ui64Stamp, &psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp) != 0) + { + err = -EFAULT; + goto unlock_and_return; + } break; } @@ -402,7 +420,11 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig { PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT = (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut; - psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp; + if (pvr_put_user(++ui64Stamp, &psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp) != 0) + { + err = -EFAULT; + goto unlock_and_return; + } break; } #endif diff --git a/sgx/services4/srvkm/env/linux/pvr_drm.c b/sgx/services4/srvkm/env/linux/pvr_drm.c index bf593d7..620c158 100755..100644 --- a/sgx/services4/srvkm/env/linux/pvr_drm.c +++ b/sgx/services4/srvkm/env/linux/pvr_drm.c @@ -44,7 +44,7 @@ #include <drm/drmP.h> #include <drm/drm.h> -#if defined(SUPPORT_DRI_DRM_EXTERNAL) +#ifdef SUPPORT_DRI_DRM_EXTERNAL # include <linux/omap_drm.h> #endif @@ -69,6 +69,7 @@ #include "lock.h" #include "linkage.h" #include "pvr_drm.h" +#include "private_data.h" #if defined(PVR_DRI_DRM_NOT_PCI) #include "pvr_drm_mod.h" @@ -235,15 +236,14 @@ PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file) DRI_DRM_STATIC void PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file) { - PVRSRVRelease(file->driver_priv); - - file->driver_priv = NULL; + PVRSRVRelease(get_private(file)); + set_private(file, IMG_NULL); } #elif defined(SUPPORT_DRI_DRM_EXTERNAL) DRI_DRM_STATIC int PVRSRVDrmRelease(struct drm_device *dev, struct drm_file *file) { - void *psDriverPriv = file->driver_priv; + void *psDriverPriv = get_private(file); PVR_TRACE(("PVRSRVDrmRelease: psDriverPriv=%p", psDriverPriv)); @@ -252,6 +252,8 @@ PVRSRVDrmRelease(struct drm_device *dev, struct drm_file *file) PVRSRVRelease(psDriverPriv); } + set_private(file, IMG_NULL); + return 0; } #else @@ -259,7 +261,7 @@ DRI_DRM_STATIC int PVRSRVDrmRelease(struct inode *inode, struct file *filp) { struct drm_file *file_priv = filp->private_data; - void *psDriverPriv = file_priv->driver_priv; + void *psDriverPriv = get_private(file_priv); int ret; ret = drm_release(inode, filp); @@ -386,6 +388,8 @@ static int pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls); #endif #if defined(SUPPORT_DRI_DRM_EXTERNAL) +int pvr_ioctl_base; +int pvr_mapper_id; static struct omap_drm_plugin plugin = { .name = PVR_DRM_NAME, @@ -394,11 +398,10 @@ static struct omap_drm_plugin plugin = { .unload = PVRSRVDrmUnload, .release = PVRSRVDrmRelease, - .mmap = PVRMMap, .ioctls = sPVRDrmIoctls, .num_ioctls = ARRAY_SIZE(sPVRDrmIoctls), - .ioctl_start = 0, + .ioctl_base = 0, /* initialized when plugin is registered */ }; #else static struct drm_driver sPVRDrmDriver = @@ -501,6 +504,8 @@ static int __init PVRSRVDrmInit(void) #if defined(SUPPORT_DRI_DRM_EXTERNAL) iRes = omap_drm_register_plugin(&plugin); + pvr_ioctl_base = plugin.ioctl_base; + pvr_mapper_id = omap_drm_register_mapper(); #else iRes = drm_init(&sPVRDrmDriver); #endif @@ -517,6 +522,7 @@ static int __init PVRSRVDrmInit(void) static void __exit PVRSRVDrmExit(void) { #if defined(SUPPORT_DRI_DRM_EXTERNAL) + omap_drm_unregister_mapper(pvr_mapper_id); omap_drm_unregister_plugin(&plugin); #else drm_exit(&sPVRDrmDriver); diff --git a/sgx/services4/srvkm/env/linux/pvr_drm.h b/sgx/services4/srvkm/env/linux/pvr_drm.h index 9d79602..9d79602 100755..100644 --- a/sgx/services4/srvkm/env/linux/pvr_drm.h +++ b/sgx/services4/srvkm/env/linux/pvr_drm.h diff --git a/sgx/services4/srvkm/env/linux/pvr_uaccess.h b/sgx/services4/srvkm/env/linux/pvr_uaccess.h index bacafe9..6e7f1d3 100644 --- a/sgx/services4/srvkm/env/linux/pvr_uaccess.h +++ b/sgx/services4/srvkm/env/linux/pvr_uaccess.h @@ -64,5 +64,8 @@ static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pv #endif } +#define pvr_put_user put_user +#define pvr_get_user get_user + #endif |