mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-11 20:06:44 +07:00
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>
This commit is contained in:
parent
7f74dc0f4f
commit
7ca380f606
@ -785,6 +785,13 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
|
|||||||
if (unlikely(!pr))
|
if (unlikely(!pr))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
|
||||||
|
!pr->flags.has_cst &&
|
||||||
|
!(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
|
||||||
|
return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cx->entry_method == ACPI_CSTATE_FFH) {
|
if (cx->entry_method == ACPI_CSTATE_FFH) {
|
||||||
if (current_set_polling_and_test())
|
if (current_set_polling_and_test())
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -831,6 +838,13 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
|
|||||||
if (unlikely(!pr))
|
if (unlikely(!pr))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
|
||||||
|
!pr->flags.has_cst &&
|
||||||
|
!(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
|
||||||
|
return acpi_idle_enter_c1(dev, drv, CPUIDLE_DRIVER_STATE_START);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
|
if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
|
||||||
if (drv->safe_state_index >= 0) {
|
if (drv->safe_state_index >= 0) {
|
||||||
return drv->states[drv->safe_state_index].enter(dev,
|
return drv->states[drv->safe_state_index].enter(dev,
|
||||||
@ -932,12 +946,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
|
|||||||
if (!cx->valid)
|
if (!cx->valid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
|
|
||||||
!pr->flags.has_cst &&
|
|
||||||
!(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
per_cpu(acpi_cstate[count], dev->cpu) = cx;
|
per_cpu(acpi_cstate[count], dev->cpu) = cx;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
@ -987,13 +995,6 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
|
|||||||
if (!cx->valid)
|
if (!cx->valid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
|
|
||||||
!pr->flags.has_cst &&
|
|
||||||
!(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
state = &drv->states[count];
|
state = &drv->states[count];
|
||||||
snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
|
snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
|
||||||
strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
|
strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
|
||||||
|
Loading…
Reference in New Issue
Block a user