diff options
Diffstat (limited to 'pvr-source/services4/srvkm/env')
32 files changed, 0 insertions, 17465 deletions
diff --git a/pvr-source/services4/srvkm/env/linux/Kbuild.mk b/pvr-source/services4/srvkm/env/linux/Kbuild.mk deleted file mode 100755 index 25e35e9..0000000 --- a/pvr-source/services4/srvkm/env/linux/Kbuild.mk +++ /dev/null @@ -1,166 +0,0 @@ -########################################################################### ### -#@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. -### ########################################################################### - -pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-y += \ - services4/srvkm/env/linux/osfunc.o \ - services4/srvkm/env/linux/mutils.o \ - services4/srvkm/env/linux/mmap.o \ - services4/srvkm/env/linux/module.o \ - services4/srvkm/env/linux/pdump.o \ - services4/srvkm/env/linux/proc.o \ - services4/srvkm/env/linux/pvr_bridge_k.o \ - services4/srvkm/env/linux/pvr_debug.o \ - services4/srvkm/env/linux/mm.o \ - 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 \ - services4/srvkm/common/mem.o \ - services4/srvkm/common/mem_debug.o \ - services4/srvkm/common/metrics.o \ - services4/srvkm/common/osfunc_common.o \ - services4/srvkm/common/pdump_common.o \ - 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 \ - services4/srvkm/bridged/bridged_support.o \ - services4/srvkm/bridged/bridged_pvr_bridge.o \ - 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_ION),1) -pvrsrvkm-y += \ - services4/srvkm/env/linux/ion.o -endif - -ifeq ($(TTRACE),1) -pvrsrvkm-y += \ - services4/srvkm/common/ttrace.o -endif - -ifneq ($(W),1) -CFLAGS_osfunc.o := -Werror -CFLAGS_mutils.o := -Werror -CFLAGS_mmap.o := -Werror -CFLAGS_module.o := -Werror -CFLAGS_pdump.o := -Werror -CFLAGS_proc.o := -Werror -CFLAGS_pvr_bridge_k.o := -Werror -CFLAGS_pvr_debug.o := -Werror -CFLAGS_mm.o := -Werror -CFLAGS_mutex.o := -Werror -CFLAGS_event.o := -Werror -CFLAGS_osperproc.o := -Werror -CFLAGS_buffer_manager.o := -Werror -CFLAGS_devicemem.o := -Werror -CFLAGS_deviceclass.o := -Werror -CFLAGS_handle.o := -Werror -CFLAGS_hash.o := -Werror -CFLAGS_metrics.o := -Werror -CFLAGS_pvrsrv.o := -Werror -CFLAGS_queue.o := -Werror -CFLAGS_ra.o := -Werror -CFLAGS_resman.o := -Werror -CFLAGS_power.o := -Werror -CFLAGS_mem.o := -Werror -CFLAGS_pdump_common.o := -Werror -CFLAGS_bridged_support.o := -Werror -CFLAGS_bridged_pvr_bridge.o := -Werror -CFLAGS_perproc.o := -Werror -CFLAGS_lists.o := -Werror -CFLAGS_mem_debug.o := -Werror -CFLAGS_osfunc_common.o := -Werror -CFLAGS_refcount.o := -Werror -endif - -# SUPPORT_SGX==1 only - -pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-y += \ - services4/srvkm/bridged/sgx/bridged_sgx_bridge.o \ - services4/srvkm/devices/sgx/sgxinit.o \ - services4/srvkm/devices/sgx/sgxpower.o \ - services4/srvkm/devices/sgx/sgxreset.o \ - services4/srvkm/devices/sgx/sgxutils.o \ - services4/srvkm/devices/sgx/sgxkick.o \ - services4/srvkm/devices/sgx/sgxtransfer.o \ - services4/srvkm/devices/sgx/mmu.o \ - services4/srvkm/devices/sgx/pb.o - -ifneq ($(W),1) -CFLAGS_bridged_sgx_bridge.o := -Werror -CFLAGS_sgxinit.o := -Werror -CFLAGS_sgxpower.o := -Werror -CFLAGS_sgxreset.o := -Werror -CFLAGS_sgxutils.o := -Werror -CFLAGS_sgxkick.o := -Werror -CFLAGS_sgxtransfer.o := -Werror -CFLAGS_mmu.o := -Werror -CFLAGS_pb.o := -Werror -endif - -ifeq ($(SUPPORT_DRI_DRM),1) - -pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV)-y += \ - services4/srvkm/env/linux/pvr_drm.o - -ccflags-y += \ - -I$(KERNELDIR)/include/drm \ - -I$(TOP)/services4/include/env/linux \ - -ifeq ($(PVR_DRI_DRM_NOT_PCI),1) -ccflags-y += -I$(TOP)/services4/3rdparty/linux_drm -endif - -endif # SUPPORT_DRI_DRM diff --git a/pvr-source/services4/srvkm/env/linux/Linux.mk b/pvr-source/services4/srvkm/env/linux/Linux.mk deleted file mode 100755 index 7e3d0fb..0000000 --- a/pvr-source/services4/srvkm/env/linux/Linux.mk +++ /dev/null @@ -1,45 +0,0 @@ -########################################################################### ### -#@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. -### ########################################################################### - -modules := srvkm - -srvkm_type := kernel_module -srvkm_target := pvrsrvkm_sgx$(SGXCORE)_$(SGX_CORE_REV).ko -srvkm_makefile := $(THIS_DIR)/Kbuild.mk diff --git a/pvr-source/services4/srvkm/env/linux/env_data.h b/pvr-source/services4/srvkm/env/linux/env_data.h deleted file mode 100755 index b838809..0000000 --- a/pvr-source/services4/srvkm/env/linux/env_data.h +++ /dev/null @@ -1,93 +0,0 @@ -/*************************************************************************/ /*! -@Title Environmental Data header file -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Linux-specific part of system data. -@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 _ENV_DATA_ -#define _ENV_DATA_ - -#include <linux/interrupt.h> -#include <linux/pci.h> - -#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) -#include <linux/workqueue.h> -#endif - -/* - * Env data specific to linux - convenient place to put this - */ - -/* Fairly arbitrary sizes - hopefully enough for all bridge calls */ -#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000 -#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000 - -typedef struct _PVR_PCI_DEV_TAG -{ - struct pci_dev *psPCIDev; - HOST_PCI_INIT_FLAGS ePCIFlags; - IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE]; -} PVR_PCI_DEV; - -typedef struct _ENV_DATA_TAG -{ - IMG_VOID *pvBridgeData; - struct pm_dev *psPowerDevice; - IMG_BOOL bLISRInstalled; - IMG_BOOL bMISRInstalled; - IMG_UINT32 ui32IRQ; - IMG_VOID *pvISRCookie; -#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) - struct workqueue_struct *psWorkQueue; -#endif -#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) - struct work_struct sMISRWork; - IMG_VOID *pvMISRData; -#else - struct tasklet_struct sMISRTasklet; -#endif -#if defined (SUPPORT_ION) - IMG_HANDLE hIonHeaps; - IMG_HANDLE hIonDev; -#endif -} ENV_DATA; - -#endif /* _ENV_DATA_ */ -/***************************************************************************** - End of file (env_data.h) -*****************************************************************************/ diff --git a/pvr-source/services4/srvkm/env/linux/env_perproc.h b/pvr-source/services4/srvkm/env/linux/env_perproc.h deleted file mode 100755 index 8a37a7f..0000000 --- a/pvr-source/services4/srvkm/env/linux/env_perproc.h +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************/ /*! -@Title OS specific per process data interface -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Linux per process data -@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 __ENV_PERPROC_H__ -#define __ENV_PERPROC_H__ - -#include <linux/list.h> -#include <linux/proc_fs.h> - -#include "services.h" -#include "handle.h" - -#define ION_CLIENT_NAME_SIZE 50 -typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_ -{ - IMG_HANDLE hBlockAlloc; - struct proc_dir_entry *psProcDir; -#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) - struct list_head sDRMAuthListHead; -#endif -#if defined (SUPPORT_ION) - struct ion_client *psIONClient; - IMG_CHAR azIonClientName[ION_CLIENT_NAME_SIZE]; -#endif -} PVRSRV_ENV_PER_PROCESS_DATA; - -IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc); - -PVRSRV_ERROR LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc); - -IMG_VOID LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc); - -PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase); - -IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID); - -#endif /* __ENV_PERPROC_H__ */ - -/****************************************************************************** - End of file (env_perproc.h) -******************************************************************************/ diff --git a/pvr-source/services4/srvkm/env/linux/event.c b/pvr-source/services4/srvkm/env/linux/event.c deleted file mode 100755 index c335640..0000000 --- a/pvr-source/services4/srvkm/env/linux/event.c +++ /dev/null @@ -1,414 +0,0 @@ -/*************************************************************************/ /*! -@Title Event Object -@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 <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#include <asm/io.h> -#include <asm/page.h> -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) -#include <asm/system.h> -#endif -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/delay.h> -#include <linux/pci.h> - -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <asm/hardirq.h> -#include <linux/spinlock.h> -#include <linux/timer.h> -#include <linux/capability.h> -#include <linux/sched.h> -#include <asm/uaccess.h> - -#include "img_types.h" -#include "services_headers.h" -#include "mm.h" -#include "pvrmmap.h" -#include "mmap.h" -#include "env_data.h" -#include "proc.h" -#include "mutex.h" -#include "lock.h" -#include "event.h" - -typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG -{ - rwlock_t sLock; - struct list_head sList; - -} PVRSRV_LINUX_EVENT_OBJECT_LIST; - - -typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG -{ - atomic_t sTimeStamp; - IMG_UINT32 ui32TimeStampPrevious; -#if defined(DEBUG) - IMG_UINT ui32Stats; -#endif - wait_queue_head_t sWait; - struct list_head sList; - IMG_HANDLE hResItem; - PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList; -} PVRSRV_LINUX_EVENT_OBJECT; - -/*! -****************************************************************************** - - @Function LinuxEventObjectListCreate - - @Description - - Linux wait object list creation - - @Output hOSEventKM : Pointer to the event object list handle - - @Return PVRSRV_ERROR : Error code - -******************************************************************************/ -PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList) -{ - PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList; - - if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), - (IMG_VOID **)&psEventObjectList, IMG_NULL, - "Linux Event Object List") != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list")); - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - - INIT_LIST_HEAD(&psEventObjectList->sList); - - rwlock_init(&psEventObjectList->sLock); - - *phEventObjectList = (IMG_HANDLE *) psEventObjectList; - - return PVRSRV_OK; -} - -/*! -****************************************************************************** - - @Function LinuxEventObjectListDestroy - - @Description - - Linux wait object list destruction - - @Input hOSEventKM : Event object list handle - - @Return PVRSRV_ERROR : Error code - -******************************************************************************/ -PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList) -{ - - PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ; - - if(psEventObjectList) - { - IMG_BOOL bListEmpty; - - read_lock(&psEventObjectList->sLock); - bListEmpty = list_empty(&psEventObjectList->sList); - read_unlock(&psEventObjectList->sLock); - - if (!bListEmpty) - { - PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty")); - return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT; - } - - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEventObjectList, IMG_NULL); - /*not nulling pointer, copy on stack*/ - } - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function LinuxEventObjectDelete - - @Description - - Linux wait object removal - - @Input hOSEventObjectList : Event object list handle - @Input hOSEventObject : Event object handle - @Input bResManCallback : Called from the resman - - @Return PVRSRV_ERROR : Error code - -******************************************************************************/ -PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject) -{ - if(hOSEventObjectList) - { - if(hOSEventObject) - { - PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject; -#if defined(DEBUG) - PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %u", psLinuxEventObject->ui32Stats)); -#endif - if(ResManFreeResByPtr(psLinuxEventObject->hResItem, CLEANUP_WITH_POLL) != PVRSRV_OK) - { - return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT; - } - - return PVRSRV_OK; - } - } - return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT; - -} - -/*! -****************************************************************************** - - @Function LinuxEventObjectDeleteCallback - - @Description - - Linux wait object removal - - @Input hOSEventObject : Event object handle - - @Return PVRSRV_ERROR : Error code - -******************************************************************************/ -static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup) -{ - PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam; - PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList; - unsigned long ulLockFlags; - - PVR_UNREFERENCED_PARAMETER(ui32Param); - PVR_UNREFERENCED_PARAMETER(bForceCleanup); - - write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags); - list_del(&psLinuxEventObject->sList); - write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags); - -#if defined(DEBUG) - PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %u", psLinuxEventObject->ui32Stats)); -#endif - - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL); - /*not nulling pointer, copy on stack*/ - - return PVRSRV_OK; -} -/*! -****************************************************************************** - - @Function LinuxEventObjectAdd - - @Description - - Linux wait object addition - - @Input hOSEventObjectList : Event object list handle - @Output phOSEventObject : Pointer to the event object handle - - @Return PVRSRV_ERROR : Error code - -******************************************************************************/ -PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject) - { - PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject; - PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; - IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); - PVRSRV_PER_PROCESS_DATA *psPerProc; - unsigned long ulLockFlags; - - psPerProc = PVRSRVPerProcessData(ui32PID); - if (psPerProc == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data")); - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - - /* allocate completion variable */ - if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), - (IMG_VOID **)&psLinuxEventObject, IMG_NULL, - "Linux Event Object") != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory ")); - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - - INIT_LIST_HEAD(&psLinuxEventObject->sList); - - atomic_set(&psLinuxEventObject->sTimeStamp, 0); - psLinuxEventObject->ui32TimeStampPrevious = 0; - -#if defined(DEBUG) - psLinuxEventObject->ui32Stats = 0; -#endif - init_waitqueue_head(&psLinuxEventObject->sWait); - - psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList; - - psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext, - RESMAN_TYPE_EVENT_OBJECT, - psLinuxEventObject, - 0, - &LinuxEventObjectDeleteCallback); - - write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags); - list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList); - write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags); - - *phOSEventObject = psLinuxEventObject; - - return PVRSRV_OK; -} - -/*! -****************************************************************************** - - @Function LinuxEventObjectSignal - - @Description - - Linux wait object signaling function - - @Input hOSEventObjectList : Event object list handle - - @Return PVRSRV_ERROR : Error code - -******************************************************************************/ -PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList) -{ - PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject; - PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; - struct list_head *psListEntry, *psList; - - psList = &psLinuxEventObjectList->sList; - - /* - * We don't take the write lock in interrupt context, so we don't - * need to use read_lock_irqsave. - */ - read_lock(&psLinuxEventObjectList->sLock); - list_for_each(psListEntry, psList) - { - - psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList); - - atomic_inc(&psLinuxEventObject->sTimeStamp); - wake_up_interruptible(&psLinuxEventObject->sWait); - } - read_unlock(&psLinuxEventObjectList->sLock); - - return PVRSRV_OK; - -} - -/*! -****************************************************************************** - - @Function LinuxEventObjectWait - - @Description - - Linux wait object routine - - @Input hOSEventObject : Event object handle - - @Input ui32MSTimeout : Time out value in msec - - @Return PVRSRV_ERROR : Error code - -******************************************************************************/ -PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout) -{ - IMG_UINT32 ui32TimeStamp; - DEFINE_WAIT(sWait); - - PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject; - - IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout); - - do - { - prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE); - ui32TimeStamp = (IMG_UINT32)atomic_read(&psLinuxEventObject->sTimeStamp); - - if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp) - { - break; - } - - LinuxUnLockMutex(&gPVRSRVLock); - - ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies); - - LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); -#if defined(DEBUG) - psLinuxEventObject->ui32Stats++; -#endif - - - } while (ui32TimeOutJiffies); - - finish_wait(&psLinuxEventObject->sWait, &sWait); - - psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp; - - return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT; - -} - diff --git a/pvr-source/services4/srvkm/env/linux/event.h b/pvr-source/services4/srvkm/env/linux/event.h deleted file mode 100755 index 5c1451c..0000000 --- a/pvr-source/services4/srvkm/env/linux/event.h +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ /*! -@Title Event Object -@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. -*/ /**************************************************************************/ - - -PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList); -PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList); -PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject); -PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject); -PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList); -PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout); diff --git a/pvr-source/services4/srvkm/env/linux/gc_bvmapping.c b/pvr-source/services4/srvkm/env/linux/gc_bvmapping.c deleted file mode 100755 index 6c5d17a..0000000 --- a/pvr-source/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/pvr-source/services4/srvkm/env/linux/gc_bvmapping.h b/pvr-source/services4/srvkm/env/linux/gc_bvmapping.h deleted file mode 100755 index 6a3a2b1..0000000 --- a/pvr-source/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/pvr-source/services4/srvkm/env/linux/ion.c b/pvr-source/services4/srvkm/env/linux/ion.c deleted file mode 100755 index e84fdc4..0000000 --- a/pvr-source/services4/srvkm/env/linux/ion.c +++ /dev/null @@ -1,363 +0,0 @@ -/*************************************************************************/ /*! -@Title Ion driver inter-operability code. -@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 "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" - -#include <linux/module.h> -#include <linux/file.h> -#include <linux/fs.h> - -#if defined (CONFIG_ION_OMAP) -#define MAX_HANDLES_PER_FD 2 -extern struct ion_client *gpsIONClient; - -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; - - /* Take the bridge mutex so the handle won't be freed underneath us */ - LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); - - psFile = fget(fd); - if(!psFile) - goto err_unlock; - - 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; - } - - psLinuxMemArea = (LinuxMemArea *)psKernelMemInfo->sMemBlk.hOSMemHandle; - BUG_ON(psLinuxMemArea == 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; - } - - /* Client is requesting fewer handles then we have */ - if(ui32NumHandles < psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes) { - - PVR_DPF((PVR_DBG_ERROR, "%s: Client requested %u handles, but we have %u", - __func__, - ui32NumHandles, - psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes)); - - /* Clear client handles */ - for (i = 0; i < ui32NumHandles; i++) - handles[i] = NULL; - - /* Return number of handles to client */ - *num_handles = psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes; - goto err_fput; - } - - for (i = 0; (i < psLinuxMemArea->uData.sIONTilerAlloc.ui32NumValidPlanes) && (i < MAX_HANDLES_PER_FD); i++) - handles[i] = psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i]; - - *num_handles = i; - - if(client) - *client = gpsIONClient; - - ret = 0; - -err_fput: - fput(psFile); -err_unlock: - /* Allow PVRSRV clients to communicate with srvkm again */ - LinuxUnLockMutex(&gPVRSRVLock); - - return ret; -} - -struct ion_handle * -PVRSRVExportFDToIONHandle(int fd, struct ion_client **client) -{ - unsigned int num_handles = 1; - struct ion_handle *psHandle = IMG_NULL; - PVRSRVExportFDToIONHandles(fd, client, &psHandle, &num_handles); - return psHandle; -} - -EXPORT_SYMBOL(PVRSRVExportFDToIONHandles); -EXPORT_SYMBOL(PVRSRVExportFDToIONHandle); -#endif - -#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_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, - } - } -}; - -PVRSRV_ERROR IonInit(IMG_VOID) -{ - int uiHeapCount = generic_config.nr; - int uiError; - int i; - - apsIonHeaps = 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); - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - - /* Register all the heaps */ - for (i = 0; i < generic_config.nr; i++) - { - struct ion_platform_heap *psPlatHeapData = &generic_config.heaps[i]; - - apsIonHeaps[i] = ion_heap_create(psPlatHeapData); - if (IS_ERR_OR_NULL(apsIonHeaps[i])) - { - uiError = PTR_ERR(apsIonHeaps[i]); - goto failHeapCreate; - } - ion_device_add_heap(psIonDev, apsIonHeaps[i]); - } - - return PVRSRV_OK; -failHeapCreate: - for (i = 0; i < uiHeapCount; i++) { - if (apsIonHeaps[i]) - { - ion_heap_destroy(apsIonHeaps[i]); - } - } - kfree(apsIonHeaps); - return PVRSRV_ERROR_OUT_OF_MEMORY; -} - -IMG_VOID IonDeinit(IMG_VOID) -{ - int uiHeapCount = generic_config.nr; - int i; - - for (i = 0; i < uiHeapCount; i++) { - if (apsIonHeaps[i]) - { - ion_heap_destroy(apsIonHeaps[i]); - } - } - kfree(apsIonHeaps); - ion_device_destroy(psIonDev); -} - -typedef struct _ION_IMPORT_DATA_ -{ - 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) -{ - struct ion_client *psIonClient = hIonDev; - struct ion_handle *psIonHandle; - struct scatterlist *psScatterList; - struct scatterlist *psTemp; - IMG_SYS_PHYADDR *pasSysPhysAddr = NULL; - 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) - { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - - /* Get the buffer handle */ - psIonHandle = ion_import_fd(psIonClient, fd); - if (psIonHandle == IMG_NULL) - { - eError = PVRSRV_ERROR_BAD_MAPPING; - goto exitFailImport; - } - - /* Create data for free callback */ - psImportData->psIonClient = psIonClient; - psImportData->psIonHandle = psIonHandle; - - psScatterList = ion_map_dma(psIonClient, psIonHandle); - if (psScatterList == NULL) - { - eError = PVRSRV_ERROR_INVALID_PARAMS; - goto exitFailMap; - } - - /* - 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) - { - 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 */ - } - - while(psTemp) - { - IMG_UINT32 j; - - for (j=0;j<psTemp->length;j+=PAGE_SIZE) - { - if (i == 1) - { - /* Pass 2: Get the page data */ - pasSysPhysAddr[ui32PageCount].uiAddr = sg_phys(psTemp); - } - ui32PageCount++; - } - psTemp = sg_next(psTemp); - } - } - - pvKernAddr = ion_map_kernel(psIonClient, psIonHandle); - if (IS_ERR(pvKernAddr)) - { - pvKernAddr = IMG_NULL; - } - - psImportData->pvKernAddr = pvKernAddr; - - *ppvKernAddr = pvKernAddr; - *pui32PageCount = ui32PageCount; - *ppasSysPhysAddr = pasSysPhysAddr; - *phPriv = psImportData; - return PVRSRV_OK; - -exitFailAlloc: - ion_unmap_dma(psIonClient, psIonHandle); -exitFailMap: - ion_free(psIonClient, psIonHandle); -exitFailImport: - kfree(psImportData); - return eError; -} - - -IMG_VOID IonUnimportBufferAndReleasePhysAddr(IMG_HANDLE hPriv) -{ - ION_IMPORT_DATA *psImportData = hPriv; - - ion_unmap_dma(psImportData->psIonClient, psImportData->psIonHandle); - if (psImportData->pvKernAddr) - { - ion_unmap_kernel(psImportData->psIonClient, psImportData->psIonHandle); - } - ion_free(psImportData->psIonClient, psImportData->psIonHandle); - kfree(psImportData); -} -#endif diff --git a/pvr-source/services4/srvkm/env/linux/ion.h b/pvr-source/services4/srvkm/env/linux/ion.h deleted file mode 100755 index 1cf385d..0000000 --- a/pvr-source/services4/srvkm/env/linux/ion.h +++ /dev/null @@ -1,74 +0,0 @@ -/*************************************************************************/ /*! -@Title Ion driver inter-operability code. -@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 __IMG_LINUX_ION_H__ -#define __IMG_LINUX_ION_H__ - -#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); - -IMG_VOID IonUnimportBufferAndReleasePhysAddr(IMG_HANDLE hPriv); -#endif -#endif /* __IMG_LINUX_ION_H__ */ diff --git a/pvr-source/services4/srvkm/env/linux/linkage.h b/pvr-source/services4/srvkm/env/linux/linkage.h deleted file mode 100755 index 55cd4f0..0000000 --- a/pvr-source/services4/srvkm/env/linux/linkage.h +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux specific Services code internal interfaces -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Interfaces between various parts of the Linux specific - Services code, that don't have any other obvious - header file to go into. -@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 __LINKAGE_H__ -#define __LINKAGE_H__ - -#if !defined(SUPPORT_DRI_DRM) -long PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, unsigned long arg); -#endif - -IMG_VOID PVRDPFInit(IMG_VOID); -PVRSRV_ERROR PVROSFuncInit(IMG_VOID); -IMG_VOID PVROSFuncDeInit(IMG_VOID); - -#ifdef DEBUG - -IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data); -void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el); - -#ifdef PVR_MANUAL_POWER_CONTROL -IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data); - -void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el); - -#endif /* PVR_MANUAL_POWER_CONTROL */ - -#endif /* DEBUG */ - -#endif /* __LINKAGE_H__ */ -/***************************************************************************** - End of file (linkage.h) -*****************************************************************************/ diff --git a/pvr-source/services4/srvkm/env/linux/lock.h b/pvr-source/services4/srvkm/env/linux/lock.h deleted file mode 100755 index 11adcaa..0000000 --- a/pvr-source/services4/srvkm/env/linux/lock.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************/ /*! -@Title Main driver lock -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description The main driver lock, held in most places in - the driver. -@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 __LOCK_H__ -#define __LOCK_H__ - -/* - * Main driver lock, used to ensure driver code is single threaded. - * There are some places where this lock must not be taken, such as - * in the mmap related deriver entry points. - */ -extern PVRSRV_LINUX_MUTEX gPVRSRVLock; - -#endif /* __LOCK_H__ */ -/***************************************************************************** - End of file (lock.h) -*****************************************************************************/ diff --git a/pvr-source/services4/srvkm/env/linux/mm.c b/pvr-source/services4/srvkm/env/linux/mm.c deleted file mode 100755 index 0815e46..0000000 --- a/pvr-source/services4/srvkm/env/linux/mm.c +++ /dev/null @@ -1,2945 +0,0 @@ -/*************************************************************************/ /*! -@Title Misc memory management utility functions for Linux -@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 <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#if !defined(PVR_LINUX_MEM_AREA_POOL_MAX_PAGES) -#define PVR_LINUX_MEM_AREA_POOL_MAX_PAGES 0 -#endif - -#include <linux/kernel.h> -#include <asm/atomic.h> -#include <linux/list.h> -#include <linux/mutex.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <asm/io.h> -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) -#include <linux/wrapper.h> -#endif -#include <linux/slab.h> -#include <linux/highmem.h> -#include <linux/sched.h> - -#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)) -#include <linux/shrinker.h> -#endif -#endif - -#include "img_defs.h" -#include "services.h" -#include "servicesint.h" -#include "syscommon.h" -#include "mutils.h" -#include "mm.h" -#include "pvrmmap.h" -#include "mmap.h" -#include "osfunc.h" -#include "pvr_debug.h" -#include "proc.h" -#include "mutex.h" -#include "lock.h" - -#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - #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 -#endif - -/* - * The page pool entry count is an atomic int so that the shrinker function - * can return it even when we can't take the lock that protects the page pool - * list. - */ -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_VMALLOC, - DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, - DEBUG_MEM_ALLOC_TYPE_IOREMAP, - DEBUG_MEM_ALLOC_TYPE_IO, - DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, - DEBUG_MEM_ALLOC_TYPE_ION, -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - DEBUG_MEM_ALLOC_TYPE_VMAP, -#endif - DEBUG_MEM_ALLOC_TYPE_COUNT -} DEBUG_MEM_ALLOC_TYPE; - -typedef struct _DEBUG_MEM_ALLOC_REC -{ - DEBUG_MEM_ALLOC_TYPE eAllocType; - IMG_VOID *pvKey; /* Some unique value (private to the eAllocType) */ - IMG_VOID *pvCpuVAddr; - IMG_UINT32 ulCpuPAddr; - IMG_VOID *pvPrivateData; - IMG_UINT32 ui32Bytes; - pid_t pid; - IMG_CHAR *pszFileName; - IMG_UINT32 ui32Line; - - struct _DEBUG_MEM_ALLOC_REC *psNext; - struct _DEBUG_MEM_ALLOC_REC **ppsThis; -} DEBUG_MEM_ALLOC_REC; - -static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE) -static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC) -static IMPLEMENT_LIST_FOR_EACH(DEBUG_MEM_ALLOC_REC) -static IMPLEMENT_LIST_INSERT(DEBUG_MEM_ALLOC_REC) -static IMPLEMENT_LIST_REMOVE(DEBUG_MEM_ALLOC_REC) - - -static DEBUG_MEM_ALLOC_REC *g_MemoryRecords; - -static IMG_UINT32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT]; -static IMG_UINT32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT]; - -/* vmalloc + kmalloc + alloc_pages + kmem_cache */ -static IMG_UINT32 g_SysRAMWaterMark; /* Doesn't include page pool */ -static IMG_UINT32 g_SysRAMHighWaterMark; /* *DOES* include page pool */ - -static inline IMG_UINT32 -SysRAMTrueWaterMark(void) -{ - return g_SysRAMWaterMark + PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount)); -} - -/* ioremap + io */ -static IMG_UINT32 g_IOMemWaterMark; -static IMG_UINT32 g_IOMemHighWaterMark; - -static IMG_VOID DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType, - IMG_VOID *pvKey, - IMG_VOID *pvCpuVAddr, - IMG_UINT32 ulCpuPAddr, - IMG_VOID *pvPrivateData, - IMG_UINT32 ui32Bytes, - 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_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType); - - -static struct 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); - -#endif - - -#if defined(DEBUG_LINUX_MEM_AREAS) -typedef struct _DEBUG_LINUX_MEM_AREA_REC -{ - LinuxMemArea *psLinuxMemArea; - IMG_UINT32 ui32Flags; - pid_t pid; - - struct _DEBUG_LINUX_MEM_AREA_REC *psNext; - struct _DEBUG_LINUX_MEM_AREA_REC **ppsThis; -}DEBUG_LINUX_MEM_AREA_REC; - - -static IMPLEMENT_LIST_ANY_VA(DEBUG_LINUX_MEM_AREA_REC) -static IMPLEMENT_LIST_FOR_EACH(DEBUG_LINUX_MEM_AREA_REC) -static IMPLEMENT_LIST_INSERT(DEBUG_LINUX_MEM_AREA_REC) -static IMPLEMENT_LIST_REMOVE(DEBUG_LINUX_MEM_AREA_REC) - - - - -static DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords; -static IMG_UINT32 g_LinuxMemAreaCount; -static IMG_UINT32 g_LinuxMemAreaWaterMark; -static IMG_UINT32 g_LinuxMemAreaHighWaterMark; - - -static struct 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) -static PVRSRV_LINUX_MUTEX g_sDebugMutex; -#endif - -#if (defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)) -static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start); -#endif - -typedef struct -{ - /* Linkage for page pool LRU list */ - struct list_head sPagePoolItem; - - struct page *psPage; -} LinuxPagePoolEntry; - -static LinuxKMemCache *g_PsLinuxMemAreaCache; -static LinuxKMemCache *g_PsLinuxPagePoolCache; - -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); -#endif - -static LinuxMemArea *LinuxMemAreaStructAlloc(IMG_VOID); -static IMG_VOID LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea); -#if defined(DEBUG_LINUX_MEM_AREAS) -static IMG_VOID DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags); -static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea); -static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea); -#endif - - -static inline IMG_BOOL -AreaIsUncached(IMG_UINT32 ui32AreaFlags) -{ - return (ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED)) != 0; -} - -static inline IMG_BOOL -CanFreeToPool(LinuxMemArea *psLinuxMemArea) -{ - return AreaIsUncached(psLinuxMemArea->ui32AreaFlags) && !psLinuxMemArea->bNeedsCacheInvalidate; -} - -IMG_VOID * -_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line) -{ - IMG_VOID *pvRet; - pvRet = kmalloc(ui32ByteSize, uFlags); -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - if (pvRet) - { - DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC, - pvRet, - pvRet, - 0, - NULL, - ui32ByteSize, - pszFileName, - ui32Line - ); - } -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - return pvRet; -} - - -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); -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - kfree(pvCpuVAddr); -} - - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -static IMG_VOID -DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType, - IMG_VOID *pvKey, - IMG_VOID *pvCpuVAddr, - IMG_UINT32 ulCpuPAddr, - IMG_VOID *pvPrivateData, - IMG_UINT32 ui32Bytes, - IMG_CHAR *pszFileName, - IMG_UINT32 ui32Line) -{ - DEBUG_MEM_ALLOC_REC *psRecord; - - LinuxLockMutex(&g_sDebugMutex); - - psRecord = kmalloc(sizeof(DEBUG_MEM_ALLOC_REC), GFP_KERNEL); - - psRecord->eAllocType = eAllocType; - psRecord->pvKey = pvKey; - psRecord->pvCpuVAddr = pvCpuVAddr; - psRecord->ulCpuPAddr = ulCpuPAddr; - psRecord->pvPrivateData = pvPrivateData; - psRecord->pid = OSGetCurrentProcessIDKM(); - psRecord->ui32Bytes = ui32Bytes; - psRecord->pszFileName = pszFileName; - psRecord->ui32Line = ui32Line; - - List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord); - - g_WaterMarkData[eAllocType] += ui32Bytes; - if (g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType]) - { - g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType]; - } - - 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) - { - IMG_UINT32 ui32SysRAMTrueWaterMark; - - g_SysRAMWaterMark += ui32Bytes; - ui32SysRAMTrueWaterMark = SysRAMTrueWaterMark(); - - if (ui32SysRAMTrueWaterMark > g_SysRAMHighWaterMark) - { - g_SysRAMHighWaterMark = ui32SysRAMTrueWaterMark; - } - } - else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP - || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO) - { - g_IOMemWaterMark += ui32Bytes; - if (g_IOMemWaterMark > g_IOMemHighWaterMark) - { - g_IOMemHighWaterMark = g_IOMemWaterMark; - } - } - - LinuxUnLockMutex(&g_sDebugMutex); -} - - -static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrentRecord, va_list va) -{ - DEBUG_MEM_ALLOC_TYPE eAllocType; - IMG_VOID *pvKey; - - eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE); - pvKey = va_arg(va, IMG_VOID*); - - if (psCurrentRecord->eAllocType == eAllocType - && psCurrentRecord->pvKey == pvKey) - { - eAllocType = psCurrentRecord->eAllocType; - g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes; - - 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; - } - else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP - || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO) - { - g_IOMemWaterMark -= psCurrentRecord->ui32Bytes; - } - - List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord); - kfree(psCurrentRecord); - - return IMG_TRUE; - } - else - { - return IMG_FALSE; - } -} - - -static IMG_VOID -DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line) -{ -/* DEBUG_MEM_ALLOC_REC **ppsCurrentRecord;*/ - - LinuxLockMutex(&g_sDebugMutex); - - /* Locate the corresponding allocation entry */ - if (!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords, - DebugMemAllocRecordRemove_AnyVaCb, - eAllocType, - pvKey)) - { - 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, - pszFileName, ui32Line)); - } - - LinuxUnLockMutex(&g_sDebugMutex); -} - - -static IMG_CHAR * -DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType) -{ - IMG_CHAR *apszDebugMemoryRecordTypes[] = { - "KMALLOC", - "VMALLOC", - "ALLOC_PAGES", - "IOREMAP", - "IO", - "KMEM_CACHE_ALLOC", -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - "VMAP" -#endif - }; - return apszDebugMemoryRecordTypes[eAllocType]; -} -#endif - - -static IMG_BOOL -AllocFlagsToPGProt(pgprot_t *pPGProtFlags, IMG_UINT32 ui32AllocFlags) -{ - pgprot_t PGProtFlags; - - switch (ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK) - { - case PVRSRV_HAP_CACHED: - PGProtFlags = PAGE_KERNEL; - break; - case PVRSRV_HAP_WRITECOMBINE: - PGProtFlags = PGPROT_WC(PAGE_KERNEL); - break; - case PVRSRV_HAP_UNCACHED: - PGProtFlags = PGPROT_UC(PAGE_KERNEL); - break; - default: - PVR_DPF((PVR_DBG_ERROR, - "%s: Unknown mapping flags=0x%08x", - __FUNCTION__, ui32AllocFlags)); - dump_stack(); - return IMG_FALSE; - } - - *pPGProtFlags = PGProtFlags; - - return IMG_TRUE; -} - -IMG_VOID * -_VMallocWrapper(IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32AllocFlags, - IMG_CHAR *pszFileName, - IMG_UINT32 ui32Line) -{ - pgprot_t PGProtFlags; - IMG_VOID *pvRet; - - if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags)) - { - return NULL; - } - - /* Allocate virtually contiguous pages */ - pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags); - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - if (pvRet) - { - DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC, - pvRet, - pvRet, - 0, - NULL, - PAGE_ALIGN(ui32Bytes), - pszFileName, - ui32Line - ); - } -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - - return pvRet; -} - - -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); -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - vfree(pvCpuVAddr); -} - - -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) -static IMG_VOID * -_VMapWrapper(struct page **ppsPageList, IMG_UINT32 ui32NumPages, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line) -{ - pgprot_t PGProtFlags; - IMG_VOID *pvRet; - - if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags)) - { - return NULL; - } - - pvRet = vmap(ppsPageList, ui32NumPages, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags); - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - if (pvRet) - { - DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMAP, - pvRet, - pvRet, - 0, - NULL, - PAGES_TO_BYTES(ui32NumPages), - pszFileName, - ui32Line - ); - } -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - - return pvRet; -} - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, __FILE__, __LINE__) -#else -#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, NULL, 0) -#endif - - -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); -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - vunmap(pvCpuVAddr); -} - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, __FILE__, __LINE__) -#else -#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, NULL, 0) -#endif - -#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */ - - -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); -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - - kmem_cache_free(psCache, pvObject); -} - - -const IMG_CHAR * -KMemCacheNameWrapper(LinuxKMemCache *psCache) -{ - PVR_UNREFERENCED_PARAMETER(psCache); - - /* In this case kmem_cache_t is an incomplete typedef, - * so we can't even de-reference to get the name member. It is also a GPL export symbol */ - return ""; -} - - -static LinuxPagePoolEntry * -LinuxPagePoolEntryAlloc(IMG_VOID) -{ - return KMemCacheAllocWrapper(g_PsLinuxPagePoolCache, GFP_KERNEL); -} - -static IMG_VOID -LinuxPagePoolEntryFree(LinuxPagePoolEntry *psPagePoolEntry) -{ - KMemCacheFreeWrapper(g_PsLinuxPagePoolCache, psPagePoolEntry); -} - - -static struct page * -AllocPageFromLinux(void) -{ - struct page *psPage; - - psPage = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 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)) - SetPageReserved(psPage); -#else - mem_map_reserve(psPage); -#endif -#endif - return psPage; -} - - -static IMG_VOID -FreePageToLinux(struct page *psPage) -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) - ClearPageReserved(psPage); -#else - mem_map_reserve(psPage); -#endif -#endif - __free_pages(psPage, 0); -} - - -#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) -static DEFINE_MUTEX(g_sPagePoolMutex); - -static inline void -PagePoolLock(void) -{ - mutex_lock(&g_sPagePoolMutex); -} - -static inline void -PagePoolUnlock(void) -{ - mutex_unlock(&g_sPagePoolMutex); -} - -static inline int -PagePoolTrylock(void) -{ - return mutex_trylock(&g_sPagePoolMutex); -} - -#else /* (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) */ -static inline void -PagePoolLock(void) -{ -} - -static inline void -PagePoolUnlock(void) -{ -} - -static inline int -PagePoolTrylock(void) -{ - return 1; -} -#endif /* (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) */ - - -static inline void -AddEntryToPool(LinuxPagePoolEntry *psPagePoolEntry) -{ - list_add_tail(&psPagePoolEntry->sPagePoolItem, &g_sPagePoolList); - atomic_inc(&g_sPagePoolEntryCount); -} - -static inline void -RemoveEntryFromPool(LinuxPagePoolEntry *psPagePoolEntry) -{ - list_del(&psPagePoolEntry->sPagePoolItem); - atomic_dec(&g_sPagePoolEntryCount); -} - -static inline LinuxPagePoolEntry * -RemoveFirstEntryFromPool(void) -{ - LinuxPagePoolEntry *psPagePoolEntry; - - if (list_empty(&g_sPagePoolList)) - { - PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0); - - return NULL; - } - - PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) > 0); - - psPagePoolEntry = list_first_entry(&g_sPagePoolList, LinuxPagePoolEntry, sPagePoolItem); - - RemoveEntryFromPool(psPagePoolEntry); - - return psPagePoolEntry; -} - -static struct page * -AllocPage(IMG_UINT32 ui32AreaFlags, IMG_BOOL *pbFromPagePool) -{ - struct page *psPage = NULL; - - /* - * Only uncached allocations can come from the page pool. - * The page pool is currently used to reduce the cost of - * invalidating the CPU cache when uncached memory is allocated. - */ - if (AreaIsUncached(ui32AreaFlags) && atomic_read(&g_sPagePoolEntryCount) != 0) - { - LinuxPagePoolEntry *psPagePoolEntry; - - PagePoolLock(); - psPagePoolEntry = RemoveFirstEntryFromPool(); - PagePoolUnlock(); - - /* List may have changed since we checked the counter */ - if (psPagePoolEntry) - { - psPage = psPagePoolEntry->psPage; - LinuxPagePoolEntryFree(psPagePoolEntry); - *pbFromPagePool = IMG_TRUE; - } - } - - if (!psPage) - { - psPage = AllocPageFromLinux(); - if (psPage) - { - *pbFromPagePool = IMG_FALSE; - } - } - - return psPage; - -} - -static IMG_VOID -FreePage(IMG_BOOL bToPagePool, struct page *psPage) -{ - /* Only uncached allocations can be freed to the page pool */ - if (bToPagePool && atomic_read(&g_sPagePoolEntryCount) < g_iPagePoolMaxEntries) - { - LinuxPagePoolEntry *psPagePoolEntry = LinuxPagePoolEntryAlloc(); - if (psPagePoolEntry) - { - psPagePoolEntry->psPage = psPage; - - PagePoolLock(); - AddEntryToPool(psPagePoolEntry); - PagePoolUnlock(); - - return; - } - } - - FreePageToLinux(psPage); -} - -static IMG_VOID -FreePagePool(IMG_VOID) -{ - LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry; - - 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))); -#else - PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0); - PVR_ASSERT(list_empty(&g_sPagePoolList)); -#endif - - list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem) - { - RemoveEntryFromPool(psPagePoolEntry); - - FreePageToLinux(psPagePoolEntry->psPage); - LinuxPagePoolEntryFree(psPagePoolEntry); - } - - PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0); - - PagePoolUnlock(); -} - -#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK) -#if defined(PVRSRV_NEED_PVR_ASSERT) -static struct shrinker g_sShrinker; -#endif - -static int -ShrinkPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl) -{ - unsigned long uNumToScan = psShrinkControl->nr_to_scan; - - PVR_ASSERT(psShrinker == &g_sShrinker); - (void)psShrinker; - - if (uNumToScan != 0) - { - 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))); - - if (!PagePoolTrylock()) - { - PVR_TRACE(("%s: Couldn't get page pool lock", __FUNCTION__)); - return -1; - } - - list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem) - { - RemoveEntryFromPool(psPagePoolEntry); - - FreePageToLinux(psPagePoolEntry->psPage); - LinuxPagePoolEntryFree(psPagePoolEntry); - - if (--uNumToScan == 0) - { - break; - } - } - - if (list_empty(&g_sPagePoolList)) - { - PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0); - } - - PagePoolUnlock(); - - PVR_DPF((PVR_DBG_MESSAGE,"%s: Pages in pool after scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount))); - } - - return atomic_read(&g_sPagePoolEntryCount); -} -#endif - -static IMG_BOOL -AllocPages(IMG_UINT32 ui32AreaFlags, struct page ***pppsPageList, IMG_HANDLE *phBlockPageList, IMG_UINT32 ui32NumPages, IMG_BOOL *pbFromPagePool) -{ - struct page **ppsPageList; - IMG_HANDLE hBlockPageList; - IMG_INT32 i; /* Must be signed; see "for" loop conditions */ - PVRSRV_ERROR eError; - IMG_BOOL bFromPagePool = IMG_FALSE; - - eError = OSAllocMem(0, sizeof(*ppsPageList) * ui32NumPages, (IMG_VOID **)&ppsPageList, &hBlockPageList, - "Array of pages"); - if (eError != PVRSRV_OK) - { - goto failed_page_list_alloc; - } - - *pbFromPagePool = IMG_TRUE; - for(i = 0; i < (IMG_INT32)ui32NumPages; i++) - { - ppsPageList[i] = AllocPage(ui32AreaFlags, &bFromPagePool); - if (!ppsPageList[i]) - { - goto failed_alloc_pages; - } - *pbFromPagePool &= bFromPagePool; - } - - *pppsPageList = ppsPageList; - *phBlockPageList = hBlockPageList; - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, - ppsPageList, - 0, - 0, - NULL, - PAGES_TO_BYTES(ui32NumPages), - "unknown", - 0 - ); -#endif - - return IMG_TRUE; - -failed_alloc_pages: - for(i--; i >= 0; i--) - { - FreePage(*pbFromPagePool, ppsPageList[i]); - } - (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList); - -failed_page_list_alloc: - return IMG_FALSE; -} - - -static IMG_VOID -FreePages(IMG_BOOL bToPagePool, struct page **ppsPageList, IMG_HANDLE hBlockPageList, IMG_UINT32 ui32NumPages) -{ - IMG_INT32 i; - - for(i = 0; i < (IMG_INT32)ui32NumPages; i++) - { - FreePage(bToPagePool, ppsPageList[i]); - } - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, ppsPageList, __FILE__, __LINE__); -#endif - - (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList); -} - - -LinuxMemArea * -NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags) -{ - LinuxMemArea *psLinuxMemArea = NULL; - IMG_VOID *pvCpuVAddr; -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - IMG_UINT32 ui32NumPages = 0; - struct page **ppsPageList = NULL; - IMG_HANDLE hBlockPageList; -#endif - IMG_BOOL bFromPagePool = IMG_FALSE; - - psLinuxMemArea = LinuxMemAreaStructAlloc(); - if (!psLinuxMemArea) - { - goto failed; - } - -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - ui32NumPages = RANGE_TO_PAGES(ui32Bytes); - - if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool)) - { - goto failed; - } - - pvCpuVAddr = VMapWrapper(ppsPageList, ui32NumPages, ui32AreaFlags); -#else /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */ - pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags); - if (!pvCpuVAddr) - { - goto failed; - } -/* 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); -#endif -#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */ - - psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC; - psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr; -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - psLinuxMemArea->uData.sVmalloc.ppsPageList = ppsPageList; - psLinuxMemArea->uData.sVmalloc.hBlockPageList = hBlockPageList; -#endif - psLinuxMemArea->ui32ByteSize = ui32Bytes; - psLinuxMemArea->ui32AreaFlags = ui32AreaFlags; - INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList); - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags); -#endif - - /* This works around a problem where Linux will not invalidate - * the cache for physical memory it frees that is direct mapped. - * - * As a result, cache entries remain that may be subsequently flushed - * to these physical pages after they have been allocated for another - * purpose. For a subsequent cached use of this memory, that is not a - * problem, but if we are allocating uncached or write-combined memory, - * and bypassing the cache, it can cause subsequent uncached writes to - * the memory to be replaced with junk from the cache. - * - * If the pages are from our page cache, no cache invalidate is needed. - * - * This just handles the __vmalloc() case (when we have a kernel virtual - * address range). The alloc_pages() path is handled in mmap.c. - */ - if (AreaIsUncached(ui32AreaFlags) && !bFromPagePool) - { - OSInvalidateCPUCacheRangeKM(psLinuxMemArea, 0, pvCpuVAddr, ui32Bytes); - } - - return psLinuxMemArea; - -failed: - PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__)); -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - if (ppsPageList) - { - FreePages(bFromPagePool, ppsPageList, hBlockPageList, ui32NumPages); - } -#endif - if (psLinuxMemArea) - { - LinuxMemAreaStructFree(psLinuxMemArea); - } - - return NULL; -} - - -IMG_VOID -FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea) -{ -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - IMG_UINT32 ui32NumPages; - struct page **ppsPageList; - IMG_HANDLE hBlockPageList; -#endif - - PVR_ASSERT(psLinuxMemArea); - PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC); - PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress); - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordRemove(psLinuxMemArea); -#endif - - PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p", - __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress)); - -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - VUnmapWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress); - - ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize); - ppsPageList = psLinuxMemArea->uData.sVmalloc.ppsPageList; - hBlockPageList = psLinuxMemArea->uData.sVmalloc.hBlockPageList; - - FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages); -#else -/* 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); -#endif - - VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress); -#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */ - - LinuxMemAreaStructFree(psLinuxMemArea); -} - - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) -/* 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) -{ - IMG_VOID *pvPage; - IMG_VOID *pvEnd = pvAddress + ui32Length; - - for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE) - { -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) - SetPageReserved(vmalloc_to_page(pvPage)); -#else - mem_map_reserve(vmalloc_to_page(pvPage)); -#endif - } -} - - -/* Un-reserve pages of memory in order that they can be freed. */ -static IMG_VOID -UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length) -{ - IMG_VOID *pvPage; - IMG_VOID *pvEnd = pvAddress + ui32Length; - - for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE) - { -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) - ClearPageReserved(vmalloc_to_page(pvPage)); -#else - mem_map_unreserve(vmalloc_to_page(pvPage)); -#endif - } -} -#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) */ - - -IMG_VOID * -_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr, - IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32MappingFlags, - IMG_CHAR *pszFileName, - IMG_UINT32 ui32Line) -{ - IMG_VOID *pvIORemapCookie; - - switch (ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK) - { - case PVRSRV_HAP_CACHED: - pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes); - break; - case PVRSRV_HAP_WRITECOMBINE: - pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes); - break; - case PVRSRV_HAP_UNCACHED: - pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes); - break; - default: - PVR_DPF((PVR_DBG_ERROR, "IORemapWrapper: unknown mapping flags")); - return NULL; - } - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - if (pvIORemapCookie) - { - DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP, - pvIORemapCookie, - pvIORemapCookie, - BasePAddr.uiAddr, - NULL, - ui32Bytes, - pszFileName, - ui32Line - ); - } -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - - return pvIORemapCookie; -} - - -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); -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - iounmap(pvIORemapCookie); -} - - -LinuxMemArea * -NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, - IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32AreaFlags) -{ - LinuxMemArea *psLinuxMemArea; - IMG_VOID *pvIORemapCookie; - - psLinuxMemArea = LinuxMemAreaStructAlloc(); - if (!psLinuxMemArea) - { - return NULL; - } - - pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags); - if (!pvIORemapCookie) - { - LinuxMemAreaStructFree(psLinuxMemArea); - return NULL; - } - - psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP; - psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie; - psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr; - psLinuxMemArea->ui32ByteSize = ui32Bytes; - psLinuxMemArea->ui32AreaFlags = ui32AreaFlags; - INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList); - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags); -#endif - - return psLinuxMemArea; -} - - -IMG_VOID -FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea) -{ - PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP); - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordRemove(psLinuxMemArea); -#endif - - IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie); - - LinuxMemAreaStructFree(psLinuxMemArea); -} - - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) -/* - * Avoid using remap_pfn_range on RAM, if possible. On x86 systems, with - * PAT enabled, remap_pfn_range checks the page attributes requested by - * remap_pfn_range against those of the direct kernel mapping for those - * pages (if any). This is rather annoying if the pages have been obtained - * with alloc_pages, where we just ask for raw pages; we don't care about - * the direct mapping. This latter issue arises when device memory is - * exported from one process to another. Services implements this - * 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) -{ - IMG_UINT32 ui32; - IMG_UINT32 ui32AddrChk; - IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes); - - /* - * If bPhysContig is IMG_TRUE, we must assume psSysPhysAddr points - * to the address of the first page, not an array of page addresses. - */ - for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr; - ui32 < ui32NumPages; - ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr) - { - if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk))) - { - break; - } - } - if (ui32 == ui32NumPages) - { - return IMG_FALSE; - } - - if (!bPhysContig) - { - for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr; - ui32 < ui32NumPages; - ui32++, ui32AddrChk += PAGE_SIZE) - { - if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk) - { - return IMG_FALSE; - } - } - } - - return IMG_TRUE; -} -#endif - -LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags) -{ - LinuxMemArea *psLinuxMemArea; - - psLinuxMemArea = LinuxMemAreaStructAlloc(); - if (!psLinuxMemArea) - { - return NULL; - } - - psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV; - psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr; - psLinuxMemArea->uData.sExternalKV.bPhysContig = -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - (bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, ui32Bytes, bPhysContig)) - ? IMG_TRUE : IMG_FALSE; -#else - bPhysContig; -#endif - if (psLinuxMemArea->uData.sExternalKV.bPhysContig) - { - psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr; - } - else - { - psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr; - } - psLinuxMemArea->ui32ByteSize = ui32Bytes; - psLinuxMemArea->ui32AreaFlags = ui32AreaFlags; - INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList); - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags); -#endif - - return psLinuxMemArea; -} - - -IMG_VOID -FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea) -{ - PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV); - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordRemove(psLinuxMemArea); -#endif - - LinuxMemAreaStructFree(psLinuxMemArea); -} - - -LinuxMemArea * -NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, - IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32AreaFlags) -{ - LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc(); - if (!psLinuxMemArea) - { - return NULL; - } - - /* 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->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, - NULL, - ui32Bytes, - "unknown", - 0 - ); -#endif - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags); -#endif - - return psLinuxMemArea; -} - - -IMG_VOID -FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea) -{ - PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO); - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordRemove(psLinuxMemArea); -#endif - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, - (IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__); -#endif - - /* Nothing more to do than free the LinuxMemArea struct */ - - LinuxMemAreaStructFree(psLinuxMemArea); -} - - -LinuxMemArea * -NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags) -{ - LinuxMemArea *psLinuxMemArea; - IMG_UINT32 ui32NumPages; - struct page **ppsPageList; - IMG_HANDLE hBlockPageList; - IMG_BOOL bFromPagePool; - - psLinuxMemArea = LinuxMemAreaStructAlloc(); - if (!psLinuxMemArea) - { - goto failed_area_alloc; - } - - ui32NumPages = RANGE_TO_PAGES(ui32Bytes); - - if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool)) - { - goto failed_alloc_pages; - } - - psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES; - psLinuxMemArea->uData.sPageList.ppsPageList = ppsPageList; - psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList; - psLinuxMemArea->ui32ByteSize = ui32Bytes; - 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) && !bFromPagePool; - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags); -#endif - - return psLinuxMemArea; - -failed_alloc_pages: - LinuxMemAreaStructFree(psLinuxMemArea); -failed_area_alloc: - PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__)); - - return NULL; -} - - -IMG_VOID -FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea) -{ - IMG_UINT32 ui32NumPages; - struct page **ppsPageList; - IMG_HANDLE hBlockPageList; - - PVR_ASSERT(psLinuxMemArea); - PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES); - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordRemove(psLinuxMemArea); -#endif - - ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize); - ppsPageList = psLinuxMemArea->uData.sPageList.ppsPageList; - hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList; - - FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages); - - 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_UINT32 ui32PageIndex; - IMG_CHAR *pui8Addr; - - switch (psLinuxMemArea->eAreaType) - { - case LINUX_MEM_AREA_ALLOC_PAGES: - ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset); - return psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageIndex]; - - case LINUX_MEM_AREA_VMALLOC: - pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress; - pui8Addr += ui32ByteOffset; - 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); - default: - PVR_DPF((PVR_DBG_ERROR, - "%s: Unsupported request for struct page from LinuxMemArea with type=%s", - __FUNCTION__, LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType))); - return NULL; - } -} - - -LinuxKMemCache * -KMemCacheCreateWrapper(IMG_CHAR *pszName, - size_t Size, - size_t Align, - IMG_UINT32 ui32Flags) -{ -#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS) - ui32Flags |= SLAB_POISON|SLAB_RED_ZONE; -#endif - return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) - , NULL -#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) */ - ); -} - - -IMG_VOID -KMemCacheDestroyWrapper(LinuxKMemCache *psCache) -{ - kmem_cache_destroy(psCache); -} - - -IMG_VOID * -_KMemCacheAllocWrapper(LinuxKMemCache *psCache, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)) - gfp_t Flags, -#else - IMG_INT Flags, -#endif - IMG_CHAR *pszFileName, - IMG_UINT32 ui32Line) -{ - IMG_VOID *pvRet; - - pvRet = kmem_cache_zalloc(psCache, Flags); - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, - pvRet, - pvRet, - 0, - psCache, - kmem_cache_size(psCache), - pszFileName, - ui32Line - ); -#else - PVR_UNREFERENCED_PARAMETER(pszFileName); - PVR_UNREFERENCED_PARAMETER(ui32Line); -#endif - - return pvRet; -} - - -LinuxMemArea * -NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea, - IMG_UINT32 ui32ByteOffset, - IMG_UINT32 ui32Bytes) -{ - LinuxMemArea *psLinuxMemArea; - - PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize); - - psLinuxMemArea = LinuxMemAreaStructAlloc(); - if (!psLinuxMemArea) - { - return NULL; - } - - psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC; - psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea = psParentLinuxMemArea; - psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset; - psLinuxMemArea->ui32ByteSize = ui32Bytes; - psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags; - psLinuxMemArea->bNeedsCacheInvalidate = psParentLinuxMemArea->bNeedsCacheInvalidate; - INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList); - -#if defined(DEBUG_LINUX_MEM_AREAS) - { - DEBUG_LINUX_MEM_AREA_REC *psParentRecord; - psParentRecord = DebugLinuxMemAreaRecordFind(psParentLinuxMemArea); - DebugLinuxMemAreaRecordAdd(psLinuxMemArea, psParentRecord->ui32Flags); - } -#endif - - return psLinuxMemArea; -} - - -static IMG_VOID -FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea) -{ - PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC); - -#if defined(DEBUG_LINUX_MEM_AREAS) - DebugLinuxMemAreaRecordRemove(psLinuxMemArea); -#endif - - /* Nothing more to do than free the LinuxMemArea structure */ - - LinuxMemAreaStructFree(psLinuxMemArea); -} - - -static LinuxMemArea * -LinuxMemAreaStructAlloc(IMG_VOID) -{ -/* debug */ -#if 0 - LinuxMemArea *psLinuxMemArea; - psLinuxMemArea = kmem_cache_alloc(g_PsLinuxMemAreaCache, GFP_KERNEL); - printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea); - dump_stack(); - return psLinuxMemArea; -#else - return KMemCacheAllocWrapper(g_PsLinuxMemAreaCache, GFP_KERNEL); -#endif -} - - -static IMG_VOID -LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea) -{ - KMemCacheFreeWrapper(g_PsLinuxMemAreaCache, psLinuxMemArea); - /* debug */ - //printk(KERN_ERR "%s(%p)\n", __FUNCTION__, psLinuxMemArea); -} - - -IMG_VOID -LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea) -{ - switch (psLinuxMemArea->eAreaType) - { - case LINUX_MEM_AREA_VMALLOC: - FreeVMallocLinuxMemArea(psLinuxMemArea); - break; - case LINUX_MEM_AREA_ALLOC_PAGES: - FreeAllocPagesLinuxMemArea(psLinuxMemArea); - break; - case LINUX_MEM_AREA_IOREMAP: - FreeIORemapLinuxMemArea(psLinuxMemArea); - break; - case LINUX_MEM_AREA_EXTERNAL_KV: - FreeExternalKVLinuxMemArea(psLinuxMemArea); - break; - case LINUX_MEM_AREA_IO: - FreeIOLinuxMemArea(psLinuxMemArea); - break; - 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)); - break; - } -} - - -#if defined(DEBUG_LINUX_MEM_AREAS) -static IMG_VOID -DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags) -{ - DEBUG_LINUX_MEM_AREA_REC *psNewRecord; - const IMG_CHAR *pi8FlagsString; - - LinuxLockMutex(&g_sDebugMutex); - - if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) - { - g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize; - if (g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark) - { - g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark; - } - } - g_LinuxMemAreaCount++; - - /* Create a new memory allocation record */ - psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL); - if (psNewRecord) - { - /* Record the allocation */ - psNewRecord->psLinuxMemArea = psLinuxMemArea; - psNewRecord->ui32Flags = ui32Flags; - psNewRecord->pid = OSGetCurrentProcessIDKM(); - - List_DEBUG_LINUX_MEM_AREA_REC_Insert(&g_LinuxMemAreaRecords, psNewRecord); - } - else - { - PVR_DPF((PVR_DBG_ERROR, - "%s: failed to allocate linux memory area record.", - __FUNCTION__)); - } - - /* Sanity check the flags */ - pi8FlagsString = HAPFlagsToString(ui32Flags); - if (strstr(pi8FlagsString, "UNKNOWN")) - { - PVR_DPF((PVR_DBG_ERROR, - "%s: Unexpected flags (0x%08x) associated with psLinuxMemArea @ %p", - __FUNCTION__, - ui32Flags, - psLinuxMemArea)); - //dump_stack(); - } - - LinuxUnLockMutex(&g_sDebugMutex); -} - - - -static IMG_VOID* MatchLinuxMemArea_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord, - va_list va) -{ - LinuxMemArea *psLinuxMemArea; - - psLinuxMemArea = va_arg(va, LinuxMemArea*); - if (psCurrentRecord->psLinuxMemArea == psLinuxMemArea) - { - return psCurrentRecord; - } - else - { - return IMG_NULL; - } -} - - -static DEBUG_LINUX_MEM_AREA_REC * -DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea) -{ - DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord; - - LinuxLockMutex(&g_sDebugMutex); - psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords, - MatchLinuxMemArea_AnyVaCb, - psLinuxMemArea); - -/*exit_unlock:*/ - LinuxUnLockMutex(&g_sDebugMutex); - - return psCurrentRecord; -} - - -static IMG_VOID -DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea) -{ - DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord; - - LinuxLockMutex(&g_sDebugMutex); - - if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) - { - g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize; - } - g_LinuxMemAreaCount--; - - /* Locate the corresponding allocation entry */ - psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords, - MatchLinuxMemArea_AnyVaCb, - psLinuxMemArea); - if (psCurrentRecord) - { - /* Unlink the allocation record */ - List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord); - kfree(psCurrentRecord); - } - else - { - PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for psLinuxMemArea=%p\n", - __FUNCTION__, psLinuxMemArea)); - } - - LinuxUnLockMutex(&g_sDebugMutex); -} -#endif - - -IMG_VOID * -LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea) -{ - switch (psLinuxMemArea->eAreaType) - { - case LINUX_MEM_AREA_VMALLOC: - return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress; - case LINUX_MEM_AREA_IOREMAP: - return psLinuxMemArea->uData.sIORemap.pvIORemapCookie; - case LINUX_MEM_AREA_EXTERNAL_KV: - return psLinuxMemArea->uData.sExternalKV.pvExternalKV; - case LINUX_MEM_AREA_SUB_ALLOC: - { - IMG_CHAR *pAddr = - LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea); /* PRQA S 3670 */ /* ignore recursive warning */ - if (!pAddr) - { - return NULL; - } - return pAddr + psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset; - } - default: - return NULL; - } -} - - -IMG_CPU_PHYADDR -LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset) -{ - IMG_CPU_PHYADDR CpuPAddr; - - CpuPAddr.uiAddr = 0; - - switch (psLinuxMemArea->eAreaType) - { - case LINUX_MEM_AREA_IOREMAP: - { - CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr; - CpuPAddr.uiAddr += ui32ByteOffset; - break; - } - case LINUX_MEM_AREA_EXTERNAL_KV: - { - if (psLinuxMemArea->uData.sExternalKV.bPhysContig) - { - CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr); - CpuPAddr.uiAddr += ui32ByteOffset; - } - else - { - IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset); - IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageIndex]; - - CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr); - CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset); - } - break; - } - case LINUX_MEM_AREA_IO: - { - CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr; - CpuPAddr.uiAddr += ui32ByteOffset; - break; - } - case LINUX_MEM_AREA_VMALLOC: - { - IMG_CHAR *pCpuVAddr; - pCpuVAddr = - (IMG_CHAR *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress; - pCpuVAddr += ui32ByteOffset; - 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]; - CpuPAddr.uiAddr = page_to_phys(page); - CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset); - break; - } - case LINUX_MEM_AREA_SUB_ALLOC: - { - CpuPAddr = - OSMemHandleToCpuPAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea, - psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset - + ui32ByteOffset); - break; - } - default: - { - PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n", - __FUNCTION__, psLinuxMemArea->eAreaType)); - PVR_ASSERT(CpuPAddr.uiAddr); - break; - } - } - - return CpuPAddr; -} - - -IMG_BOOL -LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea) -{ - switch (psLinuxMemArea->eAreaType) - { - case LINUX_MEM_AREA_IOREMAP: - case LINUX_MEM_AREA_IO: - return IMG_TRUE; - - 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; - - case LINUX_MEM_AREA_SUB_ALLOC: - /* PRQA S 3670 1 */ /* ignore recursive warning */ - return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea); - - default: - PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n", - __FUNCTION__, psLinuxMemArea->eAreaType)); - break; - } - return IMG_FALSE; -} - - -const IMG_CHAR * -LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType) -{ - /* Note we explicitly check the types instead of e.g. - * using the type to index an array of strings so - * we remain orthogonal to enum changes */ - switch (eMemAreaType) - { - case LINUX_MEM_AREA_IOREMAP: - return "LINUX_MEM_AREA_IOREMAP"; - case LINUX_MEM_AREA_EXTERNAL_KV: - return "LINUX_MEM_AREA_EXTERNAL_KV"; - case LINUX_MEM_AREA_IO: - return "LINUX_MEM_AREA_IO"; - case LINUX_MEM_AREA_VMALLOC: - return "LINUX_MEM_AREA_VMALLOC"; - case LINUX_MEM_AREA_SUB_ALLOC: - 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); - } - - return ""; -} - - -#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start) -{ - if (start) - { - LinuxLockMutex(&g_sDebugMutex); - } - else - { - LinuxUnLockMutex(&g_sDebugMutex); - } -} -#endif /* defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) */ - -#if defined(DEBUG_LINUX_MEM_AREAS) - -static IMG_VOID* DecOffMemAreaRec_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psNode, va_list va) -{ - off_t *pOff = va_arg(va, off_t*); - if (--(*pOff)) - { - return IMG_NULL; - } - else - { - return psNode; - } -} - -/* seq_file version of generating output, for reference check proc.c:CreateProcReadEntrySeq */ -static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off) -{ - DEBUG_LINUX_MEM_AREA_REC *psRecord; - psRecord = (DEBUG_LINUX_MEM_AREA_REC*) - List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords, - DecOffMemAreaRec_AnyVaCb, - &off); - return (void*)psRecord; -} - -static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off) -{ - DEBUG_LINUX_MEM_AREA_REC *psRecord; - if (!off) - { - return PVR_PROC_SEQ_START_TOKEN; - } - - psRecord = (DEBUG_LINUX_MEM_AREA_REC*) - List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords, - DecOffMemAreaRec_AnyVaCb, - &off); - return (void*)psRecord; -} - - -static void ProcSeqShowMemArea(struct seq_file *sfile,void* el) -{ - DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el; - if (el == PVR_PROC_SEQ_START_TOKEN) - { - -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - seq_printf(sfile, - "Number of Linux Memory Areas: %u\n" - "At the current water mark these areas correspond to %u bytes (excluding SUB areas)\n" - "At the highest water mark these areas corresponded to %u bytes (excluding SUB areas)\n" - "\nDetails for all Linux Memory Areas:\n" - "%s %-24s %s %s %-8s %-5s %s\n", - g_LinuxMemAreaCount, - g_LinuxMemAreaWaterMark, - g_LinuxMemAreaHighWaterMark, - "psLinuxMemArea", - "LinuxMemType", - "CpuVAddr", - "CpuPAddr", - "Bytes", - "Pid", - "Flags" - ); -#else - seq_printf(sfile, - "<mem_areas_header>\n" - "\t<count>%u</count>\n" - "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n" /* (excluding SUB areas) */ - "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n" /* (excluding SUB areas) */ - "</mem_areas_header>\n", - g_LinuxMemAreaCount, - g_LinuxMemAreaWaterMark, - g_LinuxMemAreaHighWaterMark - ); -#endif - return; - } - - seq_printf(sfile, -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - "%8p %-24s %8p %08x %-8d %-5u %08x=(%s)\n", -#else - "<linux_mem_area>\n" - "\t<pointer>%8p</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<pid>%u</pid>\n" - "\t<flags>%08x</flags>\n" - "\t<flags_string>%s</flags_string>\n" - "</linux_mem_area>\n", -#endif - psRecord->psLinuxMemArea, - LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType), - LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea), - LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr, - psRecord->psLinuxMemArea->ui32ByteSize, - psRecord->pid, - psRecord->ui32Flags, - HAPFlagsToString(psRecord->ui32Flags) - ); - -} - -#endif /* DEBUG_LINUX_MEM_AREAS */ - - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - -static IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list va) -{ - off_t *pOff = va_arg(va, off_t*); - if (--(*pOff)) - { - return IMG_NULL; - } - else - { - return psNode; - } -} - - -/* seq_file version of generating output, for reference check proc.c:CreateProcReadEntrySeq */ -static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off) -{ - DEBUG_MEM_ALLOC_REC *psRecord; - psRecord = (DEBUG_MEM_ALLOC_REC*) - List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords, - DecOffMemAllocRec_AnyVaCb, - &off); -#if defined(DEBUG_LINUX_XML_PROC_FILES) - if (!psRecord) - { - seq_printf(sfile, "</meminfo>\n"); - } -#endif - - return (void*)psRecord; -} - -static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off) -{ - DEBUG_MEM_ALLOC_REC *psRecord; - if (!off) - { - return PVR_PROC_SEQ_START_TOKEN; - } - - psRecord = (DEBUG_MEM_ALLOC_REC*) - List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords, - DecOffMemAllocRec_AnyVaCb, - &off); - -#if defined(DEBUG_LINUX_XML_PROC_FILES) - if (!psRecord) - { - seq_printf(sfile, "</meminfo>\n"); - } -#endif - - return (void*)psRecord; -} - -static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el) -{ - DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el; - if (el == PVR_PROC_SEQ_START_TOKEN) - { -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - /* NOTE: If you update this code, please also update the XML varient below - * too! */ - - seq_printf(sfile, "%-60s: %d bytes\n", - "Current Water Mark of bytes allocated via kmalloc", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Highest Water Mark of bytes allocated via kmalloc", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Current Water Mark of bytes allocated via vmalloc", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Highest Water Mark of bytes allocated via vmalloc", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Current Water Mark of bytes allocated via alloc_pages", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Highest Water Mark of bytes allocated via alloc_pages", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Current Water Mark of bytes allocated via ioremap", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Highest Water Mark of bytes allocated via ioremap", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Current Water Mark of bytes reserved for \"IO\" memory areas", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Highest Water Mark of bytes allocated for \"IO\" memory areas", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Current Water Mark of bytes allocated via kmem_cache_alloc", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Highest Water Mark of bytes allocated via kmem_cache_alloc", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]); -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - seq_printf(sfile, "%-60s: %d bytes\n", - "Current Water Mark of bytes mapped via vmap", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]); - seq_printf(sfile, "%-60s: %d bytes\n", - "Highest Water Mark of bytes mapped via vmap", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]); -#endif -#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) - seq_printf(sfile, "%-60s: %d pages\n", - "Number of pages in page pool", - atomic_read(&g_sPagePoolEntryCount)); -#endif - seq_printf( sfile, "\n"); - seq_printf(sfile, "%-60s: %d bytes\n", - "The Current Water Mark for memory allocated from system RAM", - SysRAMTrueWaterMark()); - seq_printf(sfile, "%-60s: %d bytes\n", - "The Highest Water Mark for memory allocated from system RAM", - g_SysRAMHighWaterMark); - seq_printf(sfile, "%-60s: %d bytes\n", - "The Current Water Mark for memory allocated from IO memory", - g_IOMemWaterMark); - seq_printf(sfile, "%-60s: %d bytes\n", - "The Highest Water Mark for memory allocated from IO memory", - g_IOMemHighWaterMark); - - seq_printf( sfile, "\n"); - - seq_printf(sfile, "Details for all known allocations:\n" - "%-16s %-8s %-8s %-10s %-5s %-10s %s\n", - "Type", - "CpuVAddr", - "CpuPAddr", - "Bytes", - "PID", - "PrivateData", - "Filename:Line"); - -#else /* DEBUG_LINUX_XML_PROC_FILES */ - - /* Note: If you want to update the description property of a watermark - * ensure that the key property remains unchanged so that watermark data - * logged over time from different driver revisions may remain comparable - */ - seq_printf(sfile, "<meminfo>\n<meminfo_header>\n"); - seq_printf(sfile, - "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%d\"/>\n", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]); - seq_printf(sfile, - "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%d\"/>\n", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]); - seq_printf(sfile, - "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%d\"/>\n", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]); - seq_printf(sfile, - "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%d\"/>\n", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]); - seq_printf(sfile, - "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%d\"/>\n", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]); - seq_printf(sfile, - "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%d\"/>\n", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]); - seq_printf(sfile, - "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%d\"/>\n", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]); - seq_printf(sfile, - "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%d\"/>\n", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]); - seq_printf(sfile, - "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%d\"/>\n", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]); - seq_printf(sfile, - "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%d\"/>\n", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]); - seq_printf(sfile, - "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%d\"/>\n", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]); - seq_printf(sfile, - "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%d\"/>\n", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]); -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - seq_printf(sfile, - "<watermark key=\"mr12\" description=\"vmap_current\" bytes=\"%d\"/>\n", - g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]); - seq_printf(sfile, - "<watermark key=\"mr13\" description=\"vmap_high\" bytes=\"%d\"/>\n", - g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]); -#endif - seq_printf(sfile, - "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%d\"/>\n", - SysRAMTrueWaterMark()); - seq_printf(sfile, - "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%d\"/>\n", - g_SysRAMHighWaterMark); - seq_printf(sfile, - "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%d\"/>\n", - g_IOMemWaterMark); - seq_printf(sfile, - "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%d\"/>\n", - g_IOMemHighWaterMark); - -#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) - seq_printf(sfile, - "<watermark key=\"mr18\" description=\"page_pool_current\" bytes=\"%d\"/>\n", - PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount))); -#endif - seq_printf(sfile, "</meminfo_header>\n"); - -#endif /* DEBUG_LINUX_XML_PROC_FILES */ - return; - } - - if (psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE) - { - seq_printf(sfile, -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - "%-16s %-8p %08x %-10d %-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<pid>%d</pid>\n" - "\t<private>%s</private>\n" - "\t<filename>%s</filename>\n" - "\t<line>%d</line>\n" - "</allocation>\n", -#endif - DebugMemAllocRecordTypeToString(psRecord->eAllocType), - psRecord->pvCpuVAddr, - psRecord->ulCpuPAddr, - psRecord->ui32Bytes, - psRecord->pid, - "NULL", - psRecord->pszFileName, - psRecord->ui32Line); - } - else - { - seq_printf(sfile, -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - "%-16s %-8p %08x %-10d %-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<pid>%d</pid>\n" - "\t<private>%s</private>\n" - "\t<filename>%s</filename>\n" - "\t<line>%d</line>\n" - "</allocation>\n", -#endif - DebugMemAllocRecordTypeToString(psRecord->eAllocType), - psRecord->pvCpuVAddr, - psRecord->ulCpuPAddr, - psRecord->ui32Bytes, - psRecord->pid, - KMemCacheNameWrapper(psRecord->pvPrivateData), - psRecord->pszFileName, - psRecord->ui32Line); - } -} - -#endif /* defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) */ - - -#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS) -/* This could be moved somewhere more general */ -const IMG_CHAR * -HAPFlagsToString(IMG_UINT32 ui32Flags) -{ - static IMG_CHAR szFlags[50]; - IMG_INT32 i32Pos = 0; - IMG_UINT32 ui32CacheTypeIndex, ui32MapTypeIndex; - IMG_CHAR *apszCacheTypes[] = { - "UNCACHED", - "CACHED", - "WRITECOMBINE", - "UNKNOWN" - }; - IMG_CHAR *apszMapType[] = { - "KERNEL_ONLY", - "SINGLE_PROCESS", - "MULTI_PROCESS", - "FROM_EXISTING_PROCESS", - "NO_CPU_VIRTUAL", - "UNKNOWN" - }; - - /* FIXME create an enum for the cache type that we can - * cast and select so we get compiler warnings when - * when this code isn't complete due to new flags */ - if (ui32Flags & PVRSRV_HAP_UNCACHED) { - ui32CacheTypeIndex = 0; - } else if (ui32Flags & PVRSRV_HAP_CACHED) { - ui32CacheTypeIndex = 1; - } else if (ui32Flags & PVRSRV_HAP_WRITECOMBINE) { - ui32CacheTypeIndex = 2; - } else { - ui32CacheTypeIndex = 3; - PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)", - __FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK))); - } - - /* FIXME create an enum for the map type that we can - * cast and select so we get compiler warnings when - * when this code isn't complete due to new flags */ - if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY) { - ui32MapTypeIndex = 0; - } else if (ui32Flags & PVRSRV_HAP_SINGLE_PROCESS) { - ui32MapTypeIndex = 1; - } else if (ui32Flags & PVRSRV_HAP_MULTI_PROCESS) { - ui32MapTypeIndex = 2; - } else if (ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS) { - ui32MapTypeIndex = 3; - } else if (ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL) { - ui32MapTypeIndex = 4; - } else { - ui32MapTypeIndex = 5; - PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)", - __FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK))); - } - - i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]); - if (i32Pos <= 0) - { - PVR_DPF((PVR_DBG_ERROR, "%s: sprintf for cache type %u failed (%d)", - __FUNCTION__, ui32CacheTypeIndex, i32Pos)); - szFlags[0] = 0; - } - else - { - sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]); - } - - return szFlags; -} -#endif - -#if defined(DEBUG_LINUX_MEM_AREAS) -static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord) -{ - LinuxMemArea *psLinuxMemArea; - - psLinuxMemArea = psCurrentRecord->psLinuxMemArea; - PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes", - __FUNCTION__, - psCurrentRecord->psLinuxMemArea, - LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType), - psCurrentRecord->psLinuxMemArea->ui32ByteSize)); - /* 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); -} -#endif - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord) - -{ - -/* It's a bug if anything remains allocated at this point. We - * report an error, and simply brute force free anything we find. */ - PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: " - "type=%s " - "CpuVAddr=%p " - "CpuPAddr=0x%08x, " - "allocated @ file=%s,line=%d", - __FUNCTION__, - DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType), - psCurrentRecord->pvCpuVAddr, - psCurrentRecord->ulCpuPAddr, - psCurrentRecord->pszFileName, - psCurrentRecord->ui32Line)); - switch (psCurrentRecord->eAllocType) - { - case DEBUG_MEM_ALLOC_TYPE_KMALLOC: - KFreeWrapper(psCurrentRecord->pvCpuVAddr); - break; - case DEBUG_MEM_ALLOC_TYPE_IOREMAP: - IOUnmapWrapper(psCurrentRecord->pvCpuVAddr); - break; - case DEBUG_MEM_ALLOC_TYPE_IO: - /* Nothing needed except to free the record */ - DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __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__); - break; - case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE: - KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr); - break; -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - case DEBUG_MEM_ALLOC_TYPE_VMAP: - VUnmapWrapper(psCurrentRecord->pvCpuVAddr); - break; -#endif - default: - PVR_ASSERT(0); - } -} -#endif - - -#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK) -static struct shrinker g_sShrinker = -{ - .shrink = ShrinkPagePool, - .seeks = DEFAULT_SEEKS -}; - -static IMG_BOOL g_bShrinkerRegistered; -#endif - -IMG_VOID -LinuxMMCleanup(IMG_VOID) -{ -#if defined(DEBUG_LINUX_MEM_AREAS) - { - if (g_LinuxMemAreaCount) - { - PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)", - __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark)); - } - - List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords, LinuxMMCleanup_MemAreas_ForEachCb); - - if (g_SeqFileMemArea) - { - RemoveProcEntrySeq(g_SeqFileMemArea); - } - } -#endif - -#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK) - if (g_bShrinkerRegistered) - { - unregister_shrinker(&g_sShrinker); - } -#endif - - /* - * The page pool must be freed after any remaining mem areas, but before - * the remaining memory resources. - */ - FreePagePool(); - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - { - - /* - * It's a bug if anything remains allocated at this point. We - * report an error, and simply brute force free anything we find. - */ - List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords, LinuxMMCleanup_MemRecords_ForEachVa); - - if (g_SeqFileMemoryRecords) - { - RemoveProcEntrySeq(g_SeqFileMemoryRecords); - } - } -#endif - - if (g_PsLinuxMemAreaCache) - { - KMemCacheDestroyWrapper(g_PsLinuxMemAreaCache); - } - - if (g_PsLinuxPagePoolCache) - { - KMemCacheDestroyWrapper(g_PsLinuxPagePoolCache); - } -} - -PVRSRV_ERROR -LinuxMMInit(IMG_VOID) -{ -#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - LinuxInitMutex(&g_sDebugMutex); -#endif - -#if defined(DEBUG_LINUX_MEM_AREAS) - { - g_SeqFileMemArea = CreateProcReadEntrySeq( - "mem_areas", - NULL, - ProcSeqNextMemArea, - ProcSeqShowMemArea, - ProcSeqOff2ElementMemArea, - ProcSeqStartstopDebugMutex - ); - if (!g_SeqFileMemArea) - { - goto failed; - } - } -#endif - - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - { - g_SeqFileMemoryRecords = CreateProcReadEntrySeq( - "meminfo", - NULL, - ProcSeqNextMemoryRecords, - ProcSeqShowMemoryRecords, - ProcSeqOff2ElementMemoryRecords, - ProcSeqStartstopDebugMutex - ); - if (!g_SeqFileMemoryRecords) - { - goto failed; - } - } -#endif - - g_PsLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0); - if (!g_PsLinuxMemAreaCache) - { - PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate mem area kmem_cache", __FUNCTION__)); - goto failed; - } - -#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) - g_iPagePoolMaxEntries = PVR_LINUX_MEM_AREA_POOL_MAX_PAGES; - if (g_iPagePoolMaxEntries <= 0 || g_iPagePoolMaxEntries > INT_MAX/2) - { - g_iPagePoolMaxEntries = INT_MAX/2; - PVR_TRACE(("%s: No limit set for page pool size", __FUNCTION__)); - } - else - { - PVR_TRACE(("%s: Maximum page pool size: %d", __FUNCTION__, g_iPagePoolMaxEntries)); - } - - g_PsLinuxPagePoolCache = KMemCacheCreateWrapper("img-mm-pool", sizeof(LinuxPagePoolEntry), 0, 0); - if (!g_PsLinuxPagePoolCache) - { - PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate page pool kmem_cache", __FUNCTION__)); - goto failed; - } -#endif - -#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK) - register_shrinker(&g_sShrinker); - g_bShrinkerRegistered = IMG_TRUE; -#endif - - return PVRSRV_OK; - -failed: - LinuxMMCleanup(); - return PVRSRV_ERROR_OUT_OF_MEMORY; -} - diff --git a/pvr-source/services4/srvkm/env/linux/mm.h b/pvr-source/services4/srvkm/env/linux/mm.h deleted file mode 100755 index 5c01322..0000000 --- a/pvr-source/services4/srvkm/env/linux/mm.h +++ /dev/null @@ -1,751 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux Memory Management. -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Declares various memory management utility functions - for Linux. -@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 __IMG_LINUX_MM_H__ -#define __IMG_LINUX_MM_H__ - -#include <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/list.h> - -#include <asm/io.h> - -#define PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT) -#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT) - -#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT) - -#define ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1)) - -#define PAGES_TO_BYTES(pages) ((pages) << PAGE_SHIFT) - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)) -#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_pfn_range(vma, addr, pfn, size, prot) -#else -#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) -#define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_pfn_range(vma, addr, pfn, size, prot) -#else -#define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) -#define VM_INSERT_PAGE(vma, addr, page) vm_insert_page(vma, addr, page) -#else -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)) -#define VM_INSERT_PAGE(vma, addr, page) remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, vma->vm_page_prot); -#else -#define VM_INSERT_PAGE(vma, addr, page) remap_page_range(vma, addr, page_to_phys(page), PAGE_SIZE, vma->vm_page_prot); -#endif -#endif - -static inline IMG_UINT32 VMallocToPhys(IMG_VOID *pCpuVAddr) -{ - return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr)); - -} - -typedef enum { - LINUX_MEM_AREA_IOREMAP, - LINUX_MEM_AREA_EXTERNAL_KV, - LINUX_MEM_AREA_IO, - 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 - LINUX_MEM_AREA_TYPE_COUNT -}LINUX_MEM_AREA_TYPE; - -typedef struct _LinuxMemArea LinuxMemArea; - - -/* FIXME - describe this structure. */ -struct _LinuxMemArea { - LINUX_MEM_AREA_TYPE eAreaType; - union _uData - { - struct _sIORemap - { - /* Note: The memory this represents is _not_ implicitly - * page aligned, neither is its size */ - IMG_CPU_PHYADDR CPUPhysAddr; - IMG_VOID *pvIORemapCookie; - }sIORemap; - struct _sExternalKV - { - /* Note: The memory this represents is _not_ implicitly - * page aligned, neither is its size */ - IMG_BOOL bPhysContig; - union { - /* - * SYSPhysAddr is valid if bPhysContig is true, else - * pSysPhysAddr is valid - */ - IMG_SYS_PHYADDR SysPhysAddr; - IMG_SYS_PHYADDR *pSysPhysAddr; - } uPhysAddr; - IMG_VOID *pvExternalKV; - }sExternalKV; - struct _sIO - { - /* Note: The memory this represents is _not_ implicitly - * page aligned, neither is its size */ - IMG_CPU_PHYADDR CPUPhysAddr; - }sIO; - struct _sVmalloc - { - /* Note the memory this represents _is_ implicitly - * page aligned _and_ so is its size */ - IMG_VOID *pvVmallocAddress; -#if defined(PVR_LINUX_MEM_AREA_USE_VMAP) - struct page **ppsPageList; - IMG_HANDLE hBlockPageList; -#endif - }sVmalloc; - struct _sPageList - { - /* Note the memory this represents _is_ implicitly - * page aligned _and_ so is its size */ - 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; - }sSubAlloc; - }uData; - - IMG_UINT32 ui32ByteSize; /* Size of memory area */ - - IMG_UINT32 ui32AreaFlags; /* Flags passed at creation time */ - - IMG_BOOL bMMapRegistered; /* Registered with mmap code */ - - IMG_BOOL bNeedsCacheInvalidate; /* Cache should be invalidated on first map? */ - - IMG_HANDLE hBMHandle; /* Handle back to BM for this allocation */ - - /* List entry for global list of areas registered for mmap */ - struct list_head sMMapItem; - - /* - * Head of list of all mmap offset structures associated with this - * memory area. - */ - struct list_head sMMapOffsetStructList; -}; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)) -typedef kmem_cache_t LinuxKMemCache; -#else -typedef struct kmem_cache LinuxKMemCache; -#endif - - -/*! - ******************************************************************************* - * @Function LinuxMMInit - * - * @Description - * - * Initialise linux memory management code. - * This should be called during services initialisation. - * - * @Return none -******************************************************************************/ -PVRSRV_ERROR LinuxMMInit(IMG_VOID); - - -/*! - ******************************************************************************* - * - * @Function LinuxMMCleanup - * - * @Description - * - * Cleanup state for the linux memory management code. - * This should be called at services cleanup. - * - * @Return none -******************************************************************************/ -IMG_VOID LinuxMMCleanup(IMG_VOID); - - -/*! - ******************************************************************************* - * @brief Wrappers for kmalloc/kfree with optional /proc/pvr/km tracking - * They can also be used as more concise replacements for OSAllocMem - * in Linux specific code. - * - * @param ui32ByteSize - * - * @return - ******************************************************************************/ -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define KMallocWrapper(ui32ByteSize, uFlags) _KMallocWrapper(ui32ByteSize, uFlags, __FILE__, __LINE__) -#else -#define KMallocWrapper(ui32ByteSize, uFlags) _KMallocWrapper(ui32ByteSize, uFlags, NULL, 0) -#endif -IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *szFileName, IMG_UINT32 ui32Line); - - -/*! - ******************************************************************************* - * @brief - * - * @param pvCpuVAddr - * - * @return - ******************************************************************************/ -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__) -#else -#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, NULL, 0) -#endif -IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line); - - -/*! - ******************************************************************************* - * @brief - * - * @param ui32Bytes - * @param ui32AllocFlags - * - * @return - ******************************************************************************/ -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__) -#else -#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, NULL, 0) -#endif -IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line); - - -/*! - ******************************************************************************* - * @brief - * - * @param pvCpuVAddr - * - * @return - ******************************************************************************/ -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__) -#else -#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, NULL, 0) -#endif -IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line); - - -/*! - ******************************************************************************* - * @brief Allocates virtually contiguous pages - * - * @param ui32Bytes 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); - - -/*! - ******************************************************************************* - * @brief Deallocates virtually contiguous pages - * - * @param LinuxMemArea from NewVMallocLinuxMemArea - * - ******************************************************************************/ -IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea); - - -/*! - ******************************************************************************* - * @brief Reserve physical IO memory and create a CPU virtual mapping for it - * - * @param BasePAddr - * @param ui32Bytes - * @param ui32MappingFlags - * - * @return - ******************************************************************************/ -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \ - _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__) -#else -#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \ - _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0) -#endif -IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr, - IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32MappingFlags, - IMG_CHAR *pszFileName, - IMG_UINT32 ui32Line); - - -/*! - ******************************************************************************* - * @brief Reserve physical IO memory and create a CPU virtual mapping for it - * - * @param BasePAddr - * @param ui32Bytes - * @param ui32AreaFlags Heap caching and mapping Flags - * - * @return - ******************************************************************************/ -LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags); - - -/*! - ******************************************************************************* - * @brief - * - * @param psLinuxMemArea - * - * @return - ********************************************************************************/ -IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea); - -/*! - ******************************************************************************* - * @brief Register physical memory which already has a CPU virtual mapping - * - * @param pBasePAddr - * @param pvCPUVAddr - * @param bPhysContig - * @param ui32Bytes - * @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); - - -/*! - ******************************************************************************* - * @brief - * - * @param psLinuxMemArea - * - * @return - ******************************************************************************/ -IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea); - - -/*! - ****************************************************************************** - * @brief Unmaps an IO memory mapping created using IORemap - * - * @param pvIORemapCookie - * - * @return - ******************************************************************************/ -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define IOUnmapWrapper(pvIORemapCookie) \ - _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__) -#else -#define IOUnmapWrapper(pvIORemapCookie) \ - _IOUnmapWrapper(pvIORemapCookie, NULL, 0) -#endif -IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line); - - -/*! - ******************************************************************************* - * @brief - * - * @param psLinuxMemArea - * @param ui32ByteOffset - * - * @return - ******************************************************************************/ -struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset); - - -/*! - ******************************************************************************* - * @brief - * - * @param pszName - * @param Size - * @param Align - * @param ui32Flags - * - * @return - ******************************************************************************/ -LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags); - - -/*! - ******************************************************************************* - * @brief - * - * @param psCache - * - * @return - ******************************************************************************/ -IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache); - - -/*! - ******************************************************************************* - * @brief - * - * @param psCache - * @param Flags - * - * @return - ******************************************************************************/ -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__) -#else -#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, NULL, 0) -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)) -IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, gfp_t Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line); -#else -IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line); -#endif - -/*! - ******************************************************************************* - * @brief - * - * @param psCache - * @param pvObject - * - * @return - ******************************************************************************/ -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__) -#else -#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, NULL, 0) -#endif -IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line); - - -/*! - ******************************************************************************* - * @brief - * - * @param psCache - * - * @return - ******************************************************************************/ -const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache); - - -/*! - ******************************************************************************* - * @brief - * - * @param BasePAddr - * @param ui32Bytes - * @param ui32AreaFlags Heap caching and mapping Flags - * - * @return - ******************************************************************************/ -LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags); - - -/*! - ******************************************************************************* - * @brief - * - * @param psLinuxMemArea - * - * @return - ******************************************************************************/ -IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea); - - -/*! - ******************************************************************************* - * @brief - * - * @param ui32Bytes - * @param ui32AreaFlags E.g Heap caching and mapping Flags - * - * @return - ******************************************************************************/ -LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags); - - -/*! - ******************************************************************************* - * @brief - * - * @param psLinuxMemArea - * - * @return - ******************************************************************************/ -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 - * - * @return - ******************************************************************************/ -LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea, - IMG_UINT32 ui32ByteOffset, - IMG_UINT32 ui32Bytes); - - -/*! - ******************************************************************************* - * @brief - * - * @param psLinuxMemArea - * - * @return - ******************************************************************************/ -IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea); - - -/*! - ******************************************************************************* - * @brief For debug builds, LinuxMemAreas are tracked in /proc - * - * @param psLinuxMemArea - * - ******************************************************************************/ -#if defined(LINUX_MEM_AREAS_DEBUG) -IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea); -#else -#define LinuxMemAreaRegister(X) -#endif - - -/*! - ******************************************************************************* - * @brief - * - * @param psLinuxMemArea - * - * @return - ******************************************************************************/ -IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea); - - -/*! - ******************************************************************************* - * @brief - * - * @param psLinuxMemArea - * @param ui32ByteOffset - * - * @return - ******************************************************************************/ -IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset); - - -#define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr) - -/*! - ******************************************************************************* - * @brief Indicate whether a LinuxMemArea is physically contiguous - * - * @param psLinuxMemArea - * - * @return IMG_TRUE if the physical address range is contiguous, else IMG_FALSE - ******************************************************************************/ -IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea); - -/*! - ******************************************************************************* - * @brief Return the real underlying LinuxMemArea - * - * @param psLinuxMemArea - * - * @return The real underlying LinuxMemArea - ******************************************************************************/ -static inline LinuxMemArea * -LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea) -{ - if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC) - { - return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea; - } - else - { - return psLinuxMemArea; - } -} - - -/*! - ******************************************************************************* - * @brief Return type of real underlying LinuxMemArea - * - * @param psLinuxMemArea - * - * @return The areas eAreaType or for SUB areas; return the parents eAreaType. - ******************************************************************************/ -static inline LINUX_MEM_AREA_TYPE -LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea) -{ - return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType; -} - - -/*! - ******************************************************************************* - * @brief Converts the enum type of a LinuxMemArea to a const string - * - * @param eMemAreaType - * - * @return const string representation of type - ******************************************************************************/ -const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType); - - -/*! - ******************************************************************************* - * @brief - * - * @param ui32Flags - * - * @return - ******************************************************************************/ -#if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS) -const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags); -#endif - -#endif /* __IMG_LINUX_MM_H__ */ - diff --git a/pvr-source/services4/srvkm/env/linux/mmap.c b/pvr-source/services4/srvkm/env/linux/mmap.c deleted file mode 100755 index 495031a..0000000 --- a/pvr-source/services4/srvkm/env/linux/mmap.c +++ /dev/null @@ -1,1656 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux mmap interface -@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 <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/vmalloc.h> -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) -#include <linux/wrapper.h> -#endif -#include <linux/slab.h> -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) -#include <linux/highmem.h> -#endif -#include <asm/io.h> -#include <asm/page.h> -#include <asm/shmparam.h> -#include <asm/pgtable.h> -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) -#include <linux/sched.h> -#include <asm/current.h> -#endif -#if defined(SUPPORT_DRI_DRM) -#include <drm/drmP.h> -#endif - -#include "services_headers.h" - -#include "pvrmmap.h" -#include "mutils.h" -#include "mmap.h" -#include "mm.h" -#include "proc.h" -#include "mutex.h" -#include "handle.h" -#include "perproc.h" -#include "env_perproc.h" -#include "bridged_support.h" -#if defined(SUPPORT_DRI_DRM) -#include "pvr_drm.h" -#endif - -#if !defined(PVR_SECURE_HANDLES) && !defined (SUPPORT_SID_INTERFACE) -#error "The mmap code requires PVR_SECURE_HANDLES" -#endif - -/* WARNING: - * The mmap code has its own mutex, to prevent a possible deadlock, - * when using gPVRSRVLock. - * The Linux kernel takes the mm->mmap_sem before calling the mmap - * entry points (PVRMMap, MMapVOpen, MMapVClose), but the ioctl - * entry point may take mm->mmap_sem during fault handling, or - * before calling get_user_pages. If gPVRSRVLock was used in the - * mmap entry points, a deadlock could result, due to the ioctl - * and mmap code taking the two locks in different orders. - * As a corollary to this, the mmap entry points must not call - * any driver code that relies on gPVRSRVLock is held. - */ -PVRSRV_LINUX_MUTEX g_sMMapMutex; - -static LinuxKMemCache *g_psMemmapCache = NULL; -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; -#endif - - -#if defined(DEBUG_LINUX_MMAP_AREAS) -static struct proc_dir_entry *g_ProcMMap; -#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */ - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) -/* - * Now that we are using mmap2 in srvclient, almost (*) the full 32 - * bit offset is available. The range of values is divided into two. - * The first part of the range, from FIRST_PHYSICAL_PFN to - * LAST_PHYSICAL_PFN, is for raw page mappings (VM_PFNMAP). The - * resulting 43 bit (*) physical address range should be enough for - * the current range of processors we support. - * - * NB: (*) -- the above figures assume 4KB page size. The offset - * argument to mmap2() is in units of 4,096 bytes regardless of page - * size. Thus, we lose (PAGE_SHIFT-12) bits of resolution on other - * architectures. - * - * The second part of the range, from FIRST_SPECIAL_PFN to LAST_SPECIAL_PFN, - * is used for all other mappings. These other mappings will always - * consist of pages with associated page structures, and need not - * represent a contiguous range of physical addresses. - * - */ -#define MMAP2_PGOFF_RESOLUTION (32-PAGE_SHIFT+12) -#define RESERVED_PGOFF_BITS 1 -#define MAX_MMAP_HANDLE ((1UL<<(MMAP2_PGOFF_RESOLUTION-RESERVED_PGOFF_BITS))-1) - -#define FIRST_PHYSICAL_PFN 0 -#define LAST_PHYSICAL_PFN (FIRST_PHYSICAL_PFN + MAX_MMAP_HANDLE) -#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1) -#define LAST_SPECIAL_PFN (FIRST_SPECIAL_PFN + MAX_MMAP_HANDLE) - -#else /* !defined(PVR_MAKE_ALL_PFNS_SPECIAL) */ - -#if PAGE_SHIFT != 12 -#error This build variant has not yet been made non-4KB page-size aware -#endif - -/* - * Since we no longer have to worry about clashes with the mmap - * offsets used for pure PFN mappings (VM_PFNMAP), there is greater - * freedom in choosing the mmap handles. This is useful if the - * mmap offset space has to be shared with another driver component. - */ - -#if defined(PVR_MMAP_OFFSET_BASE) -#define FIRST_SPECIAL_PFN PVR_MMAP_OFFSET_BASE -#else -#define FIRST_SPECIAL_PFN 0x80000000UL -#endif - -#if defined(PVR_NUM_MMAP_HANDLES) -#define MAX_MMAP_HANDLE PVR_NUM_MMAP_HANDLES -#else -#define MAX_MMAP_HANDLE 0x7fffffffUL -#endif - -#endif /* !defined(PVR_MAKE_ALL_PFNS_SPECIAL) */ - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) -static inline IMG_BOOL -PFNIsPhysical(IMG_UINT32 pfn) -{ - /* Unsigned, no need to compare >=0 */ - return (/*(pfn >= FIRST_PHYSICAL_PFN) &&*/ (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE; -} - -static inline IMG_BOOL -PFNIsSpecial(IMG_UINT32 pfn) -{ - /* Unsigned, no need to compare <=MAX_UINT */ - return ((pfn >= FIRST_SPECIAL_PFN) /*&& (pfn <= LAST_SPECIAL_PFN)*/) ? IMG_TRUE : IMG_FALSE; -} -#endif - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) -static inline IMG_HANDLE -MMapOffsetToHandle(IMG_UINT32 pfn) -{ - if (PFNIsPhysical(pfn)) - { - PVR_ASSERT(PFNIsPhysical(pfn)); - return IMG_NULL; - } - return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN); -} -#endif - -static inline IMG_UINT32 -#if defined (SUPPORT_SID_INTERFACE) -HandleToMMapOffset(IMG_SID hHandle) -#else -HandleToMMapOffset(IMG_HANDLE hHandle) -#endif -{ - IMG_UINT32 ulHandle = (IMG_UINT32)hHandle; - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - if (PFNIsSpecial(ulHandle)) - { - PVR_ASSERT(PFNIsSpecial(ulHandle)); - return 0; - } -#endif - return ulHandle + FIRST_SPECIAL_PFN; -} - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) -/* - * Determine whether physical or special mappings will be used for - * a given memory area. At present, this decision is made on - * whether the mapping represents a contiguous range of physical - * addresses, which is a requirement for raw page mappings (VM_PFNMAP). - * In the VMA structure for such a mapping, vm_pgoff is the PFN - * (page frame number, the physical address divided by the page size) - * of the first page in the VMA. The second page is assumed to have - * PFN (vm_pgoff + 1), the third (vm_pgoff + 2) and so on. - */ -static inline IMG_BOOL -LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea) -{ - return LinuxMemAreaPhysIsContig(psLinuxMemArea); -} -#endif - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) -static inline IMG_UINT32 -GetCurrentThreadID(IMG_VOID) -{ - /* - * The PID is the thread ID, as each thread is a - * seperate process. - */ - return (IMG_UINT32)current->pid; -} -#endif - -/* - * Create an offset structure, which is used to hold per-process - * mmap data. - */ -static PKV_OFFSET_STRUCT -CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize) -{ - PKV_OFFSET_STRUCT psOffsetStruct; -#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS) - const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea)); -#endif - -#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS) - PVR_DPF((PVR_DBG_MESSAGE, - "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8x)", - __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags)); -#endif - - PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC); - - PVR_ASSERT(psLinuxMemArea->bMMapRegistered); - - psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL); - if(psOffsetStruct == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache")); - return IMG_NULL; - } - - psOffsetStruct->ui32MMapOffset = ui32Offset; - - psOffsetStruct->psLinuxMemArea = psLinuxMemArea; - - psOffsetStruct->ui32RealByteSize = ui32RealByteSize; - - /* - * We store the TID in case two threads within a process - * generate the same offset structure, and both end up on the - * list of structures waiting to be mapped, at the same time. - * This could happen if two sub areas within the same page are - * being mapped at the same time. - * The TID allows the mmap entry point to distinguish which - * mapping is being done by which thread. - */ -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - psOffsetStruct->ui32TID = GetCurrentThreadID(); -#endif - psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM(); - -#if defined(DEBUG_LINUX_MMAP_AREAS) - /* Extra entries to support proc filesystem debug info */ - psOffsetStruct->pszName = pszName; -#endif - - list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList); - - return psOffsetStruct; -} - - -static IMG_VOID -DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct) -{ -#ifdef DEBUG - IMG_CPU_PHYADDR CpuPAddr; - CpuPAddr = LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0); -#endif - - list_del(&psOffsetStruct->sAreaItem); - - if (psOffsetStruct->bOnMMapList) - { - list_del(&psOffsetStruct->sMMapItem); - } - -#ifdef DEBUG - PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: " - "psLinuxMemArea=%p, CpuPAddr=0x%08X", __FUNCTION__, - psOffsetStruct->psLinuxMemArea, - CpuPAddr.uiAddr)); -#endif - - KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct); -} - - -/* - * There are no alignment constraints for mapping requests made by user - * mode Services. For this, and potentially other reasons, the - * mapping created for a users request may look different to the - * original request in terms of size and alignment. - * - * This function determines an offset that the user can add to the mapping - * that is _actually_ created which will point to the memory they are - * _really_ interested in. - * - */ -static inline IMG_VOID -DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea, - IMG_UINT32 *pui32RealByteSize, - IMG_UINT32 *pui32ByteOffset) -{ - IMG_UINT32 ui32PageAlignmentOffset; - IMG_CPU_PHYADDR CpuPAddr; - - CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0); - ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr); - - *pui32ByteOffset = ui32PageAlignmentOffset; - - *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset); -} - - -/*! - ******************************************************************************* - - @Function PVRMMapOSMemHandleToMMapData - - @Description - - Determine various parameters needed to mmap a memory area, and to - locate the memory within the mapped area. - - @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. - - @output pui32MMapOffset : points to mmap offset to be used in mmap2 sys call. - @output pui32ByteOffset : 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 - mapping, or 0 if it hasn't been mapped yet. - - @Return PVRSRV_ERROR : PVRSRV_OK, or error code. - - ******************************************************************************/ -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) -{ - LinuxMemArea *psLinuxMemArea; - PKV_OFFSET_STRUCT psOffsetStruct; - IMG_HANDLE hOSMemHandle; - PVRSRV_ERROR eError; - - 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; - } - else - { - DetermineUsersSizeAndByteOffset(psLinuxMemArea, - pui32RealByteSize, - pui32ByteOffset); - } - } - - /* Check whether this memory area has already been mapped */ - list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) - { - if (psPerProc->ui32PID == psOffsetStruct->ui32PID) - { - if (!psLinuxMemArea->hBMHandle) - { - PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize); - } - /* - * User mode locking is required to stop two threads racing to - * map the same memory area. The lock should prevent a - * second thread retrieving mmap data for a given handle, - * before the first thread has done the mmap. - * Without locking, both threads may attempt the mmap, - * and one of them will fail. - */ - *pui32MMapOffset = psOffsetStruct->ui32MMapOffset; - *pui32UserVAddr = psOffsetStruct->ui32UserVAddr; - PVRSRVOffsetStructIncRef(psOffsetStruct); - - eError = PVRSRV_OK; - goto exit_unlock; - } - } - - /* Memory area won't have been mapped yet */ - *pui32UserVAddr = 0; - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea)) - { - *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0); - PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset)); - } - else -#endif - { - *pui32MMapOffset = HandleToMMapOffset(hMHandle); -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset)); -#endif - } - - psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize); - if (psOffsetStruct == IMG_NULL) - { - eError = PVRSRV_ERROR_OUT_OF_MEMORY; - goto exit_unlock; - } - - /* - * Offset structures representing physical mappings are added to - * a list, so that they can be located when the memory area is mapped. - */ - list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList); - - psOffsetStruct->bOnMMapList = IMG_TRUE; - - PVRSRVOffsetStructIncRef(psOffsetStruct); - - eError = PVRSRV_OK; - - /* Need to scale up the offset to counter the shifting that - 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); - -exit_unlock: - LinuxUnLockMutex(&g_sMMapMutex); - - return eError; -} - - -/*! - ******************************************************************************* - - @Function PVRMMapReleaseMMapData - - @Description - - Release mmap data. - - @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. - - @Output pbMUnmap : points to flag that indicates whether an munmap is - required. - @output pui32UserVAddr : 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) -{ - LinuxMemArea *psLinuxMemArea; - PKV_OFFSET_STRUCT psOffsetStruct; - IMG_HANDLE hOSMemHandle; - PVRSRV_ERROR eError; - IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); - - 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; - - /* Find the offset structure */ - list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) - { - if (psOffsetStruct->ui32PID == ui32PID) - { - if (psOffsetStruct->ui32RefCount == 0) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area %p", __FUNCTION__, psOffsetStruct, psLinuxMemArea)); - eError = PVRSRV_ERROR_STILL_MAPPED; - goto exit_unlock; - } - - PVRSRVOffsetStructDecRef(psOffsetStruct); - - *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0)); - - *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0; - *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0; - - eError = PVRSRV_OK; - goto exit_unlock; - } - } - - /* 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; - -exit_unlock: - LinuxUnLockMutex(&g_sMMapMutex); - - return eError; -} - -static inline PKV_OFFSET_STRUCT -FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize) -{ - PKV_OFFSET_STRUCT psOffsetStruct; -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - IMG_UINT32 ui32TID = GetCurrentThreadID(); -#endif - IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); - - list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem) - { - if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID) - { -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - /* - * If the offset is physical, make sure the thread IDs match, - * as different threads may be mapping different memory areas - * with the same offset. - */ - if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID) -#endif - { - return psOffsetStruct; - } - } - } - - return IMG_NULL; -} - - -/* - * Map a memory area into user space. - * Note, the ui32ByteOffset is _not_ implicitly page aligned since - * LINUX_MEM_AREA_SUB_ALLOC LinuxMemAreas have no alignment constraints. - */ -static IMG_BOOL -DoMapToUser(LinuxMemArea *psLinuxMemArea, - struct vm_area_struct* ps_vma, - IMG_UINT32 ui32ByteOffset) -{ - IMG_UINT32 ui32ByteSize; - - if ((psLinuxMemArea->hBMHandle) && (ui32ByteOffset != 0)) - { - /* Partial mapping of sparse allocations should never happen */ - return IMG_FALSE; - } - - if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC) - { - return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea), /* PRQA S 3670 */ /* allow recursion */ - ps_vma, - psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset); - } - - /* - * 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); - -#if defined (__sparc__) - /* - * For LINUX_MEM_AREA_EXTERNAL_KV, we don't know where the address range - * we are being asked to map has come from, that is, whether it is memory - * or I/O. For all architectures other than SPARC, there is no distinction. - * Since we don't currently support SPARC, we won't worry about it. - */ -#error "SPARC not supported" -#endif - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - if (PFNIsPhysical(ps_vma->vm_pgoff)) - { - IMG_INT result; - - PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea)); - PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff); - /* - * Since the memory is contiguous, we can map the whole range in one - * go . - */ - - 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); - - if(result == 0) - { - return IMG_TRUE; - } - - PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result)); - } -#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 - * could, but the resulting VMA may confuse other bits of the kernel - * that attempt to interpret it). - * The only alternative is to use VM_INSERT_PAGE, which requires - * 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; -#if defined(PVR_MAKE_ALL_PFNS_SPECIAL) - IMG_BOOL bMixedMap = IMG_FALSE; -#endif - /* First pass, validate the page frame numbers */ - for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE) - { - IMG_UINT32 pfn; - IMG_BOOL bMapPage = IMG_TRUE; - - if (psLinuxMemArea->hBMHandle) - { - if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32PA)) - { - bMapPage = IMG_FALSE; - } - } - - if (bMapPage) - { - pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32AdjustedPA); - if (!pfn_valid(pfn)) - { -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%x", __FUNCTION__, pfn)); - return IMG_FALSE; -#else - bMixedMap = IMG_TRUE; -#endif - } - ui32AdjustedPA += PAGE_SIZE; - } - } - -#if defined(PVR_MAKE_ALL_PFNS_SPECIAL) - 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) - { - IMG_UINT32 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)) - { - bMapPage = IMG_FALSE; - } - } - - if (bMapPage) - { - pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32AdjustedPA); - -#if defined(PVR_MAKE_ALL_PFNS_SPECIAL) - if (bMixedMap) - { - result = vm_insert_mixed(ps_vma, ulVMAPos, pfn); - if(result != 0) - { - PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_mixed failed (%d)", __FUNCTION__, result)); - return IMG_FALSE; - } - } - else -#endif - { - struct page *psPage; - - PVR_ASSERT(pfn_valid(pfn)); - - psPage = pfn_to_page(pfn); - - result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage); - if(result != 0) - { - PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result)); - return IMG_FALSE; - } - } - ui32AdjustedPA += PAGE_SIZE; - } - ulVMAPos += PAGE_SIZE; - } - } - - return IMG_TRUE; -} - - -static IMG_VOID -MMapVOpenNoLock(struct vm_area_struct* ps_vma) -{ - PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data; - - PVR_ASSERT(psOffsetStruct != IMG_NULL); - PVR_ASSERT(!psOffsetStruct->bOnMMapList); - - PVRSRVOffsetStructIncMapped(psOffsetStruct); - - if (psOffsetStruct->ui32Mapped > 1) - { - PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %u)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped)); - PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0); - } - -#if defined(DEBUG_LINUX_MMAP_AREAS) - - PVR_DPF((PVR_DBG_MESSAGE, - "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %d, ui32Mapped %d", - __FUNCTION__, - psOffsetStruct->psLinuxMemArea, - LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea), - psOffsetStruct->ui32MMapOffset, - psOffsetStruct->ui32Mapped)); -#endif -} - - -/* - * Linux mmap open entry point. - */ -static void -MMapVOpen(struct vm_area_struct* ps_vma) -{ - LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP); - - MMapVOpenNoLock(ps_vma); - - LinuxUnLockMutex(&g_sMMapMutex); -} - - -static IMG_VOID -MMapVCloseNoLock(struct vm_area_struct* ps_vma) -{ - PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data; - PVR_ASSERT(psOffsetStruct != IMG_NULL); - -#if defined(DEBUG_LINUX_MMAP_AREAS) - PVR_DPF((PVR_DBG_MESSAGE, - "%s: psLinuxMemArea %p, CpuVAddr %p ui32MMapOffset %d, ui32Mapped %d", - __FUNCTION__, - psOffsetStruct->psLinuxMemArea, - LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea), - psOffsetStruct->ui32MMapOffset, - psOffsetStruct->ui32Mapped)); -#endif - - PVR_ASSERT(!psOffsetStruct->bOnMMapList); - PVRSRVOffsetStructDecMapped(psOffsetStruct); - if (psOffsetStruct->ui32Mapped == 0) - { - 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)); - } - - DestroyOffsetStruct(psOffsetStruct); - } - - ps_vma->vm_private_data = NULL; -} - -/* - * Linux mmap close entry point. - */ -static void -MMapVClose(struct vm_area_struct* ps_vma) -{ - LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP); - - MMapVCloseNoLock(ps_vma); - - LinuxUnLockMutex(&g_sMMapMutex); -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) -/* - * This vma operation is used to read data from mmap regions. It is called - * by access_process_vm, which is called to handle PTRACE_PEEKDATA ptrace - * requests and reads from /proc/<pid>/mem. - */ -static int MMapVAccess(struct vm_area_struct *ps_vma, unsigned long addr, - void *buf, int len, int write) -{ - PKV_OFFSET_STRUCT psOffsetStruct; - LinuxMemArea *psLinuxMemArea; - unsigned long ulOffset; - int iRetVal = -EINVAL; - IMG_VOID *pvKernelAddr; - - 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) - /* Out of range. We shouldn't get here, because the kernel will do - the necessary checks before calling access_process_vm. */ - goto exit_unlock; - - pvKernelAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea); - - if (pvKernelAddr) - { - memcpy(buf, pvKernelAddr+ulOffset, len); - iRetVal = len; - } - else - { - IMG_UINT32 pfn, ui32OffsetInPage; - struct page *page; - - pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ulOffset); - - if (!pfn_valid(pfn)) - goto exit_unlock; - - page = pfn_to_page(pfn); - ui32OffsetInPage = ADDR_TO_PAGE_OFFSET(ulOffset); - - if (ui32OffsetInPage+len > PAGE_SIZE) - /* The region crosses a page boundary */ - goto exit_unlock; - - pvKernelAddr = kmap(page); - memcpy(buf, pvKernelAddr+ui32OffsetInPage, len); - kunmap(page); - - iRetVal = len; - } - -exit_unlock: - LinuxUnLockMutex(&g_sMMapMutex); - return iRetVal; -} -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) */ - -static struct vm_operations_struct MMapIOOps = -{ - .open=MMapVOpen, - .close=MMapVClose, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) - .access=MMapVAccess, -#endif -}; - - -/*! - ******************************************************************************* - - @Function PVRMMap - - @Description - - Driver mmap entry point. - - @input pFile : unused. - @input ps_vma : pointer to linux memory area descriptor. - - @Return 0, or Linux error code. - - ******************************************************************************/ -int -PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma) -{ - LinuxMemArea *psFlushMemArea = IMG_NULL; - PKV_OFFSET_STRUCT psOffsetStruct; - IMG_UINT32 ui32ByteSize; - IMG_VOID *pvBase = IMG_NULL; - int iRetVal = 0; - IMG_UINT32 ui32ByteOffset = 0; /* Keep compiler happy */ - IMG_UINT32 ui32FlushSize = 0; - - PVR_UNREFERENCED_PARAMETER(pFile); - - LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP); - - ui32ByteSize = 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)", - __FUNCTION__, - ps_vma->vm_pgoff, - ui32ByteSize, ui32ByteSize)); - - psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize); - - if (psOffsetStruct == IMG_NULL) - { -#if defined(SUPPORT_DRI_DRM) - LinuxUnLockMutex(&g_sMMapMutex); - -#if !defined(SUPPORT_DRI_DRM_EXT) - /* Pass unknown requests onto the DRM module */ - return drm_mmap(pFile, ps_vma); -#else - /* - * Indicate to caller that the request is not for us. - * Do not return this error elsewhere in this function, as the - * caller may use it as a clue as to whether the mmap request - * should be passed on to another component (e.g. drm_mmap). - */ - return -ENOENT; -#endif -#else - PVR_UNREFERENCED_PARAMETER(pFile); - - PVR_DPF((PVR_DBG_ERROR, - "%s: Attempted to mmap unregistered area at vm_pgoff 0x%lx", - __FUNCTION__, ps_vma->vm_pgoff)); - iRetVal = -EINVAL; -#endif - goto unlock_and_return; - } - - list_del(&psOffsetStruct->sMMapItem); - psOffsetStruct->bOnMMapList = IMG_FALSE; - - /* Only support shared writeable mappings */ - if (((ps_vma->vm_flags & VM_WRITE) != 0) && - ((ps_vma->vm_flags & VM_SHARED) == 0)) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__)); - iRetVal = -EINVAL; - goto unlock_and_return; - } - - PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n", - __FUNCTION__, psOffsetStruct->psLinuxMemArea)); - - ps_vma->vm_flags |= VM_RESERVED; - ps_vma->vm_flags |= VM_IO; - - /* - * Disable mremap because our nopage handler assumes all - * page requests have already been validated. - */ - ps_vma->vm_flags |= VM_DONTEXPAND; - - /* Don't allow mapping to be inherited across a process fork */ - ps_vma->vm_flags |= VM_DONTCOPY; - - ps_vma->vm_private_data = (void *)psOffsetStruct; - - switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK) - { - case PVRSRV_HAP_CACHED: - /* This is the default, do nothing. */ - break; - case PVRSRV_HAP_WRITECOMBINE: - ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot); - break; - case PVRSRV_HAP_UNCACHED: - ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot); - break; - default: - PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__)); - iRetVal = -EINVAL; - 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 - - /* Install open and close handlers for ref-counting */ - ps_vma->vm_ops = &MMapIOOps; - - if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0)) - { - iRetVal = -EAGAIN; - goto unlock_and_return; - } - - PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0); - - psOffsetStruct->ui32UserVAddr = ps_vma->vm_start; - - /* Invalidate for the ION memory is performed during the mapping */ - if(psOffsetStruct->psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ION) - psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate = IMG_FALSE; - - /* Compute the flush region (if necessary) inside the mmap mutex */ - if(psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate) - { - psFlushMemArea = psOffsetStruct->psLinuxMemArea; - - /* Sparse mappings have to ask the BM for the virtual size */ - if (psFlushMemArea->hBMHandle) - { - pvBase = (IMG_VOID *)ps_vma->vm_start; - ui32ByteOffset = 0; - ui32FlushSize = BM_GetVirtualSize(psFlushMemArea->hBMHandle); - } - else - { - IMG_UINT32 ui32DummyByteSize; - - DetermineUsersSizeAndByteOffset(psFlushMemArea, - &ui32DummyByteSize, - &ui32ByteOffset); - - pvBase = (IMG_VOID *)ps_vma->vm_start + ui32ByteOffset; - ui32FlushSize = psFlushMemArea->ui32ByteSize; - } - - psFlushMemArea->bNeedsCacheInvalidate = IMG_FALSE; - } - - /* 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)); - -unlock_and_return: - if (iRetVal != 0 && psOffsetStruct != IMG_NULL) - { - DestroyOffsetStruct(psOffsetStruct); - } - - LinuxUnLockMutex(&g_sMMapMutex); - - if(psFlushMemArea) - { - OSInvalidateCPUCacheRangeKM(psFlushMemArea, ui32ByteOffset, pvBase, - ui32FlushSize); - } - - return iRetVal; -} - - -#if defined(DEBUG_LINUX_MMAP_AREAS) - -/* - * Lock MMap regions list (called on page start/stop while reading /proc/mmap) - - * sfile : seq_file that handles /proc file - * start : TRUE if it's start, FALSE if it's stop - * -*/ -static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start) -{ - if(start) - { - LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP); - } - else - { - LinuxUnLockMutex(&g_sMMapMutex); - } -} - - -/* - * Convert offset (index from KVOffsetTable) to element - * (called when reading /proc/mmap file) - - * sfile : seq_file that handles /proc file - * off : index into the KVOffsetTable from which to print - * - * returns void* : Pointer to element that will be dumped - * -*/ -static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off) -{ - LinuxMemArea *psLinuxMemArea; - if(!off) - { - return PVR_PROC_SEQ_START_TOKEN; - } - - list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem) - { - PKV_OFFSET_STRUCT psOffsetStruct; - - list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) - { - off--; - if (off == 0) - { - PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea); - return (void*)psOffsetStruct; - } - } - } - return (void*)0; -} - -/* - * Gets next MMap element to show. (called when reading /proc/mmap file) - - * sfile : seq_file that handles /proc file - * el : actual element - * off : index into the KVOffsetTable from which to print - * - * returns void* : Pointer to element to show (0 ends iteration) -*/ -static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off) -{ - return ProcSeqOff2ElementMMapRegistrations(sfile,off); -} - - -/* - * Show MMap element (called when reading /proc/mmap file) - - * sfile : seq_file that handles /proc file - * el : actual element - * -*/ -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; - - 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" - "psLinuxMemArea " - "UserVAddr " - "KernelVAddr " - "CpuPAddr " - "MMapOffset " - "ByteLength " - "LinuxMemType " - "Pid Name Flags\n", -#else - "<mmap_header>\n" - "\t<count>%u</count>\n" - "\t<bytes>%u</bytes>\n" - "</mmap_header>\n", -#endif - g_ui32RegisteredAreas, - g_ui32TotalByteSize - ); - return; - } - - psLinuxMemArea = psOffsetStruct->psLinuxMemArea; - - DetermineUsersSizeAndByteOffset(psLinuxMemArea, - &ui32RealByteSize, - &ui32ByteOffset); - - seq_printf( sfile, -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - "%-8p %08x %-8p %08x %08x %-8d %-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<linux_mem_area_type>%-24s</linux_mem_area_type>\n" - "\t<pid>%-5u</pid>\n" - "\t<name>%-8s</name>\n" - "\t<flags>%08x</flags>\n" - "\t<flags_string>%s</flags_string>\n" - "</mmap_record>\n", -#endif - psLinuxMemArea, - psOffsetStruct->ui32UserVAddr + ui32ByteOffset, - LinuxMemAreaToCpuVAddr(psLinuxMemArea), - LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr, - psOffsetStruct->ui32MMapOffset, - psLinuxMemArea->ui32ByteSize, - LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType), - psOffsetStruct->ui32PID, - psOffsetStruct->pszName, - psLinuxMemArea->ui32AreaFlags, - HAPFlagsToString(psLinuxMemArea->ui32AreaFlags)); -} - -#endif - - -/*! - ******************************************************************************* - - @Function PVRMMapRegisterArea - - @Description - - Register a memory area with the mmap code. - - @input psLinuxMemArea : pointer to memory area. - - @Return PVRSRV_OK, or PVRSRV_ERROR. - - ******************************************************************************/ -PVRSRV_ERROR -PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea) -{ - PVRSRV_ERROR eError; -#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS) - const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea)); -#endif - - LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP); - -#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS) - PVR_DPF((PVR_DBG_MESSAGE, - "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8x)", - __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags)); -#endif - - PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC); - - /* Check this mem area hasn't already been registered */ - if(psLinuxMemArea->bMMapRegistered) - { - PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered", - __FUNCTION__, psLinuxMemArea)); - eError = PVRSRV_ERROR_INVALID_PARAMS; - goto exit_unlock; - } - - list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList); - - psLinuxMemArea->bMMapRegistered = IMG_TRUE; - -#if defined(DEBUG_LINUX_MMAP_AREAS) - g_ui32RegisteredAreas++; - /* - * Sub memory areas are excluded from g_ui32TotalByteSize so that we - * don't count memory twice, once for the parent and again for sub - * allocationis. - */ - if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) - { - g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize; - } -#endif - - eError = PVRSRV_OK; - -exit_unlock: - LinuxUnLockMutex(&g_sMMapMutex); - - return eError; -} - - -/*! - ******************************************************************************* - - @Function PVRMMapRemoveRegisterArea - - @Description - - Unregister a memory area with the mmap code. - - @input psLinuxMemArea : pointer to memory area. - - @Return PVRSRV_OK, or PVRSRV_ERROR. - - ******************************************************************************/ -PVRSRV_ERROR -PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea) -{ - PVRSRV_ERROR eError; - PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct; - - LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP); - - PVR_ASSERT(psLinuxMemArea->bMMapRegistered); - - list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) - { - if (psOffsetStruct->ui32Mapped != 0) - { - PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %u", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped)); - dump_stack(); - PVRSRVDumpRefCountCCB(); - eError = PVRSRV_ERROR_STILL_MAPPED; - goto exit_unlock; - } - else - { - /* - * An offset structure is created when a call is made to get - * the mmap data for a physical mapping. If the data is never - * used for mmap, we will be left with an umapped offset - * structure. - */ - PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped", __FUNCTION__, psOffsetStruct)); - } - - PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList); - - DestroyOffsetStruct(psOffsetStruct); - } - - list_del(&psLinuxMemArea->sMMapItem); - - psLinuxMemArea->bMMapRegistered = IMG_FALSE; - -#if defined(DEBUG_LINUX_MMAP_AREAS) - g_ui32RegisteredAreas--; - if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) - { - g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize; - } -#endif - - eError = PVRSRV_OK; - -exit_unlock: - LinuxUnLockMutex(&g_sMMapMutex); - return eError; -} - - -/*! - ******************************************************************************* - - @Function LinuxMMapPerProcessConnect - - @Description - - Per-process mmap initialisation code. - - @input psEnvPerProc : pointer to OS specific per-process data. - - @Return PVRSRV_OK, or PVRSRV_ERROR. - - ******************************************************************************/ -PVRSRV_ERROR -LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc) -{ - PVR_UNREFERENCED_PARAMETER(psEnvPerProc); - - return PVRSRV_OK; -} - -/*! - ******************************************************************************* - - @Function LinuxMMapPerProcessDisconnect - - @Description - - Per-process mmap deinitialisation code. - - @input psEnvPerProc : pointer to OS specific per-process data. - - ******************************************************************************/ -IMG_VOID -LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc) -{ - PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct; - IMG_BOOL bWarn = IMG_FALSE; - IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); - - PVR_UNREFERENCED_PARAMETER(psEnvPerProc); - - LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP); - - list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem) - { - if (psOffsetStruct->ui32PID == ui32PID) - { - if (!bWarn) - { - PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__)); - bWarn = IMG_TRUE; - } - PVR_ASSERT(psOffsetStruct->ui32Mapped == 0); - PVR_ASSERT(psOffsetStruct->bOnMMapList); - - DestroyOffsetStruct(psOffsetStruct); - } - } - - LinuxUnLockMutex(&g_sMMapMutex); -} - - -/*! - ******************************************************************************* - - @Function LinuxMMapPerProcessHandleOptions - - @Description - - Set secure handle options required by mmap code. - - @input psHandleBase : pointer to handle base. - - @Return PVRSRV_OK, or PVRSRV_ERROR. - - ******************************************************************************/ -PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase) -{ - PVRSRV_ERROR eError; - - eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError)); - return eError; - } - - return eError; -} - - -/*! - ******************************************************************************* - - @Function PVRMMapInit - - @Description - - MMap initialisation code - - ******************************************************************************/ -IMG_VOID -PVRMMapInit(IMG_VOID) -{ - LinuxInitMutex(&g_sMMapMutex); - - g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0); - if (!g_psMemmapCache) - { - PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__)); - goto error; - } - -#if defined(DEBUG_LINUX_MMAP_AREAS) - g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL, - ProcSeqNextMMapRegistrations, - ProcSeqShowMMapRegistrations, - ProcSeqOff2ElementMMapRegistrations, - ProcSeqStartstopMMapRegistations - ); -#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */ - return; - -error: - PVRMMapCleanup(); - return; -} - - -/*! - ******************************************************************************* - - @Function PVRMMapCleanup - - @Description - - Mmap deinitialisation code - - ******************************************************************************/ -IMG_VOID -PVRMMapCleanup(IMG_VOID) -{ - PVRSRV_ERROR eError; - - if (!list_empty(&g_sMMapAreaList)) - { - LinuxMemArea *psLinuxMemArea, *psTmpMemArea; - - PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__)); - - PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__)); - list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem) - { - eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError)); - } - PVR_ASSERT(eError == PVRSRV_OK); - - LinuxMemAreaDeepFree(psLinuxMemArea); - } - } - PVR_ASSERT(list_empty((&g_sMMapAreaList))); - -#if defined(DEBUG_LINUX_MMAP_AREAS) - RemoveProcEntrySeq(g_ProcMMap); -#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */ - - if(g_psMemmapCache) - { - KMemCacheDestroyWrapper(g_psMemmapCache); - g_psMemmapCache = NULL; - } -} diff --git a/pvr-source/services4/srvkm/env/linux/mmap.h b/pvr-source/services4/srvkm/env/linux/mmap.h deleted file mode 100755 index 7140c13..0000000 --- a/pvr-source/services4/srvkm/env/linux/mmap.h +++ /dev/null @@ -1,240 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux mmap interface declaration -@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. -*/ /**************************************************************************/ - -#if !defined(__MMAP_H__) -#define __MMAP_H__ - -#include <linux/mm.h> -#include <linux/list.h> - -#if defined(VM_MIXEDMAP) -/* - * Mixed maps allow us to avoid using raw PFN mappings (VM_PFNMAP) for - * pages without pages structures ("struct page"), giving us more - * freedom in choosing the mmap offset for mappings. Mixed maps also - * allow both the mmap and the wrap code to be simplified somewhat. - */ -#define PVR_MAKE_ALL_PFNS_SPECIAL -#endif - -#include "perproc.h" -#include "mm.h" - -/* - * This structure represents the relationship between an mmap2 file - * offset and a LinuxMemArea for a given process. - */ -typedef struct KV_OFFSET_STRUCT_TAG -{ - /* - * Mapping count. Incremented when the mapping is created, and - * if the mapping is inherited across a process fork. - */ - IMG_UINT32 ui32Mapped; - - /* - * Offset to be passed to mmap2 to map the associated memory area - * into user space. The offset may represent the page frame number - * of the first page in the area (if the area is physically - * contiguous), or it may represent the secure handle associated - * with the area. - */ - IMG_UINT32 ui32MMapOffset; - - IMG_UINT32 ui32RealByteSize; - - /* Memory area associated with this offset structure */ - LinuxMemArea *psLinuxMemArea; - -#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL) - /* ID of the thread that owns this structure */ - IMG_UINT32 ui32TID; -#endif - - /* ID of the process that owns this structure */ - IMG_UINT32 ui32PID; - - /* - * For offsets that represent actual page frame numbers, this structure - * is temporarily put on a list so that it can be found from the - * driver mmap entry point. This flag indicates the structure is - * on the list. - */ - IMG_BOOL bOnMMapList; - - /* Reference count for this structure */ - IMG_UINT32 ui32RefCount; - - /* - * User mode address of start of mapping. This is not necessarily the - * first user mode address of the memory area. - */ - IMG_UINT32 ui32UserVAddr; - - /* Extra entries to support proc filesystem debug info */ -#if defined(DEBUG_LINUX_MMAP_AREAS) - const IMG_CHAR *pszName; -#endif - - /* List entry field for MMap list */ - struct list_head sMMapItem; - - /* List entry field for per-memory area list */ - struct list_head sAreaItem; -}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT; - - - -/*! - ******************************************************************************* - * @Function Mmap initialisation code - ******************************************************************************/ -IMG_VOID PVRMMapInit(IMG_VOID); - - -/*! - ******************************************************************************* - * @Function Mmap de-initialisation code - ******************************************************************************/ -IMG_VOID PVRMMapCleanup(IMG_VOID); - - -/*! - ******************************************************************************* - * @Function Registers a memory area with the mmap code - * - * @Input psLinuxMemArea - * - * @Return PVRSRV_ERROR status - ******************************************************************************/ -PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea); - - -/*! - ******************************************************************************* - * @Function Unregisters a memory area from the mmap code - * - * @Input psLinuxMemArea - * - * @Return PVRSRV_ERROR status - ******************************************************************************/ -PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea); - - -/*! - ****************************************************************************** - * @Function When a userspace services client, requests to map a memory - * area to userspace, this function validates the request and - * returns the details that the client must use when calling mmap(2). - * - * @Input psPerProc Per process data. - * @Input hMHandle Handle associated with the memory to map. - * This is a (secure) handle to the OS specific - * memory handle structure (hOSMemHandle), or - * a handle to a structure that contains the - * memory handle. - * @Output pui32MMapOffset The page aligned offset that the client must - * pass to the mmap2 system call. - * @Output pui32ByteOffset The real mapping that will be created for the - * services client may have a different - * size/alignment from it request. This offset - * is returned to the client and should be added - * to virtual address returned from mmap2 to get - * the first address corresponding to its request. - * @Output pui32RealByteOffset The size that the mapping will really be, - * that the client must also pass to mmap/munmap. - * - * @Output pui32UserVAddr Pointer to returned user mode address of - * mapping. - * @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); - -/*! - ******************************************************************************* - - @Function Release mmap data. - - @Input psPerProc Per-process data. - @Input hMHandle Memory handle. - - @Output pbMUnmap Flag that indicates whether an munmap is - required. - @Output pui32RealByteSize Location for size of mapping. - @Output pui32UserVAddr User mode address to munmap. - - @Return PVRSRV_ERROR - ******************************************************************************/ -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); - -/*! - ******************************************************************************* - * @Function driver mmap entry point - * - * @Input pFile : user file structure - * - * @Input ps_vma : vm area structure - * - * @Return 0 for success, -errno for failure. - ******************************************************************************/ -int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma); - - -#endif /* __MMAP_H__ */ - diff --git a/pvr-source/services4/srvkm/env/linux/module.c b/pvr-source/services4/srvkm/env/linux/module.c deleted file mode 100755 index 4465f36..0000000 --- a/pvr-source/services4/srvkm/env/linux/module.c +++ /dev/null @@ -1,1214 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux module setup -@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 <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#if defined(SUPPORT_DRI_DRM) && !defined(SUPPORT_DRI_DRM_PLUGIN) -#define PVR_MOD_STATIC -#else - /* - * For LDM drivers, define PVR_LDM_MODULE to indicate generic LDM - * support is required, besides indicating the exact support - * required (e.g. platform, or PCI device). - */ - #if defined(LDM_PLATFORM) - #define PVR_LDM_PLATFORM_MODULE - #define PVR_LDM_DEVICE_CLASS - #define PVR_LDM_MODULE - #else - #if defined(LDM_PCI) - #define PVR_LDM_DEVICE_CLASS - #define PVR_LDM_PCI_MODULE - #define PVR_LDM_MODULE - #else - #if defined(SYS_SHARES_WITH_3PKM) - #define PVR_LDM_DEVICE_CLASS - #endif - #endif - #endif -#define PVR_MOD_STATIC static -#endif - -#if defined(PVR_LDM_PLATFORM_PRE_REGISTERED) -#if !defined(NO_HARDWARE) -#define PVR_USE_PRE_REGISTERED_PLATFORM_DEV -#endif -#endif - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/proc_fs.h> - -#if defined(SUPPORT_DRI_DRM) -#include <drm/drmP.h> -#if defined(PVR_SECURE_DRM_AUTH_EXPORT) -#include "env_perproc.h" -#endif -#endif - -#if defined(PVR_LDM_PLATFORM_MODULE) -#include <linux/platform_device.h> -#endif /* PVR_LDM_PLATFORM_MODULE */ - -#if defined(PVR_LDM_PCI_MODULE) -#include <linux/pci.h> -#endif /* PVR_LDM_PCI_MODULE */ - -#if defined(PVR_LDM_DEVICE_CLASS) -#include <linux/device.h> -#endif /* PVR_LDM_DEVICE_CLASS */ - -#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) -#include <asm/uaccess.h> -#endif - -#include "img_defs.h" -#include "services.h" -#include "kerneldisplay.h" -#include "kernelbuffer.h" -#include "syscommon.h" -#include "pvrmmap.h" -#include "mutils.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 "proc.h" -#include "pvrmodule.h" -#include "private_data.h" -#include "lock.h" -#include "linkage.h" -#include "buffer_manager.h" - -#if defined(SUPPORT_DRI_DRM) -#include "pvr_drm.h" -#endif -/* - * DRVNAME is the name we use to register our driver. - * DEVNAME is the name we use to register actual device nodes. - */ -#if defined(PVR_LDM_MODULE) -#define DRVNAME PVR_LDM_DRIVER_REGISTRATION_NAME -#endif -#define DEVNAME PVRSRV_MODNAME - -#if defined(SUPPORT_DRI_DRM) -#define PRIVATE_DATA(pFile) ((pFile)->driver_priv) -#else -#define PRIVATE_DATA(pFile) ((pFile)->private_data) -#endif - -/* - * This is all module configuration stuff required by the linux kernel. - */ -MODULE_SUPPORTED_DEVICE(DEVNAME); - -#if defined(PVRSRV_NEED_PVR_DPF) -#include <linux/moduleparam.h> -extern IMG_UINT32 gPVRDebugLevel; -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) */ - -/* PRQA S 3207 2 */ /* ignore 'not used' warning */ -EXPORT_SYMBOL(PVRGetDisplayClassJTable); -EXPORT_SYMBOL(PVRGetBufferClassJTable); - -#if defined(PVR_LDM_DEVICE_CLASS) && !defined(SUPPORT_DRI_DRM) -/* - * Device class used for /sys entries (and udev device node creation) - */ -static struct class *psPvrClass; -#endif - -#if !defined(SUPPORT_DRI_DRM) -/* - * This is the major number we use for all nodes in /dev. - */ -static int AssignedMajorNumber; - -/* - * These are the operations that will be associated with the device node - * we create. - * - * With gcc -W, specifying only the non-null members produces "missing - * initializer" warnings. -*/ -static int PVRSRVOpen(struct inode* pInode, struct file* pFile); -static int PVRSRVRelease(struct inode* pInode, struct file* pFile); - -static struct file_operations pvrsrv_fops = -{ - .owner=THIS_MODULE, - .unlocked_ioctl = PVRSRV_BridgeDispatchKM, - .open=PVRSRVOpen, - .release=PVRSRVRelease, - .mmap=PVRMMap, -}; -#endif - -PVRSRV_LINUX_MUTEX gPVRSRVLock; - -/* PID of process being released */ -IMG_UINT32 gui32ReleasePID; - -#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) -static IMG_UINT32 gPVRPowerLevel; -#endif - -#if defined(PVR_LDM_MODULE) - -#if defined(PVR_LDM_PLATFORM_MODULE) -#define LDM_DEV struct platform_device -#define LDM_DRV struct platform_driver -#endif /*PVR_LDM_PLATFORM_MODULE */ - -#if defined(PVR_LDM_PCI_MODULE) -#define LDM_DEV struct pci_dev -#define LDM_DRV struct pci_driver -#endif /* PVR_LDM_PCI_MODULE */ -/* - * This is the driver interface we support. - */ -#if defined(PVR_LDM_PLATFORM_MODULE) -static int PVRSRVDriverRemove(LDM_DEV *device); -static int PVRSRVDriverProbe(LDM_DEV *device); -#endif -#if defined(PVR_LDM_PCI_MODULE) -static void PVRSRVDriverRemove(LDM_DEV *device); -static int PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id); -#endif -static int PVRSRVDriverSuspend(LDM_DEV *device, pm_message_t state); -static void PVRSRVDriverShutdown(LDM_DEV *device); -static int PVRSRVDriverResume(LDM_DEV *device); - -#if defined(PVR_LDM_PCI_MODULE) -/* This structure is used by the Linux module code */ -struct pci_device_id powervr_id_table[] __devinitdata = { - {PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID)}, -#if defined (SYS_SGX_DEV1_DEVICE_ID) - {PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID)}, -#endif - {0} -}; - -MODULE_DEVICE_TABLE(pci, powervr_id_table); -#endif - -#if defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) -static struct platform_device_id powervr_id_table[] __devinitdata = { - {SYS_SGX_DEV_NAME, 0}, - {} -}; -#endif - -static LDM_DRV powervr_driver = { -#if defined(PVR_LDM_PLATFORM_MODULE) - .driver = { - .name = DRVNAME, - }, -#endif -#if defined(PVR_LDM_PCI_MODULE) - .name = DRVNAME, -#endif -#if defined(PVR_LDM_PCI_MODULE) || defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) - .id_table = powervr_id_table, -#endif - .probe = PVRSRVDriverProbe, -#if defined(PVR_LDM_PLATFORM_MODULE) - .remove = PVRSRVDriverRemove, -#endif -#if defined(PVR_LDM_PCI_MODULE) - .remove = __devexit_p(PVRSRVDriverRemove), -#endif - .suspend = PVRSRVDriverSuspend, - .resume = PVRSRVDriverResume, - .shutdown = PVRSRVDriverShutdown, -}; - -LDM_DEV *gpsPVRLDMDev; - -#if defined(MODULE) && defined(PVR_LDM_PLATFORM_MODULE) && \ - !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) -static void PVRSRVDeviceRelease(struct device unref__ *pDevice) -{ -} - -static struct platform_device powervr_device = { - .name = DEVNAME, - .id = -1, - .dev = { - .release = PVRSRVDeviceRelease - } -}; -#endif - -/*! -****************************************************************************** - - @Function PVRSRVDriverProbe - - @Description - - See whether a given device is really one we can drive. The platform bus - handler has already established that we should be able to service this device - because of the name match. We probably don't need to do anything else. - - @input pDevice - the device for which a probe is requested - - @Return 0 for success or <0 for an error. - -*****************************************************************************/ -#if defined(PVR_LDM_PLATFORM_MODULE) -static int PVRSRVDriverProbe(LDM_DEV *pDevice) -#endif -#if defined(PVR_LDM_PCI_MODULE) -static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device_id *id) -#endif -{ - SYS_DATA *psSysData; - - PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice)); - -#if 0 /* INTEGRATION_POINT */ - /* Some systems require device-specific system initialisation. - * E.g. this lets the OS track a device's dependencies on various - * system hardware. - * - * Note: some systems use this to enable HW that SysAcquireData - * will depend on, therefore it must be called first. - */ - if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK) - { - return -EINVAL; - } -#endif - /* SysInitialise only designed to be called once. - */ - psSysData = SysAcquireDataNoCheck(); - if (psSysData == IMG_NULL) - { - gpsPVRLDMDev = pDevice; - if (SysInitialise() != PVRSRV_OK) - { - return -ENODEV; - } - } - -#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; -} - - -/*! -****************************************************************************** - - @Function PVRSRVDriverRemove - - @Description - - This call is the opposite of the probe call: it is called when the device is - being removed from the driver's control. See the file $KERNELDIR/drivers/ - base/bus.c:device_release_driver() for the call to this function. - - This is the correct place to clean up anything our driver did while it was - asoociated with the device. - - @input pDevice - the device for which driver detachment is happening - - @Return 0 for success or <0 for an error. - -*****************************************************************************/ -#if defined (PVR_LDM_PLATFORM_MODULE) -static int PVRSRVDriverRemove(LDM_DEV *pDevice) -#endif -#if defined(PVR_LDM_PCI_MODULE) -static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice) -#endif -{ - SYS_DATA *psSysData; - - 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) - if (gPVRPowerLevel != 0) - { - if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK) - { - gPVRPowerLevel = 0; - } - } -#endif - (void) SysDeinitialise(psSysData); - - gpsPVRLDMDev = IMG_NULL; - -#if 0 /* INTEGRATION_POINT */ - /* See previous integration point for details. */ - if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK) - { - return -EINVAL; - } -#endif - -#if defined (PVR_LDM_PLATFORM_MODULE) - return 0; -#endif -#if defined (PVR_LDM_PCI_MODULE) - return; -#endif -} -#endif /* defined(PVR_LDM_MODULE) */ - - -#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM) -static PVRSRV_LINUX_MUTEX gsPMMutex; -static IMG_BOOL bDriverIsSuspended; -static IMG_BOOL bDriverIsShutdown; -#endif - -#if defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV) -/*! -****************************************************************************** - - @Function PVRSRVDriverShutdown - - @Description - - Suspend device operation for system shutdown. This is called as part of the - system halt/reboot process. The driver is put into a quiescent state by - setting the power state to D3. - - @input pDevice - the device for which shutdown is requested - - @Return nothing - -*****************************************************************************/ -#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \ - !defined(SUPPORT_DRI_DRM_PLUGIN) -void PVRSRVDriverShutdown(struct drm_device *pDevice) -#else -PVR_MOD_STATIC void PVRSRVDriverShutdown(LDM_DEV *pDevice) -#endif -{ - PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice)); - - LinuxLockMutex(&gsPMMutex); - - if (!bDriverIsShutdown && !bDriverIsSuspended) - { - /* - * Take the bridge mutex, and never release it, to stop - * processes trying to use the driver after it has been - * shutdown. - */ - LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); - - (void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3); - } - - bDriverIsShutdown = IMG_TRUE; - - /* The bridge mutex is held on exit */ - LinuxUnLockMutex(&gsPMMutex); -} - -#endif /* defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV) */ - - -#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM) -/*! -****************************************************************************** - - @Function PVRSRVDriverSuspend - - @Description - - For 2.6 kernels: - Suspend device operation. We always get three calls to this regardless of - the state (D1-D3) chosen. The order is SUSPEND_DISABLE, SUSPEND_SAVE_STATE - then SUSPEND_POWER_DOWN. We take action as soon as we get the disable call, - the other states not being handled by us yet. - - For MontaVista 2.4 kernels: - This call gets made once only when someone does something like - - # echo -e -n "suspend powerdown 0" >/sys.devices/legacy/pvrsrv0/power - - The 3rd, numeric parameter (0) in the above has no relevence and is not - passed into us. The state parameter is always zero and the level parameter - is always SUSPEND_POWER_DOWN. Vive la difference! - - @input pDevice - the device for which resume is requested - - @Return 0 for success or <0 for an error. - -*****************************************************************************/ -#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \ - !defined(SUPPORT_DRI_DRM_PLUGIN) -#if defined(SUPPORT_DRM_MODESET) -int PVRSRVDriverSuspend(struct pci_dev *pDevice, pm_message_t state) -#else -int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state) -#endif -#else -PVR_MOD_STATIC int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state) -#endif -{ - int res = 0; -#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)) - PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice)); - - LinuxLockMutex(&gsPMMutex); - - if (!bDriverIsSuspended && !bDriverIsShutdown) - { - LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); - - if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) == PVRSRV_OK) - { - /* The bridge mutex will be held until we resume */ - bDriverIsSuspended = IMG_TRUE; - } - else - { - LinuxUnLockMutex(&gPVRSRVLock); - res = -EINVAL; - } - } - - LinuxUnLockMutex(&gsPMMutex); -#endif - return res; -} - - -/*! -****************************************************************************** - - @Function PVRSRVDriverResume - - @Description - - Resume device operation following a lull due to earlier suspension. It is - implicit we're returning to D0 (fully operational) state. We always get three - calls to this using level thus: RESUME_POWER_ON, RESUME_RESTORE_STATE then - RESUME_ENABLE. On 2.6 kernels We don't do anything until we get the enable - call; on the MontaVista set-up we only ever get the RESUME_POWER_ON call. - - @input pDevice - the device for which resume is requested - - @Return 0 for success or <0 for an error. - -*****************************************************************************/ -#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \ - !defined(SUPPORT_DRI_DRM_PLUGIN) -#if defined(SUPPORT_DRM_MODESET) -int PVRSRVDriverResume(struct pci_dev *pDevice) -#else -int PVRSRVDriverResume(struct drm_device *pDevice) -#endif -#else -PVR_MOD_STATIC int PVRSRVDriverResume(LDM_DEV *pDevice) -#endif -{ - int res = 0; -#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)) - PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice)); - - LinuxLockMutex(&gsPMMutex); - - if (bDriverIsSuspended && !bDriverIsShutdown) - { - if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK) - { - bDriverIsSuspended = IMG_FALSE; - LinuxUnLockMutex(&gPVRSRVLock); - } - else - { - /* The bridge mutex is not released on failure */ - res = -EINVAL; - } - } - - LinuxUnLockMutex(&gsPMMutex); -#endif - return res; -} -#endif /* defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM) */ - - -#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM) -/* - * If PVR_LDM_PCI_MODULE is defined (and PVR_MANUAL_POWER_CONTROL is *NOT* defined), - * the device can be suspended and resumed without suspending/resuming the - * system, by writing values into the power/state sysfs file for the device. - * To suspend: - * echo -n 2 > power/state - * To Resume: - * echo -n 0 > power/state - * - * The problem with this approach is that the device is usually left - * powered up; it is the responsibility of the bus driver to remove - * the power. - * - * Defining PVR_MANUAL_POWER_CONTROL is intended to make it easier to - * debug power management issues, especially when power is really removed - * from the device. It is easier to debug the driver if it is not being - * suspended/resumed with the rest of the system. - * - * When PVR_MANUAL_POWER_CONTROL is defined, the following proc entry is - * created: - * /proc/pvr/power_control - * The driver suspend/resume entry points defined below no longer suspend or - * resume the device. To suspend the device, type the following: - * echo 2 > /proc/pvr/power_control - * To resume the device, type: - * echo 0 > /proc/pvr/power_control - * - * The following example shows how to suspend/resume the device independently - * of the rest of the system. - * Suspend the device: - * echo 2 > /proc/pvr/power_control - * Suspend the system. Then you should be able to suspend and resume - * as normal. To resume the device type the following: - * echo 0 > /proc/pvr/power_control - */ - -IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data) -{ - IMG_CHAR data_buffer[2]; - IMG_UINT32 PVRPowerLevel; - - if (count != sizeof(data_buffer)) - { - return -EINVAL; - } - else - { - if (copy_from_user(data_buffer, buffer, count)) - return -EINVAL; - if (data_buffer[count - 1] != '\n') - return -EINVAL; - PVRPowerLevel = data_buffer[0] - '0'; - if (PVRPowerLevel != gPVRPowerLevel) - { - if (PVRPowerLevel != 0) - { - if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK) - { - return -EINVAL; - } - } - else - { - if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK) - { - return -EINVAL; - } - } - - gPVRPowerLevel = PVRPowerLevel; - } - } - return (count); -} - -void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el) -{ - seq_printf(sfile, "%lu\n", gPVRPowerLevel); -} - -#endif - -/*! -****************************************************************************** - - @Function PVRSRVOpen - - @Description - - Release access the PVR services node - called when a file is closed, whether - at exit or using close(2) system call. - - @input pInode - the inode for the file being openeded - - @input pFile - the file handle data for the actual file being opened - - @Return 0 for success or <0 for an error. - -*****************************************************************************/ -#if defined(SUPPORT_DRI_DRM) -int PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile) -#else -static int PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile) -#endif -{ - PVRSRV_FILE_PRIVATE_DATA *psPrivateData; - IMG_HANDLE hBlockAlloc; - int iRet = -ENOMEM; - PVRSRV_ERROR eError; - IMG_UINT32 ui32PID; -#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) - PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc; -#endif - - LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); - - ui32PID = OSGetCurrentProcessIDKM(); - - if (PVRSRVProcessConnect(ui32PID, 0) != PVRSRV_OK) - goto err_unlock; - -#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) - psEnvPerProc = PVRSRVPerProcessPrivateData(ui32PID); - if (psEnvPerProc == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR, "%s: No per-process private data", __FUNCTION__)); - goto err_unlock; - } -#endif - - eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, - sizeof(PVRSRV_FILE_PRIVATE_DATA), - (IMG_PVOID *)&psPrivateData, - &hBlockAlloc, - "File Private Data"); - - 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; - - list_add_tail(&psPrivateData->sDRMAuthListItem, &psEnvPerProc->sDRMAuthListHead); -#endif - psPrivateData->ui32OpenPID = ui32PID; - psPrivateData->hBlockAlloc = hBlockAlloc; - PRIVATE_DATA(pFile) = psPrivateData; - iRet = 0; -err_unlock: - LinuxUnLockMutex(&gPVRSRVLock); - return iRet; -} - - -/*! -****************************************************************************** - - @Function PVRSRVRelease - - @Description - - Release access the PVR services node - called when a file is closed, whether - at exit or using close(2) system call. - - @input pInode - the inode for the file being released - - @input pFile - the file handle data for the actual file being released - - @Return 0 for success or <0 for an error. - -*****************************************************************************/ -#if defined(SUPPORT_DRI_DRM) -void PVRSRVRelease(void *pvPrivData) -#else -static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile) -#endif -{ - PVRSRV_FILE_PRIVATE_DATA *psPrivateData; - int err = 0; - - LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); - -#if defined(SUPPORT_DRI_DRM) - psPrivateData = (PVRSRV_FILE_PRIVATE_DATA *)pvPrivData; -#else - psPrivateData = PRIVATE_DATA(pFile); -#endif - if (psPrivateData != IMG_NULL) - { -#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) - list_del(&psPrivateData->sDRMAuthListItem); -#endif - - if(psPrivateData->hKernelMemInfo) - { - PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; - - /* Look up the meminfo we just exported */ - if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE, - (IMG_PVOID *)&psKernelMemInfo, - psPrivateData->hKernelMemInfo, - PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__)); - err = -EFAULT; - goto err_unlock; - } - - /* Tell the XProc about the export if required */ - if (psKernelMemInfo->sShareMemWorkaround.bInUse) - { - BM_XProcIndexRelease(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex); - } - - /* This drops the psMemInfo refcount bumped on export */ - if(FreeMemCallBackCommon(psKernelMemInfo, 0, - PVRSRV_FREE_CALLBACK_ORIGIN_EXTERNAL) != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: FreeMemCallBackCommon failed", __FUNCTION__)); - err = -EFAULT; - goto err_unlock; - } - } - - /* Usually this is the same as OSGetCurrentProcessIDKM(), - * but not necessarily (e.g. fork(), child closes last..) - */ - gui32ReleasePID = psPrivateData->ui32OpenPID; - PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID); - gui32ReleasePID = 0; - - OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, - sizeof(PVRSRV_FILE_PRIVATE_DATA), - psPrivateData, psPrivateData->hBlockAlloc); - -#if !defined(SUPPORT_DRI_DRM) - PRIVATE_DATA(pFile) = IMG_NULL; /*nulling shared pointer*/ -#endif - } - -err_unlock: - LinuxUnLockMutex(&gPVRSRVLock); -#if defined(SUPPORT_DRI_DRM) - return; -#else - return err; -#endif -} - - -/*! -****************************************************************************** - - @Function PVRCore_Init - - @Description - - Insert the driver into the kernel. - - The device major number is allocated by the kernel dynamically. This means - that the device node (nominally /dev/pvrsrv) will need to be re-made at boot - time if the number changes between subsequent loads of the module. While the - number often stays constant between loads this is not guaranteed. The node - is made as root on the shell with: - - mknod /dev/pvrsrv c nnn 0 - - where nnn is the major number found in /proc/devices for DEVNAME and also - reported by the PVR_DPF() - look at the boot log using dmesg' to see this). - - Currently the auto-generated script /etc/init.d/rc.pvr handles creation of - the device. In other environments the device may be created either through - devfs or sysfs. - - Readable proc-filesystem entries under /proc/pvr are created with - CreateProcEntries(). These can be read at runtime to get information about - the device (eg. 'cat /proc/pvr/vm') - - __init places the function in a special memory section that the kernel frees - once the function has been run. Refer also to module_init() macro call below. - - @input none - - @Return none - -*****************************************************************************/ -#if defined(SUPPORT_DRI_DRM) -int PVRCore_Init(void) -#else -static int __init PVRCore_Init(void) -#endif -{ - int error; -#if !defined(PVR_LDM_MODULE) - PVRSRV_ERROR eError; -#endif -#if !defined(SUPPORT_DRI_DRM) && defined(PVR_LDM_DEVICE_CLASS) - struct device *psDev; -#endif - -#if !defined(SUPPORT_DRI_DRM) - /* - * Must come before attempting to print anything via Services. - * For DRM, the initialisation will already have been done. - */ - PVRDPFInit(); -#endif - PVR_TRACE(("PVRCore_Init")); - -#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM) - LinuxInitMutex(&gsPMMutex); -#endif - LinuxInitMutex(&gPVRSRVLock); - - if (CreateProcEntries ()) - { - error = -ENOMEM; - return error; - } - - if (PVROSFuncInit() != PVRSRV_OK) - { - error = -ENOMEM; - goto init_failed; - } - - PVRLinuxMUtilsInit(); - - if(LinuxMMInit() != PVRSRV_OK) - { - error = -ENOMEM; - goto init_failed; - } - - LinuxBridgeInit(); - - PVRMMapInit(); - -#if defined(PVR_LDM_MODULE) - -#if defined(PVR_LDM_PLATFORM_MODULE) || defined(SUPPORT_DRI_DRM_PLUGIN) - if ((error = platform_driver_register(&powervr_driver)) != 0) - { - PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform driver (%d)", error)); - - goto init_failed; - } - -#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) - if ((error = platform_device_register(&powervr_device)) != 0) - { - platform_driver_unregister(&powervr_driver); - - PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform device (%d)", error)); - - goto init_failed; - } -#endif -#endif /* PVR_LDM_PLATFORM_MODULE */ - -#if defined(PVR_LDM_PCI_MODULE) - if ((error = pci_register_driver(&powervr_driver)) != 0) - { - PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error)); - - goto init_failed; - } -#endif /* PVR_LDM_PCI_MODULE */ -#endif /* defined(PVR_LDM_MODULE) */ - -#if !defined(PVR_LDM_MODULE) - /* - * Drivers using LDM, will call SysInitialise in the probe/attach code - */ - if ((eError = SysInitialise()) != PVRSRV_OK) - { - error = -ENODEV; -#if defined(TCF_REV) && (TCF_REV == 110) - if(eError == PVRSRV_ERROR_NOT_SUPPORTED) - { - printk("\nAtlas wrapper (FPGA image) version mismatch"); - error = -ENODEV; - } -#endif - goto init_failed; - } -#endif /* !defined(PVR_LDM_MODULE) */ - -#if !defined(SUPPORT_DRI_DRM) - AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops); - - if (AssignedMajorNumber <= 0) - { - PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to get major number")); - - error = -EBUSY; - goto sys_deinit; - } - - PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber)); - -#if defined(PVR_LDM_DEVICE_CLASS) - /* - * This code (using GPL symbols) facilitates automatic device - * node creation on platforms with udev (or similar). - */ - psPvrClass = class_create(THIS_MODULE, "pvr"); - - if (IS_ERR(psPvrClass)) - { - PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create class (%ld)", PTR_ERR(psPvrClass))); - error = -EBUSY; - goto unregister_device; - } - - psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0), -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) - NULL, -#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) */ - DEVNAME); - if (IS_ERR(psDev)) - { - PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create device (%ld)", PTR_ERR(psDev))); - error = -EBUSY; - goto destroy_class; - } -#endif /* defined(PVR_LDM_DEVICE_CLASS) */ -#endif /* !defined(SUPPORT_DRI_DRM) */ - - return 0; - -#if !defined(SUPPORT_DRI_DRM) -#if defined(PVR_LDM_DEVICE_CLASS) -destroy_class: - class_destroy(psPvrClass); -unregister_device: - unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME); -#endif -sys_deinit: -#endif -#if defined(PVR_LDM_MODULE) -#if defined(PVR_LDM_PCI_MODULE) - pci_unregister_driver(&powervr_driver); -#endif - -#if defined (PVR_LDM_PLATFORM_MODULE) -#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) - platform_device_unregister(&powervr_device); -#endif - platform_driver_unregister(&powervr_driver); -#endif - -#else /* defined(PVR_LDM_MODULE) */ - /* LDM drivers call SysDeinitialise during PVRSRVDriverRemove */ - { - SYS_DATA *psSysData; - - psSysData = SysAcquireDataNoCheck(); - if (psSysData != IMG_NULL) - { - (void) SysDeinitialise(psSysData); - } - } -#endif /* defined(PVR_LDM_MODULE) */ -init_failed: - PVRMMapCleanup(); - LinuxMMCleanup(); - LinuxBridgeDeInit(); - PVROSFuncDeInit(); - RemoveProcEntries(); - - return error; - -} /*PVRCore_Init*/ - - -/*! -***************************************************************************** - - @Function PVRCore_Cleanup - - @Description - - Remove the driver from the kernel. - - There's no way we can get out of being unloaded other than panicking; we - just do everything and plough on regardless of error. - - __exit places the function in a special memory section that the kernel frees - once the function has been run. Refer also to module_exit() macro call below. - - Note that the for LDM on MontaVista kernels, the positioning of the driver - de-registration is the opposite way around than would be suggested by the - registration case or the 2,6 kernel case. This is the correct way to do it - and the kernel panics if you change it. You have been warned. - - @input none - - @Return none - -*****************************************************************************/ -#if defined(SUPPORT_DRI_DRM) -void PVRCore_Cleanup(void) -#else -static void __exit PVRCore_Cleanup(void) -#endif -{ -#if !defined(PVR_LDM_MODULE) - SYS_DATA *psSysData; -#endif - PVR_TRACE(("PVRCore_Cleanup")); - -#if !defined(PVR_LDM_MODULE) - SysAcquireData(&psSysData); -#endif - -#if !defined(SUPPORT_DRI_DRM) - -#if defined(PVR_LDM_DEVICE_CLASS) - device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0)); - class_destroy(psPvrClass); -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) - if ( -#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */ - unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME) -#if !(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) - ; -#else /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */ - ) - { - PVR_DPF((PVR_DBG_ERROR," can't unregister device major %d", AssignedMajorNumber)); - } -#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */ -#endif /* !defined(SUPPORT_DRI_DRM) */ - -#if defined(PVR_LDM_MODULE) - -#if defined(PVR_LDM_PCI_MODULE) - pci_unregister_driver(&powervr_driver); -#endif - -#if defined (PVR_LDM_PLATFORM_MODULE) -#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) - platform_device_unregister(&powervr_device); -#endif - platform_driver_unregister(&powervr_driver); -#endif - -#else /* defined(PVR_LDM_MODULE) */ -#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) - if (gPVRPowerLevel != 0) - { - if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK) - { - gPVRPowerLevel = 0; - } - } -#endif - /* LDM drivers call SysDeinitialise during PVRSRVDriverRemove */ - (void) SysDeinitialise(psSysData); -#endif /* defined(PVR_LDM_MODULE) */ - - PVRMMapCleanup(); - - LinuxMMCleanup(); - - LinuxBridgeDeInit(); - - PVROSFuncDeInit(); - - RemoveProcEntries(); - - PVR_TRACE(("PVRCore_Cleanup: unloading")); -} - -/* - * 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. -*/ -#if !defined(SUPPORT_DRI_DRM) -module_init(PVRCore_Init); -module_exit(PVRCore_Cleanup); -#endif diff --git a/pvr-source/services4/srvkm/env/linux/mutex.c b/pvr-source/services4/srvkm/env/linux/mutex.c deleted file mode 100755 index a7e6c12..0000000 --- a/pvr-source/services4/srvkm/env/linux/mutex.c +++ /dev/null @@ -1,163 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux mutex interface -@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 <linux/version.h> -#include <linux/errno.h> -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) -#include <linux/mutex.h> -#else -#include <asm/semaphore.h> -#endif -#include <linux/module.h> - -#include <img_defs.h> -#include <services.h> - -#include "mutex.h" - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) - -IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) -{ - mutex_init(psPVRSRVMutex); -} - -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) - { - return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR; - } - else - { - return PVRSRV_OK; - } -} - -IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) -{ - return mutex_trylock(psPVRSRVMutex); -} - -IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) -{ - mutex_unlock(psPVRSRVMutex); -} - -IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) -{ - return (mutex_is_locked(psPVRSRVMutex)) ? IMG_TRUE : IMG_FALSE; -} - - -#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */ - - -IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) -{ - init_MUTEX(&psPVRSRVMutex->sSemaphore); - atomic_set(&psPVRSRVMutex->Count, 0); -} - -IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) -{ - down(&psPVRSRVMutex->sSemaphore); - 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) - { - /* The process was sent a signal while waiting for the semaphore - * (e.g. a kill signal from userspace) - */ - return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR; - }else{ - atomic_dec(&psPVRSRVMutex->Count); - return PVRSRV_OK; - } -} - -IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) -{ - IMG_INT32 Status = down_trylock(&psPVRSRVMutex->sSemaphore); - if(Status == 0) - { - atomic_dec(&psPVRSRVMutex->Count); - } - - return Status; -} - -IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) -{ - atomic_inc(&psPVRSRVMutex->Count); - up(&psPVRSRVMutex->sSemaphore); -} - -IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex) -{ - IMG_INT32 iCount; - - iCount = atomic_read(&psPVRSRVMutex->Count); - - return (IMG_BOOL)iCount; -} - -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */ - diff --git a/pvr-source/services4/srvkm/env/linux/mutex.h b/pvr-source/services4/srvkm/env/linux/mutex.h deleted file mode 100755 index 816cf4a..0000000 --- a/pvr-source/services4/srvkm/env/linux/mutex.h +++ /dev/null @@ -1,97 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux mutex interface -@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 __INCLUDED_LINUX_MUTEX_H_ -#define __INCLUDED_LINUX_MUTEX_H_ - -#include <linux/version.h> - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) -#include <linux/mutex.h> -#else -#include <asm/semaphore.h> -#endif - - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) - -typedef struct mutex PVRSRV_LINUX_MUTEX; - -#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */ - - -typedef struct { - struct semaphore sSemaphore; - /* since Linux's struct semaphore is intended to be - * opaque we don't poke inside for the count and - * instead we track it outselves. (So we can implement - * LinuxIsLockedMutex) - */ - atomic_t Count; -}PVRSRV_LINUX_MUTEX; - -#endif - -enum PVRSRV_MUTEX_LOCK_CLASS -{ - PVRSRV_LOCK_CLASS_BRIDGE, - PVRSRV_LOCK_CLASS_MMAP, -}; - -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); - -extern IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex); - -extern IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex); - - -#endif /* __INCLUDED_LINUX_MUTEX_H_ */ - diff --git a/pvr-source/services4/srvkm/env/linux/mutils.c b/pvr-source/services4/srvkm/env/linux/mutils.c deleted file mode 100755 index 8e57476..0000000 --- a/pvr-source/services4/srvkm/env/linux/mutils.c +++ /dev/null @@ -1,166 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux memory interface support 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 <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <asm/page.h> -#include <asm/pgtable.h> - -#include "img_defs.h" -#include "pvr_debug.h" -#include "mutils.h" - -#if defined(SUPPORT_LINUX_X86_PAT) -#define PAT_LINUX_X86_WC 1 - -#define PAT_X86_ENTRY_BITS 8 - -#define PAT_X86_BIT_PWT 1U -#define PAT_X86_BIT_PCD 2U -#define PAT_X86_BIT_PAT 4U -#define PAT_X86_BIT_MASK (PAT_X86_BIT_PAT | PAT_X86_BIT_PCD | PAT_X86_BIT_PWT) - -static IMG_BOOL g_write_combining_available = IMG_FALSE; - -#define PROT_TO_PAT_INDEX(v, B) ((v & _PAGE_ ## B) ? PAT_X86_BIT_ ## B : 0) - -static inline IMG_UINT -pvr_pat_index(pgprotval_t prot_val) -{ - IMG_UINT ret = 0; - pgprotval_t val = prot_val & _PAGE_CACHE_MASK; - - ret |= PROT_TO_PAT_INDEX(val, PAT); - ret |= PROT_TO_PAT_INDEX(val, PCD); - ret |= PROT_TO_PAT_INDEX(val, PWT); - - return ret; -} - -static inline IMG_UINT -pvr_pat_entry(u64 pat, IMG_UINT index) -{ - return (IMG_UINT)(pat >> (index * PAT_X86_ENTRY_BITS)) & PAT_X86_BIT_MASK; -} - -static IMG_VOID -PVRLinuxX86PATProbe(IMG_VOID) -{ - /* - * cpu_has_pat indicates whether PAT support is available on the CPU, - * but doesn't indicate if it has been enabled. - */ - if (cpu_has_pat) /* PRQA S 3335 */ /* ignore 'no function declared' */ - { - u64 pat; - IMG_UINT pat_index; - IMG_UINT pat_entry; - - PVR_TRACE(("%s: PAT available", __FUNCTION__)); - /* - * There is no Linux API for finding out if write combining - * is avaialable through the PAT, so we take the direct - * approach, and see if the PAT MSR contains a write combining - * entry. - */ - rdmsrl(MSR_IA32_CR_PAT, pat); - PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32))); - PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat))); - - pat_index = pvr_pat_index(_PAGE_CACHE_WC); - PVR_TRACE(("%s: PAT index for write combining: %u", __FUNCTION__, pat_index)); - - pat_entry = pvr_pat_entry(pat, pat_index); - PVR_TRACE(("%s: PAT entry for write combining: 0x%.2x (should be 0x%.2x)", __FUNCTION__, pat_entry, PAT_LINUX_X86_WC)); - -#if defined(SUPPORT_LINUX_X86_WRITECOMBINE) - g_write_combining_available = (IMG_BOOL)(pat_entry == PAT_LINUX_X86_WC); -#endif - } -#if defined(DEBUG) -#if defined(SUPPORT_LINUX_X86_WRITECOMBINE) - if (g_write_combining_available) - { - PVR_TRACE(("%s: Write combining available via PAT", __FUNCTION__)); - } - else - { - PVR_TRACE(("%s: Write combining not available", __FUNCTION__)); - } -#else /* defined(SUPPORT_LINUX_X86_WRITECOMBINE) */ - PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__)); -#endif /* defined(SUPPORT_LINUX_X86_WRITECOMBINE) */ -#endif /* DEBUG */ -} - -pgprot_t -pvr_pgprot_writecombine(pgprot_t prot) -{ - /* - * It would be worth checking from time to time to see if a - * pgprot_writecombine function (or similar) is introduced on Linux for - * x86 processors. If so, this function, and PVRLinuxX86PATProbe can be - * removed, and a macro used to select between pgprot_writecombine and - * pgprot_noncached, dpending on the value for of - * SUPPORT_LINUX_X86_WRITECOMBINE. - */ - /* PRQA S 0481,0482 2 */ /* scalar expressions */ - return (g_write_combining_available) ? - __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot); -} -#endif /* defined(SUPPORT_LINUX_X86_PAT) */ - -IMG_VOID -PVRLinuxMUtilsInit(IMG_VOID) -{ -#if defined(SUPPORT_LINUX_X86_PAT) - PVRLinuxX86PATProbe(); -#endif -} - diff --git a/pvr-source/services4/srvkm/env/linux/mutils.h b/pvr-source/services4/srvkm/env/linux/mutils.h deleted file mode 100755 index 891598c..0000000 --- a/pvr-source/services4/srvkm/env/linux/mutils.h +++ /dev/null @@ -1,119 +0,0 @@ -/*************************************************************************/ /*! -@Title Memory management support utils -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Declares various memory management support functions - for Linux. -@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 __IMG_LINUX_MUTILS_H__ -#define __IMG_LINUX_MUTILS_H__ - -#include <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#if !(defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))) -#if defined(SUPPORT_LINUX_X86_PAT) -#undef SUPPORT_LINUX_X86_PAT -#endif -#endif - -#if defined(SUPPORT_LINUX_X86_PAT) - pgprot_t pvr_pgprot_writecombine(pgprot_t prot); - #define PGPROT_WC(pv) pvr_pgprot_writecombine(pv) -#else - #if defined(__arm__) || defined(__sh__) - #define PGPROT_WC(pv) pgprot_writecombine(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 - #endif -#endif - -#define PGPROT_UC(pv) pgprot_noncached(pv) - -#if defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) - #define IOREMAP(pa, bytes) ioremap_cache(pa, bytes) -#else - #if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) - #define IOREMAP(pa, bytes) ioremap_cached(pa, bytes) - #else - #define IOREMAP(pa, bytes) ioremap(pa, bytes) - #endif -#endif - -#if defined(SUPPORT_LINUX_X86_PAT) - #if defined(SUPPORT_LINUX_X86_WRITECOMBINE) - #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes) - #else - #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes) - #endif -#else - #if defined(__arm__) - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) - #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes) - #else - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) - #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes) - #else - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)) - #define IOREMAP_WC(pa, bytes) __ioremap(pa, bytes, L_PTE_BUFFERABLE) - #else - #define IOREMAP_WC(pa, bytes) __ioremap(pa, bytes, , L_PTE_BUFFERABLE, 1) - #endif - #endif - #endif - #else - #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes) - #endif -#endif - -#define IOREMAP_UC(pa, bytes) ioremap_nocache(pa, bytes) - -IMG_VOID PVRLinuxMUtilsInit(IMG_VOID); - -#endif /* __IMG_LINUX_MUTILS_H__ */ - diff --git a/pvr-source/services4/srvkm/env/linux/osfunc.c b/pvr-source/services4/srvkm/env/linux/osfunc.c deleted file mode 100755 index 4c39621..0000000 --- a/pvr-source/services4/srvkm/env/linux/osfunc.c +++ /dev/null @@ -1,4714 +0,0 @@ -/*************************************************************************/ /*! -@Title Environment 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 <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#include <asm/io.h> -#include <asm/page.h> -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) -#include <asm/system.h> -#endif -#include <asm/cacheflush.h> -#include <linux/mm.h> -#include <linux/pagemap.h> -#include <linux/hugetlb.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/delay.h> -#include <linux/pci.h> - -#include <linux/string.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <asm/hardirq.h> -#include <linux/timer.h> -#include <linux/capability.h> -#include <asm/uaccess.h> -#include <linux/spinlock.h> -#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || \ - defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) || \ - defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || \ - defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) || \ - defined(PVR_LINUX_USING_WORKQUEUES) -#include <linux/workqueue.h> -#endif - -#include "img_types.h" -#include "services_headers.h" -#include "mm.h" -#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 (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 -#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait) -#endif - -#if defined(PVR_LINUX_USING_WORKQUEUES) && !defined(CONFIG_PREEMPT) -/* - * Services spins at certain points waiting for events (e.g. swap - * chain destrucion). If those events rely on workqueues running, - * it needs to be possible to preempt the waiting thread. - * Removing the need for CONFIG_PREEMPT will require adding preemption - * points at various points in Services. - */ -#error "A preemptible Linux kernel is required when using workqueues" -#endif - -#if defined(EMULATOR) -#define EVENT_OBJECT_TIMEOUT_MS (2000) -#else -#define EVENT_OBJECT_TIMEOUT_MS (100) -#endif /* EMULATOR */ - -#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) -PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, 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) -#endif -{ - PVR_UNREFERENCED_PARAMETER(ui32Flags); - PVR_UNREFERENCED_PARAMETER(phBlockAlloc); - - if (ui32Size > PAGE_SIZE) - { - /* Try to allocate the memory using vmalloc */ -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename, ui32Line); -#else - *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED); -#endif - if (*ppvCpuVAddr) - { - return PVRSRV_OK; - } - } - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - *ppvCpuVAddr = _KMallocWrapper(ui32Size, GFP_KERNEL | __GFP_NOWARN, pszFilename, ui32Line); -#else - *ppvCpuVAddr = KMallocWrapper(ui32Size, GFP_KERNEL | __GFP_NOWARN); -#endif - if (!*ppvCpuVAddr) - { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - - return PVRSRV_OK; -} - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)) - -static inline int is_vmalloc_addr(const void *pvCpuVAddr) -{ - unsigned long lAddr = (unsigned long)pvCpuVAddr; - return lAddr >= VMALLOC_START && lAddr < VMALLOC_END; -} - -#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) -#else -PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line) -#endif -{ - PVR_UNREFERENCED_PARAMETER(ui32Flags); - PVR_UNREFERENCED_PARAMETER(ui32Size); - PVR_UNREFERENCED_PARAMETER(hBlockAlloc); - - if (is_vmalloc_addr(pvCpuVAddr)) - { -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line); -#else - VFreeWrapper(pvCpuVAddr); -#endif - } - else - { -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - _KFreeWrapper(pvCpuVAddr, pszFilename, ui32Line); -#else - KFreeWrapper(pvCpuVAddr); -#endif - } - - return PVRSRV_OK; -} - - -PVRSRV_ERROR -OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags, - IMG_UINT32 ui32Size, - IMG_UINT32 ui32PageSize, - IMG_PVOID pvPrivData, - IMG_UINT32 ui32PrivDataLength, - IMG_HANDLE hBMHandle, - IMG_VOID **ppvCpuVAddr, - IMG_HANDLE *phOSMemHandle) -{ - LinuxMemArea *psLinuxMemArea; - - PVR_UNREFERENCED_PARAMETER(ui32PageSize); - -#if 0 - /* For debug: force all OSAllocPages allocations to have a kernel - * virtual address */ - if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS) - { - ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS; - ui32AllocFlags |= PVRSRV_HAP_MULTI_PROCESS; - } -#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); - if(!psLinuxMemArea) - { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - break; - } - case PVRSRV_HAP_SINGLE_PROCESS: - { - /* 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); - if(!psLinuxMemArea) - { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - PVRMMapRegisterArea(psLinuxMemArea); - break; - } - - case PVRSRV_HAP_MULTI_PROCESS: - { - /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel - * virtual mapping and potentially multiple user space virtual - * mappings: Note: these eat into our limited kernel virtual - * address space. */ - -#if defined(VIVT_CACHE) || defined(__sh__) - /* ARM9 caches are tagged with virtual pages, not physical. As we are going to - * share this memory in different address spaces, we don't want it to be cached. - * ARM11 has physical tagging, so we can cache this memory without fear of virtual - * address aliasing in the TLB, as long as the kernel supports cache colouring for - * VIPT architectures. */ - ui32AllocFlags &= ~PVRSRV_HAP_CACHED; -#endif - psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags); - if(!psLinuxMemArea) - { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - PVRMMapRegisterArea(psLinuxMemArea); - break; - } - default: - PVR_DPF((PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n", ui32AllocFlags)); - *ppvCpuVAddr = NULL; - *phOSMemHandle = (IMG_HANDLE)0; - return PVRSRV_ERROR_INVALID_PARAMS; - } - - /* - In case of sparse mapping we need to handle back to the BM as it - knows the mapping info - */ - if (ui32AllocFlags & PVRSRV_MEM_SPARSE) - { - psLinuxMemArea->hBMHandle = hBMHandle; - } - -ExitSkipSwitch: - *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea); - *phOSMemHandle = psLinuxMemArea; - - LinuxMemAreaRegister(psLinuxMemArea); - - return PVRSRV_OK; -} - - -PVRSRV_ERROR -OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle) -{ - LinuxMemArea *psLinuxMemArea; - PVRSRV_ERROR eError; - - PVR_UNREFERENCED_PARAMETER(ui32Bytes); - PVR_UNREFERENCED_PARAMETER(pvCpuVAddr); - - psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - - switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) - { - case PVRSRV_HAP_KERNEL_ONLY: - break; - case PVRSRV_HAP_SINGLE_PROCESS: - case PVRSRV_HAP_MULTI_PROCESS: - eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, - "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%d, " - "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!", - ui32AllocFlags, ui32Bytes, pvCpuVAddr, hOSMemHandle)); - return eError; - } - break; - default: - PVR_DPF((PVR_DBG_ERROR,"%s: invalid flags 0x%x\n", - __FUNCTION__, ui32AllocFlags)); - return PVRSRV_ERROR_INVALID_PARAMS; - } - - LinuxMemAreaDeepFree(psLinuxMemArea); - - 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_UINT32 ui32Flags, - IMG_HANDLE *phOSMemHandleRet) -{ - LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea; - PVRSRV_ERROR eError; - - psParentLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - - psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes); - if(!psLinuxMemArea) - { - *phOSMemHandleRet = NULL; - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - *phOSMemHandleRet = psLinuxMemArea; - - /* KERNEL_ONLY areas are never mmapable. */ - if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY) - { - return PVRSRV_OK; - } - - eError = PVRMMapRegisterArea(psLinuxMemArea); - if(eError != PVRSRV_OK) - { - goto failed_register_area; - } - - return PVRSRV_OK; - -failed_register_area: - *phOSMemHandleRet = NULL; - LinuxMemAreaDeepFree(psLinuxMemArea); - return eError; -} - -PVRSRV_ERROR -OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags) -{ - LinuxMemArea *psLinuxMemArea; - PVRSRV_ERROR eError; - - psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC); - - if((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0) - { - eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea); - if(eError != PVRSRV_OK) - { - return eError; - } - } - LinuxMemAreaDeepFree(psLinuxMemArea); - - return PVRSRV_OK; -} - - -IMG_CPU_PHYADDR -OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset) -{ - PVR_ASSERT(hOSMemHandle); - - return LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset); -} - - -IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle) -{ - LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - - PVR_ASSERT(psLinuxMemArea); - - if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV) - return psLinuxMemArea->uData.sExternalKV.bPhysContig; - - return IMG_FALSE; -} - - -/*! -****************************************************************************** - - @Function OSMemCopy - - @Description Copies memory around - - @Input pvDst - pointer to dst - @Output pvSrc - pointer to src - @Input ui32Size - bytes to copy - - @Return none - -******************************************************************************/ -IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size) -{ -#if defined(USE_UNOPTIMISED_MEMCPY) - IMG_UINT8 *Src,*Dst; - IMG_INT i; - - Src=(IMG_UINT8 *)pvSrc; - Dst=(IMG_UINT8 *)pvDst; - for(i=0;i<ui32Size;i++) - { - Dst[i]=Src[i]; - } -#else - memcpy(pvDst, pvSrc, ui32Size); -#endif -} - - -/*! -****************************************************************************** - - @Function OSMemSet - - @Description Function that does the same as the C memset() functions - - @Modified *pvDest : pointer to start of buffer to be set - - @Input ui8Value: value to set each byte to - - @Input ui32Size : number of bytes to set - - @Return IMG_VOID - -******************************************************************************/ -IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size) -{ -#if defined(USE_UNOPTIMISED_MEMSET) - IMG_UINT8 *Buff; - IMG_INT i; - - Buff=(IMG_UINT8 *)pvDest; - for(i=0;i<ui32Size;i++) - { - Buff[i]=ui8Value; - } -#else - memset(pvDest, (IMG_INT) ui8Value, (size_t) ui32Size); -#endif -} - - -/*! -****************************************************************************** - @Function OSStringCopy - @Description strcpy -******************************************************************************/ -IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc) -{ - return (strcpy(pszDest, pszSrc)); -} - -/*! -****************************************************************************** - @Function OSSNPrintf - @Description snprintf -******************************************************************************/ -IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...) -{ - va_list argList; - IMG_INT32 iCount; - - va_start(argList, pszFormat); - iCount = vsnprintf(pStr, (size_t)ui32Size, pszFormat, argList); - va_end(argList); - - return iCount; -} - -/*! -****************************************************************************** - - @Function OSBreakResourceLock - - @Description unlocks an OS dependant resource - - @Input phResource - pointer to OS dependent resource structure - @Input ui32ID - Lock value to look for - - @Return - -******************************************************************************/ -IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID) -{ - volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock; - - if(*pui32Access) - { - if(psResource->ui32ID == ui32ID) - { - psResource->ui32ID = 0; - *pui32Access = 0; - } - else - { - PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked for this process.")); - } - } - else - { - PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked")); - } -} - - -/*! -****************************************************************************** - - @Function OSCreateResource - - @Description creates a OS dependant resource object - - @Input phResource - pointer to OS dependent resource - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource) -{ - psResource->ui32ID = 0; - psResource->ui32Lock = 0; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSDestroyResource - - @Description destroys an OS dependant resource object - - @Input phResource - pointer to OS dependent resource - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource) -{ - OSBreakResourceLock (psResource, psResource->ui32ID); - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSInitEnvData - - @Description Allocates space for env specific data - - @Input ppvEnvSpecificData - pointer to pointer in which to return - allocated data. - @Input ui32MMUMode - MMU mode. - - @Return nothing - -******************************************************************************/ -PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData) -{ - ENV_DATA *psEnvData; - PVRSRV_ERROR eError; - - /* allocate env specific data */ - eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL, - "Environment Data"); - if (eError != PVRSRV_OK) - { - return eError; - } - - eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, - &psEnvData->pvBridgeData, IMG_NULL, - "Bridge Data"); - if (eError != PVRSRV_OK) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL); - /*not nulling pointer, out of scope*/ - return eError; - } - - - /* ISR installation flags */ - psEnvData->bMISRInstalled = IMG_FALSE; - psEnvData->bLISRInstalled = IMG_FALSE; - - /* copy structure back */ - *ppvEnvSpecificData = psEnvData; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSDeInitEnvData - - @Description frees env specific data memory - - @Input pvEnvSpecificData - pointer to private structure - - @Return PVRSRV_OK on success else PVRSRV_ERROR_OUT_OF_MEMORY - -******************************************************************************/ -PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData) -{ - ENV_DATA *psEnvData = (ENV_DATA*)pvEnvSpecificData; - - PVR_ASSERT(!psEnvData->bMISRInstalled); - PVR_ASSERT(!psEnvData->bLISRInstalled); - - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, psEnvData->pvBridgeData, IMG_NULL); - psEnvData->pvBridgeData = IMG_NULL; - - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL); - /*not nulling pointer, copy on stack*/ - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSReleaseThreadQuanta - - @Description - Releases thread quanta - - @Return nothing - -******************************************************************************/ -IMG_VOID OSReleaseThreadQuanta(IMG_VOID) -{ - schedule(); -} - - -/*! -****************************************************************************** - - @Function OSClockus - - @Description - This function returns the clock in microseconds - - @Input void - - @Return - clock (us) - -******************************************************************************/ -IMG_UINT32 OSClockus(IMG_VOID) -{ - IMG_UINT32 time, j = jiffies; - - time = j * (1000000 / HZ); - - return time; -} - - -IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus) -{ - udelay(ui32Timeus); -} - - -IMG_VOID OSSleepms(IMG_UINT32 ui32Timems) -{ - msleep(ui32Timems); -} - - -/*! -****************************************************************************** - - @Function OSFuncHighResTimerCreate - - @Description - This function creates a high res timer who's handle is returned - - @Input nothing - - @Return handle - -******************************************************************************/ -IMG_HANDLE OSFuncHighResTimerCreate(IMG_VOID) -{ - /* We don't need a handle, but we must return non-NULL */ - return (IMG_HANDLE) 1; -} - -/*! -****************************************************************************** - - @Function OSFuncHighResTimerGetus - - @Description - This function returns the current timestamp in us - - @Input nothing - - @Return handle - -******************************************************************************/ -IMG_UINT32 OSFuncHighResTimerGetus(IMG_HANDLE hTimer) -{ - return (IMG_UINT32) jiffies_to_usecs(jiffies); -} - -/*! -****************************************************************************** - - @Function OSFuncHighResTimerDestroy - - @Description - This function will destroy the high res timer - - @Input nothing - - @Return handle - -******************************************************************************/ -IMG_VOID OSFuncHighResTimerDestroy(IMG_HANDLE hTimer) -{ - PVR_UNREFERENCED_PARAMETER(hTimer); -} - -/*! -****************************************************************************** - - @Function OSGetCurrentProcessIDKM - - @Description Returns handle for current process - - @Return ID of current process - -*****************************************************************************/ -IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID) -{ - if (in_interrupt()) - { - return KERNEL_ID; - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) - return (IMG_UINT32)current->pgrp; -#else -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)) - return (IMG_UINT32)task_tgid_nr(current); -#else - return (IMG_UINT32)current->tgid; -#endif -#endif -} - - -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; - - res = pvr_access_process_vm(task, mm->arg_start, buffer, len, 0); - - // 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; -} - -const char* OSGetPathBaseName(char * buffer, int buff_size) -{ - 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; -} - - -/*! -****************************************************************************** - - @Function OSGetPageSize - - @Description gets page size - - @Return page size - -******************************************************************************/ -IMG_UINT32 OSGetPageSize(IMG_VOID) -{ -#if defined(__sh__) - IMG_UINT32 ui32ReturnValue = PAGE_SIZE; - - return (ui32ReturnValue); -#else - return PAGE_SIZE; -#endif -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) -/*! -****************************************************************************** - - @Function DeviceISRWrapper - - @Description wrapper for Device ISR function to conform to ISR OS interface - - @Return - -******************************************************************************/ -static irqreturn_t DeviceISRWrapper(int irq, void *dev_id -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) - , struct pt_regs *regs -#endif - ) -{ - PVRSRV_DEVICE_NODE *psDeviceNode; - IMG_BOOL bStatus = IMG_FALSE; - - PVR_UNREFERENCED_PARAMETER(irq); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) - PVR_UNREFERENCED_PARAMETER(regs); -#endif - psDeviceNode = (PVRSRV_DEVICE_NODE*)dev_id; - if(!psDeviceNode) - { - PVR_DPF((PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n")); - goto out; - } - - bStatus = PVRSRVDeviceLISR(psDeviceNode); - - if (bStatus) - { - OSScheduleMISR((IMG_VOID *)psDeviceNode->psSysData); - } - -out: -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) - return bStatus ? IRQ_HANDLED : IRQ_NONE; -#endif -} - - - -/*! -****************************************************************************** - - @Function SystemISRWrapper - - @Description wrapper for System ISR function to conform to ISR OS interface - - @Input Interrupt - NT interrupt object. - @Input Context - Context parameter - - @Return - -******************************************************************************/ -static irqreturn_t SystemISRWrapper(int irq, void *dev_id -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) - , struct pt_regs *regs -#endif - ) -{ - SYS_DATA *psSysData; - IMG_BOOL bStatus = IMG_FALSE; - - PVR_UNREFERENCED_PARAMETER(irq); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) - PVR_UNREFERENCED_PARAMETER(regs); -#endif - psSysData = (SYS_DATA *)dev_id; - if(!psSysData) - { - PVR_DPF((PVR_DBG_ERROR, "SystemISRWrapper: invalid params\n")); - goto out; - } - - bStatus = PVRSRVSystemLISR(psSysData); - - if (bStatus) - { - OSScheduleMISR((IMG_VOID *)psSysData); - } - -out: -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) - return bStatus ? IRQ_HANDLED : IRQ_NONE; -#endif -} -/*! -****************************************************************************** - - @Function OSInstallDeviceLISR - - @Description Installs a Device ISR - - @Input pvSysData - @Input ui32Irq - IRQ number - @Input pszISRName - ISR name - @Input pvDeviceNode - device node contains ISR function and data argument - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData, - IMG_UINT32 ui32Irq, - IMG_CHAR *pszISRName, - IMG_VOID *pvDeviceNode) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (psEnvData->bLISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSInstallDeviceLISR: An ISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie)); - return PVRSRV_ERROR_ISR_ALREADY_INSTALLED; - } - - PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %p", pszISRName, ui32Irq, pvDeviceNode)); - - if(request_irq(ui32Irq, DeviceISRWrapper, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)) - SA_SHIRQ -#else - IRQF_SHARED -#endif - , pszISRName, pvDeviceNode)) - { - PVR_DPF((PVR_DBG_ERROR,"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", ui32Irq)); - - return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR; - } - - psEnvData->ui32IRQ = ui32Irq; - psEnvData->pvISRCookie = pvDeviceNode; - psEnvData->bLISRInstalled = IMG_TRUE; - - return PVRSRV_OK; -} - -/*! -****************************************************************************** - - @Function OSUninstallDeviceLISR - - @Description Uninstalls a Device ISR - - @Input pvSysData - sysdata - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (!psEnvData->bLISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSUninstallDeviceLISR: No LISR has been installed")); - return PVRSRV_ERROR_ISR_NOT_INSTALLED; - } - - PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie)); - - free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie); - - psEnvData->bLISRInstalled = IMG_FALSE; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSInstallSystemLISR - - @Description Installs a System ISR - - @Input psSysData - @Input ui32Irq - IRQ number - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (psEnvData->bLISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSInstallSystemLISR: An LISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie)); - return PVRSRV_ERROR_ISR_ALREADY_INSTALLED; - } - - PVR_TRACE(("Installing system LISR on IRQ %d with cookie %p", ui32Irq, pvSysData)); - - if(request_irq(ui32Irq, SystemISRWrapper, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)) - SA_SHIRQ -#else - IRQF_SHARED -#endif - , PVRSRV_MODNAME, pvSysData)) - { - PVR_DPF((PVR_DBG_ERROR,"OSInstallSystemLISR: Couldn't install system LISR on IRQ %d", ui32Irq)); - - return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR; - } - - psEnvData->ui32IRQ = ui32Irq; - psEnvData->pvISRCookie = pvSysData; - psEnvData->bLISRInstalled = IMG_TRUE; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSUninstallSystemLISR - - @Description Uninstalls a System ISR - - @Input psSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (!psEnvData->bLISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSUninstallSystemLISR: No LISR has been installed")); - return PVRSRV_ERROR_ISR_NOT_INSTALLED; - } - - PVR_TRACE(("Uninstalling system LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie)); - - free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie); - - psEnvData->bLISRInstalled = IMG_FALSE; - - return PVRSRV_OK; -} - -#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) -/*! -****************************************************************************** - - @Function MISRWrapper - - @Description OS dependent MISR wrapper - - @Input psSysData - - @Return error status - -******************************************************************************/ -static void MISRWrapper( -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) - void *data -#else - struct work_struct *data -#endif -) -{ - ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork); - SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData; - - PVRSRVMISR(psSysData); -} - - -/*! -****************************************************************************** - - @Function OSInstallMISR - - @Description Installs an OS dependent MISR - - @Input psSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (psEnvData->bMISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed")); - return PVRSRV_ERROR_ISR_ALREADY_INSTALLED; - } - - PVR_TRACE(("Installing MISR with cookie %p", pvSysData)); - - psEnvData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue"); - - if (psEnvData->psWorkQueue == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: create_singlethreaded_workqueue failed")); - return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD; - } - - INIT_WORK(&psEnvData->sMISRWork, MISRWrapper -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) - , (void *)&psEnvData->sMISRWork -#endif - ); - - psEnvData->pvMISRData = pvSysData; - psEnvData->bMISRInstalled = IMG_TRUE; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSUninstallMISR - - @Description Uninstalls an OS dependent MISR - - @Input psSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (!psEnvData->bMISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed")); - return PVRSRV_ERROR_ISR_NOT_INSTALLED; - } - - PVR_TRACE(("Uninstalling MISR")); - - destroy_workqueue(psEnvData->psWorkQueue); - - psEnvData->bMISRInstalled = IMG_FALSE; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSScheduleMISR - - @Description Schedules an OS dependent MISR - - @Input pvSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData; - - if (psEnvData->bMISRInstalled) - { - queue_work(psEnvData->psWorkQueue, &psEnvData->sMISRWork); - } - - return PVRSRV_OK; -} -#else /* defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */ -#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) -/*! -****************************************************************************** - - @Function MISRWrapper - - @Description OS dependent MISR wrapper - - @Input psSysData - - @Return error status - -******************************************************************************/ -static void MISRWrapper( -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) - void *data -#else - struct work_struct *data -#endif -) -{ - ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork); - SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData; - - PVRSRVMISR(psSysData); -} - - -/*! -****************************************************************************** - - @Function OSInstallMISR - - @Description Installs an OS dependent MISR - - @Input psSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (psEnvData->bMISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed")); - return PVRSRV_ERROR_ISR_ALREADY_INSTALLED; - } - - PVR_TRACE(("Installing MISR with cookie %p", pvSysData)); - - INIT_WORK(&psEnvData->sMISRWork, MISRWrapper -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) - , (void *)&psEnvData->sMISRWork -#endif - ); - - psEnvData->pvMISRData = pvSysData; - psEnvData->bMISRInstalled = IMG_TRUE; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSUninstallMISR - - @Description Uninstalls an OS dependent MISR - - @Input psSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (!psEnvData->bMISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed")); - return PVRSRV_ERROR_ISR_NOT_INSTALLED; - } - - PVR_TRACE(("Uninstalling MISR")); - - flush_scheduled_work(); - - psEnvData->bMISRInstalled = IMG_FALSE; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSScheduleMISR - - @Description Schedules an OS dependent MISR - - @Input pvSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData; - - if (psEnvData->bMISRInstalled) - { - schedule_work(&psEnvData->sMISRWork); - } - - return PVRSRV_OK; -} - -#else /* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */ - - -/*! -****************************************************************************** - - @Function MISRWrapper - - @Description OS dependent MISR wrapper - - @Input psSysData - - @Return error status - -******************************************************************************/ -static void MISRWrapper(unsigned long data) -{ - SYS_DATA *psSysData; - - psSysData = (SYS_DATA *)data; - - PVRSRVMISR(psSysData); -} - - -/*! -****************************************************************************** - - @Function OSInstallMISR - - @Description Installs an OS dependent MISR - - @Input psSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (psEnvData->bMISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed")); - return PVRSRV_ERROR_ISR_ALREADY_INSTALLED; - } - - PVR_TRACE(("Installing MISR with cookie %p", pvSysData)); - - tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper, (unsigned long)pvSysData); - - psEnvData->bMISRInstalled = IMG_TRUE; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSUninstallMISR - - @Description Uninstalls an OS dependent MISR - - @Input psSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData; - - if (!psEnvData->bMISRInstalled) - { - PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed")); - return PVRSRV_ERROR_ISR_NOT_INSTALLED; - } - - PVR_TRACE(("Uninstalling MISR")); - - tasklet_kill(&psEnvData->sMISRTasklet); - - psEnvData->bMISRInstalled = IMG_FALSE; - - return PVRSRV_OK; -} - -/*! -****************************************************************************** - - @Function OSScheduleMISR - - @Description Schedules an OS dependent MISR - - @Input pvSysData - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData) -{ - SYS_DATA *psSysData = (SYS_DATA*)pvSysData; - ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData; - - if (psEnvData->bMISRInstalled) - { - tasklet_schedule(&psEnvData->sMISRTasklet); - } - - return PVRSRV_OK; -} - -#endif /* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */ -#endif /* #if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */ - -#endif /* #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) */ - -IMG_VOID OSPanic(IMG_VOID) -{ - BUG(); -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) -#define OS_TAS(p) xchg((p), 1) -#else -#define OS_TAS(p) tas(p) -#endif -/*! -****************************************************************************** - - @Function OSLockResource - - @Description locks an OS dependant Resource - - @Input phResource - pointer to OS dependent Resource - @Input bBlock - do we want to block? - - @Return error status - -******************************************************************************/ -PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE *psResource, - IMG_UINT32 ui32ID) - -{ - PVRSRV_ERROR eError = PVRSRV_OK; - - if(!OS_TAS(&psResource->ui32Lock)) - psResource->ui32ID = ui32ID; - else - eError = PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE; - - return eError; -} - - -/*! -****************************************************************************** - - @Function OSUnlockResource - - @Description unlocks an OS dependant resource - - @Input phResource - pointer to OS dependent resource structure - - @Return - -******************************************************************************/ -PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID) -{ - volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock; - PVRSRV_ERROR eError = PVRSRV_OK; - - if(*pui32Access) - { - if(psResource->ui32ID == ui32ID) - { - psResource->ui32ID = 0; - smp_mb(); - *pui32Access = 0; - } - else - { - PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked with expected value.", psResource)); - PVR_DPF((PVR_DBG_MESSAGE,"Should be %x is actually %x", ui32ID, psResource->ui32ID)); - eError = PVRSRV_ERROR_INVALID_LOCK_ID; - } - } - else - { - PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked", psResource)); - eError = PVRSRV_ERROR_RESOURCE_NOT_LOCKED; - } - - return eError; -} - - -/*! -****************************************************************************** - - @Function OSIsResourceLocked - - @Description tests if resource is locked - - @Input phResource - pointer to OS dependent resource structure - - @Return error status - -******************************************************************************/ -IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID) -{ - volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock; - - return (*(volatile IMG_UINT32 *)pui32Access == 1) && (psResource->ui32ID == ui32ID) - ? IMG_TRUE - : IMG_FALSE; -} - - -#if !defined(SYS_CUSTOM_POWERLOCK_WRAP) -PVRSRV_ERROR OSPowerLockWrap(IMG_BOOL bTryLock) -{ - PVR_UNREFERENCED_PARAMETER(bTryLock); - - return PVRSRV_OK; -} - -IMG_VOID OSPowerLockUnwrap (IMG_VOID) -{ -} -#endif /* SYS_CUSTOM_POWERLOCK_WRAP */ - - -IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle, - IMG_VOID *pvLinAddr) -{ - IMG_CPU_PHYADDR CpuPAddr; - LinuxMemArea *psLinuxMemArea; - IMG_UINTPTR_T uiByteOffset; - IMG_UINT32 ui32ByteOffset; - - PVR_ASSERT(hOSMemHandle != IMG_NULL); - - psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - - uiByteOffset = (IMG_UINTPTR_T)pvLinAddr - (IMG_UINTPTR_T)LinuxMemAreaToCpuVAddr(psLinuxMemArea); - ui32ByteOffset = (IMG_UINT32)uiByteOffset; - - CpuPAddr = LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset); - - return CpuPAddr; -} - - -/*! -****************************************************************************** - - @Function OSMapPhysToLin - - @Description Maps the physical memory into linear addr range - - @Input BasePAddr : physical cpu address - - @Input ui32Bytes - bytes to map - - @Input ui32CacheType - cache type - - @Return : Linear addr of mapping on success, else NULL - - ******************************************************************************/ -IMG_VOID * -OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, - IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32MappingFlags, - IMG_HANDLE *phOSMemHandle) -{ - if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY) - { - /* - * Provide some backwards compatibility, until all callers - * have been updated to pass a non-null OSMemHandle pointer. - * Such callers must not call OSMapLinToCPUPhys. - */ - if(phOSMemHandle == IMG_NULL) - { - IMG_VOID *pvIORemapCookie; - pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags); - if(pvIORemapCookie == IMG_NULL) - { - return IMG_NULL; - } - return pvIORemapCookie; - } - else - { - LinuxMemArea *psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags); - - if(psLinuxMemArea == IMG_NULL) - { - return IMG_NULL; - } - - *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea; - return LinuxMemAreaToCpuVAddr(psLinuxMemArea); - } - } - - PVR_DPF((PVR_DBG_ERROR, - "OSMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY " - " (Use OSReservePhys otherwise)")); - - return IMG_NULL; -} - -/*! -****************************************************************************** - @Function OSUnMapPhysToLin - @Description Unmaps memory that was mapped with OSMapPhysToLin - @Return TRUE on success, else FALSE -******************************************************************************/ -IMG_BOOL -OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle) -{ - PVR_UNREFERENCED_PARAMETER(ui32Bytes); - - if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY) - { - if (hOSMemHandle == IMG_NULL) - { - IOUnmapWrapper(pvLinAddr); - } - else - { - LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - - PVR_ASSERT(LinuxMemAreaToCpuVAddr(psLinuxMemArea) == pvLinAddr); - - FreeIORemapLinuxMemArea(psLinuxMemArea); - } - - return IMG_TRUE; - } - - PVR_DPF((PVR_DBG_ERROR, - "OSUnMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY " - " (Use OSUnReservePhys otherwise)")); - return IMG_FALSE; -} - -/*! -****************************************************************************** - @Function RegisterExternalMem - @Description Registers external memory for user mode mapping - @Return TRUE on success, else FALSE, MemHandle out -******************************************************************************/ -static PVRSRV_ERROR -RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr, - IMG_VOID *pvCPUVAddr, - IMG_UINT32 ui32Bytes, - IMG_BOOL bPhysContig, - IMG_UINT32 ui32MappingFlags, - IMG_HANDLE *phOSMemHandle) -{ - LinuxMemArea *psLinuxMemArea; - - switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) - { - case PVRSRV_HAP_KERNEL_ONLY: - { - psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags); - - if(!psLinuxMemArea) - { - return PVRSRV_ERROR_BAD_MAPPING; - } - break; - } - case PVRSRV_HAP_SINGLE_PROCESS: - { - psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags); - - if(!psLinuxMemArea) - { - return PVRSRV_ERROR_BAD_MAPPING; - } - PVRMMapRegisterArea(psLinuxMemArea); - break; - } - case PVRSRV_HAP_MULTI_PROCESS: - { - /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel - * virtual mapping and potentially multiple user space virtual mappings. - * Beware that the kernel virtual address space is a limited resource. - */ -#if defined(VIVT_CACHE) || defined(__sh__) - /* - * ARM9 caches are tagged with virtual pages, not physical. As we are going to - * share this memory in different address spaces, we don't want it to be cached. - * ARM11 has physical tagging, so we can cache this memory without fear of virtual - * address aliasing in the TLB, as long as the kernel supports cache colouring for - * VIPT architectures. - */ - ui32MappingFlags &= ~PVRSRV_HAP_CACHED; -#endif - psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags); - - if(!psLinuxMemArea) - { - return PVRSRV_ERROR_BAD_MAPPING; - } - PVRMMapRegisterArea(psLinuxMemArea); - break; - } - default: - PVR_DPF((PVR_DBG_ERROR,"OSRegisterMem : invalid flags 0x%x\n", ui32MappingFlags)); - *phOSMemHandle = (IMG_HANDLE)0; - return PVRSRV_ERROR_INVALID_FLAGS; - } - - *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea; - - LinuxMemAreaRegister(psLinuxMemArea); - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - @Function OSRegisterMem - @Description Registers external memory for user mode mapping - @Output phOSMemHandle - handle to registered memory - @Return TRUE on success, else FALSE -******************************************************************************/ -PVRSRV_ERROR -OSRegisterMem(IMG_CPU_PHYADDR BasePAddr, - IMG_VOID *pvCPUVAddr, - IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32MappingFlags, - IMG_HANDLE *phOSMemHandle) -{ - IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr); - - return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle); -} - - -PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle) -{ - return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle); -} - - -/*! -****************************************************************************** - @Function OSUnRegisterMem - @Description UnRegisters external memory for user mode mapping - @Return TRUE on success, else FALSE -******************************************************************************/ -PVRSRV_ERROR -OSUnRegisterMem (IMG_VOID *pvCpuVAddr, - IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32MappingFlags, - IMG_HANDLE hOSMemHandle) -{ - LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - PVRSRV_ERROR eError; - - PVR_UNREFERENCED_PARAMETER(pvCpuVAddr); - PVR_UNREFERENCED_PARAMETER(ui32Bytes); - - switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) - { - case PVRSRV_HAP_KERNEL_ONLY: - break; - case PVRSRV_HAP_SINGLE_PROCESS: - case PVRSRV_HAP_MULTI_PROCESS: - { - eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!", - __FUNCTION__, pvCpuVAddr, ui32Bytes, - ui32MappingFlags, hOSMemHandle)); - return eError; - } - break; - } - default: - { - PVR_DPF((PVR_DBG_ERROR, "OSUnRegisterMem : invalid flags 0x%x", ui32MappingFlags)); - return PVRSRV_ERROR_INVALID_PARAMS; - } - } - - LinuxMemAreaDeepFree(psLinuxMemArea); - - return PVRSRV_OK; -} - -PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle) -{ - return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle); -} - -/*! -****************************************************************************** - @Function OSReservePhys - @Description Registers physical memory for user mode mapping - @Output ppvCpuVAddr - @Output phOsMemHandle handle to registered memory - @Return TRUE on success, else FALSE -******************************************************************************/ -PVRSRV_ERROR -OSReservePhys(IMG_CPU_PHYADDR BasePAddr, - IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32MappingFlags, - IMG_HANDLE hBMHandle, - IMG_VOID **ppvCpuVAddr, - IMG_HANDLE *phOSMemHandle) -{ - LinuxMemArea *psLinuxMemArea; - -#if 0 - /* For debug: force all OSReservePhys reservations to have a kernel - * virtual address */ - if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS) - { - ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS; - ui32MappingFlags |= PVRSRV_HAP_MULTI_PROCESS; - } -#endif - - switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) - { - case PVRSRV_HAP_KERNEL_ONLY: - { - /* Currently PVRSRV_HAP_KERNEL_ONLY implies that a kernel virtual - * 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); - if(!psLinuxMemArea) - { - return PVRSRV_ERROR_BAD_MAPPING; - } - break; - } - case PVRSRV_HAP_SINGLE_PROCESS: - { - /* Currently this implies that we dont need a kernel virtual - * mapping, but will need a user space virtual mapping */ - psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags); - if(!psLinuxMemArea) - { - return PVRSRV_ERROR_BAD_MAPPING; - } - PVRMMapRegisterArea(psLinuxMemArea); - break; - } - case PVRSRV_HAP_MULTI_PROCESS: - { - /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel - * virtual mapping and potentially multiple user space virtual mappings. - * Beware that the kernel virtual address space is a limited resource. - */ -#if defined(VIVT_CACHE) || defined(__sh__) - /* - * ARM9 caches are tagged with virtual pages, not physical. As we are going to - * share this memory in different address spaces, we don't want it to be cached. - * ARM11 has physical tagging, so we can cache this memory without fear of virtual - * address aliasing in the TLB, as long as the kernel supports cache colouring for - * VIPT architectures. - */ - ui32MappingFlags &= ~PVRSRV_HAP_CACHED; -#endif - psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags); - if(!psLinuxMemArea) - { - return PVRSRV_ERROR_BAD_MAPPING; - } - PVRMMapRegisterArea(psLinuxMemArea); - break; - } - default: - PVR_DPF((PVR_DBG_ERROR,"OSMapPhysToLin : invalid flags 0x%x\n", ui32MappingFlags)); - *ppvCpuVAddr = NULL; - *phOSMemHandle = (IMG_HANDLE)0; - return PVRSRV_ERROR_INVALID_FLAGS; - } - - /* - In case of sparse mapping we need to handle back to the BM as it - knows the mapping info - */ - if (ui32MappingFlags & PVRSRV_MEM_SPARSE) - { - PVR_ASSERT(hBMHandle != IMG_NULL); - psLinuxMemArea->hBMHandle = hBMHandle; - } - - *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea; - *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea); - - LinuxMemAreaRegister(psLinuxMemArea); - - return PVRSRV_OK; -} - -/*! -****************************************************************************** - @Function OSUnReservePhys - @Description UnRegisters physical memory for user mode mapping - @Return TRUE on success, else FALSE -******************************************************************************/ -PVRSRV_ERROR -OSUnReservePhys(IMG_VOID *pvCpuVAddr, - IMG_UINT32 ui32Bytes, - IMG_UINT32 ui32MappingFlags, - IMG_HANDLE hOSMemHandle) -{ - LinuxMemArea *psLinuxMemArea; - PVRSRV_ERROR eError; - - PVR_UNREFERENCED_PARAMETER(pvCpuVAddr); - PVR_UNREFERENCED_PARAMETER(ui32Bytes); - - psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - - switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) - { - case PVRSRV_HAP_KERNEL_ONLY: - break; - case PVRSRV_HAP_SINGLE_PROCESS: - case PVRSRV_HAP_MULTI_PROCESS: - { - eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!", - __FUNCTION__, pvCpuVAddr, ui32Bytes, - ui32MappingFlags, hOSMemHandle)); - return eError; - } - break; - } - default: - { - PVR_DPF((PVR_DBG_ERROR, "OSUnMapPhysToLin : invalid flags 0x%x", ui32MappingFlags)); - return PVRSRV_ERROR_INVALID_PARAMS; - } - } - - LinuxMemAreaDeepFree(psLinuxMemArea); - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - @Function OSBaseAllocContigMemory - @Description Allocate a block of contiguous virtual non-paged memory. - @Input ui32Size - number of bytes to allocate - @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) -{ -#if !defined(NO_HARDWARE) - PVR_UNREFERENCED_PARAMETER(ui32Size); - PVR_UNREFERENCED_PARAMETER(pvLinAddr); - PVR_UNREFERENCED_PARAMETER(psPhysAddr); - PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__)); - - return PVRSRV_ERROR_OUT_OF_MEMORY; -#else -/* - * On Linux, the returned virtual address should be used for CPU access, - * and not be remapped into the CPU virtual address using ioremap. The fact - * that the RAM is being managed by the kernel, and already has a virtual - * address, seems to lead to problems when the attributes of the memory are - * changed in the ioremap call (such as from cached to non-cached). - */ - IMG_VOID *pvKernLinAddr; - -#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) - pvKernLinAddr = _KMallocWrapper(ui32Size, GFP_KERNEL, __FILE__, __LINE__); -#else - pvKernLinAddr = KMallocWrapper(ui32Size, GFP_KERNEL); -#endif - if (!pvKernLinAddr) - { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - - *pvLinAddr = pvKernLinAddr; - - psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr); - - return PVRSRV_OK; -#endif /* !defined(NO_HARDWARE) */ -} - - -/*! -****************************************************************************** - @Function OSBaseFreeContigMemory - @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) -{ -#if !defined(NO_HARDWARE) - PVR_UNREFERENCED_PARAMETER(ui32Size); - 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(psPhysAddr.uiAddr); - - KFreeWrapper(pvLinAddr); -#endif - return PVRSRV_OK; -} - -/*! -****************************************************************************** - - @Function OSWriteHWReg - - @Description - - register access function - - @input pvLinRegBaseAddr : lin addr of register block base - - @input ui32Offset : - - @input ui32Value : - - @Return none - -******************************************************************************/ - -IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset) -{ -#if !defined(NO_HARDWARE) - return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset); -#else - return *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset); -#endif -} - -IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value) -{ -#if !defined(NO_HARDWARE) - writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset); -#else - *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset) = ui32Value; -#endif -} - -#if defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)) - -/*! -****************************************************************************** - - @Function OSPCISetDev - - @Description - - Set a PCI device for subsequent use. - - @input pvPCICookie : Pointer to OS specific PCI structure/cookie - - @input eFlags : Flags - - @Return Pointer to PCI device handle - -******************************************************************************/ -PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags) -{ - int err; - IMG_UINT32 i; - PVR_PCI_DEV *psPVRPCI; - - PVR_TRACE(("OSPCISetDev")); - - if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID **)&psPVRPCI, IMG_NULL, - "PCI Device") != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't allocate PVR PCI structure")); - return IMG_NULL; - } - - psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie; - psPVRPCI->ePCIFlags = eFlags; - - err = pci_enable_device(psPVRPCI->psPCIDev); - if (err != 0) - { - PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't enable device (%d)", err)); - return IMG_NULL; - } - - if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */ - { - pci_set_master(psPVRPCI->psPCIDev); - } - - if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI) /* PRQA S 3358 */ /* misuse of enums */ - { -#if defined(CONFIG_PCI_MSI) - err = pci_enable_msi(psPVRPCI->psPCIDev); - if (err != 0) - { - PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: Couldn't enable MSI (%d)", err)); - psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI; /* PRQA S 1474,3358,4130 */ /* misuse of enums */ - } -#else - PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel")); -#endif - } - - /* Initialise the PCI resource tracking array */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) - { - psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE; - } - - return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI; -} - -/*! -****************************************************************************** - - @Function OSPCIAcquireDev - - @Description - - Acquire a PCI device for subsequent use. - - @input ui16VendorID : Vendor PCI ID - - @input ui16VendorID : Device PCI ID - - @input eFlags : Flags - - @Return PVESRV_ERROR - -******************************************************************************/ -PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags) -{ - struct pci_dev *psPCIDev; - - psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL); - if (psPCIDev == NULL) - { - PVR_DPF((PVR_DBG_ERROR, "OSPCIAcquireDev: Couldn't acquire device")); - return IMG_NULL; - } - - return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags); -} - -/*! -****************************************************************************** - - @Function OSPCIIRQ - - @Description - - Get the interrupt number for the device. - - @input hPVRPCI : PCI device handle - - @input pui32IRQ : Pointer to where the interrupt number should be returned - - @Return PVESRV_ERROR - -******************************************************************************/ -PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ) -{ - PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI; - - *pui32IRQ = psPVRPCI->psPCIDev->irq; - - return PVRSRV_OK; -} - -/* Functions supported by OSPCIAddrRangeFunc */ -enum HOST_PCI_ADDR_RANGE_FUNC -{ - HOST_PCI_ADDR_RANGE_FUNC_LEN, - HOST_PCI_ADDR_RANGE_FUNC_START, - HOST_PCI_ADDR_RANGE_FUNC_END, - HOST_PCI_ADDR_RANGE_FUNC_REQUEST, - HOST_PCI_ADDR_RANGE_FUNC_RELEASE -}; - -/*! -****************************************************************************** - - @Function OSPCIAddrRangeFunc - - @Description - - Internal support function for various address range related functions - - @input eFunc : Function to perform - - @input hPVRPCI : PCI device handle - - @input ui32Index : Address range index - - @Return function dependent - -******************************************************************************/ -static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc, - PVRSRV_PCI_DEV_HANDLE hPVRPCI, - IMG_UINT32 ui32Index) -{ - PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI; - - if (ui32Index >= DEVICE_COUNT_RESOURCE) - { - PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Index out of range")); - return 0; - - } - - switch (eFunc) - { - case HOST_PCI_ADDR_RANGE_FUNC_LEN: - return pci_resource_len(psPVRPCI->psPCIDev, ui32Index); - case HOST_PCI_ADDR_RANGE_FUNC_START: - return pci_resource_start(psPVRPCI->psPCIDev, ui32Index); - case HOST_PCI_ADDR_RANGE_FUNC_END: - return pci_resource_end(psPVRPCI->psPCIDev, ui32Index); - case HOST_PCI_ADDR_RANGE_FUNC_REQUEST: - { - int err; - - err = pci_request_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index, PVRSRV_MODNAME); - if (err != 0) - { - PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: pci_request_region_failed (%d)", err)); - return 0; - } - psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE; - return 1; - } - case HOST_PCI_ADDR_RANGE_FUNC_RELEASE: - if (psPVRPCI->abPCIResourceInUse[ui32Index]) - { - pci_release_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index); - psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE; - } - return 1; - default: - PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Unknown function")); - break; - } - - return 0; -} - -/*! -****************************************************************************** - - @Function OSPCIAddrRangeLen - - @Description - - Returns length of a given address range length - - @input hPVRPCI : PCI device handle - - @input ui32Index : Address range index - - @Return Length of address range, or 0 if no such range - -******************************************************************************/ -IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index) -{ - return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index); -} - -/*! -****************************************************************************** - - @Function OSPCIAddrRangeStart - - @Description - - Returns the start of a given address range - - @input hPVRPCI : PCI device handle - - @input ui32Index : Address range index - - @Return Start of address range, or 0 if no such range - -******************************************************************************/ -IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index) -{ - return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index); -} - -/*! -****************************************************************************** - - @Function OSPCIAddrRangeEnd - - @Description - - Returns the end of a given address range - - @input hPVRPCI : PCI device handle"ayy - - @input ui32Index : Address range index - - @Return End of address range, or 0 if no such range - -******************************************************************************/ -IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index) -{ - return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index); -} - -/*! -****************************************************************************** - - @Function OSPCIRequestAddrRange - - @Description - - Request a given address range index for subsequent use - - @input hPVRPCI : PCI device handle - - @input ui32Index : Address range index - - @Return PVESRV_ERROR - -******************************************************************************/ -PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, - IMG_UINT32 ui32Index) -{ - return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK; -} - -/*! -****************************************************************************** - - @Function OSPCIReleaseAddrRange - - @Description - - Release a given address range that is no longer being used - - @input hPVRPCI : PCI device handle - - @input ui32Index : Address range index - - @Return PVESRV_ERROR - -******************************************************************************/ -PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index) -{ - return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK; -} - -/*! -****************************************************************************** - - @Function OSPCIReleaseDev - - @Description - - Release a PCI device that is no longer being used - - @input hPVRPCI : PCI device handle - - @Return PVESRV_ERROR - -******************************************************************************/ -PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI) -{ - PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI; - int i; - - PVR_TRACE(("OSPCIReleaseDev")); - - /* Release all PCI regions that are currently in use */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) - { - if (psPVRPCI->abPCIResourceInUse[i]) - { - PVR_TRACE(("OSPCIReleaseDev: Releasing Address range %d", i)); - pci_release_region(psPVRPCI->psPCIDev, i); - psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE; - } - } - -#if defined(CONFIG_PCI_MSI) - if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI) /* PRQA S 3358 */ /* misuse of enums */ - { - pci_disable_msi(psPVRPCI->psPCIDev); - } -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) - if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */ - { - pci_clear_master(psPVRPCI->psPCIDev); - } -#endif - pci_disable_device(psPVRPCI->psPCIDev); - - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL); - /*not nulling pointer, copy on stack*/ - - return PVRSRV_OK; -} - -/*! -****************************************************************************** - - @Function OSPCISuspendDev - - @Description - - Prepare PCI device to be turned off by power management - - @input hPVRPCI : PCI device handle - - @Return PVESRV_ERROR - -******************************************************************************/ -PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI) -{ - PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI; - int i; - int err; - - PVR_TRACE(("OSPCISuspendDev")); - - /* Release all PCI regions that are currently in use */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) - { - if (psPVRPCI->abPCIResourceInUse[i]) - { - pci_release_region(psPVRPCI->psPCIDev, i); - } - } - - err = pci_save_state(psPVRPCI->psPCIDev); - if (err != 0) - { - PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_save_state_failed (%d)", err)); - return PVRSRV_ERROR_PCI_CALL_FAILED; - } - - pci_disable_device(psPVRPCI->psPCIDev); - - err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_SUSPEND)); - switch(err) - { - case 0: - break; - case -EIO: - PVR_DPF((PVR_DBG_WARNING, "OSPCISuspendDev: device doesn't support PCI PM")); - break; - case -EINVAL: - PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: can't enter requested power state")); - break; - default: - PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_set_power_state failed (%d)", err)); - break; - } - - return PVRSRV_OK; -} - -/*! -****************************************************************************** - - @Function OSPCIResumeDev - - @Description - - Prepare a PCI device to be resumed by power management - - @input hPVRPCI : PCI device handle - - @input pvPCICookie : Pointer to OS specific PCI structure/cookie - - @input eFlags : Flags - - @Return PVESRV_ERROR - -******************************************************************************/ -PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI) -{ - PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI; - int err; - int i; - - PVR_TRACE(("OSPCIResumeDev")); - - err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON)); - switch(err) - { - case 0: - break; - case -EIO: - PVR_DPF((PVR_DBG_WARNING, "OSPCIResumeDev: device doesn't support PCI PM")); - break; - case -EINVAL: - PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: can't enter requested power state")); - return PVRSRV_ERROR_UNKNOWN_POWER_STATE; - default: - PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_set_power_state failed (%d)", err)); - return PVRSRV_ERROR_UNKNOWN_POWER_STATE; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - pci_restore_state(psPVRPCI->psPCIDev); -#else - err = pci_restore_state(psPVRPCI->psPCIDev); - if (err != 0) - { - PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_restore_state failed (%d)", err)); - return PVRSRV_ERROR_PCI_CALL_FAILED; - } -#endif - - err = pci_enable_device(psPVRPCI->psPCIDev); - if (err != 0) - { - PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: Couldn't enable device (%d)", err)); - return PVRSRV_ERROR_PCI_CALL_FAILED; - } - - if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */ - pci_set_master(psPVRPCI->psPCIDev); - - /* Restore the PCI resource tracking array */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) - { - if (psPVRPCI->abPCIResourceInUse[i]) - { - err = pci_request_region(psPVRPCI->psPCIDev, i, PVRSRV_MODNAME); - if (err != 0) - { - PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_request_region_failed (region %d, error %d)", i, err)); - } - } - - } - - return PVRSRV_OK; -} - -#endif /* #if defined(CONFIG_PCI) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) */ - -#define OS_MAX_TIMERS 8 - -/* Timer callback strucure used by OSAddTimer */ -typedef struct TIMER_CALLBACK_DATA_TAG -{ - IMG_BOOL bInUse; - PFN_TIMER_FUNC pfnTimerFunc; - IMG_VOID *pvData; - struct timer_list sTimer; - IMG_UINT32 ui32Delay; - IMG_BOOL bActive; -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) - struct work_struct sWork; -#endif -}TIMER_CALLBACK_DATA; - -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) -static struct workqueue_struct *psTimerWorkQueue; -#endif - -static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS]; - -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) -DEFINE_MUTEX(sTimerStructLock); -#else -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) -/* The lock is used to control access to sTimers */ -/* PRQA S 0671,0685 1 */ /* C99 macro not understood by QAC */ -static spinlock_t sTimerStructLock = SPIN_LOCK_UNLOCKED; -#else -static DEFINE_SPINLOCK(sTimerStructLock); -#endif -#endif - -static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData) -{ - if (!psTimerCBData->bActive) - return; - - /* call timer callback */ - psTimerCBData->pfnTimerFunc(psTimerCBData->pvData); - - /* reset timer */ - mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies); -} - - -/*! -****************************************************************************** - - @Function OSTimerCallbackWrapper - - @Description - - OS specific timer callback wrapper function - - @Input ui32Data : timer callback data - - @Return NONE - -******************************************************************************/ -static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data) -{ - TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data; - -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) - int res; - -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) - res = queue_work(psTimerWorkQueue, &psTimerCBData->sWork); -#else - res = schedule_work(&psTimerCBData->sWork); -#endif - if (res == 0) - { - PVR_DPF((PVR_DBG_WARNING, "OSTimerCallbackWrapper: work already queued")); - } -#else - OSTimerCallbackBody(psTimerCBData); -#endif -} - - -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) -static void OSTimerWorkQueueCallBack(struct work_struct *psWork) -{ - TIMER_CALLBACK_DATA *psTimerCBData = container_of(psWork, TIMER_CALLBACK_DATA, sWork); - - OSTimerCallbackBody(psTimerCBData); -} -#endif - -/*! -****************************************************************************** - - @Function OSAddTimer - - @Description - - OS specific function to install a timer callback - - @Input pfnTimerFunc : timer callback - - @Input *pvData :callback data - - @Input ui32MsTimeout: callback period - - @Return IMG_HANDLE : valid handle success, NULL failure - -******************************************************************************/ -IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout) -{ - TIMER_CALLBACK_DATA *psTimerCBData; - IMG_UINT32 ui32i; -#if !(defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)) - unsigned long ulLockFlags; -#endif - - /* check callback */ - if(!pfnTimerFunc) - { - PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback")); - return IMG_NULL; - } - - /* Allocate timer callback data structure */ -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) - mutex_lock(&sTimerStructLock); -#else - spin_lock_irqsave(&sTimerStructLock, ulLockFlags); -#endif - for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++) - { - psTimerCBData = &sTimers[ui32i]; - if (!psTimerCBData->bInUse) - { - psTimerCBData->bInUse = IMG_TRUE; - break; - } - } -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) - mutex_unlock(&sTimerStructLock); -#else - spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags); -#endif - if (ui32i >= OS_MAX_TIMERS) - { - PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use")); - return IMG_NULL; - } - - psTimerCBData->pfnTimerFunc = pfnTimerFunc; - psTimerCBData->pvData = pvData; - psTimerCBData->bActive = IMG_FALSE; - - /* - HZ = ticks per second - ui32MsTimeout = required ms delay - ticks = (Hz * ui32MsTimeout) / 1000 - */ - psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000) - ? 1 - : ((HZ * ui32MsTimeout) / 1000); - /* initialise object */ - init_timer(&psTimerCBData->sTimer); - - /* 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; - - return (IMG_HANDLE)(ui32i + 1); -} - - -static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer) -{ - IMG_UINT32 ui32i = ((IMG_UINT32)hTimer) - 1; - - PVR_ASSERT(ui32i < OS_MAX_TIMERS); - - return &sTimers[ui32i]; -} - -/*! -****************************************************************************** - - @Function OSRemoveTimer - - @Description - - OS specific function to remove a timer callback - - @Input hTimer : timer handle - - @Return PVRSRV_ERROR : - -******************************************************************************/ -PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer) -{ - TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer); - - PVR_ASSERT(psTimerCBData->bInUse); - PVR_ASSERT(!psTimerCBData->bActive); - - /* free timer callback data struct */ - psTimerCBData->bInUse = IMG_FALSE; - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSEnableTimer - - @Description - - OS specific function to enable a timer callback - - @Input hTimer : timer handle - - @Return PVRSRV_ERROR : - -******************************************************************************/ -PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer) -{ - TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer); - - PVR_ASSERT(psTimerCBData->bInUse); - PVR_ASSERT(!psTimerCBData->bActive); - - /* Start timer arming */ - psTimerCBData->bActive = IMG_TRUE; - - /* set the expire time */ - psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies; - - /* Add the timer to the list */ - add_timer(&psTimerCBData->sTimer); - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSDisableTimer - - @Description - - OS specific function to disable a timer callback - - @Input hTimer : timer handle - - @Return PVRSRV_ERROR : - -******************************************************************************/ -PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer) -{ - TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer); - - PVR_ASSERT(psTimerCBData->bInUse); - PVR_ASSERT(psTimerCBData->bActive); - - /* Stop timer from arming */ - psTimerCBData->bActive = IMG_FALSE; - smp_mb(); - -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) - flush_workqueue(psTimerWorkQueue); -#endif -#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) - flush_scheduled_work(); -#endif - - /* remove timer */ - del_timer_sync(&psTimerCBData->sTimer); - -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) - /* - * This second flush is to catch the case where the timer ran - * before we managed to delete it, in which case, it will have - * queued more work for the workqueue. Since the bActive flag - * has been cleared, this second flush won't result in the - * timer being rearmed. - */ - flush_workqueue(psTimerWorkQueue); -#endif -#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) - flush_scheduled_work(); -#endif - - return PVRSRV_OK; -} - - -/*! -****************************************************************************** - - @Function OSEventObjectCreateKM - - @Description - - OS specific function to create an event object - - @Input pszName : Globally unique event object name (if null name must be autogenerated) - - @Output psEventObject : OS event object info structure - - @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; - - if(psEventObject) - { - if(pszName) - { - /* copy over the event object name */ - strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH); - } - else - { - /* 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) - { - eError = PVRSRV_ERROR_OUT_OF_MEMORY; - } - - } - else - { - PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreateKM: psEventObject is not a valid pointer")); - eError = PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT; - } - - return eError; - -} - - -/*! -****************************************************************************** - - @Function OSEventObjectDestroyKM - - @Description - - OS specific function to destroy an event object - - @Input psEventObject : OS event object info structure - - @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; - - if(psEventObject) - { - if(psEventObject->hOSEventKM) - { - LinuxEventObjectListDestroy(psEventObject->hOSEventKM); - } - else - { - PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroyKM: hOSEventKM is not a valid pointer")); - eError = PVRSRV_ERROR_INVALID_PARAMS; - } - } - else - { - PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroyKM: psEventObject is not a valid pointer")); - eError = PVRSRV_ERROR_INVALID_PARAMS; - } - - return eError; -} - -/*! -****************************************************************************** - - @Function OSEventObjectWaitKM - - @Description - - OS specific function to wait for an event object. Called from client - - @Input hOSEventKM : OS and kernel specific handle to event object - - @Return PVRSRV_ERROR : - -******************************************************************************/ -PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM) -{ - PVRSRV_ERROR eError; - - if(hOSEventKM) - { - eError = LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS); - } - else - { - PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWaitKM: hOSEventKM is not a valid handle")); - eError = PVRSRV_ERROR_INVALID_PARAMS; - } - - return eError; -} - -/*! -****************************************************************************** - - @Function OSEventObjectOpenKM - - @Description - - OS specific function to open an event object. Called from client - - @Input psEventObject : Pointer to an event object - @Output phOSEvent : OS and kernel specific handle to event object - - @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; - - if(psEventObject) - { - if(LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed")); - eError = PVRSRV_ERROR_INVALID_PARAMS; - } - - } - else - { - PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreateKM: psEventObject is not a valid pointer")); - eError = PVRSRV_ERROR_INVALID_PARAMS; - } - - return eError; -} - -/*! -****************************************************************************** - - @Function OSEventObjectCloseKM - - @Description - - OS specific function to close an event object. Called from client - - @Input psEventObject : Pointer to an event object - @OInput hOSEventKM : OS and kernel specific handle to event object - - - @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; - - if(psEventObject) - { - if(LinuxEventObjectDelete(psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectDelete: failed")); - eError = PVRSRV_ERROR_INVALID_PARAMS; - } - - } - else - { - PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroyKM: psEventObject is not a valid pointer")); - eError = PVRSRV_ERROR_INVALID_PARAMS; - } - - return eError; - -} - -/*! -****************************************************************************** - - @Function OSEventObjectSignalKM - - @Description - - OS specific function to 'signal' an event object. Called from L/MISR - - @Input hOSEventKM : OS and kernel specific handle to event object - - @Return PVRSRV_ERROR : - -******************************************************************************/ -PVRSRV_ERROR OSEventObjectSignalKM(IMG_HANDLE hOSEventKM) -{ - PVRSRV_ERROR eError; - - if(hOSEventKM) - { - eError = LinuxEventObjectSignal(hOSEventKM); - } - else - { - PVR_DPF((PVR_DBG_ERROR, "OSEventObjectSignalKM: hOSEventKM is not a valid handle")); - eError = PVRSRV_ERROR_INVALID_PARAMS; - } - - return eError; -} - -/*! -****************************************************************************** - - @Function OSProcHasPrivSrvInit - - @Description - - Does the process have sufficient privileges to initialise services? - - @Input none - - @Return IMG_BOOL : - -******************************************************************************/ -IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID) -{ - return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE; -} - -/*! -****************************************************************************** - - @Function OSCopyToUser - - @Description - - Copy a block of data into user space - - @Input pvSrc - - @Output pvDest - - @Input ui32Bytes - - @Return PVRSRV_ERROR : - -******************************************************************************/ -PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, - IMG_VOID *pvDest, - IMG_VOID *pvSrc, - IMG_UINT32 ui32Bytes) -{ - PVR_UNREFERENCED_PARAMETER(pvProcess); - - if(pvr_copy_to_user(pvDest, pvSrc, ui32Bytes)==0) - return PVRSRV_OK; - else - return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY; -} - -/*! -****************************************************************************** - - @Function OSCopyFromUser - - @Description - - Copy a block of data from the user space - - @Output pvDest - - @Input pvSrc - - @Input ui32Bytes - - @Return PVRSRV_ERROR : - -******************************************************************************/ -PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess, - IMG_VOID *pvDest, - IMG_VOID *pvSrc, - IMG_UINT32 ui32Bytes) -{ - PVR_UNREFERENCED_PARAMETER(pvProcess); - - if(pvr_copy_from_user(pvDest, pvSrc, ui32Bytes)==0) - return PVRSRV_OK; - else - return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY; -} - -/*! -****************************************************************************** - - @Function OSAccessOK - - @Description - - Checks if a user space pointer is valide - - @Input eVerification - - @Input pvUserPtr - - @Input ui32Bytes - - @Return IMG_BOOL : - -******************************************************************************/ -IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes) -{ - IMG_INT linuxType; - - if (eVerification == PVR_VERIFY_READ) - { - linuxType = VERIFY_READ; - } - else - { - PVR_ASSERT(eVerification == PVR_VERIFY_WRITE); - linuxType = VERIFY_WRITE; - } - - return access_ok(linuxType, pvUserPtr, ui32Bytes); -} - -typedef enum _eWrapMemType_ -{ - WRAP_TYPE_NULL = 0, - WRAP_TYPE_GET_USER_PAGES, - WRAP_TYPE_FIND_VMA -} eWrapMemType; - -typedef struct _sWrapMemInfo_ -{ - eWrapMemType eType; - IMG_INT iNumPages; - IMG_INT iNumPagesMapped; - struct page **ppsPages; - IMG_SYS_PHYADDR *psPhysAddr; - IMG_INT iPageOffset; -#if defined(DEBUG) - IMG_UINT32 ulStartAddr; - IMG_UINT32 ulBeyondEndAddr; - struct vm_area_struct *psVMArea; -#endif -} sWrapMemInfo; - - -/*! -****************************************************************************** - - @Function *CPUVAddrToPFN - - @Description - - Find the PFN associated with a given CPU virtual address, and return - the associated page structure, if it exists. - The page in question must be present (i.e. no fault handling required), - 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. - ppsPAge - Pointer to returned page structure pointer. - - @Output *pulPFN - 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) -{ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)) - pgd_t *psPGD; - pud_t *psPUD; - pmd_t *psPMD; - pte_t *psPTE; - struct mm_struct *psMM = psVMArea->vm_mm; - spinlock_t *psPTLock; - IMG_BOOL bRet = IMG_FALSE; - - *pulPFN = 0; - *ppsPage = NULL; - - psPGD = pgd_offset(psMM, ulCPUVAddr); - if (pgd_none(*psPGD) || pgd_bad(*psPGD)) - return bRet; - - psPUD = pud_offset(psPGD, ulCPUVAddr); - if (pud_none(*psPUD) || pud_bad(*psPUD)) - return bRet; - - psPMD = pmd_offset(psPUD, ulCPUVAddr); - if (pmd_none(*psPMD) || pmd_bad(*psPMD)) - return bRet; - - psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock); - - if ((pte_none(*psPTE) == 0) && (pte_present(*psPTE) != 0) && (pte_write(*psPTE) != 0)) - { - *pulPFN = pte_pfn(*psPTE); - bRet = IMG_TRUE; - - if (pfn_valid(*pulPFN)) - { - *ppsPage = pfn_to_page(*pulPFN); - - get_page(*ppsPage); - } - } - - pte_unmap_unlock(psPTE, psPTLock); - - return bRet; -#else - return IMG_FALSE; -#endif -} - -/*! -****************************************************************************** - - @Function OSReleasePhysPageAddr - - @Description - - Release wrapped memory. - - @Input hOSWrapMem : Driver cookie - - @Return PVRSRV_ERROR - -******************************************************************************/ -PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem) -{ - sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem; - IMG_INT i; - - if (psInfo == IMG_NULL) - { - PVR_DPF((PVR_DBG_WARNING, - "OSReleasePhysPageAddr: called with null wrap handle")); - return PVRSRV_OK; - } - - switch (psInfo->eType) - { - case WRAP_TYPE_NULL: - { - PVR_DPF((PVR_DBG_WARNING, - "OSReleasePhysPageAddr: called with wrap type WRAP_TYPE_NULL")); - break; - } - case WRAP_TYPE_GET_USER_PAGES: - { - for (i = 0; i < psInfo->iNumPagesMapped; i++) - { - struct page *psPage = psInfo->ppsPages[i]; - - PVR_ASSERT(psPage != NULL); - - /* - * If the number of pages mapped is not the same as - * the number of pages in the address range, then - * get_user_pages must have failed, so we are cleaning - * up after failure, and the pages can't be dirty. - */ - if (psInfo->iNumPagesMapped == psInfo->iNumPages) - { - if (!PageReserved(psPage)) - { - SetPageDirty(psPage); - } - } - page_cache_release(psPage); - } - break; - } - case WRAP_TYPE_FIND_VMA: - { - for (i = 0; i < psInfo->iNumPages; i++) - { - if (psInfo->ppsPages[i] != IMG_NULL) - { - put_page(psInfo->ppsPages[i]); - } - } - break; - } - default: - { - PVR_DPF((PVR_DBG_ERROR, - "OSReleasePhysPageAddr: Unknown wrap type (%d)", psInfo->eType)); - return PVRSRV_ERROR_INVALID_WRAP_TYPE; - } - } - - if (psInfo->ppsPages != IMG_NULL) - { - kfree(psInfo->ppsPages); - } - - if (psInfo->psPhysAddr != IMG_NULL) - { - kfree(psInfo->psPhysAddr); - } - - kfree(psInfo); - - return PVRSRV_OK; -} - -#if defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER) - -static IMG_UINT32 CPUAddrToTilerPhy(IMG_UINT32 uiAddr) -{ - IMG_UINT32 ui32PhysAddr = 0; - pte_t *ptep, pte; - pgd_t *pgd; - pmd_t *pmd; - pud_t *pud; - - pgd = pgd_offset(current->mm, uiAddr); - if (pgd_none(*pgd) || pgd_bad(*pgd)) - goto err_out; - - pud = pud_offset(pgd, uiAddr); - if (pud_none(*pud) || pud_bad(*pud)) - goto err_out; - - pmd = pmd_offset(pud, uiAddr); - if (pmd_none(*pmd) || pmd_bad(*pmd)) - goto err_out; - - ptep = pte_offset_map(pmd, uiAddr); - if (!ptep) - goto err_out; - - pte = *ptep; - if (!pte_present(pte)) - goto err_out; - - ui32PhysAddr = (pte & PAGE_MASK) | (~PAGE_MASK & uiAddr); - - /* If the physAddr is not in the TILER physical range - * then we don't proceed. - */ - if (ui32PhysAddr < 0x60000000 && ui32PhysAddr > 0x7fffffff) - { - PVR_DPF((PVR_DBG_ERROR, "CPUAddrToTilerPhy: Not in tiler range")); - ui32PhysAddr = 0; - goto err_out; - } - -err_out: - return ui32PhysAddr; -} - -#endif /* defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER) */ - -/*! -****************************************************************************** - - @Function OSAcquirePhysPageAddr - - @Description - - @Return PVRSRV_ERROR - -******************************************************************************/ -PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr, - IMG_UINT32 ui32Bytes, - 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_INT i; - struct vm_area_struct *psVMArea; - sWrapMemInfo *psInfo = NULL; - IMG_BOOL bHavePageStructs = IMG_FALSE; - IMG_BOOL bHaveNoPageStructs = IMG_FALSE; - IMG_BOOL bMMapSemHeld = IMG_FALSE; - 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; - - /* - * Check for address range calculation overflow, and attempts to wrap - * zero bytes. - */ - if (ulBeyondEndAddr <= ulStartAddr) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Invalid address range (start %x, length %x)", - ulStartAddrOrig, ulAddrRangeOrig)); - goto error; - } - - /* Allocate information structure */ - psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL); - if (psInfo == NULL) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Couldn't allocate information structure")); - goto error; - } - memset(psInfo, 0, sizeof(*psInfo)); - -#if defined(DEBUG) - psInfo->ulStartAddr = ulStartAddrOrig; - psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig; -#endif - - psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT); - psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK); - - /* Allocate physical address array */ - psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL); - if (psInfo->psPhysAddr == NULL) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Couldn't allocate page array")); - goto error; - } - memset(psInfo->psPhysAddr, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr)); - - /* Allocate page array */ - psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL); - if (psInfo->ppsPages == NULL) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Couldn't allocate page array")); - goto error; - } - memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages)); - - /* Default error code from now on */ - eError = PVRSRV_ERROR_BAD_MAPPING; - - /* Set the mapping type to aid clean up */ - psInfo->eType = WRAP_TYPE_GET_USER_PAGES; - - /* Lock down user memory */ - down_read(¤t->mm->mmap_sem); - bMMapSemHeld = IMG_TRUE; - - /* Get page list */ - psInfo->iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL); - - if (psInfo->iNumPagesMapped >= 0) - { - /* See if we got all the pages we wanted */ - if (psInfo->iNumPagesMapped != psInfo->iNumPages) - { - PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, psInfo->iNumPagesMapped)); - - goto error; - } - - /* Build list of physical page addresses */ - for (i = 0; i < psInfo->iNumPages; i++) - { - IMG_CPU_PHYADDR CPUPhysAddr; - IMG_UINT32 ulPFN; - - ulPFN = page_to_pfn(psInfo->ppsPages[i]); - CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT; - if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN)); - - goto error; - } - psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr); - psSysPAddr[i] = psInfo->psPhysAddr[i]; - - } - - goto exit; - } - - PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), using CPU page table", psInfo->iNumPagesMapped)); - - /* Reset some fields */ - psInfo->eType = WRAP_TYPE_NULL; - psInfo->iNumPagesMapped = 0; - memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages)); - - /* - * get_user_pages didn't work. If this is due to the address range - * representing memory mapped I/O, then we'll look for the pages - * in the appropriate memory region of the process. - */ - - /* Set the mapping type to aid clean up */ - psInfo->eType = WRAP_TYPE_FIND_VMA; - - psVMArea = find_vma(current->mm, ulStartAddrOrig); - if (psVMArea == NULL) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Couldn't find memory region containing start address %x", ulStartAddrOrig)); - - goto error; - } -#if defined(DEBUG) - psInfo->psVMArea = psVMArea; -#endif - - /* - * 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) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Start address %x is outside of the region returned by find_vma", ulStartAddrOrig)); - goto error; - } - - /* Now check the end address is in range */ - if (ulBeyondEndAddrOrig > psVMArea->vm_end) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: End address %x is outside of the region returned by find_vma", ulBeyondEndAddrOrig)); - goto error; - } - - /* Does the region represent memory mapped I/O? */ - if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED)) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)", psVMArea->vm_flags)); - goto error; - } - - /* We require read and write access */ - if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE)) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: No read/write access to memory region (VMA flags: 0x%lx)", psVMArea->vm_flags)); - goto error; - } - - for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++) - { - IMG_CPU_PHYADDR CPUPhysAddr; - IMG_UINT32 ulPFN = 0; - - PVR_ASSERT(i < psInfo->iNumPages); - - if (!CPUVAddrToPFN(psVMArea, ulAddr, &ulPFN, &psInfo->ppsPages[i])) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Invalid CPU virtual address")); - - goto error; - } - if (psInfo->ppsPages[i] == NULL) - { -#if defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER) - /* This could be tiler memory.*/ - IMG_UINT32 ui32TilerAddr = CPUAddrToTilerPhy(ulAddr); - if (ui32TilerAddr) - { - bHavePageStructs = IMG_TRUE; - psInfo->iNumPagesMapped++; - psInfo->psPhysAddr[i].uiAddr = ui32TilerAddr; - psSysPAddr[i].uiAddr = ui32TilerAddr; - continue; - } -#endif /* defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER) */ - - bHaveNoPageStructs = IMG_TRUE; - } - else - { - bHavePageStructs = IMG_TRUE; - - psInfo->iNumPagesMapped++; - - PVR_ASSERT(ulPFN == page_to_pfn(psInfo->ppsPages[i])); - } - - CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT; - if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN)); - - goto error; - } - - psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr); - psSysPAddr[i] = psInfo->psPhysAddr[i]; - } - PVR_ASSERT(i == psInfo->iNumPages); - -#if defined(VM_MIXEDMAP) - if ((psVMArea->vm_flags & VM_MIXEDMAP) != 0) - { - goto exit; - } -#endif - - if (bHavePageStructs && bHaveNoPageStructs) - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Region is VM_MIXEDMAP, but isn't marked as such")); - goto error; - } - - if (!bHaveNoPageStructs) - { - /* The ideal case; every page has a page structure */ - goto exit; - } - -#if defined(VM_PFNMAP) - if ((psVMArea->vm_flags & VM_PFNMAP) == 0) -#endif - { - PVR_DPF((PVR_DBG_ERROR, - "OSAcquirePhysPageAddr: Region is VM_PFNMAP, but isn't marked as such")); - goto error; - } - -exit: - PVR_ASSERT(bMMapSemHeld); - up_read(¤t->mm->mmap_sem); - - /* Return the cookie */ - *phOSWrapMem = (IMG_HANDLE)psInfo; - - if (bHaveNoPageStructs) - { - PVR_DPF((PVR_DBG_MESSAGE, - "OSAcquirePhysPageAddr: Region contains pages which can't be locked down (no page structures)")); - } - - PVR_ASSERT(psInfo->eType != 0); - - return PVRSRV_OK; - -error: - if (bMMapSemHeld) - { - up_read(¤t->mm->mmap_sem); - } - OSReleasePhysPageAddr((IMG_HANDLE)psInfo); - - PVR_ASSERT(eError != PVRSRV_OK); - - 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); -#else -typedef void (*OuterCacheOp_t)(unsigned long ulStart, unsigned long ulEnd); -#endif - -#if defined(CONFIG_OUTER_CACHE) - -typedef IMG_BOOL (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32PageNumOffset, - IMG_UINT32 ui32PageNum, - unsigned long *pulStart); - -static IMG_BOOL VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32PageNumOffset, - IMG_UINT32 ui32PageNum, - unsigned long *pulStart) -{ - *pulStart = 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_SYS_PHYADDR SysPAddr; - IMG_CPU_PHYADDR CpuPAddr; - SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageNumOffset + ui32PageNum]; - CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr); - *pulStart = CpuPAddr.uiAddr; - return IMG_TRUE; -} - -static IMG_BOOL AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32PageNumOffset, - IMG_UINT32 ui32PageNum, - unsigned long *pulStart) -{ - struct page *pPage; - - pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageNumOffset + ui32PageNum]; - *pulStart = 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_UINT32 ui32VirtOffset = (ui32PageNumOffset + ui32PageNum) << PAGE_SHIFT; - IMG_UINT32 ui32PhysOffset; - struct page *pPage; - - if (BM_VirtOffsetToPhysical(psLinuxMemArea->hBMHandle, ui32VirtOffset, &ui32PhysOffset)) - { - PVR_ASSERT(ui32PhysOffset <= ui32VirtOffset); - pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PhysOffset >> PAGE_SHIFT]; - *pulStart = 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) -{ - IMG_CPU_PHYADDR CpuPAddr; - CpuPAddr = psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs[ui32PageNumOffset + ui32PageNum]; - *pulStart = CpuPAddr.uiAddr; - return IMG_TRUE; -} - -#endif /* defined(CONFIG_OUTER_CACHE) */ - -/* 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->ui32UserVAddr; - - /* Within permissible range */ - if(pvRangeAddrStart >= pvMinVAddr && - ui32Length <= psOffsetStruct->ui32RealByteSize) - return pvMinVAddr; - } - - return IMG_NULL; -} - -extern PVRSRV_LINUX_MUTEX g_sMMapMutex; - -static inline void DoInnerCacheOp(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length, - InnerCacheOp_t pfnInnerCacheOp) -{ - LinuxMemArea *psLinuxMemArea = hOSMemHandle; - - if (!psLinuxMemArea->hBMHandle) - { - pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length); - } - else - { - IMG_UINT32 ui32ByteRemain = ui32Length; - IMG_UINT32 ui32BytesToDo = PAGE_SIZE - (((IMG_UINT32) pvRangeAddrStart) & (~PAGE_MASK)); - IMG_UINT8 *pbDo = (IMG_UINT8 *) pvRangeAddrStart; - - while(ui32ByteRemain) - { - if (BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32ByteOffset + (ui32Length - ui32ByteRemain))) - { - pfnInnerCacheOp(pbDo, pbDo + ui32BytesToDo); - } - pbDo += ui32BytesToDo; - ui32ByteRemain -= ui32BytesToDo; - ui32BytesToDo = MIN(ui32ByteRemain, PAGE_SIZE); - } - } -} - -static -IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length, - InnerCacheOp_t pfnInnerCacheOp, - OuterCacheOp_t pfnOuterCacheOp) -{ - LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - IMG_UINT32 ui32AreaLength, ui32AreaOffset = 0; - struct list_head *psMMapOffsetStructList; - IMG_VOID *pvMinVAddr; - -#if defined(CONFIG_OUTER_CACHE) - MemAreaToPhys_t pfnMemAreaToPhys = IMG_NULL; - IMG_UINT32 ui32PageNumOffset = 0; -#endif - - PVR_ASSERT(psLinuxMemArea != IMG_NULL); - - 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 - we only know the physical length not the virtual - */ - if (!psLinuxMemArea->hBMHandle) - { - PVR_ASSERT(ui32Length <= ui32AreaLength); - } - - if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC) - { - ui32AreaOffset = psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset; - psLinuxMemArea = psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea; - } - - /* Recursion surely isn't possible? */ - PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC); - - switch(psLinuxMemArea->eAreaType) - { - case LINUX_MEM_AREA_VMALLOC: - { - if(is_vmalloc_addr(pvRangeAddrStart)) - { - pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + ui32AreaOffset; - - /* Outside permissible range */ - if(pvRangeAddrStart < pvMinVAddr) - goto err_blocked; - - DoInnerCacheOp(hOSMemHandle, - ui32ByteOffset, - pvRangeAddrStart, - ui32Length, - pfnInnerCacheOp); - } - else - { - /* If this isn't a vmalloc address, assume we're flushing by - * user-virtual. Compute the mmap base vaddr and use this to - * compute the offset in vmalloc space. - */ - - pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList, - pvRangeAddrStart, ui32Length); - if(!pvMinVAddr) - goto err_blocked; - - DoInnerCacheOp(hOSMemHandle, - ui32ByteOffset, - pvRangeAddrStart, - ui32Length, - pfnInnerCacheOp); - -#if defined(CONFIG_OUTER_CACHE) - /* - * We don't need to worry about cache aliasing here because - * we have already flushed the virtually-indexed caches (L1 - * etc.) by the supplied user-virtual addresses. - * - * 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) */ - } -#endif /* defined(CONFIG_OUTER_CACHE) */ - break; - } - - case LINUX_MEM_AREA_EXTERNAL_KV: - { - /* We'll only see bPhysContig for frame buffers, and we shouldn't - * be flushing those (they're write combined or uncached). - */ - if (psLinuxMemArea->uData.sExternalKV.bPhysContig == IMG_TRUE) - { - PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush contiguous external memory", __func__)); - goto err_blocked; - } - - /* If it has a kernel virtual address, something odd has happened. - * We expect EXTERNAL_KV _only_ from the wrapping of ALLOC_PAGES. - */ - if (psLinuxMemArea->uData.sExternalKV.pvExternalKV != IMG_NULL) - { - PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush external memory with a kernel virtual address", __func__)); - goto err_blocked; - } - - pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList, - pvRangeAddrStart, ui32Length); - 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: - { - pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList, - pvRangeAddrStart, ui32Length); - 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 = IONAreaToPhys; -#endif - break; - } - - case LINUX_MEM_AREA_ALLOC_PAGES: - { - pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList, - pvRangeAddrStart, ui32Length); - if(!pvMinVAddr) - goto err_blocked; - - DoInnerCacheOp(hOSMemHandle, - ui32ByteOffset, - pvRangeAddrStart, - ui32Length, - pfnInnerCacheOp); - -#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; - } - - LinuxUnLockMutex(&g_sMMapMutex); - -#if defined(CONFIG_OUTER_CACHE) - 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); - } - } - } -#endif - - return IMG_TRUE; - -err_blocked: - PVR_DPF((PVR_DBG_WARNING, "%s: Blocked cache op on virtual range " - "%p-%p (type %d)", __func__, - pvRangeAddrStart, pvRangeAddrStart + ui32Length, - psLinuxMemArea->eAreaType)); - LinuxUnLockMutex(&g_sMMapMutex); - return IMG_FALSE; -} - -#if defined(__i386__) - -#define ROUND_UP(x,a) (((x) + (a) - 1) & ~((a) - 1)) - -static void per_cpu_cache_flush(void *arg) -{ - PVR_UNREFERENCED_PARAMETER(arg); - wbinvd(); -} - -static void x86_flush_cache_range(const void *pvStart, const void *pvEnd) -{ - IMG_BYTE *pbStart = (IMG_BYTE *)pvStart; - IMG_BYTE *pbEnd = (IMG_BYTE *)pvEnd; - IMG_BYTE *pbBase; - - pbEnd = (IMG_BYTE *)ROUND_UP((IMG_UINTPTR_T)pbEnd, - boot_cpu_data.x86_clflush_size); - - mb(); - for(pbBase = pbStart; pbBase < pbEnd; pbBase += boot_cpu_data.x86_clflush_size) - { - clflush(pbBase); - } - mb(); -} - -IMG_VOID OSCleanCPUCacheKM(IMG_VOID) -{ - /* No clean feature on x86 */ - ON_EACH_CPU(per_cpu_cache_flush, NULL, 1); -} - -IMG_VOID OSFlushCPUCacheKM(IMG_VOID) -{ - ON_EACH_CPU(per_cpu_cache_flush, NULL, 1); -} - -IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length) -{ - /* Write-back and invalidate */ - return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length, - x86_flush_cache_range, IMG_NULL); -} - -IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length) -{ - /* No clean feature on x86 */ - return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length, - x86_flush_cache_range, IMG_NULL); -} - -IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length) -{ - /* No invalidate-only support */ - return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length, - x86_flush_cache_range, IMG_NULL); -} - -#else /* defined(__i386__) */ - -#if defined(__arm__) - -static void per_cpu_cache_flush(void *arg) -{ - PVR_UNREFERENCED_PARAMETER(arg); - flush_cache_all(); -} - -IMG_VOID OSCleanCPUCacheKM(IMG_VOID) -{ - /* No full (inner) cache clean op */ - ON_EACH_CPU(per_cpu_cache_flush, NULL, 1); -#if defined(CONFIG_OUTER_CACHE) - outer_clean_range(0, ULONG_MAX); -#endif -} - -IMG_VOID OSFlushCPUCacheKM(IMG_VOID) -{ - ON_EACH_CPU(per_cpu_cache_flush, NULL, 1); -#if defined(CONFIG_OUTER_CACHE) && \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) - /* To use the "deferred flush" (not clean) DDK feature you need a kernel - * implementation of outer_flush_all() for ARM CPUs with an outer cache - * controller (e.g. PL310, common with Cortex A9 and later). - * - * Reference DDKs don't require this functionality, as they will only - * clean the cache, never flush (clean+invalidate) it. - */ - outer_flush_all(); -#endif -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)) -static inline size_t pvr_dmac_range_len(const void *pvStart, const void *pvEnd) -{ - return (size_t)((char *)pvEnd - (char *)pvStart); -} -#endif - -static void pvr_dmac_inv_range(const void *pvStart, const void *pvEnd) -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)) - dmac_inv_range(pvStart, pvEnd); -#else - dmac_map_area(pvStart, pvr_dmac_range_len(pvStart, pvEnd), DMA_FROM_DEVICE); -#endif -} - -static void pvr_dmac_clean_range(const void *pvStart, const void *pvEnd) -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)) - dmac_clean_range(pvStart, pvEnd); -#else - dmac_map_area(pvStart, pvr_dmac_range_len(pvStart, pvEnd), DMA_TO_DEVICE); -#endif -} - -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); -} - -IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length) -{ - return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, - pvRangeAddrStart, ui32Length, - pvr_dmac_clean_range, outer_clean_range); -} - -IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length) -{ - return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, - pvRangeAddrStart, ui32Length, - pvr_dmac_inv_range, outer_inv_range); -} - -#else /* defined(__arm__) */ - -#if defined(__mips__) -/* - * dmac cache functions are supposed to be used for dma - * memory which comes from dma-able memory. However examining - * the implementation of dmac cache functions and experimenting, - * can assert that dmac functions are safe to use for high-mem - * memory as well for our OS{Clean/Flush/Invalidate}Cache functions - * - */ - -IMG_VOID OSCleanCPUCacheKM(IMG_VOID) -{ - /* dmac functions flush full cache if size is larger than - * p-cache size. This is a workaround for the fact that - * __flush_cache_all is not an exported symbol. Please - * replace with custom function if available in latest - * version of linux being used. - * Arbitrary large number (1MB) which should be larger than - * mips p-cache sizes for some time in future. - * */ - dma_cache_wback(0, 0x100000); -} - -IMG_VOID OSFlushCPUCacheKM(IMG_VOID) -{ - /* dmac functions flush full cache if size is larger than - * p-cache size. This is a workaround for the fact that - * __flush_cache_all is not an exported symbol. Please - * replace with custom function if available in latest - * version of linux being used. - * Arbitrary large number (1MB) which should be larger than - * mips p-cache sizes for some time in future. - * */ - dma_cache_wback_inv(0, 0x100000); -} - -static inline IMG_UINT32 pvr_dma_range_len(const void *pvStart, const void *pvEnd) -{ - return (IMG_UINT32)((char *)pvEnd - (char *)pvStart); -} - -static void pvr_dma_cache_wback_inv(const void *pvStart, const void *pvEnd) -{ - dma_cache_wback_inv((IMG_UINTPTR_T)pvStart, pvr_dma_range_len(pvStart, pvEnd)); -} - -static void pvr_dma_cache_wback(const void *pvStart, const void *pvEnd) -{ - dma_cache_wback((IMG_UINTPTR_T)pvStart, pvr_dma_range_len(pvStart, pvEnd)); -} - -static void pvr_dma_cache_inv(const void *pvStart, const void *pvEnd) -{ - dma_cache_inv((IMG_UINTPTR_T)pvStart, pvr_dma_range_len(pvStart, pvEnd)); -} - -IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length) -{ - return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, - pvRangeAddrStart, ui32Length, - pvr_dma_cache_wback_inv, IMG_NULL); -} - -IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length) -{ - return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, - pvRangeAddrStart, ui32Length, - pvr_dma_cache_wback, IMG_NULL); -} - -IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32ByteOffset, - IMG_VOID *pvRangeAddrStart, - IMG_UINT32 ui32Length) -{ - return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, - pvRangeAddrStart, ui32Length, - pvr_dma_cache_inv, IMG_NULL); -} - -#else /* defined(__mips__) */ - -#error "Implement CPU cache flush/clean/invalidate primitives for this CPU!" - -#endif /* defined(__mips__) */ - -#endif /* defined(__arm__) */ - -#endif /* defined(__i386__) */ - -typedef struct _AtomicStruct -{ - atomic_t RefCount; -} AtomicStruct; - -PVRSRV_ERROR OSAtomicAlloc(IMG_PVOID *ppvRefCount) -{ - AtomicStruct *psRefCount; - - psRefCount = kmalloc(sizeof(AtomicStruct), GFP_KERNEL); - if (psRefCount == NULL) - { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - atomic_set(&psRefCount->RefCount, 0); - - *ppvRefCount = psRefCount; - return PVRSRV_OK; -} - -IMG_VOID OSAtomicFree(IMG_PVOID pvRefCount) -{ - AtomicStruct *psRefCount = pvRefCount; - - PVR_ASSERT(atomic_read(&psRefCount->RefCount) == 0); - kfree(psRefCount); -} - -IMG_VOID OSAtomicInc(IMG_PVOID pvRefCount) -{ - AtomicStruct *psRefCount = pvRefCount; - - atomic_inc(&psRefCount->RefCount); -} - -IMG_BOOL OSAtomicDecAndTest(IMG_PVOID pvRefCount) -{ - AtomicStruct *psRefCount = pvRefCount; - - return atomic_dec_and_test(&psRefCount->RefCount) ? IMG_TRUE:IMG_FALSE; -} - -IMG_UINT32 OSAtomicRead(IMG_PVOID pvRefCount) -{ - AtomicStruct *psRefCount = pvRefCount; - - return (IMG_UINT32) atomic_read(&psRefCount->RefCount); -} - -IMG_VOID OSReleaseBridgeLock(IMG_VOID) -{ - LinuxUnLockMutex(&gPVRSRVLock); -} - -IMG_VOID OSReacquireBridgeLock(IMG_VOID) -{ - LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); -} - -typedef struct _OSTime -{ - unsigned long ulTime; -} OSTime; - -PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32USOffset) -{ - OSTime *psOSTime; - - psOSTime = kmalloc(sizeof(OSTime), GFP_KERNEL); - if (psOSTime == IMG_NULL) - { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - - psOSTime->ulTime = jiffies + usecs_to_jiffies(ui32USOffset); - *pvRet = psOSTime; - return PVRSRV_OK; -} - - -IMG_BOOL OSTimeHasTimePassed(IMG_PVOID pvData) -{ - OSTime *psOSTime = pvData; - - if (time_is_before_jiffies(psOSTime->ulTime)) - { - return IMG_TRUE; - } - return IMG_FALSE; -} - -IMG_VOID OSTimeDestroy(IMG_PVOID pvData) -{ - kfree(pvData); -} - -IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size) -{ - strncpy(pszName, current->comm, MIN(ui32Size,TASK_COMM_LEN)); -} - -/* One time osfunc initialisation */ -PVRSRV_ERROR PVROSFuncInit(IMG_VOID) -{ -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) - { - psTimerWorkQueue = create_workqueue("pvr_timer"); - if (psTimerWorkQueue == NULL) - { - PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__)); - return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD; - - } - } -#endif - -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) - { - IMG_UINT32 ui32i; - - for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++) - { - TIMER_CALLBACK_DATA *psTimerCBData = &sTimers[ui32i]; - - INIT_WORK(&psTimerCBData->sWork, OSTimerWorkQueueCallBack); - } - } -#endif - -#if defined (SUPPORT_ION) - { - PVRSRV_ERROR eError; - - eError = IonInit(); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: IonInit failed", __FUNCTION__)); - } - } -#endif - return PVRSRV_OK; -} - -/* - * Osfunc deinitialisation. - * Note that PVROSFuncInit may not have been called - */ -IMG_VOID PVROSFuncDeInit(IMG_VOID) -{ -#if defined (SUPPORT_ION) - IonDeinit(); -#endif -#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) - if (psTimerWorkQueue != NULL) - { - destroy_workqueue(psTimerWorkQueue); - } -#endif -} diff --git a/pvr-source/services4/srvkm/env/linux/osperproc.c b/pvr-source/services4/srvkm/env/linux/osperproc.c deleted file mode 100755 index a22b461..0000000 --- a/pvr-source/services4/srvkm/env/linux/osperproc.c +++ /dev/null @@ -1,146 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux specific per process data 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 "services_headers.h" -#include "osperproc.h" - -#include "env_perproc.h" -#include "proc.h" -#if defined (SUPPORT_ION) -#include "linux/ion.h" - -extern struct ion_device *psIonDev; -#endif -extern IMG_UINT32 gui32ReleasePID; - -PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData) -{ - PVRSRV_ERROR eError; - IMG_HANDLE hBlockAlloc; - PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc; - - eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, - sizeof(PVRSRV_ENV_PER_PROCESS_DATA), - phOsPrivateData, - &hBlockAlloc, - "Environment per Process Data"); - - if (eError != PVRSRV_OK) - { - *phOsPrivateData = IMG_NULL; - - PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError)); - return eError; - } - - psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData; - OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc)); - - psEnvPerProc->hBlockAlloc = hBlockAlloc; - - /* Linux specific mmap processing */ - LinuxMMapPerProcessConnect(psEnvPerProc); - -#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) - /* 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, - psEnvPerProc->azIonClientName); - - if (IS_ERR_OR_NULL(psEnvPerProc->psIONClient)) - { - PVR_DPF((PVR_DBG_ERROR, "OSPerProcessPrivateDataInit: Couldn't create " - "ion client for per process data")); - return PVRSRV_ERROR_OUT_OF_MEMORY; - } -#endif /* SUPPORT_ION */ - return PVRSRV_OK; -} - -PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData) -{ - PVRSRV_ERROR eError; - PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc; - - if (hOsPrivateData == IMG_NULL) - { - return PVRSRV_OK; - } - - psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData; - - /* Linux specific mmap processing */ - LinuxMMapPerProcessDisconnect(psEnvPerProc); - - /* Remove per process /proc entries */ - RemovePerProcessProcDir(psEnvPerProc); - - eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, - sizeof(PVRSRV_ENV_PER_PROCESS_DATA), - hOsPrivateData, - psEnvPerProc->hBlockAlloc); - /*not nulling pointer, copy on stack*/ - - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: OSFreeMem failed (%d)", __FUNCTION__, eError)); - } - - return PVRSRV_OK; -} - -PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase) -{ - return LinuxMMapPerProcessHandleOptions(psHandleBase); -} - -IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID) -{ - if(!gui32ReleasePID) - return NULL; - return PVRSRVPerProcessPrivateData(gui32ReleasePID); -} diff --git a/pvr-source/services4/srvkm/env/linux/pdump.c b/pvr-source/services4/srvkm/env/linux/pdump.c deleted file mode 100755 index 0124737..0000000 --- a/pvr-source/services4/srvkm/env/linux/pdump.c +++ /dev/null @@ -1,804 +0,0 @@ -/*************************************************************************/ /*! -@Title Parameter dump macro target routines -@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. -*/ /**************************************************************************/ - -#if defined (SUPPORT_SGX) || defined (SUPPORT_VGX) -#if defined (PDUMP) - -#include <asm/atomic.h> -#include <stdarg.h> -#if defined (SUPPORT_SGX) -#include "sgxdefs.h" /* Is this still needed? */ -#endif -#include "services_headers.h" - -#include "pvrversion.h" -#include "pvr_debug.h" - -#include "dbgdrvif.h" -#if defined (SUPPORT_SGX) -#include "sgxmmu.h"/* Is this still needed? */ -#endif -#include "mm.h" -#include "pdump_km.h" -#include "pdump_int.h" - -#include <linux/kernel.h> // sprintf -#include <linux/string.h> // strncpy, strlen - -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); -static IMG_VOID DbgSetFrame (PDBG_STREAM psStream, IMG_UINT32 ui32Frame); -static IMG_VOID DbgSetMarker (PDBG_STREAM psStream, IMG_UINT32 ui32Marker); - -#define PDUMP_DATAMASTER_PIXEL (1) -#define PDUMP_DATAMASTER_EDM (3) - -/* - Maximum file size to split output files -*/ -#define MAX_FILE_SIZE 0x40000000 - -static atomic_t gsPDumpSuspended = ATOMIC_INIT(0); - -static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL; - - - -IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2", - "ScriptStream2", - "DriverInfoStream"}; -typedef struct PDBG_PDUMP_STATE_TAG -{ - PDBG_STREAM psStream[PDUMP_NUM_STREAMS]; - IMG_UINT32 ui32ParamFileNum; - - IMG_CHAR *pszMsg; - IMG_CHAR *pszScript; - IMG_CHAR *pszFile; - -} PDBG_PDUMP_STATE; - -static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL}; - -#define SZ_MSG_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1 -#define SZ_SCRIPT_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1 -#define SZ_FILENAME_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1 - - - - -static inline IMG_BOOL PDumpSuspended(IMG_VOID) -{ - return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE; -} - -/*! - * \name PDumpOSGetScriptString - */ -PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, - IMG_UINT32 *pui32MaxLen) -{ - *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript; - *pui32MaxLen = SZ_SCRIPT_SIZE_MAX; - if ((!*phScript) || PDumpSuspended()) - { - return PVRSRV_ERROR_PDUMP_NOT_ACTIVE; - } - return PVRSRV_OK; -} - -/*! - * \name PDumpOSGetMessageString - */ -PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, - IMG_UINT32 *pui32MaxLen) -{ - *ppszMsg = gsDBGPdumpState.pszMsg; - *pui32MaxLen = SZ_MSG_SIZE_MAX; - if ((!*ppszMsg) || PDumpSuspended()) - { - return PVRSRV_ERROR_PDUMP_NOT_ACTIVE; - } - return PVRSRV_OK; -} - -/*! - * \name PDumpOSGetFilenameString - */ -PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, - IMG_UINT32 *pui32MaxLen) -{ - *ppszFile = gsDBGPdumpState.pszFile; - *pui32MaxLen = SZ_FILENAME_SIZE_MAX; - if ((!*ppszFile) || PDumpSuspended()) - { - return PVRSRV_ERROR_PDUMP_NOT_ACTIVE; - } - return PVRSRV_OK; -} - -/*! - * \name PDumpOSWriteString2 - */ -IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags) -{ - return PDumpWriteString2(hScript, ui32Flags); -} - -/*! - * \name PDumpOSBufprintf - */ -PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) -{ - IMG_CHAR* pszBuf = hBuf; - IMG_INT32 n; - va_list vaArgs; - - va_start(vaArgs, pszFormat); - - n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs); - - va_end(vaArgs); - - if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */ - { - PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete.")); - - return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW; - } - -#if defined(PDUMP_DEBUG_OUTFILES) - g_ui32EveryLineCounter++; -#endif - return PVRSRV_OK; -} - -/*! - * \name PDumpOSVSprintf - */ -PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) -{ - IMG_INT32 n; - - n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs); - - if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */ - { - PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete.")); - - return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW; - } - - return PVRSRV_OK; -} - -/*! - * \name PDumpOSDebugPrintf - */ -IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) -{ - PVR_UNREFERENCED_PARAMETER(pszFormat); - - /* FIXME: Implement using services PVR_DBG or otherwise with kprintf */ -} - -/*! - * \name PDumpOSSprintf - */ -PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) -{ - IMG_INT32 n; - va_list vaArgs; - - va_start(vaArgs, pszFormat); - - n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs); - - va_end(vaArgs); - - if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */ - { - PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete.")); - - return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW; - } - - return PVRSRV_OK; -} - -/*! - * \name PDumpOSBuflen - */ -IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax) -{ - IMG_CHAR* pszBuf = hBuffer; - IMG_UINT32 ui32Count = 0; - - while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) ) - { - ui32Count++; - } - return(ui32Count); -} - -/*! - * \name PDumpOSVerifyLineEnding - */ -IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax) -{ - IMG_UINT32 ui32Count; - IMG_CHAR* pszBuf = hBuffer; - - /* strlen */ - ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax); - - /* Put \r \n sequence at the end if it isn't already there */ - if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax)) - { - pszBuf[ui32Count] = '\n'; - ui32Count++; - pszBuf[ui32Count] = '\0'; - } - if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax)) - { - pszBuf[ui32Count-1] = '\r'; - pszBuf[ui32Count] = '\n'; - ui32Count++; - pszBuf[ui32Count] = '\0'; - } -} - -/*! - * \name PDumpOSGetStream - */ -IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream) -{ - return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream]; -} - -/*! - * \name PDumpOSGetStreamOffset - */ -IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream) -{ - PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream]; - return gpfnDbgDrv->pfnGetStreamOffset(psStream); -} - -/*! - * \name PDumpOSGetParamFileNum - */ -IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID) -{ - return gsDBGPdumpState.ui32ParamFileNum; -} - -/*! - * \name PDumpOSWriteString - */ -IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream, - IMG_UINT8 *psui8Data, - IMG_UINT32 ui32Size, - IMG_UINT32 ui32Flags) -{ - PDBG_STREAM psStream = (PDBG_STREAM)hStream; - return PDumpWriteILock(psStream, - psui8Data, - ui32Size, - ui32Flags); -} - -/*! - * \name PDumpOSCheckForSplitting - */ -IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags) -{ - /* File size limit not implemented for this OS. - */ - PVR_UNREFERENCED_PARAMETER(hStream); - PVR_UNREFERENCED_PARAMETER(ui32Size); - PVR_UNREFERENCED_PARAMETER(ui32Flags); -} - -/*! - * \name PDumpOSJTInitialised - */ -IMG_BOOL PDumpOSJTInitialised(IMG_VOID) -{ - if(gpfnDbgDrv) - { - return IMG_TRUE; - } - return IMG_FALSE; -} - -/*! - * \name PDumpOSIsSuspended - */ -inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID) -{ - return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE; -} - -/*! - * \name PDumpOSCPUVAddrToDevPAddr - */ -IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType, - IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32Offset, - IMG_UINT8 *pui8LinAddr, - IMG_UINT32 ui32PageSize, - IMG_DEV_PHYADDR *psDevPAddr) -{ - IMG_CPU_PHYADDR sCpuPAddr; - - PVR_UNREFERENCED_PARAMETER(pui8LinAddr); - PVR_UNREFERENCED_PARAMETER(ui32PageSize); /* for when no assert */ - - /* Caller must now alway supply hOSMemHandle, even though we only (presently) - use it here in the linux implementation */ - - PVR_ASSERT (hOSMemHandle != IMG_NULL); - - sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset); - PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0); - - /* convert CPU physical addr to device physical */ - *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr); -} - -/*! - * \name PDumpOSCPUVAddrToPhysPages - */ -IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle, - IMG_UINT32 ui32Offset, - IMG_PUINT8 pui8LinAddr, - IMG_UINT32 ui32DataPageMask, - IMG_UINT32 *pui32PageOffset) -{ - if(hOSMemHandle) - { - /* - * If a Services memory handle is provided then use it. - */ - IMG_CPU_PHYADDR sCpuPAddr; - - PVR_UNREFERENCED_PARAMETER(pui8LinAddr); - - sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset); - *pui32PageOffset = sCpuPAddr.uiAddr & ui32DataPageMask; - } - else - { - PVR_UNREFERENCED_PARAMETER(hOSMemHandle); - PVR_UNREFERENCED_PARAMETER(ui32Offset); - - *pui32PageOffset = ((IMG_UINT32)pui8LinAddr & ui32DataPageMask); - } -} - -/*! - * \name PDumpOSDebugDriverWrite - */ -IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream, - PDUMP_DDWMODE eDbgDrvWriteMode, - IMG_UINT8 *pui8Data, - IMG_UINT32 ui32BCount, - IMG_UINT32 ui32Level, - IMG_UINT32 ui32DbgDrvFlags) -{ - switch(eDbgDrvWriteMode) - { - case PDUMP_WRITE_MODE_CONTINUOUS: - PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags); - return gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, ui32Level); - case PDUMP_WRITE_MODE_LASTFRAME: - return gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, ui32Level, ui32DbgDrvFlags); - case PDUMP_WRITE_MODE_BINCM: - PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags); - return gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, ui32Level); - case PDUMP_WRITE_MODE_PERSISTENT: - PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags); - return gpfnDbgDrv->pfnWritePersist(psStream, pui8Data, ui32BCount, ui32Level); - default: - PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags); - break; - } - return 0xFFFFFFFFU; -} - -/*! - * \name PDumpOSReleaseExecution - */ -IMG_VOID PDumpOSReleaseExecution(IMG_VOID) -{ - OSReleaseThreadQuanta(); -} - -/************************************************************************** - * Function Name : PDumpInit - * Outputs : None - * Returns : - * Description : Reset connection to vldbgdrv - * Then try to connect to PDUMP streams -**************************************************************************/ -IMG_VOID PDumpInit(IMG_VOID) -{ - IMG_UINT32 i; - DBGKM_CONNECT_NOTIFIER sConnectNotifier; - - /* If we tried this earlier, then we might have connected to the driver - * But if pdump.exe was running then the stream connected would fail - */ - if (!gpfnDbgDrv) - { - DBGDrvGetServiceTable(&gpfnDbgDrv); - - - // If something failed then no point in trying to connect streams - if (gpfnDbgDrv == IMG_NULL) - { - return; - } - - /* - * Pass the connection notify callback - */ - sConnectNotifier.pfnConnectNotifier = &PDumpConnectionNotify; - gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier); - - if(!gsDBGPdumpState.pszFile) - { - if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0, - "Filename string") != PVRSRV_OK) - { - goto init_failed; - } - } - - if(!gsDBGPdumpState.pszMsg) - { - if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0, - "Message string") != PVRSRV_OK) - { - goto init_failed; - } - } - - if(!gsDBGPdumpState.pszScript) - { - if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0, - "Script string") != PVRSRV_OK) - { - goto init_failed; - } - } - - for(i=0; i < PDUMP_NUM_STREAMS; i++) - { - gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i], - DEBUG_CAPMODE_FRAMED, - DEBUG_OUTMODE_STREAMENABLE, - 0, - 10); - - gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1); - gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0); - } - - PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME); - PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FAMILY); - PDUMPCOMMENT("Start of Init Phase"); - } - - return; - -init_failed: - - if(gsDBGPdumpState.pszFile) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0); - gsDBGPdumpState.pszFile = IMG_NULL; - } - - if(gsDBGPdumpState.pszScript) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0); - gsDBGPdumpState.pszScript = IMG_NULL; - } - - if(gsDBGPdumpState.pszMsg) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0); - gsDBGPdumpState.pszMsg = IMG_NULL; - } - - /* - * Remove the connection notify callback - */ - sConnectNotifier.pfnConnectNotifier = 0; - gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier); - - gpfnDbgDrv = IMG_NULL; -} - - -IMG_VOID PDumpDeInit(IMG_VOID) -{ - IMG_UINT32 i; - DBGKM_CONNECT_NOTIFIER sConnectNotifier; - - for(i=0; i < PDUMP_NUM_STREAMS; i++) - { - gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]); - } - - if(gsDBGPdumpState.pszFile) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0); - gsDBGPdumpState.pszFile = IMG_NULL; - } - - if(gsDBGPdumpState.pszScript) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0); - gsDBGPdumpState.pszScript = IMG_NULL; - } - - if(gsDBGPdumpState.pszMsg) - { - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0); - gsDBGPdumpState.pszMsg = IMG_NULL; - } - - /* - * Remove the connection notify callback - */ - sConnectNotifier.pfnConnectNotifier = 0; - gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier); - - gpfnDbgDrv = IMG_NULL; -} - -/************************************************************************** - * Function Name : PDumpStartInitPhaseKM - * Inputs : None - * Outputs : None - * Returns : None - * Description : Resume init phase state -**************************************************************************/ -PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID) -{ - IMG_UINT32 i; - - if (gpfnDbgDrv) - { - PDUMPCOMMENT("Start Init Phase"); - for(i=0; i < PDUMP_NUM_STREAMS; i++) - { - gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]); - } - } - return PVRSRV_OK; -} - -/************************************************************************** - * Function Name : PDumpStopInitPhaseKM - * Inputs : None - * Outputs : None - * Returns : None - * Description : End init phase state -**************************************************************************/ -PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID) -{ - IMG_UINT32 i; - - if (gpfnDbgDrv) - { - PDUMPCOMMENT("Stop Init Phase"); - - for(i=0; i < PDUMP_NUM_STREAMS; i++) - { - gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]); - } - } - return PVRSRV_OK; -} - -/************************************************************************** - * Function Name : PDumpIsLastCaptureFrameKM - * Inputs : None - * Outputs : None - * Returns : True or false - * Description : Tests whether the current frame is being pdumped -**************************************************************************/ -IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID) -{ - return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]); -} - - -/************************************************************************** - * Function Name : PDumpIsCaptureFrameKM - * Inputs : None - * Outputs : None - * Returns : True or false - * Description : Tests whether the current frame is being pdumped -**************************************************************************/ -IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID) -{ - if (PDumpSuspended()) - { - return IMG_FALSE; - } - return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE); -} - -/************************************************************************** - * Function Name : PDumpSetFrameKM - * Inputs : None - * Outputs : None - * Returns : None - * Description : Sets a frame -**************************************************************************/ -PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame) -{ - IMG_UINT32 ui32Stream; - - for (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++) - { - if (gsDBGPdumpState.psStream[ui32Stream]) - { - DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame); - } - } - - return PVRSRV_OK; -} - - -/***************************************************************************** - FUNCTION : PDumpWriteString2 - - PURPOSE : - - PARAMETERS : - - RETURNS : -*****************************************************************************/ -static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags) -{ - return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags); -} - - -/***************************************************************************** - FUNCTION : PDumpWriteILock - - PURPOSE : Writes, making sure it all goes... - - PARAMETERS : - - RETURNS : -*****************************************************************************/ -static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags) -{ - 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)); - return IMG_TRUE; - } - - - /* - Set the stream marker to split output files - */ - - if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]) - { - IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]); - - if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE) - { - if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags))) - { - DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos); - gsDBGPdumpState.ui32ParamFileNum++; - } - } - } - - ui32Written = DbgWrite(psStream, pui8Data, ui32Count, ui32Flags); - - if (ui32Written == 0xFFFFFFFF) - { - return IMG_FALSE; - } - - return IMG_TRUE; -} - -/***************************************************************************** - FUNCTION : DbgSetFrame - - PURPOSE : Sets the frame in the stream - - PARAMETERS : psStream - Stream pointer - ui32Frame - Frame number to set - - RETURNS : None -*****************************************************************************/ -static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame) -{ - gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame); -} - -/***************************************************************************** - FUNCTION : DbgSetMarker - - PURPOSE : Sets the marker of the stream to split output files - - PARAMETERS : psStream - Stream pointer - ui32Marker - Marker number to set - - RETURNS : None -*****************************************************************************/ -static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker) -{ - gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker); -} - -IMG_VOID PDumpSuspendKM(IMG_VOID) -{ - atomic_inc(&gsPDumpSuspended); -} - -IMG_VOID PDumpResumeKM(IMG_VOID) -{ - atomic_dec(&gsPDumpSuspended); -} - -#endif /* #if defined (PDUMP) */ -#endif /* #if defined (SUPPORT_SGX) */ -/***************************************************************************** - End of file (PDUMP.C) -*****************************************************************************/ diff --git a/pvr-source/services4/srvkm/env/linux/private_data.h b/pvr-source/services4/srvkm/env/linux/private_data.h deleted file mode 100755 index 6b09705..0000000 --- a/pvr-source/services4/srvkm/env/linux/private_data.h +++ /dev/null @@ -1,95 +0,0 @@ -/*************************************************************************/ /*! -@Title Linux private data structure -@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 __INCLUDED_PRIVATE_DATA_H_ -#define __INCLUDED_PRIVATE_DATA_H_ - -#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) -#include <linux/list.h> -#include <drm/drmP.h> -#endif - -/* This structure is required in the rare case that a process creates - * a connection to services, but before closing the file descriptor, - * does a fork(). This fork() will duplicate the file descriptor in the - * child process. If the parent process dies before the child, this can - * cause the PVRSRVRelease() method to be called in a different process - * context than the original PVRSRVOpen(). This is bad because we need - * to update the per-process data reference count and/or free the - * per-process data. So we must keep a record of which PID's per-process - * data to inspect during ->release(). - */ - -typedef struct -{ - /* PID that created this services connection */ - 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 */ - struct list_head sDRMAuthListItem; - - struct drm_file *psDRMFile; -#endif - -#if defined(SUPPORT_MEMINFO_IDS) - /* Globally unique "stamp" for kernel MemInfo */ - IMG_UINT64 ui64Stamp; -#endif /* defined(SUPPORT_MEMINFO_IDS) */ - - /* Accounting for OSAllocMem */ - IMG_HANDLE hBlockAlloc; - -#if defined(SUPPORT_DRI_DRM_EXT) - IMG_PVOID pPriv; /*private data for extending this struct*/ -#endif -} -PVRSRV_FILE_PRIVATE_DATA; - -#endif /* __INCLUDED_PRIVATE_DATA_H_ */ - diff --git a/pvr-source/services4/srvkm/env/linux/proc.c b/pvr-source/services4/srvkm/env/linux/proc.c deleted file mode 100755 index 7307257..0000000 --- a/pvr-source/services4/srvkm/env/linux/proc.c +++ /dev/null @@ -1,1414 +0,0 @@ -/*************************************************************************/ /*! -@Title Proc files implementation. -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Functions for creating and reading proc filesystem entries. - Proc filesystem support must be built into the kernel for - these functions to be any use. -@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 <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/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" - -#include "queue.h" -#include "resman.h" -#include "pvrmmap.h" -#include "pvr_debug.h" -#include "pvrversion.h" -#include "proc.h" -#include "perproc.h" -#include "env_perproc.h" -#include "linkage.h" - -#include "lists.h" - -// 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 = -{ - .open = pvr_proc_open, - .read = seq_read, - .write = pvr_proc_write, - .llseek = seq_lseek, - .release = seq_release, -}; - -static struct seq_operations pvr_proc_seq_operations = -{ - .start = pvr_proc_seq_start, - .next = pvr_proc_seq_next, - .stop = pvr_proc_seq_stop, - .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; - -#ifdef DEBUG -static struct proc_dir_entry* g_pProcDebugLevel; -#endif - -#ifdef PVR_MANUAL_POWER_CONTROL -static struct proc_dir_entry* g_pProcPowerLevel; -#endif - - -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); - } -} - - -/*! -****************************************************************************** - - @Function : ProcSeq1ElementOff2Element - - @Description - - Heleper Offset -> Element function for /proc files with only one entry - without header. - - @Input sfile : seq_file object related to /proc/ file - - @Input off : the offset into the buffer (id of object) - - @Return : Pointer to element to be shown. - -*****************************************************************************/ -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 - if(!off) - return (void*)2; - return NULL; -} - - -/*! -****************************************************************************** - - @Function : ProcSeq1ElementHeaderOff2Element - - @Description - - Heleper Offset -> Element function for /proc files with only one entry - with header. - - @Input sfile : seq_file object related to /proc/ file - - @Input off : the offset into the buffer (id of object) - - @Return : Pointer to element to be shown. - -*****************************************************************************/ -void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off) -{ - PVR_UNREFERENCED_PARAMETER(sfile); - - if(!off) - { - return PVR_PROC_SEQ_START_TOKEN; - } - - // Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL - if(off == 1) - return (void*)2; - - return NULL; -} - - -/*! -****************************************************************************** - - @Function : pvr_proc_open - - @Description - File opening function passed to proc_dir_entry->proc_fops for /proc entries - created by CreateProcReadEntrySeq. - - @Input inode : inode entry of opened /proc file - - @Input file : file entry of opened /proc file - - @Return : 0 if no errors - -*****************************************************************************/ -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; - struct proc_dir_entry* pvr_proc_entry = PDE(inode); - - /* Add pointer to handlers to seq_file structure */ - seq->private = pvr_proc_entry->data; - return ret; -} - -/*! -****************************************************************************** - - @Function : pvr_proc_write - - @Description - File writing function passed to proc_dir_entry->proc_fops for /proc files. - It's exacly the same function that is used as default one (->fs/proc/generic.c), - it calls proc_dir_entry->write_proc for writing procedure. - -*****************************************************************************/ -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; - struct proc_dir_entry * dp; - - PVR_UNREFERENCED_PARAMETER(ppos); - dp = PDE(inode); - - if (!dp->write_proc) - return -EIO; - - return dp->write_proc(file, buffer, count, dp->data); -} - - -/*! -****************************************************************************** - - @Function : pvr_proc_seq_start - - @Description - Seq_file start function. Detailed description of seq_file workflow can - be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html. - This function ises off2element handler. - - @Input proc_seq_file : sequence file entry - - @Input pos : offset within file (id of entry) - - @Return : Pointer to element from we start enumeration (0 ends it) - -*****************************************************************************/ -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); -} - -/*! -****************************************************************************** - - @Function : pvr_proc_seq_stop - - @Description - Seq_file stop function. Detailed description of seq_file workflow can - be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html. - - @Input proc_seq_file : sequence file entry - - @Input v : current element pointer - -*****************************************************************************/ -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; - PVR_UNREFERENCED_PARAMETER(v); - - if(handlers->startstop != NULL) - handlers->startstop(proc_seq_file, IMG_FALSE); -} - -/*! -****************************************************************************** - - @Function : pvr_proc_seq_next - - @Description - Seq_file next element function. Detailed description of seq_file workflow can - be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html. - It uses supplied 'next' handler for fetching next element (or 0 if there is no one) - - @Input proc_seq_file : sequence file entry - - @Input pos : offset within file (id of entry) - - @Input v : current element pointer - - @Return : next element pointer (or 0 if end) - -*****************************************************************************/ -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; - (*pos)++; - if( handlers->next != NULL) - return handlers->next( proc_seq_file, v, *pos ); - return handlers->off2element(proc_seq_file, *pos); -} - -/*! -****************************************************************************** - - @Function : pvr_proc_seq_show - - @Description - Seq_file show element function. Detailed description of seq_file workflow can - be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html. - It call proper 'show' handler to show (dump) current element using seq_* functions - - @Input proc_seq_file : sequence file entry - - @Input v : current element pointer - - @Return : 0 if everything is OK - -*****************************************************************************/ -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; -} - - - -/*! -****************************************************************************** - - @Function : CreateProcEntryInDirSeq - - @Description - - Create a file under the given directory. These dynamic files can be used at - runtime to get or set information about the device. Whis version uses seq_file - interface - - @Input pdir : parent directory - - @Input name : the name of the file to create - - @Input data : aditional data that will be passed to handlers - - @Input next_handler : the function to call to provide the next element. OPTIONAL, if not - supplied, then off2element function is used instead - - @Input show_handler : the function to call to show element - - @Input off2element_handler : the function to call when it is needed to translate offest to element - - @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL. - - @Input whandler : the function to interpret writes from the user - - @Return Ptr to proc entry , 0 for failure - - -*****************************************************************************/ -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 - ) -{ - - struct proc_dir_entry * file; - mode_t mode; - - 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) - { - mode |= S_IRUGO; - } - - if (whandler) - { - mode |= S_IWUSR; - } - - 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; - - /* 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; - - return file; - } - } - - PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name)); - return NULL; -} - - -/*! -****************************************************************************** - - @Function : CreateProcReadEntrySeq - - @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. This version uses seq_file structure - for handling content generation. - - @Input name : the name of the file to create - - @Input data : aditional data that will be passed to handlers - - @Input next_handler : the function to call to provide the next element. OPTIONAL, if not - supplied, then off2element function is used instead - - @Input show_handler : the function to call to show element - - @Input off2element_handler : the function to call when it is needed to translate offest to element - - @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL. - - @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 - ) -{ - return CreateProcEntrySeq(name, - data, - next_handler, - show_handler, - off2element_handler, - startstop_handler, - NULL); -} - -/*! -****************************************************************************** - - @Function : CreateProcEntrySeq - - @Description - - @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. This version uses seq_file structure - for handling content generation and is fuller than CreateProcReadEntrySeq (it - supports write access); - - @Input name : the name of the file to create - - @Input data : aditional data that will be passed to handlers - - @Input next_handler : the function to call to provide the next element. OPTIONAL, if not - supplied, then off2element function is used instead - - @Input show_handler : the function to call to show element - - @Input off2element_handler : the function to call when it is needed to translate offest to element - - @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL. - - @Input whandler : the function to interpret writes from the user - - @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 - ) -{ - return CreateProcEntryInDirSeq( - dir, - name, - data, - next_handler, - show_handler, - off2element_handler, - startstop_handler, - whandler - ); -} - - - -/*! -****************************************************************************** - - @Function : CreatePerProcessProcEntrySeq - - @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. It's seq_file version. - - - - @Input name : the name of the file to create - - @Input data : aditional data that will be passed to handlers - - @Input next_handler : the function to call to provide the next element. OPTIONAL, if not - supplied, then off2element function is used instead - - @Input show_handler : the function to call to show element - - @Input off2element_handler : the function to call when it is needed to translate offest to element - - @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL. - - @Input whandler : the function to interpret writes from the user - - @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 - ) -{ - PVRSRV_ENV_PER_PROCESS_DATA *psPerProc; - IMG_UINT32 ui32PID; - - if (!dir) - { - PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot)); - return NULL; - } - - ui32PID = OSGetCurrentProcessIDKM(); - - psPerProc = PVRSRVPerProcessPrivateData(ui32PID); - if (!psPerProc) - { - PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data")); - - return NULL; - } - - if (!psPerProc->psProcDir) - { - 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)); - - 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 (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 ); - - } -} - -/*! -****************************************************************************** - - @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 (!psPerProc) - { - psPerProc = PVRSRVFindPerProcessPrivateData(); - if (!psPerProc) - { - PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't " - "remove %s, no per process data", proc_entry->name)); - return; - } - } - - 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 ); - } -} - -/*! -****************************************************************************** - - @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 - -*****************************************************************************/ -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; -} - - -/*! -****************************************************************************** - - @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 (!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; - } - - 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)); - - 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; - } - - /* 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; - } - - PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name)); - - return -ENOMEM; -} - - -/*! -****************************************************************************** - - @Function : CreateProcEntries - - @Description - - Create a directory /proc/pvr and the necessary entries within it. These - dynamic files can be used at runtime to get information about the device. - Creation might fail if proc support is not compiled into the kernel or if - there is no memory - - @Input none - - @Return nothing - -*****************************************************************************/ -IMG_INT CreateProcEntries(IMG_VOID) -{ - dir = proc_mkdir (PVRProcDirRoot, NULL); - - if (!dir) - { - PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot)); - - return -ENOMEM; - } - - g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL); - 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) - { - PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot)); - - return -ENOMEM; - } - - -#ifdef DEBUG - - g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL, - ProcSeqShowDebugLevel, - ProcSeq1ElementOff2Element, NULL, - (IMG_VOID*)PVRDebugProcSetLevel); - if(!g_pProcDebugLevel) - { - PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot)); - - return -ENOMEM; - } - -#ifdef PVR_MANUAL_POWER_CONTROL - g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL, - ProcSeqShowPowerLevel, - ProcSeq1ElementOff2Element, NULL, - PVRProcSetPowerLevel); - if(!g_pProcPowerLevel) - { - PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot)); - - return -ENOMEM; - } -#endif -#endif - - return 0; -} - - -/*! -****************************************************************************** - - @Function : RemoveProcEntry - - @Description - - Remove a single node under /proc/pvr. - - @Input name : the name of the node to remove - - @Return nothing - -*****************************************************************************/ -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)); - } -} - - -/*! -****************************************************************************** - - @Function : RemovePerProcessProcEntry - - @Description - - Remove a single node under the per process proc directory. - - @Input name : the name of the node to remove - - @Return nothing - -*****************************************************************************/ -IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name) -{ - PVRSRV_ENV_PER_PROCESS_DATA *psPerProc; - - psPerProc = LinuxTerminatingProcessPrivateData(); - if (!psPerProc) - { - psPerProc = PVRSRVFindPerProcessPrivateData(); - if (!psPerProc) - { - PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't " - "remove %s, no per process data", name)); - return; - } - } - - if (psPerProc->psProcDir) - { - remove_proc_entry(name, psPerProc->psProcDir); - - PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", name, psPerProc->psProcDir->name)); - } -} - - -/*! -****************************************************************************** - - @Function : RemovePerProcessProcDir - - @Description - - Remove the per process directorty under /proc/pvr. - - @Input psPerProc : environment specific per process data - - @Return nothing - -*****************************************************************************/ -IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc) -{ - if (psPerProc->psProcDir) - { - while (psPerProc->psProcDir->subdir) - { - PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name)); - - RemoveProcEntry(psPerProc->psProcDir->subdir->name); - } - RemoveProcEntry(psPerProc->psProcDir->name); - } -} - -/*! -****************************************************************************** - - @Function : RemoveProcEntries - - Description - - Proc filesystem entry deletion - Remove all proc filesystem entries for - the driver. - - @Input none - - @Return nothing - -*****************************************************************************/ -IMG_VOID RemoveProcEntries(IMG_VOID) -{ -#ifdef DEBUG - RemoveProcEntrySeq( g_pProcDebugLevel ); -#ifdef PVR_MANUAL_POWER_CONTROL - RemoveProcEntrySeq( g_pProcPowerLevel ); -#endif /* PVR_MANUAL_POWER_CONTROL */ -#endif - - RemoveProcEntrySeq(g_pProcQueue); - RemoveProcEntrySeq(g_pProcVersion); - RemoveProcEntrySeq(g_pProcSysNodes); - - 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); -} - -/***************************************************************************** - FUNCTION : ProcSeqShowVersion - - PURPOSE : Print the content of version to /proc file - - PARAMETERS : sfile - /proc seq_file - el - Element to print -*****************************************************************************/ -static void ProcSeqShowVersion(struct seq_file *sfile,void* el) -{ - SYS_DATA *psSysData; - IMG_CHAR *pszSystemVersionString = "None"; - - if(el == PVR_PROC_SEQ_START_TOKEN) - { - seq_printf(sfile, - "Version %s (%s) %s\n", - PVRVERSION_STRING, - PVR_BUILD_TYPE, PVR_BUILD_DIR); - return; - } - - psSysData = SysAcquireDataNoCheck(); - if(psSysData != IMG_NULL && psSysData->pszVersionString != IMG_NULL) - { - pszSystemVersionString = psSysData->pszVersionString; - } - - 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) - { - default: - { - static IMG_CHAR text[10]; - - sprintf(text, "?%x", (IMG_UINT)deviceType); - - return text; - } - } -} - - -static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass) -{ - switch (deviceClass) - { - case PVRSRV_DEVICE_CLASS_3D: - { - return "3D"; - } - case PVRSRV_DEVICE_CLASS_DISPLAY: - { - return "display"; - } - case PVRSRV_DEVICE_CLASS_BUFFER: - { - return "buffer"; - } - default: - { - static IMG_CHAR text[10]; - - sprintf(text, "?%x", (IMG_UINT)deviceClass); - return text; - } - } -} - -static IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va) -{ - off_t *pOff = va_arg(va, off_t*); - if (--(*pOff)) - { - return IMG_NULL; - } - else - { - return psNode; - } -} - -/***************************************************************************** - FUNCTION : ProcSeqShowSysNodes - - PURPOSE : Print the content of version to /proc file - - PARAMETERS : sfile - /proc seq_file - el - Element to print -*****************************************************************************/ -static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el) -{ - PVRSRV_DEVICE_NODE *psDevNode; - - if(el == PVR_PROC_SEQ_START_TOKEN) - { - seq_printf( sfile, - "Registered nodes\n" - "Addr Type Class Index Ref pvDev Size Res\n"); - return; - } - - psDevNode = (PVRSRV_DEVICE_NODE*)el; - - seq_printf( sfile, - "%p %-8s %-8s %4d %2u %p %3u %p\n", - psDevNode, - deviceTypeToString(psDevNode->sDevId.eDeviceType), - deviceClassToString(psDevNode->sDevId.eDeviceClass), - psDevNode->sDevId.eDeviceClass, - psDevNode->ui32RefCount, - psDevNode->pvDevice, - psDevNode->ui32pvDeviceSize, - psDevNode->hResManContext); -} - -/***************************************************************************** - FUNCTION : ProcSeqOff2ElementSysNodes - - PURPOSE : Transale offset to element (/proc stuff) - - PARAMETERS : sfile - /proc seq_file - off - the offset into the buffer - - RETURNS : element to print -*****************************************************************************/ -static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off) -{ - SYS_DATA *psSysData; - PVRSRV_DEVICE_NODE*psDevNode = IMG_NULL; - - PVR_UNREFERENCED_PARAMETER(sfile); - - if(!off) - { - return PVR_PROC_SEQ_START_TOKEN; - } - - psSysData = SysAcquireDataNoCheck(); - if (psSysData != IMG_NULL) - { - /* Find Dev Node */ - psDevNode = (PVRSRV_DEVICE_NODE*) - List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, - DecOffPsDev_AnyVaCb, - &off); - } - - /* Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL */ - return (void*)psDevNode; -} - -/***************************************************************************** - End of file (proc.c) -*****************************************************************************/ diff --git a/pvr-source/services4/srvkm/env/linux/proc.h b/pvr-source/services4/srvkm/env/linux/proc.h deleted file mode 100755 index bc2a554..0000000 --- a/pvr-source/services4/srvkm/env/linux/proc.h +++ /dev/null @@ -1,127 +0,0 @@ -/*************************************************************************/ /*! -@Title Proc interface definition. -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Functions for creating and reading proc filesystem entries. - Refer to proc.c -@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 __SERVICES_PROC_H__ -#define __SERVICES_PROC_H__ - -#include <asm/system.h> // va_list etc -#include <linux/proc_fs.h> // read_proc_t etc -#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); - - -#define PVR_PROC_SEQ_START_TOKEN (void*)1 -typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t); -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; -} 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); - -IMG_VOID RemoveProcEntries(IMG_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 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 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 - ); - - -IMG_VOID RemoveProcEntrySeq(struct proc_dir_entry* proc_entry); -IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry); - -#endif diff --git a/pvr-source/services4/srvkm/env/linux/pvr_bridge_k.c b/pvr-source/services4/srvkm/env/linux/pvr_bridge_k.c deleted file mode 100755 index 23379b9..0000000 --- a/pvr-source/services4/srvkm/env/linux/pvr_bridge_k.c +++ /dev/null @@ -1,524 +0,0 @@ -/*************************************************************************/ /*! -@Title PVR Bridge Module (kernel side) -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Receives calls from the user portion of services and - despatches them to functions in the kernel portion. -@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 "img_defs.h" -#include "services.h" -#include "pvr_bridge.h" -#include "perproc.h" -#include "mutex.h" -#include "syscommon.h" -#include "pvr_debug.h" -#include "proc.h" -#include "private_data.h" -#include "linkage.h" -#include "pvr_bridge_km.h" -#include "pvr_uaccess.h" -#include "refcount.h" -#include "buffer_manager.h" - -#if defined(SUPPORT_DRI_DRM) -#include <drm/drmP.h> -#include "pvr_drm.h" -#if defined(PVR_SECURE_DRM_AUTH_EXPORT) -#include "env_perproc.h" -#endif -#endif - -/* VGX: */ -#if defined(SUPPORT_VGX) -#include "vgx_bridge.h" -#endif - -/* SGX: */ -#if defined(SUPPORT_SGX) -#include "sgx_bridge.h" -#endif - -#include "bridged_pvr_bridge.h" - -#if defined(SUPPORT_DRI_DRM) -#define PRIVATE_DATA(pFile) ((pFile)->driver_priv) -#else -#define PRIVATE_DATA(pFile) ((pFile)->private_data) -#endif - -#if defined(DEBUG_BRIDGE_KM) - -static struct proc_dir_entry *g_ProcBridgeStats =0; -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); -static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start); - -#endif - -extern PVRSRV_LINUX_MUTEX gPVRSRVLock; - -#if defined(SUPPORT_MEMINFO_IDS) -static IMG_UINT64 ui64Stamp; -#endif /* defined(SUPPORT_MEMINFO_IDS) */ - -PVRSRV_ERROR -LinuxBridgeInit(IMG_VOID) -{ -#if defined(DEBUG_BRIDGE_KM) - { - g_ProcBridgeStats = CreateProcReadEntrySeq( - "bridge_stats", - NULL, - ProcSeqNextBridgeStats, - ProcSeqShowBridgeStats, - ProcSeqOff2ElementBridgeStats, - ProcSeqStartstopBridgeStats - ); - if(!g_ProcBridgeStats) - { - return PVRSRV_ERROR_OUT_OF_MEMORY; - } - } -#endif - return CommonBridgeInit(); -} - -IMG_VOID -LinuxBridgeDeInit(IMG_VOID) -{ -#if defined(DEBUG_BRIDGE_KM) - RemoveProcEntrySeq(g_ProcBridgeStats); -#endif -} - -#if defined(DEBUG_BRIDGE_KM) - -/* - * Lock MMap regions list (called on page start/stop while reading /proc/mmap) - * - * sfile : seq_file that handles /proc file - * start : TRUE if it's start, FALSE if it's stop - * - */ -static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start) -{ - if(start) - { - LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); - } - else - { - LinuxUnLockMutex(&gPVRSRVLock); - } -} - - -/* - * Convert offset (index from KVOffsetTable) to element - * (called when reading /proc/mmap file) - - * sfile : seq_file that handles /proc file - * off : index into the KVOffsetTable from which to print - * - * returns void* : Pointer to element that will be dumped - * -*/ -static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off) -{ - if(!off) - { - return PVR_PROC_SEQ_START_TOKEN; - } - - if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT) - { - return (void*)0; - } - - - return (void*)&g_BridgeDispatchTable[off-1]; -} - -/* - * Gets next MMap element to show. (called when reading /proc/mmap file) - - * sfile : seq_file that handles /proc file - * el : actual element - * off : index into the KVOffsetTable from which to print - * - * returns void* : Pointer to element to show (0 ends iteration) -*/ -static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off) -{ - return ProcSeqOff2ElementBridgeStats(sfile,off); -} - - -/* - * Show MMap element (called when reading /proc/mmap file) - - * sfile : seq_file that handles /proc file - * el : actual element - * -*/ -static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el) -{ - PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el; - - if(el == PVR_PROC_SEQ_START_TOKEN) - { - seq_printf(sfile, - "Total ioctl call count = %u\n" - "Total number of bytes copied via copy_from_user = %u\n" - "Total number of bytes copied via copy_to_user = %u\n" - "Total number of bytes copied via copy_*_user = %u\n\n" - "%-45s | %-40s | %10s | %20s | %10s\n", - g_BridgeGlobalStats.ui32IOCTLCount, - g_BridgeGlobalStats.ui32TotalCopyFromUserBytes, - g_BridgeGlobalStats.ui32TotalCopyToUserBytes, - g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes, - "Bridge Name", - "Wrapper Function", - "Call Count", - "copy_from_user Bytes", - "copy_to_user Bytes" - ); - return; - } - - seq_printf(sfile, - "%-45s %-40s %-10u %-20u %-10u\n", - psEntry->pszIOCName, - psEntry->pszFunctionName, - psEntry->ui32CallCount, - psEntry->ui32CopyFromUserTotalBytes, - psEntry->ui32CopyToUserTotalBytes); -} - -#endif /* DEBUG_BRIDGE_KM */ - - -#if defined(SUPPORT_DRI_DRM) -int -PVRSRV_BridgeDispatchKM(struct drm_device unref__ *dev, void *arg, struct drm_file *pFile) -#else -long -PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsigned long arg) -#endif -{ - IMG_UINT32 cmd; -#if !defined(SUPPORT_DRI_DRM) - PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg; - PVRSRV_BRIDGE_PACKAGE sBridgePackageKM; -#endif - PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM; - IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); - PVRSRV_PER_PROCESS_DATA *psPerProc; - IMG_INT err = -EFAULT; - - LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); - -#if defined(SUPPORT_DRI_DRM) - psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg; - PVR_ASSERT(psBridgePackageKM != IMG_NULL); -#else - psBridgePackageKM = &sBridgePackageKM; - - if(!OSAccessOK(PVR_VERIFY_WRITE, - psBridgePackageUM, - sizeof(PVRSRV_BRIDGE_PACKAGE))) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments", - __FUNCTION__)); - - goto unlock_and_return; - } - - /* FIXME - Currently the CopyFromUserWrapper which collects stats about - * how much data is shifted to/from userspace isn't available to us - * here. */ - if(OSCopyFromUser(IMG_NULL, - psBridgePackageKM, - psBridgePackageUM, - sizeof(PVRSRV_BRIDGE_PACKAGE)) - != PVRSRV_OK) - { - goto unlock_and_return; - } -#endif - - cmd = psBridgePackageKM->ui32BridgeID; - - if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES) - { - PVRSRV_ERROR eError; - - eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE, - (IMG_PVOID *)&psPerProc, - psBridgePackageKM->hKernelServices, - PVRSRV_HANDLE_TYPE_PERPROC_DATA); - if(eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)", - __FUNCTION__, eError)); - goto unlock_and_return; - } - - if(psPerProc->ui32PID != ui32PID) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data " - "belonging to process %d", __FUNCTION__, ui32PID, - psPerProc->ui32PID)); - goto unlock_and_return; - } - } - else - { - /* lookup per-process data for this process */ - psPerProc = PVRSRVPerProcessData(ui32PID); - if(psPerProc == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: " - "Couldn't create per-process data area")); - goto unlock_and_return; - } - } - - psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID); - - switch(cmd) - { - case PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2: - { - PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); - - if(psPrivateData->hKernelMemInfo) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo " - "per file descriptor", __FUNCTION__)); - err = -EINVAL; - goto unlock_and_return; - } - break; - } - - case PVRSRV_BRIDGE_MAP_DEV_MEMORY_2: - { - PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN = - (PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamIn; - PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); - - if(!psPrivateData->hKernelMemInfo) - { - PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no " - "associated MemInfo handle", __FUNCTION__)); - err = -EINVAL; - goto unlock_and_return; - } - - if (pvr_put_user(psPrivateData->hKernelMemInfo, &psMapDevMemIN->hKernelMemInfo) != 0) - { - err = -EFAULT; - goto unlock_and_return; - } - break; - } - - default: - { - PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); - - if(psPrivateData->hKernelMemInfo) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried " - "to use privileged service", __FUNCTION__)); - goto unlock_and_return; - } - break; - } - } - -#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) - switch(cmd) - { - case PVRSRV_BRIDGE_MAP_DEV_MEMORY: - case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY: - { - PVRSRV_FILE_PRIVATE_DATA *psPrivateData; - int authenticated = pFile->authenticated; - PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc; - - if (authenticated) - { - break; - } - - /* - * The DRM file structure we are using for Services - * is not one that DRI authentication was done on. - * Look for an authenticated file structure for - * this process, making sure the DRM master is the - * same as ours. - */ - psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc); - if (psEnvPerProc == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__)); - err = -EFAULT; - goto unlock_and_return; - } - - list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem) - { - struct drm_file *psDRMFile = psPrivateData->psDRMFile; - - if (pFile->master == psDRMFile->master) - { - authenticated |= psDRMFile->authenticated; - if (authenticated) - { - break; - } - } - } - - if (!authenticated) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__)); - err = -EPERM; - goto unlock_and_return; - } - break; - } - default: - break; - } -#endif /* defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) */ - - err = BridgedDispatchKM(psPerProc, psBridgePackageKM); - if(err != PVRSRV_OK) - goto unlock_and_return; - - switch(cmd) - { - case PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2: - { - PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT = - (PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut; - PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); - IMG_HANDLE hMemInfo; - PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; - - if (pvr_get_user(hMemInfo, &psExportDeviceMemOUT->hMemInfo) != 0) - { - err = -EFAULT; - goto unlock_and_return; - } - - /* Look up the meminfo we just exported */ - if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE, - (IMG_PVOID *)&psKernelMemInfo, - hMemInfo, - PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__)); - err = -EFAULT; - goto unlock_and_return; - } - - /* Bump the refcount; decremented on release of the fd */ - PVRSRVKernelMemInfoIncRef(psKernelMemInfo); - - /* Tell the XProc about the export if required */ - if (psKernelMemInfo->sShareMemWorkaround.bInUse) - { - BM_XProcIndexAcquire(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex); - } - - psPrivateData->hKernelMemInfo = hMemInfo; -#if defined(SUPPORT_MEMINFO_IDS) - psPrivateData->ui64Stamp = ++ui64Stamp; - - psKernelMemInfo->ui64Stamp = psPrivateData->ui64Stamp; - if (pvr_put_user(psPrivateData->ui64Stamp, &psExportDeviceMemOUT->ui64Stamp) != 0) - { - err = -EFAULT; - goto unlock_and_return; - } -#endif - break; - } - -#if defined(SUPPORT_MEMINFO_IDS) - case PVRSRV_BRIDGE_MAP_DEV_MEMORY: - case PVRSRV_BRIDGE_MAP_DEV_MEMORY_2: - { - PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT = - (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut; - PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); - if (pvr_put_user(psPrivateData->ui64Stamp, &psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp) != 0) - { - err = -EFAULT; - goto unlock_and_return; - } - break; - } - - case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY: - { - PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT = - (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut; - if (pvr_put_user(++ui64Stamp, &psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp) != 0) - { - err = -EFAULT; - goto unlock_and_return; - } - break; - } -#endif /* defined(SUPPORT_MEMINFO_IDS) */ - - default: - break; - } - -unlock_and_return: - LinuxUnLockMutex(&gPVRSRVLock); - return err; -} diff --git a/pvr-source/services4/srvkm/env/linux/pvr_debug.c b/pvr-source/services4/srvkm/env/linux/pvr_debug.c deleted file mode 100755 index 04e42ad..0000000 --- a/pvr-source/services4/srvkm/env/linux/pvr_debug.c +++ /dev/null @@ -1,506 +0,0 @@ -/*************************************************************************/ /*! -@Title Debug Functionality -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description Provides kernel side Debug Functionality -@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 <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#include <asm/io.h> -#include <asm/uaccess.h> -#include <linux/kernel.h> -#include <linux/hardirq.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/string.h> // strncpy, strlen -#include <stdarg.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" - -#if !defined(CONFIG_PREEMPT) -#define PVR_DEBUG_ALWAYS_USE_SPINLOCK -#endif - -static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, - const IMG_CHAR* pszFormat, va_list VArgs) - IMG_FORMAT_PRINTF(3, 0); - - -#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); - -#endif /* defined(PVRSRV_NEED_PVR_DPF) || defined(PVRSRV_NEED_PVR_TRACE) */ - -#define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN - -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) -/* Message buffer for non-IRQ messages */ -static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1]; -#endif - -/* Message buffer for IRQ messages */ -static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1]; - -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) -/* The lock is used to control access to gszBufferNonIRQ */ -static PVRSRV_LINUX_MUTEX gsDebugMutexNonIRQ; -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) -/* The lock is used to control access to gszBufferIRQ */ -/* PRQA S 0671,0685 1 */ /* ignore warnings about C99 style initialisation */ -static spinlock_t gsDebugLockIRQ = SPIN_LOCK_UNLOCKED; -#else -static DEFINE_SPINLOCK(gsDebugLockIRQ); -#endif - -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) -#if !defined (USE_SPIN_LOCK) /* to keep QAC happy */ -#define USE_SPIN_LOCK (in_interrupt() || !preemptible()) -#endif -#endif - -static inline void GetBufferLock(unsigned long *pulLockFlags) -{ -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) - if (USE_SPIN_LOCK) -#endif - { - spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags); - } -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) - else - { - LinuxLockMutex(&gsDebugMutexNonIRQ); - } -#endif -} - -static inline void ReleaseBufferLock(unsigned long ulLockFlags) -{ -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) - if (USE_SPIN_LOCK) -#endif - { - spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags); - } -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) - else - { - LinuxUnLockMutex(&gsDebugMutexNonIRQ); - } -#endif -} - -static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz) -{ -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) - if (USE_SPIN_LOCK) -#endif - { - *ppszBuf = gszBufferIRQ; - *pui32BufSiz = sizeof(gszBufferIRQ); - } -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) - else - { - *ppszBuf = gszBufferNonIRQ; - *pui32BufSiz = sizeof(gszBufferNonIRQ); - } -#endif -} - -/* - * Append a string to a buffer using formatted conversion. - * The function takes a variable number of arguments, pointed - * to by the var args list. - */ -static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs) -{ - IMG_UINT32 ui32Used; - IMG_UINT32 ui32Space; - IMG_INT32 i32Len; - - ui32Used = strlen(pszBuf); - BUG_ON(ui32Used >= ui32BufSiz); - ui32Space = ui32BufSiz - ui32Used; - - i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs); - pszBuf[ui32BufSiz - 1] = 0; - - /* Return true if string was truncated */ - return (i32Len < 0 || i32Len >= (IMG_INT32)ui32Space) ? IMG_TRUE : IMG_FALSE; -} - -/* Actually required for ReleasePrintf too */ - -IMG_VOID PVRDPFInit(IMG_VOID) -{ -#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK) - LinuxInitMutex(&gsDebugMutexNonIRQ); -#endif -} - -/*! -****************************************************************************** - @Function PVRSRVReleasePrintf - @Description To output an important message to the user in release builds - @Input pszFormat - The message format string - @Input ... - Zero or more arguments for use by the format string - @Return None - ******************************************************************************/ -IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...) -{ - va_list vaArgs; - unsigned long ulLockFlags = 0; - IMG_CHAR *pszBuf; - IMG_UINT32 ui32BufSiz; - - SelectBuffer(&pszBuf, &ui32BufSiz); - - va_start(vaArgs, pszFormat); - - GetBufferLock(&ulLockFlags); - strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1)); - - if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs)) - { - printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf); - } - else - { - printk(KERN_INFO "%s\n", pszBuf); - } - - ReleaseBufferLock(ulLockFlags); - va_end(vaArgs); - -} - -#if defined(PVRSRV_NEED_PVR_TRACE) - -/*! -****************************************************************************** - @Function PVRTrace - @Description To output a debug message to the user - @Input pszFormat - The message format string - @Input ... - Zero or more arguments for use by the format string - @Return None - ******************************************************************************/ -IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...) -{ - va_list VArgs; - unsigned long ulLockFlags = 0; - IMG_CHAR *pszBuf; - IMG_UINT32 ui32BufSiz; - - SelectBuffer(&pszBuf, &ui32BufSiz); - - va_start(VArgs, pszFormat); - - GetBufferLock(&ulLockFlags); - - strncpy(pszBuf, "PVR: ", (ui32BufSiz -1)); - - if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs)) - { - printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf); - } - else - { - printk(KERN_INFO "%s\n", pszBuf); - } - - ReleaseBufferLock(ulLockFlags); - - va_end(VArgs); -} - -#endif /* defined(PVRSRV_NEED_PVR_TRACE) */ - -#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 - @Description To output a debug message to the user - @Input uDebugLevel - The current debug level - @Input pszFile - The source file generating the message - @Input uLine - The line of the source file - @Input pszFormat - The message format string - @Input ... - Zero or more arguments for use by the format string - @Return None - ******************************************************************************/ -IMG_VOID PVRSRVDebugPrintf ( - IMG_UINT32 ui32DebugLevel, - const IMG_CHAR* pszFullFileName, - IMG_UINT32 ui32Line, - const IMG_CHAR* pszFormat, - ... - ) -{ - IMG_BOOL bTrace; - const IMG_CHAR *pszFileName = pszFullFileName; - IMG_CHAR *pszLeafName; - - - bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE; - - if (gPVRDebugLevel & ui32DebugLevel) - { - va_list vaArgs; - unsigned long ulLockFlags = 0; - IMG_CHAR *pszBuf; - IMG_UINT32 ui32BufSiz; - - SelectBuffer(&pszBuf, &ui32BufSiz); - - va_start(vaArgs, pszFormat); - - GetBufferLock(&ulLockFlags); - - /* Add in the level of warning */ - if (bTrace == IMG_FALSE) - { - switch(ui32DebugLevel) - { - case DBGPRIV_FATAL: - { - strncpy (pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz -1)); - break; - } - case DBGPRIV_ERROR: - { - strncpy (pszBuf, "PVR_K:(Error): ", (ui32BufSiz -1)); - break; - } - case DBGPRIV_WARNING: - { - strncpy (pszBuf, "PVR_K:(Warning): ", (ui32BufSiz -1)); - break; - } - case DBGPRIV_MESSAGE: - { - strncpy (pszBuf, "PVR_K:(Message): ", (ui32BufSiz -1)); - break; - } - case DBGPRIV_VERBOSE: - { - strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1)); - break; - } - default: - { - strncpy (pszBuf, "PVR_K:(Unknown message level)", (ui32BufSiz -1)); - break; - } - } - } - else - { - strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1)); - } - - if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs)) - { - printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf); - } - else - { - /* Traces don't need a location */ - if (bTrace == IMG_FALSE) - { -#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; - - /* 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); - } - } - else - { - printk(KERN_INFO "%s\n", pszBuf); - } - } - - ReleaseBufferLock(ulLockFlags); - - va_end (vaArgs); - } -} - -#endif /* PVRSRV_NEED_PVR_DPF */ - -#if defined(DEBUG) - -IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data) -{ -#define _PROC_SET_BUFFER_SZ 6 - IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ]; - - if (count > _PROC_SET_BUFFER_SZ) - { - return -EINVAL; - } - else - { - if (pvr_copy_from_user(data_buffer, buffer, count)) - return -EINVAL; - if (data_buffer[count - 1] != '\n') - return -EINVAL; - if (sscanf(data_buffer, "%i", &gPVRDebugLevel) == 0) - return -EINVAL; - gPVRDebugLevel &= (1 << DBGPRIV_DBGLEVEL_COUNT) - 1; - } - return (count); -} - -void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el) -{ - seq_printf(sfile, "%u\n", gPVRDebugLevel); -} - -#endif /* defined(DEBUG) */ diff --git a/pvr-source/services4/srvkm/env/linux/pvr_uaccess.h b/pvr-source/services4/srvkm/env/linux/pvr_uaccess.h deleted file mode 100755 index 7583d7e..0000000 --- a/pvr-source/services4/srvkm/env/linux/pvr_uaccess.h +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************/ /*! -@Title Utility functions for user space access -@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 __PVR_UACCESS_H__ -#define __PVR_UACCESS_H__ - -#include <linux/version.h> - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) -#ifndef AUTOCONF_INCLUDED -#include <linux/config.h> -#endif -#endif - -#include <asm/uaccess.h> - -static inline unsigned long pvr_copy_to_user(void __user *pvTo, const void *pvFrom, unsigned long ulBytes) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) - if (access_ok(VERIFY_WRITE, pvTo, ulBytes)) - { - return __copy_to_user(pvTo, pvFrom, ulBytes); - } - return ulBytes; -#else - return copy_to_user(pvTo, pvFrom, ulBytes); -#endif -} - -static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pvFrom, unsigned long ulBytes) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) - /* - * The compile time correctness checking introduced for copy_from_user in - * Linux 2.6.33 isn't fully comaptible with our usage of the function. - */ - if (access_ok(VERIFY_READ, pvFrom, ulBytes)) - { - return __copy_from_user(pvTo, pvFrom, ulBytes); - } - return ulBytes; -#else - return copy_from_user(pvTo, pvFrom, ulBytes); -#endif -} - -#define pvr_put_user put_user -#define pvr_get_user get_user - -#endif /* __PVR_UACCESS_H__ */ - diff --git a/pvr-source/services4/srvkm/env/linux/sysfs.c b/pvr-source/services4/srvkm/env/linux/sysfs.c deleted file mode 100755 index 63066ad..0000000 --- a/pvr-source/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/pvr-source/services4/srvkm/env/linux/sysfs.h b/pvr-source/services4/srvkm/env/linux/sysfs.h deleted file mode 100755 index fb8d20f..0000000 --- a/pvr-source/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 |