diff options
author | Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> | 2013-12-20 13:47:26 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-10 19:26:49 -0500 |
commit | 7ca380f60626d90cdd17cc60de5e756422e35b2a (patch) | |
tree | 6d7301a6da09d0804f948fcb9860d69c34926c98 /drivers/acpi | |
parent | 7f74dc0f4f5fdb745d62ab2e8f6c60cd9e59a1ac (diff) |
ACPI / cpuidle: fix max idle state handling with hotplug CPU support
acpi_processor_hotplug() calls acpi_processor_setup_cpuidle_cx()
without calling acpi_processor_setup_cpuidle_states() first so it
is possible that dev->state_count becomes different from
drv->state_count (in case of SMP system with unsupported C2/C3
states + enabled CPU hotplug and num_online_cpus() becoming > 1).
The driver code assumes that cpuidle core will handle such cases
but currently this is untrue (dev->state_count is used only for
handling cpuidle state sysfs entries and drv->state_count is used
for all other cases) and will not be fixed in the future as
dev->state_count is planned to be removed.
Fix the issue by checking for the max supported idle state in
C2/C3 state's ->enter handler (acpi_idle_enter_simple() for C2/C3
and acpi_idle_enter_bm() for C3 + bm_check flag set) and setting
the C1 state (instead of higher states) when needed.
Also remove no longer needed max idle state checks from
acpi_processor_setup_cpuidle_[states,cx]().
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Len Brown <lenb@kernel.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/processor_idle.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 644516d9bde6..45e3b81d6c29 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -785,6 +785,13 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
785 | if (unlikely(!pr)) | 785 | if (unlikely(!pr)) |
786 | return -EINVAL; | 786 | return -EINVAL; |
787 | 787 | ||
788 | #ifdef CONFIG_HOTPLUG_CPU | ||
789 | if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && | ||
790 | !pr->flags.has_cst && | ||
791 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) | ||
792 | return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START); | ||
793 | #endif | ||
794 | |||
788 | if (cx->entry_method == ACPI_CSTATE_FFH) { | 795 | if (cx->entry_method == ACPI_CSTATE_FFH) { |
789 | if (current_set_polling_and_test()) | 796 | if (current_set_polling_and_test()) |
790 | return -EINVAL; | 797 | return -EINVAL; |
@@ -831,6 +838,13 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
831 | if (unlikely(!pr)) | 838 | if (unlikely(!pr)) |
832 | return -EINVAL; | 839 | return -EINVAL; |
833 | 840 | ||
841 | #ifdef CONFIG_HOTPLUG_CPU | ||
842 | if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && | ||
843 | !pr->flags.has_cst && | ||
844 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) | ||
845 | return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START); | ||
846 | #endif | ||
847 | |||
834 | if (!cx->bm_sts_skip && acpi_idle_bm_check()) { | 848 | if (!cx->bm_sts_skip && acpi_idle_bm_check()) { |
835 | if (drv->safe_state_index >= 0) { | 849 | if (drv->safe_state_index >= 0) { |
836 | return drv->states[drv->safe_state_index].enter(dev, | 850 | return drv->states[drv->safe_state_index].enter(dev, |
@@ -932,12 +946,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, | |||
932 | if (!cx->valid) | 946 | if (!cx->valid) |
933 | continue; | 947 | continue; |
934 | 948 | ||
935 | #ifdef CONFIG_HOTPLUG_CPU | ||
936 | if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && | ||
937 | !pr->flags.has_cst && | ||
938 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) | ||
939 | continue; | ||
940 | #endif | ||
941 | per_cpu(acpi_cstate[count], dev->cpu) = cx; | 949 | per_cpu(acpi_cstate[count], dev->cpu) = cx; |
942 | 950 | ||
943 | count++; | 951 | count++; |
@@ -987,13 +995,6 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | |||
987 | if (!cx->valid) | 995 | if (!cx->valid) |
988 | continue; | 996 | continue; |
989 | 997 | ||
990 | #ifdef CONFIG_HOTPLUG_CPU | ||
991 | if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && | ||
992 | !pr->flags.has_cst && | ||
993 | !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) | ||
994 | continue; | ||
995 | #endif | ||
996 | |||
997 | state = &drv->states[count]; | 998 | state = &drv->states[count]; |
998 | snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); | 999 | snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); |
999 | strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); | 1000 | strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); |