MA-9483 [#imx-495] Refine android native fence code to match 4.9 kernel
authorRichard Liu <xuegang.liu@nxp.com>
Thu, 20 Apr 2017 09:28:22 +0000 (17:28 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:22:03 +0000 (15:22 -0500)
Android native fence implement changed in 4.9 kernel, sync.* files
have been removed from drivers/staging/android in 4.9 kernel, do the
matched change to use sync_file/fence in GPU driver.

Date: Apr 20, 2017
Signed-off-by: Richard Liu <xuegang.liu@nxp.com>
drivers/mxc/gpu-viv/Kbuild
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_sync.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6.config

index 9f66431..06e0b25 100644 (file)
@@ -133,6 +133,10 @@ ifneq ($(CONFIG_SYNC),)
 EXTRA_CFLAGS += -Idrivers/staging/android
 
 OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
+else
+    ifneq ($(CONFIG_SYNC_FILE),)
+    OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
+    endif
 endif
 
 ifeq ($(SECURITY), 1)
index aae36e9..92fb2e5 100644 (file)
@@ -214,14 +214,6 @@ struct _gckOS
     /* signal id database. */
     gcsINTEGER_DB               signalDB;
 
-#if gcdANDROID_NATIVE_FENCE_SYNC
-    /* Lock. */
-    gctPOINTER                  syncPointMutex;
-
-    /* sync point id database. */
-    gcsINTEGER_DB               syncPointDB;
-#endif
-
     gcsUSER_MAPPING_PTR         userMap;
 
     /* workqueue for os timer. */
@@ -271,8 +263,12 @@ typedef struct _gcsSIGNAL
     gctUINT32 id;
 
 #if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
     /* Parent timeline. */
     struct sync_timeline * timeline;
+#else
+    struct fence *fence;
+#endif
 #endif
 }
 gcsSIGNAL;
index 344b17f..e5c13d5 100644 (file)
@@ -677,21 +677,6 @@ gckOS_Construct(
     /* Initialize signal id database. */
     idr_init(&os->signalDB.idr);
 
-#if gcdANDROID_NATIVE_FENCE_SYNC
-    /*
-     * Initialize the sync point manager.
-     */
-
-    /* Initialize mutex. */
-    gcmkONERROR(gckOS_CreateMutex(os, &os->syncPointMutex));
-
-    /* Initialize sync point id database lock. */
-    spin_lock_init(&os->syncPointDB.lock);
-
-    /* Initialize sync point id database. */
-    idr_init(&os->syncPointDB.idr);
-#endif
-
     /* Create a workqueue for os timer. */
     os->workqueue = create_singlethread_workqueue("galcore workqueue");
 
@@ -744,15 +729,6 @@ gckOS_Construct(
     return gcvSTATUS_OK;
 
 OnError:
-
-#if gcdANDROID_NATIVE_FENCE_SYNC
-    if (os->syncPointMutex != gcvNULL)
-    {
-        gcmkVERIFY_OK(
-            gckOS_DeleteMutex(os, os->syncPointMutex));
-    }
-#endif
-
     if (os->workqueue != gcvNULL)
     {
         destroy_workqueue(os->workqueue);
@@ -797,15 +773,6 @@ gckOS_Destroy(
         Os->paddingPage = gcvNULL;
     }
 
-#if gcdANDROID_NATIVE_FENCE_SYNC
-    /*
-     * Destroy the sync point manager.
-     */
-
-    /* Destroy the mutex. */
-    gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->syncPointMutex));
-#endif
-
     /*
      * Destroy the signal manager.
      */
@@ -5713,7 +5680,11 @@ gckOS_CreateSignal(
     atomic_set(&signal->ref, 1);
 
 #if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
     signal->timeline = gcvNULL;
+#else
+    signal->fence = gcvNULL;
+#endif
 #endif
 
     gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
@@ -5833,7 +5804,11 @@ gckOS_Signal(
     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;
+#endif
 #endif
 
     gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
@@ -5855,7 +5830,12 @@ gckOS_Signal(
         complete(&signal->obj);
 
 #if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
         timeline = signal->timeline;
+#else
+        fence = signal->fence;
+        signal->fence = NULL;
+#endif
 #endif
     }
     else
@@ -5872,11 +5852,19 @@ gckOS_Signal(
     acquired = gcvFALSE;
 
 #if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
     /* Signal timeline. */
     if (timeline)
     {
         sync_timeline_signal(timeline);
     }
+#else
+    if (fence)
+    {
+        fence_signal(fence);
+        fence_put(fence);
+    }
+#endif
 #endif
 
     /* Success. */
@@ -6949,6 +6937,7 @@ gckOS_DetectProcessByName(
 }
 
 #if gcdANDROID_NATIVE_FENCE_SYNC
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
 gceSTATUS
 gckOS_CreateSyncTimeline(
     IN gckOS Os,
@@ -7183,6 +7172,11 @@ gckOS_WaitNativeFence(
         waiter = (struct sync_fence_waiter *)kmalloc(
                 sizeof (struct sync_fence_waiter), gcdNOWARN | GFP_KERNEL);
 
+        /*
+         * schedule a callback to put the sync_fence. Otherwise after this function
+         * is returned, the caller may free it since it's signaled. Then there's
+         * be a real signal on a free'ed sync fence.
+         */
         if (!waiter)
         {
             sync_fence_put(fence);
@@ -7216,6 +7210,195 @@ OnError:
     gcmkFOOTER();
     return status;
 }
+
+#else /* v4.9.0 */
+
+gceSTATUS
+gckOS_CreateSyncTimeline(
+    IN gckOS Os,
+    IN gceCORE Core,
+    OUT gctHANDLE * Timeline
+    )
+{
+    struct viv_sync_timeline *timeline;
+
+    char name[32];
+
+    snprintf(name, 32, "gccore-%u", (unsigned int) Core);
+    timeline = viv_sync_timeline_create(name, Os);
+
+    if (timeline == gcvNULL)
+    {
+        /* Out of memory. */
+        return gcvSTATUS_OUT_OF_MEMORY;
+    }
+
+    *Timeline = (gctHANDLE) timeline;
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_DestroySyncTimeline(
+    IN gckOS Os,
+    IN gctHANDLE Timeline
+    )
+{
+    struct viv_sync_timeline * timeline;
+
+    /* Destroy timeline. */
+    timeline = (struct viv_sync_timeline *) Timeline;
+    viv_sync_timeline_destroy(timeline);
+
+    return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_CreateNativeFence(
+    IN gckOS Os,
+    IN gctHANDLE Timeline,
+    IN gctSIGNAL Signal,
+    OUT gctINT * FenceFD
+    )
+{
+    struct fence *fence = NULL;
+    struct sync_file *sync = NULL;
+    int fd;
+    struct viv_sync_timeline *timeline;
+    gcsSIGNAL_PTR signal;
+    gceSTATUS status = gcvSTATUS_OK;
+
+    /* Create fence. */
+    timeline = (struct viv_sync_timeline *) Timeline;
+
+    gcmkONERROR(
+        _QueryIntegerId(&Os->signalDB,
+                        (gctUINT32)(gctUINTPTR_T)Signal,
+                        (gctPOINTER)&signal));
+
+    fence = viv_fence_create(timeline, signal);
+
+    if (!fence)
+    {
+        gcmONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    /* Create sync_file. */
+    sync = sync_file_create(fence);
+
+    if (!sync)
+    {
+        gcmONERROR(gcvSTATUS_OUT_OF_MEMORY);
+    }
+
+    /* Get a unused fd. */
+    fd = get_unused_fd_flags(O_CLOEXEC);
+
+    if (fd < 0)
+    {
+        gcmONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+    }
+
+    fd_install(fd, sync->file);
+
+    *FenceFD = fd;
+    return gcvSTATUS_OK;
+
+OnError:
+    if (sync)
+    {
+        fput(sync->file);
+    }
+
+    if (fence)
+    {
+        fence_put(fence);
+    }
+
+    if (fd > 0)
+    {
+        put_unused_fd(fd);
+    }
+
+    *FenceFD = -1;
+    return status;
+}
+
+gceSTATUS
+gckOS_WaitNativeFence(
+    IN gckOS Os,
+    IN gctHANDLE Timeline,
+    IN gctINT FenceFD,
+    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;
+
+    timeline = (struct viv_sync_timeline *) Timeline;
+
+    fence = sync_file_get_fence(FenceFD);
+
+    if (!fence)
+    {
+        gcmONERROR(gcvSTATUS_GENERIC_IO);
+    }
+
+    if (fence_is_array(fence))
+    {
+        struct fence_array *array = to_fence_array(fence);
+        fences = array->fences;
+        numFences = array->num_fences;
+    }
+    else
+    {
+        fences = &fence;
+        numFences = 1;
+    }
+
+    timeout = msecs_to_jiffies(Timeout);
+
+    for (i = 0; i < numFences; i++)
+    {
+        struct fence *f = fences[i];
+
+        if (f->context != timeline->context &&
+            !fence_is_signaled(f))
+        {
+            signed long ret;
+            ret = fence_wait_timeout(fence, 1, timeout);
+
+            if (ret == -ERESTARTSYS)
+            {
+                status = gcvSTATUS_INTERRUPTED;
+                break;
+            }
+            else if (ret <= 0)
+            {
+                status = gcvSTATUS_TIMEOUT;
+                break;
+            }
+            else
+            {
+                /* wait success. */
+                timeout -= ret;
+            }
+        }
+    }
+
+    fence_put(fence);
+
+    return gcvSTATUS_OK;
+
+OnError:
+    return status;
+}
+
+#endif /* v4.9.0 */
 #endif
 
 #if gcdSECURITY
index eb2884b..9750219 100644 (file)
 #include <linux/module.h>
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
+#include <linux/slab.h>
 
 #include "gc_hal_kernel_sync.h"
 #include "gc_hal_kernel_linux.h"
 
-static struct sync_pt *
-viv_sync_pt_dup(
-    struct sync_pt * sync_pt
-    )
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+
+static struct sync_pt * viv_sync_pt_dup(struct sync_pt *sync_pt)
 {
     gceSTATUS status;
     struct viv_sync_pt *pt;
     struct viv_sync_pt *src;
     struct viv_sync_timeline *obj;
 
-    src = (struct viv_sync_pt *) sync_pt;
+    src = (struct viv_sync_pt *)sync_pt;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
-    obj = (struct viv_sync_timeline *) sync_pt_parent(sync_pt);
+    obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
 #else
-    obj = (struct viv_sync_timeline *) sync_pt->parent;
+    obj = (struct viv_sync_timeline *)sync_pt->parent;
 #endif
 
     /* Create the new sync_pt. */
@@ -98,8 +98,7 @@ viv_sync_pt_dup(
                              gcvNULL /* (gctHANDLE) _GetProcessID() */,
                              &pt->signal);
 
-    if (gcmIS_ERROR(status))
-    {
+    if (gcmIS_ERROR(status)) {
         sync_pt_free((struct sync_pt *)pt);
         return NULL;
     }
@@ -107,26 +106,22 @@ viv_sync_pt_dup(
     return (struct sync_pt *)pt;
 }
 
-static int
-viv_sync_pt_has_signaled(
-    struct sync_pt * sync_pt
-    )
+static int viv_sync_pt_has_signaled(struct sync_pt *sync_pt)
 {
     gceSTATUS status;
-    struct viv_sync_pt * pt;
-    struct viv_sync_timeline * obj;
+    struct viv_sync_pt *pt;
+    struct viv_sync_timeline *obj;
 
     pt  = (struct viv_sync_pt *)sync_pt;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
-    obj = (struct viv_sync_timeline *) sync_pt_parent(sync_pt);
+    obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
 #else
     obj = (struct viv_sync_timeline *)sync_pt->parent;
 #endif
 
     status = _QuerySignal(obj->os, pt->signal);
 
-    if (gcmIS_ERROR(status))
-    {
+    if (gcmIS_ERROR(status)) {
         /* Error. */
         return -1;
     }
@@ -134,15 +129,11 @@ viv_sync_pt_has_signaled(
     return (int) status;
 }
 
-static int
-viv_sync_pt_compare(
-    struct sync_pt * a,
-    struct sync_pt * b
-    )
+static int viv_sync_pt_compare(struct sync_pt *a, struct sync_pt *b)
 {
     int ret;
-    struct viv_sync_pt * pt1 = (struct viv_sync_pt *) a;
-    struct viv_sync_pt * pt2 = (struct viv_sync_pt *) b;
+    struct viv_sync_pt *pt1 = (struct viv_sync_pt *)a;
+    struct viv_sync_pt *pt2 = (struct viv_sync_pt *)b;
 
     ret = (pt1->stamp <  pt2->stamp) ? -1
         : (pt1->stamp == pt2->stamp) ?  0
@@ -151,48 +142,37 @@ viv_sync_pt_compare(
     return ret;
 }
 
-static void
-viv_sync_pt_free(
-    struct sync_pt * sync_pt
-    )
+static void viv_sync_pt_free(struct sync_pt *sync_pt)
 {
-    struct viv_sync_pt * pt;
-    struct viv_sync_timeline * obj;
+    struct viv_sync_pt *pt;
+    struct viv_sync_timeline *obj;
 
-    pt  = (struct viv_sync_pt *) sync_pt;
+    pt  = (struct viv_sync_pt *)sync_pt;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
-    obj = (struct viv_sync_timeline *) sync_pt_parent(sync_pt);
+    obj = (struct viv_sync_timeline *)sync_pt_parent(sync_pt);
 #else
-    obj = (struct viv_sync_timeline *) sync_pt->parent;
+    obj = (struct viv_sync_timeline *)sync_pt->parent;
 #endif
 
     gckOS_DestroySignal(obj->os, pt->signal);
 }
 
-static void
-viv_timeline_value_str(
-    struct sync_timeline * timeline,
-    char * str,
-    int size
-    )
+static void viv_timeline_value_str(struct sync_timeline *timeline,
+                    char *str, int size)
 {
-    struct viv_sync_timeline * obj;
+    struct viv_sync_timeline *obj;
 
-    obj = (struct viv_sync_timeline *) timeline;
+    obj = (struct viv_sync_timeline *)timeline;
     snprintf(str, size, "stamp_%llu", obj->stamp);
 }
 
-static void
-viv_pt_value_str(
-    struct sync_pt * sync_pt,
-    char * str,
-    int size
-    )
+static void viv_pt_value_str(struct sync_pt *sync_pt, char *str, int size)
 {
-    struct viv_sync_pt * pt;
+    struct viv_sync_pt *pt;
 
-    pt = (struct viv_sync_pt *) sync_pt;
-    snprintf(str, size, "signal_%lu@stamp_%llu", (unsigned long) pt->signal, pt->stamp);
+    pt = (struct viv_sync_pt *)sync_pt;
+    snprintf(str, size, "signal_%lu@stamp_%llu",
+            (unsigned long)pt->signal, pt->stamp);
 }
 
 static struct sync_timeline_ops viv_timeline_ops =
@@ -206,11 +186,7 @@ static struct sync_timeline_ops viv_timeline_ops =
     .pt_value_str = viv_pt_value_str,
 };
 
-struct viv_sync_timeline *
-viv_sync_timeline_create(
-    const char * name,
-    gckOS os
-    )
+struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS os)
 {
     struct viv_sync_timeline * obj;
 
@@ -223,19 +199,16 @@ viv_sync_timeline_create(
     return obj;
 }
 
-struct sync_pt *
-viv_sync_pt_create(
-    struct viv_sync_timeline * obj,
-    gctSIGNAL Signal
-    )
+struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj,
+                        gctSIGNAL Signal)
 {
     gceSTATUS status;
-    struct viv_sync_pt * pt;
+    struct viv_sync_pt *pt;
 
     pt = (struct viv_sync_pt *)
         sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
 
-    pt->stamp  = obj->stamp++;
+    pt->stamp = obj->stamp++;
 
     /* Dup signal. */
     status = gckOS_MapSignal(obj->os,
@@ -243,13 +216,166 @@ viv_sync_pt_create(
                              gcvNULL /* (gctHANDLE) _GetProcessID() */,
                              &pt->signal);
 
-    if (gcmIS_ERROR(status))
-    {
+    if (gcmIS_ERROR(status)) {
         sync_pt_free((struct sync_pt *)pt);
         return NULL;
     }
 
-    return (struct sync_pt *) pt;
+    return (struct sync_pt *)pt;
+}
+
+#else /* v4.9.0 */
+
+struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os)
+{
+    struct viv_sync_timeline *timeline;
+
+    timeline = kmalloc(sizeof(struct viv_sync_timeline),
+                    gcdNOWARN | GFP_KERNEL);
+
+    if (!timeline)
+        return NULL;
+
+    strncpy(timeline->name, name, sizeof(timeline->name));
+    timeline->context = fence_context_alloc(1);
+    atomic64_set(&timeline->seqno, 0);
+    timeline->os = Os;
+
+    return timeline;
+}
+
+void viv_sync_timeline_destroy(struct viv_sync_timeline *timeline)
+{
+    kfree(timeline);
+}
+
+static const char * viv_fence_get_driver_name(struct fence *fence)
+{
+    return "viv_gpu_sync";
+}
+
+static const char * viv_fence_get_timeline_name(struct 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)
+{
+    struct viv_fence *f = (struct viv_fence *)fence;
+    struct viv_sync_timeline *timeline = f->parent;
+    gceSTATUS status;
+
+    status = _QuerySignal(timeline->os, f->signal);
+
+    return (status == gcvSTATUS_TRUE) ? true : false;
+}
+
+static bool viv_fence_enable_signaling(struct fence *fence)
+{
+    /* fence is locked already. */
+    return !__viv_fence_signaled(fence);
+}
+
+static bool viv_fence_signaled(struct fence *fence)
+{
+    /* fence could be locked, could be not. */
+    return __viv_fence_signaled(fence);
+}
+
+static void viv_fence_release(struct fence *fence)
+{
+    struct viv_fence *f = (struct viv_fence *)fence;
+    struct viv_sync_timeline *timeline = f->parent;
+
+    if (f->signal)
+        gckOS_DestroySignal(timeline->os, f->signal);
+
+    kfree(fence);
+}
+
+static struct 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,
+    .release = viv_fence_release,
+};
+
+struct fence * viv_fence_create(struct viv_sync_timeline *timeline,
+                    gcsSIGNAL *signal)
+{
+    gceSTATUS status;
+    struct viv_fence *fence;
+    struct fence *old_fence = NULL;
+    unsigned seqno;
+
+    fence = kmalloc(sizeof(struct viv_fence), gcdNOWARN | GFP_KERNEL);
+
+    if (!fence)
+        return NULL;
+
+    /* Reference signal in fence. */
+    status = gckOS_MapSignal(timeline->os, (gctSIGNAL)(uintptr_t)signal->id,
+                NULL, &fence->signal);
+
+    if (gcmIS_ERROR(status)) {
+        kfree(fence);
+        return NULL;
+    }
+
+    spin_lock_init(&fence->lock);
+
+    fence->parent = timeline;
+
+    seqno = (unsigned)atomic64_inc_return(&timeline->seqno);
+
+    fence_init((struct 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
+
+    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 (!completion_done(&signal->obj)) {
+        signal->fence = (struct fence*)fence;
+        fence_get((struct fence*)fence);
+    }
+
+    if (old_fence)
+        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);
+    }
+
+    return (struct fence*)fence;
 }
 
+#endif /* v4.9.0 */
+
 #endif
index 9f01681..72c6423 100644 (file)
@@ -58,6 +58,8 @@
 
 #include <linux/types.h>
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)
+
 /* sync.h is in drivers/staging/android/ for now. */
 #include <sync.h>
 
@@ -90,17 +92,55 @@ struct viv_sync_pt
 };
 
 /* Create viv_sync_timeline object. */
-struct viv_sync_timeline *
-viv_sync_timeline_create(
-    const char * Name,
-    gckOS Os
-    );
+struct viv_sync_timeline * viv_sync_timeline_create(const char *name, gckOS Os);
 
 /* Create viv_sync_pt object. */
-struct sync_pt *
-viv_sync_pt_create(
-    struct viv_sync_timeline * Obj,
-    gctSIGNAL Signal
-    );
+struct sync_pt * viv_sync_pt_create(struct viv_sync_timeline *obj,
+                        gctSIGNAL signal);
+
+#else /* v4.9.0 */
+
+#include <linux/sync_file.h>
+#include <linux/fence.h>
+#include <linux/fence-array.h>
+
+#include <gc_hal.h>
+#include <gc_hal_base.h>
+#include "gc_hal_kernel_linux.h"
+
+struct viv_sync_timeline
+{
+    char name[64];
+
+    /* Parent object. */
+    u64 context;
+
+    /* Timestamp when sync_pt is created. */
+    atomic64_t seqno;
+
+    /* Pointer to os struct. */
+    gckOS os;
+};
+
+struct viv_fence
+{
+    /* must be the first. */
+    struct fence base;
+    spinlock_t lock;
+
+    struct viv_sync_timeline *parent;
+
+    /* link with signal. */
+    gctSIGNAL signal;
+};
+
+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,
+                    gcsSIGNAL *signal);
+
+#endif /* v4.9.0 */
 
 #endif /* __gc_hal_kernel_sync_h_ */
index 1ae6b8c..481bc5f 100644 (file)
@@ -5,9 +5,9 @@ ifneq ($(CONFIG_ANDROID),)
 # build for android
 EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=2
 EXTRA_CFLAGS += -DgcdANDROID
-ifeq ($(CONFIG_SYNC),)
-$(warn CONFIG_SYNC is not set in kernel config)
-$(warn Android native fence sync needs CONFIG_SYNC)
+ifeq ($(CONFIG_SYNC)$(CONFIG_SYNC_FILE),)
+$(warn CONFIG_SYNC or CONFIG_SYNC_FILE is not set in kernel config)
+$(warn Android native fence sync requires CONFIG_SYNC or CONFIG_SYNC_FILE)
 endif
 endif