power: rk81x-battery: modify low power check threshold voltage
[firefly-linux-kernel-4.4.55.git] / drivers / gator / gator_trace_sched.c
index 655008628933d71d937ff26aceb49b55abbf7953..ad7c39e14a171e7746583547573ec9e353d2e5fd 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -8,6 +8,10 @@
  */
 
 #include <trace/events/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+#include <trace/events/task.h>
+#endif
+
 #include "gator.h"
 
 #define TASK_MAP_ENTRIES               1024    /* must be power of 2 */
@@ -23,8 +27,10 @@ enum {
 static DEFINE_PER_CPU(uint64_t *, taskname_keys);
 static DEFINE_PER_CPU(int, collecting);
 
-// this array is never read as the cpu wait charts are derived counters
-// the files are needed, nonetheless, to show that these counters are available
+/* this array is never read as the cpu wait charts are derived
+ * counters the files are needed, nonetheless, to show that these
+ * counters are available
+ */
 static ulong cpu_wait_enabled[CPU_WAIT_TOTAL];
 static ulong sched_cpu_key[CPU_WAIT_TOTAL];
 
@@ -32,26 +38,24 @@ static int sched_trace_create_files(struct super_block *sb, struct dentry *root)
 {
        struct dentry *dir;
 
-       // CPU Wait - Contention
+       /* CPU Wait - Contention */
        dir = gatorfs_mkdir(sb, root, "Linux_cpu_wait_contention");
-       if (!dir) {
+       if (!dir)
                return -1;
-       }
        gatorfs_create_ulong(sb, dir, "enabled", &cpu_wait_enabled[STATE_CONTENTION]);
        gatorfs_create_ro_ulong(sb, dir, "key", &sched_cpu_key[STATE_CONTENTION]);
 
-       // CPU Wait - I/O
+       /* CPU Wait - I/O */
        dir = gatorfs_mkdir(sb, root, "Linux_cpu_wait_io");
-       if (!dir) {
+       if (!dir)
                return -1;
-       }
        gatorfs_create_ulong(sb, dir, "enabled", &cpu_wait_enabled[STATE_WAIT_ON_IO]);
        gatorfs_create_ro_ulong(sb, dir, "key", &sched_cpu_key[STATE_WAIT_ON_IO]);
 
        return 0;
 }
 
-static void emit_pid_name(struct task_struct *task)
+static void emit_pid_name(const char *comm, struct task_struct *task)
 {
        bool found = false;
        char taskcomm[TASK_COMM_LEN + 3];
@@ -59,10 +63,10 @@ static void emit_pid_name(struct task_struct *task)
        uint64_t *keys = &(per_cpu(taskname_keys, cpu)[(task->pid & 0xFF) * TASK_MAX_COLLISIONS]);
        uint64_t value;
 
-       value = gator_chksum_crc32(task->comm);
+       value = gator_chksum_crc32(comm);
        value = (value << 32) | (uint32_t)task->pid;
 
-       // determine if the thread name was emitted already
+       /* determine if the thread name was emitted already */
        for (x = 0; x < TASK_MAX_COLLISIONS; x++) {
                if (keys[x] == value) {
                        found = true;
@@ -71,17 +75,18 @@ static void emit_pid_name(struct task_struct *task)
        }
 
        if (!found) {
-               // shift values, new value always in front
+               /* shift values, new value always in front */
                uint64_t oldv, newv = value;
+
                for (x = 0; x < TASK_MAX_COLLISIONS; x++) {
                        oldv = keys[x];
                        keys[x] = newv;
                        newv = oldv;
                }
 
-               // emit pid names, cannot use get_task_comm, as it's not exported on all kernel versions
-               if (strlcpy(taskcomm, task->comm, TASK_COMM_LEN) == TASK_COMM_LEN - 1) {
-                       // append ellipses if task->comm has length of TASK_COMM_LEN - 1
+               /* emit pid names, cannot use get_task_comm, as it's not exported on all kernel versions */
+               if (strlcpy(taskcomm, comm, TASK_COMM_LEN) == TASK_COMM_LEN - 1) {
+                       /* append ellipses if comm has length of TASK_COMM_LEN - 1 */
                        strcat(taskcomm, "...");
                }
 
@@ -89,7 +94,7 @@ static void emit_pid_name(struct task_struct *task)
        }
 }
 
-static void collect_counters(u64 time, struct task_struct *task)
+static void collect_counters(u64 time, struct task_struct *task, bool sched_switch)
 {
        int *buffer, len, cpu = get_physical_cpu();
        long long *buffer64;
@@ -98,7 +103,7 @@ static void collect_counters(u64 time, struct task_struct *task)
        if (marshal_event_header(time)) {
                list_for_each_entry(gi, &gator_events, list) {
                        if (gi->read) {
-                               len = gi->read(&buffer);
+                               len = gi->read(&buffer, sched_switch);
                                marshal_event(len, buffer);
                        } else if (gi->read64) {
                                len = gi->read64(&buffer64);
@@ -109,22 +114,26 @@ static void collect_counters(u64 time, struct task_struct *task)
                                marshal_event64(len, buffer64);
                        }
                }
-               // Only check after writing all counters so that time and corresponding counters appear in the same frame
+               if (cpu == 0)
+                       gator_emit_perf_time(time);
+               /* Only check after writing all counters so that time and corresponding counters appear in the same frame */
                buffer_check(cpu, BLOCK_COUNTER_BUF, time);
 
-               // Commit buffers on timeout
+               /* Commit buffers on timeout */
                if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) {
                        static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF, ACTIVITY_BUF };
                        int i;
 
-                       for (i = 0; i < ARRAY_SIZE(buftypes); ++i) {
+                       for (i = 0; i < ARRAY_SIZE(buftypes); ++i)
                                gator_commit_buffer(cpu, buftypes[i], time);
-                       }
 
-                       // spinlocks are noops on uniprocessor machines and mutexes do not work in sched_switch context in
-                       // RT-Preempt full, so disable proactive flushing of the annotate frame on uniprocessor machines.
+                       /* spinlocks are noops on uniprocessor machines and mutexes do
+                        * not work in sched_switch context in RT-Preempt full, so
+                        * disable proactive flushing of the annotate frame on
+                        * uniprocessor machines.
+                        */
 #ifdef CONFIG_SMP
-                       // Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full
+                       /* Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full */
                        if (on_primary_core() && spin_trylock(&annotate_lock)) {
                                gator_commit_buffer(0, ANNOTATE_BUF, time);
                                spin_unlock(&annotate_lock);
@@ -134,7 +143,7 @@ static void collect_counters(u64 time, struct task_struct *task)
        }
 }
 
-// special case used during a suspend of the system
+/* special case used during a suspend of the system */
 static void trace_sched_insert_idle(void)
 {
        marshal_sched_trace_switch(0, 0);
@@ -146,7 +155,7 @@ static void gator_trace_emit_link(struct task_struct *p)
        int cpu = get_physical_cpu();
 
        cookie = get_exec_cookie(cpu, p);
-       emit_pid_name(p);
+       emit_pid_name(p->comm, p);
 
        marshal_link(cookie, p->tgid, p->pid);
 }
@@ -161,6 +170,15 @@ GATOR_DEFINE_PROBE(sched_process_exec, TP_PROTO(struct task_struct *p, pid_t old
 {
        gator_trace_emit_link(p);
 }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
+GATOR_DEFINE_PROBE(task_rename, TP_PROTO(struct task_struct *task, char *comm))
+#else
+GATOR_DEFINE_PROBE(task_rename, TP_PROTO(struct task_struct *task, const char *comm))
+#endif
+{
+       emit_pid_name(comm, task);
+}
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
@@ -174,17 +192,16 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
 
        per_cpu(in_scheduler_context, cpu) = true;
 
-       // do as much work as possible before disabling interrupts
-       if (prev->state == TASK_RUNNING) {
+       /* do as much work as possible before disabling interrupts */
+       if (prev->state == TASK_RUNNING)
                state = STATE_CONTENTION;
-       } else if (prev->in_iowait) {
+       else if (prev->in_iowait)
                state = STATE_WAIT_ON_IO;
-       } else {
+       else
                state = STATE_WAIT_ON_OTHER;
-       }
 
        per_cpu(collecting, cpu) = 1;
-       collect_counters(gator_get_time(), prev);
+       collect_counters(gator_get_time(), prev, true);
        per_cpu(collecting, cpu) = 0;
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
@@ -202,18 +219,20 @@ GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p))
 
 static void do_nothing(void *info)
 {
-       // Intentionally do nothing
+       /* Intentionally do nothing */
        (void)info;
 }
 
 static int register_scheduler_tracepoints(void)
 {
-       // register tracepoints
+       /* register tracepoints */
        if (GATOR_REGISTER_TRACE(sched_process_fork))
                goto fail_sched_process_fork;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
        if (GATOR_REGISTER_TRACE(sched_process_exec))
                goto fail_sched_process_exec;
+       if (GATOR_REGISTER_TRACE(task_rename))
+               goto fail_task_rename;
 #endif
        if (GATOR_REGISTER_TRACE(sched_switch))
                goto fail_sched_switch;
@@ -221,21 +240,24 @@ static int register_scheduler_tracepoints(void)
                goto fail_sched_process_free;
        pr_debug("gator: registered tracepoints\n");
 
-       // Now that the scheduler tracepoint is registered, force a context switch
-       // on all cpus to capture what is currently running.
+       /* Now that the scheduler tracepoint is registered, force a context
+        * switch on all cpus to capture what is currently running.
+        */
        on_each_cpu(do_nothing, NULL, 0);
 
        return 0;
 
-       // unregister tracepoints on error
+       /* unregister tracepoints on error */
 fail_sched_process_free:
        GATOR_UNREGISTER_TRACE(sched_switch);
 fail_sched_switch:
-       GATOR_UNREGISTER_TRACE(sched_process_fork);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
-fail_sched_process_exec:
+       GATOR_UNREGISTER_TRACE(task_rename);
+fail_task_rename:
        GATOR_UNREGISTER_TRACE(sched_process_exec);
+fail_sched_process_exec:
 #endif
+       GATOR_UNREGISTER_TRACE(sched_process_fork);
 fail_sched_process_fork:
        pr_err("gator: tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n");
 
@@ -247,6 +269,7 @@ static void unregister_scheduler_tracepoints(void)
        GATOR_UNREGISTER_TRACE(sched_process_fork);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
        GATOR_UNREGISTER_TRACE(sched_process_exec);
+       GATOR_UNREGISTER_TRACE(task_rename);
 #endif
        GATOR_UNREGISTER_TRACE(sched_switch);
        GATOR_UNREGISTER_TRACE(sched_process_free);
@@ -271,7 +294,7 @@ static int gator_trace_sched_start(void)
 
        for_each_present_cpu(cpu) {
                size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t);
-               per_cpu(taskname_keys, cpu) = (uint64_t *)kmalloc(size, GFP_KERNEL);
+               per_cpu(taskname_keys, cpu) = kmalloc(size, GFP_KERNEL);
                if (!per_cpu(taskname_keys, cpu))
                        return -1;
                memset(per_cpu(taskname_keys, cpu), 0, size);
@@ -290,6 +313,7 @@ static void gator_trace_sched_offline(void)
 static void gator_trace_sched_init(void)
 {
        int i;
+
        for (i = 0; i < CPU_WAIT_TOTAL; i++) {
                cpu_wait_enabled[i] = 0;
                sched_cpu_key[i] = gator_events_get_key();