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;
	}
}
Exemple #3
0
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;
}