aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGautham R. Shenoy <ego@linux.vnet.ibm.com>2017-12-13 01:57:41 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-01-05 07:11:24 -0500
commit967b87fd81d513de7aac247320f02b1645f9ca64 (patch)
tree1bb9f436927a8b6f6dd60aba889852fe32b24e52
parent332f0a01f0dd669dcd208e4e9666d80dffd62e7b (diff)
powernv-cpufreq: Treat pstates as opaque 8-bit values
On POWER8 and POWER9, the PMSR and the PMCR registers define pstates to be 8-bit wide values. The device-tree exports pstates as 32-bit wide values of which the lower byte is the actual pstate. The current implementation in the kernel treats pstates as integer type, since it used to use the sign of the pstate for performing some boundary-checks. This is no longer required after the patch "powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous pstates". So, in this patch, we modify the powernv-cpufreq driver to uniformly treat pstates as opaque 8-bit values obtained from the device-tree or the PMCR. This simplifies the extract_pstate() helper function since we no longer no longer require to worry about the sign-extentions. Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c47
1 files changed, 19 insertions, 28 deletions
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 8e3dbcaee286..8a4e2ce0804c 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -110,12 +110,11 @@ DEFINE_HASHTABLE(pstate_revmap, POWERNV_MAX_PSTATES_ORDER);
110 * hashtable 110 * hashtable
111 */ 111 */
112struct pstate_idx_revmap_data { 112struct pstate_idx_revmap_data {
113 int pstate_id; 113 u8 pstate_id;
114 unsigned int cpufreq_table_idx; 114 unsigned int cpufreq_table_idx;
115 struct hlist_node hentry; 115 struct hlist_node hentry;
116}; 116};
117 117
118u32 pstate_sign_prefix;
119static bool rebooting, throttled, occ_reset; 118static bool rebooting, throttled, occ_reset;
120 119
121static const char * const throttle_reason[] = { 120static const char * const throttle_reason[] = {
@@ -170,14 +169,9 @@ static struct powernv_pstate_info {
170 bool wof_enabled; 169 bool wof_enabled;
171} powernv_pstate_info; 170} powernv_pstate_info;
172 171
173static inline int extract_pstate(u64 pmsr_val, unsigned int shift) 172static inline u8 extract_pstate(u64 pmsr_val, unsigned int shift)
174{ 173{
175 int ret = ((pmsr_val >> shift) & 0xFF); 174 return ((pmsr_val >> shift) & 0xFF);
176
177 if (!ret)
178 return ret;
179
180 return (pstate_sign_prefix | ret);
181} 175}
182 176
183#define extract_local_pstate(x) extract_pstate(x, LPSTATE_SHIFT) 177#define extract_local_pstate(x) extract_pstate(x, LPSTATE_SHIFT)
@@ -194,7 +188,7 @@ static inline int extract_pstate(u64 pmsr_val, unsigned int shift)
194 * If @i is out of bound, this will return the pstate 188 * If @i is out of bound, this will return the pstate
195 * corresponding to the nominal frequency. 189 * corresponding to the nominal frequency.
196 */ 190 */
197static inline int idx_to_pstate(unsigned int i) 191static inline u8 idx_to_pstate(unsigned int i)
198{ 192{
199 if (unlikely(i >= powernv_pstate_info.nr_pstates)) { 193 if (unlikely(i >= powernv_pstate_info.nr_pstates)) {
200 pr_warn_once("idx_to_pstate: index %u is out of bound\n", i); 194 pr_warn_once("idx_to_pstate: index %u is out of bound\n", i);
@@ -213,7 +207,7 @@ static inline int idx_to_pstate(unsigned int i)
213 * this will return the index of the nominal 207 * this will return the index of the nominal
214 * frequency. 208 * frequency.
215 */ 209 */
216static unsigned int pstate_to_idx(int pstate) 210static unsigned int pstate_to_idx(u8 pstate)
217{ 211{
218 unsigned int key = pstate % POWERNV_MAX_PSTATES; 212 unsigned int key = pstate % POWERNV_MAX_PSTATES;
219 struct pstate_idx_revmap_data *revmap_data; 213 struct pstate_idx_revmap_data *revmap_data;
@@ -223,7 +217,7 @@ static unsigned int pstate_to_idx(int pstate)
223 return revmap_data->cpufreq_table_idx; 217 return revmap_data->cpufreq_table_idx;
224 } 218 }
225 219
226 pr_warn_once("pstate_to_idx: pstate %d not found\n", pstate); 220 pr_warn_once("pstate_to_idx: pstate 0x%x not found\n", pstate);
227 return powernv_pstate_info.nominal; 221 return powernv_pstate_info.nominal;
228} 222}
229 223
@@ -291,7 +285,7 @@ static int init_powernv_pstates(void)
291 powernv_pstate_info.wof_enabled = true; 285 powernv_pstate_info.wof_enabled = true;
292 286
293next: 287next:
294 pr_info("cpufreq pstate min %d nominal %d max %d\n", pstate_min, 288 pr_info("cpufreq pstate min 0x%x nominal 0x%x max 0x%x\n", pstate_min,
295 pstate_nominal, pstate_max); 289 pstate_nominal, pstate_max);
296 pr_info("Workload Optimized Frequency is %s in the platform\n", 290 pr_info("Workload Optimized Frequency is %s in the platform\n",
297 (powernv_pstate_info.wof_enabled) ? "enabled" : "disabled"); 291 (powernv_pstate_info.wof_enabled) ? "enabled" : "disabled");
@@ -323,8 +317,6 @@ next:
323 powernv_pstate_info.nr_pstates = nr_pstates; 317 powernv_pstate_info.nr_pstates = nr_pstates;
324 pr_debug("NR PStates %d\n", nr_pstates); 318 pr_debug("NR PStates %d\n", nr_pstates);
325 319
326 pstate_sign_prefix = pstate_min & ~0xFF;
327
328 for (i = 0; i < nr_pstates; i++) { 320 for (i = 0; i < nr_pstates; i++) {
329 u32 id = be32_to_cpu(pstate_ids[i]); 321 u32 id = be32_to_cpu(pstate_ids[i]);
330 u32 freq = be32_to_cpu(pstate_freqs[i]); 322 u32 freq = be32_to_cpu(pstate_freqs[i]);
@@ -333,14 +325,14 @@ next:
333 325
334 pr_debug("PState id %d freq %d MHz\n", id, freq); 326 pr_debug("PState id %d freq %d MHz\n", id, freq);
335 powernv_freqs[i].frequency = freq * 1000; /* kHz */ 327 powernv_freqs[i].frequency = freq * 1000; /* kHz */
336 powernv_freqs[i].driver_data = id; 328 powernv_freqs[i].driver_data = id & 0xFF;
337 329
338 revmap_data = (struct pstate_idx_revmap_data *) 330 revmap_data = (struct pstate_idx_revmap_data *)
339 kmalloc(sizeof(*revmap_data), GFP_KERNEL); 331 kmalloc(sizeof(*revmap_data), GFP_KERNEL);
340 332
341 revmap_data->pstate_id = id; 333 revmap_data->pstate_id = id & 0xFF;
342 revmap_data->cpufreq_table_idx = i; 334 revmap_data->cpufreq_table_idx = i;
343 key = id % POWERNV_MAX_PSTATES; 335 key = (revmap_data->pstate_id) % POWERNV_MAX_PSTATES;
344 hash_add(pstate_revmap, &revmap_data->hentry, key); 336 hash_add(pstate_revmap, &revmap_data->hentry, key);
345 337
346 if (id == pstate_max) 338 if (id == pstate_max)
@@ -364,14 +356,13 @@ next:
364} 356}
365 357
366/* Returns the CPU frequency corresponding to the pstate_id. */ 358/* Returns the CPU frequency corresponding to the pstate_id. */
367static unsigned int pstate_id_to_freq(int pstate_id) 359static unsigned int pstate_id_to_freq(u8 pstate_id)
368{ 360{
369 int i; 361 int i;
370 362
371 i = pstate_to_idx(pstate_id); 363 i = pstate_to_idx(pstate_id);
372 if (i >= powernv_pstate_info.nr_pstates || i < 0) { 364 if (i >= powernv_pstate_info.nr_pstates || i < 0) {
373 pr_warn("PState id %d outside of PState table, " 365 pr_warn("PState id 0x%x outside of PState table, reporting nominal id 0x%x instead\n",
374 "reporting nominal id %d instead\n",
375 pstate_id, idx_to_pstate(powernv_pstate_info.nominal)); 366 pstate_id, idx_to_pstate(powernv_pstate_info.nominal));
376 i = powernv_pstate_info.nominal; 367 i = powernv_pstate_info.nominal;
377 } 368 }
@@ -477,8 +468,8 @@ static inline void set_pmspr(unsigned long sprn, unsigned long val)
477 */ 468 */
478struct powernv_smp_call_data { 469struct powernv_smp_call_data {
479 unsigned int freq; 470 unsigned int freq;
480 int pstate_id; 471 u8 pstate_id;
481 int gpstate_id; 472 u8 gpstate_id;
482}; 473};
483 474
484/* 475/*
@@ -501,9 +492,9 @@ static void powernv_read_cpu_freq(void *arg)
501 freq_data->pstate_id = extract_local_pstate(pmspr_val); 492 freq_data->pstate_id = extract_local_pstate(pmspr_val);
502 freq_data->freq = pstate_id_to_freq(freq_data->pstate_id); 493 freq_data->freq = pstate_id_to_freq(freq_data->pstate_id);
503 494
504 pr_debug("cpu %d pmsr %016lX pstate_id %d frequency %d kHz\n", 495 pr_debug("cpu %d pmsr %016lX pstate_id 0x%x frequency %d kHz\n",
505 raw_smp_processor_id(), pmspr_val, freq_data->pstate_id, 496 raw_smp_processor_id(), pmspr_val, freq_data->pstate_id,
506 freq_data->freq); 497 freq_data->freq);
507} 498}
508 499
509/* 500/*
@@ -565,7 +556,7 @@ static void powernv_cpufreq_throttle_check(void *data)
565 struct chip *chip; 556 struct chip *chip;
566 unsigned int cpu = smp_processor_id(); 557 unsigned int cpu = smp_processor_id();
567 unsigned long pmsr; 558 unsigned long pmsr;
568 int pmsr_pmax; 559 u8 pmsr_pmax;
569 unsigned int pmsr_pmax_idx; 560 unsigned int pmsr_pmax_idx;
570 561
571 pmsr = get_pmspr(SPRN_PMSR); 562 pmsr = get_pmspr(SPRN_PMSR);
@@ -579,7 +570,7 @@ static void powernv_cpufreq_throttle_check(void *data)
579 goto next; 570 goto next;
580 chip->throttled = true; 571 chip->throttled = true;
581 if (pmsr_pmax_idx > powernv_pstate_info.nominal) { 572 if (pmsr_pmax_idx > powernv_pstate_info.nominal) {
582 pr_warn_once("CPU %d on Chip %u has Pmax(%d) reduced below nominal frequency(%d)\n", 573 pr_warn_once("CPU %d on Chip %u has Pmax(0x%x) reduced below that of nominal frequency(0x%x)\n",
583 cpu, chip->id, pmsr_pmax, 574 cpu, chip->id, pmsr_pmax,
584 idx_to_pstate(powernv_pstate_info.nominal)); 575 idx_to_pstate(powernv_pstate_info.nominal));
585 chip->throttle_sub_turbo++; 576 chip->throttle_sub_turbo++;