mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	cpufreq: CPPC: fix perf_to_khz/khz_to_perf conversion exception
When the nominal_freq recorded by the kernel is equal to the lowest_freq,
and the frequency adjustment operation is triggered externally, there is
a logic error in cppc_perf_to_khz()/cppc_khz_to_perf(), resulting in perf
and khz conversion errors.
Fix this by adding a branch processing logic when nominal_freq is equal
to lowest_freq.
Fixes: ec1c7ad476 ("cpufreq: CPPC: Fix performance/frequency conversion")
Signed-off-by: liwei <liwei728@huawei.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Link: https://patch.msgid.link/20241024022952.2627694-1-liwei728@huawei.com
[ rjw: Subject and changelog edits ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
			
			
This commit is contained in:
		
							parent
							
								
									29dcbea924
								
							
						
					
					
						commit
						d93df29bda
					
				
					 1 changed files with 17 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -1916,9 +1916,15 @@ unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf)
 | 
			
		|||
	u64 mul, div;
 | 
			
		||||
 | 
			
		||||
	if (caps->lowest_freq && caps->nominal_freq) {
 | 
			
		||||
		/* Avoid special case when nominal_freq is equal to lowest_freq */
 | 
			
		||||
		if (caps->lowest_freq == caps->nominal_freq) {
 | 
			
		||||
			mul = caps->nominal_freq;
 | 
			
		||||
			div = caps->nominal_perf;
 | 
			
		||||
		} else {
 | 
			
		||||
			mul = caps->nominal_freq - caps->lowest_freq;
 | 
			
		||||
		mul *= KHZ_PER_MHZ;
 | 
			
		||||
			div = caps->nominal_perf - caps->lowest_perf;
 | 
			
		||||
		}
 | 
			
		||||
		mul *= KHZ_PER_MHZ;
 | 
			
		||||
		offset = caps->nominal_freq * KHZ_PER_MHZ -
 | 
			
		||||
			 div64_u64(caps->nominal_perf * mul, div);
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1942,8 +1948,14 @@ unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq)
 | 
			
		|||
	u64 mul, div;
 | 
			
		||||
 | 
			
		||||
	if (caps->lowest_freq && caps->nominal_freq) {
 | 
			
		||||
		/* Avoid special case when nominal_freq is equal to lowest_freq */
 | 
			
		||||
		if (caps->lowest_freq == caps->nominal_freq) {
 | 
			
		||||
			mul = caps->nominal_perf;
 | 
			
		||||
			div = caps->nominal_freq;
 | 
			
		||||
		} else {
 | 
			
		||||
			mul = caps->nominal_perf - caps->lowest_perf;
 | 
			
		||||
			div = caps->nominal_freq - caps->lowest_freq;
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * We don't need to convert to kHz for computing offset and can
 | 
			
		||||
		 * directly use nominal_freq and lowest_freq as the div64_u64
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue