diff options
Diffstat (limited to 'drivers/gpu/pvr/services4/srvkm/env/linux')
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_ */  |