summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--energy/Kbuild7
-rw-r--r--energy/debugfs_energy.c210
-rw-r--r--energy/energy.c486
-rw-r--r--energy/energy.h14
-rw-r--r--energy/lcd/sprdfb_panel.c186
-rw-r--r--master/Kbuild3
-rw-r--r--master/swap_deps.c69
-rw-r--r--master/swap_deps.h38
-rw-r--r--master/swap_initializer.c5
-rw-r--r--parser/swap_msg_parser.c4
-rw-r--r--parser/usm_msg.c29
-rw-r--r--parser/usm_msg.h1
-rw-r--r--preload/preload_control.c31
-rw-r--r--preload/preload_debugfs.c2
14 files changed, 1027 insertions, 58 deletions
diff --git a/energy/Kbuild b/energy/Kbuild
index 80d23c9c..9206079f 100644
--- a/energy/Kbuild
+++ b/energy/Kbuild
@@ -39,6 +39,13 @@ ifeq ($(CONFIG_DISPLAY_PANEL_S6E8AA0), y)
endif
+## FB_SCX30G
+ifeq ($(CONFIG_FB_SCX30G), y)
+ swap_energy-y += lcd/sprdfb_panel.o
+ LCD_FUNC_LIST += sprdfb_panel
+endif
+
+
# MARU:
ifeq ($(CONFIG_MARU_BACKLIGHT), y)
swap_energy-y += lcd/maru.o
diff --git a/energy/debugfs_energy.c b/energy/debugfs_energy.c
index 02784451..b6140cb6 100644
--- a/energy/debugfs_energy.c
+++ b/energy/debugfs_energy.c
@@ -39,15 +39,28 @@
static DEFINE_RATIONAL(cpu0_running_coef); /* boot core uses distinct coeff */
static DEFINE_RATIONAL(cpuN_running_coef);
-static u64 __energy_cpu(enum parameter_energy pe)
+static u64 __energy_cpu0(enum parameter_energy pe)
{
u64 times[NR_CPUS] = { 0 };
u64 val = 0;
- int i;
+ /* TODO: make for only cpu0 */
if (get_parameter_energy(pe, times, sizeof(times)) == 0) {
val = div_u64(times[0] * cpu0_running_coef.num,
cpu0_running_coef.denom);
+ }
+
+ return val;
+}
+
+static u64 __energy_cpuN(enum parameter_energy pe)
+{
+ u64 times[NR_CPUS] = { 0 };
+ u64 val = 0;
+
+ if (get_parameter_energy(pe, times, sizeof(times)) == 0) {
+ int i;
+
for (i = 1; i < NR_CPUS; i++)
val += div_u64(times[i] * cpuN_running_coef.num,
cpuN_running_coef.denom);
@@ -56,14 +69,24 @@ static u64 __energy_cpu(enum parameter_energy pe)
return val;
}
-static u64 cpu_system(void)
+static u64 cpu0_system(void)
+{
+ return __energy_cpu0(PE_TIME_SYSTEM);
+}
+
+static u64 cpuN_system(void)
+{
+ return __energy_cpuN(PE_TIME_SYSTEM);
+}
+
+static u64 cpu0_apps(void)
{
- return __energy_cpu(PE_TIME_SYSTEM);
+ return __energy_cpu0(PE_TIME_APPS);
}
-static u64 cpu_apps(void)
+static u64 cpuN_apps(void)
{
- return __energy_cpu(PE_TIME_APPS);
+ return __energy_cpuN(PE_TIME_APPS);
}
@@ -119,6 +142,137 @@ static u64 fw_apps(void)
}
+/* wifi recv */
+static DEFINE_RATIONAL(wf_recv_coef);
+
+static u64 wf_recv_system(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PE_WF_RECV_SYSTEM, &byte, sizeof(byte));
+
+ return div_u64(byte * wf_recv_coef.num, wf_recv_coef.denom);
+}
+
+static u64 wf_recv_apps(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PE_WF_RECV_APPS, &byte, sizeof(byte));
+
+ return div_u64(byte * wf_recv_coef.num, wf_recv_coef.denom);
+}
+
+/* wifi send */
+static DEFINE_RATIONAL(wf_send_coef);
+
+static u64 wf_send_system(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PE_WF_SEND_SYSTEM, &byte, sizeof(byte));
+
+ return div_u64(byte * wf_send_coef.num, wf_send_coef.denom);
+}
+
+static u64 wf_send_apps(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PE_WF_SEND_APPS, &byte, sizeof(byte));
+
+ return div_u64(byte * wf_send_coef.num, wf_send_coef.denom);
+}
+
+/* l2cap_recv_acldata */
+static DEFINE_RATIONAL(l2cap_recv_acldata_coef);
+
+static u64 l2cap_recv_acldata_system(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PE_L2CAP_RECV_SYSTEM, &byte, sizeof(byte));
+
+ return div_u64(byte * l2cap_recv_acldata_coef.num,
+ l2cap_recv_acldata_coef.denom);
+}
+
+static u64 l2cap_recv_acldata_apps(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PE_L2CAP_RECV_APPS, &byte, sizeof(byte));
+
+ return div_u64(byte * l2cap_recv_acldata_coef.num,
+ l2cap_recv_acldata_coef.denom);
+}
+
+/* sco_recv_scodata */
+static DEFINE_RATIONAL(sco_recv_scodata_coef);
+
+static u64 sco_recv_scodata_system(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PE_SCO_RECV_SYSTEM, &byte, sizeof(byte));
+
+ return div_u64(byte * sco_recv_scodata_coef.num,
+ sco_recv_scodata_coef.denom);
+}
+
+static u64 sco_recv_scodata_apps(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PE_SCO_RECV_APPS, &byte, sizeof(byte));
+
+ return div_u64(byte * sco_recv_scodata_coef.num,
+ sco_recv_scodata_coef.denom);
+}
+
+/* hci_send_acl */
+static DEFINE_RATIONAL(hci_send_acl_coef);
+
+static u64 hci_send_acl_system(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PT_SEND_ACL_SYSTEM, &byte, sizeof(byte));
+
+ return div_u64(byte * hci_send_acl_coef.num, hci_send_acl_coef.denom);
+}
+
+static u64 hci_send_acl_apps(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PT_SEND_ACL_APPS, &byte, sizeof(byte));
+
+ return div_u64(byte * hci_send_acl_coef.num, hci_send_acl_coef.denom);
+}
+
+/* hci_send_sco */
+static DEFINE_RATIONAL(hci_send_sco_coef);
+
+static u64 hci_send_sco_system(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PT_SEND_SCO_SYSTEM, &byte, sizeof(byte));
+
+ return div_u64(byte * hci_send_sco_coef.num, hci_send_sco_coef.denom);
+}
+
+static u64 hci_send_sco_apps(void)
+{
+ u64 byte = 0;
+
+ get_parameter_energy(PT_SEND_SCO_APPS, &byte, sizeof(byte));
+
+ return div_u64(byte * hci_send_sco_coef.num, hci_send_sco_coef.denom);
+}
+
+
@@ -185,14 +339,14 @@ struct param_data parameters[] = {
{
.name = "cpu_running",
.coef = &cpu0_running_coef,
- .system = cpu_system,
- .apps = cpu_apps
+ .system = cpu0_system,
+ .apps = cpu0_apps
},
{
.name = "cpuN_running",
.coef = &cpuN_running_coef,
- .system = cpu_system,
- .apps = cpu_apps
+ .system = cpuN_system,
+ .apps = cpuN_apps
},
{
.name = "cpu_idle",
@@ -211,6 +365,42 @@ struct param_data parameters[] = {
.coef = &fw_coef,
.system = fw_system,
.apps = fw_apps
+ },
+ {
+ .name = "wf_recv",
+ .coef = &wf_recv_coef,
+ .system = wf_recv_system,
+ .apps = wf_recv_apps
+ },
+ {
+ .name = "wf_send",
+ .coef = &wf_send_coef,
+ .system = wf_send_system,
+ .apps = wf_send_apps
+ },
+ {
+ .name = "sco_recv_scodata",
+ .coef = &sco_recv_scodata_coef,
+ .system = sco_recv_scodata_system,
+ .apps = sco_recv_scodata_apps
+ },
+ {
+ .name = "l2cap_recv_acldata",
+ .coef = &l2cap_recv_acldata_coef,
+ .system = l2cap_recv_acldata_system,
+ .apps = l2cap_recv_acldata_apps
+ },
+ {
+ .name = "hci_send_acl",
+ .coef = &hci_send_acl_coef,
+ .system = hci_send_acl_system,
+ .apps = hci_send_acl_apps
+ },
+ {
+ .name = "hci_send_sco",
+ .coef = &hci_send_sco_coef,
+ .system = hci_send_sco_system,
+ .apps = hci_send_sco_apps
}
};
diff --git a/energy/energy.c b/energy/energy.c
index 3192f191..6eb863cb 100644
--- a/energy/energy.c
+++ b/energy/energy.c
@@ -30,8 +30,15 @@
#include <linux/magic.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/net.h>
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/fdtable.h>
+#include <net/sock.h>
#include <kprobe/swap_kprobes.h>
#include <ksyms/ksyms.h>
+#include <master/swap_deps.h>
#include <us_manager/sspt/sspt_proc.h>
#include <us_manager/sspt/sspt_feature.h>
#include <linux/atomic.h>
@@ -41,6 +48,75 @@
/* ============================================================================
+ * = ENERGY_XXX =
+ * ============================================================================
+ */
+struct kern_probe {
+ const char *name;
+ struct kretprobe *rp;
+};
+
+static int energy_xxx_once(struct kern_probe p[], int size)
+{
+ int i;
+ const char *sym;
+
+ for (i = 0; i < size; ++i) {
+ struct kretprobe *rp = p[i].rp;
+
+ sym = p[i].name;
+ rp->kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
+ if (rp->kp.addr == NULL)
+ goto not_found;
+ }
+
+ return 0;
+
+not_found:
+ printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);
+ return -ESRCH;
+}
+
+static int energy_xxx_set(struct kern_probe p[], int size, int *flag)
+{
+ int i, ret;
+
+ for (i = 0; i < size; ++i) {
+ ret = swap_register_kretprobe(p[i].rp);
+ if (ret)
+ goto fail;
+ }
+
+ *flag = 1;
+ return 0;
+
+fail:
+ pr_err("swap_register_kretprobe(%s) ret=%d\n", p[i].name, ret);
+
+ for (--i; i != -1; --i)
+ swap_unregister_kretprobe(p[i].rp);
+
+ return ret;
+}
+
+static void energy_xxx_unset(struct kern_probe p[], int size, int *flag)
+{
+ int i;
+
+ if (*flag == 0)
+ return;
+
+ for (i = size - 1; i != -1; --i)
+ swap_unregister_kretprobe(p[i].rp);
+
+ *flag = 0;
+}
+
+
+
+
+
+/* ============================================================================
* = CPUS_TIME =
* ============================================================================
*/
@@ -130,6 +206,23 @@ struct energy_data {
/*for sys_write */
atomic64_t bytes_written;
+ /*for recvmsg*/
+ atomic64_t bytes_recv;
+
+ /* for sock_send */
+ atomic64_t bytes_send;
+
+ /* for l2cap_recv */
+ atomic64_t bytes_l2cap_recv_acldata;
+
+ /* for sco_recv_scodata */
+ atomic64_t bytes_sco_recv_scodata;
+
+ /* for hci_send_acl */
+ atomic64_t bytes_hci_send_acl;
+
+ /* for hci_send_sco */
+ atomic64_t bytes_hci_send_sco;
};
static sspt_feature_id_t feature_id = SSPT_FEATURE_ID_BAD;
@@ -142,6 +235,12 @@ static void init_ed(struct energy_data *ed)
cpus_time_init(&ed->ct, 0);
atomic64_set(&ed->bytes_read, 0);
atomic64_set(&ed->bytes_written, 0);
+ atomic64_set(&ed->bytes_recv, 0);
+ atomic64_set(&ed->bytes_send, 0);
+ atomic64_set(&ed->bytes_l2cap_recv_acldata, 0);
+ atomic64_set(&ed->bytes_sco_recv_scodata, 0);
+ atomic64_set(&ed->bytes_hci_send_acl, 0);
+ atomic64_set(&ed->bytes_hci_send_sco, 0);
}
static void uninit_ed(struct energy_data *ed)
@@ -149,6 +248,12 @@ static void uninit_ed(struct energy_data *ed)
cpus_time_init(&ed->ct, 0);
atomic64_set(&ed->bytes_read, 0);
atomic64_set(&ed->bytes_written, 0);
+ atomic64_set(&ed->bytes_recv, 0);
+ atomic64_set(&ed->bytes_send, 0);
+ atomic64_set(&ed->bytes_l2cap_recv_acldata, 0);
+ atomic64_set(&ed->bytes_sco_recv_scodata, 0);
+ atomic64_set(&ed->bytes_hci_send_acl, 0);
+ atomic64_set(&ed->bytes_hci_send_sco, 0);
}
static void *create_ed(void)
@@ -439,10 +544,327 @@ static struct kretprobe sys_write_krp = {
+/* ============================================================================
+ * = wifi =
+ * ============================================================================
+ */
+static bool check_wlan0(struct socket *sock)
+{
+ /* FIXME: hardcode interface */
+ const char *name_intrf = "wlan0";
+
+ if (sock->sk->sk_dst_cache &&
+ sock->sk->sk_dst_cache->dev &&
+ !strcmp(sock->sk->sk_dst_cache->dev->name, name_intrf))
+ return true;
+
+ return false;
+}
+
+static bool check_socket(struct task_struct *task, struct socket *socket)
+{
+ bool ret = false;
+ unsigned int fd;
+ struct files_struct *files;
+
+ files = swap_get_files_struct(task);
+ if (files == NULL)
+ return false;
+
+ rcu_read_lock();
+ for (fd = 0; fd < files_fdtable(files)->max_fds; ++fd) {
+ if (fcheck_files(files, fd) == socket->file) {
+ ret = true;
+ goto unlock;
+ }
+ }
+
+unlock:
+ rcu_read_unlock();
+ swap_put_files_struct(files);
+ return ret;
+}
+
+static struct energy_data *get_energy_data_by_socket(struct task_struct *task,
+ struct socket *socket)
+{
+ struct energy_data *ed;
+
+ ed = get_energy_data(task);
+ if (ed)
+ ed = check_socket(task, socket) ? ed : NULL;
+
+ return ed;
+}
+
+static int wf_sock_eh(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ struct socket *socket = (struct socket *)swap_get_karg(regs, 0);
+
+ *(struct socket **)ri->data = check_wlan0(socket) ? socket : NULL;
+
+ return 0;
+}
+
+static int wf_sock_aio_eh(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ struct kiocb *iocb = (struct kiocb *)swap_get_karg(regs, 0);
+ struct socket *socket = iocb->ki_filp->private_data;
+
+ *(struct socket **)ri->data = check_wlan0(socket) ? socket : NULL;
+
+ return 0;
+}
+
+static int wf_sock_recv_rh(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ int ret = regs_return_value(regs);
+
+ if (ret > 0) {
+ struct socket *socket = *(struct socket **)ri->data;
+
+ if (socket) {
+ struct energy_data *ed;
+
+ ed = get_energy_data_by_socket(current, socket);
+ if (ed)
+ atomic64_add(ret, &ed->bytes_recv);
+ atomic64_add(ret, &ed_system.bytes_recv);
+ }
+ }
+
+ return 0;
+}
+
+static int wf_sock_send_rh(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ int ret = regs_return_value(regs);
+
+ if (ret > 0) {
+ struct socket *socket = *(struct socket **)ri->data;
+
+ if (socket) {
+ struct energy_data *ed;
+
+ ed = get_energy_data_by_socket(current, socket);
+ if (ed)
+ atomic64_add(ret, &ed->bytes_send);
+ atomic64_add(ret, &ed_system.bytes_send);
+ }
+ }
+
+ return 0;
+}
+
+static struct kretprobe sock_recv_krp = {
+ .entry_handler = wf_sock_eh,
+ .handler = wf_sock_recv_rh,
+ .data_size = sizeof(struct socket *)
+};
+
+static struct kretprobe sock_send_krp = {
+ .entry_handler = wf_sock_eh,
+ .handler = wf_sock_send_rh,
+ .data_size = sizeof(struct socket *)
+};
+
+static struct kretprobe sock_aio_read_krp = {
+ .entry_handler = wf_sock_aio_eh,
+ .handler = wf_sock_recv_rh,
+ .data_size = sizeof(struct socket *)
+};
+
+static struct kretprobe sock_aio_write_krp = {
+ .entry_handler = wf_sock_aio_eh,
+ .handler = wf_sock_send_rh,
+ .data_size = sizeof(struct socket *)
+};
+
+static struct kern_probe wifi_probes[] = {
+ {
+ .name = "sock_recvmsg",
+ .rp = &sock_recv_krp,
+ },
+ {
+ .name = "sock_sendmsg",
+ .rp = &sock_send_krp,
+ },
+ {
+ .name = "sock_aio_read",
+ .rp = &sock_aio_read_krp,
+ },
+ {
+ .name = "sock_aio_write",
+ .rp = &sock_aio_write_krp,
+ }
+};
+
+enum { wifi_probes_cnt = ARRAY_SIZE(wifi_probes) };
+static int wifi_flag = 0;
+
+
+
+
+
+/* ============================================================================
+ * = bluetooth =
+ * ============================================================================
+ */
+
+struct swap_bt_data {
+ struct socket *socket;
+};
+
+static int bt_entry_handler(struct kretprobe_instance *ri,
+ struct pt_regs *regs)
+{
+ struct swap_bt_data *data = (struct swap_bt_data *)ri->data;
+ struct socket *sock = (struct socket *)swap_get_sarg(regs, 1);
+
+ data->socket = sock ? sock : NULL;
+
+ return 0;
+}
+
+static int bt_recvmsg_handler(struct kretprobe_instance *ri,
+ struct pt_regs *regs)
+{
+ int ret = regs_return_value(regs);
+ struct swap_bt_data *data = (struct swap_bt_data *)ri->data;
+
+ if (ret > 0) {
+ struct socket *socket = data->socket;
+
+ if (socket) {
+ struct energy_data *ed;
+
+ ed = get_energy_data_by_socket(current, socket);
+ if (ed)
+ atomic64_add(ret, &ed->bytes_l2cap_recv_acldata);
+ }
+ atomic64_add(ret, &ed_system.bytes_l2cap_recv_acldata);
+ }
+
+ return 0;
+}
+
+static int bt_sendmsg_handler(struct kretprobe_instance *ri,
+ struct pt_regs *regs)
+{
+ int ret = regs_return_value(regs);
+ struct swap_bt_data *data = (struct swap_bt_data *)ri->data;
+
+ if (ret > 0) {
+ struct socket *socket = data->socket;
+
+ if (socket) {
+ struct energy_data *ed;
+
+ ed = get_energy_data_by_socket(current, socket);
+ if (ed)
+ atomic64_add(ret, &ed->bytes_hci_send_sco);
+ }
+ atomic64_add(ret, &ed_system.bytes_hci_send_sco);
+ }
+
+ return 0;
+}
+
+static struct kretprobe rfcomm_sock_recvmsg_krp = {
+ .entry_handler = bt_entry_handler,
+ .handler = bt_recvmsg_handler,
+ .data_size = sizeof(struct swap_bt_data)
+};
+
+static struct kretprobe l2cap_sock_recvmsg_krp = {
+ .entry_handler = bt_entry_handler,
+ .handler = bt_recvmsg_handler,
+ .data_size = sizeof(struct swap_bt_data)
+};
+
+static struct kretprobe hci_sock_recvmsg_krp = {
+ .entry_handler = bt_entry_handler,
+ .handler = bt_recvmsg_handler,
+ .data_size = sizeof(struct swap_bt_data)
+};
+
+static struct kretprobe sco_sock_recvmsg_krp = {
+ .entry_handler = bt_entry_handler,
+ .handler = bt_recvmsg_handler,
+ .data_size = sizeof(struct swap_bt_data)
+};
+static struct kretprobe rfcomm_sock_sendmsg_krp = {
+ .entry_handler = bt_entry_handler,
+ .handler = bt_sendmsg_handler,
+ .data_size = sizeof(struct swap_bt_data)
+};
+
+static struct kretprobe l2cap_sock_sendmsg_krp = {
+ .entry_handler = bt_entry_handler,
+ .handler = bt_sendmsg_handler,
+ .data_size = sizeof(struct swap_bt_data)
+};
+
+static struct kretprobe hci_sock_sendmsg_krp = {
+ .entry_handler = bt_entry_handler,
+ .handler = bt_sendmsg_handler,
+ .data_size = sizeof(struct swap_bt_data)
+};
+
+static struct kretprobe sco_sock_sendmsg_krp = {
+ .entry_handler = bt_entry_handler,
+ .handler = bt_sendmsg_handler,
+ .data_size = sizeof(struct swap_bt_data)
+};
+
+static struct kern_probe bt_probes[] = {
+ {
+ .name = "rfcomm_sock_recvmsg",
+ .rp = &rfcomm_sock_recvmsg_krp,
+ },
+ {
+ .name = "l2cap_sock_recvmsg",
+ .rp = &l2cap_sock_recvmsg_krp,
+ },
+ {
+ .name = "hci_sock_recvmsg",
+ .rp = &hci_sock_recvmsg_krp,
+ },
+ {
+ .name = "sco_sock_recvmsg",
+ .rp = &sco_sock_recvmsg_krp,
+ },
+ {
+ .name = "rfcomm_sock_sendmsg",
+ .rp = &rfcomm_sock_sendmsg_krp,
+ },
+ {
+ .name = "l2cap_sock_sendmsg",
+ .rp = &l2cap_sock_sendmsg_krp,
+ },
+ {
+ .name = "hci_sock_sendmsg",
+ .rp = &hci_sock_sendmsg_krp,
+ },
+ {
+ .name = "sco_sock_sendmsg",
+ .rp = &sco_sock_sendmsg_krp,
+ }
+};
+
+enum { bt_probes_cnt = ARRAY_SIZE(bt_probes) };
+static int energy_bt_flag = 0;
+
enum parameter_type {
PT_CPU,
PT_READ,
- PT_WRITE
+ PT_WRITE,
+ PT_WF_RECV,
+ PT_WF_SEND,
+ PT_L2CAP_RECV,
+ PT_SCO_RECV,
+ PT_SEND_ACL,
+ PT_SEND_SCO
};
struct cmd_pt {
@@ -473,6 +895,24 @@ static void callback_for_proc(struct sspt_proc *proc, void *data)
case PT_WRITE:
*val += atomic64_read(&ed->bytes_written);
break;
+ case PT_WF_RECV:
+ *val += atomic64_read(&ed->bytes_recv);
+ break;
+ case PT_WF_SEND:
+ *val += atomic64_read(&ed->bytes_send);
+ break;
+ case PT_L2CAP_RECV:
+ *val += atomic64_read(&ed->bytes_l2cap_recv_acldata);
+ break;
+ case PT_SCO_RECV:
+ *val += atomic64_read(&ed->bytes_sco_recv_scodata);
+ break;
+ case PT_SEND_ACL:
+ *val += atomic64_read(&ed->bytes_hci_send_acl);
+ break;
+ case PT_SEND_SCO:
+ *val += atomic64_read(&ed->bytes_hci_send_sco);
+ break;
default:
break;
}
@@ -527,12 +967,48 @@ int get_parameter_energy(enum parameter_energy pe, void *buf, size_t sz)
case PE_WRITE_SYSTEM:
*val = atomic64_read(&ed_system.bytes_written);
break;
+ case PE_WF_RECV_SYSTEM:
+ *val = atomic64_read(&ed_system.bytes_recv);
+ break;
+ case PE_WF_SEND_SYSTEM:
+ *val = atomic64_read(&ed_system.bytes_send);
+ break;
+ case PE_L2CAP_RECV_SYSTEM:
+ *val = atomic64_read(&ed_system.bytes_l2cap_recv_acldata);
+ break;
+ case PE_SCO_RECV_SYSTEM:
+ *val = atomic64_read(&ed_system.bytes_sco_recv_scodata);
+ break;
+ case PT_SEND_ACL_SYSTEM:
+ *val = atomic64_read(&ed_system.bytes_hci_send_acl);
+ break;
+ case PT_SEND_SCO_SYSTEM:
+ *val = atomic64_read(&ed_system.bytes_hci_send_sco);
+ break;
case PE_READ_APPS:
current_parameter_apps(PT_READ, buf, sz);
break;
case PE_WRITE_APPS:
current_parameter_apps(PT_WRITE, buf, sz);
break;
+ case PE_WF_RECV_APPS:
+ current_parameter_apps(PT_WF_RECV, buf, sz);
+ break;
+ case PE_WF_SEND_APPS:
+ current_parameter_apps(PT_WF_SEND, buf, sz);
+ break;
+ case PE_L2CAP_RECV_APPS:
+ current_parameter_apps(PT_L2CAP_RECV, buf, sz);
+ break;
+ case PE_SCO_RECV_APPS:
+ current_parameter_apps(PT_SCO_RECV, buf, sz);
+ break;
+ case PT_SEND_ACL_APPS:
+ current_parameter_apps(PT_SEND_ACL, buf, sz);
+ break;
+ case PT_SEND_SCO_APPS:
+ current_parameter_apps(PT_SEND_SCO, buf, sz);
+ break;
default:
ret = -EINVAL;
break;
@@ -569,6 +1045,9 @@ int do_set_energy(void)
goto unregister_sys_write;
}
+ energy_xxx_set(bt_probes, bt_probes_cnt, &energy_bt_flag);
+ energy_xxx_set(wifi_probes, wifi_probes_cnt, &wifi_flag);
+
/* TODO: check return value */
lcd_set_energy();
@@ -586,6 +1065,8 @@ unregister_sys_write:
void do_unset_energy(void)
{
lcd_unset_energy();
+ energy_xxx_unset(wifi_probes, wifi_probes_cnt, &wifi_flag);
+ energy_xxx_unset(bt_probes, bt_probes_cnt, &energy_bt_flag);
swap_unregister_kretprobe(&switch_to_krp);
swap_unregister_kretprobe(&sys_write_krp);
@@ -668,6 +1149,9 @@ int energy_once(void)
if (sys_write_krp.kp.addr == NULL)
goto not_found;
+ energy_xxx_once(bt_probes, bt_probes_cnt);
+ energy_xxx_once(wifi_probes, wifi_probes_cnt);
+
return 0;
not_found:
diff --git a/energy/energy.h b/energy/energy.h
index 9626d1d4..7466570d 100644
--- a/energy/energy.h
+++ b/energy/energy.h
@@ -39,7 +39,19 @@ enum parameter_energy {
PE_READ_SYSTEM, /**< number of bytes are read by system */
PE_WRITE_SYSTEM, /**< number of bytes are write by system */
PE_READ_APPS, /**< number of bytes are read by apps */
- PE_WRITE_APPS /**< number of bytes are write by apps*/
+ PE_WRITE_APPS, /**< number of bytes are write by apps */
+ PE_WF_RECV_SYSTEM, /**< number of bytes are receive by system through wifi */
+ PE_WF_SEND_SYSTEM, /**< number of bytes are send by system through wifi */
+ PE_WF_RECV_APPS, /**< number of bytes are receive by apps through wifi */
+ PE_WF_SEND_APPS, /**< number of bytes are send by apps through wifi */
+ PE_L2CAP_RECV_SYSTEM, /**< number of bytes(ACL packets) are recv by system through bluetooth */
+ PE_L2CAP_RECV_APPS, /**< number of bytes(ACL packets) are recv by apps through bluetooth */
+ PE_SCO_RECV_SYSTEM, /**< number of bytes(SCO packets) are recv by system through bluetooth */
+ PE_SCO_RECV_APPS, /**< number of bytes(SCO packets) are recv by apps through bluetooth */
+ PT_SEND_ACL_SYSTEM, /**< number of bytes(ACL packets) are send by system through bluetooth */
+ PT_SEND_ACL_APPS, /**< number of bytes(ACL packets) are send by apps through bluetooth */
+ PT_SEND_SCO_SYSTEM, /**< number of bytes(SCO packets) are send by system through bluetooth */
+ PT_SEND_SCO_APPS, /**< number of bytes(SCO packets) are send by apps through bluetooth */
};
diff --git a/energy/lcd/sprdfb_panel.c b/energy/lcd/sprdfb_panel.c
new file mode 100644
index 00000000..4e503e01
--- /dev/null
+++ b/energy/lcd/sprdfb_panel.c
@@ -0,0 +1,186 @@
+/*
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/backlight.h>
+#include <kprobe/swap_kprobes.h>
+#include "lcd_base.h"
+
+
+static const char path_backlight[] = "/sys/class/backlight/panel/brightness";
+static const char path_backlight_max[] = "/sys/class/backlight/panel/max_brightness";
+static const char path_power[] = "/sys/class/lcd/panel/lcd_power";
+
+static const char * const all_path[] = {
+ path_backlight,
+ path_backlight_max,
+ path_power
+};
+
+
+static int sprdfb_panel_check(struct lcd_ops *ops)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(all_path); ++i) {
+ int ret = read_val(all_path[i]);
+
+ if (IS_ERR_VALUE(ret))
+ return 0;
+ }
+
+ return 1;
+}
+
+static unsigned long sprdfb_panel_get_parameter(struct lcd_ops *ops,
+ enum lcd_parameter_type type)
+{
+ switch (type) {
+ case LPD_MIN_BRIGHTNESS:
+ return 0;
+ case LPD_MAX_BRIGHTNESS:
+ return read_val(path_backlight_max);
+ case LPD_BRIGHTNESS:
+ return read_val(path_backlight);
+ case LPD_POWER:
+ return read_val(path_power);
+ }
+
+ return -EINVAL;
+}
+
+static int set_power_eh(struct kretprobe_instance *ri, struct pt_regs *regs);
+static int set_power_rh(struct kretprobe_instance *ri, struct pt_regs *regs);
+
+static struct kretprobe set_power_krp = {
+ .kp.symbol_name = "sprdfb_set_power",
+ .entry_handler = set_power_eh,
+ .handler = set_power_rh,
+ .data_size = sizeof(int)
+};
+
+
+static int set_backlight_eh(struct kretprobe_instance *ri, struct pt_regs *regs);
+static int set_backlight_rh(struct kretprobe_instance *ri, struct pt_regs *regs);
+
+static struct kretprobe set_backlight_krp = {
+ .kp.symbol_name = "panel_update_brightness",
+ .entry_handler = set_backlight_eh,
+ .handler = set_backlight_rh,
+ .data_size = sizeof(int)
+};
+
+
+int sprdfb_panel_set(struct lcd_ops *ops)
+{
+ int ret;
+
+ ret = swap_register_kretprobe(&set_power_krp);
+ if (ret)
+ return ret;
+
+ ret = swap_register_kretprobe(&set_backlight_krp);
+ if (ret)
+ swap_unregister_kretprobe(&set_power_krp);
+
+ return ret;
+}
+
+int sprdfb_panel_unset(struct lcd_ops *ops)
+{
+ swap_unregister_kretprobe(&set_backlight_krp);
+ swap_unregister_kretprobe(&set_power_krp);
+
+ return 0;
+}
+
+
+static struct lcd_ops sprdfb_panel_ops = {
+ .name = "sprdfb_panel",
+ .check = sprdfb_panel_check,
+ .set = sprdfb_panel_set,
+ .unset = sprdfb_panel_unset,
+ .get = sprdfb_panel_get_parameter
+};
+
+struct lcd_ops *LCD_MAKE_FNAME(sprdfb_panel)(void)
+{
+ return &sprdfb_panel_ops;
+}
+
+
+
+
+
+/* ============================================================================
+ * === POWER ===
+ * ============================================================================
+ */
+static int set_power_eh(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ int *power = (int *)ri->data;
+
+ *power = (int)swap_get_karg(regs, 1);
+
+ return 0;
+}
+
+static int set_power_rh(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ int ret = regs_return_value(regs);
+ int *power = (int *)ri->data;
+
+ if (!ret && sprdfb_panel_ops.notifier)
+ sprdfb_panel_ops.notifier(&sprdfb_panel_ops, LAT_POWER,
+ (void *)*power);
+ return 0;
+}
+
+
+
+
+
+/* ============================================================================
+ * === BACKLIGHT ===
+ * ============================================================================
+ */
+static int set_backlight_eh(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ int *brightness = (int *)ri->data;
+ struct backlight_device *bd;
+
+ bd = (struct backlight_device *)swap_get_karg(regs, 0);
+ *brightness = bd->props.brightness;
+
+ return 0;
+}
+
+static int set_backlight_rh(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ int ret = regs_return_value(regs);
+ int *brightness = (int *)ri->data;
+
+ if (!ret && sprdfb_panel_ops.notifier)
+ sprdfb_panel_ops.notifier(&sprdfb_panel_ops, LAT_BRIGHTNESS,
+ (void *)*brightness);
+
+ return 0;
+}
diff --git a/master/Kbuild b/master/Kbuild
index 83733a74..cd1b1c57 100644
--- a/master/Kbuild
+++ b/master/Kbuild
@@ -3,4 +3,5 @@ EXTRA_CFLAGS := $(extra_cflags)
obj-m := swap_master.o
swap_master-y := master_module.o \
swap_debugfs.o \
- swap_initializer.o
+ swap_initializer.o \
+ swap_deps.o
diff --git a/master/swap_deps.c b/master/swap_deps.c
new file mode 100644
index 00000000..0c566c14
--- /dev/null
+++ b/master/swap_deps.c
@@ -0,0 +1,69 @@
+/*
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/module.h>
+#include <ksyms/ksyms.h>
+#include "swap_deps.h"
+
+
+static struct files_struct *(*__get_files_struct)(struct task_struct *);
+static void (*__put_files_struct)(struct files_struct *fs);
+
+struct files_struct *swap_get_files_struct(struct task_struct *task)
+{
+ return __get_files_struct(task);
+}
+EXPORT_SYMBOL_GPL(swap_get_files_struct);
+
+void swap_put_files_struct(struct files_struct *fs)
+{
+ __put_files_struct(fs);
+}
+EXPORT_SYMBOL_GPL(swap_put_files_struct);
+
+
+int chef_once(void)
+{
+ const char *sym;
+ static unsigned once_flag = 0;
+
+ if (once_flag)
+ return 0;
+
+ sym = "get_files_struct";
+ __get_files_struct = (void *)swap_ksyms(sym);
+ if (__get_files_struct == NULL)
+ goto not_found;
+
+ sym = "put_files_struct";
+ __put_files_struct = (void *)swap_ksyms(sym);
+ if (__put_files_struct == NULL)
+ goto not_found;
+
+ once_flag = 1;
+ return 0;
+
+not_found:
+ printk("ERROR: symbol '%s' not found\n", sym);
+ return -ESRCH;
+}
+
diff --git a/master/swap_deps.h b/master/swap_deps.h
new file mode 100644
index 00000000..ca4c978f
--- /dev/null
+++ b/master/swap_deps.h
@@ -0,0 +1,38 @@
+/*
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#ifndef _SWAP_DEPS_H
+#define _SWAP_DEPS_H
+
+
+struct task_struct;
+struct files_struct;
+
+
+struct files_struct *swap_get_files_struct(struct task_struct *task);
+void swap_put_files_struct(struct files_struct *fs);
+
+
+int chef_once(void);
+
+
+#endif /* _SWAP_DEPS_H */
diff --git a/master/swap_initializer.c b/master/swap_initializer.c
index 16c39bb1..a7ea8c35 100644
--- a/master/swap_initializer.c
+++ b/master/swap_initializer.c
@@ -26,6 +26,7 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include "swap_initializer.h"
+#include "swap_deps.h"
enum init_level {
@@ -166,6 +167,10 @@ static int do_once(void)
int ret;
struct swap_init_struct *init;
+ ret = chef_once();
+ if (ret)
+ return ret;
+
list_for_each_entry(init, &init_list, list) {
ret = sis_once(init);
if (ret)
diff --git a/parser/swap_msg_parser.c b/parser/swap_msg_parser.c
index e5f929de..0f7e3941 100644
--- a/parser/swap_msg_parser.c
+++ b/parser/swap_msg_parser.c
@@ -170,10 +170,6 @@ static int once(void)
return ret;
ret = init_cpu_deps();
- if (ret)
- return ret;
-
- ret = usm_msg_once();
return ret;
}
diff --git a/parser/usm_msg.c b/parser/usm_msg.c
index 3fcd733d..6abcaa59 100644
--- a/parser/usm_msg.c
+++ b/parser/usm_msg.c
@@ -26,40 +26,13 @@
#include <linux/dcache.h>
#include <linux/fdtable.h>
#include <writer/swap_msg.h>
+#include <master/swap_deps.h>
#include <us_manager/sspt/sspt.h> /* ... check_vma() */
#define USM_PREFIX KERN_INFO "[USM] "
-static struct files_struct *(*swap_get_files_struct)(struct task_struct *);
-static void (*swap_put_files_struct)(struct files_struct *fs);
-
-int usm_msg_once(void)
-{
- const char *sym;
-
- sym = "get_files_struct";
- swap_get_files_struct = (void *)swap_ksyms(sym);
- if (swap_get_files_struct == NULL)
- goto not_found;
-
- sym = "put_files_struct";
- swap_put_files_struct = (void *)swap_ksyms(sym);
- if (swap_put_files_struct == NULL)
- goto not_found;
-
- return 0;
-
-not_found:
- printk("ERROR: symbol '%s' not found\n", sym);
- return -ESRCH;
-}
-
-
-
-
-
struct kmem_info {
const char *name;
unsigned long start;
diff --git a/parser/usm_msg.h b/parser/usm_msg.h
index b151be5a..6c9345d4 100644
--- a/parser/usm_msg.h
+++ b/parser/usm_msg.h
@@ -28,7 +28,6 @@ struct dentry;
struct task_struct;
struct vm_area_struct;
-int usm_msg_once(void);
void usm_msg_info(struct task_struct *task, struct dentry *dentry);
void usm_msg_term(struct task_struct *task);
diff --git a/preload/preload_control.c b/preload/preload_control.c
index 08d922e1..5b41e32d 100644
--- a/preload/preload_control.c
+++ b/preload/preload_control.c
@@ -1,6 +1,6 @@
#include <linux/mm.h>
#include <linux/slab.h>
-#include <linux/rwsem.h>
+#include <linux/spinlock.h>
#include <linux/limits.h>
#include <linux/list.h>
@@ -19,7 +19,7 @@ struct bin_desc {
};
static LIST_HEAD(target_binaries_list);
-static DECLARE_RWSEM(target_binaries_lock);
+static DEFINE_RWLOCK(target_binaries_lock);
static int target_binaries_cnt = 0;
static inline struct task_struct *__get_task_struct(void)
@@ -59,14 +59,21 @@ static void __free_target_binary(struct bin_desc *p)
static void __free_target_binaries(void)
{
struct bin_desc *p, *n;
+ struct list_head rm_head;
- down_write(&target_binaries_lock);
+ INIT_LIST_HEAD(&rm_head);
+ write_lock(&target_binaries_lock);
list_for_each_entry_safe(p, n, &target_binaries_list, list) {
+ list_move(&p->list, &rm_head);
+ }
+ target_binaries_cnt = 0;
+ write_unlock(&target_binaries_lock);
+
+ list_for_each_entry_safe(p, n, &rm_head, list) {
list_del(&p->list);
+ put_dentry(p->dentry);
__free_target_binary(p);
}
- target_binaries_cnt = 0;
- up_write(&target_binaries_lock);
}
static bool __check_dentry_already_exist(struct dentry *dentry)
@@ -74,7 +81,7 @@ static bool __check_dentry_already_exist(struct dentry *dentry)
struct bin_desc *p;
bool ret = false;
- down_read(&target_binaries_lock);
+ read_lock(&target_binaries_lock);
list_for_each_entry(p, &target_binaries_list, list) {
if (p->dentry == dentry) {
ret = true;
@@ -82,9 +89,9 @@ static bool __check_dentry_already_exist(struct dentry *dentry)
}
}
out:
- up_read(&target_binaries_lock);
+ read_unlock(&target_binaries_lock);
- return false;
+ return ret;
}
static int __add_target_binary(struct dentry *dentry, char *filename)
@@ -106,10 +113,10 @@ static int __add_target_binary(struct dentry *dentry, char *filename)
if (!p)
return -ENOMEM;
- down_write(&target_binaries_lock);
+ write_lock(&target_binaries_lock);
list_add_tail(&p->list, &target_binaries_list);
target_binaries_cnt++;
- up_write(&target_binaries_lock);
+ write_unlock(&target_binaries_lock);
return 0;
}
@@ -201,7 +208,7 @@ unsigned int preload_control_get_bin_names(char ***filenames_p)
struct bin_desc *p;
char **a = NULL;
- down_read(&target_binaries_lock);
+ read_lock(&target_binaries_lock);
if (target_binaries_cnt == 0)
goto out;
@@ -219,7 +226,7 @@ unsigned int preload_control_get_bin_names(char ***filenames_p)
*filenames_p = a;
ret = i;
out:
- up_read(&target_binaries_lock);
+ read_unlock(&target_binaries_lock);
return ret;
}
diff --git a/preload/preload_debugfs.c b/preload/preload_debugfs.c
index 7e2955b5..3c179add 100644
--- a/preload/preload_debugfs.c
+++ b/preload/preload_debugfs.c
@@ -474,6 +474,8 @@ static ssize_t write_ui_viewer_app_info(struct file *file,
if (ui_viewer_add_app_info(buf, len))
ret = -EINVAL;
+ ret = len;
+
free_buf:
kfree(buf);