diff options
Diffstat (limited to 'pvr-source/services4/srvkm/env/linux/osfunc.c')
-rwxr-xr-x | pvr-source/services4/srvkm/env/linux/osfunc.c | 4714 |
1 files changed, 0 insertions, 4714 deletions
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 -} |