Skip to content

Commit

Permalink
Merge tag 'pm-4.19-rc1-2' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/rafael/linux-pm

Pull more power management updates from Rafael Wysocki:
 "These fix the main idle loop and the menu cpuidle governor, clean up
  the latter, fix a mistake in the PCI bus type's support for system
  suspend and resume, fix the ondemand and conservative cpufreq
  governors, address a build issue in the system wakeup framework and
  make the ACPI C-states desciptions less confusing.

  Specifics:

   - Make the idle loop handle stopped scheduler tick correctly (Rafael
     Wysocki).

   - Prevent the menu cpuidle governor from letting CPUs spend too much
     time in shallow idle states when it is invoked with scheduler tick
     stopped and clean it up somewhat (Rafael Wysocki).

   - Avoid invoking the platform firmware to make the platform enter the
     ACPI S3 sleep state with suspended PCIe root ports which may
     confuse the firmware and cause it to crash (Rafael Wysocki).

   - Fix sysfs-related race in the ondemand and conservative cpufreq
     governors which may cause the system to crash if the governor
     module is removed during an update of CPU frequency limits (Henry
     Willard).

   - Select SRCU when building the system wakeup framework to avoid a
     build issue in it (zhangyi).

   - Make the descriptions of ACPI C-states vendor-neutral to avoid
     confusion (Prarit Bhargava)"

* tag 'pm-4.19-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpuidle: menu: Handle stopped tick more aggressively
  sched: idle: Avoid retaining the tick when it has been stopped
  PCI / ACPI / PM: Resume all bridges on suspend-to-RAM
  cpuidle: menu: Update stale polling override comment
  cpufreq: governor: Avoid accessing invalid governor_data
  x86/ACPI/cstate: Make APCI C1 FFH MWAIT C-state description vendor-neutral
  cpuidle: menu: Fix white space
  PM / sleep: wakeup: Fix build error caused by missing SRCU support
  • Loading branch information
Linus Torvalds committed Aug 22, 2018
2 parents 159127e + 01ac7c4 commit dfec4a8
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 25 deletions.
2 changes: 1 addition & 1 deletion arch/x86/kernel/acpi/cstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
cx->type);
}
snprintf(cx->desc,
ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
ACPI_CX_DESC_LEN, "ACPI FFH MWAIT 0x%x",
cx->address);
out:
return retval;
Expand Down
12 changes: 10 additions & 2 deletions drivers/cpufreq/cpufreq_governor.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,12 +555,20 @@ EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop);

void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
{
struct policy_dbs_info *policy_dbs = policy->governor_data;
struct policy_dbs_info *policy_dbs;

/* Protect gov->gdbs_data against cpufreq_dbs_governor_exit() */
mutex_lock(&gov_dbs_data_mutex);
policy_dbs = policy->governor_data;
if (!policy_dbs)
goto out;

mutex_lock(&policy_dbs->update_mutex);
cpufreq_policy_apply_limits(policy);
gov_update_sample_delay(policy_dbs, 0);

mutex_unlock(&policy_dbs->update_mutex);

out:
mutex_unlock(&gov_dbs_data_mutex);
}
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
45 changes: 28 additions & 17 deletions drivers/cpuidle/governors/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
unsigned int polling_threshold;

/*
* We want to default to C1 (hlt), not to busy polling
* unless the timer is happening really really soon, or
* C1's exit latency exceeds the user configured limit.
* Default to a physical idle state, not to busy polling, unless
* a timer is going to trigger really really soon.
*/
polling_threshold = max_t(unsigned int, 20, s->target_residency);
if (data->next_timer_us > polling_threshold &&
Expand All @@ -349,14 +348,12 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
* If the tick is already stopped, the cost of possible short
* idle duration misprediction is much higher, because the CPU
* may be stuck in a shallow idle state for a long time as a
* result of it. In that case say we might mispredict and try
* to force the CPU into a state for which we would have stopped
* the tick, unless a timer is going to expire really soon
* anyway.
* result of it. In that case say we might mispredict and use
* the known time till the closest timer event for the idle
* state selection.
*/
if (data->predicted_us < TICK_USEC)
data->predicted_us = min_t(unsigned int, TICK_USEC,
ktime_to_us(delta_next));
data->predicted_us = ktime_to_us(delta_next);
} else {
/*
* Use the performance multiplier and the user-configurable
Expand All @@ -381,8 +378,22 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
continue;
if (idx == -1)
idx = i; /* first enabled state */
if (s->target_residency > data->predicted_us)
break;
if (s->target_residency > data->predicted_us) {
if (!tick_nohz_tick_stopped())
break;

/*
* If the state selected so far is shallow and this
* state's target residency matches the time till the
* closest timer event, select this one to avoid getting
* stuck in the shallow one for too long.
*/
if (drv->states[idx].target_residency < TICK_USEC &&
s->target_residency <= ktime_to_us(delta_next))
idx = i;

goto out;
}
if (s->exit_latency > latency_req) {
/*
* If we break out of the loop for latency reasons, use
Expand All @@ -403,23 +414,22 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
* Don't stop the tick if the selected state is a polling one or if the
* expected idle duration is shorter than the tick period length.
*/
if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
expected_interval < TICK_USEC) {
if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
expected_interval < TICK_USEC) && !tick_nohz_tick_stopped()) {
unsigned int delta_next_us = ktime_to_us(delta_next);

*stop_tick = false;

if (!tick_nohz_tick_stopped() && idx > 0 &&
drv->states[idx].target_residency > delta_next_us) {
if (idx > 0 && drv->states[idx].target_residency > delta_next_us) {
/*
* The tick is not going to be stopped and the target
* residency of the state to be returned is not within
* the time until the next timer event including the
* tick, so try to correct that.
*/
for (i = idx - 1; i >= 0; i--) {
if (drv->states[i].disabled ||
dev->states_usage[i].disable)
if (drv->states[i].disabled ||
dev->states_usage[i].disable)
continue;

idx = i;
Expand All @@ -429,6 +439,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
}
}

out:
data->last_state_idx = idx;

return data->last_state_idx;
Expand Down
6 changes: 2 additions & 4 deletions drivers/pci/pci-acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,13 +615,11 @@ static bool acpi_pci_need_resume(struct pci_dev *dev)
/*
* In some cases (eg. Samsung 305V4A) leaving a bridge in suspend over
* system-wide suspend/resume confuses the platform firmware, so avoid
* doing that, unless the bridge has a driver that should take care of
* the PM handling. According to Section 16.1.6 of ACPI 6.2, endpoint
* doing that. According to Section 16.1.6 of ACPI 6.2, endpoint
* devices are expected to be in D3 before invoking the S3 entry path
* from the firmware, so they should not be affected by this issue.
*/
if (pci_is_bridge(dev) && !dev->driver &&
acpi_target_system_state() != ACPI_STATE_S0)
if (pci_is_bridge(dev) && acpi_target_system_state() != ACPI_STATE_S0)
return true;

if (!adev || !acpi_device_power_manageable(adev))
Expand Down
1 change: 1 addition & 0 deletions kernel/power/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ config PM_SLEEP
def_bool y
depends on SUSPEND || HIBERNATE_CALLBACKS
select PM
select SRCU

config PM_SLEEP_SMP
def_bool y
Expand Down
2 changes: 1 addition & 1 deletion kernel/sched/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ static void cpuidle_idle_call(void)
*/
next_state = cpuidle_select(drv, dev, &stop_tick);

if (stop_tick)
if (stop_tick || tick_nohz_tick_stopped())
tick_nohz_idle_stop_tick();
else
tick_nohz_idle_retain_tick();
Expand Down

0 comments on commit dfec4a8

Please sign in to comment.