diff options
-rw-r--r-- | drivers/cpufreq/powernv-cpufreq.c | 73 |
1 files changed, 34 insertions, 39 deletions
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index c670314053af..1bbc10a54c59 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/reboot.h> | 29 | #include <linux/reboot.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/cpu.h> | 31 | #include <linux/cpu.h> |
32 | #include <trace/events/power.h> | ||
32 | 33 | ||
33 | #include <asm/cputhreads.h> | 34 | #include <asm/cputhreads.h> |
34 | #include <asm/firmware.h> | 35 | #include <asm/firmware.h> |
@@ -45,12 +46,22 @@ static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; | |||
45 | static bool rebooting, throttled, occ_reset; | 46 | static bool rebooting, throttled, occ_reset; |
46 | static unsigned int *core_to_chip_map; | 47 | static unsigned int *core_to_chip_map; |
47 | 48 | ||
49 | static const char * const throttle_reason[] = { | ||
50 | "No throttling", | ||
51 | "Power Cap", | ||
52 | "Processor Over Temperature", | ||
53 | "Power Supply Failure", | ||
54 | "Over Current", | ||
55 | "OCC Reset" | ||
56 | }; | ||
57 | |||
48 | static struct chip { | 58 | static struct chip { |
49 | unsigned int id; | 59 | unsigned int id; |
50 | bool throttled; | 60 | bool throttled; |
61 | bool restore; | ||
62 | u8 throttle_reason; | ||
51 | cpumask_t mask; | 63 | cpumask_t mask; |
52 | struct work_struct throttle; | 64 | struct work_struct throttle; |
53 | bool restore; | ||
54 | } *chips; | 65 | } *chips; |
55 | 66 | ||
56 | static int nr_chips; | 67 | static int nr_chips; |
@@ -331,17 +342,17 @@ static void powernv_cpufreq_throttle_check(void *data) | |||
331 | goto next; | 342 | goto next; |
332 | chips[i].throttled = true; | 343 | chips[i].throttled = true; |
333 | if (pmsr_pmax < powernv_pstate_info.nominal) | 344 | if (pmsr_pmax < powernv_pstate_info.nominal) |
334 | pr_crit("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", | 345 | pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", |
335 | cpu, chips[i].id, pmsr_pmax, | 346 | cpu, chips[i].id, pmsr_pmax, |
336 | powernv_pstate_info.nominal); | 347 | powernv_pstate_info.nominal); |
337 | else | 348 | trace_powernv_throttle(chips[i].id, |
338 | pr_info("CPU %d on Chip %u has Pmax reduced below turbo frequency (%d < %d)\n", | 349 | throttle_reason[chips[i].throttle_reason], |
339 | cpu, chips[i].id, pmsr_pmax, | 350 | pmsr_pmax); |
340 | powernv_pstate_info.max); | ||
341 | } else if (chips[i].throttled) { | 351 | } else if (chips[i].throttled) { |
342 | chips[i].throttled = false; | 352 | chips[i].throttled = false; |
343 | pr_info("CPU %d on Chip %u has Pmax restored to %d\n", cpu, | 353 | trace_powernv_throttle(chips[i].id, |
344 | chips[i].id, pmsr_pmax); | 354 | throttle_reason[chips[i].throttle_reason], |
355 | pmsr_pmax); | ||
345 | } | 356 | } |
346 | 357 | ||
347 | /* Check if Psafe_mode_active is set in PMSR. */ | 358 | /* Check if Psafe_mode_active is set in PMSR. */ |
@@ -359,7 +370,7 @@ next: | |||
359 | 370 | ||
360 | if (throttled) { | 371 | if (throttled) { |
361 | pr_info("PMSR = %16lx\n", pmsr); | 372 | pr_info("PMSR = %16lx\n", pmsr); |
362 | pr_crit("CPU Frequency could be throttled\n"); | 373 | pr_warn("CPU Frequency could be throttled\n"); |
363 | } | 374 | } |
364 | } | 375 | } |
365 | 376 | ||
@@ -452,15 +463,6 @@ out: | |||
452 | put_online_cpus(); | 463 | put_online_cpus(); |
453 | } | 464 | } |
454 | 465 | ||
455 | static char throttle_reason[][30] = { | ||
456 | "No throttling", | ||
457 | "Power Cap", | ||
458 | "Processor Over Temperature", | ||
459 | "Power Supply Failure", | ||
460 | "Over Current", | ||
461 | "OCC Reset" | ||
462 | }; | ||
463 | |||
464 | static int powernv_cpufreq_occ_msg(struct notifier_block *nb, | 466 | static int powernv_cpufreq_occ_msg(struct notifier_block *nb, |
465 | unsigned long msg_type, void *_msg) | 467 | unsigned long msg_type, void *_msg) |
466 | { | 468 | { |
@@ -486,7 +488,7 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb, | |||
486 | */ | 488 | */ |
487 | if (!throttled) { | 489 | if (!throttled) { |
488 | throttled = true; | 490 | throttled = true; |
489 | pr_crit("CPU frequency is throttled for duration\n"); | 491 | pr_warn("CPU frequency is throttled for duration\n"); |
490 | } | 492 | } |
491 | 493 | ||
492 | break; | 494 | break; |
@@ -510,23 +512,18 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb, | |||
510 | return 0; | 512 | return 0; |
511 | } | 513 | } |
512 | 514 | ||
513 | if (omsg.throttle_status && | 515 | for (i = 0; i < nr_chips; i++) |
516 | if (chips[i].id == omsg.chip) | ||
517 | break; | ||
518 | |||
519 | if (omsg.throttle_status >= 0 && | ||
514 | omsg.throttle_status <= OCC_MAX_THROTTLE_STATUS) | 520 | omsg.throttle_status <= OCC_MAX_THROTTLE_STATUS) |
515 | pr_info("OCC: Chip %u Pmax reduced due to %s\n", | 521 | chips[i].throttle_reason = omsg.throttle_status; |
516 | (unsigned int)omsg.chip, | ||
517 | throttle_reason[omsg.throttle_status]); | ||
518 | else if (!omsg.throttle_status) | ||
519 | pr_info("OCC: Chip %u %s\n", (unsigned int)omsg.chip, | ||
520 | throttle_reason[omsg.throttle_status]); | ||
521 | else | ||
522 | return 0; | ||
523 | 522 | ||
524 | for (i = 0; i < nr_chips; i++) | 523 | if (!omsg.throttle_status) |
525 | if (chips[i].id == omsg.chip) { | 524 | chips[i].restore = true; |
526 | if (!omsg.throttle_status) | 525 | |
527 | chips[i].restore = true; | 526 | schedule_work(&chips[i].throttle); |
528 | schedule_work(&chips[i].throttle); | ||
529 | } | ||
530 | } | 527 | } |
531 | return 0; | 528 | return 0; |
532 | } | 529 | } |
@@ -581,16 +578,14 @@ static int init_chip_info(void) | |||
581 | cpumask_andnot(&cpu_mask, &cpu_mask, cpu_sibling_mask(cpu)); | 578 | cpumask_andnot(&cpu_mask, &cpu_mask, cpu_sibling_mask(cpu)); |
582 | } | 579 | } |
583 | 580 | ||
584 | chips = kmalloc_array(nr_chips, sizeof(struct chip), GFP_KERNEL); | 581 | chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL); |
585 | if (!chips) | 582 | if (!chips) |
586 | goto free_chip_map; | 583 | goto free_chip_map; |
587 | 584 | ||
588 | for (i = 0; i < nr_chips; i++) { | 585 | for (i = 0; i < nr_chips; i++) { |
589 | chips[i].id = chip[i]; | 586 | chips[i].id = chip[i]; |
590 | chips[i].throttled = false; | ||
591 | cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i])); | 587 | cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i])); |
592 | INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn); | 588 | INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn); |
593 | chips[i].restore = false; | ||
594 | } | 589 | } |
595 | 590 | ||
596 | return 0; | 591 | return 0; |