diff options
author | Xianzhong <xianzhong.li@nxp.com> | 2019-01-11 23:28:33 +0800 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:35:55 +0800 |
commit | a03bac842b9f615d3795b272fd719957534ed77a (patch) | |
tree | 483fac327e03990991d70a70c3b738a9749072c4 /drivers/mxc/gpu-viv/hal/os/linux | |
parent | d260e22591f1d645bcb0829ef128301bdb2e65ed (diff) |
MGS-4501 upgrade vivante 6.2.4.p4 gpu driver
include critical gpu bug-fixings for Android 9.0
commit-id 20ea99e9db80e834c7970568a6122f11327dd5dc
Signed-off-by: Xianzhong <xianzhong.li@nxp.com>
Diffstat (limited to 'drivers/mxc/gpu-viv/hal/os/linux')
19 files changed, 471 insertions, 246 deletions
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dma.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dma.c index bed5f6db0c74..36bf9c5552f0 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dma.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dma.c @@ -61,6 +61,10 @@ #include <linux/mman.h> #include <asm/atomic.h> #include <linux/dma-mapping.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0) +#include <linux/dma-direct.h> +#endif + #include <linux/slab.h> #include <linux/platform_device.h> @@ -129,25 +133,6 @@ _DebugfsCleanup( gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir); } -#ifdef CONFIG_ARM64 -static struct device * -_GetDevice( - IN gckOS Os - ) -{ - gcsPLATFORM *platform; - - platform = Os->device->platform; - - if (!platform) - { - return gcvNULL; - } - - return &platform->device->dev; -} -#endif - static gceSTATUS _DmaAlloc( IN gckALLOCATOR Allocator, @@ -176,12 +161,10 @@ _DmaAlloc( #endif mdlPriv->kvaddr -#if defined CONFIG_ARM64 - = dma_alloc_coherent(_GetDevice(os), NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, gfp); -#elif defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC - = dma_alloc_coherent(gcvNULL, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, gfp); +#if defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC || defined CONFIG_ARM64 + = dma_alloc_coherent(galcore_device, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, gfp); #else - = dma_alloc_writecombine(gcvNULL, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, gfp); + = dma_alloc_writecombine(galcore_device, NumPages * PAGE_SIZE, &mdlPriv->dmaHandle, gfp); #endif #ifdef CONFLICT_BETWEEN_BASE_AND_PHYS @@ -299,12 +282,10 @@ _DmaFree( struct mdl_dma_priv *mdlPriv=(struct mdl_dma_priv *)Mdl->priv; gcsDMA_PRIV_PTR allocatorPriv = (gcsDMA_PRIV_PTR)Allocator->privateData; -#if defined CONFIG_ARM64 - dma_free_coherent(_GetDevice(os), Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle); -#elif defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC - dma_free_coherent(gcvNULL, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle); +#if defined CONFIG_MIPS || defined CONFIG_CPU_CSKYV2 || defined CONFIG_PPC || defined CONFIG_ARM64 + dma_free_coherent(galcore_device, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle); #else - dma_free_writecombine(gcvNULL, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle); + dma_free_writecombine(galcore_device, Mdl->numPages * PAGE_SIZE, mdlPriv->kvaddr, mdlPriv->dmaHandle); #endif gckOS_Free(os, mdlPriv); @@ -504,8 +485,8 @@ static gceSTATUS _DmaCache( IN gckALLOCATOR Allocator, IN PLINUX_MDL Mdl, + IN gctSIZE_T Offset, IN gctPOINTER Logical, - IN gctUINT32 Physical, IN gctUINT32 Bytes, IN gceCACHEOPERATION Operation ) diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c index 5f0e7b44948b..6f37daf74778 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c @@ -244,10 +244,10 @@ _DmabufAttach( npages += (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE; } - /* Allocate page arrary. */ + /* Allocate page array. */ gcmkONERROR(gckOS_Allocate(os, npages * gcmSIZEOF(*pagearray), (gctPOINTER *)&pagearray)); - /* Fill page arrary. */ + /* Fill page array. */ for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { for (j = 0; j < (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE; j++) @@ -277,8 +277,7 @@ _DmabufAttach( Mdl->priv = buf_desc; - /* Need set it as true to avoid MMU mapping. */ - Mdl->contiguous = gcvTRUE; + Mdl->contiguous = (sgt->nents == 1) ? gcvTRUE : gcvFALSE; gcmkFOOTER_NO(); return gcvSTATUS_OK; @@ -417,8 +416,8 @@ static gceSTATUS _DmabufCache( IN gckALLOCATOR Allocator, IN PLINUX_MDL Mdl, + IN gctSIZE_T Offset, IN gctPOINTER Logical, - IN gctUINT32 Physical, IN gctUINT32 Bytes, IN gceCACHEOPERATION Operation ) @@ -434,8 +433,10 @@ _DmabufCache( dma_sync_sg_for_device(galcore_device, sgt->sgl, sgt->nents, dir); break; case gcvCACHE_FLUSH: - dir = DMA_BIDIRECTIONAL; + dir = DMA_TO_DEVICE; dma_sync_sg_for_device(galcore_device, sgt->sgl, sgt->nents, dir); + dir = DMA_FROM_DEVICE; + dma_sync_sg_for_cpu(galcore_device, sgt->sgl, sgt->nents, dir); break; case gcvCACHE_INVALIDATE: dir = DMA_FROM_DEVICE; diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_gfp.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_gfp.c index 71a867c9302c..356456eaec4d 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_gfp.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_gfp.c @@ -370,7 +370,7 @@ _GFPAlloc( mdlPriv->dma_addr = dma_map_page(galcore_device, mdlPriv->contiguousPages, 0, NumPages * PAGE_SIZE, - DMA_TO_DEVICE); + DMA_FROM_DEVICE); if (!mdlPriv->dma_addr) { @@ -427,7 +427,7 @@ _GFPAlloc( } result = dma_map_sg(galcore_device, - mdlPriv->sgt.sgl, mdlPriv->sgt.nents, DMA_TO_DEVICE); + mdlPriv->sgt.sgl, mdlPriv->sgt.nents, DMA_FROM_DEVICE); if (result != mdlPriv->sgt.nents) { @@ -680,7 +680,12 @@ _GFPMmap( if (Cacheable == gcvFALSE) { + /* Make this mapping non-cached. */ +#if gcdENABLE_BUFFERABLE_VIDEO_MEMORY vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); +#else + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +#endif } if (platform && platform->ops->adjustProt) @@ -883,24 +888,9 @@ _GFPMapKernel( gctINT numPages = Mdl->numPages; struct gfp_mdl_priv *mdlPriv = Mdl->priv; -#if gcdNONPAGED_MEMORY_CACHEABLE - if (Mdl->contiguous) - { - addr = page_address(mdlPriv->contiguousPages); - } - else - { - addr = vmap(mdlPriv->nonContiguousPages, - numPages, - 0, - PAGE_KERNEL); - - /* Trigger a page fault. */ - memset(addr, 0, numPages * PAGE_SIZE); - } -#else struct page ** pages; gctBOOL free = gcvFALSE; + pgprot_t pgprot; gctINT i; if (Mdl->contiguous) @@ -924,19 +914,26 @@ _GFPMapKernel( pages = mdlPriv->nonContiguousPages; } - addr = vmap(pages, numPages, 0, pgprot_writecombine(PAGE_KERNEL)); - - /* Trigger a page fault. */ - for (i = 0; i < numPages; i++) + /* ioremap() can't work on system memory since 2.6.38. */ + if (Mdl->cacheable) { - *(gctINT *)(addr + PAGE_SIZE * i) = 0; + pgprot = PAGE_KERNEL; } + else + { +#if gcdENABLE_BUFFERABLE_VIDEO_MEMORY + pgprot = pgprot_writecombine(PAGE_KERNEL); +#else + pgprot = pgprot_noncached(PAGE_KERNEL); +#endif + } + + addr = vmap(pages, numPages, 0, pgprot); if (free) { kfree(pages); } -#endif if (addr) { @@ -956,10 +953,7 @@ _GFPUnmapKernel( IN gctPOINTER Logical ) { - -#if !gcdNONPAGED_MEMORY_CACHEABLE vunmap(Logical); -#endif return gcvSTATUS_OK; } @@ -968,8 +962,8 @@ static gceSTATUS _GFPCache( IN gckALLOCATOR Allocator, IN PLINUX_MDL Mdl, + IN gctSIZE_T Offset, IN gctPOINTER Logical, - IN gctUINT32 Physical, IN gctUINT32 Bytes, IN gceCACHEOPERATION Operation ) @@ -995,7 +989,7 @@ _GFPCache( break; case gcvCACHE_FLUSH: - dir = DMA_BIDIRECTIONAL; + dir = DMA_TO_DEVICE; if (mdlPriv->contiguous) { @@ -1008,6 +1002,19 @@ _GFPCache( mdlPriv->sgt.sgl, mdlPriv->sgt.nents, dir); } + dir = DMA_FROM_DEVICE; + + if (mdlPriv->contiguous) + { + dma_sync_single_for_cpu(galcore_device, + mdlPriv->dma_addr, Mdl->numPages << PAGE_SHIFT, dir); + } + else + { + dma_sync_sg_for_cpu(galcore_device, + mdlPriv->sgt.sgl, mdlPriv->sgt.nents, dir); + } + break; case gcvCACHE_INVALIDATE: dir = DMA_FROM_DEVICE; diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_reserved_mem.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_reserved_mem.c index a39042fa5462..0b35e3dbac6d 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_reserved_mem.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_reserved_mem.c @@ -399,8 +399,8 @@ static gceSTATUS reserved_mem_cache_op( IN gckALLOCATOR Allocator, IN PLINUX_MDL Mdl, + IN gctSIZE_T Offset, IN gctPOINTER Logical, - IN gctUINT32 Physical, IN gctUINT32 Bytes, IN gceCACHEOPERATION Operation ) diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c index 7d4c378a1025..5759effdadeb 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_user_memory.c @@ -709,8 +709,8 @@ static gceSTATUS _UserMemoryCache( IN gckALLOCATOR Allocator, IN PLINUX_MDL Mdl, + IN gctSIZE_T Offset, IN gctPOINTER Logical, - IN gctUINT32 Physical, IN gctUINT32 Bytes, IN gceCACHEOPERATION Operation ) @@ -737,8 +737,10 @@ _UserMemoryCache( dma_sync_sg_for_device(galcore_device, um->sgt.sgl, um->sgt.nents, dir); break; case gcvCACHE_FLUSH: - dir = DMA_BIDIRECTIONAL; + dir = DMA_TO_DEVICE; dma_sync_sg_for_device(galcore_device, um->sgt.sgl, um->sgt.nents, dir); + dir = DMA_FROM_DEVICE; + dma_sync_sg_for_cpu(galcore_device, um->sgt.sgl, um->sgt.nents, dir); break; case gcvCACHE_INVALIDATE: dir = DMA_FROM_DEVICE; diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c index f0a3d166f1a5..c6a28bbb31d9 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c @@ -472,8 +472,8 @@ static gceSTATUS _CMACache( IN gckALLOCATOR Allocator, IN PLINUX_MDL Mdl, + IN gctSIZE_T Offset, IN gctPOINTER Logical, - IN gctUINT32 Physical, IN gctUINT32 Bytes, IN gceCACHEOPERATION Operation ) diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h index 81801c747e1a..4d103f1e24cc 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.h @@ -285,12 +285,12 @@ typedef struct _gcsALLOCATOR_OPERATIONS ** PLINUX_MDL Mdl ** Pointer to a Mdl object. ** + ** gctSIZE_T Offset + ** Offset to this memory block + ** ** gctPOINTER Logical ** Logical address, could be user address or kernel address ** - ** gctUINT32_PTR Physical - ** Physical address. - ** ** gctUINT32 Bytes ** Size of memory region. ** @@ -305,8 +305,8 @@ typedef struct _gcsALLOCATOR_OPERATIONS gceSTATUS (*Cache)( IN gckALLOCATOR Allocator, IN PLINUX_MDL Mdl, + IN gctSIZE_T Offset, IN gctPOINTER Logical, - IN gctUINT32 Physical, IN gctUINT32 Bytes, IN gceCACHEOPERATION Operation ); diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h index a3428a1667b8..ee80046bffd6 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.h @@ -61,6 +61,10 @@ #include <linux/time.h> #include <stdarg.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) +#include <linux/nmi.h> +#endif + #ifdef __cplusplus extern "C" { #endif 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 8f8657f4c81e..d0a930a12ed6 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 @@ -697,6 +697,7 @@ static int gc_clk_show(struct seq_file* m, void* data) gcsINFO_NODE *node = m->private; gckGALDEVICE device = node->device; gctUINT i; + gceSTATUS status; for (i = gcvCORE_MAJOR; i < gcvCORE_COUNT; i++) { @@ -710,7 +711,13 @@ static int gc_clk_show(struct seq_file* m, void* data) continue; } #endif - gckHARDWARE_QueryFrequency(hardware); + + status = gckHARDWARE_QueryFrequency(hardware); + if (gcmIS_ERROR(status)) + { + seq_printf(m, "query gpu%d clock fail.\n", i); + continue; + } if (hardware->mcClk) { 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 f059fe34fe2b..87f26e721773 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 @@ -903,7 +903,11 @@ static int gpu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #endif /* USE_LINUX_PCIE */ { int ret = -ENODEV; - static u64 dma_mask = ~0ULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) + static u64 dma_mask = DMA_BIT_MASK(40); +#else + static u64 dma_mask = DMA_40BIT_MASK; +#endif gcsMODULE_PARAMETERS moduleParam = { .irqLine = irqLine, @@ -944,14 +948,12 @@ static int gpu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) platform->device = pdev; galcore_device = &pdev->dev; - galcore_device->dma_mask = &dma_mask; - #if USE_LINUX_PCIE if (pci_enable_device(pdev)) { printk(KERN_ERR "galcore: pci_enable_device() failed.\n"); } - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + if (pci_set_dma_mask(pdev, dma_mask)) { printk(KERN_ERR "galcore: Failed to set DMA mask.\n"); } @@ -965,7 +967,9 @@ static int gpu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_enable_msi(pdev)) { printk(KERN_ERR "galcore: Failed to enable MSI.\n"); } -#endif +# endif +#else + galcore_device->dma_mask = &dma_mask; #endif if (platform->ops->getPower) diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_drm.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_drm.c index bfb76ac6b1a3..1fd340158dcc 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_drm.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_drm.c @@ -557,12 +557,11 @@ static int viv_ioctl_gem_attach_aux(struct drm_device *drm, void *data, if (args->ts_handle) { struct viv_gem_object *viv_ts_obj; - size_t num = 0; gckKERNEL kernel = gal_dev->device->map[gal_dev->device->defaultHwType].kernels[0]; gcsHAL_INTERFACE iface; gctBOOL is2BitPerTile = gckHARDWARE_IsFeatureAvailable(kernel->hardware , gcvFEATURE_TILE_STATUS_2BITS); gctBOOL isCompressionDEC400 = gckHARDWARE_IsFeatureAvailable(kernel->hardware , gcvFEATURE_COMPRESSION_DEC400); - char __user* entry = gcvNULL; + gctPOINTER entry = gcvNULL; gctUINT32 tileStatusFiller = (isCompressionDEC400 || ((kernel->hardware->identity.chipModel == gcv500) && (kernel->hardware->identity.chipRevision > 2))) ? 0xFFFFFFFF : is2BitPerTile ? 0x55555555 : 0x11111111; @@ -587,10 +586,9 @@ static int viv_ioctl_gem_attach_aux(struct drm_device *drm, void *data, gcmkONERROR(gckDEVICE_Dispatch(gal_dev->device, &iface)); /* Fill tile status node with tileStatusFiller. */ - entry = (char __user*)(uintptr_t)iface.u.LockVideoMemory.memory; - for (num=0; num<gem_ts_obj->size; num++) { - put_user(tileStatusFiller, entry+num); - } + gcmkONERROR(gckVIDMEM_NODE_LockCPU(kernel, viv_ts_obj->node_handle, &entry)); + memset(entry , tileStatusFiller , (__u64)gem_ts_obj->size); + gcmkONERROR(gckVIDMEM_NODE_UnlockCPU(kernel, viv_ts_obj->node_handle, entry)); /* UnLock tile status node. */ memset(&iface, 0, sizeof(iface)); @@ -750,7 +748,7 @@ OnError: void viv_drm_postclose(struct drm_device *drm, struct drm_file *file) { gctINT i; - gctUINT32 pid = gcmPTR2INT(file->driver_priv); + gctUINT32 pid = gcmPTR2SIZE(file->driver_priv); gckGALDEVICE gal_dev = (gckGALDEVICE)drm->dev_private; for (i = 0; i < gcdMAX_GPU_COUNT; ++i) diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h index 5d82642aed5a..c536e44d6755 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h @@ -118,14 +118,6 @@ /* Protection bit when mapping memroy to user sapce */ #define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x) -#if gcdNONPAGED_MEMORY_BUFFERABLE -#define gcmkIOREMAP ioremap_wc -#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x) -#elif !gcdNONPAGED_MEMORY_CACHEABLE -#define gcmkIOREMAP ioremap_nocache -#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x) -#endif - #define gcdSUPPRESS_OOM_MESSAGE 1 #if gcdSUPPRESS_OOM_MESSAGE @@ -225,6 +217,9 @@ struct _gckOS /* Signal management. */ + /* Lock. */ + spinlock_t signalLock; + /* signal id database. */ gcsINTEGER_DB signalDB; @@ -271,7 +266,7 @@ typedef struct _gcsSIGNAL gctBOOL manualReset; /* The reference counter. */ - volatile int ref; + atomic_t ref; /* The owner of the signal. */ gctHANDLE process; @@ -279,8 +274,8 @@ typedef struct _gcsSIGNAL /* ID. */ gctUINT32 id; -#if gcdANDROID_NATIVE_FENCE_SYNC -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) +#if gcdLINUX_SYNC_FILE +#ifndef CONFIG_SYNC_FILE /* Parent timeline. */ struct sync_timeline * timeline; # else 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 cb52a3b60362..36b1a2fd3409 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 @@ -73,7 +73,7 @@ #include <linux/anon_inodes.h> #endif -#if gcdANDROID_NATIVE_FENCE_SYNC +#if gcdLINUX_SYNC_FILE # include <linux/file.h> # include "gc_hal_kernel_sync.h" #endif @@ -276,12 +276,11 @@ _AllocateIntegerId( { int result; gctINT next; - unsigned long flags; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) idr_preload(GFP_KERNEL | gcdNOWARN); - spin_lock_irqsave(&Database->lock, flags); + spin_lock(&Database->lock); next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1; @@ -295,7 +294,7 @@ _AllocateIntegerId( Database->curr = *Id = result; } - spin_unlock_irqrestore(&Database->lock, flags); + spin_unlock(&Database->lock); idr_preload_end(); @@ -310,7 +309,7 @@ again: return gcvSTATUS_OUT_OF_MEMORY; } - spin_lock_irqsave(&Database->lock, flags); + spin_lock(&Database->lock); next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1; @@ -322,7 +321,7 @@ again: Database->curr = *Id; } - spin_unlock_irqstore(&Database->lock, flags); + spin_unlock(&Database->lock); if (result == -EAGAIN) { @@ -347,7 +346,12 @@ _QueryIntegerId( { gctPOINTER pointer; + spin_lock(&Database->lock); + pointer = idr_find(&Database->idr, Id); + + spin_unlock(&Database->lock); + if (pointer) { *KernelPointer = pointer; @@ -370,8 +374,12 @@ _DestroyIntegerId( IN gctUINT32 Id ) { + spin_lock(&Database->lock); + idr_remove(&Database->idr, Id); + spin_unlock(&Database->lock); + return gcvSTATUS_OK; } @@ -541,6 +549,9 @@ gckOS_Construct( * Initialize the signal manager. */ + /* Initialize spinlock. */ + spin_lock_init(&os->signalLock); + /* Initialize signal id database lock. */ spin_lock_init(&os->signalDB.lock); @@ -675,6 +686,62 @@ gckOS_Destroy( } gceSTATUS +gckOS_CreateKernelMapping( + IN gckOS Os, + IN gctPHYS_ADDR Physical, + IN gctSIZE_T Offset, + IN gctSIZE_T Bytes, + OUT gctPOINTER * Logical + ) +{ + gceSTATUS status = gcvSTATUS_OK; + PLINUX_MDL mdl = (PLINUX_MDL)Physical; + gckALLOCATOR allocator = mdl->allocator; + + gcmkHEADER_ARG("Os=%p Physical=%p Offset=0x%zx Bytes=0x%zx", + Os, Physical, Offset, Bytes); + + if (mdl->addr) + { + /* Already mapped whole memory. */ + *Logical = (gctUINT8_PTR)mdl->addr + Offset; + } + else + { + gcmkONERROR(allocator->ops->MapKernel(allocator, mdl, Logical)); + } + +OnError: + gcmkFOOTER_ARG("*Logical=%p", gcmOPT_POINTER(Logical)); + return status; +} + +gceSTATUS +gckOS_DestroyKernelMapping( + IN gckOS Os, + IN gctPHYS_ADDR Physical, + IN gctPOINTER Logical + ) +{ + PLINUX_MDL mdl = (PLINUX_MDL)Physical; + gckALLOCATOR allocator = mdl->allocator; + + gcmkHEADER_ARG("Os=%p Physical=%p Logical=%p", Os, Physical, Logical); + + if (mdl->addr) + { + /* Nothing to do. */ + } + else + { + allocator->ops->UnmapKernel(allocator, mdl, Logical); + } + + gcmkFOOTER_NO(); + return gcvSTATUS_OK; +} + +gceSTATUS gckOS_CreateKernelVirtualMapping( IN gckOS Os, IN gctPHYS_ADDR Physical, @@ -1323,6 +1390,8 @@ gckOS_AllocateNonPagedMemory( /* Check status. */ gcmkONERROR(status); + mdl->cacheable = Flag & gcvALLOC_FLAG_CACHEABLE; + mdl->bytes = bytes; mdl->numPages = numPages; @@ -1330,6 +1399,12 @@ gckOS_AllocateNonPagedMemory( gcmkONERROR(allocator->ops->MapKernel(allocator, mdl, &addr)); + if (!strcmp(allocator->name, "gfp")) + { + /* Trigger a page fault. */ + memset(addr, 0, numPages * PAGE_SIZE); + } + mdl->addr = addr; if (InUserSpace) @@ -2126,6 +2201,7 @@ gckOS_MapPhysical( { if ((physical >= mdl->dmaHandle) && (physical < mdl->dmaHandle + mdl->bytes) + && (mdl->addr != 0) ) { *Logical = mdl->addr + (physical - mdl->dmaHandle); @@ -2148,6 +2224,7 @@ gckOS_MapPhysical( struct page * page; gctUINT numPages; gctINT i; + pgprot_t pgprot; numPages = GetPageCount(PAGE_ALIGN(offset + Bytes), 0); @@ -2166,7 +2243,13 @@ gckOS_MapPhysical( pages[i] = nth_page(page, i); } - logical = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL)); +#if gcdENABLE_BUFFERABLE_VIDEO_MEMORY + pgprot = pgprot_writecombine(PAGE_KERNEL); +#else + pgprot = pgprot_noncached(PAGE_KERNEL); +#endif + + logical = vmap(pages, numPages, 0, pgprot); kfree(pages); @@ -3102,6 +3185,7 @@ gckOS_AllocatePagedMemoryEx( mdl->bytes = bytes; mdl->numPages = numPages; mdl->contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS; + mdl->cacheable = Flag & gcvALLOC_FLAG_CACHEABLE; if (Gid != gcvNULL) { @@ -3336,17 +3420,14 @@ gckOS_MapPagesEx( PLINUX_MDL mdl; gctUINT32* table; gctUINT32 offset = 0; -#if gcdNONPAGED_MEMORY_CACHEABLE - gckMMU mmu; - PLINUX_MDL mmuMdl; - gctUINT32 bytes; - gctPHYS_ADDR pageTablePhysical; -#endif #if gcdPROCESS_ADDRESS_SPACE gckKERNEL kernel = Os->device->kernels[Core]; gckMMU mmu; #endif + + gctUINT32 bytes = PageCount * 4; + gckALLOCATOR allocator; gctUINT32 policyID = 0; @@ -3383,11 +3464,6 @@ gckOS_MapPagesEx( #endif table = (gctUINT32 *)PageTable; -#if gcdNONPAGED_MEMORY_CACHEABLE - mmu = Os->device->kernels[Core]->mmu; - bytes = PageCount * sizeof(*table); - mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical; -#endif if (platform && platform->ops->getPolicyID) { @@ -3483,21 +3559,56 @@ gckOS_MapPagesEx( offset += PAGE_SIZE; } -#if gcdNONPAGED_MEMORY_CACHEABLE - /* Get physical address of pageTable */ - pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle + - ((gctUINT32 *)PageTable - mmu->pageTableLogical)); +#if gcdENABLE_VG + if (Core == gcvCORE_VG) + { + gckVGMMU mmu = Os->device->kernels[gcvCORE_VG]->vg->mmu; + gctPHYS_ADDR mmuMdl = mmu->pageTablePhysical; - /* Flush the mmu page table cache. */ - gcmkONERROR(gckOS_CacheClean( - Os, - _GetProcessID(), - gcvNULL, - pageTablePhysical, - PageTable, - bytes - )); -#endif + offset = (gctUINT8_PTR)PageTable - (gctUINT8_PTR)mmu->pageTableLogical; + + gcmkVERIFY_OK(gckOS_CacheClean( + Os, + _GetProcessID(), + mmuMdl, + offset, + PageTable, + bytes + )); + } + else +# endif + { + gckMMU mmu = Os->device->kernels[Core]->mmu; + gcsADDRESS_AREA * area = &mmu->area[0]; + + offset = (gctUINT8_PTR)PageTable - (gctUINT8_PTR)area->pageTableLogical; + + /* must be in dynamic area. */ + gcmkASSERT(offset < area->pageTableSize); + + gcmkVERIFY_OK(gckOS_CacheClean( + Os, + 0, + area->pageTablePhysical, + offset, + PageTable, + bytes + )); + + if (mmu->mtlbPhysical) + { + /* Flush MTLB table. */ + gcmkVERIFY_OK(gckOS_CacheClean( + Os, + 0, + mmu->mtlbPhysical, + 0, + mmu->mtlbLogical, + mmu->mtlbSize + )); + } + } OnError: @@ -4382,7 +4493,7 @@ _CacheOperation( IN gckOS Os, IN gctUINT32 ProcessID, IN gctPHYS_ADDR Handle, - IN gctPHYS_ADDR_T Physical, + IN gctSIZE_T Offset, IN gctPOINTER Logical, IN gctSIZE_T Bytes, IN gceCACHEOPERATION Operation @@ -4408,15 +4519,16 @@ _CacheOperation( mutex_unlock(&mdl->mapsMutex); - if (mdlMap == gcvNULL) + if (ProcessID && mdlMap == gcvNULL) { return gcvSTATUS_INVALID_ARGUMENT; } - if (mdlMap->cacheable) + if ((!ProcessID && mdl->cacheable) || + (mdlMap && mdlMap->cacheable)) { allocator->ops->Cache(allocator, - mdl, Logical, Physical, Bytes, Operation); + mdl, Offset, Logical, Bytes, Operation); return gcvSTATUS_OK; } @@ -4445,8 +4557,8 @@ _CacheOperation( ** gctPHYS_ADDR Handle ** Physical address handle. If gcvNULL it is video memory. ** -** gctPOINTER Physical -** Physical address to flush. +** gctSIZE_T Offset +** Offset to this memory block. ** ** gctPOINTER Logical ** Logical address to flush. @@ -4480,7 +4592,7 @@ gckOS_CacheClean( IN gckOS Os, IN gctUINT32 ProcessID, IN gctPHYS_ADDR Handle, - IN gctPHYS_ADDR_T Physical, + IN gctSIZE_T Offset, IN gctPOINTER Logical, IN gctSIZE_T Bytes ) @@ -4496,7 +4608,7 @@ gckOS_CacheClean( gcmkVERIFY_ARGUMENT(Bytes > 0); gcmkONERROR(_CacheOperation(Os, ProcessID, - Handle, Physical, Logical, Bytes, + Handle, Offset, Logical, Bytes, gcvCACHE_CLEAN)); OnError: @@ -4523,6 +4635,9 @@ OnError: ** gctPHYS_ADDR Handle ** Physical address handle. If gcvNULL it is video memory. ** +** gctSIZE_T Offset +** Offset to this memory block. +** ** gctPOINTER Logical ** Logical address to flush. ** @@ -4534,15 +4649,15 @@ gckOS_CacheInvalidate( IN gckOS Os, IN gctUINT32 ProcessID, IN gctPHYS_ADDR Handle, - IN gctPHYS_ADDR_T Physical, + IN gctSIZE_T Offset, IN gctPOINTER Logical, IN gctSIZE_T Bytes ) { gceSTATUS status; - gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=%p Bytes=%lu", - Os, ProcessID, Handle, Logical, Bytes); + gcmkHEADER_ARG("Os=%p ProcessID=%d Handle=%p Offset=0x%llx Logical=%p Bytes=0x%zx", + Os, ProcessID, Handle, Offset, Logical, Bytes); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); @@ -4550,7 +4665,7 @@ gckOS_CacheInvalidate( gcmkVERIFY_ARGUMENT(Bytes > 0); gcmkONERROR(_CacheOperation(Os, ProcessID, - Handle, Physical, Logical, Bytes, + Handle, Offset, Logical, Bytes, gcvCACHE_INVALIDATE)); OnError: @@ -4576,6 +4691,9 @@ OnError: ** gctPHYS_ADDR Handle ** Physical address handle. If gcvNULL it is video memory. ** +** gctSIZE_T Offset +** Offset to this memory block. +** ** gctPOINTER Logical ** Logical address to flush. ** @@ -4587,15 +4705,15 @@ gckOS_CacheFlush( IN gckOS Os, IN gctUINT32 ProcessID, IN gctPHYS_ADDR Handle, - IN gctPHYS_ADDR_T Physical, + IN gctSIZE_T Offset, IN gctPOINTER Logical, IN gctSIZE_T Bytes ) { gceSTATUS status; - gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=%p Bytes=%lu", - Os, ProcessID, Handle, Logical, Bytes); + gcmkHEADER_ARG("Os=%p ProcessID=%d Handle=%p Offset=0x%llx Logical=%p Bytes=0x%zx", + Os, ProcessID, Handle, Offset, Logical, Bytes); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); @@ -4603,7 +4721,7 @@ gckOS_CacheFlush( gcmkVERIFY_ARGUMENT(Bytes > 0); gcmkONERROR(_CacheOperation(Os, ProcessID, - Handle, Physical, Logical, Bytes, + Handle, Offset, Logical, Bytes, gcvCACHE_FLUSH)); OnError: @@ -5520,10 +5638,11 @@ gckOS_CreateSignal( init_waitqueue_head(&signal->wait); spin_lock_init(&signal->lock); signal->manualReset = ManualReset; - signal->ref = 1; -#if gcdANDROID_NATIVE_FENCE_SYNC -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) + atomic_set(&signal->ref, 1); + +#if gcdLINUX_SYNC_FILE +#ifndef CONFIG_SYNC_FILE signal->timeline = gcvNULL; # else signal->fence = gcvNULL; @@ -5573,7 +5692,8 @@ gckOS_DestroySignal( { gceSTATUS status; gcsSIGNAL_PTR signal; - unsigned long flags; + gctBOOL acquired = gcvFALSE; + unsigned long flags = 0; gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal); @@ -5581,31 +5701,49 @@ gckOS_DestroySignal( gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); gcmkVERIFY_ARGUMENT(Signal != gcvNULL); - spin_lock_irqsave(&Os->signalDB.lock, flags); - status = _QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal); - if (gcmIS_ERROR(status)) - { - spin_unlock_irqrestore(&Os->signalDB.lock, flags); - gcmkONERROR(status); + if(in_irq()){ + spin_lock(&Os->signalLock); + }else{ + spin_lock_irqsave(&Os->signalLock, flags); } + acquired = gcvTRUE; + + gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal)); gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal); - signal->ref--; - if (signal->ref == 0) + if (atomic_dec_and_test(&signal->ref)) { gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id)); /* Free the sgianl. */ kfree(signal); } - spin_unlock_irqrestore(&Os->signalDB.lock, flags); + + if(in_irq()){ + spin_unlock(&Os->signalLock); + }else{ + spin_unlock_irqrestore(&Os->signalLock, flags); + } + + acquired = gcvFALSE; /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: + if (acquired) + { + /* Release the mutex. */ + if(in_irq()){ + spin_unlock(&Os->signalLock); + }else{ + spin_unlock_irqrestore(&Os->signalLock, flags); + } + + } + gcmkFOOTER(); return status; } @@ -5641,14 +5779,14 @@ gckOS_Signal( { gceSTATUS status; gcsSIGNAL_PTR signal; -#if gcdANDROID_NATIVE_FENCE_SYNC -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) +#if gcdLINUX_SYNC_FILE +#ifndef CONFIG_SYNC_FILE struct sync_timeline * timeline = gcvNULL; # else struct dma_fence * fence = gcvNULL; # endif #endif - unsigned long flags; + unsigned long flags = 0; gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State); @@ -5656,13 +5794,15 @@ gckOS_Signal( gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); gcmkVERIFY_ARGUMENT(Signal != gcvNULL); - spin_lock_irqsave(&Os->signalDB.lock, flags); + spin_lock_irqsave(&Os->signalLock, flags); + status = _QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal); + if (gcmIS_ERROR(status)) { - spin_unlock_irqrestore(&Os->signalDB.lock, flags); + spin_unlock_irqrestore(&Os->signalLock, flags); gcmkONERROR(status); } @@ -5671,10 +5811,13 @@ gckOS_Signal( * concurrent issue: signaling the signal while another thread is destroying * it. */ + atomic_inc(&signal->ref); + + spin_unlock_irqrestore(&Os->signalLock, flags); + + gcmkONERROR(status); gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal); - signal->ref++; - spin_unlock_irqrestore(&Os->signalDB.lock, flags); spin_lock(&signal->lock); @@ -5684,8 +5827,8 @@ gckOS_Signal( wake_up(&signal->wait); -#if gcdANDROID_NATIVE_FENCE_SYNC -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) +#if gcdLINUX_SYNC_FILE +#ifndef CONFIG_SYNC_FILE timeline = signal->timeline; # else fence = signal->fence; @@ -5700,8 +5843,8 @@ gckOS_Signal( spin_unlock(&signal->lock); -#if gcdANDROID_NATIVE_FENCE_SYNC -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) +#if gcdLINUX_SYNC_FILE +#ifndef CONFIG_SYNC_FILE /* Signal timeline. */ if (timeline) { @@ -5716,17 +5859,17 @@ gckOS_Signal( # endif #endif - spin_lock_irqsave(&Os->signalDB.lock, flags); - signal->ref --; + spin_lock_irqsave(&Os->signalLock, flags); - if (signal->ref == 0) + if (atomic_dec_and_test(&signal->ref)) { gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id)); /* Free the sgianl. */ kfree(signal); } - spin_unlock_irqrestore(&Os->signalDB.lock, flags); + + spin_unlock_irqrestore(&Os->signalLock, flags); /* Success. */ gcmkFOOTER_NO(); @@ -5810,7 +5953,6 @@ gckOS_WaitSignal( gceSTATUS status; gcsSIGNAL_PTR signal = gcvNULL; int done; - unsigned long flags; gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait); @@ -5818,11 +5960,7 @@ gckOS_WaitSignal( gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); gcmkVERIFY_ARGUMENT(Signal != gcvNULL); - spin_lock_irqsave(&Os->signalDB.lock, flags); - status = _QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal); - spin_unlock_irqrestore(&Os->signalDB.lock, flags); - - gcmkONERROR(status); + gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal)); gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal); @@ -5909,13 +6047,10 @@ _QuerySignal( */ gceSTATUS status; gcsSIGNAL_PTR signal = gcvNULL; - unsigned long flags; - spin_lock_irqsave(&Os->signalDB.lock, flags); status = _QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal); - spin_unlock_irqrestore(&Os->signalDB.lock, flags); if (gcmIS_SUCCESS(status)) { @@ -5959,37 +6094,33 @@ gckOS_MapSignal( { gceSTATUS status; gcsSIGNAL_PTR signal = gcvNULL; - unsigned long flags; + unsigned long flags = 0; gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process); gcmkVERIFY_ARGUMENT(Signal != gcvNULL); gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL); - spin_lock_irqsave(&Os->signalDB.lock, flags); - status = _QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal); - if (gcmIS_ERROR(status)) - { - spin_unlock_irqrestore(&Os->signalDB.lock, flags); - gcmkONERROR(status); - } + spin_lock_irqsave(&Os->signalLock, flags); - signal->ref++; + gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal)); - if (signal->ref <= 1) + if (atomic_inc_return(&signal->ref) <= 1) { - spin_unlock_irqrestore(&Os->signalDB.lock, flags); /* The previous value is 0, it has been deleted. */ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } *MappedSignal = (gctSIGNAL) Signal; - spin_unlock_irqrestore(&Os->signalDB.lock, flags); + + spin_unlock_irqrestore(&Os->signalLock, flags); /* Success. */ gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal); return gcvSTATUS_OK; OnError: + spin_unlock_irqrestore(&Os->signalLock, flags); + gcmkFOOTER_NO(); return status; } @@ -6625,8 +6756,8 @@ gckOS_DetectProcessByName( : gcvSTATUS_FALSE; } -#if gcdANDROID_NATIVE_FENCE_SYNC -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) +#if gcdLINUX_SYNC_FILE +#ifndef CONFIG_SYNC_FILE gceSTATUS gckOS_CreateSyncTimeline( IN gckOS Os, @@ -6683,21 +6814,14 @@ gckOS_CreateNativeFence( char name[32]; gcsSIGNAL_PTR signal; gceSTATUS status; - unsigned long flags; gcmkHEADER_ARG("Os=0x%X Timeline=0x%X Signal=%d", Os, Timeline, (gctUINT)(gctUINTPTR_T)Signal); - spin_lock_irqsave(&Os->signalDB.lock, flags); - status = _QueryIntegerId(&Os->signalDB, + gcmkONERROR( + _QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, - (gctPOINTER)&signal); - if (gcmIS_ERROR(status)) - { - spin_unlock_irqrestore(&Os->signalDB.lock, flags); - gcmkONERROR(status); - } - spin_unlock_irqrestore(&Os->signalDB.lock, flags); + (gctPOINTER)&signal)); /* Cast timeline. */ timeline = (struct viv_sync_timeline *) Timeline; @@ -6907,7 +7031,7 @@ OnError: return status; } -# else /* v4.9.0 */ +# else /* !CONFIG_SYNC_FILE */ gceSTATUS gckOS_CreateSyncTimeline( @@ -6962,29 +7086,14 @@ gckOS_CreateNativeFence( struct viv_sync_timeline *timeline; gcsSIGNAL_PTR signal = gcvNULL; gceSTATUS status = gcvSTATUS_OK; - unsigned long flags; /* Create fence. */ timeline = (struct viv_sync_timeline *) Timeline; - spin_lock_irqsave(&Os->signalDB.lock, flags); - status = _QueryIntegerId(&Os->signalDB, + gcmkONERROR( + _QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, - (gctPOINTER)&signal); - if (gcmIS_ERROR(status)) - { - spin_unlock_irqrestore(&Os->signalDB.lock, flags); - gcmkONERROR(status); - } - - signal->ref++; - if (signal->ref <= 1) - { - spin_unlock_irqrestore(&Os->signalDB.lock, flags); - /* The previous value is 0, it has been deleted. */ - gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); - } - spin_unlock_irqrestore(&Os->signalDB.lock, flags); + (gctPOINTER)&signal)); fence = viv_fence_create(timeline, signal); @@ -7020,10 +7129,12 @@ OnError: fput(sync->file); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,68) if (fence) { dma_fence_put(fence); } +#endif if (fd > 0) { @@ -7034,6 +7145,24 @@ OnError: return status; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) +/** + * sync_file_fdget() - get a sync_file from an fd + * @fd: fd referencing a fence + * + * Ensures @fd references a valid sync_file, increments the refcount of the + * backing file. Returns the sync_file or NULL in case of error. + */ +static struct sync_file *sync_file_fdget(int fd) +{ + struct file *file = fget(fd); + + if (!file) + return NULL; + + return file->private_data; +} + gceSTATUS gckOS_WaitNativeFence( IN gckOS Os, @@ -7045,8 +7174,77 @@ gckOS_WaitNativeFence( struct viv_sync_timeline *timeline; gceSTATUS status = gcvSTATUS_OK; unsigned int i; + unsigned long timeout; unsigned int numFences; + struct sync_file *sync_file; + + timeline = (struct viv_sync_timeline *) Timeline; + + sync_file = sync_file_fdget(FenceFD); + + if (!sync_file) + { + gcmkONERROR(gcvSTATUS_GENERIC_IO); + } + + numFences = sync_file->num_fences; + + timeout = msecs_to_jiffies(Timeout); + + for (i = 0; i < numFences; i++) + { + struct fence *f = sync_file->cbs[i].fence; + fence_get(f); + + if (f->context != timeline->context && + !fence_is_signaled(f)) + { + signed long ret; + ret = fence_wait_timeout(f, 1, timeout); + + if (ret == -ERESTARTSYS) + { + status = gcvSTATUS_INTERRUPTED; + fence_put(f); + break; + } + else if (ret <= 0) + { + status = gcvSTATUS_TIMEOUT; + fence_put(f); + break; + } + else + { + /* wait success. */ + timeout -= ret; + } + } + + fence_put(f); + } + + return gcvSTATUS_OK; + +OnError: + return status; +} + +# else + +gceSTATUS +gckOS_WaitNativeFence( + IN gckOS Os, + IN gctHANDLE Timeline, + IN gctINT FenceFD, + IN gctUINT32 Timeout + ) +{ + struct viv_sync_timeline *timeline; + gceSTATUS status = gcvSTATUS_OK; + unsigned int i; unsigned long timeout; + unsigned int numFences; struct dma_fence *fence; struct dma_fence **fences; @@ -7109,7 +7307,8 @@ OnError: return status; } -# endif /* v4.9.0 */ +# endif +# endif #endif #if gcdSECURITY @@ -7365,6 +7564,11 @@ gckOS_QueryOption( *Value = device->args.gpuProfiler; return gcvSTATUS_OK; } + else if (!strcmp(Option, "platformFlagBits")) + { + *Value = device->platform->flagBits; + return gcvSTATUS_OK; + } return gcvSTATUS_NOT_SUPPORTED; } 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 3cea45f3ca26..6f63109903e1 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 @@ -89,6 +89,8 @@ struct _LINUX_MDL gctBOOL contiguous; dma_addr_t dmaHandle; + gctBOOL cacheable; + struct mutex mapsMutex; struct list_head mapsHead; diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h index f83354d47735..b570195cf044 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_platform.h @@ -281,12 +281,6 @@ typedef struct soc_platform_ops } gcsPLATFORM_OPERATIONS; -enum -{ - /* GPU can't issue more that 32bit physical address */ - gcvPLATFORM_FLAG_LIMIT_4G_ADDRESS = 1 << 0, -}; - struct soc_platform { #if USE_LINUX_PCIE diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c index 3b5a2913a922..b366a2fb71fa 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c @@ -56,7 +56,7 @@ #include <gc_hal.h> #include <gc_hal_base.h> -#if gcdANDROID_NATIVE_FENCE_SYNC +#if gcdLINUX_SYNC_FILE #include <linux/kernel.h> #include <linux/file.h> @@ -70,7 +70,7 @@ #include "gc_hal_kernel_sync.h" #include "gc_hal_kernel_linux.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) +#ifndef CONFIG_SYNC_FILE static struct sync_pt * viv_sync_pt_dup(struct sync_pt *sync_pt) { @@ -224,7 +224,7 @@ struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj, return (struct sync_pt *)pt; } -#else /* v4.9.0 */ +#else struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os) { @@ -308,6 +308,7 @@ static struct dma_fence_ops viv_fence_ops = struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline, gcsSIGNAL *signal) { + gceSTATUS status; struct viv_fence *fence; struct dma_fence *old_fence = NULL; unsigned seqno; @@ -317,9 +318,17 @@ struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline, if (!fence) return NULL; + /* Reference signal in fence. */ + status = gckOS_MapSignal(timeline->os, (gctSIGNAL)(uintptr_t)signal->id, + NULL, &fence->signal); + + if (gcmIS_ERROR(status)) { + kfree(fence); + return NULL; + } + spin_lock_init(&fence->lock); - fence->signal = (gctSIGNAL)(uintptr_t)signal->id; fence->parent = timeline; seqno = (unsigned)atomic64_inc_return(&timeline->seqno); @@ -340,6 +349,10 @@ struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline, if (!signal->done) { signal->fence = (struct dma_fence*)fence; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,68) + dma_fence_get((struct dma_fence*)fence); +#endif } spin_unlock(&signal->lock); @@ -360,6 +373,6 @@ struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline, return (struct dma_fence*)fence; } -#endif /* v4.9.0 */ +#endif #endif diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h index 695ccfff7918..d723e469a470 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h @@ -58,7 +58,7 @@ #include <linux/types.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0) +#ifndef CONFIG_SYNC_FILE /* sync.h is in drivers/staging/android/ for now. */ #include <sync.h> @@ -98,7 +98,7 @@ struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os); struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj, gctSIGNAL signal); -#else /* v4.9.0 */ +#else #include <linux/sync_file.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) @@ -146,6 +146,6 @@ void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline); struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline, gcsSIGNAL *signal); -#endif /* v4.9.0 */ +#endif #endif /* __gc_hal_kernel_sync_h_ */ diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx.c index 0349c95f4fa7..a64004e5b974 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx.c @@ -308,7 +308,7 @@ static struct notifier_block thermal_hot_pm_notifier = static ssize_t gpu3DMinClock_show(struct device_driver *dev, char *buf) { - gctUINT currentf,minf,maxf; + gctUINT currentf = 0, minf = 0, maxf = 0; gckGALDEVICE galDevice; galDevice = platform_get_drvdata(pdevice); @@ -345,8 +345,11 @@ static ssize_t gpu3DMinClock_store(struct device_driver *dev, const char *buf, s return count; } - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) static DRIVER_ATTR_RW(gpu3DMinClock); +#else +static DRIVER_ATTR(gpu3DMinClock, S_IRUGO | S_IWUSR, gpu3DMinClock_show, gpu3DMinClock_store); +#endif #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) @@ -500,9 +503,11 @@ static ssize_t gpu_govern_store(struct device_driver *dev, const char *buf, size return count; } - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) static DRIVER_ATTR_RW(gpu_govern); - +#else +static DRIVER_ATTR(gpu_govern, S_IRUGO | S_IWUSR, gpu_govern_show, gpu_govern_store); +#endif int init_gpu_opp_table(struct device *dev) { @@ -1505,9 +1510,16 @@ _AdjustParam( { patch_param(Platform->device, Args); - if (of_find_compatible_node(NULL, NULL, "fsl,imx8mq-gpu") && ((Args->baseAddress + totalram_pages * PAGE_SIZE) > 0x100000000)) - Platform->flagBits = gcvPLATFORM_FLAG_LIMIT_4G_ADDRESS; + if (of_find_compatible_node(NULL, NULL, "fsl,imx8mq-gpu") && + ((Args->baseAddress + totalram_pages * PAGE_SIZE) > 0x100000000)) + { + Platform->flagBits |= gcvPLATFORM_FLAG_LIMIT_4G_ADDRESS; + } + if (of_find_compatible_node(NULL, NULL, "fsl,imx8mm-gpu")) + { + Platform->flagBits |= gcvPLATFORM_FLAG_IMX_MM; + } return gcvSTATUS_OK; } diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx.config b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx.config index ea83bd993d35..56fcc26cffcd 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx.config +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx.config @@ -7,6 +7,7 @@ EXTRA_CFLAGS += -DgcdANDROID endif EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=2 + ifeq ($(CONFIG_SYNC)$(CONFIG_SYNC_FILE),) $(warn CONFIG_SYNC or CONFIG_SYNC_FILE is not set in kernel config) $(warn Android native fence sync requires CONFIG_SYNC or CONFIG_SYNC_FILE) |