/*
 * Copyright 2018 Red Hat Inc.
 *
 * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 "priv.h"

#include <core/memory.h>
#include <subdev/mmu.h>
#include <engine/fifo.h>

static void
gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer)
{
	struct nvkm_device *device = buffer->fault->subdev.device;
	struct nvkm_memory *mem = buffer->mem;
	const u32 foff = buffer->id * 0x14;
	u32 get = nvkm_rd32(device, 0x100e2c + foff);
	u32 put = nvkm_rd32(device, 0x100e30 + foff);
	if (put == get)
		return;

	nvkm_kmap(mem);
	while (get != put) {
		const u32   base = get * buffer->fault->func->buffer.entry_size;
		const u32 instlo = nvkm_ro32(mem, base + 0x00);
		const u32 insthi = nvkm_ro32(mem, base + 0x04);
		const u32 addrlo = nvkm_ro32(mem, base + 0x08);
		const u32 addrhi = nvkm_ro32(mem, base + 0x0c);
		const u32 timelo = nvkm_ro32(mem, base + 0x10);
		const u32 timehi = nvkm_ro32(mem, base + 0x14);
		const u32  info0 = nvkm_ro32(mem, base + 0x18);
		const u32  info1 = nvkm_ro32(mem, base + 0x1c);
		struct nvkm_fault_data info;

		if (++get == buffer->entries)
			get = 0;
		nvkm_wr32(device, 0x100e2c + foff, get);

		info.addr   = ((u64)addrhi << 32) | addrlo;
		info.inst   = ((u64)insthi << 32) | instlo;
		info.time   = ((u64)timehi << 32) | timelo;
		info.engine = (info0 & 0x000000ff);
		info.valid  = (info1 & 0x80000000) >> 31;
		info.gpc    = (info1 & 0x1f000000) >> 24;
		info.hub    = (info1 & 0x00100000) >> 20;
		info.access = (info1 & 0x000f0000) >> 16;
		info.client = (info1 & 0x00007f00) >> 8;
		info.reason = (info1 & 0x0000001f);

		nvkm_fifo_fault(device->fifo, &info);
	}
	nvkm_done(mem);
}

static void
gv100_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
{
	struct nvkm_device *device = buffer->fault->subdev.device;
	const u32 intr = buffer->id ? 0x08000000 : 0x20000000;
	const u32 foff = buffer->id * 0x14;

	nvkm_mask(device, 0x100a34, intr, intr);
	nvkm_mask(device, 0x100e34 + foff, 0x80000000, 0x00000000);
}

static void
gv100_fault_buffer_init(struct nvkm_fault_buffer *buffer)
{
	struct nvkm_device *device = buffer->fault->subdev.device;
	const u32 intr = buffer->id ? 0x08000000 : 0x20000000;
	const u32 foff = buffer->id * 0x14;

	nvkm_mask(device, 0x100e34 + foff, 0xc0000000, 0x40000000);
	nvkm_wr32(device, 0x100e28 + foff, upper_32_bits(buffer->vma->addr));
	nvkm_wr32(device, 0x100e24 + foff, lower_32_bits(buffer->vma->addr));
	nvkm_mask(device, 0x100e34 + foff, 0x80000000, 0x80000000);
	nvkm_mask(device, 0x100a2c, intr, intr);
}

static u32
gv100_fault_buffer_entries(struct nvkm_fault_buffer *buffer)
{
	struct nvkm_device *device = buffer->fault->subdev.device;
	const u32 foff = buffer->id * 0x14;
	nvkm_mask(device, 0x100e34 + foff, 0x40000000, 0x40000000);
	return nvkm_rd32(device, 0x100e34 + foff) & 0x000fffff;
}

static int
gv100_fault_ntfy_nrpfb(struct nvkm_notify *notify)
{
	struct nvkm_fault *fault = container_of(notify, typeof(*fault), nrpfb);
	gv100_fault_buffer_process(fault->buffer[0]);
	return NVKM_NOTIFY_KEEP;
}

static void
gv100_fault_intr_fault(struct nvkm_fault *fault)
{
	struct nvkm_subdev *subdev = &fault->subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_fault_data info;
	const u32 addrlo = nvkm_rd32(device, 0x100e4c);
	const u32 addrhi = nvkm_rd32(device, 0x100e50);
	const u32  info0 = nvkm_rd32(device, 0x100e54);
	const u32 insthi = nvkm_rd32(device, 0x100e58);
	const u32  info1 = nvkm_rd32(device, 0x100e5c);

	info.addr = ((u64)addrhi << 32) | addrlo;
	info.inst = ((u64)insthi << 32) | (info0 & 0xfffff000);
	info.time = 0;
	info.engine = (info0 & 0x000000ff);
	info.valid  = (info1 & 0x80000000) >> 31;
	info.gpc    = (info1 & 0x1f000000) >> 24;
	info.hub    = (info1 & 0x00100000) >> 20;
	info.access = (info1 & 0x000f0000) >> 16;
	info.client = (info1 & 0x00007f00) >> 8;
	info.reason = (info1 & 0x0000001f);

	nvkm_fifo_fault(device->fifo, &info);
}

static void
gv100_fault_intr(struct nvkm_fault *fault)
{
	struct nvkm_subdev *subdev = &fault->subdev;
	struct nvkm_device *device = subdev->device;
	u32 stat = nvkm_rd32(device, 0x100a20);

	if (stat & 0x80000000) {
		gv100_fault_intr_fault(fault);
		nvkm_wr32(device, 0x100e60, 0x80000000);
		stat &= ~0x80000000;
	}

	if (stat & 0x20000000) {
		if (fault->buffer[0]) {
			nvkm_event_send(&fault->event, 1, 0, NULL, 0);
			stat &= ~0x20000000;
		}
	}

	if (stat) {
		nvkm_debug(subdev, "intr %08x\n", stat);
	}
}

static void
gv100_fault_fini(struct nvkm_fault *fault)
{
	nvkm_notify_put(&fault->nrpfb);
	nvkm_mask(fault->subdev.device, 0x100a34, 0x80000000, 0x80000000);
}

static void
gv100_fault_init(struct nvkm_fault *fault)
{
	nvkm_mask(fault->subdev.device, 0x100a2c, 0x80000000, 0x80000000);
	nvkm_notify_get(&fault->nrpfb);
}

static int
gv100_fault_oneinit(struct nvkm_fault *fault)
{
	return nvkm_notify_init(&fault->buffer[0]->object, &fault->event,
				gv100_fault_ntfy_nrpfb, false, NULL, 0, 0,
				&fault->nrpfb);
}

static const struct nvkm_fault_func
gv100_fault = {
	.oneinit = gv100_fault_oneinit,
	.init = gv100_fault_init,
	.fini = gv100_fault_fini,
	.intr = gv100_fault_intr,
	.buffer.nr = 2,
	.buffer.entry_size = 32,
	.buffer.entries = gv100_fault_buffer_entries,
	.buffer.init = gv100_fault_buffer_init,
	.buffer.fini = gv100_fault_buffer_fini,
};

int
gv100_fault_new(struct nvkm_device *device, int index,
		struct nvkm_fault **pfault)
{
	return nvkm_fault_new_(&gv100_fault, device, index, pfault);
}
