Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

thermal: intel: powerclamp: Fix cur_state for multi package system

The powerclamp cooling device cur_state shows actual idle observed by
package C-state idle counters. But the implementation is not sufficient
for multi package or multi die system. The cur_state value is incorrect.
On these systems, these counters must be read from each package/die and
somehow aggregate them. But there is no good method for aggregation.

It was not a problem when explicit CPU model addition was required to
enable intel powerclamp. In this way certain CPU models could have
been avoided. But with the removal of CPU model check with the
availability of Package C-state counters, the driver is loaded on most
of the recent systems.

For multi package/die systems, just show the actual target idle state,
the system is trying to achieve. In powerclamp this is the user set
state minus one.

Also there is no use of starting a worker thread for polling package
C-state counters and applying any compensation for multiple package
or multiple die systems.

Fixes: b721ca0d1927 ("thermal/powerclamp: remove cpu whitelist")
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Cc: 4.14+ <stable@vger.kernel.org> # 4.14+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Srinivas Pandruvada and committed by
Rafael J. Wysocki
8e473635 2153a87f

+16 -4
+16 -4
drivers/thermal/intel/intel_powerclamp.c
··· 57 57 58 58 static unsigned int target_mwait; 59 59 static struct dentry *debug_dir; 60 + static bool poll_pkg_cstate_enable; 60 61 61 62 /* user selected target */ 62 63 static unsigned int set_target_ratio; ··· 261 260 static unsigned int get_compensation(int ratio) 262 261 { 263 262 unsigned int comp = 0; 263 + 264 + if (!poll_pkg_cstate_enable) 265 + return 0; 264 266 265 267 /* we only use compensation if all adjacent ones are good */ 266 268 if (ratio == 1 && ··· 523 519 control_cpu = cpumask_first(cpu_online_mask); 524 520 525 521 clamping = true; 526 - schedule_delayed_work(&poll_pkg_cstate_work, 0); 522 + if (poll_pkg_cstate_enable) 523 + schedule_delayed_work(&poll_pkg_cstate_work, 0); 527 524 528 525 /* start one kthread worker per online cpu */ 529 526 for_each_online_cpu(cpu) { ··· 590 585 static int powerclamp_get_cur_state(struct thermal_cooling_device *cdev, 591 586 unsigned long *state) 592 587 { 593 - if (true == clamping) 594 - *state = pkg_cstate_ratio_cur; 595 - else 588 + if (clamping) { 589 + if (poll_pkg_cstate_enable) 590 + *state = pkg_cstate_ratio_cur; 591 + else 592 + *state = set_target_ratio; 593 + } else { 596 594 /* to save power, do not poll idle ratio while not clamping */ 597 595 *state = -1; /* indicates invalid state */ 596 + } 598 597 599 598 return 0; 600 599 } ··· 720 711 retval = -ENOMEM; 721 712 goto exit_unregister; 722 713 } 714 + 715 + if (topology_max_packages() == 1 && topology_max_die_per_package() == 1) 716 + poll_pkg_cstate_enable = true; 723 717 724 718 cooling_dev = thermal_cooling_device_register("intel_powerclamp", NULL, 725 719 &powerclamp_cooling_ops);