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