Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI: Split out ACPI PSS from ACPI Processor driver

The ACPI processor driver is currently tied too closely
to the ACPI P-states (PSS) and other related constructs
for controlling CPU performance.

The newer ACPI specification (v5.1 onwards) introduces
alternative methods to PSS. These new mechanisms are
described within each ACPI Processor object and so they
need to be scanned whenever a new Processor object is detected.
This patch introduces a new Kconfig symbol to allow for
finer configurability among the two options for controlling
performance states. There is no change in functionality and
the option is auto-selected by the architectures which support it.

A future commit will introduce support for CPPC: A newer method of
controlling CPU performance. The OS is not expected to support
CPPC and PSS at the same time, so the Kconfig option lets us make
the two mutually exclusive at compile time.

Signed-off-by: Ashwin Chaugule <ashwin.chaugule@linaro.org>
[ rjw: Changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Ashwin Chaugule and committed by
Rafael J. Wysocki
239708a3 d3c68f21

+96 -38
+9 -6
drivers/acpi/Kconfig
··· 189 189 This driver supports ACPI-controlled docking stations and removable 190 190 drive bays such as the IBM Ultrabay and the Dell Module Bay. 191 191 192 + config ACPI_CPU_FREQ_PSS 193 + bool 194 + select THERMAL 195 + 192 196 config ACPI_PROCESSOR 193 197 tristate "Processor" 194 - select THERMAL 195 - select CPU_IDLE 196 198 depends on X86 || IA64 199 + select CPU_IDLE 200 + select ACPI_CPU_FREQ_PSS 197 201 default y 198 202 help 199 - This driver installs ACPI as the idle handler for Linux and uses 200 - ACPI C2 and C3 processor states to save power on systems that 201 - support it. It is required by several flavors of cpufreq 202 - performance-state drivers. 203 + This driver adds support for the ACPI Processor package. It is required 204 + by several flavors of cpufreq performance-state, thermal, throttling and 205 + idle drivers. 203 206 204 207 To compile this driver as a module, choose M here: 205 208 the module will be called processor.
+3 -2
drivers/acpi/Makefile
··· 80 80 obj-$(CONFIG_ACPI_BGRT) += bgrt.o 81 81 82 82 # processor has its own "processor." module_param namespace 83 - processor-y := processor_driver.o processor_throttling.o 84 - processor-y += processor_idle.o processor_thermal.o 83 + processor-y := processor_driver.o processor_idle.o 84 + processor-$(CONFIG_ACPI_CPU_FREQ_PSS) += processor_throttling.o \ 85 + processor_thermal.o 85 86 processor-$(CONFIG_CPU_FREQ) += processor_perflib.o 86 87 87 88 obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
+58 -28
drivers/acpi/processor_driver.c
··· 163 163 .notifier_call = acpi_cpu_soft_notify, 164 164 }; 165 165 166 - static int __acpi_processor_start(struct acpi_device *device) 166 + #ifdef CONFIG_ACPI_CPU_FREQ_PSS 167 + static int acpi_pss_perf_init(struct acpi_processor *pr, 168 + struct acpi_device *device) 167 169 { 168 - struct acpi_processor *pr = acpi_driver_data(device); 169 - acpi_status status; 170 170 int result = 0; 171 171 172 - if (!pr) 173 - return -ENODEV; 174 - 175 - if (pr->flags.need_hotplug_init) 176 - return 0; 177 - 178 - #ifdef CONFIG_CPU_FREQ 179 172 acpi_processor_ppc_has_changed(pr, 0); 180 - #endif 173 + 181 174 acpi_processor_get_throttling_info(pr); 182 175 183 176 if (pr->flags.throttling) 184 177 pr->flags.limit = 1; 185 178 186 - if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver) 187 - acpi_processor_power_init(pr); 188 - 189 179 pr->cdev = thermal_cooling_device_register("Processor", device, 190 180 &processor_cooling_ops); 191 181 if (IS_ERR(pr->cdev)) { 192 182 result = PTR_ERR(pr->cdev); 193 - goto err_power_exit; 183 + return result; 194 184 } 195 185 196 186 dev_dbg(&device->dev, "registered as cooling_device%d\n", ··· 194 204 "Failed to create sysfs link 'thermal_cooling'\n"); 195 205 goto err_thermal_unregister; 196 206 } 207 + 197 208 result = sysfs_create_link(&pr->cdev->device.kobj, 198 209 &device->dev.kobj, 199 210 "device"); ··· 204 213 goto err_remove_sysfs_thermal; 205 214 } 206 215 207 - status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, 208 - acpi_processor_notify, device); 209 - if (ACPI_SUCCESS(status)) 210 - return 0; 211 - 212 216 sysfs_remove_link(&pr->cdev->device.kobj, "device"); 213 217 err_remove_sysfs_thermal: 214 218 sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); 215 219 err_thermal_unregister: 216 220 thermal_cooling_device_unregister(pr->cdev); 217 - err_power_exit: 221 + 222 + return result; 223 + } 224 + 225 + static void acpi_pss_perf_exit(struct acpi_processor *pr, 226 + struct acpi_device *device) 227 + { 228 + if (pr->cdev) { 229 + sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); 230 + sysfs_remove_link(&pr->cdev->device.kobj, "device"); 231 + thermal_cooling_device_unregister(pr->cdev); 232 + pr->cdev = NULL; 233 + } 234 + } 235 + #else 236 + static inline int acpi_pss_perf_init(struct acpi_processor *pr, 237 + struct acpi_device *device) 238 + { 239 + return 0; 240 + } 241 + 242 + static inline void acpi_pss_perf_exit(struct acpi_processor *pr, 243 + struct acpi_device *device) {} 244 + #endif /* CONFIG_ACPI_CPU_FREQ_PSS */ 245 + 246 + static int __acpi_processor_start(struct acpi_device *device) 247 + { 248 + struct acpi_processor *pr = acpi_driver_data(device); 249 + acpi_status status; 250 + int result = 0; 251 + 252 + if (!pr) 253 + return -ENODEV; 254 + 255 + if (pr->flags.need_hotplug_init) 256 + return 0; 257 + 258 + if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver) 259 + acpi_processor_power_init(pr); 260 + 261 + result = acpi_pss_perf_init(pr, device); 262 + if (result) 263 + goto err_power_exit; 264 + 265 + status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, 266 + acpi_processor_notify, device); 267 + if (ACPI_SUCCESS(status)) 268 + return 0; 269 + 270 + err_power_exit: 218 271 acpi_processor_power_exit(pr); 219 272 return result; 220 273 } ··· 287 252 pr = acpi_driver_data(device); 288 253 if (!pr) 289 254 return 0; 290 - 291 255 acpi_processor_power_exit(pr); 292 256 293 - if (pr->cdev) { 294 - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); 295 - sysfs_remove_link(&pr->cdev->device.kobj, "device"); 296 - thermal_cooling_device_unregister(pr->cdev); 297 - pr->cdev = NULL; 298 - } 257 + acpi_pss_perf_exit(pr, device); 258 + 299 259 return 0; 300 260 } 301 261
+26 -2
include/acpi/processor.h
··· 318 318 void acpi_processor_set_pdc(acpi_handle handle); 319 319 320 320 /* in processor_throttling.c */ 321 + #ifdef CONFIG_ACPI_CPU_FREQ_PSS 321 322 int acpi_processor_tstate_has_changed(struct acpi_processor *pr); 322 323 int acpi_processor_get_throttling_info(struct acpi_processor *pr); 323 324 extern int acpi_processor_set_throttling(struct acpi_processor *pr, ··· 331 330 unsigned long action); 332 331 extern const struct file_operations acpi_processor_throttling_fops; 333 332 extern void acpi_processor_throttling_init(void); 333 + #else 334 + static inline int acpi_processor_tstate_has_changed(struct acpi_processor *pr) 335 + { 336 + return 0; 337 + } 338 + 339 + static inline int acpi_processor_get_throttling_info(struct acpi_processor *pr) 340 + { 341 + return -ENODEV; 342 + } 343 + 344 + static inline int acpi_processor_set_throttling(struct acpi_processor *pr, 345 + int state, bool force) 346 + { 347 + return -ENODEV; 348 + } 349 + 350 + static inline void acpi_processor_reevaluate_tstate(struct acpi_processor *pr, 351 + unsigned long action) {} 352 + 353 + static inline void acpi_processor_throttling_init(void) {} 354 + #endif /* CONFIG_ACPI_CPU_FREQ_PSS */ 355 + 334 356 /* in processor_idle.c */ 335 357 int acpi_processor_power_init(struct acpi_processor *pr); 336 358 int acpi_processor_power_exit(struct acpi_processor *pr); ··· 372 348 /* in processor_thermal.c */ 373 349 int acpi_processor_get_limit_info(struct acpi_processor *pr); 374 350 extern const struct thermal_cooling_device_ops processor_cooling_ops; 375 - #ifdef CONFIG_CPU_FREQ 351 + #if defined(CONFIG_ACPI_CPU_FREQ_PSS) & defined(CONFIG_CPU_FREQ) 376 352 void acpi_thermal_cpufreq_init(void); 377 353 void acpi_thermal_cpufreq_exit(void); 378 354 #else ··· 384 360 { 385 361 return; 386 362 } 387 - #endif 363 + #endif /* CONFIG_ACPI_CPU_FREQ_PSS */ 388 364 389 365 #endif