struct LinuxMemArea *NewAllocPagesLinuxMemArea(u32 ui32Bytes, u32 ui32AreaFlags) { struct LinuxMemArea *psLinuxMemArea; u32 ui32PageCount; struct page **pvPageList; void *hBlockPageList; s32 i; enum PVRSRV_ERROR eError; psLinuxMemArea = LinuxMemAreaStructAlloc(); if (!psLinuxMemArea) goto failed_area_alloc; ui32PageCount = RANGE_TO_PAGES(ui32Bytes); eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount, (void **)&pvPageList, &hBlockPageList); if (eError != PVRSRV_OK) goto failed_page_list_alloc; for (i = 0; i < ui32PageCount; i++) { pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 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->uData.sPageList.hBlockPageList = hBlockPageList; psLinuxMemArea->ui32ByteSize = ui32Bytes; psLinuxMemArea->ui32AreaFlags = ui32AreaFlags; psLinuxMemArea->bMMapRegistered = IMG_FALSE; INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList); #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); OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList); failed_page_list_alloc: LinuxMemAreaStructFree(psLinuxMemArea); failed_area_alloc: PVR_DPF(PVR_DBG_ERROR, "%s: failed", __func__); return NULL; }
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; }
static IMG_BOOL PagesAreContiguous(struct IMG_SYS_PHYADDR *psSysPhysAddr, u32 ui32Bytes) { u32 ui32; u32 ui32AddrChk; u32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes); for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr; ui32 < ui32NumPages; ui32++, ui32AddrChk += PAGE_SIZE) if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk) return IMG_FALSE; return IMG_TRUE; }
static void inv_cache_page_list(const struct LinuxMemArea *mem_area) { u32 pg_cnt; struct page **pg_list; extern void ___dma_single_dev_to_cpu(const void *, size_t, enum dma_data_direction); pg_cnt = RANGE_TO_PAGES(mem_area->ui32ByteSize); pg_list = mem_area->uData.sPageList.pvPageList; while (pg_cnt--) ___dma_single_dev_to_cpu(page_address(*pg_list++), PAGE_SIZE, DMA_FROM_DEVICE); }
BCE_ERROR BCAllocDiscontigMemory(unsigned long ulSize, BCE_HANDLE unref__ *phMemHandle, IMG_CPU_VIRTADDR *pLinAddr, IMG_SYS_PHYADDR **ppPhysAddr) { unsigned long ulPages = RANGE_TO_PAGES(ulSize); IMG_SYS_PHYADDR *pPhysAddr; unsigned long ulPage; IMG_CPU_VIRTADDR LinAddr; LinAddr = __vmalloc(ulSize, GFP_KERNEL | __GFP_HIGHMEM, pgprot_noncached(PAGE_KERNEL)); if (!LinAddr) { return BCE_ERROR_OUT_OF_MEMORY; } pPhysAddr = kmalloc(ulPages * sizeof(IMG_SYS_PHYADDR), GFP_KERNEL); if (!pPhysAddr) { vfree(LinAddr); return BCE_ERROR_OUT_OF_MEMORY; } *pLinAddr = LinAddr; for (ulPage = 0; ulPage < ulPages; ulPage++) { pPhysAddr[ulPage].uiAddr = VMALLOC_TO_PAGE_PHYS(LinAddr); LinAddr += PAGE_SIZE; } *ppPhysAddr = pPhysAddr; return BCE_OK; }