1 1.2 riastrad /* $NetBSD: nouveau_sgdma.c,v 1.3 2021/12/18 23:45:32 riastradh Exp $ */ 2 1.2 riastrad 3 1.3 riastrad // SPDX-License-Identifier: MIT 4 1.2 riastrad #include <sys/cdefs.h> 5 1.2 riastrad __KERNEL_RCSID(0, "$NetBSD: nouveau_sgdma.c,v 1.3 2021/12/18 23:45:32 riastradh Exp $"); 6 1.2 riastrad 7 1.1 riastrad #include <linux/pagemap.h> 8 1.1 riastrad #include <linux/slab.h> 9 1.1 riastrad 10 1.3 riastrad #include "nouveau_drv.h" 11 1.3 riastrad #include "nouveau_mem.h" 12 1.1 riastrad #include "nouveau_ttm.h" 13 1.1 riastrad 14 1.1 riastrad struct nouveau_sgdma_be { 15 1.1 riastrad /* this has to be the first field so populate/unpopulated in 16 1.1 riastrad * nouve_bo.c works properly, otherwise have to move them here 17 1.1 riastrad */ 18 1.1 riastrad struct ttm_dma_tt ttm; 19 1.3 riastrad struct nouveau_mem *mem; 20 1.1 riastrad }; 21 1.1 riastrad 22 1.1 riastrad static void 23 1.1 riastrad nouveau_sgdma_destroy(struct ttm_tt *ttm) 24 1.1 riastrad { 25 1.1 riastrad struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; 26 1.1 riastrad 27 1.1 riastrad if (ttm) { 28 1.1 riastrad ttm_dma_tt_fini(&nvbe->ttm); 29 1.1 riastrad kfree(nvbe); 30 1.1 riastrad } 31 1.1 riastrad } 32 1.1 riastrad 33 1.1 riastrad static int 34 1.3 riastrad nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) 35 1.1 riastrad { 36 1.1 riastrad struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; 37 1.3 riastrad struct nouveau_mem *mem = nouveau_mem(reg); 38 1.3 riastrad int ret; 39 1.1 riastrad 40 1.3 riastrad ret = nouveau_mem_host(reg, &nvbe->ttm); 41 1.3 riastrad if (ret) 42 1.3 riastrad return ret; 43 1.3 riastrad 44 1.3 riastrad ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]); 45 1.3 riastrad if (ret) { 46 1.3 riastrad nouveau_mem_fini(mem); 47 1.3 riastrad return ret; 48 1.1 riastrad } 49 1.1 riastrad 50 1.3 riastrad nvbe->mem = mem; 51 1.1 riastrad return 0; 52 1.1 riastrad } 53 1.1 riastrad 54 1.1 riastrad static int 55 1.1 riastrad nv04_sgdma_unbind(struct ttm_tt *ttm) 56 1.1 riastrad { 57 1.1 riastrad struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; 58 1.3 riastrad nouveau_mem_fini(nvbe->mem); 59 1.1 riastrad return 0; 60 1.1 riastrad } 61 1.1 riastrad 62 1.1 riastrad static struct ttm_backend_func nv04_sgdma_backend = { 63 1.1 riastrad .bind = nv04_sgdma_bind, 64 1.1 riastrad .unbind = nv04_sgdma_unbind, 65 1.1 riastrad .destroy = nouveau_sgdma_destroy 66 1.1 riastrad }; 67 1.1 riastrad 68 1.1 riastrad static int 69 1.3 riastrad nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) 70 1.1 riastrad { 71 1.1 riastrad struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; 72 1.3 riastrad struct nouveau_mem *mem = nouveau_mem(reg); 73 1.3 riastrad int ret; 74 1.1 riastrad 75 1.3 riastrad ret = nouveau_mem_host(reg, &nvbe->ttm); 76 1.3 riastrad if (ret) 77 1.3 riastrad return ret; 78 1.1 riastrad 79 1.3 riastrad nvbe->mem = mem; 80 1.1 riastrad return 0; 81 1.1 riastrad } 82 1.1 riastrad 83 1.1 riastrad static struct ttm_backend_func nv50_sgdma_backend = { 84 1.1 riastrad .bind = nv50_sgdma_bind, 85 1.3 riastrad .unbind = nv04_sgdma_unbind, 86 1.1 riastrad .destroy = nouveau_sgdma_destroy 87 1.1 riastrad }; 88 1.1 riastrad 89 1.1 riastrad struct ttm_tt * 90 1.3 riastrad nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags) 91 1.1 riastrad { 92 1.3 riastrad struct nouveau_drm *drm = nouveau_bdev(bo->bdev); 93 1.1 riastrad struct nouveau_sgdma_be *nvbe; 94 1.1 riastrad 95 1.1 riastrad nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL); 96 1.1 riastrad if (!nvbe) 97 1.1 riastrad return NULL; 98 1.1 riastrad 99 1.3 riastrad if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) 100 1.1 riastrad nvbe->ttm.ttm.func = &nv04_sgdma_backend; 101 1.1 riastrad else 102 1.1 riastrad nvbe->ttm.ttm.func = &nv50_sgdma_backend; 103 1.1 riastrad 104 1.3 riastrad if (ttm_dma_tt_init(&nvbe->ttm, bo, page_flags)) 105 1.2 riastrad /* 106 1.2 riastrad * A failing ttm_dma_tt_init() will call ttm_tt_destroy() 107 1.2 riastrad * and thus our nouveau_sgdma_destroy() hook, so we don't need 108 1.2 riastrad * to free nvbe here. 109 1.2 riastrad */ 110 1.1 riastrad return NULL; 111 1.1 riastrad return &nvbe->ttm.ttm; 112 1.1 riastrad } 113