diff options
| -rw-r--r-- | drivers/cpufreq/intel_pstate.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 81e0062a6d2a..3b5c5359a44b 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
| 26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
| 27 | #include <linux/debugfs.h> | 27 | #include <linux/debugfs.h> |
| 28 | #include <linux/acpi.h> | ||
| 28 | #include <trace/events/power.h> | 29 | #include <trace/events/power.h> |
| 29 | 30 | ||
| 30 | #include <asm/div64.h> | 31 | #include <asm/div64.h> |
| @@ -779,6 +780,72 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) | |||
| 779 | pstate_funcs.set = funcs->set; | 780 | pstate_funcs.set = funcs->set; |
| 780 | } | 781 | } |
| 781 | 782 | ||
| 783 | #if IS_ENABLED(CONFIG_ACPI) | ||
| 784 | #include <acpi/processor.h> | ||
| 785 | |||
| 786 | static bool intel_pstate_no_acpi_pss(void) | ||
| 787 | { | ||
| 788 | int i; | ||
| 789 | |||
| 790 | for_each_possible_cpu(i) { | ||
| 791 | acpi_status status; | ||
| 792 | union acpi_object *pss; | ||
| 793 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 794 | struct acpi_processor *pr = per_cpu(processors, i); | ||
| 795 | |||
| 796 | if (!pr) | ||
| 797 | continue; | ||
| 798 | |||
| 799 | status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); | ||
| 800 | if (ACPI_FAILURE(status)) | ||
| 801 | continue; | ||
| 802 | |||
| 803 | pss = buffer.pointer; | ||
| 804 | if (pss && pss->type == ACPI_TYPE_PACKAGE) { | ||
| 805 | kfree(pss); | ||
| 806 | return false; | ||
| 807 | } | ||
| 808 | |||
| 809 | kfree(pss); | ||
| 810 | } | ||
| 811 | |||
| 812 | return true; | ||
| 813 | } | ||
| 814 | |||
| 815 | struct hw_vendor_info { | ||
| 816 | u16 valid; | ||
| 817 | char oem_id[ACPI_OEM_ID_SIZE]; | ||
| 818 | char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; | ||
| 819 | }; | ||
| 820 | |||
| 821 | /* Hardware vendor-specific info that has its own power management modes */ | ||
| 822 | static struct hw_vendor_info vendor_info[] = { | ||
| 823 | {1, "HP ", "ProLiant"}, | ||
| 824 | {0, "", ""}, | ||
| 825 | }; | ||
| 826 | |||
| 827 | static bool intel_pstate_platform_pwr_mgmt_exists(void) | ||
| 828 | { | ||
| 829 | struct acpi_table_header hdr; | ||
| 830 | struct hw_vendor_info *v_info; | ||
| 831 | |||
| 832 | if (acpi_disabled | ||
| 833 | || ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr))) | ||
| 834 | return false; | ||
| 835 | |||
| 836 | for (v_info = vendor_info; v_info->valid; v_info++) { | ||
| 837 | if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE) | ||
| 838 | && !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) | ||
| 839 | && intel_pstate_no_acpi_pss()) | ||
| 840 | return true; | ||
| 841 | } | ||
| 842 | |||
| 843 | return false; | ||
| 844 | } | ||
| 845 | #else /* CONFIG_ACPI not enabled */ | ||
| 846 | static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; } | ||
| 847 | #endif /* CONFIG_ACPI */ | ||
| 848 | |||
| 782 | static int __init intel_pstate_init(void) | 849 | static int __init intel_pstate_init(void) |
| 783 | { | 850 | { |
| 784 | int cpu, rc = 0; | 851 | int cpu, rc = 0; |
| @@ -792,6 +859,13 @@ static int __init intel_pstate_init(void) | |||
| 792 | if (!id) | 859 | if (!id) |
| 793 | return -ENODEV; | 860 | return -ENODEV; |
| 794 | 861 | ||
| 862 | /* | ||
| 863 | * The Intel pstate driver will be ignored if the platform | ||
| 864 | * firmware has its own power management modes. | ||
| 865 | */ | ||
| 866 | if (intel_pstate_platform_pwr_mgmt_exists()) | ||
| 867 | return -ENODEV; | ||
| 868 | |||
| 795 | cpu_info = (struct cpu_defaults *)id->driver_data; | 869 | cpu_info = (struct cpu_defaults *)id->driver_data; |
| 796 | 870 | ||
| 797 | copy_pid_params(&cpu_info->pid_policy); | 871 | copy_pid_params(&cpu_info->pid_policy); |
