intel_pstate: Do not set utilization update hook too early
The utilization update hook in the intel_pstate driver is set too early, as it only should be set after the policy has been fully initialized by the core. That may cause intel_pstate_update_util() to use incorrect data and put the CPUs into incorrect P-states as a result. To prevent that from happening, make intel_pstate_set_policy() set the utilization update hook instead of intel_pstate_init_cpu() so intel_pstate_update_util() only runs when all things have been initialized as appropriate. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
		
							parent
							
								
									539a4c4247
								
							
						
					
					
						commit
						bb6ab52f2b
					
				| @ -1103,7 +1103,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum) | |||||||
| 	intel_pstate_sample(cpu, 0); | 	intel_pstate_sample(cpu, 0); | ||||||
| 
 | 
 | ||||||
| 	cpu->update_util.func = intel_pstate_update_util; | 	cpu->update_util.func = intel_pstate_update_util; | ||||||
| 	cpufreq_set_update_util_data(cpunum, &cpu->update_util); |  | ||||||
| 
 | 
 | ||||||
| 	pr_debug("intel_pstate: controlling: cpu %d\n", cpunum); | 	pr_debug("intel_pstate: controlling: cpu %d\n", cpunum); | ||||||
| 
 | 
 | ||||||
| @ -1122,18 +1121,29 @@ static unsigned int intel_pstate_get(unsigned int cpu_num) | |||||||
| 	return get_avg_frequency(cpu); | 	return get_avg_frequency(cpu); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void intel_pstate_set_update_util_hook(unsigned int cpu) | ||||||
|  | { | ||||||
|  | 	cpufreq_set_update_util_data(cpu, &all_cpu_data[cpu]->update_util); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void intel_pstate_clear_update_util_hook(unsigned int cpu) | ||||||
|  | { | ||||||
|  | 	cpufreq_set_update_util_data(cpu, NULL); | ||||||
|  | 	synchronize_sched(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int intel_pstate_set_policy(struct cpufreq_policy *policy) | static int intel_pstate_set_policy(struct cpufreq_policy *policy) | ||||||
| { | { | ||||||
| 	if (!policy->cpuinfo.max_freq) | 	if (!policy->cpuinfo.max_freq) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 
 | 
 | ||||||
|  | 	intel_pstate_clear_update_util_hook(policy->cpu); | ||||||
|  | 
 | ||||||
| 	if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && | 	if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && | ||||||
| 	    policy->max >= policy->cpuinfo.max_freq) { | 	    policy->max >= policy->cpuinfo.max_freq) { | ||||||
| 		pr_debug("intel_pstate: set performance\n"); | 		pr_debug("intel_pstate: set performance\n"); | ||||||
| 		limits = &performance_limits; | 		limits = &performance_limits; | ||||||
| 		if (hwp_active) | 		goto out; | ||||||
| 			intel_pstate_hwp_set(policy->cpus); |  | ||||||
| 		return 0; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	pr_debug("intel_pstate: set powersave\n"); | 	pr_debug("intel_pstate: set powersave\n"); | ||||||
| @ -1163,6 +1173,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||||||
| 	limits->max_perf = div_fp(int_tofp(limits->max_perf_pct), | 	limits->max_perf = div_fp(int_tofp(limits->max_perf_pct), | ||||||
| 				  int_tofp(100)); | 				  int_tofp(100)); | ||||||
| 
 | 
 | ||||||
|  |  out: | ||||||
|  | 	intel_pstate_set_update_util_hook(policy->cpu); | ||||||
|  | 
 | ||||||
| 	if (hwp_active) | 	if (hwp_active) | ||||||
| 		intel_pstate_hwp_set(policy->cpus); | 		intel_pstate_hwp_set(policy->cpus); | ||||||
| 
 | 
 | ||||||
| @ -1187,8 +1200,7 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy) | |||||||
| 
 | 
 | ||||||
| 	pr_debug("intel_pstate: CPU %d exiting\n", cpu_num); | 	pr_debug("intel_pstate: CPU %d exiting\n", cpu_num); | ||||||
| 
 | 
 | ||||||
| 	cpufreq_set_update_util_data(cpu_num, NULL); | 	intel_pstate_clear_update_util_hook(cpu_num); | ||||||
| 	synchronize_sched(); |  | ||||||
| 
 | 
 | ||||||
| 	if (hwp_active) | 	if (hwp_active) | ||||||
| 		return; | 		return; | ||||||
| @ -1455,8 +1467,7 @@ out: | |||||||
| 	get_online_cpus(); | 	get_online_cpus(); | ||||||
| 	for_each_online_cpu(cpu) { | 	for_each_online_cpu(cpu) { | ||||||
| 		if (all_cpu_data[cpu]) { | 		if (all_cpu_data[cpu]) { | ||||||
| 			cpufreq_set_update_util_data(cpu, NULL); | 			intel_pstate_clear_update_util_hook(cpu); | ||||||
| 			synchronize_sched(); |  | ||||||
| 			kfree(all_cpu_data[cpu]); | 			kfree(all_cpu_data[cpu]); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user