[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/devtools/met-driver/4.4/common/mem_stat.c b/src/devtools/met-driver/4.4/common/mem_stat.c
new file mode 100644
index 0000000..055824e
--- /dev/null
+++ b/src/devtools/met-driver/4.4/common/mem_stat.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+
+#include "met_drv.h"
+#include "mem_stat.h"
+#include "trace.h"
+
+
+/* define MEMSTAT_DEBUG */
+#ifdef MEMSTAT_DEBUG
+#define debug_memstat(fmt, arg...) pr_debug(fmt, ##arg)
+#else
+#define debug_memstat(fmt, arg...) do {} while (0)
+#endif
+
+struct metdevice met_memstat;
+
+unsigned int phy_memstat_mask;
+unsigned int vir_memstat_mask;
+
+#define MAX_PHY_MEMSTAT_EVENT_AMOUNT 6
+#define MAX_VIR_MEMSTAT_EVENT_AMOUNT 6
+
+struct mem_event phy_memstat_table[] = {
+	{FREE_MEM, "free_mem", "Free Memory"}
+};
+
+#define PHY_MEMSTAT_TABLE_SIZE (sizeof(phy_memstat_table) / sizeof(struct mem_event))
+
+struct mem_event vir_memstat_table[] = {
+	{FILE_PAGES, "file_pages", "File Pages"},
+	{FILE_DIRTY, "file_dirty", "FD APP->FS(KB)"},
+	{NUM_DIRTIED, "num_dirtied", "Num Dirtied"},
+	{WRITE_BACK, "write_back", "WB. FS->Block IO(KB)"},
+	{NUM_WRITTEN, "num_written", "Num Written"},
+	{PG_FAULT_CNT, "pg_fault_cnt", "Page Fault Count"}
+};
+
+#define VIR_MEMSTAT_TABLE_SIZE (sizeof(vir_memstat_table) / sizeof(struct mem_event))
+
+int vm_event_counters_enable;
+unsigned long *vm_status;
+static struct delayed_work dwork;
+
+noinline void memstat(unsigned int cnt, unsigned int *value)
+{
+	MET_GENERAL_PRINT(MET_TRACE, cnt, value);
+}
+
+static int get_phy_memstat(unsigned int *value)
+{
+	int i, cnt = 0;
+	struct sysinfo info;
+
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+
+	si_meminfo(&info);
+
+	for (i = 0; i < MAX_PHY_MEMSTAT_EVENT_AMOUNT; i++) {
+		if (phy_memstat_mask & (1 << i)) {
+			switch (i) {
+			case FREE_MEM:
+				value[cnt] = K(info.freeram);
+				break;
+			}
+
+			cnt++;
+		}
+	}
+
+	return cnt;
+}
+
+static int get_vir_memstat(unsigned int *value)
+{
+	int i, cnt = 0;
+
+	for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+		vm_status[i] = global_page_state(i);
+
+	all_vm_events(vm_status + NR_VM_ZONE_STAT_ITEMS);
+
+	for (i = 0; i < MAX_VIR_MEMSTAT_EVENT_AMOUNT; i++) {
+		if (vir_memstat_mask & (1 << i)) {
+			switch (i) {
+			case FILE_PAGES:
+				value[cnt] = vm_status[NR_FILE_PAGES] << (PAGE_SHIFT - 10);
+				break;
+			case FILE_DIRTY:
+				value[cnt] = vm_status[NR_FILE_DIRTY] << (PAGE_SHIFT - 10);
+				break;
+			case NUM_DIRTIED:
+				value[cnt] = vm_status[NR_DIRTIED] << (PAGE_SHIFT - 10);
+				break;
+			case WRITE_BACK:
+				value[cnt] = vm_status[NR_WRITEBACK] << (PAGE_SHIFT - 10);
+				break;
+			case NUM_WRITTEN:
+				value[cnt] = vm_status[NR_WRITTEN] << (PAGE_SHIFT - 10);
+				break;
+			case PG_FAULT_CNT:
+				value[cnt] = vm_status[NR_VM_ZONE_STAT_ITEMS + PGFAULT];
+				break;
+			}
+
+			cnt++;
+		}
+	}
+
+	return cnt;
+}
+
+static void wq_get_memstat(struct work_struct *work)
+{
+	int total_event_amount = 0, phy_event_amount = 0;
+	unsigned int stat_val[MAX_PHY_MEMSTAT_EVENT_AMOUNT + MAX_VIR_MEMSTAT_EVENT_AMOUNT];
+
+	memset(stat_val, 0, sizeof(unsigned int) * (MAX_PHY_MEMSTAT_EVENT_AMOUNT + MAX_VIR_MEMSTAT_EVENT_AMOUNT));
+	total_event_amount = phy_event_amount = get_phy_memstat(stat_val);
+
+	if (vm_event_counters_enable)
+		total_event_amount += get_vir_memstat(&(stat_val[phy_event_amount]));
+
+	if (total_event_amount <= (MAX_PHY_MEMSTAT_EVENT_AMOUNT + MAX_VIR_MEMSTAT_EVENT_AMOUNT))
+		memstat(total_event_amount-1, stat_val);
+}
+
+void met_memstat_polling(unsigned long long stamp, int cpu)
+{
+	schedule_delayed_work(&dwork, 0);
+}
+
+static void met_memstat_start(void)
+{
+	int stat_items_size = 0;
+
+	stat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long);
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+	stat_items_size += sizeof(struct vm_event_state);
+#endif
+
+	vm_status = kmalloc(stat_items_size, GFP_KERNEL);
+	if (vm_status == NULL)
+		return;
+	INIT_DELAYED_WORK(&dwork, wq_get_memstat);
+}
+
+static void met_memstat_stop(void)
+{
+	kfree(vm_status);
+	cancel_delayed_work_sync(&dwork);
+}
+
+static const char help[] =
+"  --memstat=[phy_mem_stat|vir_mem_stat]:event_name enable sampling physical & virtual memory status\n";
+
+static int met_memstat_print_help(char *buf, int len)
+{
+	int i, l;
+
+	l = snprintf(buf, PAGE_SIZE, help);
+
+	for (i = 0; i < PHY_MEMSTAT_TABLE_SIZE; i++)
+		l += snprintf(buf + l, PAGE_SIZE - l, "  --memstat=phy_mem_stat:%s\n",
+			      phy_memstat_table[i].name);
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+	for (i = 0; i < VIR_MEMSTAT_TABLE_SIZE; i++)
+		l += snprintf(buf + l, PAGE_SIZE - l, "  --memstat=vir_mem_stat:%s\n",
+			      vir_memstat_table[i].name);
+#endif
+
+	return l;
+}
+
+static const char header[] = "met-info [000] 0.0: ms_ud_sys_header: memstat,";
+
+
+static int met_memstat_print_header(char *buf, int len)
+{
+	int i, l;
+	int event_amount = 0;
+
+	l = snprintf(buf, PAGE_SIZE, header);
+
+	for (i = 0; i < MAX_PHY_MEMSTAT_EVENT_AMOUNT; i++) {
+		if ((phy_memstat_mask & (1 << i)) && (i < PHY_MEMSTAT_TABLE_SIZE)) {
+			l += snprintf(buf + l, PAGE_SIZE - l, phy_memstat_table[i].header_name);
+			l += snprintf(buf + l, PAGE_SIZE - l, ",");
+			event_amount++;
+		}
+	}
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+	for (i = 0; i < MAX_VIR_MEMSTAT_EVENT_AMOUNT; i++) {
+		if ((vir_memstat_mask & (1 << i)) && (i < VIR_MEMSTAT_TABLE_SIZE)) {
+			l += snprintf(buf + l, PAGE_SIZE - l, vir_memstat_table[i].header_name);
+			l += snprintf(buf + l, PAGE_SIZE - l, ",");
+			event_amount++;
+		}
+	}
+#endif
+
+	for (i = 0; i < event_amount; i++) {
+		l += snprintf(buf + l, PAGE_SIZE - l, "x");
+		l += snprintf(buf + l, PAGE_SIZE - l, ",");
+	}
+
+	phy_memstat_mask = 0;
+	vir_memstat_mask = 0;
+
+	l += snprintf(buf + l, PAGE_SIZE - l, "\n");
+
+	return l;
+}
+
+static int met_memstat_process_argument(const char *arg, int len)
+{
+	int i, found_event = 0;
+	char choice[16], event[32];
+	char *pch;
+	int str_len;
+
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+	vm_event_counters_enable = 1;
+#endif
+
+	pch = strchr(arg, ':');
+	if (pch == NULL)
+		goto error;
+
+	memset(choice, 0, sizeof(choice));
+	memset(event, 0, sizeof(event));
+
+	str_len = (int)(pch - arg);
+	memcpy(choice, arg, str_len);
+	memcpy(event, arg + str_len + 1, len - (str_len + 1));
+
+	if (strncmp(choice, "phy_mem_stat", 12) == 0) {
+		for (i = 0; i < PHY_MEMSTAT_TABLE_SIZE; i++) {
+			if (strncmp(event, phy_memstat_table[i].name, MAX_EVENT_NAME_LEN) == 0) {
+				phy_memstat_mask |= (1 << phy_memstat_table[i].id);
+				found_event = 1;
+
+				break;
+			}
+		}
+	} else if (strncmp(choice, "vir_mem_stat", 12) == 0) {
+		if (!vm_event_counters_enable) {
+			pr_debug("[%s] %d: CONFIG_VM_EVENT_COUNTERS is not configured\n", __func__,
+				 __LINE__);
+			goto error;
+		}
+
+		for (i = 0; i < VIR_MEMSTAT_TABLE_SIZE; i++) {
+			if (strncmp(event, vir_memstat_table[i].name, MAX_EVENT_NAME_LEN) == 0) {
+				vir_memstat_mask |= (1 << vir_memstat_table[i].id);
+				found_event = 1;
+
+				break;
+			}
+		}
+	} else {
+		pr_debug("[%s] %d: only support phy_mem_stat & vir_mem_stat keyword\n", __func__,
+			 __LINE__);
+		goto error;
+	}
+
+	if (!found_event) {
+		pr_debug("[%s] %d: input event name error\n", __func__, __LINE__);
+		goto error;
+	}
+
+	met_memstat.mode = 1;
+	return 0;
+
+error:
+	met_memstat.mode = 0;
+	return -EINVAL;
+}
+
+struct metdevice met_memstat = {
+	.name = "memstat",
+	.type = MET_TYPE_PMU,
+	.cpu_related = 0,
+	.start = met_memstat_start,
+	.stop = met_memstat_stop,
+	.polling_interval = 1,
+	.timed_polling = met_memstat_polling,
+	.tagged_polling = met_memstat_polling,
+	.print_help = met_memstat_print_help,
+	.print_header = met_memstat_print_header,
+	.process_argument = met_memstat_process_argument
+};