From 0b1ac11fcb2bd0da07ef4c71a768fcbb82ba8359 Mon Sep 17 00:00:00 2001 From: Hosung Kim Date: Wed, 11 Jul 2018 15:31:00 +0900 Subject: [PATCH] [ERD][NEUS7920-76] [COMMON] lib: dss: support to output notifier call functions On reboot/panic/occuring itmon, notifier call adding from device function breaks system sometime. This commit prevents such a situation to output reboot/panic notifier like following. debug-snapshot: panic_notifier_list -> hung_task_panic call + debug-snapshot: panic_notifier_list -> hung_task_panic call - debug-snapshot: panic_notifier_list -> exynos_cs_panic_handler call + debug-snapshot: panic_notifier_list -> exynos_cs_panic_handler call - Change-Id: Iec9bc3afe77a928a12d1138acd42bf02e3706bb4 Signed-off-by: Hosung Kim --- drivers/soc/samsung/debug/exynos9610-itmon.c | 2 +- include/linux/debug-snapshot.h | 8 ++++++ kernel/notifier.c | 4 +++ kernel/reboot.c | 2 +- lib/debug-snapshot-log.c | 30 ++++++++++++++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/soc/samsung/debug/exynos9610-itmon.c b/drivers/soc/samsung/debug/exynos9610-itmon.c index 1f0e0c0bbf65..69f0b0a8492e 100644 --- a/drivers/soc/samsung/debug/exynos9610-itmon.c +++ b/drivers/soc/samsung/debug/exynos9610-itmon.c @@ -491,7 +491,7 @@ struct itmon_panic_block { }; /* declare notifier_list */ -static ATOMIC_NOTIFIER_HEAD(itmon_notifier_list); +ATOMIC_NOTIFIER_HEAD(itmon_notifier_list); static const struct of_device_id itmon_dt_match[] = { {.compatible = "samsung,exynos-itmon", diff --git a/include/linux/debug-snapshot.h b/include/linux/debug-snapshot.h index 00aef34ccdb4..7605449b1673 100644 --- a/include/linux/debug-snapshot.h +++ b/include/linux/debug-snapshot.h @@ -25,6 +25,7 @@ extern void dbg_snapshot_work(void *worker, void *v_task, void *fn, int en); extern void dbg_snapshot_cpuidle(char *modes, unsigned state, int diff, int en); extern void dbg_snapshot_suspend(void *fn, void *dev, int en); extern void dbg_snapshot_irq(int irq, void *fn, void *val, int en); +extern void dbg_snapshot_print_notifier_call(void **nl, unsigned long func, int en); extern int dbg_snapshot_try_enable(const char *name, unsigned long long duration); extern int dbg_snapshot_set_enable(const char *name, int en); extern int dbg_snapshot_get_enable(const char *name); @@ -256,6 +257,13 @@ extern void dbg_snapshot_soc_helper_init(void); static inline void dbg_snapshot_bug_func(void) {BUG();} static inline void dbg_snapshot_spin_func(void) {do {wfi();} while(1);} +extern struct atomic_notifier_head restart_handler_list; +extern struct blocking_notifier_head reboot_notifier_list; + +#ifdef CONFIG_EXYNOS_ITMON +extern struct atomic_notifier_head itmon_notifier_list; +#endif + /** * dsslog_flag - added log information supported. * @DSS_FLAG_REQ: Generally, marking starting request something diff --git a/kernel/notifier.c b/kernel/notifier.c index 6196af8a8223..04cdce49998a 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c @@ -90,7 +90,11 @@ static int notifier_call_chain(struct notifier_block **nl, continue; } #endif + dbg_snapshot_print_notifier_call((void **)nl, + (unsigned long)nb->notifier_call, DSS_FLAG_IN); ret = nb->notifier_call(nb, val, v); + dbg_snapshot_print_notifier_call((void **)nl, + (unsigned long)nb->notifier_call, DSS_FLAG_OUT); if (nr_calls) (*nr_calls)++; diff --git a/kernel/reboot.c b/kernel/reboot.c index bd30a973fe94..f56409a3e1b5 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -108,7 +108,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier); * Notifier list for kernel code which wants to be called * to restart the system. */ -static ATOMIC_NOTIFIER_HEAD(restart_handler_list); +ATOMIC_NOTIFIER_HEAD(restart_handler_list); /** * register_restart_handler - Register function to be called to reset diff --git a/lib/debug-snapshot-log.c b/lib/debug-snapshot-log.c index 2073fd214afb..028c2fc48cd1 100644 --- a/lib/debug-snapshot-log.c +++ b/lib/debug-snapshot-log.c @@ -1056,6 +1056,36 @@ void dbg_snapshot_pmu(int id, const char *func_name, int mode) } #endif +static struct notifier_block **dss_should_check_nl[] = { + (struct notifier_block **)(&panic_notifier_list.head), + (struct notifier_block **)(&reboot_notifier_list.head), + (struct notifier_block **)(&restart_handler_list.head), +#ifdef CONFIG_EXYNOS_ITMON + (struct notifier_block **)(&itmon_notifier_list.head), +#endif +}; + +void dbg_snapshot_print_notifier_call(void **nl, unsigned long func, int en) +{ + struct notifier_block **nl_org = (struct notifier_block **)nl; + char notifier_name[KSYM_NAME_LEN]; + char notifier_func_name[KSYM_NAME_LEN]; + int i; + + for (i = 0; i < ARRAY_SIZE(dss_should_check_nl); i++) { + if (nl_org == dss_should_check_nl[i]) { + lookup_symbol_name((unsigned long)nl_org, notifier_name); + lookup_symbol_name((unsigned long)func, notifier_func_name); + + pr_info("debug-snapshot: %s -> %s call %s\n", + notifier_name, + notifier_func_name, + en == DSS_FLAG_IN ? "+" : "-"); + break; + } + } +} + #ifdef CONFIG_DEBUG_SNAPSHOT_FREQ static void dbg_snapshot_print_freqinfo(void) { -- 2.20.1