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(!dev_pm_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 = dev_pm_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(int cpu) 129 { 130 struct acpi_processor *pr = per_cpu(processors, cpu); 131 int ret; 132 133 ret = dev_pm_qos_add_request(get_cpu_device(cpu), 134 &pr->thermal_req, DEV_PM_QOS_MAX_FREQUENCY, 135 INT_MAX); 136 if (ret < 0) { 137 pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu, 138 ret); 139 return; 140 } 141 } 142 143 void acpi_thermal_cpufreq_exit(int cpu) 144 { 145 struct acpi_processor *pr = per_cpu(processors, cpu); 146 147 dev_pm_qos_remove_request(&pr->thermal_req); 148 } 149 #else /* ! CONFIG_CPU_FREQ */ 150 static int cpufreq_get_max_state(unsigned int cpu) 151 { 152 return 0; 153 } 154 155 static int cpufreq_get_cur_state(unsigned int cpu) 156 { 157 return 0; 158 } 159 160 static int cpufreq_set_cur_state(unsigned int cpu, int state) 161 { 162 return 0; 163 } 164 165 #endif 166 167 /* thermal cooling device callbacks */ 168 static int acpi_processor_max_state(struct acpi_processor *pr) 169 { 170 int max_state = 0; 171 172 /* 173 * There exists four states according to 174 * cpufreq_thermal_reduction_pctg. 0, 1, 2, 3 175 */ 176 max_state += cpufreq_get_max_state(pr->id); 177 if (pr->flags.throttling) 178 max_state += (pr->throttling.state_count -1); 179 180 return max_state; 181 } 182 static int 183 processor_get_max_state(struct thermal_cooling_device *cdev, 184 unsigned long *state) 185 { 186 struct acpi_device *device = cdev->devdata; 187 struct acpi_processor *pr; 188 189 if (!device) 190 return -EINVAL; 191 192 pr = acpi_driver_data(device); 193 if (!pr) 194 return -EINVAL; 195 196 *state = acpi_processor_max_state(pr); 197 return 0; 198 } 199 200 static int 201 processor_get_cur_state(struct thermal_cooling_device *cdev, 202 unsigned long *cur_state) 203 { 204 struct acpi_device *device = cdev->devdata; 205 struct acpi_processor *pr; 206 207 if (!device) 208 return -EINVAL; 209 210 pr = acpi_driver_data(device); 211 if (!pr) 212 return -EINVAL; 213 214 *cur_state = cpufreq_get_cur_state(pr->id); 215 if (pr->flags.throttling) 216 *cur_state += pr->throttling.state; 217 return 0; 218 } 219 220 static int 221 processor_set_cur_state(struct thermal_cooling_device *cdev, 222 unsigned long state) 223 { 224 struct acpi_device *device = cdev->devdata; 225 struct acpi_processor *pr; 226 int result = 0; 227 int max_pstate; 228 229 if (!device) 230 return -EINVAL; 231 232 pr = acpi_driver_data(device); 233 if (!pr) 234 return -EINVAL; 235 236 max_pstate = cpufreq_get_max_state(pr->id); 237 238 if (state > acpi_processor_max_state(pr)) 239 return -EINVAL; 240 241 if (state <= max_pstate) { 242 if (pr->flags.throttling && pr->throttling.state) 243 result = acpi_processor_set_throttling(pr, 0, false); 244 cpufreq_set_cur_state(pr->id, state); 245 } else { 246 cpufreq_set_cur_state(pr->id, max_pstate); 247 result = acpi_processor_set_throttling(pr, 248 state - max_pstate, false); 249 } 250 return result; 251 } 252 253 const struct thermal_cooling_device_ops processor_cooling_ops = { 254 .get_max_state = processor_get_max_state, 255 .get_cur_state = processor_get_cur_state, 256 .set_cur_state = processor_set_cur_state, 257 }; 258