Skip to content

Commit d0e936a

Browse files
spandruvadarafaeljw
authored andcommitted
cpufreq: intel_pstate: Process HWP Guaranteed change notification
It is possible that HWP guaranteed ratio is changed in response to change in power and thermal limits. For example when Intel Speed Select performance profile is changed or there is change in TDP, hardware can send notifications. It is possible that the guaranteed ratio is increased. This creates an issue when turbo is disabled, as the old limits set in MSR_HWP_REQUEST are still lower and hardware will clip to older limits. This change enables HWP interrupt and process HWP interrupts. When guaranteed is changed, calls cpufreq_update_policy() so that driver callbacks are called to update to new HWP limits. This callback is called from a delayed workqueue of 10ms to avoid frequent updates. Signed-off-by: Srinivas Pandruvada <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 950809c commit d0e936a

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

drivers/cpufreq/intel_pstate.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <asm/cpu_device_id.h>
3333
#include <asm/cpufeature.h>
3434
#include <asm/intel-family.h>
35+
#include "../drivers/thermal/intel/thermal_interrupt.h"
3536

3637
#define INTEL_PSTATE_SAMPLING_INTERVAL (10 * NSEC_PER_MSEC)
3738

@@ -219,6 +220,7 @@ struct global_params {
219220
* @sched_flags: Store scheduler flags for possible cross CPU update
220221
* @hwp_boost_min: Last HWP boosted min performance
221222
* @suspended: Whether or not the driver has been suspended.
223+
* @hwp_notify_work: workqueue for HWP notifications.
222224
*
223225
* This structure stores per CPU instance data for all CPUs.
224226
*/
@@ -257,6 +259,7 @@ struct cpudata {
257259
unsigned int sched_flags;
258260
u32 hwp_boost_min;
259261
bool suspended;
262+
struct delayed_work hwp_notify_work;
260263
};
261264

262265
static struct cpudata **all_cpu_data;
@@ -1625,6 +1628,40 @@ static void intel_pstate_sysfs_hide_hwp_dynamic_boost(void)
16251628

16261629
/************************** sysfs end ************************/
16271630

1631+
static void intel_pstate_notify_work(struct work_struct *work)
1632+
{
1633+
mutex_lock(&intel_pstate_driver_lock);
1634+
cpufreq_update_policy(smp_processor_id());
1635+
wrmsrl(MSR_HWP_STATUS, 0);
1636+
mutex_unlock(&intel_pstate_driver_lock);
1637+
}
1638+
1639+
void notify_hwp_interrupt(void)
1640+
{
1641+
unsigned int this_cpu = smp_processor_id();
1642+
struct cpudata *cpudata;
1643+
u64 value;
1644+
1645+
if (!hwp_active || !boot_cpu_has(X86_FEATURE_HWP_NOTIFY))
1646+
return;
1647+
1648+
rdmsrl(MSR_HWP_STATUS, value);
1649+
if (!(value & 0x01))
1650+
return;
1651+
1652+
cpudata = all_cpu_data[this_cpu];
1653+
schedule_delayed_work_on(this_cpu, &cpudata->hwp_notify_work, msecs_to_jiffies(10));
1654+
}
1655+
1656+
static void intel_pstate_enable_hwp_interrupt(struct cpudata *cpudata)
1657+
{
1658+
/* Enable HWP notification interrupt for guaranteed performance change */
1659+
if (boot_cpu_has(X86_FEATURE_HWP_NOTIFY)) {
1660+
INIT_DELAYED_WORK(&cpudata->hwp_notify_work, intel_pstate_notify_work);
1661+
wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x01);
1662+
}
1663+
}
1664+
16281665
static void intel_pstate_hwp_enable(struct cpudata *cpudata)
16291666
{
16301667
/* First disable HWP notification interrupt as we don't process them */
@@ -1634,6 +1671,8 @@ static void intel_pstate_hwp_enable(struct cpudata *cpudata)
16341671
wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
16351672
if (cpudata->epp_default == -EINVAL)
16361673
cpudata->epp_default = intel_pstate_get_epp(cpudata, 0);
1674+
1675+
intel_pstate_enable_hwp_interrupt(cpudata);
16371676
}
16381677

16391678
static int atom_get_min_pstate(void)

0 commit comments

Comments
 (0)