media: mfc: DRV3.2: support debugging mode
authorAyoung Sim <a.sim@samsung.com>
Fri, 16 Mar 2018 10:36:03 +0000 (19:36 +0900)
committerSunyoung Kang <sy0816.kang@samsung.com>
Tue, 29 May 2018 06:59:18 +0000 (15:59 +0900)
This patch supports the debugging mode,
we will enable it during the verification period.
First of all, it applies to the timeout of interrupt.

Change-Id: I3b1b402a3afadd1fe01d05f9f01c25eb46f43238
Signed-off-by: Ayoung Sim <a.sim@samsung.com>
drivers/media/platform/exynos/mfc/s5p_mfc_cal.c
drivers/media/platform/exynos/mfc/s5p_mfc_cal.h
drivers/media/platform/exynos/mfc/s5p_mfc_common.h
drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h
drivers/media/platform/exynos/mfc/s5p_mfc_debug.h
drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.c
drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.c
drivers/media/platform/exynos/mfc/s5p_mfc_sync.c
drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c

index b2dcd9c243aea6e22a11f64dd66d83c6936d3f57..1914d2658066d99073c886811f9774f5220c4d83 100644 (file)
@@ -13,6 +13,7 @@
 #include <trace/events/mfc.h>
 
 #include "s5p_mfc_cal.h"
+#include "s5p_mfc_pm.h"
 
 /* Reset the device */
 int s5p_mfc_reset_mfc(struct s5p_mfc_dev *dev)
@@ -85,3 +86,16 @@ void s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd)
        MFC_WRITEL(cmd, S5P_FIMV_HOST2RISC_CMD);
        MFC_WRITEL(0x1, S5P_FIMV_HOST2RISC_INT);
 }
+
+/* Check whether HW interrupt has occurred or not */
+int s5p_mfc_check_risc2host(struct s5p_mfc_dev *dev)
+{
+       if (s5p_mfc_pm_get_pwr_ref_cnt(dev) && s5p_mfc_pm_get_clk_ref_cnt(dev)) {
+               if (MFC_READL(S5P_FIMV_RISC2HOST_INT))
+                       return MFC_READL(S5P_FIMV_RISC2HOST_CMD);
+               else
+                       return 0;
+       }
+
+       return 0;
+}
index e8cdc7590cf33bd8ac5ad9188acc11106a78affd..6dfefddc34c502cf40a8e337223662cc9019137a 100644 (file)
                        MFC_WRITEL(0, S5P_FIMV_RISC2HOST_INT);  \
                } while (0)
 
-static inline int s5p_mfc_check_int_cmd(struct s5p_mfc_dev *dev)
-{
-       if (MFC_READL(S5P_FIMV_RISC2HOST_INT))
-               return MFC_READL(S5P_FIMV_RISC2HOST_CMD);
-       else
-               return 0;
-}
-
 static inline int s5p_mfc_stop_bus(struct s5p_mfc_dev *dev)
 {
        unsigned int status;
@@ -118,5 +110,6 @@ int s5p_mfc_reset_mfc(struct s5p_mfc_dev *dev);
 void s5p_mfc_set_risc_base_addr(struct s5p_mfc_dev *dev,
                                enum mfc_buf_usage_type buf_type);
 void s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd);
+int s5p_mfc_check_risc2host(struct s5p_mfc_dev *dev);
 
 #endif /* __S5P_MFC_CAL_H */
index f39cf55d3985cdf0fbaa964542488c3c119a0f8a..5d9b5c24cbb1d2f7890bfe7eea118c584505df2e 100644 (file)
 #define MFC_MAX_DRM_CTX                2
 
 /* Interrupt timeout */
-#define MFC_INT_TIMEOUT                5000
+#define MFC_INT_TIMEOUT                4000
 /* Interrupt short timeout */
 #define MFC_INT_SHORT_TIMEOUT  800
+/* hwlock timeout */
+#define MFC_HWLOCK_TIMEOUT     5000
 /* Busy wait timeout */
 #define MFC_BW_TIMEOUT         500
+/* Interrupt timeout count*/
+#define MFC_INT_TIMEOUT_CNT    2
 
 /* This value guarantees 299.4msec ~ 2.25sec according to MFC clock (668MHz ~ 89MHz)
  * releated with S5P_FIMV_DEC_TIMEOUT_VALUE */
index d892b6df4fc8658519651cb584b36a8722b3a12d..ddff79fd4bb55b54d06568b8f67c8c68c1e1ea0b 100644 (file)
@@ -337,6 +337,7 @@ struct s5p_mfc_debugfs {
        struct dentry *otf_dump;
        struct dentry *perf_measure_option;
        struct dentry *sfr_dump;
+       struct dentry *debug_mode;
 };
 
 /**
@@ -667,6 +668,7 @@ extern struct s5p_mfc_dump_ops mfc_dump_ops;
 struct s5p_mfc_dump_ops {
        void (*dump_regs)(struct s5p_mfc_dev *dev);
        void (*dump_and_stop_always)(struct s5p_mfc_dev *dev);
+       void (*dump_and_stop_debug_mode)(struct s5p_mfc_dev *dev);
 };
 
 /**
@@ -723,6 +725,7 @@ struct s5p_mfc_dev {
 
        struct s5p_mfc_hwlock hwlock;
 
+       atomic_t sched_wait_cnt;
        atomic_t watchdog_tick_running;
        atomic_t watchdog_tick_cnt;
        atomic_t watchdog_run;
index c3eebc00893f5b1db85746dfb163097888787a8c..8d626590e93fc253665f9c7b4517b77fbec66d73 100644 (file)
@@ -25,6 +25,7 @@ extern unsigned int nal_q_disable;
 extern unsigned int nal_q_parallel_disable;
 extern unsigned int otf_dump;
 extern unsigned int sfr_dump;
+extern unsigned int debug_mode;
 
 #define mfc_debug(level, fmt, args...)                         \
        do {                                                    \
index ec2f015a9dd12da6341a68e1eafa71f95633bdfe..58a824fc08037d8eae5e9340f224d5ef449c0376 100644 (file)
@@ -29,6 +29,8 @@ unsigned int nal_q_parallel_disable;
 unsigned int otf_dump;
 unsigned int perf_measure_option;
 unsigned int sfr_dump;
+/* It will be disable after driver is stabilized */
+unsigned int debug_mode = 1;
 
 static int mfc_info_show(struct seq_file *s, void *unused)
 {
@@ -149,4 +151,6 @@ void s5p_mfc_init_debugfs(struct s5p_mfc_dev *dev)
                        0644, debugfs->root, &perf_measure_option);
        debugfs->sfr_dump = debugfs_create_u32("sfr_dump",
                        0644, debugfs->root, &sfr_dump);
+       debugfs->debug_mode = debugfs_create_u32("debug_mode",
+                       0644, debugfs->root, &debug_mode);
 }
index 095cd3a9c6a00a693bfe3d82ad57cc74696daef2..b379f58ddd5ae2d8d4b8715d0f01ff871073d0ac 100644 (file)
@@ -166,7 +166,7 @@ int s5p_mfc_get_hwlock_dev(struct s5p_mfc_dev *dev)
 
                ret = wait_event_timeout(dev->hwlock_wq.wait_queue,
                        ((dev->hwlock.transfer_owner == 1) && (dev->hwlock.dev == 1)),
-                       msecs_to_jiffies(MFC_INT_TIMEOUT));
+                       msecs_to_jiffies(MFC_HWLOCK_TIMEOUT));
 
                MFC_TRACE_DEV_HWLOCK("get_hwlock_dev: before waiting\n");
                MFC_TRACE_DEV_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
@@ -258,7 +258,7 @@ int s5p_mfc_get_hwlock_ctx(struct s5p_mfc_ctx *curr_ctx)
 
                ret = wait_event_timeout(curr_ctx->hwlock_wq.wait_queue,
                        ((dev->hwlock.transfer_owner == 1) && (test_bit(curr_ctx->num, &dev->hwlock.bits))),
-                       msecs_to_jiffies(MFC_INT_TIMEOUT));
+                       msecs_to_jiffies(MFC_HWLOCK_TIMEOUT));
 
                MFC_TRACE_CTX_HWLOCK("get_hwlock_ctx: after waiting, ret:%d\n", ret);
                MFC_TRACE_CTX_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
index 66fbf1fbbc49e7da24165fa7f4f9f5b0a46c5cdc..f318517b0ebfce8b421ee05601d95a1a3aa04c90 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "s5p_mfc_sync.h"
 
+#include "s5p_mfc_cal.h"
 #include "s5p_mfc_perf_measure.h"
 
 #include "s5p_mfc_queue.h"
@@ -56,8 +57,22 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
        if (ret == 0) {
                mfc_err_dev("Interrupt (dev->int_reason:%d, command:%d) timed out.\n",
                                                        dev->int_reason, command);
+               if (s5p_mfc_check_risc2host(dev)) {
+                       ret = wait_event_timeout(dev->cmd_wq,
+                                       wait_condition(dev, command),
+                                       msecs_to_jiffies(MFC_INT_TIMEOUT * MFC_INT_TIMEOUT_CNT));
+                       if (ret == 0) {
+                               mfc_err_dev("Timeout: MFC driver waited for upward of %dsec\n",
+                                               3 * MFC_INT_TIMEOUT);
+                       } else {
+                               goto wait_done;
+                       }
+               }
+               call_dop(dev, dump_and_stop_debug_mode, dev);
                return 1;
        }
+
+wait_done:
        mfc_debug(2, "Finished waiting (dev->int_reason:%d, command: %d).\n",
                                                        dev->int_reason, command);
        return 0;
@@ -71,6 +86,7 @@ int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
 */
 int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx, int command)
 {
+       struct s5p_mfc_dev *dev = ctx->dev;
        int ret;
        unsigned int timeout = MFC_INT_TIMEOUT;
 
@@ -83,15 +99,30 @@ int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx, int command)
        if (ret == 0) {
                mfc_err_ctx("Interrupt (ctx->int_reason:%d, command:%d) timed out.\n",
                                                        ctx->int_reason, command);
-               return 1;
-       } else if (ret > 0) {
-               if (is_err_cond(ctx)) {
-                       mfc_err_ctx("Finished (ctx->int_reason:%d, command: %d).\n",
-                                       ctx->int_reason, command);
-                       mfc_err_ctx("But error (ctx->int_err:%d).\n", ctx->int_err);
-                       return -1;
+               if (s5p_mfc_check_risc2host(dev)) {
+                       ret = wait_event_timeout(ctx->cmd_wq,
+                                       wait_condition(ctx, command),
+                                       msecs_to_jiffies(MFC_INT_TIMEOUT * MFC_INT_TIMEOUT_CNT));
+                       if (ret == 0) {
+                               mfc_err_dev("Timeout: MFC driver waited for upward of %dsec\n",
+                                               3 * MFC_INT_TIMEOUT);
+                       } else {
+                               goto wait_done;
+                       }
                }
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               return 1;
        }
+
+wait_done:
+       if (is_err_cond(ctx)) {
+               mfc_err_ctx("Finished (ctx->int_reason:%d, command: %d).\n",
+                               ctx->int_reason, command);
+               mfc_err_ctx("But error (ctx->int_err:%d).\n", ctx->int_err);
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               return -1;
+       }
+
        mfc_debug(2, "Finished waiting (ctx->int_reason:%d, command: %d).\n",
                                                        ctx->int_reason, command);
        return 0;
index c80d9636dcaf53bff780dc0cbd964fbe469b9b21..7fbdaeb98066895ee92e60159530c980c5ed97ed 100644 (file)
@@ -275,10 +275,24 @@ static void mfc_dump_info_and_stop_hw(struct s5p_mfc_dev *dev)
        BUG();
 }
 
+static void mfc_dump_info_and_stop_hw_debug(struct s5p_mfc_dev *dev)
+{
+       if (!debug_mode)
+               return;
+
+       MFC_TRACE_DEV("** mfc will stop!!!\n");
+       mfc_display_state(dev);
+       mfc_print_trace(dev);
+       mfc_save_logging_sfr(dev);
+       mfc_dump_regs(dev);
+       exynos_sysmmu_show_status(dev->device);
+       BUG();
+}
+
 void s5p_mfc_watchdog_worker(struct work_struct *work)
 {
        struct s5p_mfc_dev *dev;
-       int cmd = 0;
+       int cmd;
 
        dev = container_of(work, struct s5p_mfc_dev, watchdog_work);
 
@@ -292,16 +306,14 @@ void s5p_mfc_watchdog_worker(struct work_struct *work)
                return;
        }
 
-       /* Check whether HW interrupt has occured or not */
-       if (s5p_mfc_pm_get_pwr_ref_cnt(dev) && s5p_mfc_pm_get_clk_ref_cnt(dev))
-               cmd = s5p_mfc_check_int_cmd(dev);
+       cmd = s5p_mfc_check_risc2host(dev);
        if (cmd) {
                if (atomic_read(&dev->watchdog_tick_cnt) == (3 * WATCHDOG_TICK_CNT_TO_START_WATCHDOG)) {
                        mfc_err_dev("MFC driver waited for upward of %dsec\n",
-                                               3 * WATCHDOG_TICK_CNT_TO_START_WATCHDOG);
+                                       3 * WATCHDOG_TICK_CNT_TO_START_WATCHDOG);
                        dev->logging_data->cause |= (1 << MFC_CAUSE_NO_SCHEDULING);
                } else {
-                       mfc_err_dev("interrupt(%d) is occured, wait scheduling\n", cmd);
+                       mfc_err_dev("interrupt(%d) is occurred, wait scheduling\n", cmd);
                        return;
                }
        } else {
@@ -322,4 +334,5 @@ void s5p_mfc_watchdog_worker(struct work_struct *work)
 struct s5p_mfc_dump_ops mfc_dump_ops = {
        .dump_regs                      = mfc_dump_regs,
        .dump_and_stop_always           = mfc_dump_info_and_stop_hw,
+       .dump_and_stop_debug_mode       = mfc_dump_info_and_stop_hw_debug,
 };