void FreeIORemapLinuxMemArea(struct LinuxMemArea *psLinuxMemArea) { PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP); #if defined(DEBUG_LINUX_MEM_AREAS) DebugLinuxMemAreaRecordRemove(psLinuxMemArea); #endif IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie); LinuxMemAreaStructFree(psLinuxMemArea); }
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; } }
enum PVRSRV_ERROR PDumpMemKM(void *pvAltLinAddr, struct PVRSRV_KERNEL_MEM_INFO *psMemInfo, u32 ui32Offset, u32 ui32Bytes, u32 ui32Flags, void *hUniqueTag) { u32 ui32PageByteOffset; u8 *pui8DataLinAddr; struct IMG_DEV_VIRTADDR sDevVPageAddr; struct IMG_DEV_VIRTADDR sDevVAddr; struct IMG_DEV_PHYADDR sDevPAddr; struct IMG_CPU_PHYADDR CpuPAddr; u32 ui32ParamOutPos; u32 ui32CurrentOffset; u32 ui32BytesRemaining; struct LinuxMemArea *psLinuxMemArea; enum LINUX_MEM_AREA_TYPE eRootAreaType; char *pui8TransientCpuVAddr; __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC); PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->ui32AllocSize); if (ui32Bytes == 0 || gui32PDumpSuspended) return PVRSRV_OK; if (pvAltLinAddr) { pui8DataLinAddr = pvAltLinAddr; } else if (psMemInfo->pvLinAddrKM) { pui8DataLinAddr = (u8 *) psMemInfo->pvLinAddrKM + ui32Offset; } else { pui8DataLinAddr = 0; psLinuxMemArea = (struct LinuxMemArea *)psMemInfo->sMemBlk.hOSMemHandle; eRootAreaType = LinuxMemAreaRootType(psLinuxMemArea); } ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState. psStream[PDUMP_STREAM_PARAM2]); if (pui8DataLinAddr) { if (!PDumpWriteILock (gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], pui8DataLinAddr, ui32Bytes, ui32Flags)) return PVRSRV_ERROR_GENERIC; } else if (eRootAreaType == LINUX_MEM_AREA_IO) { CpuPAddr = OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset); pui8TransientCpuVAddr = IORemapWrapper(CpuPAddr, ui32Bytes, PVRSRV_HAP_CACHED); if (!PDumpWriteILock (gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], pui8TransientCpuVAddr, ui32Bytes, ui32Flags)) { IOUnmapWrapper(pui8TransientCpuVAddr); return PVRSRV_ERROR_GENERIC; } IOUnmapWrapper(pui8TransientCpuVAddr); } else { PVR_ASSERT(eRootAreaType == LINUX_MEM_AREA_ALLOC_PAGES); ui32BytesRemaining = ui32Bytes; ui32CurrentOffset = ui32Offset; while (ui32BytesRemaining > 0) { u32 ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_SIZE); struct page *psCurrentPage = NULL; CpuPAddr = OSMemHandleToCpuPAddr(psMemInfo->sMemBlk. hOSMemHandle, ui32CurrentOffset); if (CpuPAddr.uiAddr & (PAGE_SIZE - 1)) ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_ALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr); psCurrentPage = LinuxMemAreaOffsetToPage(psLinuxMemArea, ui32CurrentOffset); pui8TransientCpuVAddr = KMapWrapper(psCurrentPage); pui8TransientCpuVAddr += (CpuPAddr.uiAddr & ~PAGE_MASK); if (!pui8TransientCpuVAddr) return PVRSRV_ERROR_GENERIC; if (!PDumpWriteILock (gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], pui8TransientCpuVAddr, ui32BlockBytes, ui32Flags)) { KUnMapWrapper(psCurrentPage); return PVRSRV_ERROR_GENERIC; } KUnMapWrapper(psCurrentPage); ui32BytesRemaining -= ui32BlockBytes; ui32CurrentOffset += ui32BlockBytes; } PVR_ASSERT(ui32BytesRemaining == 0); } if (gsDBGPdumpState.ui32ParamFileNum == 0) snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm"); else snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%lu.prm", gsDBGPdumpState.ui32ParamFileNum); snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "-- LDB :SGXMEM:VA_%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n", psMemInfo->sDevVAddr.uiAddr, ui32Offset, ui32Bytes, ui32ParamOutPos, pszFile); PDumpWriteString2(pszScript, ui32Flags); CpuPAddr = OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset); ui32PageByteOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1); sDevVAddr = psMemInfo->sDevVAddr; sDevVAddr.uiAddr += ui32Offset; ui32BytesRemaining = ui32Bytes; ui32CurrentOffset = ui32Offset; while (ui32BytesRemaining > 0) { u32 ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_SIZE); CpuPAddr = OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32CurrentOffset); sDevVPageAddr.uiAddr = psMemInfo->sDevVAddr.uiAddr + ui32CurrentOffset - ui32PageByteOffset; BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr); sDevPAddr.uiAddr += ui32PageByteOffset; if (ui32PageByteOffset) { ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_ALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr); ui32PageByteOffset = 0; } snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "LDB :SGXMEM:PA_%p%8.8lX:0x%8.8lX 0x%8.8lX " "0x%8.8lX %s\r\n", hUniqueTag, sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1), sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1), ui32BlockBytes, ui32ParamOutPos, pszFile); PDumpWriteString2(pszScript, ui32Flags); ui32BytesRemaining -= ui32BlockBytes; ui32CurrentOffset += ui32BlockBytes; ui32ParamOutPos += ui32BlockBytes; } PVR_ASSERT(ui32BytesRemaining == 0); return PVRSRV_OK; }