Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * processor thermal device RFIM control
0004  * Copyright (c) 2020, Intel Corporation.
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     /* mmio rapl supports package 0 only for now */
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");