.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * processor_driver.c - ACPI Processor Driver |
---|
3 | 4 | * |
---|
.. | .. |
---|
8 | 9 | * - Added processor hotplug support |
---|
9 | 10 | * Copyright (C) 2013, Intel Corporation |
---|
10 | 11 | * Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
---|
11 | | - * |
---|
12 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
13 | | - * |
---|
14 | | - * This program is free software; you can redistribute it and/or modify |
---|
15 | | - * it under the terms of the GNU General Public License as published by |
---|
16 | | - * the Free Software Foundation; either version 2 of the License, or (at |
---|
17 | | - * your option) any later version. |
---|
18 | | - * |
---|
19 | | - * This program is distributed in the hope that it will be useful, but |
---|
20 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
21 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
22 | | - * General Public License for more details. |
---|
23 | | - * |
---|
24 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
25 | 12 | */ |
---|
26 | 13 | |
---|
27 | 14 | #include <linux/kernel.h> |
---|
.. | .. |
---|
297 | 284 | return 0; |
---|
298 | 285 | } |
---|
299 | 286 | |
---|
| 287 | +bool acpi_processor_cpufreq_init; |
---|
| 288 | + |
---|
| 289 | +static int acpi_processor_notifier(struct notifier_block *nb, |
---|
| 290 | + unsigned long event, void *data) |
---|
| 291 | +{ |
---|
| 292 | + struct cpufreq_policy *policy = data; |
---|
| 293 | + |
---|
| 294 | + if (event == CPUFREQ_CREATE_POLICY) { |
---|
| 295 | + acpi_thermal_cpufreq_init(policy); |
---|
| 296 | + acpi_processor_ppc_init(policy); |
---|
| 297 | + } else if (event == CPUFREQ_REMOVE_POLICY) { |
---|
| 298 | + acpi_processor_ppc_exit(policy); |
---|
| 299 | + acpi_thermal_cpufreq_exit(policy); |
---|
| 300 | + } |
---|
| 301 | + |
---|
| 302 | + return 0; |
---|
| 303 | +} |
---|
| 304 | + |
---|
| 305 | +static struct notifier_block acpi_processor_notifier_block = { |
---|
| 306 | + .notifier_call = acpi_processor_notifier, |
---|
| 307 | +}; |
---|
| 308 | + |
---|
300 | 309 | /* |
---|
301 | 310 | * We keep the driver loaded even when ACPI is not running. |
---|
302 | 311 | * This is needed for the powernow-k8 driver, that works even without |
---|
.. | .. |
---|
323 | 332 | cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead", |
---|
324 | 333 | NULL, acpi_soft_cpu_dead); |
---|
325 | 334 | |
---|
326 | | - acpi_thermal_cpufreq_init(); |
---|
327 | | - acpi_processor_ppc_init(); |
---|
| 335 | + if (!cpufreq_register_notifier(&acpi_processor_notifier_block, |
---|
| 336 | + CPUFREQ_POLICY_NOTIFIER)) { |
---|
| 337 | + acpi_processor_cpufreq_init = true; |
---|
| 338 | + acpi_processor_ignore_ppc_init(); |
---|
| 339 | + } |
---|
| 340 | + |
---|
328 | 341 | acpi_processor_throttling_init(); |
---|
329 | 342 | return 0; |
---|
330 | 343 | err: |
---|
.. | .. |
---|
337 | 350 | if (acpi_disabled) |
---|
338 | 351 | return; |
---|
339 | 352 | |
---|
340 | | - acpi_processor_ppc_exit(); |
---|
341 | | - acpi_thermal_cpufreq_exit(); |
---|
| 353 | + if (acpi_processor_cpufreq_init) { |
---|
| 354 | + cpufreq_unregister_notifier(&acpi_processor_notifier_block, |
---|
| 355 | + CPUFREQ_POLICY_NOTIFIER); |
---|
| 356 | + acpi_processor_cpufreq_init = false; |
---|
| 357 | + } |
---|
| 358 | + |
---|
342 | 359 | cpuhp_remove_state_nocalls(hp_online); |
---|
343 | 360 | cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD); |
---|
344 | 361 | driver_unregister(&acpi_processor_driver); |
---|