Commit 26c92a38 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull power management updates from Rafael Wysocki:
 "These are mostly fixes, including some fixes for changes made during
  the recent merge window and some "stable" material, plus some minor
  extensions of the turbostat utility.

  Specifics:

   - Fix the PM core to avoid introducing a runtime PM usage counter
     imbalance when adding device links during driver probe (Rafael
     Wysocki).

   - Fix the operating performance points (OPP) framework to ensure that
     the regulator voltage is always updated as appropriate when
     updating clock rates (Waldemar Rymarkiewicz).

   - Fix the intel_pstate driver to use correct max/min limits for cores
     with differing maximum frequences (Srinivas Pandruvada).

   - Fix a typo in the intel_pstate driver documentation (Rafael
     Wysocki).

   - Fix two issues with the recently added Kryo cpufreq driver (Ilia
     Lin).

   - Fix two recent regressions and some other minor issues in the
     turbostat utility and extend it to provide some more diagnostic
     information (Len Brown, Nathan Ciobanu)"

* tag 'pm-4.18-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  Documentation: intel_pstate: Fix typo
  tools/power turbostat: version 18.06.20
  tools/power turbostat: add the missing command line switches
  tools/power turbostat: add single character tokens to help
  tools/power turbostat: alphabetize the help output
  tools/power turbostat: fix segfault on 'no node' machines
  tools/power turbostat: add optional APIC X2APIC columns
  tools/power turbostat: decode cpuid.1.HT
  tools/power turbostat: fix show/hide issues resulting from mis-merge
  PM / OPP: Update voltage in case freq == old_freq
  cpufreq: intel_pstate: Fix scaling max/min limits with Turbo 3.0
  cpufreq: kryo: Add module remove and exit
  cpufreq: kryo: Fix possible error code dereference
  PM / core: Fix supplier device runtime PM usage counter imbalance
parents 1abd8a8f b51e0013
...@@ -410,7 +410,7 @@ argument is passed to the kernel in the command line. ...@@ -410,7 +410,7 @@ argument is passed to the kernel in the command line.
That only is supported in some configurations, though (for example, if That only is supported in some configurations, though (for example, if
the `HWP feature is enabled in the processor <Active Mode With HWP_>`_, the `HWP feature is enabled in the processor <Active Mode With HWP_>`_,
the operation mode of the driver cannot be changed), and if it is not the operation mode of the driver cannot be changed), and if it is not
supported in the current configuration, writes to this attribute with supported in the current configuration, writes to this attribute will
fail with an appropriate error. fail with an appropriate error.
Interpretation of Policy Attributes Interpretation of Policy Attributes
......
...@@ -236,6 +236,13 @@ struct device_link *device_link_add(struct device *consumer, ...@@ -236,6 +236,13 @@ struct device_link *device_link_add(struct device *consumer,
link->rpm_active = true; link->rpm_active = true;
} }
pm_runtime_new_link(consumer); pm_runtime_new_link(consumer);
/*
* If the link is being added by the consumer driver at probe
* time, balance the decrementation of the supplier's runtime PM
* usage counter after consumer probe in driver_probe_device().
*/
if (consumer->links.status == DL_DEV_PROBING)
pm_runtime_get_noresume(supplier);
} }
get_device(supplier); get_device(supplier);
link->supplier = supplier; link->supplier = supplier;
...@@ -255,12 +262,12 @@ struct device_link *device_link_add(struct device *consumer, ...@@ -255,12 +262,12 @@ struct device_link *device_link_add(struct device *consumer,
switch (consumer->links.status) { switch (consumer->links.status) {
case DL_DEV_PROBING: case DL_DEV_PROBING:
/* /*
* Balance the decrementation of the supplier's * Some callers expect the link creation during
* runtime PM usage counter after consumer probe * consumer driver probe to resume the supplier
* in driver_probe_device(). * even without DL_FLAG_RPM_ACTIVE.
*/ */
if (flags & DL_FLAG_PM_RUNTIME) if (flags & DL_FLAG_PM_RUNTIME)
pm_runtime_get_sync(supplier); pm_runtime_resume(supplier);
link->status = DL_STATE_CONSUMER_PROBE; link->status = DL_STATE_CONSUMER_PROBE;
break; break;
......
...@@ -294,6 +294,7 @@ struct pstate_funcs { ...@@ -294,6 +294,7 @@ struct pstate_funcs {
static struct pstate_funcs pstate_funcs __read_mostly; static struct pstate_funcs pstate_funcs __read_mostly;
static int hwp_active __read_mostly; static int hwp_active __read_mostly;
static int hwp_mode_bdw __read_mostly;
static bool per_cpu_limits __read_mostly; static bool per_cpu_limits __read_mostly;
static bool hwp_boost __read_mostly; static bool hwp_boost __read_mostly;
...@@ -1413,7 +1414,15 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) ...@@ -1413,7 +1414,15 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
cpu->pstate.scaling = pstate_funcs.get_scaling(); cpu->pstate.scaling = pstate_funcs.get_scaling();
cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling; cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
if (hwp_active && !hwp_mode_bdw) {
unsigned int phy_max, current_max;
intel_pstate_get_hwp_max(cpu->cpu, &phy_max, &current_max);
cpu->pstate.turbo_freq = phy_max * cpu->pstate.scaling;
} else {
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) if (pstate_funcs.get_aperf_mperf_shift)
cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift(); cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift();
...@@ -2467,28 +2476,36 @@ static inline bool intel_pstate_has_acpi_ppc(void) { return false; } ...@@ -2467,28 +2476,36 @@ static inline bool intel_pstate_has_acpi_ppc(void) { return false; }
static inline void intel_pstate_request_control_from_smm(void) {} static inline void intel_pstate_request_control_from_smm(void) {}
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
#define INTEL_PSTATE_HWP_BROADWELL 0x01
#define ICPU_HWP(model, hwp_mode) \
{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_HWP, hwp_mode }
static const struct x86_cpu_id hwp_support_ids[] __initconst = { static const struct x86_cpu_id hwp_support_ids[] __initconst = {
{ X86_VENDOR_INTEL, 6, X86_MODEL_ANY, X86_FEATURE_HWP }, ICPU_HWP(INTEL_FAM6_BROADWELL_X, INTEL_PSTATE_HWP_BROADWELL),
ICPU_HWP(INTEL_FAM6_BROADWELL_XEON_D, INTEL_PSTATE_HWP_BROADWELL),
ICPU_HWP(X86_MODEL_ANY, 0),
{} {}
}; };
static int __init intel_pstate_init(void) static int __init intel_pstate_init(void)
{ {
const struct x86_cpu_id *id;
int rc; int rc;
if (no_load) if (no_load)
return -ENODEV; return -ENODEV;
if (x86_match_cpu(hwp_support_ids)) { id = x86_match_cpu(hwp_support_ids);
if (id) {
copy_cpu_funcs(&core_funcs); copy_cpu_funcs(&core_funcs);
if (!no_hwp) { if (!no_hwp) {
hwp_active++; hwp_active++;
hwp_mode_bdw = id->driver_data;
intel_pstate.attr = hwp_cpufreq_attrs; intel_pstate.attr = hwp_cpufreq_attrs;
goto hwp_cpu_matched; goto hwp_cpu_matched;
} }
} else { } else {
const struct x86_cpu_id *id;
id = x86_match_cpu(intel_pstate_cpu_ids); id = x86_match_cpu(intel_pstate_cpu_ids);
if (!id) if (!id)
return -ENODEV; return -ENODEV;
......
...@@ -42,6 +42,8 @@ enum _msm8996_version { ...@@ -42,6 +42,8 @@ enum _msm8996_version {
NUM_OF_MSM8996_VERSIONS, NUM_OF_MSM8996_VERSIONS,
}; };
struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void) static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
{ {
size_t len; size_t len;
...@@ -74,7 +76,6 @@ static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void) ...@@ -74,7 +76,6 @@ static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
{ {
struct opp_table *opp_tables[NR_CPUS] = {0}; struct opp_table *opp_tables[NR_CPUS] = {0};
struct platform_device *cpufreq_dt_pdev;
enum _msm8996_version msm8996_version; enum _msm8996_version msm8996_version;
struct nvmem_cell *speedbin_nvmem; struct nvmem_cell *speedbin_nvmem;
struct device_node *np; struct device_node *np;
...@@ -115,6 +116,8 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) ...@@ -115,6 +116,8 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
speedbin = nvmem_cell_read(speedbin_nvmem, &len); speedbin = nvmem_cell_read(speedbin_nvmem, &len);
nvmem_cell_put(speedbin_nvmem); nvmem_cell_put(speedbin_nvmem);
if (IS_ERR(speedbin))
return PTR_ERR(speedbin);
switch (msm8996_version) { switch (msm8996_version) {
case MSM8996_V3: case MSM8996_V3:
...@@ -127,6 +130,7 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) ...@@ -127,6 +130,7 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
BUG(); BUG();
break; break;
} }
kfree(speedbin);
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
cpu_dev = get_cpu_device(cpu); cpu_dev = get_cpu_device(cpu);
...@@ -162,8 +166,15 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) ...@@ -162,8 +166,15 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int qcom_cpufreq_kryo_remove(struct platform_device *pdev)
{
platform_device_unregister(cpufreq_dt_pdev);
return 0;
}
static struct platform_driver qcom_cpufreq_kryo_driver = { static struct platform_driver qcom_cpufreq_kryo_driver = {
.probe = qcom_cpufreq_kryo_probe, .probe = qcom_cpufreq_kryo_probe,
.remove = qcom_cpufreq_kryo_remove,
.driver = { .driver = {
.name = "qcom-cpufreq-kryo", .name = "qcom-cpufreq-kryo",
}, },
...@@ -198,8 +209,9 @@ static int __init qcom_cpufreq_kryo_init(void) ...@@ -198,8 +209,9 @@ static int __init qcom_cpufreq_kryo_init(void)
if (unlikely(ret < 0)) if (unlikely(ret < 0))
return ret; return ret;
ret = PTR_ERR_OR_ZERO(platform_device_register_simple( kryo_cpufreq_pdev = platform_device_register_simple(
"qcom-cpufreq-kryo", -1, NULL, 0)); "qcom-cpufreq-kryo", -1, NULL, 0);
ret = PTR_ERR_OR_ZERO(kryo_cpufreq_pdev);
if (0 == ret) if (0 == ret)
return 0; return 0;
...@@ -208,5 +220,12 @@ static int __init qcom_cpufreq_kryo_init(void) ...@@ -208,5 +220,12 @@ static int __init qcom_cpufreq_kryo_init(void)
} }
module_init(qcom_cpufreq_kryo_init); module_init(qcom_cpufreq_kryo_init);
static void __init qcom_cpufreq_kryo_exit(void)
{
platform_device_unregister(kryo_cpufreq_pdev);
platform_driver_unregister(&qcom_cpufreq_kryo_driver);
}
module_exit(qcom_cpufreq_kryo_exit);
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver"); MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -598,7 +598,7 @@ static int _generic_set_opp_regulator(const struct opp_table *opp_table, ...@@ -598,7 +598,7 @@ static int _generic_set_opp_regulator(const struct opp_table *opp_table,
} }
/* Scaling up? Scale voltage before frequency */ /* Scaling up? Scale voltage before frequency */
if (freq > old_freq) { if (freq >= old_freq) {
ret = _set_opp_voltage(dev, reg, new_supply); ret = _set_opp_voltage(dev, reg, new_supply);
if (ret) if (ret)
goto restore_voltage; goto restore_voltage;
......
...@@ -56,7 +56,7 @@ name as necessary to disambiguate it from others is necessary. Note that option ...@@ -56,7 +56,7 @@ name as necessary to disambiguate it from others is necessary. Note that option
.PP .PP
\fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group. \fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
.PP .PP
\fB--enable column\fP show the specified built-in columns, which are otherwise disabled, by default. Currently the only built-in counters disabled by default are "usec" and "Time_Of_Day_Seconds". \fB--enable column\fP show the specified built-in columns, which are otherwise disabled, by default. Currently the only built-in counters disabled by default are "usec", "Time_Of_Day_Seconds", "APIC" and "X2APIC".
The column name "all" can be used to enable all disabled-by-default built-in counters. The column name "all" can be used to enable all disabled-by-default built-in counters.
.PP .PP
\fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group. \fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
......
This diff is collapsed.
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