diff options
Diffstat (limited to 'drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c')
-rw-r--r-- | drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c | 1157 |
1 files changed, 0 insertions, 1157 deletions
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c deleted file mode 100644 index daeea084d83b..000000000000 --- a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c +++ /dev/null @@ -1,1157 +0,0 @@ -/********************************************************************** - * - * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful but, except - * as otherwise stated in writing, without any warranty; without even the - * implied warranty of merchantability or fitness for a particular purpose. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Imagination Technologies Ltd. <gpl-support@imgtec.com> - * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK - * - ******************************************************************************/ - -#ifndef AUTOCONF_INCLUDED - #include <linux/config.h> -#endif - -#include <linux/version.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/vmalloc.h> -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) -#include <linux/wrapper.h> -#endif -#include <linux/slab.h> -#include <asm/io.h> -#include <asm/page.h> -#include <asm/shmparam.h> -#include <asm/pgtable.h> -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) -#include <linux/sched.h> -#include <asm/current.h> -#endif -#if defined(SUPPORT_DRI_DRM) -#include <drm/drmP.h> -#endif - -#include "img_defs.h" -#include "services.h" -#include "servicesint.h" -#include "pvrmmap.h" -#include "mutils.h" -#include "mmap.h" -#include "mm.h" -#include "pvr_debug.h" -#include "osfunc.h" -#include "proc.h" -#include "mutex.h" -#include "handle.h" -#include "perproc.h" -#include "env_perproc.h" -#include "bridged_support.h" -#if defined(SUPPORT_DRI_DRM) -#include "pvr_drm.h" -#endif - -#if !defined(PVR_SECURE_HANDLES) -#error "The mmap code requires PVR_SECURE_HANDLES" -#endif - -static PVRSRV_LINUX_MUTEX g_sMMapMutex; - -static LinuxKMemCache *g_psMemmapCache = NULL; -static LIST_HEAD(g_sMMapAreaList); -static LIST_HEAD(g_sMMapOffsetStructList); -#if defined(DEBUG_LINUX_MMAP_AREAS) -static IMG_UINT32 g_ui32RegisteredAreas = 0; -static IMG_UINT32 g_ui32TotalByteSize = 0; -#endif - - -#if defined(PVR_PROC_USE_SEQ_FILE) && defined(DEBUG_LINUX_MMAP_AREAS) -static struct proc_dir_entry *g_ProcMMap; -#endif - -#define FIRST_PHYSICAL_PFN 0 -#define LAST_PHYSICAL_PFN 0x7fffffffUL -#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1) -#define LAST_SPECIAL_PFN 0xffffffffUL - -#define MAX_MMAP_HANDLE 0x7fffffffUL - -static inline IMG_BOOL -PFNIsPhysical(IMG_UINT32 pfn) -{ - - return ((pfn >= FIRST_PHYSICAL_PFN) && (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE; -} - -static inline IMG_BOOL -PFNIsSpecial(IMG_UINT32 pfn) -{ - - return ((pfn >= FIRST_SPECIAL_PFN) && (pfn <= LAST_SPECIAL_PFN)) ? IMG_TRUE : IMG_FALSE; -} - -static inline IMG_HANDLE -MMapOffsetToHandle(IMG_UINT32 pfn) -{ - if (PFNIsPhysical(pfn)) - { - PVR_ASSERT(PFNIsPhysical(pfn)); - return IMG_NULL; - } - - return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN); -} - -static inline IMG_UINT32 -HandleToMMapOffset(IMG_HANDLE hHandle) -{ - IMG_UINT32 ulHandle = (IMG_UINT32)hHandle; - - if (PFNIsSpecial(ulHandle)) - { - PVR_ASSERT(PFNIsSpecial(ulHandle)); - return 0; - } - - return ulHandle + FIRST_SPECIAL_PFN; -} - -static inline IMG_BOOL -LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea) -{ - return LinuxMemAreaPhysIsContig(psLinuxMemArea); -} - -static inline IMG_UINT32 -GetCurrentThreadID(IMG_VOID) -{ - - return (IMG_UINT32)current->pid; -} - -static PKV_OFFSET_STRUCT -CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize) -{ - PKV_OFFSET_STRUCT psOffsetStruct; -#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS) - const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea)); -#endif - -#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS) - PVR_DPF((PVR_DBG_MESSAGE, - "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8lx)", - __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags)); -#endif - - PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC); - - PVR_ASSERT(psLinuxMemArea->bMMapRegistered); - - psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL); - if(psOffsetStruct == IMG_NULL) - { - PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache")); - return IMG_NULL; - } - - psOffsetStruct->ui32MMapOffset = ui32Offset; - - psOffsetStruct->psLinuxMemArea = psLinuxMemArea; - - psOffsetStruct->ui32Mapped = 0; - - psOffsetStruct->ui32RealByteSize = ui32RealByteSize; - - - psOffsetStruct->ui32TID = GetCurrentThreadID(); - - psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM(); - - psOffsetStruct->bOnMMapList = IMG_FALSE; - - psOffsetStruct->ui32RefCount = 0; - - psOffsetStruct->ui32UserVAddr = 0; - -#if defined(DEBUG_LINUX_MMAP_AREAS) - - psOffsetStruct->pszName = pszName; -#endif - - list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList); - - return psOffsetStruct; -} - - -static IMG_VOID -DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct) -{ - list_del(&psOffsetStruct->sAreaItem); - - if (psOffsetStruct->bOnMMapList) - { - list_del(&psOffsetStruct->sMMapItem); - } - - PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: " - "psLinuxMemArea=0x%08lX, CpuPAddr=0x%08lX", __FUNCTION__, - psOffsetStruct->psLinuxMemArea, - LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0))); - - KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct); -} - - -static inline IMG_VOID -DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea, - IMG_UINT32 *pui32RealByteSize, - IMG_UINT32 *pui32ByteOffset) -{ - IMG_UINT32 ui32PageAlignmentOffset; - IMG_CPU_PHYADDR CpuPAddr; - - CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0); - ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr); - - *pui32ByteOffset = ui32PageAlignmentOffset; - - *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset); -} - - -PVRSRV_ERROR -PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, - IMG_HANDLE hMHandle, - IMG_UINT32 *pui32MMapOffset, - IMG_UINT32 *pui32ByteOffset, - IMG_UINT32 *pui32RealByteSize, - IMG_UINT32 *pui32UserVAddr) -{ - LinuxMemArea *psLinuxMemArea; - PKV_OFFSET_STRUCT psOffsetStruct; - IMG_HANDLE hOSMemHandle; - PVRSRV_ERROR eError; - - LinuxLockMutex(&g_sMMapMutex); - - PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE); - - eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle)); - - goto exit_unlock; - } - - psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - - DetermineUsersSizeAndByteOffset(psLinuxMemArea, - pui32RealByteSize, - pui32ByteOffset); - - - list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) - { - if (psPerProc->ui32PID == psOffsetStruct->ui32PID) - { - - PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize); - - *pui32MMapOffset = psOffsetStruct->ui32MMapOffset; - *pui32UserVAddr = psOffsetStruct->ui32UserVAddr; - psOffsetStruct->ui32RefCount++; - - eError = PVRSRV_OK; - goto exit_unlock; - } - } - - - *pui32UserVAddr = 0; - - if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea)) - { - *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0); - PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset)); - } - else - { - *pui32MMapOffset = HandleToMMapOffset(hMHandle); - PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset)); - } - - psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize); - if (psOffsetStruct == IMG_NULL) - { - eError = PVRSRV_ERROR_OUT_OF_MEMORY; - goto exit_unlock; - } - - - list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList); - - psOffsetStruct->bOnMMapList = IMG_TRUE; - - psOffsetStruct->ui32RefCount++; - - eError = PVRSRV_OK; - -exit_unlock: - LinuxUnLockMutex(&g_sMMapMutex); - - return eError; -} - - -PVRSRV_ERROR -PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, - IMG_HANDLE hMHandle, - IMG_BOOL *pbMUnmap, - IMG_UINT32 *pui32RealByteSize, - IMG_UINT32 *pui32UserVAddr) -{ - LinuxMemArea *psLinuxMemArea; - PKV_OFFSET_STRUCT psOffsetStruct; - IMG_HANDLE hOSMemHandle; - PVRSRV_ERROR eError; - IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); - - LinuxLockMutex(&g_sMMapMutex); - - PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE); - - eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle)); - - goto exit_unlock; - } - - psLinuxMemArea = (LinuxMemArea *)hOSMemHandle; - - - list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) - { - if (psOffsetStruct->ui32PID == ui32PID) - { - if (psOffsetStruct->ui32RefCount == 0) - { - PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area 0x%p", __FUNCTION__, psOffsetStruct, psLinuxMemArea)); - eError = PVRSRV_ERROR_GENERIC; - goto exit_unlock; - } - - psOffsetStruct->ui32RefCount--; - - *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0)); - - *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0; - *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0; - - eError = PVRSRV_OK; - goto exit_unlock; - } - } - - - PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle 0x%lx (memory area 0x%p)", __FUNCTION__, hMHandle, psLinuxMemArea)); - - eError = PVRSRV_ERROR_GENERIC; - -exit_unlock: - LinuxUnLockMutex(&g_sMMapMutex); - - return eError; -} - -static inline PKV_OFFSET_STRUCT -FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize) -{ - PKV_OFFSET_STRUCT psOffsetStruct; - IMG_UINT32 ui32TID = GetCurrentThreadID(); - IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); - - list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem) - { - if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID) - { - - if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID) - { - return psOffsetStruct; - } - } - } - - return IMG_NULL; -} - - -static IMG_BOOL -DoMapToUser(LinuxMemArea *psLinuxMemArea, - struct vm_area_struct* ps_vma, - IMG_UINT32 ui32ByteOffset) -{ - IMG_UINT32 ui32ByteSize; - - if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC) - { - return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea), - ps_vma, - psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset); - } - - - ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start; - PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0); - -#if defined (__sparc__) - -#error "SPARC not supported" -#endif - - if (PFNIsPhysical(ps_vma->vm_pgoff)) - { - IMG_INT result; - - PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea)); - PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff); - - - result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot); - - if(result == 0) - { - return IMG_TRUE; - } - - PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result)); - } - - { - - IMG_UINT32 ulVMAPos; - IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize; - IMG_UINT32 ui32PA; - - - for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE) - { - IMG_UINT32 pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA); - - if (!pfn_valid(pfn)) - { - PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%lx", __FUNCTION__, pfn)); - return IMG_FALSE; - } - } - - - ulVMAPos = ps_vma->vm_start; - for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE) - { - IMG_UINT32 pfn; - struct page *psPage; - IMG_INT result; - - pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA); - PVR_ASSERT(pfn_valid(pfn)); - - psPage = pfn_to_page(pfn); - - result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage); - if(result != 0) - { - PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result)); - return IMG_FALSE; - } - ulVMAPos += PAGE_SIZE; - } - } - - return IMG_TRUE; -} - - -static IMG_VOID -MMapVOpenNoLock(struct vm_area_struct* ps_vma) -{ - PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data; - PVR_ASSERT(psOffsetStruct != IMG_NULL) - psOffsetStruct->ui32Mapped++; - PVR_ASSERT(!psOffsetStruct->bOnMMapList); - - if (psOffsetStruct->ui32Mapped > 1) - { - PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %lu)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped)); - PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0); - } - -#if defined(DEBUG_LINUX_MMAP_AREAS) - - PVR_DPF((PVR_DBG_MESSAGE, - "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %ld, ui32Mapped %d", - __FUNCTION__, - psOffsetStruct->psLinuxMemArea, - LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea), - psOffsetStruct->ui32MMapOffset, - psOffsetStruct->ui32Mapped)); -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) - MOD_INC_USE_COUNT; -#endif -} - - -static void -MMapVOpen(struct vm_area_struct* ps_vma) -{ - LinuxLockMutex(&g_sMMapMutex); - - MMapVOpenNoLock(ps_vma); - - LinuxUnLockMutex(&g_sMMapMutex); -} - - -static IMG_VOID -MMapVCloseNoLock(struct vm_area_struct* ps_vma) -{ - PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data; - PVR_ASSERT(psOffsetStruct != IMG_NULL) - -#if defined(DEBUG_LINUX_MMAP_AREAS) - PVR_DPF((PVR_DBG_MESSAGE, - "%s: psLinuxMemArea 0x%p, CpuVAddr 0x%p ui32MMapOffset %ld, ui32Mapped %d", - __FUNCTION__, - psOffsetStruct->psLinuxMemArea, - LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea), - psOffsetStruct->ui32MMapOffset, - psOffsetStruct->ui32Mapped)); -#endif - - PVR_ASSERT(!psOffsetStruct->bOnMMapList); - psOffsetStruct->ui32Mapped--; - if (psOffsetStruct->ui32Mapped == 0) - { - if (psOffsetStruct->ui32RefCount != 0) - { - PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct 0x%p has non-zero reference count (ui32RefCount = %lu). User mode address of start of mapping: 0x%lx", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr)); - } - - DestroyOffsetStruct(psOffsetStruct); - } - - ps_vma->vm_private_data = NULL; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) - MOD_DEC_USE_COUNT; -#endif -} - -static void -MMapVClose(struct vm_area_struct* ps_vma) -{ - LinuxLockMutex(&g_sMMapMutex); - - MMapVCloseNoLock(ps_vma); - - LinuxUnLockMutex(&g_sMMapMutex); -} - - -static struct vm_operations_struct MMapIOOps = -{ - .open=MMapVOpen, - .close=MMapVClose -}; - - -int -PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma) -{ - IMG_UINT32 ui32ByteSize; - PKV_OFFSET_STRUCT psOffsetStruct; - int iRetVal = 0; - - PVR_UNREFERENCED_PARAMETER(pFile); - - LinuxLockMutex(&g_sMMapMutex); - - ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start; - - - PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx," - " and ui32ByteSize %ld(0x%08lx)", - __FUNCTION__, - ps_vma->vm_pgoff, - ui32ByteSize, ui32ByteSize)); - - psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize); - if (psOffsetStruct == IMG_NULL) - { -#if defined(SUPPORT_DRI_DRM) - LinuxUnLockMutex(&g_sMMapMutex); - - - return drm_mmap(pFile, ps_vma); -#else - PVR_UNREFERENCED_PARAMETER(pFile); - -#if 0 /* FIXME: crash when call to print debug messages */ - PVR_DPF((PVR_DBG_ERROR, - "%s: Attempted to mmap unregistered area at vm_pgoff %ld", - __FUNCTION__, ps_vma->vm_pgoff)); -#endif - iRetVal = -EINVAL; -#endif - goto unlock_and_return; - } - list_del(&psOffsetStruct->sMMapItem); - psOffsetStruct->bOnMMapList = IMG_FALSE; - - - if (((ps_vma->vm_flags & VM_WRITE) != 0) && - ((ps_vma->vm_flags & VM_SHARED) == 0)) - { -#if 0 /* FIXME: crash when call to print debug messages */ - PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__)); -#endif - iRetVal = -EINVAL; - goto unlock_and_return; - } - - -#if 0 /* FIXME: crash when call to print debug messages */ - PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n", - __FUNCTION__, psOffsetStruct->psLinuxMemArea)); -#endif - ps_vma->vm_flags |= VM_RESERVED; - ps_vma->vm_flags |= VM_IO; - - - ps_vma->vm_flags |= VM_DONTEXPAND; - - - ps_vma->vm_flags |= VM_DONTCOPY; - - ps_vma->vm_private_data = (void *)psOffsetStruct; - - switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK) - { - case PVRSRV_HAP_CACHED: - - break; - case PVRSRV_HAP_WRITECOMBINE: - ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot); - break; - case PVRSRV_HAP_UNCACHED: - ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot); - break; - default: - PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__)); - iRetVal = -EINVAL; - goto unlock_and_return; - } - - - ps_vma->vm_ops = &MMapIOOps; - - if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0)) - { - iRetVal = -EAGAIN; - goto unlock_and_return; - } - - PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0) - - psOffsetStruct->ui32UserVAddr = ps_vma->vm_start; - - - MMapVOpenNoLock(ps_vma); - -#if 0 /* FIXME: crash when call to print debug messages */ - PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n", - __FUNCTION__, ps_vma->vm_pgoff)); -#endif - -unlock_and_return: - if (iRetVal != 0 && psOffsetStruct != IMG_NULL) - { - DestroyOffsetStruct(psOffsetStruct); - } - - LinuxUnLockMutex(&g_sMMapMutex); - - return iRetVal; -} - - -#if defined(DEBUG_LINUX_MMAP_AREAS) - -#ifdef PVR_PROC_USE_SEQ_FILE - -static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start) -{ - if(start) - { - LinuxLockMutex(&g_sMMapMutex); - } - else - { - LinuxUnLockMutex(&g_sMMapMutex); - } -} - - -static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off) -{ - LinuxMemArea *psLinuxMemArea; - if(!off) - { - return PVR_PROC_SEQ_START_TOKEN; - } - - list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem) - { - PKV_OFFSET_STRUCT psOffsetStruct; - - list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) - { - off--; - if (off == 0) - { - PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea); - return (void*)psOffsetStruct; - } - } - } - return (void*)0; -} - -static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off) -{ - return ProcSeqOff2ElementMMapRegistrations(sfile,off); -} - - -static void ProcSeqShowMMapRegistrations(struct seq_file *sfile,void* el) -{ - KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el; - LinuxMemArea *psLinuxMemArea; - IMG_UINT32 ui32RealByteSize; - IMG_UINT32 ui32ByteOffset; - - if(el == PVR_PROC_SEQ_START_TOKEN) - { - seq_printf( sfile, -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - "Allocations registered for mmap: %lu\n" - "In total these areas correspond to %lu bytes\n" - "psLinuxMemArea " - "UserVAddr " - "KernelVAddr " - "CpuPAddr " - "MMapOffset " - "ByteLength " - "LinuxMemType " - "Pid Name Flags\n", -#else - "<mmap_header>\n" - "\t<count>%lu</count>\n" - "\t<bytes>%lu</bytes>\n" - "</mmap_header>\n", -#endif - g_ui32RegisteredAreas, - g_ui32TotalByteSize - ); - return; - } - - psLinuxMemArea = psOffsetStruct->psLinuxMemArea; - - DetermineUsersSizeAndByteOffset(psLinuxMemArea, - &ui32RealByteSize, - &ui32ByteOffset); - - seq_printf( sfile, -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - "%-8p %08lx %-8p %08lx %08lx %-8ld %-24s %-5lu %-8s %08lx(%s)\n", -#else - "<mmap_record>\n" - "\t<pointer>%-8p</pointer>\n" - "\t<user_virtual>%-8lx</user_virtual>\n" - "\t<kernel_virtual>%-8p</kernel_virtual>\n" - "\t<cpu_physical>%08lx</cpu_physical>\n" - "\t<mmap_offset>%08lx</mmap_offset>\n" - "\t<bytes>%-8ld</bytes>\n" - "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n" - "\t<pid>%-5lu</pid>\n" - "\t<name>%-8s</name>\n" - "\t<flags>%08lx</flags>\n" - "\t<flags_string>%s</flags_string>\n" - "</mmap_record>\n", -#endif - psLinuxMemArea, - psOffsetStruct->ui32UserVAddr + ui32ByteOffset, - LinuxMemAreaToCpuVAddr(psLinuxMemArea), - LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr, - psOffsetStruct->ui32MMapOffset, - psLinuxMemArea->ui32ByteSize, - LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType), - psOffsetStruct->ui32PID, - psOffsetStruct->pszName, - psLinuxMemArea->ui32AreaFlags, - HAPFlagsToString(psLinuxMemArea->ui32AreaFlags)); -} - -#else - -static off_t -PrintMMapRegistrations(IMG_CHAR *buffer, size_t size, off_t off) -{ - LinuxMemArea *psLinuxMemArea; - off_t Ret; - - LinuxLockMutex(&g_sMMapMutex); - - if(!off) - { - Ret = printAppend(buffer, size, 0, -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - "Allocations registered for mmap: %lu\n" - "In total these areas correspond to %lu bytes\n" - "psLinuxMemArea " - "UserVAddr " - "KernelVAddr " - "CpuPAddr " - "MMapOffset " - "ByteLength " - "LinuxMemType " - "Pid Name Flags\n", -#else - "<mmap_header>\n" - "\t<count>%lu</count>\n" - "\t<bytes>%lu</bytes>\n" - "</mmap_header>\n", -#endif - g_ui32RegisteredAreas, - g_ui32TotalByteSize - ); - - goto unlock_and_return; - } - - if (size < 135) - { - Ret = 0; - goto unlock_and_return; - } - - PVR_ASSERT(off != 0); - list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem) - { - PKV_OFFSET_STRUCT psOffsetStruct; - - list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) - { - off--; - if (off == 0) - { - IMG_UINT32 ui32RealByteSize; - IMG_UINT32 ui32ByteOffset; - - PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea); - - DetermineUsersSizeAndByteOffset(psLinuxMemArea, - &ui32RealByteSize, - &ui32ByteOffset); - - Ret = printAppend (buffer, size, 0, -#if !defined(DEBUG_LINUX_XML_PROC_FILES) - "%-8p %08lx %-8p %08lx %08lx %-8ld %-24s %-5lu %-8s %08lx(%s)\n", -#else - "<mmap_record>\n" - "\t<pointer>%-8p</pointer>\n" - "\t<user_virtual>%-8lx</user_virtual>\n" - "\t<kernel_virtual>%-8p</kernel_virtual>\n" - "\t<cpu_physical>%08lx</cpu_physical>\n" - "\t<mmap_offset>%08lx</mmap_offset>\n" - "\t<bytes>%-8ld</bytes>\n" - "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n" - "\t<pid>%-5lu</pid>\n" - "\t<name>%-8s</name>\n" - "\t<flags>%08lx</flags>\n" - "\t<flags_string>%s</flags_string>\n" - "</mmap_record>\n", -#endif - psLinuxMemArea, - psOffsetStruct->ui32UserVAddr + ui32ByteOffset, - LinuxMemAreaToCpuVAddr(psLinuxMemArea), - LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr, - psOffsetStruct->ui32MMapOffset, - psLinuxMemArea->ui32ByteSize, - LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType), - psOffsetStruct->ui32PID, - psOffsetStruct->pszName, - psLinuxMemArea->ui32AreaFlags, - HAPFlagsToString(psLinuxMemArea->ui32AreaFlags)); - goto unlock_and_return; - } - } - } - Ret = END_OF_FILE; - -unlock_and_return: - LinuxUnLockMutex(&g_sMMapMutex); - return Ret; -} -#endif -#endif - - -PVRSRV_ERROR -PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea) -{ - PVRSRV_ERROR eError; -#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS) - const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea)); -#endif - - LinuxLockMutex(&g_sMMapMutex); - -#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS) - PVR_DPF((PVR_DBG_MESSAGE, - "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8lx)", - __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags)); -#endif - - PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC); - - - if(psLinuxMemArea->bMMapRegistered) - { - PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered", - __FUNCTION__, psLinuxMemArea)); - eError = PVRSRV_ERROR_INVALID_PARAMS; - goto exit_unlock; - } - - list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList); - - psLinuxMemArea->bMMapRegistered = IMG_TRUE; - -#if defined(DEBUG_LINUX_MMAP_AREAS) - g_ui32RegisteredAreas++; - - if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) - { - g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize; - } -#endif - - eError = PVRSRV_OK; - -exit_unlock: - LinuxUnLockMutex(&g_sMMapMutex); - - return eError; -} - - -PVRSRV_ERROR -PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea) -{ - PVRSRV_ERROR eError; - PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct; - - LinuxLockMutex(&g_sMMapMutex); - - PVR_ASSERT(psLinuxMemArea->bMMapRegistered); - - list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) - { - if (psOffsetStruct->ui32Mapped != 0) - { - PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %lu", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped)); - eError = PVRSRV_ERROR_GENERIC; - goto exit_unlock; - } - else - { - - PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped", __FUNCTION__, psOffsetStruct)); - } - - PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList); - - DestroyOffsetStruct(psOffsetStruct); - } - - list_del(&psLinuxMemArea->sMMapItem); - - psLinuxMemArea->bMMapRegistered = IMG_FALSE; - -#if defined(DEBUG_LINUX_MMAP_AREAS) - g_ui32RegisteredAreas--; - if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) - { - g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize; - } -#endif - - eError = PVRSRV_OK; - -exit_unlock: - LinuxUnLockMutex(&g_sMMapMutex); - return eError; -} - - -PVRSRV_ERROR -LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc) -{ - PVR_UNREFERENCED_PARAMETER(psEnvPerProc); - - return PVRSRV_OK; -} - -IMG_VOID -LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc) -{ - PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct; - IMG_BOOL bWarn = IMG_FALSE; - IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); - - PVR_UNREFERENCED_PARAMETER(psEnvPerProc); - - LinuxLockMutex(&g_sMMapMutex); - - list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem) - { - if (psOffsetStruct->ui32PID == ui32PID) - { - if (!bWarn) - { - PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__)); - bWarn = IMG_TRUE; - } - PVR_ASSERT(psOffsetStruct->ui32Mapped == 0); - PVR_ASSERT(psOffsetStruct->bOnMMapList); - - DestroyOffsetStruct(psOffsetStruct); - } - } - - LinuxUnLockMutex(&g_sMMapMutex); -} - - -PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase) -{ - PVRSRV_ERROR eError; - - eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError)); - return eError; - } - - return eError; -} - - -IMG_VOID -PVRMMapInit(IMG_VOID) -{ - LinuxInitMutex(&g_sMMapMutex); - - g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0); - if (!g_psMemmapCache) - { - PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__)); - goto error; - } - -#if defined(DEBUG_LINUX_MMAP_AREAS) -#ifdef PVR_PROC_USE_SEQ_FILE - g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL, - ProcSeqNextMMapRegistrations, - ProcSeqShowMMapRegistrations, - ProcSeqOff2ElementMMapRegistrations, - ProcSeqStartstopMMapRegistations - ); -#else - CreateProcReadEntry("mmap", PrintMMapRegistrations); -#endif -#endif - return; - -error: - PVRMMapCleanup(); - return; -} - - -IMG_VOID -PVRMMapCleanup(IMG_VOID) -{ - PVRSRV_ERROR eError; - - if (!list_empty(&g_sMMapAreaList)) - { - LinuxMemArea *psLinuxMemArea, *psTmpMemArea; - - PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__)); - - PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__)); - list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem) - { - eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea); - if (eError != PVRSRV_OK) - { - PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError)); - } - PVR_ASSERT(eError == PVRSRV_OK); - - LinuxMemAreaDeepFree(psLinuxMemArea); - } - } - PVR_ASSERT(list_empty((&g_sMMapAreaList))); - -#if defined(DEBUG_LINUX_MMAP_AREAS) -#ifdef PVR_PROC_USE_SEQ_FILE - RemoveProcEntrySeq(g_ProcMMap); -#else - RemoveProcEntry("mmap"); -#endif -#endif - - if(g_psMemmapCache) - { - KMemCacheDestroyWrapper(g_psMemmapCache); - g_psMemmapCache = NULL; - } -} |