Home | History | Annotate | Line # | Download | only in nouveau
      1  1.1  riastrad /*	$NetBSD: nouveau_vmm.c,v 1.2 2021/12/18 23:45:32 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.1  riastrad __KERNEL_RCSID(0, "$NetBSD: nouveau_vmm.c,v 1.2 2021/12/18 23:45:32 riastradh Exp $");
     26  1.1  riastrad 
     27  1.1  riastrad #include "nouveau_vmm.h"
     28  1.1  riastrad #include "nouveau_drv.h"
     29  1.1  riastrad #include "nouveau_bo.h"
     30  1.1  riastrad #include "nouveau_svm.h"
     31  1.1  riastrad #include "nouveau_mem.h"
     32  1.1  riastrad 
     33  1.1  riastrad void
     34  1.1  riastrad nouveau_vma_unmap(struct nouveau_vma *vma)
     35  1.1  riastrad {
     36  1.1  riastrad 	if (vma->mem) {
     37  1.1  riastrad 		nvif_vmm_unmap(&vma->vmm->vmm, vma->addr);
     38  1.1  riastrad 		vma->mem = NULL;
     39  1.1  riastrad 	}
     40  1.1  riastrad }
     41  1.1  riastrad 
     42  1.1  riastrad int
     43  1.1  riastrad nouveau_vma_map(struct nouveau_vma *vma, struct nouveau_mem *mem)
     44  1.1  riastrad {
     45  1.1  riastrad 	struct nvif_vma tmp = { .addr = vma->addr };
     46  1.1  riastrad 	int ret = nouveau_mem_map(mem, &vma->vmm->vmm, &tmp);
     47  1.1  riastrad 	if (ret)
     48  1.1  riastrad 		return ret;
     49  1.1  riastrad 	vma->mem = mem;
     50  1.1  riastrad 	return 0;
     51  1.1  riastrad }
     52  1.1  riastrad 
     53  1.1  riastrad struct nouveau_vma *
     54  1.1  riastrad nouveau_vma_find(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm)
     55  1.1  riastrad {
     56  1.1  riastrad 	struct nouveau_vma *vma;
     57  1.1  riastrad 
     58  1.1  riastrad 	list_for_each_entry(vma, &nvbo->vma_list, head) {
     59  1.1  riastrad 		if (vma->vmm == vmm)
     60  1.1  riastrad 			return vma;
     61  1.1  riastrad 	}
     62  1.1  riastrad 
     63  1.1  riastrad 	return NULL;
     64  1.1  riastrad }
     65  1.1  riastrad 
     66  1.1  riastrad void
     67  1.1  riastrad nouveau_vma_del(struct nouveau_vma **pvma)
     68  1.1  riastrad {
     69  1.1  riastrad 	struct nouveau_vma *vma = *pvma;
     70  1.1  riastrad 	if (vma && --vma->refs <= 0) {
     71  1.1  riastrad 		if (likely(vma->addr != ~0ULL)) {
     72  1.1  riastrad 			struct nvif_vma tmp = { .addr = vma->addr, .size = 1 };
     73  1.1  riastrad 			nvif_vmm_put(&vma->vmm->vmm, &tmp);
     74  1.1  riastrad 		}
     75  1.1  riastrad 		list_del(&vma->head);
     76  1.1  riastrad 		kfree(*pvma);
     77  1.1  riastrad 	}
     78  1.1  riastrad 	*pvma = NULL;
     79  1.1  riastrad }
     80  1.1  riastrad 
     81  1.1  riastrad int
     82  1.1  riastrad nouveau_vma_new(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm,
     83  1.1  riastrad 		struct nouveau_vma **pvma)
     84  1.1  riastrad {
     85  1.1  riastrad 	struct nouveau_mem *mem = nouveau_mem(&nvbo->bo.mem);
     86  1.1  riastrad 	struct nouveau_vma *vma;
     87  1.1  riastrad 	struct nvif_vma tmp;
     88  1.1  riastrad 	int ret;
     89  1.1  riastrad 
     90  1.1  riastrad 	if ((vma = *pvma = nouveau_vma_find(nvbo, vmm))) {
     91  1.1  riastrad 		vma->refs++;
     92  1.1  riastrad 		return 0;
     93  1.1  riastrad 	}
     94  1.1  riastrad 
     95  1.1  riastrad 	if (!(vma = *pvma = kmalloc(sizeof(*vma), GFP_KERNEL)))
     96  1.1  riastrad 		return -ENOMEM;
     97  1.1  riastrad 	vma->vmm = vmm;
     98  1.1  riastrad 	vma->refs = 1;
     99  1.1  riastrad 	vma->addr = ~0ULL;
    100  1.1  riastrad 	vma->mem = NULL;
    101  1.1  riastrad 	vma->fence = NULL;
    102  1.1  riastrad 	list_add_tail(&vma->head, &nvbo->vma_list);
    103  1.1  riastrad 
    104  1.1  riastrad 	if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM &&
    105  1.1  riastrad 	    mem->mem.page == nvbo->page) {
    106  1.1  riastrad 		ret = nvif_vmm_get(&vmm->vmm, LAZY, false, mem->mem.page, 0,
    107  1.1  riastrad 				   mem->mem.size, &tmp);
    108  1.1  riastrad 		if (ret)
    109  1.1  riastrad 			goto done;
    110  1.1  riastrad 
    111  1.1  riastrad 		vma->addr = tmp.addr;
    112  1.1  riastrad 		ret = nouveau_vma_map(vma, mem);
    113  1.1  riastrad 	} else {
    114  1.1  riastrad 		ret = nvif_vmm_get(&vmm->vmm, PTES, false, mem->mem.page, 0,
    115  1.1  riastrad 				   mem->mem.size, &tmp);
    116  1.1  riastrad 		vma->addr = tmp.addr;
    117  1.1  riastrad 	}
    118  1.1  riastrad 
    119  1.1  riastrad done:
    120  1.1  riastrad 	if (ret)
    121  1.1  riastrad 		nouveau_vma_del(pvma);
    122  1.1  riastrad 	return ret;
    123  1.1  riastrad }
    124  1.1  riastrad 
    125  1.1  riastrad void
    126  1.1  riastrad nouveau_vmm_fini(struct nouveau_vmm *vmm)
    127  1.1  riastrad {
    128  1.1  riastrad 	nouveau_svmm_fini(&vmm->svmm);
    129  1.1  riastrad 	nvif_vmm_fini(&vmm->vmm);
    130  1.1  riastrad 	vmm->cli = NULL;
    131  1.1  riastrad }
    132  1.1  riastrad 
    133  1.1  riastrad int
    134  1.1  riastrad nouveau_vmm_init(struct nouveau_cli *cli, s32 oclass, struct nouveau_vmm *vmm)
    135  1.1  riastrad {
    136  1.1  riastrad 	int ret = nvif_vmm_init(&cli->mmu, oclass, false, PAGE_SIZE, 0, NULL, 0,
    137  1.1  riastrad 				&vmm->vmm);
    138  1.1  riastrad 	if (ret)
    139  1.1  riastrad 		return ret;
    140  1.1  riastrad 
    141  1.1  riastrad 	vmm->cli = cli;
    142  1.1  riastrad 	return 0;
    143  1.1  riastrad }
    144