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