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/kernel/gc_hal_kernel_os.c | |
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/kernel/gc_hal_kernel_os.c')
-rw-r--r-- | drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c | 462 |
1 files changed, 333 insertions, 129 deletions
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; } |