mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
Simplify the error path by directly returning PTR_ERR(tcc_cdev) instead of storing it in an intermediate variable ret which can be dropped then because it is only used for that. Also remove an uneeded empty line before the declaration of local variable err. Signed-off-by: Sumeet Pawnikar <sumeet4linux@gmail.com> [ rjw: Dropped unneeded changes, rewrote changelog, adjusted subject ] Link: https://patch.msgid.link/20260131151615.6230-1-sumeet4linux@gmail.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
127 lines
3.0 KiB
C
127 lines
3.0 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* cooling device driver that activates the processor throttling by
|
|
* programming the TCC Offset register.
|
|
* Copyright (c) 2021, Intel Corporation.
|
|
*/
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/intel_tcc.h>
|
|
#include <linux/module.h>
|
|
#include <linux/thermal.h>
|
|
#include <asm/cpu_device_id.h>
|
|
#include <asm/msr.h>
|
|
|
|
#define TCC_PROGRAMMABLE BIT(30)
|
|
#define TCC_LOCKED BIT(31)
|
|
|
|
static struct thermal_cooling_device *tcc_cdev;
|
|
|
|
static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long
|
|
*state)
|
|
{
|
|
*state = intel_tcc_get_offset_mask();
|
|
return 0;
|
|
}
|
|
|
|
static int tcc_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
|
|
*state)
|
|
{
|
|
int offset = intel_tcc_get_offset(-1);
|
|
|
|
if (offset < 0)
|
|
return offset;
|
|
|
|
*state = offset;
|
|
return 0;
|
|
}
|
|
|
|
static int tcc_set_cur_state(struct thermal_cooling_device *cdev, unsigned long
|
|
state)
|
|
{
|
|
return intel_tcc_set_offset(-1, (int)state);
|
|
}
|
|
|
|
static const struct thermal_cooling_device_ops tcc_cooling_ops = {
|
|
.get_max_state = tcc_get_max_state,
|
|
.get_cur_state = tcc_get_cur_state,
|
|
.set_cur_state = tcc_set_cur_state,
|
|
};
|
|
|
|
static const struct x86_cpu_id tcc_ids[] __initconst = {
|
|
X86_MATCH_VFM(INTEL_SKYLAKE, NULL),
|
|
X86_MATCH_VFM(INTEL_SKYLAKE_L, NULL),
|
|
X86_MATCH_VFM(INTEL_KABYLAKE, NULL),
|
|
X86_MATCH_VFM(INTEL_KABYLAKE_L, NULL),
|
|
X86_MATCH_VFM(INTEL_ICELAKE, NULL),
|
|
X86_MATCH_VFM(INTEL_ICELAKE_L, NULL),
|
|
X86_MATCH_VFM(INTEL_TIGERLAKE, NULL),
|
|
X86_MATCH_VFM(INTEL_TIGERLAKE_L, NULL),
|
|
X86_MATCH_VFM(INTEL_COMETLAKE, NULL),
|
|
X86_MATCH_VFM(INTEL_ALDERLAKE, NULL),
|
|
X86_MATCH_VFM(INTEL_ALDERLAKE_L, NULL),
|
|
X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, NULL),
|
|
X86_MATCH_VFM(INTEL_RAPTORLAKE, NULL),
|
|
X86_MATCH_VFM(INTEL_RAPTORLAKE_P, NULL),
|
|
X86_MATCH_VFM(INTEL_RAPTORLAKE_S, NULL),
|
|
X86_MATCH_VFM(INTEL_PANTHERLAKE_L, NULL),
|
|
X86_MATCH_VFM(INTEL_WILDCATLAKE_L, NULL),
|
|
X86_MATCH_VFM(INTEL_NOVALAKE, NULL),
|
|
X86_MATCH_VFM(INTEL_NOVALAKE_L, NULL),
|
|
{}
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(x86cpu, tcc_ids);
|
|
|
|
static int __init tcc_cooling_init(void)
|
|
{
|
|
u64 val;
|
|
const struct x86_cpu_id *id;
|
|
int err;
|
|
|
|
id = x86_match_cpu(tcc_ids);
|
|
if (!id)
|
|
return -ENODEV;
|
|
|
|
err = rdmsrq_safe(MSR_PLATFORM_INFO, &val);
|
|
if (err)
|
|
return err;
|
|
|
|
if (!(val & TCC_PROGRAMMABLE))
|
|
return -ENODEV;
|
|
|
|
err = rdmsrq_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
|
|
if (err)
|
|
return err;
|
|
|
|
if (val & TCC_LOCKED) {
|
|
pr_info("TCC Offset locked\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
pr_info("Programmable TCC Offset detected\n");
|
|
|
|
tcc_cdev =
|
|
thermal_cooling_device_register("TCC Offset", NULL,
|
|
&tcc_cooling_ops);
|
|
if (IS_ERR(tcc_cdev))
|
|
return PTR_ERR(tcc_cdev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
module_init(tcc_cooling_init)
|
|
|
|
static void __exit tcc_cooling_exit(void)
|
|
{
|
|
thermal_cooling_device_unregister(tcc_cdev);
|
|
}
|
|
|
|
module_exit(tcc_cooling_exit)
|
|
|
|
MODULE_IMPORT_NS("INTEL_TCC");
|
|
MODULE_DESCRIPTION("TCC offset cooling device Driver");
|
|
MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
|
|
MODULE_LICENSE("GPL v2");
|