| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * intel_pstate.c: Native P state management for Intel processors |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * (C) Copyright 2012 Intel Corporation |
|---|
| 5 | 6 | * Author: Dirk Brandewie <dirk.j.brandewie@intel.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or |
|---|
| 8 | | - * modify it under the terms of the GNU General Public License |
|---|
| 9 | | - * as published by the Free Software Foundation; version 2 |
|---|
| 10 | | - * of the License. |
|---|
| 11 | 7 | */ |
|---|
| 12 | 8 | |
|---|
| 13 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 28 | 24 | #include <linux/fs.h> |
|---|
| 29 | 25 | #include <linux/acpi.h> |
|---|
| 30 | 26 | #include <linux/vmalloc.h> |
|---|
| 27 | +#include <linux/pm_qos.h> |
|---|
| 31 | 28 | #include <trace/events/power.h> |
|---|
| 32 | 29 | |
|---|
| 33 | 30 | #include <asm/div64.h> |
|---|
| .. | .. |
|---|
| 39 | 36 | #define INTEL_PSTATE_SAMPLING_INTERVAL (10 * NSEC_PER_MSEC) |
|---|
| 40 | 37 | |
|---|
| 41 | 38 | #define INTEL_CPUFREQ_TRANSITION_LATENCY 20000 |
|---|
| 39 | +#define INTEL_CPUFREQ_TRANSITION_DELAY_HWP 5000 |
|---|
| 42 | 40 | #define INTEL_CPUFREQ_TRANSITION_DELAY 500 |
|---|
| 43 | 41 | |
|---|
| 44 | 42 | #ifdef CONFIG_ACPI |
|---|
| .. | .. |
|---|
| 49 | 47 | #define FRAC_BITS 8 |
|---|
| 50 | 48 | #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) |
|---|
| 51 | 49 | #define fp_toint(X) ((X) >> FRAC_BITS) |
|---|
| 50 | + |
|---|
| 51 | +#define ONE_EIGHTH_FP ((int64_t)1 << (FRAC_BITS - 3)) |
|---|
| 52 | 52 | |
|---|
| 53 | 53 | #define EXT_BITS 6 |
|---|
| 54 | 54 | #define EXT_FRAC_BITS (EXT_BITS + FRAC_BITS) |
|---|
| .. | .. |
|---|
| 173 | 173 | /** |
|---|
| 174 | 174 | * struct global_params - Global parameters, mostly tunable via sysfs. |
|---|
| 175 | 175 | * @no_turbo: Whether or not to use turbo P-states. |
|---|
| 176 | | - * @turbo_disabled: Whethet or not turbo P-states are available at all, |
|---|
| 176 | + * @turbo_disabled: Whether or not turbo P-states are available at all, |
|---|
| 177 | 177 | * based on the MSR_IA32_MISC_ENABLE value and whether or |
|---|
| 178 | 178 | * not the maximum reported turbo P-state is different from |
|---|
| 179 | 179 | * the maximum reported non-turbo one. |
|---|
| 180 | + * @turbo_disabled_mf: The @turbo_disabled value reflected by cpuinfo.max_freq. |
|---|
| 180 | 181 | * @min_perf_pct: Minimum capacity limit in percent of the maximum turbo |
|---|
| 181 | 182 | * P-state capacity. |
|---|
| 182 | 183 | * @max_perf_pct: Maximum capacity limit in percent of the maximum turbo |
|---|
| .. | .. |
|---|
| 185 | 186 | struct global_params { |
|---|
| 186 | 187 | bool no_turbo; |
|---|
| 187 | 188 | bool turbo_disabled; |
|---|
| 189 | + bool turbo_disabled_mf; |
|---|
| 188 | 190 | int max_perf_pct; |
|---|
| 189 | 191 | int min_perf_pct; |
|---|
| 190 | 192 | }; |
|---|
| .. | .. |
|---|
| 200 | 202 | * @pstate: Stores P state limits for this CPU |
|---|
| 201 | 203 | * @vid: Stores VID limits for this CPU |
|---|
| 202 | 204 | * @last_sample_time: Last Sample time |
|---|
| 203 | | - * @aperf_mperf_shift: Number of clock cycles after aperf, merf is incremented |
|---|
| 204 | | - * This shift is a multiplier to mperf delta to |
|---|
| 205 | | - * calculate CPU busy. |
|---|
| 205 | + * @aperf_mperf_shift: APERF vs MPERF counting frequency difference |
|---|
| 206 | 206 | * @prev_aperf: Last APERF value read from APERF MSR |
|---|
| 207 | 207 | * @prev_mperf: Last MPERF value read from MPERF MSR |
|---|
| 208 | 208 | * @prev_tsc: Last timestamp counter (TSC) value |
|---|
| .. | .. |
|---|
| 219 | 219 | * @epp_policy: Last saved policy used to set EPP/EPB |
|---|
| 220 | 220 | * @epp_default: Power on default HWP energy performance |
|---|
| 221 | 221 | * preference/bias |
|---|
| 222 | | - * @epp_saved: Saved EPP/EPB during system suspend or CPU offline |
|---|
| 223 | | - * operation |
|---|
| 222 | + * @epp_cached Cached HWP energy-performance preference value |
|---|
| 224 | 223 | * @hwp_req_cached: Cached value of the last HWP Request MSR |
|---|
| 225 | 224 | * @hwp_cap_cached: Cached value of the last HWP Capabilities MSR |
|---|
| 226 | 225 | * @last_io_update: Last time when IO wake flag was set |
|---|
| 227 | 226 | * @sched_flags: Store scheduler flags for possible cross CPU update |
|---|
| 228 | 227 | * @hwp_boost_min: Last HWP boosted min performance |
|---|
| 228 | + * @suspended: Whether or not the driver has been suspended. |
|---|
| 229 | 229 | * |
|---|
| 230 | 230 | * This structure stores per CPU instance data for all CPUs. |
|---|
| 231 | 231 | */ |
|---|
| .. | .. |
|---|
| 257 | 257 | s16 epp_powersave; |
|---|
| 258 | 258 | s16 epp_policy; |
|---|
| 259 | 259 | s16 epp_default; |
|---|
| 260 | | - s16 epp_saved; |
|---|
| 260 | + s16 epp_cached; |
|---|
| 261 | 261 | u64 hwp_req_cached; |
|---|
| 262 | 262 | u64 hwp_cap_cached; |
|---|
| 263 | 263 | u64 last_io_update; |
|---|
| 264 | 264 | unsigned int sched_flags; |
|---|
| 265 | 265 | u32 hwp_boost_min; |
|---|
| 266 | + bool suspended; |
|---|
| 266 | 267 | }; |
|---|
| 267 | 268 | |
|---|
| 268 | 269 | static struct cpudata **all_cpu_data; |
|---|
| .. | .. |
|---|
| 274 | 275 | * @get_min: Callback to get minimum P state |
|---|
| 275 | 276 | * @get_turbo: Callback to get turbo P state |
|---|
| 276 | 277 | * @get_scaling: Callback to get frequency scaling factor |
|---|
| 278 | + * @get_aperf_mperf_shift: Callback to get the APERF vs MPERF frequency difference |
|---|
| 277 | 279 | * @get_val: Callback to convert P state to actual MSR write value |
|---|
| 278 | 280 | * @get_vid: Callback to get VID data for Atom platforms |
|---|
| 279 | 281 | * |
|---|
| .. | .. |
|---|
| 373 | 375 | } |
|---|
| 374 | 376 | } |
|---|
| 375 | 377 | } |
|---|
| 376 | | -#else |
|---|
| 378 | + |
|---|
| 379 | +static int intel_pstate_get_cppc_guranteed(int cpu) |
|---|
| 380 | +{ |
|---|
| 381 | + struct cppc_perf_caps cppc_perf; |
|---|
| 382 | + int ret; |
|---|
| 383 | + |
|---|
| 384 | + ret = cppc_get_perf_caps(cpu, &cppc_perf); |
|---|
| 385 | + if (ret) |
|---|
| 386 | + return ret; |
|---|
| 387 | + |
|---|
| 388 | + if (cppc_perf.guaranteed_perf) |
|---|
| 389 | + return cppc_perf.guaranteed_perf; |
|---|
| 390 | + |
|---|
| 391 | + return cppc_perf.nominal_perf; |
|---|
| 392 | +} |
|---|
| 393 | + |
|---|
| 394 | +#else /* CONFIG_ACPI_CPPC_LIB */ |
|---|
| 377 | 395 | static void intel_pstate_set_itmt_prio(int cpu) |
|---|
| 378 | 396 | { |
|---|
| 379 | 397 | } |
|---|
| 380 | | -#endif |
|---|
| 398 | +#endif /* CONFIG_ACPI_CPPC_LIB */ |
|---|
| 381 | 399 | |
|---|
| 382 | 400 | static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy) |
|---|
| 383 | 401 | { |
|---|
| .. | .. |
|---|
| 425 | 443 | (u32) cpu->acpi_perf_data.states[i].control); |
|---|
| 426 | 444 | } |
|---|
| 427 | 445 | |
|---|
| 428 | | - /* |
|---|
| 429 | | - * The _PSS table doesn't contain whole turbo frequency range. |
|---|
| 430 | | - * This just contains +1 MHZ above the max non turbo frequency, |
|---|
| 431 | | - * with control value corresponding to max turbo ratio. But |
|---|
| 432 | | - * when cpufreq set policy is called, it will call with this |
|---|
| 433 | | - * max frequency, which will cause a reduced performance as |
|---|
| 434 | | - * this driver uses real max turbo frequency as the max |
|---|
| 435 | | - * frequency. So correct this frequency in _PSS table to |
|---|
| 436 | | - * correct max turbo frequency based on the turbo state. |
|---|
| 437 | | - * Also need to convert to MHz as _PSS freq is in MHz. |
|---|
| 438 | | - */ |
|---|
| 439 | | - if (!global.turbo_disabled) |
|---|
| 440 | | - cpu->acpi_perf_data.states[0].core_frequency = |
|---|
| 441 | | - policy->cpuinfo.max_freq / 1000; |
|---|
| 442 | 446 | cpu->valid_pss_table = true; |
|---|
| 443 | 447 | pr_debug("_PPC limits will be enforced\n"); |
|---|
| 444 | 448 | |
|---|
| .. | .. |
|---|
| 459 | 463 | |
|---|
| 460 | 464 | acpi_processor_unregister_performance(policy->cpu); |
|---|
| 461 | 465 | } |
|---|
| 462 | | -#else |
|---|
| 466 | +#else /* CONFIG_ACPI */ |
|---|
| 463 | 467 | static inline void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy) |
|---|
| 464 | 468 | { |
|---|
| 465 | 469 | } |
|---|
| .. | .. |
|---|
| 472 | 476 | { |
|---|
| 473 | 477 | return false; |
|---|
| 474 | 478 | } |
|---|
| 475 | | -#endif |
|---|
| 479 | +#endif /* CONFIG_ACPI */ |
|---|
| 480 | + |
|---|
| 481 | +#ifndef CONFIG_ACPI_CPPC_LIB |
|---|
| 482 | +static int intel_pstate_get_cppc_guranteed(int cpu) |
|---|
| 483 | +{ |
|---|
| 484 | + return -ENOTSUPP; |
|---|
| 485 | +} |
|---|
| 486 | +#endif /* CONFIG_ACPI_CPPC_LIB */ |
|---|
| 476 | 487 | |
|---|
| 477 | 488 | static inline void update_turbo_state(void) |
|---|
| 478 | 489 | { |
|---|
| .. | .. |
|---|
| 500 | 511 | u64 epb; |
|---|
| 501 | 512 | int ret; |
|---|
| 502 | 513 | |
|---|
| 503 | | - if (!static_cpu_has(X86_FEATURE_EPB)) |
|---|
| 514 | + if (!boot_cpu_has(X86_FEATURE_EPB)) |
|---|
| 504 | 515 | return -ENXIO; |
|---|
| 505 | 516 | |
|---|
| 506 | 517 | ret = rdmsrl_on_cpu(cpu_data->cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb); |
|---|
| .. | .. |
|---|
| 514 | 525 | { |
|---|
| 515 | 526 | s16 epp; |
|---|
| 516 | 527 | |
|---|
| 517 | | - if (static_cpu_has(X86_FEATURE_HWP_EPP)) { |
|---|
| 528 | + if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { |
|---|
| 518 | 529 | /* |
|---|
| 519 | 530 | * When hwp_req_data is 0, means that caller didn't read |
|---|
| 520 | 531 | * MSR_HWP_REQUEST, so need to read and get EPP. |
|---|
| .. | .. |
|---|
| 539 | 550 | u64 epb; |
|---|
| 540 | 551 | int ret; |
|---|
| 541 | 552 | |
|---|
| 542 | | - if (!static_cpu_has(X86_FEATURE_EPB)) |
|---|
| 553 | + if (!boot_cpu_has(X86_FEATURE_EPB)) |
|---|
| 543 | 554 | return -ENXIO; |
|---|
| 544 | 555 | |
|---|
| 545 | 556 | ret = rdmsrl_on_cpu(cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb); |
|---|
| .. | .. |
|---|
| 578 | 589 | HWP_EPP_POWERSAVE |
|---|
| 579 | 590 | }; |
|---|
| 580 | 591 | |
|---|
| 581 | | -static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data) |
|---|
| 592 | +static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data, int *raw_epp) |
|---|
| 582 | 593 | { |
|---|
| 583 | 594 | s16 epp; |
|---|
| 584 | 595 | int index = -EINVAL; |
|---|
| 585 | 596 | |
|---|
| 597 | + *raw_epp = 0; |
|---|
| 586 | 598 | epp = intel_pstate_get_epp(cpu_data, 0); |
|---|
| 587 | 599 | if (epp < 0) |
|---|
| 588 | 600 | return epp; |
|---|
| 589 | 601 | |
|---|
| 590 | | - if (static_cpu_has(X86_FEATURE_HWP_EPP)) { |
|---|
| 602 | + if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { |
|---|
| 591 | 603 | if (epp == HWP_EPP_PERFORMANCE) |
|---|
| 592 | 604 | return 1; |
|---|
| 593 | | - if (epp <= HWP_EPP_BALANCE_PERFORMANCE) |
|---|
| 605 | + if (epp == HWP_EPP_BALANCE_PERFORMANCE) |
|---|
| 594 | 606 | return 2; |
|---|
| 595 | | - if (epp <= HWP_EPP_BALANCE_POWERSAVE) |
|---|
| 607 | + if (epp == HWP_EPP_BALANCE_POWERSAVE) |
|---|
| 596 | 608 | return 3; |
|---|
| 597 | | - else |
|---|
| 609 | + if (epp == HWP_EPP_POWERSAVE) |
|---|
| 598 | 610 | return 4; |
|---|
| 599 | | - } else if (static_cpu_has(X86_FEATURE_EPB)) { |
|---|
| 611 | + *raw_epp = epp; |
|---|
| 612 | + return 0; |
|---|
| 613 | + } else if (boot_cpu_has(X86_FEATURE_EPB)) { |
|---|
| 600 | 614 | /* |
|---|
| 601 | 615 | * Range: |
|---|
| 602 | 616 | * 0x00-0x03 : Performance |
|---|
| .. | .. |
|---|
| 613 | 627 | return index; |
|---|
| 614 | 628 | } |
|---|
| 615 | 629 | |
|---|
| 630 | +static int intel_pstate_set_epp(struct cpudata *cpu, u32 epp) |
|---|
| 631 | +{ |
|---|
| 632 | + int ret; |
|---|
| 633 | + |
|---|
| 634 | + /* |
|---|
| 635 | + * Use the cached HWP Request MSR value, because in the active mode the |
|---|
| 636 | + * register itself may be updated by intel_pstate_hwp_boost_up() or |
|---|
| 637 | + * intel_pstate_hwp_boost_down() at any time. |
|---|
| 638 | + */ |
|---|
| 639 | + u64 value = READ_ONCE(cpu->hwp_req_cached); |
|---|
| 640 | + |
|---|
| 641 | + value &= ~GENMASK_ULL(31, 24); |
|---|
| 642 | + value |= (u64)epp << 24; |
|---|
| 643 | + /* |
|---|
| 644 | + * The only other updater of hwp_req_cached in the active mode, |
|---|
| 645 | + * intel_pstate_hwp_set(), is called under the same lock as this |
|---|
| 646 | + * function, so it cannot run in parallel with the update below. |
|---|
| 647 | + */ |
|---|
| 648 | + WRITE_ONCE(cpu->hwp_req_cached, value); |
|---|
| 649 | + ret = wrmsrl_on_cpu(cpu->cpu, MSR_HWP_REQUEST, value); |
|---|
| 650 | + if (!ret) |
|---|
| 651 | + cpu->epp_cached = epp; |
|---|
| 652 | + |
|---|
| 653 | + return ret; |
|---|
| 654 | +} |
|---|
| 655 | + |
|---|
| 616 | 656 | static int intel_pstate_set_energy_pref_index(struct cpudata *cpu_data, |
|---|
| 617 | | - int pref_index) |
|---|
| 657 | + int pref_index, bool use_raw, |
|---|
| 658 | + u32 raw_epp) |
|---|
| 618 | 659 | { |
|---|
| 619 | 660 | int epp = -EINVAL; |
|---|
| 620 | 661 | int ret; |
|---|
| .. | .. |
|---|
| 622 | 663 | if (!pref_index) |
|---|
| 623 | 664 | epp = cpu_data->epp_default; |
|---|
| 624 | 665 | |
|---|
| 625 | | - mutex_lock(&intel_pstate_limits_lock); |
|---|
| 626 | | - |
|---|
| 627 | | - if (static_cpu_has(X86_FEATURE_HWP_EPP)) { |
|---|
| 628 | | - u64 value; |
|---|
| 629 | | - |
|---|
| 630 | | - ret = rdmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, &value); |
|---|
| 631 | | - if (ret) |
|---|
| 632 | | - goto return_pref; |
|---|
| 633 | | - |
|---|
| 634 | | - value &= ~GENMASK_ULL(31, 24); |
|---|
| 635 | | - |
|---|
| 636 | | - if (epp == -EINVAL) |
|---|
| 666 | + if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { |
|---|
| 667 | + if (use_raw) |
|---|
| 668 | + epp = raw_epp; |
|---|
| 669 | + else if (epp == -EINVAL) |
|---|
| 637 | 670 | epp = epp_values[pref_index - 1]; |
|---|
| 638 | 671 | |
|---|
| 639 | | - value |= (u64)epp << 24; |
|---|
| 640 | | - ret = wrmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, value); |
|---|
| 672 | + /* |
|---|
| 673 | + * To avoid confusion, refuse to set EPP to any values different |
|---|
| 674 | + * from 0 (performance) if the current policy is "performance", |
|---|
| 675 | + * because those values would be overridden. |
|---|
| 676 | + */ |
|---|
| 677 | + if (epp > 0 && cpu_data->policy == CPUFREQ_POLICY_PERFORMANCE) |
|---|
| 678 | + return -EBUSY; |
|---|
| 679 | + |
|---|
| 680 | + ret = intel_pstate_set_epp(cpu_data, epp); |
|---|
| 641 | 681 | } else { |
|---|
| 642 | 682 | if (epp == -EINVAL) |
|---|
| 643 | 683 | epp = (pref_index - 1) << 2; |
|---|
| 644 | 684 | ret = intel_pstate_set_epb(cpu_data->cpu, epp); |
|---|
| 645 | 685 | } |
|---|
| 646 | | -return_pref: |
|---|
| 647 | | - mutex_unlock(&intel_pstate_limits_lock); |
|---|
| 648 | 686 | |
|---|
| 649 | 687 | return ret; |
|---|
| 650 | 688 | } |
|---|
| .. | .. |
|---|
| 665 | 703 | |
|---|
| 666 | 704 | cpufreq_freq_attr_ro(energy_performance_available_preferences); |
|---|
| 667 | 705 | |
|---|
| 706 | +static struct cpufreq_driver intel_pstate; |
|---|
| 707 | + |
|---|
| 668 | 708 | static ssize_t store_energy_performance_preference( |
|---|
| 669 | 709 | struct cpufreq_policy *policy, const char *buf, size_t count) |
|---|
| 670 | 710 | { |
|---|
| 671 | | - struct cpudata *cpu_data = all_cpu_data[policy->cpu]; |
|---|
| 711 | + struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 672 | 712 | char str_preference[21]; |
|---|
| 673 | | - int ret; |
|---|
| 713 | + bool raw = false; |
|---|
| 714 | + ssize_t ret; |
|---|
| 715 | + u32 epp = 0; |
|---|
| 674 | 716 | |
|---|
| 675 | 717 | ret = sscanf(buf, "%20s", str_preference); |
|---|
| 676 | 718 | if (ret != 1) |
|---|
| 677 | 719 | return -EINVAL; |
|---|
| 678 | 720 | |
|---|
| 679 | 721 | ret = match_string(energy_perf_strings, -1, str_preference); |
|---|
| 680 | | - if (ret < 0) |
|---|
| 681 | | - return ret; |
|---|
| 722 | + if (ret < 0) { |
|---|
| 723 | + if (!boot_cpu_has(X86_FEATURE_HWP_EPP)) |
|---|
| 724 | + return ret; |
|---|
| 682 | 725 | |
|---|
| 683 | | - intel_pstate_set_energy_pref_index(cpu_data, ret); |
|---|
| 684 | | - return count; |
|---|
| 726 | + ret = kstrtouint(buf, 10, &epp); |
|---|
| 727 | + if (ret) |
|---|
| 728 | + return ret; |
|---|
| 729 | + |
|---|
| 730 | + if (epp > 255) |
|---|
| 731 | + return -EINVAL; |
|---|
| 732 | + |
|---|
| 733 | + raw = true; |
|---|
| 734 | + } |
|---|
| 735 | + |
|---|
| 736 | + /* |
|---|
| 737 | + * This function runs with the policy R/W semaphore held, which |
|---|
| 738 | + * guarantees that the driver pointer will not change while it is |
|---|
| 739 | + * running. |
|---|
| 740 | + */ |
|---|
| 741 | + if (!intel_pstate_driver) |
|---|
| 742 | + return -EAGAIN; |
|---|
| 743 | + |
|---|
| 744 | + mutex_lock(&intel_pstate_limits_lock); |
|---|
| 745 | + |
|---|
| 746 | + if (intel_pstate_driver == &intel_pstate) { |
|---|
| 747 | + ret = intel_pstate_set_energy_pref_index(cpu, ret, raw, epp); |
|---|
| 748 | + } else { |
|---|
| 749 | + /* |
|---|
| 750 | + * In the passive mode the governor needs to be stopped on the |
|---|
| 751 | + * target CPU before the EPP update and restarted after it, |
|---|
| 752 | + * which is super-heavy-weight, so make sure it is worth doing |
|---|
| 753 | + * upfront. |
|---|
| 754 | + */ |
|---|
| 755 | + if (!raw) |
|---|
| 756 | + epp = ret ? epp_values[ret - 1] : cpu->epp_default; |
|---|
| 757 | + |
|---|
| 758 | + if (cpu->epp_cached != epp) { |
|---|
| 759 | + int err; |
|---|
| 760 | + |
|---|
| 761 | + cpufreq_stop_governor(policy); |
|---|
| 762 | + ret = intel_pstate_set_epp(cpu, epp); |
|---|
| 763 | + err = cpufreq_start_governor(policy); |
|---|
| 764 | + if (!ret) |
|---|
| 765 | + ret = err; |
|---|
| 766 | + } else { |
|---|
| 767 | + ret = 0; |
|---|
| 768 | + } |
|---|
| 769 | + } |
|---|
| 770 | + |
|---|
| 771 | + mutex_unlock(&intel_pstate_limits_lock); |
|---|
| 772 | + |
|---|
| 773 | + return ret ?: count; |
|---|
| 685 | 774 | } |
|---|
| 686 | 775 | |
|---|
| 687 | 776 | static ssize_t show_energy_performance_preference( |
|---|
| 688 | 777 | struct cpufreq_policy *policy, char *buf) |
|---|
| 689 | 778 | { |
|---|
| 690 | 779 | struct cpudata *cpu_data = all_cpu_data[policy->cpu]; |
|---|
| 691 | | - int preference; |
|---|
| 780 | + int preference, raw_epp; |
|---|
| 692 | 781 | |
|---|
| 693 | | - preference = intel_pstate_get_energy_pref_index(cpu_data); |
|---|
| 782 | + preference = intel_pstate_get_energy_pref_index(cpu_data, &raw_epp); |
|---|
| 694 | 783 | if (preference < 0) |
|---|
| 695 | 784 | return preference; |
|---|
| 696 | 785 | |
|---|
| 697 | | - return sprintf(buf, "%s\n", energy_perf_strings[preference]); |
|---|
| 786 | + if (raw_epp) |
|---|
| 787 | + return sprintf(buf, "%d\n", raw_epp); |
|---|
| 788 | + else |
|---|
| 789 | + return sprintf(buf, "%s\n", energy_perf_strings[preference]); |
|---|
| 698 | 790 | } |
|---|
| 699 | 791 | |
|---|
| 700 | 792 | cpufreq_freq_attr_rw(energy_performance_preference); |
|---|
| 701 | 793 | |
|---|
| 794 | +static ssize_t show_base_frequency(struct cpufreq_policy *policy, char *buf) |
|---|
| 795 | +{ |
|---|
| 796 | + struct cpudata *cpu; |
|---|
| 797 | + u64 cap; |
|---|
| 798 | + int ratio; |
|---|
| 799 | + |
|---|
| 800 | + ratio = intel_pstate_get_cppc_guranteed(policy->cpu); |
|---|
| 801 | + if (ratio <= 0) { |
|---|
| 802 | + rdmsrl_on_cpu(policy->cpu, MSR_HWP_CAPABILITIES, &cap); |
|---|
| 803 | + ratio = HWP_GUARANTEED_PERF(cap); |
|---|
| 804 | + } |
|---|
| 805 | + |
|---|
| 806 | + cpu = all_cpu_data[policy->cpu]; |
|---|
| 807 | + |
|---|
| 808 | + return sprintf(buf, "%d\n", ratio * cpu->pstate.scaling); |
|---|
| 809 | +} |
|---|
| 810 | + |
|---|
| 811 | +cpufreq_freq_attr_ro(base_frequency); |
|---|
| 812 | + |
|---|
| 702 | 813 | static struct freq_attr *hwp_cpufreq_attrs[] = { |
|---|
| 703 | 814 | &energy_performance_preference, |
|---|
| 704 | 815 | &energy_performance_available_preferences, |
|---|
| 816 | + &base_frequency, |
|---|
| 705 | 817 | NULL, |
|---|
| 706 | 818 | }; |
|---|
| 707 | 819 | |
|---|
| 708 | | -static void intel_pstate_get_hwp_max(unsigned int cpu, int *phy_max, |
|---|
| 820 | +static void intel_pstate_get_hwp_max(struct cpudata *cpu, int *phy_max, |
|---|
| 709 | 821 | int *current_max) |
|---|
| 710 | 822 | { |
|---|
| 711 | 823 | u64 cap; |
|---|
| 712 | 824 | |
|---|
| 713 | | - rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap); |
|---|
| 714 | | - WRITE_ONCE(all_cpu_data[cpu]->hwp_cap_cached, cap); |
|---|
| 825 | + rdmsrl_on_cpu(cpu->cpu, MSR_HWP_CAPABILITIES, &cap); |
|---|
| 826 | + WRITE_ONCE(cpu->hwp_cap_cached, cap); |
|---|
| 715 | 827 | if (global.no_turbo || global.turbo_disabled) |
|---|
| 716 | 828 | *current_max = HWP_GUARANTEED_PERF(cap); |
|---|
| 717 | 829 | else |
|---|
| .. | .. |
|---|
| 746 | 858 | |
|---|
| 747 | 859 | cpu_data->epp_policy = cpu_data->policy; |
|---|
| 748 | 860 | |
|---|
| 749 | | - if (cpu_data->epp_saved >= 0) { |
|---|
| 750 | | - epp = cpu_data->epp_saved; |
|---|
| 751 | | - cpu_data->epp_saved = -EINVAL; |
|---|
| 752 | | - goto update_epp; |
|---|
| 753 | | - } |
|---|
| 754 | | - |
|---|
| 755 | 861 | if (cpu_data->policy == CPUFREQ_POLICY_PERFORMANCE) { |
|---|
| 756 | 862 | epp = intel_pstate_get_epp(cpu_data, value); |
|---|
| 757 | 863 | cpu_data->epp_powersave = epp; |
|---|
| .. | .. |
|---|
| 778 | 884 | |
|---|
| 779 | 885 | epp = cpu_data->epp_powersave; |
|---|
| 780 | 886 | } |
|---|
| 781 | | -update_epp: |
|---|
| 782 | | - if (static_cpu_has(X86_FEATURE_HWP_EPP)) { |
|---|
| 887 | + if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { |
|---|
| 783 | 888 | value &= ~GENMASK_ULL(31, 24); |
|---|
| 784 | 889 | value |= (u64)epp << 24; |
|---|
| 785 | 890 | } else { |
|---|
| .. | .. |
|---|
| 790 | 895 | wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value); |
|---|
| 791 | 896 | } |
|---|
| 792 | 897 | |
|---|
| 793 | | -static int intel_pstate_hwp_save_state(struct cpufreq_policy *policy) |
|---|
| 898 | +static void intel_pstate_hwp_offline(struct cpudata *cpu) |
|---|
| 794 | 899 | { |
|---|
| 795 | | - struct cpudata *cpu_data = all_cpu_data[policy->cpu]; |
|---|
| 900 | + u64 value = READ_ONCE(cpu->hwp_req_cached); |
|---|
| 901 | + int min_perf; |
|---|
| 796 | 902 | |
|---|
| 797 | | - if (!hwp_active) |
|---|
| 798 | | - return 0; |
|---|
| 903 | + if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { |
|---|
| 904 | + /* |
|---|
| 905 | + * In case the EPP has been set to "performance" by the |
|---|
| 906 | + * active mode "performance" scaling algorithm, replace that |
|---|
| 907 | + * temporary value with the cached EPP one. |
|---|
| 908 | + */ |
|---|
| 909 | + value &= ~GENMASK_ULL(31, 24); |
|---|
| 910 | + value |= HWP_ENERGY_PERF_PREFERENCE(cpu->epp_cached); |
|---|
| 911 | + WRITE_ONCE(cpu->hwp_req_cached, value); |
|---|
| 912 | + } |
|---|
| 799 | 913 | |
|---|
| 800 | | - cpu_data->epp_saved = intel_pstate_get_epp(cpu_data, 0); |
|---|
| 914 | + value &= ~GENMASK_ULL(31, 0); |
|---|
| 915 | + min_perf = HWP_LOWEST_PERF(cpu->hwp_cap_cached); |
|---|
| 801 | 916 | |
|---|
| 802 | | - return 0; |
|---|
| 917 | + /* Set hwp_max = hwp_min */ |
|---|
| 918 | + value |= HWP_MAX_PERF(min_perf); |
|---|
| 919 | + value |= HWP_MIN_PERF(min_perf); |
|---|
| 920 | + |
|---|
| 921 | + /* Set EPP to min */ |
|---|
| 922 | + if (boot_cpu_has(X86_FEATURE_HWP_EPP)) |
|---|
| 923 | + value |= HWP_ENERGY_PERF_PREFERENCE(HWP_EPP_POWERSAVE); |
|---|
| 924 | + |
|---|
| 925 | + wrmsrl_on_cpu(cpu->cpu, MSR_HWP_REQUEST, value); |
|---|
| 926 | +} |
|---|
| 927 | + |
|---|
| 928 | +#define POWER_CTL_EE_ENABLE 1 |
|---|
| 929 | +#define POWER_CTL_EE_DISABLE 2 |
|---|
| 930 | + |
|---|
| 931 | +static int power_ctl_ee_state; |
|---|
| 932 | + |
|---|
| 933 | +static void set_power_ctl_ee_state(bool input) |
|---|
| 934 | +{ |
|---|
| 935 | + u64 power_ctl; |
|---|
| 936 | + |
|---|
| 937 | + mutex_lock(&intel_pstate_driver_lock); |
|---|
| 938 | + rdmsrl(MSR_IA32_POWER_CTL, power_ctl); |
|---|
| 939 | + if (input) { |
|---|
| 940 | + power_ctl &= ~BIT(MSR_IA32_POWER_CTL_BIT_EE); |
|---|
| 941 | + power_ctl_ee_state = POWER_CTL_EE_ENABLE; |
|---|
| 942 | + } else { |
|---|
| 943 | + power_ctl |= BIT(MSR_IA32_POWER_CTL_BIT_EE); |
|---|
| 944 | + power_ctl_ee_state = POWER_CTL_EE_DISABLE; |
|---|
| 945 | + } |
|---|
| 946 | + wrmsrl(MSR_IA32_POWER_CTL, power_ctl); |
|---|
| 947 | + mutex_unlock(&intel_pstate_driver_lock); |
|---|
| 803 | 948 | } |
|---|
| 804 | 949 | |
|---|
| 805 | 950 | static void intel_pstate_hwp_enable(struct cpudata *cpudata); |
|---|
| 806 | 951 | |
|---|
| 952 | +static void intel_pstate_hwp_reenable(struct cpudata *cpu) |
|---|
| 953 | +{ |
|---|
| 954 | + intel_pstate_hwp_enable(cpu); |
|---|
| 955 | + wrmsrl_on_cpu(cpu->cpu, MSR_HWP_REQUEST, READ_ONCE(cpu->hwp_req_cached)); |
|---|
| 956 | +} |
|---|
| 957 | + |
|---|
| 958 | +static int intel_pstate_suspend(struct cpufreq_policy *policy) |
|---|
| 959 | +{ |
|---|
| 960 | + struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 961 | + |
|---|
| 962 | + pr_debug("CPU %d suspending\n", cpu->cpu); |
|---|
| 963 | + |
|---|
| 964 | + cpu->suspended = true; |
|---|
| 965 | + |
|---|
| 966 | + return 0; |
|---|
| 967 | +} |
|---|
| 968 | + |
|---|
| 807 | 969 | static int intel_pstate_resume(struct cpufreq_policy *policy) |
|---|
| 808 | 970 | { |
|---|
| 809 | | - if (!hwp_active) |
|---|
| 810 | | - return 0; |
|---|
| 971 | + struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 811 | 972 | |
|---|
| 812 | | - mutex_lock(&intel_pstate_limits_lock); |
|---|
| 973 | + pr_debug("CPU %d resuming\n", cpu->cpu); |
|---|
| 813 | 974 | |
|---|
| 814 | | - if (policy->cpu == 0) |
|---|
| 815 | | - intel_pstate_hwp_enable(all_cpu_data[policy->cpu]); |
|---|
| 975 | + /* Only restore if the system default is changed */ |
|---|
| 976 | + if (power_ctl_ee_state == POWER_CTL_EE_ENABLE) |
|---|
| 977 | + set_power_ctl_ee_state(true); |
|---|
| 978 | + else if (power_ctl_ee_state == POWER_CTL_EE_DISABLE) |
|---|
| 979 | + set_power_ctl_ee_state(false); |
|---|
| 816 | 980 | |
|---|
| 817 | | - all_cpu_data[policy->cpu]->epp_policy = 0; |
|---|
| 818 | | - intel_pstate_hwp_set(policy->cpu); |
|---|
| 981 | + if (cpu->suspended && hwp_active) { |
|---|
| 982 | + mutex_lock(&intel_pstate_limits_lock); |
|---|
| 819 | 983 | |
|---|
| 820 | | - mutex_unlock(&intel_pstate_limits_lock); |
|---|
| 984 | + /* Re-enable HWP, because "online" has not done that. */ |
|---|
| 985 | + intel_pstate_hwp_reenable(cpu); |
|---|
| 986 | + |
|---|
| 987 | + mutex_unlock(&intel_pstate_limits_lock); |
|---|
| 988 | + } |
|---|
| 989 | + |
|---|
| 990 | + cpu->suspended = false; |
|---|
| 821 | 991 | |
|---|
| 822 | 992 | return 0; |
|---|
| 823 | 993 | } |
|---|
| .. | .. |
|---|
| 828 | 998 | |
|---|
| 829 | 999 | for_each_possible_cpu(cpu) |
|---|
| 830 | 1000 | cpufreq_update_policy(cpu); |
|---|
| 1001 | +} |
|---|
| 1002 | + |
|---|
| 1003 | +static void intel_pstate_update_max_freq(unsigned int cpu) |
|---|
| 1004 | +{ |
|---|
| 1005 | + struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu); |
|---|
| 1006 | + struct cpudata *cpudata; |
|---|
| 1007 | + |
|---|
| 1008 | + if (!policy) |
|---|
| 1009 | + return; |
|---|
| 1010 | + |
|---|
| 1011 | + cpudata = all_cpu_data[cpu]; |
|---|
| 1012 | + policy->cpuinfo.max_freq = global.turbo_disabled_mf ? |
|---|
| 1013 | + cpudata->pstate.max_freq : cpudata->pstate.turbo_freq; |
|---|
| 1014 | + |
|---|
| 1015 | + refresh_frequency_limits(policy); |
|---|
| 1016 | + |
|---|
| 1017 | + cpufreq_cpu_release(policy); |
|---|
| 1018 | +} |
|---|
| 1019 | + |
|---|
| 1020 | +static void intel_pstate_update_limits(unsigned int cpu) |
|---|
| 1021 | +{ |
|---|
| 1022 | + mutex_lock(&intel_pstate_driver_lock); |
|---|
| 1023 | + |
|---|
| 1024 | + update_turbo_state(); |
|---|
| 1025 | + /* |
|---|
| 1026 | + * If turbo has been turned on or off globally, policy limits for |
|---|
| 1027 | + * all CPUs need to be updated to reflect that. |
|---|
| 1028 | + */ |
|---|
| 1029 | + if (global.turbo_disabled_mf != global.turbo_disabled) { |
|---|
| 1030 | + global.turbo_disabled_mf = global.turbo_disabled; |
|---|
| 1031 | + arch_set_max_freq_ratio(global.turbo_disabled); |
|---|
| 1032 | + for_each_possible_cpu(cpu) |
|---|
| 1033 | + intel_pstate_update_max_freq(cpu); |
|---|
| 1034 | + } else { |
|---|
| 1035 | + cpufreq_update_policy(cpu); |
|---|
| 1036 | + } |
|---|
| 1037 | + |
|---|
| 1038 | + mutex_unlock(&intel_pstate_driver_lock); |
|---|
| 831 | 1039 | } |
|---|
| 832 | 1040 | |
|---|
| 833 | 1041 | /************************** sysfs begin ************************/ |
|---|
| .. | .. |
|---|
| 983 | 1191 | return count; |
|---|
| 984 | 1192 | } |
|---|
| 985 | 1193 | |
|---|
| 1194 | +static void update_qos_request(enum freq_qos_req_type type) |
|---|
| 1195 | +{ |
|---|
| 1196 | + int max_state, turbo_max, freq, i, perf_pct; |
|---|
| 1197 | + struct freq_qos_request *req; |
|---|
| 1198 | + struct cpufreq_policy *policy; |
|---|
| 1199 | + |
|---|
| 1200 | + for_each_possible_cpu(i) { |
|---|
| 1201 | + struct cpudata *cpu = all_cpu_data[i]; |
|---|
| 1202 | + |
|---|
| 1203 | + policy = cpufreq_cpu_get(i); |
|---|
| 1204 | + if (!policy) |
|---|
| 1205 | + continue; |
|---|
| 1206 | + |
|---|
| 1207 | + req = policy->driver_data; |
|---|
| 1208 | + cpufreq_cpu_put(policy); |
|---|
| 1209 | + |
|---|
| 1210 | + if (!req) |
|---|
| 1211 | + continue; |
|---|
| 1212 | + |
|---|
| 1213 | + if (hwp_active) |
|---|
| 1214 | + intel_pstate_get_hwp_max(cpu, &turbo_max, &max_state); |
|---|
| 1215 | + else |
|---|
| 1216 | + turbo_max = cpu->pstate.turbo_pstate; |
|---|
| 1217 | + |
|---|
| 1218 | + if (type == FREQ_QOS_MIN) { |
|---|
| 1219 | + perf_pct = global.min_perf_pct; |
|---|
| 1220 | + } else { |
|---|
| 1221 | + req++; |
|---|
| 1222 | + perf_pct = global.max_perf_pct; |
|---|
| 1223 | + } |
|---|
| 1224 | + |
|---|
| 1225 | + freq = DIV_ROUND_UP(turbo_max * perf_pct, 100); |
|---|
| 1226 | + freq *= cpu->pstate.scaling; |
|---|
| 1227 | + |
|---|
| 1228 | + if (freq_qos_update_request(req, freq) < 0) |
|---|
| 1229 | + pr_warn("Failed to update freq constraint: CPU%d\n", i); |
|---|
| 1230 | + } |
|---|
| 1231 | +} |
|---|
| 1232 | + |
|---|
| 986 | 1233 | static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b, |
|---|
| 987 | 1234 | const char *buf, size_t count) |
|---|
| 988 | 1235 | { |
|---|
| .. | .. |
|---|
| 1006 | 1253 | |
|---|
| 1007 | 1254 | mutex_unlock(&intel_pstate_limits_lock); |
|---|
| 1008 | 1255 | |
|---|
| 1009 | | - intel_pstate_update_policies(); |
|---|
| 1256 | + if (intel_pstate_driver == &intel_pstate) |
|---|
| 1257 | + intel_pstate_update_policies(); |
|---|
| 1258 | + else |
|---|
| 1259 | + update_qos_request(FREQ_QOS_MAX); |
|---|
| 1010 | 1260 | |
|---|
| 1011 | 1261 | mutex_unlock(&intel_pstate_driver_lock); |
|---|
| 1012 | 1262 | |
|---|
| .. | .. |
|---|
| 1037 | 1287 | |
|---|
| 1038 | 1288 | mutex_unlock(&intel_pstate_limits_lock); |
|---|
| 1039 | 1289 | |
|---|
| 1040 | | - intel_pstate_update_policies(); |
|---|
| 1290 | + if (intel_pstate_driver == &intel_pstate) |
|---|
| 1291 | + intel_pstate_update_policies(); |
|---|
| 1292 | + else |
|---|
| 1293 | + update_qos_request(FREQ_QOS_MIN); |
|---|
| 1041 | 1294 | |
|---|
| 1042 | 1295 | mutex_unlock(&intel_pstate_driver_lock); |
|---|
| 1043 | 1296 | |
|---|
| .. | .. |
|---|
| 1069 | 1322 | return count; |
|---|
| 1070 | 1323 | } |
|---|
| 1071 | 1324 | |
|---|
| 1325 | +static ssize_t show_energy_efficiency(struct kobject *kobj, struct kobj_attribute *attr, |
|---|
| 1326 | + char *buf) |
|---|
| 1327 | +{ |
|---|
| 1328 | + u64 power_ctl; |
|---|
| 1329 | + int enable; |
|---|
| 1330 | + |
|---|
| 1331 | + rdmsrl(MSR_IA32_POWER_CTL, power_ctl); |
|---|
| 1332 | + enable = !!(power_ctl & BIT(MSR_IA32_POWER_CTL_BIT_EE)); |
|---|
| 1333 | + return sprintf(buf, "%d\n", !enable); |
|---|
| 1334 | +} |
|---|
| 1335 | + |
|---|
| 1336 | +static ssize_t store_energy_efficiency(struct kobject *a, struct kobj_attribute *b, |
|---|
| 1337 | + const char *buf, size_t count) |
|---|
| 1338 | +{ |
|---|
| 1339 | + bool input; |
|---|
| 1340 | + int ret; |
|---|
| 1341 | + |
|---|
| 1342 | + ret = kstrtobool(buf, &input); |
|---|
| 1343 | + if (ret) |
|---|
| 1344 | + return ret; |
|---|
| 1345 | + |
|---|
| 1346 | + set_power_ctl_ee_state(input); |
|---|
| 1347 | + |
|---|
| 1348 | + return count; |
|---|
| 1349 | +} |
|---|
| 1350 | + |
|---|
| 1072 | 1351 | show_one(max_perf_pct, max_perf_pct); |
|---|
| 1073 | 1352 | show_one(min_perf_pct, min_perf_pct); |
|---|
| 1074 | 1353 | |
|---|
| .. | .. |
|---|
| 1079 | 1358 | define_one_global_ro(turbo_pct); |
|---|
| 1080 | 1359 | define_one_global_ro(num_pstates); |
|---|
| 1081 | 1360 | define_one_global_rw(hwp_dynamic_boost); |
|---|
| 1361 | +define_one_global_rw(energy_efficiency); |
|---|
| 1082 | 1362 | |
|---|
| 1083 | 1363 | static struct attribute *intel_pstate_attributes[] = { |
|---|
| 1084 | 1364 | &status.attr, |
|---|
| .. | .. |
|---|
| 1092 | 1372 | .attrs = intel_pstate_attributes, |
|---|
| 1093 | 1373 | }; |
|---|
| 1094 | 1374 | |
|---|
| 1375 | +static const struct x86_cpu_id intel_pstate_cpu_ee_disable_ids[]; |
|---|
| 1376 | + |
|---|
| 1377 | +static struct kobject *intel_pstate_kobject; |
|---|
| 1378 | + |
|---|
| 1095 | 1379 | static void __init intel_pstate_sysfs_expose_params(void) |
|---|
| 1096 | 1380 | { |
|---|
| 1097 | | - struct kobject *intel_pstate_kobject; |
|---|
| 1098 | 1381 | int rc; |
|---|
| 1099 | 1382 | |
|---|
| 1100 | 1383 | intel_pstate_kobject = kobject_create_and_add("intel_pstate", |
|---|
| .. | .. |
|---|
| 1119 | 1402 | rc = sysfs_create_file(intel_pstate_kobject, &min_perf_pct.attr); |
|---|
| 1120 | 1403 | WARN_ON(rc); |
|---|
| 1121 | 1404 | |
|---|
| 1122 | | - if (hwp_active) { |
|---|
| 1123 | | - rc = sysfs_create_file(intel_pstate_kobject, |
|---|
| 1124 | | - &hwp_dynamic_boost.attr); |
|---|
| 1405 | + if (x86_match_cpu(intel_pstate_cpu_ee_disable_ids)) { |
|---|
| 1406 | + rc = sysfs_create_file(intel_pstate_kobject, &energy_efficiency.attr); |
|---|
| 1125 | 1407 | WARN_ON(rc); |
|---|
| 1126 | 1408 | } |
|---|
| 1127 | 1409 | } |
|---|
| 1410 | + |
|---|
| 1411 | +static void __init intel_pstate_sysfs_remove(void) |
|---|
| 1412 | +{ |
|---|
| 1413 | + if (!intel_pstate_kobject) |
|---|
| 1414 | + return; |
|---|
| 1415 | + |
|---|
| 1416 | + sysfs_remove_group(intel_pstate_kobject, &intel_pstate_attr_group); |
|---|
| 1417 | + |
|---|
| 1418 | + if (!per_cpu_limits) { |
|---|
| 1419 | + sysfs_remove_file(intel_pstate_kobject, &max_perf_pct.attr); |
|---|
| 1420 | + sysfs_remove_file(intel_pstate_kobject, &min_perf_pct.attr); |
|---|
| 1421 | + |
|---|
| 1422 | + if (x86_match_cpu(intel_pstate_cpu_ee_disable_ids)) |
|---|
| 1423 | + sysfs_remove_file(intel_pstate_kobject, &energy_efficiency.attr); |
|---|
| 1424 | + } |
|---|
| 1425 | + |
|---|
| 1426 | + kobject_put(intel_pstate_kobject); |
|---|
| 1427 | +} |
|---|
| 1428 | + |
|---|
| 1429 | +static void intel_pstate_sysfs_expose_hwp_dynamic_boost(void) |
|---|
| 1430 | +{ |
|---|
| 1431 | + int rc; |
|---|
| 1432 | + |
|---|
| 1433 | + if (!hwp_active) |
|---|
| 1434 | + return; |
|---|
| 1435 | + |
|---|
| 1436 | + rc = sysfs_create_file(intel_pstate_kobject, &hwp_dynamic_boost.attr); |
|---|
| 1437 | + WARN_ON_ONCE(rc); |
|---|
| 1438 | +} |
|---|
| 1439 | + |
|---|
| 1440 | +static void intel_pstate_sysfs_hide_hwp_dynamic_boost(void) |
|---|
| 1441 | +{ |
|---|
| 1442 | + if (!hwp_active) |
|---|
| 1443 | + return; |
|---|
| 1444 | + |
|---|
| 1445 | + sysfs_remove_file(intel_pstate_kobject, &hwp_dynamic_boost.attr); |
|---|
| 1446 | +} |
|---|
| 1447 | + |
|---|
| 1128 | 1448 | /************************** sysfs end ************************/ |
|---|
| 1129 | 1449 | |
|---|
| 1130 | 1450 | static void intel_pstate_hwp_enable(struct cpudata *cpudata) |
|---|
| 1131 | 1451 | { |
|---|
| 1132 | 1452 | /* First disable HWP notification interrupt as we don't process them */ |
|---|
| 1133 | | - if (static_cpu_has(X86_FEATURE_HWP_NOTIFY)) |
|---|
| 1453 | + if (boot_cpu_has(X86_FEATURE_HWP_NOTIFY)) |
|---|
| 1134 | 1454 | wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00); |
|---|
| 1135 | 1455 | |
|---|
| 1136 | 1456 | wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1); |
|---|
| 1137 | | - cpudata->epp_policy = 0; |
|---|
| 1138 | 1457 | if (cpudata->epp_default == -EINVAL) |
|---|
| 1139 | 1458 | cpudata->epp_default = intel_pstate_get_epp(cpudata, 0); |
|---|
| 1140 | | -} |
|---|
| 1141 | | - |
|---|
| 1142 | | -#define MSR_IA32_POWER_CTL_BIT_EE 19 |
|---|
| 1143 | | - |
|---|
| 1144 | | -/* Disable energy efficiency optimization */ |
|---|
| 1145 | | -static void intel_pstate_disable_ee(int cpu) |
|---|
| 1146 | | -{ |
|---|
| 1147 | | - u64 power_ctl; |
|---|
| 1148 | | - int ret; |
|---|
| 1149 | | - |
|---|
| 1150 | | - ret = rdmsrl_on_cpu(cpu, MSR_IA32_POWER_CTL, &power_ctl); |
|---|
| 1151 | | - if (ret) |
|---|
| 1152 | | - return; |
|---|
| 1153 | | - |
|---|
| 1154 | | - if (!(power_ctl & BIT(MSR_IA32_POWER_CTL_BIT_EE))) { |
|---|
| 1155 | | - pr_info("Disabling energy efficiency optimization\n"); |
|---|
| 1156 | | - power_ctl |= BIT(MSR_IA32_POWER_CTL_BIT_EE); |
|---|
| 1157 | | - wrmsrl_on_cpu(cpu, MSR_IA32_POWER_CTL, power_ctl); |
|---|
| 1158 | | - } |
|---|
| 1159 | 1459 | } |
|---|
| 1160 | 1460 | |
|---|
| 1161 | 1461 | static int atom_get_min_pstate(void) |
|---|
| .. | .. |
|---|
| 1383 | 1683 | return ret; |
|---|
| 1384 | 1684 | } |
|---|
| 1385 | 1685 | |
|---|
| 1386 | | -static int intel_pstate_get_base_pstate(struct cpudata *cpu) |
|---|
| 1387 | | -{ |
|---|
| 1388 | | - return global.no_turbo || global.turbo_disabled ? |
|---|
| 1389 | | - cpu->pstate.max_pstate : cpu->pstate.turbo_pstate; |
|---|
| 1390 | | -} |
|---|
| 1391 | | - |
|---|
| 1392 | 1686 | static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) |
|---|
| 1393 | 1687 | { |
|---|
| 1394 | 1688 | trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu); |
|---|
| .. | .. |
|---|
| 1409 | 1703 | |
|---|
| 1410 | 1704 | static void intel_pstate_max_within_limits(struct cpudata *cpu) |
|---|
| 1411 | 1705 | { |
|---|
| 1412 | | - int pstate; |
|---|
| 1706 | + int pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio); |
|---|
| 1413 | 1707 | |
|---|
| 1414 | 1708 | update_turbo_state(); |
|---|
| 1415 | | - pstate = intel_pstate_get_base_pstate(cpu); |
|---|
| 1416 | | - pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio); |
|---|
| 1417 | 1709 | intel_pstate_set_pstate(cpu, pstate); |
|---|
| 1418 | 1710 | } |
|---|
| 1419 | 1711 | |
|---|
| .. | .. |
|---|
| 1427 | 1719 | if (hwp_active && !hwp_mode_bdw) { |
|---|
| 1428 | 1720 | unsigned int phy_max, current_max; |
|---|
| 1429 | 1721 | |
|---|
| 1430 | | - intel_pstate_get_hwp_max(cpu->cpu, &phy_max, ¤t_max); |
|---|
| 1722 | + intel_pstate_get_hwp_max(cpu, &phy_max, ¤t_max); |
|---|
| 1431 | 1723 | cpu->pstate.turbo_freq = phy_max * cpu->pstate.scaling; |
|---|
| 1432 | 1724 | cpu->pstate.turbo_pstate = phy_max; |
|---|
| 1433 | 1725 | cpu->pstate.max_pstate = HWP_GUARANTEED_PERF(READ_ONCE(cpu->hwp_cap_cached)); |
|---|
| .. | .. |
|---|
| 1619 | 1911 | static inline int32_t get_target_pstate(struct cpudata *cpu) |
|---|
| 1620 | 1912 | { |
|---|
| 1621 | 1913 | struct sample *sample = &cpu->sample; |
|---|
| 1622 | | - int32_t busy_frac, boost; |
|---|
| 1914 | + int32_t busy_frac; |
|---|
| 1623 | 1915 | int target, avg_pstate; |
|---|
| 1624 | 1916 | |
|---|
| 1625 | 1917 | busy_frac = div_fp(sample->mperf << cpu->aperf_mperf_shift, |
|---|
| 1626 | 1918 | sample->tsc); |
|---|
| 1627 | 1919 | |
|---|
| 1628 | | - boost = cpu->iowait_boost; |
|---|
| 1629 | | - cpu->iowait_boost >>= 1; |
|---|
| 1630 | | - |
|---|
| 1631 | | - if (busy_frac < boost) |
|---|
| 1632 | | - busy_frac = boost; |
|---|
| 1920 | + if (busy_frac < cpu->iowait_boost) |
|---|
| 1921 | + busy_frac = cpu->iowait_boost; |
|---|
| 1633 | 1922 | |
|---|
| 1634 | 1923 | sample->busy_scaled = busy_frac * 100; |
|---|
| 1635 | 1924 | |
|---|
| .. | .. |
|---|
| 1656 | 1945 | |
|---|
| 1657 | 1946 | static int intel_pstate_prepare_request(struct cpudata *cpu, int pstate) |
|---|
| 1658 | 1947 | { |
|---|
| 1659 | | - int max_pstate = intel_pstate_get_base_pstate(cpu); |
|---|
| 1660 | | - int min_pstate; |
|---|
| 1948 | + int min_pstate = max(cpu->pstate.min_pstate, cpu->min_perf_ratio); |
|---|
| 1949 | + int max_pstate = max(min_pstate, cpu->max_perf_ratio); |
|---|
| 1661 | 1950 | |
|---|
| 1662 | | - min_pstate = max(cpu->pstate.min_pstate, cpu->min_perf_ratio); |
|---|
| 1663 | | - max_pstate = max(min_pstate, cpu->max_perf_ratio); |
|---|
| 1664 | 1951 | return clamp_t(int, pstate, min_pstate, max_pstate); |
|---|
| 1665 | 1952 | } |
|---|
| 1666 | 1953 | |
|---|
| .. | .. |
|---|
| 1708 | 1995 | if (smp_processor_id() != cpu->cpu) |
|---|
| 1709 | 1996 | return; |
|---|
| 1710 | 1997 | |
|---|
| 1998 | + delta_ns = time - cpu->last_update; |
|---|
| 1711 | 1999 | if (flags & SCHED_CPUFREQ_IOWAIT) { |
|---|
| 1712 | | - cpu->iowait_boost = int_tofp(1); |
|---|
| 1713 | | - cpu->last_update = time; |
|---|
| 1714 | | - /* |
|---|
| 1715 | | - * The last time the busy was 100% so P-state was max anyway |
|---|
| 1716 | | - * so avoid overhead of computation. |
|---|
| 1717 | | - */ |
|---|
| 1718 | | - if (fp_toint(cpu->sample.busy_scaled) == 100) |
|---|
| 1719 | | - return; |
|---|
| 1720 | | - |
|---|
| 1721 | | - goto set_pstate; |
|---|
| 2000 | + /* Start over if the CPU may have been idle. */ |
|---|
| 2001 | + if (delta_ns > TICK_NSEC) { |
|---|
| 2002 | + cpu->iowait_boost = ONE_EIGHTH_FP; |
|---|
| 2003 | + } else if (cpu->iowait_boost >= ONE_EIGHTH_FP) { |
|---|
| 2004 | + cpu->iowait_boost <<= 1; |
|---|
| 2005 | + if (cpu->iowait_boost > int_tofp(1)) |
|---|
| 2006 | + cpu->iowait_boost = int_tofp(1); |
|---|
| 2007 | + } else { |
|---|
| 2008 | + cpu->iowait_boost = ONE_EIGHTH_FP; |
|---|
| 2009 | + } |
|---|
| 1722 | 2010 | } else if (cpu->iowait_boost) { |
|---|
| 1723 | 2011 | /* Clear iowait_boost if the CPU may have been idle. */ |
|---|
| 1724 | | - delta_ns = time - cpu->last_update; |
|---|
| 1725 | 2012 | if (delta_ns > TICK_NSEC) |
|---|
| 1726 | 2013 | cpu->iowait_boost = 0; |
|---|
| 2014 | + else |
|---|
| 2015 | + cpu->iowait_boost >>= 1; |
|---|
| 1727 | 2016 | } |
|---|
| 1728 | 2017 | cpu->last_update = time; |
|---|
| 1729 | 2018 | delta_ns = time - cpu->sample.time; |
|---|
| 1730 | 2019 | if ((s64)delta_ns < INTEL_PSTATE_SAMPLING_INTERVAL) |
|---|
| 1731 | 2020 | return; |
|---|
| 1732 | 2021 | |
|---|
| 1733 | | -set_pstate: |
|---|
| 1734 | 2022 | if (intel_pstate_sample(cpu, time)) |
|---|
| 1735 | 2023 | intel_pstate_adjust_pstate(cpu); |
|---|
| 1736 | 2024 | } |
|---|
| .. | .. |
|---|
| 1774 | 2062 | .get_val = core_get_val, |
|---|
| 1775 | 2063 | }; |
|---|
| 1776 | 2064 | |
|---|
| 1777 | | -#define ICPU(model, policy) \ |
|---|
| 1778 | | - { X86_VENDOR_INTEL, 6, model, X86_FEATURE_APERFMPERF,\ |
|---|
| 1779 | | - (unsigned long)&policy } |
|---|
| 2065 | +#define X86_MATCH(model, policy) \ |
|---|
| 2066 | + X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, INTEL_FAM6_##model, \ |
|---|
| 2067 | + X86_FEATURE_APERFMPERF, &policy) |
|---|
| 1780 | 2068 | |
|---|
| 1781 | 2069 | static const struct x86_cpu_id intel_pstate_cpu_ids[] = { |
|---|
| 1782 | | - ICPU(INTEL_FAM6_SANDYBRIDGE, core_funcs), |
|---|
| 1783 | | - ICPU(INTEL_FAM6_SANDYBRIDGE_X, core_funcs), |
|---|
| 1784 | | - ICPU(INTEL_FAM6_ATOM_SILVERMONT, silvermont_funcs), |
|---|
| 1785 | | - ICPU(INTEL_FAM6_IVYBRIDGE, core_funcs), |
|---|
| 1786 | | - ICPU(INTEL_FAM6_HASWELL_CORE, core_funcs), |
|---|
| 1787 | | - ICPU(INTEL_FAM6_BROADWELL_CORE, core_funcs), |
|---|
| 1788 | | - ICPU(INTEL_FAM6_IVYBRIDGE_X, core_funcs), |
|---|
| 1789 | | - ICPU(INTEL_FAM6_HASWELL_X, core_funcs), |
|---|
| 1790 | | - ICPU(INTEL_FAM6_HASWELL_ULT, core_funcs), |
|---|
| 1791 | | - ICPU(INTEL_FAM6_HASWELL_GT3E, core_funcs), |
|---|
| 1792 | | - ICPU(INTEL_FAM6_BROADWELL_GT3E, core_funcs), |
|---|
| 1793 | | - ICPU(INTEL_FAM6_ATOM_AIRMONT, airmont_funcs), |
|---|
| 1794 | | - ICPU(INTEL_FAM6_SKYLAKE_MOBILE, core_funcs), |
|---|
| 1795 | | - ICPU(INTEL_FAM6_BROADWELL_X, core_funcs), |
|---|
| 1796 | | - ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_funcs), |
|---|
| 1797 | | - ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_funcs), |
|---|
| 1798 | | - ICPU(INTEL_FAM6_XEON_PHI_KNL, knl_funcs), |
|---|
| 1799 | | - ICPU(INTEL_FAM6_XEON_PHI_KNM, knl_funcs), |
|---|
| 1800 | | - ICPU(INTEL_FAM6_ATOM_GOLDMONT, core_funcs), |
|---|
| 1801 | | - ICPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, core_funcs), |
|---|
| 1802 | | - ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs), |
|---|
| 2070 | + X86_MATCH(SANDYBRIDGE, core_funcs), |
|---|
| 2071 | + X86_MATCH(SANDYBRIDGE_X, core_funcs), |
|---|
| 2072 | + X86_MATCH(ATOM_SILVERMONT, silvermont_funcs), |
|---|
| 2073 | + X86_MATCH(IVYBRIDGE, core_funcs), |
|---|
| 2074 | + X86_MATCH(HASWELL, core_funcs), |
|---|
| 2075 | + X86_MATCH(BROADWELL, core_funcs), |
|---|
| 2076 | + X86_MATCH(IVYBRIDGE_X, core_funcs), |
|---|
| 2077 | + X86_MATCH(HASWELL_X, core_funcs), |
|---|
| 2078 | + X86_MATCH(HASWELL_L, core_funcs), |
|---|
| 2079 | + X86_MATCH(HASWELL_G, core_funcs), |
|---|
| 2080 | + X86_MATCH(BROADWELL_G, core_funcs), |
|---|
| 2081 | + X86_MATCH(ATOM_AIRMONT, airmont_funcs), |
|---|
| 2082 | + X86_MATCH(SKYLAKE_L, core_funcs), |
|---|
| 2083 | + X86_MATCH(BROADWELL_X, core_funcs), |
|---|
| 2084 | + X86_MATCH(SKYLAKE, core_funcs), |
|---|
| 2085 | + X86_MATCH(BROADWELL_D, core_funcs), |
|---|
| 2086 | + X86_MATCH(XEON_PHI_KNL, knl_funcs), |
|---|
| 2087 | + X86_MATCH(XEON_PHI_KNM, knl_funcs), |
|---|
| 2088 | + X86_MATCH(ATOM_GOLDMONT, core_funcs), |
|---|
| 2089 | + X86_MATCH(ATOM_GOLDMONT_PLUS, core_funcs), |
|---|
| 2090 | + X86_MATCH(SKYLAKE_X, core_funcs), |
|---|
| 1803 | 2091 | {} |
|---|
| 1804 | 2092 | }; |
|---|
| 1805 | 2093 | MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); |
|---|
| 1806 | 2094 | |
|---|
| 1807 | 2095 | static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = { |
|---|
| 1808 | | - ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_funcs), |
|---|
| 1809 | | - ICPU(INTEL_FAM6_BROADWELL_X, core_funcs), |
|---|
| 1810 | | - ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs), |
|---|
| 2096 | + X86_MATCH(BROADWELL_D, core_funcs), |
|---|
| 2097 | + X86_MATCH(BROADWELL_X, core_funcs), |
|---|
| 2098 | + X86_MATCH(SKYLAKE_X, core_funcs), |
|---|
| 1811 | 2099 | {} |
|---|
| 1812 | 2100 | }; |
|---|
| 1813 | 2101 | |
|---|
| 1814 | 2102 | static const struct x86_cpu_id intel_pstate_cpu_ee_disable_ids[] = { |
|---|
| 1815 | | - ICPU(INTEL_FAM6_KABYLAKE_DESKTOP, core_funcs), |
|---|
| 2103 | + X86_MATCH(KABYLAKE, core_funcs), |
|---|
| 1816 | 2104 | {} |
|---|
| 1817 | 2105 | }; |
|---|
| 1818 | 2106 | |
|---|
| 1819 | 2107 | static const struct x86_cpu_id intel_pstate_hwp_boost_ids[] = { |
|---|
| 1820 | | - ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs), |
|---|
| 1821 | | - ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_funcs), |
|---|
| 2108 | + X86_MATCH(SKYLAKE_X, core_funcs), |
|---|
| 2109 | + X86_MATCH(SKYLAKE, core_funcs), |
|---|
| 1822 | 2110 | {} |
|---|
| 1823 | 2111 | }; |
|---|
| 1824 | 2112 | |
|---|
| .. | .. |
|---|
| 1835 | 2123 | |
|---|
| 1836 | 2124 | all_cpu_data[cpunum] = cpu; |
|---|
| 1837 | 2125 | |
|---|
| 2126 | + cpu->cpu = cpunum; |
|---|
| 2127 | + |
|---|
| 1838 | 2128 | cpu->epp_default = -EINVAL; |
|---|
| 1839 | | - cpu->epp_powersave = -EINVAL; |
|---|
| 1840 | | - cpu->epp_saved = -EINVAL; |
|---|
| 2129 | + |
|---|
| 2130 | + if (hwp_active) { |
|---|
| 2131 | + const struct x86_cpu_id *id; |
|---|
| 2132 | + |
|---|
| 2133 | + intel_pstate_hwp_enable(cpu); |
|---|
| 2134 | + |
|---|
| 2135 | + id = x86_match_cpu(intel_pstate_hwp_boost_ids); |
|---|
| 2136 | + if (id && intel_pstate_acpi_pm_profile_server()) |
|---|
| 2137 | + hwp_boost = true; |
|---|
| 2138 | + } |
|---|
| 2139 | + } else if (hwp_active) { |
|---|
| 2140 | + /* |
|---|
| 2141 | + * Re-enable HWP in case this happens after a resume from ACPI |
|---|
| 2142 | + * S3 if the CPU was offline during the whole system/resume |
|---|
| 2143 | + * cycle. |
|---|
| 2144 | + */ |
|---|
| 2145 | + intel_pstate_hwp_reenable(cpu); |
|---|
| 1841 | 2146 | } |
|---|
| 1842 | 2147 | |
|---|
| 1843 | | - cpu = all_cpu_data[cpunum]; |
|---|
| 1844 | | - |
|---|
| 1845 | | - cpu->cpu = cpunum; |
|---|
| 1846 | | - |
|---|
| 1847 | | - if (hwp_active) { |
|---|
| 1848 | | - const struct x86_cpu_id *id; |
|---|
| 1849 | | - |
|---|
| 1850 | | - id = x86_match_cpu(intel_pstate_cpu_ee_disable_ids); |
|---|
| 1851 | | - if (id) |
|---|
| 1852 | | - intel_pstate_disable_ee(cpunum); |
|---|
| 1853 | | - |
|---|
| 1854 | | - intel_pstate_hwp_enable(cpu); |
|---|
| 1855 | | - |
|---|
| 1856 | | - id = x86_match_cpu(intel_pstate_hwp_boost_ids); |
|---|
| 1857 | | - if (id && intel_pstate_acpi_pm_profile_server()) |
|---|
| 1858 | | - hwp_boost = true; |
|---|
| 1859 | | - } |
|---|
| 2148 | + cpu->epp_powersave = -EINVAL; |
|---|
| 2149 | + cpu->epp_policy = 0; |
|---|
| 1860 | 2150 | |
|---|
| 1861 | 2151 | intel_pstate_get_cpu_pstates(cpu); |
|---|
| 1862 | 2152 | |
|---|
| .. | .. |
|---|
| 1893 | 2183 | |
|---|
| 1894 | 2184 | cpufreq_remove_update_util_hook(cpu); |
|---|
| 1895 | 2185 | cpu_data->update_util_set = false; |
|---|
| 1896 | | - synchronize_sched(); |
|---|
| 2186 | + synchronize_rcu(); |
|---|
| 1897 | 2187 | } |
|---|
| 1898 | 2188 | |
|---|
| 1899 | 2189 | static int intel_pstate_get_max_freq(struct cpudata *cpu) |
|---|
| .. | .. |
|---|
| 1902 | 2192 | cpu->pstate.max_freq : cpu->pstate.turbo_freq; |
|---|
| 1903 | 2193 | } |
|---|
| 1904 | 2194 | |
|---|
| 1905 | | -static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy, |
|---|
| 1906 | | - struct cpudata *cpu) |
|---|
| 2195 | +static void intel_pstate_update_perf_limits(struct cpudata *cpu, |
|---|
| 2196 | + unsigned int policy_min, |
|---|
| 2197 | + unsigned int policy_max) |
|---|
| 1907 | 2198 | { |
|---|
| 1908 | | - int max_freq = intel_pstate_get_max_freq(cpu); |
|---|
| 1909 | 2199 | int32_t max_policy_perf, min_policy_perf; |
|---|
| 1910 | 2200 | int max_state, turbo_max; |
|---|
| 2201 | + int max_freq; |
|---|
| 1911 | 2202 | |
|---|
| 1912 | 2203 | /* |
|---|
| 1913 | 2204 | * HWP needs some special consideration, because on BDX the |
|---|
| .. | .. |
|---|
| 1915 | 2206 | * rather than pure ratios. |
|---|
| 1916 | 2207 | */ |
|---|
| 1917 | 2208 | if (hwp_active) { |
|---|
| 1918 | | - intel_pstate_get_hwp_max(cpu->cpu, &turbo_max, &max_state); |
|---|
| 2209 | + intel_pstate_get_hwp_max(cpu, &turbo_max, &max_state); |
|---|
| 1919 | 2210 | } else { |
|---|
| 1920 | | - max_state = intel_pstate_get_base_pstate(cpu); |
|---|
| 2211 | + max_state = global.no_turbo || global.turbo_disabled ? |
|---|
| 2212 | + cpu->pstate.max_pstate : cpu->pstate.turbo_pstate; |
|---|
| 1921 | 2213 | turbo_max = cpu->pstate.turbo_pstate; |
|---|
| 1922 | 2214 | } |
|---|
| 2215 | + max_freq = max_state * cpu->pstate.scaling; |
|---|
| 1923 | 2216 | |
|---|
| 1924 | | - max_policy_perf = max_state * policy->max / max_freq; |
|---|
| 1925 | | - if (policy->max == policy->min) { |
|---|
| 2217 | + max_policy_perf = max_state * policy_max / max_freq; |
|---|
| 2218 | + if (policy_max == policy_min) { |
|---|
| 1926 | 2219 | min_policy_perf = max_policy_perf; |
|---|
| 1927 | 2220 | } else { |
|---|
| 1928 | | - min_policy_perf = max_state * policy->min / max_freq; |
|---|
| 2221 | + min_policy_perf = max_state * policy_min / max_freq; |
|---|
| 1929 | 2222 | min_policy_perf = clamp_t(int32_t, min_policy_perf, |
|---|
| 1930 | 2223 | 0, max_policy_perf); |
|---|
| 1931 | 2224 | } |
|---|
| 1932 | 2225 | |
|---|
| 1933 | 2226 | pr_debug("cpu:%d max_state %d min_policy_perf:%d max_policy_perf:%d\n", |
|---|
| 1934 | | - policy->cpu, max_state, |
|---|
| 1935 | | - min_policy_perf, max_policy_perf); |
|---|
| 2227 | + cpu->cpu, max_state, min_policy_perf, max_policy_perf); |
|---|
| 1936 | 2228 | |
|---|
| 1937 | 2229 | /* Normalize user input to [min_perf, max_perf] */ |
|---|
| 1938 | 2230 | if (per_cpu_limits) { |
|---|
| .. | .. |
|---|
| 1946 | 2238 | global_min = DIV_ROUND_UP(turbo_max * global.min_perf_pct, 100); |
|---|
| 1947 | 2239 | global_min = clamp_t(int32_t, global_min, 0, global_max); |
|---|
| 1948 | 2240 | |
|---|
| 1949 | | - pr_debug("cpu:%d global_min:%d global_max:%d\n", policy->cpu, |
|---|
| 2241 | + pr_debug("cpu:%d global_min:%d global_max:%d\n", cpu->cpu, |
|---|
| 1950 | 2242 | global_min, global_max); |
|---|
| 1951 | 2243 | |
|---|
| 1952 | 2244 | cpu->min_perf_ratio = max(min_policy_perf, global_min); |
|---|
| .. | .. |
|---|
| 1959 | 2251 | cpu->max_perf_ratio); |
|---|
| 1960 | 2252 | |
|---|
| 1961 | 2253 | } |
|---|
| 1962 | | - pr_debug("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n", policy->cpu, |
|---|
| 2254 | + pr_debug("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n", cpu->cpu, |
|---|
| 1963 | 2255 | cpu->max_perf_ratio, |
|---|
| 1964 | 2256 | cpu->min_perf_ratio); |
|---|
| 1965 | 2257 | } |
|---|
| .. | .. |
|---|
| 1979 | 2271 | |
|---|
| 1980 | 2272 | mutex_lock(&intel_pstate_limits_lock); |
|---|
| 1981 | 2273 | |
|---|
| 1982 | | - intel_pstate_update_perf_limits(policy, cpu); |
|---|
| 2274 | + intel_pstate_update_perf_limits(cpu, policy->min, policy->max); |
|---|
| 1983 | 2275 | |
|---|
| 1984 | 2276 | if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) { |
|---|
| 1985 | 2277 | /* |
|---|
| .. | .. |
|---|
| 2008 | 2300 | return 0; |
|---|
| 2009 | 2301 | } |
|---|
| 2010 | 2302 | |
|---|
| 2011 | | -static void intel_pstate_adjust_policy_max(struct cpufreq_policy *policy, |
|---|
| 2012 | | - struct cpudata *cpu) |
|---|
| 2303 | +static void intel_pstate_adjust_policy_max(struct cpudata *cpu, |
|---|
| 2304 | + struct cpufreq_policy_data *policy) |
|---|
| 2013 | 2305 | { |
|---|
| 2014 | 2306 | if (!hwp_active && |
|---|
| 2015 | 2307 | cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate && |
|---|
| .. | .. |
|---|
| 2020 | 2312 | } |
|---|
| 2021 | 2313 | } |
|---|
| 2022 | 2314 | |
|---|
| 2023 | | -static int intel_pstate_verify_policy(struct cpufreq_policy *policy) |
|---|
| 2315 | +static void intel_pstate_verify_cpu_policy(struct cpudata *cpu, |
|---|
| 2316 | + struct cpufreq_policy_data *policy) |
|---|
| 2024 | 2317 | { |
|---|
| 2025 | | - struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 2318 | + int max_freq; |
|---|
| 2026 | 2319 | |
|---|
| 2027 | 2320 | update_turbo_state(); |
|---|
| 2028 | | - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, |
|---|
| 2029 | | - intel_pstate_get_max_freq(cpu)); |
|---|
| 2321 | + if (hwp_active) { |
|---|
| 2322 | + int max_state, turbo_max; |
|---|
| 2030 | 2323 | |
|---|
| 2031 | | - if (policy->policy != CPUFREQ_POLICY_POWERSAVE && |
|---|
| 2032 | | - policy->policy != CPUFREQ_POLICY_PERFORMANCE) |
|---|
| 2033 | | - return -EINVAL; |
|---|
| 2324 | + intel_pstate_get_hwp_max(cpu, &turbo_max, &max_state); |
|---|
| 2325 | + max_freq = max_state * cpu->pstate.scaling; |
|---|
| 2326 | + } else { |
|---|
| 2327 | + max_freq = intel_pstate_get_max_freq(cpu); |
|---|
| 2328 | + } |
|---|
| 2329 | + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, max_freq); |
|---|
| 2034 | 2330 | |
|---|
| 2035 | | - intel_pstate_adjust_policy_max(policy, cpu); |
|---|
| 2331 | + intel_pstate_adjust_policy_max(cpu, policy); |
|---|
| 2332 | +} |
|---|
| 2333 | + |
|---|
| 2334 | +static int intel_pstate_verify_policy(struct cpufreq_policy_data *policy) |
|---|
| 2335 | +{ |
|---|
| 2336 | + intel_pstate_verify_cpu_policy(all_cpu_data[policy->cpu], policy); |
|---|
| 2036 | 2337 | |
|---|
| 2037 | 2338 | return 0; |
|---|
| 2038 | 2339 | } |
|---|
| 2039 | 2340 | |
|---|
| 2040 | | -static void intel_cpufreq_stop_cpu(struct cpufreq_policy *policy) |
|---|
| 2341 | +static int intel_pstate_cpu_offline(struct cpufreq_policy *policy) |
|---|
| 2041 | 2342 | { |
|---|
| 2042 | | - intel_pstate_set_min_pstate(all_cpu_data[policy->cpu]); |
|---|
| 2343 | + struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 2344 | + |
|---|
| 2345 | + pr_debug("CPU %d going offline\n", cpu->cpu); |
|---|
| 2346 | + |
|---|
| 2347 | + if (cpu->suspended) |
|---|
| 2348 | + return 0; |
|---|
| 2349 | + |
|---|
| 2350 | + /* |
|---|
| 2351 | + * If the CPU is an SMT thread and it goes offline with the performance |
|---|
| 2352 | + * settings different from the minimum, it will prevent its sibling |
|---|
| 2353 | + * from getting to lower performance levels, so force the minimum |
|---|
| 2354 | + * performance on CPU offline to prevent that from happening. |
|---|
| 2355 | + */ |
|---|
| 2356 | + if (hwp_active) |
|---|
| 2357 | + intel_pstate_hwp_offline(cpu); |
|---|
| 2358 | + else |
|---|
| 2359 | + intel_pstate_set_min_pstate(cpu); |
|---|
| 2360 | + |
|---|
| 2361 | + intel_pstate_exit_perf_limits(policy); |
|---|
| 2362 | + |
|---|
| 2363 | + return 0; |
|---|
| 2364 | +} |
|---|
| 2365 | + |
|---|
| 2366 | +static int intel_pstate_cpu_online(struct cpufreq_policy *policy) |
|---|
| 2367 | +{ |
|---|
| 2368 | + struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 2369 | + |
|---|
| 2370 | + pr_debug("CPU %d going online\n", cpu->cpu); |
|---|
| 2371 | + |
|---|
| 2372 | + intel_pstate_init_acpi_perf_limits(policy); |
|---|
| 2373 | + |
|---|
| 2374 | + if (hwp_active) { |
|---|
| 2375 | + /* |
|---|
| 2376 | + * Re-enable HWP and clear the "suspended" flag to let "resume" |
|---|
| 2377 | + * know that it need not do that. |
|---|
| 2378 | + */ |
|---|
| 2379 | + intel_pstate_hwp_reenable(cpu); |
|---|
| 2380 | + cpu->suspended = false; |
|---|
| 2381 | + } |
|---|
| 2382 | + |
|---|
| 2383 | + return 0; |
|---|
| 2043 | 2384 | } |
|---|
| 2044 | 2385 | |
|---|
| 2045 | 2386 | static void intel_pstate_stop_cpu(struct cpufreq_policy *policy) |
|---|
| 2046 | 2387 | { |
|---|
| 2047 | | - pr_debug("CPU %d exiting\n", policy->cpu); |
|---|
| 2388 | + pr_debug("CPU %d stopping\n", policy->cpu); |
|---|
| 2048 | 2389 | |
|---|
| 2049 | 2390 | intel_pstate_clear_update_util_hook(policy->cpu); |
|---|
| 2050 | | - if (hwp_active) |
|---|
| 2051 | | - intel_pstate_hwp_save_state(policy); |
|---|
| 2052 | | - else |
|---|
| 2053 | | - intel_cpufreq_stop_cpu(policy); |
|---|
| 2054 | 2391 | } |
|---|
| 2055 | 2392 | |
|---|
| 2056 | 2393 | static int intel_pstate_cpu_exit(struct cpufreq_policy *policy) |
|---|
| 2057 | 2394 | { |
|---|
| 2058 | | - intel_pstate_exit_perf_limits(policy); |
|---|
| 2395 | + pr_debug("CPU %d exiting\n", policy->cpu); |
|---|
| 2059 | 2396 | |
|---|
| 2060 | 2397 | policy->fast_switch_possible = false; |
|---|
| 2061 | 2398 | |
|---|
| .. | .. |
|---|
| 2082 | 2419 | /* cpuinfo and default policy values */ |
|---|
| 2083 | 2420 | policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling; |
|---|
| 2084 | 2421 | update_turbo_state(); |
|---|
| 2422 | + global.turbo_disabled_mf = global.turbo_disabled; |
|---|
| 2085 | 2423 | policy->cpuinfo.max_freq = global.turbo_disabled ? |
|---|
| 2086 | 2424 | cpu->pstate.max_pstate : cpu->pstate.turbo_pstate; |
|---|
| 2087 | 2425 | policy->cpuinfo.max_freq *= cpu->pstate.scaling; |
|---|
| .. | .. |
|---|
| 2109 | 2447 | if (ret) |
|---|
| 2110 | 2448 | return ret; |
|---|
| 2111 | 2449 | |
|---|
| 2112 | | - if (IS_ENABLED(CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE)) |
|---|
| 2113 | | - policy->policy = CPUFREQ_POLICY_PERFORMANCE; |
|---|
| 2114 | | - else |
|---|
| 2115 | | - policy->policy = CPUFREQ_POLICY_POWERSAVE; |
|---|
| 2450 | + /* |
|---|
| 2451 | + * Set the policy to powersave to provide a valid fallback value in case |
|---|
| 2452 | + * the default cpufreq governor is neither powersave nor performance. |
|---|
| 2453 | + */ |
|---|
| 2454 | + policy->policy = CPUFREQ_POLICY_POWERSAVE; |
|---|
| 2455 | + |
|---|
| 2456 | + if (hwp_active) { |
|---|
| 2457 | + struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 2458 | + |
|---|
| 2459 | + cpu->epp_cached = intel_pstate_get_epp(cpu, 0); |
|---|
| 2460 | + } |
|---|
| 2116 | 2461 | |
|---|
| 2117 | 2462 | return 0; |
|---|
| 2118 | 2463 | } |
|---|
| .. | .. |
|---|
| 2121 | 2466 | .flags = CPUFREQ_CONST_LOOPS, |
|---|
| 2122 | 2467 | .verify = intel_pstate_verify_policy, |
|---|
| 2123 | 2468 | .setpolicy = intel_pstate_set_policy, |
|---|
| 2124 | | - .suspend = intel_pstate_hwp_save_state, |
|---|
| 2469 | + .suspend = intel_pstate_suspend, |
|---|
| 2125 | 2470 | .resume = intel_pstate_resume, |
|---|
| 2126 | 2471 | .init = intel_pstate_cpu_init, |
|---|
| 2127 | 2472 | .exit = intel_pstate_cpu_exit, |
|---|
| 2128 | 2473 | .stop_cpu = intel_pstate_stop_cpu, |
|---|
| 2474 | + .offline = intel_pstate_cpu_offline, |
|---|
| 2475 | + .online = intel_pstate_cpu_online, |
|---|
| 2476 | + .update_limits = intel_pstate_update_limits, |
|---|
| 2129 | 2477 | .name = "intel_pstate", |
|---|
| 2130 | 2478 | }; |
|---|
| 2131 | 2479 | |
|---|
| 2132 | | -static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy) |
|---|
| 2480 | +static int intel_cpufreq_verify_policy(struct cpufreq_policy_data *policy) |
|---|
| 2133 | 2481 | { |
|---|
| 2134 | 2482 | struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 2135 | 2483 | |
|---|
| 2136 | | - update_turbo_state(); |
|---|
| 2137 | | - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, |
|---|
| 2138 | | - intel_pstate_get_max_freq(cpu)); |
|---|
| 2139 | | - |
|---|
| 2140 | | - intel_pstate_adjust_policy_max(policy, cpu); |
|---|
| 2141 | | - |
|---|
| 2142 | | - intel_pstate_update_perf_limits(policy, cpu); |
|---|
| 2484 | + intel_pstate_verify_cpu_policy(cpu, policy); |
|---|
| 2485 | + intel_pstate_update_perf_limits(cpu, policy->min, policy->max); |
|---|
| 2143 | 2486 | |
|---|
| 2144 | 2487 | return 0; |
|---|
| 2145 | 2488 | } |
|---|
| .. | .. |
|---|
| 2182 | 2525 | fp_toint(cpu->iowait_boost * 100)); |
|---|
| 2183 | 2526 | } |
|---|
| 2184 | 2527 | |
|---|
| 2528 | +static void intel_cpufreq_adjust_hwp(struct cpudata *cpu, u32 target_pstate, |
|---|
| 2529 | + bool strict, bool fast_switch) |
|---|
| 2530 | +{ |
|---|
| 2531 | + u64 prev = READ_ONCE(cpu->hwp_req_cached), value = prev; |
|---|
| 2532 | + |
|---|
| 2533 | + value &= ~HWP_MIN_PERF(~0L); |
|---|
| 2534 | + value |= HWP_MIN_PERF(target_pstate); |
|---|
| 2535 | + |
|---|
| 2536 | + /* |
|---|
| 2537 | + * The entire MSR needs to be updated in order to update the HWP min |
|---|
| 2538 | + * field in it, so opportunistically update the max too if needed. |
|---|
| 2539 | + */ |
|---|
| 2540 | + value &= ~HWP_MAX_PERF(~0L); |
|---|
| 2541 | + value |= HWP_MAX_PERF(strict ? target_pstate : cpu->max_perf_ratio); |
|---|
| 2542 | + |
|---|
| 2543 | + if (value == prev) |
|---|
| 2544 | + return; |
|---|
| 2545 | + |
|---|
| 2546 | + WRITE_ONCE(cpu->hwp_req_cached, value); |
|---|
| 2547 | + if (fast_switch) |
|---|
| 2548 | + wrmsrl(MSR_HWP_REQUEST, value); |
|---|
| 2549 | + else |
|---|
| 2550 | + wrmsrl_on_cpu(cpu->cpu, MSR_HWP_REQUEST, value); |
|---|
| 2551 | +} |
|---|
| 2552 | + |
|---|
| 2553 | +static void intel_cpufreq_adjust_perf_ctl(struct cpudata *cpu, |
|---|
| 2554 | + u32 target_pstate, bool fast_switch) |
|---|
| 2555 | +{ |
|---|
| 2556 | + if (fast_switch) |
|---|
| 2557 | + wrmsrl(MSR_IA32_PERF_CTL, |
|---|
| 2558 | + pstate_funcs.get_val(cpu, target_pstate)); |
|---|
| 2559 | + else |
|---|
| 2560 | + wrmsrl_on_cpu(cpu->cpu, MSR_IA32_PERF_CTL, |
|---|
| 2561 | + pstate_funcs.get_val(cpu, target_pstate)); |
|---|
| 2562 | +} |
|---|
| 2563 | + |
|---|
| 2564 | +static int intel_cpufreq_update_pstate(struct cpufreq_policy *policy, |
|---|
| 2565 | + int target_pstate, bool fast_switch) |
|---|
| 2566 | +{ |
|---|
| 2567 | + struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 2568 | + int old_pstate = cpu->pstate.current_pstate; |
|---|
| 2569 | + |
|---|
| 2570 | + target_pstate = intel_pstate_prepare_request(cpu, target_pstate); |
|---|
| 2571 | + if (hwp_active) { |
|---|
| 2572 | + intel_cpufreq_adjust_hwp(cpu, target_pstate, |
|---|
| 2573 | + policy->strict_target, fast_switch); |
|---|
| 2574 | + cpu->pstate.current_pstate = target_pstate; |
|---|
| 2575 | + } else if (target_pstate != old_pstate) { |
|---|
| 2576 | + intel_cpufreq_adjust_perf_ctl(cpu, target_pstate, fast_switch); |
|---|
| 2577 | + cpu->pstate.current_pstate = target_pstate; |
|---|
| 2578 | + } |
|---|
| 2579 | + |
|---|
| 2580 | + intel_cpufreq_trace(cpu, fast_switch ? INTEL_PSTATE_TRACE_FAST_SWITCH : |
|---|
| 2581 | + INTEL_PSTATE_TRACE_TARGET, old_pstate); |
|---|
| 2582 | + |
|---|
| 2583 | + return target_pstate; |
|---|
| 2584 | +} |
|---|
| 2585 | + |
|---|
| 2185 | 2586 | static int intel_cpufreq_target(struct cpufreq_policy *policy, |
|---|
| 2186 | 2587 | unsigned int target_freq, |
|---|
| 2187 | 2588 | unsigned int relation) |
|---|
| 2188 | 2589 | { |
|---|
| 2189 | 2590 | struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 2190 | 2591 | struct cpufreq_freqs freqs; |
|---|
| 2191 | | - int target_pstate, old_pstate; |
|---|
| 2592 | + int target_pstate; |
|---|
| 2192 | 2593 | |
|---|
| 2193 | 2594 | update_turbo_state(); |
|---|
| 2194 | 2595 | |
|---|
| .. | .. |
|---|
| 2196 | 2597 | freqs.new = target_freq; |
|---|
| 2197 | 2598 | |
|---|
| 2198 | 2599 | cpufreq_freq_transition_begin(policy, &freqs); |
|---|
| 2600 | + |
|---|
| 2199 | 2601 | switch (relation) { |
|---|
| 2200 | 2602 | case CPUFREQ_RELATION_L: |
|---|
| 2201 | 2603 | target_pstate = DIV_ROUND_UP(freqs.new, cpu->pstate.scaling); |
|---|
| .. | .. |
|---|
| 2207 | 2609 | target_pstate = DIV_ROUND_CLOSEST(freqs.new, cpu->pstate.scaling); |
|---|
| 2208 | 2610 | break; |
|---|
| 2209 | 2611 | } |
|---|
| 2210 | | - target_pstate = intel_pstate_prepare_request(cpu, target_pstate); |
|---|
| 2211 | | - old_pstate = cpu->pstate.current_pstate; |
|---|
| 2212 | | - if (target_pstate != cpu->pstate.current_pstate) { |
|---|
| 2213 | | - cpu->pstate.current_pstate = target_pstate; |
|---|
| 2214 | | - wrmsrl_on_cpu(policy->cpu, MSR_IA32_PERF_CTL, |
|---|
| 2215 | | - pstate_funcs.get_val(cpu, target_pstate)); |
|---|
| 2216 | | - } |
|---|
| 2612 | + |
|---|
| 2613 | + target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, false); |
|---|
| 2614 | + |
|---|
| 2217 | 2615 | freqs.new = target_pstate * cpu->pstate.scaling; |
|---|
| 2218 | | - intel_cpufreq_trace(cpu, INTEL_PSTATE_TRACE_TARGET, old_pstate); |
|---|
| 2616 | + |
|---|
| 2219 | 2617 | cpufreq_freq_transition_end(policy, &freqs, false); |
|---|
| 2220 | 2618 | |
|---|
| 2221 | 2619 | return 0; |
|---|
| .. | .. |
|---|
| 2225 | 2623 | unsigned int target_freq) |
|---|
| 2226 | 2624 | { |
|---|
| 2227 | 2625 | struct cpudata *cpu = all_cpu_data[policy->cpu]; |
|---|
| 2228 | | - int target_pstate, old_pstate; |
|---|
| 2626 | + int target_pstate; |
|---|
| 2229 | 2627 | |
|---|
| 2230 | 2628 | update_turbo_state(); |
|---|
| 2231 | 2629 | |
|---|
| 2232 | 2630 | target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling); |
|---|
| 2233 | | - target_pstate = intel_pstate_prepare_request(cpu, target_pstate); |
|---|
| 2234 | | - old_pstate = cpu->pstate.current_pstate; |
|---|
| 2235 | | - intel_pstate_update_pstate(cpu, target_pstate); |
|---|
| 2236 | | - intel_cpufreq_trace(cpu, INTEL_PSTATE_TRACE_FAST_SWITCH, old_pstate); |
|---|
| 2631 | + |
|---|
| 2632 | + target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, true); |
|---|
| 2633 | + |
|---|
| 2237 | 2634 | return target_pstate * cpu->pstate.scaling; |
|---|
| 2238 | 2635 | } |
|---|
| 2239 | 2636 | |
|---|
| 2240 | 2637 | static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy) |
|---|
| 2241 | 2638 | { |
|---|
| 2242 | | - int ret = __intel_pstate_cpu_init(policy); |
|---|
| 2639 | + int max_state, turbo_max, min_freq, max_freq, ret; |
|---|
| 2640 | + struct freq_qos_request *req; |
|---|
| 2641 | + struct cpudata *cpu; |
|---|
| 2642 | + struct device *dev; |
|---|
| 2243 | 2643 | |
|---|
| 2644 | + dev = get_cpu_device(policy->cpu); |
|---|
| 2645 | + if (!dev) |
|---|
| 2646 | + return -ENODEV; |
|---|
| 2647 | + |
|---|
| 2648 | + ret = __intel_pstate_cpu_init(policy); |
|---|
| 2244 | 2649 | if (ret) |
|---|
| 2245 | 2650 | return ret; |
|---|
| 2246 | 2651 | |
|---|
| 2247 | 2652 | policy->cpuinfo.transition_latency = INTEL_CPUFREQ_TRANSITION_LATENCY; |
|---|
| 2248 | | - policy->transition_delay_us = INTEL_CPUFREQ_TRANSITION_DELAY; |
|---|
| 2249 | 2653 | /* This reflects the intel_pstate_get_cpu_pstates() setting. */ |
|---|
| 2250 | 2654 | policy->cur = policy->cpuinfo.min_freq; |
|---|
| 2251 | 2655 | |
|---|
| 2656 | + req = kcalloc(2, sizeof(*req), GFP_KERNEL); |
|---|
| 2657 | + if (!req) { |
|---|
| 2658 | + ret = -ENOMEM; |
|---|
| 2659 | + goto pstate_exit; |
|---|
| 2660 | + } |
|---|
| 2661 | + |
|---|
| 2662 | + cpu = all_cpu_data[policy->cpu]; |
|---|
| 2663 | + |
|---|
| 2664 | + if (hwp_active) { |
|---|
| 2665 | + u64 value; |
|---|
| 2666 | + |
|---|
| 2667 | + intel_pstate_get_hwp_max(cpu, &turbo_max, &max_state); |
|---|
| 2668 | + policy->transition_delay_us = INTEL_CPUFREQ_TRANSITION_DELAY_HWP; |
|---|
| 2669 | + rdmsrl_on_cpu(cpu->cpu, MSR_HWP_REQUEST, &value); |
|---|
| 2670 | + WRITE_ONCE(cpu->hwp_req_cached, value); |
|---|
| 2671 | + cpu->epp_cached = intel_pstate_get_epp(cpu, value); |
|---|
| 2672 | + } else { |
|---|
| 2673 | + turbo_max = cpu->pstate.turbo_pstate; |
|---|
| 2674 | + policy->transition_delay_us = INTEL_CPUFREQ_TRANSITION_DELAY; |
|---|
| 2675 | + } |
|---|
| 2676 | + |
|---|
| 2677 | + min_freq = DIV_ROUND_UP(turbo_max * global.min_perf_pct, 100); |
|---|
| 2678 | + min_freq *= cpu->pstate.scaling; |
|---|
| 2679 | + max_freq = DIV_ROUND_UP(turbo_max * global.max_perf_pct, 100); |
|---|
| 2680 | + max_freq *= cpu->pstate.scaling; |
|---|
| 2681 | + |
|---|
| 2682 | + ret = freq_qos_add_request(&policy->constraints, req, FREQ_QOS_MIN, |
|---|
| 2683 | + min_freq); |
|---|
| 2684 | + if (ret < 0) { |
|---|
| 2685 | + dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret); |
|---|
| 2686 | + goto free_req; |
|---|
| 2687 | + } |
|---|
| 2688 | + |
|---|
| 2689 | + ret = freq_qos_add_request(&policy->constraints, req + 1, FREQ_QOS_MAX, |
|---|
| 2690 | + max_freq); |
|---|
| 2691 | + if (ret < 0) { |
|---|
| 2692 | + dev_err(dev, "Failed to add max-freq constraint (%d)\n", ret); |
|---|
| 2693 | + goto remove_min_req; |
|---|
| 2694 | + } |
|---|
| 2695 | + |
|---|
| 2696 | + policy->driver_data = req; |
|---|
| 2697 | + |
|---|
| 2252 | 2698 | return 0; |
|---|
| 2699 | + |
|---|
| 2700 | +remove_min_req: |
|---|
| 2701 | + freq_qos_remove_request(req); |
|---|
| 2702 | +free_req: |
|---|
| 2703 | + kfree(req); |
|---|
| 2704 | +pstate_exit: |
|---|
| 2705 | + intel_pstate_exit_perf_limits(policy); |
|---|
| 2706 | + |
|---|
| 2707 | + return ret; |
|---|
| 2708 | +} |
|---|
| 2709 | + |
|---|
| 2710 | +static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy) |
|---|
| 2711 | +{ |
|---|
| 2712 | + struct freq_qos_request *req; |
|---|
| 2713 | + |
|---|
| 2714 | + req = policy->driver_data; |
|---|
| 2715 | + |
|---|
| 2716 | + freq_qos_remove_request(req + 1); |
|---|
| 2717 | + freq_qos_remove_request(req); |
|---|
| 2718 | + kfree(req); |
|---|
| 2719 | + |
|---|
| 2720 | + return intel_pstate_cpu_exit(policy); |
|---|
| 2253 | 2721 | } |
|---|
| 2254 | 2722 | |
|---|
| 2255 | 2723 | static struct cpufreq_driver intel_cpufreq = { |
|---|
| .. | .. |
|---|
| 2258 | 2726 | .target = intel_cpufreq_target, |
|---|
| 2259 | 2727 | .fast_switch = intel_cpufreq_fast_switch, |
|---|
| 2260 | 2728 | .init = intel_cpufreq_cpu_init, |
|---|
| 2261 | | - .exit = intel_pstate_cpu_exit, |
|---|
| 2262 | | - .stop_cpu = intel_cpufreq_stop_cpu, |
|---|
| 2729 | + .exit = intel_cpufreq_cpu_exit, |
|---|
| 2730 | + .offline = intel_pstate_cpu_offline, |
|---|
| 2731 | + .online = intel_pstate_cpu_online, |
|---|
| 2732 | + .suspend = intel_pstate_suspend, |
|---|
| 2733 | + .resume = intel_pstate_resume, |
|---|
| 2734 | + .update_limits = intel_pstate_update_limits, |
|---|
| 2263 | 2735 | .name = "intel_cpufreq", |
|---|
| 2264 | 2736 | }; |
|---|
| 2265 | 2737 | |
|---|
| 2266 | | -static struct cpufreq_driver *default_driver = &intel_pstate; |
|---|
| 2738 | +static struct cpufreq_driver *default_driver; |
|---|
| 2267 | 2739 | |
|---|
| 2268 | 2740 | static void intel_pstate_driver_cleanup(void) |
|---|
| 2269 | 2741 | { |
|---|
| .. | .. |
|---|
| 2280 | 2752 | } |
|---|
| 2281 | 2753 | } |
|---|
| 2282 | 2754 | put_online_cpus(); |
|---|
| 2755 | + |
|---|
| 2283 | 2756 | intel_pstate_driver = NULL; |
|---|
| 2284 | 2757 | } |
|---|
| 2285 | 2758 | |
|---|
| 2286 | 2759 | static int intel_pstate_register_driver(struct cpufreq_driver *driver) |
|---|
| 2287 | 2760 | { |
|---|
| 2288 | 2761 | int ret; |
|---|
| 2762 | + |
|---|
| 2763 | + if (driver == &intel_pstate) |
|---|
| 2764 | + intel_pstate_sysfs_expose_hwp_dynamic_boost(); |
|---|
| 2289 | 2765 | |
|---|
| 2290 | 2766 | memset(&global, 0, sizeof(global)); |
|---|
| 2291 | 2767 | global.max_perf_pct = 100; |
|---|
| .. | .. |
|---|
| 2302 | 2778 | return 0; |
|---|
| 2303 | 2779 | } |
|---|
| 2304 | 2780 | |
|---|
| 2305 | | -static int intel_pstate_unregister_driver(void) |
|---|
| 2306 | | -{ |
|---|
| 2307 | | - if (hwp_active) |
|---|
| 2308 | | - return -EBUSY; |
|---|
| 2309 | | - |
|---|
| 2310 | | - cpufreq_unregister_driver(intel_pstate_driver); |
|---|
| 2311 | | - intel_pstate_driver_cleanup(); |
|---|
| 2312 | | - |
|---|
| 2313 | | - return 0; |
|---|
| 2314 | | -} |
|---|
| 2315 | | - |
|---|
| 2316 | 2781 | static ssize_t intel_pstate_show_status(char *buf) |
|---|
| 2317 | 2782 | { |
|---|
| 2318 | 2783 | if (!intel_pstate_driver) |
|---|
| .. | .. |
|---|
| 2324 | 2789 | |
|---|
| 2325 | 2790 | static int intel_pstate_update_status(const char *buf, size_t size) |
|---|
| 2326 | 2791 | { |
|---|
| 2327 | | - int ret; |
|---|
| 2328 | | - |
|---|
| 2329 | 2792 | if (size == 3 && !strncmp(buf, "off", size)) { |
|---|
| 2330 | 2793 | if (!intel_pstate_driver) |
|---|
| 2331 | 2794 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 2333 | 2796 | if (hwp_active) |
|---|
| 2334 | 2797 | return -EBUSY; |
|---|
| 2335 | 2798 | |
|---|
| 2336 | | - return intel_pstate_unregister_driver(); |
|---|
| 2799 | + cpufreq_unregister_driver(intel_pstate_driver); |
|---|
| 2800 | + intel_pstate_driver_cleanup(); |
|---|
| 2801 | + return 0; |
|---|
| 2337 | 2802 | } |
|---|
| 2338 | 2803 | |
|---|
| 2339 | 2804 | if (size == 6 && !strncmp(buf, "active", size)) { |
|---|
| .. | .. |
|---|
| 2341 | 2806 | if (intel_pstate_driver == &intel_pstate) |
|---|
| 2342 | 2807 | return 0; |
|---|
| 2343 | 2808 | |
|---|
| 2344 | | - ret = intel_pstate_unregister_driver(); |
|---|
| 2345 | | - if (ret) |
|---|
| 2346 | | - return ret; |
|---|
| 2809 | + cpufreq_unregister_driver(intel_pstate_driver); |
|---|
| 2347 | 2810 | } |
|---|
| 2348 | 2811 | |
|---|
| 2349 | 2812 | return intel_pstate_register_driver(&intel_pstate); |
|---|
| .. | .. |
|---|
| 2354 | 2817 | if (intel_pstate_driver == &intel_cpufreq) |
|---|
| 2355 | 2818 | return 0; |
|---|
| 2356 | 2819 | |
|---|
| 2357 | | - ret = intel_pstate_unregister_driver(); |
|---|
| 2358 | | - if (ret) |
|---|
| 2359 | | - return ret; |
|---|
| 2820 | + cpufreq_unregister_driver(intel_pstate_driver); |
|---|
| 2821 | + intel_pstate_sysfs_hide_hwp_dynamic_boost(); |
|---|
| 2360 | 2822 | } |
|---|
| 2361 | 2823 | |
|---|
| 2362 | 2824 | return intel_pstate_register_driver(&intel_cpufreq); |
|---|
| .. | .. |
|---|
| 2420 | 2882 | kfree(pss); |
|---|
| 2421 | 2883 | } |
|---|
| 2422 | 2884 | |
|---|
| 2885 | + pr_debug("ACPI _PSS not found\n"); |
|---|
| 2423 | 2886 | return true; |
|---|
| 2424 | 2887 | } |
|---|
| 2425 | 2888 | |
|---|
| .. | .. |
|---|
| 2430 | 2893 | |
|---|
| 2431 | 2894 | status = acpi_get_handle(NULL, "\\_SB", &handle); |
|---|
| 2432 | 2895 | if (ACPI_FAILURE(status)) |
|---|
| 2433 | | - return true; |
|---|
| 2896 | + goto not_found; |
|---|
| 2434 | 2897 | |
|---|
| 2435 | | - return !acpi_has_method(handle, "PCCH"); |
|---|
| 2898 | + if (acpi_has_method(handle, "PCCH")) |
|---|
| 2899 | + return false; |
|---|
| 2900 | + |
|---|
| 2901 | +not_found: |
|---|
| 2902 | + pr_debug("ACPI PCCH not found\n"); |
|---|
| 2903 | + return true; |
|---|
| 2436 | 2904 | } |
|---|
| 2437 | 2905 | |
|---|
| 2438 | 2906 | static bool __init intel_pstate_has_acpi_ppc(void) |
|---|
| .. | .. |
|---|
| 2447 | 2915 | if (acpi_has_method(pr->handle, "_PPC")) |
|---|
| 2448 | 2916 | return true; |
|---|
| 2449 | 2917 | } |
|---|
| 2918 | + pr_debug("ACPI _PPC not found\n"); |
|---|
| 2450 | 2919 | return false; |
|---|
| 2451 | 2920 | } |
|---|
| 2452 | 2921 | |
|---|
| .. | .. |
|---|
| 2457 | 2926 | |
|---|
| 2458 | 2927 | /* Hardware vendor-specific info that has its own power management modes */ |
|---|
| 2459 | 2928 | static struct acpi_platform_list plat_info[] __initdata = { |
|---|
| 2460 | | - {"HP ", "ProLiant", 0, ACPI_SIG_FADT, all_versions, 0, PSS}, |
|---|
| 2461 | | - {"ORACLE", "X4-2 ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2462 | | - {"ORACLE", "X4-2L ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2463 | | - {"ORACLE", "X4-2B ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2464 | | - {"ORACLE", "X3-2 ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2465 | | - {"ORACLE", "X3-2L ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2466 | | - {"ORACLE", "X3-2B ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2467 | | - {"ORACLE", "X4470M2 ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2468 | | - {"ORACLE", "X4270M3 ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2469 | | - {"ORACLE", "X4270M2 ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2470 | | - {"ORACLE", "X4170M2 ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2471 | | - {"ORACLE", "X4170 M3", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2472 | | - {"ORACLE", "X4275 M3", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2473 | | - {"ORACLE", "X6-2 ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2474 | | - {"ORACLE", "Sudbury ", 0, ACPI_SIG_FADT, all_versions, 0, PPC}, |
|---|
| 2929 | + {"HP ", "ProLiant", 0, ACPI_SIG_FADT, all_versions, NULL, PSS}, |
|---|
| 2930 | + {"ORACLE", "X4-2 ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2931 | + {"ORACLE", "X4-2L ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2932 | + {"ORACLE", "X4-2B ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2933 | + {"ORACLE", "X3-2 ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2934 | + {"ORACLE", "X3-2L ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2935 | + {"ORACLE", "X3-2B ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2936 | + {"ORACLE", "X4470M2 ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2937 | + {"ORACLE", "X4270M3 ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2938 | + {"ORACLE", "X4270M2 ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2939 | + {"ORACLE", "X4170M2 ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2940 | + {"ORACLE", "X4170 M3", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2941 | + {"ORACLE", "X4275 M3", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2942 | + {"ORACLE", "X6-2 ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2943 | + {"ORACLE", "Sudbury ", 0, ACPI_SIG_FADT, all_versions, NULL, PPC}, |
|---|
| 2475 | 2944 | { } /* End */ |
|---|
| 2476 | 2945 | }; |
|---|
| 2946 | + |
|---|
| 2947 | +#define BITMASK_OOB (BIT(8) | BIT(18)) |
|---|
| 2477 | 2948 | |
|---|
| 2478 | 2949 | static bool __init intel_pstate_platform_pwr_mgmt_exists(void) |
|---|
| 2479 | 2950 | { |
|---|
| .. | .. |
|---|
| 2484 | 2955 | id = x86_match_cpu(intel_pstate_cpu_oob_ids); |
|---|
| 2485 | 2956 | if (id) { |
|---|
| 2486 | 2957 | rdmsrl(MSR_MISC_PWR_MGMT, misc_pwr); |
|---|
| 2487 | | - if ( misc_pwr & (1 << 8)) |
|---|
| 2958 | + if (misc_pwr & BITMASK_OOB) { |
|---|
| 2959 | + pr_debug("Bit 8 or 18 in the MISC_PWR_MGMT MSR set\n"); |
|---|
| 2960 | + pr_debug("P states are controlled in Out of Band mode by the firmware/hardware\n"); |
|---|
| 2488 | 2961 | return true; |
|---|
| 2962 | + } |
|---|
| 2489 | 2963 | } |
|---|
| 2490 | 2964 | |
|---|
| 2491 | 2965 | idx = acpi_match_platform_list(plat_info); |
|---|
| .. | .. |
|---|
| 2522 | 2996 | |
|---|
| 2523 | 2997 | #define INTEL_PSTATE_HWP_BROADWELL 0x01 |
|---|
| 2524 | 2998 | |
|---|
| 2525 | | -#define ICPU_HWP(model, hwp_mode) \ |
|---|
| 2526 | | - { X86_VENDOR_INTEL, 6, model, X86_FEATURE_HWP, hwp_mode } |
|---|
| 2999 | +#define X86_MATCH_HWP(model, hwp_mode) \ |
|---|
| 3000 | + X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, INTEL_FAM6_##model, \ |
|---|
| 3001 | + X86_FEATURE_HWP, hwp_mode) |
|---|
| 2527 | 3002 | |
|---|
| 2528 | 3003 | static const struct x86_cpu_id hwp_support_ids[] __initconst = { |
|---|
| 2529 | | - ICPU_HWP(INTEL_FAM6_BROADWELL_X, INTEL_PSTATE_HWP_BROADWELL), |
|---|
| 2530 | | - ICPU_HWP(INTEL_FAM6_BROADWELL_XEON_D, INTEL_PSTATE_HWP_BROADWELL), |
|---|
| 2531 | | - ICPU_HWP(X86_MODEL_ANY, 0), |
|---|
| 3004 | + X86_MATCH_HWP(BROADWELL_X, INTEL_PSTATE_HWP_BROADWELL), |
|---|
| 3005 | + X86_MATCH_HWP(BROADWELL_D, INTEL_PSTATE_HWP_BROADWELL), |
|---|
| 3006 | + X86_MATCH_HWP(ANY, 0), |
|---|
| 2532 | 3007 | {} |
|---|
| 2533 | 3008 | }; |
|---|
| 3009 | + |
|---|
| 3010 | +static bool intel_pstate_hwp_is_enabled(void) |
|---|
| 3011 | +{ |
|---|
| 3012 | + u64 value; |
|---|
| 3013 | + |
|---|
| 3014 | + rdmsrl(MSR_PM_ENABLE, value); |
|---|
| 3015 | + return !!(value & 0x1); |
|---|
| 3016 | +} |
|---|
| 2534 | 3017 | |
|---|
| 2535 | 3018 | static int __init intel_pstate_init(void) |
|---|
| 2536 | 3019 | { |
|---|
| 2537 | 3020 | const struct x86_cpu_id *id; |
|---|
| 2538 | 3021 | int rc; |
|---|
| 2539 | 3022 | |
|---|
| 2540 | | - if (no_load) |
|---|
| 3023 | + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) |
|---|
| 2541 | 3024 | return -ENODEV; |
|---|
| 2542 | 3025 | |
|---|
| 2543 | 3026 | id = x86_match_cpu(hwp_support_ids); |
|---|
| 2544 | 3027 | if (id) { |
|---|
| 3028 | + bool hwp_forced = intel_pstate_hwp_is_enabled(); |
|---|
| 3029 | + |
|---|
| 3030 | + if (hwp_forced) |
|---|
| 3031 | + pr_info("HWP enabled by BIOS\n"); |
|---|
| 3032 | + else if (no_load) |
|---|
| 3033 | + return -ENODEV; |
|---|
| 3034 | + |
|---|
| 2545 | 3035 | copy_cpu_funcs(&core_funcs); |
|---|
| 2546 | | - if (!no_hwp) { |
|---|
| 3036 | + /* |
|---|
| 3037 | + * Avoid enabling HWP for processors without EPP support, |
|---|
| 3038 | + * because that means incomplete HWP implementation which is a |
|---|
| 3039 | + * corner case and supporting it is generally problematic. |
|---|
| 3040 | + * |
|---|
| 3041 | + * If HWP is enabled already, though, there is no choice but to |
|---|
| 3042 | + * deal with it. |
|---|
| 3043 | + */ |
|---|
| 3044 | + if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) || hwp_forced) { |
|---|
| 2547 | 3045 | hwp_active++; |
|---|
| 2548 | 3046 | hwp_mode_bdw = id->driver_data; |
|---|
| 2549 | 3047 | intel_pstate.attr = hwp_cpufreq_attrs; |
|---|
| 3048 | + intel_cpufreq.attr = hwp_cpufreq_attrs; |
|---|
| 3049 | + intel_cpufreq.flags |= CPUFREQ_NEED_UPDATE_LIMITS; |
|---|
| 3050 | + if (!default_driver) |
|---|
| 3051 | + default_driver = &intel_pstate; |
|---|
| 3052 | + |
|---|
| 2550 | 3053 | goto hwp_cpu_matched; |
|---|
| 2551 | 3054 | } |
|---|
| 3055 | + pr_info("HWP not enabled\n"); |
|---|
| 2552 | 3056 | } else { |
|---|
| 2553 | | - id = x86_match_cpu(intel_pstate_cpu_ids); |
|---|
| 2554 | | - if (!id) |
|---|
| 3057 | + if (no_load) |
|---|
| 2555 | 3058 | return -ENODEV; |
|---|
| 3059 | + |
|---|
| 3060 | + id = x86_match_cpu(intel_pstate_cpu_ids); |
|---|
| 3061 | + if (!id) { |
|---|
| 3062 | + pr_info("CPU model not supported\n"); |
|---|
| 3063 | + return -ENODEV; |
|---|
| 3064 | + } |
|---|
| 2556 | 3065 | |
|---|
| 2557 | 3066 | copy_cpu_funcs((struct pstate_funcs *)id->driver_data); |
|---|
| 2558 | 3067 | } |
|---|
| 2559 | 3068 | |
|---|
| 2560 | | - if (intel_pstate_msrs_not_valid()) |
|---|
| 3069 | + if (intel_pstate_msrs_not_valid()) { |
|---|
| 3070 | + pr_info("Invalid MSRs\n"); |
|---|
| 2561 | 3071 | return -ENODEV; |
|---|
| 3072 | + } |
|---|
| 3073 | + /* Without HWP start in the passive mode. */ |
|---|
| 3074 | + if (!default_driver) |
|---|
| 3075 | + default_driver = &intel_cpufreq; |
|---|
| 2562 | 3076 | |
|---|
| 2563 | 3077 | hwp_cpu_matched: |
|---|
| 2564 | 3078 | /* |
|---|
| 2565 | 3079 | * The Intel pstate driver will be ignored if the platform |
|---|
| 2566 | 3080 | * firmware has its own power management modes. |
|---|
| 2567 | 3081 | */ |
|---|
| 2568 | | - if (intel_pstate_platform_pwr_mgmt_exists()) |
|---|
| 3082 | + if (intel_pstate_platform_pwr_mgmt_exists()) { |
|---|
| 3083 | + pr_info("P-states controlled by the platform\n"); |
|---|
| 2569 | 3084 | return -ENODEV; |
|---|
| 3085 | + } |
|---|
| 2570 | 3086 | |
|---|
| 2571 | 3087 | if (!hwp_active && hwp_only) |
|---|
| 2572 | 3088 | return -ENOTSUPP; |
|---|
| .. | .. |
|---|
| 2584 | 3100 | mutex_lock(&intel_pstate_driver_lock); |
|---|
| 2585 | 3101 | rc = intel_pstate_register_driver(default_driver); |
|---|
| 2586 | 3102 | mutex_unlock(&intel_pstate_driver_lock); |
|---|
| 2587 | | - if (rc) |
|---|
| 3103 | + if (rc) { |
|---|
| 3104 | + intel_pstate_sysfs_remove(); |
|---|
| 2588 | 3105 | return rc; |
|---|
| 3106 | + } |
|---|
| 2589 | 3107 | |
|---|
| 2590 | | - if (hwp_active) |
|---|
| 3108 | + if (hwp_active) { |
|---|
| 3109 | + const struct x86_cpu_id *id; |
|---|
| 3110 | + |
|---|
| 3111 | + id = x86_match_cpu(intel_pstate_cpu_ee_disable_ids); |
|---|
| 3112 | + if (id) { |
|---|
| 3113 | + set_power_ctl_ee_state(false); |
|---|
| 3114 | + pr_info("Disabling energy efficiency optimization\n"); |
|---|
| 3115 | + } |
|---|
| 3116 | + |
|---|
| 2591 | 3117 | pr_info("HWP enabled\n"); |
|---|
| 3118 | + } |
|---|
| 2592 | 3119 | |
|---|
| 2593 | 3120 | return 0; |
|---|
| 2594 | 3121 | } |
|---|
| .. | .. |
|---|
| 2599 | 3126 | if (!str) |
|---|
| 2600 | 3127 | return -EINVAL; |
|---|
| 2601 | 3128 | |
|---|
| 2602 | | - if (!strcmp(str, "disable")) { |
|---|
| 3129 | + if (!strcmp(str, "disable")) |
|---|
| 2603 | 3130 | no_load = 1; |
|---|
| 2604 | | - } else if (!strcmp(str, "passive")) { |
|---|
| 2605 | | - pr_info("Passive mode enabled\n"); |
|---|
| 3131 | + else if (!strcmp(str, "active")) |
|---|
| 3132 | + default_driver = &intel_pstate; |
|---|
| 3133 | + else if (!strcmp(str, "passive")) |
|---|
| 2606 | 3134 | default_driver = &intel_cpufreq; |
|---|
| 3135 | + |
|---|
| 3136 | + if (!strcmp(str, "no_hwp")) |
|---|
| 2607 | 3137 | no_hwp = 1; |
|---|
| 2608 | | - } |
|---|
| 2609 | | - if (!strcmp(str, "no_hwp")) { |
|---|
| 2610 | | - pr_info("HWP disabled\n"); |
|---|
| 2611 | | - no_hwp = 1; |
|---|
| 2612 | | - } |
|---|
| 3138 | + |
|---|
| 2613 | 3139 | if (!strcmp(str, "force")) |
|---|
| 2614 | 3140 | force_load = 1; |
|---|
| 2615 | 3141 | if (!strcmp(str, "hwp_only")) |
|---|