summaryrefslogtreecommitdiff
path: root/drivers/gpu/pvr/services4/srvkm/env/linux
diff options
context:
space:
mode:
authorWengang Wu <wgw@motorola.com>2014-05-21 09:29:41 -0500
committerWengang Wu <wgw@motorola.com>2014-05-21 09:29:41 -0500
commit53a835f5057367679eb3db728bbdd427aab8aa8a (patch)
tree03e5bbde7d371e885d1c67210b2b0c9bb0130d40 /drivers/gpu/pvr/services4/srvkm/env/linux
parent7489b569ffb64cdb998544405b6774bd43aab70b (diff)
downloadolio-linux-3.10-53a835f5057367679eb3db728bbdd427aab8aa8a.tar.xz
olio-linux-3.10-53a835f5057367679eb3db728bbdd427aab8aa8a.zip
IKXCLOCK-1501 Upgrade to TI SGX Android OpenGL 1.12@2701748
Initial codes of TI SGX DDK 1.12@2701748 Change-Id: I75a8f6521968346ea1b2ea9fa54817ba186442ce
Diffstat (limited to 'drivers/gpu/pvr/services4/srvkm/env/linux')
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/Kbuild.mk30
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/Linux.mk2
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/env_data.h0
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/env_perproc.h4
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/event.c5
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/event.h0
-rw-r--r--drivers/gpu/pvr/services4/srvkm/env/linux/gc_bvmapping.c147
-rw-r--r--drivers/gpu/pvr/services4/srvkm/env/linux/gc_bvmapping.h27
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/ion.c504
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/ion.h35
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/linkage.h0
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/lock.h0
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/mm.c708
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/mm.h146
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/mmap.c393
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/mmap.h28
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/module.c100
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/mutex.c12
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/mutex.h10
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/mutils.c0
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/mutils.h13
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/osfunc.c862
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/osperproc.c17
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/pdump.c59
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/private_data.h4
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/proc.c896
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/proc.h104
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/pvr_bridge_k.c15
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/pvr_debug.c232
-rwxr-xr-xdrivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c739
-rwxr-xr-xdrivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.h184
-rwxr-xr-xdrivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.c1766
-rwxr-xr-xdrivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.h78
-rwxr-xr-x[-rw-r--r--]drivers/gpu/pvr/services4/srvkm/env/linux/pvr_uaccess.h0
-rw-r--r--drivers/gpu/pvr/services4/srvkm/env/linux/sysfs.c90
-rw-r--r--drivers/gpu/pvr/services4/srvkm/env/linux/sysfs.h22
-rwxr-xr-xdrivers/gpu/pvr/services4/srvkm/env/linux/systrace.c282
-rwxr-xr-xdrivers/gpu/pvr/services4/srvkm/env/linux/systrace.h68
38 files changed, 4851 insertions, 2731 deletions
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/Kbuild.mk b/drivers/gpu/pvr/services4/srvkm/env/linux/Kbuild.mk
index 25e35e934b7..10064d69c06 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/Kbuild.mk
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/Kbuild.mk
@@ -38,7 +38,7 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
### ###########################################################################
-pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-y += \
+pvrsrvkm-y += \
services4/srvkm/env/linux/osfunc.o \
services4/srvkm/env/linux/mutils.o \
services4/srvkm/env/linux/mmap.o \
@@ -51,10 +51,8 @@ pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-y += \
services4/srvkm/env/linux/mutex.o \
services4/srvkm/env/linux/event.o \
services4/srvkm/env/linux/osperproc.o \
- services4/srvkm/env/linux/sysfs.o \
services4/srvkm/common/buffer_manager.o \
services4/srvkm/common/devicemem.o \
- services4/srvkm/common/deviceclass.o \
services4/srvkm/common/handle.o \
services4/srvkm/common/hash.o \
services4/srvkm/common/lists.o \
@@ -66,7 +64,6 @@ pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-y += \
services4/srvkm/common/perproc.o \
services4/srvkm/common/power.o \
services4/srvkm/common/pvrsrv.o \
- services4/srvkm/common/queue.o \
services4/srvkm/common/ra.o \
services4/srvkm/common/refcount.o \
services4/srvkm/common/resman.o \
@@ -75,21 +72,32 @@ pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-y += \
services4/system/$(PVR_SYSTEM)/sysconfig.o \
services4/system/$(PVR_SYSTEM)/sysutils.o
-pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-$(CONFIG_ION_OMAP) += \
- services4/srvkm/env/linux/ion.o
-pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-$(CONFIG_GCBV) += \
- services4/srvkm/env/linux/gc_bvmapping.o
+ifeq ($(SUPPORT_PVRSRV_DEVICE_CLASS),1)
+pvrsrvkm-y += \
+ services4/srvkm/common/deviceclass.o \
+ services4/srvkm/common/queue.o
+endif
ifeq ($(SUPPORT_ION),1)
pvrsrvkm-y += \
services4/srvkm/env/linux/ion.o
endif
+ifeq ($(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC),1)
+pvrsrvkm-y += \
+ services4/srvkm/env/linux/pvr_sync.o
+endif
+
ifeq ($(TTRACE),1)
pvrsrvkm-y += \
services4/srvkm/common/ttrace.o
endif
+ifeq ($(SUPPORT_PVRSRV_ANDROID_SYSTRACE),1)
+pvrsrvkm-y += \
+ services4/srvkm/env/linux/systrace.o
+endif
+
ifneq ($(W),1)
CFLAGS_osfunc.o := -Werror
CFLAGS_mutils.o := -Werror
@@ -127,7 +135,7 @@ endif
# SUPPORT_SGX==1 only
-pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-y += \
+pvrsrvkm-y += \
services4/srvkm/bridged/sgx/bridged_sgx_bridge.o \
services4/srvkm/devices/sgx/sgxinit.o \
services4/srvkm/devices/sgx/sgxpower.o \
@@ -152,11 +160,11 @@ endif
ifeq ($(SUPPORT_DRI_DRM),1)
-pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-y += \
+pvrsrvkm-y += \
services4/srvkm/env/linux/pvr_drm.o
ccflags-y += \
- -I$(KERNELDIR)/include/drm \
+ -Iinclude/drm \
-I$(TOP)/services4/include/env/linux \
ifeq ($(PVR_DRI_DRM_NOT_PCI),1)
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/Linux.mk b/drivers/gpu/pvr/services4/srvkm/env/linux/Linux.mk
index 7e3d0fb2e96..535a1f91150 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/Linux.mk
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/Linux.mk
@@ -41,5 +41,5 @@
modules := srvkm
srvkm_type := kernel_module
-srvkm_target := pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV).ko
+srvkm_target := pvrsrvkm.ko
srvkm_makefile := $(THIS_DIR)/Kbuild.mk
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/env_data.h b/drivers/gpu/pvr/services4/srvkm/env/linux/env_data.h
index b8388098c7d..b8388098c7d 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/env_data.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/env_data.h
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/env_perproc.h b/drivers/gpu/pvr/services4/srvkm/env/linux/env_perproc.h
index 8a37a7f44f9..788e80fc005 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/env_perproc.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/env_perproc.h
@@ -43,8 +43,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define __ENV_PERPROC_H__
#include <linux/list.h>
-#include <linux/proc_fs.h>
+#include "proc.h"
#include "services.h"
#include "handle.h"
@@ -56,7 +56,7 @@ typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
struct list_head sDRMAuthListHead;
#endif
-#if defined (SUPPORT_ION)
+#if defined(SUPPORT_ION)
struct ion_client *psIONClient;
IMG_CHAR azIonClientName[ION_CLIENT_NAME_SIZE];
#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/event.c b/drivers/gpu/pvr/services4/srvkm/env/linux/event.c
index b70a79dfc39..c60f2d5c1a6 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/event.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/event.c
@@ -49,7 +49,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <asm/io.h>
#include <asm/page.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
#include <asm/system.h>
#endif
#include <linux/mm.h>
@@ -74,7 +74,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "pvrmmap.h"
#include "mmap.h"
#include "env_data.h"
-#include "proc.h"
#include "mutex.h"
#include "lock.h"
#include "event.h"
@@ -396,7 +395,7 @@ PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTi
ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
- LinuxLockMutex(&gPVRSRVLock);
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
#if defined(DEBUG)
psLinuxEventObject->ui32Stats++;
#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/event.h b/drivers/gpu/pvr/services4/srvkm/env/linux/event.h
index 5c1451cd342..5c1451cd342 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/event.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/event.h
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/gc_bvmapping.c b/drivers/gpu/pvr/services4/srvkm/env/linux/gc_bvmapping.c
deleted file mode 100644
index 6c5d17a0e84..00000000000
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/gc_bvmapping.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2011 Texas Instruments, Inc
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include <linux/bltsville.h>
-#include <linux/bvinternal.h>
-#include <linux/gcbv-iface.h>
-
-#include "gc_bvmapping.h"
-#include "services_headers.h"
-
-void gc_bvmap_meminfo(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
-{
- int i;
- IMG_CPU_PHYADDR phy_addr;
- unsigned long *page_addrs;
- struct bvbuffdesc *buffdesc;
- struct bvphysdesc *physdesc;
- int num_pages;
- struct bventry bv_entry;
- enum bverror bv_error;
-
- gcbv_init(&bv_entry);
- if (!bv_entry.bv_map) {
- psMemInfo->bvmap_handle = NULL;
- return;
- }
-
- num_pages = (psMemInfo->uAllocSize +
- PAGE_SIZE - 1) >> PAGE_SHIFT;
-
- page_addrs = kzalloc(sizeof(*page_addrs) * num_pages, GFP_KERNEL);
- if (!page_addrs) {
- printk(KERN_ERR "%s: Out of memory\n", __func__);
- return;
- }
-
- physdesc = kzalloc(sizeof(*physdesc), GFP_KERNEL);
- buffdesc = kzalloc(sizeof(*buffdesc), GFP_KERNEL);
- if (!buffdesc || !physdesc) {
- printk(KERN_ERR "%s: Out of memory\n", __func__);
- kfree(page_addrs);
- kfree(physdesc);
- kfree(buffdesc);
- return;
- }
-
- for (i = 0; i < num_pages; i++) {
- phy_addr = OSMemHandleToCpuPAddr(
- psMemInfo->sMemBlk.hOSMemHandle, i << PAGE_SHIFT);
- page_addrs[i] = (u32)phy_addr.uiAddr;
- }
-
- buffdesc->structsize = sizeof(*buffdesc);
- buffdesc->map = NULL;
- buffdesc->length = psMemInfo->uAllocSize;
- buffdesc->auxtype = BVAT_PHYSDESC;
- buffdesc->auxptr = physdesc;
- physdesc->structsize = sizeof(*physdesc);
- physdesc->pagesize = PAGE_SIZE;
- physdesc->pagearray = page_addrs;
- physdesc->pagecount = num_pages;
-
- /*
- * For ion allocated buffers let's verify how many planes this
- * meminfo consist of
- */
- if(psMemInfo->ui32Flags & PVRSRV_MEM_ION) {
- IMG_UINT32 num_addr_offsets = 0;
- OSGetMemMultiPlaneInfo(psMemInfo->sMemBlk.hOSMemHandle,
- NULL, &num_addr_offsets);
-
- /*
- * Account for this meminfo plane offset (relative to the base
- * address) if necessary
- */
- if(num_addr_offsets > 0)
- physdesc->pageoffset = psMemInfo->planeOffsets[0];
-
- /*
- * In BV there is no way to specify multiple offsets, check
- * all planes have the same offset and report any discrepancy
- */
- for (i = 1; i < num_addr_offsets; i++) {
- IMG_UINT32 plane_offset =
- psMemInfo->planeOffsets[i] % PAGE_SIZE;
- if (psMemInfo->planeOffsets[0] != plane_offset) {
- printk(KERN_WARNING "%s: meminfo %p offset 0 %d"
- " != offset %d %d, coalignment is "
- "missing\n", __func__, psMemInfo,
- psMemInfo->planeOffsets[0],
- i, plane_offset);
- }
- }
- }
-
- bv_error = bv_entry.bv_map(buffdesc);
- if (bv_error) {
- printk(KERN_ERR "%s: Failed to map meminfo %p, bverror %d\n",
- __func__, psMemInfo, bv_error);
- psMemInfo->bvmap_handle = NULL;
- } else
- psMemInfo->bvmap_handle = buffdesc;
-
-}
-
-void gc_bvunmap_meminfo(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
-{
- struct bvbuffdesc *buffdesc;
- struct bvphysdesc *physdesc;
- struct bventry bv_entry;
- enum bverror bv_error;
-
- gcbv_init(&bv_entry);
- if (!bv_entry.bv_map || !psMemInfo || !psMemInfo->bvmap_handle)
- return;
-
- buffdesc = psMemInfo->bvmap_handle;
- physdesc = (struct bvphysdesc*) buffdesc->auxptr;
- bv_error = bv_entry.bv_unmap(buffdesc);
- if (bv_error) {
- printk(KERN_ERR "%s: Failed to unmap bvhandle %p from meminfo "
- "%p, bverror %d\n", __func__, buffdesc, psMemInfo,
- bv_error);
- }
-
- kfree(physdesc->pagearray);
- kfree(physdesc);
- kfree(psMemInfo->bvmap_handle);
- psMemInfo->bvmap_handle = NULL;
-}
-
-IMG_VOID *gc_meminfo_to_hndl(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
-{
- return psMemInfo->bvmap_handle;
-}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/gc_bvmapping.h b/drivers/gpu/pvr/services4/srvkm/env/linux/gc_bvmapping.h
deleted file mode 100644
index 6a3a2b1ced0..00000000000
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/gc_bvmapping.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2011 Texas Instruments, Inc
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef GC_BVMAPPING_H
-#define GC_BVMAPPING_H
-
-#include "services_headers.h"
-
-void gc_bvunmap_meminfo(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
-
-void gc_bvmap_meminfo(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
-
-IMG_VOID *gc_meminfo_to_hndl(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
-
-#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c
index 3e772bca13e..036f1bd7cbe 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c
@@ -41,323 +41,417 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "ion.h"
-#include "services.h"
-#include "servicesint.h"
-#include "mutex.h"
-#include "lock.h"
-#include "mm.h"
-#include "handle.h"
-#include "perproc.h"
-#include "env_perproc.h"
-#include "private_data.h"
-#include "pvr_debug.h"
+/* Three possible configurations:
+ *
+ * - SUPPORT_ION && CONFIG_ION_OMAP
+ * Real ion support, but sharing with an SOC ion device. We need
+ * to co-share the heaps too.
+ *
+ * - SUPPORT_ION && !CONFIG_ION_OMAP
+ * "Reference" ion implementation. Creates its own ion device
+ * and heaps for the driver to use.
+ */
-#include <linux/module.h>
-#include <linux/file.h>
-#include <linux/fs.h>
+#if defined(SUPPORT_ION)
-#if defined (CONFIG_ION_OMAP)
-#define MAX_HANDLES_PER_FD 2
-extern struct ion_client *gpsIONClient;
+#include <linux/scatterlist.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
-int PVRSRVExportFDToIONHandles(int fd, struct ion_client **client,
- struct ion_handle **handles,
- unsigned int *num_handles)
-{
- PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
- PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
- LinuxMemArea *psLinuxMemArea;
- PVRSRV_ERROR eError;
- struct file *psFile;
- int i;
- unsigned int ui32NumHandles = *num_handles;
- int ret = -EINVAL;
+#if defined(CONFIG_ION_OMAP)
- /* Take the bridge mutex so the handle won't be freed underneath us */
- LinuxLockMutex(&gPVRSRVLock);
+/* Real ion with sharing */
- psFile = fget(fd);
- if(!psFile)
- goto err_unlock;
+extern struct ion_device *omap_ion_device;
+struct ion_device *gpsIonDev;
- psPrivateData = psFile->private_data;
- if(!psPrivateData)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: struct file* has no private_data; "
- "invalid export handle", __func__));
- goto err_fput;
- }
-
- eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
- (IMG_PVOID *)&psKernelMemInfo,
- psPrivateData->hKernelMemInfo,
- PVRSRV_HANDLE_TYPE_MEM_INFO);
- if(eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up MEM_INFO handle",
- __func__));
- goto err_fput;
- }
+PVRSRV_ERROR IonInit(IMG_VOID)
+{
+ gpsIonDev = omap_ion_device;
+ return PVRSRV_OK;
+}
- psLinuxMemArea = (LinuxMemArea *)psKernelMemInfo->sMemBlk.hOSMemHandle;
- BUG_ON(psLinuxMemArea == IMG_NULL);
+IMG_VOID IonDeinit(IMG_VOID)
+{
+ gpsIonDev = IMG_NULL;
+}
- if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ION)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: Valid handle, but not an ION buffer",
- __func__));
- goto err_fput;
- }
+#else /* defined(CONFIG_ION_OMAP) */
- /* Client is requesting fewer handles then we have */
- if(ui32NumHandles < psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes) {
+#if defined(CONFIG_ION_S5P)
- PVR_DPF((PVR_DBG_ERROR, "%s: Client requested %u handles, but we have %u",
- __func__,
- ui32NumHandles,
- psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes));
+/* Real ion with sharing (s5pv210) */
- /* Clear client handles */
- for (i = 0; i < ui32NumHandles; i++)
- handles[i] = NULL;
+extern struct ion_device *s5p_ion_device;
+struct ion_device *gpsIonDev;
- /* Return number of handles to client */
- *num_handles = psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes;
- goto err_fput;
- }
+PVRSRV_ERROR IonInit(IMG_VOID)
+{
+ gpsIonDev = s5p_ion_device;
+ return PVRSRV_OK;
+}
- for (i = 0; (i < psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes) && (i < MAX_HANDLES_PER_FD); i++)
- handles[i] = psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i];
+IMG_VOID IonDeinit(IMG_VOID)
+{
+ gpsIonDev = IMG_NULL;
+}
- *num_handles = i;
+#else /* defined(CONFIG_ION_S5P) */
- if(client)
- *client = gpsIONClient;
+#if defined(CONFIG_ION_SUNXI)
- ret = 0;
+/* Real ion with sharing (sunxi) */
-err_fput:
- fput(psFile);
-err_unlock:
- /* Allow PVRSRV clients to communicate with srvkm again */
- LinuxUnLockMutex(&gPVRSRVLock);
+extern struct ion_device *sunxi_ion_device;
+struct ion_device *gpsIonDev;
- return ret;
+PVRSRV_ERROR IonInit(IMG_VOID)
+{
+ gpsIonDev = sunxi_ion_device;
+ return PVRSRV_OK;
}
-struct ion_handle *
-PVRSRVExportFDToIONHandle(int fd, struct ion_client **client)
+IMG_VOID IonDeinit(IMG_VOID)
{
- unsigned int num_handles = 1;
- struct ion_handle *psHandle = IMG_NULL;
- PVRSRVExportFDToIONHandles(fd, client, &psHandle, &num_handles);
- return psHandle;
+ gpsIonDev = IMG_NULL;
}
-EXPORT_SYMBOL(PVRSRVExportFDToIONHandles);
-EXPORT_SYMBOL(PVRSRVExportFDToIONHandle);
-#endif
+#else /* defined(CONFIG_ION_SUNXI) */
+
+/* "Reference" ion implementation */
-#if defined (SUPPORT_ION)
-#include "syscommon.h"
-#include "env_data.h"
#include "../drivers/gpu/ion/ion_priv.h"
-#include "linux/kernel.h"
-struct ion_heap **apsIonHeaps;
-struct ion_device *psIonDev;
+static struct ion_heap **gapsIonHeaps;
+struct ion_device *gpsIonDev;
-static struct ion_platform_data generic_config = {
- .nr = 2,
- .heaps = {
- {
- .type = ION_HEAP_TYPE_SYSTEM_CONTIG,
- .name = "System contig",
- .id = ION_HEAP_TYPE_SYSTEM_CONTIG,
- },
- {
- .type = ION_HEAP_TYPE_SYSTEM,
- .name = "System",
- .id = ION_HEAP_TYPE_SYSTEM,
- }
- }
+#ifndef ION_CARVEOUT_MEM_BASE
+#define ION_CARVEOUT_MEM_BASE 0
+#endif
+
+#ifndef ION_CARVEOUT_MEM_SIZE
+#define ION_CARVEOUT_MEM_SIZE 0
+#endif
+
+static struct ion_platform_data gsGenericConfig =
+{
+ .nr = 3,
+ .heaps =
+ {
+ {
+ .type = ION_HEAP_TYPE_SYSTEM_CONTIG,
+ .name = "system_contig",
+ .id = ION_HEAP_TYPE_SYSTEM_CONTIG,
+ },
+ {
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .name = "system",
+ .id = ION_HEAP_TYPE_SYSTEM,
+ },
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = "carveout",
+ .id = ION_HEAP_TYPE_CARVEOUT,
+ .base = ION_CARVEOUT_MEM_BASE,
+ .size = ION_CARVEOUT_MEM_SIZE,
+ },
+ }
};
PVRSRV_ERROR IonInit(IMG_VOID)
{
- int uiHeapCount = generic_config.nr;
+ int uiHeapCount = gsGenericConfig.nr;
int uiError;
int i;
- apsIonHeaps = kzalloc(sizeof(struct ion_heap *) * uiHeapCount, GFP_KERNEL);
+ gapsIonHeaps = kzalloc(sizeof(struct ion_heap *) * uiHeapCount, GFP_KERNEL);
/* Create the ion devicenode */
- psIonDev = ion_device_create(NULL);
- if (IS_ERR_OR_NULL(psIonDev)) {
- kfree(apsIonHeaps);
+ gpsIonDev = ion_device_create(NULL);
+ if (IS_ERR_OR_NULL(gpsIonDev)) {
+ kfree(gapsIonHeaps);
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
/* Register all the heaps */
- for (i = 0; i < generic_config.nr; i++)
+ for (i = 0; i < gsGenericConfig.nr; i++)
{
- struct ion_platform_heap *psPlatHeapData = &generic_config.heaps[i];
+ struct ion_platform_heap *psPlatHeapData = &gsGenericConfig.heaps[i];
- apsIonHeaps[i] = ion_heap_create(psPlatHeapData);
- if (IS_ERR_OR_NULL(apsIonHeaps[i]))
+ gapsIonHeaps[i] = ion_heap_create(psPlatHeapData);
+ if (IS_ERR_OR_NULL(gapsIonHeaps[i]))
{
- uiError = PTR_ERR(apsIonHeaps[i]);
+ uiError = PTR_ERR(gapsIonHeaps[i]);
goto failHeapCreate;
}
- ion_device_add_heap(psIonDev, apsIonHeaps[i]);
+ ion_device_add_heap(gpsIonDev, gapsIonHeaps[i]);
}
return PVRSRV_OK;
failHeapCreate:
- for (i = 0; i < uiHeapCount; i++) {
- if (apsIonHeaps[i])
+ for (i = 0; i < uiHeapCount; i++)
+ {
+ if (gapsIonHeaps[i])
{
- ion_heap_destroy(apsIonHeaps[i]);
+ ion_heap_destroy(gapsIonHeaps[i]);
}
}
- kfree(apsIonHeaps);
+ kfree(gapsIonHeaps);
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
IMG_VOID IonDeinit(IMG_VOID)
{
- int uiHeapCount = generic_config.nr;
+ int uiHeapCount = gsGenericConfig.nr;
int i;
- for (i = 0; i < uiHeapCount; i++) {
- if (apsIonHeaps[i])
+ for (i = 0; i < uiHeapCount; i++)
+ {
+ if (gapsIonHeaps[i])
{
- ion_heap_destroy(apsIonHeaps[i]);
+ ion_heap_destroy(gapsIonHeaps[i]);
}
}
- kfree(apsIonHeaps);
- ion_device_destroy(psIonDev);
+ kfree(gapsIonHeaps);
+ ion_device_destroy(gpsIonDev);
}
+#endif /* defined(CONFIG_ION_SUNXI) */
+
+#endif /* defined(CONFIG_ION_S5P) */
+
+#endif /* defined(CONFIG_ION_OMAP) */
+
+#define MAX_IMPORT_ION_FDS 3
+
typedef struct _ION_IMPORT_DATA_
{
+ /* ion client handles are imported into */
struct ion_client *psIonClient;
- struct ion_handle *psIonHandle;
- IMG_PVOID pvKernAddr;
-} ION_IMPORT_DATA;
-PVRSRV_ERROR IonImportBufferAndAquirePhysAddr(IMG_HANDLE hIonDev,
- IMG_HANDLE hIonFD,
- IMG_UINT32 *pui32PageCount,
- IMG_SYS_PHYADDR **ppasSysPhysAddr,
- IMG_PVOID *ppvKernAddr,
- IMG_HANDLE *phPriv)
+ /* Number of ion handles represented by this import */
+ IMG_UINT32 ui32NumIonHandles;
+
+ /* Array of ion handles in use by services */
+ struct ion_handle *apsIonHandle[MAX_IMPORT_ION_FDS];
+
+ /* Array of physical addresses represented by these buffers */
+ IMG_SYS_PHYADDR *psSysPhysAddr;
+
+#if defined(PDUMP)
+ /* If ui32NumBuffers is 1 and ion_map_kernel() is implemented by the
+ * allocator, this may be non-NULL. Otherwise it will be NULL.
+ */
+ IMG_PVOID pvKernAddr0;
+#endif /* defined(PDUMP) */
+}
+ION_IMPORT_DATA;
+
+PVRSRV_ERROR IonImportBufferAndAcquirePhysAddr(IMG_HANDLE hIonDev,
+ IMG_UINT32 ui32NumFDs,
+ IMG_INT32 *pai32BufferFDs,
+ IMG_UINT32 *pui32PageCount,
+ IMG_SYS_PHYADDR **ppsSysPhysAddr,
+ IMG_PVOID *ppvKernAddr0,
+ IMG_HANDLE *phPriv,
+ IMG_HANDLE *phUnique)
{
+ struct scatterlist *psTemp, *psScatterList[MAX_IMPORT_ION_FDS] = {};
+ PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
struct ion_client *psIonClient = hIonDev;
- struct ion_handle *psIonHandle;
- struct scatterlist *psScatterList;
- struct scatterlist *psTemp;
- IMG_SYS_PHYADDR *pasSysPhysAddr = NULL;
+ IMG_UINT32 i, k, ui32PageCount = 0;
ION_IMPORT_DATA *psImportData;
- PVRSRV_ERROR eError;
- IMG_UINT32 ui32PageCount = 0;
- IMG_UINT32 i;
- IMG_PVOID pvKernAddr;
- int fd = (int) hIonFD;
- psImportData = kmalloc(sizeof(ION_IMPORT_DATA), GFP_KERNEL);
- if (psImportData == NULL)
+ if(ui32NumFDs > MAX_IMPORT_ION_FDS)
{
- return PVRSRV_ERROR_OUT_OF_MEMORY;
+ printk(KERN_ERR "%s: More ion export fds passed in than supported "
+ "(%d provided, %d max)", __func__, ui32NumFDs,
+ MAX_IMPORT_ION_FDS);
+ return PVRSRV_ERROR_INVALID_PARAMS;
}
- /* Get the buffer handle */
- psIonHandle = ion_import_fd(psIonClient, fd);
- if (psIonHandle == IMG_NULL)
+ psImportData = kzalloc(sizeof(ION_IMPORT_DATA), GFP_KERNEL);
+ if (psImportData == NULL)
{
- eError = PVRSRV_ERROR_BAD_MAPPING;
- goto exitFailImport;
+ goto exitFailKMallocImportData;
}
- /* Create data for free callback */
+ /* Set up import data for free call */
psImportData->psIonClient = psIonClient;
- psImportData->psIonHandle = psIonHandle;
+ psImportData->ui32NumIonHandles = ui32NumFDs;
- psScatterList = ion_map_dma(psIonClient, psIonHandle);
- if (psScatterList == NULL)
+ for(i = 0; i < ui32NumFDs; i++)
{
- eError = PVRSRV_ERROR_INVALID_PARAMS;
- goto exitFailMap;
- }
+ int fd = (int)pai32BufferFDs[i];
+ struct sg_table *psSgTable;
- /*
- We do a two pass process, 1st workout how many pages there
- are, 2nd fill in the data.
- */
- for (i=0;i<2;i++)
- {
- psTemp = psScatterList;
- if (i == 1)
+ psImportData->apsIonHandle[i] = ion_import_dma_buf(psIonClient, fd);
+ if (psImportData->apsIonHandle[i] == IMG_NULL)
{
- pasSysPhysAddr = kmalloc(sizeof(IMG_SYS_PHYADDR) * ui32PageCount, GFP_KERNEL);
- if (pasSysPhysAddr == NULL)
- {
- eError = PVRSRV_ERROR_OUT_OF_MEMORY;
- goto exitFailAlloc;
- }
- ui32PageCount = 0; /* Reset the page count a we use if for the index */
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto exitFailImport;
}
- while(psTemp)
+ psSgTable = ion_sg_table(psIonClient, psImportData->apsIonHandle[i]);
+ psScatterList[i] = psSgTable->sgl;
+ if (psScatterList[i] == NULL)
{
- IMG_UINT32 j;
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exitFailImport;
+ }
- for (j=0;j<psTemp->length;j+=PAGE_SIZE)
+ /* Although all heaps will provide an sg_table, the tables cannot
+ * always be trusted because sg_lists are just pointers to "struct
+ * page" values, and some memory e.g. carveout may not have valid
+ * "struct page" values. In particular, on ARM, carveout is
+ * generally reserved with memblock_remove(), which leaves the
+ * "struct page" entries uninitialized when SPARSEMEM is enabled.
+ * The effect of this is that page_to_pfn(pfn_to_page(pfn)) != pfn.
+ *
+ * There's more discussion on this mailing list thread:
+ * http://lists.linaro.org/pipermail/linaro-mm-sig/2012-August/002440.html
+ *
+ * If the heap this buffer comes from implements ->phys(), it's
+ * probably a contiguous allocator. If the phys() function is
+ * implemented, we'll use it to check sg_table->sgl[0]. If we find
+ * they don't agree, we'll assume phys() is more reliable and use
+ * that.
+ *
+ * Some heaps out there will implement phys() even though they are
+ * not for physically contiguous allocations (so the sg_table must
+ * be used). Therefore use the sg_table if the phys() and first
+ * sg_table entry match. This should be reliable because for most
+ * contiguous allocators, the sg_table should be a single span
+ * from 'start' to 'start+size'.
+ *
+ * Also, ion prints out an error message if the heap doesn't implement
+ * ->phys(), which we want to avoid, so only use ->phys() if the
+ * sg_table contains a single span and therefore could plausibly
+ * be a contiguous allocator.
+ */
+ if(!sg_next(psScatterList[i]))
+ {
+ ion_phys_addr_t sPhyAddr;
+ size_t sLength;
+
+ if(!ion_phys(psIonClient, psImportData->apsIonHandle[i],
+ &sPhyAddr, &sLength))
{
- if (i == 1)
+ BUG_ON(sLength & ~PAGE_MASK);
+
+ if(sg_phys(psScatterList[i]) != sPhyAddr)
{
- /* Pass 2: Get the page data */
- pasSysPhysAddr[ui32PageCount].uiAddr = sg_phys(psTemp);
+ psScatterList[i] = IMG_NULL;
+ ui32PageCount += sLength / PAGE_SIZE;
}
+ }
+ }
+
+ for(psTemp = psScatterList[i]; psTemp; psTemp = sg_next(psTemp))
+ {
+ IMG_UINT32 j;
+ for (j = 0; j < psTemp->length; j += PAGE_SIZE)
+ {
ui32PageCount++;
}
- psTemp = sg_next(psTemp);
}
}
- pvKernAddr = ion_map_kernel(psIonClient, psIonHandle);
- if (IS_ERR(pvKernAddr))
+ BUG_ON(ui32PageCount == 0);
+
+ psImportData->psSysPhysAddr = kmalloc(sizeof(IMG_SYS_PHYADDR) * ui32PageCount, GFP_KERNEL);
+ if (psImportData->psSysPhysAddr == NULL)
{
- pvKernAddr = IMG_NULL;
+ goto exitFailImport;
}
- psImportData->pvKernAddr = pvKernAddr;
+ for(i = 0, k = 0; i < ui32NumFDs; i++)
+ {
+ if(psScatterList[i])
+ {
+ for(psTemp = psScatterList[i]; psTemp; psTemp = sg_next(psTemp))
+ {
+ IMG_UINT32 j;
+ for (j = 0; j < psTemp->length; j += PAGE_SIZE)
+ {
+ psImportData->psSysPhysAddr[k].uiAddr = sg_phys(psTemp) + j;
+ k++;
+ }
+ }
+ }
+ else
+ {
+ ion_phys_addr_t sPhyAddr;
+ size_t sLength, j;
+
+ ion_phys(psIonClient, psImportData->apsIonHandle[i],
+ &sPhyAddr, &sLength);
+
+ for(j = 0; j < sLength; j += PAGE_SIZE)
+ {
+ psImportData->psSysPhysAddr[k].uiAddr = sPhyAddr + j;
+ k++;
+ }
+ }
+ }
- *ppvKernAddr = pvKernAddr;
*pui32PageCount = ui32PageCount;
- *ppasSysPhysAddr = pasSysPhysAddr;
+ *ppsSysPhysAddr = psImportData->psSysPhysAddr;
+
+#if defined(PDUMP)
+ if(ui32NumFDs == 1)
+ {
+ IMG_PVOID pvKernAddr0;
+
+ pvKernAddr0 = ion_map_kernel(psIonClient, psImportData->apsIonHandle[0]);
+ if (IS_ERR(pvKernAddr0))
+ {
+ pvKernAddr0 = IMG_NULL;
+ }
+
+ psImportData->pvKernAddr0 = pvKernAddr0;
+ *ppvKernAddr0 = pvKernAddr0;
+ }
+ else
+#endif /* defined(PDUMP) */
+ {
+ *ppvKernAddr0 = NULL;
+ }
+
*phPriv = psImportData;
+ *phUnique = (IMG_HANDLE)psImportData->psSysPhysAddr[0].uiAddr;
+
return PVRSRV_OK;
-exitFailAlloc:
- ion_unmap_dma(psIonClient, psIonHandle);
-exitFailMap:
- ion_free(psIonClient, psIonHandle);
exitFailImport:
+ for(i = 0; psImportData->apsIonHandle[i] != NULL; i++)
+ {
+ ion_free(psIonClient, psImportData->apsIonHandle[i]);
+ }
kfree(psImportData);
+exitFailKMallocImportData:
return eError;
}
-
IMG_VOID IonUnimportBufferAndReleasePhysAddr(IMG_HANDLE hPriv)
{
ION_IMPORT_DATA *psImportData = hPriv;
+ IMG_UINT32 i;
+
+#if defined(PDUMP)
+ if (psImportData->pvKernAddr0)
+ {
+ ion_unmap_kernel(psImportData->psIonClient, psImportData->apsIonHandle[0]);
+ }
+#endif /* defined(PDUMP) */
- ion_unmap_dma(psImportData->psIonClient, psImportData->psIonHandle);
- if (psImportData->pvKernAddr)
+ for(i = 0; i < psImportData->ui32NumIonHandles; i++)
{
- ion_unmap_kernel(psImportData->psIonClient, psImportData->psIonHandle);
+ ion_free(psImportData->psIonClient, psImportData->apsIonHandle[i]);
}
- ion_free(psImportData->psIonClient, psImportData->psIonHandle);
+
+ kfree(psImportData->psSysPhysAddr);
kfree(psImportData);
}
-#endif
+
+#endif /* defined(SUPPORT_ION) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/ion.h b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.h
index 1cf385dfd8e..042d3c4c49c 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/ion.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.h
@@ -42,33 +42,28 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef __IMG_LINUX_ION_H__
#define __IMG_LINUX_ION_H__
+#if defined(SUPPORT_ION)
+
#include <linux/ion.h>
-#if defined (CONFIG_ION_OMAP)
-#include <linux/omap_ion.h>
-#endif
-#if defined (SUPPORT_ION)
+
#include "img_types.h"
#include "servicesext.h"
-#endif
-
-int PVRSRVExportFDToIONHandles(int fd, struct ion_client **client,
- struct ion_handle **handles,
- unsigned int *num_handles);
-
-struct ion_handle *PVRSRVExportFDToIONHandle(int fd,
- struct ion_client **client);
-#if defined (SUPPORT_ION)
PVRSRV_ERROR IonInit(IMG_VOID);
+
IMG_VOID IonDeinit(IMG_VOID);
-PVRSRV_ERROR IonImportBufferAndAquirePhysAddr(IMG_HANDLE hIonDev,
- IMG_HANDLE hIonFD,
- IMG_UINT32 *pui32PageCount,
- IMG_SYS_PHYADDR **ppasSysPhysAddr,
- IMG_PVOID *ppvKernAddr,
- IMG_HANDLE *phPriv);
+PVRSRV_ERROR IonImportBufferAndAcquirePhysAddr(IMG_HANDLE hIonDev,
+ IMG_UINT32 ui32NumFDs,
+ IMG_INT32 *pi32BufferFDs,
+ IMG_UINT32 *pui32PageCount,
+ IMG_SYS_PHYADDR **ppsSysPhysAddr,
+ IMG_PVOID *ppvKernAddr0,
+ IMG_HANDLE *phPriv,
+ IMG_HANDLE *phUnique);
IMG_VOID IonUnimportBufferAndReleasePhysAddr(IMG_HANDLE hPriv);
-#endif
+
+#endif /* defined(SUPPORT_ION) */
+
#endif /* __IMG_LINUX_ION_H__ */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/linkage.h b/drivers/gpu/pvr/services4/srvkm/env/linux/linkage.h
index 55cd4f08436..55cd4f08436 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/linkage.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/linkage.h
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/lock.h b/drivers/gpu/pvr/services4/srvkm/env/linux/lock.h
index 11adcaaf21a..11adcaaf21a 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/lock.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/lock.h
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mm.c b/drivers/gpu/pvr/services4/srvkm/env/linux/mm.c
index 0815e464597..c5a9b9b0bf6 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/mm.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mm.c
@@ -89,12 +89,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "lists.h"
#endif
-/* If there is no explicit definition
- * for the minimum DMM alignment size,
- * then set it to "0" and let ION/DMM
- * set the minimum value. */
-#ifndef CONFIG_TILER_GRANULARITY
-#define CONFIG_TILER_GRANULARITY 0
+/* Decide whether or not DevMem allocs need __GFP_DMA32 */
+#ifndef SGX_FEATURE_36BIT_MMU
+# ifdef CONFIG_ZONE_DMA32
+# if defined CONFIG_X86_PAE || defined CONFIG_ARM_LPAE || defined CONFIG_64BIT
+# define PVR_USE_DMA32_FOR_DEVMEM_ALLOCS
+# endif
+# endif
#endif
/*
@@ -106,7 +107,7 @@ static atomic_t g_sPagePoolEntryCount = ATOMIC_INIT(0);
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
typedef enum {
- DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ DEBUG_MEM_ALLOC_TYPE_KMALLOC = 0,
DEBUG_MEM_ALLOC_TYPE_VMALLOC,
DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
DEBUG_MEM_ALLOC_TYPE_IOREMAP,
@@ -122,11 +123,11 @@ typedef enum {
typedef struct _DEBUG_MEM_ALLOC_REC
{
DEBUG_MEM_ALLOC_TYPE eAllocType;
- IMG_VOID *pvKey; /* Some unique value (private to the eAllocType) */
+ IMG_UINTPTR_T uiKey; /* Some unique value (private to the eAllocType) */
IMG_VOID *pvCpuVAddr;
- IMG_UINT32 ulCpuPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
IMG_VOID *pvPrivateData;
- IMG_UINT32 ui32Bytes;
+ IMG_SIZE_T uiBytes;
pid_t pid;
IMG_CHAR *pszFileName;
IMG_UINT32 ui32Line;
@@ -162,20 +163,20 @@ static IMG_UINT32 g_IOMemWaterMark;
static IMG_UINT32 g_IOMemHighWaterMark;
static IMG_VOID DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
- IMG_VOID *pvKey,
+ IMG_UINTPTR_T uiKey,
IMG_VOID *pvCpuVAddr,
- IMG_UINT32 ulCpuPAddr,
+ IMG_CPU_PHYADDR sCpuPAddr,
IMG_VOID *pvPrivateData,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uiBytes,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32Line);
-static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_UINTPTR_T uiKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
-static struct proc_dir_entry *g_SeqFileMemoryRecords;
+static struct pvr_proc_dir_entry *g_SeqFileMemoryRecords;
static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
@@ -209,12 +210,11 @@ static IMG_UINT32 g_LinuxMemAreaWaterMark;
static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
-static struct proc_dir_entry *g_SeqFileMemArea;
+static struct pvr_proc_dir_entry *g_SeqFileMemArea;
static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
static void* ProcSeqOff2ElementMemArea(struct seq_file *sfile, loff_t off);
-
#endif
#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
@@ -240,8 +240,8 @@ static LIST_HEAD(g_sPagePoolList);
static int g_iPagePoolMaxEntries;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
-static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
-static IMG_VOID UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_SIZE_T uiLength);
+static IMG_VOID UnreservePages(IMG_VOID *pvAddress, IMG_SIZE_T uiLength);
#endif
static LinuxMemArea *LinuxMemAreaStructAlloc(IMG_VOID);
@@ -266,19 +266,22 @@ CanFreeToPool(LinuxMemArea *psLinuxMemArea)
}
IMG_VOID *
-_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+_KMallocWrapper(IMG_SIZE_T uiByteSize, gfp_t uFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
IMG_VOID *pvRet;
- pvRet = kmalloc(ui32ByteSize, uFlags);
+ pvRet = kmalloc(uiByteSize, uFlags);
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
if (pvRet)
{
+ IMG_CPU_PHYADDR sCpuPAddr;
+ sCpuPAddr.uiAddr = 0;
+
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ (IMG_UINTPTR_T)pvRet,
pvRet,
- pvRet,
- 0,
+ sCpuPAddr,
NULL,
- ui32ByteSize,
+ uiByteSize,
pszFileName,
ui32Line
);
@@ -295,7 +298,11 @@ IMG_VOID
_KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+ DebugMemAllocRecordRemove(
+ DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ (IMG_UINTPTR_T)pvCpuVAddr,
+ pszFileName,
+ ui32Line);
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
PVR_UNREFERENCED_PARAMETER(ui32Line);
@@ -307,33 +314,33 @@ _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
static IMG_VOID
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
- IMG_VOID *pvKey,
+ IMG_UINTPTR_T uiKey,
IMG_VOID *pvCpuVAddr,
- IMG_UINT32 ulCpuPAddr,
+ IMG_CPU_PHYADDR sCpuPAddr,
IMG_VOID *pvPrivateData,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uiBytes,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32Line)
{
DEBUG_MEM_ALLOC_REC *psRecord;
- LinuxLockMutex(&g_sDebugMutex);
+ LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
psRecord = kmalloc(sizeof(DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
psRecord->eAllocType = eAllocType;
- psRecord->pvKey = pvKey;
+ psRecord->uiKey = uiKey;
psRecord->pvCpuVAddr = pvCpuVAddr;
- psRecord->ulCpuPAddr = ulCpuPAddr;
+ psRecord->sCpuPAddr.uiAddr = sCpuPAddr.uiAddr;
psRecord->pvPrivateData = pvPrivateData;
psRecord->pid = OSGetCurrentProcessIDKM();
- psRecord->ui32Bytes = ui32Bytes;
+ psRecord->uiBytes = uiBytes;
psRecord->pszFileName = pszFileName;
psRecord->ui32Line = ui32Line;
List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
- g_WaterMarkData[eAllocType] += ui32Bytes;
+ g_WaterMarkData[eAllocType] += uiBytes;
if (g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
{
g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
@@ -344,20 +351,20 @@ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
{
- IMG_UINT32 ui32SysRAMTrueWaterMark;
+ IMG_SIZE_T uSysRAMTrueWaterMark;
- g_SysRAMWaterMark += ui32Bytes;
- ui32SysRAMTrueWaterMark = SysRAMTrueWaterMark();
+ g_SysRAMWaterMark += uiBytes;
+ uSysRAMTrueWaterMark = SysRAMTrueWaterMark();
- if (ui32SysRAMTrueWaterMark > g_SysRAMHighWaterMark)
+ if (uSysRAMTrueWaterMark > g_SysRAMHighWaterMark)
{
- g_SysRAMHighWaterMark = ui32SysRAMTrueWaterMark;
+ g_SysRAMHighWaterMark = uSysRAMTrueWaterMark;
}
}
else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
{
- g_IOMemWaterMark += ui32Bytes;
+ g_IOMemWaterMark += uiBytes;
if (g_IOMemWaterMark > g_IOMemHighWaterMark)
{
g_IOMemHighWaterMark = g_IOMemWaterMark;
@@ -371,28 +378,28 @@ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrentRecord, va_list va)
{
DEBUG_MEM_ALLOC_TYPE eAllocType;
- IMG_VOID *pvKey;
+ IMG_UINTPTR_T uiKey;
eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
- pvKey = va_arg(va, IMG_VOID*);
+ uiKey = va_arg(va, IMG_UINTPTR_T);
if (psCurrentRecord->eAllocType == eAllocType
- && psCurrentRecord->pvKey == pvKey)
+ && psCurrentRecord->uiKey == uiKey)
{
eAllocType = psCurrentRecord->eAllocType;
- g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
+ g_WaterMarkData[eAllocType] -= psCurrentRecord->uiBytes;
if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
{
- g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
+ g_SysRAMWaterMark -= psCurrentRecord->uiBytes;
}
else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
{
- g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
+ g_IOMemWaterMark -= psCurrentRecord->uiBytes;
}
List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
@@ -408,20 +415,20 @@ static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrent
static IMG_VOID
-DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_UINTPTR_T uiKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
/* DEBUG_MEM_ALLOC_REC **ppsCurrentRecord;*/
- LinuxLockMutex(&g_sDebugMutex);
+ LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
/* Locate the corresponding allocation entry */
if (!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
DebugMemAllocRecordRemove_AnyVaCb,
eAllocType,
- pvKey))
+ uiKey))
{
- PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with pvKey=%p (called from %s, line %d\n",
- __FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with uiKey=" UINTPTR_FMT " (called from %s, line %d\n",
+ __FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), uiKey,
pszFileName, ui32Line));
}
@@ -439,8 +446,9 @@ DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
"IOREMAP",
"IO",
"KMEM_CACHE_ALLOC",
+ "ION",
#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
- "VMAP"
+ "VMAP",
#endif
};
return apszDebugMemoryRecordTypes[eAllocType];
@@ -478,31 +486,43 @@ AllocFlagsToPGProt(pgprot_t *pPGProtFlags, IMG_UINT32 ui32AllocFlags)
}
IMG_VOID *
-_VMallocWrapper(IMG_UINT32 ui32Bytes,
+_VMallocWrapper(IMG_SIZE_T uiBytes,
IMG_UINT32 ui32AllocFlags,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32Line)
{
pgprot_t PGProtFlags;
IMG_VOID *pvRet;
+ gfp_t gfp_mask;
if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags))
{
return NULL;
}
+ gfp_mask = GFP_KERNEL;
+
+#if defined(PVR_USE_DMA32_FOR_DEVMEM_ALLOCS)
+ gfp_mask |= __GFP_DMA32;
+#else
+ gfp_mask |= __GFP_HIGHMEM;
+#endif
+
/* Allocate virtually contiguous pages */
- pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+ pvRet = __vmalloc(uiBytes, gfp_mask, PGProtFlags);
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
if (pvRet)
{
+ IMG_CPU_PHYADDR sCpuPAddr;
+ sCpuPAddr.uiAddr = 0;
+
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ (IMG_UINTPTR_T)pvRet,
pvRet,
- pvRet,
- 0,
+ sCpuPAddr,
NULL,
- PAGE_ALIGN(ui32Bytes),
+ PAGE_ALIGN(uiBytes),
pszFileName,
ui32Line
);
@@ -520,7 +540,11 @@ IMG_VOID
_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+ DebugMemAllocRecordRemove(
+ DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ (IMG_UINTPTR_T)pvCpuVAddr,
+ pszFileName,
+ ui32Line);
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
PVR_UNREFERENCED_PARAMETER(ui32Line);
@@ -546,10 +570,13 @@ _VMapWrapper(struct page **ppsPageList, IMG_UINT32 ui32NumPages, IMG_UINT32 ui32
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
if (pvRet)
{
+ IMG_CPU_PHYADDR sCpuPAddr;
+ sCpuPAddr.uiAddr = 0;
+
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMAP,
+ (IMG_UINTPTR_T)pvRet,
pvRet,
- pvRet,
- 0,
+ sCpuPAddr,
NULL,
PAGES_TO_BYTES(ui32NumPages),
pszFileName,
@@ -565,9 +592,9 @@ _VMapWrapper(struct page **ppsPageList, IMG_UINT32 ui32NumPages, IMG_UINT32 ui32
}
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#define VMapWrapper(ppsPageList, uBytes, ui32AllocFlags) _VMapWrapper(ppsPageList, uBytes, ui32AllocFlags, __FILE__, __LINE__)
#else
-#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, NULL, 0)
+#define VMapWrapper(ppsPageList, uBytes, ui32AllocFlags) _VMapWrapper(ppsPageList, uBytes, ui32AllocFlags, NULL, 0)
#endif
@@ -575,7 +602,8 @@ static IMG_VOID
_VUnmapWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMAP, pvCpuVAddr, pszFileName, ui32Line);
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMAP,
+ (IMG_UINTPTR_T)pvCpuVAddr, pszFileName, ui32Line);
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
PVR_UNREFERENCED_PARAMETER(ui32Line);
@@ -596,7 +624,11 @@ IMG_VOID
_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
+ DebugMemAllocRecordRemove(
+ DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ (IMG_UINTPTR_T)pvObject,
+ pszFileName,
+ ui32Line);
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
PVR_UNREFERENCED_PARAMETER(ui32Line);
@@ -634,13 +666,22 @@ static struct page *
AllocPageFromLinux(void)
{
struct page *psPage;
+ gfp_t gfp_mask;
- psPage = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
- if (!psPage)
- {
- return NULL;
+ gfp_mask = GFP_KERNEL;
- }
+#if defined(PVR_USE_DMA32_FOR_DEVMEM_ALLOCS)
+ gfp_mask |= __GFP_DMA32;
+#else
+ gfp_mask |= __GFP_HIGHMEM;
+#endif
+
+ psPage = alloc_pages(gfp_mask, 0);
+ if (!psPage)
+ {
+ return NULL;
+
+ }
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
/* Reserve those pages to allow them to be re-mapped to user space */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
@@ -812,7 +853,7 @@ FreePagePool(IMG_VOID)
PagePoolLock();
#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
- PVR_DPF((PVR_DBG_MESSAGE,"%s: Freeing %d pages from pool", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+ PVR_TRACE(("%s: Freeing %d pages from pool", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
#else
PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
PVR_ASSERT(list_empty(&g_sPagePoolList));
@@ -848,8 +889,8 @@ ShrinkPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkContr
{
LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
- PVR_DPF((PVR_DBG_MESSAGE,"%s: Number to scan: %ld", __FUNCTION__, uNumToScan));
- PVR_DPF((PVR_DBG_MESSAGE,"%s: Pages in pool before scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+ PVR_TRACE(("%s: Number to scan: %ld", __FUNCTION__, uNumToScan));
+ PVR_TRACE(("%s: Pages in pool before scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
if (!PagePoolTrylock())
{
@@ -877,7 +918,7 @@ ShrinkPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkContr
PagePoolUnlock();
- PVR_DPF((PVR_DBG_MESSAGE,"%s: Pages in pool after scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+ PVR_TRACE(("%s: Pages in pool after scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
}
return atomic_read(&g_sPagePoolEntryCount);
@@ -893,6 +934,10 @@ AllocPages(IMG_UINT32 ui32AreaFlags, struct page ***pppsPageList, IMG_HANDLE *ph
PVRSRV_ERROR eError;
IMG_BOOL bFromPagePool = IMG_FALSE;
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ IMG_CPU_PHYADDR sCpuPAddr;
+#endif
+
eError = OSAllocMem(0, sizeof(*ppsPageList) * ui32NumPages, (IMG_VOID **)&ppsPageList, &hBlockPageList,
"Array of pages");
if (eError != PVRSRV_OK)
@@ -915,10 +960,12 @@ AllocPages(IMG_UINT32 ui32AreaFlags, struct page ***pppsPageList, IMG_HANDLE *ph
*phBlockPageList = hBlockPageList;
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ sCpuPAddr.uiAddr = 0;
+
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
- ppsPageList,
- 0,
+ (IMG_UINTPTR_T)ppsPageList,
0,
+ sCpuPAddr,
NULL,
PAGES_TO_BYTES(ui32NumPages),
"unknown",
@@ -951,7 +998,11 @@ FreePages(IMG_BOOL bToPagePool, struct page **ppsPageList, IMG_HANDLE hBlockPage
}
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, ppsPageList, __FILE__, __LINE__);
+ DebugMemAllocRecordRemove(
+ DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ (IMG_UINTPTR_T)ppsPageList,
+ __FILE__,
+ __LINE__);
#endif
(IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList);
@@ -959,7 +1010,7 @@ FreePages(IMG_BOOL bToPagePool, struct page **ppsPageList, IMG_HANDLE hBlockPage
LinuxMemArea *
-NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+NewVMallocLinuxMemArea(IMG_SIZE_T uBytes, IMG_UINT32 ui32AreaFlags)
{
LinuxMemArea *psLinuxMemArea = NULL;
IMG_VOID *pvCpuVAddr;
@@ -977,7 +1028,7 @@ NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
}
#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
- ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+ ui32NumPages = RANGE_TO_PAGES(uBytes);
if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
{
@@ -986,7 +1037,7 @@ NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
pvCpuVAddr = VMapWrapper(ppsPageList, ui32NumPages, ui32AreaFlags);
#else /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
- pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
+ pvCpuVAddr = VMallocWrapper(uBytes, ui32AreaFlags);
if (!pvCpuVAddr)
{
goto failed;
@@ -994,7 +1045,7 @@ NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
/* PG_reserved was deprecated in linux-2.6.15 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
/* Reserve those pages to allow them to be re-mapped to user space */
- ReservePages(pvCpuVAddr, ui32Bytes);
+ ReservePages(pvCpuVAddr, uBytes);
#endif
#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
@@ -1004,7 +1055,7 @@ NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
psLinuxMemArea->uData.sVmalloc.ppsPageList = ppsPageList;
psLinuxMemArea->uData.sVmalloc.hBlockPageList = hBlockPageList;
#endif
- psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->uiByteSize = uBytes;
psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
@@ -1029,7 +1080,7 @@ NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
*/
if (AreaIsUncached(ui32AreaFlags) && !bFromPagePool)
{
- OSInvalidateCPUCacheRangeKM(psLinuxMemArea, 0, pvCpuVAddr, ui32Bytes);
+ OSInvalidateCPUCacheRangeKM(psLinuxMemArea, 0, pvCpuVAddr, uBytes);
}
return psLinuxMemArea;
@@ -1074,7 +1125,7 @@ FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
VUnmapWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
- ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->uiByteSize);
ppsPageList = psLinuxMemArea->uData.sVmalloc.ppsPageList;
hBlockPageList = psLinuxMemArea->uData.sVmalloc.hBlockPageList;
@@ -1083,7 +1134,7 @@ FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
/* PG_reserved was deprecated in linux-2.6.15 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
- psLinuxMemArea->ui32ByteSize);
+ psLinuxMemArea->uiByteSize);
#endif
VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
@@ -1097,10 +1148,10 @@ FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
/* Reserve pages of memory in order that they're not automatically
deallocated after the last user reference dies. */
static IMG_VOID
-ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
+ReservePages(IMG_VOID *pvAddress, IMG_SIZE_T uLength)
{
IMG_VOID *pvPage;
- IMG_VOID *pvEnd = pvAddress + ui32Length;
+ IMG_VOID *pvEnd = pvAddress + uLength;
for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE)
{
@@ -1115,10 +1166,10 @@ ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
/* Un-reserve pages of memory in order that they can be freed. */
static IMG_VOID
-UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
+UnreservePages(IMG_VOID *pvAddress, IMG_SIZE_T uLength)
{
IMG_VOID *pvPage;
- IMG_VOID *pvEnd = pvAddress + ui32Length;
+ IMG_VOID *pvEnd = pvAddress + uLength;
for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE)
{
@@ -1134,7 +1185,7 @@ UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
IMG_VOID *
_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uBytes,
IMG_UINT32 ui32MappingFlags,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32Line)
@@ -1144,13 +1195,13 @@ _IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
switch (ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
{
case PVRSRV_HAP_CACHED:
- pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes);
+ pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, uBytes);
break;
case PVRSRV_HAP_WRITECOMBINE:
- pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes);
+ pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, uBytes);
break;
case PVRSRV_HAP_UNCACHED:
- pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes);
+ pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, uBytes);
break;
default:
PVR_DPF((PVR_DBG_ERROR, "IORemapWrapper: unknown mapping flags"));
@@ -1161,11 +1212,11 @@ _IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
if (pvIORemapCookie)
{
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ (IMG_UINTPTR_T)pvIORemapCookie,
pvIORemapCookie,
- pvIORemapCookie,
- BasePAddr.uiAddr,
+ BasePAddr,
NULL,
- ui32Bytes,
+ uBytes,
pszFileName,
ui32Line
);
@@ -1183,7 +1234,11 @@ IMG_VOID
_IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IOREMAP, pvIORemapCookie, pszFileName, ui32Line);
+ DebugMemAllocRecordRemove(
+ DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ (IMG_UINTPTR_T)pvIORemapCookie,
+ pszFileName,
+ ui32Line);
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
PVR_UNREFERENCED_PARAMETER(ui32Line);
@@ -1194,7 +1249,7 @@ _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui3
LinuxMemArea *
NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uBytes,
IMG_UINT32 ui32AreaFlags)
{
LinuxMemArea *psLinuxMemArea;
@@ -1206,7 +1261,7 @@ NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
return NULL;
}
- pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
+ pvIORemapCookie = IORemapWrapper(BasePAddr, uBytes, ui32AreaFlags);
if (!pvIORemapCookie)
{
LinuxMemAreaStructFree(psLinuxMemArea);
@@ -1216,7 +1271,7 @@ NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
- psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->uiByteSize = uBytes;
psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
@@ -1255,11 +1310,11 @@ FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea)
* using memory wrapping, which ends up creating an external KV memory area.
*/
static IMG_BOOL
-TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig)
+TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_SIZE_T uBytes, IMG_BOOL bPhysContig)
{
IMG_UINT32 ui32;
IMG_UINT32 ui32AddrChk;
- IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+ IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(uBytes);
/*
* If bPhysContig is IMG_TRUE, we must assume psSysPhysAddr points
@@ -1296,7 +1351,7 @@ TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32By
}
#endif
-LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags)
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_SIZE_T uBytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags)
{
LinuxMemArea *psLinuxMemArea;
@@ -1310,7 +1365,7 @@ LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *p
psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
psLinuxMemArea->uData.sExternalKV.bPhysContig =
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
- (bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, ui32Bytes, bPhysContig))
+ (bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, uBytes, bPhysContig))
? IMG_TRUE : IMG_FALSE;
#else
bPhysContig;
@@ -1323,7 +1378,7 @@ LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *p
{
psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
}
- psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->uiByteSize = uBytes;
psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
@@ -1350,7 +1405,7 @@ FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea)
LinuxMemArea *
NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uBytes,
IMG_UINT32 ui32AreaFlags)
{
LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
@@ -1362,17 +1417,17 @@ NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
/* Nothing to activly do. We just keep a record of the physical range. */
psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
- psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->uiByteSize = uBytes;
psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
- (IMG_VOID *)BasePAddr.uiAddr,
- 0,
BasePAddr.uiAddr,
+ 0,
+ BasePAddr,
NULL,
- ui32Bytes,
+ uBytes,
"unknown",
0
);
@@ -1397,7 +1452,9 @@ FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
- (IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__);
+ psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr,
+ __FILE__,
+ __LINE__);
#endif
/* Nothing more to do than free the LinuxMemArea struct */
@@ -1407,7 +1464,7 @@ FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
LinuxMemArea *
-NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+NewAllocPagesLinuxMemArea(IMG_SIZE_T uBytes, IMG_UINT32 ui32AreaFlags)
{
LinuxMemArea *psLinuxMemArea;
IMG_UINT32 ui32NumPages;
@@ -1421,7 +1478,7 @@ NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
goto failed_area_alloc;
}
- ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+ ui32NumPages = RANGE_TO_PAGES(uBytes);
if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
{
@@ -1431,7 +1488,7 @@ NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
psLinuxMemArea->uData.sPageList.ppsPageList = ppsPageList;
psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
- psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->uiByteSize = uBytes;
psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
@@ -1467,7 +1524,7 @@ FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
#endif
- ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->uiByteSize);
ppsPageList = psLinuxMemArea->uData.sPageList.ppsPageList;
hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
@@ -1476,315 +1533,29 @@ FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
LinuxMemAreaStructFree(psLinuxMemArea);
}
-#if defined(CONFIG_ION_OMAP)
-
-#include "env_perproc.h"
-
-#include <linux/ion.h>
-#include <linux/omap_ion.h>
-#include <linux/scatterlist.h>
-
-extern struct ion_client *gpsIONClient;
-
-LinuxMemArea *
-NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
- IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength)
-{
- const IMG_UINT32 ui32AllocDataLen =
- offsetof(struct omap_ion_tiler_alloc_data, handle);
- struct omap_ion_tiler_alloc_data asAllocData[PVRSRV_MAX_NUMBER_OF_MM_BUFFER_PLANES];
- u32 *pu32PageAddrs[PVRSRV_MAX_NUMBER_OF_MM_BUFFER_PLANES] = { NULL, NULL, NULL};
- IMG_UINT32 i, j, ui32NumHandlesPerFd;
- IMG_BYTE *pbPrivData = pvPrivData;
- IMG_CPU_PHYADDR *pCPUPhysAddrs;
- IMG_UINT32 iNumPages[PVRSRV_MAX_NUMBER_OF_MM_BUFFER_PLANES] = { 0, 0, 0};
- LinuxMemArea *psLinuxMemArea;
- IMG_UINT32 ui32ProcID;
- IMG_UINT32 ui32TotalPagesSizeInBytes = 0, ui32TotalPages = 0;
-
- psLinuxMemArea = LinuxMemAreaStructAlloc();
- if (!psLinuxMemArea)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate LinuxMemArea struct", __func__));
- goto err_out;
- }
-
- /* Depending on the UM config, userspace might give us info for
- * one, two or three ION allocations. Divide the total size of data we
- * were given by this ui32AllocDataLen, and check it's 1 or 2.
- * Otherwise abort.
- */
- BUG_ON(ui32PrivDataLength != ui32AllocDataLen &&
- ui32PrivDataLength != ui32AllocDataLen * 2 &&
- ui32PrivDataLength != ui32AllocDataLen * 3);
- /* This is bad !- change this logic to pass in the size or
- * use uniformed API */
- ui32NumHandlesPerFd = ui32PrivDataLength / ui32AllocDataLen;
-
- ui32ProcID = OSGetCurrentProcessIDKM();
-
- memset(asAllocData, 0x00, sizeof(asAllocData));
-
- /* We do not care about what the first (Y) buffer offset would be,
- * but we do care for the UV buffers to be co-aligned with Y
- * This for SGX to find the UV offset solely based on the height
- * and stride of the YUV buffer.This is very important for OMAP4470
- * and later chipsets, where SGX version is 544. 544 and later use
- * non-shader based YUV to RGB conversion unit that require
- * contiguous GPU virtual space */
- for(i = 0; i < ui32NumHandlesPerFd; i++)
- {
- memcpy(&asAllocData[i], &pbPrivData[i * ui32AllocDataLen], ui32AllocDataLen);
- asAllocData[i].token = ui32ProcID;
-
-#ifndef SGX_DISABLE_DMM_OFFSET_BUFFER_ALLOCATIONS
- if(i == 0)
- {
- /* Tiler API says:
- * Allocate first buffer with the required alignment
- * and an offset of 0 ... */
- asAllocData[i].out_align = CONFIG_TILER_GRANULARITY;
- asAllocData[i].offset = 0;
- }
- else
- { /* .. Then for the second buffer, use the offset from the first
- * buffer with alignment of PAGE_SIZE */
- asAllocData[i].out_align = PAGE_SIZE;
- asAllocData[i].offset = asAllocData[0].offset;
- }
-#else
- asAllocData[i].offset = 0;
- asAllocData[i].out_align = PAGE_SIZE;
-#endif
-
- if(asAllocData[i].fmt == TILER_PIXEL_FMT_PAGE)
- {
- /* 1D DMM Buffers */
- struct scatterlist *sg, *sglist;
- IMG_UINT32 ui32Num1dPages;
-
- asAllocData[i].handle = ion_alloc (gpsIONClient,
- ui32Bytes,
- PAGE_SIZE, (1 << OMAP_ION_HEAP_SYSTEM));
-
- if (asAllocData[i].handle == NULL)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate via ion_alloc",
- __func__));
- goto err_free;
- }
-
- sglist = ion_map_dma (gpsIONClient, asAllocData[i].handle);
- if (sglist == NULL)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: Failed to compute pages",
- __func__));
- goto err_free;
- }
-
- ui32Num1dPages = (ui32Bytes >> PAGE_SHIFT);
- pu32PageAddrs[i] = kmalloc (sizeof(u32) * ui32Num1dPages, GFP_KERNEL);
- if (pu32PageAddrs[i] == NULL)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate page array",
- __func__));
- goto err_free;
- }
-
- for_each_sg (sglist, sg, ui32Num1dPages, j)
- {
- pu32PageAddrs[i][j] = sg_phys (sg);
- }
-
- iNumPages[i] = ui32Num1dPages;
- }
- else /* 2D DMM Buffers */
- {
- if (omap_ion_tiler_alloc(gpsIONClient, &asAllocData[i]) < 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate via ion_tiler",
- __func__));
- goto err_free;
- }
-
- if (omap_tiler_pages(gpsIONClient, asAllocData[i].handle, &iNumPages[i],
- &pu32PageAddrs[i]) < 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: Failed to compute tiler pages",
- __func__));
- goto err_free;
- }
- }
- }
-
- /* Basic sanity check on plane co-alignment */
- if((ui32NumHandlesPerFd > 1) &&
- (asAllocData[0].offset != asAllocData[1].offset))
- {
- pr_err("%s: Y and UV offsets do not match for tiler handles "
- "%p,%p: %d != %d \n "
- "Expect issues with SGX544xx and later chipsets\n",
- __func__, asAllocData[0].handle, asAllocData[1].handle,
- (int)asAllocData[0].offset, (int)asAllocData[1].offset);
- }
-
- /* Assume the user-allocator has already done the tiler math and that the
- * number of tiler pages allocated matches any other allocation type.
- */
- for(i = 0; i < ui32NumHandlesPerFd; i++)
- {
- ui32TotalPages += iNumPages[i];
- }
-
- BUG_ON(ui32Bytes != (ui32TotalPages * PAGE_SIZE));
- BUG_ON(sizeof(IMG_CPU_PHYADDR) != sizeof(int));
-
- /* Glue the page lists together */
- pCPUPhysAddrs = vmalloc(sizeof(IMG_CPU_PHYADDR) * ui32TotalPages);
- if (!pCPUPhysAddrs)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate page list", __func__));
- goto err_free;
- }
-
- j = 0;
- for(i = 0; i < ui32NumHandlesPerFd; i++)
- {
- IMG_UINT32 ui32PageIndx;
- for(ui32PageIndx = 0; ui32PageIndx < iNumPages[i]; ui32PageIndx++)
- {
- pCPUPhysAddrs[j++].uiAddr = pu32PageAddrs[i][ui32PageIndx];
- }
-
- psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i] =
- asAllocData[i].handle;
- psLinuxMemArea->uData.sIONTilerAlloc.planeOffsets[i] =
- ui32TotalPagesSizeInBytes + asAllocData[i].offset;
- /* Add the number of pages this plane consists of */
- ui32TotalPagesSizeInBytes += (iNumPages[i] * PAGE_SIZE);
- }
-
- psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ION;
- psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs = pCPUPhysAddrs;
- psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes =
- ui32NumHandlesPerFd;
- psLinuxMemArea->ui32ByteSize = ui32TotalPagesSizeInBytes;
- psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
- INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
-
- /* We defer the cache flush to the first user mapping of this memory */
- psLinuxMemArea->bNeedsCacheInvalidate = AreaIsUncached(ui32AreaFlags);
-
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ION,
- asAllocData[0].handle,
- 0,
- 0,
- NULL,
- PAGE_ALIGN(ui32Bytes),
- "unknown",
- 0
- );
-#endif
-
-#if defined(DEBUG_LINUX_MEM_AREAS)
- DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
-#endif
-
-err_out:
- return psLinuxMemArea;
-
-err_free:
- LinuxMemAreaStructFree(psLinuxMemArea);
- psLinuxMemArea = IMG_NULL;
- goto err_out;
-}
-
-IMG_INT32
-GetIONLinuxMemAreaInfo(LinuxMemArea *psLinuxMemArea, IMG_UINT32* pui32AddressOffsets,
- IMG_UINT32* ui32NumAddrOffsets)
-{
- IMG_UINT32 i;
-
- if(!ui32NumAddrOffsets)
- return -1;
-
- if(*ui32NumAddrOffsets < psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes)
- {
- *ui32NumAddrOffsets = psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes;
- return -1;
- }
-
- if(!pui32AddressOffsets)
- return -1;
-
- for(i = 0; i < psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes; i++)
- {
- if(psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i])
- pui32AddressOffsets[i] =
- psLinuxMemArea->uData.sIONTilerAlloc.planeOffsets[i];
- }
-
- *ui32NumAddrOffsets = psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes;
-
- return psLinuxMemArea->ui32ByteSize;
-}
-
-IMG_VOID
-FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea)
-{
- IMG_UINT32 i;
-
-#if defined(DEBUG_LINUX_MEM_AREAS)
- DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
-#endif
-
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ION,
- psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[0],
- __FILE__, __LINE__);
-#endif
-
- for(i = 0; i < psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes; i++)
- {
- if (!psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i])
- break;
- ion_free(gpsIONClient, psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i]);
- psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i] = IMG_NULL;
- }
-
- /* free copy of page list, originals are freed by ion_free */
- vfree(psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs);
- psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs = IMG_NULL;
-
- LinuxMemAreaStructFree(psLinuxMemArea);
-}
-
-#endif /* defined(CONFIG_ION_OMAP) */
-
struct page*
LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
- IMG_UINT32 ui32ByteOffset)
+ IMG_UINTPTR_T uByteOffset)
{
- IMG_UINT32 ui32PageIndex;
+ IMG_UINTPTR_T uPageIndex;
IMG_CHAR *pui8Addr;
switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_ALLOC_PAGES:
- ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
- return psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageIndex];
+ uPageIndex = PHYS_TO_PFN(uByteOffset);
+ return psLinuxMemArea->uData.sPageList.ppsPageList[uPageIndex];
case LINUX_MEM_AREA_VMALLOC:
pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
- pui8Addr += ui32ByteOffset;
+ pui8Addr += uByteOffset;
return vmalloc_to_page(pui8Addr);
case LINUX_MEM_AREA_SUB_ALLOC:
/* PRQA S 3670 3 */ /* ignore recursive warning */
return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
- psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
- + ui32ByteOffset);
+ psLinuxMemArea->uData.sSubAlloc.uiByteOffset
+ + uByteOffset);
default:
PVR_DPF((PVR_DBG_ERROR,
"%s: Unsupported request for struct page from LinuxMemArea with type=%s",
@@ -1829,14 +1600,19 @@ _KMemCacheAllocWrapper(LinuxKMemCache *psCache,
IMG_UINT32 ui32Line)
{
IMG_VOID *pvRet;
-
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ IMG_CPU_PHYADDR sCpuPAddr;
+#endif
+
pvRet = kmem_cache_zalloc(psCache, Flags);
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ sCpuPAddr.uiAddr = 0;
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ (IMG_UINTPTR_T)pvRet,
pvRet,
- pvRet,
- 0,
+ sCpuPAddr,
psCache,
kmem_cache_size(psCache),
pszFileName,
@@ -1853,12 +1629,12 @@ _KMemCacheAllocWrapper(LinuxKMemCache *psCache,
LinuxMemArea *
NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
- IMG_UINT32 ui32ByteOffset,
- IMG_UINT32 ui32Bytes)
+ IMG_UINTPTR_T uiByteOffset,
+ IMG_SIZE_T uBytes)
{
LinuxMemArea *psLinuxMemArea;
- PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize);
+ PVR_ASSERT((uiByteOffset + uBytes) <= psParentLinuxMemArea->uiByteSize);
psLinuxMemArea = LinuxMemAreaStructAlloc();
if (!psLinuxMemArea)
@@ -1868,8 +1644,8 @@ NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea = psParentLinuxMemArea;
- psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset;
- psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->uData.sSubAlloc.uiByteOffset = uiByteOffset;
+ psLinuxMemArea->uiByteSize = uBytes;
psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
psLinuxMemArea->bNeedsCacheInvalidate = psParentLinuxMemArea->bNeedsCacheInvalidate;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
@@ -1949,9 +1725,6 @@ LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
case LINUX_MEM_AREA_SUB_ALLOC:
FreeSubLinuxMemArea(psLinuxMemArea);
break;
- case LINUX_MEM_AREA_ION:
- FreeIONLinuxMemArea(psLinuxMemArea);
- break;
default:
PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
__FUNCTION__, psLinuxMemArea->eAreaType));
@@ -1967,11 +1740,11 @@ DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
const IMG_CHAR *pi8FlagsString;
- LinuxLockMutex(&g_sDebugMutex);
+ LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
- g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
+ g_LinuxMemAreaWaterMark += psLinuxMemArea->uiByteSize;
if (g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
{
g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
@@ -2036,7 +1809,7 @@ DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea)
{
DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
- LinuxLockMutex(&g_sDebugMutex);
+ LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
MatchLinuxMemArea_AnyVaCb,
psLinuxMemArea);
@@ -2053,11 +1826,11 @@ DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea)
{
DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
- LinuxLockMutex(&g_sDebugMutex);
+ LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
- g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
+ g_LinuxMemAreaWaterMark -= psLinuxMemArea->uiByteSize;
}
g_LinuxMemAreaCount--;
@@ -2101,7 +1874,7 @@ LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
{
return NULL;
}
- return pAddr + psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+ return pAddr + psLinuxMemArea->uData.sSubAlloc.uiByteOffset;
}
default:
return NULL;
@@ -2110,7 +1883,7 @@ LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
IMG_CPU_PHYADDR
-LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
+LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINTPTR_T uiByteOffset)
{
IMG_CPU_PHYADDR CpuPAddr;
@@ -2121,7 +1894,7 @@ LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
case LINUX_MEM_AREA_IOREMAP:
{
CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
- CpuPAddr.uiAddr += ui32ByteOffset;
+ CpuPAddr.uiAddr += uiByteOffset;
break;
}
case LINUX_MEM_AREA_EXTERNAL_KV:
@@ -2129,22 +1902,22 @@ LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
{
CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr);
- CpuPAddr.uiAddr += ui32ByteOffset;
+ CpuPAddr.uiAddr += uiByteOffset;
}
else
{
- IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
- IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageIndex];
+ IMG_UINTPTR_T uiPageIndex = PHYS_TO_PFN(uiByteOffset);
+ IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[uiPageIndex];
CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
- CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(uiByteOffset);
}
break;
}
case LINUX_MEM_AREA_IO:
{
CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
- CpuPAddr.uiAddr += ui32ByteOffset;
+ CpuPAddr.uiAddr += uiByteOffset;
break;
}
case LINUX_MEM_AREA_VMALLOC:
@@ -2152,32 +1925,25 @@ LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
IMG_CHAR *pCpuVAddr;
pCpuVAddr =
(IMG_CHAR *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
- pCpuVAddr += ui32ByteOffset;
+ pCpuVAddr += uiByteOffset;
CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
break;
}
- case LINUX_MEM_AREA_ION:
- {
- IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
- CpuPAddr = psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs[ui32PageIndex];
- CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
- break;
- }
case LINUX_MEM_AREA_ALLOC_PAGES:
{
struct page *page;
- IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
- page = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageIndex];
+ IMG_UINTPTR_T uiPageIndex = PHYS_TO_PFN(uiByteOffset);
+ page = psLinuxMemArea->uData.sPageList.ppsPageList[uiPageIndex];
CpuPAddr.uiAddr = page_to_phys(page);
- CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(uiByteOffset);
break;
}
case LINUX_MEM_AREA_SUB_ALLOC:
{
CpuPAddr =
OSMemHandleToCpuPAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
- psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
- + ui32ByteOffset);
+ psLinuxMemArea->uData.sSubAlloc.uiByteOffset
+ + uiByteOffset);
break;
}
default:
@@ -2205,7 +1971,6 @@ LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
case LINUX_MEM_AREA_EXTERNAL_KV:
return psLinuxMemArea->uData.sExternalKV.bPhysContig;
- case LINUX_MEM_AREA_ION:
case LINUX_MEM_AREA_VMALLOC:
case LINUX_MEM_AREA_ALLOC_PAGES:
return IMG_FALSE;
@@ -2243,8 +2008,6 @@ LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
return "LINUX_MEM_AREA_SUB_ALLOC";
case LINUX_MEM_AREA_ALLOC_PAGES:
return "LINUX_MEM_AREA_ALLOC_PAGES";
- case LINUX_MEM_AREA_ION:
- return "LINUX_MEM_AREA_ION";
default:
PVR_ASSERT(0);
}
@@ -2258,7 +2021,7 @@ static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start)
{
if (start)
{
- LinuxLockMutex(&g_sDebugMutex);
+ LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
}
else
{
@@ -2350,14 +2113,14 @@ static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
seq_printf(sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
- "%8p %-24s %8p %08x %-8d %-5u %08x=(%s)\n",
+ "%p %-24s %p " CPUPADDR_FMT " %" SIZE_T_FMT_LEN "u %-5u %08x=(%s)\n",
#else
"<linux_mem_area>\n"
- "\t<pointer>%8p</pointer>\n"
+ "\t<pointer>%p</pointer>\n"
"\t<type>%s</type>\n"
- "\t<cpu_virtual>%8p</cpu_virtual>\n"
- "\t<cpu_physical>%08x</cpu_physical>\n"
- "\t<bytes>%d</bytes>\n"
+ "\t<cpu_virtual>%p</cpu_virtual>\n"
+ "\t<cpu_physical>" CPUPADDR_FMT "</cpu_physical>\n"
+ "\t<bytes>%" SIZE_T_FMT_LEN "d</bytes>\n"
"\t<pid>%u</pid>\n"
"\t<flags>%08x</flags>\n"
"\t<flags_string>%s</flags_string>\n"
@@ -2367,14 +2130,13 @@ static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
- psRecord->psLinuxMemArea->ui32ByteSize,
+ psRecord->psLinuxMemArea->uiByteSize,
psRecord->pid,
psRecord->ui32Flags,
HAPFlagsToString(psRecord->ui32Flags)
);
}
-
#endif /* DEBUG_LINUX_MEM_AREAS */
@@ -2393,7 +2155,6 @@ static IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list
}
}
-
/* seq_file version of generating output, for reference check proc.c:CreateProcReadEntrySeq */
static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off)
{
@@ -2598,13 +2359,13 @@ static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
{
seq_printf(sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
- "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+ "%-16s %p " CPUPADDR_FMT " %" SIZE_T_FMT_LEN "u %-5d %-10s %s:%d\n",
#else
"<allocation>\n"
"\t<type>%s</type>\n"
- "\t<cpu_virtual>%-8p</cpu_virtual>\n"
- "\t<cpu_physical>%08x</cpu_physical>\n"
- "\t<bytes>%d</bytes>\n"
+ "\t<cpu_virtual>%p</cpu_virtual>\n"
+ "\t<cpu_physical>" CPUPADDR_FMT "</cpu_physical>\n"
+ "\t<bytes>%" SIZE_T_FMT_LEN "u</bytes>\n"
"\t<pid>%d</pid>\n"
"\t<private>%s</private>\n"
"\t<filename>%s</filename>\n"
@@ -2613,8 +2374,8 @@ static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
#endif
DebugMemAllocRecordTypeToString(psRecord->eAllocType),
psRecord->pvCpuVAddr,
- psRecord->ulCpuPAddr,
- psRecord->ui32Bytes,
+ psRecord->sCpuPAddr.uiAddr,
+ psRecord->uiBytes,
psRecord->pid,
"NULL",
psRecord->pszFileName,
@@ -2624,13 +2385,13 @@ static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
{
seq_printf(sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
- "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+ "%-16s %p " CPUPADDR_FMT " %" SIZE_T_FMT_LEN "u %-5d %-10s %s:%d\n",
#else
"<allocation>\n"
"\t<type>%s</type>\n"
- "\t<cpu_virtual>%-8p</cpu_virtual>\n"
- "\t<cpu_physical>%08x</cpu_physical>\n"
- "\t<bytes>%d</bytes>\n"
+ "\t<cpu_virtual>%p</cpu_virtual>\n"
+ "\t<cpu_physical>" CPUPADDR_FMT "</cpu_physical>\n"
+ "\t<bytes>%" SIZE_T_FMT_LEN "u</bytes>\n"
"\t<pid>%d</pid>\n"
"\t<private>%s</private>\n"
"\t<filename>%s</filename>\n"
@@ -2639,15 +2400,14 @@ static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
#endif
DebugMemAllocRecordTypeToString(psRecord->eAllocType),
psRecord->pvCpuVAddr,
- psRecord->ulCpuPAddr,
- psRecord->ui32Bytes,
+ psRecord->sCpuPAddr.uiAddr,
+ psRecord->uiBytes,
psRecord->pid,
KMemCacheNameWrapper(psRecord->pvPrivateData),
psRecord->pszFileName,
psRecord->ui32Line);
}
}
-
#endif /* defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) */
@@ -2730,11 +2490,11 @@ static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCu
LinuxMemArea *psLinuxMemArea;
psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
- PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes",
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%"SIZE_T_FMT_LEN"d bytes",
__FUNCTION__,
psCurrentRecord->psLinuxMemArea,
LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
- psCurrentRecord->psLinuxMemArea->ui32ByteSize));
+ psCurrentRecord->psLinuxMemArea->uiByteSize));
/* Note this will also remove psCurrentRecord from g_LinuxMemAreaRecords
* but that's ok since we have already got a pointer to the next area. */
LinuxMemAreaDeepFree(psLinuxMemArea);
@@ -2751,12 +2511,12 @@ static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurre
PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
"type=%s "
"CpuVAddr=%p "
- "CpuPAddr=0x%08x, "
+ "CpuPAddr=0x" CPUPADDR_FMT ", "
"allocated @ file=%s,line=%d",
__FUNCTION__,
DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
psCurrentRecord->pvCpuVAddr,
- psCurrentRecord->ulCpuPAddr,
+ psCurrentRecord->sCpuPAddr.uiAddr,
psCurrentRecord->pszFileName,
psCurrentRecord->ui32Line));
switch (psCurrentRecord->eAllocType)
@@ -2769,13 +2529,13 @@ static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurre
break;
case DEBUG_MEM_ALLOC_TYPE_IO:
/* Nothing needed except to free the record */
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->uiKey, __FILE__, __LINE__);
break;
case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
VFreeWrapper(psCurrentRecord->pvCpuVAddr);
break;
case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->uiKey, __FILE__, __LINE__);
break;
case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mm.h b/drivers/gpu/pvr/services4/srvkm/env/linux/mm.h
index 6801df466e7..933420deb40 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/mm.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mm.h
@@ -88,7 +88,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#endif
-static inline IMG_UINT32 VMallocToPhys(IMG_VOID *pCpuVAddr)
+static inline IMG_UINTPTR_T VMallocToPhys(IMG_VOID *pCpuVAddr)
{
return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
@@ -101,7 +101,6 @@ typedef enum {
LINUX_MEM_AREA_VMALLOC,
LINUX_MEM_AREA_ALLOC_PAGES,
LINUX_MEM_AREA_SUB_ALLOC,
- LINUX_MEM_AREA_ION,
#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
LINUX_MEM_AREA_VMAP,
#endif
@@ -161,25 +160,16 @@ struct _LinuxMemArea {
struct page **ppsPageList;
IMG_HANDLE hBlockPageList;
}sPageList;
- struct _sIONTilerAlloc
- {
- /* Note the memory this represents _is_ implicitly
- * page aligned _and_ so is its size */
- IMG_CPU_PHYADDR *pCPUPhysAddrs;
- IMG_UINT32 ui32NumValidPlanes;
- struct ion_handle *psIONHandle[PVRSRV_MAX_NUMBER_OF_MM_BUFFER_PLANES];
- IMG_UINT32 planeOffsets[PVRSRV_MAX_NUMBER_OF_MM_BUFFER_PLANES];
- }sIONTilerAlloc;
struct _sSubAlloc
{
/* Note: The memory this represents is _not_ implicitly
* page aligned, neither is its size */
LinuxMemArea *psParentLinuxMemArea;
- IMG_UINT32 ui32ByteOffset;
+ IMG_UINTPTR_T uiByteOffset;
}sSubAlloc;
}uData;
- IMG_UINT32 ui32ByteSize; /* Size of memory area */
+ IMG_SIZE_T uiByteSize; /* Size of memory area */
IMG_UINT32 ui32AreaFlags; /* Flags passed at creation time */
@@ -241,16 +231,16 @@ IMG_VOID LinuxMMCleanup(IMG_VOID);
* They can also be used as more concise replacements for OSAllocMem
* in Linux specific code.
*
- * @param ui32ByteSize
+ * @param uByteSize
*
* @return
******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-#define KMallocWrapper(ui32ByteSize, uFlags) _KMallocWrapper(ui32ByteSize, uFlags, __FILE__, __LINE__)
+#define KMallocWrapper(uByteSize, uFlags) _KMallocWrapper(uByteSize, uFlags, __FILE__, __LINE__)
#else
-#define KMallocWrapper(ui32ByteSize, uFlags) _KMallocWrapper(ui32ByteSize, uFlags, NULL, 0)
+#define KMallocWrapper(uByteSize, uFlags) _KMallocWrapper(uByteSize, uFlags, NULL, 0)
#endif
-IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
+IMG_VOID *_KMallocWrapper(IMG_SIZE_T uByteSize, gfp_t uFlags, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
/*!
@@ -273,17 +263,17 @@ IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 u
*******************************************************************************
* @brief
*
- * @param ui32Bytes
+ * @param uBytes
* @param ui32AllocFlags
*
* @return
******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#define VMallocWrapper(uiBytes, ui32AllocFlags) _VMallocWrapper(uiBytes, ui32AllocFlags, __FILE__, __LINE__)
#else
-#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, NULL, 0)
+#define VMallocWrapper(uiBytes, ui32AllocFlags) _VMallocWrapper(uiBytes, ui32AllocFlags, NULL, 0)
#endif
-IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+IMG_VOID *_VMallocWrapper(IMG_SIZE_T uiBytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
/*!
@@ -306,12 +296,12 @@ IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 u
*******************************************************************************
* @brief Allocates virtually contiguous pages
*
- * @param ui32Bytes number of bytes to reserve
+ * @param uBytes number of bytes to reserve
* @param ui32AreaFlags Heap caching and mapping Flags
*
* @return Page-aligned address of virtual allocation or NULL on error
******************************************************************************/
-LinuxMemArea *NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+LinuxMemArea *NewVMallocLinuxMemArea(IMG_SIZE_T uBytes, IMG_UINT32 ui32AreaFlags);
/*!
@@ -329,20 +319,20 @@ IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
* @brief Reserve physical IO memory and create a CPU virtual mapping for it
*
* @param BasePAddr
- * @param ui32Bytes
+ * @param uiBytes
* @param ui32MappingFlags
*
* @return
******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
- _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
+#define IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags, __FILE__, __LINE__)
#else
-#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
- _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
+#define IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags, NULL, 0)
#endif
IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uiBytes,
IMG_UINT32 ui32MappingFlags,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32Line);
@@ -353,12 +343,12 @@ IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
* @brief Reserve physical IO memory and create a CPU virtual mapping for it
*
* @param BasePAddr
- * @param ui32Bytes
+ * @param uiBytes
* @param ui32AreaFlags Heap caching and mapping Flags
*
* @return
******************************************************************************/
-LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T uiBytes, IMG_UINT32 ui32AreaFlags);
/*!
@@ -378,12 +368,12 @@ IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
* @param pBasePAddr
* @param pvCPUVAddr
* @param bPhysContig
- * @param ui32Bytes
+ * @param uBytes
* @param ui32AreaFlags Heap caching and mapping Flags
*
* @return
******************************************************************************/
-LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_SIZE_T uBytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
/*!
@@ -420,11 +410,11 @@ IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_U
* @brief
*
* @param psLinuxMemArea
- * @param ui32ByteOffset
+ * @param uByteOffset
*
* @return
******************************************************************************/
-struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINTPTR_T uByteOffset);
/*!
@@ -506,12 +496,12 @@ const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
* @brief
*
* @param BasePAddr
- * @param ui32Bytes
+ * @param uiBytes
* @param ui32AreaFlags Heap caching and mapping Flags
*
* @return
******************************************************************************/
-LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T uiBytes, IMG_UINT32 ui32AreaFlags);
/*!
@@ -529,12 +519,12 @@ IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
*******************************************************************************
* @brief
*
- * @param ui32Bytes
+ * @param uiBytes
* @param ui32AreaFlags E.g Heap caching and mapping Flags
*
* @return
******************************************************************************/
-LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_SIZE_T uiBytes, IMG_UINT32 ui32AreaFlags);
/*!
@@ -548,83 +538,19 @@ LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Are
IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
-#if defined(CONFIG_ION_OMAP)
-
-/*!
- *******************************************************************************
- * @brief
- *
- * @param ui32Bytes
- * @param ui32AreaFlags E.g Heap caching and mapping Flags
- *
- * @return
- ******************************************************************************/
-LinuxMemArea *
-NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
- IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength);
-
-
-/*!
- *******************************************************************************
- * @brief
- *
- * @param psLinuxMemArea
- *
- * @return
- ******************************************************************************/
-IMG_VOID FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea);
-
-IMG_INT32
-GetIONLinuxMemAreaInfo(LinuxMemArea *psLinuxMemArea, IMG_UINT32* ui32AddressOffsets,
- IMG_UINT32* ui32NumAddr);
-
-#else /* defined(CONFIG_ION_OMAP) */
-
-static inline LinuxMemArea *
-NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
- IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength)
-{
- PVR_UNREFERENCED_PARAMETER(ui32Bytes);
- PVR_UNREFERENCED_PARAMETER(ui32AreaFlags);
- PVR_UNREFERENCED_PARAMETER(pvPrivData);
- PVR_UNREFERENCED_PARAMETER(ui32PrivDataLength);
- BUG();
- return IMG_NULL;
-}
-
-static inline IMG_VOID FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea)
-{
- PVR_UNREFERENCED_PARAMETER(psLinuxMemArea);
- BUG();
-}
-
-static inline IMG_INT32
-GetIONLinuxMemAreaInfo(LinuxMemArea *psLinuxMemArea, IMG_UINT32* ui32AddressOffsets,
- IMG_UINT32* ui32NumAddr)
-{
- PVR_UNREFERENCED_PARAMETER(psLinuxMemArea);
- PVR_UNREFERENCED_PARAMETER(ui32AddressOffsets);
- PVR_UNREFERENCED_PARAMETER(ui32NumAddr);
- BUG();
- return -1;
-}
-
-#endif /* defined(CONFIG_ION_OMAP) */
-
-
/*!
*******************************************************************************
* @brief
*
* @param psParentLinuxMemArea
- * @param ui32ByteOffset
- * @param ui32Bytes
+ * @param uByteOffset
+ * @param uBytes
*
* @return
******************************************************************************/
LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
- IMG_UINT32 ui32ByteOffset,
- IMG_UINT32 ui32Bytes);
+ IMG_UINTPTR_T uByteOffset,
+ IMG_SIZE_T uBytes);
/*!
@@ -668,14 +594,14 @@ IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
* @brief
*
* @param psLinuxMemArea
- * @param ui32ByteOffset
+ * @param uByteOffset
*
* @return
******************************************************************************/
-IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINTPTR_T uByteOffset);
-#define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr)
+#define LinuxMemAreaToCpuPFN(psLinuxMemArea, uByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, uByteOffset).uiAddr)
/*!
*******************************************************************************
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.c b/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.c
index 3eb2cbad2bf..a0b821117ff 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.c
@@ -69,6 +69,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <drm/drmP.h>
#endif
+#ifdef CONFIG_ARCH_OMAP5
+#ifdef CONFIG_DSSCOMP
+#include <../drivers/staging/omapdrm/omap_dmm_tiler.h>
+#endif
+#endif
+
#include "services_headers.h"
#include "pvrmmap.h"
@@ -85,7 +91,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "pvr_drm.h"
#endif
-#if !defined(PVR_SECURE_HANDLES) && !defined (SUPPORT_SID_INTERFACE)
+#if !defined(PVR_SECURE_HANDLES)
#error "The mmap code requires PVR_SECURE_HANDLES"
#endif
@@ -108,12 +114,12 @@ static LIST_HEAD(g_sMMapAreaList);
static LIST_HEAD(g_sMMapOffsetStructList);
#if defined(DEBUG_LINUX_MMAP_AREAS)
static IMG_UINT32 g_ui32RegisteredAreas = 0;
-static IMG_UINT32 g_ui32TotalByteSize = 0;
+static IMG_SIZE_T g_uiTotalByteSize = 0;
#endif
#if defined(DEBUG_LINUX_MMAP_AREAS)
-static struct proc_dir_entry *g_ProcMMap;
+static struct pvr_proc_dir_entry *g_ProcMMap;
#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
@@ -201,14 +207,10 @@ MMapOffsetToHandle(IMG_UINT32 pfn)
}
#endif
-static inline IMG_UINT32
-#if defined (SUPPORT_SID_INTERFACE)
-HandleToMMapOffset(IMG_SID hHandle)
-#else
+static inline IMG_UINTPTR_T
HandleToMMapOffset(IMG_HANDLE hHandle)
-#endif
{
- IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
+ IMG_UINTPTR_T ulHandle = (IMG_UINTPTR_T)hHandle;
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
if (PFNIsSpecial(ulHandle))
@@ -255,7 +257,7 @@ GetCurrentThreadID(IMG_VOID)
* mmap data.
*/
static PKV_OFFSET_STRUCT
-CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINTPTR_T uiOffset, IMG_SIZE_T uiRealByteSize)
{
PKV_OFFSET_STRUCT psOffsetStruct;
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
@@ -279,11 +281,11 @@ CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT
return IMG_NULL;
}
- psOffsetStruct->ui32MMapOffset = ui32Offset;
+ psOffsetStruct->uiMMapOffset = uiOffset;
psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
- psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
+ psOffsetStruct->uiRealByteSize = uiRealByteSize;
/*
* We store the TID in case two threads within a process
@@ -327,7 +329,8 @@ DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
#ifdef DEBUG
PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
- "psLinuxMemArea=%p, CpuPAddr=0x%08X", __FUNCTION__,
+ "psLinuxMemArea=%p, CpuPAddr=0x" CPUPADDR_FMT,
+ __FUNCTION__,
psOffsetStruct->psLinuxMemArea,
CpuPAddr.uiAddr));
#endif
@@ -349,18 +352,18 @@ DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
*/
static inline IMG_VOID
DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
- IMG_UINT32 *pui32RealByteSize,
- IMG_UINT32 *pui32ByteOffset)
+ IMG_SIZE_T *puiRealByteSize,
+ IMG_UINTPTR_T *puiByteOffset)
{
- IMG_UINT32 ui32PageAlignmentOffset;
+ IMG_UINTPTR_T uiPageAlignmentOffset;
IMG_CPU_PHYADDR CpuPAddr;
CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
- ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+ uiPageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
- *pui32ByteOffset = ui32PageAlignmentOffset;
+ *puiByteOffset = uiPageAlignmentOffset;
- *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+ *puiRealByteSize = PAGE_ALIGN(psLinuxMemArea->uiByteSize + uiPageAlignmentOffset);
}
@@ -376,16 +379,16 @@ DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
@input psPerProc : Per-process data.
@input hMHandle : Memory handle.
- @input pui32MMapOffset : pointer to location for returned mmap offset.
- @input pui32ByteOffset : pointer to location for returned byte offset.
- @input pui32RealByteSize : pointer to location for returned real byte size.
- @input pui32UserVaddr : pointer to location for returned user mode address.
+ @input puiMMapOffset : pointer to location for returned mmap offset.
+ @input puiByteOffset : pointer to location for returned byte offset.
+ @input puiRealByteSize : pointer to location for returned real byte size.
+ @input puiUserVaddr : pointer to location for returned user mode address.
- @output pui32MMapOffset : points to mmap offset to be used in mmap2 sys call.
- @output pui32ByteOffset : points to byte offset of start of memory
+ @output puiMMapOffset : points to mmap offset to be used in mmap2 sys call.
+ @output puiByteOffset : points to byte offset of start of memory
within mapped area returned by mmap2.
- @output pui32RealByteSize : points to size of area to be mapped.
- @output pui32UserVAddr : points to user mode address of start of
+ @output puiRealByteSize : points to size of area to be mapped.
+ @output puiUserVAddr : points to user mode address of start of
mapping, or 0 if it hasn't been mapped yet.
@Return PVRSRV_ERROR : PVRSRV_OK, or error code.
@@ -393,64 +396,43 @@ DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
******************************************************************************/
PVRSRV_ERROR
PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
-#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hMHandle,
-#else
IMG_HANDLE hMHandle,
-#endif
- IMG_UINT32 *pui32MMapOffset,
- IMG_UINT32 *pui32ByteOffset,
- IMG_UINT32 *pui32RealByteSize,
- IMG_UINT32 *pui32UserVAddr)
+ IMG_UINTPTR_T *puiMMapOffset,
+ IMG_UINTPTR_T *puiByteOffset,
+ IMG_SIZE_T *puiRealByteSize,
+ IMG_UINTPTR_T *puiUserVAddr)
{
LinuxMemArea *psLinuxMemArea;
PKV_OFFSET_STRUCT psOffsetStruct;
IMG_HANDLE hOSMemHandle;
PVRSRV_ERROR eError;
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
if (eError != PVRSRV_OK)
{
-#if defined (SUPPORT_SID_INTERFACE)
- PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %x failed", __FUNCTION__, hMHandle));
-#else
PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
-#endif
goto exit_unlock;
}
psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
- if (psLinuxMemArea && (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ION))
- {
- *pui32RealByteSize = psLinuxMemArea->ui32ByteSize;
- *pui32ByteOffset = psLinuxMemArea->uData.sIONTilerAlloc.planeOffsets[0];
- /* The offsets for the subsequent planes must be co-aligned for user
- * space mapping and sgx 544 and later. I.e.
- * psLinuxMemArea->uData.sIONTilerAlloc.planeOffsets[n];
- */
- }
- else
- {
-
/* Sparse mappings have to ask the BM for the virtual size */
if (psLinuxMemArea->hBMHandle)
{
- *pui32RealByteSize = BM_GetVirtualSize(psLinuxMemArea->hBMHandle);
- *pui32ByteOffset = 0;
+ *puiRealByteSize = BM_GetVirtualSize(psLinuxMemArea->hBMHandle);
+ *puiByteOffset = 0;
}
else
{
DetermineUsersSizeAndByteOffset(psLinuxMemArea,
- pui32RealByteSize,
- pui32ByteOffset);
+ puiRealByteSize,
+ puiByteOffset);
}
- }
/* Check whether this memory area has already been mapped */
list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
@@ -459,7 +441,7 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
{
if (!psLinuxMemArea->hBMHandle)
{
- PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+ PVR_ASSERT(*puiRealByteSize == psOffsetStruct->uiRealByteSize);
}
/*
* User mode locking is required to stop two threads racing to
@@ -469,8 +451,8 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
* Without locking, both threads may attempt the mmap,
* and one of them will fail.
*/
- *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
- *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
+ *puiMMapOffset = psOffsetStruct->uiMMapOffset;
+ *puiUserVAddr = psOffsetStruct->uiUserVAddr;
PVRSRVOffsetStructIncRef(psOffsetStruct);
eError = PVRSRV_OK;
@@ -479,24 +461,24 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
}
/* Memory area won't have been mapped yet */
- *pui32UserVAddr = 0;
+ *puiUserVAddr = 0;
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
{
- *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
- PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
+ *puiMMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+ PVR_ASSERT(PFNIsPhysical(*puiMMapOffset));
}
else
#endif
{
- *pui32MMapOffset = HandleToMMapOffset(hMHandle);
+ *puiMMapOffset = HandleToMMapOffset(hMHandle);
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
- PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
+ PVR_ASSERT(PFNIsSpecial(*puiMMapOffset));
#endif
}
- psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
+ psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *puiMMapOffset, *puiRealByteSize);
if (psOffsetStruct == IMG_NULL)
{
eError = PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -519,7 +501,7 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
is done in the mmap2() syscall, as it expects the pgoff
argument to be in units of 4,096 bytes irrespective of
page size */
- *pui32MMapOffset = *pui32MMapOffset << (PAGE_SHIFT - 12);
+ *puiMMapOffset = *puiMMapOffset << (PAGE_SHIFT - 12);
exit_unlock:
LinuxUnLockMutex(&g_sMMapMutex);
@@ -540,26 +522,22 @@ exit_unlock:
@input psPerProc : Per-process data.
@input hMHandle : Memory handle.
@input pbMUnmap : pointer to location for munmap flag.
- @input pui32UserVAddr : pointer to location for user mode address of mapping.
- @input pui32ByteSize : pointer to location for size of mapping.
+ @input puiUserVAddr : pointer to location for user mode address of mapping.
+ @input puiByteSize : pointer to location for size of mapping.
@Output pbMUnmap : points to flag that indicates whether an munmap is
required.
- @output pui32UserVAddr : points to user mode address to munmap.
+ @output puiUserVAddr : points to user mode address to munmap.
@Return PVRSRV_ERROR : PVRSRV_OK, or error code.
******************************************************************************/
PVRSRV_ERROR
PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
-#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hMHandle,
-#else
IMG_HANDLE hMHandle,
-#endif
IMG_BOOL *pbMUnmap,
- IMG_UINT32 *pui32RealByteSize,
- IMG_UINT32 *pui32UserVAddr)
+ IMG_SIZE_T *puiRealByteSize,
+ IMG_UINTPTR_T *puiUserVAddr)
{
LinuxMemArea *psLinuxMemArea;
PKV_OFFSET_STRUCT psOffsetStruct;
@@ -567,18 +545,14 @@ PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
PVRSRV_ERROR eError;
IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
if (eError != PVRSRV_OK)
{
-#if defined (SUPPORT_SID_INTERFACE)
- PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %x failed", __FUNCTION__, hMHandle));
-#else
PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
-#endif
goto exit_unlock;
}
@@ -599,10 +573,10 @@ PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
PVRSRVOffsetStructDecRef(psOffsetStruct);
- *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
+ *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->uiUserVAddr != 0));
- *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
- *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
+ *puiUserVAddr = (*pbMUnmap) ? psOffsetStruct->uiUserVAddr : 0;
+ *puiRealByteSize = (*pbMUnmap) ? psOffsetStruct->uiRealByteSize : 0;
eError = PVRSRV_OK;
goto exit_unlock;
@@ -610,11 +584,7 @@ PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
}
/* MMap data not found */
-#if defined (SUPPORT_SID_INTERFACE)
- PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle %x (memory area %p)", __FUNCTION__, hMHandle, psLinuxMemArea));
-#else
PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle %p (memory area %p)", __FUNCTION__, hMHandle, psLinuxMemArea));
-#endif
eError = PVRSRV_ERROR_MAPPING_NOT_FOUND;
@@ -625,7 +595,7 @@ exit_unlock:
}
static inline PKV_OFFSET_STRUCT
-FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+FindOffsetStructByOffset(IMG_UINTPTR_T uiOffset, IMG_SIZE_T uiRealByteSize)
{
PKV_OFFSET_STRUCT psOffsetStruct;
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
@@ -635,7 +605,7 @@ FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
{
- if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
+ if (uiOffset == psOffsetStruct->uiMMapOffset && uiRealByteSize == psOffsetStruct->uiRealByteSize && psOffsetStruct->ui32PID == ui32PID)
{
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
/*
@@ -643,7 +613,7 @@ FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
* as different threads may be mapping different memory areas
* with the same offset.
*/
- if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
+ if (!PFNIsPhysical(uiOffset) || psOffsetStruct->ui32TID == ui32TID)
#endif
{
return psOffsetStruct;
@@ -663,11 +633,11 @@ FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
static IMG_BOOL
DoMapToUser(LinuxMemArea *psLinuxMemArea,
struct vm_area_struct* ps_vma,
- IMG_UINT32 ui32ByteOffset)
+ IMG_UINTPTR_T uiByteOffset)
{
- IMG_UINT32 ui32ByteSize;
+ IMG_SIZE_T uiByteSize;
- if ((psLinuxMemArea->hBMHandle) && (ui32ByteOffset != 0))
+ if ((psLinuxMemArea->hBMHandle) && (uiByteOffset != 0))
{
/* Partial mapping of sparse allocations should never happen */
return IMG_FALSE;
@@ -677,15 +647,15 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
{
return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea), /* PRQA S 3670 */ /* allow recursion */
ps_vma,
- psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
+ psLinuxMemArea->uData.sSubAlloc.uiByteOffset + uiByteOffset);
}
/*
* Note that ui32ByteSize may be larger than the size of the memory
* area being mapped, as the former is a multiple of the page size.
*/
- ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
- PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+ uiByteSize = ps_vma->vm_end - ps_vma->vm_start;
+ PVR_ASSERT(ADDR_TO_PAGE_OFFSET(uiByteSize) == 0);
#if defined (__sparc__)
/*
@@ -700,10 +670,10 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
if (PFNIsPhysical(ps_vma->vm_pgoff))
{
- IMG_INT result;
+ IMG_INT result;
- PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
- PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
+ PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+ PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, uiByteOffset) == ps_vma->vm_pgoff);
/*
* Since the memory is contiguous, we can map the whole range in one
* go .
@@ -711,7 +681,7 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
PVR_ASSERT(psLinuxMemArea->hBMHandle == IMG_NULL);
- result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
+ result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, uiByteSize, ps_vma->vm_page_prot);
if(result == 0)
{
@@ -723,7 +693,7 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
#endif
{
- /*
+ /*
* Memory may be non-contiguous, so we map the range page,
* by page. Since VM_PFNMAP mappings are assumed to be physically
* contiguous, we can't legally use REMAP_PFN_RANGE (that is, we
@@ -733,22 +703,22 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
* finding the page structure corresponding to each page, or
* if mixed maps are supported (VM_MIXEDMAP), vm_insert_mixed.
*/
- IMG_UINT32 ulVMAPos;
- IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
- IMG_UINT32 ui32PA;
- IMG_UINT32 ui32AdjustedPA = ui32ByteOffset;
+ IMG_UINTPTR_T ulVMAPos;
+ IMG_UINTPTR_T uiByteEnd = uiByteOffset + uiByteSize;
+ IMG_UINTPTR_T uiPA;
+ IMG_UINTPTR_T uiAdjustedPA = uiByteOffset;
#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
- IMG_BOOL bMixedMap = IMG_FALSE;
+ IMG_BOOL bMixedMap = IMG_FALSE;
#endif
/* First pass, validate the page frame numbers */
- for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ for(uiPA = uiByteOffset; uiPA < uiByteEnd; uiPA += PAGE_SIZE)
{
- IMG_UINT32 pfn;
+ IMG_UINTPTR_T pfn;
IMG_BOOL bMapPage = IMG_TRUE;
if (psLinuxMemArea->hBMHandle)
{
- if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32PA))
+ if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, uiPA))
{
bMapPage = IMG_FALSE;
}
@@ -756,39 +726,45 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
if (bMapPage)
{
- pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32AdjustedPA);
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, uiAdjustedPA);
if (!pfn_valid(pfn))
{
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
- PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%x", __FUNCTION__, pfn));
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x" UINTPTR_FMT, __FUNCTION__, pfn));
return IMG_FALSE;
#else
bMixedMap = IMG_TRUE;
#endif
}
- ui32AdjustedPA += PAGE_SIZE;
+ else if (0 == page_count(pfn_to_page(pfn)))
+ {
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ bMixedMap = IMG_TRUE;
+#endif
+ }
+ uiAdjustedPA += PAGE_SIZE;
}
}
#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
- if (bMixedMap)
- {
- ps_vma->vm_flags |= VM_MIXEDMAP;
- }
+ if (bMixedMap)
+ {
+ ps_vma->vm_flags |= VM_MIXEDMAP;
+ }
#endif
/* Second pass, get the page structures and insert the pages */
ulVMAPos = ps_vma->vm_start;
- ui32AdjustedPA = ui32ByteOffset;
- for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ uiAdjustedPA = uiByteOffset;
+ for(uiPA = uiByteOffset; uiPA < uiByteEnd; uiPA += PAGE_SIZE)
{
- IMG_UINT32 pfn;
+ IMG_UINTPTR_T pfn;
IMG_INT result;
IMG_BOOL bMapPage = IMG_TRUE;
if (psLinuxMemArea->hBMHandle)
{
/* We have a sparse allocation, check if this page should be mapped */
- if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32PA))
+ if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, uiPA))
{
bMapPage = IMG_FALSE;
}
@@ -796,7 +772,7 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
if (bMapPage)
{
- pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32AdjustedPA);
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, uiAdjustedPA);
#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
if (bMixedMap)
@@ -811,7 +787,7 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
else
#endif
{
- struct page *psPage;
+ struct page *psPage;
PVR_ASSERT(pfn_valid(pfn));
@@ -824,11 +800,11 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
return IMG_FALSE;
}
}
- ui32AdjustedPA += PAGE_SIZE;
+ uiAdjustedPA += PAGE_SIZE;
+ }
+ ulVMAPos += PAGE_SIZE;
}
- ulVMAPos += PAGE_SIZE;
- }
- }
+ }
return IMG_TRUE;
}
@@ -853,11 +829,11 @@ MMapVOpenNoLock(struct vm_area_struct* ps_vma)
#if defined(DEBUG_LINUX_MMAP_AREAS)
PVR_DPF((PVR_DBG_MESSAGE,
- "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %d, ui32Mapped %d",
+ "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset " UINTPTR_FMT ", ui32Mapped %d",
__FUNCTION__,
psOffsetStruct->psLinuxMemArea,
LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
- psOffsetStruct->ui32MMapOffset,
+ psOffsetStruct->uiMMapOffset,
psOffsetStruct->ui32Mapped));
#endif
}
@@ -869,7 +845,7 @@ MMapVOpenNoLock(struct vm_area_struct* ps_vma)
static void
MMapVOpen(struct vm_area_struct* ps_vma)
{
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
MMapVOpenNoLock(ps_vma);
@@ -885,11 +861,11 @@ MMapVCloseNoLock(struct vm_area_struct* ps_vma)
#if defined(DEBUG_LINUX_MMAP_AREAS)
PVR_DPF((PVR_DBG_MESSAGE,
- "%s: psLinuxMemArea %p, CpuVAddr %p ui32MMapOffset %d, ui32Mapped %d",
+ "%s: psLinuxMemArea %p, CpuVAddr %p uiMMapOffset " UINTPTR_FMT ", ui32Mapped %d",
__FUNCTION__,
psOffsetStruct->psLinuxMemArea,
LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
- psOffsetStruct->ui32MMapOffset,
+ psOffsetStruct->uiMMapOffset,
psOffsetStruct->ui32Mapped));
#endif
@@ -899,7 +875,13 @@ MMapVCloseNoLock(struct vm_area_struct* ps_vma)
{
if (psOffsetStruct->ui32RefCount != 0)
{
- PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct %p has non-zero reference count (ui32RefCount = %u). User mode address of start of mapping: 0x%x", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
+ PVR_DPF((
+ PVR_DBG_MESSAGE,
+ "%s: psOffsetStruct %p has non-zero reference count (ui32RefCount = %u). User mode address of start of mapping: 0x" UINTPTR_FMT,
+ __FUNCTION__,
+ psOffsetStruct,
+ psOffsetStruct->ui32RefCount,
+ psOffsetStruct->uiUserVAddr));
}
DestroyOffsetStruct(psOffsetStruct);
@@ -914,7 +896,7 @@ MMapVCloseNoLock(struct vm_area_struct* ps_vma)
static void
MMapVClose(struct vm_area_struct* ps_vma)
{
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
MMapVCloseNoLock(ps_vma);
@@ -936,13 +918,13 @@ static int MMapVAccess(struct vm_area_struct *ps_vma, unsigned long addr,
int iRetVal = -EINVAL;
IMG_VOID *pvKernelAddr;
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
ulOffset = addr - ps_vma->vm_start;
- if (ulOffset+len > psLinuxMemArea->ui32ByteSize)
+ if (ulOffset+len > psLinuxMemArea->uiByteSize)
/* Out of range. We shouldn't get here, because the kernel will do
the necessary checks before calling access_process_vm. */
goto exit_unlock;
@@ -956,7 +938,7 @@ static int MMapVAccess(struct vm_area_struct *ps_vma, unsigned long addr,
}
else
{
- IMG_UINT32 pfn, ui32OffsetInPage;
+ IMG_UINTPTR_T pfn, uiOffsetInPage;
struct page *page;
pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ulOffset);
@@ -965,14 +947,14 @@ static int MMapVAccess(struct vm_area_struct *ps_vma, unsigned long addr,
goto exit_unlock;
page = pfn_to_page(pfn);
- ui32OffsetInPage = ADDR_TO_PAGE_OFFSET(ulOffset);
+ uiOffsetInPage = ADDR_TO_PAGE_OFFSET(ulOffset);
- if (ui32OffsetInPage+len > PAGE_SIZE)
+ if (uiOffsetInPage + len > PAGE_SIZE)
/* The region crosses a page boundary */
goto exit_unlock;
pvKernelAddr = kmap(page);
- memcpy(buf, pvKernelAddr+ui32OffsetInPage, len);
+ memcpy(buf, pvKernelAddr + uiOffsetInPage, len);
kunmap(page);
iRetVal = len;
@@ -1014,34 +996,35 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
{
LinuxMemArea *psFlushMemArea = IMG_NULL;
PKV_OFFSET_STRUCT psOffsetStruct;
- IMG_UINT32 ui32ByteSize;
+ IMG_SIZE_T uiByteSize;
IMG_VOID *pvBase = IMG_NULL;
int iRetVal = 0;
- IMG_UINT32 ui32ByteOffset = 0; /* Keep compiler happy */
- IMG_UINT32 ui32FlushSize = 0;
+ IMG_UINTPTR_T uiByteOffset = 0; /* Keep compiler happy */
+ IMG_SIZE_T uiFlushSize = 0;
PVR_UNREFERENCED_PARAMETER(pFile);
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
- ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+ uiByteSize = ps_vma->vm_end - ps_vma->vm_start;
- PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
- " and ui32ByteSize %d(0x%08x)",
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x" UINTPTR_FMT ","
+ " and uiByteSize %" SIZE_T_FMT_LEN "u(0x%" SIZE_T_FMT_LEN "x)",
__FUNCTION__,
ps_vma->vm_pgoff,
- ui32ByteSize, ui32ByteSize));
+ uiByteSize,
+ uiByteSize));
- psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+ psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, uiByteSize);
if (psOffsetStruct == IMG_NULL)
{
#if defined(SUPPORT_DRI_DRM)
- LinuxUnLockMutex(&g_sMMapMutex);
+ LinuxUnLockMutex(&g_sMMapMutex);
#if !defined(SUPPORT_DRI_DRM_EXT)
- /* Pass unknown requests onto the DRM module */
- return drm_mmap(pFile, ps_vma);
+ /* Pass unknown requests onto the DRM module */
+ return drm_mmap(pFile, ps_vma);
#else
/*
* Indicate to caller that the request is not for us.
@@ -1078,9 +1061,10 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
__FUNCTION__, psOffsetStruct->psLinuxMemArea));
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
+ /* This is probably superfluous and implied by VM_IO */
ps_vma->vm_flags |= VM_RESERVED;
#else
- ps_vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; /* Don't swap */
+ ps_vma->vm_flags |= VM_DONTDUMP;
#endif
ps_vma->vm_flags |= VM_IO;
@@ -1112,16 +1096,22 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
goto unlock_and_return;
}
-#if defined(SGX544) && defined(SGX_FEATURE_MP)
- /* In OMAP5, the A15 no longer masks an issue with the interconnect.
- writecombined access to the Tiler 2D memory will encounter errors due to
- interconect bus accesses. This will result in a SIGBUS error with a
- "non-line fetch abort". The workaround is to use a shared device
- access. */
- if (psOffsetStruct->psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ION)
- ps_vma->vm_page_prot = __pgprot_modify(ps_vma->vm_page_prot,
- L_PTE_MT_MASK, L_PTE_MT_DEV_SHARED);
-#endif
+#ifdef CONFIG_ARCH_OMAP5
+ {
+ IMG_BOOL bModPageProt = IMG_FALSE;
+
+#ifdef CONFIG_DSSCOMP
+ bModPageProt |= is_tiler_addr(LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0).uiAddr);
+#endif /* CONFIG_DSSCOMP */
+
+ if (bModPageProt)
+ {
+ ps_vma->vm_page_prot = __pgprot_modify(ps_vma->vm_page_prot,
+ L_PTE_MT_MASK,
+ L_PTE_MT_DEV_SHARED);
+ }
+ }
+#endif /* CONFIG_ARCH_OMAP5 */
/* Install open and close handlers for ref-counting */
ps_vma->vm_ops = &MMapIOOps;
@@ -1132,13 +1122,9 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
goto unlock_and_return;
}
- PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0);
-
- psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
+ PVR_ASSERT(psOffsetStruct->uiUserVAddr == 0);
- /* Invalidate for the ION memory is performed during the mapping */
- if(psOffsetStruct->psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ION)
- psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate = IMG_FALSE;
+ psOffsetStruct->uiUserVAddr = ps_vma->vm_start;
/* Compute the flush region (if necessary) inside the mmap mutex */
if(psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate)
@@ -1149,19 +1135,19 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
if (psFlushMemArea->hBMHandle)
{
pvBase = (IMG_VOID *)ps_vma->vm_start;
- ui32ByteOffset = 0;
- ui32FlushSize = BM_GetVirtualSize(psFlushMemArea->hBMHandle);
+ uiByteOffset = 0;
+ uiFlushSize = BM_GetVirtualSize(psFlushMemArea->hBMHandle);
}
else
{
- IMG_UINT32 ui32DummyByteSize;
+ IMG_SIZE_T uiDummyByteSize;
DetermineUsersSizeAndByteOffset(psFlushMemArea,
- &ui32DummyByteSize,
- &ui32ByteOffset);
+ &uiDummyByteSize,
+ &uiByteOffset);
- pvBase = (IMG_VOID *)ps_vma->vm_start + ui32ByteOffset;
- ui32FlushSize = psFlushMemArea->ui32ByteSize;
+ pvBase = (IMG_VOID *)ps_vma->vm_start + uiByteOffset;
+ uiFlushSize = psFlushMemArea->uiByteSize;
}
psFlushMemArea->bNeedsCacheInvalidate = IMG_FALSE;
@@ -1170,8 +1156,8 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
/* Call the open routine to increment the usage count */
MMapVOpenNoLock(ps_vma);
- PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
- __FUNCTION__, ps_vma->vm_pgoff));
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x" UINTPTR_FMT "\n",
+ __FUNCTION__, (IMG_UINTPTR_T)ps_vma->vm_pgoff));
unlock_and_return:
if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
@@ -1183,8 +1169,8 @@ unlock_and_return:
if(psFlushMemArea)
{
- OSInvalidateCPUCacheRangeKM(psFlushMemArea, ui32ByteOffset, pvBase,
- ui32FlushSize);
+ OSInvalidateCPUCacheRangeKM(psFlushMemArea, uiByteOffset, pvBase,
+ uiFlushSize);
}
return iRetVal;
@@ -1204,7 +1190,7 @@ static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL sta
{
if(start)
{
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
}
else
{
@@ -1262,7 +1248,6 @@ static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t
return ProcSeqOff2ElementMMapRegistrations(sfile,off);
}
-
/*
* Show MMap element (called when reading /proc/mmap file)
@@ -1274,15 +1259,15 @@ static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
{
KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
LinuxMemArea *psLinuxMemArea;
- IMG_UINT32 ui32RealByteSize;
- IMG_UINT32 ui32ByteOffset;
+ IMG_SIZE_T uiRealByteSize;
+ IMG_UINTPTR_T uiByteOffset;
if(el == PVR_PROC_SEQ_START_TOKEN)
{
seq_printf( sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
"Allocations registered for mmap: %u\n"
- "In total these areas correspond to %u bytes\n"
+ "In total these areas correspond to %" SIZE_T_FMT_LEN "u bytes\n"
"psLinuxMemArea "
"UserVAddr "
"KernelVAddr "
@@ -1294,11 +1279,11 @@ static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
#else
"<mmap_header>\n"
"\t<count>%u</count>\n"
- "\t<bytes>%u</bytes>\n"
+ "\t<bytes>%" SIZE_T_FMT_LEN "u</bytes>\n"
"</mmap_header>\n",
#endif
g_ui32RegisteredAreas,
- g_ui32TotalByteSize
+ g_uiTotalByteSize
);
return;
}
@@ -1306,20 +1291,20 @@ static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
DetermineUsersSizeAndByteOffset(psLinuxMemArea,
- &ui32RealByteSize,
- &ui32ByteOffset);
+ &uiRealByteSize,
+ &uiByteOffset);
seq_printf( sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
- "%-8p %08x %-8p %08x %08x %-8d %-24s %-5u %-8s %08x(%s)\n",
+ "%p %p %p " CPUPADDR_FMT " " UINTPTR_FMT " %" SIZE_T_FMT_LEN "u %-24s %-5u %-8s %08x(%s)\n",
#else
"<mmap_record>\n"
- "\t<pointer>%-8p</pointer>\n"
- "\t<user_virtual>%-8x</user_virtual>\n"
- "\t<kernel_virtual>%-8p</kernel_virtual>\n"
- "\t<cpu_physical>%08x</cpu_physical>\n"
- "\t<mmap_offset>%08x</mmap_offset>\n"
- "\t<bytes>%-8d</bytes>\n"
+ "\t<pointer>%p</pointer>\n"
+ "\t<user_virtual>%p</user_virtual>\n"
+ "\t<kernel_virtual>%p</kernel_virtual>\n"
+ "\t<cpu_physical>" CPUPADDR_FMT "</cpu_physical>\n"
+ "\t<mmap_offset>" UINTPTR_FMT "</mmap_offset>\n"
+ "\t<bytes>%" SIZE_T_FMT_LEN "u</bytes>\n"
"\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
"\t<pid>%-5u</pid>\n"
"\t<name>%-8s</name>\n"
@@ -1328,11 +1313,11 @@ static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
"</mmap_record>\n",
#endif
psLinuxMemArea,
- psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
+ (IMG_PVOID)(psOffsetStruct->uiUserVAddr + uiByteOffset),
LinuxMemAreaToCpuVAddr(psLinuxMemArea),
LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
- psOffsetStruct->ui32MMapOffset,
- psLinuxMemArea->ui32ByteSize,
+ (IMG_UINTPTR_T)psOffsetStruct->uiMMapOffset,
+ psLinuxMemArea->uiByteSize,
LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
psOffsetStruct->ui32PID,
psOffsetStruct->pszName,
@@ -1365,7 +1350,7 @@ PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
#endif
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
PVR_DPF((PVR_DBG_MESSAGE,
@@ -1397,7 +1382,7 @@ PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
*/
if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
- g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
+ g_uiTotalByteSize += psLinuxMemArea->uiByteSize;
}
#endif
@@ -1430,7 +1415,7 @@ PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
PVRSRV_ERROR eError;
PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
@@ -1468,7 +1453,7 @@ PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
g_ui32RegisteredAreas--;
if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
- g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize;
+ g_uiTotalByteSize -= psLinuxMemArea->uiByteSize;
}
#endif
@@ -1523,7 +1508,7 @@ LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
{
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.h b/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.h
index 7140c13a8d2..72640e32e01 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.h
@@ -77,9 +77,9 @@ typedef struct KV_OFFSET_STRUCT_TAG
* contiguous), or it may represent the secure handle associated
* with the area.
*/
- IMG_UINT32 ui32MMapOffset;
-
- IMG_UINT32 ui32RealByteSize;
+ IMG_UINTPTR_T uiMMapOffset;
+
+ IMG_SIZE_T uiRealByteSize;
/* Memory area associated with this offset structure */
LinuxMemArea *psLinuxMemArea;
@@ -107,7 +107,7 @@ typedef struct KV_OFFSET_STRUCT_TAG
* User mode address of start of mapping. This is not necessarily the
* first user mode address of the memory area.
*/
- IMG_UINT32 ui32UserVAddr;
+ IMG_UINTPTR_T uiUserVAddr;
/* Extra entries to support proc filesystem debug info */
#if defined(DEBUG_LINUX_MMAP_AREAS)
@@ -187,15 +187,11 @@ PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
* @Return PVRSRV_ERROR
******************************************************************************/
PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
-#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hMHandle,
-#else
IMG_HANDLE hMHandle,
-#endif
- IMG_UINT32 *pui32MMapOffset,
- IMG_UINT32 *pui32ByteOffset,
- IMG_UINT32 *pui32RealByteSize,
- IMG_UINT32 *pui32UserVAddr);
+ IMG_UINTPTR_T *puiMMapOffset,
+ IMG_UINTPTR_T *puiByteOffset,
+ IMG_SIZE_T *puiRealByteSize,
+ IMG_UINTPTR_T *puiUserVAddr);
/*!
*******************************************************************************
@@ -214,14 +210,10 @@ PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
******************************************************************************/
PVRSRV_ERROR
PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
-#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hMHandle,
-#else
IMG_HANDLE hMHandle,
-#endif
IMG_BOOL *pbMUnmap,
- IMG_UINT32 *pui32RealByteSize,
- IMG_UINT32 *pui32UserVAddr);
+ IMG_SIZE_T *puiRealByteSize,
+ IMG_UINTPTR_T *puiUserVAddr);
/*!
*******************************************************************************
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/module.c b/drivers/gpu/pvr/services4/srvkm/env/linux/module.c
index 487069daf46..a86de684c0a 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/module.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/module.c
@@ -83,7 +83,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
-#include <linux/proc_fs.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
#if defined(SUPPORT_DRI_DRM)
#include <drm/drmP.h>
@@ -129,6 +132,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "lock.h"
#include "linkage.h"
#include "buffer_manager.h"
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#include "pvr_sync.h"
+#endif
+
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE)
+#include "systrace.h"
+#endif
#if defined(SUPPORT_DRI_DRM)
#include "pvr_drm.h"
@@ -160,19 +170,16 @@ module_param(gPVRDebugLevel, uint, 0644);
MODULE_PARM_DESC(gPVRDebugLevel, "Sets the level of debug output (default 0x7)");
#endif /* defined(PVRSRV_NEED_PVR_DPF) */
-#if defined(CONFIG_ION_OMAP)
-#include <linux/ion.h>
-#include <linux/omap_ion.h>
-#include "ion.h"
-extern void omap_ion_register_pvr_export(void *);
-extern struct ion_device *omap_ion_device;
-struct ion_client *gpsIONClient;
-EXPORT_SYMBOL(gpsIONClient);
-#endif /* defined(CONFIG_ION_OMAP) */
+/* Newer kernels no longer support __devinitdata */
+#if !defined(__devinitdata)
+#define __devinitdata
+#endif
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
/* PRQA S 3207 2 */ /* ignore 'not used' warning */
EXPORT_SYMBOL(PVRGetDisplayClassJTable);
EXPORT_SYMBOL(PVRGetBufferClassJTable);
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
#if defined(PVR_LDM_DEVICE_CLASS) && !defined(SUPPORT_DRI_DRM)
/*
@@ -262,10 +269,21 @@ static struct platform_device_id powervr_id_table[] __devinitdata = {
};
#endif
+#ifdef CONFIG_OF
+static const struct of_device_id omap_gpu_id_table[] = {
+ { .compatible = "ti,omap4-gpu" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, omap_gpu_id_table);
+#endif
+
static LDM_DRV powervr_driver = {
#if defined(PVR_LDM_PLATFORM_MODULE)
.driver = {
.name = DRVNAME,
+#ifdef CONFIG_OF
+ .of_match_table = of_match_ptr(omap_gpu_id_table),
+#endif
},
#endif
#if defined(PVR_LDM_PCI_MODULE)
@@ -355,20 +373,6 @@ static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device
}
}
-#if defined(CONFIG_ION_OMAP)
- gpsIONClient = ion_client_create(omap_ion_device,
- 1 << ION_HEAP_TYPE_CARVEOUT |
- 1 << OMAP_ION_HEAP_TYPE_TILER |
- 1 << ION_HEAP_TYPE_SYSTEM,
- "pvr");
- if (IS_ERR_OR_NULL(gpsIONClient))
- {
- PVR_DPF((PVR_DBG_ERROR, "PVRSRVDriverProbe: Couldn't create ion client"));
- return PTR_ERR(gpsIONClient);
- }
- omap_ion_register_pvr_export(&PVRSRVExportFDToIONHandles);
-#endif /* defined(CONFIG_ION_OMAP) */
-
return 0;
}
@@ -403,11 +407,6 @@ static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
-#if defined(CONFIG_ION_OMAP)
- ion_client_destroy(gpsIONClient);
- gpsIONClient = IMG_NULL;
-#endif
-
SysAcquireData(&psSysData);
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
@@ -473,7 +472,7 @@ PVR_MOD_STATIC void PVRSRVDriverShutdown(LDM_DEV *pDevice)
{
PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
- LinuxLockMutex(&gsPMMutex);
+ LinuxLockMutexNested(&gsPMMutex, PVRSRV_LOCK_CLASS_POWER);
if (!bDriverIsShutdown && !bDriverIsSuspended)
{
@@ -482,7 +481,7 @@ PVR_MOD_STATIC void PVRSRVDriverShutdown(LDM_DEV *pDevice)
* processes trying to use the driver after it has been
* shutdown.
*/
- LinuxLockMutex(&gPVRSRVLock);
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
(void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
}
@@ -539,11 +538,11 @@ PVR_MOD_STATIC int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
- LinuxLockMutex(&gsPMMutex);
+ LinuxLockMutexNested(&gsPMMutex, PVRSRV_LOCK_CLASS_POWER);
if (!bDriverIsSuspended && !bDriverIsShutdown)
{
- LinuxLockMutex(&gPVRSRVLock);
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) == PVRSRV_OK)
{
@@ -596,7 +595,7 @@ PVR_MOD_STATIC int PVRSRVDriverResume(LDM_DEV *pDevice)
#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
- LinuxLockMutex(&gsPMMutex);
+ LinuxLockMutexNested(&gsPMMutex, PVRSRV_LOCK_CLASS_POWER);
if (bDriverIsSuspended && !bDriverIsShutdown)
{
@@ -709,10 +708,10 @@ void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)
@Description
- Release access the PVR services node - called when a file is closed, whether
- at exit or using close(2) system call.
+ Open the PVR services node - called when the relevant device node is open()ed.
@input pInode - the inode for the file being openeded
+ @input dev - the DRM device corresponding to this driver.
@input pFile - the file handle data for the actual file being opened
@@ -734,7 +733,7 @@ static int PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
#endif
- LinuxLockMutex(&gPVRSRVLock);
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
ui32PID = OSGetCurrentProcessIDKM();
@@ -759,11 +758,7 @@ static int PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
if(eError != PVRSRV_OK)
goto err_unlock;
-#if defined (SUPPORT_SID_INTERFACE)
- psPrivateData->hKernelMemInfo = 0;
-#else
psPrivateData->hKernelMemInfo = NULL;
-#endif
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
psPrivateData->psDRMFile = pFile;
@@ -805,7 +800,7 @@ static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
int err = 0;
- LinuxLockMutex(&gPVRSRVLock);
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
#if defined(SUPPORT_DRI_DRM)
psPrivateData = (PVRSRV_FILE_PRIVATE_DATA *)pvPrivData;
@@ -925,6 +920,8 @@ static int __init PVRCore_Init(void)
struct device *psDev;
#endif
+
+
#if !defined(SUPPORT_DRI_DRM)
/*
* Must come before attempting to print anything via Services.
@@ -960,6 +957,7 @@ static int __init PVRCore_Init(void)
}
LinuxBridgeInit();
+
PVRMMapInit();
@@ -1054,6 +1052,13 @@ static int __init PVRCore_Init(void)
#endif /* defined(PVR_LDM_DEVICE_CLASS) */
#endif /* !defined(SUPPORT_DRI_DRM) */
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE)
+ SystraceCreateFS();
+#endif
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ PVRSyncDeviceInit();
+#endif
return 0;
#if !defined(SUPPORT_DRI_DRM)
@@ -1063,6 +1068,8 @@ destroy_class:
unregister_device:
unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME);
#endif
+#endif
+#if !defined(SUPPORT_DRI_DRM)
sys_deinit:
#endif
#if defined(PVR_LDM_MODULE)
@@ -1095,7 +1102,6 @@ init_failed:
LinuxBridgeDeInit();
PVROSFuncDeInit();
RemoveProcEntries();
-
return error;
} /*PVRCore_Init*/
@@ -1141,6 +1147,10 @@ static void __exit PVRCore_Cleanup(void)
SysAcquireData(&psSysData);
#endif
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ PVRSyncDeviceDeInit();
+#endif
+
#if !defined(SUPPORT_DRI_DRM)
#if defined(PVR_LDM_DEVICE_CLASS)
@@ -1199,6 +1209,10 @@ static void __exit PVRCore_Cleanup(void)
RemoveProcEntries();
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE)
+ SystraceDestroyFS();
+#endif
+
PVR_TRACE(("PVRCore_Cleanup: unloading"));
}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.c b/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.c
index 2cd666f5ca4..56422d6ecd5 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.c
@@ -66,6 +66,11 @@ IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
mutex_lock(psPVRSRVMutex);
}
+IMG_VOID LinuxLockMutexNested(PVRSRV_LINUX_MUTEX *psPVRSRVMutex, unsigned int uiLockClass)
+{
+ mutex_lock_nested(psPVRSRVMutex, uiLockClass);
+}
+
PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
{
if(mutex_lock_interruptible(psPVRSRVMutex) == -EINTR)
@@ -109,6 +114,11 @@ IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
atomic_dec(&psPVRSRVMutex->Count);
}
+IMG_VOID LinuxLockMutexNested(PVRSRV_LINUX_MUTEX *psPVRSRVMutex, unsigned int uiLockClass)
+{
+ LinuxLockMutex(psPVRSRVMutex);
+}
+
PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
{
if(down_interruptible(&psPVRSRVMutex->sSemaphore) == -EINTR)
@@ -131,7 +141,7 @@ IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
atomic_dec(&psPVRSRVMutex->Count);
}
- return Status;
+ return Status == 0;
}
IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.h b/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.h
index c590da15c69..09ae46d4183 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.h
@@ -72,11 +72,21 @@ typedef struct {
#endif
+enum PVRSRV_MUTEX_LOCK_CLASS
+{
+ PVRSRV_LOCK_CLASS_POWER,
+ PVRSRV_LOCK_CLASS_BRIDGE,
+ PVRSRV_LOCK_CLASS_MMAP,
+ PVRSRV_LOCK_CLASS_MM_DEBUG,
+ PVRSRV_LOCK_CLASS_PVR_DEBUG,
+};
extern IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
extern IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+extern IMG_VOID LinuxLockMutexNested(PVRSRV_LINUX_MUTEX *psPVRSRVMutex, unsigned int uiLockClass);
+
extern PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
extern IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.c b/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.c
index 8e57476fd9b..8e57476fd9b 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.c
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.h b/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.h
index 891598c28b7..6bcee26e3eb 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.h
@@ -63,13 +63,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#else
#if defined(__arm__) || defined(__sh__)
#define PGPROT_WC(pv) pgprot_writecombine(pv)
+ #elif defined(__mips__)
+ #define PGPROT_WC(pv) pgprot_noncached_wa(pv)
+ #elif defined(__i386__) || defined(__x86_64)
+ /* PAT support supersedes this */
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
#else
- #if defined(__i386__) || defined(__mips__)
- #define PGPROT_WC(pv) pgprot_noncached(pv)
- #else
- #define PGPROT_WC(pv) pgprot_noncached(pv)
- #error Unsupported architecture!
- #endif
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
+ #error Unsupported architecture!
#endif
#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/osfunc.c b/drivers/gpu/pvr/services4/srvkm/env/linux/osfunc.c
index ca405828173..f2803abc024 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/osfunc.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/osfunc.c
@@ -49,7 +49,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <asm/io.h>
#include <asm/page.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
#include <asm/system.h>
#endif
#include <asm/cacheflush.h>
@@ -66,6 +66,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <linux/interrupt.h>
#include <asm/hardirq.h>
#include <linux/timer.h>
+#if defined(MEM_TRACK_INFO_DEBUG)
+#include <linux/time.h>
+#endif
#include <linux/capability.h>
#include <asm/uaccess.h>
#include <linux/spinlock.h>
@@ -83,22 +86,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "pvrmmap.h"
#include "mmap.h"
#include "env_data.h"
-#include "proc.h"
#include "mutex.h"
#include "event.h"
#include "linkage.h"
#include "pvr_uaccess.h"
#include "lock.h"
-#include <syslocal.h>
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#include "pvr_sync.h"
+#endif
#if defined (SUPPORT_ION)
#include "ion.h"
#endif
-#if defined (CONFIG_X86_PAE)
-#error Physical Address Extension not supported with the driver
-#endif
-
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
#else
@@ -123,21 +123,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif /* EMULATOR */
#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uiSize, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
#else
-PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uiSize, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
#endif
{
PVR_UNREFERENCED_PARAMETER(ui32Flags);
PVR_UNREFERENCED_PARAMETER(phBlockAlloc);
- if (ui32Size > PAGE_SIZE)
+ if (uiSize > PAGE_SIZE)
{
/* Try to allocate the memory using vmalloc */
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename, ui32Line);
+ *ppvCpuVAddr = _VMallocWrapper(uiSize, PVRSRV_HAP_CACHED, pszFilename, ui32Line);
#else
- *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
+ *ppvCpuVAddr = VMallocWrapper(uiSize, PVRSRV_HAP_CACHED);
#endif
if (*ppvCpuVAddr)
{
@@ -146,9 +146,9 @@ PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOI
}
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- *ppvCpuVAddr = _KMallocWrapper(ui32Size, GFP_KERNEL | __GFP_NOWARN, pszFilename, ui32Line);
+ *ppvCpuVAddr = _KMallocWrapper(uiSize, GFP_KERNEL | __GFP_NOWARN, pszFilename, ui32Line);
#else
- *ppvCpuVAddr = KMallocWrapper(ui32Size, GFP_KERNEL | __GFP_NOWARN);
+ *ppvCpuVAddr = KMallocWrapper(uiSize, GFP_KERNEL | __GFP_NOWARN);
#endif
if (!*ppvCpuVAddr)
{
@@ -169,13 +169,13 @@ static inline int is_vmalloc_addr(const void *pvCpuVAddr)
#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)) */
#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uiSize, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
#else
-PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uiSize, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
#endif
{
PVR_UNREFERENCED_PARAMETER(ui32Flags);
- PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
PVR_UNREFERENCED_PARAMETER(hBlockAlloc);
if (is_vmalloc_addr(pvCpuVAddr))
@@ -201,7 +201,7 @@ PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID
PVRSRV_ERROR
OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
- IMG_UINT32 ui32Size,
+ IMG_SIZE_T uiSize,
IMG_UINT32 ui32PageSize,
IMG_PVOID pvPrivData,
IMG_UINT32 ui32PrivDataLength,
@@ -223,27 +223,11 @@ OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
}
#endif
- if(ui32AllocFlags & PVRSRV_MEM_ION)
- {
- /* We'll only see HAP_SINGLE_PROCESS with MEM_ION */
- BUG_ON((ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) != PVRSRV_HAP_SINGLE_PROCESS);
-
- psLinuxMemArea = NewIONLinuxMemArea(ui32Size, ui32AllocFlags,
- pvPrivData, ui32PrivDataLength);
- if(!psLinuxMemArea)
- {
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
-
- PVRMMapRegisterArea(psLinuxMemArea);
- goto ExitSkipSwitch;
- }
-
switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
{
case PVRSRV_HAP_KERNEL_ONLY:
{
- psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ psLinuxMemArea = NewVMallocLinuxMemArea(uiSize, ui32AllocFlags);
if(!psLinuxMemArea)
{
return PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -255,7 +239,7 @@ OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
/* Currently PVRSRV_HAP_SINGLE_PROCESS implies that we dont need a
* kernel virtual mapping, but will need a user space virtual mapping */
- psLinuxMemArea = NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
+ psLinuxMemArea = NewAllocPagesLinuxMemArea(uiSize, ui32AllocFlags);
if(!psLinuxMemArea)
{
return PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -279,7 +263,7 @@ OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
* VIPT architectures. */
ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
#endif
- psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ psLinuxMemArea = NewVMallocLinuxMemArea(uiSize, ui32AllocFlags);
if(!psLinuxMemArea)
{
return PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -303,7 +287,6 @@ OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
psLinuxMemArea->hBMHandle = hBMHandle;
}
-ExitSkipSwitch:
*ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
*phOSMemHandle = psLinuxMemArea;
@@ -314,12 +297,12 @@ ExitSkipSwitch:
PVRSRV_ERROR
-OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle)
+OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_SIZE_T uiBytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle)
{
LinuxMemArea *psLinuxMemArea;
PVRSRV_ERROR eError;
- PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(uiBytes);
PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
@@ -334,9 +317,9 @@ OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAdd
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,
- "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%d, "
+ "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%" SIZE_T_FMT_LEN "u, "
"pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
- ui32AllocFlags, ui32Bytes, pvCpuVAddr, hOSMemHandle));
+ ui32AllocFlags, uiBytes, pvCpuVAddr, hOSMemHandle));
return eError;
}
break;
@@ -351,31 +334,11 @@ OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAdd
return PVRSRV_OK;
}
-IMG_INT32
-OSGetMemMultiPlaneInfo(IMG_HANDLE hOSMemHandle, IMG_UINT32* pui32AddressOffsets,
- IMG_UINT32* ui32NumAddrOffsets)
-{
- LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
-
- if(!ui32NumAddrOffsets)
- return -1;
-
- if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ION)
- return GetIONLinuxMemAreaInfo(psLinuxMemArea, pui32AddressOffsets, ui32NumAddrOffsets);
-
- if(!pui32AddressOffsets)
- return -1;
-
- *pui32AddressOffsets = 0;
- *ui32NumAddrOffsets = 1;
-
- return psLinuxMemArea->ui32ByteSize;
-}
PVRSRV_ERROR
OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
- IMG_UINT32 ui32ByteOffset,
- IMG_UINT32 ui32Bytes,
+ IMG_UINTPTR_T uiByteOffset,
+ IMG_SIZE_T uiBytes,
IMG_UINT32 ui32Flags,
IMG_HANDLE *phOSMemHandleRet)
{
@@ -384,7 +347,7 @@ OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
psParentLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
- psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
+ psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, uiByteOffset, uiBytes);
if(!psLinuxMemArea)
{
*phOSMemHandleRet = NULL;
@@ -436,11 +399,11 @@ OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags)
IMG_CPU_PHYADDR
-OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset)
+OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINTPTR_T uiByteOffset)
{
PVR_ASSERT(hOSMemHandle);
- return LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+ return LinuxMemAreaToCpuPAddr(hOSMemHandle, uiByteOffset);
}
@@ -471,7 +434,7 @@ IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle)
@Return none
******************************************************************************/
-IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_SIZE_T uiSize)
{
#if defined(USE_UNOPTIMISED_MEMCPY)
IMG_UINT8 *Src,*Dst;
@@ -479,12 +442,12 @@ IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
Src=(IMG_UINT8 *)pvSrc;
Dst=(IMG_UINT8 *)pvDst;
- for(i=0;i<ui32Size;i++)
+ for(i=0;i<uiSize;i++)
{
Dst[i]=Src[i];
}
#else
- memcpy(pvDst, pvSrc, ui32Size);
+ memcpy(pvDst, pvSrc, uiSize);
#endif
}
@@ -505,19 +468,19 @@ IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
@Return IMG_VOID
******************************************************************************/
-IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T uiSize)
{
#if defined(USE_UNOPTIMISED_MEMSET)
IMG_UINT8 *Buff;
IMG_INT i;
Buff=(IMG_UINT8 *)pvDest;
- for(i=0;i<ui32Size;i++)
+ for(i=0;i<uiSize;i++)
{
Buff[i]=ui8Value;
}
#else
- memset(pvDest, (IMG_INT) ui8Value, (size_t) ui32Size);
+ memset(pvDest, (IMG_INT) ui8Value, (size_t) uiSize);
#endif
}
@@ -537,13 +500,13 @@ IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
@Function OSSNPrintf
@Description snprintf
******************************************************************************/
-IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...)
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T uiSize, const IMG_CHAR *pszFormat, ...)
{
va_list argList;
IMG_INT32 iCount;
va_start(argList, pszFormat);
- iCount = vsnprintf(pStr, (size_t)ui32Size, pszFormat, argList);
+ iCount = vsnprintf(pStr, (size_t)uiSize, pszFormat, argList);
va_end(argList);
return iCount;
@@ -839,59 +802,22 @@ IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
#endif
}
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
-int OSGetProcCmdline(IMG_UINT32 ui32PID, char * buffer, int buff_size)
-{
- int res = 0;
- unsigned int len;
- struct task_struct *task = pid_task(find_vpid(ui32PID), PIDTYPE_PID);
- struct mm_struct *mm = task ? get_task_mm(task) : IMG_NULL;
- if (!mm)
- goto out;
- if (!mm->arg_end)
- goto out_mm; /* Shh! No looking before we're done */
-
- len = mm->arg_end - mm->arg_start;
-
- if (len > buff_size)
- len = buff_size;
+#if defined(MEM_TRACK_INFO_DEBUG)
+/*!
+******************************************************************************
- res = pvr_access_process_vm(task, mm->arg_start, buffer, len, 0);
+ @Function OSGetCurrentTimeInUSecsKM
+
+ @Description Returns current time in usecs
- // If the nul at the end of args has been overwritten, then
- // assume application is using setproctitle(3).
- if (res > 0 && buffer[res-1] != '\0' && len < buff_size) {
- len = strnlen(buffer, res);
- if (len < res) {
- res = len;
- } else {
- len = mm->env_end - mm->env_start;
- if (len > buff_size - res)
- len = buff_size - res;
- res += pvr_access_process_vm(task, mm->env_start, buffer+res, len, 0);
- res = strnlen(buffer, res);
- }
- }
-out_mm:
- mmput(mm);
-out:
- return res;
-}
+ @Return ID of current process
-const char* OSGetPathBaseName(char * buffer, int buff_size)
+*****************************************************************************/
+IMG_UINT32 OSGetCurrentTimeInUSecsKM(IMG_VOID)
{
- const char *base_name = buffer;
- while (1)
- {
- const char *next = strnchr(base_name, buff_size, '/');
- if (!next)
- break;
-
- buff_size -= (next - base_name -1);
- base_name = (next + 1);
-
- }
- return base_name;
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ return (tv.tv_sec * 1000000 + tv.tv_usec);
}
#endif
@@ -1197,6 +1123,10 @@ static void MISRWrapper(
SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData;
PVRSRVMISR(psSysData);
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+ PVRSyncUpdateAllSyncs();
+#endif
}
@@ -1703,7 +1633,7 @@ IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle,
******************************************************************************/
IMG_VOID *
OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uiBytes,
IMG_UINT32 ui32MappingFlags,
IMG_HANDLE *phOSMemHandle)
{
@@ -1717,7 +1647,7 @@ OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
if(phOSMemHandle == IMG_NULL)
{
IMG_VOID *pvIORemapCookie;
- pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
+ pvIORemapCookie = IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags);
if(pvIORemapCookie == IMG_NULL)
{
return IMG_NULL;
@@ -1726,7 +1656,7 @@ OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
}
else
{
- LinuxMemArea *psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ LinuxMemArea *psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, uiBytes, ui32MappingFlags);
if(psLinuxMemArea == IMG_NULL)
{
@@ -1752,9 +1682,9 @@ OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
@Return TRUE on success, else FALSE
******************************************************************************/
IMG_BOOL
-OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
+OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T uiBytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
{
- PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(uiBytes);
if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
{
@@ -1868,19 +1798,19 @@ RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
PVRSRV_ERROR
OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
IMG_VOID *pvCPUVAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uiBytes,
IMG_UINT32 ui32MappingFlags,
IMG_HANDLE *phOSMemHandle)
{
IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
- return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle);
+ return RegisterExternalMem(&SysPAddr, pvCPUVAddr, uiBytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle);
}
-PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle)
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle)
{
- return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle);
+ return RegisterExternalMem(pBasePAddr, pvCPUVAddr, uBytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle);
}
@@ -1892,7 +1822,7 @@ PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPU
******************************************************************************/
PVRSRV_ERROR
OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uiBytes,
IMG_UINT32 ui32MappingFlags,
IMG_HANDLE hOSMemHandle)
{
@@ -1900,7 +1830,7 @@ OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
PVRSRV_ERROR eError;
PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
- PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(uiBytes);
switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
{
@@ -1912,8 +1842,8 @@ OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
if (eError != PVRSRV_OK)
{
- PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
- __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %" SIZE_T_FMT_LEN "u, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, uiBytes,
ui32MappingFlags, hOSMemHandle));
return eError;
}
@@ -1931,9 +1861,9 @@ OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
return PVRSRV_OK;
}
-PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
{
- return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+ return OSUnRegisterMem(pvCpuVAddr, uBytes, ui32Flags, hOSMemHandle);
}
/*!
@@ -1946,7 +1876,7 @@ PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes
******************************************************************************/
PVRSRV_ERROR
OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uiBytes,
IMG_UINT32 ui32MappingFlags,
IMG_HANDLE hBMHandle,
IMG_VOID **ppvCpuVAddr,
@@ -1972,7 +1902,7 @@ OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
* mapping is required for the allocation and no user virtual
* mappings are allowed: Note these eat into our limited kernel
* virtual address space */
- psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, uiBytes, ui32MappingFlags);
if(!psLinuxMemArea)
{
return PVRSRV_ERROR_BAD_MAPPING;
@@ -1983,7 +1913,7 @@ OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
{
/* Currently this implies that we dont need a kernel virtual
* mapping, but will need a user space virtual mapping */
- psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, uiBytes, ui32MappingFlags);
if(!psLinuxMemArea)
{
return PVRSRV_ERROR_BAD_MAPPING;
@@ -2007,7 +1937,7 @@ OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
*/
ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
#endif
- psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, uiBytes, ui32MappingFlags);
if(!psLinuxMemArea)
{
return PVRSRV_ERROR_BAD_MAPPING;
@@ -2048,7 +1978,7 @@ OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
******************************************************************************/
PVRSRV_ERROR
OSUnReservePhys(IMG_VOID *pvCpuVAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uiBytes,
IMG_UINT32 ui32MappingFlags,
IMG_HANDLE hOSMemHandle)
{
@@ -2056,7 +1986,7 @@ OSUnReservePhys(IMG_VOID *pvCpuVAddr,
PVRSRV_ERROR eError;
PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
- PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(uiBytes);
psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
@@ -2070,8 +2000,8 @@ OSUnReservePhys(IMG_VOID *pvCpuVAddr,
eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
if (eError != PVRSRV_OK)
{
- PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
- __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %" SIZE_T_FMT_LEN "u, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, uiBytes,
ui32MappingFlags, hOSMemHandle));
return eError;
}
@@ -2098,10 +2028,10 @@ OSUnReservePhys(IMG_VOID *pvCpuVAddr,
@Output ppvLinAddr - pointer to variable that will receive the linear address of buffer
@Return PVRSRV_OK if allocation successed else returns PVRSRV_ERROR_OUT_OF_MEMORY
**************************************************************************/
-PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T uiSize, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
{
#if !defined(NO_HARDWARE)
- PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
PVR_UNREFERENCED_PARAMETER(pvLinAddr);
PVR_UNREFERENCED_PARAMETER(psPhysAddr);
PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__));
@@ -2118,9 +2048,9 @@ PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLi
IMG_VOID *pvKernLinAddr;
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- pvKernLinAddr = _KMallocWrapper(ui32Size, GFP_KERNEL, __FILE__, __LINE__);
+ pvKernLinAddr = _KMallocWrapper(uiSize, GFP_KERNEL, __FILE__, __LINE__);
#else
- pvKernLinAddr = KMallocWrapper(ui32Size, GFP_KERNEL);
+ pvKernLinAddr = KMallocWrapper(uiSize, GFP_KERNEL);
#endif
if (!pvKernLinAddr)
{
@@ -2142,16 +2072,16 @@ PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLi
@Description Frees memory allocated with OSBaseAllocContigMemory
@Input LinAddr - pointer to buffer allocated with OSBaseAllocContigMemory
**************************************************************************/
-PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_SIZE_T uiSize, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
{
#if !defined(NO_HARDWARE)
- PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
PVR_UNREFERENCED_PARAMETER(pvLinAddr);
PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
#else
- PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(uiSize);
PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
KFreeWrapper(pvLinAddr);
@@ -2762,9 +2692,9 @@ static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
@Return NONE
******************************************************************************/
-static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
+static IMG_VOID OSTimerCallbackWrapper(IMG_UINTPTR_T uiData)
{
- TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data;
+ TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)uiData;
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
int res;
@@ -2814,7 +2744,7 @@ static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
{
TIMER_CALLBACK_DATA *psTimerCBData;
- IMG_UINT32 ui32i;
+ IMG_UINTPTR_T ui;
#if !(defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE))
unsigned long ulLockFlags;
#endif
@@ -2832,9 +2762,9 @@ IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32
#else
spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
#endif
- for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ for (ui = 0; ui < OS_MAX_TIMERS; ui++)
{
- psTimerCBData = &sTimers[ui32i];
+ psTimerCBData = &sTimers[ui];
if (!psTimerCBData->bInUse)
{
psTimerCBData->bInUse = IMG_TRUE;
@@ -2846,7 +2776,7 @@ IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32
#else
spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
#endif
- if (ui32i >= OS_MAX_TIMERS)
+ if (ui >= OS_MAX_TIMERS)
{
PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use"));
return IMG_NULL;
@@ -2870,19 +2800,19 @@ IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32
/* setup timer object */
/* PRQA S 0307,0563 1 */ /* ignore warning about inconpartible ptr casting */
psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
- psTimerCBData->sTimer.data = (IMG_UINT32)psTimerCBData;
+ psTimerCBData->sTimer.data = (IMG_UINTPTR_T)psTimerCBData;
- return (IMG_HANDLE)(ui32i + 1);
+ return (IMG_HANDLE)(ui + 1);
}
static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
{
- IMG_UINT32 ui32i = ((IMG_UINT32)hTimer) - 1;
+ IMG_UINTPTR_T ui = ((IMG_UINTPTR_T)hTimer) - 1;
- PVR_ASSERT(ui32i < OS_MAX_TIMERS);
+ PVR_ASSERT(ui < OS_MAX_TIMERS);
- return &sTimers[ui32i];
+ return &sTimers[ui];
}
/*!
@@ -3016,11 +2946,7 @@ PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
@Return PVRSRV_ERROR :
******************************************************************************/
-#if defined (SUPPORT_SID_INTERFACE)
-PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT_KM *psEventObject)
-#else
PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *psEventObject)
-#endif
{
PVRSRV_ERROR eError = PVRSRV_OK;
@@ -3036,11 +2962,7 @@ PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *
{
/* autogenerate a name */
static IMG_UINT16 ui16NameIndex = 0;
-#if defined (SUPPORT_SID_INTERFACE)
- snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_KM_%d", ui16NameIndex++);
-#else
snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
-#endif
}
if(LinuxEventObjectListCreate(&psEventObject->hOSEventKM) != PVRSRV_OK)
@@ -3074,11 +2996,7 @@ PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *
@Return PVRSRV_ERROR :
******************************************************************************/
-#if defined (SUPPORT_SID_INTERFACE)
-PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT_KM *psEventObject)
-#else
PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT *psEventObject)
-#endif
{
PVRSRV_ERROR eError = PVRSRV_OK;
@@ -3149,11 +3067,7 @@ PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM)
@Return PVRSRV_ERROR :
******************************************************************************/
-#if defined (SUPPORT_SID_INTERFACE)
-PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
-#else
PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT *psEventObject,
-#endif
IMG_HANDLE *phOSEvent)
{
PVRSRV_ERROR eError = PVRSRV_OK;
@@ -3192,11 +3106,7 @@ PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT *psEventObject,
@Return PVRSRV_ERROR :
******************************************************************************/
-#if defined (SUPPORT_SID_INTERFACE)
-PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
-#else
PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT *psEventObject,
-#endif
IMG_HANDLE hOSEventKM)
{
PVRSRV_ERROR eError = PVRSRV_OK;
@@ -3291,11 +3201,11 @@ IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
IMG_VOID *pvDest,
IMG_VOID *pvSrc,
- IMG_UINT32 ui32Bytes)
+ IMG_SIZE_T uiBytes)
{
PVR_UNREFERENCED_PARAMETER(pvProcess);
- if(pvr_copy_to_user(pvDest, pvSrc, ui32Bytes)==0)
+ if(pvr_copy_to_user(pvDest, pvSrc, uiBytes)==0)
return PVRSRV_OK;
else
return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
@@ -3322,11 +3232,11 @@ PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
IMG_VOID *pvDest,
IMG_VOID *pvSrc,
- IMG_UINT32 ui32Bytes)
+ IMG_SIZE_T uiBytes)
{
PVR_UNREFERENCED_PARAMETER(pvProcess);
- if(pvr_copy_from_user(pvDest, pvSrc, ui32Bytes)==0)
+ if(pvr_copy_from_user(pvDest, pvSrc, uiBytes)==0)
return PVRSRV_OK;
else
return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
@@ -3350,7 +3260,7 @@ PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
@Return IMG_BOOL :
******************************************************************************/
-IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes)
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_SIZE_T uiBytes)
{
IMG_INT linuxType;
@@ -3364,7 +3274,7 @@ IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT
linuxType = VERIFY_WRITE;
}
- return access_ok(linuxType, pvUserPtr, ui32Bytes);
+ return access_ok(linuxType, pvUserPtr, uiBytes);
}
typedef enum _eWrapMemType_
@@ -3383,8 +3293,8 @@ typedef struct _sWrapMemInfo_
IMG_SYS_PHYADDR *psPhysAddr;
IMG_INT iPageOffset;
#if defined(DEBUG)
- IMG_UINT32 ulStartAddr;
- IMG_UINT32 ulBeyondEndAddr;
+ IMG_UINTPTR_T uStartAddr;
+ IMG_UINTPTR_T uBeyondEndAddr;
struct vm_area_struct *psVMArea;
#endif
} sWrapMemInfo;
@@ -3403,16 +3313,16 @@ typedef struct _sWrapMemInfo_
and must be writable. A get_page is done on the returned page structure.
@Input psVMArea - pointer to VM area structure
- ulCPUVAddr - CPU virtual address
- pulPFN - Pointer to returned PFN.
+ uCPUVAddr - CPU virtual address
+ pui32PFN - Pointer to returned PFN.
ppsPAge - Pointer to returned page structure pointer.
- @Output *pulPFN - Set to PFN
+ @Output *pui32PFN - Set to PFN
*ppsPage - Pointer to the page structure if present, else NULL.
@Return IMG_TRUE if PFN lookup was succesful.
******************************************************************************/
-static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUVAddr, IMG_UINT32 *pulPFN, struct page **ppsPage)
+static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINTPTR_T uCPUVAddr, IMG_UINT32 *pui32PFN, struct page **ppsPage)
{
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
pgd_t *psPGD;
@@ -3423,31 +3333,31 @@ static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUV
spinlock_t *psPTLock;
IMG_BOOL bRet = IMG_FALSE;
- *pulPFN = 0;
+ *pui32PFN = 0;
*ppsPage = NULL;
- psPGD = pgd_offset(psMM, ulCPUVAddr);
+ psPGD = pgd_offset(psMM, uCPUVAddr);
if (pgd_none(*psPGD) || pgd_bad(*psPGD))
return bRet;
- psPUD = pud_offset(psPGD, ulCPUVAddr);
+ psPUD = pud_offset(psPGD, uCPUVAddr);
if (pud_none(*psPUD) || pud_bad(*psPUD))
return bRet;
- psPMD = pmd_offset(psPUD, ulCPUVAddr);
+ psPMD = pmd_offset(psPUD, uCPUVAddr);
if (pmd_none(*psPMD) || pmd_bad(*psPMD))
return bRet;
- psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock);
+ psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, uCPUVAddr, &psPTLock);
if ((pte_none(*psPTE) == 0) && (pte_present(*psPTE) != 0) && (pte_write(*psPTE) != 0))
{
- *pulPFN = pte_pfn(*psPTE);
+ *pui32PFN = pte_pfn(*psPTE);
bRet = IMG_TRUE;
- if (pfn_valid(*pulPFN))
+ if (pfn_valid(*pui32PFN))
{
- *ppsPage = pfn_to_page(*pulPFN);
+ *ppsPage = pfn_to_page(*pui32PFN);
get_page(*ppsPage);
}
@@ -3600,7 +3510,7 @@ err_out:
return ui32PhysAddr;
}
-#endif /* defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER) */
+#endif /* defined(CONFIG_TI_TILER) && defined(CONFIG_DRM_OMAP_DMM_TILER) */
/*!
******************************************************************************
@@ -3613,17 +3523,17 @@ err_out:
******************************************************************************/
PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
- IMG_UINT32 ui32Bytes,
+ IMG_SIZE_T uiBytes,
IMG_SYS_PHYADDR *psSysPAddr,
IMG_HANDLE *phOSWrapMem)
{
- IMG_UINT32 ulStartAddrOrig = (IMG_UINT32) pvCPUVAddr;
- IMG_UINT32 ulAddrRangeOrig = (IMG_UINT32) ui32Bytes;
- IMG_UINT32 ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
- IMG_UINT32 ulStartAddr;
- IMG_UINT32 ulAddrRange;
- IMG_UINT32 ulBeyondEndAddr;
- IMG_UINT32 ulAddr;
+ IMG_UINTPTR_T uStartAddrOrig = (IMG_UINTPTR_T) pvCPUVAddr;
+ IMG_SIZE_T uAddrRangeOrig = uiBytes;
+ IMG_UINTPTR_T uBeyondEndAddrOrig = uStartAddrOrig + uAddrRangeOrig;
+ IMG_UINTPTR_T uStartAddr;
+ IMG_SIZE_T uAddrRange;
+ IMG_UINTPTR_T uBeyondEndAddr;
+ IMG_UINTPTR_T uAddr;
IMG_INT i;
struct vm_area_struct *psVMArea;
sWrapMemInfo *psInfo = NULL;
@@ -3633,19 +3543,19 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
/* Align start and end addresses to page boundaries */
- ulStartAddr = ulStartAddrOrig & PAGE_MASK;
- ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
- ulAddrRange = ulBeyondEndAddr - ulStartAddr;
+ uStartAddr = uStartAddrOrig & PAGE_MASK;
+ uBeyondEndAddr = PAGE_ALIGN(uBeyondEndAddrOrig);
+ uAddrRange = uBeyondEndAddr - uStartAddr;
/*
* Check for address range calculation overflow, and attempts to wrap
* zero bytes.
*/
- if (ulBeyondEndAddr <= ulStartAddr)
+ if (uBeyondEndAddr <= uStartAddr)
{
PVR_DPF((PVR_DBG_ERROR,
- "OSAcquirePhysPageAddr: Invalid address range (start %x, length %x)",
- ulStartAddrOrig, ulAddrRangeOrig));
+ "OSAcquirePhysPageAddr: Invalid address range (start " UINTPTR_FMT ", length %" SIZE_T_FMT_LEN "x)",
+ uStartAddrOrig, uAddrRangeOrig));
goto error;
}
@@ -3660,12 +3570,12 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
memset(psInfo, 0, sizeof(*psInfo));
#if defined(DEBUG)
- psInfo->ulStartAddr = ulStartAddrOrig;
- psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
+ psInfo->uStartAddr = uStartAddrOrig;
+ psInfo->uBeyondEndAddr = uBeyondEndAddrOrig;
#endif
- psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT);
- psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK);
+ psInfo->iNumPages = (IMG_INT)(uAddrRange >> PAGE_SHIFT);
+ psInfo->iPageOffset = (IMG_INT)(uStartAddrOrig & ~PAGE_MASK);
/* Allocate physical address array */
psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
@@ -3698,7 +3608,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
bMMapSemHeld = IMG_TRUE;
/* Get page list */
- psInfo->iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
+ psInfo->iNumPagesMapped = get_user_pages(current, current->mm, uStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
if (psInfo->iNumPagesMapped >= 0)
{
@@ -3714,14 +3624,14 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
for (i = 0; i < psInfo->iNumPages; i++)
{
IMG_CPU_PHYADDR CPUPhysAddr;
- IMG_UINT32 ulPFN;
+ IMG_UINT32 ui32PFN;
- ulPFN = page_to_pfn(psInfo->ppsPages[i]);
- CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT;
- if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN)
+ ui32PFN = page_to_pfn(psInfo->ppsPages[i]);
+ CPUPhysAddr.uiAddr = ui32PFN << PAGE_SHIFT;
+ if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ui32PFN)
{
PVR_DPF((PVR_DBG_ERROR,
- "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN));
+ "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ui32PFN));
goto error;
}
@@ -3749,11 +3659,12 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
/* Set the mapping type to aid clean up */
psInfo->eType = WRAP_TYPE_FIND_VMA;
- psVMArea = find_vma(current->mm, ulStartAddrOrig);
+ psVMArea = find_vma(current->mm, uStartAddrOrig);
if (psVMArea == NULL)
{
PVR_DPF((PVR_DBG_ERROR,
- "OSAcquirePhysPageAddr: Couldn't find memory region containing start address %x", ulStartAddrOrig));
+ "OSAcquirePhysPageAddr: Couldn't find memory region containing start address " UINTPTR_FMT,
+ uStartAddrOrig));
goto error;
}
@@ -3765,27 +3676,24 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
* find_vma locates a region with an end point past a given
* virtual address. So check the address is actually in the region.
*/
- if (ulStartAddrOrig < psVMArea->vm_start)
+ if (uStartAddrOrig < psVMArea->vm_start)
{
PVR_DPF((PVR_DBG_ERROR,
- "OSAcquirePhysPageAddr: Start address %x is outside of the region returned by find_vma", ulStartAddrOrig));
+ "OSAcquirePhysPageAddr: Start address " UINTPTR_FMT " is outside of the region returned by find_vma",
+ uStartAddrOrig));
goto error;
}
/* Now check the end address is in range */
- if (ulBeyondEndAddrOrig > psVMArea->vm_end)
+ if (uBeyondEndAddrOrig > psVMArea->vm_end)
{
PVR_DPF((PVR_DBG_ERROR,
- "OSAcquirePhysPageAddr: End address %x is outside of the region returned by find_vma", ulBeyondEndAddrOrig));
+ "OSAcquirePhysPageAddr: End address " UINTPTR_FMT " is outside of the region returned by find_vma", uBeyondEndAddrOrig));
goto error;
}
/* Does the region represent memory mapped I/O? */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
- if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED))
-#else
- if ((psVMArea->vm_flags & (VM_IO | VM_DONTEXPAND | VM_DONTDUMP)) != (VM_IO | VM_DONTEXPAND | VM_DONTDUMP))
-#endif
+ if (!(psVMArea->vm_flags & VM_IO))
{
PVR_DPF((PVR_DBG_ERROR,
"OSAcquirePhysPageAddr: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)", psVMArea->vm_flags));
@@ -3800,14 +3708,14 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
goto error;
}
- for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+ for (uAddr = uStartAddrOrig, i = 0; uAddr < uBeyondEndAddrOrig; uAddr += PAGE_SIZE, i++)
{
IMG_CPU_PHYADDR CPUPhysAddr;
- IMG_UINT32 ulPFN = 0;
+ IMG_UINT32 ui32PFN = 0;
PVR_ASSERT(i < psInfo->iNumPages);
- if (!CPUVAddrToPFN(psVMArea, ulAddr, &ulPFN, &psInfo->ppsPages[i]))
+ if (!CPUVAddrToPFN(psVMArea, uAddr, &ui32PFN, &psInfo->ppsPages[i]))
{
PVR_DPF((PVR_DBG_ERROR,
"OSAcquirePhysPageAddr: Invalid CPU virtual address"));
@@ -3818,7 +3726,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
{
#if defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER)
/* This could be tiler memory.*/
- IMG_UINT32 ui32TilerAddr = CPUAddrToTilerPhy(ulAddr);
+ IMG_UINT32 ui32TilerAddr = CPUAddrToTilerPhy(uAddr);
if (ui32TilerAddr)
{
bHavePageStructs = IMG_TRUE;
@@ -3837,14 +3745,14 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
psInfo->iNumPagesMapped++;
- PVR_ASSERT(ulPFN == page_to_pfn(psInfo->ppsPages[i]));
+ PVR_ASSERT(ui32PFN == page_to_pfn(psInfo->ppsPages[i]));
}
- CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT;
- if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN)
+ CPUPhysAddr.uiAddr = ui32PFN << PAGE_SHIFT;
+ if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ui32PFN)
{
PVR_DPF((PVR_DBG_ERROR,
- "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN));
+ "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ui32PFN));
goto error;
}
@@ -3912,64 +3820,105 @@ error:
return eError;
}
-typedef void (*InnerCacheOp_t)(const void *pvStart, const void *pvEnd);
-
-#if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
-typedef void (*OuterCacheOp_t)(phys_addr_t uStart, phys_addr_t uEnd);
+#if ! defined(__arm__)
+# define USE_VIRTUAL_CACHE_OP
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+# define USE_VIRTUAL_CACHE_OP
+# if defined(CONFIG_OUTER_CACHE)
+# define USE_PHYSICAL_CACHE_OP
+# endif
#else
-typedef void (*OuterCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
+# define USE_PHYSICAL_CACHE_OP
#endif
-#if defined(CONFIG_OUTER_CACHE)
+extern PVRSRV_LINUX_MUTEX g_sMMapMutex;
+
+/* g_sMMapMutex must be held while this function is called */
+static
+IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
+ IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_VOID *pvMinVAddr;
+
+ /* There's no kernel-virtual for this type of allocation, so if
+ * we're flushing it, it must be user-virtual, and therefore
+ * have a mapping.
+ */
+ list_for_each_entry(psOffsetStruct, psMMapOffsetStructList, sAreaItem)
+ {
+ if(OSGetCurrentProcessIDKM() != psOffsetStruct->ui32PID)
+ continue;
+
+ pvMinVAddr = (IMG_VOID *)psOffsetStruct->uiUserVAddr;
+ /* Within permissible range */
+ if(pvRangeAddrStart >= pvMinVAddr &&
+ ui32Length <= psOffsetStruct->uiRealByteSize)
+ return pvMinVAddr;
+ }
+
+ return IMG_NULL;
+}
+
+#if defined(USE_PHYSICAL_CACHE_OP)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+typedef void (*PhysicalCacheOp_t)(phys_addr_t uStart, phys_addr_t uEnd);
+#else
+typedef void (*PhysicalCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
+#endif
+
+/*
+ Note: use IMG_CPU_PHYADDR to return CPU Phys Addresses, and not just 'unsigned long',
+ as this is not big enough to hold physical addresses on 32-bit PAE devices.
+*/
typedef IMG_BOOL (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum,
- unsigned long *pulStart);
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ IMG_CPU_PHYADDR *psStart);
static IMG_BOOL VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum,
- unsigned long *pulStart)
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ IMG_CPU_PHYADDR *psStart)
{
- *pulStart = vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
+ psStart->uiAddr = vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
return IMG_TRUE;
}
static IMG_BOOL ExternalKVAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum,
- unsigned long *pulStart)
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ IMG_CPU_PHYADDR *psStart)
{
IMG_SYS_PHYADDR SysPAddr;
- IMG_CPU_PHYADDR CpuPAddr;
SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageNumOffset + ui32PageNum];
- CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
- *pulStart = CpuPAddr.uiAddr;
+ *psStart = SysSysPAddrToCpuPAddr(SysPAddr);
return IMG_TRUE;
}
static IMG_BOOL AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum,
- unsigned long *pulStart)
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ IMG_CPU_PHYADDR *psStart)
{
struct page *pPage;
pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageNumOffset + ui32PageNum];
- *pulStart = page_to_pfn(pPage) << PAGE_SHIFT;
+ psStart->uiAddr = page_to_pfn(pPage) << PAGE_SHIFT;
return IMG_TRUE;
}
static IMG_BOOL AllocPagesSparseAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum,
- unsigned long *pulStart)
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ IMG_CPU_PHYADDR *psStart)
{
IMG_UINT32 ui32VirtOffset = (ui32PageNumOffset + ui32PageNum) << PAGE_SHIFT;
IMG_UINT32 ui32PhysOffset;
@@ -3979,82 +3928,80 @@ static IMG_BOOL AllocPagesSparseAreaToPhys(LinuxMemArea *psLinuxMemArea,
{
PVR_ASSERT(ui32PhysOffset <= ui32VirtOffset);
pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PhysOffset >> PAGE_SHIFT];
- *pulStart = page_to_pfn(pPage) << PAGE_SHIFT;
+ psStart->uiAddr = page_to_pfn(pPage) << PAGE_SHIFT;
return IMG_TRUE;
}
return IMG_FALSE;
}
-
-static IMG_BOOL IONAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum,
- unsigned long *pulStart)
+static inline void DoPhysicalCacheOp(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_SIZE_T uiLength,
+ IMG_UINTPTR_T uPageNumOffset,
+ MemAreaToPhys_t pfnMemAreaToPhys,
+ PhysicalCacheOp_t pfnPhysicalCacheOp)
{
- IMG_CPU_PHYADDR CpuPAddr;
- CpuPAddr = psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs[ui32PageNumOffset + ui32PageNum];
- *pulStart = CpuPAddr.uiAddr;
- return IMG_TRUE;
-}
-
-#endif /* defined(CONFIG_OUTER_CACHE) */
+ IMG_CPU_PHYADDR sStart, sEnd;
+ unsigned long ulLength, ulStartOffset, ulEndOffset;
+ IMG_UINT32 i, ui32NumPages;
+ IMG_BOOL bValidPage;
-/* g_sMMapMutex must be held while this function is called */
+ /* Length and offsets of flush region WRT page alignment */
+ ulLength = (unsigned long)uiLength;
+ ulStartOffset = ((unsigned long)pvRangeAddrStart) & (PAGE_SIZE - 1);
+ ulEndOffset = ((unsigned long)pvRangeAddrStart + ulLength) & (PAGE_SIZE - 1);
-static
-IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
- IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length)
-{
- PKV_OFFSET_STRUCT psOffsetStruct;
- IMG_VOID *pvMinVAddr;
+ /* The affected pages, rounded up */
+ ui32NumPages = (ulStartOffset + ulLength + PAGE_SIZE - 1) >> PAGE_SHIFT;
- /* There's no kernel-virtual for this type of allocation, so if
- * we're flushing it, it must be user-virtual, and therefore
- * have a mapping.
- */
- list_for_each_entry(psOffsetStruct, psMMapOffsetStructList, sAreaItem)
+ for(i = 0; i < ui32NumPages; i++)
{
- if(OSGetCurrentProcessIDKM() != psOffsetStruct->ui32PID)
- continue;
+ bValidPage = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
+ uPageNumOffset, i, &sStart);
+ if (bValidPage)
+ {
+ sEnd.uiAddr = sStart.uiAddr + PAGE_SIZE;
- pvMinVAddr = (IMG_VOID *)psOffsetStruct->ui32UserVAddr;
+ if(i == ui32NumPages - 1 && ulEndOffset != 0)
+ sEnd.uiAddr = sStart.uiAddr + ulEndOffset;
- /* Within permissible range */
- if(pvRangeAddrStart >= pvMinVAddr &&
- ui32Length <= psOffsetStruct->ui32RealByteSize)
- return pvMinVAddr;
- }
+ if(i == 0)
+ sStart.uiAddr += ulStartOffset;
- return IMG_NULL;
+ pfnPhysicalCacheOp(sStart.uiAddr, sEnd.uiAddr);
+ }
+ }
}
-extern PVRSRV_LINUX_MUTEX g_sMMapMutex;
+#endif /* defined(USE_PHYSICAL_CACHE_OP) */
-static inline void DoInnerCacheOp(IMG_HANDLE hOSMemHandle,
- IMG_UINT32 ui32ByteOffset,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32Length,
- InnerCacheOp_t pfnInnerCacheOp)
+#if defined(USE_VIRTUAL_CACHE_OP)
+typedef void (*VirtualCacheOp_t)(const void *pvStart, const void *pvEnd);
+
+static inline void DoVirtualCacheOp(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length,
+ VirtualCacheOp_t pfnVirtualCacheOp)
{
LinuxMemArea *psLinuxMemArea = hOSMemHandle;
if (!psLinuxMemArea->hBMHandle)
{
- pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ pfnVirtualCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
}
else
{
IMG_UINT32 ui32ByteRemain = ui32Length;
- IMG_UINT32 ui32BytesToDo = PAGE_SIZE - (((IMG_UINT32) pvRangeAddrStart) & (~PAGE_MASK));
+ IMG_UINT32 ui32BytesToDo = PAGE_SIZE - (((IMG_UINTPTR_T) pvRangeAddrStart) & (~PAGE_MASK));
IMG_UINT8 *pbDo = (IMG_UINT8 *) pvRangeAddrStart;
while(ui32ByteRemain)
{
if (BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32ByteOffset + (ui32Length - ui32ByteRemain)))
{
- pfnInnerCacheOp(pbDo, pbDo + ui32BytesToDo);
+ pfnVirtualCacheOp(pbDo, pbDo + ui32BytesToDo);
}
pbDo += ui32BytesToDo;
ui32ByteRemain -= ui32BytesToDo;
@@ -4062,31 +4009,36 @@ static inline void DoInnerCacheOp(IMG_HANDLE hOSMemHandle,
}
}
}
+#endif /* defined(USE_VIRTUAL_CACHE_OP) */
static
IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
- IMG_UINT32 ui32ByteOffset,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32Length,
- InnerCacheOp_t pfnInnerCacheOp,
- OuterCacheOp_t pfnOuterCacheOp)
+ IMG_UINT32 ui32ByteOffset,
+ IMG_VOID *pvVirtRangeStart,
+ IMG_SIZE_T uiLength
+#if defined(USE_VIRTUAL_CACHE_OP)
+ , VirtualCacheOp_t pfnVirtualCacheOp
+#endif
+#if defined(USE_PHYSICAL_CACHE_OP)
+ , PhysicalCacheOp_t pfnPhysicalCacheOp
+#endif
+ )
{
LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
- IMG_UINT32 ui32AreaLength, ui32AreaOffset = 0;
+ IMG_UINTPTR_T uiAreaOffset = 0;
struct list_head *psMMapOffsetStructList;
IMG_VOID *pvMinVAddr;
-
-#if defined(CONFIG_OUTER_CACHE)
+#if defined(USE_PHYSICAL_CACHE_OP)
MemAreaToPhys_t pfnMemAreaToPhys = IMG_NULL;
- IMG_UINT32 ui32PageNumOffset = 0;
+ IMG_UINTPTR_T uPageNumOffset = 0;
+ IMG_VOID *pvPhysRangeStart = pvVirtRangeStart;
#endif
PVR_ASSERT(psLinuxMemArea != IMG_NULL);
- LinuxLockMutex(&g_sMMapMutex);
+ LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
psMMapOffsetStructList = &psLinuxMemArea->sMMapOffsetStructList;
- ui32AreaLength = psLinuxMemArea->ui32ByteSize;
/*
Don't check the length in the case of sparse mappings as
@@ -4094,12 +4046,12 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
*/
if (!psLinuxMemArea->hBMHandle)
{
- PVR_ASSERT(ui32Length <= ui32AreaLength);
+ PVR_ASSERT(uiLength <= psLinuxMemArea->uiByteSize);
}
if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
{
- ui32AreaOffset = psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+ uiAreaOffset = psLinuxMemArea->uData.sSubAlloc.uiByteOffset;
psLinuxMemArea = psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
}
@@ -4110,19 +4062,13 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
{
case LINUX_MEM_AREA_VMALLOC:
{
- if(is_vmalloc_addr(pvRangeAddrStart))
+ if(is_vmalloc_addr(pvVirtRangeStart))
{
- pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + ui32AreaOffset;
+ pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + uiAreaOffset;
/* Outside permissible range */
- if(pvRangeAddrStart < pvMinVAddr)
+ if(pvVirtRangeStart < pvMinVAddr)
goto err_blocked;
-
- DoInnerCacheOp(hOSMemHandle,
- ui32ByteOffset,
- pvRangeAddrStart,
- ui32Length,
- pfnInnerCacheOp);
}
else
{
@@ -4132,17 +4078,11 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
*/
pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
- pvRangeAddrStart, ui32Length);
+ pvVirtRangeStart, uiLength);
if(!pvMinVAddr)
goto err_blocked;
- DoInnerCacheOp(hOSMemHandle,
- ui32ByteOffset,
- pvRangeAddrStart,
- ui32Length,
- pfnInnerCacheOp);
-
-#if defined(CONFIG_OUTER_CACHE)
+#if defined(USE_PHYSICAL_CACHE_OP)
/*
* We don't need to worry about cache aliasing here because
* we have already flushed the virtually-indexed caches (L1
@@ -4151,14 +4091,10 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
* The vmalloc address will only be used to determine
* affected physical pages for outer cache flushing.
*/
- pvRangeAddrStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +
- (ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr);
- }
-
- pfnMemAreaToPhys = VMallocAreaToPhys;
-#else /* defined(CONFIG_OUTER_CACHE) */
+ pvPhysRangeStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +
+ (uiAreaOffset & PAGE_MASK) + (pvVirtRangeStart - pvMinVAddr);
+#endif
}
-#endif /* defined(CONFIG_OUTER_CACHE) */
break;
}
@@ -4183,111 +4119,80 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
}
pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
- pvRangeAddrStart, ui32Length);
+ pvVirtRangeStart, uiLength);
if(!pvMinVAddr)
goto err_blocked;
- DoInnerCacheOp(hOSMemHandle,
- ui32ByteOffset,
- pvRangeAddrStart,
- ui32Length,
- pfnInnerCacheOp);
-
-#if defined(CONFIG_OUTER_CACHE)
- ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
- pfnMemAreaToPhys = ExternalKVAreaToPhys;
-#endif
break;
}
- case LINUX_MEM_AREA_ION:
+ case LINUX_MEM_AREA_ALLOC_PAGES:
{
pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
- pvRangeAddrStart, ui32Length);
+ pvVirtRangeStart, uiLength);
if(!pvMinVAddr)
goto err_blocked;
- DoInnerCacheOp(hOSMemHandle,
- ui32ByteOffset,
- pvRangeAddrStart,
- ui32Length,
- pfnInnerCacheOp);
+ break;
+ }
-#if defined(CONFIG_OUTER_CACHE)
- ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
- pfnMemAreaToPhys = IONAreaToPhys;
-#endif
+ default:
+ PVR_DBG_BREAK;
+ goto err_blocked;
+ }
+
+#if defined(USE_PHYSICAL_CACHE_OP)
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ {
+ pfnMemAreaToPhys = VMallocAreaToPhys;
break;
}
- case LINUX_MEM_AREA_ALLOC_PAGES:
+ case LINUX_MEM_AREA_EXTERNAL_KV:
{
- pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
- pvRangeAddrStart, ui32Length);
- if(!pvMinVAddr)
- goto err_blocked;
+ uPageNumOffset = ((uiAreaOffset & PAGE_MASK) + (pvPhysRangeStart - pvMinVAddr)) >> PAGE_SHIFT;
+ pfnMemAreaToPhys = ExternalKVAreaToPhys;
+ break;
+ }
- DoInnerCacheOp(hOSMemHandle,
- ui32ByteOffset,
- pvRangeAddrStart,
- ui32Length,
- pfnInnerCacheOp);
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ {
+ uPageNumOffset = ((uiAreaOffset & PAGE_MASK) + (pvPhysRangeStart - pvMinVAddr)) >> PAGE_SHIFT;
-#if defined(CONFIG_OUTER_CACHE)
- ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
if (psLinuxMemArea->hBMHandle)
- {
pfnMemAreaToPhys = AllocPagesSparseAreaToPhys;
- }
else
- {
pfnMemAreaToPhys = AllocPagesAreaToPhys;
- }
-#endif
+
break;
}
default:
PVR_DBG_BREAK;
}
+#endif
+
+#if defined(USE_VIRTUAL_CACHE_OP)
+ DoVirtualCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvVirtRangeStart,
+ uiLength,
+ pfnVirtualCacheOp);
+#endif
LinuxUnLockMutex(&g_sMMapMutex);
-#if defined(CONFIG_OUTER_CACHE)
+#if defined(USE_PHYSICAL_CACHE_OP)
PVR_ASSERT(pfnMemAreaToPhys != IMG_NULL);
- /* Outer caches need some more work, to get a list of physical addresses */
- {
- unsigned long ulStart, ulEnd, ulLength, ulStartOffset, ulEndOffset;
- IMG_UINT32 i, ui32NumPages;
- IMG_BOOL bValidPage;
-
- /* Length and offsets of flush region WRT page alignment */
- ulLength = (unsigned long)ui32Length;
- ulStartOffset = ((unsigned long)pvRangeAddrStart) & (PAGE_SIZE - 1);
- ulEndOffset = ((unsigned long)pvRangeAddrStart + ulLength) & (PAGE_SIZE - 1);
-
- /* The affected pages, rounded up */
- ui32NumPages = (ulStartOffset + ulLength + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
- for(i = 0; i < ui32NumPages; i++)
- {
- bValidPage = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
- ui32PageNumOffset, i, &ulStart);
- if (bValidPage)
- {
- ulEnd = ulStart + PAGE_SIZE;
-
- if(i == ui32NumPages - 1 && ulEndOffset != 0)
- ulEnd = ulStart + ulEndOffset;
-
- if(i == 0)
- ulStart += ulStartOffset;
-
- pfnOuterCacheOp(ulStart, ulEnd);
- }
- }
- }
+ DoPhysicalCacheOp(psLinuxMemArea,
+ pvPhysRangeStart,
+ uiLength,
+ uPageNumOffset,
+ pfnMemAreaToPhys,
+ pfnPhysicalCacheOp);
#endif
return IMG_TRUE;
@@ -4295,13 +4200,13 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
err_blocked:
PVR_DPF((PVR_DBG_WARNING, "%s: Blocked cache op on virtual range "
"%p-%p (type %d)", __func__,
- pvRangeAddrStart, pvRangeAddrStart + ui32Length,
+ pvVirtRangeStart, pvVirtRangeStart + uiLength,
psLinuxMemArea->eAreaType));
LinuxUnLockMutex(&g_sMMapMutex);
return IMG_FALSE;
}
-#if defined(__i386__)
+#if defined(__i386__) || defined (__x86_64__)
#define ROUND_UP(x,a) (((x) + (a) - 1) & ~((a) - 1))
@@ -4346,7 +4251,7 @@ IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
{
/* Write-back and invalidate */
return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
- x86_flush_cache_range, IMG_NULL);
+ x86_flush_cache_range);
}
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
@@ -4356,7 +4261,7 @@ IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
{
/* No clean feature on x86 */
return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
- x86_flush_cache_range, IMG_NULL);
+ x86_flush_cache_range);
}
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
@@ -4366,12 +4271,10 @@ IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
{
/* No invalidate-only support */
return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
- x86_flush_cache_range, IMG_NULL);
+ x86_flush_cache_range);
}
-#else /* defined(__i386__) */
-
-#if defined(__arm__)
+#elif defined(__arm__)
static void per_cpu_cache_flush(void *arg)
{
@@ -4411,6 +4314,8 @@ static inline size_t pvr_dmac_range_len(const void *pvStart, const void *pvEnd)
}
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+
static void pvr_dmac_inv_range(const void *pvStart, const void *pvEnd)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
@@ -4429,14 +4334,41 @@ static void pvr_dmac_clean_range(const void *pvStart, const void *pvEnd)
#endif
}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) */
+
+static void pvr_flush_range(phys_addr_t pStart, phys_addr_t pEnd)
+{
+ arm_dma_ops.sync_single_for_device(NULL, pStart, pEnd - pStart, DMA_TO_DEVICE);
+ arm_dma_ops.sync_single_for_cpu(NULL, pStart, pEnd - pStart, DMA_FROM_DEVICE);
+}
+
+static void pvr_clean_range(phys_addr_t pStart, phys_addr_t pEnd)
+{
+ arm_dma_ops.sync_single_for_device(NULL, pStart, pEnd - pStart, DMA_TO_DEVICE);
+}
+
+static void pvr_invalidate_range(phys_addr_t pStart, phys_addr_t pEnd)
+{
+ arm_dma_ops.sync_single_for_cpu(NULL, pStart, pEnd - pStart, DMA_FROM_DEVICE);
+}
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) */
+
IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
- pvRangeAddrStart, ui32Length,
- dmac_flush_range, outer_flush_range);
+ pvRangeAddrStart, ui32Length,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+ pvr_flush_range
+#elif defined(CONFIG_OUTER_CACHE)
+ dmac_flush_range, outer_flush_range
+#else
+ dmac_flush_range
+#endif
+ );
}
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
@@ -4445,8 +4377,15 @@ IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Length)
{
return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
- pvRangeAddrStart, ui32Length,
- pvr_dmac_clean_range, outer_clean_range);
+ pvRangeAddrStart, ui32Length,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+ pvr_clean_range
+#elif defined(CONFIG_OUTER_CACHE)
+ pvr_dmac_clean_range, outer_clean_range
+#else
+ pvr_dmac_clean_range
+#endif
+ );
}
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
@@ -4455,13 +4394,18 @@ IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Length)
{
return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
- pvRangeAddrStart, ui32Length,
- pvr_dmac_inv_range, outer_inv_range);
+ pvRangeAddrStart, ui32Length,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+ pvr_invalidate_range
+#elif defined(CONFIG_OUTER_CACHE)
+ pvr_dmac_inv_range, outer_inv_range
+#else
+ pvr_dmac_inv_range
+#endif
+ );
}
-#else /* defined(__arm__) */
-
-#if defined(__mips__)
+#elif defined(__mips__)
/*
* dmac cache functions are supposed to be used for dma
* memory which comes from dma-able memory. However examining
@@ -4524,7 +4468,7 @@ IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
{
return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
pvRangeAddrStart, ui32Length,
- pvr_dma_cache_wback_inv, IMG_NULL);
+ pvr_dma_cache_wback_inv);
}
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
@@ -4534,7 +4478,7 @@ IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
{
return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
pvRangeAddrStart, ui32Length,
- pvr_dma_cache_wback, IMG_NULL);
+ pvr_dma_cache_wback);
}
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
@@ -4544,18 +4488,14 @@ IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
{
return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
pvRangeAddrStart, ui32Length,
- pvr_dma_cache_inv, IMG_NULL);
+ pvr_dma_cache_inv);
}
-#else /* defined(__mips__) */
+#else
#error "Implement CPU cache flush/clean/invalidate primitives for this CPU!"
-#endif /* defined(__mips__) */
-
-#endif /* defined(__arm__) */
-
-#endif /* defined(__i386__) */
+#endif
typedef struct _AtomicStruct
{
@@ -4613,7 +4553,7 @@ IMG_VOID OSReleaseBridgeLock(IMG_VOID)
IMG_VOID OSReacquireBridgeLock(IMG_VOID)
{
- LinuxLockMutex(&gPVRSRVLock);
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
}
typedef struct _OSTime
@@ -4631,7 +4571,7 @@ PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32USOffset)
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
- psOSTime->ulTime = usecs_to_jiffies(jiffies_to_usecs(jiffies) + ui32USOffset);
+ psOSTime->ulTime = jiffies + usecs_to_jiffies(ui32USOffset);
*pvRet = psOSTime;
return PVRSRV_OK;
}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/osperproc.c b/drivers/gpu/pvr/services4/srvkm/env/linux/osperproc.c
index a22b4614993..3485d8ae61c 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/osperproc.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/osperproc.c
@@ -43,12 +43,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "osperproc.h"
#include "env_perproc.h"
-#include "proc.h"
-#if defined (SUPPORT_ION)
-#include "linux/ion.h"
-extern struct ion_device *psIonDev;
+#if defined (SUPPORT_ION)
+#include <linux/err.h>
+#include "ion.h"
+extern struct ion_device *gpsIonDev;
#endif
+
extern IMG_UINT32 gui32ReleasePID;
PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
@@ -83,12 +84,11 @@ PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
/* 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(psIonDev,
- 1 << ION_HEAP_TYPE_SYSTEM_CONTIG |
- 1 << ION_HEAP_TYPE_SYSTEM,
+ ion_client_create(gpsIonDev,
psEnvPerProc->azIonClientName);
if (IS_ERR_OR_NULL(psEnvPerProc->psIONClient))
@@ -97,7 +97,8 @@ PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
"ion client for per process data"));
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-#endif /* SUPPORT_ION */
+#endif /* defined(SUPPORT_ION) */
+
return PVRSRV_OK;
}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pdump.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pdump.c
index 01247374185..548e8dce0f7 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/pdump.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pdump.c
@@ -62,6 +62,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <linux/kernel.h> // sprintf
#include <linux/string.h> // strncpy, strlen
+#include <linux/mutex.h>
static IMG_BOOL PDumpWriteString2 (IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
static IMG_BOOL PDumpWriteILock (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
@@ -80,7 +81,8 @@ static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
-
+DEFINE_MUTEX(sPDumpLock);
+DEFINE_MUTEX(sPDumpMsgLock);
IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
"ScriptStream2",
@@ -391,7 +393,7 @@ IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
IMG_PUINT8 pui8LinAddr,
- IMG_UINT32 ui32DataPageMask,
+ IMG_UINTPTR_T ui32DataPageMask,
IMG_UINT32 *pui32PageOffset)
{
if(hOSMemHandle)
@@ -411,7 +413,7 @@ IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
PVR_UNREFERENCED_PARAMETER(ui32Offset);
- *pui32PageOffset = ((IMG_UINT32)pui8LinAddr & ui32DataPageMask);
+ *pui32PageOffset = ((IMG_UINTPTR_T)pui8LinAddr & ui32DataPageMask);
}
}
@@ -724,7 +726,7 @@ static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_U
IMG_UINT32 ui32Written = 0;
if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
{
- PVR_DPF((PVR_DBG_MESSAGE, "PDumpWriteILock: Failed to write 0x%x bytes to stream 0x%x", ui32Count, (IMG_UINT32)psStream));
+ PVR_DPF((PVR_DBG_MESSAGE, "PDumpWriteILock: Failed to write 0x%x bytes to stream 0x%p", ui32Count, psStream));
return IMG_TRUE;
}
@@ -797,6 +799,55 @@ IMG_VOID PDumpResumeKM(IMG_VOID)
atomic_dec(&gsPDumpSuspended);
}
+/* Set to 1 if you want to debug PDump locking issues */
+#define DEBUG_PDUMP_LOCKS 0
+
+#if DEBUG_PDUMP_LOCKS
+static IMG_UINT32 ui32Count=0;
+static IMG_UINT32 aui32LockLine[2] = {0};
+static IMG_UINT32 aui32UnlockLine[2] = {0};
+static IMG_UINT32 ui32LockLineCount = 0;
+static IMG_UINT32 ui32UnlockLineCount = 0;
+#endif
+
+IMG_VOID PDumpOSLock(IMG_UINT32 ui32Line)
+{
+#if DEBUG_PDUMP_LOCKS
+ aui32LockLine[ui32LockLineCount++ % 2] = ui32Line;
+ ui32Count++;
+ if (ui32Count == 2)
+ {
+ IMG_UINT32 i;
+ printk(KERN_ERR "Double lock\n");
+ dump_stack();
+ for (i=0;i<2;i++)
+ {
+ printk(KERN_ERR "Lock[%d] = %d, Unlock[%d] = %d\n", i, aui32LockLine[i],i, aui32UnlockLine[i]);
+ }
+ }
+#endif
+ mutex_lock(&sPDumpLock);
+}
+
+IMG_VOID PDumpOSUnlock(IMG_UINT32 ui32Line)
+{
+ mutex_unlock(&sPDumpLock);
+#if DEBUG_PDUMP_LOCKS
+ aui32UnlockLine[ui32UnlockLineCount++ % 2] = ui32Line;
+ ui32Count--;
+#endif
+}
+
+IMG_VOID PDumpOSLockMessageBuffer(IMG_VOID)
+{
+ mutex_lock(&sPDumpMsgLock);
+}
+
+IMG_VOID PDumpOSUnlockMessageBuffer(IMG_VOID)
+{
+ mutex_unlock(&sPDumpMsgLock);
+}
+
#endif /* #if defined (PDUMP) */
#endif /* #if defined (SUPPORT_SGX) */
/*****************************************************************************
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/private_data.h b/drivers/gpu/pvr/services4/srvkm/env/linux/private_data.h
index 6b097052ba4..e2a6c74d35d 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/private_data.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/private_data.h
@@ -64,11 +64,7 @@ typedef struct
IMG_UINT32 ui32OpenPID;
/* Global kernel MemInfo handle */
-#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hKernelMemInfo;
-#else
IMG_HANDLE hKernelMemInfo;
-#endif
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
/* The private data is on a list in the per-process data structure */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/proc.c b/drivers/gpu/pvr/services4/srvkm/env/linux/proc.c
index 4a6e2fedc42..788757ba2a4 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/proc.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/proc.c
@@ -52,11 +52,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <linux/sched.h>
#include "services_headers.h"
@@ -72,16 +70,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "lists.h"
+struct pvr_proc_dir_entry {
+ struct proc_dir_entry *pde;
+
+ pvr_next_proc_seq_t *next;
+ pvr_show_proc_seq_t *show;
+ pvr_off2element_proc_seq_t *off2element;
+ pvr_startstop_proc_seq_t *startstop;
+
+ pvr_proc_write_t *write;
+
+ IMG_VOID *data;
+};
+
// The proc entry for our /proc/pvr directory
static struct proc_dir_entry * dir;
static const IMG_CHAR PVRProcDirRoot[] = "pvr";
static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
-static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
-static void pvr_proc_seq_stop (struct seq_file *m, void *v);
-static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
-static int pvr_proc_seq_show (struct seq_file *m, void *v);
static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
static struct file_operations pvr_proc_operations =
@@ -93,17 +100,10 @@ static struct file_operations pvr_proc_operations =
.release = seq_release,
};
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
-static ssize_t pvr_proc_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos);
-static struct file_operations pvr_read_proc_operations =
-{
- .open = pvr_proc_open,
- .read = pvr_proc_read,
- .write = pvr_proc_write,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-#endif
+static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
+static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
+static void pvr_proc_seq_stop (struct seq_file *m, void *v);
+static int pvr_proc_seq_show (struct seq_file *m, void *v);
static struct seq_operations pvr_proc_seq_operations =
{
@@ -113,16 +113,18 @@ static struct seq_operations pvr_proc_seq_operations =
.show = pvr_proc_seq_show,
};
-static struct proc_dir_entry* g_pProcQueue;
-static struct proc_dir_entry* g_pProcVersion;
-static struct proc_dir_entry* g_pProcSysNodes;
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+static struct pvr_proc_dir_entry* g_pProcQueue;
+#endif
+static struct pvr_proc_dir_entry* g_pProcVersion;
+static struct pvr_proc_dir_entry* g_pProcSysNodes;
#ifdef DEBUG
-static struct proc_dir_entry* g_pProcDebugLevel;
+static struct pvr_proc_dir_entry* g_pProcDebugLevel;
#endif
#ifdef PVR_MANUAL_POWER_CONTROL
-static struct proc_dir_entry* g_pProcPowerLevel;
+static struct pvr_proc_dir_entry* g_pProcPowerLevel;
#endif
@@ -131,55 +133,12 @@ static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
-/*!
-******************************************************************************
-
- @Function : printAppend
-
- @Description
-
- Print into the supplied buffer at the specified offset remaining within
- the specified total buffer size.
- @Input size : the total size of the buffer
-
- @Input off : the offset into the buffer to start printing
-
- @Input format : the printf format string
-
- @Input ... : format args
-
- @Return : The number of chars now in the buffer (original value of 'off'
- plus number of chars added); 'size' if full.
-
-*****************************************************************************/
-off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
-{
- IMG_INT n;
- size_t space = size - (size_t)off;
- va_list ap;
-
- va_start (ap, format);
-
- n = vsnprintf (buffer+off, space, format, ap);
-
- va_end (ap);
- /* According to POSIX, n is greater than or equal to the size available if
- * the print would have overflowed the buffer. Other platforms may
- * return -1 if printing was truncated.
- */
- if (n >= (IMG_INT)space || n < 0)
- {
- /* Ensure final string is terminated */
- buffer[size - 1] = 0;
- return (off_t)(size - 1);
- }
- else
- {
- return (off + (off_t)n);
- }
-}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+#define PDE_DATA(x) PDE(x)->data;
+#endif
+#ifdef DEBUG
/*!
******************************************************************************
@@ -198,7 +157,7 @@ off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * fo
@Return : Pointer to element to be shown.
*****************************************************************************/
-void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
+static void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
{
PVR_UNREFERENCED_PARAMETER(sfile);
// Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL
@@ -207,6 +166,7 @@ void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
return NULL;
}
+#endif
/*!
******************************************************************************
@@ -225,7 +185,7 @@ void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
@Return : Pointer to element to be shown.
*****************************************************************************/
-void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
+static void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
{
PVR_UNREFERENCED_PARAMETER(sfile);
@@ -263,15 +223,10 @@ static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
struct seq_file *seq = (struct seq_file*)file->private_data;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- struct proc_dir_entry* pvr_proc_entry = PDE(inode);
+ struct pvr_proc_dir_entry* ppde = PDE_DATA(inode);
/* Add pointer to handlers to seq_file structure */
- seq->private = pvr_proc_entry->data;
-#else
- PVR_PROC_SEQ_HANDLERS *data = (PVR_PROC_SEQ_HANDLERS *)PDE_DATA(inode);
- seq->private = data;
-#endif
+ seq->private = ppde;
return ret;
}
@@ -290,23 +245,15 @@ static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
struct inode *inode = file->f_path.dentry->d_inode;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- struct proc_dir_entry * dp;
+ struct pvr_proc_dir_entry * ppde;
PVR_UNREFERENCED_PARAMETER(ppos);
- dp = PDE(inode);
+ ppde = PDE_DATA(inode);
- if (!dp->write_proc)
+ if (!ppde->write)
return -EIO;
- return dp->write_proc(file, buffer, count, dp->data);
-#else
- PVR_PROC_SEQ_HANDLERS *data = (PVR_PROC_SEQ_HANDLERS *)PDE_DATA(inode);
- PVR_UNREFERENCED_PARAMETER(ppos);
- if (!data->write_proc)
- return -EIO;
- return data->write_proc(file, buffer, count, data);
-#endif
+ return ppde->write(file, buffer, count, ppde->data);
}
@@ -329,10 +276,10 @@ static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
*****************************************************************************/
static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
{
- PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
- if(handlers->startstop != NULL)
- handlers->startstop(proc_seq_file, IMG_TRUE);
- return handlers->off2element(proc_seq_file, *pos);
+ struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
+ if(ppde->startstop != NULL)
+ ppde->startstop(proc_seq_file, IMG_TRUE);
+ return ppde->off2element(proc_seq_file, *pos);
}
/*!
@@ -351,11 +298,11 @@ static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
*****************************************************************************/
static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
{
- PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
PVR_UNREFERENCED_PARAMETER(v);
- if(handlers->startstop != NULL)
- handlers->startstop(proc_seq_file, IMG_FALSE);
+ if(ppde->startstop != NULL)
+ ppde->startstop(proc_seq_file, IMG_FALSE);
}
/*!
@@ -379,11 +326,11 @@ static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
*****************************************************************************/
static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
{
- PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
(*pos)++;
- if( handlers->next != NULL)
- return handlers->next( proc_seq_file, v, *pos );
- return handlers->off2element(proc_seq_file, *pos);
+ if(ppde->next != NULL)
+ return ppde->next( proc_seq_file, v, *pos );
+ return ppde->off2element(proc_seq_file, *pos);
}
/*!
@@ -405,9 +352,9 @@ static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t
*****************************************************************************/
static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
{
- PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
- handlers->show( proc_seq_file,v );
- return 0;
+ struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
+ ppde->show( proc_seq_file,v );
+ return 0;
}
@@ -444,90 +391,60 @@ static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
*****************************************************************************/
-static struct proc_dir_entry* CreateProcEntryInDirSeq(
- struct proc_dir_entry *pdir,
- const IMG_CHAR * name,
- IMG_VOID* data,
- pvr_next_proc_seq_t next_handler,
- pvr_show_proc_seq_t show_handler,
- pvr_off2element_proc_seq_t off2element_handler,
- pvr_startstop_proc_seq_t startstop_handler,
- write_proc_t whandler
- )
+static struct pvr_proc_dir_entry* CreateProcEntryInDirSeq(struct proc_dir_entry *pdir,
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ pvr_proc_write_t whandler)
{
- struct proc_dir_entry * file;
+ struct pvr_proc_dir_entry * ppde;
mode_t mode;
- if (!dir)
- {
- PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
- return NULL;
- }
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+ return NULL;
+ }
mode = S_IFREG;
- if (show_handler)
- {
+ if (show_handler)
+ {
mode |= S_IRUGO;
- }
+ }
- if (whandler)
- {
+ if (whandler)
+ {
mode |= S_IWUSR;
- }
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- file=create_proc_entry(name, mode, pdir);
-
- if (file)
- {
- PVR_PROC_SEQ_HANDLERS *seq_handlers;
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
- file->owner = THIS_MODULE;
-#endif
+ }
- file->proc_fops = &pvr_proc_operations;
- file->write_proc = whandler;
+ ppde = kmalloc(sizeof(struct pvr_proc_dir_entry), GFP_KERNEL);
+ if (!ppde)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+ return NULL;
+ }
+
+ ppde->next = next_handler;
+ ppde->show = show_handler;
+ ppde->off2element = off2element_handler;
+ ppde->startstop = startstop_handler;
+ ppde->write = whandler;
+ ppde->data = data;
- /* Pass the handlers */
- file->data = kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
- if(file->data)
- {
- seq_handlers = (PVR_PROC_SEQ_HANDLERS*)file->data;
- seq_handlers->next = next_handler;
- seq_handlers->show = show_handler;
- seq_handlers->off2element = off2element_handler;
- seq_handlers->startstop = startstop_handler;
- seq_handlers->data = data;
+ ppde->pde=proc_create_data(name, mode, pdir, &pvr_proc_operations, ppde);
- return file;
- }
- }
-#else
- /* Pass the handlers */
+ if (!ppde->pde)
{
- PVR_PROC_SEQ_HANDLERS *seq_handlers;
- seq_handlers = (PVR_PROC_SEQ_HANDLERS *)kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
- if (seq_handlers)
- {
- seq_handlers->next = next_handler;
- seq_handlers->show = show_handler;
- seq_handlers->off2element = off2element_handler;
- seq_handlers->startstop = startstop_handler;
- seq_handlers->data = data;
- seq_handlers->write_proc = whandler;
- file = proc_create_data(name, mode, pdir, &pvr_proc_operations,seq_handlers);
- if (file)
- return file;
- kfree(seq_handlers);
- }
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: proc_create_data failed", PVRProcDirRoot, name));
+ kfree(ppde);
+ return NULL;
}
-#endif
-
- PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
- return NULL;
+ return ppde;
}
@@ -560,22 +477,20 @@ static struct proc_dir_entry* CreateProcEntryInDirSeq(
@Return Ptr to proc entry , 0 for failure
*****************************************************************************/
-struct proc_dir_entry* CreateProcReadEntrySeq (
- const IMG_CHAR * name,
- IMG_VOID* data,
- pvr_next_proc_seq_t next_handler,
- pvr_show_proc_seq_t show_handler,
- pvr_off2element_proc_seq_t off2element_handler,
- pvr_startstop_proc_seq_t startstop_handler
- )
+struct pvr_proc_dir_entry* CreateProcReadEntrySeq (const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler)
{
return CreateProcEntrySeq(name,
- data,
- next_handler,
- show_handler,
- off2element_handler,
- startstop_handler,
- NULL);
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ NULL);
}
/*!
@@ -612,26 +527,22 @@ struct proc_dir_entry* CreateProcReadEntrySeq (
@Return Ptr to proc entry , 0 for failure
*****************************************************************************/
-struct proc_dir_entry* CreateProcEntrySeq (
- const IMG_CHAR * name,
- IMG_VOID* data,
- pvr_next_proc_seq_t next_handler,
- pvr_show_proc_seq_t show_handler,
- pvr_off2element_proc_seq_t off2element_handler,
- pvr_startstop_proc_seq_t startstop_handler,
- write_proc_t whandler
- )
+struct pvr_proc_dir_entry* CreateProcEntrySeq (const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ pvr_proc_write_t whandler)
{
- return CreateProcEntryInDirSeq(
- dir,
- name,
- data,
- next_handler,
- show_handler,
- off2element_handler,
- startstop_handler,
- whandler
- );
+ return CreateProcEntryInDirSeq(dir,
+ name,
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ whandler);
}
@@ -667,15 +578,13 @@ struct proc_dir_entry* CreateProcEntrySeq (
@Return Ptr to proc entry , 0 for failure
*****************************************************************************/
-struct proc_dir_entry* CreatePerProcessProcEntrySeq (
- const IMG_CHAR * name,
- IMG_VOID* data,
- pvr_next_proc_seq_t next_handler,
- pvr_show_proc_seq_t show_handler,
- pvr_off2element_proc_seq_t off2element_handler,
- pvr_startstop_proc_seq_t startstop_handler,
- write_proc_t whandler
- )
+struct pvr_proc_dir_entry* CreatePerProcessProcEntrySeq (const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ pvr_proc_write_t whandler)
{
PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
IMG_UINT32 ui32PID;
@@ -692,444 +601,35 @@ struct proc_dir_entry* CreatePerProcessProcEntrySeq (
if (!psPerProc)
{
PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
-
return NULL;
}
if (!psPerProc->psProcDir)
{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- IMG_CHAR dirname_buffer[256];
- IMG_CHAR dirname[256];
- IMG_INT ret;
- const IMG_CHAR *proc_basename = dirname_buffer;
- dirname_buffer[255] = dirname[255] = '\0';
-
- OSGetProcCmdline(ui32PID, dirname_buffer, sizeof(dirname_buffer));
- PVR_DPF((PVR_DBG_MESSAGE, "Command Line of the process with ID %u is %s", ui32PID, dirname_buffer));
-
- proc_basename = OSGetPathBaseName(dirname_buffer, sizeof(dirname_buffer));
- PVR_DPF((PVR_DBG_MESSAGE, "Base Name of the process with ID %u is %s\n", ui32PID, proc_basename));
-
- ret = snprintf(dirname, sizeof(dirname), "%u-%s", ui32PID, proc_basename);
- PVR_DPF((PVR_DBG_MESSAGE, "Creating a new process entry for %s with ID %u\n", proc_basename, ui32PID));
-#else
IMG_CHAR dirname[16];
IMG_INT ret;
ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
-#endif
-
- if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
- {
- PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
- return NULL;
- }
- 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 NULL;
- }
- }
- }
-
- return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
- show_handler,off2element_handler,startstop_handler,whandler);
-}
-
-
-/*!
-******************************************************************************
-
- @Function : RemoveProcEntrySeq
-
- @Description
-
- Remove a single node (created using *Seq function) under /proc/pvr.
-
- @Input proc_entry : structure returned by Create function.
- @Return nothing
-
-*****************************************************************************/
-IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
-{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- if (dir)
- {
- void* data = proc_entry->data ;
- PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, proc_entry->name));
-
- remove_proc_entry(proc_entry->name, dir);
- if( data)
- kfree( data );
-
- }
-#endif
-}
-
-/*!
-******************************************************************************
-
- @Function : RemovePerProcessProcEntry Seq
-
- @Description
-
- Remove a single node under the per process proc directory (created by *Seq function).
-
- Remove a single node (created using *Seq function) under /proc/pvr.
-
- @Input proc_entry : structure returned by Create function.
-
- @Return nothing
-
-*****************************************************************************/
-IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
-{
- PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
-
- psPerProc = LinuxTerminatingProcessPrivateData();
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- if (!psPerProc)
- {
- psPerProc = PVRSRVFindPerProcessPrivateData();
- if (!psPerProc)
+ if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
{
- PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
- "remove %s, no per process data", proc_entry->name));
- return;
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+ return NULL;
}
- }
-
- if (psPerProc->psProcDir)
- {
- void* data = proc_entry->data ;
- PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", proc_entry->name, psPerProc->psProcDir->name));
-
- remove_proc_entry(proc_entry->name, psPerProc->psProcDir);
- if(data)
- kfree( data );
- }
-#endif
-}
-
-/*!
-******************************************************************************
-
- @Function : pvr_read_proc_vm
-
- @Description
-
- When the user accesses the proc filesystem entry for the device, we are
- called here to create the content for the 'file'. We can print anything we
- want here. If the info we want to return is too big for one page ('count'
- chars), we return successive chunks on each call. For a number of ways of
- achieving this, refer to proc_file_read() in linux/fs/proc/generic.c.
-
- Here, as we are accessing lists of information, we output '1' in '*start' to
- instruct proc to advance 'off' by 1 on each call. The number of chars placed
- in the buffer is returned. Multiple calls are made here by the proc
- filesystem until we set *eof. We can return zero without setting eof to
- instruct proc to flush 'page' (causing it to be printed) if there is not
- enough space left (eg for a complete line).
-
- @Input page : where to write the output
-
- @Input start : memory location into which should be written next offset
- to read from.
-
- @Input off : the offset into the /proc file being read
-
- @Input count : the size of the buffer 'page'
-
- @Input eof : memory location into which 1 should be written when at EOF
-
- @Input data : data specific to this /proc file entry
-
- @Return : length of string written to page
-
-*****************************************************************************/
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
-static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
- IMG_INT count, IMG_INT *eof, IMG_VOID *data)
-{
- /* PRQA S 0307 1 */ /* ignore warning about casting to different pointer type */
- pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
-
- off_t len = pprn (page, (size_t)count, off);
-
- if (len == END_OF_FILE)
- {
- len = 0;
- *eof = 1;
- }
- else if (!len) /* not enough space in the buffer */
- {
- *start = (IMG_CHAR *) 0; /* don't advance the offset */
- }
- else
- {
- *start = (IMG_CHAR *) 1;
- }
-
- return len;
-}
-#else
-static ssize_t pvr_proc_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
- struct inode *inode = file->f_path.dentry->d_inode;
- PVR_PROC_SEQ_HANDLERS *data = (PVR_PROC_SEQ_HANDLERS *)PDE_DATA(inode);
- PVR_UNREFERENCED_PARAMETER(ppos);
- if (!data->read_proc)
- return -EIO;
- return -EIO;
-
-}
-#endif
-
-
-/*!
-******************************************************************************
-
- @Function : CreateProcEntryInDir
-
- @Description
-
- Create a file under the given directory. These dynamic files can be used at
- runtime to get or set information about the device.
-
- @Input pdir : parent directory
-
- @Input name : the name of the file to create
-
- @Input rhandler : the function to supply the content
-
- @Input whandler : the function to interpret writes from the user
-
- @Return success code : 0 or -errno.
-
-*****************************************************************************/
-static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
-{
- struct proc_dir_entry * file;
- mode_t mode;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
- PVR_PROC_SEQ_HANDLERS *handlers;
-#endif
-
- if (!pdir)
- {
- PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDir: parent directory doesn't exist"));
-
- return -ENOMEM;
- }
-
- mode = S_IFREG;
-
- if (rhandler)
- {
- mode |= S_IRUGO;
- }
-
- if (whandler)
- {
- mode |= S_IWUSR;
- }
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- file = create_proc_entry(name, mode, pdir);
-
- if (file)
- {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
- file->owner = THIS_MODULE;
-#endif
- file->read_proc = rhandler;
- file->write_proc = whandler;
- file->data = data;
-
- PVR_DPF((PVR_DBG_MESSAGE, "Created proc entry %s in %s", name, pdir->name));
-
- return 0;
- }
-
- PVR_DPF((PVR_DBG_ERROR, "CreateProcEntry: cannot create proc entry %s in %s", name, pdir->name));
-#else
- handlers = (PVR_PROC_SEQ_HANDLERS *)kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
- if (handlers)
- {
- handlers->data = data;
- handlers->read_proc = rhandler;
- handlers->write_proc = whandler;
- file = proc_create_data(name, mode, pdir, &pvr_read_proc_operations, handlers);
- if (file)
- {
- PVR_DPF((PVR_DBG_MESSAGE, "Created proc entry %s in %s", name, "?" /*pdir->name*/));
- return 0;
- }
- kfree (handlers);
+ 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 NULL;
+ }
}
- PVR_DPF((PVR_DBG_ERROR, "CreateProcEntry: cannot create proc entry %s in %s", name, "?" /*pdir->name*/));
-#endif
-
- return -ENOMEM;
-}
-
-
-/*!
-******************************************************************************
-
- @Function : CreateProcEntry
-
- @Description
-
- Create a file under /proc/pvr. These dynamic files can be used at runtime
- to get or set information about the device.
-
- This interface is fuller than CreateProcReadEntry, and supports write access;
- it is really just a wrapper for the native linux functions.
-
- @Input name : the name of the file to create under /proc/pvr
-
- @Input rhandler : the function to supply the content
-
- @Input whandler : the function to interpret writes from the user
-
- @Return success code : 0 or -errno.
-
-*****************************************************************************/
-IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
-{
- return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
-}
-
-
-/*!
-******************************************************************************
-
- @Function : CreatePerProcessProcEntry
-
- @Description
-
- Create a file under /proc/pvr/<current process ID>. Apart from the
- directory where the file is created, this works the same way as
- CreateProcEntry.
-
- @Input name : the name of the file to create under the per process /proc directory
-
- @Input rhandler : the function to supply the content
-
- @Input whandler : the function to interpret writes from the user
-
- @Return success code : 0 or -errno.
-
-*****************************************************************************/
-IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
-{
- PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
- IMG_UINT32 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)
- {
- IMG_CHAR dirname[16];
- IMG_INT ret;
-
- ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
-
- if (ret <=0 || ret >= (IMG_INT)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);
-}
-
-
-/*!
-******************************************************************************
-
- @Function : CreateProcReadEntry
-
- @Description
-
- Create a file under /proc/pvr. These dynamic files can be used at runtime
- to get information about the device. Creation WILL fail if proc support is
- not compiled into the kernel. That said, the Linux kernel is not even happy
- to build without /proc support these days.
-
- @Input name : the name of the file to create
-
- @Input handler : the function to call to provide the content
-
- @Return 0 for success, -errno for failure
-
-*****************************************************************************/
-IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
-{
- struct proc_dir_entry * file;
-
- if (!dir)
- {
- PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
-
- return -ENOMEM;
}
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- /* PRQA S 0307 1 */ /* ignore warning about casting to different pointer type */
- file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
-
- if (file)
- {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
- file->owner = THIS_MODULE;
-#endif
- return 0;
- }
-#else
- /* use file_ops pointing to pvr_read_proc */
- file = proc_create_data(name, S_IFREG | S_IRUGO, dir, &pvr_read_proc_operations, handler);
- if (file)
- return 0;
-#endif
-
- PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
-
- return -ENOMEM;
+ return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
+ show_handler,off2element_handler,startstop_handler,whandler);
}
@@ -1161,11 +661,17 @@ IMG_INT CreateProcEntries(IMG_VOID)
return -ENOMEM;
}
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
+#endif
g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
- if(!g_pProcQueue || !g_pProcVersion || !g_pProcSysNodes)
+ if(!g_pProcVersion || !g_pProcSysNodes
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+ || !g_pProcQueue
+#endif
+ )
{
PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
@@ -1207,44 +713,45 @@ IMG_INT CreateProcEntries(IMG_VOID)
/*!
******************************************************************************
- @Function : RemoveProcEntry
+ @Function : RemoveProcEntrySeq
@Description
- Remove a single node under /proc/pvr.
+ Remove a single node (created using *Seq function) under /proc/pvr.
- @Input name : the name of the node to remove
+ @Input proc_entry : structure returned by Create function.
@Return nothing
*****************************************************************************/
-IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+IMG_VOID RemoveProcEntrySeq(struct pvr_proc_dir_entry* ppde)
{
- if (dir)
- {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- remove_proc_entry(name, dir);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+ remove_proc_entry(ppde->pde->name, dir);
+#else
+ proc_remove(ppde->pde);
#endif
- PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
- }
+ kfree(ppde);
}
/*!
******************************************************************************
- @Function : RemovePerProcessProcEntry
+ @Function : RemovePerProcessProcEntrySeq
@Description
- Remove a single node under the per process proc directory.
+ Remove a single node under the per process proc directory (created by *Seq function).
- @Input name : the name of the node to remove
+ Remove a single node (created using *Seq function) under /proc/pvr.
+
+ @Input proc_entry : structure returned by Create function.
@Return nothing
*****************************************************************************/
-IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
+IMG_VOID RemovePerProcessProcEntrySeq(struct pvr_proc_dir_entry* ppde)
{
PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
@@ -1254,19 +761,44 @@ IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
psPerProc = PVRSRVFindPerProcessPrivateData();
if (!psPerProc)
{
- PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
- "remove %s, no per process data", name));
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't remove proc entry, no per process data"));
return;
}
}
if (psPerProc->psProcDir)
{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
- remove_proc_entry(name, psPerProc->psProcDir);
-
- PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", name, psPerProc->psProcDir->name));
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing per-process proc entry"));
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+ remove_proc_entry(ppde->pde->name, psPerProc->psProcDir);
+#else
+ proc_remove(ppde->pde);
#endif
+ kfree(ppde);
+ }
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+/*!
+******************************************************************************
+
+ @Function : RemoveProcEntry
+
+ @Description
+
+ Remove a single node under /proc/pvr.
+
+ @Input name : the name of the node to remove
+
+ @Return nothing
+
+*****************************************************************************/
+static IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+{
+ if (dir)
+ {
+ remove_proc_entry(name, dir);
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
}
}
@@ -1289,7 +821,6 @@ IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
{
if (psPerProc->psProcDir)
{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
while (psPerProc->psProcDir->subdir)
{
PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
@@ -1297,10 +828,14 @@ IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
RemoveProcEntry(psPerProc->psProcDir->subdir->name);
}
RemoveProcEntry(psPerProc->psProcDir->name);
-#endif
}
}
-
+#else
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+ proc_remove(psPerProc->psProcDir);
+}
+#endif
/*!
******************************************************************************
@@ -1318,7 +853,6 @@ IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
*****************************************************************************/
IMG_VOID RemoveProcEntries(IMG_VOID)
{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
#ifdef DEBUG
RemoveProcEntrySeq( g_pProcDebugLevel );
#ifdef PVR_MANUAL_POWER_CONTROL
@@ -1326,21 +860,35 @@ IMG_VOID RemoveProcEntries(IMG_VOID)
#endif /* PVR_MANUAL_POWER_CONTROL */
#endif
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
RemoveProcEntrySeq(g_pProcQueue);
+#endif
RemoveProcEntrySeq(g_pProcVersion);
RemoveProcEntrySeq(g_pProcSysNodes);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
while (dir->subdir)
{
PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
RemoveProcEntry(dir->subdir->name);
}
-
remove_proc_entry(PVRProcDirRoot, NULL);
#else
proc_remove(dir);
#endif
+
+}
+
+/*************************************************************************/ /*!
+@Function PVRProcGetData
+@Description Extract data from PVR proc object.
+@Input pointer to pvr_proc_dir_entr object
+@Return pointer to data object passed in to Proc create function.
+*/ /**************************************************************************/
+void *PVRProcGetData(struct pvr_proc_dir_entry *ppde)
+{
+ return ppde->data;
}
/*****************************************************************************
@@ -1351,7 +899,7 @@ IMG_VOID RemoveProcEntries(IMG_VOID)
PARAMETERS : sfile - /proc seq_file
el - Element to print
*****************************************************************************/
-static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
+static void ProcSeqShowVersion(struct seq_file *sfile, void* el)
{
SYS_DATA *psSysData;
IMG_CHAR *pszSystemVersionString = "None";
@@ -1374,24 +922,6 @@ static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
}
-/*!
-******************************************************************************
-
- @Function procDumpSysNodes (plus deviceTypeToString and deviceClassToString)
-
- @Description
-
- Format the contents of /proc/pvr/nodes
-
- @Input buf : where to place format contents data.
-
- @Input size : the size of the buffer into which to place data
-
- @Input off : how far into the file we are.
-
- @Return amount of data placed in buffer, 0, or END_OF_FILE :
-
-******************************************************************************/
static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
{
switch (deviceType)
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/proc.h b/drivers/gpu/pvr/services4/srvkm/env/linux/proc.h
index 62c6dafc0ad..e3abec2bb33 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/proc.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/proc.h
@@ -44,18 +44,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef __SERVICES_PROC_H__
#define __SERVICES_PROC_H__
-#include <asm/system.h> // va_list etc
-#include <linux/proc_fs.h> // read_proc_t etc
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
-typedef int (read_proc_t)(char *page, char **start, off_t off, int count, int *eof, void *data);
-typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+#include <asm/system.h>
#endif
-#include <linux/seq_file.h> // seq_file
-
-#define END_OF_FILE (off_t) -1
-
-typedef off_t (pvr_read_proc_t)(IMG_CHAR *, size_t, off_t);
+#include <linux/seq_file.h>
+#include "img_defs.h"
+struct pvr_proc_dir_entry;
#define PVR_PROC_SEQ_START_TOKEN (void*)1
typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t);
@@ -63,73 +58,38 @@ typedef void* (pvr_off2element_proc_seq_t)(struct seq_file *, loff_t);
typedef void (pvr_show_proc_seq_t)(struct seq_file *,void*);
typedef void (pvr_startstop_proc_seq_t)(struct seq_file *, IMG_BOOL start);
-typedef struct _PVR_PROC_SEQ_HANDLERS_ {
- pvr_next_proc_seq_t *next;
- pvr_show_proc_seq_t *show;
- pvr_off2element_proc_seq_t *off2element;
- pvr_startstop_proc_seq_t *startstop;
- IMG_VOID *data;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
- read_proc_t *read_proc;
- write_proc_t *write_proc;
-#endif
-} PVR_PROC_SEQ_HANDLERS;
-
-
-/** off2element function for elements with only ONE element (no header) */
-void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
-
-/** off2element function for elements with only ONE element (+ header) */
-void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
-
-off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
- __attribute__((format(printf, 4, 5)));
-
-IMG_INT CreateProcEntries(IMG_VOID);
-
-IMG_INT CreateProcReadEntry (const IMG_CHAR * name, pvr_read_proc_t handler);
-
-IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
-
-IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
-
-IMG_VOID RemoveProcEntry(const IMG_CHAR * name);
-
-IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR * name);
+typedef int (pvr_proc_write_t)(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
-IMG_VOID RemoveProcEntries(IMG_VOID);
+IMG_INT CreateProcEntries(void);
+void RemoveProcEntries(void);
-struct proc_dir_entry* CreateProcReadEntrySeq (
- const IMG_CHAR* name,
- IMG_VOID* data,
- pvr_next_proc_seq_t next_handler,
- pvr_show_proc_seq_t show_handler,
- pvr_off2element_proc_seq_t off2element_handler,
- pvr_startstop_proc_seq_t startstop_handler
- );
+struct pvr_proc_dir_entry* CreateProcReadEntrySeq(const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler);
-struct proc_dir_entry* CreateProcEntrySeq (
- const IMG_CHAR* name,
- IMG_VOID* data,
- pvr_next_proc_seq_t next_handler,
- pvr_show_proc_seq_t show_handler,
- pvr_off2element_proc_seq_t off2element_handler,
- pvr_startstop_proc_seq_t startstop_handler,
- write_proc_t whandler
- );
+struct pvr_proc_dir_entry* CreateProcEntrySeq(const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ pvr_proc_write_t whandler);
-struct proc_dir_entry* CreatePerProcessProcEntrySeq (
- const IMG_CHAR* name,
- IMG_VOID* data,
- pvr_next_proc_seq_t next_handler,
- pvr_show_proc_seq_t show_handler,
- pvr_off2element_proc_seq_t off2element_handler,
- pvr_startstop_proc_seq_t startstop_handler,
- write_proc_t whandler
- );
+struct pvr_proc_dir_entry* CreatePerProcessProcEntrySeq(const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ pvr_proc_write_t whandler);
+void RemoveProcEntrySeq(struct pvr_proc_dir_entry* proc_entry);
+void RemovePerProcessProcEntrySeq(struct pvr_proc_dir_entry* proc_entry);
-IMG_VOID RemoveProcEntrySeq(struct proc_dir_entry* proc_entry);
-IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry);
+void *PVRProcGetData(struct pvr_proc_dir_entry* ppde);
#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_bridge_k.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
index 5d1ad8c36b0..2a61e545015 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
@@ -41,6 +41,8 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ /**************************************************************************/
+#include <linux/fs.h>
+
#include "img_defs.h"
#include "services.h"
#include "pvr_bridge.h"
@@ -84,7 +86,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#if defined(DEBUG_BRIDGE_KM)
-static struct proc_dir_entry *g_ProcBridgeStats =0;
+static struct pvr_proc_dir_entry *g_ProcBridgeStats =0;
static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
@@ -95,7 +97,7 @@ static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
#if defined(SUPPORT_MEMINFO_IDS)
-static IMG_UINT64 ui64Stamp;
+IMG_UINT64 g_ui64MemInfoID;
#endif /* defined(SUPPORT_MEMINFO_IDS) */
PVRSRV_ERROR
@@ -141,7 +143,7 @@ static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
{
if(start)
{
- LinuxLockMutex(&gPVRSRVLock);
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
}
else
{
@@ -231,7 +233,6 @@ static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
psEntry->ui32CopyFromUserTotalBytes,
psEntry->ui32CopyToUserTotalBytes);
}
-
#endif /* DEBUG_BRIDGE_KM */
@@ -253,7 +254,7 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
PVRSRV_PER_PROCESS_DATA *psPerProc;
IMG_INT err = -EFAULT;
- LinuxLockMutex(&gPVRSRVLock);
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
#if defined(SUPPORT_DRI_DRM)
psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
@@ -474,7 +475,7 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
psPrivateData->hKernelMemInfo = hMemInfo;
#if defined(SUPPORT_MEMINFO_IDS)
- psPrivateData->ui64Stamp = ++ui64Stamp;
+ psPrivateData->ui64Stamp = ++g_ui64MemInfoID;
psKernelMemInfo->ui64Stamp = psPrivateData->ui64Stamp;
if (pvr_put_user(psPrivateData->ui64Stamp, &psExportDeviceMemOUT->ui64Stamp) != 0)
@@ -505,7 +506,7 @@ 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;
- if (pvr_put_user(++ui64Stamp, &psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp) != 0)
+ if (pvr_put_user(++g_ui64MemInfoID, &psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp) != 0)
{
err = -EFAULT;
goto unlock_and_return;
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_debug.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_debug.c
index 04e42ad3afb..df3a9b5ef22 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_debug.c
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_debug.c
@@ -51,16 +51,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/string.h> // strncpy, strlen
#include <stdarg.h>
+#include <linux/seq_file.h>
#include "img_types.h"
#include "servicesext.h"
#include "pvr_debug.h"
#include "srvkm.h"
-#include "proc.h"
#include "mutex.h"
#include "linkage.h"
#include "pvr_uaccess.h"
@@ -69,6 +70,104 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define PVR_DEBUG_ALWAYS_USE_SPINLOCK
#endif
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+/******** BUFFERED LOG MESSAGES ********/
+
+/* Because we don't want to have to handle CCB wrapping, each buffered
+ * message is rounded up to PVRSRV_DEBUG_CCB_MESG_MAX bytes. This means
+ * there is the same fixed number of messages that can be stored,
+ * regardless of message length.
+ */
+
+#if defined(PVRSRV_DEBUG_CCB_MAX)
+
+#define PVRSRV_DEBUG_CCB_MESG_MAX PVR_MAX_DEBUG_MESSAGE_LEN
+
+#include <linux/syscalls.h>
+#include <linux/time.h>
+
+typedef struct
+{
+ const IMG_CHAR *pszFile;
+ IMG_INT iLine;
+ IMG_UINT32 ui32TID;
+ IMG_CHAR pcMesg[PVRSRV_DEBUG_CCB_MESG_MAX];
+ struct timeval sTimeVal;
+}
+PVRSRV_DEBUG_CCB;
+
+static PVRSRV_DEBUG_CCB gsDebugCCB[PVRSRV_DEBUG_CCB_MAX] = { { 0 } };
+
+static IMG_UINT giOffset = 0;
+
+static PVRSRV_LINUX_MUTEX gsDebugCCBMutex;
+
+static void
+AddToBufferCCB(const IMG_CHAR *pszFileName, IMG_UINT32 ui32Line,
+ const IMG_CHAR *szBuffer)
+{
+ LinuxLockMutex(&gsDebugCCBMutex);
+
+ gsDebugCCB[giOffset].pszFile = pszFileName;
+ gsDebugCCB[giOffset].iLine = ui32Line;
+ gsDebugCCB[giOffset].ui32TID = current->tgid;
+
+ do_gettimeofday(&gsDebugCCB[giOffset].sTimeVal);
+
+ strncpy(gsDebugCCB[giOffset].pcMesg, szBuffer, PVRSRV_DEBUG_CCB_MESG_MAX - 1);
+ gsDebugCCB[giOffset].pcMesg[PVRSRV_DEBUG_CCB_MESG_MAX - 1] = 0;
+
+ giOffset = (giOffset + 1) % PVRSRV_DEBUG_CCB_MAX;
+
+ LinuxUnLockMutex(&gsDebugCCBMutex);
+}
+
+IMG_EXPORT IMG_VOID PVRSRVDebugPrintfDumpCCB(void)
+{
+ int i;
+
+ LinuxLockMutex(&gsDebugCCBMutex);
+
+ for(i = 0; i < PVRSRV_DEBUG_CCB_MAX; i++)
+ {
+ PVRSRV_DEBUG_CCB *psDebugCCBEntry =
+ &gsDebugCCB[(giOffset + i) % PVRSRV_DEBUG_CCB_MAX];
+
+ /* Early on, we won't have PVRSRV_DEBUG_CCB_MAX messages */
+ if(!psDebugCCBEntry->pszFile)
+ continue;
+
+ printk("%s:%d:\t[%5ld.%6ld] %s\n",
+ psDebugCCBEntry->pszFile,
+ psDebugCCBEntry->iLine,
+ (long)psDebugCCBEntry->sTimeVal.tv_sec,
+ (long)psDebugCCBEntry->sTimeVal.tv_usec,
+ psDebugCCBEntry->pcMesg);
+ }
+
+ LinuxUnLockMutex(&gsDebugCCBMutex);
+}
+
+#else /* defined(PVRSRV_DEBUG_CCB_MAX) */
+static INLINE void
+AddToBufferCCB(const IMG_CHAR *pszFileName, IMG_UINT32 ui32Line,
+ const IMG_CHAR *szBuffer)
+{
+ (void)pszFileName;
+ (void)szBuffer;
+ (void)ui32Line;
+}
+
+IMG_EXPORT IMG_VOID PVRSRVDebugPrintfDumpCCB(void)
+{
+ /* Not available */
+}
+
+#endif /* defined(PVRSRV_DEBUG_CCB_MAX) */
+
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
+
static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
const IMG_CHAR* pszFormat, va_list VArgs)
IMG_FORMAT_PRINTF(3, 0);
@@ -76,15 +175,9 @@ static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
#if defined(PVRSRV_NEED_PVR_DPF)
-#define PVR_MAX_FILEPATH_LEN 256
-
-static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
- const IMG_CHAR *pszFormat, ...)
- IMG_FORMAT_PRINTF(3, 4);
-
/* NOTE: Must NOT be static! Used in module.c.. */
IMG_UINT32 gPVRDebugLevel =
- (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING);
+ (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING | DBGPRIV_BUFFERED);
#endif /* defined(PVRSRV_NEED_PVR_DPF) || defined(PVRSRV_NEED_PVR_TRACE) */
@@ -128,7 +221,7 @@ static inline void GetBufferLock(unsigned long *pulLockFlags)
#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
else
{
- LinuxLockMutex(&gsDebugMutexNonIRQ);
+ LinuxLockMutexNested(&gsDebugMutexNonIRQ, PVRSRV_LOCK_CLASS_PVR_DEBUG);
}
#endif
}
@@ -194,7 +287,10 @@ static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR
IMG_VOID PVRDPFInit(IMG_VOID)
{
#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
- LinuxInitMutex(&gsDebugMutexNonIRQ);
+ LinuxInitMutex(&gsDebugMutexNonIRQ);
+#endif
+#if defined(PVRSRV_DEBUG_CCB_MAX)
+ LinuxInitMutex(&gsDebugCCBMutex);
#endif
}
@@ -231,7 +327,6 @@ IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
ReleaseBufferLock(ulLockFlags);
va_end(vaArgs);
-
}
#if defined(PVRSRV_NEED_PVR_TRACE)
@@ -277,25 +372,6 @@ IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
#if defined(PVRSRV_NEED_PVR_DPF)
-/*
- * Append a string to a buffer using formatted conversion.
- * The function takes a variable number of arguments, calling
- * VBAppend to do the actual work.
- */
-static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
-{
- va_list VArgs;
- IMG_BOOL bTrunc;
-
- va_start (VArgs, pszFormat);
-
- bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
-
- va_end (VArgs);
-
- return bTrunc;
-}
-
/*!
******************************************************************************
@Function PVRSRVDebugPrintf
@@ -317,8 +393,6 @@ IMG_VOID PVRSRVDebugPrintf (
{
IMG_BOOL bTrace;
const IMG_CHAR *pszFileName = pszFullFileName;
- IMG_CHAR *pszLeafName;
-
bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
@@ -365,9 +439,14 @@ IMG_VOID PVRSRVDebugPrintf (
strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1));
break;
}
+ case DBGPRIV_BUFFERED:
+ {
+ strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+ break;
+ }
default:
{
- strncpy (pszBuf, "PVR_K:(Unknown message level)", (ui32BufSiz -1));
+ strncpy (pszBuf, "PVR_K:(Unknown message level): ", (ui32BufSiz -1));
break;
}
}
@@ -383,82 +462,14 @@ IMG_VOID PVRSRVDebugPrintf (
}
else
{
- /* Traces don't need a location */
- if (bTrace == IMG_FALSE)
+ if (ui32DebugLevel & DBGPRIV_BUFFERED)
{
-#ifdef DEBUG_LOG_PATH_TRUNCATE
- /* Buffer for rewriting filepath in log messages */
- static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
-
- IMG_CHAR* pszTruncIter;
- IMG_CHAR* pszTruncBackInter;
-
- /* Truncate path (DEBUG_LOG_PATH_TRUNCATE shoud be set to EURASIA env var)*/
- if (strlen(pszFullFileName) > strlen(DEBUG_LOG_PATH_TRUNCATE)+1)
- pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
+ /* We don't need the full path here */
+ const IMG_CHAR *pszShortName = strrchr(pszFileName, '/') + 1;
+ if(pszShortName)
+ pszFileName = pszShortName;
- /* Try to find '/../' entries and remove it together with
- previous entry. Repeat unit all removed */
- strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
-
- if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
- IMG_CHAR szTruncateMassage[] = "FILENAME TRUNCATED";
- strcpy(szFileNameRewrite + (PVR_MAX_FILEPATH_LEN - 1 - strlen(szTruncateMassage)), szTruncateMassage);
- }
-
- pszTruncIter = szFileNameRewrite;
- while(*pszTruncIter++ != 0)
- {
- IMG_CHAR* pszNextStartPoint;
- /* Find '/../' pattern */
- if(
- !( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) &&
- ( *(pszTruncIter-1) == '.') &&
- ( *(pszTruncIter-2) == '.') &&
- ( *(pszTruncIter-3) == '/') )
- ) continue;
-
- /* Find previous '/' */
- pszTruncBackInter = pszTruncIter - 3;
- while(*(--pszTruncBackInter) != '/')
- {
- if(pszTruncBackInter <= szFileNameRewrite) break;
- }
- pszNextStartPoint = pszTruncBackInter;
-
- /* Remove found region */
- while(*pszTruncIter != 0)
- {
- *pszTruncBackInter++ = *pszTruncIter++;
- }
- *pszTruncBackInter = 0;
-
- /* Start again */
- pszTruncIter = pszNextStartPoint;
- }
-
- pszFileName = szFileNameRewrite;
- /* Remove first '/' if exist (it's always relative path */
- if(*pszFileName == '/') pszFileName++;
-#endif
-
-#if !defined(__sh__)
- pszLeafName = (IMG_CHAR *)strrchr (pszFileName, '\\');
-
- if (pszLeafName)
- {
- pszFileName = pszLeafName;
- }
-#endif /* __sh__ */
-
- if (BAppend(pszBuf, ui32BufSiz, " [%u, %s]", ui32Line, pszFileName))
- {
- printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
- }
- else
- {
- printk(KERN_INFO "%s\n", pszBuf);
- }
+ AddToBufferCCB(pszFileName, ui32Line, pszBuf);
}
else
{
@@ -481,6 +492,9 @@ IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT
#define _PROC_SET_BUFFER_SZ 6
IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
+ PVR_UNREFERENCED_PARAMETER(file);
+ PVR_UNREFERENCED_PARAMETER(data);
+
if (count > _PROC_SET_BUFFER_SZ)
{
return -EINVAL;
@@ -498,8 +512,10 @@ IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT
return (count);
}
-void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el)
+void ProcSeqShowDebugLevel(struct seq_file *sfile, void* el)
{
+ PVR_UNREFERENCED_PARAMETER(el);
+
seq_printf(sfile, "%u\n", gPVRDebugLevel);
}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c
new file mode 100755
index 00000000000..3aae69e232e
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c
@@ -0,0 +1,739 @@
+/*************************************************************************/ /*!
+@Title PowerVR drm driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description linux module setup
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if defined(SUPPORT_DRI_DRM)
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <asm/ioctl.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "pvr_bridge.h"
+#include "pvrmodule.h"
+#include "pvrversion.h"
+#include "lock.h"
+#include "linkage.h"
+#include "pvr_drm.h"
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+#include "pvr_drm_mod.h"
+#endif
+
+#if (defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(PVR_LDM_PLATFORM_PRE_REGISTERED)) || defined(NO_HARDWARE)
+#define PVR_DRM_NAME SYS_SGX_DEV_NAME
+#else
+#define PVR_DRM_NAME PVRSRV_MODNAME
+#endif
+
+#define PVR_DRM_DESC "Imagination Technologies PVR DRM"
+
+#define PVR_DRM_DATE "20110701"
+
+#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+#define PVR_NEW_STYLE_DRM_PLATFORM_DEV
+#else
+#define PVR_OLD_STYLE_DRM_PLATFORM_DEV
+#endif
+#endif
+
+/*
+ * Prior to Linux 2.6.36, we couldn't do the release processing in post close
+ * when workqueues were being used, because drm_release held the big kernel
+ * lock (BKL) when it called post close.
+ * If the resman needs to wait for processing being done by a workqueue,
+ * that processing won't complete whilst the lock is held by another thread,
+ * as the workqueue won't get scheduled.
+ */
+#undef PVR_DRI_DRM_USE_POST_CLOSE
+#if (defined(SUPPORT_DRI_DRM_EXT) && !defined(PVR_LINUX_USING_WORKQUEUES)) || \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+#define PVR_DRI_DRM_USE_POST_CLOSE
+#endif
+
+DECLARE_WAIT_QUEUE_HEAD(sWaitForInit);
+
+#if defined(SUPPORT_DRM_MODESET)
+static struct drm_driver sPVRDrmDriver;
+#endif
+
+/* Once bInitComplete and bInitFailed are set, they stay set */
+IMG_BOOL bInitComplete;
+IMG_BOOL bInitFailed;
+
+#if !defined(PVR_DRI_DRM_NOT_PCI) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+struct platform_device *gpsPVRLDMDev;
+#else
+struct pci_dev *gpsPVRLDMDev;
+#endif
+#endif
+
+struct drm_device *gpsPVRDRMDev;
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+#error "Linux kernel version 2.6.25 or later required for PVR DRM support"
+#endif
+
+#define PVR_DRM_FILE struct drm_file *
+
+#if !defined(SUPPORT_DRI_DRM_EXT) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+static struct platform_device_id asPlatIdList[] = {
+ {SYS_SGX_DEV_NAME, 0},
+ {}
+};
+#else /* defined(PVR_DRI_DRM_PLATFORM_DEV) */
+static struct pci_device_id asPciIdList[] = {
+#if defined(PVR_DRI_DRM_NOT_PCI)
+ {1, 1, 1, 1, 0, 0, 0},
+#else /* defined(PVR_DRI_DRM_NOT_PCI) */
+ {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#if defined(SYS_SGX_DEV1_DEVICE_ID)
+ {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif /* defined(SYS_SGX_DEV1_DEVICE_ID) */
+#endif /* defined(PVR_DRI_DRM_NOT_PCI) */
+ {0}
+};
+#endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) */
+#endif /* !defined(SUPPORT_DRI_DRM_EXT) */
+
+DRI_DRM_STATIC int
+PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
+{
+ int iRes = 0;
+
+ PVR_TRACE(("PVRSRVDrmLoad"));
+
+ gpsPVRDRMDev = dev;
+#if !defined(PVR_DRI_DRM_NOT_PCI) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+ gpsPVRLDMDev = dev->platformdev;
+#else
+ gpsPVRLDMDev = dev->pdev;
+#endif
+#endif
+
+#if defined(PDUMP)
+ iRes = dbgdrv_init();
+ if (iRes != 0)
+ {
+ goto exit;
+ }
+#endif
+ /* Module initialisation */
+ iRes = PVRCore_Init();
+ if (iRes != 0)
+ {
+ goto exit_dbgdrv_cleanup;
+ }
+
+#if defined(DISPLAY_CONTROLLER)
+ iRes = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(dev);
+ if (iRes != 0)
+ {
+ goto exit_pvrcore_cleanup;
+ }
+#endif
+ goto exit;
+
+#if defined(DISPLAY_CONTROLLER)
+exit_pvrcore_cleanup:
+ PVRCore_Cleanup();
+#endif
+exit_dbgdrv_cleanup:
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+exit:
+ if (iRes != 0)
+ {
+ bInitFailed = IMG_TRUE;
+ }
+ bInitComplete = IMG_TRUE;
+
+ wake_up_interruptible(&sWaitForInit);
+
+ return iRes;
+}
+
+DRI_DRM_STATIC int
+PVRSRVDrmUnload(struct drm_device *dev)
+{
+ PVR_TRACE(("PVRSRVDrmUnload"));
+
+#if defined(DISPLAY_CONTROLLER)
+ PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(dev);
+#endif
+
+ PVRCore_Cleanup();
+
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+
+ return 0;
+}
+
+DRI_DRM_STATIC int
+PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file)
+{
+ while (!bInitComplete)
+ {
+ DEFINE_WAIT(sWait);
+
+ prepare_to_wait(&sWaitForInit, &sWait, TASK_INTERRUPTIBLE);
+
+ if (!bInitComplete)
+ {
+ PVR_TRACE(("%s: Waiting for module initialisation to complete", __FUNCTION__));
+
+ schedule();
+ }
+
+ finish_wait(&sWaitForInit, &sWait);
+
+ if (signal_pending(current))
+ {
+ return -ERESTARTSYS;
+ }
+ }
+
+ if (bInitFailed)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Module initialisation failed", __FUNCTION__));
+ return -EINVAL;
+ }
+
+ return PVRSRVOpen(dev, file);
+}
+
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE) || defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+DRI_DRM_STATIC int
+PVRSRVDrmRelease(struct drm_device *dev, struct drm_file *file)
+#else
+DRI_DRM_STATIC void
+PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file)
+#endif
+{
+ PVRSRVRelease(file->driver_priv);
+
+ file->driver_priv = NULL;
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+ return 0;
+#endif
+}
+#else
+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;
+ int ret;
+
+ ret = drm_release(inode, filp);
+
+ if (ret != 0)
+ {
+ /*
+ * An error means drm_release didn't call drm_lastclose,
+ * but it will have freed file_priv.
+ */
+ PVR_DPF((PVR_DBG_ERROR, "%s : drm_release failed: %d",
+ __FUNCTION__, ret));
+ }
+
+ PVRSRVRelease(psDriverPriv);
+
+ return 0;
+}
+#endif
+
+DRI_DRM_STATIC int
+PVRDRMIsMaster(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+ return 0;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+int
+PVRDRM_Dummy_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+ return 0;
+}
+#endif
+
+DRI_DRM_STATIC int
+PVRDRMUnprivCmd(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+ int ret = 0;
+
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+ if (arg == NULL)
+ {
+ ret = -EFAULT;
+ }
+ else
+ {
+ drm_pvr_unpriv_cmd *psArgs = (drm_pvr_unpriv_cmd *)arg;
+
+ switch (psArgs->cmd)
+ {
+ case PVR_DRM_UNPRIV_INIT_SUCCESFUL:
+ psArgs->res = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0;
+ break;
+
+ default:
+ ret = -EFAULT;
+ }
+
+ }
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ return ret;
+}
+
+#if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+static int
+PVRDRM_Display_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+ int res;
+
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+ res = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(dev, arg, pFile);
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ return res;
+}
+#endif
+
+#if defined(SUPPORT_DRM_MODESET)
+static int
+PVRSRVPciProbe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ PVR_TRACE(("PVRSRVPciProbe"));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+ return drm_get_pci_dev(dev, id, &sPVRDrmDriver);
+#else
+ return drm_get_dev(dev, id, &sPVRDrmDriver);
+#endif
+}
+
+static void
+PVRSRVPciRemove(struct pci_dev *dev)
+{
+ struct drm_device *psDrmDev;
+
+ PVR_TRACE(("PVRSRVPciRemove"));
+
+ psDrmDev = pci_get_drvdata(dev);
+ drm_put_dev(psDrmDev);
+}
+#endif
+
+/*
+ * For Linux 2.6.33 and above, the DRM ioctl entry point is of the unlocked
+ * variety. The big kernel lock is still taken for ioctls, unless
+ * the DRM_UNLOCKED flag is set. If you revise one of the driver specific
+ * ioctls, or add a new one, consider whether the gPVRSRVLock mutex needs
+ * to be taken.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+#define PVR_DRM_FOPS_IOCTL .unlocked_ioctl
+#define PVR_DRM_UNLOCKED DRM_UNLOCKED
+#else
+#define PVR_DRM_FOPS_IOCTL .ioctl
+#define PVR_DRM_UNLOCKED 0
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+
+#if defined(DRM_IOCTL_DEF)
+#define PVR_DRM_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(DRM_##ioctl, _func, _flags)
+#else
+#define PVR_DRM_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)
+#endif
+
+struct drm_ioctl_desc sPVRDrmIoctls[] = {
+ PVR_DRM_IOCTL_DEF(PVR_SRVKM, PVRSRV_BridgeDispatchKM, PVR_DRM_UNLOCKED),
+ PVR_DRM_IOCTL_DEF(PVR_IS_MASTER, PVRDRMIsMaster, DRM_MASTER | PVR_DRM_UNLOCKED),
+ PVR_DRM_IOCTL_DEF(PVR_UNPRIV, PVRDRMUnprivCmd, PVR_DRM_UNLOCKED),
+#if defined(PDUMP)
+ PVR_DRM_IOCTL_DEF(PVR_DBGDRV, dbgdrv_ioctl, PVR_DRM_UNLOCKED),
+#endif
+#if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+ PVR_DRM_IOCTL_DEF(PVR_DISP, PVRDRM_Display_ioctl, DRM_MASTER | PVR_DRM_UNLOCKED)
+#endif
+};
+
+#if !defined(SUPPORT_DRI_DRM_PLUGIN)
+static int pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls);
+#endif
+
+#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
+static int PVRSRVDrmProbe(struct platform_device *pDevice);
+static int PVRSRVDrmRemove(struct platform_device *pDevice);
+#endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) */
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+static PVRSRV_DRM_PLUGIN sPVRDrmPlugin =
+{
+ .name = PVR_DRM_NAME,
+
+ .open = PVRSRVDrmOpen,
+ .load = PVRSRVDrmLoad,
+ .unload = PVRSRVDrmUnload,
+
+ .release = PVRSRVDrmRelease,
+
+ .mmap = PVRMMap,
+
+ .ioctls = sPVRDrmIoctls,
+ .num_ioctls = DRM_ARRAY_SIZE(sPVRDrmIoctls),
+ .ioctl_start = 0
+};
+#else /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+static const struct file_operations sPVRFileOps =
+{
+ .owner = THIS_MODULE,
+ .open = drm_open,
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE)
+ .release = drm_release,
+#else
+ .release = PVRSRVDrmRelease,
+#endif
+ PVR_DRM_FOPS_IOCTL = drm_ioctl,
+ .mmap = PVRMMap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+};
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */
+
+static struct drm_driver sPVRDrmDriver =
+{
+#if defined(PVR_OLD_STYLE_DRM_PLATFORM_DEV)
+ .driver_features = DRIVER_USE_PLATFORM_DEVICE,
+#else
+ .driver_features = 0,
+#endif
+ .dev_priv_size = 0,
+ .load = PVRSRVDrmLoad,
+ .unload = PVRSRVDrmUnload,
+ .open = PVRSRVDrmOpen,
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE)
+ .postclose = PVRSRVDrmPostClose,
+#endif
+#if !defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRM_MODESET)
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37))
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+#endif
+ .ioctls = sPVRDrmIoctls,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+ .fops = &sPVRFileOps,
+#else
+ .fops =
+ {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE)
+ .release = drm_release,
+#else
+ .release = PVRSRVDrmRelease,
+#endif
+ PVR_DRM_FOPS_IOCTL = drm_ioctl,
+ .mmap = PVRMMap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ },
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+#if defined(PVR_OLD_STYLE_DRM_PLATFORM_DEV)
+ .platform_driver =
+ {
+ .id_table = asPlatIdList,
+ .driver =
+ {
+ .name = PVR_DRM_NAME,
+ },
+ .probe = PVRSRVDrmProbe,
+ .remove = PVRSRVDrmRemove,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+ .shutdown = PVRSRVDriverShutdown,
+ },
+#else
+ .pci_driver =
+ {
+ .name = PVR_DRM_NAME,
+ .id_table = asPciIdList,
+#if defined(SUPPORT_DRM_MODESET)
+ .probe = PVRSRVPciProbe,
+ .remove = PVRSRVPciRemove,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+#endif
+ },
+#endif
+#endif
+ .name = PVR_DRM_NAME,
+ .desc = PVR_DRM_DESC,
+ .date = PVR_DRM_DATE,
+ .major = PVRVERSION_MAJ,
+ .minor = PVRVERSION_MIN,
+ .patchlevel = PVRVERSION_BUILD,
+};
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) && !defined(PVR_DRI_DRM_PLATFORM_DEV)
+static struct pci_driver sPVRPCIDriver =
+{
+ .name = PVR_DRM_NAME,
+ .id_table = asPciIdList,
+#if defined(SUPPORT_DRM_MODESET)
+ .probe = PVRSRVPciProbe,
+ .remove = PVRSRVPciRemove,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+#endif
+};
+#endif
+
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+#if !defined(PVR_LDM_PLATFORM_PRE_REGISTERED) || defined(NO_HARDWARE)
+static void PVRSRVDeviceRelease(struct device unref__ *pDevice)
+{
+}
+
+static struct platform_device sPVRPlatDevice = {
+ .name = PVR_DRM_NAME,
+ .id = -1,
+ .dev = {
+ .release = PVRSRVDeviceRelease
+ }
+};
+#endif
+
+static struct platform_driver sPVRPlatDriver =
+{
+ .id_table = asPlatIdList,
+ .driver =
+ {
+ .name = PVR_DRM_NAME,
+ },
+ .probe = PVRSRVDrmProbe,
+ .remove = PVRSRVDrmRemove,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+ .shutdown = PVRSRVDriverShutdown,
+};
+#endif
+
+#endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+
+#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
+static int
+PVRSRVDrmProbe(struct platform_device *pDevice)
+{
+ PVR_TRACE(("PVRSRVDrmProbe"));
+
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+ gpsPVRLDMDev = pDevice;
+
+ return drm_platform_init(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
+ return drm_get_platform_dev(pDevice, &sPVRDrmDriver);
+#endif
+}
+
+static int
+PVRSRVDrmRemove(struct platform_device *pDevice)
+{
+ PVR_TRACE(("PVRSRVDrmRemove"));
+
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+ drm_platform_exit(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
+ drm_put_dev(gpsPVRDRMDev);
+#endif
+ return 0;
+}
+#endif
+
+static int __init PVRSRVDrmInit(void)
+{
+ int iRes;
+#if !defined(SUPPORT_DRI_DRM_PLUGIN)
+ sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
+#endif
+
+#if defined(SUPPORT_DRM_MODESET)
+ sPVRDrmDriver.driver_features |= DRIVER_MODESET;
+#endif
+
+ /* Must come before attempting to print anything via Services */
+ PVRDPFInit();
+
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+ iRes = platform_driver_register(&sPVRPlatDriver);
+#if !defined(PVR_LDM_PLATFORM_PRE_REGISTERED) || defined(NO_HARDWARE)
+ if (iRes == 0)
+ {
+ iRes = platform_device_register(&sPVRPlatDevice);
+ if (iRes != 0)
+ {
+ platform_driver_unregister(&sPVRPlatDriver);
+ }
+ }
+#endif
+#else /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+ iRes = SysDRMRegisterPlugin(&sPVRDrmPlugin);
+#else /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#if defined(PVR_DRI_DRM_NOT_PCI)
+ iRes = drm_pvr_dev_add();
+ if (iRes != 0)
+ {
+ return iRes;
+ }
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+ iRes = drm_platform_init(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
+ iRes = drm_pci_init(&sPVRDrmDriver, &sPVRPCIDriver);
+#endif
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+ iRes = drm_init(&sPVRDrmDriver);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+ if (iRes != 0)
+ {
+ drm_pvr_dev_remove();
+ }
+#endif
+#endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#endif /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+ return iRes;
+}
+
+static void __exit PVRSRVDrmExit(void)
+{
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+#if !defined(PVR_LDM_PLATFORM_PRE_REGISTERED) || defined(NO_HARDWARE)
+ platform_device_unregister(&sPVRPlatDevice);
+#endif
+ platform_driver_unregister(&sPVRPlatDriver);
+#else /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+ SysDRMUnregisterPlugin(&sPVRDrmPlugin);
+#else /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+ drm_platform_exit(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
+ drm_pci_exit(&sPVRDrmDriver, &sPVRPCIDriver);
+#endif
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+ drm_exit(&sPVRDrmDriver);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+ drm_pvr_dev_remove();
+#endif
+#endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#endif /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+}
+
+/*
+ * These macro calls define the initialisation and removal functions of the
+ * driver. Although they are prefixed `module_', they apply when compiling
+ * statically as well; in both cases they define the function the kernel will
+ * run to start/stop the driver.
+*/
+module_init(PVRSRVDrmInit);
+module_exit(PVRSRVDrmExit);
+#endif /* !defined(SUPPORT_DRI_DRM_EXT) */
+#endif /* defined(SUPPORT_DRI_DRM) */
+
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.h
new file mode 100755
index 00000000000..c3ed413a720
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.h
@@ -0,0 +1,184 @@
+/*************************************************************************/ /*!
+@Title PowerVR drm driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description drm module
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if !defined(__PVR_DRM_H__)
+#define __PVR_DRM_H__
+
+#if defined (PDUMP)
+#include "linuxsrv.h"
+#endif
+
+#include "pvr_drm_shared.h"
+
+#if defined(SUPPORT_DRI_DRM)
+
+#if defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+#include "3rdparty_dc_drm_shared.h"
+#endif
+
+#define PVR_DRM_MAKENAME_HELPER(x, y) x ## y
+#define PVR_DRM_MAKENAME(x, y) PVR_DRM_MAKENAME_HELPER(x, y)
+
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+#define LDM_DEV struct platform_device
+#endif
+
+int PVRCore_Init(void);
+void PVRCore_Cleanup(void);
+int PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
+void PVRSRVRelease(void *pvPrivData);
+
+#if !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+void PVRSRVDriverShutdown(LDM_DEV *pDevice);
+int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state);
+int PVRSRVDriverResume(LDM_DEV *pDevice);
+#else
+#if defined(SUPPORT_DRM_MODESET)
+int PVRSRVDriverSuspend(struct pci_dev *pDevice, pm_message_t state);
+int PVRSRVDriverResume(struct pci_dev *pDevice);
+#else
+int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state);
+int PVRSRVDriverResume(struct drm_device *pDevice);
+#endif /* defined(SUPPORT_DRM_MODESET) */
+#endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) */
+#endif /* !defined(SUPPORT_DRI_DRM_PLUGIN) */
+
+int PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg, struct drm_file *pFile);
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define DRI_DRM_STATIC
+/*Exported functions to common drm layer*/
+int PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags);
+int PVRSRVDrmUnload(struct drm_device *dev);
+int PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file);
+#if defined(PVR_LINUX_USING_WORKQUEUES)
+DRI_DRM_STATIC int PVRSRVDrmRelease(struct inode *inode, struct file *filp);
+#else
+void PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file);
+#endif
+int PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#else
+#define DRI_DRM_STATIC static
+#endif /* defined(SUPPORT_DRI_DRM_EXT) */
+
+#if defined(DISPLAY_CONTROLLER)
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
+extern void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device *);
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Suspend)(struct drm_device *);
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Resume)(struct drm_device *);
+#if defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device *dev, void *arg, struct drm_file *pFile);
+#endif
+#endif
+
+#if defined(PDUMP)
+int dbgdrv_init(void);
+void dbgdrv_cleanup(void);
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+/*
+ * We need the command number names to begin with "DRM_" for newer versions
+ * of the macro used to fill out the DRM ioctl table. Similarly, the
+ * ioctl number names must begin with "DRM_IOCTL_". The suffixes for the
+ * two sets of strings must match (e.g. end with "PVR_SRVKM" in both
+ * cases).
+ */
+
+#define DRM_PVR_SRVKM PVR_DRM_SRVKM_CMD
+#define DRM_PVR_IS_MASTER PVR_DRM_IS_MASTER_CMD
+#define DRM_PVR_UNPRIV PVR_DRM_UNPRIV_CMD
+#define DRM_PVR_DBGDRV PVR_DRM_DBGDRV_CMD
+#define DRM_PVR_DISP PVR_DRM_DISP_CMD
+
+/*
+ * Some versions of the kernel will dereference a NULL pointer if data is
+ * is passed to an ioctl that doesn't expect any, so avoid using the _IO
+ * macro, and use _IOW instead, specifying a dummy argument.
+*/
+typedef struct {
+ char dummy[4];
+} drm_pvr_dummy_arg;
+
+/* IOCTL numbers, relative to DRM_COMMAND_BASE */
+#define DRM_IOCTL_PVR_SRVKM _IOWR(0, DRM_PVR_SRVKM, PVRSRV_BRIDGE_PACKAGE)
+#define DRM_IOCTL_PVR_IS_MASTER _IOW(0, DRM_PVR_IS_MASTER, drm_pvr_dummy_arg)
+#define DRM_IOCTL_PVR_UNPRIV _IOWR(0, DRM_PVR_UNPRIV, drm_pvr_unpriv_cmd)
+
+#if defined(PDUMP)
+#define DRM_IOCTL_PVR_DBGDRV _IOWR(0, DRM_PVR_DBGDRV, IOCTL_PACKAGE)
+#endif
+
+#if defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+#define DRM_IOCTL_PVR_DISP _IOWR(0, DRM_PVR_DISP, drm_pvr_display_cmd)
+#endif
+#endif /* !defined(SUPPORT_DRI_DRM_EXT) */
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+typedef struct {
+ char *name;
+
+ int (*load)(struct drm_device *dev, unsigned long flags);
+ int (*unload)(struct drm_device *dev);
+
+ int (*open)(struct drm_device *dev, struct drm_file *file);
+ int (*release)(struct drm_device *dev, struct drm_file *file);
+
+ int (*mmap)(struct file* pFile, struct vm_area_struct* ps_vma);
+
+ struct drm_ioctl_desc *ioctls;
+ int num_ioctls;
+ int ioctl_start;
+} PVRSRV_DRM_PLUGIN;
+
+int SysDRMRegisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin);
+void SysDRMUnregisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin);
+#endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */
+
+#endif /* defined(SUPPORT_DRI_DRM) */
+
+#endif /* defined(__PVR_DRM_H__) */
+
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.c
new file mode 100755
index 00000000000..476f0a8cb10
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.c
@@ -0,0 +1,1766 @@
+/*************************************************************************/ /*!
+@File pvr_sync.c
+@Title Kernel driver for Android's sync mechanism
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "pvr_sync.h"
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/anon_inodes.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+#include "mutex.h"
+#include "lock.h"
+
+//#define DEBUG_PRINT
+
+#if defined(DEBUG_PRINT)
+#define DPF(fmt, ...) PVR_DPF((PVR_DBG_BUFFERED, fmt, __VA_ARGS__))
+#else
+#define DPF(fmt, ...) do {} while(0)
+#endif
+
+/* We can't support this code when the MISR runs in atomic context because
+ * PVRSyncFreeSync() may be called by sync_timeline_signal() which may be
+ * scheduled by the MISR. PVRSyncFreeSync() needs to protect the handle
+ * tables against modification and so uses the Linux bridge mutex.
+ *
+ * You can't lock a mutex in atomic context.
+ */
+#if !defined(PVR_LINUX_MISR_USING_WORKQUEUE) && \
+ !defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#error The Android sync driver requires that the SGX MISR runs in wq context
+#endif
+
+/* Local wrapper around PVRSRV_KERNEL_SYNC_INFO to add a list head */
+
+struct PVR_SYNC_KERNEL_SYNC_INFO
+{
+ /* Base services sync info structure */
+ PVRSRV_KERNEL_SYNC_INFO *psBase;
+
+ /* Sync points can go away when there are deferred hardware
+ * operations still outstanding. We must not free the SYNC_INFO
+ * until the hardware is finished, so we add it to a defer list
+ * which is processed periodically ("defer-free").
+ *
+ * This is also used for "defer-free" of a timeline -- the process
+ * may destroy its timeline or terminate abnormally but the HW could
+ * still be using the sync object hanging off of the timeline.
+ *
+ * Note that the defer-free list is global, not per-timeline.
+ */
+ struct list_head sHead;
+};
+
+/* This is the IMG extension of a sync_timeline */
+
+struct PVR_SYNC_TIMELINE
+{
+ struct sync_timeline obj;
+
+ /* Needed to keep a global list of all timelines for MISR checks. */
+ struct list_head sTimelineList;
+
+ /* True if a sync point on the timeline has signaled */
+ IMG_BOOL bSyncHasSignaled;
+
+ /* A mutex, as we want to ensure that the comparison (and possible
+ * reset) of the highest SW fence value is atomic with the takeop,
+ * so both the SW fence value and the WOP snapshot should both have
+ * the same order for all SW syncs.
+ *
+ * This mutex also protects modifications to the fence stamp counter.
+ */
+ struct mutex sTimelineLock;
+
+ /* Every timeline has a services sync object. This object must not
+ * be used by the hardware to enforce ordering -- that's what the
+ * per sync-point objects are for. This object is attached to every
+ * TQ scheduled on the timeline and is primarily useful for debugging.
+ */
+ struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo;
+};
+
+/* A PVR_SYNC_DATA is the basic guts of a sync point. It's kept separate
+ * because sync points can be dup'ed, and we don't want to duplicate all
+ * of the shared metadata.
+ *
+ * This is also used to back an allocated sync info, which can be passed to
+ * the CREATE ioctl to insert the fence and add it to the timeline. This is
+ * used as an intermediate step as a PVRSRV_KERNEL_SYNC_INFO is needed to
+ * attach to the transfer task used as a fence in the hardware.
+ */
+
+struct PVR_SYNC_DATA
+{
+ /* Every sync point has a services sync object. This object is used
+ * by the hardware to enforce ordering -- it is attached as a source
+ * dependency to various commands.
+ */
+ struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo;
+
+ /* This refcount is incremented at create and dup time, and decremented
+ * at free time. It ensures the object doesn't start the defer-free
+ * process until it is no longer referenced.
+ */
+ atomic_t sRefcount;
+
+ /* This is purely a debug feature. Record the WOP snapshot from the
+ * timeline synchronization object when a new fence is created.
+ */
+ IMG_UINT32 ui32WOPSnapshot;
+
+ /* This is a globally unique ID for the sync point. If a sync point is
+ * dupped, its stamp is copied over (seems counter-intuitive, but in
+ * nearly all cases a sync point is merged with another, the original
+ * is freed).
+ */
+ IMG_UINT64 ui64Stamp;
+};
+
+/* A PVR_ALLOC_SYNC_DATA is used to back an allocated, but not yet created
+ * and inserted into a timeline, sync data. This is required as we must
+ * allocate the syncinfo to be passed down with the transfer task used to
+ * implement fences in the hardware.
+ */
+struct PVR_ALLOC_SYNC_DATA
+{
+ struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo;
+
+ /* A link to the timeline is required to add a per-timeline sync
+ * to the fence transfer task.
+ */
+ struct PVR_SYNC_TIMELINE *psTimeline;
+ struct file *psFile;
+};
+
+/* This is the IMG extension of a sync_pt */
+
+struct PVR_SYNC
+{
+ struct sync_pt pt;
+ struct PVR_SYNC_DATA *psSyncData;
+};
+
+struct PVR_SYNC_FENCE
+{
+ /* Base sync_fence structure */
+ struct sync_fence *psBase;
+
+ /* To ensure callbacks are always received for fences / sync_pts, even
+ * after the fence has been 'put' (freed), we must take a reference to
+ * the fence. We still need to 'put' the fence ourselves, but this might
+ * happen in irq context, where fput() is not allowed (in kernels <3.6).
+ * We must add the fence to a list which is processed in WQ context.
+ */
+ struct list_head sHead;
+};
+
+/* Any sync point from a foreign (non-PVR) timeline needs to have a "shadow"
+ * syncinfo. This is modelled as a software operation. The foreign driver
+ * completes the operation by calling a callback we registered with it.
+ *
+ * Because we are allocating SYNCINFOs for each sync_pt, rather than each
+ * fence, we need to extend the waiter struct slightly to include the
+ * necessary metadata.
+ */
+struct PVR_SYNC_FENCE_WAITER
+{
+ /* Base sync driver waiter structure */
+ struct sync_fence_waiter sWaiter;
+
+ /* "Shadow" syncinfo backing the foreign driver's sync_pt */
+ struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo;
+
+ /* Optimizes lookup of fence for defer-put operation */
+ struct PVR_SYNC_FENCE *psSyncFence;
+};
+
+/* Global data relating to PVR services connection */
+
+static struct
+{
+ /* Process that initialized the sync driver. House-keep this so
+ * the correct per-proc data is used during shutdown. This PID is
+ * conventionally whatever `pvrsrvctl' was when it was alive.
+ */
+ IMG_UINT32 ui32Pid;
+
+ /* Device cookie for services allocation functions. The device would
+ * ordinarily be SGX, and the first/only device in the system.
+ */
+ IMG_HANDLE hDevCookie;
+
+ /* Device memory context that all SYNC_INFOs allocated by this driver
+ * will be created in. Because SYNC_INFOs are placed in a shared heap,
+ * it does not matter from which process the create ioctl originates.
+ */
+ IMG_HANDLE hDevMemContext;
+}
+gsSyncServicesConnection;
+
+/* Multi-purpose workqueue. Various functions in the Google sync driver
+ * may call down to us in atomic context. However, sometimes we may need
+ * to lock a mutex. To work around this conflict, use the workqueue to
+ * defer whatever the operation was.
+ */
+static struct workqueue_struct *gpsWorkQueue;
+
+/* Linux work struct for workqueue. */
+static struct work_struct gsWork;
+
+/* List of timelines, used by MISR callback to find signalled sync points
+ * and also to kick the hardware if signalling may allow progress to be
+ * made.
+ */
+static LIST_HEAD(gTimelineList);
+static DEFINE_MUTEX(gTimelineListLock);
+
+/* The "defer-free" object list. Driver global. */
+static LIST_HEAD(gSyncInfoFreeList);
+static DEFINE_SPINLOCK(gSyncInfoFreeListLock);
+
+/* The "defer-put" object list. Driver global. */
+static LIST_HEAD(gFencePutList);
+static DEFINE_SPINLOCK(gFencePutListLock);
+
+/* Sync point stamp counter -- incremented on creation of a new sync point */
+static IMG_UINT64 gui64SyncPointStamp;
+
+/* Forward declare due to cyclic dependency on gsSyncFenceAllocFOps */
+static struct PVR_ALLOC_SYNC_DATA *PVRSyncAllocFDGet(int fd);
+
+/* NOTE: Must only be called with services bridge mutex held */
+static void PVRSyncSWTakeOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+ psKernelSyncInfo->psSyncData->ui32WriteOpsPending = 1;
+}
+
+static void PVRSyncSWCompleteOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+ psKernelSyncInfo->psSyncData->ui32WriteOpsComplete = 1;
+}
+
+static struct PVR_SYNC *
+PVRSyncCreateSync(struct PVR_SYNC_TIMELINE *obj,
+ struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo)
+{
+ struct PVR_SYNC *psPt = NULL;
+
+ psPt = (struct PVR_SYNC *)
+ sync_pt_create(&obj->obj, sizeof(struct PVR_SYNC));
+ if(!psPt)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: sync_pt_create failed", __func__));
+ goto err_out;
+ }
+
+ psPt->psSyncData = kmalloc(sizeof(struct PVR_SYNC_DATA), GFP_KERNEL);
+ if(!psPt->psSyncData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_SYNC_DATA",
+ __func__));
+ goto err_free_pt;
+ }
+
+ atomic_set(&psPt->psSyncData->sRefcount, 1);
+
+ psPt->psSyncData->ui32WOPSnapshot =
+ obj->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending;
+
+ psPt->psSyncData->psSyncInfo = psSyncInfo;
+
+ /* Stamp the point and update the global counter under lock */
+ mutex_lock(&obj->sTimelineLock);
+ psPt->psSyncData->ui64Stamp = gui64SyncPointStamp++;
+ mutex_unlock(&obj->sTimelineLock);
+
+err_out:
+ return psPt;
+err_free_pt:
+ sync_pt_free((struct sync_pt *)psPt);
+ psPt = NULL;
+ goto err_out;
+}
+
+static IMG_BOOL PVRSyncIsSyncInfoInUse(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo)
+{
+ return !(psSyncInfo->psSyncData->ui32WriteOpsPending ==
+ psSyncInfo->psSyncData->ui32WriteOpsComplete &&
+ psSyncInfo->psSyncData->ui32ReadOpsPending ==
+ psSyncInfo->psSyncData->ui32ReadOpsComplete &&
+ psSyncInfo->psSyncData->ui32ReadOps2Pending ==
+ psSyncInfo->psSyncData->ui32ReadOps2Complete);
+}
+
+/* Releases a sync info by adding it to a deferred list to be freed later. */
+static void
+PVRSyncReleaseSyncInfo(struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&gSyncInfoFreeListLock, flags);
+ list_add_tail(&psSyncInfo->sHead, &gSyncInfoFreeList);
+ spin_unlock_irqrestore(&gSyncInfoFreeListLock, flags);
+
+ queue_work(gpsWorkQueue, &gsWork);
+}
+
+static void PVRSyncFreeSyncData(struct PVR_SYNC_DATA *psSyncData)
+{
+ PVR_ASSERT(atomic_read(&psSyncData->sRefcount) == 0);
+ PVRSyncReleaseSyncInfo(psSyncData->psSyncInfo);
+ psSyncData->psSyncInfo = NULL;
+ kfree(psSyncData);
+}
+
+static void PVRSyncFreeSync(struct sync_pt *psPt)
+{
+ struct PVR_SYNC *psSync = (struct PVR_SYNC *)psPt;
+#if defined(DEBUG_PRINT)
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo =
+ psSync->psSyncData->psSyncInfo->psBase;
+#endif
+
+ PVR_ASSERT(atomic_read(&psSync->psSyncData->sRefcount) > 0);
+
+ /* Only free on the last reference */
+ if (atomic_dec_return(&psSync->psSyncData->sRefcount) != 0)
+ return;
+
+ DPF("R( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X "
+ "WOP/C=0x%x/0x%x ROP/C=0x%x/0x%x RO2P/C=0x%x/0x%x "
+ "ID=%llu, S=0x%x, F=%p",
+ psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+ psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+ psSyncInfo->sReadOps2CompleteDevVAddr.uiAddr,
+ psSyncInfo->psSyncData->ui32WriteOpsPending,
+ psSyncInfo->psSyncData->ui32WriteOpsComplete,
+ psSyncInfo->psSyncData->ui32ReadOpsPending,
+ psSyncInfo->psSyncData->ui32ReadOpsComplete,
+ psSyncInfo->psSyncData->ui32ReadOps2Pending,
+ psSyncInfo->psSyncData->ui32ReadOps2Complete,
+ psSync->psSyncData->ui64Stamp,
+ psSync->psSyncData->ui32WOPSnapshot,
+ psSync->pt.fence);
+
+ PVRSyncFreeSyncData(psSync->psSyncData);
+ psSync->psSyncData = NULL;
+}
+
+static struct sync_pt *PVRSyncDup(struct sync_pt *sync_pt)
+{
+ struct PVR_SYNC *psPt, *psParentPt = (struct PVR_SYNC *)sync_pt;
+
+ psPt = (struct PVR_SYNC *)
+ sync_pt_create(sync_pt->parent, sizeof(struct PVR_SYNC));
+ if(!psPt)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: sync_pt_create failed", __func__));
+ goto err_out;
+ }
+
+ psPt->psSyncData = psParentPt->psSyncData;
+ atomic_inc(&psPt->psSyncData->sRefcount);
+
+ PVR_ASSERT(atomic_read(&psPt->psSyncData->sRefcount) > 1);
+
+err_out:
+ return (struct sync_pt*)psPt;
+}
+
+static int PVRSyncHasSignaled(struct sync_pt *sync_pt)
+{
+ struct PVR_SYNC *psPt = (struct PVR_SYNC *)sync_pt;
+ struct PVR_SYNC_TIMELINE *psTimeline =
+ (struct PVR_SYNC_TIMELINE *) sync_pt->parent;
+ PVRSRV_SYNC_DATA *psSyncData =
+ psPt->psSyncData->psSyncInfo->psBase->psSyncData;
+
+ if (psSyncData->ui32WriteOpsComplete >= psSyncData->ui32WriteOpsPending)
+ {
+ psTimeline->bSyncHasSignaled = IMG_TRUE;
+ return 1;
+ }
+
+ return 0;
+}
+
+static int PVRSyncCompare(struct sync_pt *a, struct sync_pt *b)
+{
+ IMG_UINT64 ui64StampA = ((struct PVR_SYNC *)a)->psSyncData->ui64Stamp;
+ IMG_UINT64 ui64StampB = ((struct PVR_SYNC *)b)->psSyncData->ui64Stamp;
+
+ if (ui64StampA == ui64StampB)
+ return 0;
+ else if (ui64StampA > ui64StampB)
+ return 1;
+ else
+ return -1;
+}
+
+static void PVRSyncPrintTimeline(struct seq_file *s,
+ struct sync_timeline *psObj)
+{
+ struct PVR_SYNC_TIMELINE *psTimeline = (struct PVR_SYNC_TIMELINE *)psObj;
+
+ seq_printf(s, "WOP/WOC=0x%x/0x%x",
+ psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending,
+ psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsComplete);
+}
+
+static void PVRSyncPrint(struct seq_file *s, struct sync_pt *psPt)
+{
+ struct PVR_SYNC *psSync = (struct PVR_SYNC *)psPt;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo =
+ psSync->psSyncData->psSyncInfo->psBase;
+
+ seq_printf(s, "ID=%llu, refs=%u, WOPSnapshot=0x%x, parent=%p",
+ psSync->psSyncData->ui64Stamp,
+ atomic_read(&psSync->psSyncData->sRefcount),
+ psSync->psSyncData->ui32WOPSnapshot,
+ psSync->pt.parent);
+ seq_printf(s, "\n WOP/WOC=0x%x/0x%x, "
+ "ROP/ROC=0x%x/0x%x, ROP2/ROC2=0x%x/0x%x, "
+ "WOC DevVA=0x%.8x, ROC DevVA=0x%.8x, "
+ "ROC2 DevVA=0x%.8x",
+ psSyncInfo->psSyncData->ui32WriteOpsPending,
+ psSyncInfo->psSyncData->ui32WriteOpsComplete,
+ psSyncInfo->psSyncData->ui32ReadOpsPending,
+ psSyncInfo->psSyncData->ui32ReadOpsComplete,
+ psSyncInfo->psSyncData->ui32ReadOps2Pending,
+ psSyncInfo->psSyncData->ui32ReadOps2Complete,
+ psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+ psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+ psSyncInfo->sReadOps2CompleteDevVAddr.uiAddr);
+}
+
+static void PVRSyncReleaseTimeline(struct sync_timeline *psObj)
+{
+ struct PVR_SYNC_TIMELINE *psTimeline = (struct PVR_SYNC_TIMELINE *)psObj;
+
+ mutex_lock(&gTimelineListLock);
+ list_del(&psTimeline->sTimelineList);
+ mutex_unlock(&gTimelineListLock);
+
+ DPF("R(t): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X "
+ "WOP/C=0x%x/0x%x ROP/C=0x%x/0x%x RO2P/C=0x%x/0x%x T=%p",
+ psTimeline->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+ psTimeline->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+ psTimeline->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+ psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending,
+ psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsComplete,
+ psTimeline->psSyncInfo->psBase->psSyncData->ui32ReadOpsPending,
+ psTimeline->psSyncInfo->psBase->psSyncData->ui32ReadOpsComplete,
+ psTimeline->psSyncInfo->psBase->psSyncData->ui32ReadOps2Pending,
+ psTimeline->psSyncInfo->psBase->psSyncData->ui32ReadOps2Complete,
+ psTimeline);
+
+ PVRSyncReleaseSyncInfo(psTimeline->psSyncInfo);
+ psTimeline->psSyncInfo = NULL;
+}
+
+static PVRSRV_ERROR PVRSyncInitServices(void)
+{
+ IMG_BOOL bCreated, bShared[PVRSRV_MAX_CLIENT_HEAPS];
+ PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+ IMG_UINT32 ui32ClientHeapCount = 0;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ PVRSRV_ERROR eError;
+
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+ gsSyncServicesConnection.ui32Pid = OSGetCurrentProcessIDKM();
+
+ eError = PVRSRVProcessConnect(gsSyncServicesConnection.ui32Pid, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVProcessConnect failed",
+ __func__));
+ goto err_unlock;
+ }
+
+ psPerProc = PVRSRVFindPerProcessData();
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVFindPerProcessData failed",
+ __func__));
+ goto err_disconnect;
+ }
+
+ eError = PVRSRVAcquireDeviceDataKM(0, PVRSRV_DEVICE_TYPE_SGX,
+ &gsSyncServicesConnection.hDevCookie);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVAcquireDeviceDataKM failed",
+ __func__));
+ goto err_disconnect;
+ }
+
+ if (!gsSyncServicesConnection.hDevCookie)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: hDevCookie is NULL", __func__));
+ goto err_disconnect;
+ }
+
+ eError = PVRSRVCreateDeviceMemContextKM(gsSyncServicesConnection.hDevCookie,
+ psPerProc,
+ &gsSyncServicesConnection.hDevMemContext,
+ &ui32ClientHeapCount,
+ &sHeapInfo[0],
+ &bCreated,
+ &bShared[0]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVCreateDeviceMemContextKM failed",
+ __func__));
+ goto err_disconnect;
+ }
+
+ if (!gsSyncServicesConnection.hDevMemContext)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: hDevMemContext is NULL", __func__));
+ goto err_disconnect;
+ }
+
+err_unlock:
+ LinuxUnLockMutex(&gPVRSRVLock);
+ return eError;
+
+err_disconnect:
+ PVRSRVProcessDisconnect(gsSyncServicesConnection.ui32Pid);
+ goto err_unlock;
+}
+
+static void PVRSyncCloseServices(void)
+{
+ IMG_BOOL bDummy;
+
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+ PVRSRVDestroyDeviceMemContextKM(gsSyncServicesConnection.hDevCookie,
+ gsSyncServicesConnection.hDevMemContext,
+ &bDummy);
+ gsSyncServicesConnection.hDevMemContext = NULL;
+ gsSyncServicesConnection.hDevCookie = NULL;
+
+ PVRSRVProcessDisconnect(gsSyncServicesConnection.ui32Pid);
+ gsSyncServicesConnection.ui32Pid = 0;
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+static struct sync_timeline_ops gsTimelineOps =
+{
+ .driver_name = "pvr_sync",
+ .dup = PVRSyncDup,
+ .has_signaled = PVRSyncHasSignaled,
+ .compare = PVRSyncCompare,
+ .release_obj = PVRSyncReleaseTimeline,
+ .print_obj = PVRSyncPrintTimeline,
+ .print_pt = PVRSyncPrint,
+ .free_pt = PVRSyncFreeSync,
+};
+
+static struct PVR_SYNC_TIMELINE *PVRSyncCreateTimeline(const IMG_CHAR *pszName)
+{
+ struct PVR_SYNC_TIMELINE *psTimeline;
+ PVRSRV_ERROR eError;
+
+ psTimeline = (struct PVR_SYNC_TIMELINE *)
+ sync_timeline_create(&gsTimelineOps, sizeof(struct PVR_SYNC_TIMELINE),
+ pszName);
+ if (!psTimeline)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: sync_timeline_create failed", __func__));
+ goto err_out;
+ }
+
+ psTimeline->psSyncInfo =
+ kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+ if(!psTimeline->psSyncInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+ "PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+ goto err_free_timeline;
+ }
+
+ psTimeline->bSyncHasSignaled = IMG_FALSE;
+
+ mutex_init(&psTimeline->sTimelineLock);
+
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+ eError = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+ gsSyncServicesConnection.hDevMemContext,
+ &psTimeline->psSyncInfo->psBase);
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate timeline syncinfo",
+ __func__));
+ goto err_free_syncinfo;
+ }
+
+ DPF("A(t): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X T=%p %s",
+ psTimeline->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+ psTimeline->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+ psTimeline->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+ psTimeline, pszName);
+
+err_out:
+ return psTimeline;
+err_free_syncinfo:
+ kfree(psTimeline->psSyncInfo);
+err_free_timeline:
+ sync_timeline_destroy((struct sync_timeline *)psTimeline);
+ psTimeline = NULL;
+ goto err_out;
+}
+
+static int PVRSyncOpen(struct inode *inode, struct file *file)
+{
+ struct PVR_SYNC_TIMELINE *psTimeline;
+ IMG_CHAR task_comm[TASK_COMM_LEN+1];
+
+ get_task_comm(task_comm, current);
+
+ psTimeline = PVRSyncCreateTimeline(task_comm);
+ if (!psTimeline)
+ return -ENOMEM;
+
+ mutex_lock(&gTimelineListLock);
+ list_add_tail(&psTimeline->sTimelineList, &gTimelineList);
+ mutex_unlock(&gTimelineListLock);
+
+ file->private_data = psTimeline;
+ return 0;
+}
+
+static int PVRSyncRelease(struct inode *inode, struct file *file)
+{
+ struct PVR_SYNC_TIMELINE *psTimeline = file->private_data;
+ sync_timeline_destroy(&psTimeline->obj);
+ return 0;
+}
+
+static long
+PVRSyncIOCTLCreate(struct PVR_SYNC_TIMELINE *psObj, void __user *pvData)
+{
+ struct PVR_SYNC_KERNEL_SYNC_INFO *psProvidedSyncInfo = NULL;
+ struct PVR_ALLOC_SYNC_DATA *psAllocSyncData;
+ struct PVR_SYNC_CREATE_IOCTL_DATA sData;
+ int err = -EFAULT, iFd = get_unused_fd();
+ struct sync_fence *psFence;
+ struct sync_pt *psPt;
+
+ if (iFd < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to find unused fd (%d)",
+ __func__, iFd));
+ goto err_out;
+ }
+
+ if (!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+ goto err_put_fd;
+
+ if (copy_from_user(&sData, pvData, sizeof(sData)))
+ goto err_put_fd;
+
+ if (sData.allocdSyncInfo < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Requested to create a fence from "
+ " an invalid alloc'd fd (%d)", __func__,
+ sData.allocdSyncInfo));
+ goto err_put_fd;
+ }
+
+ psAllocSyncData = PVRSyncAllocFDGet(sData.allocdSyncInfo);
+ if (!psAllocSyncData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRSyncAllocFDGet returned NULL, "
+ "possibly fd passed to CREATE is not an "
+ "ALLOC'd sync?", __func__));
+ goto err_put_fd;
+ }
+
+ /* Move the psSyncInfo to the newly created sync, to avoid attempting
+ * to create multiple syncs from the same allocation.
+ */
+ psProvidedSyncInfo = psAllocSyncData->psSyncInfo;
+ psAllocSyncData->psSyncInfo = NULL;
+
+ if (psProvidedSyncInfo == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Alloc'd sync info is null - "
+ "possibly already CREATEd?", __func__));
+ fput(psAllocSyncData->psFile);
+ goto err_put_fd;
+ }
+
+ fput(psAllocSyncData->psFile);
+
+ psPt = (struct sync_pt *)PVRSyncCreateSync(psObj, psProvidedSyncInfo);
+ if (!psPt)
+ {
+ err = -ENOMEM;
+ goto err_put_fd;
+ }
+
+ sData.name[sizeof(sData.name) - 1] = '\0';
+ psFence = sync_fence_create(sData.name, psPt);
+ if (!psFence)
+ {
+ sync_pt_free(psPt);
+ err = -ENOMEM;
+ goto err_put_fd;
+ }
+
+ sData.fence = iFd;
+
+ if (!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+ {
+ sync_fence_put(psFence);
+ goto err_put_fd;
+ }
+
+ if (copy_to_user(pvData, &sData, sizeof(sData)))
+ {
+ sync_fence_put(psFence);
+ goto err_put_fd;
+ }
+
+ /* If the fence is a 'real' one, its signal status will be updated by
+ * the MISR calling PVRSyncUpdateAllSyncs(). However, if we created
+ * a 'fake' fence (for power optimization reasons) it has already
+ * completed, and needs to be marked signalled (as the MISR will
+ * never run for 'fake' fences).
+ */
+ if(psProvidedSyncInfo->psBase->psSyncData->ui32WriteOpsPending == 0)
+ sync_timeline_signal((struct sync_timeline *)psObj);
+
+ DPF("C( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X F=%p %s",
+ psProvidedSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+ psProvidedSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+ psProvidedSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+ psFence, sData.name);
+
+ sync_fence_install(psFence, iFd);
+ err = 0;
+err_out:
+ return err;
+
+err_put_fd:
+ put_unused_fd(iFd);
+ goto err_out;
+}
+
+static long
+PVRSyncIOCTLDebug(struct PVR_SYNC_TIMELINE *psObj, void __user *pvData)
+{
+ struct PVR_SYNC_DEBUG_IOCTL_DATA sData;
+ struct sync_fence *psFence;
+ struct list_head *psEntry;
+ int i = 0, err = -EFAULT;
+
+ if(!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+ goto err_out;
+
+ if(copy_from_user(&sData, pvData, sizeof(sData)))
+ goto err_out;
+
+ psFence = sync_fence_fdget(sData.iFenceFD);
+ if(!psFence)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get fence from fd", __func__));
+ goto err_out;
+ }
+
+ list_for_each(psEntry, &psFence->pt_list_head)
+ {
+ PVR_SYNC_DEBUG *psMetaData = &sData.sSync[i].sMetaData;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ struct PVR_SYNC_TIMELINE *psTimeline;
+ struct PVR_SYNC *psPt;
+
+ if(i == PVR_SYNC_DEBUG_MAX_POINTS)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Fence merged with more than %d "
+ "points", __func__,
+ PVR_SYNC_DEBUG_MAX_POINTS));
+ break;
+ }
+
+ psPt = (struct PVR_SYNC *)
+ container_of(psEntry, struct sync_pt, pt_list);
+
+ /* Don't dump foreign points */
+ if(psPt->pt.parent->ops != &gsTimelineOps)
+ continue;
+
+ psTimeline = (struct PVR_SYNC_TIMELINE *)psPt->pt.parent;
+ psKernelSyncInfo = psPt->psSyncData->psSyncInfo->psBase;
+ PVR_ASSERT(psKernelSyncInfo != NULL);
+
+ /* The sync refcount is valid as long as the FenceFD stays open,
+ * so we can access it directly without worrying about it being
+ * freed.
+ */
+ sData.sSync[i].sSyncData = *psKernelSyncInfo->psSyncData;
+
+ psMetaData->ui64Stamp = psPt->psSyncData->ui64Stamp;
+ psMetaData->ui32WriteOpsPendingSnapshot = psPt->psSyncData->ui32WOPSnapshot;
+ i++;
+ }
+
+ sync_fence_put(psFence);
+
+ sData.ui32NumPoints = i;
+
+ if(!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+ goto err_out;
+
+ if(copy_to_user(pvData, &sData, sizeof(sData)))
+ goto err_out;
+
+ err = 0;
+err_out:
+ return err;
+}
+
+static int PVRSyncFenceAllocRelease(struct inode *inode, struct file *file)
+{
+ struct PVR_ALLOC_SYNC_DATA *psAllocSyncData = file->private_data;
+
+ if(psAllocSyncData->psSyncInfo)
+ {
+#if defined(DEBUG_PRINT)
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo =
+ psAllocSyncData->psSyncInfo->psBase;
+#endif
+
+ DPF("R(a): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+ psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+ psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+ psSyncInfo->sReadOps2CompleteDevVAddr.uiAddr);
+
+ PVRSyncReleaseSyncInfo(psAllocSyncData->psSyncInfo);
+ psAllocSyncData->psSyncInfo = NULL;
+ }
+
+ kfree(psAllocSyncData);
+ return 0;
+}
+
+static const struct file_operations gsSyncFenceAllocFOps =
+{
+ .release = PVRSyncFenceAllocRelease,
+};
+
+static struct PVR_ALLOC_SYNC_DATA *PVRSyncAllocFDGet(int fd)
+{
+ struct file *file = fget(fd);
+ if (!file)
+ return NULL;
+ if (file->f_op != &gsSyncFenceAllocFOps)
+ goto err;
+ return file->private_data;
+err:
+ fput(file);
+ return NULL;
+}
+
+static long
+PVRSyncIOCTLAlloc(struct PVR_SYNC_TIMELINE *psTimeline, void __user *pvData)
+{
+ struct PVR_ALLOC_SYNC_DATA *psAllocSyncData;
+ int err = -EFAULT, iFd = get_unused_fd();
+ struct PVR_SYNC_ALLOC_IOCTL_DATA sData;
+ PVRSRV_SYNC_DATA *psSyncData;
+ struct file *psFile;
+ PVRSRV_ERROR eError;
+
+ if (iFd < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to find unused fd (%d)",
+ __func__, iFd));
+ goto err_out;
+ }
+
+ if (!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+ goto err_put_fd;
+
+ if (copy_from_user(&sData, pvData, sizeof(sData)))
+ goto err_put_fd;
+
+ psAllocSyncData = kmalloc(sizeof(struct PVR_ALLOC_SYNC_DATA), GFP_KERNEL);
+ if (!psAllocSyncData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_ALLOC_SYNC_DATA",
+ __func__));
+ err = -ENOMEM;
+ goto err_put_fd;
+ }
+
+ psAllocSyncData->psSyncInfo =
+ kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+ if (!psAllocSyncData->psSyncInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+ "PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+ err = -ENOMEM;
+ goto err_free_alloc_sync_data;
+ }
+
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+ eError = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+ gsSyncServicesConnection.hDevMemContext,
+ &psAllocSyncData->psSyncInfo->psBase);
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to alloc syncinfo (%d)",
+ __func__, eError));
+ err = -ENOMEM;
+ goto err_free_sync_info;
+ }
+
+ psFile = anon_inode_getfile("pvr_sync_alloc",
+ &gsSyncFenceAllocFOps, psAllocSyncData, 0);
+ if (!psFile)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create anon inode",
+ __func__));
+ err = -ENOMEM;
+ goto err_release_sync_info;
+ }
+
+ sData.fence = iFd;
+
+ /* Check if this timeline looks idle. If there are still TQs running
+ * on it, userspace shouldn't attempt any kind of power optimization
+ * (e.g. it must not dummy-process GPU fences).
+ *
+ * Determining idleness here is safe because the ALLOC and CREATE
+ * pvr_sync ioctls must be called under the gralloc module lock, so
+ * we can't be creating another new fence op while we are still
+ * processing this one.
+ *
+ * Take the bridge lock anyway so we can be sure that we read the
+ * timeline sync's pending value coherently. The complete value may
+ * be modified by the GPU, but worse-case we will decide we can't do
+ * the power optimization and will still be correct.
+ */
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+ psSyncData = psTimeline->psSyncInfo->psBase->psSyncData;
+ if(psSyncData->ui32WriteOpsPending == psSyncData->ui32WriteOpsComplete)
+ sData.bTimelineIdle = IMG_TRUE;
+ else
+ sData.bTimelineIdle = IMG_FALSE;
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ if (!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+ goto err_release_file;
+
+ if (copy_to_user(pvData, &sData, sizeof(sData)))
+ goto err_release_file;
+
+ psAllocSyncData->psTimeline = psTimeline;
+ psAllocSyncData->psFile = psFile;
+
+ DPF("A( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+ psAllocSyncData->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+ psAllocSyncData->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+ psAllocSyncData->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr);
+
+ fd_install(iFd, psFile);
+ err = 0;
+err_out:
+ return err;
+err_release_sync_info:
+ PVRSRVReleaseSyncInfoKM(psAllocSyncData->psSyncInfo->psBase);
+err_free_sync_info:
+ kfree(psAllocSyncData->psSyncInfo);
+err_free_alloc_sync_data:
+ kfree(psAllocSyncData);
+err_put_fd:
+ put_unused_fd(iFd);
+ goto err_out;
+err_release_file:
+ fput(psFile);
+ put_unused_fd(iFd);
+ goto err_out;
+}
+
+static long
+PVRSyncIOCTL(struct file *file, unsigned int cmd, unsigned long __user arg)
+{
+ struct PVR_SYNC_TIMELINE *psTimeline = file->private_data;
+ void __user *pvData = (void __user *)arg;
+
+ switch (cmd)
+ {
+ case PVR_SYNC_IOC_CREATE_FENCE:
+ return PVRSyncIOCTLCreate(psTimeline, pvData);
+ case PVR_SYNC_IOC_DEBUG_FENCE:
+ return PVRSyncIOCTLDebug(psTimeline, pvData);
+ case PVR_SYNC_IOC_ALLOC_FENCE:
+ return PVRSyncIOCTLAlloc(psTimeline, pvData);
+ default:
+ return -ENOTTY;
+ }
+}
+
+static void PVRSyncWorkQueueFunction(struct work_struct *data)
+{
+ PVRSRV_DEVICE_NODE *psDevNode =
+ (PVRSRV_DEVICE_NODE*)gsSyncServicesConnection.hDevCookie;
+ struct list_head sFreeList, *psEntry, *n;
+ unsigned long flags;
+
+ /* We lock the bridge mutex here for two reasons.
+ *
+ * Firstly, the SGXScheduleProcessQueuesKM and PVRSRVReleaseSyncInfoKM
+ * functions require that they are called under lock. Multiple threads
+ * into services are not allowed.
+ *
+ * Secondly, we need to ensure that when processing the defer-free list,
+ * the PVRSyncIsSyncInfoInUse() function is called *after* any freed
+ * sync was attached as a HW dependency (had ROP/ROP2 taken). This is
+ * because for 'foreign' sync timelines we allocate a new object and
+ * mark it for deletion immediately. If the 'foreign' sync_pt signals
+ * before the kick ioctl has completed, we can block it from being
+ * prematurely freed by holding the bridge mutex.
+ *
+ * NOTE: This code relies on the assumption that we can acquire a
+ * spinlock while a mutex is held and that other users of the spinlock
+ * do not need to hold the bridge mutex.
+ */
+ LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+ /* A completed SW operation may un-block the GPU */
+ SGXScheduleProcessQueuesKM(psDevNode);
+
+ /* We can't call PVRSRVReleaseSyncInfoKM directly in this loop because
+ * that will take the mmap mutex. We can't take mutexes while we have
+ * this list locked with a spinlock. So move all the items we want to
+ * free to another, local list (no locking required) and process it
+ * in a second loop.
+ */
+
+ INIT_LIST_HEAD(&sFreeList);
+ spin_lock_irqsave(&gSyncInfoFreeListLock, flags);
+ list_for_each_safe(psEntry, n, &gSyncInfoFreeList)
+ {
+ struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo =
+ container_of(psEntry, struct PVR_SYNC_KERNEL_SYNC_INFO, sHead);
+
+ if(!PVRSyncIsSyncInfoInUse(psSyncInfo->psBase))
+ list_move_tail(psEntry, &sFreeList);
+
+ }
+ spin_unlock_irqrestore(&gSyncInfoFreeListLock, flags);
+
+ list_for_each_safe(psEntry, n, &sFreeList)
+ {
+ struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo =
+ container_of(psEntry, struct PVR_SYNC_KERNEL_SYNC_INFO, sHead);
+
+ list_del(psEntry);
+
+ DPF("F(d): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+ psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+ psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+ psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr);
+
+ PVRSRVReleaseSyncInfoKM(psSyncInfo->psBase);
+ psSyncInfo->psBase = NULL;
+
+ kfree(psSyncInfo);
+ }
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ /* Copying from one list to another (so a spinlock isn't held) used to
+ * work around the problem that PVRSyncReleaseSyncInfo() would hold the
+ * services mutex. However, we no longer do this, so this code could
+ * potentially be simplified.
+ *
+ * Note however that sync_fence_put must be called from process/WQ
+ * context because it uses fput(), which is not allowed to be called
+ * from interrupt context in kernels <3.6.
+ */
+ INIT_LIST_HEAD(&sFreeList);
+ spin_lock_irqsave(&gFencePutListLock, flags);
+ list_for_each_safe(psEntry, n, &gFencePutList)
+ {
+ list_move_tail(psEntry, &sFreeList);
+ }
+ spin_unlock_irqrestore(&gFencePutListLock, flags);
+
+ list_for_each_safe(psEntry, n, &sFreeList)
+ {
+ struct PVR_SYNC_FENCE *psSyncFence =
+ container_of(psEntry, struct PVR_SYNC_FENCE, sHead);
+
+ list_del(psEntry);
+
+ sync_fence_put(psSyncFence->psBase);
+ psSyncFence->psBase = NULL;
+
+ kfree(psSyncFence);
+ }
+}
+
+static const struct file_operations gsPVRSyncFOps =
+{
+ .owner = THIS_MODULE,
+ .open = PVRSyncOpen,
+ .release = PVRSyncRelease,
+ .unlocked_ioctl = PVRSyncIOCTL,
+};
+
+static struct miscdevice gsPVRSyncDev =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "pvr_sync",
+ .fops = &gsPVRSyncFOps,
+};
+
+IMG_INTERNAL
+int PVRSyncDeviceInit(void)
+{
+ int err = -1;
+
+ if(PVRSyncInitServices() != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to initialise services",
+ __func__));
+ goto err_out;
+ }
+
+ gpsWorkQueue = create_freezable_workqueue("pvr_sync_workqueue");
+ if(!gpsWorkQueue)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create pvr_sync workqueue",
+ __func__));
+ goto err_deinit_services;
+ }
+
+ INIT_WORK(&gsWork, PVRSyncWorkQueueFunction);
+
+ err = misc_register(&gsPVRSyncDev);
+ if(err)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to register pvr_sync misc "
+ "device (err=%d)", __func__, err));
+ goto err_deinit_services;
+ }
+
+ err = 0;
+err_out:
+ return err;
+err_deinit_services:
+ PVRSyncCloseServices();
+ goto err_out;
+}
+
+IMG_INTERNAL
+void PVRSyncDeviceDeInit(void)
+{
+ misc_deregister(&gsPVRSyncDev);
+ destroy_workqueue(gpsWorkQueue);
+ PVRSyncCloseServices();
+}
+
+IMG_INTERNAL
+void PVRSyncUpdateAllSyncs(void)
+{
+ IMG_BOOL bNeedToProcessQueues = IMG_FALSE;
+ struct list_head *psEntry;
+
+ /* Check to see if any syncs have signalled. If they have, it may unblock
+ * the GPU. Decide what is needed and optionally schedule queue
+ * processing.
+ */
+ mutex_lock(&gTimelineListLock);
+ list_for_each(psEntry, &gTimelineList)
+ {
+ struct PVR_SYNC_TIMELINE *psTimeline =
+ container_of(psEntry, struct PVR_SYNC_TIMELINE, sTimelineList);
+
+ sync_timeline_signal((struct sync_timeline *)psTimeline);
+
+ if(psTimeline->bSyncHasSignaled)
+ {
+ psTimeline->bSyncHasSignaled = IMG_FALSE;
+ bNeedToProcessQueues = IMG_TRUE;
+ }
+ }
+ mutex_unlock(&gTimelineListLock);
+
+ if(bNeedToProcessQueues)
+ queue_work(gpsWorkQueue, &gsWork);
+}
+
+static IMG_BOOL
+PVRSyncIsDuplicate(PVRSRV_KERNEL_SYNC_INFO *psA, PVRSRV_KERNEL_SYNC_INFO *psB)
+{
+ return psA->sWriteOpsCompleteDevVAddr.uiAddr ==
+ psB->sWriteOpsCompleteDevVAddr.uiAddr ? IMG_TRUE : IMG_FALSE;
+}
+
+static void ForeignSyncPtSignaled(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter)
+{
+ struct PVR_SYNC_FENCE_WAITER *psWaiter =
+ (struct PVR_SYNC_FENCE_WAITER *)waiter;
+ unsigned long flags;
+
+ PVRSyncSWCompleteOp(psWaiter->psSyncInfo->psBase);
+
+ DPF("R(f): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X "
+ "WOP/C=0x%x/0x%x ROP/C=0x%x/0x%x RO2P/C=0x%x/0x%x",
+ psWaiter->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+ psWaiter->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+ psWaiter->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+ psWaiter->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending,
+ psWaiter->psSyncInfo->psBase->psSyncData->ui32WriteOpsComplete,
+ psWaiter->psSyncInfo->psBase->psSyncData->ui32ReadOpsPending,
+ psWaiter->psSyncInfo->psBase->psSyncData->ui32ReadOpsComplete,
+ psWaiter->psSyncInfo->psBase->psSyncData->ui32ReadOps2Pending,
+ psWaiter->psSyncInfo->psBase->psSyncData->ui32ReadOps2Complete);
+
+ PVRSyncReleaseSyncInfo(psWaiter->psSyncInfo);
+ psWaiter->psSyncInfo = NULL;
+
+ /* We can 'put' the fence now, but this function might be called in irq
+ * context so we must defer to WQ.
+ */
+ spin_lock_irqsave(&gFencePutListLock, flags);
+ list_add_tail(&psWaiter->psSyncFence->sHead, &gFencePutList);
+ psWaiter->psSyncFence = NULL;
+ spin_unlock_irqrestore(&gFencePutListLock, flags);
+
+ /* The PVRSyncReleaseSyncInfo() call above already queued work */
+ /*queue_work(gpsWorkQueue, &gsWork);*/
+
+ kfree(psWaiter);
+}
+
+static PVRSRV_KERNEL_SYNC_INFO *ForeignSyncPointToSyncInfo(int iFenceFd)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ struct PVR_SYNC_FENCE_WAITER *psWaiter;
+ struct PVR_SYNC_FENCE *psSyncFence;
+ struct sync_fence *psFence;
+ PVRSRV_ERROR eError;
+ int err;
+
+ /* FIXME: Could optimize this function by pre-testing sync_wait(.., 0)
+ * to determine if it has already signalled. We must avoid this
+ * for now because the sync driver was broken in earlier kernels.
+ */
+
+ /* The custom waiter structure is freed in the waiter callback */
+ psWaiter = kmalloc(sizeof(struct PVR_SYNC_FENCE_WAITER), GFP_KERNEL);
+ if(!psWaiter)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate waiter", __func__));
+ goto err_out;
+ }
+
+ psWaiter->psSyncInfo =
+ kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+ if(!psWaiter->psSyncInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+ "PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+ goto err_free_waiter;
+ }
+
+ /* We take another reference on the parent fence, each time we see a
+ * 'foreign' sync_pt. This is to ensure the timeline, fence and sync_pts
+ * from the foreign timeline cannot go away until the sync_pt signals.
+ * In practice this also means they will not go away until the entire
+ * fence signals. It means that we will always get a
+ * sync_fence_wait_async() callback for these points.
+ */
+ psFence = sync_fence_fdget(iFenceFd);
+ if(!psFence)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to take reference on fence",
+ __func__));
+ goto err_free_syncinfo;
+ }
+
+ /* Allocate packet we can store this fence on (with a list head) so we
+ * can add it to the defer-put list without allocating memory in irq
+ * context.
+ *
+ * NOTE: At the moment we allocate one of these per sync_pts, but it
+ * might be possible to optimize this to one per fence.
+ */
+ psSyncFence = kmalloc(sizeof(struct PVR_SYNC_FENCE), GFP_KERNEL);
+ if(!psSyncFence)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+ "PVR_SYNC_FENCE", __func__));
+ goto err_sync_fence_put;
+ }
+
+ psSyncFence->psBase = psFence;
+ psWaiter->psSyncFence = psSyncFence;
+
+ /* Allocate a "shadow" SYNCINFO for this sync_pt and set it up to be
+ * completed by the callback.
+ */
+ eError = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+ gsSyncServicesConnection.hDevMemContext,
+ &psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate syncinfo", __func__));
+ goto err_free_sync_fence;
+ }
+
+ /* Make sure we take the SW operation before adding the waiter, to avoid
+ * racing with parallel completes.
+ */
+ PVRSyncSWTakeOp(psKernelSyncInfo);
+
+ sync_fence_waiter_init(&psWaiter->sWaiter, ForeignSyncPtSignaled);
+ psWaiter->psSyncInfo->psBase = psKernelSyncInfo;
+
+ err = sync_fence_wait_async(psFence, &psWaiter->sWaiter);
+ if(err)
+ {
+ if(err < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Fence was in error state", __func__));
+ /* Fall-thru */
+ }
+
+ /* -1 means the fence was broken, 1 means the fence already
+ * signalled. In either case, roll back what we've done and
+ * skip using this sync_pt for synchronization.
+ */
+ goto err_release_sync_info;
+ }
+
+ DPF("A(f): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X F=%p",
+ psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+ psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+ psKernelSyncInfo->sReadOps2CompleteDevVAddr.uiAddr,
+ psFence);
+
+ /* NOTE: Don't use psWaiter after this point as it may asynchronously
+ * signal before this function completes (and be freed already).
+ */
+
+ /* Even if the fence signals while we're hanging on to this, the sync
+ * can't be freed until the bridge mutex is taken in the callback. The
+ * bridge mutex won't be released by the caller of this function until
+ * the GPU operation has been scheduled, which increments ROP,
+ * preventing the sync from being freed when still in use by the GPU.
+ */
+ return psKernelSyncInfo;
+
+err_release_sync_info:
+ PVRSyncSWCompleteOp(psKernelSyncInfo);
+ PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+err_free_sync_fence:
+ kfree(psSyncFence);
+err_sync_fence_put:
+ sync_fence_put(psFence);
+err_free_syncinfo:
+ kfree(psWaiter->psSyncInfo);
+err_free_waiter:
+ kfree(psWaiter);
+err_out:
+ return NULL;
+}
+
+static void
+CopyKernelSyncInfoToDeviceSyncObject(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ PVRSRV_DEVICE_SYNC_OBJECT *psSyncObject)
+{
+ psSyncObject->sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psSyncObject->sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSyncObject->sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
+ psSyncObject->ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSyncObject->ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ psSyncObject->ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+}
+
+static IMG_BOOL FenceHasForeignPoints(struct sync_fence *psFence)
+{
+ struct list_head *psEntry;
+
+ list_for_each(psEntry, &psFence->pt_list_head)
+ {
+ struct sync_pt *psPt =
+ container_of(psEntry, struct sync_pt, pt_list);
+
+ if(psPt->parent->ops != &gsTimelineOps)
+ return IMG_TRUE;
+ }
+
+ return IMG_FALSE;
+}
+
+static IMG_BOOL
+AddSyncInfoToArray(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_UINT32 ui32SyncPointLimit,
+ IMG_UINT32 *pui32NumRealSyncs,
+ PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[])
+{
+ /* Ran out of syncs. Not much userspace can do about this, since it
+ * could have been passed multiple merged syncs and doesn't know they
+ * were merged. Allow this through, but print a warning and stop
+ * synchronizing.
+ */
+ if(*pui32NumRealSyncs == ui32SyncPointLimit)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Ran out of source syncs %d == %d",
+ __func__, *pui32NumRealSyncs,
+ ui32SyncPointLimit));
+ return IMG_FALSE;
+ }
+
+ apsSyncInfo[*pui32NumRealSyncs] = psSyncInfo;
+ (*pui32NumRealSyncs)++;
+ return IMG_TRUE;
+}
+
+static IMG_BOOL
+ExpandAndDeDuplicateFenceSyncs(IMG_UINT32 ui32NumSyncs,
+ int aiFenceFds[],
+ IMG_UINT32 ui32SyncPointLimit,
+ struct sync_fence *apsFence[],
+ IMG_UINT32 *pui32NumRealSyncs,
+ PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[])
+{
+ IMG_UINT32 i, j, ui32FenceIndex = 0;
+ IMG_BOOL bRet = IMG_TRUE;
+
+ *pui32NumRealSyncs = 0;
+
+ for(i = 0; i < ui32NumSyncs; i++)
+ {
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ struct list_head *psEntry;
+
+ /* Skip any invalid fence file descriptors without error */
+ if(aiFenceFds[i] < 0)
+ continue;
+
+ /* By converting a file descriptor to a struct sync_fence, we are
+ * taking a reference on the fence. We don't want the fence to go
+ * away until we have submitted the command, even if it signals
+ * before we dispatch the command, or the timeline(s) are destroyed.
+ *
+ * This reference should be released by the caller of this function
+ * once hardware operations have been scheduled on the GPU sync_pts
+ * participating in this fence. When our MISR is scheduled, the
+ * defer-free list will be processed, cleaning up the SYNCINFO.
+ *
+ * Note that this reference *isn't* enough for non-GPU sync_pts.
+ * We'll take another reference on the fence for those operations
+ * later (the life-cycle requirements there are totally different).
+ *
+ * Fence lookup may fail here if the fd became invalid since it was
+ * patched in userspace. That's really a userspace driver bug, so
+ * just fail here instead of not synchronizing.
+ */
+ apsFence[ui32FenceIndex] = sync_fence_fdget(aiFenceFds[i]);
+ if(!apsFence[ui32FenceIndex])
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get fence from fd=%d",
+ __func__, aiFenceFds[i]));
+ bRet = IMG_FALSE;
+ goto err_out;
+ }
+
+ /* If this fence has any points from foreign timelines, we need to
+ * allocate a 'shadow' SYNCINFO and update it in software ourselves,
+ * so the ukernel can test the readiness of the dependency.
+ *
+ * It's tempting to just handle all fences like this (since most of
+ * the time they *will* be merged with sw_sync) but such 'shadow'
+ * syncs are slower. This is because we need to wait for the MISR to
+ * schedule to update the GPU part of the fence (normally the ukernel
+ * would be able to make the update directly).
+ */
+ if(FenceHasForeignPoints(apsFence[ui32FenceIndex]))
+ {
+ psSyncInfo = ForeignSyncPointToSyncInfo(aiFenceFds[i]);
+ if(psSyncInfo)
+ {
+ if(!AddSyncInfoToArray(psSyncInfo, ui32SyncPointLimit,
+ pui32NumRealSyncs, apsSyncInfo))
+ {
+ /* Soft-fail. Stop synchronizing. */
+ goto err_out;
+ }
+ }
+ ui32FenceIndex++;
+ continue;
+ }
+
+ /* FIXME: The ForeignSyncPointToSyncInfo() path optimizes away already
+ * signalled fences. Consider optimizing this path too.
+ */
+ list_for_each(psEntry, &apsFence[ui32FenceIndex]->pt_list_head)
+ {
+ struct sync_pt *psPt =
+ container_of(psEntry, struct sync_pt, pt_list);
+
+ psSyncInfo =
+ ((struct PVR_SYNC *)psPt)->psSyncData->psSyncInfo->psBase;
+
+ /* Walk the current list of points and make sure this isn't a
+ * duplicate. Duplicates will deadlock.
+ */
+ for(j = 0; j < *pui32NumRealSyncs; j++)
+ {
+ /* The point is from a different timeline so we must use it */
+ if(!PVRSyncIsDuplicate(apsSyncInfo[j], psSyncInfo))
+ continue;
+
+ /* There's no need to bump the real sync count as we either
+ * ignored the duplicate or replaced an previously counted
+ * entry.
+ */
+ break;
+ }
+
+ if(j == *pui32NumRealSyncs)
+ {
+ /* It's not a duplicate; moving on.. */
+ if(!AddSyncInfoToArray(psSyncInfo, ui32SyncPointLimit,
+ pui32NumRealSyncs, apsSyncInfo))
+ goto err_out;
+ }
+ }
+
+ ui32FenceIndex++;
+ }
+
+err_out:
+ return bRet;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+PVRSyncPatchCCBKickSyncInfos(IMG_HANDLE ahSyncs[SGX_MAX_SRC_SYNCS_TA],
+ PVRSRV_DEVICE_SYNC_OBJECT asDevSyncs[SGX_MAX_SRC_SYNCS_TA],
+ IMG_UINT32 *pui32NumSrcSyncs)
+{
+ PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+ struct sync_fence *apsFence[SGX_MAX_SRC_SYNCS_TA] = {};
+ IMG_UINT32 i, ui32NumRealSrcSyncs;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(!ExpandAndDeDuplicateFenceSyncs(*pui32NumSrcSyncs,
+ (int *)ahSyncs,
+ SGX_MAX_SRC_SYNCS_TA,
+ apsFence,
+ &ui32NumRealSrcSyncs,
+ apsSyncInfo))
+ {
+ eError = PVRSRV_ERROR_HANDLE_NOT_FOUND;
+ goto err_put_fence;
+ }
+
+ /* There should only be one destination sync for a transfer.
+ * Ultimately this will be patched to two (the sync_pt SYNCINFO,
+ * and the timeline's SYNCINFO for debugging).
+ */
+ for(i = 0; i < ui32NumRealSrcSyncs; i++)
+ {
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = apsSyncInfo[i];
+
+ /* The following code is mostly the same as the texture dependencies
+ * handling in SGXDoKickKM, but we have to copy it here because it
+ * must be run while the fence is 'locked' by sync_fence_fdget.
+ */
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_SRC_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ CopyKernelSyncInfoToDeviceSyncObject(psSyncInfo, &asDevSyncs[i]);
+
+ /* Texture dependencies are read operations */
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ /* Finally, patch the sync back into the input array.
+ * NOTE: The syncs are protected here by the defer-free worker.
+ */
+ ahSyncs[i] = psSyncInfo;
+ }
+
+ /* Updating this allows the PDUMP handling and ROP rollbacks to work
+ * correctly in SGXDoKickKM.
+ */
+ *pui32NumSrcSyncs = ui32NumRealSrcSyncs;
+
+err_put_fence:
+ for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+ sync_fence_put(apsFence[i]);
+ return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+PVRSyncPatchTransferSyncInfos(IMG_HANDLE ahSyncs[SGX_MAX_SRC_SYNCS_TA],
+ PVRSRV_DEVICE_SYNC_OBJECT asDevSyncs[SGX_MAX_SRC_SYNCS_TA],
+ IMG_UINT32 *pui32NumSrcSyncs)
+{
+ struct PVR_ALLOC_SYNC_DATA *psTransferSyncData;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (*pui32NumSrcSyncs != 1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid number of syncs (%d), clamping "
+ "to 1", __func__, *pui32NumSrcSyncs));
+ }
+
+ psTransferSyncData = PVRSyncAllocFDGet((int)ahSyncs[0]);
+
+ if (!psTransferSyncData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get PVR_SYNC_DATA from "
+ "supplied fd", __func__));
+ eError = PVRSRV_ERROR_HANDLE_NOT_FOUND;
+ goto err_out;
+ }
+
+ /* There should only be one destination sync for a transfer.
+ * Ultimately this will be patched to two (the sync_pt SYNCINFO,
+ * and the timeline's SYNCINFO for debugging).
+ */
+ psSyncInfo = psTransferSyncData->psSyncInfo->psBase;
+
+ /* The following code is mostly the same as the texture dependencies
+ * handling in SGXDoKickKM, but we have to copy it here because it
+ * must be run while the fence is 'locked' by sync_fence_fdget.
+ */
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_SRC_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ CopyKernelSyncInfoToDeviceSyncObject(psSyncInfo, &asDevSyncs[0]);
+ CopyKernelSyncInfoToDeviceSyncObject(psTransferSyncData->psTimeline->psSyncInfo->psBase,
+ &asDevSyncs[1]);
+
+ /* Treat fence TQs as write operations */
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psTransferSyncData->psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending++;
+
+ /* Finally, patch the sync back into the input array.
+ * NOTE: The syncs are protected here by the defer-free worker.
+ */
+ ahSyncs[0] = psSyncInfo;
+ ahSyncs[1] = psTransferSyncData->psTimeline->psSyncInfo->psBase;
+
+ /* Updating this allows the PDUMP handling and ROP rollbacks to work
+ * correctly in SGXDoKickKM.
+ */
+ *pui32NumSrcSyncs = 2;
+
+ fput(psTransferSyncData->psFile);
+err_out:
+ return eError;
+}
+
+/* NOTE: This returns an array of sync_fences which need to be 'put'
+ * or they will leak.
+ */
+
+IMG_INTERNAL PVRSRV_ERROR
+PVRSyncFencesToSyncInfos(PVRSRV_KERNEL_SYNC_INFO *apsSyncs[],
+ IMG_UINT32 *pui32NumSyncs,
+ struct sync_fence *apsFence[SGX_MAX_SRC_SYNCS_TA])
+{
+ PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+ IMG_UINT32 i, ui32NumRealSrcSyncs;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ memset(apsFence, 0, sizeof(struct sync_fence *) * SGX_MAX_SRC_SYNCS_TA);
+
+ if(!ExpandAndDeDuplicateFenceSyncs(*pui32NumSyncs,
+ (int *)apsSyncs,
+ *pui32NumSyncs,
+ apsFence,
+ &ui32NumRealSrcSyncs,
+ apsSyncInfo))
+ {
+ for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+ sync_fence_put(apsFence[i]);
+ return PVRSRV_ERROR_HANDLE_NOT_FOUND;
+ }
+
+ /* We don't expect to see merged syncs here. Abort if that happens.
+ * Allow through cases where the same fence was specified more than
+ * once -- we can handle that without reallocation of memory.
+ */
+ PVR_ASSERT(ui32NumRealSrcSyncs <= *pui32NumSyncs);
+
+ for(i = 0; i < ui32NumRealSrcSyncs; i++)
+ apsSyncs[i] = apsSyncInfo[i];
+
+ *pui32NumSyncs = ui32NumRealSrcSyncs;
+ return eError;
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.h
new file mode 100755
index 00000000000..fa05b6093a2
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.h
@@ -0,0 +1,78 @@
+/*************************************************************************/ /*!
+@File pvr_sync.c
+@Title Kernel sync driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Version numbers and strings for PVR Consumer services
+ components.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _PVR_SYNC_H
+#define _PVR_SYNC_H
+
+#include <linux/seq_file.h>
+#include <linux/version.h>
+
+#if !defined(__KERNEL__) || (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
+#include <linux/sync.h>
+#else
+#include <../drivers/staging/android/sync.h>
+#endif
+
+#include "pvr_sync_user.h"
+#include "servicesint.h" // PVRSRV_DEVICE_SYNC_OBJECT
+
+/* services4 internal interface */
+
+int PVRSyncDeviceInit(void);
+void PVRSyncDeviceDeInit(void);
+void PVRSyncUpdateAllSyncs(void);
+PVRSRV_ERROR
+PVRSyncPatchCCBKickSyncInfos(IMG_HANDLE ahSyncs[SGX_MAX_SRC_SYNCS_TA],
+ PVRSRV_DEVICE_SYNC_OBJECT asDevSyncs[SGX_MAX_SRC_SYNCS_TA],
+ IMG_UINT32 *pui32NumSrcSyncs);
+PVRSRV_ERROR
+PVRSyncPatchTransferSyncInfos(IMG_HANDLE ahSyncs[SGX_MAX_SRC_SYNCS_TA],
+ PVRSRV_DEVICE_SYNC_OBJECT asDevSyncs[SGX_MAX_SRC_SYNCS_TA],
+ IMG_UINT32 *pui32NumSrcSyncs);
+PVRSRV_ERROR
+PVRSyncFencesToSyncInfos(PVRSRV_KERNEL_SYNC_INFO *apsSyncs[],
+ IMG_UINT32 *pui32NumSyncs,
+ struct sync_fence *apsFence[SGX_MAX_SRC_SYNCS_TA]);
+
+#endif /* _PVR_SYNC_H */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_uaccess.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_uaccess.h
index 7583d7eb25b..7583d7eb25b 100644..100755
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_uaccess.h
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_uaccess.h
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/sysfs.c b/drivers/gpu/pvr/services4/srvkm/env/linux/sysfs.c
deleted file mode 100644
index 63066ade212..00000000000
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/sysfs.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2012 Texas Instruments, Inc
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kobject.h>
-#include <linux/sysfs.h>
-#include <linux/stat.h>
-#include <asm/page.h>
-#include <linux/slab.h>
-#include "services_headers.h"
-#include "pdump_km.h"
-#include "sysfs.h"
-
-/* sysfs structures */
-struct pvrsrv_attribute {
- struct attribute attr;
- int sgx_version;
- int sgx_revision;
-};
-
-static struct pvrsrv_attribute PVRSRVAttr = {
- .attr.name = "egl.cfg",
- .attr.mode = S_IRUGO,
- .sgx_version = SGXCORE,
- .sgx_revision = SGX_CORE_REV,
-};
-
-/* sysfs read function */
-static ssize_t PVRSRVEglCfgShow(struct kobject *kobj, struct attribute *attr,
- char *buffer) {
- struct pvrsrv_attribute *pvrsrv_attr;
-
- pvrsrv_attr = container_of(attr, struct pvrsrv_attribute, attr);
- return snprintf(buffer, PAGE_SIZE, "0 0 android\n0 1 POWERVR_SGX%d_%d",
- pvrsrv_attr->sgx_version, pvrsrv_attr->sgx_revision);
-}
-
-/* sysfs write function unsupported*/
-static ssize_t PVRSRVEglCfgStore(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t size) {
- PVR_DPF((PVR_DBG_ERROR, "PVRSRVEglCfgStore not implemented"));
- return 0;
-}
-
-static struct attribute *pvrsrv_sysfs_attrs[] = {
- &PVRSRVAttr.attr,
- NULL
-};
-
-static const struct sysfs_ops pvrsrv_sysfs_ops = {
- .show = PVRSRVEglCfgShow,
- .store = PVRSRVEglCfgStore,
-};
-
-static struct kobj_type pvrsrv_ktype = {
- .sysfs_ops = &pvrsrv_sysfs_ops,
- .default_attrs = pvrsrv_sysfs_attrs,
-};
-
-/* create sysfs entry /sys/egl/egl.cfg to determine
- which gfx libraries to load */
-
-int PVRSRVCreateSysfsEntry(void)
-{
- struct kobject *egl_cfg_kobject;
- int r;
-
- egl_cfg_kobject = kzalloc(sizeof(*egl_cfg_kobject), GFP_KERNEL);
- r = kobject_init_and_add(egl_cfg_kobject, &pvrsrv_ktype, NULL, "egl");
-
- if (r) {
- PVR_DPF((PVR_DBG_ERROR,
- "Failed to create egl.cfg sysfs entry"));
- return PVRSRV_ERROR_INIT_FAILURE;
- }
-
- return PVRSRV_OK;
-}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/sysfs.h b/drivers/gpu/pvr/services4/srvkm/env/linux/sysfs.h
deleted file mode 100644
index fb8d20f23e2..00000000000
--- a/drivers/gpu/pvr/services4/srvkm/env/linux/sysfs.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2012 Texas Instruments, Inc
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __SYSFS_H
-#define __SYSFS_H
-
-int PVRSRVCreateSysfsEntry(void);
-
-#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.c b/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.c
new file mode 100755
index 00000000000..00f3e4fc319
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.c
@@ -0,0 +1,282 @@
+/*************************************************************************/ /*!
+@Title Systrace related functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "systrace.h"
+
+#include <trace/events/gpu.h>
+
+#include <linux/debugfs.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+
+#include "img_types.h"
+
+/*Kernel debugfs variables*/
+static unsigned int capture_hwperfdata;
+static struct dentry *pvrdir_ret;
+
+static PVRSRV_SYSTRACE_ERROR CreateJob(PVRSRV_SYSTRACE_DATA *psSystraceData, IMG_UINT32 ui32PID, IMG_UINT32 ui32FrameNum, IMG_UINT32 ui32RTData)
+{
+ PVRSRV_SYSTRACE_CONTEXT *psContext = NULL;
+ PVRSRV_SYSTRACE_JOB *psJob = NULL;
+ IMG_UINT32 i = 0;
+
+ if(psSystraceData == NULL)
+ return PVRSRV_SYSTRACE_NOT_INITIALISED;
+
+ /*Look for the PID in the context CB*/
+ for(i = 0; i < 8; ++i)
+ {
+ if(psSystraceData->asSystraceContext[i].ui32PID == ui32PID)
+ {
+ psContext = &(psSystraceData->asSystraceContext[i]);
+ break;
+ }
+ }
+
+ /*If we find it lets check its jobs, otherwise we create it*/
+ if(psContext == NULL)
+ {
+ psSystraceData->ui32Index = (psSystraceData->ui32Index+1)%8;
+
+ psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32CtxID = psSystraceData->ui32CurrentCtxID;
+ ++psSystraceData->ui32CurrentCtxID;
+ psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32PID = ui32PID;
+ psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32Start = 0;
+ psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32End = 0;
+ psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32CurrentJobID = 0;
+
+ psContext = &(psSystraceData->asSystraceContext[psSystraceData->ui32Index]);
+ }
+
+ /*This is just done during the first kick so it must not be in the job list*/
+ /*JobID not found, we create it*/
+ psJob = &(psContext->asJobs[psContext->ui32End]);
+ psJob->ui32JobID = psContext->ui32CurrentJobID;
+ ++psContext->ui32CurrentJobID;
+
+ psJob->ui32FrameNum = ui32FrameNum;
+ psJob->ui32RTData = ui32RTData;
+ /*Advance the CB*/
+ psContext->ui32End = (psContext->ui32End + 1)%16;
+ if(psContext->ui32End == psContext->ui32Start)
+ psContext->ui32Start = (psContext->ui32Start + 1)%16;
+
+ return PVRSRV_SYSTRACE_OK;
+}
+
+static PVRSRV_SYSTRACE_ERROR GetCtxAndJobID(PVRSRV_SYSTRACE_DATA *psSystraceData, IMG_UINT32 ui32PID, IMG_UINT32 ui32FrameNum, IMG_UINT32 ui32RTData,
+ IMG_UINT32 *pui32CtxID, IMG_UINT32 *pui32JobID)
+{
+ PVRSRV_SYSTRACE_CONTEXT *psContext = NULL;
+ //PVRSRV_SYSTRACE_JOB *psJob = NULL;
+ IMG_UINT32 i = 0;
+
+ if(psSystraceData == NULL)
+ return PVRSRV_SYSTRACE_NOT_INITIALISED;
+
+ /*Look for the PID in the context CB*/
+ for(i = 0; i < 8; ++i)
+ {
+ if(psSystraceData->asSystraceContext[i].ui32PID == ui32PID)
+ {
+ psContext = &(psSystraceData->asSystraceContext[i]);
+ break;
+ }
+ }
+ /*If we find it lets check its jobs, otherwise we create it*/
+ if(psContext == NULL)
+ {
+ /*Don't create anything here*/
+ return PVRSRV_SYSTRACE_JOB_NOT_FOUND;
+ }
+ /*Look for the JobID in the jobs CB otherwise create it and return ID*/
+ for(i = 0; i < 16; ++i)
+ {
+ if((psContext->asJobs[i].ui32FrameNum == ui32FrameNum) &&
+ (psContext->asJobs[i].ui32RTData == ui32RTData))
+ {
+ *pui32CtxID = psContext->ui32CtxID;
+ *pui32JobID = psContext->asJobs[i].ui32JobID;
+ return PVRSRV_SYSTRACE_OK;
+ }
+ }
+ /*Not found*/
+ return PVRSRV_SYSTRACE_JOB_NOT_FOUND;
+}
+
+void SystraceCreateFS(void)
+{
+ struct dentry *capture_sgx_hwperfdata_ret;
+
+ pvrdir_ret = debugfs_create_dir("pvr", NULL);
+ capture_sgx_hwperfdata_ret = debugfs_create_bool("gpu_tracing_on", S_IFREG | S_IRUGO | S_IWUSR, pvrdir_ret, &capture_hwperfdata);
+}
+
+void SystraceDestroyFS(void)
+{
+ debugfs_remove_recursive(pvrdir_ret);
+}
+
+IMG_BOOL SystraceIsCapturingHWData(void)
+{
+ return capture_hwperfdata;
+}
+
+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");
+ }
+}
+
+void SystraceHWPerfPackets(PVRSRV_SGXDEV_INFO *psDevInfo, PVRSRV_SGX_HWPERF_CB_ENTRY* psSGXHWPerf, IMG_UINT32 ui32DataCount, IMG_UINT32 ui32SgxClockspeed)
+{
+ IMG_UINT32 ui32PID, ui32FrameNo, ui32EvtType, ui32RTData, ui32Clocksx16Difference, ui32ClockMultiplier;
+
+ IMG_UINT32 ui32SgxClocksx16 = 0;
+ IMG_UINT32 i = 0;
+ IMG_UINT64 ui64HostTimestamp = 0;
+ IMG_UINT64 ui64TimeDifference = 0;
+ IMG_UINT64 ui64PacketTimeStamp = 0;
+
+ IMG_UINT32 ui32JobID = 0;
+ IMG_UINT32 ui32CtxID = 0;
+
+ IMG_UINT64 ui64LastHostTimestamp = 0;
+ IMG_UINT32 ui32LastSGXClocksx16 = 0;
+
+ ui64LastHostTimestamp = psDevInfo->psSystraceData->ui64LastHostTimestamp;
+ ui32LastSGXClocksx16 = psDevInfo->psSystraceData->ui32LastSGXClocksx16;
+ ui64HostTimestamp = sched_clock();
+
+ /*If this is the first packet read, use it as the initial reference*/
+ if (ui64LastHostTimestamp == 0)
+ {
+ if (ui32DataCount > 0)
+ {
+ ui64LastHostTimestamp = ui64HostTimestamp;
+ ui32LastSGXClocksx16 = psSGXHWPerf[0].ui32Clocksx16;
+ }
+ }
+
+ /* SGX clockspeed reported 307200000 HZ */
+ /* Get the ui32ClockMultipliertiplier per 1us*/
+ ui32ClockMultiplier = (ui32SgxClockspeed)/(1000*1000);
+
+ for(i = 0; i < ui32DataCount; ++i)
+ {
+ ui32SgxClocksx16 = psSGXHWPerf[i].ui32Clocksx16;
+ ui32EvtType = psSGXHWPerf[i].ui32Type;
+ ui32FrameNo = psSGXHWPerf[i].ui32FrameNo;
+ ui32PID = psSGXHWPerf[i].ui32PID;
+ ui32RTData = psSGXHWPerf[i].ui32RTData;
+
+ if ((ui32EvtType == PVRSRV_SGX_HWPERF_TYPE_TA_START) ||
+ (ui32EvtType == PVRSRV_SGX_HWPERF_TYPE_TA_END) ||
+ (ui32EvtType == PVRSRV_SGX_HWPERF_TYPE_3D_START) ||
+ (ui32EvtType == PVRSRV_SGX_HWPERF_TYPE_3D_END))
+ {
+ /*Get the JobID*/
+ GetCtxAndJobID(psDevInfo->psSystraceData, ui32PID, ui32FrameNo, ui32RTData, &ui32CtxID, &ui32JobID);
+
+ /* Calculate the time difference in ns*/
+ /* Get the clock difference */
+ ui32Clocksx16Difference = (ui32SgxClocksx16 - ui32LastSGXClocksx16);
+ /* Multipy it by 16 and 1000 to convert from us to ns */
+ ui64TimeDifference = (16*ui32Clocksx16Difference*1000)/ui32ClockMultiplier;
+
+
+ /* Add the time diff to the last time-stamp, in nanoseconds*/
+ ui64PacketTimeStamp = (unsigned long long) ui64LastHostTimestamp + (unsigned long long)ui64TimeDifference;
+
+ switch(ui32EvtType)
+ {
+ case PVRSRV_SGX_HWPERF_TYPE_TA_START:
+ trace_gpu_sched_switch("TA", ui64PacketTimeStamp, ui32CtxID, ui32FrameNo, ui32JobID);
+ break;
+
+ case PVRSRV_SGX_HWPERF_TYPE_TA_END:
+ trace_gpu_sched_switch("TA", ui64PacketTimeStamp, 0, ui32FrameNo, ui32JobID);
+ break;
+
+ case PVRSRV_SGX_HWPERF_TYPE_3D_START:
+ trace_gpu_sched_switch("3D", ui64PacketTimeStamp, ui32CtxID, ui32FrameNo, ui32JobID);
+ break;
+
+ case PVRSRV_SGX_HWPERF_TYPE_3D_END:
+ trace_gpu_sched_switch("3D", ui64PacketTimeStamp, 0, ui32FrameNo, ui32JobID);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ if(ui32DataCount > 0)
+ {
+ psDevInfo->psSystraceData->ui32LastSGXClocksx16 = ui32SgxClocksx16;
+ }
+ /* Get the last set of packets timestamp and sleep 1ms */
+ psDevInfo->psSystraceData->ui64LastHostTimestamp = ui64HostTimestamp;
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.h b/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.h
new file mode 100755
index 00000000000..ad4bcc0ccee
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@Title Systrace related functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SYSTRACE_
+#define _SYSTRACE_
+
+#include "img_defs.h"
+#include "img_types.h"
+
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+
+typedef enum
+{
+ PVRSRV_SYSTRACE_OK = 0x00,
+ PVRSRV_SYSTRACE_NOT_INITIALISED,
+ PVRSRV_SYSTRACE_JOB_NOT_FOUND
+} PVRSRV_SYSTRACE_ERROR;
+
+
+void SystraceHWPerfPackets(PVRSRV_SGXDEV_INFO *psDevInfo, PVRSRV_SGX_HWPERF_CB_ENTRY* psSGXHWPerf, IMG_UINT32 ui32DataCount, IMG_UINT32 ui32SgxClockspeed);
+void SystraceTAKick(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FrameNum, IMG_UINT32 ui32RTData, IMG_BOOL bIsFirstKick);
+
+void SystraceCreateFS(void);
+void SystraceDestroyFS(void);
+IMG_BOOL SystraceIsCapturingHWData(void);
+
+#endif /* _SYSTRACE_ */