64
64
/**
65
65
* struct global_pstate_info - Per policy data structure to maintain history of
66
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
69
* @elapsed_time: Time in ms spent in ramping down from
69
- * highest_lpstate
70
+ * highest_lpstate_idx
70
71
* @last_sampled_time: Time from boot in ms when global pstates were
71
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
75
* @timer: Is used for ramping down if cpu goes idle for
74
76
* a long time with global pstate held high
75
77
* @gpstate_lock: A spinlock to maintain synchronization between
76
78
* routines called by the timer handler and
77
79
* governer's target_index calls
78
80
*/
79
81
struct global_pstate_info {
80
- int highest_lpstate ;
82
+ int highest_lpstate_idx ;
81
83
unsigned int elapsed_time ;
82
84
unsigned int last_sampled_time ;
83
- int last_lpstate ;
84
- int last_gpstate ;
85
+ int last_lpstate_idx ;
86
+ int last_gpstate_idx ;
85
87
spinlock_t gpstate_lock ;
86
88
struct timer_list timer ;
87
89
};
@@ -124,29 +126,47 @@ static int nr_chips;
124
126
static DEFINE_PER_CPU (struct chip * , chip_info ) ;
125
127
126
128
/*
127
- * Note: The set of pstates consists of contiguous integers, the
128
- * smallest of which is indicated by powernv_pstate_info.min, the
129
- * largest of which is indicated by powernv_pstate_info.max.
129
+ * Note:
130
+ * The set of pstates consists of contiguous integers.
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
132
- * platform. This is indicated by powernv_pstate_info.nominal .
135
+ * powernv_pstate_info. nominal indicates the index to the highest
136
+ * non-turbo frequency .
133
137
*/
134
138
static struct powernv_pstate_info {
135
- int min ;
136
- int max ;
137
- int nominal ;
138
- int nr_pstates ;
139
+ unsigned int min ;
140
+ unsigned int max ;
141
+ unsigned int nominal ;
142
+ unsigned int nr_pstates ;
139
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
161
static inline void reset_gpstates (struct cpufreq_policy * policy )
142
162
{
143
163
struct global_pstate_info * gpstates = policy -> driver_data ;
144
164
145
- gpstates -> highest_lpstate = 0 ;
165
+ gpstates -> highest_lpstate_idx = 0 ;
146
166
gpstates -> elapsed_time = 0 ;
147
167
gpstates -> last_sampled_time = 0 ;
148
- gpstates -> last_lpstate = 0 ;
149
- gpstates -> last_gpstate = 0 ;
168
+ gpstates -> last_lpstate_idx = 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
176
static int init_powernv_pstates (void )
157
177
{
158
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
180
const __be32 * pstate_ids , * pstate_freqs ;
161
181
u32 len_ids , len_freqs ;
182
+ u32 pstate_min , pstate_max , pstate_nominal ;
162
183
163
184
power_mgt = of_find_node_by_path ("/ibm,opal/power-mgt" );
164
185
if (!power_mgt ) {
@@ -208,6 +229,7 @@ static int init_powernv_pstates(void)
208
229
return - ENODEV ;
209
230
}
210
231
232
+ powernv_pstate_info .nr_pstates = nr_pstates ;
211
233
pr_debug ("NR PStates %d\n" , nr_pstates );
212
234
for (i = 0 ; i < nr_pstates ; i ++ ) {
213
235
u32 id = be32_to_cpu (pstate_ids [i ]);
@@ -216,15 +238,17 @@ static int init_powernv_pstates(void)
216
238
pr_debug ("PState id %d freq %d MHz\n" , id , freq );
217
239
powernv_freqs [i ].frequency = freq * 1000 ; /* kHz */
218
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
250
/* End of list marker entry */
221
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
252
return 0 ;
229
253
}
230
254
@@ -233,12 +257,12 @@ static unsigned int pstate_id_to_freq(int pstate_id)
233
257
{
234
258
int i ;
235
259
236
- i = powernv_pstate_info . max - pstate_id ;
260
+ i = pstate_to_idx ( pstate_id ) ;
237
261
if (i >= powernv_pstate_info .nr_pstates || i < 0 ) {
238
262
pr_warn ("PState id %d outside of PState table, "
239
263
"reporting nominal id %d instead\n" ,
240
- pstate_id , powernv_pstate_info .nominal );
241
- i = powernv_pstate_info .max - powernv_pstate_info . nominal ;
264
+ pstate_id , idx_to_pstate ( powernv_pstate_info .nominal ) );
265
+ i = powernv_pstate_info .nominal ;
242
266
}
243
267
244
268
return powernv_freqs [i ].frequency ;
@@ -252,7 +276,7 @@ static ssize_t cpuinfo_nominal_freq_show(struct cpufreq_policy *policy,
252
276
char * buf )
253
277
{
254
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
282
struct freq_attr cpufreq_freq_attr_cpuinfo_nominal_freq =
@@ -426,7 +450,7 @@ static void set_pstate(void *data)
426
450
*/
427
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
456
static void powernv_cpufreq_throttle_check (void * data )
@@ -435,20 +459,22 @@ static void powernv_cpufreq_throttle_check(void *data)
435
459
unsigned int cpu = smp_processor_id ();
436
460
unsigned long pmsr ;
437
461
int pmsr_pmax ;
462
+ unsigned int pmsr_pmax_idx ;
438
463
439
464
pmsr = get_pmspr (SPRN_PMSR );
440
465
chip = this_cpu_read (chip_info );
441
466
442
467
/* Check for Pmax Capping */
443
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
471
if (chip -> throttled )
446
472
goto next ;
447
473
chip -> throttled = true;
448
- if (pmsr_pmax < powernv_pstate_info .nominal ) {
449
- pr_warn_once ("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n" ,
474
+ if (pmsr_pmax_idx > powernv_pstate_info .nominal ) {
475
+ pr_warn_once ("CPU %d on Chip %u has Pmax(%d) reduced below nominal frequency( %d)\n" ,
450
476
cpu , chip -> id , pmsr_pmax ,
451
- powernv_pstate_info .nominal );
477
+ idx_to_pstate ( powernv_pstate_info .nominal ) );
452
478
chip -> throttle_sub_turbo ++ ;
453
479
} else {
454
480
chip -> throttle_turbo ++ ;
@@ -484,34 +510,35 @@ static void powernv_cpufreq_throttle_check(void *data)
484
510
485
511
/**
486
512
* calc_global_pstate - Calculate global pstate
487
- * @elapsed_time: Elapsed time in milliseconds
488
- * @local_pstate: New local pstate
489
- * @highest_lpstate : pstate from which its ramping down
513
+ * @elapsed_time: Elapsed time in milliseconds
514
+ * @local_pstate_idx: New local pstate
515
+ * @highest_lpstate_idx : pstate from which its ramping down
490
516
*
491
517
* Finds the appropriate global pstate based on the pstate from which its
492
518
* ramping down and the time elapsed in ramping down. It follows a quadratic
493
519
* equation which ensures that it reaches ramping down to pmin in 5sec.
494
520
*/
495
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
528
* Using ramp_down_percent we get the percentage of rampdown
502
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
531
* number of how many pstates we will drop eventually by the end of
505
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 ) *
508
- (highest_lpstate - powernv_pstate_info .min )) / 100 ;
534
+ index_diff = ((int )ramp_down_percent (elapsed_time ) *
535
+ (powernv_pstate_info .min - highest_lpstate_idx )) / 100 ;
509
536
510
537
/* Ensure that global pstate is >= to local pstate */
511
- if (highest_lpstate - pstate_diff < local_pstate )
512
- return local_pstate ;
538
+ if (highest_lpstate_idx + index_diff >= local_pstate_idx )
539
+ return local_pstate_idx ;
513
540
else
514
- return highest_lpstate - pstate_diff ;
541
+ return highest_lpstate_idx + index_diff ;
515
542
}
516
543
517
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
575
struct cpufreq_policy * policy = (struct cpufreq_policy * )data ;
549
576
struct global_pstate_info * gpstates = policy -> driver_data ;
550
- int gpstate_id ;
577
+ int gpstate_idx ;
551
578
unsigned int time_diff = jiffies_to_msecs (jiffies )
552
579
- gpstates -> last_sampled_time ;
553
580
struct powernv_smp_call_data freq_data ;
@@ -557,29 +584,29 @@ void gpstate_timer_handler(unsigned long data)
557
584
558
585
gpstates -> last_sampled_time += time_diff ;
559
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
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
592
reset_gpstates (policy );
566
- gpstates -> highest_lpstate = freq_data . pstate_id ;
593
+ gpstates -> highest_lpstate_idx = gpstate_idx ;
567
594
} else {
568
- gpstate_id = calc_global_pstate (gpstates -> elapsed_time ,
569
- gpstates -> highest_lpstate ,
570
- freq_data .pstate_id );
595
+ gpstate_idx = calc_global_pstate (gpstates -> elapsed_time ,
596
+ gpstates -> highest_lpstate_idx ,
597
+ freq_data .pstate_id );
571
598
}
572
599
573
600
/*
574
601
* If local pstate is equal to global pstate, rampdown is over
575
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
605
queue_gpstate_timer (gpstates );
579
606
580
- freq_data .gpstate_id = gpstate_id ;
581
- gpstates -> last_gpstate = freq_data .gpstate_id ;
582
- gpstates -> last_lpstate = freq_data .pstate_id ;
607
+ freq_data .gpstate_id = idx_to_pstate ( gpstate_idx ) ;
608
+ gpstates -> last_gpstate_idx = pstate_to_idx ( freq_data .gpstate_id ) ;
609
+ gpstates -> last_lpstate_idx = pstate_to_idx ( freq_data .pstate_id ) ;
583
610
584
611
spin_unlock (& gpstates -> gpstate_lock );
585
612
@@ -596,7 +623,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
596
623
unsigned int new_index )
597
624
{
598
625
struct powernv_smp_call_data freq_data ;
599
- unsigned int cur_msec , gpstate_id ;
626
+ unsigned int cur_msec , gpstate_idx ;
600
627
struct global_pstate_info * gpstates = policy -> driver_data ;
601
628
602
629
if (unlikely (rebooting ) && new_index != get_nominal_index ())
@@ -608,15 +635,15 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
608
635
cur_msec = jiffies_to_msecs (get_jiffies_64 ());
609
636
610
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
640
if (!gpstates -> last_sampled_time ) {
614
- gpstate_id = freq_data . pstate_id ;
615
- gpstates -> highest_lpstate = freq_data . pstate_id ;
641
+ gpstate_idx = new_index ;
642
+ gpstates -> highest_lpstate_idx = new_index ;
616
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
647
gpstates -> elapsed_time += cur_msec -
621
648
gpstates -> last_sampled_time ;
622
649
@@ -627,34 +654,34 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
627
654
*/
628
655
if (gpstates -> elapsed_time > MAX_RAMP_DOWN_TIME ) {
629
656
reset_gpstates (policy );
630
- gpstates -> highest_lpstate = freq_data . pstate_id ;
631
- gpstate_id = freq_data . pstate_id ;
657
+ gpstates -> highest_lpstate_idx = new_index ;
658
+ gpstate_idx = new_index ;
632
659
} else {
633
660
/* Elaspsed_time is less than 5 seconds, continue to rampdown */
634
- gpstate_id = calc_global_pstate (gpstates -> elapsed_time ,
635
- gpstates -> highest_lpstate ,
636
- freq_data . pstate_id );
661
+ gpstate_idx = calc_global_pstate (gpstates -> elapsed_time ,
662
+ gpstates -> highest_lpstate_idx ,
663
+ new_index );
637
664
}
638
665
} else {
639
666
reset_gpstates (policy );
640
- gpstates -> highest_lpstate = freq_data . pstate_id ;
641
- gpstate_id = freq_data . pstate_id ;
667
+ gpstates -> highest_lpstate_idx = new_index ;
668
+ gpstate_idx = new_index ;
642
669
}
643
670
644
671
/*
645
672
* If local pstate is equal to global pstate, rampdown is over
646
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
676
queue_gpstate_timer (gpstates );
650
677
else
651
678
del_timer_sync (& gpstates -> timer );
652
679
653
680
gpstates_done :
654
- freq_data .gpstate_id = gpstate_id ;
681
+ freq_data .gpstate_id = idx_to_pstate ( gpstate_idx ) ;
655
682
gpstates -> last_sampled_time = cur_msec ;
656
- gpstates -> last_gpstate = freq_data . gpstate_id ;
657
- gpstates -> last_lpstate = freq_data . pstate_id ;
683
+ gpstates -> last_gpstate_idx = gpstate_idx ;
684
+ gpstates -> last_lpstate_idx = new_index ;
658
685
659
686
spin_unlock (& gpstates -> gpstate_lock );
660
687
@@ -846,8 +873,8 @@ static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy)
846
873
struct powernv_smp_call_data freq_data ;
847
874
struct global_pstate_info * gpstates = policy -> driver_data ;
848
875
849
- freq_data .pstate_id = powernv_pstate_info .min ;
850
- freq_data .gpstate_id = powernv_pstate_info .min ;
876
+ freq_data .pstate_id = idx_to_pstate ( powernv_pstate_info .min ) ;
877
+ freq_data .gpstate_id = idx_to_pstate ( powernv_pstate_info .min ) ;
851
878
smp_call_function_single (policy -> cpu , set_pstate , & freq_data , 1 );
852
879
del_timer_sync (& gpstates -> timer );
853
880
}
0 commit comments