1 /**********************************************************************
2 Copyright (c) Imagination Technologies Ltd.
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 ******************************************************************************/
23 #ifndef __IMG_LINUX_MM_H__
24 #define __IMG_LINUX_MM_H__
26 #include <linux/version.h>
27 #include <linux/slab.h>
29 #include <linux/list.h>
33 #define PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
34 #define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
36 #define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
38 #define ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
40 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
41 #define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_pfn_range(vma, addr, pfn, size, prot)
43 #define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
46 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
47 #define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_pfn_range(vma, addr, pfn, size, prot)
49 #define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
52 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
53 #define VM_INSERT_PAGE(vma, addr, page) vm_insert_page(vma, addr, page)
55 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
56 #define VM_INSERT_PAGE(vma, addr, page) remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, vma->vm_page_prot);
58 #define VM_INSERT_PAGE(vma, addr, page) remap_page_range(vma, addr, page_to_phys(page), PAGE_SIZE, vma->vm_page_prot);
62 static inline IMG_UINT32 VMallocToPhys(IMG_VOID *pCpuVAddr)
64 return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
69 LINUX_MEM_AREA_IOREMAP,
70 LINUX_MEM_AREA_EXTERNAL_KV,
72 LINUX_MEM_AREA_VMALLOC,
73 LINUX_MEM_AREA_ALLOC_PAGES,
74 LINUX_MEM_AREA_SUB_ALLOC,
75 LINUX_MEM_AREA_TYPE_COUNT
78 typedef struct _LinuxMemArea LinuxMemArea;
81 struct _LinuxMemArea {
82 LINUX_MEM_AREA_TYPE eAreaType;
88 IMG_CPU_PHYADDR CPUPhysAddr;
89 IMG_VOID *pvIORemapCookie;
97 IMG_SYS_PHYADDR SysPhysAddr;
98 IMG_SYS_PHYADDR *pSysPhysAddr;
100 IMG_VOID *pvExternalKV;
105 IMG_CPU_PHYADDR CPUPhysAddr;
110 IMG_VOID *pvVmallocAddress;
115 struct page **pvPageList;
116 IMG_HANDLE hBlockPageList;
121 LinuxMemArea *psParentLinuxMemArea;
122 IMG_UINT32 ui32ByteOffset;
126 IMG_UINT32 ui32ByteSize;
128 IMG_UINT32 ui32AreaFlags;
130 IMG_BOOL bMMapRegistered;
133 struct list_head sMMapItem;
136 struct list_head sMMapOffsetStructList;
139 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
140 typedef kmem_cache_t LinuxKMemCache;
142 typedef struct kmem_cache LinuxKMemCache;
146 PVRSRV_ERROR LinuxMMInit(IMG_VOID);
149 IMG_VOID LinuxMMCleanup(IMG_VOID);
152 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
153 #define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, __FILE__, __LINE__)
155 #define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, NULL, 0)
157 IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
160 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
161 #define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
163 #define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, NULL, 0)
165 IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
168 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
169 #define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
171 #define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, NULL, 0)
173 IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
176 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
177 #define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
179 #define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, NULL, 0)
181 IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
184 LinuxMemArea *NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
187 IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
190 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
191 #define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
192 _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
194 #define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
195 _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
197 IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
198 IMG_UINT32 ui32Bytes,
199 IMG_UINT32 ui32MappingFlags,
200 IMG_CHAR *pszFileName,
201 IMG_UINT32 ui32Line);
204 LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
207 IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
209 LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
212 IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
215 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
216 #define IOUnmapWrapper(pvIORemapCookie) \
217 _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
219 #define IOUnmapWrapper(pvIORemapCookie) \
220 _IOUnmapWrapper(pvIORemapCookie, NULL, 0)
222 IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
225 struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
228 LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags);
231 IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache);
234 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
235 #define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
237 #define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, NULL, 0)
240 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
241 IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, gfp_t Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
243 IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
246 #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
247 #define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
249 #define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, NULL, 0)
251 IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
254 const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
257 LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
260 IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
263 LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
266 IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
269 LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
270 IMG_UINT32 ui32ByteOffset,
271 IMG_UINT32 ui32Bytes);
274 IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
277 #if defined(LINUX_MEM_AREAS_DEBUG)
278 IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
280 #define LinuxMemAreaRegister(X)
284 IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
287 IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
290 #define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr)
292 IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
294 static inline LinuxMemArea *
295 LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
297 if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
299 return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
303 return psLinuxMemArea;
308 static inline LINUX_MEM_AREA_TYPE
309 LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
311 return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
315 const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
318 #if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS)
319 const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags);