diff options
-rw-r--r-- | drivers/cpufreq/powernv-cpufreq.c | 177 |
1 files changed, 102 insertions, 75 deletions
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 2a2920c4fdf9..0f138b050e9a 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c | |||
@@ -64,12 +64,14 @@ | |||
64 | /** | 64 | /** |
65 | * struct global_pstate_info - Per policy data structure to maintain history of | 65 | * struct global_pstate_info - Per policy data structure to maintain history of |
66 | * global pstates | 66 | * global pstates |
67 | * @highest_lpstate: The local pstate from which we are ramping down | 67 | * @highest_lpstate_idx: The local pstate index from which we are |
68 | * ramping down | ||
68 | * @elapsed_time: Time in ms spent in ramping down from | 69 | * @elapsed_time: Time in ms spent in ramping down from |
69 | * highest_lpstate | 70 | * highest_lpstate_idx |
70 | * @last_sampled_time: Time from boot in ms when global pstates were | 71 | * @last_sampled_time: Time from boot in ms when global pstates were |
71 | * last set | 72 | * last set |
72 | * @last_lpstate,last_gpstate: Last set values for local and global pstates | 73 | * @last_lpstate_idx, Last set value of local pstate and global |
74 | * last_gpstate_idx pstate in terms of cpufreq table index | ||
73 | * @timer: Is used for ramping down if cpu goes idle for | 75 | * @timer: Is used for ramping down if cpu goes idle for |
74 | * a long time with global pstate held high | 76 | * a long time with global pstate held high |
75 | * @gpstate_lock: A spinlock to maintain synchronization between | 77 | * @gpstate_lock: A spinlock to maintain synchronization between |
@@ -77,11 +79,11 @@ | |||
77 | * governer's target_index calls | 79 | * governer's target_index calls |
78 | */ | 80 | */ |
79 | struct global_pstate_info { | 81 | struct global_pstate_info { |
80 | int highest_lpstate; | 82 | int highest_lpstate_idx; |
81 | unsigned int elapsed_time; | 83 | unsigned int elapsed_time; |
82 | unsigned int last_sampled_time; | 84 | unsigned int last_sampled_time; |
83 | int last_lpstate; | 85 | int last_lpstate_idx; |
84 | int last_gpstate; | 86 | int last_gpstate_idx; |
85 | spinlock_t gpstate_lock; | 87 | spinlock_t gpstate_lock; |
86 | struct timer_list timer; | 88 | struct timer_list timer; |
87 | }; | 89 | }; |
@@ -124,29 +126,47 @@ static int nr_chips; | |||
124 | static DEFINE_PER_CPU(struct chip *, chip_info); | 126 | static DEFINE_PER_CPU(struct chip *, chip_info); |
125 | 127 | ||
126 | /* | 128 | /* |
127 | * Note: The set of pstates consists of contiguous integers, the | 129 | * Note: |
128 | * smallest of which is indicated by powernv_pstate_info.min, the | 130 | * The set of pstates consists of contiguous integers. |
129 | * largest of which is indicated by powernv_pstate_info.max. | 131 | * powernv_pstate_info stores the index of the frequency table for |
132 | * max, min and nominal frequencies. It also stores number of | ||
133 | * available frequencies. | ||
130 | * | 134 | * |
131 | * The nominal pstate is the highest non-turbo pstate in this | 135 | * powernv_pstate_info.nominal indicates the index to the highest |
132 | * platform. This is indicated by powernv_pstate_info.nominal. | 136 | * non-turbo frequency. |
133 | */ | 137 | */ |
134 | static struct powernv_pstate_info { | 138 | static struct powernv_pstate_info { |
135 | int min; | 139 | unsigned int min; |
136 | int max; | 140 | unsigned int max; |
137 | int nominal; | 141 | unsigned int nominal; |
138 | int nr_pstates; | 142 | unsigned int nr_pstates; |
139 | } powernv_pstate_info; | 143 | } powernv_pstate_info; |
140 | 144 | ||
145 | /* Use following macros for conversions between pstate_id and index */ | ||
146 | static inline int idx_to_pstate(unsigned int i) | ||
147 | { | ||
148 | return powernv_freqs[i].driver_data; | ||
149 | } | ||
150 | |||
151 | static inline unsigned int pstate_to_idx(int pstate) | ||
152 | { | ||
153 | /* | ||
154 | * abs() is deliberately used so that is works with | ||
155 | * both monotonically increasing and decreasing | ||
156 | * pstate values | ||
157 | */ | ||
158 | return abs(pstate - idx_to_pstate(powernv_pstate_info.max)); | ||
159 | } | ||
160 | |||
141 | static inline void reset_gpstates(struct cpufreq_policy *policy) | 161 | static inline void reset_gpstates(struct cpufreq_policy *policy) |
142 | { | 162 | { |
143 | struct global_pstate_info *gpstates = policy->driver_data; | 163 | struct global_pstate_info *gpstates = policy->driver_data; |
144 | 164 | ||
145 | gpstates->highest_lpstate = 0; | 165 | gpstates->highest_lpstate_idx = 0; |
146 | gpstates->elapsed_time = 0; | 166 | gpstates->elapsed_time = 0; |
147 | gpstates->last_sampled_time = 0; | 167 | gpstates->last_sampled_time = 0; |
148 | gpstates->last_lpstate = 0; | 168 | gpstates->last_lpstate_idx = 0; |
149 | gpstates->last_gpstate = 0; | 169 | gpstates->last_gpstate_idx = 0; |
150 | } | 170 | } |
151 | 171 | ||
152 | /* | 172 | /* |
@@ -156,9 +176,10 @@ static inline void reset_gpstates(struct cpufreq_policy *policy) | |||
156 | static int init_powernv_pstates(void) | 176 | static int init_powernv_pstates(void) |
157 | { | 177 | { |
158 | struct device_node *power_mgt; | 178 | struct device_node *power_mgt; |
159 | int i, pstate_min, pstate_max, pstate_nominal, nr_pstates = 0; | 179 | int i, nr_pstates = 0; |
160 | const __be32 *pstate_ids, *pstate_freqs; | 180 | const __be32 *pstate_ids, *pstate_freqs; |
161 | u32 len_ids, len_freqs; | 181 | u32 len_ids, len_freqs; |
182 | u32 pstate_min, pstate_max, pstate_nominal; | ||
162 | 183 | ||
163 | power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); | 184 | power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); |
164 | if (!power_mgt) { | 185 | if (!power_mgt) { |
@@ -208,6 +229,7 @@ static int init_powernv_pstates(void) | |||
208 | return -ENODEV; | 229 | return -ENODEV; |
209 | } | 230 | } |
210 | 231 | ||
232 | powernv_pstate_info.nr_pstates = nr_pstates; | ||
211 | pr_debug("NR PStates %d\n", nr_pstates); | 233 | pr_debug("NR PStates %d\n", nr_pstates); |
212 | for (i = 0; i < nr_pstates; i++) { | 234 | for (i = 0; i < nr_pstates; i++) { |
213 | u32 id = be32_to_cpu(pstate_ids[i]); | 235 | u32 id = be32_to_cpu(pstate_ids[i]); |
@@ -216,15 +238,17 @@ static int init_powernv_pstates(void) | |||
216 | pr_debug("PState id %d freq %d MHz\n", id, freq); | 238 | pr_debug("PState id %d freq %d MHz\n", id, freq); |
217 | powernv_freqs[i].frequency = freq * 1000; /* kHz */ | 239 | powernv_freqs[i].frequency = freq * 1000; /* kHz */ |
218 | powernv_freqs[i].driver_data = id; | 240 | powernv_freqs[i].driver_data = id; |
241 | |||
242 | if (id == pstate_max) | ||
243 | powernv_pstate_info.max = i; | ||
244 | else if (id == pstate_nominal) | ||
245 | powernv_pstate_info.nominal = i; | ||
246 | else if (id == pstate_min) | ||
247 | powernv_pstate_info.min = i; | ||
219 | } | 248 | } |
249 | |||
220 | /* End of list marker entry */ | 250 | /* End of list marker entry */ |
221 | powernv_freqs[i].frequency = CPUFREQ_TABLE_END; | 251 | powernv_freqs[i].frequency = CPUFREQ_TABLE_END; |
222 | |||
223 | powernv_pstate_info.min = pstate_min; | ||
224 | powernv_pstate_info.max = pstate_max; | ||
225 | powernv_pstate_info.nominal = pstate_nominal; | ||
226 | powernv_pstate_info.nr_pstates = nr_pstates; | ||
227 | |||
228 | return 0; | 252 | return 0; |
229 | } | 253 | } |
230 | 254 | ||
@@ -233,12 +257,12 @@ static unsigned int pstate_id_to_freq(int pstate_id) | |||
233 | { | 257 | { |
234 | int i; | 258 | int i; |
235 | 259 | ||
236 | i = powernv_pstate_info.max - pstate_id; | 260 | i = pstate_to_idx(pstate_id); |
237 | if (i >= powernv_pstate_info.nr_pstates || i < 0) { | 261 | if (i >= powernv_pstate_info.nr_pstates || i < 0) { |
238 | pr_warn("PState id %d outside of PState table, " | 262 | pr_warn("PState id %d outside of PState table, " |
239 | "reporting nominal id %d instead\n", | 263 | "reporting nominal id %d instead\n", |
240 | pstate_id, powernv_pstate_info.nominal); | 264 | pstate_id, idx_to_pstate(powernv_pstate_info.nominal)); |
241 | i = powernv_pstate_info.max - powernv_pstate_info.nominal; | 265 | i = powernv_pstate_info.nominal; |
242 | } | 266 | } |
243 | 267 | ||
244 | return powernv_freqs[i].frequency; | 268 | return powernv_freqs[i].frequency; |
@@ -252,7 +276,7 @@ static ssize_t cpuinfo_nominal_freq_show(struct cpufreq_policy *policy, | |||
252 | char *buf) | 276 | char *buf) |
253 | { | 277 | { |
254 | return sprintf(buf, "%u\n", | 278 | return sprintf(buf, "%u\n", |
255 | pstate_id_to_freq(powernv_pstate_info.nominal)); | 279 | powernv_freqs[powernv_pstate_info.nominal].frequency); |
256 | } | 280 | } |
257 | 281 | ||
258 | struct freq_attr cpufreq_freq_attr_cpuinfo_nominal_freq = | 282 | struct freq_attr cpufreq_freq_attr_cpuinfo_nominal_freq = |
@@ -426,7 +450,7 @@ static void set_pstate(void *data) | |||
426 | */ | 450 | */ |
427 | static inline unsigned int get_nominal_index(void) | 451 | static inline unsigned int get_nominal_index(void) |
428 | { | 452 | { |
429 | return powernv_pstate_info.max - powernv_pstate_info.nominal; | 453 | return powernv_pstate_info.nominal; |
430 | } | 454 | } |
431 | 455 | ||
432 | static void powernv_cpufreq_throttle_check(void *data) | 456 | static void powernv_cpufreq_throttle_check(void *data) |
@@ -435,20 +459,22 @@ static void powernv_cpufreq_throttle_check(void *data) | |||
435 | unsigned int cpu = smp_processor_id(); | 459 | unsigned int cpu = smp_processor_id(); |
436 | unsigned long pmsr; | 460 | unsigned long pmsr; |
437 | int pmsr_pmax; | 461 | int pmsr_pmax; |
462 | unsigned int pmsr_pmax_idx; | ||
438 | 463 | ||
439 | pmsr = get_pmspr(SPRN_PMSR); | 464 | pmsr = get_pmspr(SPRN_PMSR); |
440 | chip = this_cpu_read(chip_info); | 465 | chip = this_cpu_read(chip_info); |
441 | 466 | ||
442 | /* Check for Pmax Capping */ | 467 | /* Check for Pmax Capping */ |
443 | pmsr_pmax = (s8)PMSR_MAX(pmsr); | 468 | pmsr_pmax = (s8)PMSR_MAX(pmsr); |
444 | if (pmsr_pmax != powernv_pstate_info.max) { | 469 | pmsr_pmax_idx = pstate_to_idx(pmsr_pmax); |
470 | if (pmsr_pmax_idx != powernv_pstate_info.max) { | ||
445 | if (chip->throttled) | 471 | if (chip->throttled) |
446 | goto next; | 472 | goto next; |
447 | chip->throttled = true; | 473 | chip->throttled = true; |
448 | if (pmsr_pmax < powernv_pstate_info.nominal) { | 474 | if (pmsr_pmax_idx > powernv_pstate_info.nominal) { |
449 | pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", | 475 | pr_warn_once("CPU %d on Chip %u has Pmax(%d) reduced below nominal frequency(%d)\n", |
450 | cpu, chip->id, pmsr_pmax, | 476 | cpu, chip->id, pmsr_pmax, |
451 | powernv_pstate_info.nominal); | 477 | idx_to_pstate(powernv_pstate_info.nominal)); |
452 | chip->throttle_sub_turbo++; | 478 | chip->throttle_sub_turbo++; |
453 | } else { | 479 | } else { |
454 | chip->throttle_turbo++; | 480 | chip->throttle_turbo++; |
@@ -484,34 +510,35 @@ next: | |||
484 | 510 | ||
485 | /** | 511 | /** |
486 | * calc_global_pstate - Calculate global pstate | 512 | * calc_global_pstate - Calculate global pstate |
487 | * @elapsed_time: Elapsed time in milliseconds | 513 | * @elapsed_time: Elapsed time in milliseconds |
488 | * @local_pstate: New local pstate | 514 | * @local_pstate_idx: New local pstate |
489 | * @highest_lpstate: pstate from which its ramping down | 515 | * @highest_lpstate_idx: pstate from which its ramping down |
490 | * | 516 | * |
491 | * Finds the appropriate global pstate based on the pstate from which its | 517 | * Finds the appropriate global pstate based on the pstate from which its |
492 | * ramping down and the time elapsed in ramping down. It follows a quadratic | 518 | * ramping down and the time elapsed in ramping down. It follows a quadratic |
493 | * equation which ensures that it reaches ramping down to pmin in 5sec. | 519 | * equation which ensures that it reaches ramping down to pmin in 5sec. |
494 | */ | 520 | */ |
495 | static inline int calc_global_pstate(unsigned int elapsed_time, | 521 | static inline int calc_global_pstate(unsigned int elapsed_time, |
496 | int highest_lpstate, int local_pstate) | 522 | int highest_lpstate_idx, |
523 | int local_pstate_idx) | ||
497 | { | 524 | { |
498 | int pstate_diff; | 525 | int index_diff; |
499 | 526 | ||
500 | /* | 527 | /* |
501 | * Using ramp_down_percent we get the percentage of rampdown | 528 | * Using ramp_down_percent we get the percentage of rampdown |
502 | * that we are expecting to be dropping. Difference between | 529 | * that we are expecting to be dropping. Difference between |
503 | * highest_lpstate and powernv_pstate_info.min will give a absolute | 530 | * highest_lpstate_idx and powernv_pstate_info.min will give a absolute |
504 | * number of how many pstates we will drop eventually by the end of | 531 | * number of how many pstates we will drop eventually by the end of |
505 | * 5 seconds, then just scale it get the number pstates to be dropped. | 532 | * 5 seconds, then just scale it get the number pstates to be dropped. |
506 | */ | 533 | */ |
507 | pstate_diff = ((int)ramp_down_percent(elapsed_time) * | 534 | index_diff = ((int)ramp_down_percent(elapsed_time) * |
508 | (highest_lpstate - powernv_pstate_info.min)) / 100; | 535 | (powernv_pstate_info.min - highest_lpstate_idx)) / 100; |
509 | 536 | ||
510 | /* Ensure that global pstate is >= to local pstate */ | 537 | /* Ensure that global pstate is >= to local pstate */ |
511 | if (highest_lpstate - pstate_diff < local_pstate) | 538 | if (highest_lpstate_idx + index_diff >= local_pstate_idx) |
512 | return local_pstate; | 539 | return local_pstate_idx; |
513 | else | 540 | else |
514 | return highest_lpstate - pstate_diff; | 541 | return highest_lpstate_idx + index_diff; |
515 | } | 542 | } |
516 | 543 | ||
517 | static inline void queue_gpstate_timer(struct global_pstate_info *gpstates) | 544 | static inline void queue_gpstate_timer(struct global_pstate_info *gpstates) |
@@ -547,7 +574,7 @@ void gpstate_timer_handler(unsigned long data) | |||
547 | { | 574 | { |
548 | struct cpufreq_policy *policy = (struct cpufreq_policy *)data; | 575 | struct cpufreq_policy *policy = (struct cpufreq_policy *)data; |
549 | struct global_pstate_info *gpstates = policy->driver_data; | 576 | struct global_pstate_info *gpstates = policy->driver_data; |
550 | int gpstate_id; | 577 | int gpstate_idx; |
551 | unsigned int time_diff = jiffies_to_msecs(jiffies) | 578 | unsigned int time_diff = jiffies_to_msecs(jiffies) |
552 | - gpstates->last_sampled_time; | 579 | - gpstates->last_sampled_time; |
553 | struct powernv_smp_call_data freq_data; | 580 | struct powernv_smp_call_data freq_data; |
@@ -557,29 +584,29 @@ void gpstate_timer_handler(unsigned long data) | |||
557 | 584 | ||
558 | gpstates->last_sampled_time += time_diff; | 585 | gpstates->last_sampled_time += time_diff; |
559 | gpstates->elapsed_time += time_diff; | 586 | gpstates->elapsed_time += time_diff; |
560 | freq_data.pstate_id = gpstates->last_lpstate; | 587 | freq_data.pstate_id = idx_to_pstate(gpstates->last_lpstate_idx); |
561 | 588 | ||
562 | if ((gpstates->last_gpstate == freq_data.pstate_id) || | 589 | if ((gpstates->last_gpstate_idx == gpstates->last_lpstate_idx) || |
563 | (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) { | 590 | (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) { |
564 | gpstate_id = freq_data.pstate_id; | 591 | gpstate_idx = pstate_to_idx(freq_data.pstate_id); |
565 | reset_gpstates(policy); | 592 | reset_gpstates(policy); |
566 | gpstates->highest_lpstate = freq_data.pstate_id; | 593 | gpstates->highest_lpstate_idx = gpstate_idx; |
567 | } else { | 594 | } else { |
568 | gpstate_id = calc_global_pstate(gpstates->elapsed_time, | 595 | gpstate_idx = calc_global_pstate(gpstates->elapsed_time, |
569 | gpstates->highest_lpstate, | 596 | gpstates->highest_lpstate_idx, |
570 | freq_data.pstate_id); | 597 | freq_data.pstate_id); |
571 | } | 598 | } |
572 | 599 | ||
573 | /* | 600 | /* |
574 | * If local pstate is equal to global pstate, rampdown is over | 601 | * If local pstate is equal to global pstate, rampdown is over |
575 | * So timer is not required to be queued. | 602 | * So timer is not required to be queued. |
576 | */ | 603 | */ |
577 | if (gpstate_id != freq_data.pstate_id) | 604 | if (gpstate_idx != gpstates->last_lpstate_idx) |
578 | queue_gpstate_timer(gpstates); | 605 | queue_gpstate_timer(gpstates); |
579 | 606 | ||
580 | freq_data.gpstate_id = gpstate_id; | 607 | freq_data.gpstate_id = idx_to_pstate(gpstate_idx); |
581 | gpstates->last_gpstate = freq_data.gpstate_id; | 608 | gpstates->last_gpstate_idx = pstate_to_idx(freq_data.gpstate_id); |
582 | gpstates->last_lpstate = freq_data.pstate_id; | 609 | gpstates->last_lpstate_idx = pstate_to_idx(freq_data.pstate_id); |
583 | 610 | ||
584 | spin_unlock(&gpstates->gpstate_lock); | 611 | spin_unlock(&gpstates->gpstate_lock); |
585 | 612 | ||
@@ -596,7 +623,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, | |||
596 | unsigned int new_index) | 623 | unsigned int new_index) |
597 | { | 624 | { |
598 | struct powernv_smp_call_data freq_data; | 625 | struct powernv_smp_call_data freq_data; |
599 | unsigned int cur_msec, gpstate_id; | 626 | unsigned int cur_msec, gpstate_idx; |
600 | struct global_pstate_info *gpstates = policy->driver_data; | 627 | struct global_pstate_info *gpstates = policy->driver_data; |
601 | 628 | ||
602 | if (unlikely(rebooting) && new_index != get_nominal_index()) | 629 | if (unlikely(rebooting) && new_index != get_nominal_index()) |
@@ -608,15 +635,15 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, | |||
608 | cur_msec = jiffies_to_msecs(get_jiffies_64()); | 635 | cur_msec = jiffies_to_msecs(get_jiffies_64()); |
609 | 636 | ||
610 | spin_lock(&gpstates->gpstate_lock); | 637 | spin_lock(&gpstates->gpstate_lock); |
611 | freq_data.pstate_id = powernv_freqs[new_index].driver_data; | 638 | freq_data.pstate_id = idx_to_pstate(new_index); |
612 | 639 | ||
613 | if (!gpstates->last_sampled_time) { | 640 | if (!gpstates->last_sampled_time) { |
614 | gpstate_id = freq_data.pstate_id; | 641 | gpstate_idx = new_index; |
615 | gpstates->highest_lpstate = freq_data.pstate_id; | 642 | gpstates->highest_lpstate_idx = new_index; |
616 | goto gpstates_done; | 643 | goto gpstates_done; |
617 | } | 644 | } |
618 | 645 | ||
619 | if (gpstates->last_gpstate > freq_data.pstate_id) { | 646 | if (gpstates->last_gpstate_idx < new_index) { |
620 | gpstates->elapsed_time += cur_msec - | 647 | gpstates->elapsed_time += cur_msec - |
621 | gpstates->last_sampled_time; | 648 | gpstates->last_sampled_time; |
622 | 649 | ||
@@ -627,34 +654,34 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, | |||
627 | */ | 654 | */ |
628 | if (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME) { | 655 | if (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME) { |
629 | reset_gpstates(policy); | 656 | reset_gpstates(policy); |
630 | gpstates->highest_lpstate = freq_data.pstate_id; | 657 | gpstates->highest_lpstate_idx = new_index; |
631 | gpstate_id = freq_data.pstate_id; | 658 | gpstate_idx = new_index; |
632 | } else { | 659 | } else { |
633 | /* Elaspsed_time is less than 5 seconds, continue to rampdown */ | 660 | /* Elaspsed_time is less than 5 seconds, continue to rampdown */ |
634 | gpstate_id = calc_global_pstate(gpstates->elapsed_time, | 661 | gpstate_idx = calc_global_pstate(gpstates->elapsed_time, |
635 | gpstates->highest_lpstate, | 662 | gpstates->highest_lpstate_idx, |
636 | freq_data.pstate_id); | 663 | new_index); |
637 | } | 664 | } |
638 | } else { | 665 | } else { |
639 | reset_gpstates(policy); | 666 | reset_gpstates(policy); |
640 | gpstates->highest_lpstate = freq_data.pstate_id; | 667 | gpstates->highest_lpstate_idx = new_index; |
641 | gpstate_id = freq_data.pstate_id; | 668 | gpstate_idx = new_index; |
642 | } | 669 | } |
643 | 670 | ||
644 | /* | 671 | /* |
645 | * If local pstate is equal to global pstate, rampdown is over | 672 | * If local pstate is equal to global pstate, rampdown is over |
646 | * So timer is not required to be queued. | 673 | * So timer is not required to be queued. |
647 | */ | 674 | */ |
648 | if (gpstate_id != freq_data.pstate_id) | 675 | if (gpstate_idx != new_index) |
649 | queue_gpstate_timer(gpstates); | 676 | queue_gpstate_timer(gpstates); |
650 | else | 677 | else |
651 | del_timer_sync(&gpstates->timer); | 678 | del_timer_sync(&gpstates->timer); |
652 | 679 | ||
653 | gpstates_done: | 680 | gpstates_done: |
654 | freq_data.gpstate_id = gpstate_id; | 681 | freq_data.gpstate_id = idx_to_pstate(gpstate_idx); |
655 | gpstates->last_sampled_time = cur_msec; | 682 | gpstates->last_sampled_time = cur_msec; |
656 | gpstates->last_gpstate = freq_data.gpstate_id; | 683 | gpstates->last_gpstate_idx = gpstate_idx; |
657 | gpstates->last_lpstate = freq_data.pstate_id; | 684 | gpstates->last_lpstate_idx = new_index; |
658 | 685 | ||
659 | spin_unlock(&gpstates->gpstate_lock); | 686 | spin_unlock(&gpstates->gpstate_lock); |
660 | 687 | ||
@@ -846,8 +873,8 @@ static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy) | |||
846 | struct powernv_smp_call_data freq_data; | 873 | struct powernv_smp_call_data freq_data; |
847 | struct global_pstate_info *gpstates = policy->driver_data; | 874 | struct global_pstate_info *gpstates = policy->driver_data; |
848 | 875 | ||
849 | freq_data.pstate_id = powernv_pstate_info.min; | 876 | freq_data.pstate_id = idx_to_pstate(powernv_pstate_info.min); |
850 | freq_data.gpstate_id = powernv_pstate_info.min; | 877 | freq_data.gpstate_id = idx_to_pstate(powernv_pstate_info.min); |
851 | smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1); | 878 | smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1); |
852 | del_timer_sync(&gpstates->timer); | 879 | del_timer_sync(&gpstates->timer); |
853 | } | 880 | } |