Skip to content

Commit 09ca4c9

Browse files
Over-enthusiasticrafaeljw
authored andcommitted
cpufreq: powernv: Replacing pstate_id with frequency table index
Refactoring code to use frequency table index instead of pstate_id. This abstraction will make the code independent of the pstate values. - No functional changes - The highest frequency is at frequency table index 0 and the frequency decreases as the index increases. - Macros pstates_to_idx() and idx_to_pstate() can be used for conversion between pstate_id and index. - powernv_pstate_info now contains frequency table index to min, max and nominal frequency (instead of pstate_ids) - global_pstate_info new stores index values instead pstate ids. - variables renamed as *_idx which now store index instead of pstate Signed-off-by: Akshay Adiga <[email protected]> Reviewed-by: Gautham R. Shenoy <[email protected]> Acked-by: Viresh Kumar <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 5fc8f70 commit 09ca4c9

File tree

1 file changed

+102
-75
lines changed

1 file changed

+102
-75
lines changed

drivers/cpufreq/powernv-cpufreq.c

+102-75
Original file line numberDiff line numberDiff line change
@@ -64,24 +64,26 @@
6464
/**
6565
* struct global_pstate_info - Per policy data structure to maintain history of
6666
* 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
6869
* @elapsed_time: Time in ms spent in ramping down from
69-
* highest_lpstate
70+
* highest_lpstate_idx
7071
* @last_sampled_time: Time from boot in ms when global pstates were
7172
* 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
7375
* @timer: Is used for ramping down if cpu goes idle for
7476
* a long time with global pstate held high
7577
* @gpstate_lock: A spinlock to maintain synchronization between
7678
* routines called by the timer handler and
7779
* governer's target_index calls
7880
*/
7981
struct global_pstate_info {
80-
int highest_lpstate;
82+
int highest_lpstate_idx;
8183
unsigned int elapsed_time;
8284
unsigned int last_sampled_time;
83-
int last_lpstate;
84-
int last_gpstate;
85+
int last_lpstate_idx;
86+
int last_gpstate_idx;
8587
spinlock_t gpstate_lock;
8688
struct timer_list timer;
8789
};
@@ -124,29 +126,47 @@ static int nr_chips;
124126
static DEFINE_PER_CPU(struct chip *, chip_info);
125127

126128
/*
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.
130134
*
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.
133137
*/
134138
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;
139143
} powernv_pstate_info;
140144

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+
141161
static inline void reset_gpstates(struct cpufreq_policy *policy)
142162
{
143163
struct global_pstate_info *gpstates = policy->driver_data;
144164

145-
gpstates->highest_lpstate = 0;
165+
gpstates->highest_lpstate_idx = 0;
146166
gpstates->elapsed_time = 0;
147167
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;
150170
}
151171

152172
/*
@@ -156,9 +176,10 @@ static inline void reset_gpstates(struct cpufreq_policy *policy)
156176
static int init_powernv_pstates(void)
157177
{
158178
struct device_node *power_mgt;
159-
int i, pstate_min, pstate_max, pstate_nominal, nr_pstates = 0;
179+
int i, nr_pstates = 0;
160180
const __be32 *pstate_ids, *pstate_freqs;
161181
u32 len_ids, len_freqs;
182+
u32 pstate_min, pstate_max, pstate_nominal;
162183

163184
power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
164185
if (!power_mgt) {
@@ -208,6 +229,7 @@ static int init_powernv_pstates(void)
208229
return -ENODEV;
209230
}
210231

232+
powernv_pstate_info.nr_pstates = nr_pstates;
211233
pr_debug("NR PStates %d\n", nr_pstates);
212234
for (i = 0; i < nr_pstates; i++) {
213235
u32 id = be32_to_cpu(pstate_ids[i]);
@@ -216,15 +238,17 @@ static int init_powernv_pstates(void)
216238
pr_debug("PState id %d freq %d MHz\n", id, freq);
217239
powernv_freqs[i].frequency = freq * 1000; /* kHz */
218240
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;
219248
}
249+
220250
/* End of list marker entry */
221251
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-
228252
return 0;
229253
}
230254

@@ -233,12 +257,12 @@ static unsigned int pstate_id_to_freq(int pstate_id)
233257
{
234258
int i;
235259

236-
i = powernv_pstate_info.max - pstate_id;
260+
i = pstate_to_idx(pstate_id);
237261
if (i >= powernv_pstate_info.nr_pstates || i < 0) {
238262
pr_warn("PState id %d outside of PState table, "
239263
"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;
242266
}
243267

244268
return powernv_freqs[i].frequency;
@@ -252,7 +276,7 @@ static ssize_t cpuinfo_nominal_freq_show(struct cpufreq_policy *policy,
252276
char *buf)
253277
{
254278
return sprintf(buf, "%u\n",
255-
pstate_id_to_freq(powernv_pstate_info.nominal));
279+
powernv_freqs[powernv_pstate_info.nominal].frequency);
256280
}
257281

258282
struct freq_attr cpufreq_freq_attr_cpuinfo_nominal_freq =
@@ -426,7 +450,7 @@ static void set_pstate(void *data)
426450
*/
427451
static inline unsigned int get_nominal_index(void)
428452
{
429-
return powernv_pstate_info.max - powernv_pstate_info.nominal;
453+
return powernv_pstate_info.nominal;
430454
}
431455

432456
static void powernv_cpufreq_throttle_check(void *data)
@@ -435,20 +459,22 @@ static void powernv_cpufreq_throttle_check(void *data)
435459
unsigned int cpu = smp_processor_id();
436460
unsigned long pmsr;
437461
int pmsr_pmax;
462+
unsigned int pmsr_pmax_idx;
438463

439464
pmsr = get_pmspr(SPRN_PMSR);
440465
chip = this_cpu_read(chip_info);
441466

442467
/* Check for Pmax Capping */
443468
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) {
445471
if (chip->throttled)
446472
goto next;
447473
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",
450476
cpu, chip->id, pmsr_pmax,
451-
powernv_pstate_info.nominal);
477+
idx_to_pstate(powernv_pstate_info.nominal));
452478
chip->throttle_sub_turbo++;
453479
} else {
454480
chip->throttle_turbo++;
@@ -484,34 +510,35 @@ static void powernv_cpufreq_throttle_check(void *data)
484510

485511
/**
486512
* 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
490516
*
491517
* Finds the appropriate global pstate based on the pstate from which its
492518
* ramping down and the time elapsed in ramping down. It follows a quadratic
493519
* equation which ensures that it reaches ramping down to pmin in 5sec.
494520
*/
495521
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)
497524
{
498-
int pstate_diff;
525+
int index_diff;
499526

500527
/*
501528
* Using ramp_down_percent we get the percentage of rampdown
502529
* 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
504531
* number of how many pstates we will drop eventually by the end of
505532
* 5 seconds, then just scale it get the number pstates to be dropped.
506533
*/
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;
509536

510537
/* 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;
513540
else
514-
return highest_lpstate - pstate_diff;
541+
return highest_lpstate_idx + index_diff;
515542
}
516543

517544
static inline void queue_gpstate_timer(struct global_pstate_info *gpstates)
@@ -547,7 +574,7 @@ void gpstate_timer_handler(unsigned long data)
547574
{
548575
struct cpufreq_policy *policy = (struct cpufreq_policy *)data;
549576
struct global_pstate_info *gpstates = policy->driver_data;
550-
int gpstate_id;
577+
int gpstate_idx;
551578
unsigned int time_diff = jiffies_to_msecs(jiffies)
552579
- gpstates->last_sampled_time;
553580
struct powernv_smp_call_data freq_data;
@@ -557,29 +584,29 @@ void gpstate_timer_handler(unsigned long data)
557584

558585
gpstates->last_sampled_time += time_diff;
559586
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);
561588

562-
if ((gpstates->last_gpstate == freq_data.pstate_id) ||
589+
if ((gpstates->last_gpstate_idx == gpstates->last_lpstate_idx) ||
563590
(gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) {
564-
gpstate_id = freq_data.pstate_id;
591+
gpstate_idx = pstate_to_idx(freq_data.pstate_id);
565592
reset_gpstates(policy);
566-
gpstates->highest_lpstate = freq_data.pstate_id;
593+
gpstates->highest_lpstate_idx = gpstate_idx;
567594
} 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);
571598
}
572599

573600
/*
574601
* If local pstate is equal to global pstate, rampdown is over
575602
* So timer is not required to be queued.
576603
*/
577-
if (gpstate_id != freq_data.pstate_id)
604+
if (gpstate_idx != gpstates->last_lpstate_idx)
578605
queue_gpstate_timer(gpstates);
579606

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);
583610

584611
spin_unlock(&gpstates->gpstate_lock);
585612

@@ -596,7 +623,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
596623
unsigned int new_index)
597624
{
598625
struct powernv_smp_call_data freq_data;
599-
unsigned int cur_msec, gpstate_id;
626+
unsigned int cur_msec, gpstate_idx;
600627
struct global_pstate_info *gpstates = policy->driver_data;
601628

602629
if (unlikely(rebooting) && new_index != get_nominal_index())
@@ -608,15 +635,15 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
608635
cur_msec = jiffies_to_msecs(get_jiffies_64());
609636

610637
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);
612639

613640
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;
616643
goto gpstates_done;
617644
}
618645

619-
if (gpstates->last_gpstate > freq_data.pstate_id) {
646+
if (gpstates->last_gpstate_idx < new_index) {
620647
gpstates->elapsed_time += cur_msec -
621648
gpstates->last_sampled_time;
622649

@@ -627,34 +654,34 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
627654
*/
628655
if (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME) {
629656
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;
632659
} else {
633660
/* 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);
637664
}
638665
} else {
639666
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;
642669
}
643670

644671
/*
645672
* If local pstate is equal to global pstate, rampdown is over
646673
* So timer is not required to be queued.
647674
*/
648-
if (gpstate_id != freq_data.pstate_id)
675+
if (gpstate_idx != new_index)
649676
queue_gpstate_timer(gpstates);
650677
else
651678
del_timer_sync(&gpstates->timer);
652679

653680
gpstates_done:
654-
freq_data.gpstate_id = gpstate_id;
681+
freq_data.gpstate_id = idx_to_pstate(gpstate_idx);
655682
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;
658685

659686
spin_unlock(&gpstates->gpstate_lock);
660687

@@ -846,8 +873,8 @@ static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy)
846873
struct powernv_smp_call_data freq_data;
847874
struct global_pstate_info *gpstates = policy->driver_data;
848875

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);
851878
smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1);
852879
del_timer_sync(&gpstates->timer);
853880
}

0 commit comments

Comments
 (0)