* Re: [Powertop] [PATCH POWERTOP V4] devfreq: add devfreq devices stats support
@ 2014-10-21 14:57 Alexandra Yates
0 siblings, 0 replies; 3+ messages in thread
From: Alexandra Yates @ 2014-10-21 14:57 UTC (permalink / raw)
To: powertop
[-- Attachment #1: Type: text/plain, Size: 14694 bytes --]
> add window to show frequency stats for devfreq devices
>
> Signed-off-by: Rajagopal Venkat <rajagopal.venkat(a)gmail.com>
> Signed-off-by: Sanjay Singh Rawat <sanjay.rawat(a)linaro.org>
> ---
>
> v4 - remove resizing before freeing the vector
>
> v3 - remove unused variables, reduce array size to suitable value
> - replace the inactive code block in the report function with
> TODO comment
>
> v2 - Show devfreq window on support basis. Check for empty devfreq
> directory.
> - Free the open dirp while exiting.
> ---
> src/Makefile.am | 1 +
> src/devices/devfreq.cpp | 332
> ++++++++++++++++++++++++++++++++++++++++++++++
> src/devices/devfreq.h | 75 +++++++++++
> src/main.cpp | 9 ++
> src/report/report-maker.h | 1 +
> 5 files changed, 418 insertions(+)
> create mode 100644 src/devices/devfreq.cpp
> create mode 100644 src/devices/devfreq.h
>
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 311b75e..d2f1da7 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -39,6 +39,7 @@ powertop_SOURCES = \
> devices/alsa.h \
> devices/backlight.cpp \
> devices/backlight.h \
> + devices/devfreq.cpp \
> devices/device.cpp \
> devices/device.h \
> devices/gpu_rapl_device.cpp \
> diff --git a/src/devices/devfreq.cpp b/src/devices/devfreq.cpp
> new file mode 100644
> index 0000000..d2e56e3
> --- /dev/null
> +++ b/src/devices/devfreq.cpp
> @@ -0,0 +1,332 @@
> +/*
> + * Copyright 2012, Linaro
> + *
> + * This file is part of PowerTOP
> + *
> + * This program file is free software; you can redistribute it and/or
> modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but
> WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program in a file named COPYING; if not, write to the
> + * Free Software Foundation, Inc,
> + * 51 Franklin Street, Fifth Floor,
> + * Boston, MA 02110-1301 USA
> + * or just google for it.
> + *
> + * Authors:
> + * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
> + */
> +
> +#include <iostream>
> +#include <fstream>
> +
> +#include <dirent.h>
> +#include <stdlib.h>
> +#include <time.h>
> +#include <unistd.h>
> +
> +#include "device.h"
> +#include "devfreq.h"
> +#include "../display.h"
> +#include "../cpu/cpu.h"
> +#include "../report/report.h"
> +#include "../report/report-maker.h"
> +
> +static bool is_enabled = true;
> +static DIR *dir = NULL;
> +
> +static vector<class devfreq *> all_devfreq;
> +
> +devfreq::devfreq(const char* dpath): device()
> +{
> + strncpy(dir_name, dpath, sizeof(dir_name));
> +}
> +
> +uint64_t devfreq::parse_freq_time(char* pchr)
> +{
> + char *cptr, *pptr = pchr;
> + uint64_t ctime;
> +
> + cptr = strtok(pchr, " :");
> + while (cptr != NULL) {
> + cptr = strtok(NULL, " :");
> + if (cptr )
> + pptr = cptr;
> + }
> +
> + ctime = strtoull(pptr, NULL, 10);
> + return ctime;
> +}
> +
> +void devfreq::process_time_stamps()
> +{
> + unsigned int i;
> + uint64_t active_time = 0;
> +
> + sample_time = (1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec))
> + + ((stamp_after.tv_usec - stamp_before.tv_usec) );
> +
> + for (i=0; i < dstates.size()-1; i++) {
> + struct frequency *state = dstates[i];
> + state->time_after = 1000 * (state->time_after - state->time_before);
> + active_time += state->time_after;
> + }
> + /* Compute idle time for the device */
> + dstates[i]->time_after = sample_time - active_time;
> +}
> +
> +void devfreq::add_devfreq_freq_state(uint64_t freq, uint64_t time)
> +{
> + struct frequency *state;
> +
> + state = new(std::nothrow) struct frequency;
> + if (!state)
> + return;
> +
> + memset(state, 0, sizeof(*state));
> + dstates.push_back(state);
> +
> + state->freq = freq;
> + if (freq == 0)
> + strcpy(state->human_name, "Idle");
> + else
> + hz_to_human(freq, state->human_name);
> + state->time_before = time;
> +}
> +
> +void devfreq::update_devfreq_freq_state(uint64_t freq, uint64_t time)
> +{
> + unsigned int i;
> + struct frequency *state = NULL;
> +
> + for(i=0; i < dstates.size(); i++) {
> + if (freq == dstates[i]->freq)
> + state = dstates[i];
> + }
> +
> + if (state == NULL) {
> + add_devfreq_freq_state(freq, time);
> + return;
> + }
> +
> + state->time_after = time;
> +}
> +
> +void devfreq::parse_devfreq_trans_stat(char *dname)
> +{
> + ifstream file;
> + char filename[256];
> +
> + sprintf(filename, "/sys/class/devfreq/%s/trans_stat", dir_name);
> + file.open(filename);
> +
> + if (!file)
> + return;
> +
> + char line[1024];
> + char *c;
> +
> + while (file) {
> + uint64_t freq;
> + uint64_t time;
> + char *pchr;
> +
> + memset(line, 0, sizeof(line));
> + file.getline(line, sizeof(line));
> +
> + pchr = strchr(line, '*');
> + pchr = (pchr != NULL) ? pchr+1 : line;
> +
> + freq = strtoull(pchr, &c, 10);
> + if (!freq)
> + continue;
> +
> + time = parse_freq_time(pchr);
> + update_devfreq_freq_state(freq, time);
> + }
> + file.close();
> +}
> +
> +void devfreq::start_measurement(void)
> +{
> + unsigned int i;
> +
> + for (i=0; i < dstates.size(); i++)
> + delete dstates[i];
> + dstates.resize(0);
> + sample_time = 0;
> +
> + gettimeofday(&stamp_before, NULL);
> + parse_devfreq_trans_stat(dir_name);
> + /* add device idle state */
> + update_devfreq_freq_state(0, 0);
> +}
> +
> +void devfreq::end_measurement(void)
> +{
> + parse_devfreq_trans_stat(dir_name);
> + gettimeofday(&stamp_after, NULL);
> + process_time_stamps();
> +}
> +
> +double devfreq::power_usage(struct result_bundle *result, struct
> parameter_bundle *bundle)
> +{
> + return 0;
> +}
> +
> +double devfreq::utilization(void)
> +{
> + return 0;
> +}
> +
> +void devfreq::fill_freq_utilization(unsigned int idx, char *buf)
> +{
> + buf[0] = 0;
> +
> + if (idx < dstates.size() && dstates[idx]) {
> + struct frequency *state = dstates[idx];
> + sprintf(buf, " %5.1f%% ", percentage(1.0 * state->time_after /
> sample_time));
> + }
> +}
> +
> +void devfreq::fill_freq_name(unsigned int idx, char *buf)
> +{
> + buf[0] = 0;
> +
> + if (idx < dstates.size() && dstates[idx]) {
> + sprintf(buf, "%-15s", dstates[idx]->human_name);
> + }
> +}
> +
> +void start_devfreq_measurement(void)
> +{
> + unsigned int i;
> +
> + for (i=0; i<all_devfreq.size(); i++)
> + all_devfreq[i]->start_measurement();
> +}
> +
> +void end_devfreq_measurement(void)
> +{
> + unsigned int i;
> +
> + for (i=0; i<all_devfreq.size(); i++)
> + all_devfreq[i]->end_measurement();
> +}
> +
> +static void devfreq_dev_callback(const char *d_name)
> +{
> + devfreq *df = new(std::nothrow) class devfreq(d_name);
> + if (df)
> + all_devfreq.push_back(df);
> +}
> +
> +void create_all_devfreq_devices(void)
> +{
> + struct dirent *entry;
> + int num = 0;
> +
> + std::string p = "/sys/class/devfreq/";
> + dir = opendir(p.c_str());
> + if (dir == NULL) {
> + fprintf(stderr, "Devfreq not enabled\n");
> + is_enabled = false;
> + return;
> + }
> +
> + while((entry = readdir(dir)) != NULL)
> + num++;
> +
> + if (num == 2) {
> + fprintf(stderr, "Devfreq not enabled\n");
> + is_enabled = false;
> + closedir(dir);
> + return;
> + }
> +
> + callback fn = &devfreq_dev_callback;
> + process_directory(p.c_str(), fn);
> +}
> +
> +void initialize_devfreq(void)
> +{
> + if (is_enabled)
> + create_tab("Device Freq stats", _("Device Freq stats"));
> +}
> +
> +void display_devfreq_devices(void)
> +{
> + unsigned int i, j;
> + WINDOW *win;
> + char fline[1024];
> + char buf[128];
> +
> + win = get_ncurses_win("Device Freq stats");
> + if (!win)
> + return;
> +
> + wclear(win);
> + wmove(win, 2,0);
> +
> + if (!is_enabled) {
> + wprintw(win, _(" Devfreq is not enabled"));
> + return;
> + }
> +
> + if (!all_devfreq.size()) {
> + wprintw(win, _(" No devfreq devices available"));
> + return;
> + }
> +
> + for (i=0; i<all_devfreq.size(); i++) {
> +
> + class devfreq *df = all_devfreq[i];
> + wprintw(win, "\n%s\n", df->device_name());
> +
> + for(j=0; j < df->dstates.size(); j++) {
> + memset(fline, 0, sizeof(fline));
> + strcpy(fline, "\t");
> + df->fill_freq_name(j, buf);
> + strcat(fline, buf);
> + df->fill_freq_utilization(j, buf);
> + strcat(fline, buf);
> + strcat(fline, "\n");
> + wprintw(win, fline);
> + }
> + wprintw(win, "\n");
> + }
> +}
> +
> +void report_devfreq_devices(void)
> +{
> + if (!is_enabled) {
> + return;
> + }
> +
> +/* todo: adapt to new report format */
> +
> +}
> +
> +void clear_all_devfreq()
> +{
> + unsigned int i, j;
> +
> + for (i=0; i < all_devfreq.size(); i++) {
> + class devfreq *df = all_devfreq[i];
> +
> + for(j=0; j < df->dstates.size(); j++)
> + delete df->dstates[j];
> +
> + delete df;
> + }
> + all_devfreq.clear();
> + /* close /sys/class/devfreq */
> + if (dir != NULL)
> + closedir(dir);
> +}
> diff --git a/src/devices/devfreq.h b/src/devices/devfreq.h
> new file mode 100644
> index 0000000..16a60fb
> --- /dev/null
> +++ b/src/devices/devfreq.h
> @@ -0,0 +1,75 @@
> +/*
> + * Copyright 2012, Linaro
> + *
> + * This file is part of PowerTOP
> + *
> + * This program file is free software; you can redistribute it and/or
> modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but
> WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program in a file named COPYING; if not, write to the
> + * Free Software Foundation, Inc,
> + * 51 Franklin Street, Fifth Floor,
> + * Boston, MA 02110-1301 USA
> + * or just google for it.
> + *
> + * Authors:
> + * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
> + */
> +#ifndef _INCLUDE_GUARD_DEVFREQ_H
> +#define _INCLUDE_GUARD_DEVFREQ_H
> +
> +#include "device.h"
> +#include "../parameters/parameters.h"
> +
> +struct frequency;
> +
> +class devfreq: public device {
> + char dir_name[128];
> + struct timeval stamp_before, stamp_after;
> + double sample_time;
> +
> + uint64_t parse_freq_time(char *ptr);
> + void add_devfreq_freq_state(uint64_t freq, uint64_t time);
> + void update_devfreq_freq_state(uint64_t freq, uint64_t time);
> + void parse_devfreq_trans_stat(char *dname);
> + void process_time_stamps();
> +
> +public:
> +
> + vector<struct frequency *> dstates;
> +
> + devfreq(const char *c);
> + void fill_freq_utilization(unsigned int idx, char *buf);
> + void fill_freq_name(unsigned int idx, char *buf);
> +
> + virtual void start_measurement(void);
> + virtual void end_measurement(void);
> +
> + virtual double utilization(void); /* percentage */
> +
> + virtual const char * class_name(void) { return "devfreq";};
> +
> + virtual const char * device_name(void) { return dir_name;};
> + virtual const char * human_name(void) { return "devfreq";};
> + virtual double power_usage(struct result_bundle *result, struct
> parameter_bundle *bundle);
> + virtual const char * util_units(void) { return " rpm"; };
> + virtual int power_valid(void) { return 0;
> /*utilization_power_valid(r_index);*/};
> + virtual int grouping_prio(void) { return 1; };
> +};
> +
> +extern void create_all_devfreq_devices(void);
> +extern void clear_all_devfreq(void);
> +extern void display_devfreq_devices(void);
> +extern void report_devfreq_devices(void);
> +extern void initialize_devfreq(void);
> +extern void start_devfreq_measurement(void);
> +extern void end_devfreq_measurement(void);
> +
> +#endif
> diff --git a/src/main.cpp b/src/main.cpp
> index d3963ed..2162004 100644
> --- a/src/main.cpp
> +++ b/src/main.cpp
> @@ -48,6 +48,7 @@
>
>
> #include "devices/device.h"
> +#include "devices/devfreq.h"
> #include "devices/usb.h"
> #include "devices/ahci.h"
> #include "measurement/measurement.h"
> @@ -201,6 +202,7 @@ void one_measurement(int seconds, char *workload)
> create_all_usb_devices();
> start_power_measurement();
> devices_start_measurement();
> + start_devfreq_measurement();
> start_process_measurement();
> start_cpu_measurement();
>
> @@ -213,6 +215,7 @@ void one_measurement(int seconds, char *workload)
> end_cpu_measurement();
> end_process_measurement();
> collect_open_devices();
> + end_devfreq_measurement();
> devices_end_measurement();
> end_power_measurement();
>
> @@ -240,6 +243,8 @@ void one_measurement(int seconds, char *workload)
> report_show_open_devices();
>
> report_devices();
> + display_devfreq_devices();
> + report_devfreq_devices();
> ahci_create_device_stats_table();
> store_results(measurement_time);
> end_cpu_data();
> @@ -353,6 +358,7 @@ static void powertop_init(void)
>
> enumerate_cpus();
> create_all_devices();
> + create_all_devfreq_devices();
> detect_power_meters();
>
> register_parameter("base power", 100, 0.5);
> @@ -464,6 +470,8 @@ int main(int argc, char **argv)
> }
> if (!auto_tune)
> init_display();
> +
> + initialize_devfreq();
> initialize_tuning();
> /* first one is short to not let the user wait too long */
> one_measurement(1, NULL);
> @@ -500,6 +508,7 @@ int main(int argc, char **argv)
>
> clean_open_devices();
> clear_all_devices();
> + clear_all_devfreq();
> clear_all_cpus();
>
> return 0;
> diff --git a/src/report/report-maker.h b/src/report/report-maker.h
> index 423568a..bda4cef 100644
> --- a/src/report/report-maker.h
> +++ b/src/report/report-maker.h
> @@ -89,6 +89,7 @@ enum section_type {
> SECTION_SYSINFO,
> SECTION_CPUIDLE,
> SECTION_CPUFREQ,
> + SECTION_DEVFREQ,
> SECTION_DEVPOWER,
> SECTION_SOFTWARE,
> SECTION_SUMMARY,
> --
> 1.8.3.2
>
>
Your patch was added today.
Thank you,
Alexandra.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Powertop] [PATCH POWERTOP V4] devfreq: add devfreq devices stats support
@ 2014-10-15 14:05 Sergey Senozhatsky
0 siblings, 0 replies; 3+ messages in thread
From: Sergey Senozhatsky @ 2014-10-15 14:05 UTC (permalink / raw)
To: powertop
[-- Attachment #1: Type: text/plain, Size: 14696 bytes --]
> add window to show frequency stats for devfreq devices
>
> Signed-off-by: Rajagopal Venkat <rajagopal.venkat(a)gmail.com>
> Signed-off-by: Sanjay Singh Rawat <sanjay.rawat(a)linaro.org>
> ---
>
> v4 - remove resizing before freeing the vector
>
> v3 - remove unused variables, reduce array size to suitable value
> - replace the inactive code block in the report function with
> TODO comment
>
> v2 - Show devfreq window on support basis. Check for empty devfreq
> directory.
> - Free the open dirp while exiting.
> ---
> src/Makefile.am | 1 +
> src/devices/devfreq.cpp | 332 ++++++++++++++++++++++++++++++++++++++++++++++
> src/devices/devfreq.h | 75 +++++++++++
> src/main.cpp | 9 ++
> src/report/report-maker.h | 1 +
> 5 files changed, 418 insertions(+)
> create mode 100644 src/devices/devfreq.cpp
> create mode 100644 src/devices/devfreq.h
I think I don't have any serious/outstanding objections.
-ss
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 311b75e..d2f1da7 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -39,6 +39,7 @@ powertop_SOURCES = \
> devices/alsa.h \
> devices/backlight.cpp \
> devices/backlight.h \
> + devices/devfreq.cpp \
> devices/device.cpp \
> devices/device.h \
> devices/gpu_rapl_device.cpp \
> diff --git a/src/devices/devfreq.cpp b/src/devices/devfreq.cpp
> new file mode 100644
> index 0000000..d2e56e3
> --- /dev/null
> +++ b/src/devices/devfreq.cpp
> @@ -0,0 +1,332 @@
> +/*
> + * Copyright 2012, Linaro
> + *
> + * This file is part of PowerTOP
> + *
> + * This program file is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program in a file named COPYING; if not, write to the
> + * Free Software Foundation, Inc,
> + * 51 Franklin Street, Fifth Floor,
> + * Boston, MA 02110-1301 USA
> + * or just google for it.
> + *
> + * Authors:
> + * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
> + */
> +
> +#include <iostream>
> +#include <fstream>
> +
> +#include <dirent.h>
> +#include <stdlib.h>
> +#include <time.h>
> +#include <unistd.h>
> +
> +#include "device.h"
> +#include "devfreq.h"
> +#include "../display.h"
> +#include "../cpu/cpu.h"
> +#include "../report/report.h"
> +#include "../report/report-maker.h"
> +
> +static bool is_enabled = true;
> +static DIR *dir = NULL;
> +
> +static vector<class devfreq *> all_devfreq;
> +
> +devfreq::devfreq(const char* dpath): device()
> +{
> + strncpy(dir_name, dpath, sizeof(dir_name));
> +}
> +
> +uint64_t devfreq::parse_freq_time(char* pchr)
> +{
> + char *cptr, *pptr = pchr;
> + uint64_t ctime;
> +
> + cptr = strtok(pchr, " :");
> + while (cptr != NULL) {
> + cptr = strtok(NULL, " :");
> + if (cptr )
> + pptr = cptr;
> + }
> +
> + ctime = strtoull(pptr, NULL, 10);
> + return ctime;
> +}
> +
> +void devfreq::process_time_stamps()
> +{
> + unsigned int i;
> + uint64_t active_time = 0;
> +
> + sample_time = (1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec))
> + + ((stamp_after.tv_usec - stamp_before.tv_usec) );
> +
> + for (i=0; i < dstates.size()-1; i++) {
> + struct frequency *state = dstates[i];
> + state->time_after = 1000 * (state->time_after - state->time_before);
> + active_time += state->time_after;
> + }
> + /* Compute idle time for the device */
> + dstates[i]->time_after = sample_time - active_time;
> +}
> +
> +void devfreq::add_devfreq_freq_state(uint64_t freq, uint64_t time)
> +{
> + struct frequency *state;
> +
> + state = new(std::nothrow) struct frequency;
> + if (!state)
> + return;
> +
> + memset(state, 0, sizeof(*state));
> + dstates.push_back(state);
> +
> + state->freq = freq;
> + if (freq == 0)
> + strcpy(state->human_name, "Idle");
> + else
> + hz_to_human(freq, state->human_name);
> + state->time_before = time;
> +}
> +
> +void devfreq::update_devfreq_freq_state(uint64_t freq, uint64_t time)
> +{
> + unsigned int i;
> + struct frequency *state = NULL;
> +
> + for(i=0; i < dstates.size(); i++) {
> + if (freq == dstates[i]->freq)
> + state = dstates[i];
> + }
> +
> + if (state == NULL) {
> + add_devfreq_freq_state(freq, time);
> + return;
> + }
> +
> + state->time_after = time;
> +}
> +
> +void devfreq::parse_devfreq_trans_stat(char *dname)
> +{
> + ifstream file;
> + char filename[256];
> +
> + sprintf(filename, "/sys/class/devfreq/%s/trans_stat", dir_name);
> + file.open(filename);
> +
> + if (!file)
> + return;
> +
> + char line[1024];
> + char *c;
> +
> + while (file) {
> + uint64_t freq;
> + uint64_t time;
> + char *pchr;
> +
> + memset(line, 0, sizeof(line));
> + file.getline(line, sizeof(line));
> +
> + pchr = strchr(line, '*');
> + pchr = (pchr != NULL) ? pchr+1 : line;
> +
> + freq = strtoull(pchr, &c, 10);
> + if (!freq)
> + continue;
> +
> + time = parse_freq_time(pchr);
> + update_devfreq_freq_state(freq, time);
> + }
> + file.close();
> +}
> +
> +void devfreq::start_measurement(void)
> +{
> + unsigned int i;
> +
> + for (i=0; i < dstates.size(); i++)
> + delete dstates[i];
> + dstates.resize(0);
> + sample_time = 0;
> +
> + gettimeofday(&stamp_before, NULL);
> + parse_devfreq_trans_stat(dir_name);
> + /* add device idle state */
> + update_devfreq_freq_state(0, 0);
> +}
> +
> +void devfreq::end_measurement(void)
> +{
> + parse_devfreq_trans_stat(dir_name);
> + gettimeofday(&stamp_after, NULL);
> + process_time_stamps();
> +}
> +
> +double devfreq::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
> +{
> + return 0;
> +}
> +
> +double devfreq::utilization(void)
> +{
> + return 0;
> +}
> +
> +void devfreq::fill_freq_utilization(unsigned int idx, char *buf)
> +{
> + buf[0] = 0;
> +
> + if (idx < dstates.size() && dstates[idx]) {
> + struct frequency *state = dstates[idx];
> + sprintf(buf, " %5.1f%% ", percentage(1.0 * state->time_after / sample_time));
> + }
> +}
> +
> +void devfreq::fill_freq_name(unsigned int idx, char *buf)
> +{
> + buf[0] = 0;
> +
> + if (idx < dstates.size() && dstates[idx]) {
> + sprintf(buf, "%-15s", dstates[idx]->human_name);
> + }
> +}
> +
> +void start_devfreq_measurement(void)
> +{
> + unsigned int i;
> +
> + for (i=0; i<all_devfreq.size(); i++)
> + all_devfreq[i]->start_measurement();
> +}
> +
> +void end_devfreq_measurement(void)
> +{
> + unsigned int i;
> +
> + for (i=0; i<all_devfreq.size(); i++)
> + all_devfreq[i]->end_measurement();
> +}
> +
> +static void devfreq_dev_callback(const char *d_name)
> +{
> + devfreq *df = new(std::nothrow) class devfreq(d_name);
> + if (df)
> + all_devfreq.push_back(df);
> +}
> +
> +void create_all_devfreq_devices(void)
> +{
> + struct dirent *entry;
> + int num = 0;
> +
> + std::string p = "/sys/class/devfreq/";
> + dir = opendir(p.c_str());
> + if (dir == NULL) {
> + fprintf(stderr, "Devfreq not enabled\n");
> + is_enabled = false;
> + return;
> + }
> +
> + while((entry = readdir(dir)) != NULL)
> + num++;
> +
> + if (num == 2) {
> + fprintf(stderr, "Devfreq not enabled\n");
> + is_enabled = false;
> + closedir(dir);
> + return;
> + }
> +
> + callback fn = &devfreq_dev_callback;
> + process_directory(p.c_str(), fn);
> +}
> +
> +void initialize_devfreq(void)
> +{
> + if (is_enabled)
> + create_tab("Device Freq stats", _("Device Freq stats"));
> +}
> +
> +void display_devfreq_devices(void)
> +{
> + unsigned int i, j;
> + WINDOW *win;
> + char fline[1024];
> + char buf[128];
> +
> + win = get_ncurses_win("Device Freq stats");
> + if (!win)
> + return;
> +
> + wclear(win);
> + wmove(win, 2,0);
> +
> + if (!is_enabled) {
> + wprintw(win, _(" Devfreq is not enabled"));
> + return;
> + }
> +
> + if (!all_devfreq.size()) {
> + wprintw(win, _(" No devfreq devices available"));
> + return;
> + }
> +
> + for (i=0; i<all_devfreq.size(); i++) {
> +
> + class devfreq *df = all_devfreq[i];
> + wprintw(win, "\n%s\n", df->device_name());
> +
> + for(j=0; j < df->dstates.size(); j++) {
> + memset(fline, 0, sizeof(fline));
> + strcpy(fline, "\t");
> + df->fill_freq_name(j, buf);
> + strcat(fline, buf);
> + df->fill_freq_utilization(j, buf);
> + strcat(fline, buf);
> + strcat(fline, "\n");
> + wprintw(win, fline);
> + }
> + wprintw(win, "\n");
> + }
> +}
> +
> +void report_devfreq_devices(void)
> +{
> + if (!is_enabled) {
> + return;
> + }
> +
> +/* todo: adapt to new report format */
> +
> +}
> +
> +void clear_all_devfreq()
> +{
> + unsigned int i, j;
> +
> + for (i=0; i < all_devfreq.size(); i++) {
> + class devfreq *df = all_devfreq[i];
> +
> + for(j=0; j < df->dstates.size(); j++)
> + delete df->dstates[j];
> +
> + delete df;
> + }
> + all_devfreq.clear();
> + /* close /sys/class/devfreq */
> + if (dir != NULL)
> + closedir(dir);
> +}
> diff --git a/src/devices/devfreq.h b/src/devices/devfreq.h
> new file mode 100644
> index 0000000..16a60fb
> --- /dev/null
> +++ b/src/devices/devfreq.h
> @@ -0,0 +1,75 @@
> +/*
> + * Copyright 2012, Linaro
> + *
> + * This file is part of PowerTOP
> + *
> + * This program file is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program in a file named COPYING; if not, write to the
> + * Free Software Foundation, Inc,
> + * 51 Franklin Street, Fifth Floor,
> + * Boston, MA 02110-1301 USA
> + * or just google for it.
> + *
> + * Authors:
> + * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
> + */
> +#ifndef _INCLUDE_GUARD_DEVFREQ_H
> +#define _INCLUDE_GUARD_DEVFREQ_H
> +
> +#include "device.h"
> +#include "../parameters/parameters.h"
> +
> +struct frequency;
> +
> +class devfreq: public device {
> + char dir_name[128];
> + struct timeval stamp_before, stamp_after;
> + double sample_time;
> +
> + uint64_t parse_freq_time(char *ptr);
> + void add_devfreq_freq_state(uint64_t freq, uint64_t time);
> + void update_devfreq_freq_state(uint64_t freq, uint64_t time);
> + void parse_devfreq_trans_stat(char *dname);
> + void process_time_stamps();
> +
> +public:
> +
> + vector<struct frequency *> dstates;
> +
> + devfreq(const char *c);
> + void fill_freq_utilization(unsigned int idx, char *buf);
> + void fill_freq_name(unsigned int idx, char *buf);
> +
> + virtual void start_measurement(void);
> + virtual void end_measurement(void);
> +
> + virtual double utilization(void); /* percentage */
> +
> + virtual const char * class_name(void) { return "devfreq";};
> +
> + virtual const char * device_name(void) { return dir_name;};
> + virtual const char * human_name(void) { return "devfreq";};
> + virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
> + virtual const char * util_units(void) { return " rpm"; };
> + virtual int power_valid(void) { return 0; /*utilization_power_valid(r_index);*/};
> + virtual int grouping_prio(void) { return 1; };
> +};
> +
> +extern void create_all_devfreq_devices(void);
> +extern void clear_all_devfreq(void);
> +extern void display_devfreq_devices(void);
> +extern void report_devfreq_devices(void);
> +extern void initialize_devfreq(void);
> +extern void start_devfreq_measurement(void);
> +extern void end_devfreq_measurement(void);
> +
> +#endif
> diff --git a/src/main.cpp b/src/main.cpp
> index d3963ed..2162004 100644
> --- a/src/main.cpp
> +++ b/src/main.cpp
> @@ -48,6 +48,7 @@
>
>
> #include "devices/device.h"
> +#include "devices/devfreq.h"
> #include "devices/usb.h"
> #include "devices/ahci.h"
> #include "measurement/measurement.h"
> @@ -201,6 +202,7 @@ void one_measurement(int seconds, char *workload)
> create_all_usb_devices();
> start_power_measurement();
> devices_start_measurement();
> + start_devfreq_measurement();
> start_process_measurement();
> start_cpu_measurement();
>
> @@ -213,6 +215,7 @@ void one_measurement(int seconds, char *workload)
> end_cpu_measurement();
> end_process_measurement();
> collect_open_devices();
> + end_devfreq_measurement();
> devices_end_measurement();
> end_power_measurement();
>
> @@ -240,6 +243,8 @@ void one_measurement(int seconds, char *workload)
> report_show_open_devices();
>
> report_devices();
> + display_devfreq_devices();
> + report_devfreq_devices();
> ahci_create_device_stats_table();
> store_results(measurement_time);
> end_cpu_data();
> @@ -353,6 +358,7 @@ static void powertop_init(void)
>
> enumerate_cpus();
> create_all_devices();
> + create_all_devfreq_devices();
> detect_power_meters();
>
> register_parameter("base power", 100, 0.5);
> @@ -464,6 +470,8 @@ int main(int argc, char **argv)
> }
> if (!auto_tune)
> init_display();
> +
> + initialize_devfreq();
> initialize_tuning();
> /* first one is short to not let the user wait too long */
> one_measurement(1, NULL);
> @@ -500,6 +508,7 @@ int main(int argc, char **argv)
>
> clean_open_devices();
> clear_all_devices();
> + clear_all_devfreq();
> clear_all_cpus();
>
> return 0;
> diff --git a/src/report/report-maker.h b/src/report/report-maker.h
> index 423568a..bda4cef 100644
> --- a/src/report/report-maker.h
> +++ b/src/report/report-maker.h
> @@ -89,6 +89,7 @@ enum section_type {
> SECTION_SYSINFO,
> SECTION_CPUIDLE,
> SECTION_CPUFREQ,
> + SECTION_DEVFREQ,
> SECTION_DEVPOWER,
> SECTION_SOFTWARE,
> SECTION_SUMMARY,
> --
> 1.8.3.2
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Powertop] [PATCH POWERTOP V4] devfreq: add devfreq devices stats support
@ 2014-10-10 10:04 Sanjay Singh Rawat
0 siblings, 0 replies; 3+ messages in thread
From: Sanjay Singh Rawat @ 2014-10-10 10:04 UTC (permalink / raw)
To: powertop
[-- Attachment #1: Type: text/plain, Size: 13564 bytes --]
add window to show frequency stats for devfreq devices
Signed-off-by: Rajagopal Venkat <rajagopal.venkat(a)gmail.com>
Signed-off-by: Sanjay Singh Rawat <sanjay.rawat(a)linaro.org>
---
v4 - remove resizing before freeing the vector
v3 - remove unused variables, reduce array size to suitable value
- replace the inactive code block in the report function with
TODO comment
v2 - Show devfreq window on support basis. Check for empty devfreq
directory.
- Free the open dirp while exiting.
---
src/Makefile.am | 1 +
src/devices/devfreq.cpp | 332 ++++++++++++++++++++++++++++++++++++++++++++++
src/devices/devfreq.h | 75 +++++++++++
src/main.cpp | 9 ++
src/report/report-maker.h | 1 +
5 files changed, 418 insertions(+)
create mode 100644 src/devices/devfreq.cpp
create mode 100644 src/devices/devfreq.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 311b75e..d2f1da7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,6 +39,7 @@ powertop_SOURCES = \
devices/alsa.h \
devices/backlight.cpp \
devices/backlight.h \
+ devices/devfreq.cpp \
devices/device.cpp \
devices/device.h \
devices/gpu_rapl_device.cpp \
diff --git a/src/devices/devfreq.cpp b/src/devices/devfreq.cpp
new file mode 100644
index 0000000..d2e56e3
--- /dev/null
+++ b/src/devices/devfreq.cpp
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "device.h"
+#include "devfreq.h"
+#include "../display.h"
+#include "../cpu/cpu.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+
+static bool is_enabled = true;
+static DIR *dir = NULL;
+
+static vector<class devfreq *> all_devfreq;
+
+devfreq::devfreq(const char* dpath): device()
+{
+ strncpy(dir_name, dpath, sizeof(dir_name));
+}
+
+uint64_t devfreq::parse_freq_time(char* pchr)
+{
+ char *cptr, *pptr = pchr;
+ uint64_t ctime;
+
+ cptr = strtok(pchr, " :");
+ while (cptr != NULL) {
+ cptr = strtok(NULL, " :");
+ if (cptr )
+ pptr = cptr;
+ }
+
+ ctime = strtoull(pptr, NULL, 10);
+ return ctime;
+}
+
+void devfreq::process_time_stamps()
+{
+ unsigned int i;
+ uint64_t active_time = 0;
+
+ sample_time = (1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec))
+ + ((stamp_after.tv_usec - stamp_before.tv_usec) );
+
+ for (i=0; i < dstates.size()-1; i++) {
+ struct frequency *state = dstates[i];
+ state->time_after = 1000 * (state->time_after - state->time_before);
+ active_time += state->time_after;
+ }
+ /* Compute idle time for the device */
+ dstates[i]->time_after = sample_time - active_time;
+}
+
+void devfreq::add_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ struct frequency *state;
+
+ state = new(std::nothrow) struct frequency;
+ if (!state)
+ return;
+
+ memset(state, 0, sizeof(*state));
+ dstates.push_back(state);
+
+ state->freq = freq;
+ if (freq == 0)
+ strcpy(state->human_name, "Idle");
+ else
+ hz_to_human(freq, state->human_name);
+ state->time_before = time;
+}
+
+void devfreq::update_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ unsigned int i;
+ struct frequency *state = NULL;
+
+ for(i=0; i < dstates.size(); i++) {
+ if (freq == dstates[i]->freq)
+ state = dstates[i];
+ }
+
+ if (state == NULL) {
+ add_devfreq_freq_state(freq, time);
+ return;
+ }
+
+ state->time_after = time;
+}
+
+void devfreq::parse_devfreq_trans_stat(char *dname)
+{
+ ifstream file;
+ char filename[256];
+
+ sprintf(filename, "/sys/class/devfreq/%s/trans_stat", dir_name);
+ file.open(filename);
+
+ if (!file)
+ return;
+
+ char line[1024];
+ char *c;
+
+ while (file) {
+ uint64_t freq;
+ uint64_t time;
+ char *pchr;
+
+ memset(line, 0, sizeof(line));
+ file.getline(line, sizeof(line));
+
+ pchr = strchr(line, '*');
+ pchr = (pchr != NULL) ? pchr+1 : line;
+
+ freq = strtoull(pchr, &c, 10);
+ if (!freq)
+ continue;
+
+ time = parse_freq_time(pchr);
+ update_devfreq_freq_state(freq, time);
+ }
+ file.close();
+}
+
+void devfreq::start_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i < dstates.size(); i++)
+ delete dstates[i];
+ dstates.resize(0);
+ sample_time = 0;
+
+ gettimeofday(&stamp_before, NULL);
+ parse_devfreq_trans_stat(dir_name);
+ /* add device idle state */
+ update_devfreq_freq_state(0, 0);
+}
+
+void devfreq::end_measurement(void)
+{
+ parse_devfreq_trans_stat(dir_name);
+ gettimeofday(&stamp_after, NULL);
+ process_time_stamps();
+}
+
+double devfreq::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ return 0;
+}
+
+double devfreq::utilization(void)
+{
+ return 0;
+}
+
+void devfreq::fill_freq_utilization(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ struct frequency *state = dstates[idx];
+ sprintf(buf, " %5.1f%% ", percentage(1.0 * state->time_after / sample_time));
+ }
+}
+
+void devfreq::fill_freq_name(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ sprintf(buf, "%-15s", dstates[idx]->human_name);
+ }
+}
+
+void start_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->start_measurement();
+}
+
+void end_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->end_measurement();
+}
+
+static void devfreq_dev_callback(const char *d_name)
+{
+ devfreq *df = new(std::nothrow) class devfreq(d_name);
+ if (df)
+ all_devfreq.push_back(df);
+}
+
+void create_all_devfreq_devices(void)
+{
+ struct dirent *entry;
+ int num = 0;
+
+ std::string p = "/sys/class/devfreq/";
+ dir = opendir(p.c_str());
+ if (dir == NULL) {
+ fprintf(stderr, "Devfreq not enabled\n");
+ is_enabled = false;
+ return;
+ }
+
+ while((entry = readdir(dir)) != NULL)
+ num++;
+
+ if (num == 2) {
+ fprintf(stderr, "Devfreq not enabled\n");
+ is_enabled = false;
+ closedir(dir);
+ return;
+ }
+
+ callback fn = &devfreq_dev_callback;
+ process_directory(p.c_str(), fn);
+}
+
+void initialize_devfreq(void)
+{
+ if (is_enabled)
+ create_tab("Device Freq stats", _("Device Freq stats"));
+}
+
+void display_devfreq_devices(void)
+{
+ unsigned int i, j;
+ WINDOW *win;
+ char fline[1024];
+ char buf[128];
+
+ win = get_ncurses_win("Device Freq stats");
+ if (!win)
+ return;
+
+ wclear(win);
+ wmove(win, 2,0);
+
+ if (!is_enabled) {
+ wprintw(win, _(" Devfreq is not enabled"));
+ return;
+ }
+
+ if (!all_devfreq.size()) {
+ wprintw(win, _(" No devfreq devices available"));
+ return;
+ }
+
+ for (i=0; i<all_devfreq.size(); i++) {
+
+ class devfreq *df = all_devfreq[i];
+ wprintw(win, "\n%s\n", df->device_name());
+
+ for(j=0; j < df->dstates.size(); j++) {
+ memset(fline, 0, sizeof(fline));
+ strcpy(fline, "\t");
+ df->fill_freq_name(j, buf);
+ strcat(fline, buf);
+ df->fill_freq_utilization(j, buf);
+ strcat(fline, buf);
+ strcat(fline, "\n");
+ wprintw(win, fline);
+ }
+ wprintw(win, "\n");
+ }
+}
+
+void report_devfreq_devices(void)
+{
+ if (!is_enabled) {
+ return;
+ }
+
+/* todo: adapt to new report format */
+
+}
+
+void clear_all_devfreq()
+{
+ unsigned int i, j;
+
+ for (i=0; i < all_devfreq.size(); i++) {
+ class devfreq *df = all_devfreq[i];
+
+ for(j=0; j < df->dstates.size(); j++)
+ delete df->dstates[j];
+
+ delete df;
+ }
+ all_devfreq.clear();
+ /* close /sys/class/devfreq */
+ if (dir != NULL)
+ closedir(dir);
+}
diff --git a/src/devices/devfreq.h b/src/devices/devfreq.h
new file mode 100644
index 0000000..16a60fb
--- /dev/null
+++ b/src/devices/devfreq.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
+ */
+#ifndef _INCLUDE_GUARD_DEVFREQ_H
+#define _INCLUDE_GUARD_DEVFREQ_H
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+struct frequency;
+
+class devfreq: public device {
+ char dir_name[128];
+ struct timeval stamp_before, stamp_after;
+ double sample_time;
+
+ uint64_t parse_freq_time(char *ptr);
+ void add_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void update_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void parse_devfreq_trans_stat(char *dname);
+ void process_time_stamps();
+
+public:
+
+ vector<struct frequency *> dstates;
+
+ devfreq(const char *c);
+ void fill_freq_utilization(unsigned int idx, char *buf);
+ void fill_freq_name(unsigned int idx, char *buf);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "devfreq";};
+
+ virtual const char * device_name(void) { return dir_name;};
+ virtual const char * human_name(void) { return "devfreq";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual const char * util_units(void) { return " rpm"; };
+ virtual int power_valid(void) { return 0; /*utilization_power_valid(r_index);*/};
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_all_devfreq_devices(void);
+extern void clear_all_devfreq(void);
+extern void display_devfreq_devices(void);
+extern void report_devfreq_devices(void);
+extern void initialize_devfreq(void);
+extern void start_devfreq_measurement(void);
+extern void end_devfreq_measurement(void);
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
index d3963ed..2162004 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -48,6 +48,7 @@
#include "devices/device.h"
+#include "devices/devfreq.h"
#include "devices/usb.h"
#include "devices/ahci.h"
#include "measurement/measurement.h"
@@ -201,6 +202,7 @@ void one_measurement(int seconds, char *workload)
create_all_usb_devices();
start_power_measurement();
devices_start_measurement();
+ start_devfreq_measurement();
start_process_measurement();
start_cpu_measurement();
@@ -213,6 +215,7 @@ void one_measurement(int seconds, char *workload)
end_cpu_measurement();
end_process_measurement();
collect_open_devices();
+ end_devfreq_measurement();
devices_end_measurement();
end_power_measurement();
@@ -240,6 +243,8 @@ void one_measurement(int seconds, char *workload)
report_show_open_devices();
report_devices();
+ display_devfreq_devices();
+ report_devfreq_devices();
ahci_create_device_stats_table();
store_results(measurement_time);
end_cpu_data();
@@ -353,6 +358,7 @@ static void powertop_init(void)
enumerate_cpus();
create_all_devices();
+ create_all_devfreq_devices();
detect_power_meters();
register_parameter("base power", 100, 0.5);
@@ -464,6 +470,8 @@ int main(int argc, char **argv)
}
if (!auto_tune)
init_display();
+
+ initialize_devfreq();
initialize_tuning();
/* first one is short to not let the user wait too long */
one_measurement(1, NULL);
@@ -500,6 +508,7 @@ int main(int argc, char **argv)
clean_open_devices();
clear_all_devices();
+ clear_all_devfreq();
clear_all_cpus();
return 0;
diff --git a/src/report/report-maker.h b/src/report/report-maker.h
index 423568a..bda4cef 100644
--- a/src/report/report-maker.h
+++ b/src/report/report-maker.h
@@ -89,6 +89,7 @@ enum section_type {
SECTION_SYSINFO,
SECTION_CPUIDLE,
SECTION_CPUFREQ,
+ SECTION_DEVFREQ,
SECTION_DEVPOWER,
SECTION_SOFTWARE,
SECTION_SUMMARY,
--
1.8.3.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-10-21 14:57 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-21 14:57 [Powertop] [PATCH POWERTOP V4] devfreq: add devfreq devices stats support Alexandra Yates
-- strict thread matches above, loose matches on Subject: below --
2014-10-15 14:05 Sergey Senozhatsky
2014-10-10 10:04 Sanjay Singh Rawat
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.