mirror of
https://github.com/torvalds/linux.git
synced 2026-07-30 03:01:41 +02:00
sched/walt/halt: track halt reasons
Currently, there are no protections under conditions where CPUs may be halted or unhalted twice, which could lead to undesired behavior. Track reasons for refcounts per CPU to ensure proper accounting. Change-Id: Ic85a13f3536e3287fc76a02004d2b4601ada7a1a Signed-off-by: Shaleen Agrawal <quic_shalagra@quicinc.com>
This commit is contained in:
parent
99a0b1fcbc
commit
4014533422
|
|
@ -109,7 +109,7 @@ static inline int pause_cpu(int cpu)
|
|||
cpumask_clear(&cpus_to_pause);
|
||||
cpumask_set_cpu(cpu, &cpus_to_pause);
|
||||
|
||||
ret = walt_pause_cpus(&cpus_to_pause);
|
||||
ret = walt_pause_cpus(&cpus_to_pause, PAUSE_HYP);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -122,7 +122,7 @@ static inline int resume_cpu(int cpu)
|
|||
cpumask_clear(&cpus_to_resume);
|
||||
cpumask_set_cpu(cpu, &cpus_to_resume);
|
||||
|
||||
ret = walt_resume_cpus(&cpus_to_resume);
|
||||
ret = walt_resume_cpus(&cpus_to_resume, PAUSE_HYP);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ static int thermal_pause_work(struct thermal_pause_cdev *thermal_pause_cdev)
|
|||
pr_debug("Pause:%*pbl\n", cpumask_pr_args(&thermal_pause_cdev->cpu_mask));
|
||||
|
||||
mutex_unlock(&cpus_pause_lock);
|
||||
ret = walt_pause_cpus(&cpus_to_pause);
|
||||
ret = walt_pause_cpus(&cpus_to_pause, PAUSE_THERMAL);
|
||||
mutex_lock(&cpus_pause_lock);
|
||||
|
||||
if (ret == 0) {
|
||||
|
|
@ -149,7 +149,7 @@ static int thermal_resume_work(struct thermal_pause_cdev *thermal_pause_cdev)
|
|||
pr_debug("Unpause:%*pbl\n", cpumask_pr_args(&cpus_to_unpause));
|
||||
|
||||
mutex_unlock(&cpus_pause_lock);
|
||||
ret = walt_resume_cpus(&cpus_to_unpause);
|
||||
ret = walt_resume_cpus(&cpus_to_unpause, PAUSE_THERMAL);
|
||||
mutex_lock(&cpus_pause_lock);
|
||||
|
||||
if (ret == 0) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@
|
|||
#include <linux/spinlock_types.h>
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
enum pause_reason {
|
||||
PAUSE_CORE_CTL = 0x01,
|
||||
PAUSE_THERMAL = 0x02,
|
||||
PAUSE_HYP = 0x04,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_SCHED_WALT)
|
||||
|
||||
#define MAX_CPUS_PER_CLUSTER 6
|
||||
|
|
@ -170,10 +176,11 @@ struct notifier_block;
|
|||
extern void core_ctl_notifier_register(struct notifier_block *n);
|
||||
extern void core_ctl_notifier_unregister(struct notifier_block *n);
|
||||
extern int core_ctl_set_boost(bool boost);
|
||||
extern int walt_pause_cpus(struct cpumask *cpus);
|
||||
extern int walt_resume_cpus(struct cpumask *cpus);
|
||||
extern int walt_halt_cpus(struct cpumask *cpus);
|
||||
extern int walt_start_cpus(struct cpumask *cpus);
|
||||
|
||||
extern int walt_pause_cpus(struct cpumask *cpus, enum pause_reason reason);
|
||||
extern int walt_resume_cpus(struct cpumask *cpus, enum pause_reason reason);
|
||||
extern int walt_halt_cpus(struct cpumask *cpus, enum pause_reason reason);
|
||||
extern int walt_start_cpus(struct cpumask *cpus, enum pause_reason reason);
|
||||
#else
|
||||
static inline int sched_lpm_disallowed_time(int cpu, u64 *timeout)
|
||||
{
|
||||
|
|
@ -211,11 +218,11 @@ static inline void core_ctl_notifier_unregister(struct notifier_block *n)
|
|||
{
|
||||
}
|
||||
|
||||
inline int walt_pause_cpus(struct cpumask *cpus)
|
||||
inline int walt_pause_cpus(struct cpumask *cpus, enum pause_reason reason)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
inline int walt_resume_cpus(struct cpumask *cpus)
|
||||
inline int walt_resume_cpus(struct cpumask *cpus, enum pause_reason reason)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1163,7 +1163,7 @@ static void core_ctl_pause_cpus(struct cpumask *cpus_to_pause)
|
|||
cpumask_copy(&saved_cpus, cpus_to_pause);
|
||||
|
||||
if (cpumask_any(cpus_to_pause) < nr_cpu_ids) {
|
||||
if (walt_halt_cpus(cpus_to_pause) < 0)
|
||||
if (walt_halt_cpus(cpus_to_pause, PAUSE_CORE_CTL) < 0)
|
||||
pr_debug("core_ctl pause operation failed cpus=%*pbl paused_by_us=%*pbl\n",
|
||||
cpumask_pr_args(cpus_to_pause),
|
||||
cpumask_pr_args(&cpus_paused_by_us));
|
||||
|
|
@ -1192,7 +1192,7 @@ static void core_ctl_resume_cpus(struct cpumask *cpus_to_unpause)
|
|||
cpumask_copy(&saved_cpus, cpus_to_unpause);
|
||||
|
||||
if (cpumask_any(cpus_to_unpause) < nr_cpu_ids) {
|
||||
if (walt_start_cpus(cpus_to_unpause) < 0)
|
||||
if (walt_start_cpus(cpus_to_unpause, PAUSE_CORE_CTL) < 0)
|
||||
pr_debug("core_ctl resume operation failed cpus=%*pbl paused_by_us=%*pbl\n",
|
||||
cpumask_pr_args(cpus_to_unpause),
|
||||
cpumask_pr_args(&cpus_paused_by_us));
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ static DEFINE_RAW_SPINLOCK(halt_lock);
|
|||
|
||||
struct halt_cpu_state {
|
||||
u64 last_halt;
|
||||
int ref_count;
|
||||
u8 reason;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct halt_cpu_state, halt_state);
|
||||
|
|
@ -333,20 +333,18 @@ static int start_cpus(struct cpumask *cpus)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* increment/decrement ref count for cpus in yield/halt mask */
|
||||
static void update_ref_counts(struct cpumask *cpus, bool halt)
|
||||
/* update reason for cpus in yield/halt mask */
|
||||
static void update_reasons(struct cpumask *cpus, bool halt, enum pause_reason reason)
|
||||
{
|
||||
int cpu;
|
||||
struct halt_cpu_state *halt_cpu_state;
|
||||
|
||||
for_each_cpu(cpu, cpus) {
|
||||
halt_cpu_state = per_cpu_ptr(&halt_state, cpu);
|
||||
if (halt) {
|
||||
halt_cpu_state->ref_count++;
|
||||
} else {
|
||||
WARN_ON_ONCE(halt_cpu_state->ref_count == 0);
|
||||
halt_cpu_state->ref_count--;
|
||||
}
|
||||
if (halt)
|
||||
halt_cpu_state->reason |= reason;
|
||||
else
|
||||
halt_cpu_state->reason &= ~reason;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,13 +356,13 @@ static void update_halt_cpus(struct cpumask *cpus)
|
|||
|
||||
for_each_cpu(cpu, cpus) {
|
||||
halt_cpu_state = per_cpu_ptr(&halt_state, cpu);
|
||||
if (halt_cpu_state->ref_count)
|
||||
if (halt_cpu_state->reason)
|
||||
cpumask_clear_cpu(cpu, cpus);
|
||||
}
|
||||
}
|
||||
|
||||
/* cpus will be modified */
|
||||
int walt_halt_cpus(struct cpumask *cpus)
|
||||
int walt_halt_cpus(struct cpumask *cpus, enum pause_reason reason)
|
||||
{
|
||||
int ret = 0;
|
||||
cpumask_t requested_cpus;
|
||||
|
|
@ -378,7 +376,7 @@ int walt_halt_cpus(struct cpumask *cpus)
|
|||
update_halt_cpus(cpus);
|
||||
|
||||
if (cpumask_empty(cpus)) {
|
||||
update_ref_counts(&requested_cpus, true);
|
||||
update_reasons(&requested_cpus, true, reason);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
|
|
@ -388,21 +386,21 @@ int walt_halt_cpus(struct cpumask *cpus)
|
|||
pr_debug("halt_cpus failure ret=%d cpus=%*pbl\n", ret,
|
||||
cpumask_pr_args(&requested_cpus));
|
||||
else
|
||||
update_ref_counts(&requested_cpus, true);
|
||||
update_reasons(&requested_cpus, true, reason);
|
||||
unlock:
|
||||
raw_spin_unlock_irqrestore(&halt_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int walt_pause_cpus(struct cpumask *cpus)
|
||||
int walt_pause_cpus(struct cpumask *cpus, enum pause_reason reason)
|
||||
{
|
||||
return walt_halt_cpus(cpus);
|
||||
return walt_halt_cpus(cpus, reason);
|
||||
}
|
||||
EXPORT_SYMBOL(walt_pause_cpus);
|
||||
|
||||
/* cpus will be modified */
|
||||
int walt_start_cpus(struct cpumask *cpus)
|
||||
int walt_start_cpus(struct cpumask *cpus, enum pause_reason reason)
|
||||
{
|
||||
int ret = 0;
|
||||
cpumask_t requested_cpus;
|
||||
|
|
@ -410,9 +408,9 @@ int walt_start_cpus(struct cpumask *cpus)
|
|||
|
||||
raw_spin_lock_irqsave(&halt_lock, flags);
|
||||
cpumask_copy(&requested_cpus, cpus);
|
||||
update_ref_counts(&requested_cpus, false);
|
||||
update_reasons(&requested_cpus, false, reason);
|
||||
|
||||
/* remove cpus that should still be halted, due to ref-counts */
|
||||
/* remove cpus that should still be halted */
|
||||
update_halt_cpus(cpus);
|
||||
|
||||
ret = start_cpus(cpus);
|
||||
|
|
@ -421,7 +419,7 @@ int walt_start_cpus(struct cpumask *cpus)
|
|||
pr_debug("halt_cpus failure ret=%d cpus=%*pbl\n", ret,
|
||||
cpumask_pr_args(&requested_cpus));
|
||||
/* restore/increment ref counts in case of error */
|
||||
update_ref_counts(&requested_cpus, true);
|
||||
update_reasons(&requested_cpus, true, reason);
|
||||
}
|
||||
|
||||
raw_spin_unlock_irqrestore(&halt_lock, flags);
|
||||
|
|
@ -429,9 +427,9 @@ int walt_start_cpus(struct cpumask *cpus)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int walt_resume_cpus(struct cpumask *cpus)
|
||||
int walt_resume_cpus(struct cpumask *cpus, enum pause_reason reason)
|
||||
{
|
||||
return walt_start_cpus(cpus);
|
||||
return walt_start_cpus(cpus, reason);
|
||||
}
|
||||
EXPORT_SYMBOL(walt_resume_cpus);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user