2 * Copyright 2017 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
22 #include "nouveau_mem.h"
23 #include "nouveau_drv.h"
24 #include "nouveau_bo.h"
26 #include <drm/ttm/ttm_bo_driver.h>
28 #include <nvif/class.h>
29 #include <nvif/if000a.h>
30 #include <nvif/if500b.h>
31 #include <nvif/if500d.h>
32 #include <nvif/if900b.h>
33 #include <nvif/if900d.h>
36 nouveau_mem_map(struct nouveau_mem
*mem
,
37 struct nvif_vmm
*vmm
, struct nvif_vma
*vma
)
40 struct nv50_vmm_map_v0 nv50
;
41 struct gf100_vmm_map_v0 gf100
;
47 switch (vmm
->object
.oclass
) {
48 case NVIF_CLASS_VMM_NV04
:
50 case NVIF_CLASS_VMM_NV50
:
51 args
.nv50
.version
= 0;
54 args
.nv50
.kind
= mem
->kind
;
55 args
.nv50
.comp
= mem
->comp
;
56 argc
= sizeof(args
.nv50
);
58 case NVIF_CLASS_VMM_GF100
:
59 case NVIF_CLASS_VMM_GM200
:
60 case NVIF_CLASS_VMM_GP100
:
61 args
.gf100
.version
= 0;
62 if (mem
->mem
.type
& NVIF_MEM_VRAM
)
68 args
.gf100
.kind
= mem
->kind
;
69 argc
= sizeof(args
.gf100
);
76 super
= vmm
->object
.client
->super
;
77 vmm
->object
.client
->super
= true;
78 ret
= nvif_vmm_map(vmm
, vma
->addr
, mem
->mem
.size
, &args
, argc
,
80 vmm
->object
.client
->super
= super
;
85 nouveau_mem_fini(struct nouveau_mem
*mem
)
87 nvif_vmm_put(&mem
->cli
->drm
->client
.vmm
.vmm
, &mem
->vma
[1]);
88 nvif_vmm_put(&mem
->cli
->drm
->client
.vmm
.vmm
, &mem
->vma
[0]);
89 mutex_lock(&mem
->cli
->drm
->master
.lock
);
90 nvif_mem_fini(&mem
->mem
);
91 mutex_unlock(&mem
->cli
->drm
->master
.lock
);
95 nouveau_mem_host(struct ttm_mem_reg
*reg
, struct ttm_dma_tt
*tt
)
97 struct nouveau_mem
*mem
= nouveau_mem(reg
);
98 struct nouveau_cli
*cli
= mem
->cli
;
99 struct nouveau_drm
*drm
= cli
->drm
;
100 struct nvif_mmu
*mmu
= &cli
->mmu
;
101 struct nvif_mem_ram_v0 args
= {};
102 bool super
= cli
->base
.super
;
106 if (!nouveau_drm_use_coherent_gpu_mapping(drm
))
107 type
= drm
->ttm
.type_ncoh
[!!mem
->kind
];
109 type
= drm
->ttm
.type_host
[0];
111 if (mem
->kind
&& !(mmu
->type
[type
].type
& NVIF_MEM_KIND
))
112 mem
->comp
= mem
->kind
= 0;
113 if (mem
->comp
&& !(mmu
->type
[type
].type
& NVIF_MEM_COMP
)) {
114 if (mmu
->object
.oclass
>= NVIF_CLASS_MMU_GF100
)
115 mem
->kind
= mmu
->kind
[mem
->kind
];
119 if (tt
->ttm
.sg
) args
.sgl
= tt
->ttm
.sg
->sgl
;
120 else args
.dma
= tt
->dma_address
;
122 mutex_lock(&drm
->master
.lock
);
123 cli
->base
.super
= true;
124 ret
= nvif_mem_init_type(mmu
, cli
->mem
->oclass
, type
, PAGE_SHIFT
,
125 reg
->num_pages
<< PAGE_SHIFT
,
126 &args
, sizeof(args
), &mem
->mem
);
127 cli
->base
.super
= super
;
128 mutex_unlock(&drm
->master
.lock
);
133 nouveau_mem_vram(struct ttm_mem_reg
*reg
, bool contig
, u8 page
)
135 struct nouveau_mem
*mem
= nouveau_mem(reg
);
136 struct nouveau_cli
*cli
= mem
->cli
;
137 struct nouveau_drm
*drm
= cli
->drm
;
138 struct nvif_mmu
*mmu
= &cli
->mmu
;
139 bool super
= cli
->base
.super
;
140 u64 size
= ALIGN(reg
->num_pages
<< PAGE_SHIFT
, 1 << page
);
143 mutex_lock(&drm
->master
.lock
);
144 cli
->base
.super
= true;
145 switch (cli
->mem
->oclass
) {
146 case NVIF_CLASS_MEM_GF100
:
147 ret
= nvif_mem_init_type(mmu
, cli
->mem
->oclass
,
148 drm
->ttm
.type_vram
, page
, size
,
149 &(struct gf100_mem_v0
) {
151 }, sizeof(struct gf100_mem_v0
),
154 case NVIF_CLASS_MEM_NV50
:
155 ret
= nvif_mem_init_type(mmu
, cli
->mem
->oclass
,
156 drm
->ttm
.type_vram
, page
, size
,
157 &(struct nv50_mem_v0
) {
158 .bankswz
= mmu
->kind
[mem
->kind
] == 2,
160 }, sizeof(struct nv50_mem_v0
),
168 cli
->base
.super
= super
;
169 mutex_unlock(&drm
->master
.lock
);
171 reg
->start
= mem
->mem
.addr
>> PAGE_SHIFT
;
176 nouveau_mem_del(struct ttm_mem_reg
*reg
)
178 struct nouveau_mem
*mem
= nouveau_mem(reg
);
179 nouveau_mem_fini(mem
);
185 nouveau_mem_new(struct nouveau_cli
*cli
, u8 kind
, u8 comp
,
186 struct ttm_mem_reg
*reg
)
188 struct nouveau_mem
*mem
;
190 if (!(mem
= kzalloc(sizeof(*mem
), GFP_KERNEL
)))