Merge branch 'powercap'
Merge power capping updates for 6.5-rc1: - Introduce power capping core support for Intel TPMI (Topology Aware Register and PM Capsule Interface) and a TPMI interface driver for Intel RAPL (Zhang Rui, Dan Carpenter). - Fix CONFIG_IOSF_MBI dependency in the Intel RAPL power capping driver (Zhang Rui). - Fix invalid initialization for pl4_supported field in the Intel RAPL power capping driver (Sumeet Pawnikar). * powercap: powercap: RAPL: Fix a NULL vs IS_ERR() bug powercap: RAPL: Fix CONFIG_IOSF_MBI dependency powercap: RAPL: fix invalid initialization for pl4_supported field powercap: intel_rapl: Introduce RAPL TPMI interface driver powercap: intel_rapl: Introduce core support for TPMI interface powercap: intel_rapl: Introduce RAPL I/F type powercap: intel_rapl: Make cpu optional for rapl_package powercap: intel_rapl: Remove redundant cpu parameter powercap: intel_rapl: Add support for lock bit per Power Limit powercap: intel_rapl: Cleanup Power Limits support powercap: intel_rapl: Use bitmap for Power Limits powercap: intel_rapl: Change primitive order powercap: intel_rapl: Use index to initialize primitive information powercap: intel_rapl: Support per domain energy/power/time unit powercap: intel_rapl: Support per Interface primitive information powercap: intel_rapl: Support per Interface rapl_defaults powercap: intel_rapl: Allow probing without CPUID match powercap: intel_rapl: Remove unused field in struct rapl_if_priv
This commit is contained in:
commit
c89a27f4f8
@ -18,10 +18,12 @@ if POWERCAP
|
||||
# Client driver configurations go here.
|
||||
config INTEL_RAPL_CORE
|
||||
tristate
|
||||
depends on PCI
|
||||
select IOSF_MBI
|
||||
|
||||
config INTEL_RAPL
|
||||
tristate "Intel RAPL Support via MSR Interface"
|
||||
depends on X86 && IOSF_MBI
|
||||
depends on X86 && PCI
|
||||
select INTEL_RAPL_CORE
|
||||
help
|
||||
This enables support for the Intel Running Average Power Limit (RAPL)
|
||||
@ -33,6 +35,20 @@ config INTEL_RAPL
|
||||
controller, CPU core (Power Plane 0), graphics uncore (Power Plane
|
||||
1), etc.
|
||||
|
||||
config INTEL_RAPL_TPMI
|
||||
tristate "Intel RAPL Support via TPMI Interface"
|
||||
depends on X86
|
||||
depends on INTEL_TPMI
|
||||
select INTEL_RAPL_CORE
|
||||
help
|
||||
This enables support for the Intel Running Average Power Limit (RAPL)
|
||||
technology via TPMI interface, which allows power limits to be enforced
|
||||
and monitored.
|
||||
|
||||
In RAPL, the platform level settings are divided into domains for
|
||||
fine grained control. These domains include processor package, DRAM
|
||||
controller, platform, etc.
|
||||
|
||||
config IDLE_INJECT
|
||||
bool "Idle injection framework"
|
||||
depends on CPU_IDLE
|
||||
|
@ -5,5 +5,6 @@ obj-$(CONFIG_DTPM_DEVFREQ) += dtpm_devfreq.o
|
||||
obj-$(CONFIG_POWERCAP) += powercap_sys.o
|
||||
obj-$(CONFIG_INTEL_RAPL_CORE) += intel_rapl_common.o
|
||||
obj-$(CONFIG_INTEL_RAPL) += intel_rapl_msr.o
|
||||
obj-$(CONFIG_INTEL_RAPL_TPMI) += intel_rapl_tpmi.o
|
||||
obj-$(CONFIG_IDLE_INJECT) += idle_inject.o
|
||||
obj-$(CONFIG_ARM_SCMI_POWERCAP) += arm_scmi_powercap.o
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,6 @@
|
||||
#include <linux/processor.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/iosf_mbi.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/intel-family.h>
|
||||
|
||||
@ -34,6 +33,7 @@
|
||||
static struct rapl_if_priv *rapl_msr_priv;
|
||||
|
||||
static struct rapl_if_priv rapl_msr_priv_intel = {
|
||||
.type = RAPL_IF_MSR,
|
||||
.reg_unit = MSR_RAPL_POWER_UNIT,
|
||||
.regs[RAPL_DOMAIN_PACKAGE] = {
|
||||
MSR_PKG_POWER_LIMIT, MSR_PKG_ENERGY_STATUS, MSR_PKG_PERF_STATUS, 0, MSR_PKG_POWER_INFO },
|
||||
@ -45,11 +45,12 @@ static struct rapl_if_priv rapl_msr_priv_intel = {
|
||||
MSR_DRAM_POWER_LIMIT, MSR_DRAM_ENERGY_STATUS, MSR_DRAM_PERF_STATUS, 0, MSR_DRAM_POWER_INFO },
|
||||
.regs[RAPL_DOMAIN_PLATFORM] = {
|
||||
MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0},
|
||||
.limits[RAPL_DOMAIN_PACKAGE] = 2,
|
||||
.limits[RAPL_DOMAIN_PLATFORM] = 2,
|
||||
.limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2),
|
||||
.limits[RAPL_DOMAIN_PLATFORM] = BIT(POWER_LIMIT2),
|
||||
};
|
||||
|
||||
static struct rapl_if_priv rapl_msr_priv_amd = {
|
||||
.type = RAPL_IF_MSR,
|
||||
.reg_unit = MSR_AMD_RAPL_POWER_UNIT,
|
||||
.regs[RAPL_DOMAIN_PACKAGE] = {
|
||||
0, MSR_AMD_PKG_ENERGY_STATUS, 0, 0, 0 },
|
||||
@ -68,9 +69,9 @@ static int rapl_cpu_online(unsigned int cpu)
|
||||
{
|
||||
struct rapl_package *rp;
|
||||
|
||||
rp = rapl_find_package_domain(cpu, rapl_msr_priv);
|
||||
rp = rapl_find_package_domain(cpu, rapl_msr_priv, true);
|
||||
if (!rp) {
|
||||
rp = rapl_add_package(cpu, rapl_msr_priv);
|
||||
rp = rapl_add_package(cpu, rapl_msr_priv, true);
|
||||
if (IS_ERR(rp))
|
||||
return PTR_ERR(rp);
|
||||
}
|
||||
@ -83,7 +84,7 @@ static int rapl_cpu_down_prep(unsigned int cpu)
|
||||
struct rapl_package *rp;
|
||||
int lead_cpu;
|
||||
|
||||
rp = rapl_find_package_domain(cpu, rapl_msr_priv);
|
||||
rp = rapl_find_package_domain(cpu, rapl_msr_priv, true);
|
||||
if (!rp)
|
||||
return 0;
|
||||
|
||||
@ -137,14 +138,14 @@ static int rapl_msr_write_raw(int cpu, struct reg_action *ra)
|
||||
|
||||
/* List of verified CPUs. */
|
||||
static const struct x86_cpu_id pl4_support_ids[] = {
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_TIGERLAKE_L, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE_L, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE_N, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_RAPTORLAKE, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_RAPTORLAKE_P, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_METEORLAKE, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_METEORLAKE_L, X86_FEATURE_ANY },
|
||||
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, NULL),
|
||||
X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE_L, NULL),
|
||||
{}
|
||||
};
|
||||
|
||||
@ -169,7 +170,7 @@ static int rapl_msr_probe(struct platform_device *pdev)
|
||||
rapl_msr_priv->write_raw = rapl_msr_write_raw;
|
||||
|
||||
if (id) {
|
||||
rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] = 3;
|
||||
rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] |= BIT(POWER_LIMIT4);
|
||||
rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] =
|
||||
MSR_VR_CURRENT_CONFIG;
|
||||
pr_info("PL4 support detected.\n");
|
||||
|
325
drivers/powercap/intel_rapl_tpmi.c
Normal file
325
drivers/powercap/intel_rapl_tpmi.c
Normal file
@ -0,0 +1,325 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* intel_rapl_tpmi: Intel RAPL driver via TPMI interface
|
||||
*
|
||||
* Copyright (c) 2023, Intel Corporation.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/intel_tpmi.h>
|
||||
#include <linux/intel_rapl.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define TPMI_RAPL_VERSION 1
|
||||
|
||||
/* 1 header + 10 registers + 5 reserved. 8 bytes for each. */
|
||||
#define TPMI_RAPL_DOMAIN_SIZE 128
|
||||
|
||||
enum tpmi_rapl_domain_type {
|
||||
TPMI_RAPL_DOMAIN_INVALID,
|
||||
TPMI_RAPL_DOMAIN_SYSTEM,
|
||||
TPMI_RAPL_DOMAIN_PACKAGE,
|
||||
TPMI_RAPL_DOMAIN_RESERVED,
|
||||
TPMI_RAPL_DOMAIN_MEMORY,
|
||||
TPMI_RAPL_DOMAIN_MAX,
|
||||
};
|
||||
|
||||
enum tpmi_rapl_register {
|
||||
TPMI_RAPL_REG_HEADER,
|
||||
TPMI_RAPL_REG_UNIT,
|
||||
TPMI_RAPL_REG_PL1,
|
||||
TPMI_RAPL_REG_PL2,
|
||||
TPMI_RAPL_REG_PL3,
|
||||
TPMI_RAPL_REG_PL4,
|
||||
TPMI_RAPL_REG_RESERVED,
|
||||
TPMI_RAPL_REG_ENERGY_STATUS,
|
||||
TPMI_RAPL_REG_PERF_STATUS,
|
||||
TPMI_RAPL_REG_POWER_INFO,
|
||||
TPMI_RAPL_REG_INTERRUPT,
|
||||
TPMI_RAPL_REG_MAX = 15,
|
||||
};
|
||||
|
||||
struct tpmi_rapl_package {
|
||||
struct rapl_if_priv priv;
|
||||
struct intel_tpmi_plat_info *tpmi_info;
|
||||
struct rapl_package *rp;
|
||||
void __iomem *base;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
static LIST_HEAD(tpmi_rapl_packages);
|
||||
static DEFINE_MUTEX(tpmi_rapl_lock);
|
||||
|
||||
static struct powercap_control_type *tpmi_control_type;
|
||||
|
||||
static int tpmi_rapl_read_raw(int id, struct reg_action *ra)
|
||||
{
|
||||
if (!ra->reg)
|
||||
return -EINVAL;
|
||||
|
||||
ra->value = readq((void __iomem *)ra->reg);
|
||||
|
||||
ra->value &= ra->mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tpmi_rapl_write_raw(int id, struct reg_action *ra)
|
||||
{
|
||||
u64 val;
|
||||
|
||||
if (!ra->reg)
|
||||
return -EINVAL;
|
||||
|
||||
val = readq((void __iomem *)ra->reg);
|
||||
|
||||
val &= ~ra->mask;
|
||||
val |= ra->value;
|
||||
|
||||
writeq(val, (void __iomem *)ra->reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tpmi_rapl_package *trp_alloc(int pkg_id)
|
||||
{
|
||||
struct tpmi_rapl_package *trp;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&tpmi_rapl_lock);
|
||||
|
||||
if (list_empty(&tpmi_rapl_packages)) {
|
||||
tpmi_control_type = powercap_register_control_type(NULL, "intel-rapl", NULL);
|
||||
if (IS_ERR(tpmi_control_type)) {
|
||||
ret = PTR_ERR(tpmi_control_type);
|
||||
goto err_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
trp = kzalloc(sizeof(*trp), GFP_KERNEL);
|
||||
if (!trp) {
|
||||
ret = -ENOMEM;
|
||||
goto err_del_powercap;
|
||||
}
|
||||
|
||||
list_add(&trp->node, &tpmi_rapl_packages);
|
||||
|
||||
mutex_unlock(&tpmi_rapl_lock);
|
||||
return trp;
|
||||
|
||||
err_del_powercap:
|
||||
if (list_empty(&tpmi_rapl_packages))
|
||||
powercap_unregister_control_type(tpmi_control_type);
|
||||
err_unlock:
|
||||
mutex_unlock(&tpmi_rapl_lock);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static void trp_release(struct tpmi_rapl_package *trp)
|
||||
{
|
||||
mutex_lock(&tpmi_rapl_lock);
|
||||
list_del(&trp->node);
|
||||
|
||||
if (list_empty(&tpmi_rapl_packages))
|
||||
powercap_unregister_control_type(tpmi_control_type);
|
||||
|
||||
kfree(trp);
|
||||
mutex_unlock(&tpmi_rapl_lock);
|
||||
}
|
||||
|
||||
static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset)
|
||||
{
|
||||
u8 tpmi_domain_version;
|
||||
enum rapl_domain_type domain_type;
|
||||
enum tpmi_rapl_domain_type tpmi_domain_type;
|
||||
enum tpmi_rapl_register reg_index;
|
||||
enum rapl_domain_reg_id reg_id;
|
||||
int tpmi_domain_size, tpmi_domain_flags;
|
||||
u64 *tpmi_rapl_regs = trp->base + offset;
|
||||
u64 tpmi_domain_header = readq((void __iomem *)tpmi_rapl_regs);
|
||||
|
||||
/* Domain Parent bits are ignored for now */
|
||||
tpmi_domain_version = tpmi_domain_header & 0xff;
|
||||
tpmi_domain_type = tpmi_domain_header >> 8 & 0xff;
|
||||
tpmi_domain_size = tpmi_domain_header >> 16 & 0xff;
|
||||
tpmi_domain_flags = tpmi_domain_header >> 32 & 0xffff;
|
||||
|
||||
if (tpmi_domain_version != TPMI_RAPL_VERSION) {
|
||||
pr_warn(FW_BUG "Unsupported version:%d\n", tpmi_domain_version);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Domain size: in unit of 128 Bytes */
|
||||
if (tpmi_domain_size != 1) {
|
||||
pr_warn(FW_BUG "Invalid Domain size %d\n", tpmi_domain_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Unit register and Energy Status register are mandatory for each domain */
|
||||
if (!(tpmi_domain_flags & BIT(TPMI_RAPL_REG_UNIT)) ||
|
||||
!(tpmi_domain_flags & BIT(TPMI_RAPL_REG_ENERGY_STATUS))) {
|
||||
pr_warn(FW_BUG "Invalid Domain flag 0x%x\n", tpmi_domain_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (tpmi_domain_type) {
|
||||
case TPMI_RAPL_DOMAIN_PACKAGE:
|
||||
domain_type = RAPL_DOMAIN_PACKAGE;
|
||||
break;
|
||||
case TPMI_RAPL_DOMAIN_SYSTEM:
|
||||
domain_type = RAPL_DOMAIN_PLATFORM;
|
||||
break;
|
||||
case TPMI_RAPL_DOMAIN_MEMORY:
|
||||
domain_type = RAPL_DOMAIN_DRAM;
|
||||
break;
|
||||
default:
|
||||
pr_warn(FW_BUG "Unsupported Domain type %d\n", tpmi_domain_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (trp->priv.regs[domain_type][RAPL_DOMAIN_REG_UNIT]) {
|
||||
pr_warn(FW_BUG "Duplicate Domain type %d\n", tpmi_domain_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reg_index = TPMI_RAPL_REG_HEADER;
|
||||
while (++reg_index != TPMI_RAPL_REG_MAX) {
|
||||
if (!(tpmi_domain_flags & BIT(reg_index)))
|
||||
continue;
|
||||
|
||||
switch (reg_index) {
|
||||
case TPMI_RAPL_REG_UNIT:
|
||||
reg_id = RAPL_DOMAIN_REG_UNIT;
|
||||
break;
|
||||
case TPMI_RAPL_REG_PL1:
|
||||
reg_id = RAPL_DOMAIN_REG_LIMIT;
|
||||
trp->priv.limits[domain_type] |= BIT(POWER_LIMIT1);
|
||||
break;
|
||||
case TPMI_RAPL_REG_PL2:
|
||||
reg_id = RAPL_DOMAIN_REG_PL2;
|
||||
trp->priv.limits[domain_type] |= BIT(POWER_LIMIT2);
|
||||
break;
|
||||
case TPMI_RAPL_REG_PL4:
|
||||
reg_id = RAPL_DOMAIN_REG_PL4;
|
||||
trp->priv.limits[domain_type] |= BIT(POWER_LIMIT4);
|
||||
break;
|
||||
case TPMI_RAPL_REG_ENERGY_STATUS:
|
||||
reg_id = RAPL_DOMAIN_REG_STATUS;
|
||||
break;
|
||||
case TPMI_RAPL_REG_PERF_STATUS:
|
||||
reg_id = RAPL_DOMAIN_REG_PERF;
|
||||
break;
|
||||
case TPMI_RAPL_REG_POWER_INFO:
|
||||
reg_id = RAPL_DOMAIN_REG_INFO;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
trp->priv.regs[domain_type][reg_id] = (u64)&tpmi_rapl_regs[reg_index];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_rapl_tpmi_probe(struct auxiliary_device *auxdev,
|
||||
const struct auxiliary_device_id *id)
|
||||
{
|
||||
struct tpmi_rapl_package *trp;
|
||||
struct intel_tpmi_plat_info *info;
|
||||
struct resource *res;
|
||||
u32 offset;
|
||||
int ret;
|
||||
|
||||
info = tpmi_get_platform_data(auxdev);
|
||||
if (!info)
|
||||
return -ENODEV;
|
||||
|
||||
trp = trp_alloc(info->package_id);
|
||||
if (IS_ERR(trp))
|
||||
return PTR_ERR(trp);
|
||||
|
||||
if (tpmi_get_resource_count(auxdev) > 1) {
|
||||
dev_err(&auxdev->dev, "does not support multiple resources\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
res = tpmi_get_resource_at_index(auxdev, 0);
|
||||
if (!res) {
|
||||
dev_err(&auxdev->dev, "can't fetch device resource info\n");
|
||||
ret = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
trp->base = devm_ioremap_resource(&auxdev->dev, res);
|
||||
if (IS_ERR(trp->base)) {
|
||||
ret = PTR_ERR(trp->base);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (offset = 0; offset < resource_size(res); offset += TPMI_RAPL_DOMAIN_SIZE) {
|
||||
ret = parse_one_domain(trp, offset);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
trp->tpmi_info = info;
|
||||
trp->priv.type = RAPL_IF_TPMI;
|
||||
trp->priv.read_raw = tpmi_rapl_read_raw;
|
||||
trp->priv.write_raw = tpmi_rapl_write_raw;
|
||||
trp->priv.control_type = tpmi_control_type;
|
||||
|
||||
/* RAPL TPMI I/F is per physical package */
|
||||
trp->rp = rapl_find_package_domain(info->package_id, &trp->priv, false);
|
||||
if (trp->rp) {
|
||||
dev_err(&auxdev->dev, "Domain for Package%d already exists\n", info->package_id);
|
||||
ret = -EEXIST;
|
||||
goto err;
|
||||
}
|
||||
|
||||
trp->rp = rapl_add_package(info->package_id, &trp->priv, false);
|
||||
if (IS_ERR(trp->rp)) {
|
||||
dev_err(&auxdev->dev, "Failed to add RAPL Domain for Package%d, %ld\n",
|
||||
info->package_id, PTR_ERR(trp->rp));
|
||||
ret = PTR_ERR(trp->rp);
|
||||
goto err;
|
||||
}
|
||||
|
||||
auxiliary_set_drvdata(auxdev, trp);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
trp_release(trp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void intel_rapl_tpmi_remove(struct auxiliary_device *auxdev)
|
||||
{
|
||||
struct tpmi_rapl_package *trp = auxiliary_get_drvdata(auxdev);
|
||||
|
||||
rapl_remove_package(trp->rp);
|
||||
trp_release(trp);
|
||||
}
|
||||
|
||||
static const struct auxiliary_device_id intel_rapl_tpmi_ids[] = {
|
||||
{.name = "intel_vsec.tpmi-rapl" },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(auxiliary, intel_rapl_tpmi_ids);
|
||||
|
||||
static struct auxiliary_driver intel_rapl_tpmi_driver = {
|
||||
.probe = intel_rapl_tpmi_probe,
|
||||
.remove = intel_rapl_tpmi_remove,
|
||||
.id_table = intel_rapl_tpmi_ids,
|
||||
};
|
||||
|
||||
module_auxiliary_driver(intel_rapl_tpmi_driver)
|
||||
|
||||
MODULE_IMPORT_NS(INTEL_TPMI);
|
||||
|
||||
MODULE_DESCRIPTION("Intel RAPL TPMI Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -15,8 +15,8 @@ static const struct rapl_mmio_regs rapl_mmio_default = {
|
||||
.reg_unit = 0x5938,
|
||||
.regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930},
|
||||
.regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0},
|
||||
.limits[RAPL_DOMAIN_PACKAGE] = 2,
|
||||
.limits[RAPL_DOMAIN_DRAM] = 2,
|
||||
.limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2),
|
||||
.limits[RAPL_DOMAIN_DRAM] = BIT(POWER_LIMIT2),
|
||||
};
|
||||
|
||||
static int rapl_mmio_cpu_online(unsigned int cpu)
|
||||
@ -27,9 +27,9 @@ static int rapl_mmio_cpu_online(unsigned int cpu)
|
||||
if (topology_physical_package_id(cpu))
|
||||
return 0;
|
||||
|
||||
rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
|
||||
rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true);
|
||||
if (!rp) {
|
||||
rp = rapl_add_package(cpu, &rapl_mmio_priv);
|
||||
rp = rapl_add_package(cpu, &rapl_mmio_priv, true);
|
||||
if (IS_ERR(rp))
|
||||
return PTR_ERR(rp);
|
||||
}
|
||||
@ -42,7 +42,7 @@ static int rapl_mmio_cpu_down_prep(unsigned int cpu)
|
||||
struct rapl_package *rp;
|
||||
int lead_cpu;
|
||||
|
||||
rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
|
||||
rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true);
|
||||
if (!rp)
|
||||
return 0;
|
||||
|
||||
@ -97,6 +97,7 @@ int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc
|
||||
rapl_regs->regs[domain][reg];
|
||||
rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain];
|
||||
}
|
||||
rapl_mmio_priv.type = RAPL_IF_MMIO;
|
||||
rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit;
|
||||
|
||||
rapl_mmio_priv.read_raw = rapl_mmio_read_raw;
|
||||
|
@ -14,6 +14,12 @@
|
||||
#include <linux/powercap.h>
|
||||
#include <linux/cpuhotplug.h>
|
||||
|
||||
enum rapl_if_type {
|
||||
RAPL_IF_MSR, /* RAPL I/F using MSR registers */
|
||||
RAPL_IF_MMIO, /* RAPL I/F using MMIO registers */
|
||||
RAPL_IF_TPMI, /* RAPL I/F using TPMI registers */
|
||||
};
|
||||
|
||||
enum rapl_domain_type {
|
||||
RAPL_DOMAIN_PACKAGE, /* entire package/socket */
|
||||
RAPL_DOMAIN_PP0, /* core power plane */
|
||||
@ -30,17 +36,23 @@ enum rapl_domain_reg_id {
|
||||
RAPL_DOMAIN_REG_POLICY,
|
||||
RAPL_DOMAIN_REG_INFO,
|
||||
RAPL_DOMAIN_REG_PL4,
|
||||
RAPL_DOMAIN_REG_UNIT,
|
||||
RAPL_DOMAIN_REG_PL2,
|
||||
RAPL_DOMAIN_REG_MAX,
|
||||
};
|
||||
|
||||
struct rapl_domain;
|
||||
|
||||
enum rapl_primitives {
|
||||
ENERGY_COUNTER,
|
||||
POWER_LIMIT1,
|
||||
POWER_LIMIT2,
|
||||
POWER_LIMIT4,
|
||||
ENERGY_COUNTER,
|
||||
FW_LOCK,
|
||||
FW_HIGH_LOCK,
|
||||
PL1_LOCK,
|
||||
PL2_LOCK,
|
||||
PL4_LOCK,
|
||||
|
||||
PL1_ENABLE, /* power limit 1, aka long term */
|
||||
PL1_CLAMP, /* allow frequency to go below OS request */
|
||||
@ -74,12 +86,13 @@ struct rapl_domain_data {
|
||||
unsigned long timestamp;
|
||||
};
|
||||
|
||||
#define NR_POWER_LIMITS (3)
|
||||
#define NR_POWER_LIMITS (POWER_LIMIT4 + 1)
|
||||
|
||||
struct rapl_power_limit {
|
||||
struct powercap_zone_constraint *constraint;
|
||||
int prim_id; /* primitive ID used to enable */
|
||||
struct rapl_domain *domain;
|
||||
const char *name;
|
||||
bool locked;
|
||||
u64 last_power_limit;
|
||||
};
|
||||
|
||||
@ -96,7 +109,9 @@ struct rapl_domain {
|
||||
struct rapl_power_limit rpl[NR_POWER_LIMITS];
|
||||
u64 attr_map; /* track capabilities */
|
||||
unsigned int state;
|
||||
unsigned int domain_energy_unit;
|
||||
unsigned int power_unit;
|
||||
unsigned int energy_unit;
|
||||
unsigned int time_unit;
|
||||
struct rapl_package *rp;
|
||||
};
|
||||
|
||||
@ -121,16 +136,20 @@ struct reg_action {
|
||||
* registers.
|
||||
* @write_raw: Callback for writing RAPL interface specific
|
||||
* registers.
|
||||
* @defaults: internal pointer to interface default settings
|
||||
* @rpi: internal pointer to interface primitive info
|
||||
*/
|
||||
struct rapl_if_priv {
|
||||
enum rapl_if_type type;
|
||||
struct powercap_control_type *control_type;
|
||||
struct rapl_domain *platform_rapl_domain;
|
||||
enum cpuhp_state pcap_rapl_online;
|
||||
u64 reg_unit;
|
||||
u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX];
|
||||
int limits[RAPL_DOMAIN_MAX];
|
||||
int (*read_raw)(int cpu, struct reg_action *ra);
|
||||
int (*write_raw)(int cpu, struct reg_action *ra);
|
||||
int (*read_raw)(int id, struct reg_action *ra);
|
||||
int (*write_raw)(int id, struct reg_action *ra);
|
||||
void *defaults;
|
||||
void *rpi;
|
||||
};
|
||||
|
||||
/* maximum rapl package domain name: package-%d-die-%d */
|
||||
@ -140,9 +159,6 @@ struct rapl_package {
|
||||
unsigned int id; /* logical die id, equals physical 1-die systems */
|
||||
unsigned int nr_domains;
|
||||
unsigned long domain_map; /* bit map of active domains */
|
||||
unsigned int power_unit;
|
||||
unsigned int energy_unit;
|
||||
unsigned int time_unit;
|
||||
struct rapl_domain *domains; /* array of domains, sized at runtime */
|
||||
struct powercap_zone *power_zone; /* keep track of parent zone */
|
||||
unsigned long power_limit_irq; /* keep track of package power limit
|
||||
@ -156,8 +172,8 @@ struct rapl_package {
|
||||
struct rapl_if_priv *priv;
|
||||
};
|
||||
|
||||
struct rapl_package *rapl_find_package_domain(int cpu, struct rapl_if_priv *priv);
|
||||
struct rapl_package *rapl_add_package(int cpu, struct rapl_if_priv *priv);
|
||||
struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu);
|
||||
struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu);
|
||||
void rapl_remove_package(struct rapl_package *rp);
|
||||
|
||||
#endif /* __INTEL_RAPL_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user