/**
 * Copyright (C) ARM Limited 2010-2014. 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
 * published by the Free Software Foundation.
 *
 */

static void marshal_frame(int cpu, int buftype)
{
	int frame;
	bool write_cpu;

	if (!per_cpu(gator_buffer, cpu)[buftype])
		return;

	switch (buftype) {
	case SUMMARY_BUF:
		write_cpu = false;
		frame = FRAME_SUMMARY;
		break;
	case BACKTRACE_BUF:
		write_cpu = true;
		frame = FRAME_BACKTRACE;
		break;
	case NAME_BUF:
		write_cpu = true;
		frame = FRAME_NAME;
		break;
	case COUNTER_BUF:
		write_cpu = false;
		frame = FRAME_COUNTER;
		break;
	case BLOCK_COUNTER_BUF:
		write_cpu = true;
		frame = FRAME_BLOCK_COUNTER;
		break;
	case ANNOTATE_BUF:
		write_cpu = false;
		frame = FRAME_ANNOTATE;
		break;
	case SCHED_TRACE_BUF:
		write_cpu = true;
		frame = FRAME_SCHED_TRACE;
		break;
	case IDLE_BUF:
		write_cpu = false;
		frame = FRAME_IDLE;
		break;
	case ACTIVITY_BUF:
		write_cpu = false;
		frame = FRAME_ACTIVITY;
		break;
	default:
		write_cpu = false;
		frame = -1;
		break;
	}

	/* add response type */
	if (gator_response_type > 0)
		gator_buffer_write_packed_int(cpu, buftype, gator_response_type);

	/* leave space for 4-byte unpacked length */
	per_cpu(gator_buffer_write, cpu)[buftype] = (per_cpu(gator_buffer_write, cpu)[buftype] + sizeof(s32)) & gator_buffer_mask[buftype];

	/* add frame type and core number */
	gator_buffer_write_packed_int(cpu, buftype, frame);
	if (write_cpu)
		gator_buffer_write_packed_int(cpu, buftype, cpu);
}

static int buffer_bytes_available(int cpu, int buftype)
{
	int remaining, filled;

	filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_read, cpu)[buftype];
	if (filled < 0)
		filled += gator_buffer_size[buftype];

	remaining = gator_buffer_size[buftype] - filled;

	if (per_cpu(buffer_space_available, cpu)[buftype])
		/* Give some extra room; also allows space to insert the overflow error packet */
		remaining -= 200;
	else
		/* Hysteresis, prevents multiple overflow messages */
		remaining -= 2000;

	return remaining;
}

static bool buffer_check_space(int cpu, int buftype, int bytes)
{
	int remaining = buffer_bytes_available(cpu, buftype);

	if (remaining < bytes)
		per_cpu(buffer_space_available, cpu)[buftype] = false;
	else
		per_cpu(buffer_space_available, cpu)[buftype] = true;

	return per_cpu(buffer_space_available, cpu)[buftype];
}

static int contiguous_space_available(int cpu, int buftype)
{
	int remaining = buffer_bytes_available(cpu, buftype);
	int contiguous = gator_buffer_size[buftype] - per_cpu(gator_buffer_write, cpu)[buftype];

	if (remaining < contiguous)
		return remaining;
	return contiguous;
}

static void gator_commit_buffer(int cpu, int buftype, u64 time)
{
	int type_length, commit, length, byte;
	unsigned long flags;

	if (!per_cpu(gator_buffer, cpu)[buftype])
		return;

	/* post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload */
	local_irq_save(flags);
	type_length = gator_response_type ? 1 : 0;
	commit = per_cpu(gator_buffer_commit, cpu)[buftype];
	length = per_cpu(gator_buffer_write, cpu)[buftype] - commit;
	if (length < 0)
		length += gator_buffer_size[buftype];
	length = length - type_length - sizeof(s32);

	if (length <= FRAME_HEADER_SIZE) {
		/* Nothing to write, only the frame header is present */
		local_irq_restore(flags);
		return;
	}

	for (byte = 0; byte < sizeof(s32); byte++)
		per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF;

	per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype];

	if (gator_live_rate > 0) {
		while (time > per_cpu(gator_buffer_commit_time, cpu))
			per_cpu(gator_buffer_commit_time, cpu) += gator_live_rate;
	}

	marshal_frame(cpu, buftype);
	local_irq_restore(flags);

	/* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */
	if (per_cpu(in_scheduler_context, cpu)) {
#ifndef CONFIG_PREEMPT_RT_FULL
		/* mod_timer can not be used in interrupt context in RT-Preempt full */
		mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
#endif
	} else {
		up(&gator_buffer_wake_sem);
	}
}

static void buffer_check(int cpu, int buftype, u64 time)
{
	int filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_commit, cpu)[buftype];

	if (filled < 0)
		filled += gator_buffer_size[buftype];
	if (filled >= ((gator_buffer_size[buftype] * 3) / 4))
		gator_commit_buffer(cpu, buftype, time);
}
