From: chenlinz Date: Sat, 28 Apr 2012 06:21:11 +0000 (+0800) Subject: GFX: optimize vmalloc allocation as it's fragmented severely byPVR driver X-Git-Tag: 2.1b_release~836 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5eb74cd030d52b1a6ea12fc0d6f2bbc1d0a24fa0;p=kernel%2Fkernel-mfld-blackbay.git GFX: optimize vmalloc allocation as it's fragmented severely byPVR driver BZ: 31145 GFX allocates lots of 1 page szie vmalloc areas. It causes dramatic vmalloc fragmentation. Most such small vmalloc areas are created as PVRSRV_HAP_WRITECOMBINE. We create a special gen_pool based on a big vmalloc area. Then, allocate all small PVRSRV_HAP_WRITECOMBINE request from the pool. Change-Id: Ia38c4cc78e0e716a52cbd3592b2f8bcf099e08c8 Signed-off-by: Yanmin Zhang Signed-off-by: chenlinz Reviewed-on: http://android.intel.com:8080/46647 Reviewed-by: Jiang, Fei Reviewed-by: Tu, Yun Reviewed-by: Zeng, Li Reviewed-by: Tong, BoX Tested-by: Tong, BoX Reviewed-by: buildbot Tested-by: buildbot --- diff --git a/drivers/staging/mrst/Kconfig b/drivers/staging/mrst/Kconfig index 1083644..2868ed1 100644 --- a/drivers/staging/mrst/Kconfig +++ b/drivers/staging/mrst/Kconfig @@ -12,6 +12,7 @@ config DRM_INTEL_MID select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT select DRM_KMS_HELPER + select GENERIC_ALLOCATOR select DRM_TTM help xxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.c b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.c index 7f12ff5..f18df04 100644 --- a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.c +++ b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "img_defs.h" #include "services.h" @@ -186,6 +187,51 @@ static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLin static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea); #endif +/* + We assume the total area space for PVRSRV_HAP_WRITECOMBINE is fewer than 4MB. +If it's more than 4MB, it fails over to vmalloc automatically. + */ +#define POOL_SIZE (4*1024*1024) +static struct gen_pool *pvrsrv_pool_writecombine; +static char *pool_start; + +static void init_pvr_pool(void) +{ + pgprot_t PGProtFlags; + int ret = -1; + + pvrsrv_pool_writecombine = gen_pool_create(12, -1); + if (!pvrsrv_pool_writecombine) { + printk(KERN_ERR "%s: create pvrsrv_pool failed\n", + __func__); + return ; + } + PGProtFlags = PGPROT_WC(PAGE_KERNEL); + pool_start = __vmalloc(POOL_SIZE, GFP_KERNEL | __GFP_HIGHMEM, + PGProtFlags); + + if (!pool_start) { + printk(KERN_ERR "%s:No vm space to create POOL\n", + __func__); + gen_pool_destroy(pvrsrv_pool_writecombine); + pvrsrv_pool_writecombine = NULL; + return ; + } else { + ret = gen_pool_add(pvrsrv_pool_writecombine, + pool_start, POOL_SIZE, -1); + if (ret) { + printk(KERN_ERR "%s:could not remainder pool\n", + __func__); + gen_pool_destroy(pvrsrv_pool_writecombine); + pvrsrv_pool_writecombine = NULL; + vfree(pool_start); + pool_start = NULL; + return ; + } + } + return ; +} + PVRSRV_ERROR LinuxMMInit(IMG_VOID) { @@ -235,7 +281,8 @@ LinuxMMInit(IMG_VOID) return PVRSRV_ERROR_OUT_OF_MEMORY; } - return PVRSRV_OK; + init_pvr_pool(); + return PVRSRV_OK; } #if defined(DEBUG_LINUX_MEM_AREAS) @@ -583,7 +630,7 @@ LinuxMemArea * NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags) { LinuxMemArea *psLinuxMemArea; - IMG_VOID *pvCpuVAddr; + IMG_VOID *pvCpuVAddr = NULL; psLinuxMemArea = LinuxMemAreaStructAlloc(); if(!psLinuxMemArea) @@ -591,7 +638,20 @@ NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags) goto failed; } - pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags); + psLinuxMemArea->bfromPool = IMG_FALSE; + if (pvrsrv_pool_writecombine && ui32Bytes <= 128*1024) { + if ((ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK) == + PVRSRV_HAP_WRITECOMBINE) { + pvCpuVAddr = gen_pool_alloc(pvrsrv_pool_writecombine, + PAGE_ALIGN(ui32Bytes)); + if (pvCpuVAddr) + psLinuxMemArea->bfromPool = IMG_TRUE; + } + } + + if (!pvCpuVAddr) + pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags); + if(!pvCpuVAddr) { goto failed; @@ -644,7 +704,12 @@ FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea) PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p", __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress)); - VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress); + if (psLinuxMemArea->bfromPool) { + gen_pool_free(pvrsrv_pool_writecombine, + psLinuxMemArea->uData.sVmalloc.pvVmallocAddress, + PAGE_ALIGN(psLinuxMemArea->ui32ByteSize)); + } else + VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress); LinuxMemAreaStructFree(psLinuxMemArea); } diff --git a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.h b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.h index 0fb0917..03f2827 100644 --- a/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.h +++ b/drivers/staging/mrst/pvr/services4/srvkm/env/linux/mm.h @@ -149,6 +149,7 @@ struct _LinuxMemArea { IMG_BOOL bNeedsCacheInvalidate; + IMG_BOOL bfromPool; struct list_head sMMapItem;