Commit 73784fb7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm-4.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
 "These fix two cpufreq issues, one introduced recently and one related
  to recent changes, fix cpufreq documentation, fix up recently added
  code in the Thunderbolt driver and update runtime PM framework
  documentation.

  Specifics:

   - Fix the handling of the scaling_cur_freq cpufreq policy attribute
     on x86 systems with the MPERF/APERF registers present to make it
     behave more as expected after recent changes (Rafael Wysocki).

   - Drop a leftover callback from the intel_pstate driver which also
     prevents the cpuinfo_cur_freq cpufreq policy attribute from being
     incorrectly exposed when intel_pstate works in the active mode
     (Rafael Wysocki).

   - Add a missing piece describing the cpuinfo_cur_freq policy
     attribute to cpufreq documentation (Rafael Wysocki).

   - Fix up a recently added part of the Thunderbolt driver to avoid
     aborting system suspends if its mailbox commands time out (Rafael
     Wysocki).

   - Update device runtime PM framework documentation to reflect the
     current behavior of the code (Johan Hovold)"

* tag 'pm-4.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  thunderbolt: icm: Ignore mailbox errors in icm_suspend()
  cpufreq: x86: Make scaling_cur_freq behave more as expected
  PM / runtime: Document new pm_runtime_set_suspended() constraint
  cpufreq: docs: Add missing cpuinfo_cur_freq description
  cpufreq: intel_pstate: Drop ->get from intel_pstate structure
parents 19ec50a4 78aa904a
...@@ -237,6 +237,14 @@ are the following: ...@@ -237,6 +237,14 @@ are the following:
This attribute is not present if the scaling driver in use does not This attribute is not present if the scaling driver in use does not
support it. support it.
``cpuinfo_cur_freq``
Current frequency of the CPUs belonging to this policy as obtained from
the hardware (in KHz).
This is expected to be the frequency the hardware actually runs at.
If that frequency cannot be determined, this attribute should not
be present.
``cpuinfo_max_freq`` ``cpuinfo_max_freq``
Maximum possible operating frequency the CPUs belonging to this policy Maximum possible operating frequency the CPUs belonging to this policy
can run at (in kHz). can run at (in kHz).
......
...@@ -435,7 +435,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: ...@@ -435,7 +435,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
PM status to 'suspended' and update its parent's counter of 'active' PM status to 'suspended' and update its parent's counter of 'active'
children as appropriate (it is only valid to use this function if children as appropriate (it is only valid to use this function if
'power.runtime_error' is set or 'power.disable_depth' is greater than 'power.runtime_error' is set or 'power.disable_depth' is greater than
zero) zero); it will fail and return an error code if the device has a child
which is active and the 'power.ignore_children' flag is unset
bool pm_runtime_active(struct device *dev); bool pm_runtime_active(struct device *dev);
- return true if the device's runtime PM status is 'active' or its - return true if the device's runtime PM status is 'active' or its
......
...@@ -8,20 +8,25 @@ ...@@ -8,20 +8,25 @@
* This file is licensed under GPLv2. * This file is licensed under GPLv2.
*/ */
#include <linux/jiffies.h> #include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/math64.h> #include <linux/math64.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/smp.h> #include <linux/smp.h>
struct aperfmperf_sample { struct aperfmperf_sample {
unsigned int khz; unsigned int khz;
unsigned long jiffies; ktime_t time;
u64 aperf; u64 aperf;
u64 mperf; u64 mperf;
}; };
static DEFINE_PER_CPU(struct aperfmperf_sample, samples); static DEFINE_PER_CPU(struct aperfmperf_sample, samples);
#define APERFMPERF_CACHE_THRESHOLD_MS 10
#define APERFMPERF_REFRESH_DELAY_MS 20
#define APERFMPERF_STALE_THRESHOLD_MS 1000
/* /*
* aperfmperf_snapshot_khz() * aperfmperf_snapshot_khz()
* On the current CPU, snapshot APERF, MPERF, and jiffies * On the current CPU, snapshot APERF, MPERF, and jiffies
...@@ -33,9 +38,11 @@ static void aperfmperf_snapshot_khz(void *dummy) ...@@ -33,9 +38,11 @@ static void aperfmperf_snapshot_khz(void *dummy)
u64 aperf, aperf_delta; u64 aperf, aperf_delta;
u64 mperf, mperf_delta; u64 mperf, mperf_delta;
struct aperfmperf_sample *s = this_cpu_ptr(&samples); struct aperfmperf_sample *s = this_cpu_ptr(&samples);
ktime_t now = ktime_get();
s64 time_delta = ktime_ms_delta(now, s->time);
/* Don't bother re-computing within 10 ms */ /* Don't bother re-computing within the cache threshold time. */
if (time_before(jiffies, s->jiffies + HZ/100)) if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS)
return; return;
rdmsrl(MSR_IA32_APERF, aperf); rdmsrl(MSR_IA32_APERF, aperf);
...@@ -51,22 +58,21 @@ static void aperfmperf_snapshot_khz(void *dummy) ...@@ -51,22 +58,21 @@ static void aperfmperf_snapshot_khz(void *dummy)
if (mperf_delta == 0) if (mperf_delta == 0)
return; return;
/* s->time = now;
* if (cpu_khz * aperf_delta) fits into ULLONG_MAX, then
* khz = (cpu_khz * aperf_delta) / mperf_delta
*/
if (div64_u64(ULLONG_MAX, cpu_khz) > aperf_delta)
s->khz = div64_u64((cpu_khz * aperf_delta), mperf_delta);
else /* khz = aperf_delta / (mperf_delta / cpu_khz) */
s->khz = div64_u64(aperf_delta,
div64_u64(mperf_delta, cpu_khz));
s->jiffies = jiffies;
s->aperf = aperf; s->aperf = aperf;
s->mperf = mperf; s->mperf = mperf;
/* If the previous iteration was too long ago, discard it. */
if (time_delta > APERFMPERF_STALE_THRESHOLD_MS)
s->khz = 0;
else
s->khz = div64_u64((cpu_khz * aperf_delta), mperf_delta);
} }
unsigned int arch_freq_get_on_cpu(int cpu) unsigned int arch_freq_get_on_cpu(int cpu)
{ {
unsigned int khz;
if (!cpu_khz) if (!cpu_khz)
return 0; return 0;
...@@ -74,6 +80,12 @@ unsigned int arch_freq_get_on_cpu(int cpu) ...@@ -74,6 +80,12 @@ unsigned int arch_freq_get_on_cpu(int cpu)
return 0; return 0;
smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1); smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1);
khz = per_cpu(samples.khz, cpu);
if (khz)
return khz;
msleep(APERFMPERF_REFRESH_DELAY_MS);
smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1);
return per_cpu(samples.khz, cpu); return per_cpu(samples.khz, cpu);
} }
...@@ -1922,13 +1922,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum) ...@@ -1922,13 +1922,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
return 0; return 0;
} }
static unsigned int intel_pstate_get(unsigned int cpu_num)
{
struct cpudata *cpu = all_cpu_data[cpu_num];
return cpu ? get_avg_frequency(cpu) : 0;
}
static void intel_pstate_set_update_util_hook(unsigned int cpu_num) static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
{ {
struct cpudata *cpu = all_cpu_data[cpu_num]; struct cpudata *cpu = all_cpu_data[cpu_num];
...@@ -2169,7 +2162,6 @@ static struct cpufreq_driver intel_pstate = { ...@@ -2169,7 +2162,6 @@ static struct cpufreq_driver intel_pstate = {
.setpolicy = intel_pstate_set_policy, .setpolicy = intel_pstate_set_policy,
.suspend = intel_pstate_hwp_save_state, .suspend = intel_pstate_hwp_save_state,
.resume = intel_pstate_resume, .resume = intel_pstate_resume,
.get = intel_pstate_get,
.init = intel_pstate_cpu_init, .init = intel_pstate_cpu_init,
.exit = intel_pstate_cpu_exit, .exit = intel_pstate_cpu_exit,
.stop_cpu = intel_pstate_stop_cpu, .stop_cpu = intel_pstate_stop_cpu,
......
...@@ -904,7 +904,14 @@ static int icm_driver_ready(struct tb *tb) ...@@ -904,7 +904,14 @@ static int icm_driver_ready(struct tb *tb)
static int icm_suspend(struct tb *tb) static int icm_suspend(struct tb *tb)
{ {
return nhi_mailbox_cmd(tb->nhi, NHI_MAILBOX_SAVE_DEVS, 0); int ret;
ret = nhi_mailbox_cmd(tb->nhi, NHI_MAILBOX_SAVE_DEVS, 0);
if (ret)
tb_info(tb, "Ignoring mailbox command error (%d) in %s\n",
ret, __func__);
return 0;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment