Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * processor_thermal.c - Passive cooling submodule of the ACPI processor driver
0004  *
0005  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
0006  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
0007  *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
0008  *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
0009  *              - Added processor hotplug support
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/init.h>
0015 #include <linux/cpufreq.h>
0016 #include <linux/acpi.h>
0017 #include <acpi/processor.h>
0018 #include <linux/uaccess.h>
0019 
0020 #ifdef CONFIG_CPU_FREQ
0021 
0022 /* If a passive cooling situation is detected, primarily CPUfreq is used, as it
0023  * offers (in most cases) voltage scaling in addition to frequency scaling, and
0024  * thus a cubic (instead of linear) reduction of energy. Also, we allow for
0025  * _any_ cpufreq driver and not only the acpi-cpufreq driver.
0026  */
0027 
0028 #define CPUFREQ_THERMAL_MIN_STEP 0
0029 #define CPUFREQ_THERMAL_MAX_STEP 3
0030 
0031 static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg);
0032 
0033 #define reduction_pctg(cpu) \
0034     per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu))
0035 
0036 /*
0037  * Emulate "per package data" using per cpu data (which should really be
0038  * provided elsewhere)
0039  *
0040  * Note we can lose a CPU on cpu hotunplug, in this case we forget the state
0041  * temporarily. Fortunately that's not a big issue here (I hope)
0042  */
0043 static int phys_package_first_cpu(int cpu)
0044 {
0045     int i;
0046     int id = topology_physical_package_id(cpu);
0047 
0048     for_each_online_cpu(i)
0049         if (topology_physical_package_id(i) == id)
0050             return i;
0051     return 0;
0052 }
0053 
0054 static int cpu_has_cpufreq(unsigned int cpu)
0055 {
0056     struct cpufreq_policy *policy;
0057 
0058     if (!acpi_processor_cpufreq_init)
0059         return 0;
0060 
0061     policy = cpufreq_cpu_get(cpu);
0062     if (policy) {
0063         cpufreq_cpu_put(policy);
0064         return 1;
0065     }
0066     return 0;
0067 }
0068 
0069 static int cpufreq_get_max_state(unsigned int cpu)
0070 {
0071     if (!cpu_has_cpufreq(cpu))
0072         return 0;
0073 
0074     return CPUFREQ_THERMAL_MAX_STEP;
0075 }
0076 
0077 static int cpufreq_get_cur_state(unsigned int cpu)
0078 {
0079     if (!cpu_has_cpufreq(cpu))
0080         return 0;
0081 
0082     return reduction_pctg(cpu);
0083 }
0084 
0085 static int cpufreq_set_cur_state(unsigned int cpu, int state)
0086 {
0087     struct cpufreq_policy *policy;
0088     struct acpi_processor *pr;
0089     unsigned long max_freq;
0090     int i, ret;
0091 
0092     if (!cpu_has_cpufreq(cpu))
0093         return 0;
0094 
0095     reduction_pctg(cpu) = state;
0096 
0097     /*
0098      * Update all the CPUs in the same package because they all
0099      * contribute to the temperature and often share the same
0100      * frequency.
0101      */
0102     for_each_online_cpu(i) {
0103         if (topology_physical_package_id(i) !=
0104             topology_physical_package_id(cpu))
0105             continue;
0106 
0107         pr = per_cpu(processors, i);
0108 
0109         if (unlikely(!freq_qos_request_active(&pr->thermal_req)))
0110             continue;
0111 
0112         policy = cpufreq_cpu_get(i);
0113         if (!policy)
0114             return -EINVAL;
0115 
0116         max_freq = (policy->cpuinfo.max_freq * (100 - reduction_pctg(i) * 20)) / 100;
0117 
0118         cpufreq_cpu_put(policy);
0119 
0120         ret = freq_qos_update_request(&pr->thermal_req, max_freq);
0121         if (ret < 0) {
0122             pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n",
0123                 pr->id, ret);
0124         }
0125     }
0126     return 0;
0127 }
0128 
0129 void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy)
0130 {
0131     unsigned int cpu;
0132 
0133     for_each_cpu(cpu, policy->related_cpus) {
0134         struct acpi_processor *pr = per_cpu(processors, cpu);
0135         int ret;
0136 
0137         if (!pr)
0138             continue;
0139 
0140         ret = freq_qos_add_request(&policy->constraints,
0141                        &pr->thermal_req,
0142                        FREQ_QOS_MAX, INT_MAX);
0143         if (ret < 0)
0144             pr_err("Failed to add freq constraint for CPU%d (%d)\n",
0145                    cpu, ret);
0146     }
0147 }
0148 
0149 void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
0150 {
0151     unsigned int cpu;
0152 
0153     for_each_cpu(cpu, policy->related_cpus) {
0154         struct acpi_processor *pr = per_cpu(processors, cpu);
0155 
0156         if (pr)
0157             freq_qos_remove_request(&pr->thermal_req);
0158     }
0159 }
0160 #else               /* ! CONFIG_CPU_FREQ */
0161 static int cpufreq_get_max_state(unsigned int cpu)
0162 {
0163     return 0;
0164 }
0165 
0166 static int cpufreq_get_cur_state(unsigned int cpu)
0167 {
0168     return 0;
0169 }
0170 
0171 static int cpufreq_set_cur_state(unsigned int cpu, int state)
0172 {
0173     return 0;
0174 }
0175 
0176 #endif
0177 
0178 /* thermal cooling device callbacks */
0179 static int acpi_processor_max_state(struct acpi_processor *pr)
0180 {
0181     int max_state = 0;
0182 
0183     /*
0184      * There exists four states according to
0185      * cpufreq_thermal_reduction_pctg. 0, 1, 2, 3
0186      */
0187     max_state += cpufreq_get_max_state(pr->id);
0188     if (pr->flags.throttling)
0189         max_state += (pr->throttling.state_count -1);
0190 
0191     return max_state;
0192 }
0193 static int
0194 processor_get_max_state(struct thermal_cooling_device *cdev,
0195             unsigned long *state)
0196 {
0197     struct acpi_device *device = cdev->devdata;
0198     struct acpi_processor *pr;
0199 
0200     if (!device)
0201         return -EINVAL;
0202 
0203     pr = acpi_driver_data(device);
0204     if (!pr)
0205         return -EINVAL;
0206 
0207     *state = acpi_processor_max_state(pr);
0208     return 0;
0209 }
0210 
0211 static int
0212 processor_get_cur_state(struct thermal_cooling_device *cdev,
0213             unsigned long *cur_state)
0214 {
0215     struct acpi_device *device = cdev->devdata;
0216     struct acpi_processor *pr;
0217 
0218     if (!device)
0219         return -EINVAL;
0220 
0221     pr = acpi_driver_data(device);
0222     if (!pr)
0223         return -EINVAL;
0224 
0225     *cur_state = cpufreq_get_cur_state(pr->id);
0226     if (pr->flags.throttling)
0227         *cur_state += pr->throttling.state;
0228     return 0;
0229 }
0230 
0231 static int
0232 processor_set_cur_state(struct thermal_cooling_device *cdev,
0233             unsigned long state)
0234 {
0235     struct acpi_device *device = cdev->devdata;
0236     struct acpi_processor *pr;
0237     int result = 0;
0238     int max_pstate;
0239 
0240     if (!device)
0241         return -EINVAL;
0242 
0243     pr = acpi_driver_data(device);
0244     if (!pr)
0245         return -EINVAL;
0246 
0247     max_pstate = cpufreq_get_max_state(pr->id);
0248 
0249     if (state > acpi_processor_max_state(pr))
0250         return -EINVAL;
0251 
0252     if (state <= max_pstate) {
0253         if (pr->flags.throttling && pr->throttling.state)
0254             result = acpi_processor_set_throttling(pr, 0, false);
0255         cpufreq_set_cur_state(pr->id, state);
0256     } else {
0257         cpufreq_set_cur_state(pr->id, max_pstate);
0258         result = acpi_processor_set_throttling(pr,
0259                 state - max_pstate, false);
0260     }
0261     return result;
0262 }
0263 
0264 const struct thermal_cooling_device_ops processor_cooling_ops = {
0265     .get_max_state = processor_get_max_state,
0266     .get_cur_state = processor_get_cur_state,
0267     .set_cur_state = processor_set_cur_state,
0268 };
0269 
0270 int acpi_processor_thermal_init(struct acpi_processor *pr,
0271                 struct acpi_device *device)
0272 {
0273     int result = 0;
0274 
0275     pr->cdev = thermal_cooling_device_register("Processor", device,
0276                            &processor_cooling_ops);
0277     if (IS_ERR(pr->cdev)) {
0278         result = PTR_ERR(pr->cdev);
0279         return result;
0280     }
0281 
0282     dev_dbg(&device->dev, "registered as cooling_device%d\n",
0283         pr->cdev->id);
0284 
0285     result = sysfs_create_link(&device->dev.kobj,
0286                    &pr->cdev->device.kobj,
0287                    "thermal_cooling");
0288     if (result) {
0289         dev_err(&device->dev,
0290             "Failed to create sysfs link 'thermal_cooling'\n");
0291         goto err_thermal_unregister;
0292     }
0293 
0294     result = sysfs_create_link(&pr->cdev->device.kobj,
0295                    &device->dev.kobj,
0296                    "device");
0297     if (result) {
0298         dev_err(&pr->cdev->device,
0299             "Failed to create sysfs link 'device'\n");
0300         goto err_remove_sysfs_thermal;
0301     }
0302 
0303     return 0;
0304 
0305 err_remove_sysfs_thermal:
0306     sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
0307 err_thermal_unregister:
0308     thermal_cooling_device_unregister(pr->cdev);
0309 
0310     return result;
0311 }
0312 
0313 void acpi_processor_thermal_exit(struct acpi_processor *pr,
0314                  struct acpi_device *device)
0315 {
0316     if (pr->cdev) {
0317         sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
0318         sysfs_remove_link(&pr->cdev->device.kobj, "device");
0319         thermal_cooling_device_unregister(pr->cdev);
0320         pr->cdev = NULL;
0321     }
0322 }