/*
 * Copyright 2016 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.
 *
 * Authors: Ben Skeggs <bskeggs@redhat.com>
 */
#include "priv.h"

struct nvkm_top_device *
nvkm_top_device_new(struct nvkm_top *top)
{
	struct nvkm_top_device *info = kmalloc(sizeof(*info), GFP_KERNEL);
	if (info) {
		info->index = NVKM_SUBDEV_NR;
		info->addr = 0;
		info->fault = -1;
		info->engine = -1;
		info->runlist = -1;
		info->reset = -1;
		info->intr = -1;
		list_add_tail(&info->head, &top->device);
	}
	return info;
}

u32
nvkm_top_addr(struct nvkm_device *device, enum nvkm_devidx index)
{
	struct nvkm_top *top = device->top;
	struct nvkm_top_device *info;

	if (top) {
		list_for_each_entry(info, &top->device, head) {
			if (info->index == index)
				return info->addr;
		}
	}

	return 0;
}

u32
nvkm_top_reset(struct nvkm_device *device, enum nvkm_devidx index)
{
	struct nvkm_top *top = device->top;
	struct nvkm_top_device *info;

	if (top) {
		list_for_each_entry(info, &top->device, head) {
			if (info->index == index && info->reset >= 0)
				return BIT(info->reset);
		}
	}

	return 0;
}

u32
nvkm_top_intr_mask(struct nvkm_device *device, enum nvkm_devidx devidx)
{
	struct nvkm_top *top = device->top;
	struct nvkm_top_device *info;

	if (top) {
		list_for_each_entry(info, &top->device, head) {
			if (info->index == devidx && info->intr >= 0)
				return BIT(info->intr);
		}
	}

	return 0;
}

u32
nvkm_top_intr(struct nvkm_device *device, u32 intr, u64 *psubdevs)
{
	struct nvkm_top *top = device->top;
	struct nvkm_top_device *info;
	u64 subdevs = 0;
	u32 handled = 0;

	if (top) {
		list_for_each_entry(info, &top->device, head) {
			if (info->index != NVKM_SUBDEV_NR && info->intr >= 0) {
				if (intr & BIT(info->intr)) {
					subdevs |= BIT_ULL(info->index);
					handled |= BIT(info->intr);
				}
			}
		}
	}

	*psubdevs = subdevs;
	return intr & ~handled;
}

int
nvkm_top_fault_id(struct nvkm_device *device, enum nvkm_devidx devidx)
{
	struct nvkm_top *top = device->top;
	struct nvkm_top_device *info;

	list_for_each_entry(info, &top->device, head) {
		if (info->index == devidx && info->fault >= 0)
			return info->fault;
	}

	return -ENOENT;
}

enum nvkm_devidx
nvkm_top_fault(struct nvkm_device *device, int fault)
{
	struct nvkm_top *top = device->top;
	struct nvkm_top_device *info;

	list_for_each_entry(info, &top->device, head) {
		if (info->fault == fault)
			return info->index;
	}

	return NVKM_SUBDEV_NR;
}

enum nvkm_devidx
nvkm_top_engine(struct nvkm_device *device, int index, int *runl, int *engn)
{
	struct nvkm_top *top = device->top;
	struct nvkm_top_device *info;
	int n = 0;

	list_for_each_entry(info, &top->device, head) {
		if (info->engine >= 0 && info->runlist >= 0 && n++ == index) {
			*runl = info->runlist;
			*engn = info->engine;
			return info->index;
		}
	}

	return -ENODEV;
}

static int
nvkm_top_oneinit(struct nvkm_subdev *subdev)
{
	struct nvkm_top *top = nvkm_top(subdev);
	return top->func->oneinit(top);
}

static void *
nvkm_top_dtor(struct nvkm_subdev *subdev)
{
	struct nvkm_top *top = nvkm_top(subdev);
	struct nvkm_top_device *info, *temp;

	list_for_each_entry_safe(info, temp, &top->device, head) {
		list_del(&info->head);
		kfree(info);
	}

	return top;
}

static const struct nvkm_subdev_func
nvkm_top = {
	.dtor = nvkm_top_dtor,
	.oneinit = nvkm_top_oneinit,
};

int
nvkm_top_new_(const struct nvkm_top_func *func, struct nvkm_device *device,
	      int index, struct nvkm_top **ptop)
{
	struct nvkm_top *top;
	if (!(top = *ptop = kzalloc(sizeof(*top), GFP_KERNEL)))
		return -ENOMEM;
	nvkm_subdev_ctor(&nvkm_top, device, index, &top->subdev);
	top->func = func;
	INIT_LIST_HEAD(&top->device);
	return 0;
}
