From: Junho Choi Date: Fri, 20 Jul 2018 05:26:26 +0000 (+0900) Subject: [9610] soc: samsung: smc: Add DEBUG_SNAPSHOT_LOGGING_SMC feature X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=b07db0a34b6b626cbaec5dd7477cb58779ec0028;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [9610] soc: samsung: smc: Add DEBUG_SNAPSHOT_LOGGING_SMC feature This feature logs the information like clock, latency and etc. of every SMCs. Change-Id: I1984510424fbe6668128121ccd5495fd74623920 Signed-off-by: Junho Choi --- diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig index 19837cf16db0..06e6fbbc3bdb 100644 --- a/drivers/soc/samsung/Kconfig +++ b/drivers/soc/samsung/Kconfig @@ -159,4 +159,14 @@ config USI_V2 bool "Enable Universal Serial Interface version 2" default y +config EXYNOS_SMC_LOG_THRESHOLD + int "threshold of detection(microsecond)" + range 0 1000000 + default 0 + +config DEBUG_SNAPSHOT_LOGGING_SMC + bool "Exynos Logging SMC" + depends on DEBUG_SNAPSHOT + default y + endif diff --git a/drivers/soc/samsung/exynos-smc.c b/drivers/soc/samsung/exynos-smc.c index 6c850adbd064..aeb0b0db4dd9 100644 --- a/drivers/soc/samsung/exynos-smc.c +++ b/drivers/soc/samsung/exynos-smc.c @@ -13,50 +13,139 @@ #include #include #include +#include +#include +#include #include -#define CONFIG_EXYNOS_SMC_LOGGING +#include -#ifdef CONFIG_EXYNOS_SMC_LOGGING -#define EXYNOS_SMC_LOG_SIZE 1024 +#ifdef CONFIG_DEBUG_SNAPSHOT_LOGGING_SMC +#define EXYNOS_SMC_LOG_SIZE (1024) -struct exynos_smc_log_entry { - u64 cpu_clk; - u32 cmd; - u32 arg1; - u32 arg2; - u32 arg3; +static DEFINE_SPINLOCK(smc_log_lock); + +static struct bus_type esmc_subsys = { + .name = "exynos-smc", + .dev_name = "exynos-smc", +}; + +struct esmc_log { + unsigned long cpu_clk; /* cpu clock */ + unsigned long long start_time; /* start time */ + unsigned long sp; /* call stack */ + unsigned long long end_time; /* end time */ + unsigned long long latency; /* latency */ + unsigned long cmd; + unsigned long arg1; + unsigned long arg2; + unsigned long arg3; +}; + +struct esmc_log smc_log[NR_CPUS][EXYNOS_SMC_LOG_SIZE]; +static uint32_t smc_log_idx[NR_CPUS]; + +static unsigned int esmc_log_threshold = + CONFIG_EXYNOS_SMC_LOG_THRESHOLD; + +static ssize_t esmc_log_threshold_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + ssize_t n; + + n = scnprintf(buf, 46, "threshold : %12u us\n", esmc_log_threshold); + + return n; +} + +static ssize_t esmc_log_threshold_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long val; + int err; + + err = kstrtoul(buf, 0, &val); + + if (err != 0) { + pr_err("can't read threshold value with err 0x%x\n", err); + } else { + esmc_log_threshold = val; + pr_info("threshold value : %lu\n", val); + } + + return count; +} + +static struct kobj_attribute esmc_log_threshold_attr = + __ATTR(threshold_esmc_log, 0644, esmc_log_threshold_show, + esmc_log_threshold_store); + +static struct attribute *esmc_sysfs_attrs[] = { + &esmc_log_threshold_attr.attr, + NULL, }; -static DEFINE_SPINLOCK(drm_smc_log_lock); +static struct attribute_group esmc_sysfs_group = { + .attrs = esmc_sysfs_attrs, +}; -struct exynos_smc_log_entry drm_smc_log[EXYNOS_SMC_LOG_SIZE]; +static const struct attribute_group *esmc_sysfs_groups[] = { + &esmc_sysfs_group, + NULL, +}; -static unsigned int drm_smc_log_idx; +static int __init esmc_sysfs_init(void) +{ + int ret = 0; + + ret = subsys_system_register(&esmc_subsys, esmc_sysfs_groups); + if (ret) + pr_err("fail to register exynos-smc subsys\n"); + + return ret; +} +late_initcall(esmc_sysfs_init); #endif int exynos_smc(unsigned long cmd, unsigned long arg1, unsigned long arg2, unsigned long arg3) { -#ifdef CONFIG_EXYNOS_SMC_LOGGING - unsigned long flags; + int32_t ret; +#ifdef CONFIG_DEBUG_SNAPSHOT_LOGGING_SMC + unsigned long flags, stime, etime, latency; + unsigned int cpu, idx; + + cpu = raw_smp_processor_id(); + stime = cpu_clock(cpu); #endif -#ifdef CONFIG_EXYNOS_SMC_LOGGING - if ((uint32_t)cmd >= SMC_PROTECTION_SET && (uint32_t)cmd < MC_FC_SET_CFW_PROT) { - pr_debug("%s: cmd: 0x%x, arg1: 0x%x, arg2: 0x%x, arg3: 0x%x\n", - __func__, (u32)cmd, (u32)arg1, (u32)arg2, (u32)arg3); - spin_lock_irqsave(&drm_smc_log_lock, flags); - drm_smc_log[drm_smc_log_idx].cpu_clk = local_clock(); - drm_smc_log[drm_smc_log_idx].cmd = (u32)cmd; - drm_smc_log[drm_smc_log_idx].arg1 = (u32)arg1; - drm_smc_log[drm_smc_log_idx].arg2 = (u32)arg2; - drm_smc_log[drm_smc_log_idx].arg3 = (u32)arg3; - drm_smc_log_idx++; - if (drm_smc_log_idx == EXYNOS_SMC_LOG_SIZE) - drm_smc_log_idx = 0; - spin_unlock_irqrestore(&drm_smc_log_lock, flags); + ret = __exynos_smc(cmd, arg1, arg2, arg3); + +#ifdef CONFIG_DEBUG_SNAPSHOT_LOGGING_SMC + etime = cpu_clock(cpu); + latency = etime - stime; + + spin_lock_irqsave(&smc_log_lock, flags); + + if (latency > (esmc_log_threshold * 1000)) { + idx = smc_log_idx[cpu]; + + smc_log[cpu][idx].cpu_clk = local_clock(); + smc_log[cpu][idx].latency = latency; + smc_log[cpu][idx].start_time = stime; + smc_log[cpu][idx].end_time = etime; + smc_log[cpu][idx].sp = (uint64_t)current_stack_pointer; + smc_log[cpu][idx].cmd = cmd; + smc_log[cpu][idx].arg1 = arg1; + smc_log[cpu][idx].arg2 = arg2; + smc_log[cpu][idx].arg3 = arg3; + + smc_log_idx[cpu]++; + if (smc_log_idx[cpu] == EXYNOS_SMC_LOG_SIZE) + smc_log_idx[cpu] = 0; } -#endif - return __exynos_smc(cmd, arg1, arg2, arg3); + spin_unlock_irqrestore(&smc_log_lock, flags); +#endif + return ret; }