media: mfc: add performance measuring
authorJiho Chang <jiho04.chang@samsung.com>
Sat, 7 Oct 2017 06:19:16 +0000 (06:19 +0000)
committerSunyoung Kang <sy0816.kang@samsung.com>
Tue, 29 May 2018 06:59:18 +0000 (15:59 +0900)
Change-Id: I347ddd5d3d2441ea2fc2eda7c838c1b42b72d9e4
Signed-off-by: Jiho Chang <jiho04.chang@samsung.com>
drivers/media/platform/exynos/mfc/Makefile
drivers/media/platform/exynos/mfc/s5p_mfc.c
drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h
drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.c
drivers/media/platform/exynos/mfc/s5p_mfc_inst.c
drivers/media/platform/exynos/mfc/s5p_mfc_irq.c
drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/s5p_mfc_sync.c

index 75e203ebb218487e8b24afcd545000f5d632e6fd..36de58256e300d83409d06a7907d79d1797bbc5f 100644 (file)
@@ -1,7 +1,7 @@
 obj-$(CONFIG_VIDEO_EXYNOS_MFC) := s5p-mfc.o
 s5p-mfc-y += s5p_mfc.o s5p_mfc_irq.o s5p_mfc_dec.o s5p_mfc_dec_vb2_ops.o s5p_mfc_enc.o s5p_mfc_enc_vb2_ops.o
 s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_hwlock.o s5p_mfc_nal_q.o s5p_mfc_watchdog.o s5p_mfc_opr.o s5p_mfc_sync.o
-s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_inst.o s5p_mfc_cmd.o s5p_mfc_cal.o s5p_mfc_reg.o
+s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_inst.o s5p_mfc_cmd.o s5p_mfc_cal.o s5p_mfc_reg.o s5p_mfc_perf_measure.o
 s5p-mfc-y += s5p_mfc_dec_ops.o s5p_mfc_enc_ops.o s5p_mfc_enc_param.o
 s5p-mfc-y += s5p_mfc_queue.o s5p_mfc_buf.o s5p_mfc_utils.o s5p_mfc_qos.o s5p_mfc_mem.o
 s5p-mfc-y += s5p_mfc_debugfs.o s5p_mfc_otf.o
index 95c324807bac2d9f6b69e78b5518ac3e0c9a8388..d27b81f633ef33e6477c2e4b7abc34b8740f576a 100644 (file)
@@ -37,6 +37,7 @@
 #include "s5p_mfc_inst.h"
 #include "s5p_mfc_pm.h"
 #include "s5p_mfc_cal.h"
+#include "s5p_mfc_perf_measure.h"
 #include "s5p_mfc_reg.h"
 
 #include "s5p_mfc_qos.h"
@@ -561,6 +562,7 @@ static int s5p_mfc_open(struct file *file)
                        goto err_init_inst;
        }
 
+       s5p_mfc_perf_init(dev);
        trace_mfc_node_open(ctx->num, dev->num_inst, ctx->type, ctx->is_drm);
        mfc_info_ctx("MFC open completed [%d:%d] dev = 0x%p, ctx = 0x%p, version = %d\n",
                        dev->num_drm_inst, dev->num_inst, dev, ctx, MFC_DRIVER_INFO);
@@ -758,6 +760,8 @@ static int s5p_mfc_release(struct file *file)
        dev->ctx[ctx->num] = 0;
        kfree(ctx);
 
+       s5p_mfc_perf_print();
+
        mfc_info_dev("mfc driver release finished [%d:%d], dev = 0x%p\n",
                        dev->num_drm_inst, dev->num_inst, dev);
 
@@ -974,6 +978,8 @@ static int mfc_register_resource(struct platform_device *pdev, struct s5p_mfc_de
        struct resource *res;
        int ret;
 
+       s5p_mfc_perf_register(dev);
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
                dev_err(&pdev->dev, "failed to get memory region resource\n");
index 1b1767038cff286d8bad1a8932524ea40cfb73ec..fbbbfeeb1a2dc63598ced0a37a40232e752a85ac 100644 (file)
@@ -319,6 +319,7 @@ struct s5p_mfc_debugfs {
        struct dentry *nal_q_disable;
        struct dentry *nal_q_parallel_disable;
        struct dentry *otf_dump;
+       struct dentry *perf_measure_option;
 };
 
 /**
@@ -633,6 +634,18 @@ struct _otf_handle {
 };
 /********************************************************************/
 
+struct s5p_mfc_perf {
+       void __iomem *regs_base0;
+       void __iomem *regs_base1;
+
+       struct timeval begin;
+       struct timeval end;
+
+       int new_start;
+       int count;
+       int drv_margin;
+};
+
 /**
  * struct s5p_mfc_dev - The struct containing driver internal parameters.
  */
@@ -735,6 +748,8 @@ struct s5p_mfc_dev {
 #endif
 
        struct s5p_mfc_debugfs debugfs;
+
+       struct s5p_mfc_perf perf;
 };
 
 /**
index f29b008126eff0d7cacb92b5a5bad2a7e0be7c73..a3d1d838ddbc8c9c791c4689a7916f3a75dc1edd 100644 (file)
@@ -27,6 +27,7 @@ unsigned int nal_q_dump;
 unsigned int nal_q_disable;
 unsigned int nal_q_parallel_disable;
 unsigned int otf_dump;
+unsigned int perf_measure_option;
 
 static int mfc_info_show(struct seq_file *s, void *unused)
 {
@@ -131,4 +132,6 @@ void s5p_mfc_init_debugfs(struct s5p_mfc_dev *dev)
                        0644, debugfs->root, &nal_q_parallel_disable);
        debugfs->otf_dump = debugfs_create_u32("otf_dump",
                        0644, debugfs->root, &otf_dump);
+       debugfs->perf_measure_option = debugfs_create_u32("perf_measure_option",
+                       0644, debugfs->root, &perf_measure_option);
 }
index 72f39b30ac8d60c66e262ad2037fee9f271de290..e9fa1e03fc596b7ac987c80ff26833241db8b919 100644 (file)
@@ -15,6 +15,7 @@
 #include "s5p_mfc_cmd.h"
 #include "s5p_mfc_enc_param.h"
 #include "s5p_mfc_cal.h"
+#include "s5p_mfc_perf_measure.h"
 #include "s5p_mfc_reg.h"
 
 #include "s5p_mfc_utils.h"
@@ -239,6 +240,8 @@ int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
         * is the last frame or not. */
        switch (last_frame) {
        case 0:
+               s5p_mfc_perf_measure_on(dev);
+
                s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_START);
                break;
        case 1:
@@ -412,6 +415,8 @@ int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
         * is the last frame or not. */
        switch (last_frame) {
        case 0:
+               s5p_mfc_perf_measure_on(dev);
+
                s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_START);
                break;
        case 1:
index bb06159d2f2ae1e93ae536bc8f03e5e309604354..76d039fb4e00cbf01b314d66732b81b3f85ace91 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "s5p_mfc_pm.h"
 #include "s5p_mfc_cal.h"
+#include "s5p_mfc_perf_measure.h"
 #include "s5p_mfc_reg.h"
 
 #include "s5p_mfc_qos.h"
@@ -1277,6 +1278,8 @@ irqreturn_t s5p_mfc_top_half_irq(int irq, void *priv)
                        dev->curr_ctx, reason, err);
        MFC_TRACE_CTX("<< INT(top): %d\n", reason);
 
+       s5p_mfc_perf_measure_off(dev);
+
        return IRQ_WAKE_THREAD;
 }
 
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c b/drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c
new file mode 100644 (file)
index 0000000..47e7731
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "s5p_mfc_perf_measure.h"
+
+#ifndef PERF_MEASURE
+
+void s5p_mfc_perf_register(struct s5p_mfc_dev *dev) {}
+void mfc_measure_init(void) {}
+void mfc_measure_on(struct s5p_mfc_dev *dev) {}
+void mfc_measure_off(struct s5p_mfc_dev *dev) {}
+void mfc_measure_store(struct s5p_mfc_dev *dev, int diff) {}
+void s5p_mfc_perf_print(void) {}
+
+#else
+
+#endif
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h b/drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h
new file mode 100644 (file)
index 0000000..7c4426b
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __S5P_MFC_PERF_MEASURE_H
+#define __S5P_MFC_PERF_MEASURE_H __FILE__
+
+#include <linux/clk.h>
+
+#include "s5p_mfc_reg.h"
+
+void s5p_mfc_perf_register(struct s5p_mfc_dev *dev);
+void mfc_measure_init(void);
+void mfc_measure_on(struct s5p_mfc_dev *dev);
+void mfc_measure_off(struct s5p_mfc_dev *dev);
+void mfc_measure_store(struct s5p_mfc_dev *dev, int diff);
+void s5p_mfc_perf_print(void);
+
+//#define PERF_MEASURE
+
+#ifndef PERF_MEASURE
+
+static inline void s5p_mfc_perf_init(struct s5p_mfc_dev *dev) {}
+static inline void s5p_mfc_perf_cancel_drv_margin(struct s5p_mfc_dev *dev) {}
+static inline void s5p_mfc_perf_measure_on(struct s5p_mfc_dev *dev) {}
+static inline void s5p_mfc_perf_measure_off(struct s5p_mfc_dev *dev) {}
+
+#else
+
+extern unsigned int perf_measure_option;
+
+static inline void s5p_mfc_perf_init(struct s5p_mfc_dev *dev)
+{
+       dev->perf.new_start = 0;
+       dev->perf.count = 0;
+       dev->perf.drv_margin = 0;
+
+       mfc_measure_init();
+
+       mfc_info_dev("MFC frequency : %ld\n", clk_get_rate(dev->pm.clock));
+}
+
+static inline void s5p_mfc_perf_cancel_drv_margin(struct s5p_mfc_dev *dev)
+{
+       dev->perf.drv_margin = 0;
+}
+
+static inline void s5p_mfc_perf_measure_on(struct s5p_mfc_dev *dev)
+{
+       int diff;
+
+       if (dev->perf.drv_margin) {
+               do_gettimeofday(&dev->perf.end);
+
+               diff = (dev->perf.end.tv_sec * 1000000 + dev->perf.end.tv_usec)
+                       - (dev->perf.begin.tv_sec * 1000000 + dev->perf.begin.tv_usec);
+
+               mfc_info_dev("IRQ -> NAL_START time(ms) = %03d.%03d\n", diff / 1000, diff % 1000);
+
+               dev->perf.drv_margin = 0;
+       }
+
+       do_gettimeofday(&dev->perf.begin);
+
+       mfc_measure_on(dev);
+
+       dev->perf.new_start = 1;
+       dev->perf.count++;
+}
+
+static inline void s5p_mfc_perf_measure_off(struct s5p_mfc_dev *dev)
+{
+       unsigned int diff;
+
+       if ((dev->perf.new_start) && (dev->perf.count > 0)) {
+               mfc_measure_off(dev);
+
+               do_gettimeofday(&dev->perf.end);
+
+               diff = (dev->perf.end.tv_sec * 1000000 + dev->perf.end.tv_usec)
+                       - (dev->perf.begin.tv_sec * 1000000 + dev->perf.begin.tv_usec);
+
+               mfc_measure_store(dev, diff);
+
+               mfc_debug(3, "uDECtype :%d, uENCtype :%d, codectype :%d\n",
+                       s5p_mfc_get_dec_frame_type(), s5p_mfc_get_enc_slice_type(), MFC_READL(S5P_FIMV_CODEC_TYPE));
+
+               dev->perf.drv_margin = 1;
+
+               do_gettimeofday(&dev->perf.begin);
+       }
+
+       dev->perf.new_start = 0;
+}
+
+#endif
+
+#endif /* __S5P_MFC_PERF_MEASURE_H */
index a4ecf11f95959da1ebeea50ba19450ada15f7a5e..66fbf1fbbc49e7da24165fa7f4f9f5b0a46c5cdc 100644 (file)
@@ -12,6 +12,8 @@
 
 #include "s5p_mfc_sync.h"
 
+#include "s5p_mfc_perf_measure.h"
+
 #include "s5p_mfc_queue.h"
 
 #define R2H_BIT(x)     (((x) > 0) ? (1 << ((x) - 1)) : 0)
@@ -230,6 +232,7 @@ int s5p_mfc_dec_ctx_ready(struct s5p_mfc_ctx *ctx)
                src_buf_queue_greater_than_0)
                return 1;
 
+       s5p_mfc_perf_cancel_drv_margin(dev);
        mfc_debug(2, "ctx is not ready.\n");
 
        return 0;
@@ -296,6 +299,7 @@ int s5p_mfc_enc_ctx_ready(struct s5p_mfc_ctx *ctx)
                src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
                return 1;
 
+       s5p_mfc_perf_cancel_drv_margin(dev);
        mfc_debug(2, "ctx is not ready.\n");
 
        return 0;