1*4882a593Smuzhiyun // SPDX-License-Identifier: MIT
2*4882a593Smuzhiyun #include <linux/pagemap.h>
3*4882a593Smuzhiyun #include <linux/slab.h>
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include "nouveau_drv.h"
6*4882a593Smuzhiyun #include "nouveau_mem.h"
7*4882a593Smuzhiyun #include "nouveau_ttm.h"
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun struct nouveau_sgdma_be {
10*4882a593Smuzhiyun /* this has to be the first field so populate/unpopulated in
11*4882a593Smuzhiyun * nouve_bo.c works properly, otherwise have to move them here
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun struct ttm_dma_tt ttm;
14*4882a593Smuzhiyun struct nouveau_mem *mem;
15*4882a593Smuzhiyun };
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun void
nouveau_sgdma_destroy(struct ttm_bo_device * bdev,struct ttm_tt * ttm)18*4882a593Smuzhiyun nouveau_sgdma_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun if (ttm) {
23*4882a593Smuzhiyun nouveau_sgdma_unbind(bdev, ttm);
24*4882a593Smuzhiyun ttm_tt_destroy_common(bdev, ttm);
25*4882a593Smuzhiyun ttm_dma_tt_fini(&nvbe->ttm);
26*4882a593Smuzhiyun kfree(nvbe);
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun int
nouveau_sgdma_bind(struct ttm_bo_device * bdev,struct ttm_tt * ttm,struct ttm_resource * reg)31*4882a593Smuzhiyun nouveau_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *reg)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
34*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_bdev(bdev);
35*4882a593Smuzhiyun struct nouveau_mem *mem = nouveau_mem(reg);
36*4882a593Smuzhiyun int ret;
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun if (nvbe->mem)
39*4882a593Smuzhiyun return 0;
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun ret = nouveau_mem_host(reg, &nvbe->ttm);
42*4882a593Smuzhiyun if (ret)
43*4882a593Smuzhiyun return ret;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
46*4882a593Smuzhiyun ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]);
47*4882a593Smuzhiyun if (ret) {
48*4882a593Smuzhiyun nouveau_mem_fini(mem);
49*4882a593Smuzhiyun return ret;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun nvbe->mem = mem;
54*4882a593Smuzhiyun return 0;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun void
nouveau_sgdma_unbind(struct ttm_bo_device * bdev,struct ttm_tt * ttm)58*4882a593Smuzhiyun nouveau_sgdma_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
61*4882a593Smuzhiyun if (nvbe->mem) {
62*4882a593Smuzhiyun nouveau_mem_fini(nvbe->mem);
63*4882a593Smuzhiyun nvbe->mem = NULL;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun struct ttm_tt *
nouveau_sgdma_create_ttm(struct ttm_buffer_object * bo,uint32_t page_flags)68*4882a593Smuzhiyun nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun struct nouveau_sgdma_be *nvbe;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL);
73*4882a593Smuzhiyun if (!nvbe)
74*4882a593Smuzhiyun return NULL;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun if (ttm_dma_tt_init(&nvbe->ttm, bo, page_flags)) {
77*4882a593Smuzhiyun kfree(nvbe);
78*4882a593Smuzhiyun return NULL;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun return &nvbe->ttm.ttm;
81*4882a593Smuzhiyun }
82