Skip to content

Instantly share code, notes, and snippets.

@gibsson
Created August 25, 2020 07:43
Show Gist options
  • Save gibsson/45921590256a95c5b868e37387e1909d to your computer and use it in GitHub Desktop.
Save gibsson/45921590256a95c5b868e37387e1909d to your computer and use it in GitHub Desktop.
o800 gpu-viv semi-upgrade
From b71bea48fa38d7886c1e9e182bcfc0a4918300e3 Mon Sep 17 00:00:00 2001
From: Gary Bisson <gary.bisson@boundarydevices.com>
Date: Mon, 24 Aug 2020 23:02:40 +0200
Subject: [PATCH] gpu-viv: update locking and fence syncing from
p9.0.0_2.2.0-ga
- use spinlocks instead of mutexes
- better track fence allocation / free
- check on cacheable flag
Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
---
.../hal/os/linux/kernel/gc_hal_kernel_linux.h | 32 +-
.../hal/os/linux/kernel/gc_hal_kernel_os.c | 445 ++++++++++--------
.../hal/os/linux/kernel/gc_hal_kernel_os.h | 17 +-
.../hal/os/linux/kernel/gc_hal_kernel_sync.c | 53 +--
.../hal/os/linux/kernel/gc_hal_kernel_sync.h | 15 +-
5 files changed, 339 insertions(+), 223 deletions(-)
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 32233cc3418e..e184ee40b8f9 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
@@ -154,6 +154,27 @@
# endif
#endif
+/* gcdLINUX_SYNC_FILE and CONFIG_SYNC_FILE. */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)
+# define dma_fence fence
+# define dma_fence_array fence_array
+# define dma_fence_ops fence_ops
+
+# define dma_fence_default_wait fence_default_wait
+
+# define dma_fence_signal(f) fence_signal(f)
+# define dma_fence_signal_locked(f) fence_signal_locked(f)
+# define dma_fence_get(f) fence_get(f)
+# define dma_fence_put(f) fence_put(f)
+# define dma_fence_is_array(f) fence_is_array(f)
+# define dma_fence_is_signaled(f) fence_is_signaled(f)
+# define to_dma_fence_array(f) to_fence_array(f)
+# define dma_fence_wait_timeout(f, n, t) fence_wait_timeout((f), (n), (t))
+# define dma_fence_init(f, o, l, t, s) fence_init((f), (o), (l), (t), (s))
+# define dma_fence_context_alloc(s) fence_context_alloc(s)
+
+#endif
+
/******************************************************************************\
********************************** Structures **********************************
\******************************************************************************/
@@ -209,7 +230,7 @@ struct _gckOS
/* Signal management. */
/* Lock. */
- struct mutex signalMutex;
+ spinlock_t signalLock;
/* signal id database. */
gcsINTEGER_DB signalDB;
@@ -232,7 +253,7 @@ struct _gckOS
gctBOOL allocatorLimitMarker;
/* Lock for register access check. */
- struct mutex registerAccessLocks[gcdMAX_GPU_COUNT];
+ spinlock_t registerAccessLock;
/* External power states. */
gctBOOL powerStates[gcdMAX_GPU_COUNT];
@@ -248,7 +269,10 @@ typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
typedef struct _gcsSIGNAL
{
/* Kernel sync primitive. */
- struct completion obj;
+ volatile unsigned int done;
+ spinlock_t lock;
+
+ wait_queue_head_t wait;
/* Manual reset flag. */
gctBOOL manualReset;
@@ -267,7 +291,7 @@ typedef struct _gcsSIGNAL
/* Parent timeline. */
struct sync_timeline * timeline;
# else
- struct fence *fence;
+ struct dma_fence *fence;
# endif
#endif
}
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 0f7bdb692230..6c861eb88c1b 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
@@ -86,19 +86,12 @@
#include "gc_hal_kernel_allocator.h"
-#define gcmkBUG_ON(x, func, line) \
+#define gcmkBUG_ON(x) \
do { \
- if (unlikely(x)) \
+ if (unlikely(!!(x))) \
{ \
- int i = 0; \
- while (1) \
- { \
- static int delay = 10 * 1000; \
- gcmkPRINT("[galcore]: BUG ON @ %s(%d) (%d)", func, line, i++); \
- dump_stack(); \
- gckOS_Delay(gcvNULL, delay); \
- delay *= 2; \
- } \
+ printk("[galcore]: BUG ON @ %s(%d)\n", __func__, __LINE__); \
+ dump_stack(); \
} \
} while (0)
@@ -637,7 +630,6 @@ gckOS_Construct(
{
gckOS os;
gceSTATUS status;
- gctINT i;
gcmkHEADER_ARG("Context=0x%X", Context);
@@ -678,8 +670,8 @@ gckOS_Construct(
* Initialize the signal manager.
*/
- /* Initialize mutex. */
- mutex_init(&os->signalMutex);
+ /* Initialize spinlock. */
+ spin_lock_init(&os->signalLock);
/* Initialize signal id database lock. */
spin_lock_init(&os->signalDB.lock);
@@ -707,10 +699,7 @@ gckOS_Construct(
SetPageReserved(os->paddingPage);
}
- for (i = 0; i < gcdMAX_GPU_COUNT; i++)
- {
- mutex_init(&os->registerAccessLocks[i]);
- }
+ spin_lock_init(&os->registerAccessLock);
gckOS_ImportAllocators(os);
@@ -1269,6 +1258,8 @@ gckOS_UnmapMemoryEx(
if (Logical)
{
+ gckALLOCATOR allocator = mdl->allocator;
+
mutex_lock(&mdl->mapsMutex);
mdlMap = FindMdlMap(mdl, PID);
@@ -1281,7 +1272,9 @@ gckOS_UnmapMemoryEx(
return gcvSTATUS_INVALID_ARGUMENT;
}
- _UnmapUserLogical(mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
+ BUG_ON(!allocator || !allocator->ops->UnmapUser);
+
+ allocator->ops->UnmapUser(allocator, mdl, mdl->bytes);
gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
@@ -1462,14 +1455,20 @@ gckOS_AllocateNonPagedMemory(
/* Check status. */
gcmkONERROR(status);
+ mdl->cacheable = flag & gcvALLOC_FLAG_CACHEABLE;
+
+ mdl->bytes = bytes;
mdl->numPages = numPages;
mdl->contiguous = gcvTRUE;
gcmkONERROR(allocator->ops->MapKernel(allocator, mdl, &addr));
- /* Trigger a page fault. */
- memset(addr, 0, numPages * PAGE_SIZE);
+ if (!strcmp(allocator->name, "gfp"))
+ {
+ /* Trigger a page fault. */
+ memset(addr, 0, numPages * PAGE_SIZE);
+ }
mdl->addr = addr;
@@ -1633,35 +1632,74 @@ gckOS_ReadRegisterEx(
OUT gctUINT32 * Data
)
{
- gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
+ if (in_irq())
+ {
+ uint32_t data;
- /* Verify the arguments. */
- gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ spin_lock(&Os->registerAccessLock);
- gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
+ if (unlikely(Os->clockStates[Core] == gcvFALSE))
+ {
+ spin_unlock(&Os->registerAccessLock);
- gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+ /*
+ * Read register when external clock off:
+ * 1. In shared IRQ, read register may be called and that's not our irq.
+ */
+ return gcvSTATUS_GENERIC_IO;
+ }
- if (!in_irq())
- {
- mutex_lock(&Os->registerAccessLocks[Core]);
+ data = readl(Os->device->registerBases[Core]);
+
+ if (unlikely((data & 0x3) == 0x3))
+ {
+ spin_unlock(&Os->registerAccessLock);
+
+ /*
+ * Read register when internal clock off:
+ * a. In shared IRQ, read register may be called and that's not our irq.
+ * b. In some condition, when ISR handled normal FE/PE, PM thread could
+ * trun off internal clock before ISR read register of async FE. And
+ * then IRQ handler will call read register with internal clock off.
+ * So here we just skip for such case.
+ */
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
+ spin_unlock(&Os->registerAccessLock);
}
+ else
+ {
+ unsigned long flags;
- gcmkBUG_ON(!_AllowAccess(Os, Core, Address), __FUNCTION__, __LINE__);
+ spin_lock_irqsave(&Os->registerAccessLock, flags);
- *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
+ if (unlikely(Os->clockStates[Core] == gcvFALSE))
+ {
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
- if (!in_irq())
- {
- mutex_unlock(&Os->registerAccessLocks[Core]);
- }
+ /*
+ * Read register when external clock off:
+ * 2. In non-irq context, register access should not be called,
+ * otherwise it's driver bug.
+ */
+ printk(KERN_ERR "[galcore]: %s(%d) GPU[%d] external clock off",
+ __func__, __LINE__, Core);
+ gcmkBUG_ON(1);
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
#if gcdDUMP_AHB_ACCESS
- gcmkPRINT("@[RD %d] %08x %08x", Core, Address, *Data);
+ /* Dangerous to print in interrupt context, skip. */
+ gcmkPRINT("@[RD %d] %08x %08x", Core, Address, *Data);
#endif
+ }
/* Success. */
- gcmkFOOTER_ARG("*Data=0x%08x", *Data);
return gcvSTATUS_OK;
}
@@ -1704,30 +1742,53 @@ gckOS_WriteRegisterEx(
IN gctUINT32 Data
)
{
- gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
+ if (in_irq())
+ {
+ spin_lock(&Os->registerAccessLock);
- gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
+ if (unlikely(Os->clockStates[Core] == gcvFALSE))
+ {
+ spin_unlock(&Os->registerAccessLock);
- if (!in_interrupt())
- {
- mutex_lock(&Os->registerAccessLocks[Core]);
+ printk(KERN_ERR "[galcore]: %s(%d) GPU[%d] external clock off",
+ __func__, __LINE__, Core);
+
+ /* Driver bug: register write when clock off. */
+ gcmkBUG_ON(1);
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
+ spin_unlock(&Os->registerAccessLock);
}
+ else
+ {
+ unsigned long flags;
- gcmkBUG_ON(!_AllowAccess(Os, Core, Address), __FUNCTION__, __LINE__);
+ spin_lock_irqsave(&Os->registerAccessLock, flags);
- writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
+ if (unlikely(Os->clockStates[Core] == gcvFALSE))
+ {
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
- if (!in_interrupt())
- {
- mutex_unlock(&Os->registerAccessLocks[Core]);
- }
+ printk(KERN_ERR "[galcore]: %s(%d) GPU[%d] external clock off",
+ __func__, __LINE__, Core);
+
+ /* Driver bug: register write when clock off. */
+ gcmkBUG_ON(1);
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
#if gcdDUMP_AHB_ACCESS
- gcmkPRINT("@[WR %d] %08x %08x", Core, Address, Data);
+ /* Dangerous to print in interrupt context, skip. */
+ gcmkPRINT("@[WR %d] %08x %08x", Core, Address, Data);
#endif
+ }
/* Success. */
- gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
@@ -3496,7 +3557,7 @@ gckOS_MapPagesEx(
{
platform->ops->getPolicyID(platform, Type, &policyID, &axiConfig);
- gcmkBUG_ON(policyID > 0x1F, __FUNCTION__, __LINE__);
+ gcmkBUG_ON(policyID > 0x1F);
/* ID[3:0] is used in STLB. */
policyID &= 0xF;
@@ -3519,7 +3580,7 @@ gckOS_MapPagesEx(
if (policyID)
{
/* AxUSER must not used for address currently. */
- gcmkBUG_ON((phys >> 32) & 0xF, __FUNCTION__, __LINE__);
+ gcmkBUG_ON((phys >> 32) & 0xF);
/* Merge policyID to AxUSER[7:4].*/
phys |= ((gctPHYS_ADDR_T)policyID << 36);
@@ -5355,16 +5416,32 @@ gckOS_SetGPUPower(
if (clockChange)
{
- mutex_lock(&Os->registerAccessLocks[Core]);
+ unsigned long flags;
+
+ if (!Clock)
+ {
+ spin_lock_irqsave(&Os->registerAccessLock, flags);
+
+ /* Record clock off, ahead. */
+ Os->clockStates[Core] = gcvFALSE;
+
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+ }
if (platform && platform->ops->setClock)
{
gcmkVERIFY_OK(platform->ops->setClock(platform, Core, Clock));
}
- Os->clockStates[Core] = Clock;
+ if (Clock)
+ {
+ spin_lock_irqsave(&Os->registerAccessLock, flags);
+
+ /* Record clock on, behind. */
+ Os->clockStates[Core] = gcvTRUE;
- mutex_unlock(&Os->registerAccessLocks[Core]);
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+ }
}
if (powerChange && (Power == gcvFALSE))
@@ -5686,8 +5763,10 @@ gckOS_CreateSignal(
/* Save the process ID. */
signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
+ signal->done = 0;
+ init_waitqueue_head(&signal->wait);
+ spin_lock_init(&signal->lock);
signal->manualReset = ManualReset;
- init_completion(&signal->obj);
atomic_set(&signal->ref, 1);
#if gcdANDROID_NATIVE_FENCE_SYNC
@@ -5742,6 +5821,7 @@ gckOS_DestroySignal(
gceSTATUS status;
gcsSIGNAL_PTR signal;
gctBOOL acquired = gcvFALSE;
+ unsigned long flags = 0;
gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
@@ -5749,7 +5829,11 @@ gckOS_DestroySignal(
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- mutex_lock(&Os->signalMutex);
+ 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));
@@ -5764,7 +5848,12 @@ gckOS_DestroySignal(
kfree(signal);
}
- mutex_unlock(&Os->signalMutex);
+ if(in_irq()){
+ spin_unlock(&Os->signalLock);
+ }else{
+ spin_unlock_irqrestore(&Os->signalLock, flags);
+ }
+
acquired = gcvFALSE;
/* Success. */
@@ -5775,7 +5864,12 @@ gckOS_DestroySignal(
if (acquired)
{
/* Release the mutex. */
- mutex_unlock(&Os->signalMutex);
+ if(in_irq()){
+ spin_unlock(&Os->signalLock);
+ }else{
+ spin_unlock_irqrestore(&Os->signalLock, flags);
+ }
+
}
gcmkFOOTER();
@@ -5813,14 +5907,14 @@ gckOS_Signal(
{
gceSTATUS status;
gcsSIGNAL_PTR signal;
- gctBOOL acquired = gcvFALSE;
#if gcdANDROID_NATIVE_FENCE_SYNC
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
struct sync_timeline * timeline = gcvNULL;
# else
- struct fence * fence = gcvNULL;
+ struct dma_fence * fence = gcvNULL;
# endif
#endif
+ unsigned long flags = 0;
gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
@@ -5828,17 +5922,38 @@ gckOS_Signal(
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- mutex_lock(&Os->signalMutex);
- acquired = gcvTRUE;
+ spin_lock_irqsave(&Os->signalLock, flags);
- gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
+ status = _QueryIntegerId(&Os->signalDB,
+ (gctUINT32)(gctUINTPTR_T)Signal,
+ (gctPOINTER)&signal);
+
+ if (gcmIS_ERROR(status))
+ {
+ spin_unlock_irqrestore(&Os->signalLock, flags);
+ gcmkONERROR(status);
+ }
+
+ /*
+ * Signal saved in event is not referenced. Inc reference here to avoid
+ * 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);
+ spin_lock(&signal->lock);
+
if (State)
{
- /* Set the event to a signaled state. */
- complete(&signal->obj);
+ signal->done = 1;
+
+ wake_up(&signal->wait);
#if gcdANDROID_NATIVE_FENCE_SYNC
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
@@ -5851,16 +5966,10 @@ gckOS_Signal(
}
else
{
- /* Set the event to an unsignaled state. */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
- reinit_completion(&signal->obj);
-#else
- INIT_COMPLETION(signal->obj);
-#endif
+ signal->done = 0;
}
- mutex_unlock(&Os->signalMutex);
- acquired = gcvFALSE;
+ spin_unlock(&signal->lock);
#if gcdANDROID_NATIVE_FENCE_SYNC
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
@@ -5872,23 +5981,29 @@ gckOS_Signal(
# else
if (fence)
{
- fence_signal(fence);
- fence_put(fence);
+ dma_fence_signal(fence);
+ dma_fence_put(fence);
}
# endif
#endif
+ spin_lock_irqsave(&Os->signalLock, flags);
+
+ if (atomic_dec_and_test(&signal->ref))
+ {
+ gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
+
+ /* Free the sgianl. */
+ kfree(signal);
+ }
+
+ spin_unlock_irqrestore(&Os->signalLock, flags);
+
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
- if (acquired)
- {
- /* Release the mutex. */
- mutex_unlock(&Os->signalMutex);
- }
-
gcmkFOOTER();
return status;
}
@@ -6024,7 +6139,8 @@ gckOS_WaitSignal(
)
{
gceSTATUS status = gcvSTATUS_OK;
- gcsSIGNAL_PTR signal;
+ gcsSIGNAL_PTR signal = gcvNULL;
+ int done;
gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
@@ -6036,21 +6152,28 @@ gckOS_WaitSignal(
gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
- might_sleep();
+ spin_lock(&signal->lock);
+ done = signal->done;
+ spin_unlock(&signal->lock);
-#ifdef gcdRT_KERNEL
- raw_spin_lock_irq(&signal->obj.wait.lock);
-#else
- spin_lock_irq(&signal->obj.wait.lock);
-#endif
- if (signal->obj.done)
+ /*
+ * Do not need to lock below:
+ * 1. If signal already done, return immediately.
+ * 2. If signal not done, wait_event_xxx will handle correctly even read of
+ * signal->done is not atomic.
+ *
+ * Rest signal->done do not require lock either:
+ * No other thread can query/wait auto-reseted signal, because that is
+ * logic error.
+ */
+ if (done)
{
+ status = gcvSTATUS_OK;
+
if (!signal->manualReset)
{
- signal->obj.done = 0;
+ signal->done = 0;
}
-
- status = gcvSTATUS_OK;
}
else if (Wait == 0)
{
@@ -6060,84 +6183,40 @@ gckOS_WaitSignal(
{
/* Convert wait to milliseconds. */
long timeout = (Wait == gcvINFINITE)
- ? MAX_SCHEDULE_TIMEOUT
- : msecs_to_jiffies(Wait);
+ ? MAX_SCHEDULE_TIMEOUT
+ : msecs_to_jiffies(Wait);
-#ifdef gcdRT_KERNEL
- DEFINE_SWAITER(wait);
-#else
- DECLARE_WAITQUEUE(wait, current);
- wait.flags |= WQ_FLAG_EXCLUSIVE;
-#endif
+ long ret;
-#ifdef gcdRT_KERNEL
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
- __prepare_to_swait(&signal->obj.wait, &wait);
-#else
- swait_prepare_locked(&signal->obj.wait, &wait);
-#endif
-#else
- __add_wait_queue_tail(&signal->obj.wait, &wait);
-#endif
- while (gcvTRUE)
+ if (Interruptable)
{
- if (Interruptable && signal_pending(current))
- {
- /* Interrupt received. */
- status = gcvSTATUS_INTERRUPTED;
- break;
- }
-
- __set_current_state(TASK_INTERRUPTIBLE);
-#ifdef gcdRT_KERNEL
- raw_spin_unlock_irq(&signal->obj.wait.lock);
-#else
- spin_unlock_irq(&signal->obj.wait.lock);
-#endif
- timeout = schedule_timeout(timeout);
-#ifdef gcdRT_KERNEL
- raw_spin_lock_irq(&signal->obj.wait.lock);
-#else
- spin_lock_irq(&signal->obj.wait.lock);
-#endif
- if (signal->obj.done)
- {
- if (!signal->manualReset)
- {
- signal->obj.done = 0;
- }
+ ret = wait_event_interruptible_timeout(signal->wait, signal->done, timeout);
+ }
+ else
+ {
+ ret = wait_event_timeout(signal->wait, signal->done, timeout);
+ }
- status = gcvSTATUS_OK;
- break;
- }
+ if (likely(ret > 0))
+ {
+ status = gcvSTATUS_OK;
- if (timeout == 0)
+ if (!signal->manualReset)
{
-
- status = gcvSTATUS_TIMEOUT;
- break;
+ /* Auto reset. */
+ signal->done = 0;
}
}
-
-#ifdef gcdRT_KERNEL
-#if LINUX_VERSION_CODE > KERNEL_VERSION(4,4,0)
- __finish_swait(&signal->obj.wait, &wait);
-#else
- swait_finish_locked(&signal->obj.wait, &wait);
-#endif
-#else
- __remove_wait_queue(&signal->obj.wait, &wait);
-#endif
+ else
+ {
+ status = (ret == -ERESTARTSYS) ? gcvSTATUS_INTERRUPTED
+ : gcvSTATUS_TIMEOUT;
+ }
}
-#ifdef gcdRT_KERNEL
- raw_spin_unlock_irq(&signal->obj.wait.lock);
-#else
- spin_unlock_irq(&signal->obj.wait.lock);
-#endif
OnError:
/* Return status. */
- gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
+ gcmkFOOTER_ARG("Signal=0x%lX status=%d", Signal, status);
return status;
}
@@ -6155,7 +6234,7 @@ _QuerySignal(
* spinlock for 'Os->signalDB.lock' and 'signal->obj.wait.lock'.
*/
gceSTATUS status;
- gcsSIGNAL_PTR signal;
+ gcsSIGNAL_PTR signal = gcvNULL;
status = _QueryIntegerId(&Os->signalDB,
(gctUINT32)(gctUINTPTR_T)Signal,
@@ -6163,14 +6242,9 @@ _QuerySignal(
if (gcmIS_SUCCESS(status))
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
- status = completion_done(&signal->obj)
- ? gcvSTATUS_TRUE : gcvSTATUS_FALSE;
-#else
- spin_lock(&signal->obj.wait.lock);
- status = signal->obj.done ? gcvSTATUS_TRUE : gcvSTATUS_FALSE;
- spin_unlock(&signal->obj.wait.lock);
-#endif
+ spin_lock(&signal->lock);
+ status = signal->done ? gcvSTATUS_TRUE : gcvSTATUS_FALSE;
+ spin_unlock(&signal->lock);
}
return status;
@@ -6207,13 +6281,14 @@ gckOS_MapSignal(
)
{
gceSTATUS status;
- gcsSIGNAL_PTR signal;
+ gcsSIGNAL_PTR signal = gcvNULL;
+ 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);
- mutex_lock(&Os->signalMutex);
+ spin_lock_irqsave(&Os->signalLock, flags);
gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
@@ -6225,14 +6300,14 @@ gckOS_MapSignal(
*MappedSignal = (gctSIGNAL) Signal;
- mutex_unlock(&Os->signalMutex);
+ spin_unlock_irqrestore(&Os->signalLock, flags);
/* Success. */
gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
return gcvSTATUS_OK;
OnError:
- mutex_unlock(&Os->signalMutex);
+ spin_unlock_irqrestore(&Os->signalLock, flags);
gcmkFOOTER_NO();
return status;
@@ -7271,11 +7346,11 @@ gckOS_CreateNativeFence(
OUT gctINT * FenceFD
)
{
- struct fence *fence = NULL;
+ struct dma_fence *fence = NULL;
struct sync_file *sync = NULL;
- int fd;
+ int fd = -1;
struct viv_sync_timeline *timeline;
- gcsSIGNAL_PTR signal;
+ gcsSIGNAL_PTR signal = gcvNULL;
gceSTATUS status = gcvSTATUS_OK;
/* Create fence. */
@@ -7322,7 +7397,7 @@ gckOS_CreateNativeFence(
if (fence)
{
- fence_put(fence);
+ dma_fence_put(fence);
}
if (fd > 0)
@@ -7342,13 +7417,13 @@ gckOS_WaitNativeFence(
IN gctUINT32 Timeout
)
{
- struct fence *fence;
struct viv_sync_timeline *timeline;
gceSTATUS status = gcvSTATUS_OK;
unsigned int i;
- unsigned int numFences;
- struct fence **fences;
unsigned long timeout;
+ unsigned int numFences;
+ struct dma_fence *fence;
+ struct dma_fence **fences;
timeline = (struct viv_sync_timeline *) Timeline;
@@ -7359,9 +7434,9 @@ gckOS_WaitNativeFence(
gcmONERROR(gcvSTATUS_GENERIC_IO);
}
- if (fence_is_array(fence))
+ if (dma_fence_is_array(fence))
{
- struct fence_array *array = to_fence_array(fence);
+ struct dma_fence_array *array = to_dma_fence_array(fence);
fences = array->fences;
numFences = array->num_fences;
}
@@ -7375,13 +7450,13 @@ gckOS_WaitNativeFence(
for (i = 0; i < numFences; i++)
{
- struct fence *f = fences[i];
+ struct dma_fence *f = fences[i];
if (f->context != timeline->context &&
- !fence_is_signaled(f))
+ !dma_fence_is_signaled(f))
{
signed long ret;
- ret = fence_wait_timeout(fence, 1, timeout);
+ ret = dma_fence_wait_timeout(f, 1, timeout);
if (ret == -ERESTARTSYS)
{
@@ -7401,7 +7476,7 @@ gckOS_WaitNativeFence(
}
}
- fence_put(fence);
+ dma_fence_put(fence);
return gcvSTATUS_OK;
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 c17a8f5c56d7..8e3552e4cb95 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
@@ -62,20 +62,35 @@ typedef struct _LINUX_MDL_MAP LINUX_MDL_MAP, *PLINUX_MDL_MAP;
struct _LINUX_MDL_MAP
{
gctINT pid;
- gctPOINTER vmaAddr;
+
+ /* map references. */
gctUINT32 count;
+ struct vm_area_struct * vma;
+ gctPOINTER vmaAddr;
+ gctBOOL cacheable;
+
struct list_head link;
};
struct _LINUX_MDL
{
+ gckOS os;
+
+ atomic_t refs;
+
+ /* Kernel address. */
char * addr;
+ /* Size and covered page count. */
+ size_t bytes;
gctINT numPages;
+
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_sync.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c
index c2572f949e85..45d172230011 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
@@ -237,7 +237,7 @@ struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os)
return NULL;
strncpy(timeline->name, name, sizeof(timeline->name) - 1);
- timeline->context = fence_context_alloc(1);
+ timeline->context = dma_fence_context_alloc(1);
atomic64_set(&timeline->seqno, 0);
timeline->os = Os;
@@ -249,19 +249,19 @@ void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline)
kfree(timeline);
}
-static const char * viv_fence_get_driver_name(struct fence *fence)
+static const char * viv_fence_get_driver_name(struct dma_fence *fence)
{
return "viv_gpu_sync";
}
-static const char * viv_fence_get_timeline_name(struct fence *fence)
+static const char * viv_fence_get_timeline_name(struct dma_fence *fence)
{
struct viv_fence *f = (struct viv_fence *)fence;
return f->parent->name;
}
/* Same as fence_signaled. */
-static inline bool __viv_fence_signaled(struct fence *fence)
+static inline bool __viv_fence_signaled(struct dma_fence *fence)
{
struct viv_fence *f = (struct viv_fence *)fence;
struct viv_sync_timeline *timeline = f->parent;
@@ -272,19 +272,19 @@ static inline bool __viv_fence_signaled(struct fence *fence)
return (status == gcvSTATUS_TRUE) ? true : false;
}
-static bool viv_fence_enable_signaling(struct fence *fence)
+static bool viv_fence_enable_signaling(struct dma_fence *fence)
{
/* fence is locked already. */
return !__viv_fence_signaled(fence);
}
-static bool viv_fence_signaled(struct fence *fence)
+static bool viv_fence_signaled(struct dma_fence *fence)
{
/* fence could be locked, could be not. */
return __viv_fence_signaled(fence);
}
-static void viv_fence_release(struct fence *fence)
+static void viv_fence_release(struct dma_fence *fence)
{
struct viv_fence *f = (struct viv_fence *)fence;
struct viv_sync_timeline *timeline = f->parent;
@@ -295,22 +295,22 @@ static void viv_fence_release(struct fence *fence)
kfree(fence);
}
-static struct fence_ops viv_fence_ops =
+static struct dma_fence_ops viv_fence_ops =
{
.get_driver_name = viv_fence_get_driver_name,
.get_timeline_name = viv_fence_get_timeline_name,
.enable_signaling = viv_fence_enable_signaling,
.signaled = viv_fence_signaled,
- .wait = fence_default_wait,
+ .wait = dma_fence_default_wait,
.release = viv_fence_release,
};
-struct fence * viv_fence_create(struct viv_sync_timeline *timeline,
+struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline,
gcsSIGNAL *signal)
{
gceSTATUS status;
struct viv_fence *fence;
- struct fence *old_fence = NULL;
+ struct dma_fence *old_fence = NULL;
unsigned seqno;
fence = kzalloc(sizeof(struct viv_fence), gcdNOWARN | GFP_KERNEL);
@@ -333,47 +333,44 @@ struct fence * viv_fence_create(struct viv_sync_timeline *timeline,
seqno = (unsigned)atomic64_inc_return(&timeline->seqno);
- fence_init((struct fence *)fence, &viv_fence_ops,
+ dma_fence_init((struct dma_fence *)fence, &viv_fence_ops,
&fence->lock, timeline->context, seqno);
/*
* Reference fence in signal.
* Be aware of recursive reference!!
*/
-#ifdef gcdRT_KERNEL
- raw_spin_lock_irq(&signal->obj.wait.lock);
-#else
- spin_lock_irq(&signal->obj.wait.lock);
-#endif
+ spin_lock(&signal->lock);
if (signal->fence) {
old_fence = signal->fence;
signal->fence = NULL;
}
-#ifdef gcdRT_KERNEL
- raw_spin_unlock_irq(&signal->obj.wait.lock);
-#else
- spin_unlock_irq(&signal->obj.wait.lock);
-#endif
+ if (!signal->done) {
+ signal->fence = (struct dma_fence*)fence;
- if (!completion_done(&signal->obj)) {
- signal->fence = (struct fence*)fence;
- fence_get((struct fence*)fence);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,68)
+ dma_fence_get((struct dma_fence*)fence);
+#endif
}
+ spin_unlock(&signal->lock);
+
if (old_fence)
- fence_put(old_fence);
+ dma_fence_put(old_fence);
if (!signal->fence) {
/* Fence already signaled. */
gckOS_DestroySignal(timeline->os, fence->signal);
fence->signal = NULL;
- fence_signal_locked((struct fence*)fence);
+ dma_fence_signal_locked((struct dma_fence*)fence);
+ dma_fence_put((struct dma_fence*)fence);
+ fence = NULL;
}
- return (struct fence*)fence;
+ return (struct dma_fence*)fence;
}
#endif /* v4.9.0 */
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 72c6423f7306..b1ca95a6ddd1 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
@@ -98,11 +98,16 @@ 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>
-#include <linux/fence.h>
-#include <linux/fence-array.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)
+# include <linux/fence.h>
+# include <linux/fence-array.h>
+#else
+# include <linux/dma-fence.h>
+# include <linux/dma-fence-array.h>
+#endif
#include <gc_hal.h>
#include <gc_hal_base.h>
@@ -125,7 +130,7 @@ struct viv_sync_timeline
struct viv_fence
{
/* must be the first. */
- struct fence base;
+ struct dma_fence base;
spinlock_t lock;
struct viv_sync_timeline *parent;
@@ -138,7 +143,7 @@ struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os);
void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline);
-struct fence * viv_fence_create(struct viv_sync_timeline *timeline,
+struct dma_fence * viv_fence_create(struct viv_sync_timeline *timeline,
gcsSIGNAL *signal);
#endif /* v4.9.0 */
--
2.28.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment