Commit 63a86362 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull power management fixes from Rafael Wysocki:
 "These are two stable-candidate fixes for the intel_pstate driver and
  the generic power domains (genpd) framework.

  Specifics:

   - Fix the average CPU load computations in the intel_pstate driver on
     Knights Landing (Xeon Phi) processors that require an extra factor
     to compensate for a rate change differences between the TSC and
     MPERF which is missing (Srinivas Pandruvada).

   - Fix an initialization ordering issue in the generic power domains
     (genpd) framework (Sudeep Holla)"

* tag 'pm-4.13-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  PM / Domains: defer dev_pm_domain_set() until genpd->attach_dev succeeds if present
  cpufreq: intel_pstate: Correct the busy calculation for KNL
parents 54a7d50b ffa64d5e
...@@ -1222,8 +1222,6 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev, ...@@ -1222,8 +1222,6 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev,
spin_unlock_irq(&dev->power.lock); spin_unlock_irq(&dev->power.lock);
dev_pm_domain_set(dev, &genpd->domain);
return gpd_data; return gpd_data;
err_free: err_free:
...@@ -1237,8 +1235,6 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev, ...@@ -1237,8 +1235,6 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev,
static void genpd_free_dev_data(struct device *dev, static void genpd_free_dev_data(struct device *dev,
struct generic_pm_domain_data *gpd_data) struct generic_pm_domain_data *gpd_data)
{ {
dev_pm_domain_set(dev, NULL);
spin_lock_irq(&dev->power.lock); spin_lock_irq(&dev->power.lock);
dev->power.subsys_data->domain_data = NULL; dev->power.subsys_data->domain_data = NULL;
...@@ -1275,6 +1271,8 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, ...@@ -1275,6 +1271,8 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
if (ret) if (ret)
goto out; goto out;
dev_pm_domain_set(dev, &genpd->domain);
genpd->device_count++; genpd->device_count++;
genpd->max_off_time_changed = true; genpd->max_off_time_changed = true;
...@@ -1336,6 +1334,8 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, ...@@ -1336,6 +1334,8 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
if (genpd->detach_dev) if (genpd->detach_dev)
genpd->detach_dev(genpd, dev); genpd->detach_dev(genpd, dev);
dev_pm_domain_set(dev, NULL);
list_del_init(&pdd->list_node); list_del_init(&pdd->list_node);
genpd_unlock(genpd); genpd_unlock(genpd);
......
...@@ -225,6 +225,9 @@ struct global_params { ...@@ -225,6 +225,9 @@ struct global_params {
* @vid: Stores VID limits for this CPU * @vid: Stores VID limits for this CPU
* @pid: Stores PID parameters for this CPU * @pid: Stores PID parameters for this CPU
* @last_sample_time: Last Sample time * @last_sample_time: Last Sample time
* @aperf_mperf_shift: Number of clock cycles after aperf, merf is incremented
* This shift is a multiplier to mperf delta to
* calculate CPU busy.
* @prev_aperf: Last APERF value read from APERF MSR * @prev_aperf: Last APERF value read from APERF MSR
* @prev_mperf: Last MPERF value read from MPERF MSR * @prev_mperf: Last MPERF value read from MPERF MSR
* @prev_tsc: Last timestamp counter (TSC) value * @prev_tsc: Last timestamp counter (TSC) value
...@@ -259,6 +262,7 @@ struct cpudata { ...@@ -259,6 +262,7 @@ struct cpudata {
u64 last_update; u64 last_update;
u64 last_sample_time; u64 last_sample_time;
u64 aperf_mperf_shift;
u64 prev_aperf; u64 prev_aperf;
u64 prev_mperf; u64 prev_mperf;
u64 prev_tsc; u64 prev_tsc;
...@@ -321,6 +325,7 @@ struct pstate_funcs { ...@@ -321,6 +325,7 @@ struct pstate_funcs {
int (*get_min)(void); int (*get_min)(void);
int (*get_turbo)(void); int (*get_turbo)(void);
int (*get_scaling)(void); int (*get_scaling)(void);
int (*get_aperf_mperf_shift)(void);
u64 (*get_val)(struct cpudata*, int pstate); u64 (*get_val)(struct cpudata*, int pstate);
void (*get_vid)(struct cpudata *); void (*get_vid)(struct cpudata *);
void (*update_util)(struct update_util_data *data, u64 time, void (*update_util)(struct update_util_data *data, u64 time,
...@@ -1486,6 +1491,11 @@ static u64 core_get_val(struct cpudata *cpudata, int pstate) ...@@ -1486,6 +1491,11 @@ static u64 core_get_val(struct cpudata *cpudata, int pstate)
return val; return val;
} }
static int knl_get_aperf_mperf_shift(void)
{
return 10;
}
static int knl_get_turbo_pstate(void) static int knl_get_turbo_pstate(void)
{ {
u64 value; u64 value;
...@@ -1543,6 +1553,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) ...@@ -1543,6 +1553,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling; cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling; cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
if (pstate_funcs.get_aperf_mperf_shift)
cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift();
if (pstate_funcs.get_vid) if (pstate_funcs.get_vid)
pstate_funcs.get_vid(cpu); pstate_funcs.get_vid(cpu);
...@@ -1616,7 +1629,8 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu) ...@@ -1616,7 +1629,8 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
int32_t busy_frac, boost; int32_t busy_frac, boost;
int target, avg_pstate; int target, avg_pstate;
busy_frac = div_fp(sample->mperf, sample->tsc); busy_frac = div_fp(sample->mperf << cpu->aperf_mperf_shift,
sample->tsc);
boost = cpu->iowait_boost; boost = cpu->iowait_boost;
cpu->iowait_boost >>= 1; cpu->iowait_boost >>= 1;
...@@ -1675,7 +1689,8 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu) ...@@ -1675,7 +1689,8 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
sample_ratio = div_fp(pid_params.sample_rate_ns, duration_ns); sample_ratio = div_fp(pid_params.sample_rate_ns, duration_ns);
perf_scaled = mul_fp(perf_scaled, sample_ratio); perf_scaled = mul_fp(perf_scaled, sample_ratio);
} else { } else {
sample_ratio = div_fp(100 * cpu->sample.mperf, cpu->sample.tsc); sample_ratio = div_fp(100 * (cpu->sample.mperf << cpu->aperf_mperf_shift),
cpu->sample.tsc);
if (sample_ratio < int_tofp(1)) if (sample_ratio < int_tofp(1))
perf_scaled = 0; perf_scaled = 0;
} }
...@@ -1807,6 +1822,7 @@ static const struct pstate_funcs knl_funcs = { ...@@ -1807,6 +1822,7 @@ static const struct pstate_funcs knl_funcs = {
.get_max_physical = core_get_max_pstate_physical, .get_max_physical = core_get_max_pstate_physical,
.get_min = core_get_min_pstate, .get_min = core_get_min_pstate,
.get_turbo = knl_get_turbo_pstate, .get_turbo = knl_get_turbo_pstate,
.get_aperf_mperf_shift = knl_get_aperf_mperf_shift,
.get_scaling = core_get_scaling, .get_scaling = core_get_scaling,
.get_val = core_get_val, .get_val = core_get_val,
.update_util = intel_pstate_update_util_pid, .update_util = intel_pstate_update_util_pid,
...@@ -2403,6 +2419,7 @@ static void __init copy_cpu_funcs(struct pstate_funcs *funcs) ...@@ -2403,6 +2419,7 @@ static void __init copy_cpu_funcs(struct pstate_funcs *funcs)
pstate_funcs.get_val = funcs->get_val; pstate_funcs.get_val = funcs->get_val;
pstate_funcs.get_vid = funcs->get_vid; pstate_funcs.get_vid = funcs->get_vid;
pstate_funcs.update_util = funcs->update_util; pstate_funcs.update_util = funcs->update_util;
pstate_funcs.get_aperf_mperf_shift = funcs->get_aperf_mperf_shift;
intel_pstate_use_acpi_profile(); intel_pstate_use_acpi_profile();
} }
......
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