|
@@ -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;
|
|
|
|
|
|
/*
|