From 56bb615a4a1035122924f9e652c200fc113e2466 Mon Sep 17 00:00:00 2001
From: Valentin Raevsky <valentin@compulab.co.il>
Date: Thu, 8 Dec 2016 14:32:16 +0200
Subject: GPU: VIV: Use the imx-gpu-viv 5.0.11.p8.6

Make use of the kernel-module-imx-gpu-viv code 5.0.11.p8.6

Signed-off-by: Valentin Raevsky <valentin@compulab.co.il>
---
 .../hal/kernel/arch/gc_hal_kernel_hardware.c       | 48 +++++++++++-
 .../hal/kernel/arch/gc_hal_kernel_hardware.h       |  1 +
 drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c     | 12 ++-
 drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h     |  2 +
 .../mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c | 22 +++++-
 .../gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c  | 20 ++++-
 drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c  | 11 ++-
 drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c  | 34 ++++----
 .../hal/kernel/gc_hal_kernel_video_memory.c        | 31 ++++++++
 drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h   | 12 +++
 .../default/gc_hal_kernel_allocator_dmabuf.c       |  5 ++
 .../freescale/gc_hal_kernel_allocator_cma.c        |  5 ++
 .../hal/os/linux/kernel/gc_hal_kernel_allocator.c  |  4 +
 .../hal/os/linux/kernel/gc_hal_kernel_device.c     |  2 +-
 .../gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c | 90 +++++++++++++++++++++-
 .../freescale/gc_hal_kernel_platform_imx6q14.c     | 25 ++++--
 .../gc_hal_kernel_platform_imx6q14.config          |  2 +-
 17 files changed, 282 insertions(+), 44 deletions(-)

diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
index 7ced643..728006e 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
@@ -5394,6 +5394,9 @@ gckHARDWARE_SetPowerManagementState(
         /* Force the command queue to reload the next context. */
         command->currContext = gcvNULL;
 
+        /* Trigger a possible dummy draw. */
+        command->dummyDraw = gcvTRUE;
+
         /* Need to config mmu after command start. */
         configMmu = gcvTRUE;
     }
@@ -7354,6 +7357,15 @@ gckHARDWARE_IsFeatureAvailable(
         }
         break;
 
+    /* Only available for v60.*/
+    case gcvFEATURE_USC_DEFER_FILL_FIX:
+        available = gcvFALSE;
+        break;
+
+    case gcvFEATURE_USC:
+        available = gcvFALSE;
+        break;
+
     default:
         gcmkFATAL("Invalid feature has been requested.");
         available = gcvFALSE;
@@ -8472,10 +8484,11 @@ gckHARDWARE_DummyDraw(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
     IN gctUINT32 Address,
+    IN gceDUMMY_DRAW_TYPE DummyDrawType,
     IN OUT gctUINT32 * Bytes
     )
 {
-    gctUINT32 dummyDraw[] = {
+    gctUINT32 dummyDraw_gc400[] = {
 
         ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
         | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0193) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
@@ -8597,14 +8610,41 @@ gckHARDWARE_DummyDraw(
         ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:0) - (0 ? 23:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:0) - (0 ? 23:0) + 1))))))) << (0 ? 23:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:0) - (0 ? 23:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:0) - (0 ? 23:0) + 1))))))) << (0 ? 23:0))),
         };
 
-    dummyDraw[1] = Address;
+    gctUINT32 dummyDraw_v60[] = {
+
+        /* disbale first.*/
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))),
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+
+    };
+
+    gctUINT32 bytes = 0;
+    gctUINT32_PTR dummyDraw = gcvNULL;
+
+
+    switch(DummyDrawType)
+    {
+    case gcvDUMMY_DRAW_GC400:
+        dummyDraw = dummyDraw_gc400;
+        bytes = gcmSIZEOF(dummyDraw_gc400);
+        *(dummyDraw + 1) = Address;
+        break;
+    case gcvDUMMY_DRAW_V60:
+        dummyDraw = dummyDraw_v60;
+        bytes = gcmSIZEOF(dummyDraw_v60);
+        break;
+    default:
+        /* other chip no need dummy draw.*/
+        gcmkASSERT(0);
+        break;
+    };
 
     if (Logical != gcvNULL)
     {
-        gckOS_MemCopy(Logical, dummyDraw, gcmSIZEOF(dummyDraw));
+        gckOS_MemCopy(Logical, dummyDraw, bytes);
     }
 
-    *Bytes = gcmSIZEOF(dummyDraw);
+    *Bytes = bytes;
 
     return gcvSTATUS_OK;
 }
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
index 1c8b1ba..317cb8e 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
@@ -212,6 +212,7 @@ gckHARDWARE_DummyDraw(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
     IN gctUINT32 Address,
+    IN gceDUMMY_DRAW_TYPE DummyDrawType,
     IN OUT gctUINT32 * Bytes
     );
 
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
index 6258f1f..e4d61b5 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
@@ -70,7 +70,7 @@ const char * _VERSION = "\n\0$VERSION$"
                         gcmTXT2STR(gcvVERSION_MAJOR) "."
                         gcmTXT2STR(gcvVERSION_MINOR) "."
                         gcmTXT2STR(gcvVERSION_PATCH) ":"
-                        gcmTXT2STR(gcvVERSION_BUILD) "$\n";
+                        gcmTXT2STR(gcvVERSION_BUILD) "+fslc$\n";
 
 /******************************************************************************\
 ******************************* gckKERNEL API Code ******************************
@@ -285,7 +285,7 @@ _DumpDriverConfigure(
     gcmkPRINT_N(0, "***   GPU DRV CONFIG   ***\n");
     gcmkPRINT_N(0, "**************************\n");
 
-    gcmkPRINT("Galcore version %d.%d.%d.%d\n",
+    gcmkPRINT("Galcore version %d.%d.%d.%d+fslc\n",
               gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
 
     gckOS_DumpParam();
@@ -2503,7 +2503,7 @@ gckKERNEL_Dispatch(
         Interface->u.Version.build = gcvVERSION_BUILD;
 #if gcmIS_DEBUG(gcdDEBUG_TRACE)
         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
-                       "KERNEL version %d.%d.%d build %u",
+                       "KERNEL version %d.%d.%d build %u (fslc)",
                        gcvVERSION_MAJOR, gcvVERSION_MINOR,
                        gcvVERSION_PATCH, gcvVERSION_BUILD);
 #endif
@@ -2688,6 +2688,12 @@ gckKERNEL_Dispatch(
                                               syncPoint));
                 break;
 
+            case gcvSYNC_POINT_SIGNAL:
+                syncPoint = gcmUINT64_TO_PTR(Interface->u.SyncPoint.syncPoint);
+
+                gcmkONERROR(gckOS_SignalSyncPoint(Kernel->os, syncPoint));
+                break;
+
             default:
                 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
                 break;
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
index 1b4f661..0700ee0 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
@@ -750,6 +750,8 @@ struct _gckCOMMAND
     struct _gckENTRYQUEUE       queue;
 
     gckFENCE                    fence;
+
+    gctBOOL                     dummyDraw;
 };
 
 typedef struct _gcsEVENT *      gcsEVENT_PTR;
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
index b43143b..7aaedd0 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
@@ -463,7 +463,18 @@ _DummyDraw(
 
     gctUINT32 dummyDrawBytes;
 
-    gckHARDWARE_DummyDraw(hardware, gcvNULL, Command->queues[0].address, &dummyDrawBytes);
+    gceDUMMY_DRAW_TYPE dummyDrawType = gcvDUMMY_DRAW_INVALID;
+
+    if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_FE_NEED_DUMMYDRAW))
+    {
+        dummyDrawType = gcvDUMMY_DRAW_GC400;
+    }
+
+    /* 5.0.11 not support v60.*/
+
+    if (dummyDrawType != gcvDUMMY_DRAW_INVALID)
+    {
+        gckHARDWARE_DummyDraw(hardware, gcvNULL, Command->queues[0].address, dummyDrawType, &dummyDrawBytes);
 
     /* Reserve space. */
     gcmkONERROR(gckCOMMAND_Reserve(
@@ -473,9 +484,10 @@ _DummyDraw(
         &bufferSize
         ));
 
-    gckHARDWARE_DummyDraw(hardware, pointer, Command->queues[0].address, &dummyDrawBytes);
+        gckHARDWARE_DummyDraw(hardware, pointer, Command->queues[0].address, dummyDrawType, &dummyDrawBytes);
 
     gcmkONERROR(gckCOMMAND_Execute(Command, dummyDrawBytes));
+    }
 
     return gcvSTATUS_OK;
 OnError:
@@ -710,6 +722,8 @@ gckCOMMAND_Construct(
     command->queue.rear = 0;
     command->queue.count = 0;
 
+    command->dummyDraw = gcvTRUE;
+
     /* Return pointer to the gckCOMMAND object. */
     *Command = command;
 
@@ -1516,8 +1530,10 @@ gckCOMMAND_Commit(
 
     gcmkONERROR(_FlushMMU(Command));
 
-    if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_FE_NEED_DUMMYDRAW) && Command->currContext == gcvNULL)
+    if (Command->dummyDraw == gcvTRUE &&
+        Context != gcvNULL)
     {
+        Command->dummyDraw = gcvFALSE;
         gcmkONERROR(_DummyDraw(Command));
     }
 
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
index ed209a3..7042ef4 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
@@ -1609,15 +1609,27 @@ _TaskSignal(
 
         /* Map the signal into kernel space. */
 #ifdef __QNXNTO__
-        gcmkERR_BREAK(gckOS_UserSignal(
+        status = gckOS_UserSignal(
             Command->os, task->signal, task->rcvid, task->coid
-            ));
+            );
 #else
-        gcmkERR_BREAK(gckOS_UserSignal(
+        status = gckOS_UserSignal(
             Command->os, task->signal, task->process
-            ));
+            );
 #endif /* __QNXNTO__ */
 
+        if (gcmIS_ERROR(status))
+        {
+            if (status == gcvSTATUS_NOT_FOUND)
+            {
+                status = gcvSTATUS_OK;
+            }
+            else
+            {
+                break;
+            }
+        }
+
         /* Update the reference counter. */
         TaskHeader->container->referenceCount -= 1;
 
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
index 1c3eaa6..29144a2 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
@@ -94,6 +94,7 @@ gckKERNEL_NewDatabase(
     gctBOOL acquired = gcvFALSE;
     gctSIZE_T slot;
     gcsDATABASE_PTR existingDatabase;
+    gctPOINTER pointer = gcvNULL;
 
     gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
 
@@ -124,8 +125,6 @@ gckKERNEL_NewDatabase(
     }
     else
     {
-        gctPOINTER pointer = gcvNULL;
-
         /* Allocate a new database from the heap. */
         gcmkONERROR(gckOS_Allocate(Kernel->os,
                                    gcmSIZEOF(gcsDATABASE),
@@ -156,6 +155,11 @@ gckKERNEL_NewDatabase(
     return gcvSTATUS_OK;
 
 OnError:
+    if (pointer)
+    {
+        gcmkVERIFY_OK(gckOS_Free(Kernel->os,pointer));
+    }
+
     if (acquired)
     {
         /* Release the database mutex. */
@@ -1485,6 +1489,9 @@ gckKERNEL_DestroyProcessDB(
             break;
 
         case gcvDB_MAP_USER_MEMORY:
+
+            gcmkERR_BREAK(gckCOMMAND_Stall(Kernel->command, gcvFALSE));
+
             /* TODO: Unmap user memory. */
             status = gckOS_UnmapUserMemory(Kernel->os,
                                            Kernel->core,
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
index b78fb65..1443fcc 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
@@ -481,29 +481,29 @@ gceSTATUS gckVGKERNEL_Dispatch(
         break;
 
     case gcvHAL_FREE_NON_PAGED_MEMORY:
-        physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
+        physical = gcmNAME_TO_PTR(kernelInterface->u.FreeNonPagedMemory.physical);
 
         /* Unmap user logical out of physical memory first. */
         gcmkERR_BREAK(gckOS_UnmapUserLogical(
             Kernel->os,
             physical,
-            (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
-            gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
+            (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes,
+            gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical)
             ));
 
         /* Free non-paged memory. */
         gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
             Kernel->os,
-            (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
+            (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes,
             physical,
-            gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
+            gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical)
             ));
 
-        gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
+        gcmRELEASE_NAME(kernelInterface->u.FreeNonPagedMemory.physical);
         break;
 
     case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
-        bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
+        bytes = (gctSIZE_T) kernelInterface->u.AllocateContiguousMemory.bytes;
         /* Allocate contiguous memory. */
         gcmkERR_BREAK(gckOS_AllocateContiguous(
             Kernel->os,
@@ -513,30 +513,30 @@ gceSTATUS gckVGKERNEL_Dispatch(
             &logical
             ));
 
-        kernelInterface->u.AllocateNonPagedMemory.bytes    = bytes;
-        kernelInterface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
-        kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
+        kernelInterface->u.AllocateContiguousMemory.bytes    = bytes;
+        kernelInterface->u.AllocateContiguousMemory.logical  = gcmPTR_TO_UINT64(logical);
+        kernelInterface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical);
         break;
 
     case gcvHAL_FREE_CONTIGUOUS_MEMORY:
-        physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
+        physical = gcmNAME_TO_PTR(kernelInterface->u.FreeContiguousMemory.physical);
         /* Unmap user logical out of physical memory first. */
         gcmkERR_BREAK(gckOS_UnmapUserLogical(
             Kernel->os,
             physical,
-            (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
-            gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
+            (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes,
+            gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical)
             ));
 
         /* Free contiguous memory. */
         gcmkERR_BREAK(gckOS_FreeContiguous(
             Kernel->os,
             physical,
-            gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical),
-            (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes
+            gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical),
+            (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes
             ));
 
-        gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
+        gcmRELEASE_NAME(kernelInterface->u.FreeContiguousMemory.physical);
         break;
 
     case gcvHAL_ALLOCATE_VIDEO_MEMORY:
@@ -576,6 +576,8 @@ gceSTATUS gckVGKERNEL_Dispatch(
             gckVIDMEM_HANDLE_Lookup(Kernel, processID,
                                     (gctUINT32)kernelInterface->u.ReleaseVideoMemory.node, &nodeObject));
 
+        gckVIDMEM_HANDLE_Dereference(Kernel, processID,(gctUINT32)Interface->u.ReleaseVideoMemory.node);
+
         gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
     }
 
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
index b6694c7..1b0d542 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
@@ -55,6 +55,14 @@
 
 #include "gc_hal_kernel_precomp.h"
 
+#if defined(__QNXNTO__)
+#include <stdlib.h>
+#include <sys/slogcodes.h>
+#include <time.h>
+
+extern unsigned int slogUsageInterval;
+#endif
+
 #define _GC_OBJ_ZONE    gcvZONE_VIDMEM
 
 /******************************************************************************\
@@ -896,7 +904,29 @@ gckVIDMEM_AllocateLinear(
     gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
 
     acquired = gcvTRUE;
+#if defined(__QNXNTO__)
+    if (slogUsageInterval > 0) {
+        static gctSIZE_T lowwaterFPC = ~0;
+        static time_t last_slog_time;
+        int do_slog_now = 0;
+        time_t this_slog_time = time(NULL);
+
+        if (Memory->freeBytes < lowwaterFPC) {
+            do_slog_now = 1;
+            lowwaterFPC = Memory->freeBytes;
+        }
 
+        if (abs(this_slog_time - last_slog_time) > slogUsageInterval) {
+            do_slog_now = 1;
+        }
+
+        if (do_slog_now) {
+            last_slog_time = this_slog_time;
+            slogf(_SLOGC_GRAPHICS_GL, _SLOG_INFO, "%s: Memory->freeBytes = %u, lowest Memory->freeBytes = %u",
+                    __FUNCTION__, (unsigned) Memory->freeBytes, (unsigned) lowwaterFPC);
+        }
+    }
+#endif
     if (Bytes > Memory->freeBytes)
     {
         /* Not enough memory. */
@@ -2611,6 +2641,7 @@ gckVIDMEM_NODE_Dereference(
 #endif
         gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Node->mutex));
         gcmkOS_SAFE_FREE(Kernel->os, Node);
+        Node = NULL;
     }
 
     gcmkFOOTER_NO();
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
index 85700c5..b53f738 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
@@ -326,12 +326,24 @@ typedef enum _gceFEATURE
 
     gcvFEATURE_PE_ENHANCEMENTS2,
     gcvFEATURE_FE_NEED_DUMMYDRAW,
+    gcvFEATURE_USC_DEFER_FILL_FIX,
+    gcvFEATURE_USC,
 
     /* Insert features above this comment only. */
     gcvFEATURE_COUNT                /* Not a feature. */
 }
 gceFEATURE;
 
+/* dummy draw type.*/
+typedef enum _gceDUMMY_DRAW_TYPE
+{
+    gcvDUMMY_DRAW_INVALID = 0,
+    gcvDUMMY_DRAW_GC400,
+    gcvDUMMY_DRAW_V60,
+}
+gceDUMMY_DRAW_TYPE;
+
+
 /* Chip SWWA. */
 typedef enum _gceSWWA
 {
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 43203f7..cea2e8b 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
@@ -164,6 +164,11 @@ _DmabufAttach(
     return gcvSTATUS_OK;
 
 OnError:
+    if(pagearray)
+    {
+        gcmkVERIFY_OK(gckOS_Free(os, (gctPOINTER)pagearray));
+    }
+
     gcmkFOOTER();
     return status;
 }
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 a0d7840..7d759ff 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
@@ -441,6 +441,11 @@ _CMAFSLAlloctorInit(
     return gcvSTATUS_OK;
 
 OnError:
+    if(allocator)
+    {
+        gcmkVERIFY_OK(gckOS_Free(Os, (gctPOINTER)allocator));
+    }
+
     return status;
 }
 
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
index 93d6fa8..55de406 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
@@ -799,6 +799,10 @@ _DefaultAlloctorInit(
     return gcvSTATUS_OK;
 
 OnError:
+    if(allocator)
+    {
+        gcmkVERIFY_OK(gckOS_Free(Os, (gctPOINTER)allocator));
+    }
     return status;
 }
 
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 92e7ebc..2f2fa2b 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
@@ -382,7 +382,7 @@ gc_version_show(struct seq_file *m, void *data)
     gcsPLATFORM * platform = device->platform;
     gctCONST_STRING name;
 
-    seq_printf(m, "%s built at %s\n",  gcvVERSION_STRING, HOST);
+    seq_printf(m, "%s+fslc built at %s\n",  gcvVERSION_STRING, HOST);
 
     if (platform->ops->name)
     {
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 c3f9170..886acff 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
@@ -6886,6 +6886,9 @@ gckOS_QueryProfileTickRate(
     OUT gctUINT64_PTR TickRate
     )
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0)
+    *TickRate = hrtimer_resolution;
+#else
     struct timespec res;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
@@ -6896,6 +6899,7 @@ gckOS_QueryProfileTickRate(
 #endif
 
     *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
+#endif
 
     return gcvSTATUS_OK;
 }
@@ -7382,7 +7386,11 @@ gckOS_WaitSignal(
 
     might_sleep();
 
+#ifdef CONFIG_PREEMPT_RT_BASE
+    raw_spin_lock_irq(&signal->obj.wait.lock);
+#else
     spin_lock_irq(&signal->obj.wait.lock);
+#endif
 
     if (signal->obj.done)
     {
@@ -7404,9 +7412,14 @@ gckOS_WaitSignal(
             ? MAX_SCHEDULE_TIMEOUT
             : Wait * HZ / 1000;
 
+#ifdef CONFIG_PREEMPT_RT_BASE
+        DEFINE_SWAITER(wait);
+        swait_prepare_locked(&signal->obj.wait, &wait);
+#else
         DECLARE_WAITQUEUE(wait, current);
         wait.flags |= WQ_FLAG_EXCLUSIVE;
         __add_wait_queue_tail(&signal->obj.wait, &wait);
+#endif
 
         while (gcvTRUE)
         {
@@ -7418,9 +7431,15 @@ gckOS_WaitSignal(
             }
 
             __set_current_state(TASK_INTERRUPTIBLE);
+#ifdef CONFIG_PREEMPT_RT_BASE
+            raw_spin_unlock_irq(&signal->obj.wait.lock);
+            timeout = schedule_timeout(timeout);
+            raw_spin_lock_irq(&signal->obj.wait.lock);
+#else
             spin_unlock_irq(&signal->obj.wait.lock);
             timeout = schedule_timeout(timeout);
             spin_lock_irq(&signal->obj.wait.lock);
+#endif
 
             if (signal->obj.done)
             {
@@ -7441,10 +7460,18 @@ gckOS_WaitSignal(
             }
         }
 
+#ifdef CONFIG_PREEMPT_RT_BASE
+        swait_finish_locked(&signal->obj.wait, &wait);
+#else
         __remove_wait_queue(&signal->obj.wait, &wait);
+#endif
     }
 
+#ifdef CONFIG_PREEMPT_RT_BASE
+    raw_spin_unlock_irq(&signal->obj.wait.lock);
+#else
     spin_unlock_irq(&signal->obj.wait.lock);
+#endif
 
 OnError:
     /* Return status. */
@@ -8556,6 +8583,16 @@ OnError:
     return status;
 }
 
+static void
+_NativeFenceSignaled(
+    struct sync_fence *fence,
+    struct sync_fence_waiter *waiter
+    )
+{
+    kfree(waiter);
+    sync_fence_put(fence);
+}
+
 gceSTATUS
 gckOS_WaitNativeFence(
     IN gckOS Os,
@@ -8566,7 +8603,7 @@ gckOS_WaitNativeFence(
 {
     struct sync_timeline * timeline;
     struct sync_fence * fence;
-    gctBOOL wait = gcvFALSE;
+    gctBOOL wait;
     gceSTATUS status = gcvSTATUS_OK;
 
     gcmkHEADER_ARG("Os=0x%X Timeline=0x%X FenceFD=%d Timeout=%u",
@@ -8583,6 +8620,17 @@ gckOS_WaitNativeFence(
         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
     }
 
+    if (sync_fence_wait(fence, 0) == 0)
+    {
+        /* Already signaled. */
+        sync_fence_put(fence);
+
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    wait = gcvFALSE;
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
     {
         int i;
@@ -8624,6 +8672,9 @@ gckOS_WaitNativeFence(
         long timeout = (Timeout == gcvINFINITE) ? - 1 : (long) Timeout;
         err = sync_fence_wait(fence, timeout);
 
+        /* Put the fence. */
+        sync_fence_put(fence);
+
         switch (err)
         {
         case 0:
@@ -8633,11 +8684,44 @@ gckOS_WaitNativeFence(
             break;
         default:
             gcmkONERROR(gcvSTATUS_GENERIC_IO);
+            break;
         }
     }
+    else
+    {
+        int err;
+        struct sync_fence_waiter *waiter;
+        waiter = (struct sync_fence_waiter *)kmalloc(
+                sizeof (struct sync_fence_waiter), gcdNOWARN | GFP_KERNEL);
 
-    /* Put the fence. */
-    sync_fence_put(fence);
+        if (!waiter)
+        {
+            sync_fence_put(fence);
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+
+        /* Schedule a waiter callback. */
+        sync_fence_waiter_init(waiter, _NativeFenceSignaled);
+        err = sync_fence_wait_async(fence, waiter);
+
+        switch (err)
+        {
+        case 0:
+            /* Put fence in callback function. */
+            break;
+        case 1:
+            /* already signaled. */
+            sync_fence_put(fence);
+            break;
+        default:
+            sync_fence_put(fence);
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+            break;
+        }
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 
 OnError:
     gcmkFOOTER();
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c
index e436ada..dc7c976 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c
@@ -119,6 +119,7 @@ struct platform_device *pdevice;
 #    include <linux/mm.h>
 #    include <linux/oom.h>
 #    include <linux/sched.h>
+#    include <linux/profile.h>
 
 struct task_struct *lowmem_deathpending;
 
@@ -137,7 +138,7 @@ task_notify_func(struct notifier_block *self, unsigned long val, void *data)
 	if (task == lowmem_deathpending)
 		lowmem_deathpending = NULL;
 
-	return NOTIFY_OK;
+	return NOTIFY_DONE;
 }
 
 extern struct task_struct *lowmem_deathpending;
@@ -475,8 +476,10 @@ gckPLATFORM_AdjustParam(
 
     Args->gpu3DMinClock = initgpu3DMinClock;
 
-  if(Args->physSize == 0)
-    Args->physSize = 0x80000000;
+    if(Args->physSize == 0)
+    {
+        Args->physSize = 0x80000000;
+    }
 
     return gcvSTATUS_OK;
 }
@@ -489,7 +492,11 @@ _AllocPriv(
     Platform->priv = &imxPriv;
 
 #ifdef CONFIG_GPU_LOW_MEMORY_KILLER
-    task_free_register(&task_nb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+     task_free_register(&task_nb);
+#else
+    task_handoff_register(&task_nb);
+#endif
 #endif
 
     return gcvSTATUS_OK;
@@ -501,7 +508,11 @@ _FreePriv(
     )
 {
 #ifdef CONFIG_GPU_LOW_MEMORY_KILLER
-    task_free_unregister(&task_nb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+     task_free_unregister(&task_nb);
+#else
+    task_handoff_unregister(&task_nb);
+#endif
 #endif
 
     return gcvSTATUS_OK;
@@ -628,7 +639,7 @@ _GetPower(
     }
 
 
-#if gcdENABLE_FSCALE_VAL_ADJUST
+#if gcdENABLE_FSCALE_VAL_ADJUST && defined(CONFIG_DEVICE_THERMAL)
     pdevice = Platform->device;
     REG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
     {
@@ -692,7 +703,7 @@ _PutPower(
     }
 #endif
 
-#if gcdENABLE_FSCALE_VAL_ADJUST
+#if gcdENABLE_FSCALE_VAL_ADJUST && defined(CONFIG_DEVICE_THERMAL)
     UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
 
     driver_remove_file(pdevice->dev.driver, &driver_attr_gpu3DMinClock);
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config
index 0b2cb43..1a520e9 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config
@@ -3,7 +3,7 @@ EXTRA_CFLAGS += -DgcdFSL_CONTIGUOUS_SIZE=134217728
 
 ifneq ($(CONFIG_ANDROID),)
 # build for android
-EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=3
+EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=2
 
 ifeq ($(CONFIG_SYNC),)
 $(warn CONFIG_SYNC is not set in kernel config)
-- 
1.9.1

