/*
 * Copyright © 2013 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 */

#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "igt_perf.h"

#include "gem-interrupts.h"
#include "debugfs.h"

static long long debugfs_read(void)
{
	char buf[8192], *b;
	int fd, len;

	sprintf(buf, "%s/i915_gem_interrupt", debugfs_dri_path);
	fd = open(buf, 0);
	if (fd < 0)
		return -1;

	len = read(fd, buf, sizeof(buf)-1);
	close(fd);

	if (len < 0)
		return -1;

	buf[len] = '\0';

	b = strstr(buf, "Interrupts received:");
	if (b == NULL)
		return -1;

	return strtoull(b + sizeof("Interrupts received:"), 0, 0);
}

static long long procfs_read(void)
{
	char buf[8192], *b;
	int fd, len;
	unsigned long long val;

/* 44:         51      42446          0          0   PCI-MSI-edge      i915*/
	fd = open("/proc/interrupts", 0);
	if (fd < 0)
		return -1;

	len = read(fd, buf, sizeof(buf)-1);
	close(fd);

	if (len < 0)
		return -1;

	buf[len] = '\0';

	b = strstr(buf, "i915");
	if (b == NULL)
		return -1;
	while (*--b != ':')
		;

	val = 0;
	do {
		while (isspace(*++b))
			;
		if (!isdigit(*b))
			break;

		val += strtoull(b, &b, 0);
	} while(1);

	return val;
}

static long long interrupts_read(void)
{
	long long val;

	val = debugfs_read();
	if (val < 0)
		val = procfs_read();
	return val;
}

int gem_interrupts_init(struct gem_interrupts *irqs)
{
	memset(irqs, 0, sizeof(*irqs));

	irqs->fd = perf_i915_open(I915_PMU_INTERRUPTS);
	if (irqs->fd < 0 && interrupts_read() < 0)
		irqs->error = ENODEV;

	return irqs->error;
}

int gem_interrupts_update(struct gem_interrupts *irqs)
{
	uint64_t val;
	int update;

	if (irqs->error)
		return irqs->error;

	if (irqs->fd < 0) {
		long long ret;
		ret = interrupts_read();
		if (ret < 0)
			return irqs->error = ENODEV;
		else
			val = ret;
	} else {
		uint64_t data[2];

		if (read(irqs->fd, data, sizeof(data)) < 0)
			return irqs->error = errno;

		val = data[0];
	}

	update = irqs->last_count == 0;
	irqs->last_count = irqs->count;
	irqs->count = val;
	irqs->delta = irqs->count - irqs->last_count;
	return update ? EAGAIN : 0;
}
