-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
thermal/intel: Introduce Intel TCC library
There are several different drivers that accesses the Intel TCC (thermal control circuitry) MSRs, and each of them has its own implementation for the same functionalities, e.g. getting the current temperature, getting the tj_max, and getting/setting the tj_max offset. Introduce a library to unify the code for Intel CPU TCC MSR access. At the same time, ensure the temperature is got based on the updated tjmax value because tjmax can be changed at runtime for cases like the Intel SST-PP (Intel Speed Select Technology - Performance Profile) level change. Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
- Loading branch information
Zhang Rui
authored and
Rafael J. Wysocki
committed
Dec 30, 2022
1 parent
b878d3b
commit a3c1f06
Showing
4 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// 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. | ||
* @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: Temperature in degrees C on success, negative error code otherwise. | ||
*/ | ||
int intel_tcc_get_temp(int cpu, bool pkg) | ||
{ | ||
u32 low, high; | ||
u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS; | ||
int tjmax, temp, 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); | ||
|
||
/* Do not allow negative CPU temperature */ | ||
return temp >= 0 ? temp : -ENODATA; | ||
} | ||
EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* header for Intel TCC (thermal control circuitry) library | ||
* | ||
* Copyright (C) 2022 Intel Corporation. | ||
*/ | ||
|
||
#ifndef __INTEL_TCC_H__ | ||
#define __INTEL_TCC_H__ | ||
|
||
#include <linux/types.h> | ||
|
||
int intel_tcc_get_tjmax(int cpu); | ||
int intel_tcc_get_offset(int cpu); | ||
int intel_tcc_set_offset(int cpu, int offset); | ||
int intel_tcc_get_temp(int cpu, bool pkg); | ||
|
||
#endif /* __INTEL_TCC_H__ */ |