a5923b6c31
The Processor Thermal PCI device supports multiple features. Currently we export only RAPL. But we need more features from this device exposed for Tiger Lake and Alder Lake based platforms. So re-structure the current MMIO interface, so that more features can be added cleanly. No functional changes are expected with this change. Changes done in this patch: - Using PCI_DEVICE_DATA(), hence names of defines changed - Move RAPL MMIO code to its own module - Move the RAPL MMIO offsets to RAPL MMIO module - Adjust Kconfig dependency of PROC_THERMAL_MMIO_RAPL - Per processor driver data now contains the supported features - Moved all the common data structures and defines to a common header file - This new header file contains all the processor_thermal_* interfaces - Based on the features supported the module interface is called - Each module atleast provides one add and one remove function Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20201126171829.945969-1-srinivas.pandruvada@linux.intel.com
135 lines
3.4 KiB
C
135 lines
3.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* processor thermal device RFIM control
|
|
* Copyright (c) 2020, Intel Corporation.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/pci.h>
|
|
#include "processor_thermal_device.h"
|
|
|
|
static struct rapl_if_priv rapl_mmio_priv;
|
|
|
|
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,
|
|
};
|
|
|
|
static int rapl_mmio_cpu_online(unsigned int cpu)
|
|
{
|
|
struct rapl_package *rp;
|
|
|
|
/* mmio rapl supports package 0 only for now */
|
|
if (topology_physical_package_id(cpu))
|
|
return 0;
|
|
|
|
rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
|
|
if (!rp) {
|
|
rp = rapl_add_package(cpu, &rapl_mmio_priv);
|
|
if (IS_ERR(rp))
|
|
return PTR_ERR(rp);
|
|
}
|
|
cpumask_set_cpu(cpu, &rp->cpumask);
|
|
return 0;
|
|
}
|
|
|
|
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);
|
|
if (!rp)
|
|
return 0;
|
|
|
|
cpumask_clear_cpu(cpu, &rp->cpumask);
|
|
lead_cpu = cpumask_first(&rp->cpumask);
|
|
if (lead_cpu >= nr_cpu_ids)
|
|
rapl_remove_package(rp);
|
|
else if (rp->lead_cpu == cpu)
|
|
rp->lead_cpu = lead_cpu;
|
|
return 0;
|
|
}
|
|
|
|
static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
|
|
{
|
|
if (!ra->reg)
|
|
return -EINVAL;
|
|
|
|
ra->value = readq((void __iomem *)ra->reg);
|
|
ra->value &= ra->mask;
|
|
return 0;
|
|
}
|
|
|
|
static int rapl_mmio_write_raw(int cpu, 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;
|
|
}
|
|
|
|
int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
|
|
{
|
|
const struct rapl_mmio_regs *rapl_regs = &rapl_mmio_default;
|
|
enum rapl_domain_reg_id reg;
|
|
enum rapl_domain_type domain;
|
|
int ret;
|
|
|
|
if (!rapl_regs)
|
|
return 0;
|
|
|
|
for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) {
|
|
for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++)
|
|
if (rapl_regs->regs[domain][reg])
|
|
rapl_mmio_priv.regs[domain][reg] =
|
|
(u64)proc_priv->mmio_base +
|
|
rapl_regs->regs[domain][reg];
|
|
rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain];
|
|
}
|
|
rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit;
|
|
|
|
rapl_mmio_priv.read_raw = rapl_mmio_read_raw;
|
|
rapl_mmio_priv.write_raw = rapl_mmio_write_raw;
|
|
|
|
rapl_mmio_priv.control_type = powercap_register_control_type(NULL, "intel-rapl-mmio", NULL);
|
|
if (IS_ERR(rapl_mmio_priv.control_type)) {
|
|
pr_debug("failed to register powercap control_type.\n");
|
|
return PTR_ERR(rapl_mmio_priv.control_type);
|
|
}
|
|
|
|
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online",
|
|
rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep);
|
|
if (ret < 0) {
|
|
powercap_unregister_control_type(rapl_mmio_priv.control_type);
|
|
rapl_mmio_priv.control_type = NULL;
|
|
return ret;
|
|
}
|
|
rapl_mmio_priv.pcap_rapl_online = ret;
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(proc_thermal_rapl_add);
|
|
|
|
void proc_thermal_rapl_remove(void)
|
|
{
|
|
if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type))
|
|
return;
|
|
|
|
cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online);
|
|
powercap_unregister_control_type(rapl_mmio_priv.control_type);
|
|
}
|
|
EXPORT_SYMBOL_GPL(proc_thermal_rapl_remove);
|
|
|
|
MODULE_LICENSE("GPL v2");
|