mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-15 22:41:38 +00:00
Depends on the interface used, the RAPL registers can be either MSR indexes or memory mapped IO addresses. Current RAPL common code uses u64 to save both MSR and memory mapped IO registers. With this, when handling register address with an __iomem annotation, it triggers a sparse warning like below: sparse warnings: (new ones prefixed by >>) >> drivers/powercap/intel_rapl_tpmi.c:141:41: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected unsigned long long [usertype] *tpmi_rapl_regs @@ got void [noderef] __iomem * @@ drivers/powercap/intel_rapl_tpmi.c:141:41: sparse: expected unsigned long long [usertype] *tpmi_rapl_regs drivers/powercap/intel_rapl_tpmi.c:141:41: sparse: got void [noderef] __iomem * Fix the problem by using a union to save the registers instead. Suggested-by: David Laight <David.Laight@ACULAB.COM> Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202307031405.dy3druuy-lkp@intel.com/ Tested-by: Wang Wendy <wendy.wang@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
136 lines
3.4 KiB
C
136 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] = BIT(POWER_LIMIT2),
|
|
.limits[RAPL_DOMAIN_DRAM] = BIT(POWER_LIMIT2),
|
|
};
|
|
|
|
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, true);
|
|
if (!rp) {
|
|
rp = rapl_add_package(cpu, &rapl_mmio_priv, true);
|
|
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, true);
|
|
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.mmio)
|
|
return -EINVAL;
|
|
|
|
ra->value = readq(ra->reg.mmio);
|
|
ra->value &= ra->mask;
|
|
return 0;
|
|
}
|
|
|
|
static int rapl_mmio_write_raw(int cpu, struct reg_action *ra)
|
|
{
|
|
u64 val;
|
|
|
|
if (!ra->reg.mmio)
|
|
return -EINVAL;
|
|
|
|
val = readq(ra->reg.mmio);
|
|
val &= ~ra->mask;
|
|
val |= ra->value;
|
|
writeq(val, ra->reg.mmio);
|
|
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].mmio =
|
|
proc_priv->mmio_base +
|
|
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.mmio = 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");
|