Re: [PATCH v5 5/5] cpufreq: powernv: Add sysfs attributes to show throttle stats

2016-01-21 Thread Gautham R Shenoy
On Thu, Jan 21, 2016 at 03:08:59PM +0530, Shilpasri G Bhat wrote:
> Signed-off-by: Shilpasri G Bhat 
Reviewed-by: Gautham R. Shenoy 

--
Thanks and Regards
gautham.



[PATCH v5 5/5] cpufreq: powernv: Add sysfs attributes to show throttle stats

2016-01-21 Thread Shilpasri G Bhat
Create sysfs attributes to export throttle information in
/sys/devices/system/cpu/cpufreq/chipN. The newly added sysfs files are as
follows:

1)/sys/devices/system/cpu/cpufreq/chip0/throttle_frequencies
  This gives the throttle stats for each of the available frequencies.
  The throttle stat of a frequency is the total number of times the max
  frequency is reduced to that frequency.
  # cat /sys/devices/system/cpu/cpufreq/chip0/throttle_frequencies
  4023000 0
  399 0
  3956000 1
  3923000 0
  389 0
  3857000 2
  3823000 0
  379 0
  3757000 2
  3724000 1
  369 1
  ...

2)/sys/devices/system/cpu/cpufreq/chip0/throttle_reasons
  This directory contains throttle reason files. Each file gives the
  total number of times the max frequency is throttled, except for
  'throttle_reset', which gives the total number of times the max
  frequency is unthrottled after being throttled.
  # cd /sys/devices/system/cpu/cpufreq/chip0/throttle_reasons
  # cat cpu_over_temperature
  7
  # cat occ_reset
  0
  # cat over_current
  0
  # cat power_cap
  0
  # cat power_supply_failure
  0
  # cat throttle_reset
  7

3)/sys/devices/system/cpu/cpufreq/chip0/throttle_stat
  This gives the total number of events of max frequency throttling to
  lower frequencies in the turbo range of frequencies and the sub-turbo(at
  and below nominal) range of frequencies.
  # cat /sys/devices/system/cpu/cpufreq/chip0/throttle_stat
  turbo 7
  sub-turbo 0

Signed-off-by: Shilpasri G Bhat 
---
Changes from v4:
- Taken care of Gautham's comments to use inline get_chip_index()

Changes from v3:
- Seperate the patch to contain only the throttle sysfs attribute changes.
- Add helper inline function get_chip_index()

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]

Changes from v1:
- Added a kobject to struct chip
- Grouped the throttle reasons under a separate attribute_group and
  exported each reason as individual file.
- Moved the sysfs files from /sys/devices/system/node/nodeN to
  /sys/devices/system/cpu/cpufreq/chipN
- As suggested by Paul Clarke replaced 'Nominal' with 'sub-turbo'.
- Modified the commit message.

 drivers/cpufreq/powernv-cpufreq.c | 205 --
 1 file changed, 196 insertions(+), 9 deletions(-)

diff --git a/drivers/cpufreq/powernv-cpufreq.c 
b/drivers/cpufreq/powernv-cpufreq.c
index 0ed7d82..ecda5f7 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -54,6 +54,16 @@ static const char * const throttle_reason[] = {
"OCC Reset"
 };
 
+enum throt_reason_type {
+   NO_THROTTLE = 0,
+   POWERCAP,
+   CPU_OVERTEMP,
+   POWER_SUPPLY_FAILURE,
+   OVERCURRENT,
+   OCC_RESET_THROTTLE,
+   OCC_MAX_REASON
+};
+
 static struct chip {
unsigned int id;
bool throttled;
@@ -61,6 +71,11 @@ static struct chip {
u8 throt_reason;
cpumask_t mask;
struct work_struct throttle;
+   int throt_turbo;
+   int throt_nominal;
+   int reason[OCC_MAX_REASON];
+   int *pstate_stat;
+   struct kobject *kobj;
 } *chips;
 
 static int nr_chips;
@@ -195,6 +210,128 @@ static struct freq_attr *powernv_cpu_freq_attr[] = {
NULL,
 };
 
+static inline int get_chip_index(unsigned int id)
+{
+   int i;
+
+   for (i = 0; i < nr_chips; i++)
+   if (chips[i].id == id)
+   return i;
+
+   return -EINVAL;
+}
+
+static ssize_t throttle_freq_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+   int i, count = 0, id;
+
+   i = kstrtoint(kobj->name + 4, 0, &id);
+   if (i)
+   return i;
+
+   id = get_chip_index(id);
+   if (id < 0) {
+   pr_warn_once("%s Matching chip-id not found\n", __func__);
+   return id;
+   }
+
+   for (i = 0; i < powernv_pstate_info.nr_pstates; i++)
+   count += sprintf(&buf[count], "%d %d\n",
+  powernv_freqs[i].frequency,
+  chips[id].pstate_stat[i]);
+
+   return count;
+}
+
+static struct kobj_attribute attr_throttle_frequencies =
+__ATTR(throttle_frequencies, 0444, throttle_freq_show, NULL);
+
+static ssize_t throttle_stat_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+   int ret, id, count = 0;
+
+   ret = kstrtoint(kobj->name + 4, 0, &id);
+   if (ret)
+   return ret;
+
+   id = get_chip_index(id);
+   if (id < 0) {
+   pr_warn_once("%s Matching chip-id not found\n", __func__);
+   return id;
+   }
+
+   count += sprintf(&buf[count], "turbo %d\n", chips[id].throt_turbo);
+   count += sprintf(&buf[count], "sub-turbo %d\n",
+   chip