Messages in this thread | | | Subject | Re: [PATCH 1/4] thermal: int340x: processor_thermal: Refactor MMIO interface | From | Srinivas Pandruvada <> | Date | Wed, 09 Dec 2020 08:15:28 -0800 |
| |
On Thu, 2020-11-26 at 09:18 -0800, Srinivas Pandruvada wrote: > 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. > Any objection for this series for 5.11?
Thanks, Srinivas
> 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> > --- > drivers/thermal/intel/int340x_thermal/Kconfig | 6 +- > .../thermal/intel/int340x_thermal/Makefile | 1 + > .../processor_thermal_device.c | 261 ++++---------- > ---- > .../processor_thermal_device.h | 72 +++++ > .../int340x_thermal/processor_thermal_rapl.c | 134 +++++++++ > 5 files changed, 263 insertions(+), 211 deletions(-) > create mode 100644 > drivers/thermal/intel/int340x_thermal/processor_thermal_device.h > create mode 100644 > drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c > > diff --git a/drivers/thermal/intel/int340x_thermal/Kconfig > b/drivers/thermal/intel/int340x_thermal/Kconfig > index 797907542e43..45c31f3d6054 100644 > --- a/drivers/thermal/intel/int340x_thermal/Kconfig > +++ b/drivers/thermal/intel/int340x_thermal/Kconfig > @@ -10,6 +10,7 @@ config INT340X_THERMAL > select ACPI_THERMAL_REL > select ACPI_FAN > select INTEL_SOC_DTS_IOSF_CORE > + select PROC_THERMAL_MMIO_RAPL if X86_64 && POWERCAP > help > Newer laptops and tablets that use ACPI may have thermal > sensors and > other devices with thermal control capabilities outside the > core > @@ -41,9 +42,6 @@ config INT3406_THERMAL > power consumed by display device. > > config PROC_THERMAL_MMIO_RAPL > - bool > - depends on 64BIT > - depends on POWERCAP > + tristate > select INTEL_RAPL_CORE > - default y > endif > diff --git a/drivers/thermal/intel/int340x_thermal/Makefile > b/drivers/thermal/intel/int340x_thermal/Makefile > index 287eb0a1476d..86e8d3c87df7 100644 > --- a/drivers/thermal/intel/int340x_thermal/Makefile > +++ b/drivers/thermal/intel/int340x_thermal/Makefile > @@ -4,5 +4,6 @@ obj-$(CONFIG_INT340X_THERMAL) += > int340x_thermal_zone.o > obj-$(CONFIG_INT340X_THERMAL) += int3402_thermal.o > obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o > obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device.o > +obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o > obj-$(CONFIG_INT3406_THERMAL) += int3406_thermal.o > obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o > diff --git > a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c > b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c > index 81e8b15ef405..5b8dc5e9ec86 100644 > --- > a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c > +++ > b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c > @@ -12,74 +12,18 @@ > #include <linux/acpi.h> > #include <linux/thermal.h> > #include <linux/cpuhotplug.h> > -#include <linux/intel_rapl.h> > #include "int340x_thermal_zone.h" > +#include "processor_thermal_device.h" > #include "../intel_soc_dts_iosf.h" > > -/* Broadwell-U/HSB thermal reporting device */ > -#define PCI_DEVICE_ID_PROC_BDW_THERMAL 0x1603 > -#define PCI_DEVICE_ID_PROC_HSB_THERMAL 0x0A03 > - > -/* Skylake thermal reporting device */ > -#define PCI_DEVICE_ID_PROC_SKL_THERMAL 0x1903 > - > -/* CannonLake thermal reporting device */ > -#define PCI_DEVICE_ID_PROC_CNL_THERMAL 0x5a03 > -#define PCI_DEVICE_ID_PROC_CFL_THERMAL 0x3E83 > - > -/* Braswell thermal reporting device */ > -#define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC > - > -/* Broxton thermal reporting device */ > -#define PCI_DEVICE_ID_PROC_BXT0_THERMAL 0x0A8C > -#define PCI_DEVICE_ID_PROC_BXT1_THERMAL 0x1A8C > -#define PCI_DEVICE_ID_PROC_BXTX_THERMAL 0x4A8C > -#define PCI_DEVICE_ID_PROC_BXTP_THERMAL 0x5A8C > - > -/* GeminiLake thermal reporting device */ > -#define PCI_DEVICE_ID_PROC_GLK_THERMAL 0x318C > - > -/* IceLake thermal reporting device */ > -#define PCI_DEVICE_ID_PROC_ICL_THERMAL 0x8a03 > - > -/* JasperLake thermal reporting device */ > -#define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4E03 > - > -/* TigerLake thermal reporting device */ > -#define PCI_DEVICE_ID_PROC_TGL_THERMAL 0x9A03 > - > #define DRV_NAME "proc_thermal" > > -struct power_config { > - u32 index; > - u32 min_uw; > - u32 max_uw; > - u32 tmin_us; > - u32 tmax_us; > - u32 step_uw; > -}; > - > -struct proc_thermal_device { > - struct device *dev; > - struct acpi_device *adev; > - struct power_config power_limits[2]; > - struct int34x_thermal_zone *int340x_zone; > - struct intel_soc_dts_sensors *soc_dts; > - void __iomem *mmio_base; > -}; > - > enum proc_thermal_emum_mode_type { > PROC_THERMAL_NONE, > PROC_THERMAL_PCI, > PROC_THERMAL_PLATFORM_DEV > }; > > -struct rapl_mmio_regs { > - u64 reg_unit; > - u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX]; > - int limits[RAPL_DOMAIN_MAX]; > -}; > - > /* > * We can have only one type of enumeration, PCI or Platform, > * not both. So we don't need instance specific data. > @@ -461,84 +405,13 @@ static irqreturn_t proc_thermal_pci_msi_irq(int > irq, void *devid) > return IRQ_HANDLED; > } > > -#ifdef CONFIG_PROC_THERMAL_MMIO_RAPL > - > #define MCHBAR 0 > > -/* RAPL Support via MMIO interface */ > -static struct rapl_if_priv rapl_mmio_priv; > - > -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) > +static int proc_thermal_set_mmio_base(struct pci_dev *pdev, > + struct proc_thermal_device > *proc_priv) > { > - 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; > -} > - > -static int proc_thermal_rapl_add(struct pci_dev *pdev, > - struct proc_thermal_device *proc_priv, > - struct rapl_mmio_regs *rapl_regs) > -{ > - enum rapl_domain_reg_id reg; > - enum rapl_domain_type domain; > int ret; > > - if (!rapl_regs) > - return 0; > - > ret = pcim_iomap_regions(pdev, 1 << MCHBAR, DRV_NAME); > if (ret) { > dev_err(&pdev->dev, "cannot reserve PCI memory > region\n"); > @@ -547,66 +420,42 @@ static int proc_thermal_rapl_add(struct pci_dev > *pdev, > > proc_priv->mmio_base = pcim_iomap_table(pdev)[MCHBAR]; > > - 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; > + return 0; > +} > > - rapl_mmio_priv.read_raw = rapl_mmio_read_raw; > - rapl_mmio_priv.write_raw = rapl_mmio_write_raw; > +static int proc_thermal_mmio_add(struct pci_dev *pdev, > + struct proc_thermal_device *proc_priv, > + kernel_ulong_t feature_mask) > +{ > + int ret; > > - 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); > + if (feature_mask) { > + ret = proc_thermal_set_mmio_base(pdev, proc_priv); > + if (ret) > + return ret; > } > > - 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; > + if (feature_mask & PROC_THERMAL_FEATURE_RAPL) { > + ret = proc_thermal_rapl_add(pdev, proc_priv); > + if (ret) { > + dev_err(&pdev->dev, "failed to add RAPL MMIO > interface\n"); > + return ret; > + } > } > - rapl_mmio_priv.pcap_rapl_online = ret; > + > + proc_priv->mmio_feature_mask = feature_mask; > > return 0; > } > > -static void proc_thermal_rapl_remove(void) > +static void proc_thermal_mmio_remove(struct pci_dev *pdev) > { > - 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); > -} > + struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); > > -static const struct rapl_mmio_regs rapl_mmio_hsw = { > - .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, > -}; > + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_RAPL) > + proc_thermal_rapl_remove(); > > -#else > - > -static int proc_thermal_rapl_add(struct pci_dev *pdev, > - struct proc_thermal_device *proc_priv, > - struct rapl_mmio_regs *rapl_regs) > -{ > - return 0; > } > -static void proc_thermal_rapl_remove(void) {} > -static const struct rapl_mmio_regs rapl_mmio_hsw; > - > -#endif /* CONFIG_MMIO_RAPL */ > > static int proc_thermal_pci_probe(struct pci_dev *pdev, > const struct pci_device_id *id) > @@ -629,18 +478,10 @@ static int proc_thermal_pci_probe(struct > pci_dev *pdev, > if (ret) > return ret; > > - ret = proc_thermal_rapl_add(pdev, proc_priv, > - (struct rapl_mmio_regs *)id- > >driver_data); > - if (ret) { > - dev_err(&pdev->dev, "failed to add RAPL MMIO > interface\n"); > - proc_thermal_remove(proc_priv); > - return ret; > - } > - > pci_set_drvdata(pdev, proc_priv); > proc_thermal_emum_mode = PROC_THERMAL_PCI; > > - if (pdev->device == PCI_DEVICE_ID_PROC_BSW_THERMAL) { > + if (pdev->device == PCI_DEVICE_ID_INTEL_BSW_THERMAL) { > /* > * Enumerate additional DTS sensors available via IOSF. > * But we are not treating as a failure condition, if > @@ -676,10 +517,18 @@ static int proc_thermal_pci_probe(struct > pci_dev *pdev, > return ret; > > ret = sysfs_create_group(&pdev->dev.kobj, > &power_limit_attribute_group); > - if (ret) > + if (ret) { > sysfs_remove_file(&pdev->dev.kobj, > &dev_attr_tcc_offset_degree_celsius.attr); > + return ret; > + } > > - return ret; > + ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); > + if (ret) { > + proc_thermal_remove(proc_priv); > + return ret; > + } > + > + return 0; > } > > static void proc_thermal_pci_remove(struct pci_dev *pdev) > @@ -693,7 +542,8 @@ static void proc_thermal_pci_remove(struct > pci_dev *pdev) > pci_disable_msi(pdev); > } > } > - proc_thermal_rapl_remove(); > + > + proc_thermal_mmio_remove(pdev); > proc_thermal_remove(proc_priv); > } > > @@ -716,24 +566,21 @@ static int proc_thermal_resume(struct device > *dev) > static SIMPLE_DEV_PM_OPS(proc_thermal_pm, NULL, > proc_thermal_resume); > > static const struct pci_device_id proc_thermal_pci_ids[] = { > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_BDW_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_HSB_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_SKL_THERMAL), > - .driver_data = (kernel_ulong_t)&rapl_mmio_hsw, }, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_BSW_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_BXT0_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_BXT1_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_BXTX_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_BXTP_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_CNL_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_CFL_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_GLK_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_ICL_THERMAL), > - .driver_data = (kernel_ulong_t)&rapl_mmio_hsw, }, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_JSL_THERMAL)}, > - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, > PCI_DEVICE_ID_PROC_TGL_THERMAL), > - .driver_data = (kernel_ulong_t)&rapl_mmio_hsw, }, > - { 0, }, > + { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, BSW_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, BXT0_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, BXT1_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, BXTX_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, BXTP_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, CNL_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, CFL_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, GLK_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, HSB_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, > PROC_THERMAL_FEATURE_RAPL) }, > + { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) }, > + { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, > PROC_THERMAL_FEATURE_RAPL) }, > + { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, > PROC_THERMAL_FEATURE_RAPL) }, > + { }, > }; > > MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); > diff --git > a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h > b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h > new file mode 100644 > index 000000000000..e20d142a55b4 > --- /dev/null > +++ > b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h > @@ -0,0 +1,72 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * processor_thermal_device.h > + * Copyright (c) 2020, Intel Corporation. > + */ > + > +#ifndef __PROCESSOR_THERMAL_DEVICE_H__ > +#define __PROCESSOR_THERMAL_DEVICE_H__ > + > +#include <linux/intel_rapl.h> > + > +#define PCI_DEVICE_ID_INTEL_BDW_THERMAL 0x1603 > +#define PCI_DEVICE_ID_INTEL_BSW_THERMAL 0x22DC > + > +#define PCI_DEVICE_ID_INTEL_BXT0_THERMAL 0x0A8C > +#define PCI_DEVICE_ID_INTEL_BXT1_THERMAL 0x1A8C > +#define PCI_DEVICE_ID_INTEL_BXTX_THERMAL 0x4A8C > +#define PCI_DEVICE_ID_INTEL_BXTP_THERMAL 0x5A8C > + > +#define PCI_DEVICE_ID_INTEL_CNL_THERMAL 0x5a03 > +#define PCI_DEVICE_ID_INTEL_CFL_THERMAL 0x3E83 > +#define PCI_DEVICE_ID_INTEL_GLK_THERMAL 0x318C > +#define PCI_DEVICE_ID_INTEL_HSB_THERMAL 0x0A03 > +#define PCI_DEVICE_ID_INTEL_ICL_THERMAL 0x8a03 > +#define PCI_DEVICE_ID_INTEL_JSL_THERMAL 0x4E03 > +#define PCI_DEVICE_ID_INTEL_SKL_THERMAL 0x1903 > +#define PCI_DEVICE_ID_INTEL_TGL_THERMAL 0x9A03 > + > +struct power_config { > + u32 index; > + u32 min_uw; > + u32 max_uw; > + u32 tmin_us; > + u32 tmax_us; > + u32 step_uw; > +}; > + > +struct proc_thermal_device { > + struct device *dev; > + struct acpi_device *adev; > + struct power_config power_limits[2]; > + struct int34x_thermal_zone *int340x_zone; > + struct intel_soc_dts_sensors *soc_dts; > + u32 mmio_feature_mask; > + void __iomem *mmio_base; > +}; > + > +struct rapl_mmio_regs { > + u64 reg_unit; > + u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX]; > + int limits[RAPL_DOMAIN_MAX]; > +}; > + > +#define PROC_THERMAL_FEATURE_NONE 0x00 > +#define PROC_THERMAL_FEATURE_RAPL 0x01 > + > +#if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) > +int proc_thermal_rapl_add(struct pci_dev *pdev, struct > proc_thermal_device *proc_priv); > +void proc_thermal_rapl_remove(void); > +#else > +static int __maybe_unused proc_thermal_rapl_add(struct pci_dev > *pdev, > + struct > proc_thermal_device *proc_priv) > +{ > + return 0; > +} > + > +static void __maybe_unused proc_thermal_rapl_remove(void) > +{ > +} > +#endif > + > +#endif > diff --git > a/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c > b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c > new file mode 100644 > index 000000000000..a205221ec8df > --- /dev/null > +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c > @@ -0,0 +1,134 @@ > +// 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");
| |