/*
 * Copyright 2010 ARM Ltd.
 *
 * Perf-events backend for OProfile.
 */
#include <linux/perf_event.h>
#include <linux/platform_device.h>
#include <linux/oprofile.h>
#include <linux/slab.h>

/*
 * Per performance monitor configuration as set via oprofilefs.
 */
struct op_counter_config {
	unsigned long count;
	unsigned long enabled;
	unsigned long event;
	unsigned long unit_mask;
	unsigned long kernel;
	unsigned long user;
	struct perf_event_attr attr;
};

static int oprofile_perf_enabled;
static DEFINE_MUTEX(oprofile_perf_mutex);

static struct op_counter_config *counter_config;
static struct perf_event **perf_events[NR_CPUS];
static int num_counters;

/*
 * Overflow callback for oprofile.
 */
static void op_overflow_handler(struct perf_event *event,
			struct perf_sample_data *data, struct pt_regs *regs)
{
	int id;
	u32 cpu = smp_processor_id();

	for (id = 0; id < num_counters; ++id)
		if (perf_events[cpu][id] == event)
			break;

	if (id != num_counters)
		oprofile_add_sample(regs, id);
	else
		pr_warning("oprofile: ignoring spurious overflow "
				"on cpu %u\n", cpu);
}

/*
 * Called by oprofile_perf_setup to create perf attributes to mirror the oprofile
 * settings in counter_config. Attributes are created as `pinned' events and
 * so are permanently scheduled on the PMU.
 */
static void op_perf_setup(void)
{
	int i;
	u32 size = sizeof(struct perf_event_attr);
	struct perf_event_attr *attr;

	for (i = 0; i < num_counters; ++i) {
		attr = &counter_config[i].attr;
		memset(attr, 0, size);
		attr->type		= PERF_TYPE_RAW;
		attr->size		= size;
		attr->config		= counter_config[i].event;
		attr->sample_period	= counter_config[i].count;
		attr->pinned		= 1;
	}
}

static int op_create_counter(int cpu, int event)
{
	struct perf_event *pevent;

	if (!counter_config[event].enabled || perf_events[cpu][event])
		return 0;

	pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
						  cpu, NULL,
						  op_overflow_handler, NULL);

	if (IS_ERR(pevent))
		return PTR_ERR(pevent);

	if (pevent->state != PERF_EVENT_STATE_ACTIVE) {
		perf_event_release_kernel(pevent);
		pr_warning("oprofile: failed to enable event %d "
				"on CPU %d\n", event, cpu);
		return -EBUSY;
	}

	perf_events[cpu][event] = pevent;

	return 0;
}

static void op_destroy_counter(int cpu, int event)
{
	struct perf_event *pevent = perf_events[cpu][event];

	if (pevent) {
		perf_event_release_kernel(pevent);
		perf_events[cpu][event] = NULL;
	}
}

/*
 * Called by oprofile_perf_start to create active perf events based on the
 * perviously configured attributes.
 */
static int op_perf_start(void)
{
	int cpu, event, ret = 0;

	for_each_online_cpu(cpu) {
		for (event = 0; event < num_counters; ++event) {
			ret = op_create_counter(cpu, event);
			if (ret)
				return ret;
		}
	}

	return ret;
}

/*
 * Called by oprofile_perf_stop at the end of a profiling run.
 */
static void op_perf_stop(void)
{
	int cpu, event;

	for_each_online_cpu(cpu)
		for (event = 0; event < num_counters; ++event)
			op_destroy_counter(cpu, event);
}

static int oprofile_perf_create_files(struct super_block *sb, struct dentry *root)
{
	unsigned int i;

	for (i = 0; i < num_counters; i++) {
		struct dentry *dir;
		char buf[4];

		snprintf(buf, sizeof buf, "%d", i);
		dir = oprofilefs_mkdir(sb, root, buf);
		oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled);
		oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event);
		oprofilefs_create_ulong(sb, dir, "count", &counter_config[i].count);
		oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
		oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
		oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
	}

	return 0;
}

static int oprofile_perf_setup(void)
{
	raw_spin_lock(&oprofilefs_lock);
	op_perf_setup();
	raw_spin_unlock(&oprofilefs_lock);
	return 0;
}

static int oprofile_perf_start(void)
{
	int ret = -EBUSY;

	mutex_lock(&oprofile_perf_mutex);
	if (!oprofile_perf_enabled) {
		ret = 0;
		op_perf_start();
		oprofile_perf_enabled = 1;
	}
	mutex_unlock(&oprofile_perf_mutex);
	return ret;
}

static void oprofile_perf_stop(void)
{
	mutex_lock(&oprofile_perf_mutex);
	if (oprofile_perf_enabled)
		op_perf_stop();
	oprofile_perf_enabled = 0;
	mutex_unlock(&oprofile_perf_mutex);
}

#ifdef CONFIG_PM

static int oprofile_perf_suspend(struct platform_device *dev, pm_message_t state)
{
	mutex_lock(&oprofile_perf_mutex);
	if (oprofile_perf_enabled)
		op_perf_stop();
	mutex_unlock(&oprofile_perf_mutex);
	return 0;
}

static int oprofile_perf_resume(struct platform_device *dev)
{
	mutex_lock(&oprofile_perf_mutex);
	if (oprofile_perf_enabled && op_perf_start())
		oprofile_perf_enabled = 0;
	mutex_unlock(&oprofile_perf_mutex);
	return 0;
}

static struct platform_driver oprofile_driver = {
	.driver		= {
		.name		= "oprofile-perf",
	},
	.resume		= oprofile_perf_resume,
	.suspend	= oprofile_perf_suspend,
};

static struct platform_device *oprofile_pdev;

static int __init init_driverfs(void)
{
	int ret;

	ret = platform_driver_register(&oprofile_driver);
	if (ret)
		return ret;

	oprofile_pdev =	platform_device_register_simple(
				oprofile_driver.driver.name, 0, NULL, 0);
	if (IS_ERR(oprofile_pdev)) {
		ret = PTR_ERR(oprofile_pdev);
		platform_driver_unregister(&oprofile_driver);
	}

	return ret;
}

static void exit_driverfs(void)
{
	platform_device_unregister(oprofile_pdev);
	platform_driver_unregister(&oprofile_driver);
}

#else

static inline int  init_driverfs(void) { return 0; }
static inline void exit_driverfs(void) { }

#endif /* CONFIG_PM */

void oprofile_perf_exit(void)
{
	int cpu, id;
	struct perf_event *event;

	for_each_possible_cpu(cpu) {
		for (id = 0; id < num_counters; ++id) {
			event = perf_events[cpu][id];
			if (event)
				perf_event_release_kernel(event);
		}

		kfree(perf_events[cpu]);
	}

	kfree(counter_config);
	exit_driverfs();
}

int __init oprofile_perf_init(struct oprofile_operations *ops)
{
	int cpu, ret = 0;

	ret = init_driverfs();
	if (ret)
		return ret;

	memset(&perf_events, 0, sizeof(perf_events));

	num_counters = perf_num_counters();
	if (num_counters <= 0) {
		pr_info("oprofile: no performance counters\n");
		ret = -ENODEV;
		goto out;
	}

	counter_config = kcalloc(num_counters,
			sizeof(struct op_counter_config), GFP_KERNEL);

	if (!counter_config) {
		pr_info("oprofile: failed to allocate %d "
				"counters\n", num_counters);
		ret = -ENOMEM;
		num_counters = 0;
		goto out;
	}

	for_each_possible_cpu(cpu) {
		perf_events[cpu] = kcalloc(num_counters,
				sizeof(struct perf_event *), GFP_KERNEL);
		if (!perf_events[cpu]) {
			pr_info("oprofile: failed to allocate %d perf events "
					"for cpu %d\n", num_counters, cpu);
			ret = -ENOMEM;
			goto out;
		}
	}

	ops->create_files	= oprofile_perf_create_files;
	ops->setup		= oprofile_perf_setup;
	ops->start		= oprofile_perf_start;
	ops->stop		= oprofile_perf_stop;
	ops->shutdown		= oprofile_perf_stop;
	ops->cpu_type		= op_name_from_perf_id();

	if (!ops->cpu_type)
		ret = -ENODEV;
	else
		pr_info("oprofile: using %s\n", ops->cpu_type);

out:
	if (ret)
		oprofile_perf_exit();

	return ret;
}
