xref: /openbmc/linux/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c (revision b181f7029bd71238ac2754ce7052dffd69432085)
1d38ceaf9SAlex Deucher /*
2d38ceaf9SAlex Deucher  * Copyright 2009 Jerome Glisse.
3d38ceaf9SAlex Deucher  * All Rights Reserved.
4d38ceaf9SAlex Deucher  *
5d38ceaf9SAlex Deucher  * Permission is hereby granted, free of charge, to any person obtaining a
6d38ceaf9SAlex Deucher  * copy of this software and associated documentation files (the
7d38ceaf9SAlex Deucher  * "Software"), to deal in the Software without restriction, including
8d38ceaf9SAlex Deucher  * without limitation the rights to use, copy, modify, merge, publish,
9d38ceaf9SAlex Deucher  * distribute, sub license, and/or sell copies of the Software, and to
10d38ceaf9SAlex Deucher  * permit persons to whom the Software is furnished to do so, subject to
11d38ceaf9SAlex Deucher  * the following conditions:
12d38ceaf9SAlex Deucher  *
13d38ceaf9SAlex Deucher  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14d38ceaf9SAlex Deucher  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15d38ceaf9SAlex Deucher  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16d38ceaf9SAlex Deucher  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17d38ceaf9SAlex Deucher  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18d38ceaf9SAlex Deucher  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19d38ceaf9SAlex Deucher  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20d38ceaf9SAlex Deucher  *
21d38ceaf9SAlex Deucher  * The above copyright notice and this permission notice (including the
22d38ceaf9SAlex Deucher  * next paragraph) shall be included in all copies or substantial portions
23d38ceaf9SAlex Deucher  * of the Software.
24d38ceaf9SAlex Deucher  *
25d38ceaf9SAlex Deucher  */
26d38ceaf9SAlex Deucher /*
27d38ceaf9SAlex Deucher  * Authors:
28d38ceaf9SAlex Deucher  *    Jerome Glisse <glisse@freedesktop.org>
29d38ceaf9SAlex Deucher  *    Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
30d38ceaf9SAlex Deucher  *    Dave Airlie
31d38ceaf9SAlex Deucher  */
32d38ceaf9SAlex Deucher #include <linux/list.h>
33d38ceaf9SAlex Deucher #include <linux/slab.h>
342d4dad27SChristian König #include <linux/dma-buf.h>
35fdf2f6c5SSam Ravnborg 
3662d5f9f7SLeslie Shi #include <drm/drm_drv.h>
37d38ceaf9SAlex Deucher #include <drm/amdgpu_drm.h>
38a187f17fSOded Gabbay #include <drm/drm_cache.h>
39d38ceaf9SAlex Deucher #include "amdgpu.h"
40d38ceaf9SAlex Deucher #include "amdgpu_trace.h"
41a46a2cd1SFelix Kuehling #include "amdgpu_amdkfd.h"
42d38ceaf9SAlex Deucher 
436f4e8d6eSSamuel Li /**
446f4e8d6eSSamuel Li  * DOC: amdgpu_object
456f4e8d6eSSamuel Li  *
466f4e8d6eSSamuel Li  * This defines the interfaces to operate on an &amdgpu_bo buffer object which
476f4e8d6eSSamuel Li  * represents memory used by driver (VRAM, system memory, etc.). The driver
486f4e8d6eSSamuel Li  * provides DRM/GEM APIs to userspace. DRM/GEM APIs then use these interfaces
496f4e8d6eSSamuel Li  * to create/destroy/set buffer object which are then managed by the kernel TTM
506f4e8d6eSSamuel Li  * memory manager.
516f4e8d6eSSamuel Li  * The interfaces are also used internally by kernel clients, including gfx,
526f4e8d6eSSamuel Li  * uvd, etc. for kernel managed allocations used by the GPU.
536f4e8d6eSSamuel Li  *
546f4e8d6eSSamuel Li  */
556f4e8d6eSSamuel Li 
amdgpu_bo_destroy(struct ttm_buffer_object * tbo)56c704ab18SChristian König static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo)
57d38ceaf9SAlex Deucher {
58b82485fdSAndres Rodriguez 	struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo);
59d38ceaf9SAlex Deucher 
606375bbb4SChristian König 	amdgpu_bo_kunmap(bo);
61d38ceaf9SAlex Deucher 
62c105de28SGerd Hoffmann 	if (bo->tbo.base.import_attach)
63c105de28SGerd Hoffmann 		drm_prime_gem_destroy(&bo->tbo.base, bo->tbo.sg);
64c105de28SGerd Hoffmann 	drm_gem_object_release(&bo->tbo.base);
6523e24fbbSNirmoy Das 	amdgpu_bo_unref(&bo->parent);
6623e24fbbSNirmoy Das 	kvfree(bo);
6723e24fbbSNirmoy Das }
6823e24fbbSNirmoy Das 
amdgpu_bo_user_destroy(struct ttm_buffer_object * tbo)6923e24fbbSNirmoy Das static void amdgpu_bo_user_destroy(struct ttm_buffer_object *tbo)
7023e24fbbSNirmoy Das {
7123e24fbbSNirmoy Das 	struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo);
7223e24fbbSNirmoy Das 	struct amdgpu_bo_user *ubo;
7323e24fbbSNirmoy Das 
7423e24fbbSNirmoy Das 	ubo = to_amdgpu_bo_user(bo);
7523e24fbbSNirmoy Das 	kfree(ubo->metadata);
7623e24fbbSNirmoy Das 	amdgpu_bo_destroy(tbo);
7723e24fbbSNirmoy Das }
7823e24fbbSNirmoy Das 
amdgpu_bo_vm_destroy(struct ttm_buffer_object * tbo)7923e24fbbSNirmoy Das static void amdgpu_bo_vm_destroy(struct ttm_buffer_object *tbo)
8023e24fbbSNirmoy Das {
8123e24fbbSNirmoy Das 	struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
82cbb63eccSHoratio Zhang 	struct amdgpu_bo *shadow_bo = ttm_to_amdgpu_bo(tbo), *bo;
83e18aaea7SNirmoy Das 	struct amdgpu_bo_vm *vmbo;
8423e24fbbSNirmoy Das 
85cbb63eccSHoratio Zhang 	bo = shadow_bo->parent;
86e18aaea7SNirmoy Das 	vmbo = to_amdgpu_bo_vm(bo);
8736e499b2Swentalou 	/* in case amdgpu_device_recover_vram got NULL of bo->parent */
88e18aaea7SNirmoy Das 	if (!list_empty(&vmbo->shadow_list)) {
89a7d64de6SChristian König 		mutex_lock(&adev->shadow_list_lock);
90e18aaea7SNirmoy Das 		list_del_init(&vmbo->shadow_list);
91a7d64de6SChristian König 		mutex_unlock(&adev->shadow_list_lock);
920c4e7fa5SChunming Zhou 	}
9336e499b2Swentalou 
9423e24fbbSNirmoy Das 	amdgpu_bo_destroy(tbo);
95d38ceaf9SAlex Deucher }
96d38ceaf9SAlex Deucher 
976f4e8d6eSSamuel Li /**
98c704ab18SChristian König  * amdgpu_bo_is_amdgpu_bo - check if the buffer object is an &amdgpu_bo
996f4e8d6eSSamuel Li  * @bo: buffer object to be checked
1006f4e8d6eSSamuel Li  *
1016f4e8d6eSSamuel Li  * Uses destroy function associated with the object to determine if this is
1026f4e8d6eSSamuel Li  * an &amdgpu_bo.
1036f4e8d6eSSamuel Li  *
1042472e11bSMichel Dänzer  * Returns:
1052472e11bSMichel Dänzer  * true if the object belongs to &amdgpu_bo, false if not.
1066f4e8d6eSSamuel Li  */
amdgpu_bo_is_amdgpu_bo(struct ttm_buffer_object * bo)107c704ab18SChristian König bool amdgpu_bo_is_amdgpu_bo(struct ttm_buffer_object *bo)
108d38ceaf9SAlex Deucher {
10923e24fbbSNirmoy Das 	if (bo->destroy == &amdgpu_bo_destroy ||
11023e24fbbSNirmoy Das 	    bo->destroy == &amdgpu_bo_user_destroy ||
11123e24fbbSNirmoy Das 	    bo->destroy == &amdgpu_bo_vm_destroy)
112d38ceaf9SAlex Deucher 		return true;
11323e24fbbSNirmoy Das 
114d38ceaf9SAlex Deucher 	return false;
115d38ceaf9SAlex Deucher }
116d38ceaf9SAlex Deucher 
1176f4e8d6eSSamuel Li /**
118c704ab18SChristian König  * amdgpu_bo_placement_from_domain - set buffer's placement
1196f4e8d6eSSamuel Li  * @abo: &amdgpu_bo buffer object whose placement is to be set
1206f4e8d6eSSamuel Li  * @domain: requested domain
1216f4e8d6eSSamuel Li  *
1226f4e8d6eSSamuel Li  * Sets buffer's placement according to requested domain and the buffer's
1236f4e8d6eSSamuel Li  * flags.
1246f4e8d6eSSamuel Li  */
amdgpu_bo_placement_from_domain(struct amdgpu_bo * abo,u32 domain)125c704ab18SChristian König void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
126d38ceaf9SAlex Deucher {
127c09312a6SChristian König 	struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
128c09312a6SChristian König 	struct ttm_placement *placement = &abo->placement;
129c09312a6SChristian König 	struct ttm_place *places = abo->placements;
130c09312a6SChristian König 	u64 flags = abo->flags;
1316369f6f1SChristian König 	u32 c = 0;
1327e5a547fSChunming Zhou 
133d38ceaf9SAlex Deucher 	if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
1341d6ecab1SSrinivasan Shanmugam 		unsigned int visible_pfn = adev->gmc.visible_vram_size >> PAGE_SHIFT;
1353ebfd221SPhilip Yang 		int8_t mem_id = KFD_XCP_MEM_ID(adev, abo->xcp_id);
136faceaf6aSChristian König 
1373ebfd221SPhilip Yang 		if (adev->gmc.mem_partitions && mem_id >= 0) {
1383ebfd221SPhilip Yang 			places[c].fpfn = adev->gmc.mem_partitions[mem_id].range.fpfn;
1396cfba94aSPhilip Yang 			/*
1406cfba94aSPhilip Yang 			 * memory partition range lpfn is inclusive start + size - 1
1416cfba94aSPhilip Yang 			 * TTM place lpfn is exclusive start + size
1426cfba94aSPhilip Yang 			 */
1433ebfd221SPhilip Yang 			places[c].lpfn = adev->gmc.mem_partitions[mem_id].range.lpfn + 1;
1447f6db894SPhilip Yang 		} else {
145faceaf6aSChristian König 			places[c].fpfn = 0;
14689bb5752SChristian König 			places[c].lpfn = 0;
1477f6db894SPhilip Yang 		}
14848e07c23SChristian König 		places[c].mem_type = TTM_PL_VRAM;
149ce65b874SChristian König 		places[c].flags = 0;
15089bb5752SChristian König 
151faceaf6aSChristian König 		if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
1527f6db894SPhilip Yang 			places[c].lpfn = min_not_zero(places[c].lpfn, visible_pfn);
15359eddd4eSArunpravin Paneer Selvam 		else
154faceaf6aSChristian König 			places[c].flags |= TTM_PL_FLAG_TOPDOWN;
15589bb5752SChristian König 
15689bb5752SChristian König 		if (flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
15789bb5752SChristian König 			places[c].flags |= TTM_PL_FLAG_CONTIGUOUS;
158faceaf6aSChristian König 		c++;
159d38ceaf9SAlex Deucher 	}
160d38ceaf9SAlex Deucher 
161dc3499c7SAlex Deucher 	if (domain & AMDGPU_GEM_DOMAIN_DOORBELL) {
162dc3499c7SAlex Deucher 		places[c].fpfn = 0;
163dc3499c7SAlex Deucher 		places[c].lpfn = 0;
164dc3499c7SAlex Deucher 		places[c].mem_type = AMDGPU_PL_DOORBELL;
165dc3499c7SAlex Deucher 		places[c].flags = 0;
166dc3499c7SAlex Deucher 		c++;
167dc3499c7SAlex Deucher 	}
168dc3499c7SAlex Deucher 
169d38ceaf9SAlex Deucher 	if (domain & AMDGPU_GEM_DOMAIN_GTT) {
170faceaf6aSChristian König 		places[c].fpfn = 0;
171faceaf6aSChristian König 		places[c].lpfn = 0;
172b453e42aSFelix Kuehling 		places[c].mem_type =
173b453e42aSFelix Kuehling 			abo->flags & AMDGPU_GEM_CREATE_PREEMPTIBLE ?
174b453e42aSFelix Kuehling 			AMDGPU_PL_PREEMPT : TTM_PL_TT;
17548e07c23SChristian König 		places[c].flags = 0;
176faceaf6aSChristian König 		c++;
177d38ceaf9SAlex Deucher 	}
178d38ceaf9SAlex Deucher 
179d38ceaf9SAlex Deucher 	if (domain & AMDGPU_GEM_DOMAIN_CPU) {
180faceaf6aSChristian König 		places[c].fpfn = 0;
181faceaf6aSChristian König 		places[c].lpfn = 0;
18248e07c23SChristian König 		places[c].mem_type = TTM_PL_SYSTEM;
18348e07c23SChristian König 		places[c].flags = 0;
184faceaf6aSChristian König 		c++;
185d38ceaf9SAlex Deucher 	}
186d38ceaf9SAlex Deucher 
187d38ceaf9SAlex Deucher 	if (domain & AMDGPU_GEM_DOMAIN_GDS) {
188faceaf6aSChristian König 		places[c].fpfn = 0;
189faceaf6aSChristian König 		places[c].lpfn = 0;
19048e07c23SChristian König 		places[c].mem_type = AMDGPU_PL_GDS;
191ce65b874SChristian König 		places[c].flags = 0;
192faceaf6aSChristian König 		c++;
193d38ceaf9SAlex Deucher 	}
194faceaf6aSChristian König 
195d38ceaf9SAlex Deucher 	if (domain & AMDGPU_GEM_DOMAIN_GWS) {
196faceaf6aSChristian König 		places[c].fpfn = 0;
197faceaf6aSChristian König 		places[c].lpfn = 0;
19848e07c23SChristian König 		places[c].mem_type = AMDGPU_PL_GWS;
199ce65b874SChristian König 		places[c].flags = 0;
200faceaf6aSChristian König 		c++;
201d38ceaf9SAlex Deucher 	}
202faceaf6aSChristian König 
203d38ceaf9SAlex Deucher 	if (domain & AMDGPU_GEM_DOMAIN_OA) {
204faceaf6aSChristian König 		places[c].fpfn = 0;
205faceaf6aSChristian König 		places[c].lpfn = 0;
20648e07c23SChristian König 		places[c].mem_type = AMDGPU_PL_OA;
207ce65b874SChristian König 		places[c].flags = 0;
208faceaf6aSChristian König 		c++;
209d38ceaf9SAlex Deucher 	}
210d38ceaf9SAlex Deucher 
211d38ceaf9SAlex Deucher 	if (!c) {
212faceaf6aSChristian König 		places[c].fpfn = 0;
213faceaf6aSChristian König 		places[c].lpfn = 0;
21448e07c23SChristian König 		places[c].mem_type = TTM_PL_SYSTEM;
215ce65b874SChristian König 		places[c].flags = 0;
216faceaf6aSChristian König 		c++;
217d38ceaf9SAlex Deucher 	}
218d38ceaf9SAlex Deucher 
219ea7acd7cSAndrey Grodzovsky 	BUG_ON(c > AMDGPU_BO_MAX_PLACEMENTS);
220bf314ca3SChristian König 
221faceaf6aSChristian König 	placement->num_placement = c;
222faceaf6aSChristian König 	placement->placement = places;
223faceaf6aSChristian König 
224faceaf6aSChristian König 	placement->num_busy_placement = c;
225faceaf6aSChristian König 	placement->busy_placement = places;
226d38ceaf9SAlex Deucher }
227d38ceaf9SAlex Deucher 
2287c204889SChristian König /**
2299d903cbdSChristian König  * amdgpu_bo_create_reserved - create reserved BO for kernel use
2307c204889SChristian König  *
2317c204889SChristian König  * @adev: amdgpu device object
2327c204889SChristian König  * @size: size for the new BO
2337c204889SChristian König  * @align: alignment for the new BO
2347c204889SChristian König  * @domain: where to place it
23564350f1bSAndrey Grodzovsky  * @bo_ptr: used to initialize BOs in structures
2367c204889SChristian König  * @gpu_addr: GPU addr of the pinned BO
2377c204889SChristian König  * @cpu_addr: optional CPU address mapping
2387c204889SChristian König  *
2399d903cbdSChristian König  * Allocates and pins a BO for kernel internal use, and returns it still
2409d903cbdSChristian König  * reserved.
2417c204889SChristian König  *
24264350f1bSAndrey Grodzovsky  * Note: For bo_ptr new BO is only created if bo_ptr points to NULL.
24364350f1bSAndrey Grodzovsky  *
2442472e11bSMichel Dänzer  * Returns:
2452472e11bSMichel Dänzer  * 0 on success, negative error code otherwise.
2467c204889SChristian König  */
amdgpu_bo_create_reserved(struct amdgpu_device * adev,unsigned long size,int align,u32 domain,struct amdgpu_bo ** bo_ptr,u64 * gpu_addr,void ** cpu_addr)2479d903cbdSChristian König int amdgpu_bo_create_reserved(struct amdgpu_device *adev,
2487c204889SChristian König 			      unsigned long size, int align,
2497c204889SChristian König 			      u32 domain, struct amdgpu_bo **bo_ptr,
2507c204889SChristian König 			      u64 *gpu_addr, void **cpu_addr)
2517c204889SChristian König {
2523216c6b7SChunming Zhou 	struct amdgpu_bo_param bp;
25353766e5aSChristian König 	bool free = false;
2547c204889SChristian König 	int r;
2557c204889SChristian König 
25621a7e77fSChristian König 	if (!size) {
25721a7e77fSChristian König 		amdgpu_bo_unref(bo_ptr);
25821a7e77fSChristian König 		return 0;
25921a7e77fSChristian König 	}
26021a7e77fSChristian König 
2613216c6b7SChunming Zhou 	memset(&bp, 0, sizeof(bp));
2623216c6b7SChunming Zhou 	bp.size = size;
2633216c6b7SChunming Zhou 	bp.byte_align = align;
2643216c6b7SChunming Zhou 	bp.domain = domain;
265828d6fdeSTianci.Yin 	bp.flags = cpu_addr ? AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED
266828d6fdeSTianci.Yin 		: AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
267828d6fdeSTianci.Yin 	bp.flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
2683216c6b7SChunming Zhou 	bp.type = ttm_bo_type_kernel;
2693216c6b7SChunming Zhou 	bp.resv = NULL;
2709fd5543eSNirmoy Das 	bp.bo_ptr_size = sizeof(struct amdgpu_bo);
2713216c6b7SChunming Zhou 
27253766e5aSChristian König 	if (!*bo_ptr) {
2733216c6b7SChunming Zhou 		r = amdgpu_bo_create(adev, &bp, bo_ptr);
2747c204889SChristian König 		if (r) {
27553766e5aSChristian König 			dev_err(adev->dev, "(%d) failed to allocate kernel bo\n",
27653766e5aSChristian König 				r);
2777c204889SChristian König 			return r;
2787c204889SChristian König 		}
27953766e5aSChristian König 		free = true;
28053766e5aSChristian König 	}
2817c204889SChristian König 
2827c204889SChristian König 	r = amdgpu_bo_reserve(*bo_ptr, false);
2837c204889SChristian König 	if (r) {
2847c204889SChristian König 		dev_err(adev->dev, "(%d) failed to reserve kernel bo\n", r);
2857c204889SChristian König 		goto error_free;
2867c204889SChristian König 	}
2877c204889SChristian König 
2887b7c6c81SJunwei Zhang 	r = amdgpu_bo_pin(*bo_ptr, domain);
2897c204889SChristian König 	if (r) {
2907c204889SChristian König 		dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
2917c204889SChristian König 		goto error_unreserve;
2927c204889SChristian König 	}
293bb812f1eSJunwei Zhang 
294bb812f1eSJunwei Zhang 	r = amdgpu_ttm_alloc_gart(&(*bo_ptr)->tbo);
295bb812f1eSJunwei Zhang 	if (r) {
296bb812f1eSJunwei Zhang 		dev_err(adev->dev, "%p bind failed\n", *bo_ptr);
297bb812f1eSJunwei Zhang 		goto error_unpin;
298bb812f1eSJunwei Zhang 	}
299bb812f1eSJunwei Zhang 
3007b7c6c81SJunwei Zhang 	if (gpu_addr)
3017b7c6c81SJunwei Zhang 		*gpu_addr = amdgpu_bo_gpu_offset(*bo_ptr);
3027c204889SChristian König 
3037c204889SChristian König 	if (cpu_addr) {
3047c204889SChristian König 		r = amdgpu_bo_kmap(*bo_ptr, cpu_addr);
3057c204889SChristian König 		if (r) {
3067c204889SChristian König 			dev_err(adev->dev, "(%d) kernel bo map failed\n", r);
307dc407ee0SJunwei Zhang 			goto error_unpin;
3087c204889SChristian König 		}
3097c204889SChristian König 	}
3107c204889SChristian König 
3117c204889SChristian König 	return 0;
3127c204889SChristian König 
313bb812f1eSJunwei Zhang error_unpin:
314bb812f1eSJunwei Zhang 	amdgpu_bo_unpin(*bo_ptr);
3157c204889SChristian König error_unreserve:
3167c204889SChristian König 	amdgpu_bo_unreserve(*bo_ptr);
3177c204889SChristian König 
3187c204889SChristian König error_free:
31953766e5aSChristian König 	if (free)
3207c204889SChristian König 		amdgpu_bo_unref(bo_ptr);
3217c204889SChristian König 
3227c204889SChristian König 	return r;
3237c204889SChristian König }
3247c204889SChristian König 
325aa1d562eSJunwei Zhang /**
3269d903cbdSChristian König  * amdgpu_bo_create_kernel - create BO for kernel use
3279d903cbdSChristian König  *
3289d903cbdSChristian König  * @adev: amdgpu device object
3299d903cbdSChristian König  * @size: size for the new BO
3309d903cbdSChristian König  * @align: alignment for the new BO
3319d903cbdSChristian König  * @domain: where to place it
33264350f1bSAndrey Grodzovsky  * @bo_ptr:  used to initialize BOs in structures
3339d903cbdSChristian König  * @gpu_addr: GPU addr of the pinned BO
3349d903cbdSChristian König  * @cpu_addr: optional CPU address mapping
3359d903cbdSChristian König  *
3369d903cbdSChristian König  * Allocates and pins a BO for kernel internal use.
3379d903cbdSChristian König  *
33864350f1bSAndrey Grodzovsky  * Note: For bo_ptr new BO is only created if bo_ptr points to NULL.
33964350f1bSAndrey Grodzovsky  *
3402472e11bSMichel Dänzer  * Returns:
3412472e11bSMichel Dänzer  * 0 on success, negative error code otherwise.
3429d903cbdSChristian König  */
amdgpu_bo_create_kernel(struct amdgpu_device * adev,unsigned long size,int align,u32 domain,struct amdgpu_bo ** bo_ptr,u64 * gpu_addr,void ** cpu_addr)3439d903cbdSChristian König int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
3449d903cbdSChristian König 			    unsigned long size, int align,
3459d903cbdSChristian König 			    u32 domain, struct amdgpu_bo **bo_ptr,
3469d903cbdSChristian König 			    u64 *gpu_addr, void **cpu_addr)
3479d903cbdSChristian König {
3489d903cbdSChristian König 	int r;
3499d903cbdSChristian König 
3509d903cbdSChristian König 	r = amdgpu_bo_create_reserved(adev, size, align, domain, bo_ptr,
3519d903cbdSChristian König 				      gpu_addr, cpu_addr);
3529d903cbdSChristian König 
3539d903cbdSChristian König 	if (r)
3549d903cbdSChristian König 		return r;
3559d903cbdSChristian König 
356ddaf5013STom St Denis 	if (*bo_ptr)
3579d903cbdSChristian König 		amdgpu_bo_unreserve(*bo_ptr);
3589d903cbdSChristian König 
3599d903cbdSChristian König 	return 0;
3609d903cbdSChristian König }
3619d903cbdSChristian König 
3629d903cbdSChristian König /**
363de7b45baSChristian König  * amdgpu_bo_create_kernel_at - create BO for kernel use at specific location
364de7b45baSChristian König  *
365de7b45baSChristian König  * @adev: amdgpu device object
366de7b45baSChristian König  * @offset: offset of the BO
367de7b45baSChristian König  * @size: size of the BO
368de7b45baSChristian König  * @bo_ptr:  used to initialize BOs in structures
369de7b45baSChristian König  * @cpu_addr: optional CPU address mapping
370de7b45baSChristian König  *
3713273f116SLuben Tuikov  * Creates a kernel BO at a specific offset in VRAM.
372de7b45baSChristian König  *
373de7b45baSChristian König  * Returns:
374de7b45baSChristian König  * 0 on success, negative error code otherwise.
375de7b45baSChristian König  */
amdgpu_bo_create_kernel_at(struct amdgpu_device * adev,uint64_t offset,uint64_t size,struct amdgpu_bo ** bo_ptr,void ** cpu_addr)376de7b45baSChristian König int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev,
3773273f116SLuben Tuikov 			       uint64_t offset, uint64_t size,
378de7b45baSChristian König 			       struct amdgpu_bo **bo_ptr, void **cpu_addr)
379de7b45baSChristian König {
380de7b45baSChristian König 	struct ttm_operation_ctx ctx = { false, false };
381de7b45baSChristian König 	unsigned int i;
382de7b45baSChristian König 	int r;
383de7b45baSChristian König 
384de7b45baSChristian König 	offset &= PAGE_MASK;
385de7b45baSChristian König 	size = ALIGN(size, PAGE_SIZE);
386de7b45baSChristian König 
3873273f116SLuben Tuikov 	r = amdgpu_bo_create_reserved(adev, size, PAGE_SIZE,
3883273f116SLuben Tuikov 				      AMDGPU_GEM_DOMAIN_VRAM, bo_ptr, NULL,
3893273f116SLuben Tuikov 				      cpu_addr);
390de7b45baSChristian König 	if (r)
391de7b45baSChristian König 		return r;
392de7b45baSChristian König 
39337912e96SAlex Deucher 	if ((*bo_ptr) == NULL)
39437912e96SAlex Deucher 		return 0;
39537912e96SAlex Deucher 
396de7b45baSChristian König 	/*
397de7b45baSChristian König 	 * Remove the original mem node and create a new one at the request
398de7b45baSChristian König 	 * position.
399de7b45baSChristian König 	 */
4004a246528SChristian König 	if (cpu_addr)
4014a246528SChristian König 		amdgpu_bo_kunmap(*bo_ptr);
4024a246528SChristian König 
403bfa3357eSChristian König 	ttm_resource_free(&(*bo_ptr)->tbo, &(*bo_ptr)->tbo.resource);
4044a246528SChristian König 
405de7b45baSChristian König 	for (i = 0; i < (*bo_ptr)->placement.num_placement; ++i) {
406de7b45baSChristian König 		(*bo_ptr)->placements[i].fpfn = offset >> PAGE_SHIFT;
407de7b45baSChristian König 		(*bo_ptr)->placements[i].lpfn = (offset + size) >> PAGE_SHIFT;
408de7b45baSChristian König 	}
409de7b45baSChristian König 	r = ttm_bo_mem_space(&(*bo_ptr)->tbo, &(*bo_ptr)->placement,
410bfa3357eSChristian König 			     &(*bo_ptr)->tbo.resource, &ctx);
411de7b45baSChristian König 	if (r)
412de7b45baSChristian König 		goto error;
413de7b45baSChristian König 
414de7b45baSChristian König 	if (cpu_addr) {
415de7b45baSChristian König 		r = amdgpu_bo_kmap(*bo_ptr, cpu_addr);
416de7b45baSChristian König 		if (r)
417de7b45baSChristian König 			goto error;
418de7b45baSChristian König 	}
419de7b45baSChristian König 
420de7b45baSChristian König 	amdgpu_bo_unreserve(*bo_ptr);
421de7b45baSChristian König 	return 0;
422de7b45baSChristian König 
423de7b45baSChristian König error:
424de7b45baSChristian König 	amdgpu_bo_unreserve(*bo_ptr);
425de7b45baSChristian König 	amdgpu_bo_unref(bo_ptr);
426de7b45baSChristian König 	return r;
427de7b45baSChristian König }
428de7b45baSChristian König 
429de7b45baSChristian König /**
430aa1d562eSJunwei Zhang  * amdgpu_bo_free_kernel - free BO for kernel use
431aa1d562eSJunwei Zhang  *
432aa1d562eSJunwei Zhang  * @bo: amdgpu BO to free
4332472e11bSMichel Dänzer  * @gpu_addr: pointer to where the BO's GPU memory space address was stored
4342472e11bSMichel Dänzer  * @cpu_addr: pointer to where the BO's CPU memory space address was stored
435aa1d562eSJunwei Zhang  *
436aa1d562eSJunwei Zhang  * unmaps and unpin a BO for kernel internal use.
437aa1d562eSJunwei Zhang  */
amdgpu_bo_free_kernel(struct amdgpu_bo ** bo,u64 * gpu_addr,void ** cpu_addr)438aa1d562eSJunwei Zhang void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr,
439aa1d562eSJunwei Zhang 			   void **cpu_addr)
440aa1d562eSJunwei Zhang {
441aa1d562eSJunwei Zhang 	if (*bo == NULL)
442aa1d562eSJunwei Zhang 		return;
443aa1d562eSJunwei Zhang 
4444d2ccd96SChristian König 	WARN_ON(amdgpu_ttm_adev((*bo)->tbo.bdev)->in_suspend);
4454d2ccd96SChristian König 
446f3aa745eSAlex Xie 	if (likely(amdgpu_bo_reserve(*bo, true) == 0)) {
447aa1d562eSJunwei Zhang 		if (cpu_addr)
448aa1d562eSJunwei Zhang 			amdgpu_bo_kunmap(*bo);
449aa1d562eSJunwei Zhang 
450aa1d562eSJunwei Zhang 		amdgpu_bo_unpin(*bo);
451aa1d562eSJunwei Zhang 		amdgpu_bo_unreserve(*bo);
452aa1d562eSJunwei Zhang 	}
453aa1d562eSJunwei Zhang 	amdgpu_bo_unref(bo);
454aa1d562eSJunwei Zhang 
455aa1d562eSJunwei Zhang 	if (gpu_addr)
456aa1d562eSJunwei Zhang 		*gpu_addr = 0;
457aa1d562eSJunwei Zhang 
458aa1d562eSJunwei Zhang 	if (cpu_addr)
459aa1d562eSJunwei Zhang 		*cpu_addr = NULL;
460aa1d562eSJunwei Zhang }
461aa1d562eSJunwei Zhang 
46279c63123SAndrey Grodzovsky /* Validate bo size is bit bigger then the request domain */
amdgpu_bo_validate_size(struct amdgpu_device * adev,unsigned long size,u32 domain)46379c63123SAndrey Grodzovsky static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
46479c63123SAndrey Grodzovsky 					  unsigned long size, u32 domain)
46579c63123SAndrey Grodzovsky {
4669de59bc2SDave Airlie 	struct ttm_resource_manager *man = NULL;
46779c63123SAndrey Grodzovsky 
46879c63123SAndrey Grodzovsky 	/*
46979c63123SAndrey Grodzovsky 	 * If GTT is part of requested domains the check must succeed to
4707554886dSLuben Tuikov 	 * allow fall back to GTT.
47179c63123SAndrey Grodzovsky 	 */
47279c63123SAndrey Grodzovsky 	if (domain & AMDGPU_GEM_DOMAIN_GTT) {
4736c28aed6SDave Airlie 		man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
47479c63123SAndrey Grodzovsky 
4757554886dSLuben Tuikov 		if (man && size < man->size)
47679c63123SAndrey Grodzovsky 			return true;
4777554886dSLuben Tuikov 		else if (!man)
4787554886dSLuben Tuikov 			WARN_ON_ONCE("GTT domain requested but GTT mem manager uninitialized");
47979c63123SAndrey Grodzovsky 		goto fail;
4807554886dSLuben Tuikov 	} else if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
4816c28aed6SDave Airlie 		man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
48279c63123SAndrey Grodzovsky 
4837554886dSLuben Tuikov 		if (man && size < man->size)
48479c63123SAndrey Grodzovsky 			return true;
48579c63123SAndrey Grodzovsky 		goto fail;
48679c63123SAndrey Grodzovsky 	}
48779c63123SAndrey Grodzovsky 
488dc3499c7SAlex Deucher 	/* TODO add more domains checks, such as AMDGPU_GEM_DOMAIN_CPU, _DOMAIN_DOORBELL */
48979c63123SAndrey Grodzovsky 	return true;
49079c63123SAndrey Grodzovsky 
49179c63123SAndrey Grodzovsky fail:
49208e60facSLuben Tuikov 	if (man)
493299c776cSMichel Dänzer 		DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
4944499c90eSChristian König 			  man->size);
49579c63123SAndrey Grodzovsky 	return false;
49679c63123SAndrey Grodzovsky }
49779c63123SAndrey Grodzovsky 
amdgpu_bo_support_uswc(u64 bo_flags)4983d1b8ec7SAndrey Grodzovsky bool amdgpu_bo_support_uswc(u64 bo_flags)
4993d1b8ec7SAndrey Grodzovsky {
5003d1b8ec7SAndrey Grodzovsky 
5013d1b8ec7SAndrey Grodzovsky #ifdef CONFIG_X86_32
5023d1b8ec7SAndrey Grodzovsky 	/* XXX: Write-combined CPU mappings of GTT seem broken on 32-bit
5033d1b8ec7SAndrey Grodzovsky 	 * See https://bugs.freedesktop.org/show_bug.cgi?id=84627
5043d1b8ec7SAndrey Grodzovsky 	 */
5053d1b8ec7SAndrey Grodzovsky 	return false;
5063d1b8ec7SAndrey Grodzovsky #elif defined(CONFIG_X86) && !defined(CONFIG_X86_PAT)
5073d1b8ec7SAndrey Grodzovsky 	/* Don't try to enable write-combining when it can't work, or things
5083d1b8ec7SAndrey Grodzovsky 	 * may be slow
5093d1b8ec7SAndrey Grodzovsky 	 * See https://bugs.freedesktop.org/show_bug.cgi?id=88758
5103d1b8ec7SAndrey Grodzovsky 	 */
5113d1b8ec7SAndrey Grodzovsky 
5123d1b8ec7SAndrey Grodzovsky #ifndef CONFIG_COMPILE_TEST
5133d1b8ec7SAndrey Grodzovsky #warning Please enable CONFIG_MTRR and CONFIG_X86_PAT for better performance \
5143d1b8ec7SAndrey Grodzovsky 	 thanks to write-combining
5153d1b8ec7SAndrey Grodzovsky #endif
5163d1b8ec7SAndrey Grodzovsky 
5173d1b8ec7SAndrey Grodzovsky 	if (bo_flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
5183d1b8ec7SAndrey Grodzovsky 		DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
5193d1b8ec7SAndrey Grodzovsky 			      "better performance thanks to write-combining\n");
5203d1b8ec7SAndrey Grodzovsky 	return false;
5213d1b8ec7SAndrey Grodzovsky #else
5223d1b8ec7SAndrey Grodzovsky 	/* For architectures that don't support WC memory,
5233d1b8ec7SAndrey Grodzovsky 	 * mask out the WC flag from the BO
5243d1b8ec7SAndrey Grodzovsky 	 */
5253d1b8ec7SAndrey Grodzovsky 	if (!drm_arch_can_wc_memory())
5263d1b8ec7SAndrey Grodzovsky 		return false;
5273d1b8ec7SAndrey Grodzovsky 
5283d1b8ec7SAndrey Grodzovsky 	return true;
5293d1b8ec7SAndrey Grodzovsky #endif
5303d1b8ec7SAndrey Grodzovsky }
5313d1b8ec7SAndrey Grodzovsky 
532cd2454d6SNirmoy Das /**
533cd2454d6SNirmoy Das  * amdgpu_bo_create - create an &amdgpu_bo buffer object
534cd2454d6SNirmoy Das  * @adev: amdgpu device object
535cd2454d6SNirmoy Das  * @bp: parameters to be used for the buffer object
536cd2454d6SNirmoy Das  * @bo_ptr: pointer to the buffer object pointer
537cd2454d6SNirmoy Das  *
538cd2454d6SNirmoy Das  * Creates an &amdgpu_bo buffer object.
539cd2454d6SNirmoy Das  *
540cd2454d6SNirmoy Das  * Returns:
541cd2454d6SNirmoy Das  * 0 for success or a negative error code on failure.
542cd2454d6SNirmoy Das  */
amdgpu_bo_create(struct amdgpu_device * adev,struct amdgpu_bo_param * bp,struct amdgpu_bo ** bo_ptr)543cd2454d6SNirmoy Das int amdgpu_bo_create(struct amdgpu_device *adev,
544a906dbb1SChunming Zhou 			       struct amdgpu_bo_param *bp,
5457e5a547fSChunming Zhou 			       struct amdgpu_bo **bo_ptr)
546d38ceaf9SAlex Deucher {
5479251859aSRoger He 	struct ttm_operation_ctx ctx = {
548a906dbb1SChunming Zhou 		.interruptible = (bp->type != ttm_bo_type_kernel),
549061468c4SChristian König 		.no_wait_gpu = bp->no_wait_gpu,
550586052b0SChristian König 		/* We opt to avoid OOM on system pages allocations */
551586052b0SChristian König 		.gfp_retry_mayfail = true,
552c44dfe4dSChristian König 		.allow_res_evict = bp->type != ttm_bo_type_kernel,
553c44dfe4dSChristian König 		.resv = bp->resv
5549251859aSRoger He 	};
555d38ceaf9SAlex Deucher 	struct amdgpu_bo *bo;
556a906dbb1SChunming Zhou 	unsigned long page_align, size = bp->size;
557d38ceaf9SAlex Deucher 	int r;
558d38ceaf9SAlex Deucher 
559fe57085aSMarek Olšák 	/* Note that GDS/GWS/OA allocates 1 page per byte/resource. */
560fe57085aSMarek Olšák 	if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) {
561fe57085aSMarek Olšák 		/* GWS and OA don't need any alignment. */
562fe57085aSMarek Olšák 		page_align = bp->byte_align;
56377a2faa5SChristian König 		size <<= PAGE_SHIFT;
564e3c92eb4SSomalapuram Amaranath 
565fe57085aSMarek Olšák 	} else if (bp->domain & AMDGPU_GEM_DOMAIN_GDS) {
566fe57085aSMarek Olšák 		/* Both size and alignment must be a multiple of 4. */
567fe57085aSMarek Olšák 		page_align = ALIGN(bp->byte_align, 4);
568fe57085aSMarek Olšák 		size = ALIGN(size, 4) << PAGE_SHIFT;
569fe57085aSMarek Olšák 	} else {
570fe57085aSMarek Olšák 		/* Memory should be aligned at least to a page size. */
571fe57085aSMarek Olšák 		page_align = ALIGN(bp->byte_align, PAGE_SIZE) >> PAGE_SHIFT;
572d38ceaf9SAlex Deucher 		size = ALIGN(size, PAGE_SIZE);
573fe57085aSMarek Olšák 	}
574d38ceaf9SAlex Deucher 
575a906dbb1SChunming Zhou 	if (!amdgpu_bo_validate_size(adev, size, bp->domain))
57679c63123SAndrey Grodzovsky 		return -ENOMEM;
57779c63123SAndrey Grodzovsky 
5789fd5543eSNirmoy Das 	BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo));
579d38ceaf9SAlex Deucher 
5809fd5543eSNirmoy Das 	*bo_ptr = NULL;
58131c759bbSChangfeng 	bo = kvzalloc(bp->bo_ptr_size, GFP_KERNEL);
582d38ceaf9SAlex Deucher 	if (bo == NULL)
583d38ceaf9SAlex Deucher 		return -ENOMEM;
5844a580877SLuben Tuikov 	drm_gem_private_object_init(adev_to_drm(adev), &bo->tbo.base, size);
585646b9025SChristian König 	bo->vm_bo = NULL;
5863f188453SChunming Zhou 	bo->preferred_domains = bp->preferred_domain ? bp->preferred_domain :
587aa2b2e28SChunming Zhou 		bp->domain;
58808082104SChristian König 	bo->allowed_domains = bo->preferred_domains;
589a906dbb1SChunming Zhou 	if (bp->type != ttm_bo_type_kernel &&
590fab2cc83SChristian König 	    !(bp->flags & AMDGPU_GEM_CREATE_DISCARDABLE) &&
59108082104SChristian König 	    bo->allowed_domains == AMDGPU_GEM_DOMAIN_VRAM)
59208082104SChristian König 		bo->allowed_domains |= AMDGPU_GEM_DOMAIN_GTT;
593d38ceaf9SAlex Deucher 
594a906dbb1SChunming Zhou 	bo->flags = bp->flags;
595a187f17fSOded Gabbay 
5963ebfd221SPhilip Yang 	if (adev->gmc.mem_partitions)
5973ebfd221SPhilip Yang 		/* For GPUs with spatial partitioning, bo->xcp_id=-1 means any partition */
5983ebfd221SPhilip Yang 		bo->xcp_id = bp->xcp_id_plus1 - 1;
5993ebfd221SPhilip Yang 	else
6003ebfd221SPhilip Yang 		/* For GPUs without spatial partitioning */
6013ebfd221SPhilip Yang 		bo->xcp_id = 0;
602f24e924bSPhilip Yang 
6033d1b8ec7SAndrey Grodzovsky 	if (!amdgpu_bo_support_uswc(bo->flags))
604a2e2f299SNils Holland 		bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
605a187f17fSOded Gabbay 
606fc6ea4beSFelix Kuehling 	if (adev->ras_enabled)
607fc6ea4beSFelix Kuehling 		bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
608fc6ea4beSFelix Kuehling 
609c09312a6SChristian König 	bo->tbo.bdev = &adev->mman.bdev;
61047722220SChristian König 	if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA |
61147722220SChristian König 			  AMDGPU_GEM_DOMAIN_GDS))
61247722220SChristian König 		amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
61347722220SChristian König 	else
614c704ab18SChristian König 		amdgpu_bo_placement_from_domain(bo, bp->domain);
615a50cb948SJunwei Zhang 	if (bp->type == ttm_bo_type_kernel)
616*04cf241fSFelix Kuehling 		bo->tbo.priority = 2;
617*04cf241fSFelix Kuehling 	else if (!(bp->flags & AMDGPU_GEM_CREATE_DISCARDABLE))
618a50cb948SJunwei Zhang 		bo->tbo.priority = 1;
61908082104SChristian König 
62023e24fbbSNirmoy Das 	if (!bp->destroy)
62123e24fbbSNirmoy Das 		bp->destroy = &amdgpu_bo_destroy;
62223e24fbbSNirmoy Das 
623347987a2SChristian König 	r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, bp->type,
624f07069daSChristian König 				 &bo->placement, page_align, &ctx,  NULL,
62523e24fbbSNirmoy Das 				 bp->resv, bp->destroy);
62608082104SChristian König 	if (unlikely(r != 0))
627a695e437SChristian König 		return r;
628a695e437SChristian König 
629c8c5e569SAndrey Grodzovsky 	if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
6304c5eaf0cSChristian König 	    amdgpu_res_cpu_visible(adev, bo->tbo.resource))
6316af046d2SChristian König 		amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved,
6326af046d2SChristian König 					     ctx.bytes_moved);
63300f06b24SJohn Brooks 	else
6346af046d2SChristian König 		amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved, 0);
635fad06127SSamuel Pitoiset 
636a906dbb1SChunming Zhou 	if (bp->flags & AMDGPU_GEM_CREATE_VRAM_CLEARED &&
637d3116756SChristian König 	    bo->tbo.resource->mem_type == TTM_PL_VRAM) {
638f54d1867SChris Wilson 		struct dma_fence *fence;
6394fea83ffSFlora Cui 
640c3aaca43SMukul Joshi 		r = amdgpu_fill_buffer(bo, 0, bo->tbo.base.resv, &fence, true);
641c3af1258SChristian König 		if (unlikely(r))
642c3af1258SChristian König 			goto fail_unreserve;
643c3af1258SChristian König 
6448bb31587SChristian König 		dma_resv_add_fence(bo->tbo.base.resv, fence,
6458bb31587SChristian König 				   DMA_RESV_USAGE_KERNEL);
646f54d1867SChris Wilson 		dma_fence_put(fence);
6474fea83ffSFlora Cui 	}
648a906dbb1SChunming Zhou 	if (!bp->resv)
64959c66c91SNicolai Hähnle 		amdgpu_bo_unreserve(bo);
650d38ceaf9SAlex Deucher 	*bo_ptr = bo;
651d38ceaf9SAlex Deucher 
652d38ceaf9SAlex Deucher 	trace_amdgpu_bo_create(bo);
653d38ceaf9SAlex Deucher 
65496cf8271SJohn Brooks 	/* Treat CPU_ACCESS_REQUIRED only as a hint if given by UMD */
655a906dbb1SChunming Zhou 	if (bp->type == ttm_bo_type_device)
65696cf8271SJohn Brooks 		bo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
65796cf8271SJohn Brooks 
658d38ceaf9SAlex Deucher 	return 0;
6594fea83ffSFlora Cui 
6604fea83ffSFlora Cui fail_unreserve:
661a906dbb1SChunming Zhou 	if (!bp->resv)
66252791eeeSChristian König 		dma_resv_unlock(bo->tbo.base.resv);
6634fea83ffSFlora Cui 	amdgpu_bo_unref(&bo);
6644fea83ffSFlora Cui 	return r;
665d38ceaf9SAlex Deucher }
666d38ceaf9SAlex Deucher 
6676f4e8d6eSSamuel Li /**
6689ad0d033SNirmoy Das  * amdgpu_bo_create_user - create an &amdgpu_bo_user buffer object
6699ad0d033SNirmoy Das  * @adev: amdgpu device object
6709ad0d033SNirmoy Das  * @bp: parameters to be used for the buffer object
6719ad0d033SNirmoy Das  * @ubo_ptr: pointer to the buffer object pointer
6729ad0d033SNirmoy Das  *
6739ad0d033SNirmoy Das  * Create a BO to be used by user application;
6749ad0d033SNirmoy Das  *
6759ad0d033SNirmoy Das  * Returns:
6769ad0d033SNirmoy Das  * 0 for success or a negative error code on failure.
6779ad0d033SNirmoy Das  */
6789ad0d033SNirmoy Das 
amdgpu_bo_create_user(struct amdgpu_device * adev,struct amdgpu_bo_param * bp,struct amdgpu_bo_user ** ubo_ptr)6799ad0d033SNirmoy Das int amdgpu_bo_create_user(struct amdgpu_device *adev,
6809ad0d033SNirmoy Das 			  struct amdgpu_bo_param *bp,
6819ad0d033SNirmoy Das 			  struct amdgpu_bo_user **ubo_ptr)
6829ad0d033SNirmoy Das {
6839ad0d033SNirmoy Das 	struct amdgpu_bo *bo_ptr;
6849ad0d033SNirmoy Das 	int r;
6859ad0d033SNirmoy Das 
6869ad0d033SNirmoy Das 	bp->bo_ptr_size = sizeof(struct amdgpu_bo_user);
68723e24fbbSNirmoy Das 	bp->destroy = &amdgpu_bo_user_destroy;
688cd2454d6SNirmoy Das 	r = amdgpu_bo_create(adev, bp, &bo_ptr);
6899ad0d033SNirmoy Das 	if (r)
6909ad0d033SNirmoy Das 		return r;
6919ad0d033SNirmoy Das 
6929ad0d033SNirmoy Das 	*ubo_ptr = to_amdgpu_bo_user(bo_ptr);
6939ad0d033SNirmoy Das 	return r;
6949ad0d033SNirmoy Das }
6956fdd6f4aSNirmoy Das 
6966fdd6f4aSNirmoy Das /**
6976fdd6f4aSNirmoy Das  * amdgpu_bo_create_vm - create an &amdgpu_bo_vm buffer object
6986fdd6f4aSNirmoy Das  * @adev: amdgpu device object
6996fdd6f4aSNirmoy Das  * @bp: parameters to be used for the buffer object
7006fdd6f4aSNirmoy Das  * @vmbo_ptr: pointer to the buffer object pointer
7016fdd6f4aSNirmoy Das  *
7026fdd6f4aSNirmoy Das  * Create a BO to be for GPUVM.
7036fdd6f4aSNirmoy Das  *
7046fdd6f4aSNirmoy Das  * Returns:
7056fdd6f4aSNirmoy Das  * 0 for success or a negative error code on failure.
7066fdd6f4aSNirmoy Das  */
7076fdd6f4aSNirmoy Das 
amdgpu_bo_create_vm(struct amdgpu_device * adev,struct amdgpu_bo_param * bp,struct amdgpu_bo_vm ** vmbo_ptr)7086fdd6f4aSNirmoy Das int amdgpu_bo_create_vm(struct amdgpu_device *adev,
7096fdd6f4aSNirmoy Das 			struct amdgpu_bo_param *bp,
7106fdd6f4aSNirmoy Das 			struct amdgpu_bo_vm **vmbo_ptr)
7116fdd6f4aSNirmoy Das {
7126fdd6f4aSNirmoy Das 	struct amdgpu_bo *bo_ptr;
7136fdd6f4aSNirmoy Das 	int r;
7146fdd6f4aSNirmoy Das 
7156fdd6f4aSNirmoy Das 	/* bo_ptr_size will be determined by the caller and it depends on
7166fdd6f4aSNirmoy Das 	 * num of amdgpu_vm_pt entries.
7176fdd6f4aSNirmoy Das 	 */
7186fdd6f4aSNirmoy Das 	BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo_vm));
7196fdd6f4aSNirmoy Das 	r = amdgpu_bo_create(adev, bp, &bo_ptr);
7206fdd6f4aSNirmoy Das 	if (r)
7216fdd6f4aSNirmoy Das 		return r;
7226fdd6f4aSNirmoy Das 
7236fdd6f4aSNirmoy Das 	*vmbo_ptr = to_amdgpu_bo_vm(bo_ptr);
7246fdd6f4aSNirmoy Das 	return r;
7256fdd6f4aSNirmoy Das }
7266fdd6f4aSNirmoy Das 
7279ad0d033SNirmoy Das /**
7281fdc79f6SNirmoy Das  * amdgpu_bo_add_to_shadow_list - add a BO to the shadow list
7291fdc79f6SNirmoy Das  *
730d8c33180SAnson Jacob  * @vmbo: BO that will be inserted into the shadow list
7311fdc79f6SNirmoy Das  *
7321fdc79f6SNirmoy Das  * Insert a BO to the shadow list.
7331fdc79f6SNirmoy Das  */
amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm * vmbo)734e18aaea7SNirmoy Das void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo)
7351fdc79f6SNirmoy Das {
736e18aaea7SNirmoy Das 	struct amdgpu_device *adev = amdgpu_ttm_adev(vmbo->bo.tbo.bdev);
7371fdc79f6SNirmoy Das 
7381fdc79f6SNirmoy Das 	mutex_lock(&adev->shadow_list_lock);
739e18aaea7SNirmoy Das 	list_add_tail(&vmbo->shadow_list, &adev->shadow_list);
740cbb63eccSHoratio Zhang 	vmbo->shadow->parent = amdgpu_bo_ref(&vmbo->bo);
741cbb63eccSHoratio Zhang 	vmbo->shadow->tbo.destroy = &amdgpu_bo_vm_destroy;
7421fdc79f6SNirmoy Das 	mutex_unlock(&adev->shadow_list_lock);
7431fdc79f6SNirmoy Das }
7441fdc79f6SNirmoy Das 
7451fdc79f6SNirmoy Das /**
746403009bfSChristian König  * amdgpu_bo_restore_shadow - restore an &amdgpu_bo shadow
747403009bfSChristian König  *
748403009bfSChristian König  * @shadow: &amdgpu_bo shadow to be restored
7496f4e8d6eSSamuel Li  * @fence: dma_fence associated with the operation
7506f4e8d6eSSamuel Li  *
7516f4e8d6eSSamuel Li  * Copies a buffer object's shadow content back to the object.
7526f4e8d6eSSamuel Li  * This is used for recovering a buffer from its shadow in case of a gpu
7536f4e8d6eSSamuel Li  * reset where vram context may be lost.
7546f4e8d6eSSamuel Li  *
7552472e11bSMichel Dänzer  * Returns:
7562472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
7576f4e8d6eSSamuel Li  */
amdgpu_bo_restore_shadow(struct amdgpu_bo * shadow,struct dma_fence ** fence)758403009bfSChristian König int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, struct dma_fence **fence)
75920f4eff1SChunming Zhou 
76020f4eff1SChunming Zhou {
761403009bfSChristian König 	struct amdgpu_device *adev = amdgpu_ttm_adev(shadow->tbo.bdev);
762403009bfSChristian König 	struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
763403009bfSChristian König 	uint64_t shadow_addr, parent_addr;
76420f4eff1SChunming Zhou 
765403009bfSChristian König 	shadow_addr = amdgpu_bo_gpu_offset(shadow);
766403009bfSChristian König 	parent_addr = amdgpu_bo_gpu_offset(shadow->parent);
76720f4eff1SChunming Zhou 
768403009bfSChristian König 	return amdgpu_copy_buffer(ring, shadow_addr, parent_addr,
769403009bfSChristian König 				  amdgpu_bo_size(shadow), NULL, fence,
770c9dc9cfeSAaron Liu 				  true, false, false);
77120f4eff1SChunming Zhou }
77220f4eff1SChunming Zhou 
7736f4e8d6eSSamuel Li /**
7746f4e8d6eSSamuel Li  * amdgpu_bo_kmap - map an &amdgpu_bo buffer object
7756f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object to be mapped
7766f4e8d6eSSamuel Li  * @ptr: kernel virtual address to be returned
7776f4e8d6eSSamuel Li  *
7786f4e8d6eSSamuel Li  * Calls ttm_bo_kmap() to set up the kernel virtual mapping; calls
7796f4e8d6eSSamuel Li  * amdgpu_bo_kptr() to get the kernel virtual address.
7806f4e8d6eSSamuel Li  *
7812472e11bSMichel Dänzer  * Returns:
7822472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
7836f4e8d6eSSamuel Li  */
amdgpu_bo_kmap(struct amdgpu_bo * bo,void ** ptr)784d38ceaf9SAlex Deucher int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
785d38ceaf9SAlex Deucher {
786f5e1c740SChristian König 	void *kptr;
787587f3c70SChristian König 	long r;
788d38ceaf9SAlex Deucher 
789271c8125SChristian König 	if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
790271c8125SChristian König 		return -EPERM;
791271c8125SChristian König 
792c35fcfa3SChristian König 	r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_KERNEL,
793c35fcfa3SChristian König 				  false, MAX_SCHEDULE_TIMEOUT);
794c35fcfa3SChristian König 	if (r < 0)
795c35fcfa3SChristian König 		return r;
796c35fcfa3SChristian König 
797f5e1c740SChristian König 	kptr = amdgpu_bo_kptr(bo);
798f5e1c740SChristian König 	if (kptr) {
799f5e1c740SChristian König 		if (ptr)
800f5e1c740SChristian König 			*ptr = kptr;
801d38ceaf9SAlex Deucher 		return 0;
802d38ceaf9SAlex Deucher 	}
803587f3c70SChristian König 
804e3c92eb4SSomalapuram Amaranath 	r = ttm_bo_kmap(&bo->tbo, 0, PFN_UP(bo->tbo.base.size), &bo->kmap);
805587f3c70SChristian König 	if (r)
806587f3c70SChristian König 		return r;
807587f3c70SChristian König 
808587f3c70SChristian König 	if (ptr)
809f5e1c740SChristian König 		*ptr = amdgpu_bo_kptr(bo);
810587f3c70SChristian König 
811d38ceaf9SAlex Deucher 	return 0;
812d38ceaf9SAlex Deucher }
813d38ceaf9SAlex Deucher 
8146f4e8d6eSSamuel Li /**
8156f4e8d6eSSamuel Li  * amdgpu_bo_kptr - returns a kernel virtual address of the buffer object
8166f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object
8176f4e8d6eSSamuel Li  *
8186f4e8d6eSSamuel Li  * Calls ttm_kmap_obj_virtual() to get the kernel virtual address
8196f4e8d6eSSamuel Li  *
8202472e11bSMichel Dänzer  * Returns:
8212472e11bSMichel Dänzer  * the virtual address of a buffer object area.
8226f4e8d6eSSamuel Li  */
amdgpu_bo_kptr(struct amdgpu_bo * bo)823f5e1c740SChristian König void *amdgpu_bo_kptr(struct amdgpu_bo *bo)
824f5e1c740SChristian König {
825f5e1c740SChristian König 	bool is_iomem;
826f5e1c740SChristian König 
827f5e1c740SChristian König 	return ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
828f5e1c740SChristian König }
829f5e1c740SChristian König 
8306f4e8d6eSSamuel Li /**
8316f4e8d6eSSamuel Li  * amdgpu_bo_kunmap - unmap an &amdgpu_bo buffer object
8326f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object to be unmapped
8336f4e8d6eSSamuel Li  *
8346f4e8d6eSSamuel Li  * Unmaps a kernel map set up by amdgpu_bo_kmap().
8356f4e8d6eSSamuel Li  */
amdgpu_bo_kunmap(struct amdgpu_bo * bo)836d38ceaf9SAlex Deucher void amdgpu_bo_kunmap(struct amdgpu_bo *bo)
837d38ceaf9SAlex Deucher {
838f5e1c740SChristian König 	if (bo->kmap.bo)
839d38ceaf9SAlex Deucher 		ttm_bo_kunmap(&bo->kmap);
840d38ceaf9SAlex Deucher }
841d38ceaf9SAlex Deucher 
8426f4e8d6eSSamuel Li /**
8436f4e8d6eSSamuel Li  * amdgpu_bo_ref - reference an &amdgpu_bo buffer object
8446f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object
8456f4e8d6eSSamuel Li  *
8466f4e8d6eSSamuel Li  * References the contained &ttm_buffer_object.
8476f4e8d6eSSamuel Li  *
8482472e11bSMichel Dänzer  * Returns:
8492472e11bSMichel Dänzer  * a refcounted pointer to the &amdgpu_bo buffer object.
8506f4e8d6eSSamuel Li  */
amdgpu_bo_ref(struct amdgpu_bo * bo)851d38ceaf9SAlex Deucher struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo)
852d38ceaf9SAlex Deucher {
853d38ceaf9SAlex Deucher 	if (bo == NULL)
854d38ceaf9SAlex Deucher 		return NULL;
855d38ceaf9SAlex Deucher 
85671d5ef11SThomas Zimmermann 	ttm_bo_get(&bo->tbo);
857d38ceaf9SAlex Deucher 	return bo;
858d38ceaf9SAlex Deucher }
859d38ceaf9SAlex Deucher 
8606f4e8d6eSSamuel Li /**
8616f4e8d6eSSamuel Li  * amdgpu_bo_unref - unreference an &amdgpu_bo buffer object
8626f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object
8636f4e8d6eSSamuel Li  *
8646f4e8d6eSSamuel Li  * Unreferences the contained &ttm_buffer_object and clear the pointer
8656f4e8d6eSSamuel Li  */
amdgpu_bo_unref(struct amdgpu_bo ** bo)866d38ceaf9SAlex Deucher void amdgpu_bo_unref(struct amdgpu_bo **bo)
867d38ceaf9SAlex Deucher {
868d38ceaf9SAlex Deucher 	struct ttm_buffer_object *tbo;
869d38ceaf9SAlex Deucher 
870d38ceaf9SAlex Deucher 	if ((*bo) == NULL)
871d38ceaf9SAlex Deucher 		return;
872d38ceaf9SAlex Deucher 
873d38ceaf9SAlex Deucher 	tbo = &((*bo)->tbo);
874fea872b2SThomas Zimmermann 	ttm_bo_put(tbo);
875d38ceaf9SAlex Deucher 	*bo = NULL;
876d38ceaf9SAlex Deucher }
877d38ceaf9SAlex Deucher 
8786f4e8d6eSSamuel Li /**
8796f4e8d6eSSamuel Li  * amdgpu_bo_pin_restricted - pin an &amdgpu_bo buffer object
8806f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object to be pinned
8816f4e8d6eSSamuel Li  * @domain: domain to be pinned to
8826f4e8d6eSSamuel Li  * @min_offset: the start of requested address range
8836f4e8d6eSSamuel Li  * @max_offset: the end of requested address range
8846f4e8d6eSSamuel Li  *
8856f4e8d6eSSamuel Li  * Pins the buffer object according to requested domain and address range. If
8866f4e8d6eSSamuel Li  * the memory is unbound gart memory, binds the pages into gart table. Adjusts
8876f4e8d6eSSamuel Li  * pin_count and pin_size accordingly.
8886f4e8d6eSSamuel Li  *
8896f4e8d6eSSamuel Li  * Pinning means to lock pages in memory along with keeping them at a fixed
8906f4e8d6eSSamuel Li  * offset. It is required when a buffer can not be moved, for example, when
8916f4e8d6eSSamuel Li  * a display buffer is being scanned out.
8926f4e8d6eSSamuel Li  *
8936f4e8d6eSSamuel Li  * Compared with amdgpu_bo_pin(), this function gives more flexibility on
8946f4e8d6eSSamuel Li  * where to pin a buffer if there are specific restrictions on where a buffer
8956f4e8d6eSSamuel Li  * must be located.
8966f4e8d6eSSamuel Li  *
8972472e11bSMichel Dänzer  * Returns:
8982472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
8996f4e8d6eSSamuel Li  */
amdgpu_bo_pin_restricted(struct amdgpu_bo * bo,u32 domain,u64 min_offset,u64 max_offset)9007e5a547fSChunming Zhou int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
9017b7c6c81SJunwei Zhang 			     u64 min_offset, u64 max_offset)
902d38ceaf9SAlex Deucher {
903a7d64de6SChristian König 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
90419be5570SChristian König 	struct ttm_operation_ctx ctx = { false, false };
905d38ceaf9SAlex Deucher 	int r, i;
906d38ceaf9SAlex Deucher 
907cc325d19SChristian König 	if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm))
908d38ceaf9SAlex Deucher 		return -EPERM;
909d38ceaf9SAlex Deucher 
9107e5a547fSChunming Zhou 	if (WARN_ON_ONCE(min_offset > max_offset))
9117e5a547fSChunming Zhou 		return -EINVAL;
9127e5a547fSChunming Zhou 
913f5ba1404SLeo Li 	/* Check domain to be pinned to against preferred domains */
914f5ba1404SLeo Li 	if (bo->preferred_domains & domain)
915f5ba1404SLeo Li 		domain = bo->preferred_domains & domain;
916f5ba1404SLeo Li 
917803d89adSChristopher James Halse Rogers 	/* A shared bo cannot be migrated to VRAM */
9188c505bdcSChristian König 	if (bo->tbo.base.import_attach) {
9199b3f217fSSamuel Li 		if (domain & AMDGPU_GEM_DOMAIN_GTT)
9209b3f217fSSamuel Li 			domain = AMDGPU_GEM_DOMAIN_GTT;
9219b3f217fSSamuel Li 		else
922803d89adSChristopher James Halse Rogers 			return -EINVAL;
9239b3f217fSSamuel Li 	}
924803d89adSChristopher James Halse Rogers 
9254671078eSChristian König 	if (bo->tbo.pin_count) {
926d3116756SChristian König 		uint32_t mem_type = bo->tbo.resource->mem_type;
927d3116756SChristian König 		uint32_t mem_flags = bo->tbo.resource->placement;
928408778e8SFlora Cui 
929f5318959SChristian König 		if (!(domain & amdgpu_mem_type_to_domain(mem_type)))
930408778e8SFlora Cui 			return -EINVAL;
931408778e8SFlora Cui 
932e1a4b67aSxinhui pan 		if ((mem_type == TTM_PL_VRAM) &&
933e1a4b67aSxinhui pan 		    (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) &&
934eda1068dSFelix Kuehling 		    !(mem_flags & TTM_PL_FLAG_CONTIGUOUS))
935eda1068dSFelix Kuehling 			return -EINVAL;
936eda1068dSFelix Kuehling 
9374671078eSChristian König 		ttm_bo_pin(&bo->tbo);
938d38ceaf9SAlex Deucher 
939d38ceaf9SAlex Deucher 		if (max_offset != 0) {
940b1a8ef95SNirmoy Das 			u64 domain_start = amdgpu_ttm_domain_start(adev,
941b1a8ef95SNirmoy Das 								   mem_type);
942d38ceaf9SAlex Deucher 			WARN_ON_ONCE(max_offset <
943d38ceaf9SAlex Deucher 				     (amdgpu_bo_gpu_offset(bo) - domain_start));
944d38ceaf9SAlex Deucher 		}
945d38ceaf9SAlex Deucher 
946d38ceaf9SAlex Deucher 		return 0;
947d38ceaf9SAlex Deucher 	}
94803f48dd5SChristian König 
9499deb0b3dSChristian König 	/* This assumes only APU display buffers are pinned with (VRAM|GTT).
9509deb0b3dSChristian König 	 * See function amdgpu_display_supported_domains()
9519deb0b3dSChristian König 	 */
952d035f84dSYifan Zhang 	domain = amdgpu_bo_get_preferred_domain(adev, domain);
9539deb0b3dSChristian König 
954a448cb00SChristian König 	if (bo->tbo.base.import_attach)
955a448cb00SChristian König 		dma_buf_pin(bo->tbo.base.import_attach);
956a448cb00SChristian König 
957e9c7577cSChristian König 	/* force to pin into visible video ram */
958e9c7577cSChristian König 	if (!(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS))
959e9c7577cSChristian König 		bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
960c704ab18SChristian König 	amdgpu_bo_placement_from_domain(bo, domain);
961d38ceaf9SAlex Deucher 	for (i = 0; i < bo->placement.num_placement; i++) {
9621d6ecab1SSrinivasan Shanmugam 		unsigned int fpfn, lpfn;
963e9c7577cSChristian König 
9647e5a547fSChunming Zhou 		fpfn = min_offset >> PAGE_SHIFT;
9657e5a547fSChunming Zhou 		lpfn = max_offset >> PAGE_SHIFT;
966e9c7577cSChristian König 
9677e5a547fSChunming Zhou 		if (fpfn > bo->placements[i].fpfn)
9687e5a547fSChunming Zhou 			bo->placements[i].fpfn = fpfn;
96978d0e182SChristian König 		if (!bo->placements[i].lpfn ||
97078d0e182SChristian König 		    (lpfn && lpfn < bo->placements[i].lpfn))
9717e5a547fSChunming Zhou 			bo->placements[i].lpfn = lpfn;
972d38ceaf9SAlex Deucher 	}
973d38ceaf9SAlex Deucher 
97419be5570SChristian König 	r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
9756681c5ebSChristian König 	if (unlikely(r)) {
976a7d64de6SChristian König 		dev_err(adev->dev, "%p pin failed\n", bo);
9776681c5ebSChristian König 		goto error;
9786681c5ebSChristian König 	}
97907306b4fSChunming Zhou 
9804671078eSChristian König 	ttm_bo_pin(&bo->tbo);
9815e91fb57SChristian König 
982d3116756SChristian König 	domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
983e131b914SChunming Zhou 	if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
984a5ccfe5cSMichel Dänzer 		atomic64_add(amdgpu_bo_size(bo), &adev->vram_pin_size);
985a5ccfe5cSMichel Dänzer 		atomic64_add(amdgpu_vram_mgr_bo_visible_size(bo),
986a5ccfe5cSMichel Dänzer 			     &adev->visible_pin_size);
98732ab75f0SFlora Cui 	} else if (domain == AMDGPU_GEM_DOMAIN_GTT) {
988a5ccfe5cSMichel Dänzer 		atomic64_add(amdgpu_bo_size(bo), &adev->gart_pin_size);
989d38ceaf9SAlex Deucher 	}
9906681c5ebSChristian König 
9916681c5ebSChristian König error:
992d38ceaf9SAlex Deucher 	return r;
993d38ceaf9SAlex Deucher }
994d38ceaf9SAlex Deucher 
9956f4e8d6eSSamuel Li /**
9966f4e8d6eSSamuel Li  * amdgpu_bo_pin - pin an &amdgpu_bo buffer object
9976f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object to be pinned
9986f4e8d6eSSamuel Li  * @domain: domain to be pinned to
9996f4e8d6eSSamuel Li  *
10006f4e8d6eSSamuel Li  * A simple wrapper to amdgpu_bo_pin_restricted().
10016f4e8d6eSSamuel Li  * Provides a simpler API for buffers that do not have any strict restrictions
10026f4e8d6eSSamuel Li  * on where a buffer must be located.
10036f4e8d6eSSamuel Li  *
10042472e11bSMichel Dänzer  * Returns:
10052472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
10066f4e8d6eSSamuel Li  */
amdgpu_bo_pin(struct amdgpu_bo * bo,u32 domain)10077b7c6c81SJunwei Zhang int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain)
1008d38ceaf9SAlex Deucher {
1009eda1068dSFelix Kuehling 	bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
10107b7c6c81SJunwei Zhang 	return amdgpu_bo_pin_restricted(bo, domain, 0, 0);
1011d38ceaf9SAlex Deucher }
1012d38ceaf9SAlex Deucher 
10136f4e8d6eSSamuel Li /**
10146f4e8d6eSSamuel Li  * amdgpu_bo_unpin - unpin an &amdgpu_bo buffer object
10156f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object to be unpinned
10166f4e8d6eSSamuel Li  *
10176f4e8d6eSSamuel Li  * Decreases the pin_count, and clears the flags if pin_count reaches 0.
10186f4e8d6eSSamuel Li  * Changes placement and pin size accordingly.
10196f4e8d6eSSamuel Li  *
10202472e11bSMichel Dänzer  * Returns:
10212472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
10226f4e8d6eSSamuel Li  */
amdgpu_bo_unpin(struct amdgpu_bo * bo)10234671078eSChristian König void amdgpu_bo_unpin(struct amdgpu_bo *bo)
1024d38ceaf9SAlex Deucher {
1025e2ac8531SChristian König 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
1026e2ac8531SChristian König 
10274671078eSChristian König 	ttm_bo_unpin(&bo->tbo);
10284671078eSChristian König 	if (bo->tbo.pin_count)
10294671078eSChristian König 		return;
10306681c5ebSChristian König 
1031a448cb00SChristian König 	if (bo->tbo.base.import_attach)
1032a448cb00SChristian König 		dma_buf_unpin(bo->tbo.base.import_attach);
1033e2ac8531SChristian König 
1034d3116756SChristian König 	if (bo->tbo.resource->mem_type == TTM_PL_VRAM) {
1035e2ac8531SChristian König 		atomic64_sub(amdgpu_bo_size(bo), &adev->vram_pin_size);
1036e2ac8531SChristian König 		atomic64_sub(amdgpu_vram_mgr_bo_visible_size(bo),
1037e2ac8531SChristian König 			     &adev->visible_pin_size);
1038d3116756SChristian König 	} else if (bo->tbo.resource->mem_type == TTM_PL_TT) {
1039e2ac8531SChristian König 		atomic64_sub(amdgpu_bo_size(bo), &adev->gart_pin_size);
1040e2ac8531SChristian König 	}
1041dc3499c7SAlex Deucher 
1042d38ceaf9SAlex Deucher }
1043d38ceaf9SAlex Deucher 
10441d6ecab1SSrinivasan Shanmugam static const char * const amdgpu_vram_names[] = {
10451f8628c7SAlex Deucher 	"UNKNOWN",
10461f8628c7SAlex Deucher 	"GDDR1",
10471f8628c7SAlex Deucher 	"DDR2",
10481f8628c7SAlex Deucher 	"GDDR3",
10491f8628c7SAlex Deucher 	"GDDR4",
10501f8628c7SAlex Deucher 	"GDDR5",
10511f8628c7SAlex Deucher 	"HBM",
1052bc227cfaSTom St Denis 	"DDR3",
1053bc227cfaSTom St Denis 	"DDR4",
10545228fe30SHawking Zhang 	"GDDR6",
1055d534ca71SAlex Deucher 	"DDR5",
1056d534ca71SAlex Deucher 	"LPDDR4",
1057d534ca71SAlex Deucher 	"LPDDR5"
10581f8628c7SAlex Deucher };
10591f8628c7SAlex Deucher 
10606f4e8d6eSSamuel Li /**
10616f4e8d6eSSamuel Li  * amdgpu_bo_init - initialize memory manager
10626f4e8d6eSSamuel Li  * @adev: amdgpu device object
10636f4e8d6eSSamuel Li  *
10646f4e8d6eSSamuel Li  * Calls amdgpu_ttm_init() to initialize amdgpu memory manager.
10656f4e8d6eSSamuel Li  *
10662472e11bSMichel Dänzer  * Returns:
10672472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
10686f4e8d6eSSamuel Li  */
amdgpu_bo_init(struct amdgpu_device * adev)1069d38ceaf9SAlex Deucher int amdgpu_bo_init(struct amdgpu_device *adev)
1070d38ceaf9SAlex Deucher {
107135d5f224SOak Zeng 	/* On A+A platform, VRAM can be mapped as WB */
1072228ce176SRajneesh Bhardwaj 	if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) {
10737cf321d1SDave Airlie 		/* reserve PAT memory space to WC for VRAM */
107426db557eSNirmoy Das 		int r = arch_io_reserve_memtype_wc(adev->gmc.aper_base,
1075770d13b1SChristian König 				adev->gmc.aper_size);
10767cf321d1SDave Airlie 
107726db557eSNirmoy Das 		if (r) {
107826db557eSNirmoy Das 			DRM_ERROR("Unable to set WC memtype for the aperture base\n");
107926db557eSNirmoy Das 			return r;
108026db557eSNirmoy Das 		}
108126db557eSNirmoy Das 
1082d38ceaf9SAlex Deucher 		/* Add an MTRR for the VRAM */
1083770d13b1SChristian König 		adev->gmc.vram_mtrr = arch_phys_wc_add(adev->gmc.aper_base,
1084770d13b1SChristian König 				adev->gmc.aper_size);
108535d5f224SOak Zeng 	}
108635d5f224SOak Zeng 
1087d38ceaf9SAlex Deucher 	DRM_INFO("Detected VRAM RAM=%lluM, BAR=%lluM\n",
1088770d13b1SChristian König 		 adev->gmc.mc_vram_size >> 20,
1089770d13b1SChristian König 		 (unsigned long long)adev->gmc.aper_size >> 20);
10901f8628c7SAlex Deucher 	DRM_INFO("RAM width %dbits %s\n",
1091770d13b1SChristian König 		 adev->gmc.vram_width, amdgpu_vram_names[adev->gmc.vram_type]);
1092d38ceaf9SAlex Deucher 	return amdgpu_ttm_init(adev);
1093d38ceaf9SAlex Deucher }
1094d38ceaf9SAlex Deucher 
10956f4e8d6eSSamuel Li /**
10966f4e8d6eSSamuel Li  * amdgpu_bo_fini - tear down memory manager
10976f4e8d6eSSamuel Li  * @adev: amdgpu device object
10986f4e8d6eSSamuel Li  *
10996f4e8d6eSSamuel Li  * Reverses amdgpu_bo_init() to tear down memory manager.
11006f4e8d6eSSamuel Li  */
amdgpu_bo_fini(struct amdgpu_device * adev)1101d38ceaf9SAlex Deucher void amdgpu_bo_fini(struct amdgpu_device *adev)
1102d38ceaf9SAlex Deucher {
110362d5f9f7SLeslie Shi 	int idx;
110462d5f9f7SLeslie Shi 
1105d38ceaf9SAlex Deucher 	amdgpu_ttm_fini(adev);
110662d5f9f7SLeslie Shi 
110762d5f9f7SLeslie Shi 	if (drm_dev_enter(adev_to_drm(adev), &idx)) {
1108a0ba1279SLijo Lazar 		if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) {
110962d5f9f7SLeslie Shi 			arch_phys_wc_del(adev->gmc.vram_mtrr);
111062d5f9f7SLeslie Shi 			arch_io_free_memtype_wc(adev->gmc.aper_base, adev->gmc.aper_size);
111162d5f9f7SLeslie Shi 		}
111262d5f9f7SLeslie Shi 		drm_dev_exit(idx);
111362d5f9f7SLeslie Shi 	}
1114d38ceaf9SAlex Deucher }
1115d38ceaf9SAlex Deucher 
11166f4e8d6eSSamuel Li /**
11176f4e8d6eSSamuel Li  * amdgpu_bo_set_tiling_flags - set tiling flags
11186f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object
11196f4e8d6eSSamuel Li  * @tiling_flags: new flags
11206f4e8d6eSSamuel Li  *
11216f4e8d6eSSamuel Li  * Sets buffer object's tiling flags with the new one. Used by GEM ioctl or
11226f4e8d6eSSamuel Li  * kernel driver to set the tiling flags on a buffer.
11236f4e8d6eSSamuel Li  *
11242472e11bSMichel Dänzer  * Returns:
11252472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
11266f4e8d6eSSamuel Li  */
amdgpu_bo_set_tiling_flags(struct amdgpu_bo * bo,u64 tiling_flags)1127d38ceaf9SAlex Deucher int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags)
1128d38ceaf9SAlex Deucher {
11299079ac76SMarek Olšák 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
1130cc1bcf85SNirmoy Das 	struct amdgpu_bo_user *ubo;
11319079ac76SMarek Olšák 
1132030bb4adSNirmoy Das 	BUG_ON(bo->tbo.type == ttm_bo_type_kernel);
11339079ac76SMarek Olšák 	if (adev->family <= AMDGPU_FAMILY_CZ &&
11349079ac76SMarek Olšák 	    AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT) > 6)
1135d38ceaf9SAlex Deucher 		return -EINVAL;
1136d38ceaf9SAlex Deucher 
1137cc1bcf85SNirmoy Das 	ubo = to_amdgpu_bo_user(bo);
1138cc1bcf85SNirmoy Das 	ubo->tiling_flags = tiling_flags;
1139d38ceaf9SAlex Deucher 	return 0;
1140d38ceaf9SAlex Deucher }
1141d38ceaf9SAlex Deucher 
11426f4e8d6eSSamuel Li /**
11436f4e8d6eSSamuel Li  * amdgpu_bo_get_tiling_flags - get tiling flags
11446f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object
11456f4e8d6eSSamuel Li  * @tiling_flags: returned flags
11466f4e8d6eSSamuel Li  *
11476f4e8d6eSSamuel Li  * Gets buffer object's tiling flags. Used by GEM ioctl or kernel driver to
11486f4e8d6eSSamuel Li  * set the tiling flags on a buffer.
11496f4e8d6eSSamuel Li  */
amdgpu_bo_get_tiling_flags(struct amdgpu_bo * bo,u64 * tiling_flags)1150d38ceaf9SAlex Deucher void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags)
1151d38ceaf9SAlex Deucher {
1152cc1bcf85SNirmoy Das 	struct amdgpu_bo_user *ubo;
1153cc1bcf85SNirmoy Das 
1154030bb4adSNirmoy Das 	BUG_ON(bo->tbo.type == ttm_bo_type_kernel);
115552791eeeSChristian König 	dma_resv_assert_held(bo->tbo.base.resv);
1156cc1bcf85SNirmoy Das 	ubo = to_amdgpu_bo_user(bo);
1157d38ceaf9SAlex Deucher 
1158d38ceaf9SAlex Deucher 	if (tiling_flags)
1159cc1bcf85SNirmoy Das 		*tiling_flags = ubo->tiling_flags;
1160d38ceaf9SAlex Deucher }
1161d38ceaf9SAlex Deucher 
11626f4e8d6eSSamuel Li /**
11636f4e8d6eSSamuel Li  * amdgpu_bo_set_metadata - set metadata
11646f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object
11656f4e8d6eSSamuel Li  * @metadata: new metadata
11666f4e8d6eSSamuel Li  * @metadata_size: size of the new metadata
11676f4e8d6eSSamuel Li  * @flags: flags of the new metadata
11686f4e8d6eSSamuel Li  *
11696f4e8d6eSSamuel Li  * Sets buffer object's metadata, its size and flags.
11706f4e8d6eSSamuel Li  * Used via GEM ioctl.
11716f4e8d6eSSamuel Li  *
11722472e11bSMichel Dänzer  * Returns:
11732472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
11746f4e8d6eSSamuel Li  */
amdgpu_bo_set_metadata(struct amdgpu_bo * bo,void * metadata,u32 metadata_size,uint64_t flags)1175d38ceaf9SAlex Deucher int amdgpu_bo_set_metadata(struct amdgpu_bo *bo, void *metadata,
11761d6ecab1SSrinivasan Shanmugam 			   u32 metadata_size, uint64_t flags)
1177d38ceaf9SAlex Deucher {
1178cc1bcf85SNirmoy Das 	struct amdgpu_bo_user *ubo;
1179d38ceaf9SAlex Deucher 	void *buffer;
1180d38ceaf9SAlex Deucher 
1181030bb4adSNirmoy Das 	BUG_ON(bo->tbo.type == ttm_bo_type_kernel);
1182cc1bcf85SNirmoy Das 	ubo = to_amdgpu_bo_user(bo);
1183d38ceaf9SAlex Deucher 	if (!metadata_size) {
1184cc1bcf85SNirmoy Das 		if (ubo->metadata_size) {
1185cc1bcf85SNirmoy Das 			kfree(ubo->metadata);
1186cc1bcf85SNirmoy Das 			ubo->metadata = NULL;
1187cc1bcf85SNirmoy Das 			ubo->metadata_size = 0;
1188d38ceaf9SAlex Deucher 		}
1189d38ceaf9SAlex Deucher 		return 0;
1190d38ceaf9SAlex Deucher 	}
1191d38ceaf9SAlex Deucher 
1192d38ceaf9SAlex Deucher 	if (metadata == NULL)
1193d38ceaf9SAlex Deucher 		return -EINVAL;
1194d38ceaf9SAlex Deucher 
119571affda5SAndrzej Hajda 	buffer = kmemdup(metadata, metadata_size, GFP_KERNEL);
1196d38ceaf9SAlex Deucher 	if (buffer == NULL)
1197d38ceaf9SAlex Deucher 		return -ENOMEM;
1198d38ceaf9SAlex Deucher 
1199cc1bcf85SNirmoy Das 	kfree(ubo->metadata);
1200cc1bcf85SNirmoy Das 	ubo->metadata_flags = flags;
1201cc1bcf85SNirmoy Das 	ubo->metadata = buffer;
1202cc1bcf85SNirmoy Das 	ubo->metadata_size = metadata_size;
1203d38ceaf9SAlex Deucher 
1204d38ceaf9SAlex Deucher 	return 0;
1205d38ceaf9SAlex Deucher }
1206d38ceaf9SAlex Deucher 
12076f4e8d6eSSamuel Li /**
12086f4e8d6eSSamuel Li  * amdgpu_bo_get_metadata - get metadata
12096f4e8d6eSSamuel Li  * @bo: &amdgpu_bo buffer object
12106f4e8d6eSSamuel Li  * @buffer: returned metadata
12116f4e8d6eSSamuel Li  * @buffer_size: size of the buffer
12126f4e8d6eSSamuel Li  * @metadata_size: size of the returned metadata
12136f4e8d6eSSamuel Li  * @flags: flags of the returned metadata
12146f4e8d6eSSamuel Li  *
12156f4e8d6eSSamuel Li  * Gets buffer object's metadata, its size and flags. buffer_size shall not be
12166f4e8d6eSSamuel Li  * less than metadata_size.
12176f4e8d6eSSamuel Li  * Used via GEM ioctl.
12186f4e8d6eSSamuel Li  *
12192472e11bSMichel Dänzer  * Returns:
12202472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
12216f4e8d6eSSamuel Li  */
amdgpu_bo_get_metadata(struct amdgpu_bo * bo,void * buffer,size_t buffer_size,uint32_t * metadata_size,uint64_t * flags)1222d38ceaf9SAlex Deucher int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
1223d38ceaf9SAlex Deucher 			   size_t buffer_size, uint32_t *metadata_size,
1224d38ceaf9SAlex Deucher 			   uint64_t *flags)
1225d38ceaf9SAlex Deucher {
1226cc1bcf85SNirmoy Das 	struct amdgpu_bo_user *ubo;
1227cc1bcf85SNirmoy Das 
1228d38ceaf9SAlex Deucher 	if (!buffer && !metadata_size)
1229d38ceaf9SAlex Deucher 		return -EINVAL;
1230d38ceaf9SAlex Deucher 
1231030bb4adSNirmoy Das 	BUG_ON(bo->tbo.type == ttm_bo_type_kernel);
1232cc1bcf85SNirmoy Das 	ubo = to_amdgpu_bo_user(bo);
1233eba98523SShiwu Zhang 	if (metadata_size)
1234eba98523SShiwu Zhang 		*metadata_size = ubo->metadata_size;
1235eba98523SShiwu Zhang 
1236d38ceaf9SAlex Deucher 	if (buffer) {
1237cc1bcf85SNirmoy Das 		if (buffer_size < ubo->metadata_size)
1238d38ceaf9SAlex Deucher 			return -EINVAL;
1239d38ceaf9SAlex Deucher 
1240cc1bcf85SNirmoy Das 		if (ubo->metadata_size)
1241cc1bcf85SNirmoy Das 			memcpy(buffer, ubo->metadata, ubo->metadata_size);
1242d38ceaf9SAlex Deucher 	}
1243d38ceaf9SAlex Deucher 
1244d38ceaf9SAlex Deucher 	if (flags)
1245cc1bcf85SNirmoy Das 		*flags = ubo->metadata_flags;
1246d38ceaf9SAlex Deucher 
1247d38ceaf9SAlex Deucher 	return 0;
1248d38ceaf9SAlex Deucher }
1249d38ceaf9SAlex Deucher 
12506f4e8d6eSSamuel Li /**
12516f4e8d6eSSamuel Li  * amdgpu_bo_move_notify - notification about a memory move
12526f4e8d6eSSamuel Li  * @bo: pointer to a buffer object
12536f4e8d6eSSamuel Li  * @evict: if this move is evicting the buffer from the graphics address space
12540c7ed3edSChristian König  * @new_mem: new resource for backing the BO
12556f4e8d6eSSamuel Li  *
12566f4e8d6eSSamuel Li  * Marks the corresponding &amdgpu_bo buffer object as invalid, also performs
12576f4e8d6eSSamuel Li  * bookkeeping.
12586f4e8d6eSSamuel Li  * TTM driver callback which is called when ttm moves a buffer.
12596f4e8d6eSSamuel Li  */
amdgpu_bo_move_notify(struct ttm_buffer_object * bo,bool evict,struct ttm_resource * new_mem)12600c7ed3edSChristian König void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
12610c7ed3edSChristian König 			   bool evict,
12620c7ed3edSChristian König 			   struct ttm_resource *new_mem)
1263d38ceaf9SAlex Deucher {
1264a7d64de6SChristian König 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
12650c7ed3edSChristian König 	struct ttm_resource *old_mem = bo->resource;
1266765e7fbfSChristian König 	struct amdgpu_bo *abo;
1267d38ceaf9SAlex Deucher 
1268c704ab18SChristian König 	if (!amdgpu_bo_is_amdgpu_bo(bo))
1269d38ceaf9SAlex Deucher 		return;
1270d38ceaf9SAlex Deucher 
1271b82485fdSAndres Rodriguez 	abo = ttm_to_amdgpu_bo(bo);
12723f3333f8SChristian König 	amdgpu_vm_bo_invalidate(adev, abo, evict);
1273d38ceaf9SAlex Deucher 
12746375bbb4SChristian König 	amdgpu_bo_kunmap(abo);
12756375bbb4SChristian König 
12762d4dad27SChristian König 	if (abo->tbo.base.dma_buf && !abo->tbo.base.import_attach &&
12770c7ed3edSChristian König 	    old_mem && old_mem->mem_type != TTM_PL_SYSTEM)
12782d4dad27SChristian König 		dma_buf_move_notify(abo->tbo.base.dma_buf);
12792d4dad27SChristian König 
12800c7ed3edSChristian König 	/* move_notify is called before move happens */
12810c7ed3edSChristian König 	trace_amdgpu_bo_move(abo, new_mem ? new_mem->mem_type : -1,
12820c7ed3edSChristian König 			     old_mem ? old_mem->mem_type : -1);
1283d38ceaf9SAlex Deucher }
1284d38ceaf9SAlex Deucher 
amdgpu_bo_get_memory(struct amdgpu_bo * bo,struct amdgpu_mem_stats * stats)1285d6530c33SMarek Olšák void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
1286d6530c33SMarek Olšák 			  struct amdgpu_mem_stats *stats)
128787444254SRoy Sun {
12884c5eaf0cSChristian König 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
12894c5eaf0cSChristian König 	struct ttm_resource *res = bo->tbo.resource;
1290d6530c33SMarek Olšák 	uint64_t size = amdgpu_bo_size(bo);
1291f85a55fbSAlex Deucher 	struct drm_gem_object *obj;
1292ca0b954aSChristian König 	unsigned int domain;
1293f85a55fbSAlex Deucher 	bool shared;
1294ca0b954aSChristian König 
1295ca0b954aSChristian König 	/* Abort if the BO doesn't currently have a backing store */
12964c5eaf0cSChristian König 	if (!res)
1297ca0b954aSChristian König 		return;
129887444254SRoy Sun 
1299f85a55fbSAlex Deucher 	obj = &bo->tbo.base;
1300f85a55fbSAlex Deucher 	shared = drm_gem_object_is_shared_for_memory_stats(obj);
1301f85a55fbSAlex Deucher 
13024c5eaf0cSChristian König 	domain = amdgpu_mem_type_to_domain(res->mem_type);
130387444254SRoy Sun 	switch (domain) {
130487444254SRoy Sun 	case AMDGPU_GEM_DOMAIN_VRAM:
1305d6530c33SMarek Olšák 		stats->vram += size;
13064c5eaf0cSChristian König 		if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
1307d6530c33SMarek Olšák 			stats->visible_vram += size;
1308f85a55fbSAlex Deucher 		if (shared)
1309f85a55fbSAlex Deucher 			stats->vram_shared += size;
131087444254SRoy Sun 		break;
131187444254SRoy Sun 	case AMDGPU_GEM_DOMAIN_GTT:
1312d6530c33SMarek Olšák 		stats->gtt += size;
1313f85a55fbSAlex Deucher 		if (shared)
1314f85a55fbSAlex Deucher 			stats->gtt_shared += size;
131587444254SRoy Sun 		break;
131687444254SRoy Sun 	case AMDGPU_GEM_DOMAIN_CPU:
131787444254SRoy Sun 	default:
1318d6530c33SMarek Olšák 		stats->cpu += size;
1319f85a55fbSAlex Deucher 		if (shared)
1320f85a55fbSAlex Deucher 			stats->cpu_shared += size;
132187444254SRoy Sun 		break;
132287444254SRoy Sun 	}
1323d6530c33SMarek Olšák 
1324d6530c33SMarek Olšák 	if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) {
1325d6530c33SMarek Olšák 		stats->requested_vram += size;
1326d6530c33SMarek Olšák 		if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
1327d6530c33SMarek Olšák 			stats->requested_visible_vram += size;
1328d6530c33SMarek Olšák 
1329d6530c33SMarek Olšák 		if (domain != AMDGPU_GEM_DOMAIN_VRAM) {
1330d6530c33SMarek Olšák 			stats->evicted_vram += size;
1331d6530c33SMarek Olšák 			if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
1332d6530c33SMarek Olšák 				stats->evicted_visible_vram += size;
1333d6530c33SMarek Olšák 		}
1334d6530c33SMarek Olšák 	} else if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_GTT) {
1335d6530c33SMarek Olšák 		stats->requested_gtt += size;
1336d6530c33SMarek Olšák 	}
133787444254SRoy Sun }
133887444254SRoy Sun 
13396f4e8d6eSSamuel Li /**
1340736b1729SKevin Wang  * amdgpu_bo_release_notify - notification about a BO being released
1341ab2f7a5cSFelix Kuehling  * @bo: pointer to a buffer object
1342ab2f7a5cSFelix Kuehling  *
1343ab2f7a5cSFelix Kuehling  * Wipes VRAM buffers whose contents should not be leaked before the
1344ab2f7a5cSFelix Kuehling  * memory is released.
1345ab2f7a5cSFelix Kuehling  */
amdgpu_bo_release_notify(struct ttm_buffer_object * bo)1346ab2f7a5cSFelix Kuehling void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
1347ab2f7a5cSFelix Kuehling {
134832f90e65SGuchun Chen 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
1349ab2f7a5cSFelix Kuehling 	struct dma_fence *fence = NULL;
1350ab2f7a5cSFelix Kuehling 	struct amdgpu_bo *abo;
1351ab2f7a5cSFelix Kuehling 	int r;
1352ab2f7a5cSFelix Kuehling 
1353ab2f7a5cSFelix Kuehling 	if (!amdgpu_bo_is_amdgpu_bo(bo))
1354ab2f7a5cSFelix Kuehling 		return;
1355ab2f7a5cSFelix Kuehling 
1356ab2f7a5cSFelix Kuehling 	abo = ttm_to_amdgpu_bo(bo);
1357ab2f7a5cSFelix Kuehling 
1358ab2f7a5cSFelix Kuehling 	if (abo->kfd_bo)
13595702d052SFelix Kuehling 		amdgpu_amdkfd_release_notify(abo);
1360ab2f7a5cSFelix Kuehling 
1361f4a3c42bSxinhui pan 	/* We only remove the fence if the resv has individualized. */
13629fe58d0bSxinhui pan 	WARN_ON_ONCE(bo->type == ttm_bo_type_kernel
13639fe58d0bSxinhui pan 			&& bo->base.resv != &bo->base._resv);
1364f4a3c42bSxinhui pan 	if (bo->base.resv == &bo->base._resv)
1365f4a3c42bSxinhui pan 		amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo);
1366f4a3c42bSxinhui pan 
136763af82cfSChristian König 	if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM ||
136832f90e65SGuchun Chen 	    !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) ||
136993bb18d2Slyndonli 	    adev->in_suspend || drm_dev_is_unplugged(adev_to_drm(adev)))
1370ab2f7a5cSFelix Kuehling 		return;
1371ab2f7a5cSFelix Kuehling 
1372447c7997SRajneesh Bhardwaj 	if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv)))
1373447c7997SRajneesh Bhardwaj 		return;
1374ab2f7a5cSFelix Kuehling 
1375c3aaca43SMukul Joshi 	r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence, true);
1376ab2f7a5cSFelix Kuehling 	if (!WARN_ON(r)) {
1377ab2f7a5cSFelix Kuehling 		amdgpu_bo_fence(abo, fence, false);
1378ab2f7a5cSFelix Kuehling 		dma_fence_put(fence);
1379ab2f7a5cSFelix Kuehling 	}
1380ab2f7a5cSFelix Kuehling 
13815f680625SDave Airlie 	dma_resv_unlock(bo->base.resv);
1382ab2f7a5cSFelix Kuehling }
1383ab2f7a5cSFelix Kuehling 
1384ab2f7a5cSFelix Kuehling /**
13856f4e8d6eSSamuel Li  * amdgpu_bo_fault_reserve_notify - notification about a memory fault
13866f4e8d6eSSamuel Li  * @bo: pointer to a buffer object
13876f4e8d6eSSamuel Li  *
13886f4e8d6eSSamuel Li  * Notifies the driver we are taking a fault on this BO and have reserved it,
13896f4e8d6eSSamuel Li  * also performs bookkeeping.
13906f4e8d6eSSamuel Li  * TTM driver callback for dealing with vm faults.
13916f4e8d6eSSamuel Li  *
13922472e11bSMichel Dänzer  * Returns:
13932472e11bSMichel Dänzer  * 0 for success or a negative error code on failure.
13946f4e8d6eSSamuel Li  */
amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object * bo)1395d3ef581aSChristian König vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
1396d38ceaf9SAlex Deucher {
1397a7d64de6SChristian König 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
139819be5570SChristian König 	struct ttm_operation_ctx ctx = { false, false };
1399d3ef581aSChristian König 	struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
140096cf8271SJohn Brooks 	int r;
1401d38ceaf9SAlex Deucher 
140296cf8271SJohn Brooks 	/* Remember that this BO was accessed by the CPU */
140396cf8271SJohn Brooks 	abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
140496cf8271SJohn Brooks 
14054c5eaf0cSChristian König 	if (amdgpu_res_cpu_visible(adev, bo->resource))
14065fb1941dSChristian König 		return 0;
14075fb1941dSChristian König 
1408104ece97SMichel Dänzer 	/* Can't move a pinned BO to visible VRAM */
14094671078eSChristian König 	if (abo->tbo.pin_count > 0)
1410d3ef581aSChristian König 		return VM_FAULT_SIGBUS;
1411104ece97SMichel Dänzer 
1412d38ceaf9SAlex Deucher 	/* hurrah the memory is not visible ! */
141368e2c5ffSMarek Olšák 	atomic64_inc(&adev->num_vram_cpu_page_faults);
1414c704ab18SChristian König 	amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM |
141541d9a6a7SJohn Brooks 					AMDGPU_GEM_DOMAIN_GTT);
141641d9a6a7SJohn Brooks 
141741d9a6a7SJohn Brooks 	/* Avoid costly evictions; only set GTT as a busy placement */
141841d9a6a7SJohn Brooks 	abo->placement.num_busy_placement = 1;
141941d9a6a7SJohn Brooks 	abo->placement.busy_placement = &abo->placements[1];
142041d9a6a7SJohn Brooks 
142119be5570SChristian König 	r = ttm_bo_validate(bo, &abo->placement, &ctx);
1422d3ef581aSChristian König 	if (unlikely(r == -EBUSY || r == -ERESTARTSYS))
1423d3ef581aSChristian König 		return VM_FAULT_NOPAGE;
1424d3ef581aSChristian König 	else if (unlikely(r))
1425d3ef581aSChristian König 		return VM_FAULT_SIGBUS;
14265fb1941dSChristian König 
14275fb1941dSChristian König 	/* this should never happen */
1428d3116756SChristian König 	if (bo->resource->mem_type == TTM_PL_VRAM &&
14294c5eaf0cSChristian König 	    !amdgpu_res_cpu_visible(adev, bo->resource))
1430d3ef581aSChristian König 		return VM_FAULT_SIGBUS;
14315fb1941dSChristian König 
1432d3ef581aSChristian König 	ttm_bo_move_to_lru_tail_unlocked(bo);
1433d38ceaf9SAlex Deucher 	return 0;
1434d38ceaf9SAlex Deucher }
1435d38ceaf9SAlex Deucher 
1436d38ceaf9SAlex Deucher /**
1437d38ceaf9SAlex Deucher  * amdgpu_bo_fence - add fence to buffer object
1438d38ceaf9SAlex Deucher  *
1439d38ceaf9SAlex Deucher  * @bo: buffer object in question
1440d38ceaf9SAlex Deucher  * @fence: fence to add
1441d38ceaf9SAlex Deucher  * @shared: true if fence should be added shared
1442d38ceaf9SAlex Deucher  *
1443d38ceaf9SAlex Deucher  */
amdgpu_bo_fence(struct amdgpu_bo * bo,struct dma_fence * fence,bool shared)1444f54d1867SChris Wilson void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
1445d38ceaf9SAlex Deucher 		     bool shared)
1446d38ceaf9SAlex Deucher {
144752791eeeSChristian König 	struct dma_resv *resv = bo->tbo.base.resv;
1448c8d4c18bSChristian König 	int r;
1449c8d4c18bSChristian König 
1450c8d4c18bSChristian König 	r = dma_resv_reserve_fences(resv, 1);
1451c8d4c18bSChristian König 	if (r) {
1452c8d4c18bSChristian König 		/* As last resort on OOM we block for the fence */
1453c8d4c18bSChristian König 		dma_fence_wait(fence, false);
1454c8d4c18bSChristian König 		return;
1455c8d4c18bSChristian König 	}
1456d38ceaf9SAlex Deucher 
145773511edfSChristian König 	dma_resv_add_fence(resv, fence, shared ? DMA_RESV_USAGE_READ :
145873511edfSChristian König 			   DMA_RESV_USAGE_WRITE);
1459d38ceaf9SAlex Deucher }
1460cdb7e8f2SChristian König 
1461cdb7e8f2SChristian König /**
14629f3cc18dSChristian König  * amdgpu_bo_sync_wait_resv - Wait for BO reservation fences
1463e8e32426SFelix Kuehling  *
14649f3cc18dSChristian König  * @adev: amdgpu device pointer
14659f3cc18dSChristian König  * @resv: reservation object to sync to
14669f3cc18dSChristian König  * @sync_mode: synchronization mode
1467e8e32426SFelix Kuehling  * @owner: fence owner
1468e8e32426SFelix Kuehling  * @intr: Whether the wait is interruptible
1469e8e32426SFelix Kuehling  *
14709f3cc18dSChristian König  * Extract the fences from the reservation object and waits for them to finish.
14719f3cc18dSChristian König  *
14729f3cc18dSChristian König  * Returns:
14739f3cc18dSChristian König  * 0 on success, errno otherwise.
14749f3cc18dSChristian König  */
amdgpu_bo_sync_wait_resv(struct amdgpu_device * adev,struct dma_resv * resv,enum amdgpu_sync_mode sync_mode,void * owner,bool intr)14759f3cc18dSChristian König int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv,
14769f3cc18dSChristian König 			     enum amdgpu_sync_mode sync_mode, void *owner,
14779f3cc18dSChristian König 			     bool intr)
14789f3cc18dSChristian König {
14799f3cc18dSChristian König 	struct amdgpu_sync sync;
14809f3cc18dSChristian König 	int r;
14819f3cc18dSChristian König 
14829f3cc18dSChristian König 	amdgpu_sync_create(&sync);
14839f3cc18dSChristian König 	amdgpu_sync_resv(adev, &sync, resv, sync_mode, owner);
14849f3cc18dSChristian König 	r = amdgpu_sync_wait(&sync, intr);
14859f3cc18dSChristian König 	amdgpu_sync_free(&sync);
14869f3cc18dSChristian König 	return r;
14879f3cc18dSChristian König }
14889f3cc18dSChristian König 
14899f3cc18dSChristian König /**
14909f3cc18dSChristian König  * amdgpu_bo_sync_wait - Wrapper for amdgpu_bo_sync_wait_resv
14919f3cc18dSChristian König  * @bo: buffer object to wait for
14929f3cc18dSChristian König  * @owner: fence owner
14939f3cc18dSChristian König  * @intr: Whether the wait is interruptible
14949f3cc18dSChristian König  *
14959f3cc18dSChristian König  * Wrapper to wait for fences in a BO.
1496e8e32426SFelix Kuehling  * Returns:
1497e8e32426SFelix Kuehling  * 0 on success, errno otherwise.
1498e8e32426SFelix Kuehling  */
amdgpu_bo_sync_wait(struct amdgpu_bo * bo,void * owner,bool intr)1499e8e32426SFelix Kuehling int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr)
1500e8e32426SFelix Kuehling {
1501e8e32426SFelix Kuehling 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
1502e8e32426SFelix Kuehling 
15039f3cc18dSChristian König 	return amdgpu_bo_sync_wait_resv(adev, bo->tbo.base.resv,
15049f3cc18dSChristian König 					AMDGPU_SYNC_NE_OWNER, owner, intr);
1505e8e32426SFelix Kuehling }
1506e8e32426SFelix Kuehling 
1507e8e32426SFelix Kuehling /**
1508cdb7e8f2SChristian König  * amdgpu_bo_gpu_offset - return GPU offset of bo
1509cdb7e8f2SChristian König  * @bo:	amdgpu object for which we query the offset
1510cdb7e8f2SChristian König  *
1511cdb7e8f2SChristian König  * Note: object should either be pinned or reserved when calling this
1512cdb7e8f2SChristian König  * function, it might be useful to add check for this for debugging.
15132472e11bSMichel Dänzer  *
15142472e11bSMichel Dänzer  * Returns:
15152472e11bSMichel Dänzer  * current GPU offset of the object.
1516cdb7e8f2SChristian König  */
amdgpu_bo_gpu_offset(struct amdgpu_bo * bo)1517cdb7e8f2SChristian König u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
1518cdb7e8f2SChristian König {
1519d3116756SChristian König 	WARN_ON_ONCE(bo->tbo.resource->mem_type == TTM_PL_SYSTEM);
152052791eeeSChristian König 	WARN_ON_ONCE(!dma_resv_is_locked(bo->tbo.base.resv) &&
15214671078eSChristian König 		     !bo->tbo.pin_count && bo->tbo.type != ttm_bo_type_kernel);
1522d3116756SChristian König 	WARN_ON_ONCE(bo->tbo.resource->start == AMDGPU_BO_INVALID_OFFSET);
1523d3116756SChristian König 	WARN_ON_ONCE(bo->tbo.resource->mem_type == TTM_PL_VRAM &&
152403f48dd5SChristian König 		     !(bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS));
1525cdb7e8f2SChristian König 
1526b1a8ef95SNirmoy Das 	return amdgpu_bo_gpu_offset_no_check(bo);
1527b1a8ef95SNirmoy Das }
1528b1a8ef95SNirmoy Das 
1529b1a8ef95SNirmoy Das /**
1530b1a8ef95SNirmoy Das  * amdgpu_bo_gpu_offset_no_check - return GPU offset of bo
1531b1a8ef95SNirmoy Das  * @bo:	amdgpu object for which we query the offset
1532b1a8ef95SNirmoy Das  *
1533b1a8ef95SNirmoy Das  * Returns:
1534b1a8ef95SNirmoy Das  * current GPU offset of the object without raising warnings.
1535b1a8ef95SNirmoy Das  */
amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo * bo)1536b1a8ef95SNirmoy Das u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo)
1537b1a8ef95SNirmoy Das {
1538b1a8ef95SNirmoy Das 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
1539b1a8ef95SNirmoy Das 	uint64_t offset;
1540b1a8ef95SNirmoy Das 
1541d3116756SChristian König 	offset = (bo->tbo.resource->start << PAGE_SHIFT) +
1542d3116756SChristian König 		 amdgpu_ttm_domain_start(adev, bo->tbo.resource->mem_type);
1543b1a8ef95SNirmoy Das 
1544b1a8ef95SNirmoy Das 	return amdgpu_gmc_sign_extend(offset);
1545cdb7e8f2SChristian König }
154684b74608SDeepak Sharma 
15472472e11bSMichel Dänzer /**
1548d035f84dSYifan Zhang  * amdgpu_bo_get_preferred_domain - get preferred domain
15492472e11bSMichel Dänzer  * @adev: amdgpu device object
15502472e11bSMichel Dänzer  * @domain: allowed :ref:`memory domains <amdgpu_memory_domains>`
15512472e11bSMichel Dänzer  *
15522472e11bSMichel Dänzer  * Returns:
1553d035f84dSYifan Zhang  * Which of the allowed domains is preferred for allocating the BO.
15542472e11bSMichel Dänzer  */
amdgpu_bo_get_preferred_domain(struct amdgpu_device * adev,uint32_t domain)1555d035f84dSYifan Zhang uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev,
155684b74608SDeepak Sharma 					    uint32_t domain)
155784b74608SDeepak Sharma {
155881d0bcf9SAlex Deucher 	if ((domain == (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) &&
155981d0bcf9SAlex Deucher 	    ((adev->asic_type == CHIP_CARRIZO) || (adev->asic_type == CHIP_STONEY))) {
156084b74608SDeepak Sharma 		domain = AMDGPU_GEM_DOMAIN_VRAM;
156184b74608SDeepak Sharma 		if (adev->gmc.real_vram_size <= AMDGPU_SG_THRESHOLD)
156284b74608SDeepak Sharma 			domain = AMDGPU_GEM_DOMAIN_GTT;
156384b74608SDeepak Sharma 	}
156484b74608SDeepak Sharma 	return domain;
156584b74608SDeepak Sharma }
1566ff72bc40SMihir Bhogilal Patel 
1567ff72bc40SMihir Bhogilal Patel #if defined(CONFIG_DEBUG_FS)
1568ff72bc40SMihir Bhogilal Patel #define amdgpu_bo_print_flag(m, bo, flag)		        \
1569ff72bc40SMihir Bhogilal Patel 	do {							\
1570ff72bc40SMihir Bhogilal Patel 		if (bo->flags & (AMDGPU_GEM_CREATE_ ## flag)) {	\
1571ff72bc40SMihir Bhogilal Patel 			seq_printf((m), " " #flag);		\
1572ff72bc40SMihir Bhogilal Patel 		}						\
1573ff72bc40SMihir Bhogilal Patel 	} while (0)
1574ff72bc40SMihir Bhogilal Patel 
1575ff72bc40SMihir Bhogilal Patel /**
157625dd7a44SMauro Carvalho Chehab  * amdgpu_bo_print_info - print BO info in debugfs file
1577ff72bc40SMihir Bhogilal Patel  *
1578ff72bc40SMihir Bhogilal Patel  * @id: Index or Id of the BO
1579ff72bc40SMihir Bhogilal Patel  * @bo: Requested BO for printing info
1580ff72bc40SMihir Bhogilal Patel  * @m: debugfs file
1581ff72bc40SMihir Bhogilal Patel  *
1582ff72bc40SMihir Bhogilal Patel  * Print BO information in debugfs file
1583ff72bc40SMihir Bhogilal Patel  *
1584ff72bc40SMihir Bhogilal Patel  * Returns:
1585ff72bc40SMihir Bhogilal Patel  * Size of the BO in bytes.
1586ff72bc40SMihir Bhogilal Patel  */
amdgpu_bo_print_info(int id,struct amdgpu_bo * bo,struct seq_file * m)1587ff72bc40SMihir Bhogilal Patel u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
1588ff72bc40SMihir Bhogilal Patel {
15894c5eaf0cSChristian König 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
1590ff72bc40SMihir Bhogilal Patel 	struct dma_buf_attachment *attachment;
1591ff72bc40SMihir Bhogilal Patel 	struct dma_buf *dma_buf;
1592ff72bc40SMihir Bhogilal Patel 	const char *placement;
1593ff72bc40SMihir Bhogilal Patel 	unsigned int pin_count;
1594ff72bc40SMihir Bhogilal Patel 	u64 size;
1595ff72bc40SMihir Bhogilal Patel 
1596818c158fSPierre-Eric Pelloux-Prayer 	if (dma_resv_trylock(bo->tbo.base.resv)) {
1597818c158fSPierre-Eric Pelloux-Prayer 		unsigned int domain;
15984c5eaf0cSChristian König 
1599d3116756SChristian König 		domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
1600ff72bc40SMihir Bhogilal Patel 		switch (domain) {
1601ff72bc40SMihir Bhogilal Patel 		case AMDGPU_GEM_DOMAIN_VRAM:
16024c5eaf0cSChristian König 			if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
1603818c158fSPierre-Eric Pelloux-Prayer 				placement = "VRAM VISIBLE";
1604818c158fSPierre-Eric Pelloux-Prayer 			else
1605ff72bc40SMihir Bhogilal Patel 				placement = "VRAM";
1606ff72bc40SMihir Bhogilal Patel 			break;
1607ff72bc40SMihir Bhogilal Patel 		case AMDGPU_GEM_DOMAIN_GTT:
1608ff72bc40SMihir Bhogilal Patel 			placement = "GTT";
1609ff72bc40SMihir Bhogilal Patel 			break;
1610ff72bc40SMihir Bhogilal Patel 		case AMDGPU_GEM_DOMAIN_CPU:
1611ff72bc40SMihir Bhogilal Patel 		default:
1612ff72bc40SMihir Bhogilal Patel 			placement = "CPU";
1613ff72bc40SMihir Bhogilal Patel 			break;
1614ff72bc40SMihir Bhogilal Patel 		}
1615818c158fSPierre-Eric Pelloux-Prayer 		dma_resv_unlock(bo->tbo.base.resv);
1616818c158fSPierre-Eric Pelloux-Prayer 	} else {
1617818c158fSPierre-Eric Pelloux-Prayer 		placement = "UNKNOWN";
1618818c158fSPierre-Eric Pelloux-Prayer 	}
1619ff72bc40SMihir Bhogilal Patel 
1620ff72bc40SMihir Bhogilal Patel 	size = amdgpu_bo_size(bo);
1621ff72bc40SMihir Bhogilal Patel 	seq_printf(m, "\t\t0x%08x: %12lld byte %s",
1622ff72bc40SMihir Bhogilal Patel 			id, size, placement);
1623ff72bc40SMihir Bhogilal Patel 
16245b8c5969SDave Airlie 	pin_count = READ_ONCE(bo->tbo.pin_count);
1625ff72bc40SMihir Bhogilal Patel 	if (pin_count)
1626ff72bc40SMihir Bhogilal Patel 		seq_printf(m, " pin count %d", pin_count);
1627ff72bc40SMihir Bhogilal Patel 
1628ff72bc40SMihir Bhogilal Patel 	dma_buf = READ_ONCE(bo->tbo.base.dma_buf);
1629ff72bc40SMihir Bhogilal Patel 	attachment = READ_ONCE(bo->tbo.base.import_attach);
1630ff72bc40SMihir Bhogilal Patel 
1631ff72bc40SMihir Bhogilal Patel 	if (attachment)
163226fd808bSPierre-Eric Pelloux-Prayer 		seq_printf(m, " imported from ino:%lu", file_inode(dma_buf->file)->i_ino);
1633ff72bc40SMihir Bhogilal Patel 	else if (dma_buf)
163426fd808bSPierre-Eric Pelloux-Prayer 		seq_printf(m, " exported as ino:%lu", file_inode(dma_buf->file)->i_ino);
1635ff72bc40SMihir Bhogilal Patel 
1636ff72bc40SMihir Bhogilal Patel 	amdgpu_bo_print_flag(m, bo, CPU_ACCESS_REQUIRED);
1637ff72bc40SMihir Bhogilal Patel 	amdgpu_bo_print_flag(m, bo, NO_CPU_ACCESS);
1638ff72bc40SMihir Bhogilal Patel 	amdgpu_bo_print_flag(m, bo, CPU_GTT_USWC);
1639ff72bc40SMihir Bhogilal Patel 	amdgpu_bo_print_flag(m, bo, VRAM_CLEARED);
1640ff72bc40SMihir Bhogilal Patel 	amdgpu_bo_print_flag(m, bo, VRAM_CONTIGUOUS);
1641ff72bc40SMihir Bhogilal Patel 	amdgpu_bo_print_flag(m, bo, VM_ALWAYS_VALID);
1642ff72bc40SMihir Bhogilal Patel 	amdgpu_bo_print_flag(m, bo, EXPLICIT_SYNC);
1643ff72bc40SMihir Bhogilal Patel 
1644ff72bc40SMihir Bhogilal Patel 	seq_puts(m, "\n");
1645ff72bc40SMihir Bhogilal Patel 
1646ff72bc40SMihir Bhogilal Patel 	return size;
1647ff72bc40SMihir Bhogilal Patel }
1648ff72bc40SMihir Bhogilal Patel #endif
1649