[COMMON] g2d: release performance lock
authorhyesoo.yu <hyesoo.yu@samsung.com>
Fri, 18 Aug 2017 02:21:56 +0000 (11:21 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:22:14 +0000 (20:22 +0300)
If there is no further request from the user for 50ms,
performance lock is released automatically.

Change-Id: Id36220bbe6eecd45c716fd1c83f3e12f523c3f82
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 f2ba826e0b04e7f8fa2944d625e69773f64043be..afb69d2820ae70481efca082cab45eb72e38c9ca 100644 (file)
@@ -118,8 +118,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 f7da2d4481bfb90253af2b6b92f88230e8cd9f6e..6b03d1bd3e77442499b2941fd5e9abd76769ba45 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 d18ae4e40153bc1f82e6835405c5050cc33f0c5e..b60ed1160bf0187eb0149209e8ad2ac791c29961 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)