linux/drivers/acpi/processor_driver.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * processor_driver.c - 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 *  Copyright (C) 2013, Intel Corporation
  11 *                      Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/init.h>
  17#include <linux/cpufreq.h>
  18#include <linux/cpu.h>
  19#include <linux/cpuidle.h>
  20#include <linux/slab.h>
  21#include <linux/acpi.h>
  22
  23#include <acpi/processor.h>
  24
  25#include "internal.h"
  26
  27#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
  28#define ACPI_PROCESSOR_NOTIFY_POWER     0x81
  29#define ACPI_PROCESSOR_NOTIFY_THROTTLING        0x82
  30
  31#define _COMPONENT              ACPI_PROCESSOR_COMPONENT
  32ACPI_MODULE_NAME("processor_driver");
  33
  34MODULE_AUTHOR("Paul Diefenbaugh");
  35MODULE_DESCRIPTION("ACPI Processor Driver");
  36MODULE_LICENSE("GPL");
  37
  38static int acpi_processor_start(struct device *dev);
  39static int acpi_processor_stop(struct device *dev);
  40
  41static const struct acpi_device_id processor_device_ids[] = {
  42        {ACPI_PROCESSOR_OBJECT_HID, 0},
  43        {ACPI_PROCESSOR_DEVICE_HID, 0},
  44        {"", 0},
  45};
  46MODULE_DEVICE_TABLE(acpi, processor_device_ids);
  47
  48static struct device_driver acpi_processor_driver = {
  49        .name = "processor",
  50        .bus = &cpu_subsys,
  51        .acpi_match_table = processor_device_ids,
  52        .probe = acpi_processor_start,
  53        .remove = acpi_processor_stop,
  54};
  55
  56static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
  57{
  58        struct acpi_device *device = data;
  59        struct acpi_processor *pr;
  60        int saved;
  61
  62        if (device->handle != handle)
  63                return;
  64
  65        pr = acpi_driver_data(device);
  66        if (!pr)
  67                return;
  68
  69        switch (event) {
  70        case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
  71                saved = pr->performance_platform_limit;
  72                acpi_processor_ppc_has_changed(pr, 1);
  73                if (saved == pr->performance_platform_limit)
  74                        break;
  75                acpi_bus_generate_netlink_event(device->pnp.device_class,
  76                                                  dev_name(&device->dev), event,
  77                                                  pr->performance_platform_limit);
  78                break;
  79        case ACPI_PROCESSOR_NOTIFY_POWER:
  80                acpi_processor_power_state_has_changed(pr);
  81                acpi_bus_generate_netlink_event(device->pnp.device_class,
  82                                                  dev_name(&device->dev), event, 0);
  83                break;
  84        case ACPI_PROCESSOR_NOTIFY_THROTTLING:
  85                acpi_processor_tstate_has_changed(pr);
  86                acpi_bus_generate_netlink_event(device->pnp.device_class,
  87                                                  dev_name(&device->dev), event, 0);
  88                break;
  89        default:
  90                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  91                                  "Unsupported event [0x%x]\n", event));
  92                break;
  93        }
  94
  95        return;
  96}
  97
  98static int __acpi_processor_start(struct acpi_device *device);
  99
 100static int acpi_soft_cpu_online(unsigned int cpu)
 101{
 102        struct acpi_processor *pr = per_cpu(processors, cpu);
 103        struct acpi_device *device;
 104
 105        if (!pr || acpi_bus_get_device(pr->handle, &device))
 106                return 0;
 107        /*
 108         * CPU got physically hotplugged and onlined for the first time:
 109         * Initialize missing things.
 110         */
 111        if (pr->flags.need_hotplug_init) {
 112                int ret;
 113
 114                pr_info("Will online and init hotplugged CPU: %d\n",
 115                        pr->id);
 116                pr->flags.need_hotplug_init = 0;
 117                ret = __acpi_processor_start(device);
 118                WARN(ret, "Failed to start CPU: %d\n", pr->id);
 119        } else {
 120                /* Normal CPU soft online event. */
 121                acpi_processor_ppc_has_changed(pr, 0);
 122                acpi_processor_hotplug(pr);
 123                acpi_processor_reevaluate_tstate(pr, false);
 124                acpi_processor_tstate_has_changed(pr);
 125        }
 126        return 0;
 127}
 128
 129static int acpi_soft_cpu_dead(unsigned int cpu)
 130{
 131        struct acpi_processor *pr = per_cpu(processors, cpu);
 132        struct acpi_device *device;
 133
 134        if (!pr || acpi_bus_get_device(pr->handle, &device))
 135                return 0;
 136
 137        acpi_processor_reevaluate_tstate(pr, true);
 138        return 0;
 139}
 140
 141#ifdef CONFIG_ACPI_CPU_FREQ_PSS
 142static int acpi_pss_perf_init(struct acpi_processor *pr,
 143                struct acpi_device *device)
 144{
 145        int result = 0;
 146
 147        acpi_processor_ppc_has_changed(pr, 0);
 148
 149        acpi_processor_get_throttling_info(pr);
 150
 151        if (pr->flags.throttling)
 152                pr->flags.limit = 1;
 153
 154        pr->cdev = thermal_cooling_device_register("Processor", device,
 155                                                   &processor_cooling_ops);
 156        if (IS_ERR(pr->cdev)) {
 157                result = PTR_ERR(pr->cdev);
 158                return result;
 159        }
 160
 161        dev_dbg(&device->dev, "registered as cooling_device%d\n",
 162                pr->cdev->id);
 163
 164        result = sysfs_create_link(&device->dev.kobj,
 165                                   &pr->cdev->device.kobj,
 166                                   "thermal_cooling");
 167        if (result) {
 168                dev_err(&device->dev,
 169                        "Failed to create sysfs link 'thermal_cooling'\n");
 170                goto err_thermal_unregister;
 171        }
 172
 173        result = sysfs_create_link(&pr->cdev->device.kobj,
 174                                   &device->dev.kobj,
 175                                   "device");
 176        if (result) {
 177                dev_err(&pr->cdev->device,
 178                        "Failed to create sysfs link 'device'\n");
 179                goto err_remove_sysfs_thermal;
 180        }
 181
 182        return 0;
 183
 184 err_remove_sysfs_thermal:
 185        sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
 186 err_thermal_unregister:
 187        thermal_cooling_device_unregister(pr->cdev);
 188
 189        return result;
 190}
 191
 192static void acpi_pss_perf_exit(struct acpi_processor *pr,
 193                struct acpi_device *device)
 194{
 195        if (pr->cdev) {
 196                sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
 197                sysfs_remove_link(&pr->cdev->device.kobj, "device");
 198                thermal_cooling_device_unregister(pr->cdev);
 199                pr->cdev = NULL;
 200        }
 201}
 202#else
 203static inline int acpi_pss_perf_init(struct acpi_processor *pr,
 204                struct acpi_device *device)
 205{
 206        return 0;
 207}
 208
 209static inline void acpi_pss_perf_exit(struct acpi_processor *pr,
 210                struct acpi_device *device) {}
 211#endif /* CONFIG_ACPI_CPU_FREQ_PSS */
 212
 213static int __acpi_processor_start(struct acpi_device *device)
 214{
 215        struct acpi_processor *pr = acpi_driver_data(device);
 216        acpi_status status;
 217        int result = 0;
 218
 219        if (!pr)
 220                return -ENODEV;
 221
 222        if (pr->flags.need_hotplug_init)
 223                return 0;
 224
 225        result = acpi_cppc_processor_probe(pr);
 226        if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
 227                dev_dbg(&device->dev, "CPPC data invalid or not present\n");
 228
 229        if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
 230                acpi_processor_power_init(pr);
 231
 232        result = acpi_pss_perf_init(pr, device);
 233        if (result)
 234                goto err_power_exit;
 235
 236        status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
 237                                             acpi_processor_notify, device);
 238        if (ACPI_SUCCESS(status))
 239                return 0;
 240
 241        result = -ENODEV;
 242        acpi_pss_perf_exit(pr, device);
 243
 244err_power_exit:
 245        acpi_processor_power_exit(pr);
 246        return result;
 247}
 248
 249static int acpi_processor_start(struct device *dev)
 250{
 251        struct acpi_device *device = ACPI_COMPANION(dev);
 252        int ret;
 253
 254        if (!device)
 255                return -ENODEV;
 256
 257        /* Protect against concurrent CPU hotplug operations */
 258        cpu_hotplug_disable();
 259        ret = __acpi_processor_start(device);
 260        cpu_hotplug_enable();
 261        return ret;
 262}
 263
 264static int acpi_processor_stop(struct device *dev)
 265{
 266        struct acpi_device *device = ACPI_COMPANION(dev);
 267        struct acpi_processor *pr;
 268
 269        if (!device)
 270                return 0;
 271
 272        acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
 273                                   acpi_processor_notify);
 274
 275        pr = acpi_driver_data(device);
 276        if (!pr)
 277                return 0;
 278        acpi_processor_power_exit(pr);
 279
 280        acpi_pss_perf_exit(pr, device);
 281
 282        acpi_cppc_processor_exit(pr);
 283
 284        return 0;
 285}
 286
 287bool acpi_processor_cpufreq_init;
 288
 289static 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
 305static struct notifier_block acpi_processor_notifier_block = {
 306        .notifier_call = acpi_processor_notifier,
 307};
 308
 309/*
 310 * We keep the driver loaded even when ACPI is not running.
 311 * This is needed for the powernow-k8 driver, that works even without
 312 * ACPI, but needs symbols from this driver
 313 */
 314static enum cpuhp_state hp_online;
 315static int __init acpi_processor_driver_init(void)
 316{
 317        int result = 0;
 318
 319        if (acpi_disabled)
 320                return 0;
 321
 322        result = driver_register(&acpi_processor_driver);
 323        if (result < 0)
 324                return result;
 325
 326        result = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
 327                                           "acpi/cpu-drv:online",
 328                                           acpi_soft_cpu_online, NULL);
 329        if (result < 0)
 330                goto err;
 331        hp_online = result;
 332        cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead",
 333                                  NULL, acpi_soft_cpu_dead);
 334
 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
 341        acpi_processor_throttling_init();
 342        return 0;
 343err:
 344        driver_unregister(&acpi_processor_driver);
 345        return result;
 346}
 347
 348static void __exit acpi_processor_driver_exit(void)
 349{
 350        if (acpi_disabled)
 351                return;
 352
 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
 359        cpuhp_remove_state_nocalls(hp_online);
 360        cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
 361        driver_unregister(&acpi_processor_driver);
 362}
 363
 364module_init(acpi_processor_driver_init);
 365module_exit(acpi_processor_driver_exit);
 366
 367MODULE_ALIAS("processor");
 368