0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/pci.h>
0010 #include "processor_thermal_device.h"
0011
0012 static struct rapl_if_priv rapl_mmio_priv;
0013
0014 static const struct rapl_mmio_regs rapl_mmio_default = {
0015 .reg_unit = 0x5938,
0016 .regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930},
0017 .regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0},
0018 .limits[RAPL_DOMAIN_PACKAGE] = 2,
0019 .limits[RAPL_DOMAIN_DRAM] = 2,
0020 };
0021
0022 static int rapl_mmio_cpu_online(unsigned int cpu)
0023 {
0024 struct rapl_package *rp;
0025
0026
0027 if (topology_physical_package_id(cpu))
0028 return 0;
0029
0030 rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
0031 if (!rp) {
0032 rp = rapl_add_package(cpu, &rapl_mmio_priv);
0033 if (IS_ERR(rp))
0034 return PTR_ERR(rp);
0035 }
0036 cpumask_set_cpu(cpu, &rp->cpumask);
0037 return 0;
0038 }
0039
0040 static int rapl_mmio_cpu_down_prep(unsigned int cpu)
0041 {
0042 struct rapl_package *rp;
0043 int lead_cpu;
0044
0045 rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
0046 if (!rp)
0047 return 0;
0048
0049 cpumask_clear_cpu(cpu, &rp->cpumask);
0050 lead_cpu = cpumask_first(&rp->cpumask);
0051 if (lead_cpu >= nr_cpu_ids)
0052 rapl_remove_package(rp);
0053 else if (rp->lead_cpu == cpu)
0054 rp->lead_cpu = lead_cpu;
0055 return 0;
0056 }
0057
0058 static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
0059 {
0060 if (!ra->reg)
0061 return -EINVAL;
0062
0063 ra->value = readq((void __iomem *)ra->reg);
0064 ra->value &= ra->mask;
0065 return 0;
0066 }
0067
0068 static int rapl_mmio_write_raw(int cpu, struct reg_action *ra)
0069 {
0070 u64 val;
0071
0072 if (!ra->reg)
0073 return -EINVAL;
0074
0075 val = readq((void __iomem *)ra->reg);
0076 val &= ~ra->mask;
0077 val |= ra->value;
0078 writeq(val, (void __iomem *)ra->reg);
0079 return 0;
0080 }
0081
0082 int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
0083 {
0084 const struct rapl_mmio_regs *rapl_regs = &rapl_mmio_default;
0085 enum rapl_domain_reg_id reg;
0086 enum rapl_domain_type domain;
0087 int ret;
0088
0089 if (!rapl_regs)
0090 return 0;
0091
0092 for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) {
0093 for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++)
0094 if (rapl_regs->regs[domain][reg])
0095 rapl_mmio_priv.regs[domain][reg] =
0096 (u64)proc_priv->mmio_base +
0097 rapl_regs->regs[domain][reg];
0098 rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain];
0099 }
0100 rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit;
0101
0102 rapl_mmio_priv.read_raw = rapl_mmio_read_raw;
0103 rapl_mmio_priv.write_raw = rapl_mmio_write_raw;
0104
0105 rapl_mmio_priv.control_type = powercap_register_control_type(NULL, "intel-rapl-mmio", NULL);
0106 if (IS_ERR(rapl_mmio_priv.control_type)) {
0107 pr_debug("failed to register powercap control_type.\n");
0108 return PTR_ERR(rapl_mmio_priv.control_type);
0109 }
0110
0111 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online",
0112 rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep);
0113 if (ret < 0) {
0114 powercap_unregister_control_type(rapl_mmio_priv.control_type);
0115 rapl_mmio_priv.control_type = NULL;
0116 return ret;
0117 }
0118 rapl_mmio_priv.pcap_rapl_online = ret;
0119
0120 return 0;
0121 }
0122 EXPORT_SYMBOL_GPL(proc_thermal_rapl_add);
0123
0124 void proc_thermal_rapl_remove(void)
0125 {
0126 if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type))
0127 return;
0128
0129 cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online);
0130 powercap_unregister_control_type(rapl_mmio_priv.control_type);
0131 }
0132 EXPORT_SYMBOL_GPL(proc_thermal_rapl_remove);
0133
0134 MODULE_LICENSE("GPL v2");