diff options
author | Xianzhong <b07117@freescale.com> | 2013-10-10 00:24:05 +0800 |
---|---|---|
committer | Xianzhong <b07117@freescale.com> | 2013-11-29 01:11:34 +0800 |
commit | 74523055b96629ed389de92118b8370c18e70088 (patch) | |
tree | 598fd7a2c8b038ca9d52a2687ba36cef130b7a2e /drivers/mxc/gpu-viv/hal/os | |
parent | 5721c2db080cd0f9f7370a5eee6704ea71a5c7a4 (diff) |
ENGR00283031 [GPU]Integrate 4.6.9p13 release kernel driver
Integrate GPU 4.6.9p13 release kernel driver for Android.
Signed-off-by: Xianzhong <b07117@freescale.com>
Acked-by: Jason Liu
Diffstat (limited to 'drivers/mxc/gpu-viv/hal/os')
5 files changed, 727 insertions, 125 deletions
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c index 4d48bd55f115..bff85a0e9bf4 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c @@ -25,7 +25,9 @@ #include <linux/mm.h> #include <linux/mman.h> #include <linux/slab.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) #include <mach/hardware.h> +#endif #include <linux/pm_runtime.h> #define _GC_OBJ_ZONE gcvZONE_DEVICE @@ -305,6 +307,7 @@ gckGALDEVICE_Construct( IN gctUINT LogFileSize, IN struct device *pdev, IN gctINT PowerManagement, + IN gctINT GpuProfiler, OUT gckGALDEVICE *Device ) { @@ -369,6 +372,10 @@ gckGALDEVICE_Construct( #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) /*get gpu regulator*/ device->gpu_regulator = regulator_get(pdev, "cpu_vddgpu"); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + device->gpu_regulator = devm_regulator_get(pdev, "pu"); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) if (IS_ERR(device->gpu_regulator)) { gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Failed to get gpu regulator %s/%s \n", @@ -541,6 +548,10 @@ gckGALDEVICE_Construct( device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement )); + gcmkONERROR(gckHARDWARE_SetGpuProfiler( + device->kernels[gcvCORE_MAJOR]->hardware, GpuProfiler + )); + #if COMMAND_PROCESSOR_VERSION == 1 /* Start the command queue. */ gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command)); @@ -599,6 +610,7 @@ gckGALDEVICE_Construct( device->kernels[gcvCORE_2D]->hardware, PowerManagement )); + #if COMMAND_PROCESSOR_VERSION == 1 /* Start the command queue. */ gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command)); @@ -635,6 +647,7 @@ gckGALDEVICE_Construct( device->kernels[gcvCORE_VG]->vg->hardware, PowerManagement )); + #endif } else @@ -849,6 +862,7 @@ gckGALDEVICE_Construct( } else { +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) mem_region = request_mem_region( ContiguousBase, ContiguousSize, "galcore managed memory" ); @@ -864,6 +878,7 @@ gckGALDEVICE_Construct( gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } +#endif device->requestedContiguousBase = ContiguousBase; device->requestedContiguousSize = ContiguousSize; diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h index dde4f034442e..c51432f47c17 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h @@ -26,6 +26,15 @@ ******************************* gckGALDEVICE Structure ******************************* \******************************************************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +struct contiguous_mem_pool { + struct dma_attrs attrs; + dma_addr_t phys; + void *virt; + size_t size; +}; +#endif + typedef struct _gckGALDEVICE { /* Objects. */ @@ -91,12 +100,16 @@ typedef struct _gckGALDEVICE struct clk *clk_2d_axi; struct clk *clk_vg_axi; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) /*Power management.*/ struct regulator *gpu_regulator; #endif /*Run time pm*/ struct device *pmdev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + struct contiguous_mem_pool *pool; + struct reset_control *rstc[gcdMAX_GPU_COUNT]; +#endif } * gckGALDEVICE; @@ -171,6 +184,7 @@ gceSTATUS gckGALDEVICE_Construct( IN gctUINT LogFileSize, IN struct device *pdev, IN gctINT PowerManagement, + IN gctINT GpuProfiler, OUT gckGALDEVICE *Device ); diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c index bacd5311894d..ebd316e24c5b 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c @@ -1,7 +1,7 @@ /**************************************************************************** * * Copyright (C) 2005 - 2013 by Vivante Corp. -* Copyright (C) 2011-2012 Freescale Semiconductor, Inc. +* Copyright (C) 2011-2013 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,6 @@ * *****************************************************************************/ - #include <linux/device.h> #include <linux/slab.h> #include <linux/notifier.h> @@ -69,14 +68,27 @@ task_notify_func(struct notifier_block *self, unsigned long val, void *data) #include <mach/viv_gpu.h> #else #include <linux/pm_runtime.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) #include <mach/busfreq.h> +#else +#include <linux/busfreq-imx6.h> +#include <linux/reset.h> +#endif #endif /* Zone used for header/footer. */ #define _GC_OBJ_ZONE gcvZONE_DRIVER #if gcdENABLE_FSCALE_VAL_ADJUST +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#include <linux/device_cooling.h> +#define REG_THERMAL_NOTIFIER(a) register_devfreq_cooling_notifier(a); +#define UNREG_THERMAL_NOTIFIER(a) unregister_devfreq_cooling_notifier(a); +#else extern int register_thermal_notifier(struct notifier_block *nb); extern int unregister_thermal_notifier(struct notifier_block *nb); +#define REG_THERMAL_NOTIFIER(a) register_thermal_notifier(a); +#define UNREG_THERMAL_NOTIFIER(a) unregister_thermal_notifier(a); +#endif #endif MODULE_DESCRIPTION("Vivante Graphics Driver"); @@ -116,7 +128,11 @@ module_param(registerMemBaseVG, ulong, 0644); static ulong registerMemSizeVG = 2 << 10; module_param(registerMemSizeVG, ulong, 0644); +#if gcdENABLE_FSCALE_VAL_ADJUST +static ulong contiguousSize = 128 << 20; +#else static ulong contiguousSize = 4 << 20; +#endif module_param(contiguousSize, ulong, 0644); static ulong contiguousBase = 0; @@ -134,6 +150,9 @@ module_param(compression, int, 0644); static int powerManagement = 1; module_param(powerManagement, int, 0644); +static int gpuProfiler = 0; +module_param(gpuProfiler, int, 0644); + static int signal = 48; module_param(signal, int, 0644); @@ -786,7 +805,9 @@ static int drv_init(struct device *pdev) printk(KERN_INFO "Galcore version %d.%d.%d.%d\n", gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD); - + /* when enable gpu profiler, we need to turn off gpu powerMangement */ + if(gpuProfiler) + powerManagement = 0; if (showArgs) { printk("galcore options:\n"); @@ -818,6 +839,7 @@ static int drv_init(struct device *pdev) printk(" physSize = 0x%08lX\n", physSize); printk(" logFileSize = %d KB \n", logFileSize); printk(" powerManagement = %d\n", powerManagement); + printk(" gpuProfiler = %d\n", gpuProfiler); #if ENABLE_GPU_CLOCK_BY_DRIVER printk(" coreClock = %lu\n", coreClock); #endif @@ -841,9 +863,14 @@ static int drv_init(struct device *pdev) logFileSize, pdev, powerManagement, + gpuProfiler, &device )); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + device->pool = dev_get_drvdata(pdev); +#endif + /* Start the GAL device. */ gcmkONERROR(gckGALDEVICE_Start(device)); @@ -1028,11 +1055,18 @@ static struct notifier_block thermal_hot_pm_notifier = { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) +static int gpu_probe(struct platform_device *pdev) +#else static int __devinit gpu_probe(struct platform_device *pdev) +#endif { int ret = -ENODEV; struct resource* res; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + struct contiguous_mem_pool *pool; + struct reset_control *rstc; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) struct device_node *dn =pdev->dev.of_node; const u32 *prop; #else @@ -1077,7 +1111,22 @@ static int __devinit gpu_probe(struct platform_device *pdev) registerMemSizeVG = res->end - res->start + 1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + pool = devm_kzalloc(&pdev->dev, sizeof(*pool), GFP_KERNEL); + if (!pool) + return -ENOMEM; + pool->size = contiguousSize; + init_dma_attrs(&pool->attrs); + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &pool->attrs); + pool->virt = dma_alloc_attrs(&pdev->dev, pool->size, &pool->phys, + GFP_KERNEL, &pool->attrs); + if (!pool->virt) { + dev_err(&pdev->dev, "Failed to allocate contiguous memory\n"); + return -ENOMEM; + } + contiguousBase = pool->phys; + dev_set_drvdata(&pdev->dev, pool); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) prop = of_get_property(dn, "contiguousbase", NULL); if(prop) contiguousBase = *prop; @@ -1095,30 +1144,56 @@ static int __devinit gpu_probe(struct platform_device *pdev) if (!ret) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + rstc = devm_reset_control_get(&pdev->dev, "gpu3d"); + galDevice->rstc[gcvCORE_MAJOR] = IS_ERR(rstc) ? NULL : rstc; + + rstc = devm_reset_control_get(&pdev->dev, "gpu2d"); + galDevice->rstc[gcvCORE_2D] = IS_ERR(rstc) ? NULL : rstc; + + rstc = devm_reset_control_get(&pdev->dev, "gpuvg"); + galDevice->rstc[gcvCORE_VG] = IS_ERR(rstc) ? NULL : rstc; +#endif platform_set_drvdata(pdev, galDevice); #if gcdENABLE_FSCALE_VAL_ADJUST - if(galDevice->kernels[gcvCORE_MAJOR]) - register_thermal_notifier(&thermal_hot_pm_notifier); + if (galDevice->kernels[gcvCORE_MAJOR]) + REG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier); #endif gcmkFOOTER_NO(); return ret; } #if gcdENABLE_FSCALE_VAL_ADJUST - unregister_thermal_notifier(&thermal_hot_pm_notifier); + UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + dma_free_attrs(&pdev->dev, pool->size, pool->virt, pool->phys, + &pool->attrs); #endif gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret); return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) +static int gpu_remove(struct platform_device *pdev) +#else static int __devexit gpu_remove(struct platform_device *pdev) +#endif { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + gckGALDEVICE device = platform_get_drvdata(pdev); + struct contiguous_mem_pool *pool = device->pool; +#endif gcmkHEADER(); #if gcdENABLE_FSCALE_VAL_ADJUST if(galDevice->kernels[gcvCORE_MAJOR]) - unregister_thermal_notifier(&thermal_hot_pm_notifier); + UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier); #endif drv_exit(); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + dma_free_attrs(&pdev->dev, pool->size, pool->virt, pool->phys, + &pool->attrs); +#endif gcmkFOOTER_NO(); return 0; } @@ -1254,13 +1329,17 @@ MODULE_DEVICE_TABLE(of, mxs_gpu_dt_ids); #ifdef CONFIG_PM static int gpu_runtime_suspend(struct device *dev) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 7) release_bus_freq(BUS_FREQ_HIGH); +#endif return 0; } static int gpu_runtime_resume(struct device *dev) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 7) request_bus_freq(BUS_FREQ_HIGH); +#endif return 0; } @@ -1284,7 +1363,11 @@ static const struct dev_pm_ops gpu_pm_ops = { static struct platform_driver gpu_driver = { .probe = gpu_probe, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + .remove = gpu_remove, +#else .remove = __devexit_p(gpu_remove), +#endif .suspend = gpu_suspend, .resume = gpu_resume, diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c index b7717fca0ec6..4c9b01aeded3 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c @@ -30,19 +30,30 @@ #include <linux/dma-mapping.h> #include <linux/slab.h> #include <linux/idr.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) #include <mach/hardware.h> +#endif #include <linux/workqueue.h> #include <linux/idr.h> #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) #include <linux/math64.h> #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#include <linux/reset.h> +static inline void imx_gpc_power_up_pu(bool flag) {} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) #include <mach/common.h> #endif #include <linux/delay.h> #include <linux/pm_runtime.h> +#if gcdANDROID_NATIVE_FENCE_SYNC +#include <linux/file.h> +#include "gc_hal_kernel_sync.h" +#endif + + #define _GC_OBJ_ZONE gcvZONE_OS /******************************************************************************* @@ -148,6 +159,7 @@ typedef struct _gcsINTEGER_DB { struct idr idr; spinlock_t lock; + gctINT curr; } gcsINTEGER_DB; @@ -180,6 +192,14 @@ struct _gckOS /* signal id database. */ gcsINTEGER_DB signalDB; +#if gcdANDROID_NATIVE_FENCE_SYNC + /* Lock. */ + gctPOINTER syncPointMutex; + + /* sync point id database. */ + gcsINTEGER_DB syncPointDB; +#endif + gcsUSER_MAPPING_PTR userMap; gctPOINTER debugLock; @@ -215,6 +235,25 @@ typedef struct _gcsSIGNAL } gcsSIGNAL; +#if gcdANDROID_NATIVE_FENCE_SYNC +typedef struct _gcsSYNC_POINT * gcsSYNC_POINT_PTR; +typedef struct _gcsSYNC_POINT +{ + /* The reference counter. */ + atomic_t ref; + + /* State. */ + atomic_t state; + + /* timeline. */ + struct sync_timeline * timeline; + + /* ID. */ + gctUINT32 id; +} +gcsSYNC_POINT; +#endif + typedef struct _gcsPageInfo * gcsPageInfo_PTR; typedef struct _gcsPageInfo { @@ -336,10 +375,10 @@ _CreateMdlMap( return gcvNULL; } - mdlMap->pid = ProcessID; - mdlMap->vmaAddr = gcvNULL; - mdlMap->vma = gcvNULL; - mdlMap->reference = 0; + mdlMap->pid = ProcessID; + mdlMap->vmaAddr = gcvNULL; + mdlMap->vma = gcvNULL; + mdlMap->count = 0; mdlMap->next = Mdl->maps; Mdl->maps = mdlMap; @@ -768,7 +807,32 @@ _AllocateIntegerId( ) { int result; + gctINT next; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) + idr_preload(GFP_KERNEL | gcdNOWARN); + + spin_lock(&Database->lock); + next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1; + result = idr_alloc(&Database->idr, KernelPointer, next, 0, GFP_ATOMIC); + + if (!result) + { + Database->curr = *Id; + } + + spin_unlock(&Database->lock); + + idr_preload_end(); + + if (result < 0) + { + return gcvSTATUS_OUT_OF_RESOURCES; + } + + *Id = result; +#else again: if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0) { @@ -777,8 +841,15 @@ again: spin_lock(&Database->lock); - /* Try to get a id greater than 0. */ - result = idr_get_new_above(&Database->idr, KernelPointer, 1, Id); + next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1; + + /* Try to get a id greater than current id. */ + result = idr_get_new_above(&Database->idr, KernelPointer, next, Id); + + if (!result) + { + Database->curr = *Id; + } spin_unlock(&Database->lock); @@ -791,6 +862,7 @@ again: { return gcvSTATUS_OUT_OF_RESOURCES; } +#endif return gcvSTATUS_OK; } @@ -1009,6 +1081,21 @@ gckOS_Construct( /* Initialize signal id database. */ idr_init(&os->signalDB.idr); +#if gcdANDROID_NATIVE_FENCE_SYNC + /* + * Initialize the sync point manager. + */ + + /* Initialize mutex. */ + gcmkONERROR(gckOS_CreateMutex(os, &os->syncPointMutex)); + + /* Initialize sync point id database lock. */ + spin_lock_init(&os->syncPointDB.lock); + + /* Initialize sync point id database. */ + idr_init(&os->syncPointDB.idr); +#endif + #if gcdUSE_NON_PAGED_MEMORY_CACHE os->cacheSize = 0; os->cacheHead = gcvNULL; @@ -1032,6 +1119,15 @@ gckOS_Construct( return gcvSTATUS_OK; OnError: + +#if gcdANDROID_NATIVE_FENCE_SYNC + if (os->syncPointMutex != gcvNULL) + { + gcmkVERIFY_OK( + gckOS_DeleteMutex(os, os->syncPointMutex)); + } +#endif + if (os->signalMutex != gcvNULL) { gcmkVERIFY_OK( @@ -1105,6 +1201,15 @@ gckOS_Destroy( _FreeAllNonPagedMemoryCache(Os); #endif +#if gcdANDROID_NATIVE_FENCE_SYNC + /* + * Destroy the sync point manager. + */ + + /* Destroy the mutex. */ + gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->syncPointMutex)); +#endif + /* * Destroy the signal manager. */ @@ -1962,12 +2067,6 @@ gckOS_AllocateNonPagedMemory( gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY); } - if ((Os->device->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000)) - { - mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000) - | (Os->device->baseAddress & 0x80000000); - } - mdl->addr = addr; /* Return allocated memory. */ @@ -2308,6 +2407,7 @@ gckOS_ReadRegisterEx( /* Verify the arguments. */ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); + gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]); gcmkVERIFY_ARGUMENT(Data != gcvNULL); *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address); @@ -2358,6 +2458,8 @@ gckOS_WriteRegisterEx( { gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data); + gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]); + writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address); /* Success. */ @@ -2800,16 +2902,25 @@ gckOS_MapPhysical( if (mdl == gcvNULL) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + struct contiguous_mem_pool *pool = Os->device->pool; + + if (Physical >= pool->phys && Physical < pool->phys + pool->size) + logical = (gctPOINTER)(Physical - pool->phys + pool->virt); + else + logical = gcvNULL; +#else /* Map memory as cached memory. */ request_mem_region(physical, Bytes, "MapRegion"); logical = (gctPOINTER) ioremap_nocache(physical, Bytes); +#endif if (logical == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_INFO, gcvZONE_OS, - "%s(%d): Failed to ioremap", - __FUNCTION__, __LINE__ + "%s(%d): Failed to map physical address 0x%08x", + __FUNCTION__, __LINE__, Physical ); MEMORY_UNLOCK(Os); @@ -3622,7 +3733,7 @@ gckOS_Delay( if (Delay > 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) - ktime_t delay = ktime_set(0, Delay * NSEC_PER_MSEC); + ktime_t delay = ktime_set(Delay/1000, (Delay%1000) * NSEC_PER_MSEC); __set_current_state(TASK_UNINTERRUPTIBLE); schedule_hrtimeout(&delay, HRTIMER_MODE_REL); #else @@ -3856,6 +3967,9 @@ gckOS_AllocatePagedMemoryEx( gctSIZE_T bytes; gctBOOL locked = gcvFALSE; gceSTATUS status; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) + gctPOINTER addr = gcvNULL; +#endif gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes); @@ -3879,15 +3993,34 @@ gckOS_AllocatePagedMemoryEx( if (Contiguous) { - /* Get contiguous pages, and suppress warning (stack dump) from kernel when - we run out of memory. */ - mdl->u.contiguousPages = - alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, GetOrder(numPages)); + gctUINT32 order = get_order(bytes); + + if (order >= MAX_ORDER) + { + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY); + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) + addr = + alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY); + + mdl->u.contiguousPages = addr + ? virt_to_page(addr) + : gcvNULL; + + mdl->exact = gcvTRUE; +#else + mdl->u.contiguousPages = + alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, order); +#endif if (mdl->u.contiguousPages == gcvNULL) { mdl->u.contiguousPages = - alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, GetOrder(numPages)); + alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, order); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) + mdl->exact = gcvFALSE; +#endif } } else @@ -4032,7 +4165,16 @@ gckOS_FreePagedMemory( if (mdl->contiguous) { - __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) + if (mdl->exact == gcvTRUE) + { + free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE); + } + else +#endif + { + __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages)); + } } else { @@ -4214,13 +4356,13 @@ gckOS_LockPages( } mdlMap->vma->vm_flags |= gcdVM_FLAGS; -#if !gcdPAGED_MEMORY_CACHEABLE + if (Cacheable == gcvFALSE) { /* Make this mapping non-cached. */ mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot); } -#endif + addr = mdl->addr; /* Now map all the vmalloc pages to this user address. */ @@ -4291,16 +4433,7 @@ gckOS_LockPages( up_write(¤t->mm->mmap_sem); } -#if 0 - else - { - /* mdlMap->vmaAddr != gcvNULL means current process has already locked this node. */ - MEMORY_UNLOCK(Os); - - gcmkFOOTER_ARG("*status=%d, mdlMap->vmaAddr=%x", gcvSTATUS_MEMORY_LOCKED, mdlMap->vmaAddr); - return gcvSTATUS_MEMORY_LOCKED; - } -#endif + mdlMap->count++; /* Convert pointer to MDL. */ *Logical = mdlMap->vmaAddr; @@ -4311,9 +4444,6 @@ gckOS_LockPages( *PageCount = mdl->numPages * (PAGE_SIZE / 4096); - /* Increase reference count. */ - mdlMap->reference++; - MEMORY_UNLOCK(Os); gcmkVERIFY_OK(gckOS_CacheFlush( @@ -4580,13 +4710,11 @@ gckOS_UnlockPages( { if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid)) { - if (--mdlMap->reference > 0) + if (--mdlMap->count == 0) { - continue; + _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE); + mdlMap->vmaAddr = gcvNULL; } - - _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE); - mdlMap->vmaAddr = gcvNULL; } mdlMap = mdlMap->next; @@ -5322,6 +5450,7 @@ OnError: { /* Get the user pages. */ down_read(¤t->mm->mmap_sem); + result = get_user_pages(current, current->mm, memory & PAGE_MASK, @@ -5331,109 +5460,127 @@ OnError: pages, gcvNULL ); + up_read(¤t->mm->mmap_sem); if (result <=0 || result < pageCount) { struct vm_area_struct *vma; - /* Free the page table. */ - if (pages != gcvNULL) + /* Release the pages if any. */ + if (result > 0) { - /* Release the pages if any. */ - if (result > 0) + for (i = 0; i < result; i++) { - for (i = 0; i < result; i++) + if (pages[i] == gcvNULL) { - if (pages[i] == gcvNULL) - { - break; - } - - page_cache_release(pages[i]); + break; } + + page_cache_release(pages[i]); + pages[i] = gcvNULL; } - kfree(pages); - pages = gcvNULL; + result = 0; } vma = find_vma(current->mm, memory); - if (vma && (vma->vm_flags & VM_PFNMAP) ) + if (vma && (vma->vm_flags & VM_PFNMAP)) { pte_t * pte; spinlock_t * ptl; - unsigned long pfn; + gctUINTPTR_T logical = memory; - pgd_t * pgd = pgd_offset(current->mm, memory); - pud_t * pud = pud_offset(pgd, memory); - if (pud) + for (i = 0; i < pageCount; i++) { - pmd_t * pmd = pmd_offset(pud, memory); - pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl); - if (!pte) + pgd_t * pgd = pgd_offset(current->mm, logical); + pud_t * pud = pud_offset(pgd, logical); + + if (pud) + { + pmd_t * pmd = pmd_offset(pud, logical); + pte = pte_offset_map_lock(current->mm, pmd, logical, &ptl); + if (!pte) + { + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); + } + } + else { gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } + + pages[i] = pte_page(*pte); + pte_unmap_unlock(pte, ptl); + + /* Advance to next. */ + logical += PAGE_SIZE; } - else + } + else + { + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); + } + + /* Check if this memory is contiguous for old mmu. */ + if (Os->device->kernels[Core]->hardware->mmuVersion == 0) + { + for (i = 1; i < pageCount; i++) { - gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); + if (pages[i] != nth_page(pages[0], i)) + { + /* Non-contiguous. */ + break; + } } - pfn = pte_pfn(*pte); - - physical = (pfn << PAGE_SHIFT) | (memory & ~PAGE_MASK); + if (i == pageCount) + { + /* Contiguous memory. */ + physical = page_to_phys(pages[0]) | (memory & ~PAGE_MASK); - pte_unmap_unlock(pte, ptl); + if (!((physical - Os->device->baseAddress) & 0x80000000)) + { + kfree(pages); + pages = gcvNULL; - if ((Os->device->kernels[Core]->hardware->mmuVersion == 0) - && !((physical - Os->device->baseAddress) & 0x80000000)) - { - info->pages = gcvNULL; - info->pageTable = gcvNULL; + info->pages = gcvNULL; + info->pageTable = gcvNULL; - MEMORY_MAP_UNLOCK(Os); + MEMORY_MAP_UNLOCK(Os); - *Address = physical - Os->device->baseAddress; - *Info = info; + *Address = physical - Os->device->baseAddress; + *Info = info; - gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", - *Info, *Address); + gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", + *Info, *Address); - return gcvSTATUS_OK; + return gcvSTATUS_OK; + } } } - else + + /* Reference pages. */ + for (i = 0; i < pageCount; i++) { - gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); + get_page(pages[i]); } } } - if (pages) + for (i = 0; i < pageCount; i++) { - for (i = 0; i < pageCount; i++) - { #ifdef CONFIG_ARM - gctUINT32 data; - get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE)); + gctUINT32 data; + get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE)); #endif - /* Flush(clean) the data cache. */ - gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL, - (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]), - (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE, - PAGE_SIZE)); - } - } - else - { + /* Flush(clean) the data cache. */ gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL, - (gctPOINTER)(gctUINTPTR_T)(physical & PAGE_MASK), - (gctPOINTER)(memory & PAGE_MASK), - PAGE_SIZE * pageCount)); + (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]), + (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE, + PAGE_SIZE)); } #if gcdENABLE_VG @@ -5454,20 +5601,14 @@ OnError: (gctPOINTER *) &pageTable, &address)); } + /* Fill the page table. */ for (i = 0; i < pageCount; i++) { gctUINT32 phys; gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096); - if (pages) - { - phys = page_to_phys(pages[i]); - } - else - { - phys = (physical & PAGE_MASK) + i * PAGE_SIZE; - } + phys = page_to_phys(pages[i]); #if gcdENABLE_VG if (Core == gcvCORE_VG) @@ -6116,7 +6257,7 @@ gckOS_CacheClean( #else dma_sync_single_for_device( gcvNULL, - Physical, + (dma_addr_t)Physical, Bytes, DMA_TO_DEVICE); #endif @@ -6195,7 +6336,7 @@ gckOS_CacheInvalidate( #else dma_sync_single_for_device( gcvNULL, - Physical, + (dma_addr_t)Physical, Bytes, DMA_FROM_DEVICE); #endif @@ -6269,7 +6410,7 @@ gckOS_CacheFlush( #else dma_sync_single_for_device( gcvNULL, - Physical, + (dma_addr_t)Physical, Bytes, DMA_BIDIRECTIONAL); #endif @@ -6818,6 +6959,9 @@ gckOS_SetGPUPower( struct clk *clk_2dcore = Os->device->clk_2d_core; struct clk *clk_2d_axi = Os->device->clk_2d_axi; struct clk *clk_vg_axi = Os->device->clk_vg_axi; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + int ret; +#endif gctBOOL oldClockState = gcvFALSE; gctBOOL oldPowerState = gcvFALSE; @@ -6843,10 +6987,14 @@ gckOS_SetGPUPower( } if((Power == gcvTRUE) && (oldPowerState == gcvFALSE)) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) mutex_lock(&set_cpufreq_lock); - if(!IS_ERR(Os->device->gpu_regulator)) - regulator_enable(Os->device->gpu_regulator); + if(!IS_ERR(Os->device->gpu_regulator)) { + ret = regulator_enable(Os->device->gpu_regulator); + if (ret != 0) + gckOS_Print("%s(%d): fail to enable pu regulator %d!\n", + __FUNCTION__, __LINE__, ret); + } mutex_unlock(&set_cpufreq_lock); #else imx_gpc_power_up_pu(true); @@ -6962,7 +7110,7 @@ gckOS_SetGPUPower( pm_runtime_put_sync(Os->device->pmdev); #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) mutex_lock(&set_cpufreq_lock); if(!IS_ERR(Os->device->gpu_regulator)) regulator_disable(Os->device->gpu_regulator); @@ -7028,6 +7176,10 @@ gckOS_ResetGPU( } gcmkFOOTER_NO(); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + struct reset_control *rstc = Os->device->rstc[Core]; + if (rstc) + reset_control_reset(rstc); #else imx_src_reset_gpu((int)Core); #endif @@ -8534,3 +8686,338 @@ gckOS_GetProcessNameByPid( return gcvSTATUS_OK; } +#if gcdANDROID_NATIVE_FENCE_SYNC + +gceSTATUS +gckOS_CreateSyncPoint( + IN gckOS Os, + OUT gctSYNC_POINT * SyncPoint + ) +{ + gceSTATUS status; + gcsSYNC_POINT_PTR syncPoint; + + gcmkHEADER_ARG("Os=0x%X", Os); + + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); + + /* Create an sync point structure. */ + syncPoint = (gcsSYNC_POINT_PTR) kmalloc( + sizeof(gcsSYNC_POINT), GFP_KERNEL | gcdNOWARN); + + if (syncPoint == gcvNULL) + { + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY); + } + + /* Initialize the sync point. */ + atomic_set(&syncPoint->ref, 1); + atomic_set(&syncPoint->state, 0); + + gcmkONERROR(_AllocateIntegerId(&Os->syncPointDB, syncPoint, &syncPoint->id)); + + *SyncPoint = (gctSYNC_POINT)(gctUINTPTR_T)syncPoint->id; + + gcmkFOOTER_ARG("*SyncPonint=%d", syncPoint->id); + return gcvSTATUS_OK; + +OnError: + if (syncPoint != gcvNULL) + { + kfree(syncPoint); + } + + gcmkFOOTER(); + return status; +} + +gceSTATUS +gckOS_ReferenceSyncPoint( + IN gckOS Os, + IN gctSYNC_POINT SyncPoint + ) +{ + gceSTATUS status; + gcsSYNC_POINT_PTR syncPoint; + + gcmkHEADER_ARG("Os=0x%X", Os); + + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); + gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL); + + gcmkONERROR( + _QueryIntegerId(&Os->syncPointDB, + (gctUINT32)(gctUINTPTR_T)SyncPoint, + (gctPOINTER)&syncPoint)); + + /* Initialize the sync point. */ + atomic_inc(&syncPoint->ref); + + gcmkFOOTER_NO(); + return gcvSTATUS_OK; + +OnError: + gcmkFOOTER(); + return status; +} + +gceSTATUS +gckOS_DestroySyncPoint( + IN gckOS Os, + IN gctSYNC_POINT SyncPoint + ) +{ + gceSTATUS status; + gcsSYNC_POINT_PTR syncPoint; + gctBOOL acquired = gcvFALSE; + + gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint); + + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); + gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL); + + gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE)); + acquired = gcvTRUE; + + gcmkONERROR( + _QueryIntegerId(&Os->syncPointDB, + (gctUINT32)(gctUINTPTR_T)SyncPoint, + (gctPOINTER)&syncPoint)); + + gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint); + + if (atomic_dec_and_test(&syncPoint->ref)) + { + gcmkVERIFY_OK(_DestroyIntegerId(&Os->syncPointDB, syncPoint->id)); + + /* Free the sgianl. */ + syncPoint->timeline = gcvNULL; + kfree(syncPoint); + } + + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex)); + acquired = gcvFALSE; + + /* Success. */ + gcmkFOOTER_NO(); + return gcvSTATUS_OK; + +OnError: + if (acquired) + { + /* Release the mutex. */ + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex)); + } + + gcmkFOOTER(); + return status; +} + +gceSTATUS +gckOS_SignalSyncPoint( + IN gckOS Os, + IN gctSYNC_POINT SyncPoint + ) +{ + gceSTATUS status; + gcsSYNC_POINT_PTR syncPoint; + gctBOOL acquired = gcvFALSE; + + gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint); + + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); + gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL); + + gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE)); + acquired = gcvTRUE; + + gcmkONERROR( + _QueryIntegerId(&Os->syncPointDB, + (gctUINT32)(gctUINTPTR_T)SyncPoint, + (gctPOINTER)&syncPoint)); + + gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint); + + /* Get state. */ + atomic_set(&syncPoint->state, gcvTRUE); + + /* Signal timeline. */ + if (syncPoint->timeline) + { + sync_timeline_signal(syncPoint->timeline); + } + + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex)); + acquired = gcvFALSE; + + /* Success. */ + gcmkFOOTER_NO(); + return gcvSTATUS_OK; + +OnError: + if (acquired) + { + /* Release the mutex. */ + gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex)); + } + + gcmkFOOTER(); + return status; +} + +gceSTATUS +gckOS_QuerySyncPoint( + IN gckOS Os, + IN gctSYNC_POINT SyncPoint, + OUT gctBOOL_PTR State + ) +{ + gceSTATUS status; + gcsSYNC_POINT_PTR syncPoint; + + gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint); + + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); + gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL); + + gcmkONERROR( + _QueryIntegerId(&Os->syncPointDB, + (gctUINT32)(gctUINTPTR_T)SyncPoint, + (gctPOINTER)&syncPoint)); + + gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint); + + /* Get state. */ + *State = atomic_read(&syncPoint->state); + + /* Success. */ + gcmkFOOTER_ARG("*State=%d", *State); + return gcvSTATUS_OK; + +OnError: + gcmkFOOTER(); + return status; +} + +gceSTATUS +gckOS_CreateSyncTimeline( + IN gckOS Os, + OUT gctHANDLE * Timeline + ) +{ + struct viv_sync_timeline * timeline; + + /* Create viv sync timeline. */ + timeline = viv_sync_timeline_create("viv timeline", Os); + + if (timeline == gcvNULL) + { + /* Out of memory. */ + return gcvSTATUS_OUT_OF_MEMORY; + } + + *Timeline = (gctHANDLE) timeline; + return gcvSTATUS_OK; +} + +gceSTATUS +gckOS_DestroySyncTimeline( + IN gckOS Os, + IN gctHANDLE Timeline + ) +{ + struct viv_sync_timeline * timeline; + gcmkASSERT(Timeline != gcvNULL); + + /* Destroy timeline. */ + timeline = (struct viv_sync_timeline *) Timeline; + sync_timeline_destroy(&timeline->obj); + + return gcvSTATUS_OK; +} + +gceSTATUS +gckOS_CreateNativeFence( + IN gckOS Os, + IN gctHANDLE Timeline, + IN gctSYNC_POINT SyncPoint, + OUT gctINT * FenceFD + ) +{ + int fd = -1; + struct viv_sync_timeline *timeline; + struct sync_pt * pt = gcvNULL; + struct sync_fence * fence; + char name[32]; + gcsSYNC_POINT_PTR syncPoint; + gceSTATUS status; + + gcmkHEADER_ARG("Os=0x%X Timeline=0x%X SyncPoint=%d", + Os, Timeline, (gctUINT)(gctUINTPTR_T)SyncPoint); + + gcmkONERROR( + _QueryIntegerId(&Os->syncPointDB, + (gctUINT32)(gctUINTPTR_T)SyncPoint, + (gctPOINTER)&syncPoint)); + + /* Cast timeline. */ + timeline = (struct viv_sync_timeline *) Timeline; + + fd = get_unused_fd(); + + if (fd < 0) + { + /* Out of resources. */ + gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); + } + + /* Create viv_sync_pt. */ + pt = viv_sync_pt_create(timeline, SyncPoint); + + if (pt == gcvNULL) + { + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY); + } + + /* Reference sync_timeline. */ + syncPoint->timeline = &timeline->obj; + + /* Build fence name. */ + snprintf(name, 32, "viv sync_fence-%u", (gctUINT)(gctUINTPTR_T)SyncPoint); + + /* Create sync_fence. */ + fence = sync_fence_create(name, pt); + + if (fence == NULL) + { + gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY); + } + + /* Install fence to fd. */ + sync_fence_install(fence, fd); + + *FenceFD = fd; + gcmkFOOTER_ARG("*FenceFD=%d", fd); + return gcvSTATUS_OK; + +OnError: + /* Error roll back. */ + if (pt) + { + sync_pt_free(pt); + } + + if (fd > 0) + { + put_unused_fd(fd); + } + + gcmkFOOTER(); + return status; +} +#endif diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h index 9307e832e167..b22081740fdb 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h @@ -26,8 +26,8 @@ typedef struct _LINUX_MDL_MAP { gctINT pid; gctPOINTER vmaAddr; + gctUINT32 count; struct vm_area_struct * vma; - gctINT reference; struct _LINUX_MDL_MAP * next; } LINUX_MDL_MAP; @@ -55,6 +55,9 @@ typedef struct _LINUX_MDL gctINT numPages; gctINT pagedMem; gctBOOL contiguous; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) + gctBOOL exact; +#endif dma_addr_t dmaHandle; PLINUX_MDL_MAP maps; struct _LINUX_MDL * prev; |