diff options
Diffstat (limited to 'drivers/cpuidle/lpm-levels.c')
| -rw-r--r-- | drivers/cpuidle/lpm-levels.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 64c4bf8f58a8..4224b594f1b8 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -43,6 +43,7 @@ #include <soc/qcom/event_timer.h> #include <soc/qcom/lpm-stats.h> #include <soc/qcom/jtag.h> +#include <soc/qcom/minidump.h> #include <asm/cputype.h> #include <asm/arch_timer.h> #include <asm/cacheflush.h> @@ -72,6 +73,8 @@ enum debug_event { CLUSTER_ENTER, CLUSTER_EXIT, PRE_PC_CB, + CPU_HP_STARTING, + CPU_HP_DYING, }; struct lpm_debug { @@ -341,10 +344,16 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb, switch (action & ~CPU_TASKS_FROZEN) { case CPU_DYING: + update_debug_pc_event(CPU_HP_DYING, cpu, + cluster->num_children_in_sync.bits[0], + cluster->child_cpus.bits[0], false); cluster_prepare(cluster, get_cpu_mask((unsigned int) cpu), NR_LPM_LEVELS, false, 0); break; case CPU_STARTING: + update_debug_pc_event(CPU_HP_STARTING, cpu, + cluster->num_children_in_sync.bits[0], + cluster->child_cpus.bits[0], false); cluster_unprepare(cluster, get_cpu_mask((unsigned int) cpu), NR_LPM_LEVELS, false, 0); break; @@ -682,7 +691,7 @@ static int cpu_power_select(struct cpuidle_device *dev, if (!cpu) return -EINVAL; - if (sleep_disabled) + if (sleep_disabled && !cpu_isolated(dev->cpu)) return 0; idx_restrict = cpu->nlevels + 1; @@ -1123,6 +1132,8 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, struct cpumask nextcpu, *cpumask; uint64_t us; uint32_t pred_us; + uint64_t sec; + uint64_t nsec; us = get_cluster_sleep_time(cluster, &nextcpu, from_idle, &pred_us); @@ -1134,11 +1145,20 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, goto failed_set_mode; } - us = (us + 1) * 1000; clear_predict_history(); clear_cl_predict_history(); - do_div(us, NSEC_PER_SEC/SCLK_HZ); + us = us + 1; + sec = us; + do_div(sec, USEC_PER_SEC); + nsec = us - sec * USEC_PER_SEC; + + sec = sec * SCLK_HZ; + if (nsec > 0) { + nsec = nsec * NSEC_PER_USEC; + do_div(nsec, NSEC_PER_SEC/SCLK_HZ); + } + us = sec + nsec; msm_mpm_enter_sleep(us, from_idle, cpumask); } @@ -1835,6 +1855,7 @@ static int lpm_probe(struct platform_device *pdev) int ret; int size; struct kobject *module_kobj = NULL; + struct md_region md_entry; get_online_cpus(); lpm_root_node = lpm_of_parse_cluster(pdev); @@ -1895,6 +1916,14 @@ static int lpm_probe(struct platform_device *pdev) goto failed; } + /* Add lpm_debug to Minidump*/ + strlcpy(md_entry.name, "KLPMDEBUG", sizeof(md_entry.name)); + md_entry.virt_addr = (uintptr_t)lpm_debug; + md_entry.phys_addr = lpm_debug_phys; + md_entry.size = size; + if (msm_minidump_add_region(&md_entry)) + pr_info("Failed to add lpm_debug in Minidump\n"); + return 0; failed: free_cluster_node(lpm_root_node); |
