[COMMON] g2d: release performance lock
authorhyesoo.yu <hyesoo.yu@samsung.com>
Fri, 18 Aug 2017 02:21:56 +0000 (11:21 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:27:36 +0000 (14:27 +0900)
If there is no further request from the user for 50ms,
performance lock is released automatically.

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

index 50bf4b2db70fce21dc950887952c0e2074194693..4bf2a1e3c98b7569bf5829e32bdf87537cb13ecb 100644 (file)
@@ -126,8 +126,9 @@ struct g2d_context {
        u32 priority;
        int authority;
 
-       struct pm_qos_request req;
+       struct delayed_work dwork;
 
+       struct pm_qos_request req;
        struct list_head qos_node;
        u64     r_bw;
        u64     w_bw;
index 5ef0fabb52096e037f29ba5655d78b93dcc00941..3921e3200d564c880eebff03c2a650ddc23ad0cd 100644 (file)
@@ -235,6 +235,14 @@ static __u32 get_hw_version(struct g2d_device *g2d_dev, __u32 *version)
        return ret;
 }
 
+static void g2d_timeout_perf_work(struct work_struct *work)
+{
+       struct g2d_context *ctx = container_of(work, struct g2d_context,
+                                             dwork.work);
+
+       g2d_put_performance(ctx);
+}
+
 static int g2d_open(struct inode *inode, struct file *filp)
 {
        struct g2d_device *g2d_dev;
@@ -260,6 +268,7 @@ static int g2d_open(struct inode *inode, struct file *filp)
        atomic_inc(&g2d_dev->prior_stats[g2d_ctx->priority]);
 
        INIT_LIST_HEAD(&g2d_ctx->qos_node);
+       INIT_DELAYED_WORK(&(g2d_ctx->dwork), g2d_timeout_perf_work);
 
        return 0;
 }
index 1d409afb893411536b67311948e4265b40e906db..cd376fdea73dd438dadc6545aacaf540945a45cd 100644 (file)
@@ -20,6 +20,8 @@
 #include "g2d_task.h"
 #include "g2d_uapi.h"
 
+#include <linux/workqueue.h>
+
 #ifdef CONFIG_PM_DEVFREQ
 static void g2d_pm_qos_update_devfreq(struct pm_qos_request *req, u32 freq)
 {
@@ -149,7 +151,7 @@ static void g2d_set_device_frequency(struct g2d_context *g2d_ctx,
                }
        }
 
-       if (!ip_clock && !g2d_still_need_perf(g2d_dev))
+       if (!ip_clock)
                g2d_pm_qos_remove_devfreq(&g2d_ctx->req);
        else if (ip_clock)
                g2d_pm_qos_update_devfreq(&g2d_ctx->req, ip_clock);
@@ -179,11 +181,6 @@ static void g2d_set_qos_frequency(struct g2d_context *g2d_ctx,
        if (list_empty(&g2d_ctx->qos_node) && !rbw && !wbw)
                return;
 
-       if (!rbw && !rbw && g2d_still_need_perf(g2d_dev))
-               return;
-
-       mutex_lock(&g2d_dev->lock_qos);
-
        if (!list_empty(&g2d_dev->qos_contexts)) {
                struct g2d_context *ctx_qos;
 
@@ -238,13 +235,12 @@ static void g2d_set_qos_frequency(struct g2d_context *g2d_ctx,
                 * bts_update_bw(BTS_BW_G2D, bw);
                 */
        }
-
-       mutex_unlock(&g2d_dev->lock_qos);
 }
 
 void g2d_set_performance(struct g2d_context *ctx,
                                struct g2d_performance_data *data)
 {
+       struct g2d_device *g2d_dev = ctx->g2d_dev;
        int i;
 
        if (data->num_frame > G2D_PERF_MAX_FRAMES)
@@ -255,8 +251,23 @@ void g2d_set_performance(struct g2d_context *ctx,
                        return;
        }
 
+       mutex_lock(&g2d_dev->lock_qos);
+
+       if (!data->num_frame) {
+               if (g2d_still_need_perf(g2d_dev)) {
+                       mutex_unlock(&g2d_dev->lock_qos);
+                       return;
+               }
+               cancel_delayed_work(&ctx->dwork);
+       } else {
+               mod_delayed_work(system_wq, &ctx->dwork,
+                       msecs_to_jiffies(50));
+       }
+
        g2d_set_qos_frequency(ctx, data);
        g2d_set_device_frequency(ctx, data);
+
+       mutex_unlock(&g2d_dev->lock_qos);
 }
 
 void g2d_put_performance(struct g2d_context *ctx)