[COMMON] media: mfc: add ITMON notifier.
authorJeonghee Kim <jhhhh.kim@samsung.com>
Wed, 9 May 2018 11:15:54 +0000 (20:15 +0900)
committerSunyoung Kang <sy0816.kang@samsung.com>
Tue, 29 May 2018 06:59:18 +0000 (15:59 +0900)
Change-Id: I8fa23e382d902d6aace27194c0a57ff8fc6b36cc
Signed-off-by: Jeonghee Kim <jhhhh.kim@samsung.com>
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_watchdog.c
drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h

index c8449388720ad540af325284963f27eada2075e9..679f1f10c9efc187316f06eaddf5f13a7d380689 100644 (file)
@@ -927,7 +927,6 @@ int s5p_mfc_sysmmu_fault_handler(struct iommu_domain *iodmn, struct device *devi
        }
        dev->logging_data->fault_addr = (unsigned int)addr;
 
-       s5p_mfc_dump_buffer_info(dev, addr);
        call_dop(dev, dump_info, dev);
 
        return 0;
@@ -1106,6 +1105,47 @@ err_ioremap:
        return -ENOENT;
 }
 
+#ifdef CONFIG_EXYNOS_ITMON
+static int mfc_itmon_notifier(struct notifier_block *nb, unsigned long action, void *nb_data)
+{
+       struct s5p_mfc_dev *dev;
+       struct itmon_notifier *itmon_info = nb_data;
+       int is_mfc_itmon = 0, is_master = 0;
+
+       dev = container_of(nb, struct s5p_mfc_dev, itmon_nb);
+
+       if (IS_ERR_OR_NULL(itmon_info))
+               return NOTIFY_DONE;
+
+       /* print dump if it is an MFC ITMON error */
+       if ((strncmp("MFC", itmon_info->port, sizeof("MFC") - 1) == 0) &&
+                       (strncmp("MFC", itmon_info->master, sizeof("MFC") - 1) == 0)) {
+               is_mfc_itmon = 1;
+               is_master = 1;
+       } else if (strncmp("MFC", itmon_info->dest, sizeof("MFC") - 1) == 0) {
+               is_mfc_itmon = 1;
+               is_master = 0;
+       }
+
+       if (is_mfc_itmon) {
+               pr_err("mfc_itmon_notifier: MFC +\n");
+               pr_err("MFC is %s.\n", is_master ? "master" : "dest");
+               if (!dev->itmon_notified) {
+                       pr_err("dump MFC information.\n");
+                       if (is_master || (!is_master && itmon_info->onoff))
+                               call_dop(dev, dump_info, dev);
+                       else
+                               call_dop(dev, dump_info_without_regs, dev);
+               } else {
+                       pr_err("MFC notifier has already been called. skip MFC information.\n");
+               }
+               pr_err("mfc_itmon_notifier: MFC -\n");
+               dev->itmon_notified = 1;
+       }
+       return NOTIFY_DONE;
+}
+#endif
+
 /* MFC probe function */
 static int s5p_mfc_probe(struct platform_device *pdev)
 {
@@ -1282,6 +1322,11 @@ static int s5p_mfc_probe(struct platform_device *pdev)
                goto err_alloc_debug;
        }
 
+#ifdef CONFIG_EXYNOS_ITMON
+       dev->itmon_nb.notifier_call = mfc_itmon_notifier;
+       itmon_notifier_chain_register(&dev->itmon_nb);
+#endif
+
        s5p_mfc_init_debugfs(dev);
 
        pr_debug("%s--\n", __func__);
index af7a254bc8f1203ccd1bd9a598e1fbac62cbae49..0283548f318158d17744ce560af8e735fadf789f 100644 (file)
@@ -24,6 +24,9 @@
 #include <soc/samsung/bts.h>
 #endif
 #include <linux/videodev2.h>
+#ifdef CONFIG_EXYNOS_ITMON
+#include <soc/samsung/exynos-itmon.h>
+#endif
 
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
@@ -643,6 +646,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_info)(struct s5p_mfc_dev *dev);
+       void (*dump_info_without_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);
 };
@@ -760,6 +764,11 @@ struct s5p_mfc_dev {
        struct s5p_mfc_perf perf;
 
        struct s5p_mfc_mmcache mmcache;
+
+#ifdef CONFIG_EXYNOS_ITMON
+       struct notifier_block itmon_nb;
+       int itmon_notified;
+#endif
 };
 
 /**
index dee4fd615ec7269f12e61a37604cb680b77ec8e5..cedaa93d0450378c74eb54d2c5a85a2aedf1d37c 100644 (file)
@@ -191,13 +191,14 @@ static void mfc_print_trace(struct s5p_mfc_dev *dev)
        }
 }
 
-void s5p_mfc_dump_buffer_info(struct s5p_mfc_dev *dev, unsigned long addr)
+void mfc_dump_buffer_info(struct s5p_mfc_dev *dev)
 {
        struct s5p_mfc_ctx *ctx;
 
        ctx = dev->ctx[dev->curr_ctx];
        if (ctx) {
-               pr_err("-----------dumping MFC buffer info (fault at: %#lx)\n", addr);
+               pr_err("-----------dumping MFC buffer info (fault at: %#x)\n",
+                               dev->logging_data->fault_addr);
                pr_err("common:%#llx~%#llx, instance:%#llx~%#llx, codec:%#llx~%#llx\n",
                                dev->common_ctx_buf.daddr,
                                dev->common_ctx_buf.daddr + PAGE_ALIGN(0x7800),
@@ -264,11 +265,17 @@ void s5p_mfc_dump_buffer_info(struct s5p_mfc_dev *dev, unsigned long addr)
        }
 }
 
-static void mfc_dump_info(struct s5p_mfc_dev *dev)
+static void mfc_dump_info_without_regs(struct s5p_mfc_dev *dev)
 {
        mfc_display_state(dev);
        mfc_print_trace(dev);
+}
+
+static void mfc_dump_info(struct s5p_mfc_dev *dev)
+{
+       mfc_dump_info_without_regs(dev);
        mfc_save_logging_sfr(dev);
+       mfc_dump_buffer_info(dev);
        mfc_dump_regs(dev);
        exynos_sysmmu_show_status(dev->device);
 }
@@ -335,6 +342,7 @@ void s5p_mfc_watchdog_worker(struct work_struct *work)
 struct s5p_mfc_dump_ops mfc_dump_ops = {
        .dump_regs                      = mfc_dump_regs,
        .dump_info                      = mfc_dump_info,
+       .dump_info_without_regs         = mfc_dump_info_without_regs,
        .dump_and_stop_always           = mfc_dump_info_and_stop_hw,
        .dump_and_stop_debug_mode       = mfc_dump_info_and_stop_hw_debug,
 };
index d72f15634c14fba16bf403c6b384052d52d3ddbd..b715fb7a8156c8b63cbee854f941b3826bcaaa58 100644 (file)
@@ -15,7 +15,6 @@
 
 #include "s5p_mfc_common.h"
 
-void s5p_mfc_dump_buffer_info(struct s5p_mfc_dev *dev, unsigned long addr);
 void s5p_mfc_watchdog_worker(struct work_struct *work);
 
 #endif /* __S5P_MFC_WATCHDOG_H */