/*
 * Copyright 2017 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 "nouveau_mem.h"
#include "nouveau_drv.h"
#include "nouveau_bo.h"

#include <drm/ttm/ttm_bo_driver.h>

#include <nvif/class.h>
#include <nvif/if000a.h>
#include <nvif/if500b.h>
#include <nvif/if500d.h>
#include <nvif/if900b.h>
#include <nvif/if900d.h>

int
nouveau_mem_map(struct nouveau_mem *mem,
		struct nvif_vmm *vmm, struct nvif_vma *vma)
{
	union {
		struct nv50_vmm_map_v0 nv50;
		struct gf100_vmm_map_v0 gf100;
	} args;
	u32 argc = 0;
	bool super;
	int ret;

	switch (vmm->object.oclass) {
	case NVIF_CLASS_VMM_NV04:
		break;
	case NVIF_CLASS_VMM_NV50:
		args.nv50.version = 0;
		args.nv50.ro = 0;
		args.nv50.priv = 0;
		args.nv50.kind = mem->kind;
		args.nv50.comp = mem->comp;
		argc = sizeof(args.nv50);
		break;
	case NVIF_CLASS_VMM_GF100:
	case NVIF_CLASS_VMM_GM200:
	case NVIF_CLASS_VMM_GP100:
		args.gf100.version = 0;
		if (mem->mem.type & NVIF_MEM_VRAM)
			args.gf100.vol = 0;
		else
			args.gf100.vol = 1;
		args.gf100.ro = 0;
		args.gf100.priv = 0;
		args.gf100.kind = mem->kind;
		argc = sizeof(args.gf100);
		break;
	default:
		WARN_ON(1);
		return -ENOSYS;
	}

	super = vmm->object.client->super;
	vmm->object.client->super = true;
	ret = nvif_vmm_map(vmm, vma->addr, mem->mem.size, &args, argc,
			   &mem->mem, 0);
	vmm->object.client->super = super;
	return ret;
}

void
nouveau_mem_fini(struct nouveau_mem *mem)
{
	nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[1]);
	nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[0]);
	mutex_lock(&mem->cli->drm->master.lock);
	nvif_mem_dtor(&mem->mem);
	mutex_unlock(&mem->cli->drm->master.lock);
}

int
nouveau_mem_host(struct ttm_resource *reg, struct ttm_dma_tt *tt)
{
	struct nouveau_mem *mem = nouveau_mem(reg);
	struct nouveau_cli *cli = mem->cli;
	struct nouveau_drm *drm = cli->drm;
	struct nvif_mmu *mmu = &cli->mmu;
	struct nvif_mem_ram_v0 args = {};
	bool super = cli->base.super;
	u8 type;
	int ret;

	if (!nouveau_drm_use_coherent_gpu_mapping(drm))
		type = drm->ttm.type_ncoh[!!mem->kind];
	else
		type = drm->ttm.type_host[0];

	if (mem->kind && !(mmu->type[type].type & NVIF_MEM_KIND))
		mem->comp = mem->kind = 0;
	if (mem->comp && !(mmu->type[type].type & NVIF_MEM_COMP)) {
		if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100)
			mem->kind = mmu->kind[mem->kind];
		mem->comp = 0;
	}

	if (tt->ttm.sg) args.sgl = tt->ttm.sg->sgl;
	else            args.dma = tt->dma_address;

	mutex_lock(&drm->master.lock);
	cli->base.super = true;
	ret = nvif_mem_ctor_type(mmu, "ttmHostMem", cli->mem->oclass, type, PAGE_SHIFT,
				 reg->num_pages << PAGE_SHIFT,
				 &args, sizeof(args), &mem->mem);
	cli->base.super = super;
	mutex_unlock(&drm->master.lock);
	return ret;
}

int
nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page)
{
	struct nouveau_mem *mem = nouveau_mem(reg);
	struct nouveau_cli *cli = mem->cli;
	struct nouveau_drm *drm = cli->drm;
	struct nvif_mmu *mmu = &cli->mmu;
	bool super = cli->base.super;
	u64 size = ALIGN(reg->num_pages << PAGE_SHIFT, 1 << page);
	int ret;

	mutex_lock(&drm->master.lock);
	cli->base.super = true;
	switch (cli->mem->oclass) {
	case NVIF_CLASS_MEM_GF100:
		ret = nvif_mem_ctor_type(mmu, "ttmVram", cli->mem->oclass,
					 drm->ttm.type_vram, page, size,
					 &(struct gf100_mem_v0) {
						.contig = contig,
					 }, sizeof(struct gf100_mem_v0),
					 &mem->mem);
		break;
	case NVIF_CLASS_MEM_NV50:
		ret = nvif_mem_ctor_type(mmu, "ttmVram", cli->mem->oclass,
					 drm->ttm.type_vram, page, size,
					 &(struct nv50_mem_v0) {
						.bankswz = mmu->kind[mem->kind] == 2,
						.contig = contig,
					 }, sizeof(struct nv50_mem_v0),
					 &mem->mem);
		break;
	default:
		ret = -ENOSYS;
		WARN_ON(1);
		break;
	}
	cli->base.super = super;
	mutex_unlock(&drm->master.lock);

	reg->start = mem->mem.addr >> PAGE_SHIFT;
	return ret;
}

void
nouveau_mem_del(struct ttm_resource *reg)
{
	struct nouveau_mem *mem = nouveau_mem(reg);
	if (!mem)
		return;
	nouveau_mem_fini(mem);
	kfree(reg->mm_node);
	reg->mm_node = NULL;
}

int
nouveau_mem_new(struct nouveau_cli *cli, u8 kind, u8 comp,
		struct ttm_resource *reg)
{
	struct nouveau_mem *mem;

	if (!(mem = kzalloc(sizeof(*mem), GFP_KERNEL)))
		return -ENOMEM;
	mem->cli = cli;
	mem->kind = kind;
	mem->comp = comp;

	reg->mm_node = mem;
	return 0;
}
