From 2d10ac091ce925ebfb159a5e1e6b66731afe9920 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Sun, 3 Apr 2016 22:23:59 -0700 Subject: power: Add Platform-level sleep state stats for angler Change-Id: I12ff2260a28584d2db6289f062ce44d7d486b18c --- power/power.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 1 deletion(-) (limited to 'power') diff --git a/power/power.c b/power/power.c index 92fefc6..cff60c9 100644 --- a/power/power.c +++ b/power/power.c @@ -30,6 +30,7 @@ #define LOG_NIDEBUG 0 #include +#include #include #include #include @@ -56,6 +57,36 @@ #define CPU6_ONLINE_PATH "/sys/devices/system/cpu/cpu6/online" #define CPU7_ONLINE_PATH "/sys/devices/system/cpu/cpu7/online" +#define PLATFORM_SLEEP_MODES 2 +#define XO_VOTERS 3 +#define VMIN_VOTERS 0 + +#define RPM_PARAMETERS 4 +#define NUM_PARAMETERS 10 + +#ifndef RPM_STAT +#define RPM_STAT "/d/rpm_stats" +#endif + +#ifndef RPM_MASTER_STAT +#define RPM_MASTER_STAT "/d/rpm_master_stats" +#endif + +/* RPM runs at 19.2Mhz. Divide by 19200 for msec */ +#define RPM_CLK 19200 + +const char *parameter_names[] = { + "vlow_count", + "accumulated_vlow_time", + "vmin_count", + "accumulated_vmin_time", + "xo_accumulated_duration", + "xo_count", + "xo_accumulated_duration", + "xo_count", + "xo_accumulated_duration", + "xo_count"}; + static int saved_dcvs_cpu0_slack_max = -1; static int saved_dcvs_cpu0_slack_min = -1; static int saved_mpdecision_slack_max = -1; @@ -597,10 +628,125 @@ void set_interactive(struct power_module *module, int on) saved_interactive_mode = !!on; } +static ssize_t get_number_of_platform_modes(struct power_module *module) { + return PLATFORM_SLEEP_MODES; +} + +static int get_voter_list(struct power_module *module, size_t *voter) { + voter[0] = XO_VOTERS; + voter[1] = VMIN_VOTERS; + + return 0; +} + +static int extract_stats(uint64_t *list, char *file, + unsigned int num_parameters, unsigned int index) { + FILE *fp; + ssize_t read; + size_t len; + char *line; + int ret; + + fp = fopen(file, "r"); + if (fp == NULL) { + ret = -errno; + ALOGE("%s: failed to open: %s", __func__, strerror(errno)); + return ret; + } + + for (line = NULL, len = 0; + ((read = getline(&line, &len, fp) != -1) && (index < num_parameters)); + free(line), line = NULL, len = 0) { + uint64_t value; + char* offset; + + size_t begin = strspn(line, " \t"); + if (strncmp(line + begin, parameter_names[index], strlen(parameter_names[index]))) { + continue; + } + + offset = memchr(line, ':', len); + if (!offset) { + continue; + } + + if (!strcmp(file, RPM_MASTER_STAT)) { + /* RPM_MASTER_STAT is reported in hex */ + sscanf(offset, ":%" SCNx64, &value); + /* Duration is reported in rpm SLEEP TICKS */ + if (!strcmp(parameter_names[index], "xo_accumulated_duration")) { + value /= RPM_CLK; + } + } else { + /* RPM_STAT is reported in decimal */ + sscanf(offset, ":%" SCNu64, &value); + } + list[index] = value; + index++; + } + free(line); + + fclose(fp); + return 0; +} + +static int get_platform_low_power_stats(struct power_module *module, + power_state_platform_sleep_state_t *list) { + uint64_t stats[sizeof(parameter_names)] = {0}; + int ret; + + if (!list) { + return -EINVAL; + } + + ret = extract_stats(stats, RPM_STAT, RPM_PARAMETERS, 0); + + if (ret) { + return ret; + } + + ret = extract_stats(stats, RPM_MASTER_STAT, NUM_PARAMETERS, 4); + + if (ret) { + return ret; + } + + /* Update statistics for XO_shutdown */ + strcpy(list[0].name, "XO_shutdown"); + list[0].total_transitions = stats[0]; + list[0].residency_in_msec_since_boot = stats[1]; + list[0].supported_only_in_suspend = false; + list[0].number_of_voters = XO_VOTERS; + + /* Update statistics for APSS voter */ + strcpy(list[0].voters[0].name, "APSS"); + list[0].voters[0].total_time_in_msec_voted_for_since_boot = stats[4]; + list[0].voters[0].total_number_of_times_voted_since_boot = stats[5]; + + /* Update statistics for MPSS voter */ + strcpy(list[0].voters[1].name, "MPSS"); + list[0].voters[1].total_time_in_msec_voted_for_since_boot = stats[6]; + list[0].voters[1].total_number_of_times_voted_since_boot = stats[7]; + + /* Update statistics for LPASS voter */ + strcpy(list[0].voters[2].name, "LPASS"); + list[0].voters[2].total_time_in_msec_voted_for_since_boot = stats[8]; + list[0].voters[2].total_number_of_times_voted_since_boot = stats[9]; + + /* Update statistics for VMIN state */ + strcpy(list[1].name, "VMIN"); + list[1].total_transitions = stats[2]; + list[1].residency_in_msec_since_boot = stats[3]; + list[1].supported_only_in_suspend = false; + list[1].number_of_voters = VMIN_VOTERS; + + return 0; +} + struct power_module HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, - .module_api_version = POWER_MODULE_API_VERSION_0_2, + .module_api_version = POWER_MODULE_API_VERSION_0_5, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = POWER_HARDWARE_MODULE_ID, .name = "QCOM Power HAL", @@ -611,4 +757,7 @@ struct power_module HAL_MODULE_INFO_SYM = { .init = power_init, .powerHint = power_hint, .setInteractive = set_interactive, + .get_number_of_platform_modes = get_number_of_platform_modes, + .get_platform_low_power_stats = get_platform_low_power_stats, + .get_voter_list = get_voter_list }; -- cgit v1.2.3