diff options
-rw-r--r-- | energy/Kbuild | 7 | ||||
-rw-r--r-- | energy/debugfs_energy.c | 210 | ||||
-rw-r--r-- | energy/energy.c | 486 | ||||
-rw-r--r-- | energy/energy.h | 14 | ||||
-rw-r--r-- | energy/lcd/sprdfb_panel.c | 186 | ||||
-rw-r--r-- | master/Kbuild | 3 | ||||
-rw-r--r-- | master/swap_deps.c | 69 | ||||
-rw-r--r-- | master/swap_deps.h | 38 | ||||
-rw-r--r-- | master/swap_initializer.c | 5 | ||||
-rw-r--r-- | parser/swap_msg_parser.c | 4 | ||||
-rw-r--r-- | parser/usm_msg.c | 29 | ||||
-rw-r--r-- | parser/usm_msg.h | 1 | ||||
-rw-r--r-- | preload/preload_control.c | 31 | ||||
-rw-r--r-- | preload/preload_debugfs.c | 2 |
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); |