When using intel_pstate driver, "scaling_available_freqs" attr is not 
exported to sysfs. It causes assertion of idlestat due to memory of
struct cpufreq_pstate was not allocated.

Allocate struct cpufreq_pstate dynamically when getting frequency 
information from trace file instead of parsing available frequencies
from sysfs

Signed-off-by: Pi-Cheng Chen <pi-cheng.c...@linaro.org>
---
 idlestat.c | 109 ++++++++++++++++++++++++++-----------------------------------
 1 file changed, 47 insertions(+), 62 deletions(-)

diff --git a/idlestat.c b/idlestat.c
index bba8951..0046063 100644
--- a/idlestat.c
+++ b/idlestat.c
@@ -509,8 +509,8 @@ static void release_pstate_info(struct cpufreq_pstates 
*pstates, int nrcpus)
 }
 
 /**
- * build_pstate_info - parse cpufreq sysfs entries and build per-CPU
- * structs to maintain statistics of P-state transitions
+ * build_pstate_info - allocate and initialize per-CPU structs to
+ * maintain statistics of P-state transitions
  * @nrcpus: number of CPUs
  *
  * Return: per-CPU array of structs (success) or NULL (error)
@@ -526,55 +526,8 @@ static struct cpufreq_pstates *build_pstate_info(int 
nrcpus)
        memset(pstates, 0, sizeof(*pstates) * nrcpus);
 
        for (cpu = 0; cpu < nrcpus; cpu++) {
-               struct cpufreq_pstate *pstate;
-               int nrfreq;
-               char *fpath, *freq, line[256];
-               FILE *sc_av_freq;
-
-               if (asprintf(&fpath, CPUFREQ_AVFREQ_PATH_FORMAT, cpu) < 0)
-                       goto clean_exit;
-
-               /* read scaling_available_frequencies for the CPU */
-               sc_av_freq = fopen(fpath, "r");
-               free(fpath);
-               if (!sc_av_freq) {
-                       fprintf(stderr, "warning: P-states not supported for "
-                               "CPU%d\n", cpu);
-                       continue;
-               }
-               freq = fgets(line, sizeof(line)/sizeof(line[0]), sc_av_freq);
-               fclose(sc_av_freq);
-               if (!freq) {
-                       /* unlikely to be here, but just in case... */
-                       fprintf(stderr, "warning: P-state info not found for "
-                               "CPU%d\n", cpu);
-                       continue;
-               }
-
-               /* tokenize line and populate each frequency */
-               nrfreq = 0;
-               pstate = NULL;
-               while ((freq = strtok(freq, "\n ")) != NULL) {
-                       struct cpufreq_pstate *tmp = realloc(pstate, 
sizeof(*pstate) * (nrfreq+1));
-                       if (!tmp)
-                               goto clean_exit;
-                       pstate = tmp;
-
-                       /* initialize pstate record */
-                       pstate[nrfreq].id = nrfreq;
-                       pstate[nrfreq].freq = atol(freq);
-                       pstate[nrfreq].count = 0;
-                       pstate[nrfreq].min_time = DBL_MAX;
-                       pstate[nrfreq].max_time = 0.;
-                       pstate[nrfreq].avg_time = 0.;
-                       pstate[nrfreq].duration = 0.;
-                       nrfreq++;
-                       freq = NULL;
-               }
-
-               /* now populate cpufreq_pstates for this CPU */
-               pstates[cpu].pstate = pstate;
-               pstates[cpu].max = nrfreq;
+               pstates[cpu].pstate = NULL;
+               pstates[cpu].max = 0;
                pstates[cpu].current = -1;      /* unknown */
                pstates[cpu].idle = -1;         /* unknown */
                pstates[cpu].time_enter = 0.;
@@ -582,10 +535,43 @@ static struct cpufreq_pstates *build_pstate_info(int 
nrcpus)
        }
 
        return pstates;
+}
 
-clean_exit:
-       release_pstate_info(pstates, nrcpus);
-       return NULL;
+/**
+ * alloc_pstate - allocate and initialize pstate struct to
+ * maintain statistics of P-state transitions
+ * @pstates: per-CPU P-state statistics struct
+ * @freq: frequency for which the newly pstate is allocated
+ *
+ * Return: the index of the newly allocated pstate struct
+ */
+static int alloc_pstate(struct cpufreq_pstates *pstates, unsigned int freq)
+{
+       struct cpufreq_pstate *pstate, *tmp;
+       int nrfreq;
+
+       pstate = pstates->pstate;
+       nrfreq = pstates->max;
+
+       tmp = realloc(pstate, sizeof(*pstate) * (nrfreq + 1));
+       if (!tmp) {
+               perror("realloc pstate");
+               return -1;
+       }
+       pstate = tmp;
+
+       pstate[nrfreq].id = nrfreq;
+       pstate[nrfreq].freq = freq;
+       pstate[nrfreq].count = 0;
+       pstate[nrfreq].min_time = DBL_MAX;
+       pstate[nrfreq].max_time = 0;
+       pstate[nrfreq].avg_time = 0;
+       pstate[nrfreq].duration = 0;
+
+       pstates->pstate = tmp;
+       pstates->max = nrfreq + 1;
+
+       return nrfreq;
 }
 
 static int get_current_pstate(struct cpuidle_datas *datas, int cpu,
@@ -660,6 +646,9 @@ static void cpu_change_pstate(struct cpuidle_datas *datas, 
int cpu,
 
        cur = get_current_pstate(datas, cpu, &ps, &p);
        next = freq_to_pstate_index(ps, freq);
+       if (next < 0)
+               next = alloc_pstate(ps, freq);
+       assert(next >= 0);
 
        switch (cur) {
        case 1:
@@ -711,7 +700,6 @@ static int store_data(double time, int state, int cpu,
                      struct cpuidle_datas *datas, int count)
 {
        struct cpuidle_cstates *cstates = &datas->cstates[cpu];
-       struct cpufreq_pstate *pstate = datas->pstates[cpu].pstate;
        struct cpuidle_cstate *cstate;
        struct cpuidle_data *data, *tmp;
        int nrdata, last_cstate = cstates->last_cstate;
@@ -774,9 +762,8 @@ static int store_data(double time, int state, int cpu,
                /* need indication if CPU is idle or not */
                cstates->last_cstate = -1;
 
-               /* update P-state stats if supported */
-               if (pstate)
-                       cpu_pstate_running(datas, cpu, time);
+               /* update P-state stats */
+               cpu_pstate_running(datas, cpu, time);
 
                return 0;
        }
@@ -794,9 +781,8 @@ static int store_data(double time, int state, int cpu,
        cstates->cstate_max = MAX(cstates->cstate_max, state);
        cstates->last_cstate = state;
        cstates->wakeirq = NULL;
-       /* update P-state stats if supported */
-       if (pstate)
-               cpu_pstate_idle(datas, cpu, time);
+       /* update P-state stats*/
+       cpu_pstate_idle(datas, cpu, time);
 
        return 0;
 }
@@ -966,7 +952,6 @@ static struct cpuidle_datas *idlestat_load(struct 
program_options *options)
                } else if (strstr(buffer, "cpu_frequency")) {
                        assert(sscanf(buffer, TRACE_FORMAT, &time, &freq,
                                      &cpu) == 3);
-                       assert(datas->pstates[cpu].pstate != NULL);
                        cpu_change_pstate(datas, cpu, freq, time);
                        count++;
                        continue;
-- 
1.9.1


_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to