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