1 1.3 riastrad /* $NetBSD: nouveau_mem.c,v 1.3 2021/12/19 10:51:56 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2017 Red Hat Inc. 5 1.1 riastrad * 6 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 7 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 8 1.1 riastrad * to deal in the Software without restriction, including without limitation 9 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 11 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 12 1.1 riastrad * 13 1.1 riastrad * The above copyright notice and this permission notice shall be included in 14 1.1 riastrad * all copies or substantial portions of the Software. 15 1.1 riastrad * 16 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 1.1 riastrad * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 1.1 riastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 1.1 riastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 1.1 riastrad * OTHER DEALINGS IN THE SOFTWARE. 23 1.1 riastrad */ 24 1.1 riastrad #include <sys/cdefs.h> 25 1.3 riastrad __KERNEL_RCSID(0, "$NetBSD: nouveau_mem.c,v 1.3 2021/12/19 10:51:56 riastradh Exp $"); 26 1.1 riastrad 27 1.1 riastrad #include "nouveau_mem.h" 28 1.1 riastrad #include "nouveau_drv.h" 29 1.1 riastrad #include "nouveau_bo.h" 30 1.1 riastrad 31 1.1 riastrad #include <drm/ttm/ttm_bo_driver.h> 32 1.1 riastrad 33 1.1 riastrad #include <nvif/class.h> 34 1.1 riastrad #include <nvif/if000a.h> 35 1.1 riastrad #include <nvif/if500b.h> 36 1.1 riastrad #include <nvif/if500d.h> 37 1.1 riastrad #include <nvif/if900b.h> 38 1.1 riastrad #include <nvif/if900d.h> 39 1.1 riastrad 40 1.3 riastrad #include <linux/nbsd-namespace.h> 41 1.3 riastrad 42 1.1 riastrad int 43 1.1 riastrad nouveau_mem_map(struct nouveau_mem *mem, 44 1.1 riastrad struct nvif_vmm *vmm, struct nvif_vma *vma) 45 1.1 riastrad { 46 1.1 riastrad union { 47 1.1 riastrad struct nv50_vmm_map_v0 nv50; 48 1.1 riastrad struct gf100_vmm_map_v0 gf100; 49 1.1 riastrad } args; 50 1.1 riastrad u32 argc = 0; 51 1.1 riastrad bool super; 52 1.1 riastrad int ret; 53 1.1 riastrad 54 1.1 riastrad switch (vmm->object.oclass) { 55 1.1 riastrad case NVIF_CLASS_VMM_NV04: 56 1.1 riastrad break; 57 1.1 riastrad case NVIF_CLASS_VMM_NV50: 58 1.1 riastrad args.nv50.version = 0; 59 1.1 riastrad args.nv50.ro = 0; 60 1.1 riastrad args.nv50.priv = 0; 61 1.1 riastrad args.nv50.kind = mem->kind; 62 1.1 riastrad args.nv50.comp = mem->comp; 63 1.1 riastrad argc = sizeof(args.nv50); 64 1.1 riastrad break; 65 1.1 riastrad case NVIF_CLASS_VMM_GF100: 66 1.1 riastrad case NVIF_CLASS_VMM_GM200: 67 1.1 riastrad case NVIF_CLASS_VMM_GP100: 68 1.1 riastrad args.gf100.version = 0; 69 1.1 riastrad if (mem->mem.type & NVIF_MEM_VRAM) 70 1.1 riastrad args.gf100.vol = 0; 71 1.1 riastrad else 72 1.1 riastrad args.gf100.vol = 1; 73 1.1 riastrad args.gf100.ro = 0; 74 1.1 riastrad args.gf100.priv = 0; 75 1.1 riastrad args.gf100.kind = mem->kind; 76 1.1 riastrad argc = sizeof(args.gf100); 77 1.1 riastrad break; 78 1.1 riastrad default: 79 1.1 riastrad WARN_ON(1); 80 1.1 riastrad return -ENOSYS; 81 1.1 riastrad } 82 1.1 riastrad 83 1.1 riastrad super = vmm->object.client->super; 84 1.1 riastrad vmm->object.client->super = true; 85 1.1 riastrad ret = nvif_vmm_map(vmm, vma->addr, mem->mem.size, &args, argc, 86 1.1 riastrad &mem->mem, 0); 87 1.1 riastrad vmm->object.client->super = super; 88 1.1 riastrad return ret; 89 1.1 riastrad } 90 1.1 riastrad 91 1.1 riastrad void 92 1.1 riastrad nouveau_mem_fini(struct nouveau_mem *mem) 93 1.1 riastrad { 94 1.1 riastrad nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[1]); 95 1.1 riastrad nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[0]); 96 1.1 riastrad mutex_lock(&mem->cli->drm->master.lock); 97 1.1 riastrad nvif_mem_fini(&mem->mem); 98 1.1 riastrad mutex_unlock(&mem->cli->drm->master.lock); 99 1.1 riastrad } 100 1.1 riastrad 101 1.1 riastrad int 102 1.1 riastrad nouveau_mem_host(struct ttm_mem_reg *reg, struct ttm_dma_tt *tt) 103 1.1 riastrad { 104 1.1 riastrad struct nouveau_mem *mem = nouveau_mem(reg); 105 1.1 riastrad struct nouveau_cli *cli = mem->cli; 106 1.1 riastrad struct nouveau_drm *drm = cli->drm; 107 1.1 riastrad struct nvif_mmu *mmu = &cli->mmu; 108 1.1 riastrad struct nvif_mem_ram_v0 args = {}; 109 1.1 riastrad bool super = cli->base.super; 110 1.1 riastrad u8 type; 111 1.1 riastrad int ret; 112 1.1 riastrad 113 1.1 riastrad if (!nouveau_drm_use_coherent_gpu_mapping(drm)) 114 1.1 riastrad type = drm->ttm.type_ncoh[!!mem->kind]; 115 1.1 riastrad else 116 1.1 riastrad type = drm->ttm.type_host[0]; 117 1.1 riastrad 118 1.1 riastrad if (mem->kind && !(mmu->type[type].type & NVIF_MEM_KIND)) 119 1.1 riastrad mem->comp = mem->kind = 0; 120 1.1 riastrad if (mem->comp && !(mmu->type[type].type & NVIF_MEM_COMP)) { 121 1.1 riastrad if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100) 122 1.1 riastrad mem->kind = mmu->kind[mem->kind]; 123 1.1 riastrad mem->comp = 0; 124 1.1 riastrad } 125 1.1 riastrad 126 1.3 riastrad #ifdef __NetBSD__ /* XXX prime */ 127 1.3 riastrad args.dma = tt->dma_address; 128 1.3 riastrad #else 129 1.1 riastrad if (tt->ttm.sg) args.sgl = tt->ttm.sg->sgl; 130 1.1 riastrad else args.dma = tt->dma_address; 131 1.3 riastrad #endif 132 1.1 riastrad 133 1.1 riastrad mutex_lock(&drm->master.lock); 134 1.1 riastrad cli->base.super = true; 135 1.1 riastrad ret = nvif_mem_init_type(mmu, cli->mem->oclass, type, PAGE_SHIFT, 136 1.1 riastrad reg->num_pages << PAGE_SHIFT, 137 1.1 riastrad &args, sizeof(args), &mem->mem); 138 1.1 riastrad cli->base.super = super; 139 1.1 riastrad mutex_unlock(&drm->master.lock); 140 1.1 riastrad return ret; 141 1.1 riastrad } 142 1.1 riastrad 143 1.1 riastrad int 144 1.1 riastrad nouveau_mem_vram(struct ttm_mem_reg *reg, bool contig, u8 page) 145 1.1 riastrad { 146 1.1 riastrad struct nouveau_mem *mem = nouveau_mem(reg); 147 1.1 riastrad struct nouveau_cli *cli = mem->cli; 148 1.1 riastrad struct nouveau_drm *drm = cli->drm; 149 1.1 riastrad struct nvif_mmu *mmu = &cli->mmu; 150 1.1 riastrad bool super = cli->base.super; 151 1.1 riastrad u64 size = ALIGN(reg->num_pages << PAGE_SHIFT, 1 << page); 152 1.1 riastrad int ret; 153 1.1 riastrad 154 1.1 riastrad mutex_lock(&drm->master.lock); 155 1.1 riastrad cli->base.super = true; 156 1.1 riastrad switch (cli->mem->oclass) { 157 1.1 riastrad case NVIF_CLASS_MEM_GF100: 158 1.1 riastrad ret = nvif_mem_init_type(mmu, cli->mem->oclass, 159 1.1 riastrad drm->ttm.type_vram, page, size, 160 1.1 riastrad &(struct gf100_mem_v0) { 161 1.1 riastrad .contig = contig, 162 1.1 riastrad }, sizeof(struct gf100_mem_v0), 163 1.1 riastrad &mem->mem); 164 1.1 riastrad break; 165 1.1 riastrad case NVIF_CLASS_MEM_NV50: 166 1.1 riastrad ret = nvif_mem_init_type(mmu, cli->mem->oclass, 167 1.1 riastrad drm->ttm.type_vram, page, size, 168 1.1 riastrad &(struct nv50_mem_v0) { 169 1.1 riastrad .bankswz = mmu->kind[mem->kind] == 2, 170 1.1 riastrad .contig = contig, 171 1.1 riastrad }, sizeof(struct nv50_mem_v0), 172 1.1 riastrad &mem->mem); 173 1.1 riastrad break; 174 1.1 riastrad default: 175 1.1 riastrad ret = -ENOSYS; 176 1.1 riastrad WARN_ON(1); 177 1.1 riastrad break; 178 1.1 riastrad } 179 1.1 riastrad cli->base.super = super; 180 1.1 riastrad mutex_unlock(&drm->master.lock); 181 1.1 riastrad 182 1.1 riastrad reg->start = mem->mem.addr >> PAGE_SHIFT; 183 1.1 riastrad return ret; 184 1.1 riastrad } 185 1.1 riastrad 186 1.1 riastrad void 187 1.1 riastrad nouveau_mem_del(struct ttm_mem_reg *reg) 188 1.1 riastrad { 189 1.1 riastrad struct nouveau_mem *mem = nouveau_mem(reg); 190 1.1 riastrad nouveau_mem_fini(mem); 191 1.1 riastrad kfree(reg->mm_node); 192 1.1 riastrad reg->mm_node = NULL; 193 1.1 riastrad } 194 1.1 riastrad 195 1.1 riastrad int 196 1.1 riastrad nouveau_mem_new(struct nouveau_cli *cli, u8 kind, u8 comp, 197 1.1 riastrad struct ttm_mem_reg *reg) 198 1.1 riastrad { 199 1.1 riastrad struct nouveau_mem *mem; 200 1.1 riastrad 201 1.1 riastrad if (!(mem = kzalloc(sizeof(*mem), GFP_KERNEL))) 202 1.1 riastrad return -ENOMEM; 203 1.1 riastrad mem->cli = cli; 204 1.1 riastrad mem->kind = kind; 205 1.1 riastrad mem->comp = comp; 206 1.1 riastrad 207 1.1 riastrad reg->mm_node = mem; 208 1.1 riastrad return 0; 209 1.1 riastrad } 210