Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ea5777d authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

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

parents 74cb3f15 e44f87c4
Loading
Loading
Loading
Loading
+172 −43
Original line number Original line Diff line number Diff line
@@ -29,7 +29,6 @@ static struct kobject *kobj;
static unsigned int sections_per_block;
static unsigned int sections_per_block;
static u32 offline_granule;
static u32 offline_granule;
#define MODULE_CLASS_NAME	"mem-offline"
#define MODULE_CLASS_NAME	"mem-offline"
#define BUF_LEN			100


struct section_stat {
struct section_stat {
	unsigned long success_count;
	unsigned long success_count;
@@ -39,6 +38,8 @@ struct section_stat {
	unsigned long worst_time;
	unsigned long worst_time;
	unsigned long total_time;
	unsigned long total_time;
	unsigned long last_recorded_time;
	unsigned long last_recorded_time;
	ktime_t resident_time;
	ktime_t resident_since;
};
};


enum memory_states {
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 total_sec = end_section_nr - start_section_nr + 1;
	unsigned int blk_nr = (sec - start_section_nr + mode * total_sec) /
	unsigned int blk_nr = (sec - start_section_nr + mode * total_sec) /
				sections_per_block;
				sections_per_block;
	ktime_t now, delta;


	if (sec > end_section_nr)
	if (sec > end_section_nr)
		return;
		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].total_time / mem_info[blk_nr].success_count;


	mem_info[blk_nr].last_recorded_time = delay;
	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)
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,
static ssize_t show_mem_offline_granule(struct kobject *kobj,
				struct kobj_attribute *attr, char *buf)
				struct kobj_attribute *attr, char *buf)
{
{
	return snprintf(buf, BUF_LEN, "%lu\n", (unsigned long)offline_granule *
	return scnprintf(buf, PAGE_SIZE, "%lu\n",
									SZ_1M);
			(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)
				struct kobj_attribute *attr, char *buf)
{
{


	unsigned int blk_start = start_section_nr / sections_per_block;
	unsigned int blk_start = start_section_nr / sections_per_block;
	unsigned int blk_end = end_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 tot_blks = blk_end - blk_start;
	unsigned int char_count = 0;
	ktime_t *total_time;
	unsigned int idx = tot_blks + 1;
	unsigned int c = 0;
	unsigned int i, j;
	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++) {
	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");
			"\n\t%s\n\t\t\t", j == 0 ? "ONLINE" : "OFFLINE");
		for (i = blk_start; i <= blk_end; i++)
		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);
							"%s%d\t\t", "mem", i);
		char_count += snprintf(buf + char_count, BUF_LEN, "\n");
		c += scnprintf(buf + c, sz - c, "\n");
		char_count += snprintf(buf + char_count, BUF_LEN,
		c += scnprintf(buf + c, sz - c,
							"\tLast recd time:\t");
							"\tLast recd time:\t");
		for (i = 0; i <= blk_end - blk_start; i++)
		for (i = 0; i <= tot_blks; i++)
			char_count += snprintf(buf + char_count, BUF_LEN,
			c += scnprintf(buf + c, sz - c, "%lums\t\t",
			     "%lums\t\t", mem_info[i+j*idx].last_recorded_time);
				mem_info[i + j * idx].last_recorded_time);
		char_count += snprintf(buf + char_count, BUF_LEN, "\n");
		c += scnprintf(buf + c, sz - c, "\n");
		char_count += snprintf(buf + char_count, BUF_LEN,
		c += scnprintf(buf + c, sz - c,
							"\tAvg time:\t");
							"\tAvg time:\t");
		for (i = 0; i <= blk_end - blk_start; i++)
		for (i = 0; i <= tot_blks; i++)
			char_count += snprintf(buf + char_count, BUF_LEN,
			c += scnprintf(buf + c, sz - c,
				"%lums\t\t", mem_info[i + j * idx].avg_time);
				"%lums\t\t", mem_info[i + j * idx].avg_time);
		char_count += snprintf(buf + char_count, BUF_LEN, "\n");
		c += scnprintf(buf + c, sz - c, "\n");
		char_count += snprintf(buf + char_count, BUF_LEN,
		c += scnprintf(buf + c, sz - c,
							"\tBest time:\t");
							"\tBest time:\t");
		for (i = 0; i <= blk_end - blk_start; i++)
		for (i = 0; i <= tot_blks; i++)
			char_count += snprintf(buf + char_count, BUF_LEN,
			c += scnprintf(buf + c, sz - c,
				"%lums\t\t", mem_info[i + j * idx].best_time);
				"%lums\t\t", mem_info[i + j * idx].best_time);
		char_count += snprintf(buf + char_count, BUF_LEN, "\n");
		c += scnprintf(buf + c, sz - c, "\n");
		char_count += snprintf(buf + char_count, BUF_LEN,
		c += scnprintf(buf + c, sz - c,
							"\tWorst time:\t");
							"\tWorst time:\t");
		for (i = 0; i <= blk_end - blk_start; i++)
		for (i = 0; i <= tot_blks; i++)
			char_count += snprintf(buf + char_count, BUF_LEN,
			c += scnprintf(buf + c, sz - c,
				"%lums\t\t", mem_info[i + j * idx].worst_time);
				"%lums\t\t", mem_info[i + j * idx].worst_time);
		char_count += snprintf(buf + char_count, BUF_LEN, "\n");
		c += scnprintf(buf + c, sz - c, "\n");
		char_count += snprintf(buf + char_count, BUF_LEN,
		c += scnprintf(buf + c, sz - c,
							"\tSuccess count:\t");
							"\tSuccess count:\t");
		for (i = 0; i <= blk_end - blk_start; i++)
		for (i = 0; i <= tot_blks; i++)
			char_count += snprintf(buf + char_count, BUF_LEN,
			c += scnprintf(buf + c, sz - c,
				"%lu\t\t", mem_info[i + j * idx].success_count);
				"%lu\t\t", mem_info[i + j * idx].success_count);
		char_count += snprintf(buf + char_count, BUF_LEN, "\n");
		c += scnprintf(buf + c, sz - c, "\n");
		char_count += snprintf(buf + char_count, BUF_LEN,
		c += scnprintf(buf + c, sz - c,
							"\tFail count:\t");
							"\tFail count:\t");
		for (i = 0; i <= blk_end - blk_start; i++)
		for (i = 0; i <= tot_blks; i++)
			char_count += snprintf(buf + char_count, BUF_LEN,
			c += scnprintf(buf + c, sz - c,
				"%lu\t\t", mem_info[i + j * idx].fail_count);
				"%lu\t\t", mem_info[i + j * idx].fail_count);
		char_count += snprintf(buf + char_count, BUF_LEN, "\n");
		c += scnprintf(buf + c, sz - c, "\n");
	}

	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");
	}
	}
	return char_count;
	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 =
static struct kobj_attribute stats_attr =
		__ATTR(perf_stats, 0444, show_mem_perf_stats, NULL);
		__ATTR(stats, 0444, show_mem_stats, NULL);


static struct kobj_attribute offline_granule_attr =
static struct kobj_attribute offline_granule_attr =
		__ATTR(offline_granule, 0444, show_mem_offline_granule, NULL);
		__ATTR(offline_granule, 0444, show_mem_offline_granule, NULL);


static struct attribute *mem_root_attrs[] = {
static struct attribute *mem_root_attrs[] = {
		&perf_stats_attr.attr,
		&stats_attr.attr,
		&offline_granule_attr.attr,
		&offline_granule_attr.attr,
		NULL,
		NULL,
};
};
@@ -573,6 +696,7 @@ static int mem_offline_driver_probe(struct platform_device *pdev)
{
{
	unsigned int total_blks;
	unsigned int total_blks;
	int ret, i;
	int ret, i;
	ktime_t now;


	ret = mem_parse_dt(pdev);
	ret = mem_parse_dt(pdev);
	if (ret)
	if (ret)
@@ -592,6 +716,11 @@ static int mem_offline_driver_probe(struct platform_device *pdev)
	if (!mem_info)
	if (!mem_info)
		return -ENOMEM;
		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);
	mem_sec_state = kcalloc(total_blks, sizeof(*mem_sec_state), GFP_KERNEL);
	if (!mem_sec_state) {
	if (!mem_sec_state) {
		ret = -ENOMEM;
		ret = -ENOMEM;