diff options
Diffstat (limited to 'drivers/cpuidle/lpm-levels.c')
-rw-r--r-- | drivers/cpuidle/lpm-levels.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 4224b594f1b8..584a1857624a 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -363,6 +363,24 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb, return NOTIFY_OK; } +#ifdef CONFIG_ARM_PSCI + +static int __init set_cpuidle_ops(void) +{ + int ret = 0, cpu; + + for_each_possible_cpu(cpu) { + ret = arm_cpuidle_init(cpu); + if (ret) + goto exit; + } + +exit: + return ret; +} + +#endif + static enum hrtimer_restart lpm_hrtimer_cb(struct hrtimer *h) { return HRTIMER_NORESTART; @@ -676,22 +694,21 @@ static int cpu_power_select(struct cpuidle_device *dev, int best_level = -1; uint32_t latency_us = pm_qos_request_for_cpu(PM_QOS_CPU_DMA_LATENCY, dev->cpu); - uint32_t sleep_us = - (uint32_t)(ktime_to_us(tick_nohz_get_sleep_length())); + s64 sleep_us = ktime_to_us(tick_nohz_get_sleep_length()); uint32_t modified_time_us = 0; uint32_t next_event_us = 0; int i, idx_restrict; uint32_t lvl_latency_us = 0; uint64_t predicted = 0; uint32_t htime = 0, idx_restrict_time = 0; - uint32_t next_wakeup_us = sleep_us; + uint32_t next_wakeup_us = (uint32_t)sleep_us; uint32_t *min_residency = get_per_cpu_min_residency(dev->cpu); uint32_t *max_residency = get_per_cpu_max_residency(dev->cpu); if (!cpu) return -EINVAL; - if (sleep_disabled && !cpu_isolated(dev->cpu)) + if ((sleep_disabled && !cpu_isolated(dev->cpu)) || sleep_us < 0) return 0; idx_restrict = cpu->nlevels + 1; @@ -732,8 +749,8 @@ static int cpu_power_select(struct cpuidle_device *dev, if (next_wakeup_us > max_residency[i]) { predicted = lpm_cpuidle_predict(dev, cpu, &idx_restrict, &idx_restrict_time); - if (predicted < min_residency[i]) - predicted = 0; + if (predicted && (predicted < min_residency[i])) + predicted = min_residency[i]; } else invalidate_predict_history(dev); } @@ -1101,10 +1118,14 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, bool from_idle, int predicted) { struct lpm_cluster_level *level = &cluster->levels[idx]; + struct cpumask online_cpus; int ret, i; + cpumask_and(&online_cpus, &cluster->num_children_in_sync, + cpu_online_mask); + if (!cpumask_equal(&cluster->num_children_in_sync, &cluster->child_cpus) - || is_IPI_pending(&cluster->num_children_in_sync)) { + || is_IPI_pending(&online_cpus)) { return -EPERM; } @@ -1954,6 +1975,14 @@ static int __init lpm_levels_module_init(void) goto fail; } +#ifdef CONFIG_ARM_PSCI + rc = set_cpuidle_ops(); + if (rc) { + pr_err("%s(): Failed to set cpuidle ops\n", __func__); + goto fail; + } +#endif + fail: return rc; } |