void FreeAllocPagesLinuxMemArea(struct LinuxMemArea *psLinuxMemArea) { u32 ui32PageCount; struct page **pvPageList; u32 i; PVR_ASSERT(psLinuxMemArea); PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES); #if defined(DEBUG_LINUX_MEM_AREAS) DebugLinuxMemAreaRecordRemove(psLinuxMemArea); #endif ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize); pvPageList = psLinuxMemArea->uData.sPageList.pvPageList; #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList, __FILE__, __LINE__); #endif for (i = 0; i < ui32PageCount; i++) __free_pages(pvPageList[i], 0); VFreeWrapper(psLinuxMemArea->uData.sPageList.pvPageList); LinuxMemAreaStructFree(psLinuxMemArea); }
struct LinuxMemArea *NewAllocPagesLinuxMemArea(u32 ui32Bytes, u32 ui32AreaFlags) { struct LinuxMemArea *psLinuxMemArea; u32 ui32PageCount; struct page **pvPageList; u32 i; psLinuxMemArea = LinuxMemAreaStructAlloc(); if (!psLinuxMemArea) goto failed_area_alloc; ui32PageCount = RANGE_TO_PAGES(ui32Bytes); pvPageList = VMallocWrapper(sizeof(void *) * ui32PageCount, PVRSRV_HAP_CACHED); if (!pvPageList) goto failed_vmalloc; for (i = 0; i < ui32PageCount; i++) { pvPageList[i] = alloc_pages(GFP_KERNEL, 0); if (!pvPageList[i]) goto failed_alloc_pages; } #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList, NULL, 0, NULL, PAGE_ALIGN(ui32Bytes), "unknown", 0); #endif psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES; psLinuxMemArea->uData.sPageList.pvPageList = pvPageList; psLinuxMemArea->ui32ByteSize = ui32Bytes; #if defined(DEBUG_LINUX_MEM_AREAS) DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags); #endif return psLinuxMemArea; failed_alloc_pages: for (i--; i >= 0; i--) __free_pages(pvPageList[i], 0); VFreeWrapper(pvPageList); failed_vmalloc: LinuxMemAreaStructFree(psLinuxMemArea); failed_area_alloc: PVR_DPF(PVR_DBG_ERROR, "%s: failed", __func__); return NULL; }
void FreeVMallocLinuxMemArea(struct LinuxMemArea *psLinuxMemArea) { PVR_ASSERT(psLinuxMemArea); PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC); PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress); #if defined(DEBUG_LINUX_MEM_AREAS) DebugLinuxMemAreaRecordRemove(psLinuxMemArea); #endif PVR_DPF(PVR_DBG_MESSAGE, "%s: pvCpuVAddr: %p", __func__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress); VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress); LinuxMemAreaStructFree(psLinuxMemArea); }
void LinuxMMCleanup(void) { #if defined(DEBUG_LINUX_MEM_AREAS) { struct DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord = g_LinuxMemAreaRecords, *psNextRecord; if (g_LinuxMemAreaCount) PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: " "There are %d struct LinuxMemArea " "allocation unfreed (%ld bytes)", __func__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark); while (psCurrentRecord) { struct LinuxMemArea *psLinuxMemArea; psNextRecord = psCurrentRecord->psNext; psLinuxMemArea = psCurrentRecord->psLinuxMemArea; PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: " "Cleaning up Linux memory area (%p), " "type=%s, size=%ld bytes", __func__, psCurrentRecord->psLinuxMemArea, LinuxMemAreaTypeToString(psCurrentRecord-> psLinuxMemArea-> eAreaType), psCurrentRecord->psLinuxMemArea-> ui32ByteSize); LinuxMemAreaDeepFree(psLinuxMemArea); psCurrentRecord = psNextRecord; } RemoveProcEntry("mem_areas"); } #endif #if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) { struct DEBUG_MEM_ALLOC_REC *psCurrentRecord = g_MemoryRecords, *psNextRecord; while (psCurrentRecord) { psNextRecord = psCurrentRecord->psNext; PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: " "type=%s CpuVAddr=%p CpuPAddr=0x%08lx, " "allocated @ file=%s,line=%d", __func__, DebugMemAllocRecordTypeToString (psCurrentRecord->eAllocType), psCurrentRecord->pvCpuVAddr, psCurrentRecord->ulCpuPAddr, psCurrentRecord->pszFileName, psCurrentRecord->ui32Line); switch (psCurrentRecord->eAllocType) { case DEBUG_MEM_ALLOC_TYPE_KMALLOC: KFreeWrapper(psCurrentRecord->pvCpuVAddr); break; case DEBUG_MEM_ALLOC_TYPE_IOREMAP: IOUnmapWrapper((__force __iomem void *) psCurrentRecord->pvCpuVAddr); break; case DEBUG_MEM_ALLOC_TYPE_IO: DebugMemAllocRecordRemove (DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__); break; case DEBUG_MEM_ALLOC_TYPE_VMALLOC: VFreeWrapper(psCurrentRecord->pvCpuVAddr); break; case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES: DebugMemAllocRecordRemove (DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__); break; case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE: KMemCacheFreeWrapper(psCurrentRecord-> pvPrivateData, psCurrentRecord-> pvCpuVAddr); break; default: PVR_ASSERT(0); } psCurrentRecord = psNextRecord; } RemoveProcEntry("meminfo"); } #endif if (psLinuxMemAreaCache) { kmem_cache_destroy(psLinuxMemAreaCache); psLinuxMemAreaCache = NULL; } }