blob: ec6ec1f8a0852cd87984a74497bfdf886cf74be1 [file] [log] [blame]
Alex Deucherd38ceaf2015-04-20 16:55:21 -04001/*
2 * Copyright 2009 Jerome Glisse.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19 * USE OR OTHER DEALINGS IN THE SOFTWARE.
20 *
21 * The above copyright notice and this permission notice (including the
22 * next paragraph) shall be included in all copies or substantial portions
23 * of the Software.
24 *
25 */
26/*
27 * Authors:
28 * Jerome Glisse <glisse@freedesktop.org>
29 * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
30 * Dave Airlie
31 */
32#include <linux/list.h>
33#include <linux/slab.h>
34#include <drm/drmP.h>
35#include <drm/amdgpu_drm.h>
Oded Gabbaya187f172016-01-30 07:59:34 +020036#include <drm/drm_cache.h>
Alex Deucherd38ceaf2015-04-20 16:55:21 -040037#include "amdgpu.h"
38#include "amdgpu_trace.h"
Felix Kuehlinga46a2cd2018-02-06 20:32:38 -050039#include "amdgpu_amdkfd.h"
Alex Deucherd38ceaf2015-04-20 16:55:21 -040040
Alex Deucher6b8f4ee2017-12-15 16:45:02 -050041static bool amdgpu_need_backup(struct amdgpu_device *adev)
42{
43 if (adev->flags & AMD_IS_APU)
44 return false;
45
Christian König4f4b94e2017-12-20 14:21:25 +010046 if (amdgpu_gpu_recovery == 0 ||
47 (amdgpu_gpu_recovery == -1 && !amdgpu_sriov_vf(adev)))
48 return false;
49
50 return true;
Alex Deucher6b8f4ee2017-12-15 16:45:02 -050051}
52
Alex Deucherd38ceaf2015-04-20 16:55:21 -040053static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
54{
Christian Königa7d64de2016-09-15 14:58:48 +020055 struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
Andres Rodriguezb82485f2017-09-15 21:05:19 -040056 struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo);
Alex Deucherd38ceaf2015-04-20 16:55:21 -040057
Felix Kuehlinga46a2cd2018-02-06 20:32:38 -050058 if (bo->kfd_bo)
59 amdgpu_amdkfd_unreserve_system_memory_limit(bo);
60
Christian König6375bbb2017-07-11 17:25:49 +020061 amdgpu_bo_kunmap(bo);
Alex Deucherd38ceaf2015-04-20 16:55:21 -040062
Alex Deucherd38ceaf2015-04-20 16:55:21 -040063 drm_gem_object_release(&bo->gem_base);
Christian König82b9c552015-11-27 16:49:00 +010064 amdgpu_bo_unref(&bo->parent);
Chunming Zhou0c4e7fa2016-08-17 11:41:30 +080065 if (!list_empty(&bo->shadow_list)) {
Christian Königa7d64de2016-09-15 14:58:48 +020066 mutex_lock(&adev->shadow_list_lock);
Chunming Zhou0c4e7fa2016-08-17 11:41:30 +080067 list_del_init(&bo->shadow_list);
Christian Königa7d64de2016-09-15 14:58:48 +020068 mutex_unlock(&adev->shadow_list_lock);
Chunming Zhou0c4e7fa2016-08-17 11:41:30 +080069 }
Alex Deucherd38ceaf2015-04-20 16:55:21 -040070 kfree(bo->metadata);
71 kfree(bo);
72}
73
74bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo)
75{
76 if (bo->destroy == &amdgpu_ttm_bo_destroy)
77 return true;
78 return false;
79}
80
Christian Königc09312a2017-09-12 10:56:17 +020081void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
Alex Deucherd38ceaf2015-04-20 16:55:21 -040082{
Christian Königc09312a2017-09-12 10:56:17 +020083 struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
84 struct ttm_placement *placement = &abo->placement;
85 struct ttm_place *places = abo->placements;
86 u64 flags = abo->flags;
Christian König6369f6f2016-08-15 14:08:54 +020087 u32 c = 0;
Chunming Zhou7e5a5472015-04-24 17:37:30 +080088
Alex Deucherd38ceaf2015-04-20 16:55:21 -040089 if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
Christian König770d13b2018-01-12 14:52:22 +010090 unsigned visible_pfn = adev->gmc.visible_vram_size >> PAGE_SHIFT;
Christian Königfaceaf62016-08-15 14:06:50 +020091
Christian Königfaceaf62016-08-15 14:06:50 +020092 places[c].fpfn = 0;
Christian König89bb5752017-03-29 13:41:57 +020093 places[c].lpfn = 0;
Christian Königfaceaf62016-08-15 14:06:50 +020094 places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
Chunming Zhou7e5a5472015-04-24 17:37:30 +080095 TTM_PL_FLAG_VRAM;
Christian König89bb5752017-03-29 13:41:57 +020096
Christian Königfaceaf62016-08-15 14:06:50 +020097 if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
98 places[c].lpfn = visible_pfn;
99 else
100 places[c].flags |= TTM_PL_FLAG_TOPDOWN;
Christian König89bb5752017-03-29 13:41:57 +0200101
102 if (flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
103 places[c].flags |= TTM_PL_FLAG_CONTIGUOUS;
Christian Königfaceaf62016-08-15 14:06:50 +0200104 c++;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400105 }
106
107 if (domain & AMDGPU_GEM_DOMAIN_GTT) {
Christian Königfaceaf62016-08-15 14:06:50 +0200108 places[c].fpfn = 0;
Christian Königcf273a52017-08-18 15:50:17 +0200109 if (flags & AMDGPU_GEM_CREATE_SHADOW)
Christian König770d13b2018-01-12 14:52:22 +0100110 places[c].lpfn = adev->gmc.gart_size >> PAGE_SHIFT;
Christian Königcf273a52017-08-18 15:50:17 +0200111 else
112 places[c].lpfn = 0;
Christian Königfaceaf62016-08-15 14:06:50 +0200113 places[c].flags = TTM_PL_FLAG_TT;
114 if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
115 places[c].flags |= TTM_PL_FLAG_WC |
116 TTM_PL_FLAG_UNCACHED;
117 else
118 places[c].flags |= TTM_PL_FLAG_CACHED;
119 c++;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400120 }
121
122 if (domain & AMDGPU_GEM_DOMAIN_CPU) {
Christian Königfaceaf62016-08-15 14:06:50 +0200123 places[c].fpfn = 0;
124 places[c].lpfn = 0;
125 places[c].flags = TTM_PL_FLAG_SYSTEM;
126 if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
127 places[c].flags |= TTM_PL_FLAG_WC |
128 TTM_PL_FLAG_UNCACHED;
129 else
130 places[c].flags |= TTM_PL_FLAG_CACHED;
131 c++;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400132 }
133
134 if (domain & AMDGPU_GEM_DOMAIN_GDS) {
Christian Königfaceaf62016-08-15 14:06:50 +0200135 places[c].fpfn = 0;
136 places[c].lpfn = 0;
137 places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_GDS;
138 c++;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400139 }
Christian Königfaceaf62016-08-15 14:06:50 +0200140
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400141 if (domain & AMDGPU_GEM_DOMAIN_GWS) {
Christian Königfaceaf62016-08-15 14:06:50 +0200142 places[c].fpfn = 0;
143 places[c].lpfn = 0;
144 places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_GWS;
145 c++;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400146 }
Christian Königfaceaf62016-08-15 14:06:50 +0200147
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400148 if (domain & AMDGPU_GEM_DOMAIN_OA) {
Christian Königfaceaf62016-08-15 14:06:50 +0200149 places[c].fpfn = 0;
150 places[c].lpfn = 0;
151 places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_OA;
152 c++;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400153 }
154
155 if (!c) {
Christian Königfaceaf62016-08-15 14:06:50 +0200156 places[c].fpfn = 0;
157 places[c].lpfn = 0;
158 places[c].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
159 c++;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400160 }
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400161
Christian Königfaceaf62016-08-15 14:06:50 +0200162 placement->num_placement = c;
163 placement->placement = places;
164
165 placement->num_busy_placement = c;
166 placement->busy_placement = places;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400167}
168
Christian König7c204882015-12-14 13:18:01 +0100169/**
Christian König9d903cb2017-07-27 17:08:54 +0200170 * amdgpu_bo_create_reserved - create reserved BO for kernel use
Christian König7c204882015-12-14 13:18:01 +0100171 *
172 * @adev: amdgpu device object
173 * @size: size for the new BO
174 * @align: alignment for the new BO
175 * @domain: where to place it
176 * @bo_ptr: resulting BO
177 * @gpu_addr: GPU addr of the pinned BO
178 * @cpu_addr: optional CPU address mapping
179 *
Christian König9d903cb2017-07-27 17:08:54 +0200180 * Allocates and pins a BO for kernel internal use, and returns it still
181 * reserved.
Christian König7c204882015-12-14 13:18:01 +0100182 *
183 * Returns 0 on success, negative error code otherwise.
184 */
Christian König9d903cb2017-07-27 17:08:54 +0200185int amdgpu_bo_create_reserved(struct amdgpu_device *adev,
186 unsigned long size, int align,
187 u32 domain, struct amdgpu_bo **bo_ptr,
188 u64 *gpu_addr, void **cpu_addr)
Christian König7c204882015-12-14 13:18:01 +0100189{
Christian König53766e52017-07-27 14:52:53 +0200190 bool free = false;
Christian König7c204882015-12-14 13:18:01 +0100191 int r;
192
Christian König53766e52017-07-27 14:52:53 +0200193 if (!*bo_ptr) {
Christian Königeab3de22018-03-14 14:48:17 -0500194 r = amdgpu_bo_create(adev, size, align, domain,
Christian König53766e52017-07-27 14:52:53 +0200195 AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
196 AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
Christian Königeab3de22018-03-14 14:48:17 -0500197 ttm_bo_type_kernel, NULL, bo_ptr);
Christian König53766e52017-07-27 14:52:53 +0200198 if (r) {
199 dev_err(adev->dev, "(%d) failed to allocate kernel bo\n",
200 r);
201 return r;
202 }
203 free = true;
Christian König7c204882015-12-14 13:18:01 +0100204 }
205
206 r = amdgpu_bo_reserve(*bo_ptr, false);
207 if (r) {
208 dev_err(adev->dev, "(%d) failed to reserve kernel bo\n", r);
209 goto error_free;
210 }
211
212 r = amdgpu_bo_pin(*bo_ptr, domain, gpu_addr);
213 if (r) {
214 dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
215 goto error_unreserve;
216 }
217
218 if (cpu_addr) {
219 r = amdgpu_bo_kmap(*bo_ptr, cpu_addr);
220 if (r) {
221 dev_err(adev->dev, "(%d) kernel bo map failed\n", r);
222 goto error_unreserve;
223 }
224 }
225
Christian König7c204882015-12-14 13:18:01 +0100226 return 0;
227
228error_unreserve:
229 amdgpu_bo_unreserve(*bo_ptr);
230
231error_free:
Christian König53766e52017-07-27 14:52:53 +0200232 if (free)
233 amdgpu_bo_unref(bo_ptr);
Christian König7c204882015-12-14 13:18:01 +0100234
235 return r;
236}
237
Junwei Zhangaa1d5622016-09-08 10:13:32 +0800238/**
Christian König9d903cb2017-07-27 17:08:54 +0200239 * amdgpu_bo_create_kernel - create BO for kernel use
240 *
241 * @adev: amdgpu device object
242 * @size: size for the new BO
243 * @align: alignment for the new BO
244 * @domain: where to place it
245 * @bo_ptr: resulting BO
246 * @gpu_addr: GPU addr of the pinned BO
247 * @cpu_addr: optional CPU address mapping
248 *
249 * Allocates and pins a BO for kernel internal use.
250 *
251 * Returns 0 on success, negative error code otherwise.
252 */
253int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
254 unsigned long size, int align,
255 u32 domain, struct amdgpu_bo **bo_ptr,
256 u64 *gpu_addr, void **cpu_addr)
257{
258 int r;
259
260 r = amdgpu_bo_create_reserved(adev, size, align, domain, bo_ptr,
261 gpu_addr, cpu_addr);
262
263 if (r)
264 return r;
265
266 amdgpu_bo_unreserve(*bo_ptr);
267
268 return 0;
269}
270
271/**
Junwei Zhangaa1d5622016-09-08 10:13:32 +0800272 * amdgpu_bo_free_kernel - free BO for kernel use
273 *
274 * @bo: amdgpu BO to free
275 *
276 * unmaps and unpin a BO for kernel internal use.
277 */
278void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr,
279 void **cpu_addr)
280{
281 if (*bo == NULL)
282 return;
283
Alex Xief3aa7452017-04-24 14:27:00 -0400284 if (likely(amdgpu_bo_reserve(*bo, true) == 0)) {
Junwei Zhangaa1d5622016-09-08 10:13:32 +0800285 if (cpu_addr)
286 amdgpu_bo_kunmap(*bo);
287
288 amdgpu_bo_unpin(*bo);
289 amdgpu_bo_unreserve(*bo);
290 }
291 amdgpu_bo_unref(bo);
292
293 if (gpu_addr)
294 *gpu_addr = 0;
295
296 if (cpu_addr)
297 *cpu_addr = NULL;
298}
299
Andrey Grodzovsky79c63122017-11-10 18:35:56 -0500300/* Validate bo size is bit bigger then the request domain */
301static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
302 unsigned long size, u32 domain)
303{
304 struct ttm_mem_type_manager *man = NULL;
305
306 /*
307 * If GTT is part of requested domains the check must succeed to
308 * allow fall back to GTT
309 */
310 if (domain & AMDGPU_GEM_DOMAIN_GTT) {
311 man = &adev->mman.bdev.man[TTM_PL_TT];
312
313 if (size < (man->size << PAGE_SHIFT))
314 return true;
315 else
316 goto fail;
317 }
318
319 if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
320 man = &adev->mman.bdev.man[TTM_PL_VRAM];
321
322 if (size < (man->size << PAGE_SHIFT))
323 return true;
324 else
325 goto fail;
326 }
327
328
329 /* TODO add more domains checks, such as AMDGPU_GEM_DOMAIN_CPU */
330 return true;
331
332fail:
Michel Dänzer299c7762017-11-15 11:37:23 +0100333 DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
334 man->size << PAGE_SHIFT);
Andrey Grodzovsky79c63122017-11-10 18:35:56 -0500335 return false;
336}
337
Christian Königeab3de22018-03-14 14:48:17 -0500338static int amdgpu_bo_do_create(struct amdgpu_device *adev, unsigned long size,
339 int byte_align, u32 domain,
340 u64 flags, enum ttm_bo_type type,
Christian Königc09312a2017-09-12 10:56:17 +0200341 struct reservation_object *resv,
Christian Königc09312a2017-09-12 10:56:17 +0200342 struct amdgpu_bo **bo_ptr)
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400343{
Roger He92518592017-12-08 13:31:52 +0800344 struct ttm_operation_ctx ctx = {
Christian Königeab3de22018-03-14 14:48:17 -0500345 .interruptible = (type != ttm_bo_type_kernel),
Roger He92518592017-12-08 13:31:52 +0800346 .no_wait_gpu = false,
Roger Hed330fca2018-02-06 11:22:57 +0800347 .resv = resv,
348 .flags = TTM_OPT_FLAG_ALLOW_RES_EVICT
Roger He92518592017-12-08 13:31:52 +0800349 };
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400350 struct amdgpu_bo *bo;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400351 unsigned long page_align;
352 size_t acc_size;
353 int r;
354
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400355 page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
356 size = ALIGN(size, PAGE_SIZE);
357
Andrey Grodzovsky79c63122017-11-10 18:35:56 -0500358 if (!amdgpu_bo_validate_size(adev, size, domain))
359 return -ENOMEM;
360
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400361 *bo_ptr = NULL;
362
363 acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size,
364 sizeof(struct amdgpu_bo));
365
366 bo = kzalloc(sizeof(struct amdgpu_bo), GFP_KERNEL);
367 if (bo == NULL)
368 return -ENOMEM;
Christian Königc06cc6f2018-02-16 09:52:51 +0100369 drm_gem_private_object_init(adev->ddev, &bo->gem_base, size);
Chunming Zhou0c4e7fa2016-08-17 11:41:30 +0800370 INIT_LIST_HEAD(&bo->shadow_list);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400371 INIT_LIST_HEAD(&bo->va);
Kent Russell6d7d9c52017-08-08 07:58:01 -0400372 bo->preferred_domains = domain & (AMDGPU_GEM_DOMAIN_VRAM |
Christian König1ea863f2015-12-18 22:13:12 +0100373 AMDGPU_GEM_DOMAIN_GTT |
374 AMDGPU_GEM_DOMAIN_CPU |
375 AMDGPU_GEM_DOMAIN_GDS |
376 AMDGPU_GEM_DOMAIN_GWS |
377 AMDGPU_GEM_DOMAIN_OA);
Kent Russell6d7d9c52017-08-08 07:58:01 -0400378 bo->allowed_domains = bo->preferred_domains;
Christian Königeab3de22018-03-14 14:48:17 -0500379 if (type != ttm_bo_type_kernel &&
380 bo->allowed_domains == AMDGPU_GEM_DOMAIN_VRAM)
Christian König1ea863f2015-12-18 22:13:12 +0100381 bo->allowed_domains |= AMDGPU_GEM_DOMAIN_GTT;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400382
383 bo->flags = flags;
Oded Gabbaya187f172016-01-30 07:59:34 +0200384
Nils Hollanda2e2f292017-01-22 20:15:27 +0100385#ifdef CONFIG_X86_32
386 /* XXX: Write-combined CPU mappings of GTT seem broken on 32-bit
387 * See https://bugs.freedesktop.org/show_bug.cgi?id=84627
388 */
389 bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
390#elif defined(CONFIG_X86) && !defined(CONFIG_X86_PAT)
391 /* Don't try to enable write-combining when it can't work, or things
392 * may be slow
393 * See https://bugs.freedesktop.org/show_bug.cgi?id=88758
394 */
395
Arnd Bergmann31bb90f2017-02-01 16:59:21 +0100396#ifndef CONFIG_COMPILE_TEST
Nils Hollanda2e2f292017-01-22 20:15:27 +0100397#warning Please enable CONFIG_MTRR and CONFIG_X86_PAT for better performance \
398 thanks to write-combining
Arnd Bergmann31bb90f2017-02-01 16:59:21 +0100399#endif
Nils Hollanda2e2f292017-01-22 20:15:27 +0100400
401 if (bo->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
402 DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
403 "better performance thanks to write-combining\n");
404 bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
405#else
Oded Gabbaya187f172016-01-30 07:59:34 +0200406 /* For architectures that don't support WC memory,
407 * mask out the WC flag from the BO
408 */
409 if (!drm_arch_can_wc_memory())
410 bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
Nils Hollanda2e2f292017-01-22 20:15:27 +0100411#endif
Oded Gabbaya187f172016-01-30 07:59:34 +0200412
Christian Königc09312a2017-09-12 10:56:17 +0200413 bo->tbo.bdev = &adev->mman.bdev;
414 amdgpu_ttm_placement_from_domain(bo, domain);
Christian Königf45dc742016-11-17 12:24:48 +0100415
Nicolai Hähnle59c66c92017-02-16 11:01:44 +0100416 r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, type,
Christian König724daa42018-02-22 15:52:31 +0100417 &bo->placement, page_align, &ctx, acc_size,
Christian Königeab3de22018-03-14 14:48:17 -0500418 NULL, resv, &amdgpu_ttm_bo_destroy);
Christian Königa695e432017-10-31 09:36:13 +0100419 if (unlikely(r != 0))
420 return r;
421
Christian König770d13b2018-01-12 14:52:22 +0100422 if (adev->gmc.visible_vram_size < adev->gmc.real_vram_size &&
John Brooks00f06b22017-06-27 22:33:18 -0400423 bo->tbo.mem.mem_type == TTM_PL_VRAM &&
Christian König770d13b2018-01-12 14:52:22 +0100424 bo->tbo.mem.start < adev->gmc.visible_vram_size >> PAGE_SHIFT)
Christian König6af046d2017-04-27 18:20:47 +0200425 amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved,
426 ctx.bytes_moved);
John Brooks00f06b22017-06-27 22:33:18 -0400427 else
Christian König6af046d2017-04-27 18:20:47 +0200428 amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved, 0);
Samuel Pitoisetfad06122017-02-09 11:33:37 +0100429
Christian Königeab3de22018-03-14 14:48:17 -0500430 if (type == ttm_bo_type_kernel)
Roger.Hec309cd02017-03-27 19:38:11 +0800431 bo->tbo.priority = 1;
Christian Könige1f055b2017-01-10 17:27:49 +0100432
Flora Cui4fea83f2016-07-20 14:44:38 +0800433 if (flags & AMDGPU_GEM_CREATE_VRAM_CLEARED &&
434 bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) {
Chris Wilsonf54d1862016-10-25 13:00:45 +0100435 struct dma_fence *fence;
Flora Cui4fea83f2016-07-20 14:44:38 +0800436
Christian König8febe612018-01-24 19:55:32 +0100437 r = amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence);
Christian Königc3af12582016-11-17 12:16:34 +0100438 if (unlikely(r))
439 goto fail_unreserve;
440
Flora Cui4fea83f2016-07-20 14:44:38 +0800441 amdgpu_bo_fence(bo, fence, false);
Chris Wilsonf54d1862016-10-25 13:00:45 +0100442 dma_fence_put(bo->tbo.moving);
443 bo->tbo.moving = dma_fence_get(fence);
444 dma_fence_put(fence);
Flora Cui4fea83f2016-07-20 14:44:38 +0800445 }
Christian Königf45dc742016-11-17 12:24:48 +0100446 if (!resv)
Nicolai Hähnle59c66c92017-02-16 11:01:44 +0100447 amdgpu_bo_unreserve(bo);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400448 *bo_ptr = bo;
449
450 trace_amdgpu_bo_create(bo);
451
John Brooks96cf8272017-06-30 11:31:08 -0400452 /* Treat CPU_ACCESS_REQUIRED only as a hint if given by UMD */
453 if (type == ttm_bo_type_device)
454 bo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
455
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400456 return 0;
Flora Cui4fea83f2016-07-20 14:44:38 +0800457
458fail_unreserve:
Nicolai Hähnlef1543f52017-01-10 20:36:56 +0100459 if (!resv)
460 ww_mutex_unlock(&bo->tbo.resv->lock);
Flora Cui4fea83f2016-07-20 14:44:38 +0800461 amdgpu_bo_unref(&bo);
462 return r;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400463}
464
Chunming Zhoue7893c42016-07-26 14:13:21 +0800465static int amdgpu_bo_create_shadow(struct amdgpu_device *adev,
466 unsigned long size, int byte_align,
467 struct amdgpu_bo *bo)
468{
Chunming Zhoue7893c42016-07-26 14:13:21 +0800469 int r;
470
471 if (bo->shadow)
472 return 0;
473
Christian Königeab3de22018-03-14 14:48:17 -0500474 r = amdgpu_bo_do_create(adev, size, byte_align, AMDGPU_GEM_DOMAIN_GTT,
Christian Königc09312a2017-09-12 10:56:17 +0200475 AMDGPU_GEM_CREATE_CPU_GTT_USWC |
476 AMDGPU_GEM_CREATE_SHADOW,
Christian Königeab3de22018-03-14 14:48:17 -0500477 ttm_bo_type_kernel,
478 bo->tbo.resv, &bo->shadow);
Chunming Zhou0c4e7fa2016-08-17 11:41:30 +0800479 if (!r) {
Chunming Zhoue7893c42016-07-26 14:13:21 +0800480 bo->shadow->parent = amdgpu_bo_ref(bo);
Chunming Zhou0c4e7fa2016-08-17 11:41:30 +0800481 mutex_lock(&adev->shadow_list_lock);
482 list_add_tail(&bo->shadow_list, &adev->shadow_list);
483 mutex_unlock(&adev->shadow_list_lock);
484 }
Chunming Zhoue7893c42016-07-26 14:13:21 +0800485
486 return r;
487}
488
Christian Königeab3de22018-03-14 14:48:17 -0500489int amdgpu_bo_create(struct amdgpu_device *adev, unsigned long size,
490 int byte_align, u32 domain,
491 u64 flags, enum ttm_bo_type type,
Christian König72d76682015-09-03 17:34:59 +0200492 struct reservation_object *resv,
493 struct amdgpu_bo **bo_ptr)
Chunming Zhou7e5a5472015-04-24 17:37:30 +0800494{
Christian Königcf273a52017-08-18 15:50:17 +0200495 uint64_t parent_flags = flags & ~AMDGPU_GEM_CREATE_SHADOW;
Chunming Zhoue7893c42016-07-26 14:13:21 +0800496 int r;
Chunming Zhou7e5a5472015-04-24 17:37:30 +0800497
Christian Königeab3de22018-03-14 14:48:17 -0500498 r = amdgpu_bo_do_create(adev, size, byte_align, domain,
499 parent_flags, type, resv, bo_ptr);
Chunming Zhoue7893c42016-07-26 14:13:21 +0800500 if (r)
501 return r;
502
Christian Königcf273a52017-08-18 15:50:17 +0200503 if ((flags & AMDGPU_GEM_CREATE_SHADOW) && amdgpu_need_backup(adev)) {
504 if (!resv)
505 WARN_ON(reservation_object_lock((*bo_ptr)->tbo.resv,
506 NULL));
Nicolai Hähnle36ea83d2017-01-10 19:06:00 +0100507
Chunming Zhoue7893c42016-07-26 14:13:21 +0800508 r = amdgpu_bo_create_shadow(adev, size, byte_align, (*bo_ptr));
Nicolai Hähnle36ea83d2017-01-10 19:06:00 +0100509
510 if (!resv)
Christian Königcf273a52017-08-18 15:50:17 +0200511 reservation_object_unlock((*bo_ptr)->tbo.resv);
Nicolai Hähnle36ea83d2017-01-10 19:06:00 +0100512
Chunming Zhoue7893c42016-07-26 14:13:21 +0800513 if (r)
514 amdgpu_bo_unref(bo_ptr);
515 }
516
517 return r;
Chunming Zhou7e5a5472015-04-24 17:37:30 +0800518}
519
Chunming Zhou20f4eff2016-08-04 16:51:18 +0800520int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev,
521 struct amdgpu_ring *ring,
522 struct amdgpu_bo *bo,
523 struct reservation_object *resv,
Chris Wilsonf54d1862016-10-25 13:00:45 +0100524 struct dma_fence **fence,
Chunming Zhou20f4eff2016-08-04 16:51:18 +0800525 bool direct)
526
527{
528 struct amdgpu_bo *shadow = bo->shadow;
529 uint64_t bo_addr, shadow_addr;
530 int r;
531
532 if (!shadow)
533 return -EINVAL;
534
535 bo_addr = amdgpu_bo_gpu_offset(bo);
536 shadow_addr = amdgpu_bo_gpu_offset(bo->shadow);
537
538 r = reservation_object_reserve_shared(bo->tbo.resv);
539 if (r)
540 goto err;
541
542 r = amdgpu_copy_buffer(ring, bo_addr, shadow_addr,
543 amdgpu_bo_size(bo), resv, fence,
Christian Königfc9c8f52017-06-29 11:46:15 +0200544 direct, false);
Chunming Zhou20f4eff2016-08-04 16:51:18 +0800545 if (!r)
546 amdgpu_bo_fence(bo, *fence, true);
547
548err:
549 return r;
550}
551
Roger.He82521312017-04-21 13:08:43 +0800552int amdgpu_bo_validate(struct amdgpu_bo *bo)
553{
Christian König19be5572017-04-12 14:24:39 +0200554 struct ttm_operation_ctx ctx = { false, false };
Roger.He82521312017-04-21 13:08:43 +0800555 uint32_t domain;
556 int r;
557
558 if (bo->pin_count)
559 return 0;
560
Kent Russell6d7d9c52017-08-08 07:58:01 -0400561 domain = bo->preferred_domains;
Roger.He82521312017-04-21 13:08:43 +0800562
563retry:
564 amdgpu_ttm_placement_from_domain(bo, domain);
Christian König19be5572017-04-12 14:24:39 +0200565 r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
Roger.He82521312017-04-21 13:08:43 +0800566 if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) {
567 domain = bo->allowed_domains;
568 goto retry;
569 }
570
571 return r;
572}
573
Chunming Zhou20f4eff2016-08-04 16:51:18 +0800574int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
575 struct amdgpu_ring *ring,
576 struct amdgpu_bo *bo,
577 struct reservation_object *resv,
Chris Wilsonf54d1862016-10-25 13:00:45 +0100578 struct dma_fence **fence,
Chunming Zhou20f4eff2016-08-04 16:51:18 +0800579 bool direct)
580
581{
582 struct amdgpu_bo *shadow = bo->shadow;
583 uint64_t bo_addr, shadow_addr;
584 int r;
585
586 if (!shadow)
587 return -EINVAL;
588
589 bo_addr = amdgpu_bo_gpu_offset(bo);
590 shadow_addr = amdgpu_bo_gpu_offset(bo->shadow);
591
592 r = reservation_object_reserve_shared(bo->tbo.resv);
593 if (r)
594 goto err;
595
596 r = amdgpu_copy_buffer(ring, shadow_addr, bo_addr,
597 amdgpu_bo_size(bo), resv, fence,
Christian Königfc9c8f52017-06-29 11:46:15 +0200598 direct, false);
Chunming Zhou20f4eff2016-08-04 16:51:18 +0800599 if (!r)
600 amdgpu_bo_fence(bo, *fence, true);
601
602err:
603 return r;
604}
605
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400606int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
607{
Christian Königf5e1c742017-07-20 23:45:18 +0200608 void *kptr;
Christian König587f3c72016-03-10 16:21:04 +0100609 long r;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400610
Christian König271c8122015-05-13 14:30:53 +0200611 if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
612 return -EPERM;
613
Christian Königf5e1c742017-07-20 23:45:18 +0200614 kptr = amdgpu_bo_kptr(bo);
615 if (kptr) {
616 if (ptr)
617 *ptr = kptr;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400618 return 0;
619 }
Christian König587f3c72016-03-10 16:21:04 +0100620
621 r = reservation_object_wait_timeout_rcu(bo->tbo.resv, false, false,
622 MAX_SCHEDULE_TIMEOUT);
623 if (r < 0)
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400624 return r;
Christian König587f3c72016-03-10 16:21:04 +0100625
626 r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
627 if (r)
628 return r;
629
Christian König587f3c72016-03-10 16:21:04 +0100630 if (ptr)
Christian Königf5e1c742017-07-20 23:45:18 +0200631 *ptr = amdgpu_bo_kptr(bo);
Christian König587f3c72016-03-10 16:21:04 +0100632
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400633 return 0;
634}
635
Christian Königf5e1c742017-07-20 23:45:18 +0200636void *amdgpu_bo_kptr(struct amdgpu_bo *bo)
637{
638 bool is_iomem;
639
640 return ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
641}
642
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400643void amdgpu_bo_kunmap(struct amdgpu_bo *bo)
644{
Christian Königf5e1c742017-07-20 23:45:18 +0200645 if (bo->kmap.bo)
646 ttm_bo_kunmap(&bo->kmap);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400647}
648
649struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo)
650{
651 if (bo == NULL)
652 return NULL;
653
654 ttm_bo_reference(&bo->tbo);
655 return bo;
656}
657
658void amdgpu_bo_unref(struct amdgpu_bo **bo)
659{
660 struct ttm_buffer_object *tbo;
661
662 if ((*bo) == NULL)
663 return;
664
665 tbo = &((*bo)->tbo);
666 ttm_bo_unref(&tbo);
667 if (tbo == NULL)
668 *bo = NULL;
669}
670
Chunming Zhou7e5a5472015-04-24 17:37:30 +0800671int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
672 u64 min_offset, u64 max_offset,
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400673 u64 *gpu_addr)
674{
Christian Königa7d64de2016-09-15 14:58:48 +0200675 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
Christian König19be5572017-04-12 14:24:39 +0200676 struct ttm_operation_ctx ctx = { false, false };
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400677 int r, i;
678
Christian Königcc325d12016-02-08 11:08:35 +0100679 if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm))
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400680 return -EPERM;
681
Chunming Zhou7e5a5472015-04-24 17:37:30 +0800682 if (WARN_ON_ONCE(min_offset > max_offset))
683 return -EINVAL;
684
Christopher James Halse Rogers803d89a2017-04-03 13:31:22 +1000685 /* A shared bo cannot be migrated to VRAM */
686 if (bo->prime_shared_count && (domain == AMDGPU_GEM_DOMAIN_VRAM))
687 return -EINVAL;
688
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400689 if (bo->pin_count) {
Flora Cui408778e2016-08-18 12:55:13 +0800690 uint32_t mem_type = bo->tbo.mem.mem_type;
691
Christian Königf5318952017-10-23 17:29:36 +0200692 if (!(domain & amdgpu_mem_type_to_domain(mem_type)))
Flora Cui408778e2016-08-18 12:55:13 +0800693 return -EINVAL;
694
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400695 bo->pin_count++;
696 if (gpu_addr)
697 *gpu_addr = amdgpu_bo_gpu_offset(bo);
698
699 if (max_offset != 0) {
Flora Cui27798e02016-08-18 13:18:09 +0800700 u64 domain_start = bo->tbo.bdev->man[mem_type].gpu_offset;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400701 WARN_ON_ONCE(max_offset <
702 (amdgpu_bo_gpu_offset(bo) - domain_start));
703 }
704
705 return 0;
706 }
Christian König03f48dd2016-08-15 17:00:22 +0200707
708 bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
Christian Könige9c75772017-09-11 17:29:26 +0200709 /* force to pin into visible video ram */
710 if (!(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS))
711 bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400712 amdgpu_ttm_placement_from_domain(bo, domain);
713 for (i = 0; i < bo->placement.num_placement; i++) {
Christian Könige9c75772017-09-11 17:29:26 +0200714 unsigned fpfn, lpfn;
715
716 fpfn = min_offset >> PAGE_SHIFT;
717 lpfn = max_offset >> PAGE_SHIFT;
718
Chunming Zhou7e5a5472015-04-24 17:37:30 +0800719 if (fpfn > bo->placements[i].fpfn)
720 bo->placements[i].fpfn = fpfn;
Christian König78d0e182016-01-19 12:48:14 +0100721 if (!bo->placements[i].lpfn ||
722 (lpfn && lpfn < bo->placements[i].lpfn))
Chunming Zhou7e5a5472015-04-24 17:37:30 +0800723 bo->placements[i].lpfn = lpfn;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400724 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
725 }
726
Christian König19be5572017-04-12 14:24:39 +0200727 r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
Christian König6681c5e2016-08-12 16:50:12 +0200728 if (unlikely(r)) {
Christian Königa7d64de2016-09-15 14:58:48 +0200729 dev_err(adev->dev, "%p pin failed\n", bo);
Christian König6681c5e2016-08-12 16:50:12 +0200730 goto error;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400731 }
Christian König6681c5e2016-08-12 16:50:12 +0200732
Christian Königc5835bb2017-10-27 15:43:14 +0200733 r = amdgpu_ttm_alloc_gart(&bo->tbo);
Christian Königead282a2017-10-20 13:12:12 +0200734 if (unlikely(r)) {
735 dev_err(adev->dev, "%p bind failed\n", bo);
736 goto error;
Chunming Zhou07306b42017-07-12 12:36:47 +0800737 }
Christian König5e91fb52017-10-20 13:11:00 +0200738
Christian Königead282a2017-10-20 13:12:12 +0200739 bo->pin_count = 1;
740 if (gpu_addr != NULL)
741 *gpu_addr = amdgpu_bo_gpu_offset(bo);
742
Christian König5e91fb52017-10-20 13:11:00 +0200743 domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
Christian König6681c5e2016-08-12 16:50:12 +0200744 if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
Christian Königa7d64de2016-09-15 14:58:48 +0200745 adev->vram_pin_size += amdgpu_bo_size(bo);
Christian König6681c5e2016-08-12 16:50:12 +0200746 if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
Christian Königa7d64de2016-09-15 14:58:48 +0200747 adev->invisible_pin_size += amdgpu_bo_size(bo);
Flora Cui32ab75f2016-08-18 13:17:07 +0800748 } else if (domain == AMDGPU_GEM_DOMAIN_GTT) {
Christian Königa7d64de2016-09-15 14:58:48 +0200749 adev->gart_pin_size += amdgpu_bo_size(bo);
Christian König6681c5e2016-08-12 16:50:12 +0200750 }
751
752error:
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400753 return r;
754}
755
756int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain, u64 *gpu_addr)
757{
Chunming Zhou7e5a5472015-04-24 17:37:30 +0800758 return amdgpu_bo_pin_restricted(bo, domain, 0, 0, gpu_addr);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400759}
760
761int amdgpu_bo_unpin(struct amdgpu_bo *bo)
762{
Christian Königa7d64de2016-09-15 14:58:48 +0200763 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
Christian König19be5572017-04-12 14:24:39 +0200764 struct ttm_operation_ctx ctx = { false, false };
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400765 int r, i;
766
767 if (!bo->pin_count) {
Christian Königa7d64de2016-09-15 14:58:48 +0200768 dev_warn(adev->dev, "%p unpin not necessary\n", bo);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400769 return 0;
770 }
771 bo->pin_count--;
772 if (bo->pin_count)
773 return 0;
774 for (i = 0; i < bo->placement.num_placement; i++) {
775 bo->placements[i].lpfn = 0;
776 bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
777 }
Christian König19be5572017-04-12 14:24:39 +0200778 r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
Christian König6681c5e2016-08-12 16:50:12 +0200779 if (unlikely(r)) {
Christian Königa7d64de2016-09-15 14:58:48 +0200780 dev_err(adev->dev, "%p validate failed for unpin\n", bo);
Christian König6681c5e2016-08-12 16:50:12 +0200781 goto error;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400782 }
Christian König6681c5e2016-08-12 16:50:12 +0200783
784 if (bo->tbo.mem.mem_type == TTM_PL_VRAM) {
Christian Königa7d64de2016-09-15 14:58:48 +0200785 adev->vram_pin_size -= amdgpu_bo_size(bo);
Christian König6681c5e2016-08-12 16:50:12 +0200786 if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
Christian Königa7d64de2016-09-15 14:58:48 +0200787 adev->invisible_pin_size -= amdgpu_bo_size(bo);
Flora Cui441f90e2016-09-09 14:15:30 +0800788 } else if (bo->tbo.mem.mem_type == TTM_PL_TT) {
Christian Königa7d64de2016-09-15 14:58:48 +0200789 adev->gart_pin_size -= amdgpu_bo_size(bo);
Christian König6681c5e2016-08-12 16:50:12 +0200790 }
791
792error:
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400793 return r;
794}
795
796int amdgpu_bo_evict_vram(struct amdgpu_device *adev)
797{
798 /* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */
Jammy Zhou2f7d10b2015-07-22 11:29:01 +0800799 if (0 && (adev->flags & AMD_IS_APU)) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400800 /* Useless to evict on IGP chips */
801 return 0;
802 }
803 return ttm_bo_evict_mm(&adev->mman.bdev, TTM_PL_VRAM);
804}
805
Alex Deucher1f8628c2016-03-31 16:56:22 -0400806static const char *amdgpu_vram_names[] = {
807 "UNKNOWN",
808 "GDDR1",
809 "DDR2",
810 "GDDR3",
811 "GDDR4",
812 "GDDR5",
813 "HBM",
Tom St Denisbc227cf2018-03-09 06:16:55 -0500814 "DDR3",
815 "DDR4",
Alex Deucher1f8628c2016-03-31 16:56:22 -0400816};
817
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400818int amdgpu_bo_init(struct amdgpu_device *adev)
819{
Dave Airlie7cf321d2016-10-24 15:37:48 +1000820 /* reserve PAT memory space to WC for VRAM */
Christian König770d13b2018-01-12 14:52:22 +0100821 arch_io_reserve_memtype_wc(adev->gmc.aper_base,
822 adev->gmc.aper_size);
Dave Airlie7cf321d2016-10-24 15:37:48 +1000823
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400824 /* Add an MTRR for the VRAM */
Christian König770d13b2018-01-12 14:52:22 +0100825 adev->gmc.vram_mtrr = arch_phys_wc_add(adev->gmc.aper_base,
826 adev->gmc.aper_size);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400827 DRM_INFO("Detected VRAM RAM=%lluM, BAR=%lluM\n",
Christian König770d13b2018-01-12 14:52:22 +0100828 adev->gmc.mc_vram_size >> 20,
829 (unsigned long long)adev->gmc.aper_size >> 20);
Alex Deucher1f8628c2016-03-31 16:56:22 -0400830 DRM_INFO("RAM width %dbits %s\n",
Christian König770d13b2018-01-12 14:52:22 +0100831 adev->gmc.vram_width, amdgpu_vram_names[adev->gmc.vram_type]);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400832 return amdgpu_ttm_init(adev);
833}
834
835void amdgpu_bo_fini(struct amdgpu_device *adev)
836{
837 amdgpu_ttm_fini(adev);
Christian König770d13b2018-01-12 14:52:22 +0100838 arch_phys_wc_del(adev->gmc.vram_mtrr);
839 arch_io_free_memtype_wc(adev->gmc.aper_base, adev->gmc.aper_size);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400840}
841
842int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo,
843 struct vm_area_struct *vma)
844{
845 return ttm_fbdev_mmap(vma, &bo->tbo);
846}
847
848int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags)
849{
Marek Olšák9079ac72017-03-03 16:03:15 -0500850 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
851
852 if (adev->family <= AMDGPU_FAMILY_CZ &&
853 AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT) > 6)
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400854 return -EINVAL;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400855
856 bo->tiling_flags = tiling_flags;
857 return 0;
858}
859
860void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags)
861{
862 lockdep_assert_held(&bo->tbo.resv->lock.base);
863
864 if (tiling_flags)
865 *tiling_flags = bo->tiling_flags;
866}
867
868int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
869 uint32_t metadata_size, uint64_t flags)
870{
871 void *buffer;
872
873 if (!metadata_size) {
874 if (bo->metadata_size) {
875 kfree(bo->metadata);
Dave Airlie0092d3e2016-05-03 12:44:29 +1000876 bo->metadata = NULL;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400877 bo->metadata_size = 0;
878 }
879 return 0;
880 }
881
882 if (metadata == NULL)
883 return -EINVAL;
884
Andrzej Hajda71affda2015-09-21 17:34:39 -0400885 buffer = kmemdup(metadata, metadata_size, GFP_KERNEL);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400886 if (buffer == NULL)
887 return -ENOMEM;
888
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400889 kfree(bo->metadata);
890 bo->metadata_flags = flags;
891 bo->metadata = buffer;
892 bo->metadata_size = metadata_size;
893
894 return 0;
895}
896
897int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
898 size_t buffer_size, uint32_t *metadata_size,
899 uint64_t *flags)
900{
901 if (!buffer && !metadata_size)
902 return -EINVAL;
903
904 if (buffer) {
905 if (buffer_size < bo->metadata_size)
906 return -EINVAL;
907
908 if (bo->metadata_size)
909 memcpy(buffer, bo->metadata, bo->metadata_size);
910 }
911
912 if (metadata_size)
913 *metadata_size = bo->metadata_size;
914 if (flags)
915 *flags = bo->metadata_flags;
916
917 return 0;
918}
919
920void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
Nicolai Hähnle66257db2016-12-15 17:23:49 +0100921 bool evict,
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400922 struct ttm_mem_reg *new_mem)
923{
Christian Königa7d64de2016-09-15 14:58:48 +0200924 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
Christian König765e7fb2016-09-15 15:06:50 +0200925 struct amdgpu_bo *abo;
David Mao15da3012016-06-07 17:48:52 +0800926 struct ttm_mem_reg *old_mem = &bo->mem;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400927
928 if (!amdgpu_ttm_bo_is_amdgpu_bo(bo))
929 return;
930
Andres Rodriguezb82485f2017-09-15 21:05:19 -0400931 abo = ttm_to_amdgpu_bo(bo);
Christian König3f3333f2017-08-03 14:02:13 +0200932 amdgpu_vm_bo_invalidate(adev, abo, evict);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400933
Christian König6375bbb2017-07-11 17:25:49 +0200934 amdgpu_bo_kunmap(abo);
935
Nicolai Hähnle661a7602016-12-15 17:26:42 +0100936 /* remember the eviction */
937 if (evict)
938 atomic64_inc(&adev->num_evictions);
939
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400940 /* update statistics */
941 if (!new_mem)
942 return;
943
944 /* move_notify is called before move happens */
Christian König765e7fb2016-09-15 15:06:50 +0200945 trace_amdgpu_ttm_bo_move(abo, new_mem->mem_type, old_mem->mem_type);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400946}
947
948int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
949{
Christian Königa7d64de2016-09-15 14:58:48 +0200950 struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
Christian König19be5572017-04-12 14:24:39 +0200951 struct ttm_operation_ctx ctx = { false, false };
Christian König5fb19412015-05-21 17:03:46 +0200952 struct amdgpu_bo *abo;
John Brooks96cf8272017-06-30 11:31:08 -0400953 unsigned long offset, size;
954 int r;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400955
956 if (!amdgpu_ttm_bo_is_amdgpu_bo(bo))
957 return 0;
Christian König5fb19412015-05-21 17:03:46 +0200958
Andres Rodriguezb82485f2017-09-15 21:05:19 -0400959 abo = ttm_to_amdgpu_bo(bo);
John Brooks96cf8272017-06-30 11:31:08 -0400960
961 /* Remember that this BO was accessed by the CPU */
962 abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
963
Christian König5fb19412015-05-21 17:03:46 +0200964 if (bo->mem.mem_type != TTM_PL_VRAM)
965 return 0;
966
967 size = bo->mem.num_pages << PAGE_SHIFT;
968 offset = bo->mem.start << PAGE_SHIFT;
Christian König770d13b2018-01-12 14:52:22 +0100969 if ((offset + size) <= adev->gmc.visible_vram_size)
Christian König5fb19412015-05-21 17:03:46 +0200970 return 0;
971
Michel Dänzer104ece92016-03-28 12:53:02 +0900972 /* Can't move a pinned BO to visible VRAM */
973 if (abo->pin_count > 0)
974 return -EINVAL;
975
Christian König5fb19412015-05-21 17:03:46 +0200976 /* hurrah the memory is not visible ! */
Marek Olšák68e2c5f2017-05-17 20:05:08 +0200977 atomic64_inc(&adev->num_vram_cpu_page_faults);
John Brooks41d9a6a2017-06-27 22:33:21 -0400978 amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM |
979 AMDGPU_GEM_DOMAIN_GTT);
980
981 /* Avoid costly evictions; only set GTT as a busy placement */
982 abo->placement.num_busy_placement = 1;
983 abo->placement.busy_placement = &abo->placements[1];
984
Christian König19be5572017-04-12 14:24:39 +0200985 r = ttm_bo_validate(bo, &abo->placement, &ctx);
John Brooks41d9a6a2017-06-27 22:33:21 -0400986 if (unlikely(r != 0))
Christian König5fb19412015-05-21 17:03:46 +0200987 return r;
Christian König5fb19412015-05-21 17:03:46 +0200988
989 offset = bo->mem.start << PAGE_SHIFT;
990 /* this should never happen */
John Brooks41d9a6a2017-06-27 22:33:21 -0400991 if (bo->mem.mem_type == TTM_PL_VRAM &&
Christian König770d13b2018-01-12 14:52:22 +0100992 (offset + size) > adev->gmc.visible_vram_size)
Christian König5fb19412015-05-21 17:03:46 +0200993 return -EINVAL;
994
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400995 return 0;
996}
997
998/**
999 * amdgpu_bo_fence - add fence to buffer object
1000 *
1001 * @bo: buffer object in question
1002 * @fence: fence to add
1003 * @shared: true if fence should be added shared
1004 *
1005 */
Chris Wilsonf54d1862016-10-25 13:00:45 +01001006void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
Alex Deucherd38ceaf2015-04-20 16:55:21 -04001007 bool shared)
1008{
1009 struct reservation_object *resv = bo->tbo.resv;
1010
1011 if (shared)
Chunming Zhoue40a3112015-08-03 11:38:09 +08001012 reservation_object_add_shared_fence(resv, fence);
Alex Deucherd38ceaf2015-04-20 16:55:21 -04001013 else
Chunming Zhoue40a3112015-08-03 11:38:09 +08001014 reservation_object_add_excl_fence(resv, fence);
Alex Deucherd38ceaf2015-04-20 16:55:21 -04001015}
Christian Königcdb7e8f2016-07-25 17:56:18 +02001016
1017/**
1018 * amdgpu_bo_gpu_offset - return GPU offset of bo
1019 * @bo: amdgpu object for which we query the offset
1020 *
1021 * Returns current GPU offset of the object.
1022 *
1023 * Note: object should either be pinned or reserved when calling this
1024 * function, it might be useful to add check for this for debugging.
1025 */
1026u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
1027{
1028 WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
Christian Königc855e252016-09-05 17:00:57 +02001029 WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_TT &&
Christian König3da917b2017-10-27 14:17:09 +02001030 !amdgpu_gtt_mgr_has_gart_addr(&bo->tbo.mem));
Christian Königcdb7e8f2016-07-25 17:56:18 +02001031 WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) &&
1032 !bo->pin_count);
Christian König9702d402016-09-07 15:10:44 +02001033 WARN_ON_ONCE(bo->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET);
Christian König03f48dd2016-08-15 17:00:22 +02001034 WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_VRAM &&
1035 !(bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS));
Christian Königcdb7e8f2016-07-25 17:56:18 +02001036
1037 return bo->tbo.offset;
1038}