diff options
author | Sudeep Holla <Sudeep.Holla@arm.com> | 2016-07-19 13:52:53 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-07-21 17:24:35 -0400 |
commit | 35ae713355868aa493edbfbabf615473473215cc (patch) | |
tree | 3ee0ef3e3d20c76cfb774d9e39d11b55aca1e4cb | |
parent | 92d21ac74a9e3c09b0b01c764e530657e4c85c49 (diff) |
ACPI / processor_idle: introduce ACPI_PROCESSOR_CSTATE
ACPI 6.0 adds a new method to specify the CPU idle states(C-states)
called Low Power Idle(LPI) states. Since new architectures like ARM64
use only LPIs, introduce ACPI_PROCESSOR_CSTATE to encapsulate all the
code supporting the old style C-states(_CST).
This patch will help to extend the processor_idle module to support
LPI.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/Kconfig | 4 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 80 | ||||
-rw-r--r-- | include/acpi/processor.h | 2 |
3 files changed, 58 insertions, 28 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b7e2e776397d..1358fb7d7a68 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -213,6 +213,10 @@ config ACPI_CPU_FREQ_PSS | |||
213 | bool | 213 | bool |
214 | select THERMAL | 214 | select THERMAL |
215 | 215 | ||
216 | config ACPI_PROCESSOR_CSTATE | ||
217 | def_bool y | ||
218 | depends on IA64 || X86 | ||
219 | |||
216 | config ACPI_PROCESSOR_IDLE | 220 | config ACPI_PROCESSOR_IDLE |
217 | bool | 221 | bool |
218 | select CPU_IDLE | 222 | select CPU_IDLE |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 444e3745c8b3..ca0de35d1c3a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -59,6 +59,12 @@ module_param(latency_factor, uint, 0644); | |||
59 | 59 | ||
60 | static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); | 60 | static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); |
61 | 61 | ||
62 | struct cpuidle_driver acpi_idle_driver = { | ||
63 | .name = "acpi_idle", | ||
64 | .owner = THIS_MODULE, | ||
65 | }; | ||
66 | |||
67 | #ifdef CONFIG_ACPI_PROCESSOR_CSTATE | ||
62 | static | 68 | static |
63 | DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); | 69 | DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); |
64 | 70 | ||
@@ -804,11 +810,6 @@ static void acpi_idle_enter_freeze(struct cpuidle_device *dev, | |||
804 | acpi_idle_do_entry(cx); | 810 | acpi_idle_do_entry(cx); |
805 | } | 811 | } |
806 | 812 | ||
807 | struct cpuidle_driver acpi_idle_driver = { | ||
808 | .name = "acpi_idle", | ||
809 | .owner = THIS_MODULE, | ||
810 | }; | ||
811 | |||
812 | /** | 813 | /** |
813 | * acpi_processor_setup_cpuidle_cx - prepares and configures CPUIDLE | 814 | * acpi_processor_setup_cpuidle_cx - prepares and configures CPUIDLE |
814 | * device i.e. per-cpu data | 815 | * device i.e. per-cpu data |
@@ -925,6 +926,50 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | |||
925 | return 0; | 926 | return 0; |
926 | } | 927 | } |
927 | 928 | ||
929 | static inline void acpi_processor_cstate_first_run_checks(void) | ||
930 | { | ||
931 | acpi_status status; | ||
932 | static int first_run; | ||
933 | |||
934 | if (first_run) | ||
935 | return; | ||
936 | dmi_check_system(processor_power_dmi_table); | ||
937 | max_cstate = acpi_processor_cstate_check(max_cstate); | ||
938 | if (max_cstate < ACPI_C_STATES_MAX) | ||
939 | pr_notice("ACPI: processor limited to max C-state %d\n", | ||
940 | max_cstate); | ||
941 | first_run++; | ||
942 | |||
943 | if (acpi_gbl_FADT.cst_control && !nocst) { | ||
944 | status = acpi_os_write_port(acpi_gbl_FADT.smi_command, | ||
945 | acpi_gbl_FADT.cst_control, 8); | ||
946 | if (ACPI_FAILURE(status)) | ||
947 | ACPI_EXCEPTION((AE_INFO, status, | ||
948 | "Notifying BIOS of _CST ability failed")); | ||
949 | } | ||
950 | } | ||
951 | #else | ||
952 | |||
953 | static inline int disabled_by_idle_boot_param(void) { return 0; } | ||
954 | static inline void acpi_processor_cstate_first_run_checks(void) { } | ||
955 | static int acpi_processor_get_power_info(struct acpi_processor *pr) | ||
956 | { | ||
957 | return -ENODEV; | ||
958 | } | ||
959 | |||
960 | static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, | ||
961 | struct cpuidle_device *dev) | ||
962 | { | ||
963 | return -EINVAL; | ||
964 | } | ||
965 | |||
966 | static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | ||
967 | { | ||
968 | return -EINVAL; | ||
969 | } | ||
970 | |||
971 | #endif /* CONFIG_ACPI_PROCESSOR_CSTATE */ | ||
972 | |||
928 | int acpi_processor_hotplug(struct acpi_processor *pr) | 973 | int acpi_processor_hotplug(struct acpi_processor *pr) |
929 | { | 974 | { |
930 | int ret = 0; | 975 | int ret = 0; |
@@ -1015,35 +1060,16 @@ static int acpi_processor_registered; | |||
1015 | 1060 | ||
1016 | int acpi_processor_power_init(struct acpi_processor *pr) | 1061 | int acpi_processor_power_init(struct acpi_processor *pr) |
1017 | { | 1062 | { |
1018 | acpi_status status; | ||
1019 | int retval; | 1063 | int retval; |
1020 | struct cpuidle_device *dev; | 1064 | struct cpuidle_device *dev; |
1021 | static int first_run; | ||
1022 | 1065 | ||
1023 | if (disabled_by_idle_boot_param()) | 1066 | if (disabled_by_idle_boot_param()) |
1024 | return 0; | 1067 | return 0; |
1025 | 1068 | ||
1026 | if (!first_run) { | 1069 | acpi_processor_cstate_first_run_checks(); |
1027 | dmi_check_system(processor_power_dmi_table); | ||
1028 | max_cstate = acpi_processor_cstate_check(max_cstate); | ||
1029 | if (max_cstate < ACPI_C_STATES_MAX) | ||
1030 | printk(KERN_NOTICE | ||
1031 | "ACPI: processor limited to max C-state %d\n", | ||
1032 | max_cstate); | ||
1033 | first_run++; | ||
1034 | } | ||
1035 | 1070 | ||
1036 | if (acpi_gbl_FADT.cst_control && !nocst) { | 1071 | if (!acpi_processor_get_power_info(pr)) |
1037 | status = | 1072 | pr->flags.power_setup_done = 1; |
1038 | acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8); | ||
1039 | if (ACPI_FAILURE(status)) { | ||
1040 | ACPI_EXCEPTION((AE_INFO, status, | ||
1041 | "Notifying BIOS of _CST ability failed")); | ||
1042 | } | ||
1043 | } | ||
1044 | |||
1045 | acpi_processor_get_power_info(pr); | ||
1046 | pr->flags.power_setup_done = 1; | ||
1047 | 1073 | ||
1048 | /* | 1074 | /* |
1049 | * Install the idle handler if processor power management is supported. | 1075 | * Install the idle handler if processor power management is supported. |
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 6f1805dd5d3c..48779d678122 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h | |||
@@ -242,7 +242,7 @@ extern int acpi_processor_get_performance_info(struct acpi_processor *pr); | |||
242 | DECLARE_PER_CPU(struct acpi_processor *, processors); | 242 | DECLARE_PER_CPU(struct acpi_processor *, processors); |
243 | extern struct acpi_processor_errata errata; | 243 | extern struct acpi_processor_errata errata; |
244 | 244 | ||
245 | #ifdef ARCH_HAS_POWER_INIT | 245 | #if defined(ARCH_HAS_POWER_INIT) && defined(CONFIG_ACPI_PROCESSOR_CSTATE) |
246 | void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, | 246 | void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, |
247 | unsigned int cpu); | 247 | unsigned int cpu); |
248 | int acpi_processor_ffh_cstate_probe(unsigned int cpu, | 248 | int acpi_processor_ffh_cstate_probe(unsigned int cpu, |