Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1307233 > unrolled thread
| Started by | Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> |
|---|---|
| First post | 2016-01-12 11:30 +0100 |
| Last post | 2016-01-12 12:00 +0100 |
| Articles | 3 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH RESEND v4 0/4] cpufreq: powernv: Redesign the presentation of throttle notification Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> - 2016-01-12 11:30 +0100
[PATCH RESEND v4 3/4] cpufreq: powernv: Add a trace print for the throttle event Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> - 2016-01-12 11:30 +0100
Re: [PATCH RESEND v4 3/4] cpufreq: powernv: Add a trace print for the throttle event Gautham R Shenoy <ego@linux.vnet.ibm.com> - 2016-01-12 12:00 +0100
| From | Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-01-12 11:30 +0100 |
| Subject | [PATCH RESEND v4 0/4] cpufreq: powernv: Redesign the presentation of throttle notification |
| Message-ID | <qQ4n8-81P-19@gated-at.bofh.it> |
In POWER8, OCC(On-Chip-Controller) can throttle the frequency of the CPU when the chip crosses its thermal and power limits. Currently, powernv-cpufreq driver detects and reports this event as a console message. Some machines may not sustain the max turbo frequency in all conditions and can be throttled frequently. This can lead to the flooding of console with throttle messages. So this patchset aims to redesign the presentation of this event via sysfs counters and tracepoints. Patches [2] to [4] will add a perf trace point "power:powernv_throttle" and sysfs throttle counter stats in /sys/devices/system/cpu/cpufreq/chipN. Patch [1] solves a bug in powernv_cpufreq_throttle_check(), which calls in to cpu_to_chip_id() in hot path which reads DT every time to find the chip id. Resending the patchset as I has cc'ed stable@vger.kernel.org in developemnt cycle and used --in-reply-to to post a new version. Changes from v3: - Add a fix to replace cpu_to_chip_id() with simpler PIR shift to obtain the chip id. - Break patch2 in to two patches separating the tracepoint and sysfs attribute changes. Changes from v2: - Fixed kbuild test warning. drivers/cpufreq/powernv-cpufreq.c:609:2: warning: ignoring return value of 'kstrtoint', declared with attribute warn_unused_result [-Wunused-result] Shilpasri G Bhat (4): cpufreq: powernv: Remove cpu_to_chip_id() from hot-path cpufreq: powernv/tracing: Add powernv_throttle tracepoint cpufreq: powernv: Add a trace print for the throttle event cpufreq: powernv: Add sysfs attributes to show throttle stats drivers/cpufreq/powernv-cpufreq.c | 279 +++++++++++++++++++++++++++++++------- include/trace/events/power.h | 22 +++ kernel/trace/power-traces.c | 1 + 3 files changed, 250 insertions(+), 52 deletions(-) -- 1.9.1
[toc] | [next] | [standalone]
| From | Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-01-12 11:30 +0100 |
| Subject | [PATCH RESEND v4 3/4] cpufreq: powernv: Add a trace print for the throttle event |
| Message-ID | <qQ4n9-81P-43@gated-at.bofh.it> |
| In reply to | #1307233 |
Record the throttle event with a trace print replacing the printk,
except for events like throttling below nominal and occ reset
event which print a warning message.
Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>
---
Changes from v3:
- Separate this patch to contain trace_point changes
- Move struct chip member 'restore' of type bool above 'mask' to reduce
structure padding.
No changes from v2.
Changes from v1:
- As suggested by Paul Clarke replaced char * throttle_reason[][30] by
const char * const throttle_reason[].
drivers/cpufreq/powernv-cpufreq.c | 95 ++++++++++++++++++++-------------------
1 file changed, 49 insertions(+), 46 deletions(-)
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 597a084..c98a6e7 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -28,6 +28,7 @@
#include <linux/of.h>
#include <linux/reboot.h>
#include <linux/slab.h>
+#include <trace/events/power.h>
#include <asm/cputhreads.h>
#include <asm/firmware.h>
@@ -44,12 +45,22 @@
static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
static bool rebooting, throttled, occ_reset;
+static const char * const throttle_reason[] = {
+ "No throttling",
+ "Power Cap",
+ "Processor Over Temperature",
+ "Power Supply Failure",
+ "Over Current",
+ "OCC Reset"
+};
+
static struct chip {
unsigned int id;
bool throttled;
+ bool restore;
+ u8 throt_reason;
cpumask_t mask;
struct work_struct throttle;
- bool restore;
} *chips;
static int nr_chips;
@@ -310,41 +321,49 @@ static inline unsigned int get_nominal_index(void)
return powernv_pstate_info.max - powernv_pstate_info.nominal;
}
-static void powernv_cpufreq_throttle_check(void *data)
+static void powernv_cpufreq_check_pmax(void)
{
unsigned int cpu = smp_processor_id();
unsigned int chip_id = pir_to_chip_id(hard_smp_processor_id());
- unsigned long pmsr;
int pmsr_pmax, i;
- pmsr = get_pmspr(SPRN_PMSR);
+ pmsr_pmax = (s8)PMSR_MAX(get_pmspr(SPRN_PMSR));
for (i = 0; i < nr_chips; i++)
if (chips[i].id == chip_id)
break;
- /* Check for Pmax Capping */
- pmsr_pmax = (s8)PMSR_MAX(pmsr);
if (pmsr_pmax != powernv_pstate_info.max) {
if (chips[i].throttled)
- goto next;
+ return;
+
chips[i].throttled = true;
if (pmsr_pmax < powernv_pstate_info.nominal)
- pr_crit("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n",
- cpu, chips[i].id, pmsr_pmax,
- powernv_pstate_info.nominal);
- else
- pr_info("CPU %d on Chip %u has Pmax reduced below turbo frequency (%d < %d)\n",
- cpu, chips[i].id, pmsr_pmax,
- powernv_pstate_info.max);
+ pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n",
+ cpu, chips[i].id, pmsr_pmax,
+ powernv_pstate_info.nominal);
+
+ trace_powernv_throttle(chips[i].id,
+ throttle_reason[chips[i].throt_reason],
+ pmsr_pmax);
} else if (chips[i].throttled) {
chips[i].throttled = false;
- pr_info("CPU %d on Chip %u has Pmax restored to %d\n", cpu,
- chips[i].id, pmsr_pmax);
+ trace_powernv_throttle(chips[i].id,
+ throttle_reason[chips[i].throt_reason],
+ pmsr_pmax);
}
+}
+
+static void powernv_cpufreq_throttle_check(void *data)
+{
+ unsigned long pmsr;
+
+ pmsr = get_pmspr(SPRN_PMSR);
+
+ /* Check for Pmax Capping */
+ powernv_cpufreq_check_pmax();
/* Check if Psafe_mode_active is set in PMSR. */
-next:
if (pmsr & PMSR_PSAFE_ENABLE) {
throttled = true;
pr_info("Pstate set to safe frequency\n");
@@ -358,7 +377,7 @@ next:
if (throttled) {
pr_info("PMSR = %16lx\n", pmsr);
- pr_crit("CPU Frequency could be throttled\n");
+ pr_warn("CPU Frequency could be throttled\n");
}
}
@@ -449,15 +468,6 @@ void powernv_cpufreq_work_fn(struct work_struct *work)
}
}
-static char throttle_reason[][30] = {
- "No throttling",
- "Power Cap",
- "Processor Over Temperature",
- "Power Supply Failure",
- "Over Current",
- "OCC Reset"
- };
-
static int powernv_cpufreq_occ_msg(struct notifier_block *nb,
unsigned long msg_type, void *_msg)
{
@@ -483,7 +493,7 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb,
*/
if (!throttled) {
throttled = true;
- pr_crit("CPU frequency is throttled for duration\n");
+ pr_warn("CPU frequency is throttled for duration\n");
}
break;
@@ -507,23 +517,18 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb,
return 0;
}
- if (omsg.throttle_status &&
+ for (i = 0; i < nr_chips; i++)
+ if (chips[i].id == omsg.chip)
+ break;
+
+ if (omsg.throttle_status >= 0 &&
omsg.throttle_status <= OCC_MAX_THROTTLE_STATUS)
- pr_info("OCC: Chip %u Pmax reduced due to %s\n",
- (unsigned int)omsg.chip,
- throttle_reason[omsg.throttle_status]);
- else if (!omsg.throttle_status)
- pr_info("OCC: Chip %u %s\n", (unsigned int)omsg.chip,
- throttle_reason[omsg.throttle_status]);
- else
- return 0;
+ chips[i].throt_reason = omsg.throttle_status;
- for (i = 0; i < nr_chips; i++)
- if (chips[i].id == omsg.chip) {
- if (!omsg.throttle_status)
- chips[i].restore = true;
- schedule_work(&chips[i].throttle);
- }
+ if (!omsg.throttle_status)
+ chips[i].restore = true;
+
+ schedule_work(&chips[i].throttle);
}
return 0;
}
@@ -569,16 +574,14 @@ static int init_chip_info(void)
}
}
- chips = kmalloc_array(nr_chips, sizeof(struct chip), GFP_KERNEL);
+ chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL);
if (!chips)
return -ENOMEM;
for (i = 0; i < nr_chips; i++) {
chips[i].id = chip[i];
- chips[i].throttled = false;
cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i]));
INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn);
- chips[i].restore = false;
}
return 0;
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Gautham R Shenoy <ego@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-01-12 12:00 +0100 |
| Subject | Re: [PATCH RESEND v4 3/4] cpufreq: powernv: Add a trace print for the throttle event |
| Message-ID | <qQ4Qa-8ey-17@gated-at.bofh.it> |
| In reply to | #1307235 |
Hi Shilpa,
Just saw this resend!
On Tue, Jan 12, 2016 at 04:24:26AM -0600, Shilpasri G Bhat wrote:
> Record the throttle event with a trace print replacing the printk,
> except for events like throttling below nominal and occ reset
> event which print a warning message.
>
> Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>
> ---
[..snip..]
>
> -static void powernv_cpufreq_throttle_check(void *data)
> +static void powernv_cpufreq_check_pmax(void)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This function only contains code moved from
powernv_cpufreq_throttle_check with pr_crit/pr_warns replaced by
trace_powernv_throttle. Furthermore, it is not called from any other
place. Given that the original function was ~60 lines do we really
need to split it into two separate functions ? If yes, could it be an
inline function ?
> {
> unsigned int cpu = smp_processor_id();
> unsigned int chip_id = pir_to_chip_id(hard_smp_processor_id());
> - unsigned long pmsr;
> int pmsr_pmax, i;
>
> - pmsr = get_pmspr(SPRN_PMSR);
> + pmsr_pmax = (s8)PMSR_MAX(get_pmspr(SPRN_PMSR));
>
> for (i = 0; i < nr_chips; i++)
> if (chips[i].id == chip_id)
> break;
>
> - /* Check for Pmax Capping */
> - pmsr_pmax = (s8)PMSR_MAX(pmsr);
> if (pmsr_pmax != powernv_pstate_info.max) {
> if (chips[i].throttled)
> - goto next;
> + return;
> +
> chips[i].throttled = true;
> if (pmsr_pmax < powernv_pstate_info.nominal)
> - pr_crit("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n",
> - cpu, chips[i].id, pmsr_pmax,
> - powernv_pstate_info.nominal);
> - else
> - pr_info("CPU %d on Chip %u has Pmax reduced below turbo frequency (%d < %d)\n",
> - cpu, chips[i].id, pmsr_pmax,
> - powernv_pstate_info.max);
> + pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n",
> + cpu, chips[i].id, pmsr_pmax,
> + powernv_pstate_info.nominal);
> +
> + trace_powernv_throttle(chips[i].id,
> + throttle_reason[chips[i].throt_reason],
> + pmsr_pmax);
> } else if (chips[i].throttled) {
> chips[i].throttled = false;
> - pr_info("CPU %d on Chip %u has Pmax restored to %d\n", cpu,
> - chips[i].id, pmsr_pmax);
> + trace_powernv_throttle(chips[i].id,
> + throttle_reason[chips[i].throt_reason],
> + pmsr_pmax);
> }
> +}
> +
> +static void powernv_cpufreq_throttle_check(void *data)
> +{
> + unsigned long pmsr;
> +
> + pmsr = get_pmspr(SPRN_PMSR);
> +
> + /* Check for Pmax Capping */
> + powernv_cpufreq_check_pmax();
If you want to retain this function, you could pass pmsr as an
argument instead of computing it afresh in
powernv_cpufreq_check_pmax()
> /* Check if Psafe_mode_active is set in PMSR. */
> -next:
> if (pmsr & PMSR_PSAFE_ENABLE) {
> throttled = true;
> pr_info("Pstate set to safe frequency\n");
--
Thanks and Regards
gautham.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web