summaryrefslogtreecommitdiff
path: root/sgx/services4/srvkm/env
diff options
context:
space:
mode:
Diffstat (limited to 'sgx/services4/srvkm/env')
-rwxr-xr-xsgx/services4/srvkm/env/linux/Kbuild.mk2
-rw-r--r--sgx/services4/srvkm/env/linux/env_perproc.h7
-rw-r--r--sgx/services4/srvkm/env/linux/mm.c23
-rw-r--r--sgx/services4/srvkm/env/linux/mm.h6
-rw-r--r--sgx/services4/srvkm/env/linux/mmap.c275
-rw-r--r--[-rwxr-xr-x]sgx/services4/srvkm/env/linux/module.c14
-rw-r--r--sgx/services4/srvkm/env/linux/osfunc.c17
-rw-r--r--sgx/services4/srvkm/env/linux/private_data.h32
-rw-r--r--[-rwxr-xr-x]sgx/services4/srvkm/env/linux/pvr_bridge_k.c64
-rw-r--r--[-rwxr-xr-x]sgx/services4/srvkm/env/linux/pvr_drm.c22
-rw-r--r--[-rwxr-xr-x]sgx/services4/srvkm/env/linux/pvr_drm.h0
-rw-r--r--sgx/services4/srvkm/env/linux/pvr_uaccess.h3
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