/*
 * Copyright (c) 2012, 2016 The Linux Foundation. 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 and
 * only 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/kernel.h>
#include <linux/module.h>
#include <linux/percpu.h>
#include <linux/slab.h>
#include <linux/rbtree.h>
#include <linux/hrtimer.h>
#include <linux/tracefs.h>
#include <linux/ktime.h>
#include <trace/events/power.h>
#include "trace_stat.h"
#include "trace.h"

struct trans {
	struct rb_node node;
	unsigned int cpu;
	unsigned int start_freq;
	unsigned int end_freq;
	unsigned int min_us;
	unsigned int max_us;
	ktime_t total_t;
	unsigned int count;
};
static struct rb_root freq_trans_tree = RB_ROOT;

static struct trans *tr_search(struct rb_root *root, unsigned int cpu,
			       unsigned int start_freq, unsigned int end_freq)
{
	struct rb_node *node = root->rb_node;

	while (node) {
		struct trans *tr = container_of(node, struct trans, node);

		if (cpu < tr->cpu)
			node = node->rb_left;
		else if (cpu > tr->cpu)
			node = node->rb_right;
		else if (start_freq < tr->start_freq)
			node = node->rb_left;
		else if (start_freq > tr->start_freq)
			node = node->rb_right;
		else if (end_freq < tr->end_freq)
			node = node->rb_left;
		else if (end_freq > tr->end_freq)
			node = node->rb_right;
		else
			return tr;
	}
	return NULL;
}

static int tr_insert(struct rb_root *root, struct trans *tr)
{
	struct rb_node **new = &(root->rb_node), *parent = NULL;

	while (*new) {
		struct trans *this = container_of(*new, struct trans, node);

		parent = *new;
		if (tr->cpu < this->cpu)
			new = &((*new)->rb_left);
		else if (tr->cpu > this->cpu)
			new = &((*new)->rb_right);
		else if (tr->start_freq < this->start_freq)
			new = &((*new)->rb_left);
		else if (tr->start_freq > this->start_freq)
			new = &((*new)->rb_right);
		else if (tr->end_freq < this->end_freq)
			new = &((*new)->rb_left);
		else if (tr->end_freq > this->end_freq)
			new = &((*new)->rb_right);
		else
			return -EINVAL;
	}

	rb_link_node(&tr->node, parent, new);
	rb_insert_color(&tr->node, root);

	return 0;
}

struct trans_state {
	spinlock_t lock;
	unsigned int start_freq;
	unsigned int end_freq;
	ktime_t start_t;
	bool started;
};
static DEFINE_PER_CPU(struct trans_state, freq_trans_state);

static DEFINE_SPINLOCK(state_lock);

static void probe_start(void *ignore, unsigned int start_freq,
			unsigned int end_freq, unsigned int cpu)
{
	unsigned long flags;

	spin_lock_irqsave(&state_lock, flags);
	per_cpu(freq_trans_state, cpu).start_freq = start_freq;
	per_cpu(freq_trans_state, cpu).end_freq = end_freq;
	per_cpu(freq_trans_state, cpu).start_t = ktime_get();
	per_cpu(freq_trans_state, cpu).started = true;
	spin_unlock_irqrestore(&state_lock, flags);
}

static void probe_end(void *ignore, unsigned int cpu)
{
	unsigned long flags;
	struct trans *tr;
	s64 dur_us;
	ktime_t dur_t, end_t = ktime_get();

	spin_lock_irqsave(&state_lock, flags);

	if (!per_cpu(freq_trans_state, cpu).started)
		goto out;

	dur_t = ktime_sub(end_t, per_cpu(freq_trans_state, cpu).start_t);
	dur_us = ktime_to_us(dur_t);

	tr = tr_search(&freq_trans_tree, cpu,
		       per_cpu(freq_trans_state, cpu).start_freq,
		       per_cpu(freq_trans_state, cpu).end_freq);
	if (!tr) {
		tr = kzalloc(sizeof(*tr), GFP_ATOMIC);
		if (!tr) {
			WARN_ONCE(1, "CPU frequency trace is now invalid!\n");
			goto out;
		}

		tr->start_freq = per_cpu(freq_trans_state, cpu).start_freq;
		tr->end_freq = per_cpu(freq_trans_state, cpu).end_freq;
		tr->cpu = cpu;
		tr->min_us = UINT_MAX;
		tr_insert(&freq_trans_tree, tr);
	}
	tr->total_t = ktime_add(tr->total_t, dur_t);
	tr->count++;

	if (dur_us > tr->max_us)
		tr->max_us = dur_us;
	if (dur_us < tr->min_us)
		tr->min_us = dur_us;

	per_cpu(freq_trans_state, cpu).started = false;
out:
	spin_unlock_irqrestore(&state_lock, flags);
}

static void *freq_switch_stat_start(struct tracer_stat *trace)
{
	struct rb_node *n;
	unsigned long flags;

	spin_lock_irqsave(&state_lock, flags);
	n = rb_first(&freq_trans_tree);
	spin_unlock_irqrestore(&state_lock, flags);

	return n;
}

static void *freq_switch_stat_next(void *prev, int idx)
{
	struct rb_node *n;
	unsigned long flags;

	spin_lock_irqsave(&state_lock, flags);
	n = rb_next(prev);
	spin_unlock_irqrestore(&state_lock, flags);

	return n;
}

static int freq_switch_stat_show(struct seq_file *s, void *p)
{
	unsigned long flags;
	struct trans *tr = p;

	spin_lock_irqsave(&state_lock, flags);
	seq_printf(s, "%3d %9d %8d %5d %6lld %6d %6d\n", tr->cpu,
		   tr->start_freq, tr->end_freq, tr->count,
		   div_s64(ktime_to_us(tr->total_t), tr->count),
		   tr->min_us, tr->max_us);
	spin_unlock_irqrestore(&state_lock, flags);

	return 0;
}

static void freq_switch_stat_release(void *stat)
{
	struct trans *tr = stat;
	unsigned long flags;

	spin_lock_irqsave(&state_lock, flags);
	rb_erase(&tr->node, &freq_trans_tree);
	spin_unlock_irqrestore(&state_lock, flags);
	kfree(tr);
}

static int freq_switch_stat_headers(struct seq_file *s)
{
	seq_puts(s, "CPU START_KHZ  END_KHZ COUNT AVG_US MIN_US MAX_US\n");
	seq_puts(s, "  |         |        |     |      |      |      |\n");
	return 0;
}

struct tracer_stat freq_switch_stats __read_mostly = {
	.name = "cpu_freq_switch",
	.stat_start = freq_switch_stat_start,
	.stat_next = freq_switch_stat_next,
	.stat_show = freq_switch_stat_show,
	.stat_release = freq_switch_stat_release,
	.stat_headers = freq_switch_stat_headers
};

static void trace_freq_switch_disable(void)
{
	unregister_stat_tracer(&freq_switch_stats);
	unregister_trace_cpu_frequency_switch_end(probe_end, NULL);
	unregister_trace_cpu_frequency_switch_start(probe_start, NULL);
	pr_info("disabled cpu frequency switch time profiling\n");
}

static int trace_freq_switch_enable(void)
{
	int ret;

	ret = register_trace_cpu_frequency_switch_start(probe_start, NULL);
	if (ret)
		goto out;

	ret = register_trace_cpu_frequency_switch_end(probe_end, NULL);
	if (ret)
		goto err_register_switch_end;

	ret = register_stat_tracer(&freq_switch_stats);
	if (ret)
		goto err_register_stat_tracer;

	pr_info("enabled cpu frequency switch time profiling\n");
	return 0;

err_register_stat_tracer:
	unregister_trace_cpu_frequency_switch_end(probe_end, NULL);
err_register_switch_end:
	register_trace_cpu_frequency_switch_start(probe_start, NULL);
out:
	pr_err("failed to enable cpu frequency switch time profiling\n");

	return ret;
}

static DEFINE_MUTEX(debugfs_lock);
static bool trace_freq_switch_enabled;

static int debug_toggle_tracing(void *data, u64 val)
{
	int ret = 0;

	mutex_lock(&debugfs_lock);

	if (val == 1 && !trace_freq_switch_enabled)
		ret = trace_freq_switch_enable();
	else if (val == 0 && trace_freq_switch_enabled)
		trace_freq_switch_disable();
	else if (val > 1)
		ret = -EINVAL;

	if (!ret)
		trace_freq_switch_enabled = val;

	mutex_unlock(&debugfs_lock);

	return ret;
}

static int debug_tracing_state_get(void *data, u64 *val)
{
	mutex_lock(&debugfs_lock);
	*val = trace_freq_switch_enabled;
	mutex_unlock(&debugfs_lock);

	return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(debug_tracing_state_fops, debug_tracing_state_get,
			debug_toggle_tracing, "%llu\n");

static int __init trace_freq_switch_init(void)
{
	struct dentry *d_tracer = tracing_init_dentry();

	if (IS_ERR(d_tracer))
		return 0;

	tracefs_create_file("cpu_freq_switch_profile_enabled",
		0644, d_tracer, NULL, &debug_tracing_state_fops);

	return 0;
}
late_initcall(trace_freq_switch_init);
