Loading drivers/cpuidle/lpm-levels.c +51 −4 Original line number Diff line number Diff line /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. * Copyright (C) 2006-2007 Adam Belay <abelay@novell.com> * Copyright (C) 2009 Intel Corporation * Loading Loading @@ -109,6 +109,7 @@ static DEFINE_PER_CPU(struct lpm_cpu*, cpu_lpm); static bool suspend_in_progress; static struct hrtimer lpm_hrtimer; static DEFINE_PER_CPU(struct hrtimer, histtimer); static DEFINE_PER_CPU(struct hrtimer, biastimer); static struct lpm_debug *lpm_debug; static phys_addr_t lpm_debug_phys; static const int num_dbg_elements = 0x100; Loading Loading @@ -435,6 +436,34 @@ static void msm_pm_set_timer(uint32_t modified_time_us) hrtimer_start(&lpm_hrtimer, modified_ktime, HRTIMER_MODE_REL_PINNED); } static void biastimer_cancel(void) { unsigned int cpu = raw_smp_processor_id(); struct hrtimer *cpu_biastimer = &per_cpu(biastimer, cpu); ktime_t time_rem; time_rem = hrtimer_get_remaining(cpu_biastimer); if (ktime_to_us(time_rem) <= 0) return; hrtimer_try_to_cancel(cpu_biastimer); } static enum hrtimer_restart biastimer_fn(struct hrtimer *h) { return HRTIMER_NORESTART; } static void biastimer_start(uint32_t time_ns) { ktime_t bias_ktime = ns_to_ktime(time_ns); unsigned int cpu = raw_smp_processor_id(); struct hrtimer *cpu_biastimer = &per_cpu(biastimer, cpu); cpu_biastimer->function = biastimer_fn; hrtimer_start(cpu_biastimer, bias_ktime, HRTIMER_MODE_REL_PINNED); } static uint64_t lpm_cpuidle_predict(struct cpuidle_device *dev, struct lpm_cpu *cpu, int *idx_restrict, uint32_t *idx_restrict_time) Loading Loading @@ -595,15 +624,22 @@ static void clear_predict_history(void) static void update_history(struct cpuidle_device *dev, int idx); static inline bool is_cpu_biased(int cpu) static inline bool is_cpu_biased(int cpu, uint64_t *bias_time) { u64 now = sched_clock(); u64 last = sched_get_cpu_last_busy_time(cpu); u64 diff = 0; if (!last) return false; return (now - last) < BIAS_HYST; diff = now - last; if (diff < BIAS_HYST) { *bias_time = BIAS_HYST - diff; return true; } return false; } static int cpu_power_select(struct cpuidle_device *dev, Loading @@ -623,6 +659,7 @@ static int cpu_power_select(struct cpuidle_device *dev, uint32_t next_wakeup_us = (uint32_t)sleep_us; uint32_t min_residency, max_residency; struct power_params *pwr_params; uint64_t bias_time = 0; if ((sleep_disabled && !cpu_isolated(dev->cpu)) || sleep_us < 0) return best_level; Loading @@ -631,8 +668,10 @@ static int cpu_power_select(struct cpuidle_device *dev, next_event_us = (uint32_t)(ktime_to_us(get_next_event_time(dev->cpu))); if (is_cpu_biased(dev->cpu) && (!cpu_isolated(dev->cpu))) if (is_cpu_biased(dev->cpu, &bias_time) && (!cpu_isolated(dev->cpu))) { cpu->bias = bias_time; goto done_select; } for (i = 0; i < cpu->nlevels; i++) { bool allow; Loading Loading @@ -1310,6 +1349,8 @@ static bool psci_enter_sleep(struct lpm_cpu *cpu, int idx, bool from_idle) */ if (!idx) { if (cpu->bias) biastimer_start(cpu->bias); stop_critical_timings(); wfi(); start_critical_timings(); Loading Loading @@ -1420,6 +1461,10 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, histtimer_cancel(); clusttimer_cancel(); } if (cpu->bias) { biastimer_cancel(); cpu->bias = 0; } local_irq_enable(); return idx; } Loading Loading @@ -1723,6 +1768,8 @@ static int lpm_probe(struct platform_device *pdev) for_each_possible_cpu(cpu) { cpu_histtimer = &per_cpu(histtimer, cpu); hrtimer_init(cpu_histtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); cpu_histtimer = &per_cpu(biastimer, cpu); hrtimer_init(cpu_histtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); } cluster_timer_init(lpm_root_node); Loading drivers/cpuidle/lpm-levels.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -52,6 +52,7 @@ struct lpm_cpu { uint32_t ref_premature_cnt; uint32_t tmr_add; bool lpm_prediction; uint64_t bias; struct cpuidle_driver *drv; struct lpm_cluster *parent; }; Loading Loading
drivers/cpuidle/lpm-levels.c +51 −4 Original line number Diff line number Diff line /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. * Copyright (C) 2006-2007 Adam Belay <abelay@novell.com> * Copyright (C) 2009 Intel Corporation * Loading Loading @@ -109,6 +109,7 @@ static DEFINE_PER_CPU(struct lpm_cpu*, cpu_lpm); static bool suspend_in_progress; static struct hrtimer lpm_hrtimer; static DEFINE_PER_CPU(struct hrtimer, histtimer); static DEFINE_PER_CPU(struct hrtimer, biastimer); static struct lpm_debug *lpm_debug; static phys_addr_t lpm_debug_phys; static const int num_dbg_elements = 0x100; Loading Loading @@ -435,6 +436,34 @@ static void msm_pm_set_timer(uint32_t modified_time_us) hrtimer_start(&lpm_hrtimer, modified_ktime, HRTIMER_MODE_REL_PINNED); } static void biastimer_cancel(void) { unsigned int cpu = raw_smp_processor_id(); struct hrtimer *cpu_biastimer = &per_cpu(biastimer, cpu); ktime_t time_rem; time_rem = hrtimer_get_remaining(cpu_biastimer); if (ktime_to_us(time_rem) <= 0) return; hrtimer_try_to_cancel(cpu_biastimer); } static enum hrtimer_restart biastimer_fn(struct hrtimer *h) { return HRTIMER_NORESTART; } static void biastimer_start(uint32_t time_ns) { ktime_t bias_ktime = ns_to_ktime(time_ns); unsigned int cpu = raw_smp_processor_id(); struct hrtimer *cpu_biastimer = &per_cpu(biastimer, cpu); cpu_biastimer->function = biastimer_fn; hrtimer_start(cpu_biastimer, bias_ktime, HRTIMER_MODE_REL_PINNED); } static uint64_t lpm_cpuidle_predict(struct cpuidle_device *dev, struct lpm_cpu *cpu, int *idx_restrict, uint32_t *idx_restrict_time) Loading Loading @@ -595,15 +624,22 @@ static void clear_predict_history(void) static void update_history(struct cpuidle_device *dev, int idx); static inline bool is_cpu_biased(int cpu) static inline bool is_cpu_biased(int cpu, uint64_t *bias_time) { u64 now = sched_clock(); u64 last = sched_get_cpu_last_busy_time(cpu); u64 diff = 0; if (!last) return false; return (now - last) < BIAS_HYST; diff = now - last; if (diff < BIAS_HYST) { *bias_time = BIAS_HYST - diff; return true; } return false; } static int cpu_power_select(struct cpuidle_device *dev, Loading @@ -623,6 +659,7 @@ static int cpu_power_select(struct cpuidle_device *dev, uint32_t next_wakeup_us = (uint32_t)sleep_us; uint32_t min_residency, max_residency; struct power_params *pwr_params; uint64_t bias_time = 0; if ((sleep_disabled && !cpu_isolated(dev->cpu)) || sleep_us < 0) return best_level; Loading @@ -631,8 +668,10 @@ static int cpu_power_select(struct cpuidle_device *dev, next_event_us = (uint32_t)(ktime_to_us(get_next_event_time(dev->cpu))); if (is_cpu_biased(dev->cpu) && (!cpu_isolated(dev->cpu))) if (is_cpu_biased(dev->cpu, &bias_time) && (!cpu_isolated(dev->cpu))) { cpu->bias = bias_time; goto done_select; } for (i = 0; i < cpu->nlevels; i++) { bool allow; Loading Loading @@ -1310,6 +1349,8 @@ static bool psci_enter_sleep(struct lpm_cpu *cpu, int idx, bool from_idle) */ if (!idx) { if (cpu->bias) biastimer_start(cpu->bias); stop_critical_timings(); wfi(); start_critical_timings(); Loading Loading @@ -1420,6 +1461,10 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, histtimer_cancel(); clusttimer_cancel(); } if (cpu->bias) { biastimer_cancel(); cpu->bias = 0; } local_irq_enable(); return idx; } Loading Loading @@ -1723,6 +1768,8 @@ static int lpm_probe(struct platform_device *pdev) for_each_possible_cpu(cpu) { cpu_histtimer = &per_cpu(histtimer, cpu); hrtimer_init(cpu_histtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); cpu_histtimer = &per_cpu(biastimer, cpu); hrtimer_init(cpu_histtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); } cluster_timer_init(lpm_root_node); Loading
drivers/cpuidle/lpm-levels.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -52,6 +52,7 @@ struct lpm_cpu { uint32_t ref_premature_cnt; uint32_t tmr_add; bool lpm_prediction; uint64_t bias; struct cpuidle_driver *drv; struct lpm_cluster *parent; }; Loading