1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * processor_thermal.c - Passive cooling submodule of the ACPI processor driver 4 * 5 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 6 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 7 * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de> 8 * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> 9 * - Added processor hotplug support 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/init.h> 15 #include <linux/cpufreq.h> 16 #include <linux/acpi.h> 17 #include <acpi/processor.h> 18 #include <linux/uaccess.h> 19 20 #ifdef CONFIG_CPU_FREQ 21 22 /* If a passive cooling situation is detected, primarily CPUfreq is used, as it 23 * offers (in most cases) voltage scaling in addition to frequency scaling, and 24 * thus a cubic (instead of linear) reduction of energy. Also, we allow for 25 * _any_ cpufreq driver and not only the acpi-cpufreq driver. 26 */ 27 28 #define CPUFREQ_THERMAL_MIN_STEP 0 29 #define CPUFREQ_THERMAL_MAX_STEP 3 30 31 static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); 32 33 #define reduction_pctg(cpu) \ 34 per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu)) 35 36 /* 37 * Emulate "per package data" using per cpu data (which should really be 38 * provided elsewhere) 39 * 40 * Note we can lose a CPU on cpu hotunplug, in this case we forget the state 41 * temporarily. Fortunately that's not a big issue here (I hope) 42 */ 43 static int phys_package_first_cpu(int cpu) 44 { 45 int i; 46 int id = topology_physical_package_id(cpu); 47 48 for_each_online_cpu(i) 49 if (topology_physical_package_id(i) == id) 50 return i; 51 return 0; 52 } 53 54 static int cpu_has_cpufreq(unsigned int cpu) 55 { 56 struct cpufreq_policy *policy; 57 58 if (!acpi_processor_cpufreq_init) 59 return 0; 60 61 policy = cpufreq_cpu_get(cpu); 62 if (policy) { 63 cpufreq_cpu_put(policy); 64 return 1; 65 } 66 return 0; 67 } 68 69 static int cpufreq_get_max_state(unsigned int cpu) 70 { 71 if (!cpu_has_cpufreq(cpu)) 72 return 0; 73 74 return CPUFREQ_THERMAL_MAX_STEP; 75 } 76 77 static int cpufreq_get_cur_state(unsigned int cpu) 78 { 79 if (!cpu_has_cpufreq(cpu)) 80 return 0; 81 82 return reduction_pctg(cpu); 83 } 84 85 static int cpufreq_set_cur_state(unsigned int cpu, int state) 86 { 87 struct cpufreq_policy *policy; 88 struct acpi_processor *pr; 89 unsigned long max_freq; 90 int i, ret; 91 92 if (!cpu_has_cpufreq(cpu)) 93 return 0; 94 95 reduction_pctg(cpu) = state; 96 97 /* 98 * Update all the CPUs in the same package because they all 99 * contribute to the temperature and often share the same 100 * frequency. 101 */ 102 for_each_online_cpu(i) { 103 if (topology_physical_package_id(i) != 104 topology_physical_package_id(cpu)) 105 continue; 106 107 pr = per_cpu(processors, i); 108 109 if (unlikely(!freq_qos_request_active(&pr->thermal_req))) 110 continue; 111 112 policy = cpufreq_cpu_get(i); 113 if (!policy) 114 return -EINVAL; 115 116 max_freq = (policy->cpuinfo.max_freq * (100 - reduction_pctg(i) * 20)) / 100; 117 118 cpufreq_cpu_put(policy); 119 120 ret = freq_qos_update_request(&pr->thermal_req, max_freq); 121 if (ret < 0) { 122 pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n", 123 pr->id, ret); 124 } 125 } 126 return 0; 127 } 128 129 void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy) 130 { 131 unsigned int cpu; 132 133 for_each_cpu(cpu, policy->related_cpus) { 134 struct acpi_processor *pr = per_cpu(processors, cpu); 135 int ret; 136 137 if (!pr) 138 continue; 139 140 ret = freq_qos_add_request(&policy->constraints, 141 &pr->thermal_req, 142 FREQ_QOS_MAX, INT_MAX); 143 if (ret < 0) 144 pr_err("Failed to add freq constraint for CPU%d (%d)\n", 145 cpu, ret); 146 } 147 } 148 149 void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy) 150 { 151 unsigned int cpu; 152 153 for_each_cpu(cpu, policy->related_cpus) { 154 struct acpi_processor *pr = per_cpu(processors, policy->cpu); 155 156 if (pr) 157 freq_qos_remove_request(&pr->thermal_req); 158 } 159 } 160 #else /* ! CONFIG_CPU_FREQ */ 161 static int cpufreq_get_max_state(unsigned int cpu) 162 { 163 return 0; 164 } 165 166 static int cpufreq_get_cur_state(unsigned int cpu) 167 { 168 return 0; 169 } 170 171 static int cpufreq_set_cur_state(unsigned int cpu, int state) 172 { 173 return 0; 174 } 175 176 #endif 177 178 /* thermal cooling device callbacks */ 179 static int acpi_processor_max_state(struct acpi_processor *pr) 180 { 181 int max_state = 0; 182 183 /* 184 * There exists four states according to 185 * cpufreq_thermal_reduction_pctg. 0, 1, 2, 3 186 */ 187 max_state += cpufreq_get_max_state(pr->id); 188 if (pr->flags.throttling) 189 max_state += (pr->throttling.state_count -1); 190 191 return max_state; 192 } 193 static int 194 processor_get_max_state(struct thermal_cooling_device *cdev, 195 unsigned long *state) 196 { 197 struct acpi_device *device = cdev->devdata; 198 struct acpi_processor *pr; 199 200 if (!device) 201 return -EINVAL; 202 203 pr = acpi_driver_data(device); 204 if (!pr) 205 return -EINVAL; 206 207 *state = acpi_processor_max_state(pr); 208 return 0; 209 } 210 211 static int 212 processor_get_cur_state(struct thermal_cooling_device *cdev, 213 unsigned long *cur_state) 214 { 215 struct acpi_device *device = cdev->devdata; 216 struct acpi_processor *pr; 217 218 if (!device) 219 return -EINVAL; 220 221 pr = acpi_driver_data(device); 222 if (!pr) 223 return -EINVAL; 224 225 *cur_state = cpufreq_get_cur_state(pr->id); 226 if (pr->flags.throttling) 227 *cur_state += pr->throttling.state; 228 return 0; 229 } 230 231 static int 232 processor_set_cur_state(struct thermal_cooling_device *cdev, 233 unsigned long state) 234 { 235 struct acpi_device *device = cdev->devdata; 236 struct acpi_processor *pr; 237 int result = 0; 238 int max_pstate; 239 240 if (!device) 241 return -EINVAL; 242 243 pr = acpi_driver_data(device); 244 if (!pr) 245 return -EINVAL; 246 247 max_pstate = cpufreq_get_max_state(pr->id); 248 249 if (state > acpi_processor_max_state(pr)) 250 return -EINVAL; 251 252 if (state <= max_pstate) { 253 if (pr->flags.throttling && pr->throttling.state) 254 result = acpi_processor_set_throttling(pr, 0, false); 255 cpufreq_set_cur_state(pr->id, state); 256 } else { 257 cpufreq_set_cur_state(pr->id, max_pstate); 258 result = acpi_processor_set_throttling(pr, 259 state - max_pstate, false); 260 } 261 return result; 262 } 263 264 const struct thermal_cooling_device_ops processor_cooling_ops = { 265 .get_max_state = processor_get_max_state, 266 .get_cur_state = processor_get_cur_state, 267 .set_cur_state = processor_set_cur_state, 268 }; 269