diff options
author | Michael Neuling <mikey@neuling.org> | 2016-03-21 12:54:52 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-03-21 20:08:55 -0400 |
commit | 3e5963bc343b3fb4ca045e9d1c14cb9ce89234b8 (patch) | |
tree | 216fb97bcf417def706207afe7e44f77fb6d8c53 | |
parent | ed72662a84771fec1337dd8b187e070af6fd3890 (diff) |
cpufreq: powernv: Define per_cpu chip pointer to optimize hot-path
Commit 96c4726f01cd "cpufreq: powernv: Remove cpu_to_chip_id() from
hot-path" introduced a 'core_to_chip_map' array to cache the chip-ids
of all cores.
Replace this with a per-CPU variable that stores the pointer to the
chip-array. This removes the linear lookup and provides a neater and
simpler solution.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/cpufreq/powernv-cpufreq.c | 50 |
1 files changed, 17 insertions, 33 deletions
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 50bf12033bbc..a00bcc2cef09 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c | |||
@@ -44,7 +44,6 @@ | |||
44 | 44 | ||
45 | static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; | 45 | static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; |
46 | static bool rebooting, throttled, occ_reset; | 46 | static bool rebooting, throttled, occ_reset; |
47 | static unsigned int *core_to_chip_map; | ||
48 | 47 | ||
49 | static const char * const throttle_reason[] = { | 48 | static const char * const throttle_reason[] = { |
50 | "No throttling", | 49 | "No throttling", |
@@ -65,6 +64,7 @@ static struct chip { | |||
65 | } *chips; | 64 | } *chips; |
66 | 65 | ||
67 | static int nr_chips; | 66 | static int nr_chips; |
67 | static DEFINE_PER_CPU(struct chip *, chip_info); | ||
68 | 68 | ||
69 | /* | 69 | /* |
70 | * Note: The set of pstates consists of contiguous integers, the | 70 | * Note: The set of pstates consists of contiguous integers, the |
@@ -324,34 +324,31 @@ static inline unsigned int get_nominal_index(void) | |||
324 | 324 | ||
325 | static void powernv_cpufreq_throttle_check(void *data) | 325 | static void powernv_cpufreq_throttle_check(void *data) |
326 | { | 326 | { |
327 | struct chip *chip; | ||
327 | unsigned int cpu = smp_processor_id(); | 328 | unsigned int cpu = smp_processor_id(); |
328 | unsigned int chip_id = core_to_chip_map[cpu_core_index_of_thread(cpu)]; | ||
329 | unsigned long pmsr; | 329 | unsigned long pmsr; |
330 | int pmsr_pmax, i; | 330 | int pmsr_pmax; |
331 | 331 | ||
332 | pmsr = get_pmspr(SPRN_PMSR); | 332 | pmsr = get_pmspr(SPRN_PMSR); |
333 | 333 | chip = this_cpu_read(chip_info); | |
334 | for (i = 0; i < nr_chips; i++) | ||
335 | if (chips[i].id == chip_id) | ||
336 | break; | ||
337 | 334 | ||
338 | /* Check for Pmax Capping */ | 335 | /* Check for Pmax Capping */ |
339 | pmsr_pmax = (s8)PMSR_MAX(pmsr); | 336 | pmsr_pmax = (s8)PMSR_MAX(pmsr); |
340 | if (pmsr_pmax != powernv_pstate_info.max) { | 337 | if (pmsr_pmax != powernv_pstate_info.max) { |
341 | if (chips[i].throttled) | 338 | if (chip->throttled) |
342 | goto next; | 339 | goto next; |
343 | chips[i].throttled = true; | 340 | chip->throttled = true; |
344 | if (pmsr_pmax < powernv_pstate_info.nominal) | 341 | if (pmsr_pmax < powernv_pstate_info.nominal) |
345 | pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", | 342 | pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", |
346 | cpu, chips[i].id, pmsr_pmax, | 343 | cpu, chip->id, pmsr_pmax, |
347 | powernv_pstate_info.nominal); | 344 | powernv_pstate_info.nominal); |
348 | trace_powernv_throttle(chips[i].id, | 345 | trace_powernv_throttle(chip->id, |
349 | throttle_reason[chips[i].throttle_reason], | 346 | throttle_reason[chip->throttle_reason], |
350 | pmsr_pmax); | 347 | pmsr_pmax); |
351 | } else if (chips[i].throttled) { | 348 | } else if (chip->throttled) { |
352 | chips[i].throttled = false; | 349 | chip->throttled = false; |
353 | trace_powernv_throttle(chips[i].id, | 350 | trace_powernv_throttle(chip->id, |
354 | throttle_reason[chips[i].throttle_reason], | 351 | throttle_reason[chip->throttle_reason], |
355 | pmsr_pmax); | 352 | pmsr_pmax); |
356 | } | 353 | } |
357 | 354 | ||
@@ -558,47 +555,34 @@ static int init_chip_info(void) | |||
558 | unsigned int chip[256]; | 555 | unsigned int chip[256]; |
559 | unsigned int cpu, i; | 556 | unsigned int cpu, i; |
560 | unsigned int prev_chip_id = UINT_MAX; | 557 | unsigned int prev_chip_id = UINT_MAX; |
561 | cpumask_t cpu_mask; | ||
562 | int ret = -ENOMEM; | ||
563 | |||
564 | core_to_chip_map = kcalloc(cpu_nr_cores(), sizeof(unsigned int), | ||
565 | GFP_KERNEL); | ||
566 | if (!core_to_chip_map) | ||
567 | goto out; | ||
568 | 558 | ||
569 | cpumask_copy(&cpu_mask, cpu_possible_mask); | 559 | for_each_possible_cpu(cpu) { |
570 | for_each_cpu(cpu, &cpu_mask) { | ||
571 | unsigned int id = cpu_to_chip_id(cpu); | 560 | unsigned int id = cpu_to_chip_id(cpu); |
572 | 561 | ||
573 | if (prev_chip_id != id) { | 562 | if (prev_chip_id != id) { |
574 | prev_chip_id = id; | 563 | prev_chip_id = id; |
575 | chip[nr_chips++] = id; | 564 | chip[nr_chips++] = id; |
576 | } | 565 | } |
577 | core_to_chip_map[cpu_core_index_of_thread(cpu)] = id; | ||
578 | cpumask_andnot(&cpu_mask, &cpu_mask, cpu_sibling_mask(cpu)); | ||
579 | } | 566 | } |
580 | 567 | ||
581 | chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL); | 568 | chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL); |
582 | if (!chips) | 569 | if (!chips) |
583 | goto free_chip_map; | 570 | return -ENOMEM; |
584 | 571 | ||
585 | for (i = 0; i < nr_chips; i++) { | 572 | for (i = 0; i < nr_chips; i++) { |
586 | chips[i].id = chip[i]; | 573 | chips[i].id = chip[i]; |
587 | cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i])); | 574 | cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i])); |
588 | INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn); | 575 | INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn); |
576 | for_each_cpu(cpu, &chips[i].mask) | ||
577 | per_cpu(chip_info, cpu) = &chips[i]; | ||
589 | } | 578 | } |
590 | 579 | ||
591 | return 0; | 580 | return 0; |
592 | free_chip_map: | ||
593 | kfree(core_to_chip_map); | ||
594 | out: | ||
595 | return ret; | ||
596 | } | 581 | } |
597 | 582 | ||
598 | static inline void clean_chip_info(void) | 583 | static inline void clean_chip_info(void) |
599 | { | 584 | { |
600 | kfree(chips); | 585 | kfree(chips); |
601 | kfree(core_to_chip_map); | ||
602 | } | 586 | } |
603 | 587 | ||
604 | static inline void unregister_all_notifiers(void) | 588 | static inline void unregister_all_notifiers(void) |