diff options
| author | Wengang Wu <wgw@motorola.com> | 2014-05-21 09:29:41 -0500 |
|---|---|---|
| committer | Wengang Wu <wgw@motorola.com> | 2014-05-21 09:29:41 -0500 |
| commit | 53a835f5057367679eb3db728bbdd427aab8aa8a (patch) | |
| tree | 03e5bbde7d371e885d1c67210b2b0c9bb0130d40 /drivers/gpu/pvr/services4/srvkm/env/linux | |
| parent | 7489b569ffb64cdb998544405b6774bd43aab70b (diff) | |
| download | olio-linux-3.10-53a835f5057367679eb3db728bbdd427aab8aa8a.tar.xz olio-linux-3.10-53a835f5057367679eb3db728bbdd427aab8aa8a.zip | |
IKXCLOCK-1501 Upgrade to TI SGX Android OpenGL 1.12@2701748
Initial codes of TI SGX DDK 1.12@2701748
Change-Id: I75a8f6521968346ea1b2ea9fa54817ba186442ce
Diffstat (limited to 'drivers/gpu/pvr/services4/srvkm/env/linux')
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_ */ |