aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Huang <adrianhuang0701@gmail.com>2013-10-31 11:24:05 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-06 20:05:48 -0500
commitfbbcdc0744dace5fcc8147d11c5fb0791126848a (patch)
treee2506ea9e867fb609300b06cbfa746b6ed0fd59b
parent880eef041655b35f9aa488726ea3c4303a4f2204 (diff)
intel_pstate: skip the driver if ACPI has power mgmt option
Do not load the Intel pstate driver if the platform firmware (ACPI BIOS) supports the power management alternatives. The ACPI BIOS indicates that the OS control mode can be used if the _PSS (Performance Supported States) is defined in ACPI table. For the OS control mode, the Intel pstate driver will be loaded. HP BIOS has several power management modes (firmware, OS-control and so on). For the OS control mode in HP BIOS, the Intel p-state driver will be loaded. When the customer chooses the firmware power management in HP BIOS, the Intel p-state driver will be ignored. I put hw_vendor_info vendor_info in case other vendors (Dell, Lenovo...) have their firmware power management. Vendors should make sure their firmware power management works properly, and they can go for adding their vendor info to the variable. I have verified the patch on HP ProLiant servers. The patch worked correctly. Signed-off-by: Adrian Huang <adrianhuang0701@gmail.com> [rjw: Fixed up !CONFIG_ACPI build] [Linda Knippers: As Adrian has recently left HP, I retested the updated patch on an HP ProLiant server and verified that it is behaving correctly. When the BIOS is configured for OS control for power management, the intel_pstate driver loads as expected. When the BIOS is configured to provide the power management, the intel_pstate driver does not load and we get the pcc_cpufreq driver instead.] Signed-off-by: Linda Knippers <linda.knippers@hp.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/intel_pstate.c74
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
786static 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
815struct 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 */
822static struct hw_vendor_info vendor_info[] = {
823 {1, "HP ", "ProLiant"},
824 {0, "", ""},
825};
826
827static 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 */
846static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; }
847#endif /* CONFIG_ACPI */
848
782static int __init intel_pstate_init(void) 849static 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);