summaryrefslogtreecommitdiff
path: root/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
diff options
context:
space:
mode:
authorXianzhong <xianzhong.li@nxp.com>2019-01-11 23:28:33 +0800
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:35:55 +0800
commita03bac842b9f615d3795b272fd719957534ed77a (patch)
tree483fac327e03990991d70a70c3b738a9749072c4 /drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
parentd260e22591f1d645bcb0829ef128301bdb2e65ed (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.c462
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;
}