[COMMON] g2d: split timer as purpose
authorhyesoo.yu <hyesoo.yu@samsung.com>
Tue, 3 Apr 2018 10:25:30 +0000 (19:25 +0900)
committerJanghyuck Kim <janghyuck.kim@samsung.com>
Mon, 23 Jul 2018 05:39:34 +0000 (14:39 +0900)
One timer is used for two purposes, but it may cause
unexpected race condition between timer handler
and deletion, initialization for another purpose.

So, we seperate timers into two for each purpose.

Change-Id: I44831a4a7b663d75c5d5d4297a78e245f3b4d3ef
Signed-off-by: hyesoo.yu <hyesoo.yu@samsung.com>
drivers/gpu/exynos/g2d/g2d_drv.c
drivers/gpu/exynos/g2d/g2d_task.c
drivers/gpu/exynos/g2d/g2d_task.h

index 178458c7e5900cdef5a7a6de66af185c9200bcc2..e0d90217a6449dd095d373e00e49ef4f4a0f09d6 100644 (file)
@@ -111,7 +111,7 @@ void g2d_hw_timeout_handler(unsigned long arg)
                goto out;
        }
 
-       mod_timer(&task->timer,
+       mod_timer(&task->hw_timer,
          jiffies + msecs_to_jiffies(G2D_HW_TIMEOUT_MSEC));
 
        if (!g2d_hw_stuck_state(g2d_dev) &&
index 40792662e1eeccf2a27bd28aa14280bf9b9f50b7..c4b84976355f49ca4165578e0044221097e3dc40 100644 (file)
@@ -113,7 +113,7 @@ static void g2d_finish_task(struct g2d_device *g2d_dev,
 
        task->ktime_end = ktime_get();
 
-       del_timer(&task->timer);
+       del_timer(&task->hw_timer);
 
        g2d_stamp_task(task, G2D_STAMP_STATE_DONE,
                (int)ktime_us_delta(task->ktime_end, task->ktime_begin));
@@ -171,13 +171,9 @@ static void g2d_execute_task(struct g2d_device *g2d_dev, struct g2d_task *task)
        list_move_tail(&task->node, &g2d_dev->tasks_active);
        change_task_state_active(task);
 
-       del_timer(&task->timer);
-
-       setup_timer(&task->timer,
-                   g2d_hw_timeout_handler, (unsigned long)task);
-
-       mod_timer(&task->timer,
-                 jiffies + msecs_to_jiffies(G2D_HW_TIMEOUT_MSEC));
+       task->hw_timer.expires =
+               jiffies + msecs_to_jiffies(G2D_HW_TIMEOUT_MSEC);
+       add_timer(&task->hw_timer);
 
        /*
         * g2d_device_run() is not reentrant while g2d_schedule() is
@@ -225,7 +221,7 @@ static void g2d_schedule_task(struct g2d_task *task)
        unsigned long flags;
        int ret;
 
-       del_timer(&task->timer);
+       del_timer(&task->fence_timer);
 
        g2d_complete_commands(task);
 
@@ -286,12 +282,11 @@ void g2d_start_task(struct g2d_task *task)
 {
        reinit_completion(&task->completion);
 
-       setup_timer(&task->timer,
-                   g2d_fence_timeout_handler, (unsigned long)task);
-
-       if (atomic_read(&task->starter.refcount.refs) > 1)
-               mod_timer(&task->timer,
-                       jiffies + msecs_to_jiffies(G2D_FENCE_TIMEOUT_MSEC));
+       if (atomic_read(&task->starter.refcount.refs) > 1) {
+               task->fence_timer.expires =
+                       jiffies + msecs_to_jiffies(G2D_FENCE_TIMEOUT_MSEC);
+               add_timer(&task->fence_timer);
+       }
 
        task->ktime_begin = ktime_get();
 
@@ -434,6 +429,11 @@ static struct g2d_task *g2d_create_task(struct g2d_device *g2d_dev, int id)
        init_completion(&task->completion);
        spin_lock_init(&task->fence_timeout_lock);
 
+       setup_timer(&task->hw_timer,
+                   g2d_hw_timeout_handler, (unsigned long)task);
+       setup_timer(&task->fence_timer,
+                   g2d_fence_timeout_handler, (unsigned long)task);
+
        return task;
 
 err_map:
index fa1b7b302ad31faeb2d7ea58a80074d1ad2ba145..f6e0ef2e8ffec658781e89b51f8d8e952469befe 100644 (file)
@@ -93,7 +93,8 @@ struct g2d_task {
        unsigned long           state;
        struct sync_file        *release_fence;
        struct kref             starter;
-       struct timer_list       timer;
+       struct timer_list       fence_timer;
+       struct timer_list       hw_timer;
 
        struct g2d_layer        *source;
        struct g2d_layer        target;