From 98b54a8bdb486e748baff7f8db49a7ab62f60ef6 Mon Sep 17 00:00:00 2001 From: Jeonghee Kim Date: Wed, 9 May 2018 20:15:54 +0900 Subject: [PATCH] [COMMON] media: mfc: add ITMON notifier. Change-Id: I8fa23e382d902d6aace27194c0a57ff8fc6b36cc Signed-off-by: Jeonghee Kim --- drivers/media/platform/exynos/mfc/s5p_mfc.c | 47 ++++++++++++++++++- .../platform/exynos/mfc/s5p_mfc_data_struct.h | 9 ++++ .../platform/exynos/mfc/s5p_mfc_watchdog.c | 14 ++++-- .../platform/exynos/mfc/s5p_mfc_watchdog.h | 1 - 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc.c b/drivers/media/platform/exynos/mfc/s5p_mfc.c index c8449388720a..679f1f10c9ef 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc.c @@ -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__); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h b/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h index af7a254bc8f1..0283548f3181 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h @@ -24,6 +24,9 @@ #include #endif #include +#ifdef CONFIG_EXYNOS_ITMON +#include +#endif #include #include @@ -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 }; /** diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c b/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c index dee4fd615ec7..cedaa93d0450 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c @@ -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, }; diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h b/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h index d72f15634c14..b715fb7a8156 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h @@ -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 */ -- 2.20.1