diff options
-rw-r--r-- | drivers/cpufreq/powernv-cpufreq.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 2dfd4fdb5a52..ebef0d8279c7 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -34,9 +34,13 @@ #include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */ #define POWERNV_MAX_PSTATES 256 +#define PMSR_PSAFE_ENABLE (1UL << 30) +#define PMSR_SPR_EM_DISABLE (1UL << 31) +#define PMSR_MAX(x) ((x >> 32) & 0xFF) +#define PMSR_LP(x) ((x >> 48) & 0xFF) static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; -static bool rebooting; +static bool rebooting, throttled; /* * Note: The set of pstates consists of contiguous integers, the @@ -294,6 +298,44 @@ static inline unsigned int get_nominal_index(void) return powernv_pstate_info.max - powernv_pstate_info.nominal; } +static void powernv_cpufreq_throttle_check(unsigned int cpu) +{ + unsigned long pmsr; + int pmsr_pmax, pmsr_lp; + + pmsr = get_pmspr(SPRN_PMSR); + + /* Check for Pmax Capping */ + pmsr_pmax = (s8)PMSR_MAX(pmsr); + if (pmsr_pmax != powernv_pstate_info.max) { + throttled = true; + pr_info("CPU %d Pmax is reduced to %d\n", cpu, pmsr_pmax); + pr_info("Max allowed Pstate is capped\n"); + } + + /* + * Check for Psafe by reading LocalPstate + * or check if Psafe_mode_active is set in PMSR. + */ + pmsr_lp = (s8)PMSR_LP(pmsr); + if ((pmsr_lp < powernv_pstate_info.min) || + (pmsr & PMSR_PSAFE_ENABLE)) { + throttled = true; + pr_info("Pstate set to safe frequency\n"); + } + + /* Check if SPR_EM_DISABLE is set in PMSR */ + if (pmsr & PMSR_SPR_EM_DISABLE) { + throttled = true; + pr_info("Frequency Control disabled from OS\n"); + } + + if (throttled) { + pr_info("PMSR = %16lx\n", pmsr); + pr_crit("CPU Frequency could be throttled\n"); + } +} + /* * powernv_cpufreq_target_index: Sets the frequency corresponding to * the cpufreq table entry indexed by new_index on the cpus in the @@ -307,6 +349,9 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, if (unlikely(rebooting) && new_index != get_nominal_index()) return 0; + if (!throttled) + powernv_cpufreq_throttle_check(smp_processor_id()); + freq_data.pstate_id = powernv_freqs[new_index].driver_data; /* |