Merge "soc: qcom: mem-offline: log additional time stats"

This commit is contained in:
qctecmdr 2020-07-25 10:33:09 -07:00 • committed by Gerrit - the friendly Code Review server
commit 3ea5777d6d

View file

@ -29,7 +29,6 @@ static struct kobject *kobj;
static unsigned int sections_per_block;
static u32 offline_granule;
#define MODULE_CLASS_NAME "mem-offline"
#define BUF_LEN 100
struct section_stat {
unsigned long success_count;
@ -39,6 +38,8 @@ struct section_stat {
unsigned long worst_time;
unsigned long total_time;
unsigned long last_recorded_time;
ktime_t resident_time;
ktime_t resident_since;
};
enum memory_states {
@ -115,6 +116,7 @@ static void record_stat(unsigned long sec, ktime_t delay, int mode)
unsigned int total_sec = end_section_nr - start_section_nr + 1;
unsigned int blk_nr = (sec - start_section_nr + mode * total_sec) /
sections_per_block;
ktime_t now, delta;
if (sec > end_section_nr)
return;
@ -135,6 +137,18 @@ static void record_stat(unsigned long sec, ktime_t delay, int mode)
mem_info[blk_nr].total_time / mem_info[blk_nr].success_count;
mem_info[blk_nr].last_recorded_time = delay;
now = ktime_get();
mem_info[blk_nr].resident_since = now;
/* since other state has gone inactive, update the stats */
mode = mode ? MEMORY_ONLINE : MEMORY_OFFLINE;
blk_nr = (sec - start_section_nr + mode * total_sec) /
sections_per_block;
delta = ktime_sub(now, mem_info[blk_nr].resident_since);
mem_info[blk_nr].resident_time =
ktime_add(mem_info[blk_nr].resident_time, delta);
mem_info[blk_nr].resident_since = 0;
}
static int aop_send_msg(unsigned long addr, bool online)
@ -434,75 +448,184 @@ static int mem_online_remaining_blocks(void)
static ssize_t show_mem_offline_granule(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return snprintf(buf, BUF_LEN, "%lu\n", (unsigned long)offline_granule *
SZ_1M);
return scnprintf(buf, PAGE_SIZE, "%lu\n",
(unsigned long)offline_granule * SZ_1M);
}
static ssize_t show_mem_perf_stats(struct kobject *kobj,
static unsigned int print_blk_residency_percentage(char *buf, size_t sz,
unsigned int tot_blks, ktime_t *total_time,
enum memory_states mode)
{
unsigned int i;
unsigned int c = 0;
int percent;
unsigned int idx = tot_blks + 1;
for (i = 0; i <= tot_blks; i++) {
percent = (int)ktime_divns(total_time[i + mode * idx] * 100,
ktime_add(total_time[i + MEMORY_ONLINE * idx],
total_time[i + MEMORY_OFFLINE * idx]));
c += scnprintf(buf + c, sz - c, "%d%%\t\t", percent);
}
return c;
}
static unsigned int print_blk_residency_times(char *buf, size_t sz,
unsigned int tot_blks, ktime_t *total_time,
enum memory_states mode)
{
unsigned int i;
unsigned int c = 0;
ktime_t now, delta;
unsigned int idx = tot_blks + 1;
now = ktime_get();
for (i = 0; i <= tot_blks; i++) {
if (mem_sec_state[i] == mode)
delta = ktime_sub(now,
mem_info[i + mode * idx].resident_since);
else
delta = 0;
delta = ktime_add(delta,
mem_info[i + mode * idx].resident_time);
c += scnprintf(buf + c, sz - c, "%lus\t\t",
ktime_to_ms(delta) / MSEC_PER_SEC);
total_time[i + mode * idx] = delta;
}
return c;
}
static ssize_t show_mem_stats(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
unsigned int blk_start = start_section_nr / sections_per_block;
unsigned int blk_end = end_section_nr / sections_per_block;
unsigned int idx = blk_end - blk_start + 1;
unsigned int char_count = 0;
unsigned int tot_blks = blk_end - blk_start;
ktime_t *total_time;
unsigned int idx = tot_blks + 1;
unsigned int c = 0;
unsigned int i, j;
size_t sz = PAGE_SIZE;
ktime_t total = 0, total_online = 0, total_offline = 0;
total_time = kcalloc(idx * MAX_STATE, sizeof(*total_time), GFP_KERNEL);
if (!total_time)
return -ENOMEM;
for (j = 0; j < MAX_STATE; j++) {
char_count += snprintf(buf + char_count, BUF_LEN,
c += scnprintf(buf + c, sz - c,
"\n\t%s\n\t\t\t", j == 0 ? "ONLINE" : "OFFLINE");
for (i = blk_start; i <= blk_end; i++)
char_count += snprintf(buf + char_count, BUF_LEN,
c += scnprintf(buf + c, sz - c,
"%s%d\t\t", "mem", i);
char_count += snprintf(buf + char_count, BUF_LEN, "\n");
char_count += snprintf(buf + char_count, BUF_LEN,
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c,
"\tLast recd time:\t");
for (i = 0; i <= blk_end - blk_start; i++)
char_count += snprintf(buf + char_count, BUF_LEN,
"%lums\t\t", mem_info[i+j*idx].last_recorded_time);
char_count += snprintf(buf + char_count, BUF_LEN, "\n");
char_count += snprintf(buf + char_count, BUF_LEN,
for (i = 0; i <= tot_blks; i++)
c += scnprintf(buf + c, sz - c, "%lums\t\t",
mem_info[i + j * idx].last_recorded_time);
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c,
"\tAvg time:\t");
for (i = 0; i <= blk_end - blk_start; i++)
char_count += snprintf(buf + char_count, BUF_LEN,
"%lums\t\t", mem_info[i+j*idx].avg_time);
char_count += snprintf(buf + char_count, BUF_LEN, "\n");
char_count += snprintf(buf + char_count, BUF_LEN,
for (i = 0; i <= tot_blks; i++)
c += scnprintf(buf + c, sz - c,
"%lums\t\t", mem_info[i + j * idx].avg_time);
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c,
"\tBest time:\t");
for (i = 0; i <= blk_end - blk_start; i++)
char_count += snprintf(buf + char_count, BUF_LEN,
"%lums\t\t", mem_info[i+j*idx].best_time);
char_count += snprintf(buf + char_count, BUF_LEN, "\n");
char_count += snprintf(buf + char_count, BUF_LEN,
for (i = 0; i <= tot_blks; i++)
c += scnprintf(buf + c, sz - c,
"%lums\t\t", mem_info[i + j * idx].best_time);
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c,
"\tWorst time:\t");
for (i = 0; i <= blk_end - blk_start; i++)
char_count += snprintf(buf + char_count, BUF_LEN,
"%lums\t\t", mem_info[i+j*idx].worst_time);
char_count += snprintf(buf + char_count, BUF_LEN, "\n");
char_count += snprintf(buf + char_count, BUF_LEN,
for (i = 0; i <= tot_blks; i++)
c += scnprintf(buf + c, sz - c,
"%lums\t\t", mem_info[i + j * idx].worst_time);
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c,
"\tSuccess count:\t");
for (i = 0; i <= blk_end - blk_start; i++)
char_count += snprintf(buf + char_count, BUF_LEN,
"%lu\t\t", mem_info[i+j*idx].success_count);
char_count += snprintf(buf + char_count, BUF_LEN, "\n");
char_count += snprintf(buf + char_count, BUF_LEN,
for (i = 0; i <= tot_blks; i++)
c += scnprintf(buf + c, sz - c,
"%lu\t\t", mem_info[i + j * idx].success_count);
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c,
"\tFail count:\t");
for (i = 0; i <= blk_end - blk_start; i++)
char_count += snprintf(buf + char_count, BUF_LEN,
"%lu\t\t", mem_info[i+j*idx].fail_count);
char_count += snprintf(buf + char_count, BUF_LEN, "\n");
for (i = 0; i <= tot_blks; i++)
c += scnprintf(buf + c, sz - c,
"%lu\t\t", mem_info[i + j * idx].fail_count);
c += scnprintf(buf + c, sz - c, "\n");
}
return char_count;
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c, "\tState:\t\t");
for (i = 0; i <= tot_blks; i++) {
c += scnprintf(buf + c, sz - c, "%s\t\t",
mem_sec_state[i] == MEMORY_ONLINE ?
"Online" : "Offline");
}
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c, "\tOnline time:\t");
c += print_blk_residency_times(buf + c, sz - c,
tot_blks, total_time, MEMORY_ONLINE);
c += scnprintf(buf + c, sz - c, "\n");
c += scnprintf(buf + c, sz - c, "\tOffline time:\t");
c += print_blk_residency_times(buf + c, sz - c,
tot_blks, total_time, MEMORY_OFFLINE);
c += scnprintf(buf + c, sz, "\n");
c += scnprintf(buf + c, sz, "\n");
c += scnprintf(buf + c, sz, "\tOnline %%:\t");
c += print_blk_residency_percentage(buf + c, sz - c,
tot_blks, total_time, MEMORY_ONLINE);
c += scnprintf(buf + c, sz, "\n");
c += scnprintf(buf + c, sz, "\tOffline %%:\t");
c += print_blk_residency_percentage(buf + c, sz - c,
tot_blks, total_time, MEMORY_OFFLINE);
c += scnprintf(buf + c, sz, "\n");
c += scnprintf(buf + c, sz, "\n");
for (i = 0; i <= tot_blks; i++)
total = ktime_add(total,
ktime_add(total_time[i + MEMORY_ONLINE * idx],
total_time[i + MEMORY_OFFLINE * idx]));
for (i = 0; i <= tot_blks; i++)
total_online = ktime_add(total_online,
total_time[i + MEMORY_ONLINE * idx]);
total_offline = ktime_sub(total, total_online);
c += scnprintf(buf + c, sz,
"\tAvg Online %%:\t%d%%\n",
((int)total_online * 100) / total);
c += scnprintf(buf + c, sz,
"\tAvg Offline %%:\t%d%%\n",
((int)total_offline * 100) / total);
c += scnprintf(buf + c, sz, "\n");
kfree(total_time);
return c;
}
static struct kobj_attribute perf_stats_attr =
__ATTR(perf_stats, 0444, show_mem_perf_stats, NULL);
static struct kobj_attribute stats_attr =
__ATTR(stats, 0444, show_mem_stats, NULL);
static struct kobj_attribute offline_granule_attr =
__ATTR(offline_granule, 0444, show_mem_offline_granule, NULL);
static struct attribute *mem_root_attrs[] = {
&perf_stats_attr.attr,
&stats_attr.attr,
&offline_granule_attr.attr,
NULL,
};
@ -573,6 +696,7 @@ static int mem_offline_driver_probe(struct platform_device *pdev)
{
unsigned int total_blks;
int ret, i;
ktime_t now;
ret = mem_parse_dt(pdev);
if (ret)
@ -592,6 +716,11 @@ static int mem_offline_driver_probe(struct platform_device *pdev)
if (!mem_info)
return -ENOMEM;
/* record time of online for all blocks */
now = ktime_get();
for (i = 0; i < total_blks; i++)
mem_info[i].resident_since = now;
mem_sec_state = kcalloc(total_blks, sizeof(*mem_sec_state), GFP_KERNEL);
if (!mem_sec_state) {
ret = -ENOMEM;