mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 08:14:15 +08:00
7251b9e8a0
CPU temperature can be negative in some cases. Thus the negative CPU
temperature should not be considered as a failure.
Fix intel_tcc_get_temp() and its users to support negative CPU
temperature.
Fixes: a3c1f066e1
("thermal/intel: Introduce Intel TCC library")
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Reviewed-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
Cc: 6.3+ <stable@vger.kernel.org> # 6.3+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
140 lines
3.6 KiB
C
140 lines
3.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* intel_tcc.c - Library for Intel TCC (thermal control circuitry) MSR access
|
|
* Copyright (c) 2022, Intel Corporation.
|
|
*/
|
|
|
|
#include <linux/errno.h>
|
|
#include <linux/intel_tcc.h>
|
|
#include <asm/msr.h>
|
|
|
|
/**
|
|
* intel_tcc_get_tjmax() - returns the default TCC activation Temperature
|
|
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
|
|
*
|
|
* Get the TjMax value, which is the default thermal throttling or TCC
|
|
* activation temperature in degrees C.
|
|
*
|
|
* Return: Tjmax value in degrees C on success, negative error code otherwise.
|
|
*/
|
|
int intel_tcc_get_tjmax(int cpu)
|
|
{
|
|
u32 low, high;
|
|
int val, err;
|
|
|
|
if (cpu < 0)
|
|
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
|
else
|
|
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
|
if (err)
|
|
return err;
|
|
|
|
val = (low >> 16) & 0xff;
|
|
|
|
return val ? val : -ENODATA;
|
|
}
|
|
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_tjmax, INTEL_TCC);
|
|
|
|
/**
|
|
* intel_tcc_get_offset() - returns the TCC Offset value to Tjmax
|
|
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
|
|
*
|
|
* Get the TCC offset value to Tjmax. The effective thermal throttling or TCC
|
|
* activation temperature equals "Tjmax" - "TCC Offset", in degrees C.
|
|
*
|
|
* Return: Tcc offset value in degrees C on success, negative error code otherwise.
|
|
*/
|
|
int intel_tcc_get_offset(int cpu)
|
|
{
|
|
u32 low, high;
|
|
int err;
|
|
|
|
if (cpu < 0)
|
|
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
|
else
|
|
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
|
if (err)
|
|
return err;
|
|
|
|
return (low >> 24) & 0x3f;
|
|
}
|
|
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, INTEL_TCC);
|
|
|
|
/**
|
|
* intel_tcc_set_offset() - set the TCC offset value to Tjmax
|
|
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
|
|
* @offset: TCC offset value in degree C
|
|
*
|
|
* Set the TCC Offset value to Tjmax. The effective thermal throttling or TCC
|
|
* activation temperature equals "Tjmax" - "TCC Offset", in degree C.
|
|
*
|
|
* Return: On success returns 0, negative error code otherwise.
|
|
*/
|
|
|
|
int intel_tcc_set_offset(int cpu, int offset)
|
|
{
|
|
u32 low, high;
|
|
int err;
|
|
|
|
if (offset < 0 || offset > 0x3f)
|
|
return -EINVAL;
|
|
|
|
if (cpu < 0)
|
|
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
|
else
|
|
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
|
|
if (err)
|
|
return err;
|
|
|
|
/* MSR Locked */
|
|
if (low & BIT(31))
|
|
return -EPERM;
|
|
|
|
low &= ~(0x3f << 24);
|
|
low |= offset << 24;
|
|
|
|
if (cpu < 0)
|
|
return wrmsr_safe(MSR_IA32_TEMPERATURE_TARGET, low, high);
|
|
else
|
|
return wrmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, low, high);
|
|
}
|
|
EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
|
|
|
|
/**
|
|
* intel_tcc_get_temp() - returns the current temperature
|
|
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
|
|
* @temp: pointer to the memory for saving cpu temperature.
|
|
* @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor.
|
|
*
|
|
* Get the current temperature returned by the CPU core/package level
|
|
* thermal sensor, in degrees C.
|
|
*
|
|
* Return: 0 on success, negative error code otherwise.
|
|
*/
|
|
int intel_tcc_get_temp(int cpu, int *temp, bool pkg)
|
|
{
|
|
u32 low, high;
|
|
u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS;
|
|
int tjmax, err;
|
|
|
|
tjmax = intel_tcc_get_tjmax(cpu);
|
|
if (tjmax < 0)
|
|
return tjmax;
|
|
|
|
if (cpu < 0)
|
|
err = rdmsr_safe(msr, &low, &high);
|
|
else
|
|
err = rdmsr_safe_on_cpu(cpu, msr, &low, &high);
|
|
if (err)
|
|
return err;
|
|
|
|
/* Temperature is beyond the valid thermal sensor range */
|
|
if (!(low & BIT(31)))
|
|
return -ENODATA;
|
|
|
|
*temp = tjmax - ((low >> 16) & 0x7f);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC);
|