Merge tag 'pm-4.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Aug 2017 19:32:49 +0000 (12:32 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Aug 2017 19:32:49 +0000 (12:32 -0700)
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

Documentation/admin-guide/pm/cpufreq.rst
Documentation/power/runtime_pm.txt
arch/x86/kernel/cpu/aperfmperf.c
drivers/cpufreq/intel_pstate.c
drivers/thunderbolt/icm.c

index 463cf7e73db80b3bf3f8a36afe91bcf3d7f0d429..7af83a92d2d6103ea3fb0a3a0425e994b29f7f53 100644 (file)
@@ -237,6 +237,14 @@ are the following:
        This attribute is not present if the scaling driver in use does not
        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``
        Maximum possible operating frequency the CPUs belonging to this policy
        can run at (in kHz).
index 0fde3dcf077a302eb24ea6d8fd8df65c4b252d8e..625549d4c74a09642d72bce75387c15348406223 100644 (file)
@@ -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'
       children as appropriate (it is only valid to use this function if
       '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);
     - return true if the device's runtime PM status is 'active' or its
index d869c8671e364d55e343322b410fec9a3e5f66c6..7cf7c70b6ef2a20483361fb8333a85ace25bf1d7 100644 (file)
@@ -8,20 +8,25 @@
  * This file is licensed under GPLv2.
  */
 
-#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/ktime.h>
 #include <linux/math64.h>
 #include <linux/percpu.h>
 #include <linux/smp.h>
 
 struct aperfmperf_sample {
        unsigned int    khz;
-       unsigned long   jiffies;
+       ktime_t time;
        u64     aperf;
        u64     mperf;
 };
 
 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()
  * On the current CPU, snapshot APERF, MPERF, and jiffies
@@ -33,9 +38,11 @@ static void aperfmperf_snapshot_khz(void *dummy)
        u64 aperf, aperf_delta;
        u64 mperf, mperf_delta;
        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 */
-       if (time_before(jiffies, s->jiffies + HZ/100))
+       /* Don't bother re-computing within the cache threshold time. */
+       if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS)
                return;
 
        rdmsrl(MSR_IA32_APERF, aperf);
@@ -51,22 +58,21 @@ static void aperfmperf_snapshot_khz(void *dummy)
        if (mperf_delta == 0)
                return;
 
-       /*
-        * 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->time = now;
        s->aperf = aperf;
        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 khz;
+
        if (!cpu_khz)
                return 0;
 
@@ -74,6 +80,12 @@ unsigned int arch_freq_get_on_cpu(int cpu)
                return 0;
 
        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);
 }
index 6cd50352563894bea24866d2d36d6b815d0abc20..0566455f233ed3cd663506321f08f7ae546862be 100644 (file)
@@ -1922,13 +1922,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
        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)
 {
        struct cpudata *cpu = all_cpu_data[cpu_num];
@@ -2169,7 +2162,6 @@ static struct cpufreq_driver intel_pstate = {
        .setpolicy      = intel_pstate_set_policy,
        .suspend        = intel_pstate_hwp_save_state,
        .resume         = intel_pstate_resume,
-       .get            = intel_pstate_get,
        .init           = intel_pstate_cpu_init,
        .exit           = intel_pstate_cpu_exit,
        .stop_cpu       = intel_pstate_stop_cpu,
index 8ee34029021986c94319e20adf4d36ce1d4ef374..bdaac1ff00a5af7518da6e3e03a2c8e6ef99a11b 100644 (file)
@@ -904,7 +904,14 @@ static int icm_driver_ready(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;
 }
 
 /*