]>
Commit | Line | Data |
---|---|---|
24e8375b BS |
1 | /* |
2 | * Copyright 2017 Red Hat Inc. | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
20 | * OTHER DEALINGS IN THE SOFTWARE. | |
21 | */ | |
22 | #include "nouveau_vmm.h" | |
23 | #include "nouveau_drv.h" | |
24 | #include "nouveau_bo.h" | |
25 | #include "nouveau_mem.h" | |
26 | ||
27 | void | |
28 | nouveau_vma_unmap(struct nouveau_vma *vma) | |
29 | { | |
30 | if (vma->mem) { | |
d7722134 | 31 | nvif_vmm_unmap(&vma->vmm->vmm, vma->addr); |
24e8375b BS |
32 | vma->mem = NULL; |
33 | } | |
34 | } | |
35 | ||
36 | int | |
37 | nouveau_vma_map(struct nouveau_vma *vma, struct nouveau_mem *mem) | |
38 | { | |
d7722134 BS |
39 | struct nvif_vma tmp = { .addr = vma->addr }; |
40 | int ret = nouveau_mem_map(mem, &vma->vmm->vmm, &tmp); | |
24e8375b BS |
41 | if (ret) |
42 | return ret; | |
43 | vma->mem = mem; | |
44 | return 0; | |
45 | } | |
46 | ||
47 | struct nouveau_vma * | |
48 | nouveau_vma_find(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm) | |
49 | { | |
50 | struct nouveau_vma *vma; | |
51 | ||
52 | list_for_each_entry(vma, &nvbo->vma_list, head) { | |
53 | if (vma->vmm == vmm) | |
54 | return vma; | |
55 | } | |
56 | ||
57 | return NULL; | |
58 | } | |
59 | ||
60 | void | |
61 | nouveau_vma_del(struct nouveau_vma **pvma) | |
62 | { | |
63 | struct nouveau_vma *vma = *pvma; | |
64 | if (vma && --vma->refs <= 0) { | |
d7722134 BS |
65 | if (likely(vma->addr != ~0ULL)) { |
66 | struct nvif_vma tmp = { .addr = vma->addr, .size = 1 }; | |
67 | nvif_vmm_put(&vma->vmm->vmm, &tmp); | |
68 | } | |
24e8375b | 69 | list_del(&vma->head); |
24e8375b | 70 | kfree(*pvma); |
4ef92892 | 71 | *pvma = NULL; |
24e8375b BS |
72 | } |
73 | } | |
74 | ||
75 | int | |
76 | nouveau_vma_new(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm, | |
77 | struct nouveau_vma **pvma) | |
78 | { | |
79 | struct nouveau_mem *mem = nouveau_mem(&nvbo->bo.mem); | |
80 | struct nouveau_vma *vma; | |
d7722134 | 81 | struct nvif_vma tmp; |
24e8375b BS |
82 | int ret; |
83 | ||
84 | if ((vma = *pvma = nouveau_vma_find(nvbo, vmm))) { | |
85 | vma->refs++; | |
86 | return 0; | |
87 | } | |
88 | ||
89 | if (!(vma = *pvma = kmalloc(sizeof(*vma), GFP_KERNEL))) | |
90 | return -ENOMEM; | |
91 | vma->vmm = vmm; | |
92 | vma->refs = 1; | |
93 | vma->addr = ~0ULL; | |
94 | vma->mem = NULL; | |
95 | list_add_tail(&vma->head, &nvbo->vma_list); | |
96 | ||
97 | if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM && | |
98 | mem->mem.page == nvbo->page) { | |
d7722134 BS |
99 | ret = nvif_vmm_get(&vmm->vmm, LAZY, false, mem->mem.page, 0, |
100 | mem->mem.size, &tmp); | |
24e8375b BS |
101 | if (ret) |
102 | goto done; | |
103 | ||
d7722134 | 104 | vma->addr = tmp.addr; |
24e8375b BS |
105 | ret = nouveau_vma_map(vma, mem); |
106 | } else { | |
d7722134 BS |
107 | ret = nvif_vmm_get(&vmm->vmm, PTES, false, mem->mem.page, 0, |
108 | mem->mem.size, &tmp); | |
109 | vma->addr = tmp.addr; | |
24e8375b BS |
110 | } |
111 | ||
112 | done: | |
113 | if (ret) | |
114 | nouveau_vma_del(pvma); | |
115 | return ret; | |
116 | } | |
117 | ||
118 | void | |
119 | nouveau_vmm_fini(struct nouveau_vmm *vmm) | |
120 | { | |
96da0bcd BS |
121 | nvif_vmm_fini(&vmm->vmm); |
122 | vmm->cli = NULL; | |
24e8375b BS |
123 | } |
124 | ||
125 | int | |
126 | nouveau_vmm_init(struct nouveau_cli *cli, s32 oclass, struct nouveau_vmm *vmm) | |
127 | { | |
96da0bcd BS |
128 | int ret = nvif_vmm_init(&cli->mmu, oclass, PAGE_SIZE, 0, NULL, 0, |
129 | &vmm->vmm); | |
130 | if (ret) | |
131 | return ret; | |
132 | ||
24e8375b | 133 | vmm->cli = cli; |
96da0bcd | 134 | return 0; |
24e8375b | 135 | } |