1d722e3fbSopenharmony_ci/**************************************************************************
2d722e3fbSopenharmony_ci *
3d722e3fbSopenharmony_ci * Copyright � 2007 Red Hat Inc.
4d722e3fbSopenharmony_ci * Copyright � 2007-2012 Intel Corporation
5d722e3fbSopenharmony_ci * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
6d722e3fbSopenharmony_ci * All Rights Reserved.
7d722e3fbSopenharmony_ci *
8d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
9d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the
10d722e3fbSopenharmony_ci * "Software"), to deal in the Software without restriction, including
11d722e3fbSopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
12d722e3fbSopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
13d722e3fbSopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
14d722e3fbSopenharmony_ci * the following conditions:
15d722e3fbSopenharmony_ci *
16d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19d722e3fbSopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
20d722e3fbSopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21d722e3fbSopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22d722e3fbSopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
23d722e3fbSopenharmony_ci *
24d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the
25d722e3fbSopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
26d722e3fbSopenharmony_ci * of the Software.
27d722e3fbSopenharmony_ci *
28d722e3fbSopenharmony_ci *
29d722e3fbSopenharmony_ci **************************************************************************/
30d722e3fbSopenharmony_ci/*
31d722e3fbSopenharmony_ci * Authors: Thomas Hellstr�m <thomas-at-tungstengraphics-dot-com>
32d722e3fbSopenharmony_ci *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
33d722e3fbSopenharmony_ci *	    Eric Anholt <eric@anholt.net>
34d722e3fbSopenharmony_ci *	    Dave Airlie <airlied@linux.ie>
35d722e3fbSopenharmony_ci */
36d722e3fbSopenharmony_ci
37d722e3fbSopenharmony_ci#include <xf86drm.h>
38d722e3fbSopenharmony_ci#include <xf86atomic.h>
39d722e3fbSopenharmony_ci#include <fcntl.h>
40d722e3fbSopenharmony_ci#include <stdio.h>
41d722e3fbSopenharmony_ci#include <stdlib.h>
42d722e3fbSopenharmony_ci#include <string.h>
43d722e3fbSopenharmony_ci#include <unistd.h>
44d722e3fbSopenharmony_ci#include <assert.h>
45d722e3fbSopenharmony_ci#include <pthread.h>
46d722e3fbSopenharmony_ci#include <sys/ioctl.h>
47d722e3fbSopenharmony_ci#include <sys/stat.h>
48d722e3fbSopenharmony_ci#include <sys/types.h>
49d722e3fbSopenharmony_ci#include <stdbool.h>
50d722e3fbSopenharmony_ci
51d722e3fbSopenharmony_ci#include "errno.h"
52d722e3fbSopenharmony_ci#ifndef ETIME
53d722e3fbSopenharmony_ci#define ETIME ETIMEDOUT
54d722e3fbSopenharmony_ci#endif
55d722e3fbSopenharmony_ci#include "libdrm_macros.h"
56d722e3fbSopenharmony_ci#include "libdrm_lists.h"
57d722e3fbSopenharmony_ci#include "intel_bufmgr.h"
58d722e3fbSopenharmony_ci#include "intel_bufmgr_priv.h"
59d722e3fbSopenharmony_ci#include "intel_chipset.h"
60d722e3fbSopenharmony_ci#include "string.h"
61d722e3fbSopenharmony_ci
62d722e3fbSopenharmony_ci#include "i915_drm.h"
63d722e3fbSopenharmony_ci#include "uthash.h"
64d722e3fbSopenharmony_ci
65d722e3fbSopenharmony_ci#if HAVE_VALGRIND
66d722e3fbSopenharmony_ci#include <valgrind.h>
67d722e3fbSopenharmony_ci#include <memcheck.h>
68d722e3fbSopenharmony_ci#define VG(x) x
69d722e3fbSopenharmony_ci#else
70d722e3fbSopenharmony_ci#define VG(x)
71d722e3fbSopenharmony_ci#endif
72d722e3fbSopenharmony_ci
73d722e3fbSopenharmony_ci#define memclear(s) memset(&s, 0, sizeof(s))
74d722e3fbSopenharmony_ci
75d722e3fbSopenharmony_ci#define DBG(...) do {					\
76d722e3fbSopenharmony_ci	if (bufmgr_gem->bufmgr.debug)			\
77d722e3fbSopenharmony_ci		fprintf(stderr, __VA_ARGS__);		\
78d722e3fbSopenharmony_ci} while (0)
79d722e3fbSopenharmony_ci
80d722e3fbSopenharmony_ci#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
81d722e3fbSopenharmony_ci#define MAX2(A, B) ((A) > (B) ? (A) : (B))
82d722e3fbSopenharmony_ci
83d722e3fbSopenharmony_ci/**
84d722e3fbSopenharmony_ci * upper_32_bits - return bits 32-63 of a number
85d722e3fbSopenharmony_ci * @n: the number we're accessing
86d722e3fbSopenharmony_ci *
87d722e3fbSopenharmony_ci * A basic shift-right of a 64- or 32-bit quantity.  Use this to suppress
88d722e3fbSopenharmony_ci * the "right shift count >= width of type" warning when that quantity is
89d722e3fbSopenharmony_ci * 32-bits.
90d722e3fbSopenharmony_ci */
91d722e3fbSopenharmony_ci#define upper_32_bits(n) ((__u32)(((n) >> 16) >> 16))
92d722e3fbSopenharmony_ci
93d722e3fbSopenharmony_ci/**
94d722e3fbSopenharmony_ci * lower_32_bits - return bits 0-31 of a number
95d722e3fbSopenharmony_ci * @n: the number we're accessing
96d722e3fbSopenharmony_ci */
97d722e3fbSopenharmony_ci#define lower_32_bits(n) ((__u32)(n))
98d722e3fbSopenharmony_ci
99d722e3fbSopenharmony_citypedef struct _drm_intel_bo_gem drm_intel_bo_gem;
100d722e3fbSopenharmony_ci
101d722e3fbSopenharmony_cistruct drm_intel_gem_bo_bucket {
102d722e3fbSopenharmony_ci	drmMMListHead head;
103d722e3fbSopenharmony_ci	unsigned long size;
104d722e3fbSopenharmony_ci};
105d722e3fbSopenharmony_ci
106d722e3fbSopenharmony_citypedef struct _drm_intel_bufmgr_gem {
107d722e3fbSopenharmony_ci	drm_intel_bufmgr bufmgr;
108d722e3fbSopenharmony_ci
109d722e3fbSopenharmony_ci	atomic_t refcount;
110d722e3fbSopenharmony_ci
111d722e3fbSopenharmony_ci	int fd;
112d722e3fbSopenharmony_ci
113d722e3fbSopenharmony_ci	int max_relocs;
114d722e3fbSopenharmony_ci
115d722e3fbSopenharmony_ci	pthread_mutex_t lock;
116d722e3fbSopenharmony_ci
117d722e3fbSopenharmony_ci	struct drm_i915_gem_exec_object2 *exec2_objects;
118d722e3fbSopenharmony_ci	drm_intel_bo **exec_bos;
119d722e3fbSopenharmony_ci	int exec_size;
120d722e3fbSopenharmony_ci	int exec_count;
121d722e3fbSopenharmony_ci
122d722e3fbSopenharmony_ci	/** Array of lists of cached gem objects of power-of-two sizes */
123d722e3fbSopenharmony_ci	struct drm_intel_gem_bo_bucket cache_bucket[14 * 4];
124d722e3fbSopenharmony_ci	int num_buckets;
125d722e3fbSopenharmony_ci	time_t time;
126d722e3fbSopenharmony_ci
127d722e3fbSopenharmony_ci	drmMMListHead managers;
128d722e3fbSopenharmony_ci
129d722e3fbSopenharmony_ci	drm_intel_bo_gem *name_table;
130d722e3fbSopenharmony_ci	drm_intel_bo_gem *handle_table;
131d722e3fbSopenharmony_ci
132d722e3fbSopenharmony_ci	drmMMListHead vma_cache;
133d722e3fbSopenharmony_ci	int vma_count, vma_open, vma_max;
134d722e3fbSopenharmony_ci
135d722e3fbSopenharmony_ci	uint64_t gtt_size;
136d722e3fbSopenharmony_ci	int available_fences;
137d722e3fbSopenharmony_ci	int pci_device;
138d722e3fbSopenharmony_ci	int gen;
139d722e3fbSopenharmony_ci	unsigned int has_bsd : 1;
140d722e3fbSopenharmony_ci	unsigned int has_blt : 1;
141d722e3fbSopenharmony_ci	unsigned int has_relaxed_fencing : 1;
142d722e3fbSopenharmony_ci	unsigned int has_llc : 1;
143d722e3fbSopenharmony_ci	unsigned int has_wait_timeout : 1;
144d722e3fbSopenharmony_ci	unsigned int bo_reuse : 1;
145d722e3fbSopenharmony_ci	unsigned int no_exec : 1;
146d722e3fbSopenharmony_ci	unsigned int has_vebox : 1;
147d722e3fbSopenharmony_ci	unsigned int has_exec_async : 1;
148d722e3fbSopenharmony_ci	bool fenced_relocs;
149d722e3fbSopenharmony_ci
150d722e3fbSopenharmony_ci	struct {
151d722e3fbSopenharmony_ci		void *ptr;
152d722e3fbSopenharmony_ci		uint32_t handle;
153d722e3fbSopenharmony_ci	} userptr_active;
154d722e3fbSopenharmony_ci
155d722e3fbSopenharmony_ci} drm_intel_bufmgr_gem;
156d722e3fbSopenharmony_ci
157d722e3fbSopenharmony_ci#define DRM_INTEL_RELOC_FENCE (1<<0)
158d722e3fbSopenharmony_ci
159d722e3fbSopenharmony_citypedef struct _drm_intel_reloc_target_info {
160d722e3fbSopenharmony_ci	drm_intel_bo *bo;
161d722e3fbSopenharmony_ci	int flags;
162d722e3fbSopenharmony_ci} drm_intel_reloc_target;
163d722e3fbSopenharmony_ci
164d722e3fbSopenharmony_cistruct _drm_intel_bo_gem {
165d722e3fbSopenharmony_ci	drm_intel_bo bo;
166d722e3fbSopenharmony_ci
167d722e3fbSopenharmony_ci	atomic_t refcount;
168d722e3fbSopenharmony_ci	uint32_t gem_handle;
169d722e3fbSopenharmony_ci	const char *name;
170d722e3fbSopenharmony_ci
171d722e3fbSopenharmony_ci	/**
172d722e3fbSopenharmony_ci	 * Kenel-assigned global name for this object
173d722e3fbSopenharmony_ci         *
174d722e3fbSopenharmony_ci         * List contains both flink named and prime fd'd objects
175d722e3fbSopenharmony_ci	 */
176d722e3fbSopenharmony_ci	unsigned int global_name;
177d722e3fbSopenharmony_ci
178d722e3fbSopenharmony_ci	UT_hash_handle handle_hh;
179d722e3fbSopenharmony_ci	UT_hash_handle name_hh;
180d722e3fbSopenharmony_ci
181d722e3fbSopenharmony_ci	/**
182d722e3fbSopenharmony_ci	 * Index of the buffer within the validation list while preparing a
183d722e3fbSopenharmony_ci	 * batchbuffer execution.
184d722e3fbSopenharmony_ci	 */
185d722e3fbSopenharmony_ci	int validate_index;
186d722e3fbSopenharmony_ci
187d722e3fbSopenharmony_ci	/**
188d722e3fbSopenharmony_ci	 * Current tiling mode
189d722e3fbSopenharmony_ci	 */
190d722e3fbSopenharmony_ci	uint32_t tiling_mode;
191d722e3fbSopenharmony_ci	uint32_t swizzle_mode;
192d722e3fbSopenharmony_ci	unsigned long stride;
193d722e3fbSopenharmony_ci
194d722e3fbSopenharmony_ci	unsigned long kflags;
195d722e3fbSopenharmony_ci
196d722e3fbSopenharmony_ci	time_t free_time;
197d722e3fbSopenharmony_ci
198d722e3fbSopenharmony_ci	/** Array passed to the DRM containing relocation information. */
199d722e3fbSopenharmony_ci	struct drm_i915_gem_relocation_entry *relocs;
200d722e3fbSopenharmony_ci	/**
201d722e3fbSopenharmony_ci	 * Array of info structs corresponding to relocs[i].target_handle etc
202d722e3fbSopenharmony_ci	 */
203d722e3fbSopenharmony_ci	drm_intel_reloc_target *reloc_target_info;
204d722e3fbSopenharmony_ci	/** Number of entries in relocs */
205d722e3fbSopenharmony_ci	int reloc_count;
206d722e3fbSopenharmony_ci	/** Array of BOs that are referenced by this buffer and will be softpinned */
207d722e3fbSopenharmony_ci	drm_intel_bo **softpin_target;
208d722e3fbSopenharmony_ci	/** Number softpinned BOs that are referenced by this buffer */
209d722e3fbSopenharmony_ci	int softpin_target_count;
210d722e3fbSopenharmony_ci	/** Maximum amount of softpinned BOs that are referenced by this buffer */
211d722e3fbSopenharmony_ci	int softpin_target_size;
212d722e3fbSopenharmony_ci
213d722e3fbSopenharmony_ci	/** Mapped address for the buffer, saved across map/unmap cycles */
214d722e3fbSopenharmony_ci	void *mem_virtual;
215d722e3fbSopenharmony_ci	/** GTT virtual address for the buffer, saved across map/unmap cycles */
216d722e3fbSopenharmony_ci	void *gtt_virtual;
217d722e3fbSopenharmony_ci	/** WC CPU address for the buffer, saved across map/unmap cycles */
218d722e3fbSopenharmony_ci	void *wc_virtual;
219d722e3fbSopenharmony_ci	/**
220d722e3fbSopenharmony_ci	 * Virtual address of the buffer allocated by user, used for userptr
221d722e3fbSopenharmony_ci	 * objects only.
222d722e3fbSopenharmony_ci	 */
223d722e3fbSopenharmony_ci	void *user_virtual;
224d722e3fbSopenharmony_ci	int map_count;
225d722e3fbSopenharmony_ci	drmMMListHead vma_list;
226d722e3fbSopenharmony_ci
227d722e3fbSopenharmony_ci	/** BO cache list */
228d722e3fbSopenharmony_ci	drmMMListHead head;
229d722e3fbSopenharmony_ci
230d722e3fbSopenharmony_ci	/**
231d722e3fbSopenharmony_ci	 * Boolean of whether this BO and its children have been included in
232d722e3fbSopenharmony_ci	 * the current drm_intel_bufmgr_check_aperture_space() total.
233d722e3fbSopenharmony_ci	 */
234d722e3fbSopenharmony_ci	bool included_in_check_aperture;
235d722e3fbSopenharmony_ci
236d722e3fbSopenharmony_ci	/**
237d722e3fbSopenharmony_ci	 * Boolean of whether this buffer has been used as a relocation
238d722e3fbSopenharmony_ci	 * target and had its size accounted for, and thus can't have any
239d722e3fbSopenharmony_ci	 * further relocations added to it.
240d722e3fbSopenharmony_ci	 */
241d722e3fbSopenharmony_ci	bool used_as_reloc_target;
242d722e3fbSopenharmony_ci
243d722e3fbSopenharmony_ci	/**
244d722e3fbSopenharmony_ci	 * Boolean of whether we have encountered an error whilst building the relocation tree.
245d722e3fbSopenharmony_ci	 */
246d722e3fbSopenharmony_ci	bool has_error;
247d722e3fbSopenharmony_ci
248d722e3fbSopenharmony_ci	/**
249d722e3fbSopenharmony_ci	 * Boolean of whether this buffer can be re-used
250d722e3fbSopenharmony_ci	 */
251d722e3fbSopenharmony_ci	bool reusable;
252d722e3fbSopenharmony_ci
253d722e3fbSopenharmony_ci	/**
254d722e3fbSopenharmony_ci	 * Boolean of whether the GPU is definitely not accessing the buffer.
255d722e3fbSopenharmony_ci	 *
256d722e3fbSopenharmony_ci	 * This is only valid when reusable, since non-reusable
257d722e3fbSopenharmony_ci	 * buffers are those that have been shared with other
258d722e3fbSopenharmony_ci	 * processes, so we don't know their state.
259d722e3fbSopenharmony_ci	 */
260d722e3fbSopenharmony_ci	bool idle;
261d722e3fbSopenharmony_ci
262d722e3fbSopenharmony_ci	/**
263d722e3fbSopenharmony_ci	 * Boolean of whether this buffer was allocated with userptr
264d722e3fbSopenharmony_ci	 */
265d722e3fbSopenharmony_ci	bool is_userptr;
266d722e3fbSopenharmony_ci
267d722e3fbSopenharmony_ci	/**
268d722e3fbSopenharmony_ci	 * Size in bytes of this buffer and its relocation descendents.
269d722e3fbSopenharmony_ci	 *
270d722e3fbSopenharmony_ci	 * Used to avoid costly tree walking in
271d722e3fbSopenharmony_ci	 * drm_intel_bufmgr_check_aperture in the common case.
272d722e3fbSopenharmony_ci	 */
273d722e3fbSopenharmony_ci	int reloc_tree_size;
274d722e3fbSopenharmony_ci
275d722e3fbSopenharmony_ci	/**
276d722e3fbSopenharmony_ci	 * Number of potential fence registers required by this buffer and its
277d722e3fbSopenharmony_ci	 * relocations.
278d722e3fbSopenharmony_ci	 */
279d722e3fbSopenharmony_ci	int reloc_tree_fences;
280d722e3fbSopenharmony_ci
281d722e3fbSopenharmony_ci	/** Flags that we may need to do the SW_FINISH ioctl on unmap. */
282d722e3fbSopenharmony_ci	bool mapped_cpu_write;
283d722e3fbSopenharmony_ci};
284d722e3fbSopenharmony_ci
285d722e3fbSopenharmony_cistatic unsigned int
286d722e3fbSopenharmony_cidrm_intel_gem_estimate_batch_space(drm_intel_bo ** bo_array, int count);
287d722e3fbSopenharmony_ci
288d722e3fbSopenharmony_cistatic unsigned int
289d722e3fbSopenharmony_cidrm_intel_gem_compute_batch_space(drm_intel_bo ** bo_array, int count);
290d722e3fbSopenharmony_ci
291d722e3fbSopenharmony_cistatic int
292d722e3fbSopenharmony_cidrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
293d722e3fbSopenharmony_ci			    uint32_t * swizzle_mode);
294d722e3fbSopenharmony_ci
295d722e3fbSopenharmony_cistatic int
296d722e3fbSopenharmony_cidrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo,
297d722e3fbSopenharmony_ci				     uint32_t tiling_mode,
298d722e3fbSopenharmony_ci				     uint32_t stride);
299d722e3fbSopenharmony_ci
300d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo,
301d722e3fbSopenharmony_ci						      time_t time);
302d722e3fbSopenharmony_ci
303d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo);
304d722e3fbSopenharmony_ci
305d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_free(drm_intel_bo *bo);
306d722e3fbSopenharmony_ci
307d722e3fbSopenharmony_cistatic inline drm_intel_bo_gem *to_bo_gem(drm_intel_bo *bo)
308d722e3fbSopenharmony_ci{
309d722e3fbSopenharmony_ci        return (drm_intel_bo_gem *)bo;
310d722e3fbSopenharmony_ci}
311d722e3fbSopenharmony_ci
312d722e3fbSopenharmony_cistatic unsigned long
313d722e3fbSopenharmony_cidrm_intel_gem_bo_tile_size(drm_intel_bufmgr_gem *bufmgr_gem, unsigned long size,
314d722e3fbSopenharmony_ci			   uint32_t *tiling_mode)
315d722e3fbSopenharmony_ci{
316d722e3fbSopenharmony_ci	unsigned long min_size, max_size;
317d722e3fbSopenharmony_ci	unsigned long i;
318d722e3fbSopenharmony_ci
319d722e3fbSopenharmony_ci	if (*tiling_mode == I915_TILING_NONE)
320d722e3fbSopenharmony_ci		return size;
321d722e3fbSopenharmony_ci
322d722e3fbSopenharmony_ci	/* 965+ just need multiples of page size for tiling */
323d722e3fbSopenharmony_ci	if (bufmgr_gem->gen >= 4)
324d722e3fbSopenharmony_ci		return ROUND_UP_TO(size, 4096);
325d722e3fbSopenharmony_ci
326d722e3fbSopenharmony_ci	/* Older chips need powers of two, of at least 512k or 1M */
327d722e3fbSopenharmony_ci	if (bufmgr_gem->gen == 3) {
328d722e3fbSopenharmony_ci		min_size = 1024*1024;
329d722e3fbSopenharmony_ci		max_size = 128*1024*1024;
330d722e3fbSopenharmony_ci	} else {
331d722e3fbSopenharmony_ci		min_size = 512*1024;
332d722e3fbSopenharmony_ci		max_size = 64*1024*1024;
333d722e3fbSopenharmony_ci	}
334d722e3fbSopenharmony_ci
335d722e3fbSopenharmony_ci	if (size > max_size) {
336d722e3fbSopenharmony_ci		*tiling_mode = I915_TILING_NONE;
337d722e3fbSopenharmony_ci		return size;
338d722e3fbSopenharmony_ci	}
339d722e3fbSopenharmony_ci
340d722e3fbSopenharmony_ci	/* Do we need to allocate every page for the fence? */
341d722e3fbSopenharmony_ci	if (bufmgr_gem->has_relaxed_fencing)
342d722e3fbSopenharmony_ci		return ROUND_UP_TO(size, 4096);
343d722e3fbSopenharmony_ci
344d722e3fbSopenharmony_ci	for (i = min_size; i < size; i <<= 1)
345d722e3fbSopenharmony_ci		;
346d722e3fbSopenharmony_ci
347d722e3fbSopenharmony_ci	return i;
348d722e3fbSopenharmony_ci}
349d722e3fbSopenharmony_ci
350d722e3fbSopenharmony_ci/*
351d722e3fbSopenharmony_ci * Round a given pitch up to the minimum required for X tiling on a
352d722e3fbSopenharmony_ci * given chip.  We use 512 as the minimum to allow for a later tiling
353d722e3fbSopenharmony_ci * change.
354d722e3fbSopenharmony_ci */
355d722e3fbSopenharmony_cistatic unsigned long
356d722e3fbSopenharmony_cidrm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem,
357d722e3fbSopenharmony_ci			    unsigned long pitch, uint32_t *tiling_mode)
358d722e3fbSopenharmony_ci{
359d722e3fbSopenharmony_ci	unsigned long tile_width;
360d722e3fbSopenharmony_ci	unsigned long i;
361d722e3fbSopenharmony_ci
362d722e3fbSopenharmony_ci	/* If untiled, then just align it so that we can do rendering
363d722e3fbSopenharmony_ci	 * to it with the 3D engine.
364d722e3fbSopenharmony_ci	 */
365d722e3fbSopenharmony_ci	if (*tiling_mode == I915_TILING_NONE)
366d722e3fbSopenharmony_ci		return ALIGN(pitch, 64);
367d722e3fbSopenharmony_ci
368d722e3fbSopenharmony_ci	if (*tiling_mode == I915_TILING_X
369d722e3fbSopenharmony_ci			|| (IS_915(bufmgr_gem->pci_device)
370d722e3fbSopenharmony_ci			    && *tiling_mode == I915_TILING_Y))
371d722e3fbSopenharmony_ci		tile_width = 512;
372d722e3fbSopenharmony_ci	else
373d722e3fbSopenharmony_ci		tile_width = 128;
374d722e3fbSopenharmony_ci
375d722e3fbSopenharmony_ci	/* 965 is flexible */
376d722e3fbSopenharmony_ci	if (bufmgr_gem->gen >= 4)
377d722e3fbSopenharmony_ci		return ROUND_UP_TO(pitch, tile_width);
378d722e3fbSopenharmony_ci
379d722e3fbSopenharmony_ci	/* The older hardware has a maximum pitch of 8192 with tiled
380d722e3fbSopenharmony_ci	 * surfaces, so fallback to untiled if it's too large.
381d722e3fbSopenharmony_ci	 */
382d722e3fbSopenharmony_ci	if (pitch > 8192) {
383d722e3fbSopenharmony_ci		*tiling_mode = I915_TILING_NONE;
384d722e3fbSopenharmony_ci		return ALIGN(pitch, 64);
385d722e3fbSopenharmony_ci	}
386d722e3fbSopenharmony_ci
387d722e3fbSopenharmony_ci	/* Pre-965 needs power of two tile width */
388d722e3fbSopenharmony_ci	for (i = tile_width; i < pitch; i <<= 1)
389d722e3fbSopenharmony_ci		;
390d722e3fbSopenharmony_ci
391d722e3fbSopenharmony_ci	return i;
392d722e3fbSopenharmony_ci}
393d722e3fbSopenharmony_ci
394d722e3fbSopenharmony_cistatic struct drm_intel_gem_bo_bucket *
395d722e3fbSopenharmony_cidrm_intel_gem_bo_bucket_for_size(drm_intel_bufmgr_gem *bufmgr_gem,
396d722e3fbSopenharmony_ci				 unsigned long size)
397d722e3fbSopenharmony_ci{
398d722e3fbSopenharmony_ci	int i;
399d722e3fbSopenharmony_ci
400d722e3fbSopenharmony_ci	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
401d722e3fbSopenharmony_ci		struct drm_intel_gem_bo_bucket *bucket =
402d722e3fbSopenharmony_ci		    &bufmgr_gem->cache_bucket[i];
403d722e3fbSopenharmony_ci		if (bucket->size >= size) {
404d722e3fbSopenharmony_ci			return bucket;
405d722e3fbSopenharmony_ci		}
406d722e3fbSopenharmony_ci	}
407d722e3fbSopenharmony_ci
408d722e3fbSopenharmony_ci	return NULL;
409d722e3fbSopenharmony_ci}
410d722e3fbSopenharmony_ci
411d722e3fbSopenharmony_cistatic void
412d722e3fbSopenharmony_cidrm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem)
413d722e3fbSopenharmony_ci{
414d722e3fbSopenharmony_ci	int i, j;
415d722e3fbSopenharmony_ci
416d722e3fbSopenharmony_ci	for (i = 0; i < bufmgr_gem->exec_count; i++) {
417d722e3fbSopenharmony_ci		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
418d722e3fbSopenharmony_ci		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
419d722e3fbSopenharmony_ci
420d722e3fbSopenharmony_ci		if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) {
421d722e3fbSopenharmony_ci			DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle,
422d722e3fbSopenharmony_ci			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
423d722e3fbSopenharmony_ci			    bo_gem->name);
424d722e3fbSopenharmony_ci			continue;
425d722e3fbSopenharmony_ci		}
426d722e3fbSopenharmony_ci
427d722e3fbSopenharmony_ci		for (j = 0; j < bo_gem->reloc_count; j++) {
428d722e3fbSopenharmony_ci			drm_intel_bo *target_bo = bo_gem->reloc_target_info[j].bo;
429d722e3fbSopenharmony_ci			drm_intel_bo_gem *target_gem =
430d722e3fbSopenharmony_ci			    (drm_intel_bo_gem *) target_bo;
431d722e3fbSopenharmony_ci
432d722e3fbSopenharmony_ci			DBG("%2d: %d %s(%s)@0x%08x %08x -> "
433d722e3fbSopenharmony_ci			    "%d (%s)@0x%08x %08x + 0x%08x\n",
434d722e3fbSopenharmony_ci			    i,
435d722e3fbSopenharmony_ci			    bo_gem->gem_handle,
436d722e3fbSopenharmony_ci			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
437d722e3fbSopenharmony_ci			    bo_gem->name,
438d722e3fbSopenharmony_ci			    upper_32_bits(bo_gem->relocs[j].offset),
439d722e3fbSopenharmony_ci			    lower_32_bits(bo_gem->relocs[j].offset),
440d722e3fbSopenharmony_ci			    target_gem->gem_handle,
441d722e3fbSopenharmony_ci			    target_gem->name,
442d722e3fbSopenharmony_ci			    upper_32_bits(target_bo->offset64),
443d722e3fbSopenharmony_ci			    lower_32_bits(target_bo->offset64),
444d722e3fbSopenharmony_ci			    bo_gem->relocs[j].delta);
445d722e3fbSopenharmony_ci		}
446d722e3fbSopenharmony_ci
447d722e3fbSopenharmony_ci		for (j = 0; j < bo_gem->softpin_target_count; j++) {
448d722e3fbSopenharmony_ci			drm_intel_bo *target_bo = bo_gem->softpin_target[j];
449d722e3fbSopenharmony_ci			drm_intel_bo_gem *target_gem =
450d722e3fbSopenharmony_ci			    (drm_intel_bo_gem *) target_bo;
451d722e3fbSopenharmony_ci			DBG("%2d: %d %s(%s) -> "
452d722e3fbSopenharmony_ci			    "%d *(%s)@0x%08x %08x\n",
453d722e3fbSopenharmony_ci			    i,
454d722e3fbSopenharmony_ci			    bo_gem->gem_handle,
455d722e3fbSopenharmony_ci			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
456d722e3fbSopenharmony_ci			    bo_gem->name,
457d722e3fbSopenharmony_ci			    target_gem->gem_handle,
458d722e3fbSopenharmony_ci			    target_gem->name,
459d722e3fbSopenharmony_ci			    upper_32_bits(target_bo->offset64),
460d722e3fbSopenharmony_ci			    lower_32_bits(target_bo->offset64));
461d722e3fbSopenharmony_ci		}
462d722e3fbSopenharmony_ci	}
463d722e3fbSopenharmony_ci}
464d722e3fbSopenharmony_ci
465d722e3fbSopenharmony_cistatic inline void
466d722e3fbSopenharmony_cidrm_intel_gem_bo_reference(drm_intel_bo *bo)
467d722e3fbSopenharmony_ci{
468d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
469d722e3fbSopenharmony_ci
470d722e3fbSopenharmony_ci	atomic_inc(&bo_gem->refcount);
471d722e3fbSopenharmony_ci}
472d722e3fbSopenharmony_ci
473d722e3fbSopenharmony_ci/**
474d722e3fbSopenharmony_ci * Adds the given buffer to the list of buffers to be validated (moved into the
475d722e3fbSopenharmony_ci * appropriate memory type) with the next batch submission.
476d722e3fbSopenharmony_ci *
477d722e3fbSopenharmony_ci * If a buffer is validated multiple times in a batch submission, it ends up
478d722e3fbSopenharmony_ci * with the intersection of the memory type flags and the union of the
479d722e3fbSopenharmony_ci * access flags.
480d722e3fbSopenharmony_ci */
481d722e3fbSopenharmony_cistatic void
482d722e3fbSopenharmony_cidrm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence)
483d722e3fbSopenharmony_ci{
484d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
485d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
486d722e3fbSopenharmony_ci	int index;
487d722e3fbSopenharmony_ci	unsigned long flags;
488d722e3fbSopenharmony_ci
489d722e3fbSopenharmony_ci	flags = 0;
490d722e3fbSopenharmony_ci	if (need_fence)
491d722e3fbSopenharmony_ci		flags |= EXEC_OBJECT_NEEDS_FENCE;
492d722e3fbSopenharmony_ci
493d722e3fbSopenharmony_ci	if (bo_gem->validate_index != -1) {
494d722e3fbSopenharmony_ci		bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags;
495d722e3fbSopenharmony_ci		return;
496d722e3fbSopenharmony_ci	}
497d722e3fbSopenharmony_ci
498d722e3fbSopenharmony_ci	/* Extend the array of validation entries as necessary. */
499d722e3fbSopenharmony_ci	if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
500d722e3fbSopenharmony_ci		int new_size = bufmgr_gem->exec_size * 2;
501d722e3fbSopenharmony_ci
502d722e3fbSopenharmony_ci		if (new_size == 0)
503d722e3fbSopenharmony_ci			new_size = 5;
504d722e3fbSopenharmony_ci
505d722e3fbSopenharmony_ci		bufmgr_gem->exec2_objects =
506d722e3fbSopenharmony_ci			realloc(bufmgr_gem->exec2_objects,
507d722e3fbSopenharmony_ci				sizeof(*bufmgr_gem->exec2_objects) * new_size);
508d722e3fbSopenharmony_ci		bufmgr_gem->exec_bos =
509d722e3fbSopenharmony_ci			realloc(bufmgr_gem->exec_bos,
510d722e3fbSopenharmony_ci				sizeof(*bufmgr_gem->exec_bos) * new_size);
511d722e3fbSopenharmony_ci		bufmgr_gem->exec_size = new_size;
512d722e3fbSopenharmony_ci	}
513d722e3fbSopenharmony_ci
514d722e3fbSopenharmony_ci	index = bufmgr_gem->exec_count;
515d722e3fbSopenharmony_ci	bo_gem->validate_index = index;
516d722e3fbSopenharmony_ci	/* Fill in array entry */
517d722e3fbSopenharmony_ci	bufmgr_gem->exec2_objects[index].handle = bo_gem->gem_handle;
518d722e3fbSopenharmony_ci	bufmgr_gem->exec2_objects[index].relocation_count = bo_gem->reloc_count;
519d722e3fbSopenharmony_ci	bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
520d722e3fbSopenharmony_ci	bufmgr_gem->exec2_objects[index].alignment = bo->align;
521d722e3fbSopenharmony_ci	bufmgr_gem->exec2_objects[index].offset = bo->offset64;
522d722e3fbSopenharmony_ci	bufmgr_gem->exec2_objects[index].flags = bo_gem->kflags | flags;
523d722e3fbSopenharmony_ci	bufmgr_gem->exec2_objects[index].rsvd1 = 0;
524d722e3fbSopenharmony_ci	bufmgr_gem->exec2_objects[index].rsvd2 = 0;
525d722e3fbSopenharmony_ci	bufmgr_gem->exec_bos[index] = bo;
526d722e3fbSopenharmony_ci	bufmgr_gem->exec_count++;
527d722e3fbSopenharmony_ci}
528d722e3fbSopenharmony_ci
529d722e3fbSopenharmony_ci#define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \
530d722e3fbSopenharmony_ci	sizeof(uint32_t))
531d722e3fbSopenharmony_ci
532d722e3fbSopenharmony_cistatic void
533d722e3fbSopenharmony_cidrm_intel_bo_gem_set_in_aperture_size(drm_intel_bufmgr_gem *bufmgr_gem,
534d722e3fbSopenharmony_ci				      drm_intel_bo_gem *bo_gem,
535d722e3fbSopenharmony_ci				      unsigned int alignment)
536d722e3fbSopenharmony_ci{
537d722e3fbSopenharmony_ci	unsigned int size;
538d722e3fbSopenharmony_ci
539d722e3fbSopenharmony_ci	assert(!bo_gem->used_as_reloc_target);
540d722e3fbSopenharmony_ci
541d722e3fbSopenharmony_ci	/* The older chipsets are far-less flexible in terms of tiling,
542d722e3fbSopenharmony_ci	 * and require tiled buffer to be size aligned in the aperture.
543d722e3fbSopenharmony_ci	 * This means that in the worst possible case we will need a hole
544d722e3fbSopenharmony_ci	 * twice as large as the object in order for it to fit into the
545d722e3fbSopenharmony_ci	 * aperture. Optimal packing is for wimps.
546d722e3fbSopenharmony_ci	 */
547d722e3fbSopenharmony_ci	size = bo_gem->bo.size;
548d722e3fbSopenharmony_ci	if (bufmgr_gem->gen < 4 && bo_gem->tiling_mode != I915_TILING_NONE) {
549d722e3fbSopenharmony_ci		unsigned int min_size;
550d722e3fbSopenharmony_ci
551d722e3fbSopenharmony_ci		if (bufmgr_gem->has_relaxed_fencing) {
552d722e3fbSopenharmony_ci			if (bufmgr_gem->gen == 3)
553d722e3fbSopenharmony_ci				min_size = 1024*1024;
554d722e3fbSopenharmony_ci			else
555d722e3fbSopenharmony_ci				min_size = 512*1024;
556d722e3fbSopenharmony_ci
557d722e3fbSopenharmony_ci			while (min_size < size)
558d722e3fbSopenharmony_ci				min_size *= 2;
559d722e3fbSopenharmony_ci		} else
560d722e3fbSopenharmony_ci			min_size = size;
561d722e3fbSopenharmony_ci
562d722e3fbSopenharmony_ci		/* Account for worst-case alignment. */
563d722e3fbSopenharmony_ci		alignment = MAX2(alignment, min_size);
564d722e3fbSopenharmony_ci	}
565d722e3fbSopenharmony_ci
566d722e3fbSopenharmony_ci	bo_gem->reloc_tree_size = size + alignment;
567d722e3fbSopenharmony_ci}
568d722e3fbSopenharmony_ci
569d722e3fbSopenharmony_cistatic int
570d722e3fbSopenharmony_cidrm_intel_setup_reloc_list(drm_intel_bo *bo)
571d722e3fbSopenharmony_ci{
572d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
573d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
574d722e3fbSopenharmony_ci	unsigned int max_relocs = bufmgr_gem->max_relocs;
575d722e3fbSopenharmony_ci
576d722e3fbSopenharmony_ci	if (bo->size / 4 < max_relocs)
577d722e3fbSopenharmony_ci		max_relocs = bo->size / 4;
578d722e3fbSopenharmony_ci
579d722e3fbSopenharmony_ci	bo_gem->relocs = malloc(max_relocs *
580d722e3fbSopenharmony_ci				sizeof(struct drm_i915_gem_relocation_entry));
581d722e3fbSopenharmony_ci	bo_gem->reloc_target_info = malloc(max_relocs *
582d722e3fbSopenharmony_ci					   sizeof(drm_intel_reloc_target));
583d722e3fbSopenharmony_ci	if (bo_gem->relocs == NULL || bo_gem->reloc_target_info == NULL) {
584d722e3fbSopenharmony_ci		bo_gem->has_error = true;
585d722e3fbSopenharmony_ci
586d722e3fbSopenharmony_ci		free (bo_gem->relocs);
587d722e3fbSopenharmony_ci		bo_gem->relocs = NULL;
588d722e3fbSopenharmony_ci
589d722e3fbSopenharmony_ci		free (bo_gem->reloc_target_info);
590d722e3fbSopenharmony_ci		bo_gem->reloc_target_info = NULL;
591d722e3fbSopenharmony_ci
592d722e3fbSopenharmony_ci		return 1;
593d722e3fbSopenharmony_ci	}
594d722e3fbSopenharmony_ci
595d722e3fbSopenharmony_ci	return 0;
596d722e3fbSopenharmony_ci}
597d722e3fbSopenharmony_ci
598d722e3fbSopenharmony_cistatic int
599d722e3fbSopenharmony_cidrm_intel_gem_bo_busy(drm_intel_bo *bo)
600d722e3fbSopenharmony_ci{
601d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
602d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
603d722e3fbSopenharmony_ci	struct drm_i915_gem_busy busy;
604d722e3fbSopenharmony_ci	int ret;
605d722e3fbSopenharmony_ci
606d722e3fbSopenharmony_ci	if (bo_gem->reusable && bo_gem->idle)
607d722e3fbSopenharmony_ci		return false;
608d722e3fbSopenharmony_ci
609d722e3fbSopenharmony_ci	memclear(busy);
610d722e3fbSopenharmony_ci	busy.handle = bo_gem->gem_handle;
611d722e3fbSopenharmony_ci
612d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
613d722e3fbSopenharmony_ci	if (ret == 0) {
614d722e3fbSopenharmony_ci		bo_gem->idle = !busy.busy;
615d722e3fbSopenharmony_ci		return busy.busy;
616d722e3fbSopenharmony_ci	} else {
617d722e3fbSopenharmony_ci		return false;
618d722e3fbSopenharmony_ci	}
619d722e3fbSopenharmony_ci}
620d722e3fbSopenharmony_ci
621d722e3fbSopenharmony_cistatic int
622d722e3fbSopenharmony_cidrm_intel_gem_bo_madvise_internal(drm_intel_bufmgr_gem *bufmgr_gem,
623d722e3fbSopenharmony_ci				  drm_intel_bo_gem *bo_gem, int state)
624d722e3fbSopenharmony_ci{
625d722e3fbSopenharmony_ci	struct drm_i915_gem_madvise madv;
626d722e3fbSopenharmony_ci
627d722e3fbSopenharmony_ci	memclear(madv);
628d722e3fbSopenharmony_ci	madv.handle = bo_gem->gem_handle;
629d722e3fbSopenharmony_ci	madv.madv = state;
630d722e3fbSopenharmony_ci	madv.retained = 1;
631d722e3fbSopenharmony_ci	drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv);
632d722e3fbSopenharmony_ci
633d722e3fbSopenharmony_ci	return madv.retained;
634d722e3fbSopenharmony_ci}
635d722e3fbSopenharmony_ci
636d722e3fbSopenharmony_cistatic int
637d722e3fbSopenharmony_cidrm_intel_gem_bo_madvise(drm_intel_bo *bo, int madv)
638d722e3fbSopenharmony_ci{
639d722e3fbSopenharmony_ci	return drm_intel_gem_bo_madvise_internal
640d722e3fbSopenharmony_ci		((drm_intel_bufmgr_gem *) bo->bufmgr,
641d722e3fbSopenharmony_ci		 (drm_intel_bo_gem *) bo,
642d722e3fbSopenharmony_ci		 madv);
643d722e3fbSopenharmony_ci}
644d722e3fbSopenharmony_ci
645d722e3fbSopenharmony_ci/* drop the oldest entries that have been purged by the kernel */
646d722e3fbSopenharmony_cistatic void
647d722e3fbSopenharmony_cidrm_intel_gem_bo_cache_purge_bucket(drm_intel_bufmgr_gem *bufmgr_gem,
648d722e3fbSopenharmony_ci				    struct drm_intel_gem_bo_bucket *bucket)
649d722e3fbSopenharmony_ci{
650d722e3fbSopenharmony_ci	while (!DRMLISTEMPTY(&bucket->head)) {
651d722e3fbSopenharmony_ci		drm_intel_bo_gem *bo_gem;
652d722e3fbSopenharmony_ci
653d722e3fbSopenharmony_ci		bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
654d722e3fbSopenharmony_ci				      bucket->head.next, head);
655d722e3fbSopenharmony_ci		if (drm_intel_gem_bo_madvise_internal
656d722e3fbSopenharmony_ci		    (bufmgr_gem, bo_gem, I915_MADV_DONTNEED))
657d722e3fbSopenharmony_ci			break;
658d722e3fbSopenharmony_ci
659d722e3fbSopenharmony_ci		DRMLISTDEL(&bo_gem->head);
660d722e3fbSopenharmony_ci		drm_intel_gem_bo_free(&bo_gem->bo);
661d722e3fbSopenharmony_ci	}
662d722e3fbSopenharmony_ci}
663d722e3fbSopenharmony_ci
664d722e3fbSopenharmony_cistatic drm_intel_bo *
665d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc_internal(drm_intel_bufmgr *bufmgr,
666d722e3fbSopenharmony_ci				const char *name,
667d722e3fbSopenharmony_ci				unsigned long size,
668d722e3fbSopenharmony_ci				unsigned long flags,
669d722e3fbSopenharmony_ci				uint32_t tiling_mode,
670d722e3fbSopenharmony_ci				unsigned long stride,
671d722e3fbSopenharmony_ci				unsigned int alignment)
672d722e3fbSopenharmony_ci{
673d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
674d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem;
675d722e3fbSopenharmony_ci	unsigned int page_size = getpagesize();
676d722e3fbSopenharmony_ci	int ret;
677d722e3fbSopenharmony_ci	struct drm_intel_gem_bo_bucket *bucket;
678d722e3fbSopenharmony_ci	bool alloc_from_cache;
679d722e3fbSopenharmony_ci	unsigned long bo_size;
680d722e3fbSopenharmony_ci	bool for_render = false;
681d722e3fbSopenharmony_ci
682d722e3fbSopenharmony_ci	if (flags & BO_ALLOC_FOR_RENDER)
683d722e3fbSopenharmony_ci		for_render = true;
684d722e3fbSopenharmony_ci
685d722e3fbSopenharmony_ci	/* Round the allocated size up to a power of two number of pages. */
686d722e3fbSopenharmony_ci	bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, size);
687d722e3fbSopenharmony_ci
688d722e3fbSopenharmony_ci	/* If we don't have caching at this size, don't actually round the
689d722e3fbSopenharmony_ci	 * allocation up.
690d722e3fbSopenharmony_ci	 */
691d722e3fbSopenharmony_ci	if (bucket == NULL) {
692d722e3fbSopenharmony_ci		bo_size = size;
693d722e3fbSopenharmony_ci		if (bo_size < page_size)
694d722e3fbSopenharmony_ci			bo_size = page_size;
695d722e3fbSopenharmony_ci	} else {
696d722e3fbSopenharmony_ci		bo_size = bucket->size;
697d722e3fbSopenharmony_ci	}
698d722e3fbSopenharmony_ci
699d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
700d722e3fbSopenharmony_ci	/* Get a buffer out of the cache if available */
701d722e3fbSopenharmony_ciretry:
702d722e3fbSopenharmony_ci	alloc_from_cache = false;
703d722e3fbSopenharmony_ci	if (bucket != NULL && !DRMLISTEMPTY(&bucket->head)) {
704d722e3fbSopenharmony_ci		if (for_render) {
705d722e3fbSopenharmony_ci			/* Allocate new render-target BOs from the tail (MRU)
706d722e3fbSopenharmony_ci			 * of the list, as it will likely be hot in the GPU
707d722e3fbSopenharmony_ci			 * cache and in the aperture for us.
708d722e3fbSopenharmony_ci			 */
709d722e3fbSopenharmony_ci			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
710d722e3fbSopenharmony_ci					      bucket->head.prev, head);
711d722e3fbSopenharmony_ci			DRMLISTDEL(&bo_gem->head);
712d722e3fbSopenharmony_ci			alloc_from_cache = true;
713d722e3fbSopenharmony_ci			bo_gem->bo.align = alignment;
714d722e3fbSopenharmony_ci		} else {
715d722e3fbSopenharmony_ci			assert(alignment == 0);
716d722e3fbSopenharmony_ci			/* For non-render-target BOs (where we're probably
717d722e3fbSopenharmony_ci			 * going to map it first thing in order to fill it
718d722e3fbSopenharmony_ci			 * with data), check if the last BO in the cache is
719d722e3fbSopenharmony_ci			 * unbusy, and only reuse in that case. Otherwise,
720d722e3fbSopenharmony_ci			 * allocating a new buffer is probably faster than
721d722e3fbSopenharmony_ci			 * waiting for the GPU to finish.
722d722e3fbSopenharmony_ci			 */
723d722e3fbSopenharmony_ci			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
724d722e3fbSopenharmony_ci					      bucket->head.next, head);
725d722e3fbSopenharmony_ci			if (!drm_intel_gem_bo_busy(&bo_gem->bo)) {
726d722e3fbSopenharmony_ci				alloc_from_cache = true;
727d722e3fbSopenharmony_ci				DRMLISTDEL(&bo_gem->head);
728d722e3fbSopenharmony_ci			}
729d722e3fbSopenharmony_ci		}
730d722e3fbSopenharmony_ci
731d722e3fbSopenharmony_ci		if (alloc_from_cache) {
732d722e3fbSopenharmony_ci			if (!drm_intel_gem_bo_madvise_internal
733d722e3fbSopenharmony_ci			    (bufmgr_gem, bo_gem, I915_MADV_WILLNEED)) {
734d722e3fbSopenharmony_ci				drm_intel_gem_bo_free(&bo_gem->bo);
735d722e3fbSopenharmony_ci				drm_intel_gem_bo_cache_purge_bucket(bufmgr_gem,
736d722e3fbSopenharmony_ci								    bucket);
737d722e3fbSopenharmony_ci				goto retry;
738d722e3fbSopenharmony_ci			}
739d722e3fbSopenharmony_ci
740d722e3fbSopenharmony_ci			if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo,
741d722e3fbSopenharmony_ci								 tiling_mode,
742d722e3fbSopenharmony_ci								 stride)) {
743d722e3fbSopenharmony_ci				drm_intel_gem_bo_free(&bo_gem->bo);
744d722e3fbSopenharmony_ci				goto retry;
745d722e3fbSopenharmony_ci			}
746d722e3fbSopenharmony_ci		}
747d722e3fbSopenharmony_ci	}
748d722e3fbSopenharmony_ci
749d722e3fbSopenharmony_ci	if (!alloc_from_cache) {
750d722e3fbSopenharmony_ci		struct drm_i915_gem_create create;
751d722e3fbSopenharmony_ci
752d722e3fbSopenharmony_ci		bo_gem = calloc(1, sizeof(*bo_gem));
753d722e3fbSopenharmony_ci		if (!bo_gem)
754d722e3fbSopenharmony_ci			goto err;
755d722e3fbSopenharmony_ci
756d722e3fbSopenharmony_ci		/* drm_intel_gem_bo_free calls DRMLISTDEL() for an uninitialized
757d722e3fbSopenharmony_ci		   list (vma_list), so better set the list head here */
758d722e3fbSopenharmony_ci		DRMINITLISTHEAD(&bo_gem->vma_list);
759d722e3fbSopenharmony_ci
760d722e3fbSopenharmony_ci		bo_gem->bo.size = bo_size;
761d722e3fbSopenharmony_ci
762d722e3fbSopenharmony_ci		memclear(create);
763d722e3fbSopenharmony_ci		create.size = bo_size;
764d722e3fbSopenharmony_ci
765d722e3fbSopenharmony_ci		ret = drmIoctl(bufmgr_gem->fd,
766d722e3fbSopenharmony_ci			       DRM_IOCTL_I915_GEM_CREATE,
767d722e3fbSopenharmony_ci			       &create);
768d722e3fbSopenharmony_ci		if (ret != 0) {
769d722e3fbSopenharmony_ci			free(bo_gem);
770d722e3fbSopenharmony_ci			goto err;
771d722e3fbSopenharmony_ci		}
772d722e3fbSopenharmony_ci
773d722e3fbSopenharmony_ci		bo_gem->gem_handle = create.handle;
774d722e3fbSopenharmony_ci		HASH_ADD(handle_hh, bufmgr_gem->handle_table,
775d722e3fbSopenharmony_ci			 gem_handle, sizeof(bo_gem->gem_handle),
776d722e3fbSopenharmony_ci			 bo_gem);
777d722e3fbSopenharmony_ci
778d722e3fbSopenharmony_ci		bo_gem->bo.handle = bo_gem->gem_handle;
779d722e3fbSopenharmony_ci		bo_gem->bo.bufmgr = bufmgr;
780d722e3fbSopenharmony_ci		bo_gem->bo.align = alignment;
781d722e3fbSopenharmony_ci
782d722e3fbSopenharmony_ci		bo_gem->tiling_mode = I915_TILING_NONE;
783d722e3fbSopenharmony_ci		bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
784d722e3fbSopenharmony_ci		bo_gem->stride = 0;
785d722e3fbSopenharmony_ci
786d722e3fbSopenharmony_ci		if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo,
787d722e3fbSopenharmony_ci							 tiling_mode,
788d722e3fbSopenharmony_ci							 stride))
789d722e3fbSopenharmony_ci			goto err_free;
790d722e3fbSopenharmony_ci	}
791d722e3fbSopenharmony_ci
792d722e3fbSopenharmony_ci	bo_gem->name = name;
793d722e3fbSopenharmony_ci	atomic_set(&bo_gem->refcount, 1);
794d722e3fbSopenharmony_ci	bo_gem->validate_index = -1;
795d722e3fbSopenharmony_ci	bo_gem->reloc_tree_fences = 0;
796d722e3fbSopenharmony_ci	bo_gem->used_as_reloc_target = false;
797d722e3fbSopenharmony_ci	bo_gem->has_error = false;
798d722e3fbSopenharmony_ci	bo_gem->reusable = true;
799d722e3fbSopenharmony_ci
800d722e3fbSopenharmony_ci	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment);
801d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
802d722e3fbSopenharmony_ci
803d722e3fbSopenharmony_ci	DBG("bo_create: buf %d (%s) %ldb\n",
804d722e3fbSopenharmony_ci	    bo_gem->gem_handle, bo_gem->name, size);
805d722e3fbSopenharmony_ci
806d722e3fbSopenharmony_ci	return &bo_gem->bo;
807d722e3fbSopenharmony_ci
808d722e3fbSopenharmony_cierr_free:
809d722e3fbSopenharmony_ci	drm_intel_gem_bo_free(&bo_gem->bo);
810d722e3fbSopenharmony_cierr:
811d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
812d722e3fbSopenharmony_ci	return NULL;
813d722e3fbSopenharmony_ci}
814d722e3fbSopenharmony_ci
815d722e3fbSopenharmony_cistatic drm_intel_bo *
816d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc_for_render(drm_intel_bufmgr *bufmgr,
817d722e3fbSopenharmony_ci				  const char *name,
818d722e3fbSopenharmony_ci				  unsigned long size,
819d722e3fbSopenharmony_ci				  unsigned int alignment)
820d722e3fbSopenharmony_ci{
821d722e3fbSopenharmony_ci	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size,
822d722e3fbSopenharmony_ci					       BO_ALLOC_FOR_RENDER,
823d722e3fbSopenharmony_ci					       I915_TILING_NONE, 0,
824d722e3fbSopenharmony_ci					       alignment);
825d722e3fbSopenharmony_ci}
826d722e3fbSopenharmony_ci
827d722e3fbSopenharmony_cistatic drm_intel_bo *
828d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr,
829d722e3fbSopenharmony_ci		       const char *name,
830d722e3fbSopenharmony_ci		       unsigned long size,
831d722e3fbSopenharmony_ci		       unsigned int alignment)
832d722e3fbSopenharmony_ci{
833d722e3fbSopenharmony_ci	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0,
834d722e3fbSopenharmony_ci					       I915_TILING_NONE, 0, 0);
835d722e3fbSopenharmony_ci}
836d722e3fbSopenharmony_ci
837d722e3fbSopenharmony_cistatic drm_intel_bo *
838d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name,
839d722e3fbSopenharmony_ci			     int x, int y, int cpp, uint32_t *tiling_mode,
840d722e3fbSopenharmony_ci			     unsigned long *pitch, unsigned long flags)
841d722e3fbSopenharmony_ci{
842d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
843d722e3fbSopenharmony_ci	unsigned long size, stride;
844d722e3fbSopenharmony_ci	uint32_t tiling;
845d722e3fbSopenharmony_ci
846d722e3fbSopenharmony_ci	do {
847d722e3fbSopenharmony_ci		unsigned long aligned_y, height_alignment;
848d722e3fbSopenharmony_ci
849d722e3fbSopenharmony_ci		tiling = *tiling_mode;
850d722e3fbSopenharmony_ci
851d722e3fbSopenharmony_ci		/* If we're tiled, our allocations are in 8 or 32-row blocks,
852d722e3fbSopenharmony_ci		 * so failure to align our height means that we won't allocate
853d722e3fbSopenharmony_ci		 * enough pages.
854d722e3fbSopenharmony_ci		 *
855d722e3fbSopenharmony_ci		 * If we're untiled, we still have to align to 2 rows high
856d722e3fbSopenharmony_ci		 * because the data port accesses 2x2 blocks even if the
857d722e3fbSopenharmony_ci		 * bottom row isn't to be rendered, so failure to align means
858d722e3fbSopenharmony_ci		 * we could walk off the end of the GTT and fault.  This is
859d722e3fbSopenharmony_ci		 * documented on 965, and may be the case on older chipsets
860d722e3fbSopenharmony_ci		 * too so we try to be careful.
861d722e3fbSopenharmony_ci		 */
862d722e3fbSopenharmony_ci		aligned_y = y;
863d722e3fbSopenharmony_ci		height_alignment = 2;
864d722e3fbSopenharmony_ci
865d722e3fbSopenharmony_ci		if ((bufmgr_gem->gen == 2) && tiling != I915_TILING_NONE)
866d722e3fbSopenharmony_ci			height_alignment = 16;
867d722e3fbSopenharmony_ci		else if (tiling == I915_TILING_X
868d722e3fbSopenharmony_ci			|| (IS_915(bufmgr_gem->pci_device)
869d722e3fbSopenharmony_ci			    && tiling == I915_TILING_Y))
870d722e3fbSopenharmony_ci			height_alignment = 8;
871d722e3fbSopenharmony_ci		else if (tiling == I915_TILING_Y)
872d722e3fbSopenharmony_ci			height_alignment = 32;
873d722e3fbSopenharmony_ci		aligned_y = ALIGN(y, height_alignment);
874d722e3fbSopenharmony_ci
875d722e3fbSopenharmony_ci		stride = x * cpp;
876d722e3fbSopenharmony_ci		stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling_mode);
877d722e3fbSopenharmony_ci		size = stride * aligned_y;
878d722e3fbSopenharmony_ci		size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode);
879d722e3fbSopenharmony_ci	} while (*tiling_mode != tiling);
880d722e3fbSopenharmony_ci	*pitch = stride;
881d722e3fbSopenharmony_ci
882d722e3fbSopenharmony_ci	if (tiling == I915_TILING_NONE)
883d722e3fbSopenharmony_ci		stride = 0;
884d722e3fbSopenharmony_ci
885d722e3fbSopenharmony_ci	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags,
886d722e3fbSopenharmony_ci					       tiling, stride, 0);
887d722e3fbSopenharmony_ci}
888d722e3fbSopenharmony_ci
889d722e3fbSopenharmony_cistatic drm_intel_bo *
890d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
891d722e3fbSopenharmony_ci				const char *name,
892d722e3fbSopenharmony_ci				void *addr,
893d722e3fbSopenharmony_ci				uint32_t tiling_mode,
894d722e3fbSopenharmony_ci				uint32_t stride,
895d722e3fbSopenharmony_ci				unsigned long size,
896d722e3fbSopenharmony_ci				unsigned long flags)
897d722e3fbSopenharmony_ci{
898d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
899d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem;
900d722e3fbSopenharmony_ci	int ret;
901d722e3fbSopenharmony_ci	struct drm_i915_gem_userptr userptr;
902d722e3fbSopenharmony_ci
903d722e3fbSopenharmony_ci	/* Tiling with userptr surfaces is not supported
904d722e3fbSopenharmony_ci	 * on all hardware so refuse it for time being.
905d722e3fbSopenharmony_ci	 */
906d722e3fbSopenharmony_ci	if (tiling_mode != I915_TILING_NONE)
907d722e3fbSopenharmony_ci		return NULL;
908d722e3fbSopenharmony_ci
909d722e3fbSopenharmony_ci	bo_gem = calloc(1, sizeof(*bo_gem));
910d722e3fbSopenharmony_ci	if (!bo_gem)
911d722e3fbSopenharmony_ci		return NULL;
912d722e3fbSopenharmony_ci
913d722e3fbSopenharmony_ci	atomic_set(&bo_gem->refcount, 1);
914d722e3fbSopenharmony_ci	DRMINITLISTHEAD(&bo_gem->vma_list);
915d722e3fbSopenharmony_ci
916d722e3fbSopenharmony_ci	bo_gem->bo.size = size;
917d722e3fbSopenharmony_ci
918d722e3fbSopenharmony_ci	memclear(userptr);
919d722e3fbSopenharmony_ci	userptr.user_ptr = (__u64)((unsigned long)addr);
920d722e3fbSopenharmony_ci	userptr.user_size = size;
921d722e3fbSopenharmony_ci	userptr.flags = flags;
922d722e3fbSopenharmony_ci
923d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
924d722e3fbSopenharmony_ci			DRM_IOCTL_I915_GEM_USERPTR,
925d722e3fbSopenharmony_ci			&userptr);
926d722e3fbSopenharmony_ci	if (ret != 0) {
927d722e3fbSopenharmony_ci		DBG("bo_create_userptr: "
928d722e3fbSopenharmony_ci		    "ioctl failed with user ptr %p size 0x%lx, "
929d722e3fbSopenharmony_ci		    "user flags 0x%lx\n", addr, size, flags);
930d722e3fbSopenharmony_ci		free(bo_gem);
931d722e3fbSopenharmony_ci		return NULL;
932d722e3fbSopenharmony_ci	}
933d722e3fbSopenharmony_ci
934d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
935d722e3fbSopenharmony_ci
936d722e3fbSopenharmony_ci	bo_gem->gem_handle = userptr.handle;
937d722e3fbSopenharmony_ci	bo_gem->bo.handle = bo_gem->gem_handle;
938d722e3fbSopenharmony_ci	bo_gem->bo.bufmgr    = bufmgr;
939d722e3fbSopenharmony_ci	bo_gem->is_userptr   = true;
940d722e3fbSopenharmony_ci	bo_gem->bo.virtual   = addr;
941d722e3fbSopenharmony_ci	/* Save the address provided by user */
942d722e3fbSopenharmony_ci	bo_gem->user_virtual = addr;
943d722e3fbSopenharmony_ci	bo_gem->tiling_mode  = I915_TILING_NONE;
944d722e3fbSopenharmony_ci	bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
945d722e3fbSopenharmony_ci	bo_gem->stride       = 0;
946d722e3fbSopenharmony_ci
947d722e3fbSopenharmony_ci	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
948d722e3fbSopenharmony_ci		 gem_handle, sizeof(bo_gem->gem_handle),
949d722e3fbSopenharmony_ci		 bo_gem);
950d722e3fbSopenharmony_ci
951d722e3fbSopenharmony_ci	bo_gem->name = name;
952d722e3fbSopenharmony_ci	bo_gem->validate_index = -1;
953d722e3fbSopenharmony_ci	bo_gem->reloc_tree_fences = 0;
954d722e3fbSopenharmony_ci	bo_gem->used_as_reloc_target = false;
955d722e3fbSopenharmony_ci	bo_gem->has_error = false;
956d722e3fbSopenharmony_ci	bo_gem->reusable = false;
957d722e3fbSopenharmony_ci
958d722e3fbSopenharmony_ci	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
959d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
960d722e3fbSopenharmony_ci
961d722e3fbSopenharmony_ci	DBG("bo_create_userptr: "
962d722e3fbSopenharmony_ci	    "ptr %p buf %d (%s) size %ldb, stride 0x%x, tile mode %d\n",
963d722e3fbSopenharmony_ci		addr, bo_gem->gem_handle, bo_gem->name,
964d722e3fbSopenharmony_ci		size, stride, tiling_mode);
965d722e3fbSopenharmony_ci
966d722e3fbSopenharmony_ci	return &bo_gem->bo;
967d722e3fbSopenharmony_ci}
968d722e3fbSopenharmony_ci
969d722e3fbSopenharmony_cistatic bool
970d722e3fbSopenharmony_cihas_userptr(drm_intel_bufmgr_gem *bufmgr_gem)
971d722e3fbSopenharmony_ci{
972d722e3fbSopenharmony_ci	int ret;
973d722e3fbSopenharmony_ci	void *ptr;
974d722e3fbSopenharmony_ci	long pgsz;
975d722e3fbSopenharmony_ci	struct drm_i915_gem_userptr userptr;
976d722e3fbSopenharmony_ci
977d722e3fbSopenharmony_ci	pgsz = sysconf(_SC_PAGESIZE);
978d722e3fbSopenharmony_ci	assert(pgsz > 0);
979d722e3fbSopenharmony_ci
980d722e3fbSopenharmony_ci	ret = posix_memalign(&ptr, pgsz, pgsz);
981d722e3fbSopenharmony_ci	if (ret) {
982d722e3fbSopenharmony_ci		DBG("Failed to get a page (%ld) for userptr detection!\n",
983d722e3fbSopenharmony_ci			pgsz);
984d722e3fbSopenharmony_ci		return false;
985d722e3fbSopenharmony_ci	}
986d722e3fbSopenharmony_ci
987d722e3fbSopenharmony_ci	memclear(userptr);
988d722e3fbSopenharmony_ci	userptr.user_ptr = (__u64)(unsigned long)ptr;
989d722e3fbSopenharmony_ci	userptr.user_size = pgsz;
990d722e3fbSopenharmony_ci
991d722e3fbSopenharmony_ciretry:
992d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr);
993d722e3fbSopenharmony_ci	if (ret) {
994d722e3fbSopenharmony_ci		if (errno == ENODEV && userptr.flags == 0) {
995d722e3fbSopenharmony_ci			userptr.flags = I915_USERPTR_UNSYNCHRONIZED;
996d722e3fbSopenharmony_ci			goto retry;
997d722e3fbSopenharmony_ci		}
998d722e3fbSopenharmony_ci		free(ptr);
999d722e3fbSopenharmony_ci		return false;
1000d722e3fbSopenharmony_ci	}
1001d722e3fbSopenharmony_ci
1002d722e3fbSopenharmony_ci	/* We don't release the userptr bo here as we want to keep the
1003d722e3fbSopenharmony_ci	 * kernel mm tracking alive for our lifetime. The first time we
1004d722e3fbSopenharmony_ci	 * create a userptr object the kernel has to install a mmu_notifer
1005d722e3fbSopenharmony_ci	 * which is a heavyweight operation (e.g. it requires taking all
1006d722e3fbSopenharmony_ci	 * mm_locks and stop_machine()).
1007d722e3fbSopenharmony_ci	 */
1008d722e3fbSopenharmony_ci
1009d722e3fbSopenharmony_ci	bufmgr_gem->userptr_active.ptr = ptr;
1010d722e3fbSopenharmony_ci	bufmgr_gem->userptr_active.handle = userptr.handle;
1011d722e3fbSopenharmony_ci
1012d722e3fbSopenharmony_ci	return true;
1013d722e3fbSopenharmony_ci}
1014d722e3fbSopenharmony_ci
1015d722e3fbSopenharmony_cistatic drm_intel_bo *
1016d722e3fbSopenharmony_cicheck_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
1017d722e3fbSopenharmony_ci		       const char *name,
1018d722e3fbSopenharmony_ci		       void *addr,
1019d722e3fbSopenharmony_ci		       uint32_t tiling_mode,
1020d722e3fbSopenharmony_ci		       uint32_t stride,
1021d722e3fbSopenharmony_ci		       unsigned long size,
1022d722e3fbSopenharmony_ci		       unsigned long flags)
1023d722e3fbSopenharmony_ci{
1024d722e3fbSopenharmony_ci	if (has_userptr((drm_intel_bufmgr_gem *)bufmgr))
1025d722e3fbSopenharmony_ci		bufmgr->bo_alloc_userptr = drm_intel_gem_bo_alloc_userptr;
1026d722e3fbSopenharmony_ci	else
1027d722e3fbSopenharmony_ci		bufmgr->bo_alloc_userptr = NULL;
1028d722e3fbSopenharmony_ci
1029d722e3fbSopenharmony_ci	return drm_intel_bo_alloc_userptr(bufmgr, name, addr,
1030d722e3fbSopenharmony_ci					  tiling_mode, stride, size, flags);
1031d722e3fbSopenharmony_ci}
1032d722e3fbSopenharmony_ci
1033d722e3fbSopenharmony_cistatic int get_tiling_mode(drm_intel_bufmgr_gem *bufmgr_gem,
1034d722e3fbSopenharmony_ci			   uint32_t gem_handle,
1035d722e3fbSopenharmony_ci			   uint32_t *tiling_mode,
1036d722e3fbSopenharmony_ci			   uint32_t *swizzle_mode)
1037d722e3fbSopenharmony_ci{
1038d722e3fbSopenharmony_ci	struct drm_i915_gem_get_tiling get_tiling = {
1039d722e3fbSopenharmony_ci		.handle = gem_handle,
1040d722e3fbSopenharmony_ci	};
1041d722e3fbSopenharmony_ci	int ret;
1042d722e3fbSopenharmony_ci
1043d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
1044d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GEM_GET_TILING,
1045d722e3fbSopenharmony_ci		       &get_tiling);
1046d722e3fbSopenharmony_ci	if (ret != 0 && errno != EOPNOTSUPP)
1047d722e3fbSopenharmony_ci		return ret;
1048d722e3fbSopenharmony_ci
1049d722e3fbSopenharmony_ci	*tiling_mode = get_tiling.tiling_mode;
1050d722e3fbSopenharmony_ci	*swizzle_mode = get_tiling.swizzle_mode;
1051d722e3fbSopenharmony_ci
1052d722e3fbSopenharmony_ci	return 0;
1053d722e3fbSopenharmony_ci}
1054d722e3fbSopenharmony_ci
1055d722e3fbSopenharmony_ci/**
1056d722e3fbSopenharmony_ci * Returns a drm_intel_bo wrapping the given buffer object handle.
1057d722e3fbSopenharmony_ci *
1058d722e3fbSopenharmony_ci * This can be used when one application needs to pass a buffer object
1059d722e3fbSopenharmony_ci * to another.
1060d722e3fbSopenharmony_ci */
1061d722e3fbSopenharmony_cidrm_public drm_intel_bo *
1062d722e3fbSopenharmony_cidrm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr,
1063d722e3fbSopenharmony_ci				  const char *name,
1064d722e3fbSopenharmony_ci				  unsigned int handle)
1065d722e3fbSopenharmony_ci{
1066d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
1067d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem;
1068d722e3fbSopenharmony_ci	int ret;
1069d722e3fbSopenharmony_ci	struct drm_gem_open open_arg;
1070d722e3fbSopenharmony_ci
1071d722e3fbSopenharmony_ci	/* At the moment most applications only have a few named bo.
1072d722e3fbSopenharmony_ci	 * For instance, in a DRI client only the render buffers passed
1073d722e3fbSopenharmony_ci	 * between X and the client are named. And since X returns the
1074d722e3fbSopenharmony_ci	 * alternating names for the front/back buffer a linear search
1075d722e3fbSopenharmony_ci	 * provides a sufficiently fast match.
1076d722e3fbSopenharmony_ci	 */
1077d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
1078d722e3fbSopenharmony_ci	HASH_FIND(name_hh, bufmgr_gem->name_table,
1079d722e3fbSopenharmony_ci		  &handle, sizeof(handle), bo_gem);
1080d722e3fbSopenharmony_ci	if (bo_gem) {
1081d722e3fbSopenharmony_ci		drm_intel_gem_bo_reference(&bo_gem->bo);
1082d722e3fbSopenharmony_ci		goto out;
1083d722e3fbSopenharmony_ci	}
1084d722e3fbSopenharmony_ci
1085d722e3fbSopenharmony_ci	memclear(open_arg);
1086d722e3fbSopenharmony_ci	open_arg.name = handle;
1087d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
1088d722e3fbSopenharmony_ci		       DRM_IOCTL_GEM_OPEN,
1089d722e3fbSopenharmony_ci		       &open_arg);
1090d722e3fbSopenharmony_ci	if (ret != 0) {
1091d722e3fbSopenharmony_ci		DBG("Couldn't reference %s handle 0x%08x: %s\n",
1092d722e3fbSopenharmony_ci		    name, handle, strerror(errno));
1093d722e3fbSopenharmony_ci		bo_gem = NULL;
1094d722e3fbSopenharmony_ci		goto out;
1095d722e3fbSopenharmony_ci	}
1096d722e3fbSopenharmony_ci        /* Now see if someone has used a prime handle to get this
1097d722e3fbSopenharmony_ci         * object from the kernel before by looking through the list
1098d722e3fbSopenharmony_ci         * again for a matching gem_handle
1099d722e3fbSopenharmony_ci         */
1100d722e3fbSopenharmony_ci	HASH_FIND(handle_hh, bufmgr_gem->handle_table,
1101d722e3fbSopenharmony_ci		  &open_arg.handle, sizeof(open_arg.handle), bo_gem);
1102d722e3fbSopenharmony_ci	if (bo_gem) {
1103d722e3fbSopenharmony_ci		drm_intel_gem_bo_reference(&bo_gem->bo);
1104d722e3fbSopenharmony_ci		goto out;
1105d722e3fbSopenharmony_ci	}
1106d722e3fbSopenharmony_ci
1107d722e3fbSopenharmony_ci	bo_gem = calloc(1, sizeof(*bo_gem));
1108d722e3fbSopenharmony_ci	if (!bo_gem)
1109d722e3fbSopenharmony_ci		goto out;
1110d722e3fbSopenharmony_ci
1111d722e3fbSopenharmony_ci	atomic_set(&bo_gem->refcount, 1);
1112d722e3fbSopenharmony_ci	DRMINITLISTHEAD(&bo_gem->vma_list);
1113d722e3fbSopenharmony_ci
1114d722e3fbSopenharmony_ci	bo_gem->bo.size = open_arg.size;
1115d722e3fbSopenharmony_ci	bo_gem->bo.offset = 0;
1116d722e3fbSopenharmony_ci	bo_gem->bo.offset64 = 0;
1117d722e3fbSopenharmony_ci	bo_gem->bo.virtual = NULL;
1118d722e3fbSopenharmony_ci	bo_gem->bo.bufmgr = bufmgr;
1119d722e3fbSopenharmony_ci	bo_gem->name = name;
1120d722e3fbSopenharmony_ci	bo_gem->validate_index = -1;
1121d722e3fbSopenharmony_ci	bo_gem->gem_handle = open_arg.handle;
1122d722e3fbSopenharmony_ci	bo_gem->bo.handle = open_arg.handle;
1123d722e3fbSopenharmony_ci	bo_gem->global_name = handle;
1124d722e3fbSopenharmony_ci	bo_gem->reusable = false;
1125d722e3fbSopenharmony_ci
1126d722e3fbSopenharmony_ci	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
1127d722e3fbSopenharmony_ci		 gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
1128d722e3fbSopenharmony_ci	HASH_ADD(name_hh, bufmgr_gem->name_table,
1129d722e3fbSopenharmony_ci		 global_name, sizeof(bo_gem->global_name), bo_gem);
1130d722e3fbSopenharmony_ci
1131d722e3fbSopenharmony_ci	ret = get_tiling_mode(bufmgr_gem, bo_gem->gem_handle,
1132d722e3fbSopenharmony_ci			      &bo_gem->tiling_mode, &bo_gem->swizzle_mode);
1133d722e3fbSopenharmony_ci	if (ret != 0)
1134d722e3fbSopenharmony_ci		goto err_unref;
1135d722e3fbSopenharmony_ci
1136d722e3fbSopenharmony_ci	/* XXX stride is unknown */
1137d722e3fbSopenharmony_ci	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
1138d722e3fbSopenharmony_ci	DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
1139d722e3fbSopenharmony_ci
1140d722e3fbSopenharmony_ciout:
1141d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
1142d722e3fbSopenharmony_ci	return &bo_gem->bo;
1143d722e3fbSopenharmony_ci
1144d722e3fbSopenharmony_cierr_unref:
1145d722e3fbSopenharmony_ci	drm_intel_gem_bo_free(&bo_gem->bo);
1146d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
1147d722e3fbSopenharmony_ci	return NULL;
1148d722e3fbSopenharmony_ci}
1149d722e3fbSopenharmony_ci
1150d722e3fbSopenharmony_cistatic void
1151d722e3fbSopenharmony_cidrm_intel_gem_bo_free(drm_intel_bo *bo)
1152d722e3fbSopenharmony_ci{
1153d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1154d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1155d722e3fbSopenharmony_ci	int ret;
1156d722e3fbSopenharmony_ci
1157d722e3fbSopenharmony_ci	DRMLISTDEL(&bo_gem->vma_list);
1158d722e3fbSopenharmony_ci	if (bo_gem->mem_virtual) {
1159d722e3fbSopenharmony_ci		VG(VALGRIND_FREELIKE_BLOCK(bo_gem->mem_virtual, 0));
1160d722e3fbSopenharmony_ci		drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
1161d722e3fbSopenharmony_ci		bufmgr_gem->vma_count--;
1162d722e3fbSopenharmony_ci	}
1163d722e3fbSopenharmony_ci	if (bo_gem->wc_virtual) {
1164d722e3fbSopenharmony_ci		VG(VALGRIND_FREELIKE_BLOCK(bo_gem->wc_virtual, 0));
1165d722e3fbSopenharmony_ci		drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
1166d722e3fbSopenharmony_ci		bufmgr_gem->vma_count--;
1167d722e3fbSopenharmony_ci	}
1168d722e3fbSopenharmony_ci	if (bo_gem->gtt_virtual) {
1169d722e3fbSopenharmony_ci		drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
1170d722e3fbSopenharmony_ci		bufmgr_gem->vma_count--;
1171d722e3fbSopenharmony_ci	}
1172d722e3fbSopenharmony_ci
1173d722e3fbSopenharmony_ci	if (bo_gem->global_name)
1174d722e3fbSopenharmony_ci		HASH_DELETE(name_hh, bufmgr_gem->name_table, bo_gem);
1175d722e3fbSopenharmony_ci	HASH_DELETE(handle_hh, bufmgr_gem->handle_table, bo_gem);
1176d722e3fbSopenharmony_ci
1177d722e3fbSopenharmony_ci	/* Close this object */
1178d722e3fbSopenharmony_ci	ret = drmCloseBufferHandle(bufmgr_gem->fd, bo_gem->gem_handle);
1179d722e3fbSopenharmony_ci	if (ret != 0) {
1180d722e3fbSopenharmony_ci		DBG("drmCloseBufferHandle %d failed (%s): %s\n",
1181d722e3fbSopenharmony_ci		    bo_gem->gem_handle, bo_gem->name, strerror(errno));
1182d722e3fbSopenharmony_ci	}
1183d722e3fbSopenharmony_ci	free(bo);
1184d722e3fbSopenharmony_ci}
1185d722e3fbSopenharmony_ci
1186d722e3fbSopenharmony_cistatic void
1187d722e3fbSopenharmony_cidrm_intel_gem_bo_mark_mmaps_incoherent(drm_intel_bo *bo)
1188d722e3fbSopenharmony_ci{
1189d722e3fbSopenharmony_ci#if HAVE_VALGRIND
1190d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1191d722e3fbSopenharmony_ci
1192d722e3fbSopenharmony_ci	if (bo_gem->mem_virtual)
1193d722e3fbSopenharmony_ci		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size);
1194d722e3fbSopenharmony_ci
1195d722e3fbSopenharmony_ci	if (bo_gem->wc_virtual)
1196d722e3fbSopenharmony_ci		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->wc_virtual, bo->size);
1197d722e3fbSopenharmony_ci
1198d722e3fbSopenharmony_ci	if (bo_gem->gtt_virtual)
1199d722e3fbSopenharmony_ci		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size);
1200d722e3fbSopenharmony_ci#endif
1201d722e3fbSopenharmony_ci}
1202d722e3fbSopenharmony_ci
1203d722e3fbSopenharmony_ci/** Frees all cached buffers significantly older than @time. */
1204d722e3fbSopenharmony_cistatic void
1205d722e3fbSopenharmony_cidrm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time)
1206d722e3fbSopenharmony_ci{
1207d722e3fbSopenharmony_ci	int i;
1208d722e3fbSopenharmony_ci
1209d722e3fbSopenharmony_ci	if (bufmgr_gem->time == time)
1210d722e3fbSopenharmony_ci		return;
1211d722e3fbSopenharmony_ci
1212d722e3fbSopenharmony_ci	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
1213d722e3fbSopenharmony_ci		struct drm_intel_gem_bo_bucket *bucket =
1214d722e3fbSopenharmony_ci		    &bufmgr_gem->cache_bucket[i];
1215d722e3fbSopenharmony_ci
1216d722e3fbSopenharmony_ci		while (!DRMLISTEMPTY(&bucket->head)) {
1217d722e3fbSopenharmony_ci			drm_intel_bo_gem *bo_gem;
1218d722e3fbSopenharmony_ci
1219d722e3fbSopenharmony_ci			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
1220d722e3fbSopenharmony_ci					      bucket->head.next, head);
1221d722e3fbSopenharmony_ci			if (time - bo_gem->free_time <= 1)
1222d722e3fbSopenharmony_ci				break;
1223d722e3fbSopenharmony_ci
1224d722e3fbSopenharmony_ci			DRMLISTDEL(&bo_gem->head);
1225d722e3fbSopenharmony_ci
1226d722e3fbSopenharmony_ci			drm_intel_gem_bo_free(&bo_gem->bo);
1227d722e3fbSopenharmony_ci		}
1228d722e3fbSopenharmony_ci	}
1229d722e3fbSopenharmony_ci
1230d722e3fbSopenharmony_ci	bufmgr_gem->time = time;
1231d722e3fbSopenharmony_ci}
1232d722e3fbSopenharmony_ci
1233d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem)
1234d722e3fbSopenharmony_ci{
1235d722e3fbSopenharmony_ci	int limit;
1236d722e3fbSopenharmony_ci
1237d722e3fbSopenharmony_ci	DBG("%s: cached=%d, open=%d, limit=%d\n", __FUNCTION__,
1238d722e3fbSopenharmony_ci	    bufmgr_gem->vma_count, bufmgr_gem->vma_open, bufmgr_gem->vma_max);
1239d722e3fbSopenharmony_ci
1240d722e3fbSopenharmony_ci	if (bufmgr_gem->vma_max < 0)
1241d722e3fbSopenharmony_ci		return;
1242d722e3fbSopenharmony_ci
1243d722e3fbSopenharmony_ci	/* We may need to evict a few entries in order to create new mmaps */
1244d722e3fbSopenharmony_ci	limit = bufmgr_gem->vma_max - 2*bufmgr_gem->vma_open;
1245d722e3fbSopenharmony_ci	if (limit < 0)
1246d722e3fbSopenharmony_ci		limit = 0;
1247d722e3fbSopenharmony_ci
1248d722e3fbSopenharmony_ci	while (bufmgr_gem->vma_count > limit) {
1249d722e3fbSopenharmony_ci		drm_intel_bo_gem *bo_gem;
1250d722e3fbSopenharmony_ci
1251d722e3fbSopenharmony_ci		bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
1252d722e3fbSopenharmony_ci				      bufmgr_gem->vma_cache.next,
1253d722e3fbSopenharmony_ci				      vma_list);
1254d722e3fbSopenharmony_ci		assert(bo_gem->map_count == 0);
1255d722e3fbSopenharmony_ci		DRMLISTDELINIT(&bo_gem->vma_list);
1256d722e3fbSopenharmony_ci
1257d722e3fbSopenharmony_ci		if (bo_gem->mem_virtual) {
1258d722e3fbSopenharmony_ci			drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
1259d722e3fbSopenharmony_ci			bo_gem->mem_virtual = NULL;
1260d722e3fbSopenharmony_ci			bufmgr_gem->vma_count--;
1261d722e3fbSopenharmony_ci		}
1262d722e3fbSopenharmony_ci		if (bo_gem->wc_virtual) {
1263d722e3fbSopenharmony_ci			drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
1264d722e3fbSopenharmony_ci			bo_gem->wc_virtual = NULL;
1265d722e3fbSopenharmony_ci			bufmgr_gem->vma_count--;
1266d722e3fbSopenharmony_ci		}
1267d722e3fbSopenharmony_ci		if (bo_gem->gtt_virtual) {
1268d722e3fbSopenharmony_ci			drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
1269d722e3fbSopenharmony_ci			bo_gem->gtt_virtual = NULL;
1270d722e3fbSopenharmony_ci			bufmgr_gem->vma_count--;
1271d722e3fbSopenharmony_ci		}
1272d722e3fbSopenharmony_ci	}
1273d722e3fbSopenharmony_ci}
1274d722e3fbSopenharmony_ci
1275d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem,
1276d722e3fbSopenharmony_ci				       drm_intel_bo_gem *bo_gem)
1277d722e3fbSopenharmony_ci{
1278d722e3fbSopenharmony_ci	bufmgr_gem->vma_open--;
1279d722e3fbSopenharmony_ci	DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache);
1280d722e3fbSopenharmony_ci	if (bo_gem->mem_virtual)
1281d722e3fbSopenharmony_ci		bufmgr_gem->vma_count++;
1282d722e3fbSopenharmony_ci	if (bo_gem->wc_virtual)
1283d722e3fbSopenharmony_ci		bufmgr_gem->vma_count++;
1284d722e3fbSopenharmony_ci	if (bo_gem->gtt_virtual)
1285d722e3fbSopenharmony_ci		bufmgr_gem->vma_count++;
1286d722e3fbSopenharmony_ci	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
1287d722e3fbSopenharmony_ci}
1288d722e3fbSopenharmony_ci
1289d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem,
1290d722e3fbSopenharmony_ci				      drm_intel_bo_gem *bo_gem)
1291d722e3fbSopenharmony_ci{
1292d722e3fbSopenharmony_ci	bufmgr_gem->vma_open++;
1293d722e3fbSopenharmony_ci	DRMLISTDEL(&bo_gem->vma_list);
1294d722e3fbSopenharmony_ci	if (bo_gem->mem_virtual)
1295d722e3fbSopenharmony_ci		bufmgr_gem->vma_count--;
1296d722e3fbSopenharmony_ci	if (bo_gem->wc_virtual)
1297d722e3fbSopenharmony_ci		bufmgr_gem->vma_count--;
1298d722e3fbSopenharmony_ci	if (bo_gem->gtt_virtual)
1299d722e3fbSopenharmony_ci		bufmgr_gem->vma_count--;
1300d722e3fbSopenharmony_ci	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
1301d722e3fbSopenharmony_ci}
1302d722e3fbSopenharmony_ci
1303d722e3fbSopenharmony_cistatic void
1304d722e3fbSopenharmony_cidrm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time)
1305d722e3fbSopenharmony_ci{
1306d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1307d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1308d722e3fbSopenharmony_ci	struct drm_intel_gem_bo_bucket *bucket;
1309d722e3fbSopenharmony_ci	int i;
1310d722e3fbSopenharmony_ci
1311d722e3fbSopenharmony_ci	/* Unreference all the target buffers */
1312d722e3fbSopenharmony_ci	for (i = 0; i < bo_gem->reloc_count; i++) {
1313d722e3fbSopenharmony_ci		if (bo_gem->reloc_target_info[i].bo != bo) {
1314d722e3fbSopenharmony_ci			drm_intel_gem_bo_unreference_locked_timed(bo_gem->
1315d722e3fbSopenharmony_ci								  reloc_target_info[i].bo,
1316d722e3fbSopenharmony_ci								  time);
1317d722e3fbSopenharmony_ci		}
1318d722e3fbSopenharmony_ci	}
1319d722e3fbSopenharmony_ci	for (i = 0; i < bo_gem->softpin_target_count; i++)
1320d722e3fbSopenharmony_ci		drm_intel_gem_bo_unreference_locked_timed(bo_gem->softpin_target[i],
1321d722e3fbSopenharmony_ci								  time);
1322d722e3fbSopenharmony_ci	bo_gem->kflags = 0;
1323d722e3fbSopenharmony_ci	bo_gem->reloc_count = 0;
1324d722e3fbSopenharmony_ci	bo_gem->used_as_reloc_target = false;
1325d722e3fbSopenharmony_ci	bo_gem->softpin_target_count = 0;
1326d722e3fbSopenharmony_ci
1327d722e3fbSopenharmony_ci	DBG("bo_unreference final: %d (%s)\n",
1328d722e3fbSopenharmony_ci	    bo_gem->gem_handle, bo_gem->name);
1329d722e3fbSopenharmony_ci
1330d722e3fbSopenharmony_ci	/* release memory associated with this object */
1331d722e3fbSopenharmony_ci	if (bo_gem->reloc_target_info) {
1332d722e3fbSopenharmony_ci		free(bo_gem->reloc_target_info);
1333d722e3fbSopenharmony_ci		bo_gem->reloc_target_info = NULL;
1334d722e3fbSopenharmony_ci	}
1335d722e3fbSopenharmony_ci	if (bo_gem->relocs) {
1336d722e3fbSopenharmony_ci		free(bo_gem->relocs);
1337d722e3fbSopenharmony_ci		bo_gem->relocs = NULL;
1338d722e3fbSopenharmony_ci	}
1339d722e3fbSopenharmony_ci	if (bo_gem->softpin_target) {
1340d722e3fbSopenharmony_ci		free(bo_gem->softpin_target);
1341d722e3fbSopenharmony_ci		bo_gem->softpin_target = NULL;
1342d722e3fbSopenharmony_ci		bo_gem->softpin_target_size = 0;
1343d722e3fbSopenharmony_ci	}
1344d722e3fbSopenharmony_ci
1345d722e3fbSopenharmony_ci	/* Clear any left-over mappings */
1346d722e3fbSopenharmony_ci	if (bo_gem->map_count) {
1347d722e3fbSopenharmony_ci		DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count);
1348d722e3fbSopenharmony_ci		bo_gem->map_count = 0;
1349d722e3fbSopenharmony_ci		drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
1350d722e3fbSopenharmony_ci		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
1351d722e3fbSopenharmony_ci	}
1352d722e3fbSopenharmony_ci
1353d722e3fbSopenharmony_ci	bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
1354d722e3fbSopenharmony_ci	/* Put the buffer into our internal cache for reuse if we can. */
1355d722e3fbSopenharmony_ci	if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL &&
1356d722e3fbSopenharmony_ci	    drm_intel_gem_bo_madvise_internal(bufmgr_gem, bo_gem,
1357d722e3fbSopenharmony_ci					      I915_MADV_DONTNEED)) {
1358d722e3fbSopenharmony_ci		bo_gem->free_time = time;
1359d722e3fbSopenharmony_ci
1360d722e3fbSopenharmony_ci		bo_gem->name = NULL;
1361d722e3fbSopenharmony_ci		bo_gem->validate_index = -1;
1362d722e3fbSopenharmony_ci
1363d722e3fbSopenharmony_ci		DRMLISTADDTAIL(&bo_gem->head, &bucket->head);
1364d722e3fbSopenharmony_ci	} else {
1365d722e3fbSopenharmony_ci		drm_intel_gem_bo_free(bo);
1366d722e3fbSopenharmony_ci	}
1367d722e3fbSopenharmony_ci}
1368d722e3fbSopenharmony_ci
1369d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo,
1370d722e3fbSopenharmony_ci						      time_t time)
1371d722e3fbSopenharmony_ci{
1372d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1373d722e3fbSopenharmony_ci
1374d722e3fbSopenharmony_ci	assert(atomic_read(&bo_gem->refcount) > 0);
1375d722e3fbSopenharmony_ci	if (atomic_dec_and_test(&bo_gem->refcount))
1376d722e3fbSopenharmony_ci		drm_intel_gem_bo_unreference_final(bo, time);
1377d722e3fbSopenharmony_ci}
1378d722e3fbSopenharmony_ci
1379d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo)
1380d722e3fbSopenharmony_ci{
1381d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1382d722e3fbSopenharmony_ci
1383d722e3fbSopenharmony_ci	assert(atomic_read(&bo_gem->refcount) > 0);
1384d722e3fbSopenharmony_ci
1385d722e3fbSopenharmony_ci	if (atomic_add_unless(&bo_gem->refcount, -1, 1)) {
1386d722e3fbSopenharmony_ci		drm_intel_bufmgr_gem *bufmgr_gem =
1387d722e3fbSopenharmony_ci		    (drm_intel_bufmgr_gem *) bo->bufmgr;
1388d722e3fbSopenharmony_ci		struct timespec time;
1389d722e3fbSopenharmony_ci
1390d722e3fbSopenharmony_ci		clock_gettime(CLOCK_MONOTONIC, &time);
1391d722e3fbSopenharmony_ci
1392d722e3fbSopenharmony_ci		pthread_mutex_lock(&bufmgr_gem->lock);
1393d722e3fbSopenharmony_ci
1394d722e3fbSopenharmony_ci		if (atomic_dec_and_test(&bo_gem->refcount)) {
1395d722e3fbSopenharmony_ci			drm_intel_gem_bo_unreference_final(bo, time.tv_sec);
1396d722e3fbSopenharmony_ci			drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec);
1397d722e3fbSopenharmony_ci		}
1398d722e3fbSopenharmony_ci
1399d722e3fbSopenharmony_ci		pthread_mutex_unlock(&bufmgr_gem->lock);
1400d722e3fbSopenharmony_ci	}
1401d722e3fbSopenharmony_ci}
1402d722e3fbSopenharmony_ci
1403d722e3fbSopenharmony_cistatic int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
1404d722e3fbSopenharmony_ci{
1405d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1406d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1407d722e3fbSopenharmony_ci	struct drm_i915_gem_set_domain set_domain;
1408d722e3fbSopenharmony_ci	int ret;
1409d722e3fbSopenharmony_ci
1410d722e3fbSopenharmony_ci	if (bo_gem->is_userptr) {
1411d722e3fbSopenharmony_ci		/* Return the same user ptr */
1412d722e3fbSopenharmony_ci		bo->virtual = bo_gem->user_virtual;
1413d722e3fbSopenharmony_ci		return 0;
1414d722e3fbSopenharmony_ci	}
1415d722e3fbSopenharmony_ci
1416d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
1417d722e3fbSopenharmony_ci
1418d722e3fbSopenharmony_ci	if (bo_gem->map_count++ == 0)
1419d722e3fbSopenharmony_ci		drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
1420d722e3fbSopenharmony_ci
1421d722e3fbSopenharmony_ci	if (!bo_gem->mem_virtual) {
1422d722e3fbSopenharmony_ci		struct drm_i915_gem_mmap mmap_arg;
1423d722e3fbSopenharmony_ci
1424d722e3fbSopenharmony_ci		DBG("bo_map: %d (%s), map_count=%d\n",
1425d722e3fbSopenharmony_ci		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
1426d722e3fbSopenharmony_ci
1427d722e3fbSopenharmony_ci		memclear(mmap_arg);
1428d722e3fbSopenharmony_ci		mmap_arg.handle = bo_gem->gem_handle;
1429d722e3fbSopenharmony_ci		mmap_arg.size = bo->size;
1430d722e3fbSopenharmony_ci		ret = drmIoctl(bufmgr_gem->fd,
1431d722e3fbSopenharmony_ci			       DRM_IOCTL_I915_GEM_MMAP,
1432d722e3fbSopenharmony_ci			       &mmap_arg);
1433d722e3fbSopenharmony_ci		if (ret != 0) {
1434d722e3fbSopenharmony_ci			ret = -errno;
1435d722e3fbSopenharmony_ci			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
1436d722e3fbSopenharmony_ci			    __FILE__, __LINE__, bo_gem->gem_handle,
1437d722e3fbSopenharmony_ci			    bo_gem->name, strerror(errno));
1438d722e3fbSopenharmony_ci			if (--bo_gem->map_count == 0)
1439d722e3fbSopenharmony_ci				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
1440d722e3fbSopenharmony_ci			pthread_mutex_unlock(&bufmgr_gem->lock);
1441d722e3fbSopenharmony_ci			return ret;
1442d722e3fbSopenharmony_ci		}
1443d722e3fbSopenharmony_ci		VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
1444d722e3fbSopenharmony_ci		bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
1445d722e3fbSopenharmony_ci	}
1446d722e3fbSopenharmony_ci	DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
1447d722e3fbSopenharmony_ci	    bo_gem->mem_virtual);
1448d722e3fbSopenharmony_ci	bo->virtual = bo_gem->mem_virtual;
1449d722e3fbSopenharmony_ci
1450d722e3fbSopenharmony_ci	memclear(set_domain);
1451d722e3fbSopenharmony_ci	set_domain.handle = bo_gem->gem_handle;
1452d722e3fbSopenharmony_ci	set_domain.read_domains = I915_GEM_DOMAIN_CPU;
1453d722e3fbSopenharmony_ci	if (write_enable)
1454d722e3fbSopenharmony_ci		set_domain.write_domain = I915_GEM_DOMAIN_CPU;
1455d722e3fbSopenharmony_ci	else
1456d722e3fbSopenharmony_ci		set_domain.write_domain = 0;
1457d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
1458d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
1459d722e3fbSopenharmony_ci		       &set_domain);
1460d722e3fbSopenharmony_ci	if (ret != 0) {
1461d722e3fbSopenharmony_ci		DBG("%s:%d: Error setting to CPU domain %d: %s\n",
1462d722e3fbSopenharmony_ci		    __FILE__, __LINE__, bo_gem->gem_handle,
1463d722e3fbSopenharmony_ci		    strerror(errno));
1464d722e3fbSopenharmony_ci	}
1465d722e3fbSopenharmony_ci
1466d722e3fbSopenharmony_ci	if (write_enable)
1467d722e3fbSopenharmony_ci		bo_gem->mapped_cpu_write = true;
1468d722e3fbSopenharmony_ci
1469d722e3fbSopenharmony_ci	drm_intel_gem_bo_mark_mmaps_incoherent(bo);
1470d722e3fbSopenharmony_ci	VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->mem_virtual, bo->size));
1471d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
1472d722e3fbSopenharmony_ci
1473d722e3fbSopenharmony_ci	return 0;
1474d722e3fbSopenharmony_ci}
1475d722e3fbSopenharmony_ci
1476d722e3fbSopenharmony_cistatic int
1477d722e3fbSopenharmony_cimap_gtt(drm_intel_bo *bo)
1478d722e3fbSopenharmony_ci{
1479d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1480d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1481d722e3fbSopenharmony_ci	int ret;
1482d722e3fbSopenharmony_ci
1483d722e3fbSopenharmony_ci	if (bo_gem->is_userptr)
1484d722e3fbSopenharmony_ci		return -EINVAL;
1485d722e3fbSopenharmony_ci
1486d722e3fbSopenharmony_ci	if (bo_gem->map_count++ == 0)
1487d722e3fbSopenharmony_ci		drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
1488d722e3fbSopenharmony_ci
1489d722e3fbSopenharmony_ci	/* Get a mapping of the buffer if we haven't before. */
1490d722e3fbSopenharmony_ci	if (bo_gem->gtt_virtual == NULL) {
1491d722e3fbSopenharmony_ci		struct drm_i915_gem_mmap_gtt mmap_arg;
1492d722e3fbSopenharmony_ci
1493d722e3fbSopenharmony_ci		DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
1494d722e3fbSopenharmony_ci		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
1495d722e3fbSopenharmony_ci
1496d722e3fbSopenharmony_ci		memclear(mmap_arg);
1497d722e3fbSopenharmony_ci		mmap_arg.handle = bo_gem->gem_handle;
1498d722e3fbSopenharmony_ci
1499d722e3fbSopenharmony_ci		/* Get the fake offset back... */
1500d722e3fbSopenharmony_ci		ret = drmIoctl(bufmgr_gem->fd,
1501d722e3fbSopenharmony_ci			       DRM_IOCTL_I915_GEM_MMAP_GTT,
1502d722e3fbSopenharmony_ci			       &mmap_arg);
1503d722e3fbSopenharmony_ci		if (ret != 0) {
1504d722e3fbSopenharmony_ci			ret = -errno;
1505d722e3fbSopenharmony_ci			DBG("%s:%d: Error preparing buffer map %d (%s): %s .\n",
1506d722e3fbSopenharmony_ci			    __FILE__, __LINE__,
1507d722e3fbSopenharmony_ci			    bo_gem->gem_handle, bo_gem->name,
1508d722e3fbSopenharmony_ci			    strerror(errno));
1509d722e3fbSopenharmony_ci			if (--bo_gem->map_count == 0)
1510d722e3fbSopenharmony_ci				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
1511d722e3fbSopenharmony_ci			return ret;
1512d722e3fbSopenharmony_ci		}
1513d722e3fbSopenharmony_ci
1514d722e3fbSopenharmony_ci		/* and mmap it */
1515d722e3fbSopenharmony_ci		bo_gem->gtt_virtual = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE,
1516d722e3fbSopenharmony_ci					       MAP_SHARED, bufmgr_gem->fd,
1517d722e3fbSopenharmony_ci					       mmap_arg.offset);
1518d722e3fbSopenharmony_ci		if (bo_gem->gtt_virtual == MAP_FAILED) {
1519d722e3fbSopenharmony_ci			bo_gem->gtt_virtual = NULL;
1520d722e3fbSopenharmony_ci			ret = -errno;
1521d722e3fbSopenharmony_ci			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
1522d722e3fbSopenharmony_ci			    __FILE__, __LINE__,
1523d722e3fbSopenharmony_ci			    bo_gem->gem_handle, bo_gem->name,
1524d722e3fbSopenharmony_ci			    strerror(errno));
1525d722e3fbSopenharmony_ci			if (--bo_gem->map_count == 0)
1526d722e3fbSopenharmony_ci				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
1527d722e3fbSopenharmony_ci			return ret;
1528d722e3fbSopenharmony_ci		}
1529d722e3fbSopenharmony_ci	}
1530d722e3fbSopenharmony_ci
1531d722e3fbSopenharmony_ci	bo->virtual = bo_gem->gtt_virtual;
1532d722e3fbSopenharmony_ci
1533d722e3fbSopenharmony_ci	DBG("bo_map_gtt: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
1534d722e3fbSopenharmony_ci	    bo_gem->gtt_virtual);
1535d722e3fbSopenharmony_ci
1536d722e3fbSopenharmony_ci	return 0;
1537d722e3fbSopenharmony_ci}
1538d722e3fbSopenharmony_ci
1539d722e3fbSopenharmony_cidrm_public int
1540d722e3fbSopenharmony_cidrm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
1541d722e3fbSopenharmony_ci{
1542d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1543d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1544d722e3fbSopenharmony_ci	struct drm_i915_gem_set_domain set_domain;
1545d722e3fbSopenharmony_ci	int ret;
1546d722e3fbSopenharmony_ci
1547d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
1548d722e3fbSopenharmony_ci
1549d722e3fbSopenharmony_ci	ret = map_gtt(bo);
1550d722e3fbSopenharmony_ci	if (ret) {
1551d722e3fbSopenharmony_ci		pthread_mutex_unlock(&bufmgr_gem->lock);
1552d722e3fbSopenharmony_ci		return ret;
1553d722e3fbSopenharmony_ci	}
1554d722e3fbSopenharmony_ci
1555d722e3fbSopenharmony_ci	/* Now move it to the GTT domain so that the GPU and CPU
1556d722e3fbSopenharmony_ci	 * caches are flushed and the GPU isn't actively using the
1557d722e3fbSopenharmony_ci	 * buffer.
1558d722e3fbSopenharmony_ci	 *
1559d722e3fbSopenharmony_ci	 * The pagefault handler does this domain change for us when
1560d722e3fbSopenharmony_ci	 * it has unbound the BO from the GTT, but it's up to us to
1561d722e3fbSopenharmony_ci	 * tell it when we're about to use things if we had done
1562d722e3fbSopenharmony_ci	 * rendering and it still happens to be bound to the GTT.
1563d722e3fbSopenharmony_ci	 */
1564d722e3fbSopenharmony_ci	memclear(set_domain);
1565d722e3fbSopenharmony_ci	set_domain.handle = bo_gem->gem_handle;
1566d722e3fbSopenharmony_ci	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
1567d722e3fbSopenharmony_ci	set_domain.write_domain = I915_GEM_DOMAIN_GTT;
1568d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
1569d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
1570d722e3fbSopenharmony_ci		       &set_domain);
1571d722e3fbSopenharmony_ci	if (ret != 0) {
1572d722e3fbSopenharmony_ci		DBG("%s:%d: Error setting domain %d: %s\n",
1573d722e3fbSopenharmony_ci		    __FILE__, __LINE__, bo_gem->gem_handle,
1574d722e3fbSopenharmony_ci		    strerror(errno));
1575d722e3fbSopenharmony_ci	}
1576d722e3fbSopenharmony_ci
1577d722e3fbSopenharmony_ci	drm_intel_gem_bo_mark_mmaps_incoherent(bo);
1578d722e3fbSopenharmony_ci	VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size));
1579d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
1580d722e3fbSopenharmony_ci
1581d722e3fbSopenharmony_ci	return 0;
1582d722e3fbSopenharmony_ci}
1583d722e3fbSopenharmony_ci
1584d722e3fbSopenharmony_ci/**
1585d722e3fbSopenharmony_ci * Performs a mapping of the buffer object like the normal GTT
1586d722e3fbSopenharmony_ci * mapping, but avoids waiting for the GPU to be done reading from or
1587d722e3fbSopenharmony_ci * rendering to the buffer.
1588d722e3fbSopenharmony_ci *
1589d722e3fbSopenharmony_ci * This is used in the implementation of GL_ARB_map_buffer_range: The
1590d722e3fbSopenharmony_ci * user asks to create a buffer, then does a mapping, fills some
1591d722e3fbSopenharmony_ci * space, runs a drawing command, then asks to map it again without
1592d722e3fbSopenharmony_ci * synchronizing because it guarantees that it won't write over the
1593d722e3fbSopenharmony_ci * data that the GPU is busy using (or, more specifically, that if it
1594d722e3fbSopenharmony_ci * does write over the data, it acknowledges that rendering is
1595d722e3fbSopenharmony_ci * undefined).
1596d722e3fbSopenharmony_ci */
1597d722e3fbSopenharmony_ci
1598d722e3fbSopenharmony_cidrm_public int
1599d722e3fbSopenharmony_cidrm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo)
1600d722e3fbSopenharmony_ci{
1601d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1602d722e3fbSopenharmony_ci#if HAVE_VALGRIND
1603d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1604d722e3fbSopenharmony_ci#endif
1605d722e3fbSopenharmony_ci	int ret;
1606d722e3fbSopenharmony_ci
1607d722e3fbSopenharmony_ci	/* If the CPU cache isn't coherent with the GTT, then use a
1608d722e3fbSopenharmony_ci	 * regular synchronized mapping.  The problem is that we don't
1609d722e3fbSopenharmony_ci	 * track where the buffer was last used on the CPU side in
1610d722e3fbSopenharmony_ci	 * terms of drm_intel_bo_map vs drm_intel_gem_bo_map_gtt, so
1611d722e3fbSopenharmony_ci	 * we would potentially corrupt the buffer even when the user
1612d722e3fbSopenharmony_ci	 * does reasonable things.
1613d722e3fbSopenharmony_ci	 */
1614d722e3fbSopenharmony_ci	if (!bufmgr_gem->has_llc)
1615d722e3fbSopenharmony_ci		return drm_intel_gem_bo_map_gtt(bo);
1616d722e3fbSopenharmony_ci
1617d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
1618d722e3fbSopenharmony_ci
1619d722e3fbSopenharmony_ci	ret = map_gtt(bo);
1620d722e3fbSopenharmony_ci	if (ret == 0) {
1621d722e3fbSopenharmony_ci		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
1622d722e3fbSopenharmony_ci		VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size));
1623d722e3fbSopenharmony_ci	}
1624d722e3fbSopenharmony_ci
1625d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
1626d722e3fbSopenharmony_ci
1627d722e3fbSopenharmony_ci	return ret;
1628d722e3fbSopenharmony_ci}
1629d722e3fbSopenharmony_ci
1630d722e3fbSopenharmony_cistatic int drm_intel_gem_bo_unmap(drm_intel_bo *bo)
1631d722e3fbSopenharmony_ci{
1632d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem;
1633d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1634d722e3fbSopenharmony_ci	int ret = 0;
1635d722e3fbSopenharmony_ci
1636d722e3fbSopenharmony_ci	if (bo == NULL)
1637d722e3fbSopenharmony_ci		return 0;
1638d722e3fbSopenharmony_ci
1639d722e3fbSopenharmony_ci	if (bo_gem->is_userptr)
1640d722e3fbSopenharmony_ci		return 0;
1641d722e3fbSopenharmony_ci
1642d722e3fbSopenharmony_ci	bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1643d722e3fbSopenharmony_ci
1644d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
1645d722e3fbSopenharmony_ci
1646d722e3fbSopenharmony_ci	if (bo_gem->map_count <= 0) {
1647d722e3fbSopenharmony_ci		DBG("attempted to unmap an unmapped bo\n");
1648d722e3fbSopenharmony_ci		pthread_mutex_unlock(&bufmgr_gem->lock);
1649d722e3fbSopenharmony_ci		/* Preserve the old behaviour of just treating this as a
1650d722e3fbSopenharmony_ci		 * no-op rather than reporting the error.
1651d722e3fbSopenharmony_ci		 */
1652d722e3fbSopenharmony_ci		return 0;
1653d722e3fbSopenharmony_ci	}
1654d722e3fbSopenharmony_ci
1655d722e3fbSopenharmony_ci	if (bo_gem->mapped_cpu_write) {
1656d722e3fbSopenharmony_ci		struct drm_i915_gem_sw_finish sw_finish;
1657d722e3fbSopenharmony_ci
1658d722e3fbSopenharmony_ci		/* Cause a flush to happen if the buffer's pinned for
1659d722e3fbSopenharmony_ci		 * scanout, so the results show up in a timely manner.
1660d722e3fbSopenharmony_ci		 * Unlike GTT set domains, this only does work if the
1661d722e3fbSopenharmony_ci		 * buffer should be scanout-related.
1662d722e3fbSopenharmony_ci		 */
1663d722e3fbSopenharmony_ci		memclear(sw_finish);
1664d722e3fbSopenharmony_ci		sw_finish.handle = bo_gem->gem_handle;
1665d722e3fbSopenharmony_ci		ret = drmIoctl(bufmgr_gem->fd,
1666d722e3fbSopenharmony_ci			       DRM_IOCTL_I915_GEM_SW_FINISH,
1667d722e3fbSopenharmony_ci			       &sw_finish);
1668d722e3fbSopenharmony_ci		ret = ret == -1 ? -errno : 0;
1669d722e3fbSopenharmony_ci
1670d722e3fbSopenharmony_ci		bo_gem->mapped_cpu_write = false;
1671d722e3fbSopenharmony_ci	}
1672d722e3fbSopenharmony_ci
1673d722e3fbSopenharmony_ci	/* We need to unmap after every innovation as we cannot track
1674d722e3fbSopenharmony_ci	 * an open vma for every bo as that will exhaust the system
1675d722e3fbSopenharmony_ci	 * limits and cause later failures.
1676d722e3fbSopenharmony_ci	 */
1677d722e3fbSopenharmony_ci	if (--bo_gem->map_count == 0) {
1678d722e3fbSopenharmony_ci		drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
1679d722e3fbSopenharmony_ci		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
1680d722e3fbSopenharmony_ci		bo->virtual = NULL;
1681d722e3fbSopenharmony_ci	}
1682d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
1683d722e3fbSopenharmony_ci
1684d722e3fbSopenharmony_ci	return ret;
1685d722e3fbSopenharmony_ci}
1686d722e3fbSopenharmony_ci
1687d722e3fbSopenharmony_cidrm_public int
1688d722e3fbSopenharmony_cidrm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo)
1689d722e3fbSopenharmony_ci{
1690d722e3fbSopenharmony_ci	return drm_intel_gem_bo_unmap(bo);
1691d722e3fbSopenharmony_ci}
1692d722e3fbSopenharmony_ci
1693d722e3fbSopenharmony_cistatic bool is_cache_coherent(drm_intel_bo *bo)
1694d722e3fbSopenharmony_ci{
1695d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1696d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1697d722e3fbSopenharmony_ci	struct drm_i915_gem_caching arg = {};
1698d722e3fbSopenharmony_ci
1699d722e3fbSopenharmony_ci	arg.handle = bo_gem->gem_handle;
1700d722e3fbSopenharmony_ci	if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_CACHING, &arg))
1701d722e3fbSopenharmony_ci		assert(false);
1702d722e3fbSopenharmony_ci	return arg.caching != I915_CACHING_NONE;
1703d722e3fbSopenharmony_ci}
1704d722e3fbSopenharmony_ci
1705d722e3fbSopenharmony_cistatic void set_domain(drm_intel_bo *bo, uint32_t read, uint32_t write)
1706d722e3fbSopenharmony_ci{
1707d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1708d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1709d722e3fbSopenharmony_ci	struct drm_i915_gem_set_domain arg = {};
1710d722e3fbSopenharmony_ci
1711d722e3fbSopenharmony_ci	arg.handle = bo_gem->gem_handle;
1712d722e3fbSopenharmony_ci	arg.read_domains = read;
1713d722e3fbSopenharmony_ci	arg.write_domain = write;
1714d722e3fbSopenharmony_ci	if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &arg))
1715d722e3fbSopenharmony_ci		assert(false);
1716d722e3fbSopenharmony_ci}
1717d722e3fbSopenharmony_ci
1718d722e3fbSopenharmony_cistatic int mmap_write(drm_intel_bo *bo, unsigned long offset,
1719d722e3fbSopenharmony_ci		      unsigned long length, const void *buf)
1720d722e3fbSopenharmony_ci{
1721d722e3fbSopenharmony_ci	void *map = NULL;
1722d722e3fbSopenharmony_ci
1723d722e3fbSopenharmony_ci	if (!length)
1724d722e3fbSopenharmony_ci		return 0;
1725d722e3fbSopenharmony_ci
1726d722e3fbSopenharmony_ci	if (is_cache_coherent(bo)) {
1727d722e3fbSopenharmony_ci		map = drm_intel_gem_bo_map__cpu(bo);
1728d722e3fbSopenharmony_ci		if (map)
1729d722e3fbSopenharmony_ci			set_domain(bo, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
1730d722e3fbSopenharmony_ci	}
1731d722e3fbSopenharmony_ci	if (!map) {
1732d722e3fbSopenharmony_ci		map = drm_intel_gem_bo_map__wc(bo);
1733d722e3fbSopenharmony_ci		if (map)
1734d722e3fbSopenharmony_ci			set_domain(bo, I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
1735d722e3fbSopenharmony_ci	}
1736d722e3fbSopenharmony_ci
1737d722e3fbSopenharmony_ci	assert(map);
1738d722e3fbSopenharmony_ci	memcpy((char *)map + offset, buf, length);
1739d722e3fbSopenharmony_ci	drm_intel_gem_bo_unmap(bo);
1740d722e3fbSopenharmony_ci	return 0;
1741d722e3fbSopenharmony_ci}
1742d722e3fbSopenharmony_ci
1743d722e3fbSopenharmony_cistatic int mmap_read(drm_intel_bo *bo, unsigned long offset,
1744d722e3fbSopenharmony_ci		      unsigned long length, void *buf)
1745d722e3fbSopenharmony_ci{
1746d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1747d722e3fbSopenharmony_ci	void *map = NULL;
1748d722e3fbSopenharmony_ci
1749d722e3fbSopenharmony_ci	if (!length)
1750d722e3fbSopenharmony_ci		return 0;
1751d722e3fbSopenharmony_ci
1752d722e3fbSopenharmony_ci	if (bufmgr_gem->has_llc || is_cache_coherent(bo)) {
1753d722e3fbSopenharmony_ci		map = drm_intel_gem_bo_map__cpu(bo);
1754d722e3fbSopenharmony_ci		if (map)
1755d722e3fbSopenharmony_ci			set_domain(bo, I915_GEM_DOMAIN_CPU, 0);
1756d722e3fbSopenharmony_ci	}
1757d722e3fbSopenharmony_ci	if (!map) {
1758d722e3fbSopenharmony_ci		map = drm_intel_gem_bo_map__wc(bo);
1759d722e3fbSopenharmony_ci		if (map)
1760d722e3fbSopenharmony_ci			set_domain(bo, I915_GEM_DOMAIN_WC, 0);
1761d722e3fbSopenharmony_ci	}
1762d722e3fbSopenharmony_ci
1763d722e3fbSopenharmony_ci	assert(map);
1764d722e3fbSopenharmony_ci	memcpy(buf, (char *)map + offset, length);
1765d722e3fbSopenharmony_ci	drm_intel_gem_bo_unmap(bo);
1766d722e3fbSopenharmony_ci	return 0;
1767d722e3fbSopenharmony_ci}
1768d722e3fbSopenharmony_ci
1769d722e3fbSopenharmony_cistatic int
1770d722e3fbSopenharmony_cidrm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset,
1771d722e3fbSopenharmony_ci			 unsigned long size, const void *data)
1772d722e3fbSopenharmony_ci{
1773d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1774d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1775d722e3fbSopenharmony_ci	struct drm_i915_gem_pwrite pwrite;
1776d722e3fbSopenharmony_ci	int ret;
1777d722e3fbSopenharmony_ci
1778d722e3fbSopenharmony_ci	if (bo_gem->is_userptr)
1779d722e3fbSopenharmony_ci		return -EINVAL;
1780d722e3fbSopenharmony_ci
1781d722e3fbSopenharmony_ci	memclear(pwrite);
1782d722e3fbSopenharmony_ci	pwrite.handle = bo_gem->gem_handle;
1783d722e3fbSopenharmony_ci	pwrite.offset = offset;
1784d722e3fbSopenharmony_ci	pwrite.size = size;
1785d722e3fbSopenharmony_ci	pwrite.data_ptr = (uint64_t) (uintptr_t) data;
1786d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
1787d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GEM_PWRITE,
1788d722e3fbSopenharmony_ci		       &pwrite);
1789d722e3fbSopenharmony_ci	if (ret)
1790d722e3fbSopenharmony_ci		ret = -errno;
1791d722e3fbSopenharmony_ci
1792d722e3fbSopenharmony_ci	if (ret != 0 && ret != -EOPNOTSUPP) {
1793d722e3fbSopenharmony_ci		DBG("%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
1794d722e3fbSopenharmony_ci		    __FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
1795d722e3fbSopenharmony_ci		    (int)size, strerror(errno));
1796d722e3fbSopenharmony_ci		return ret;
1797d722e3fbSopenharmony_ci	}
1798d722e3fbSopenharmony_ci
1799d722e3fbSopenharmony_ci	if (ret == -EOPNOTSUPP)
1800d722e3fbSopenharmony_ci		mmap_write(bo, offset, size, data);
1801d722e3fbSopenharmony_ci
1802d722e3fbSopenharmony_ci	return 0;
1803d722e3fbSopenharmony_ci}
1804d722e3fbSopenharmony_ci
1805d722e3fbSopenharmony_cistatic int
1806d722e3fbSopenharmony_cidrm_intel_gem_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id)
1807d722e3fbSopenharmony_ci{
1808d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
1809d722e3fbSopenharmony_ci	struct drm_i915_get_pipe_from_crtc_id get_pipe_from_crtc_id;
1810d722e3fbSopenharmony_ci	int ret;
1811d722e3fbSopenharmony_ci
1812d722e3fbSopenharmony_ci	memclear(get_pipe_from_crtc_id);
1813d722e3fbSopenharmony_ci	get_pipe_from_crtc_id.crtc_id = crtc_id;
1814d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
1815d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID,
1816d722e3fbSopenharmony_ci		       &get_pipe_from_crtc_id);
1817d722e3fbSopenharmony_ci	if (ret != 0) {
1818d722e3fbSopenharmony_ci		/* We return -1 here to signal that we don't
1819d722e3fbSopenharmony_ci		 * know which pipe is associated with this crtc.
1820d722e3fbSopenharmony_ci		 * This lets the caller know that this information
1821d722e3fbSopenharmony_ci		 * isn't available; using the wrong pipe for
1822d722e3fbSopenharmony_ci		 * vblank waiting can cause the chipset to lock up
1823d722e3fbSopenharmony_ci		 */
1824d722e3fbSopenharmony_ci		return -1;
1825d722e3fbSopenharmony_ci	}
1826d722e3fbSopenharmony_ci
1827d722e3fbSopenharmony_ci	return get_pipe_from_crtc_id.pipe;
1828d722e3fbSopenharmony_ci}
1829d722e3fbSopenharmony_ci
1830d722e3fbSopenharmony_cistatic int
1831d722e3fbSopenharmony_cidrm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset,
1832d722e3fbSopenharmony_ci			     unsigned long size, void *data)
1833d722e3fbSopenharmony_ci{
1834d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1835d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1836d722e3fbSopenharmony_ci	struct drm_i915_gem_pread pread;
1837d722e3fbSopenharmony_ci	int ret;
1838d722e3fbSopenharmony_ci
1839d722e3fbSopenharmony_ci	if (bo_gem->is_userptr)
1840d722e3fbSopenharmony_ci		return -EINVAL;
1841d722e3fbSopenharmony_ci
1842d722e3fbSopenharmony_ci	memclear(pread);
1843d722e3fbSopenharmony_ci	pread.handle = bo_gem->gem_handle;
1844d722e3fbSopenharmony_ci	pread.offset = offset;
1845d722e3fbSopenharmony_ci	pread.size = size;
1846d722e3fbSopenharmony_ci	pread.data_ptr = (uint64_t) (uintptr_t) data;
1847d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
1848d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GEM_PREAD,
1849d722e3fbSopenharmony_ci		       &pread);
1850d722e3fbSopenharmony_ci	if (ret)
1851d722e3fbSopenharmony_ci		ret = -errno;
1852d722e3fbSopenharmony_ci
1853d722e3fbSopenharmony_ci	if (ret != 0 && ret != -EOPNOTSUPP) {
1854d722e3fbSopenharmony_ci		DBG("%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
1855d722e3fbSopenharmony_ci		    __FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
1856d722e3fbSopenharmony_ci		    (int)size, strerror(errno));
1857d722e3fbSopenharmony_ci		return ret;
1858d722e3fbSopenharmony_ci	}
1859d722e3fbSopenharmony_ci
1860d722e3fbSopenharmony_ci	if (ret == -EOPNOTSUPP)
1861d722e3fbSopenharmony_ci		mmap_read(bo, offset, size, data);
1862d722e3fbSopenharmony_ci
1863d722e3fbSopenharmony_ci	return 0;
1864d722e3fbSopenharmony_ci}
1865d722e3fbSopenharmony_ci
1866d722e3fbSopenharmony_ci/** Waits for all GPU rendering with the object to have completed. */
1867d722e3fbSopenharmony_cistatic void
1868d722e3fbSopenharmony_cidrm_intel_gem_bo_wait_rendering(drm_intel_bo *bo)
1869d722e3fbSopenharmony_ci{
1870d722e3fbSopenharmony_ci	drm_intel_gem_bo_start_gtt_access(bo, 1);
1871d722e3fbSopenharmony_ci}
1872d722e3fbSopenharmony_ci
1873d722e3fbSopenharmony_ci/**
1874d722e3fbSopenharmony_ci * Waits on a BO for the given amount of time.
1875d722e3fbSopenharmony_ci *
1876d722e3fbSopenharmony_ci * @bo: buffer object to wait for
1877d722e3fbSopenharmony_ci * @timeout_ns: amount of time to wait in nanoseconds.
1878d722e3fbSopenharmony_ci *   If value is less than 0, an infinite wait will occur.
1879d722e3fbSopenharmony_ci *
1880d722e3fbSopenharmony_ci * Returns 0 if the wait was successful ie. the last batch referencing the
1881d722e3fbSopenharmony_ci * object has completed within the allotted time. Otherwise some negative return
1882d722e3fbSopenharmony_ci * value describes the error. Of particular interest is -ETIME when the wait has
1883d722e3fbSopenharmony_ci * failed to yield the desired result.
1884d722e3fbSopenharmony_ci *
1885d722e3fbSopenharmony_ci * Similar to drm_intel_gem_bo_wait_rendering except a timeout parameter allows
1886d722e3fbSopenharmony_ci * the operation to give up after a certain amount of time. Another subtle
1887d722e3fbSopenharmony_ci * difference is the internal locking semantics are different (this variant does
1888d722e3fbSopenharmony_ci * not hold the lock for the duration of the wait). This makes the wait subject
1889d722e3fbSopenharmony_ci * to a larger userspace race window.
1890d722e3fbSopenharmony_ci *
1891d722e3fbSopenharmony_ci * The implementation shall wait until the object is no longer actively
1892d722e3fbSopenharmony_ci * referenced within a batch buffer at the time of the call. The wait will
1893d722e3fbSopenharmony_ci * not guarantee that the buffer is re-issued via another thread, or an flinked
1894d722e3fbSopenharmony_ci * handle. Userspace must make sure this race does not occur if such precision
1895d722e3fbSopenharmony_ci * is important.
1896d722e3fbSopenharmony_ci *
1897d722e3fbSopenharmony_ci * Note that some kernels have broken the inifite wait for negative values
1898d722e3fbSopenharmony_ci * promise, upgrade to latest stable kernels if this is the case.
1899d722e3fbSopenharmony_ci */
1900d722e3fbSopenharmony_cidrm_public int
1901d722e3fbSopenharmony_cidrm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns)
1902d722e3fbSopenharmony_ci{
1903d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1904d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1905d722e3fbSopenharmony_ci	struct drm_i915_gem_wait wait;
1906d722e3fbSopenharmony_ci	int ret;
1907d722e3fbSopenharmony_ci
1908d722e3fbSopenharmony_ci	if (!bufmgr_gem->has_wait_timeout) {
1909d722e3fbSopenharmony_ci		DBG("%s:%d: Timed wait is not supported. Falling back to "
1910d722e3fbSopenharmony_ci		    "infinite wait\n", __FILE__, __LINE__);
1911d722e3fbSopenharmony_ci		if (timeout_ns) {
1912d722e3fbSopenharmony_ci			drm_intel_gem_bo_wait_rendering(bo);
1913d722e3fbSopenharmony_ci			return 0;
1914d722e3fbSopenharmony_ci		} else {
1915d722e3fbSopenharmony_ci			return drm_intel_gem_bo_busy(bo) ? -ETIME : 0;
1916d722e3fbSopenharmony_ci		}
1917d722e3fbSopenharmony_ci	}
1918d722e3fbSopenharmony_ci
1919d722e3fbSopenharmony_ci	memclear(wait);
1920d722e3fbSopenharmony_ci	wait.bo_handle = bo_gem->gem_handle;
1921d722e3fbSopenharmony_ci	wait.timeout_ns = timeout_ns;
1922d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
1923d722e3fbSopenharmony_ci	if (ret == -1)
1924d722e3fbSopenharmony_ci		return -errno;
1925d722e3fbSopenharmony_ci
1926d722e3fbSopenharmony_ci	return ret;
1927d722e3fbSopenharmony_ci}
1928d722e3fbSopenharmony_ci
1929d722e3fbSopenharmony_ci/**
1930d722e3fbSopenharmony_ci * Sets the object to the GTT read and possibly write domain, used by the X
1931d722e3fbSopenharmony_ci * 2D driver in the absence of kernel support to do drm_intel_gem_bo_map_gtt().
1932d722e3fbSopenharmony_ci *
1933d722e3fbSopenharmony_ci * In combination with drm_intel_gem_bo_pin() and manual fence management, we
1934d722e3fbSopenharmony_ci * can do tiled pixmaps this way.
1935d722e3fbSopenharmony_ci */
1936d722e3fbSopenharmony_cidrm_public void
1937d722e3fbSopenharmony_cidrm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable)
1938d722e3fbSopenharmony_ci{
1939d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1940d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
1941d722e3fbSopenharmony_ci	struct drm_i915_gem_set_domain set_domain;
1942d722e3fbSopenharmony_ci	int ret;
1943d722e3fbSopenharmony_ci
1944d722e3fbSopenharmony_ci	memclear(set_domain);
1945d722e3fbSopenharmony_ci	set_domain.handle = bo_gem->gem_handle;
1946d722e3fbSopenharmony_ci	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
1947d722e3fbSopenharmony_ci	set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_GTT : 0;
1948d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
1949d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
1950d722e3fbSopenharmony_ci		       &set_domain);
1951d722e3fbSopenharmony_ci	if (ret != 0) {
1952d722e3fbSopenharmony_ci		DBG("%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
1953d722e3fbSopenharmony_ci		    __FILE__, __LINE__, bo_gem->gem_handle,
1954d722e3fbSopenharmony_ci		    set_domain.read_domains, set_domain.write_domain,
1955d722e3fbSopenharmony_ci		    strerror(errno));
1956d722e3fbSopenharmony_ci	}
1957d722e3fbSopenharmony_ci}
1958d722e3fbSopenharmony_ci
1959d722e3fbSopenharmony_cistatic void
1960d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr)
1961d722e3fbSopenharmony_ci{
1962d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
1963d722e3fbSopenharmony_ci	int i, ret;
1964d722e3fbSopenharmony_ci
1965d722e3fbSopenharmony_ci	free(bufmgr_gem->exec2_objects);
1966d722e3fbSopenharmony_ci	free(bufmgr_gem->exec_bos);
1967d722e3fbSopenharmony_ci
1968d722e3fbSopenharmony_ci	pthread_mutex_destroy(&bufmgr_gem->lock);
1969d722e3fbSopenharmony_ci
1970d722e3fbSopenharmony_ci	/* Free any cached buffer objects we were going to reuse */
1971d722e3fbSopenharmony_ci	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
1972d722e3fbSopenharmony_ci		struct drm_intel_gem_bo_bucket *bucket =
1973d722e3fbSopenharmony_ci		    &bufmgr_gem->cache_bucket[i];
1974d722e3fbSopenharmony_ci		drm_intel_bo_gem *bo_gem;
1975d722e3fbSopenharmony_ci
1976d722e3fbSopenharmony_ci		while (!DRMLISTEMPTY(&bucket->head)) {
1977d722e3fbSopenharmony_ci			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
1978d722e3fbSopenharmony_ci					      bucket->head.next, head);
1979d722e3fbSopenharmony_ci			DRMLISTDEL(&bo_gem->head);
1980d722e3fbSopenharmony_ci
1981d722e3fbSopenharmony_ci			drm_intel_gem_bo_free(&bo_gem->bo);
1982d722e3fbSopenharmony_ci		}
1983d722e3fbSopenharmony_ci	}
1984d722e3fbSopenharmony_ci
1985d722e3fbSopenharmony_ci	/* Release userptr bo kept hanging around for optimisation. */
1986d722e3fbSopenharmony_ci	if (bufmgr_gem->userptr_active.ptr) {
1987d722e3fbSopenharmony_ci		ret = drmCloseBufferHandle(bufmgr_gem->fd,
1988d722e3fbSopenharmony_ci					   bufmgr_gem->userptr_active.handle);
1989d722e3fbSopenharmony_ci		free(bufmgr_gem->userptr_active.ptr);
1990d722e3fbSopenharmony_ci		if (ret)
1991d722e3fbSopenharmony_ci			fprintf(stderr,
1992d722e3fbSopenharmony_ci				"Failed to release test userptr object! (%d) "
1993d722e3fbSopenharmony_ci				"i915 kernel driver may not be sane!\n", errno);
1994d722e3fbSopenharmony_ci	}
1995d722e3fbSopenharmony_ci
1996d722e3fbSopenharmony_ci	free(bufmgr);
1997d722e3fbSopenharmony_ci}
1998d722e3fbSopenharmony_ci
1999d722e3fbSopenharmony_ci/**
2000d722e3fbSopenharmony_ci * Adds the target buffer to the validation list and adds the relocation
2001d722e3fbSopenharmony_ci * to the reloc_buffer's relocation list.
2002d722e3fbSopenharmony_ci *
2003d722e3fbSopenharmony_ci * The relocation entry at the given offset must already contain the
2004d722e3fbSopenharmony_ci * precomputed relocation value, because the kernel will optimize out
2005d722e3fbSopenharmony_ci * the relocation entry write when the buffer hasn't moved from the
2006d722e3fbSopenharmony_ci * last known offset in target_bo.
2007d722e3fbSopenharmony_ci */
2008d722e3fbSopenharmony_cistatic int
2009d722e3fbSopenharmony_cido_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
2010d722e3fbSopenharmony_ci		 drm_intel_bo *target_bo, uint32_t target_offset,
2011d722e3fbSopenharmony_ci		 uint32_t read_domains, uint32_t write_domain,
2012d722e3fbSopenharmony_ci		 bool need_fence)
2013d722e3fbSopenharmony_ci{
2014d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2015d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2016d722e3fbSopenharmony_ci	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
2017d722e3fbSopenharmony_ci	bool fenced_command;
2018d722e3fbSopenharmony_ci
2019d722e3fbSopenharmony_ci	if (bo_gem->has_error)
2020d722e3fbSopenharmony_ci		return -ENOMEM;
2021d722e3fbSopenharmony_ci
2022d722e3fbSopenharmony_ci	if (target_bo_gem->has_error) {
2023d722e3fbSopenharmony_ci		bo_gem->has_error = true;
2024d722e3fbSopenharmony_ci		return -ENOMEM;
2025d722e3fbSopenharmony_ci	}
2026d722e3fbSopenharmony_ci
2027d722e3fbSopenharmony_ci	/* We never use HW fences for rendering on 965+ */
2028d722e3fbSopenharmony_ci	if (bufmgr_gem->gen >= 4)
2029d722e3fbSopenharmony_ci		need_fence = false;
2030d722e3fbSopenharmony_ci
2031d722e3fbSopenharmony_ci	fenced_command = need_fence;
2032d722e3fbSopenharmony_ci	if (target_bo_gem->tiling_mode == I915_TILING_NONE)
2033d722e3fbSopenharmony_ci		need_fence = false;
2034d722e3fbSopenharmony_ci
2035d722e3fbSopenharmony_ci	/* Create a new relocation list if needed */
2036d722e3fbSopenharmony_ci	if (bo_gem->relocs == NULL && drm_intel_setup_reloc_list(bo))
2037d722e3fbSopenharmony_ci		return -ENOMEM;
2038d722e3fbSopenharmony_ci
2039d722e3fbSopenharmony_ci	/* Check overflow */
2040d722e3fbSopenharmony_ci	assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
2041d722e3fbSopenharmony_ci
2042d722e3fbSopenharmony_ci	/* Check args */
2043d722e3fbSopenharmony_ci	assert(offset <= bo->size - 4);
2044d722e3fbSopenharmony_ci	assert((write_domain & (write_domain - 1)) == 0);
2045d722e3fbSopenharmony_ci
2046d722e3fbSopenharmony_ci	/* An object needing a fence is a tiled buffer, so it won't have
2047d722e3fbSopenharmony_ci	 * relocs to other buffers.
2048d722e3fbSopenharmony_ci	 */
2049d722e3fbSopenharmony_ci	if (need_fence) {
2050d722e3fbSopenharmony_ci		assert(target_bo_gem->reloc_count == 0);
2051d722e3fbSopenharmony_ci		target_bo_gem->reloc_tree_fences = 1;
2052d722e3fbSopenharmony_ci	}
2053d722e3fbSopenharmony_ci
2054d722e3fbSopenharmony_ci	/* Make sure that we're not adding a reloc to something whose size has
2055d722e3fbSopenharmony_ci	 * already been accounted for.
2056d722e3fbSopenharmony_ci	 */
2057d722e3fbSopenharmony_ci	assert(!bo_gem->used_as_reloc_target);
2058d722e3fbSopenharmony_ci	if (target_bo_gem != bo_gem) {
2059d722e3fbSopenharmony_ci		target_bo_gem->used_as_reloc_target = true;
2060d722e3fbSopenharmony_ci		bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size;
2061d722e3fbSopenharmony_ci		bo_gem->reloc_tree_fences += target_bo_gem->reloc_tree_fences;
2062d722e3fbSopenharmony_ci	}
2063d722e3fbSopenharmony_ci
2064d722e3fbSopenharmony_ci	bo_gem->reloc_target_info[bo_gem->reloc_count].bo = target_bo;
2065d722e3fbSopenharmony_ci	if (target_bo != bo)
2066d722e3fbSopenharmony_ci		drm_intel_gem_bo_reference(target_bo);
2067d722e3fbSopenharmony_ci	if (fenced_command)
2068d722e3fbSopenharmony_ci		bo_gem->reloc_target_info[bo_gem->reloc_count].flags =
2069d722e3fbSopenharmony_ci			DRM_INTEL_RELOC_FENCE;
2070d722e3fbSopenharmony_ci	else
2071d722e3fbSopenharmony_ci		bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 0;
2072d722e3fbSopenharmony_ci
2073d722e3fbSopenharmony_ci	bo_gem->relocs[bo_gem->reloc_count].offset = offset;
2074d722e3fbSopenharmony_ci	bo_gem->relocs[bo_gem->reloc_count].delta = target_offset;
2075d722e3fbSopenharmony_ci	bo_gem->relocs[bo_gem->reloc_count].target_handle =
2076d722e3fbSopenharmony_ci	    target_bo_gem->gem_handle;
2077d722e3fbSopenharmony_ci	bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
2078d722e3fbSopenharmony_ci	bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
2079d722e3fbSopenharmony_ci	bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset64;
2080d722e3fbSopenharmony_ci	bo_gem->reloc_count++;
2081d722e3fbSopenharmony_ci
2082d722e3fbSopenharmony_ci	return 0;
2083d722e3fbSopenharmony_ci}
2084d722e3fbSopenharmony_ci
2085d722e3fbSopenharmony_cistatic void
2086d722e3fbSopenharmony_cidrm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable)
2087d722e3fbSopenharmony_ci{
2088d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2089d722e3fbSopenharmony_ci
2090d722e3fbSopenharmony_ci	if (enable)
2091d722e3fbSopenharmony_ci		bo_gem->kflags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
2092d722e3fbSopenharmony_ci	else
2093d722e3fbSopenharmony_ci		bo_gem->kflags &= ~EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
2094d722e3fbSopenharmony_ci}
2095d722e3fbSopenharmony_ci
2096d722e3fbSopenharmony_cistatic int
2097d722e3fbSopenharmony_cidrm_intel_gem_bo_add_softpin_target(drm_intel_bo *bo, drm_intel_bo *target_bo)
2098d722e3fbSopenharmony_ci{
2099d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2100d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2101d722e3fbSopenharmony_ci	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
2102d722e3fbSopenharmony_ci	if (bo_gem->has_error)
2103d722e3fbSopenharmony_ci		return -ENOMEM;
2104d722e3fbSopenharmony_ci
2105d722e3fbSopenharmony_ci	if (target_bo_gem->has_error) {
2106d722e3fbSopenharmony_ci		bo_gem->has_error = true;
2107d722e3fbSopenharmony_ci		return -ENOMEM;
2108d722e3fbSopenharmony_ci	}
2109d722e3fbSopenharmony_ci
2110d722e3fbSopenharmony_ci	if (!(target_bo_gem->kflags & EXEC_OBJECT_PINNED))
2111d722e3fbSopenharmony_ci		return -EINVAL;
2112d722e3fbSopenharmony_ci	if (target_bo_gem == bo_gem)
2113d722e3fbSopenharmony_ci		return -EINVAL;
2114d722e3fbSopenharmony_ci
2115d722e3fbSopenharmony_ci	if (bo_gem->softpin_target_count == bo_gem->softpin_target_size) {
2116d722e3fbSopenharmony_ci		int new_size = bo_gem->softpin_target_size * 2;
2117d722e3fbSopenharmony_ci		if (new_size == 0)
2118d722e3fbSopenharmony_ci			new_size = bufmgr_gem->max_relocs;
2119d722e3fbSopenharmony_ci
2120d722e3fbSopenharmony_ci		bo_gem->softpin_target = realloc(bo_gem->softpin_target, new_size *
2121d722e3fbSopenharmony_ci				sizeof(drm_intel_bo *));
2122d722e3fbSopenharmony_ci		if (!bo_gem->softpin_target)
2123d722e3fbSopenharmony_ci			return -ENOMEM;
2124d722e3fbSopenharmony_ci
2125d722e3fbSopenharmony_ci		bo_gem->softpin_target_size = new_size;
2126d722e3fbSopenharmony_ci	}
2127d722e3fbSopenharmony_ci	bo_gem->softpin_target[bo_gem->softpin_target_count] = target_bo;
2128d722e3fbSopenharmony_ci	drm_intel_gem_bo_reference(target_bo);
2129d722e3fbSopenharmony_ci	bo_gem->softpin_target_count++;
2130d722e3fbSopenharmony_ci
2131d722e3fbSopenharmony_ci	return 0;
2132d722e3fbSopenharmony_ci}
2133d722e3fbSopenharmony_ci
2134d722e3fbSopenharmony_cistatic int
2135d722e3fbSopenharmony_cidrm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
2136d722e3fbSopenharmony_ci			    drm_intel_bo *target_bo, uint32_t target_offset,
2137d722e3fbSopenharmony_ci			    uint32_t read_domains, uint32_t write_domain)
2138d722e3fbSopenharmony_ci{
2139d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
2140d722e3fbSopenharmony_ci	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo;
2141d722e3fbSopenharmony_ci
2142d722e3fbSopenharmony_ci	if (target_bo_gem->kflags & EXEC_OBJECT_PINNED)
2143d722e3fbSopenharmony_ci		return drm_intel_gem_bo_add_softpin_target(bo, target_bo);
2144d722e3fbSopenharmony_ci	else
2145d722e3fbSopenharmony_ci		return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
2146d722e3fbSopenharmony_ci					read_domains, write_domain,
2147d722e3fbSopenharmony_ci					!bufmgr_gem->fenced_relocs);
2148d722e3fbSopenharmony_ci}
2149d722e3fbSopenharmony_ci
2150d722e3fbSopenharmony_cistatic int
2151d722e3fbSopenharmony_cidrm_intel_gem_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset,
2152d722e3fbSopenharmony_ci				  drm_intel_bo *target_bo,
2153d722e3fbSopenharmony_ci				  uint32_t target_offset,
2154d722e3fbSopenharmony_ci				  uint32_t read_domains, uint32_t write_domain)
2155d722e3fbSopenharmony_ci{
2156d722e3fbSopenharmony_ci	return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
2157d722e3fbSopenharmony_ci				read_domains, write_domain, true);
2158d722e3fbSopenharmony_ci}
2159d722e3fbSopenharmony_ci
2160d722e3fbSopenharmony_cidrm_public int
2161d722e3fbSopenharmony_cidrm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo)
2162d722e3fbSopenharmony_ci{
2163d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2164d722e3fbSopenharmony_ci
2165d722e3fbSopenharmony_ci	return bo_gem->reloc_count;
2166d722e3fbSopenharmony_ci}
2167d722e3fbSopenharmony_ci
2168d722e3fbSopenharmony_ci/**
2169d722e3fbSopenharmony_ci * Removes existing relocation entries in the BO after "start".
2170d722e3fbSopenharmony_ci *
2171d722e3fbSopenharmony_ci * This allows a user to avoid a two-step process for state setup with
2172d722e3fbSopenharmony_ci * counting up all the buffer objects and doing a
2173d722e3fbSopenharmony_ci * drm_intel_bufmgr_check_aperture_space() before emitting any of the
2174d722e3fbSopenharmony_ci * relocations for the state setup.  Instead, save the state of the
2175d722e3fbSopenharmony_ci * batchbuffer including drm_intel_gem_get_reloc_count(), emit all the
2176d722e3fbSopenharmony_ci * state, and then check if it still fits in the aperture.
2177d722e3fbSopenharmony_ci *
2178d722e3fbSopenharmony_ci * Any further drm_intel_bufmgr_check_aperture_space() queries
2179d722e3fbSopenharmony_ci * involving this buffer in the tree are undefined after this call.
2180d722e3fbSopenharmony_ci *
2181d722e3fbSopenharmony_ci * This also removes all softpinned targets being referenced by the BO.
2182d722e3fbSopenharmony_ci */
2183d722e3fbSopenharmony_cidrm_public void
2184d722e3fbSopenharmony_cidrm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start)
2185d722e3fbSopenharmony_ci{
2186d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2187d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2188d722e3fbSopenharmony_ci	int i;
2189d722e3fbSopenharmony_ci	struct timespec time;
2190d722e3fbSopenharmony_ci
2191d722e3fbSopenharmony_ci	clock_gettime(CLOCK_MONOTONIC, &time);
2192d722e3fbSopenharmony_ci
2193d722e3fbSopenharmony_ci	assert(bo_gem->reloc_count >= start);
2194d722e3fbSopenharmony_ci
2195d722e3fbSopenharmony_ci	/* Unreference the cleared target buffers */
2196d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
2197d722e3fbSopenharmony_ci
2198d722e3fbSopenharmony_ci	for (i = start; i < bo_gem->reloc_count; i++) {
2199d722e3fbSopenharmony_ci		drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->reloc_target_info[i].bo;
2200d722e3fbSopenharmony_ci		if (&target_bo_gem->bo != bo) {
2201d722e3fbSopenharmony_ci			bo_gem->reloc_tree_fences -= target_bo_gem->reloc_tree_fences;
2202d722e3fbSopenharmony_ci			drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo,
2203d722e3fbSopenharmony_ci								  time.tv_sec);
2204d722e3fbSopenharmony_ci		}
2205d722e3fbSopenharmony_ci	}
2206d722e3fbSopenharmony_ci	bo_gem->reloc_count = start;
2207d722e3fbSopenharmony_ci
2208d722e3fbSopenharmony_ci	for (i = 0; i < bo_gem->softpin_target_count; i++) {
2209d722e3fbSopenharmony_ci		drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->softpin_target[i];
2210d722e3fbSopenharmony_ci		drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, time.tv_sec);
2211d722e3fbSopenharmony_ci	}
2212d722e3fbSopenharmony_ci	bo_gem->softpin_target_count = 0;
2213d722e3fbSopenharmony_ci
2214d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
2215d722e3fbSopenharmony_ci
2216d722e3fbSopenharmony_ci}
2217d722e3fbSopenharmony_ci
2218d722e3fbSopenharmony_ci/**
2219d722e3fbSopenharmony_ci * Walk the tree of relocations rooted at BO and accumulate the list of
2220d722e3fbSopenharmony_ci * validations to be performed and update the relocation buffers with
2221d722e3fbSopenharmony_ci * index values into the validation list.
2222d722e3fbSopenharmony_ci */
2223d722e3fbSopenharmony_cistatic void
2224d722e3fbSopenharmony_cidrm_intel_gem_bo_process_reloc2(drm_intel_bo *bo)
2225d722e3fbSopenharmony_ci{
2226d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
2227d722e3fbSopenharmony_ci	int i;
2228d722e3fbSopenharmony_ci
2229d722e3fbSopenharmony_ci	if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL)
2230d722e3fbSopenharmony_ci		return;
2231d722e3fbSopenharmony_ci
2232d722e3fbSopenharmony_ci	for (i = 0; i < bo_gem->reloc_count; i++) {
2233d722e3fbSopenharmony_ci		drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo;
2234d722e3fbSopenharmony_ci		int need_fence;
2235d722e3fbSopenharmony_ci
2236d722e3fbSopenharmony_ci		if (target_bo == bo)
2237d722e3fbSopenharmony_ci			continue;
2238d722e3fbSopenharmony_ci
2239d722e3fbSopenharmony_ci		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
2240d722e3fbSopenharmony_ci
2241d722e3fbSopenharmony_ci		/* Continue walking the tree depth-first. */
2242d722e3fbSopenharmony_ci		drm_intel_gem_bo_process_reloc2(target_bo);
2243d722e3fbSopenharmony_ci
2244d722e3fbSopenharmony_ci		need_fence = (bo_gem->reloc_target_info[i].flags &
2245d722e3fbSopenharmony_ci			      DRM_INTEL_RELOC_FENCE);
2246d722e3fbSopenharmony_ci
2247d722e3fbSopenharmony_ci		/* Add the target to the validate list */
2248d722e3fbSopenharmony_ci		drm_intel_add_validate_buffer2(target_bo, need_fence);
2249d722e3fbSopenharmony_ci	}
2250d722e3fbSopenharmony_ci
2251d722e3fbSopenharmony_ci	for (i = 0; i < bo_gem->softpin_target_count; i++) {
2252d722e3fbSopenharmony_ci		drm_intel_bo *target_bo = bo_gem->softpin_target[i];
2253d722e3fbSopenharmony_ci
2254d722e3fbSopenharmony_ci		if (target_bo == bo)
2255d722e3fbSopenharmony_ci			continue;
2256d722e3fbSopenharmony_ci
2257d722e3fbSopenharmony_ci		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
2258d722e3fbSopenharmony_ci		drm_intel_gem_bo_process_reloc2(target_bo);
2259d722e3fbSopenharmony_ci		drm_intel_add_validate_buffer2(target_bo, false);
2260d722e3fbSopenharmony_ci	}
2261d722e3fbSopenharmony_ci}
2262d722e3fbSopenharmony_ci
2263d722e3fbSopenharmony_cistatic void
2264d722e3fbSopenharmony_cidrm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem)
2265d722e3fbSopenharmony_ci{
2266d722e3fbSopenharmony_ci	int i;
2267d722e3fbSopenharmony_ci
2268d722e3fbSopenharmony_ci	for (i = 0; i < bufmgr_gem->exec_count; i++) {
2269d722e3fbSopenharmony_ci		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
2270d722e3fbSopenharmony_ci		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
2271d722e3fbSopenharmony_ci
2272d722e3fbSopenharmony_ci		/* Update the buffer offset */
2273d722e3fbSopenharmony_ci		if (bufmgr_gem->exec2_objects[i].offset != bo->offset64) {
2274d722e3fbSopenharmony_ci			/* If we're seeing softpinned object here it means that the kernel
2275d722e3fbSopenharmony_ci			 * has relocated our object... Indicating a programming error
2276d722e3fbSopenharmony_ci			 */
2277d722e3fbSopenharmony_ci			assert(!(bo_gem->kflags & EXEC_OBJECT_PINNED));
2278d722e3fbSopenharmony_ci			DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n",
2279d722e3fbSopenharmony_ci			    bo_gem->gem_handle, bo_gem->name,
2280d722e3fbSopenharmony_ci			    upper_32_bits(bo->offset64),
2281d722e3fbSopenharmony_ci			    lower_32_bits(bo->offset64),
2282d722e3fbSopenharmony_ci			    upper_32_bits(bufmgr_gem->exec2_objects[i].offset),
2283d722e3fbSopenharmony_ci			    lower_32_bits(bufmgr_gem->exec2_objects[i].offset));
2284d722e3fbSopenharmony_ci			bo->offset64 = bufmgr_gem->exec2_objects[i].offset;
2285d722e3fbSopenharmony_ci			bo->offset = bufmgr_gem->exec2_objects[i].offset;
2286d722e3fbSopenharmony_ci		}
2287d722e3fbSopenharmony_ci	}
2288d722e3fbSopenharmony_ci}
2289d722e3fbSopenharmony_ci
2290d722e3fbSopenharmony_cidrm_public void
2291d722e3fbSopenharmony_cidrm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo,
2292d722e3fbSopenharmony_ci			      int x1, int y1, int width, int height,
2293d722e3fbSopenharmony_ci			      enum aub_dump_bmp_format format,
2294d722e3fbSopenharmony_ci			      int pitch, int offset)
2295d722e3fbSopenharmony_ci{
2296d722e3fbSopenharmony_ci}
2297d722e3fbSopenharmony_ci
2298d722e3fbSopenharmony_cistatic int
2299d722e3fbSopenharmony_cido_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
2300d722e3fbSopenharmony_ci	 drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
2301d722e3fbSopenharmony_ci	 int in_fence, int *out_fence,
2302d722e3fbSopenharmony_ci	 unsigned int flags)
2303d722e3fbSopenharmony_ci{
2304d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
2305d722e3fbSopenharmony_ci	struct drm_i915_gem_execbuffer2 execbuf;
2306d722e3fbSopenharmony_ci	int ret = 0;
2307d722e3fbSopenharmony_ci	int i;
2308d722e3fbSopenharmony_ci
2309d722e3fbSopenharmony_ci	if (to_bo_gem(bo)->has_error)
2310d722e3fbSopenharmony_ci		return -ENOMEM;
2311d722e3fbSopenharmony_ci
2312d722e3fbSopenharmony_ci	switch (flags & 0x7) {
2313d722e3fbSopenharmony_ci	default:
2314d722e3fbSopenharmony_ci		return -EINVAL;
2315d722e3fbSopenharmony_ci	case I915_EXEC_BLT:
2316d722e3fbSopenharmony_ci		if (!bufmgr_gem->has_blt)
2317d722e3fbSopenharmony_ci			return -EINVAL;
2318d722e3fbSopenharmony_ci		break;
2319d722e3fbSopenharmony_ci	case I915_EXEC_BSD:
2320d722e3fbSopenharmony_ci		if (!bufmgr_gem->has_bsd)
2321d722e3fbSopenharmony_ci			return -EINVAL;
2322d722e3fbSopenharmony_ci		break;
2323d722e3fbSopenharmony_ci	case I915_EXEC_VEBOX:
2324d722e3fbSopenharmony_ci		if (!bufmgr_gem->has_vebox)
2325d722e3fbSopenharmony_ci			return -EINVAL;
2326d722e3fbSopenharmony_ci		break;
2327d722e3fbSopenharmony_ci	case I915_EXEC_RENDER:
2328d722e3fbSopenharmony_ci	case I915_EXEC_DEFAULT:
2329d722e3fbSopenharmony_ci		break;
2330d722e3fbSopenharmony_ci	}
2331d722e3fbSopenharmony_ci
2332d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
2333d722e3fbSopenharmony_ci	/* Update indices and set up the validate list. */
2334d722e3fbSopenharmony_ci	drm_intel_gem_bo_process_reloc2(bo);
2335d722e3fbSopenharmony_ci
2336d722e3fbSopenharmony_ci	/* Add the batch buffer to the validation list.  There are no relocations
2337d722e3fbSopenharmony_ci	 * pointing to it.
2338d722e3fbSopenharmony_ci	 */
2339d722e3fbSopenharmony_ci	drm_intel_add_validate_buffer2(bo, 0);
2340d722e3fbSopenharmony_ci
2341d722e3fbSopenharmony_ci	memclear(execbuf);
2342d722e3fbSopenharmony_ci	execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec2_objects;
2343d722e3fbSopenharmony_ci	execbuf.buffer_count = bufmgr_gem->exec_count;
2344d722e3fbSopenharmony_ci	execbuf.batch_start_offset = 0;
2345d722e3fbSopenharmony_ci	execbuf.batch_len = used;
2346d722e3fbSopenharmony_ci	execbuf.cliprects_ptr = (uintptr_t)cliprects;
2347d722e3fbSopenharmony_ci	execbuf.num_cliprects = num_cliprects;
2348d722e3fbSopenharmony_ci	execbuf.DR1 = 0;
2349d722e3fbSopenharmony_ci	execbuf.DR4 = DR4;
2350d722e3fbSopenharmony_ci	execbuf.flags = flags;
2351d722e3fbSopenharmony_ci	if (ctx == NULL)
2352d722e3fbSopenharmony_ci		i915_execbuffer2_set_context_id(execbuf, 0);
2353d722e3fbSopenharmony_ci	else
2354d722e3fbSopenharmony_ci		i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
2355d722e3fbSopenharmony_ci	execbuf.rsvd2 = 0;
2356d722e3fbSopenharmony_ci	if (in_fence != -1) {
2357d722e3fbSopenharmony_ci		execbuf.rsvd2 = in_fence;
2358d722e3fbSopenharmony_ci		execbuf.flags |= I915_EXEC_FENCE_IN;
2359d722e3fbSopenharmony_ci	}
2360d722e3fbSopenharmony_ci	if (out_fence != NULL) {
2361d722e3fbSopenharmony_ci		*out_fence = -1;
2362d722e3fbSopenharmony_ci		execbuf.flags |= I915_EXEC_FENCE_OUT;
2363d722e3fbSopenharmony_ci	}
2364d722e3fbSopenharmony_ci
2365d722e3fbSopenharmony_ci	if (bufmgr_gem->no_exec)
2366d722e3fbSopenharmony_ci		goto skip_execution;
2367d722e3fbSopenharmony_ci
2368d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
2369d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GEM_EXECBUFFER2_WR,
2370d722e3fbSopenharmony_ci		       &execbuf);
2371d722e3fbSopenharmony_ci	if (ret != 0) {
2372d722e3fbSopenharmony_ci		ret = -errno;
2373d722e3fbSopenharmony_ci		if (ret == -ENOSPC) {
2374d722e3fbSopenharmony_ci			DBG("Execbuffer fails to pin. "
2375d722e3fbSopenharmony_ci			    "Estimate: %u. Actual: %u. Available: %u\n",
2376d722e3fbSopenharmony_ci			    drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos,
2377d722e3fbSopenharmony_ci							       bufmgr_gem->exec_count),
2378d722e3fbSopenharmony_ci			    drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos,
2379d722e3fbSopenharmony_ci							      bufmgr_gem->exec_count),
2380d722e3fbSopenharmony_ci			    (unsigned int) bufmgr_gem->gtt_size);
2381d722e3fbSopenharmony_ci		}
2382d722e3fbSopenharmony_ci	}
2383d722e3fbSopenharmony_ci	drm_intel_update_buffer_offsets2(bufmgr_gem);
2384d722e3fbSopenharmony_ci
2385d722e3fbSopenharmony_ci	if (ret == 0 && out_fence != NULL)
2386d722e3fbSopenharmony_ci		*out_fence = execbuf.rsvd2 >> 32;
2387d722e3fbSopenharmony_ci
2388d722e3fbSopenharmony_ciskip_execution:
2389d722e3fbSopenharmony_ci	if (bufmgr_gem->bufmgr.debug)
2390d722e3fbSopenharmony_ci		drm_intel_gem_dump_validation_list(bufmgr_gem);
2391d722e3fbSopenharmony_ci
2392d722e3fbSopenharmony_ci	for (i = 0; i < bufmgr_gem->exec_count; i++) {
2393d722e3fbSopenharmony_ci		drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]);
2394d722e3fbSopenharmony_ci
2395d722e3fbSopenharmony_ci		bo_gem->idle = false;
2396d722e3fbSopenharmony_ci
2397d722e3fbSopenharmony_ci		/* Disconnect the buffer from the validate list */
2398d722e3fbSopenharmony_ci		bo_gem->validate_index = -1;
2399d722e3fbSopenharmony_ci		bufmgr_gem->exec_bos[i] = NULL;
2400d722e3fbSopenharmony_ci	}
2401d722e3fbSopenharmony_ci	bufmgr_gem->exec_count = 0;
2402d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
2403d722e3fbSopenharmony_ci
2404d722e3fbSopenharmony_ci	return ret;
2405d722e3fbSopenharmony_ci}
2406d722e3fbSopenharmony_ci
2407d722e3fbSopenharmony_cistatic int
2408d722e3fbSopenharmony_cidrm_intel_gem_bo_exec2(drm_intel_bo *bo, int used,
2409d722e3fbSopenharmony_ci		       drm_clip_rect_t *cliprects, int num_cliprects,
2410d722e3fbSopenharmony_ci		       int DR4)
2411d722e3fbSopenharmony_ci{
2412d722e3fbSopenharmony_ci	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
2413d722e3fbSopenharmony_ci			-1, NULL, I915_EXEC_RENDER);
2414d722e3fbSopenharmony_ci}
2415d722e3fbSopenharmony_ci
2416d722e3fbSopenharmony_cistatic int
2417d722e3fbSopenharmony_cidrm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
2418d722e3fbSopenharmony_ci			drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
2419d722e3fbSopenharmony_ci			unsigned int flags)
2420d722e3fbSopenharmony_ci{
2421d722e3fbSopenharmony_ci	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
2422d722e3fbSopenharmony_ci			-1, NULL, flags);
2423d722e3fbSopenharmony_ci}
2424d722e3fbSopenharmony_ci
2425d722e3fbSopenharmony_cidrm_public int
2426d722e3fbSopenharmony_cidrm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
2427d722e3fbSopenharmony_ci			      int used, unsigned int flags)
2428d722e3fbSopenharmony_ci{
2429d722e3fbSopenharmony_ci	return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags);
2430d722e3fbSopenharmony_ci}
2431d722e3fbSopenharmony_ci
2432d722e3fbSopenharmony_cidrm_public int
2433d722e3fbSopenharmony_cidrm_intel_gem_bo_fence_exec(drm_intel_bo *bo,
2434d722e3fbSopenharmony_ci			    drm_intel_context *ctx,
2435d722e3fbSopenharmony_ci			    int used,
2436d722e3fbSopenharmony_ci			    int in_fence,
2437d722e3fbSopenharmony_ci			    int *out_fence,
2438d722e3fbSopenharmony_ci			    unsigned int flags)
2439d722e3fbSopenharmony_ci{
2440d722e3fbSopenharmony_ci	return do_exec2(bo, used, ctx, NULL, 0, 0, in_fence, out_fence, flags);
2441d722e3fbSopenharmony_ci}
2442d722e3fbSopenharmony_ci
2443d722e3fbSopenharmony_cistatic int
2444d722e3fbSopenharmony_cidrm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment)
2445d722e3fbSopenharmony_ci{
2446d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2447d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2448d722e3fbSopenharmony_ci	struct drm_i915_gem_pin pin;
2449d722e3fbSopenharmony_ci	int ret;
2450d722e3fbSopenharmony_ci
2451d722e3fbSopenharmony_ci	memclear(pin);
2452d722e3fbSopenharmony_ci	pin.handle = bo_gem->gem_handle;
2453d722e3fbSopenharmony_ci	pin.alignment = alignment;
2454d722e3fbSopenharmony_ci
2455d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
2456d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GEM_PIN,
2457d722e3fbSopenharmony_ci		       &pin);
2458d722e3fbSopenharmony_ci	if (ret != 0)
2459d722e3fbSopenharmony_ci		return -errno;
2460d722e3fbSopenharmony_ci
2461d722e3fbSopenharmony_ci	bo->offset64 = pin.offset;
2462d722e3fbSopenharmony_ci	bo->offset = pin.offset;
2463d722e3fbSopenharmony_ci	return 0;
2464d722e3fbSopenharmony_ci}
2465d722e3fbSopenharmony_ci
2466d722e3fbSopenharmony_cistatic int
2467d722e3fbSopenharmony_cidrm_intel_gem_bo_unpin(drm_intel_bo *bo)
2468d722e3fbSopenharmony_ci{
2469d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2470d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2471d722e3fbSopenharmony_ci	struct drm_i915_gem_unpin unpin;
2472d722e3fbSopenharmony_ci	int ret;
2473d722e3fbSopenharmony_ci
2474d722e3fbSopenharmony_ci	memclear(unpin);
2475d722e3fbSopenharmony_ci	unpin.handle = bo_gem->gem_handle;
2476d722e3fbSopenharmony_ci
2477d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
2478d722e3fbSopenharmony_ci	if (ret != 0)
2479d722e3fbSopenharmony_ci		return -errno;
2480d722e3fbSopenharmony_ci
2481d722e3fbSopenharmony_ci	return 0;
2482d722e3fbSopenharmony_ci}
2483d722e3fbSopenharmony_ci
2484d722e3fbSopenharmony_cistatic int
2485d722e3fbSopenharmony_cidrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo,
2486d722e3fbSopenharmony_ci				     uint32_t tiling_mode,
2487d722e3fbSopenharmony_ci				     uint32_t stride)
2488d722e3fbSopenharmony_ci{
2489d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2490d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2491d722e3fbSopenharmony_ci	struct drm_i915_gem_set_tiling set_tiling;
2492d722e3fbSopenharmony_ci	int ret;
2493d722e3fbSopenharmony_ci
2494d722e3fbSopenharmony_ci	if (bo_gem->global_name == 0 &&
2495d722e3fbSopenharmony_ci	    tiling_mode == bo_gem->tiling_mode &&
2496d722e3fbSopenharmony_ci	    stride == bo_gem->stride)
2497d722e3fbSopenharmony_ci		return 0;
2498d722e3fbSopenharmony_ci
2499d722e3fbSopenharmony_ci	memset(&set_tiling, 0, sizeof(set_tiling));
2500d722e3fbSopenharmony_ci	do {
2501d722e3fbSopenharmony_ci		/* set_tiling is slightly broken and overwrites the
2502d722e3fbSopenharmony_ci		 * input on the error path, so we have to open code
2503d722e3fbSopenharmony_ci		 * rmIoctl.
2504d722e3fbSopenharmony_ci		 */
2505d722e3fbSopenharmony_ci		set_tiling.handle = bo_gem->gem_handle;
2506d722e3fbSopenharmony_ci		set_tiling.tiling_mode = tiling_mode;
2507d722e3fbSopenharmony_ci		set_tiling.stride = stride;
2508d722e3fbSopenharmony_ci
2509d722e3fbSopenharmony_ci		ret = ioctl(bufmgr_gem->fd,
2510d722e3fbSopenharmony_ci			    DRM_IOCTL_I915_GEM_SET_TILING,
2511d722e3fbSopenharmony_ci			    &set_tiling);
2512d722e3fbSopenharmony_ci	} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
2513d722e3fbSopenharmony_ci	if (ret == -1)
2514d722e3fbSopenharmony_ci		return -errno;
2515d722e3fbSopenharmony_ci
2516d722e3fbSopenharmony_ci	bo_gem->tiling_mode = set_tiling.tiling_mode;
2517d722e3fbSopenharmony_ci	bo_gem->swizzle_mode = set_tiling.swizzle_mode;
2518d722e3fbSopenharmony_ci	bo_gem->stride = set_tiling.stride;
2519d722e3fbSopenharmony_ci	return 0;
2520d722e3fbSopenharmony_ci}
2521d722e3fbSopenharmony_ci
2522d722e3fbSopenharmony_cistatic int
2523d722e3fbSopenharmony_cidrm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
2524d722e3fbSopenharmony_ci			    uint32_t stride)
2525d722e3fbSopenharmony_ci{
2526d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2527d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2528d722e3fbSopenharmony_ci	int ret;
2529d722e3fbSopenharmony_ci
2530d722e3fbSopenharmony_ci	/* Tiling with userptr surfaces is not supported
2531d722e3fbSopenharmony_ci	 * on all hardware so refuse it for time being.
2532d722e3fbSopenharmony_ci	 */
2533d722e3fbSopenharmony_ci	if (bo_gem->is_userptr)
2534d722e3fbSopenharmony_ci		return -EINVAL;
2535d722e3fbSopenharmony_ci
2536d722e3fbSopenharmony_ci	/* Linear buffers have no stride. By ensuring that we only ever use
2537d722e3fbSopenharmony_ci	 * stride 0 with linear buffers, we simplify our code.
2538d722e3fbSopenharmony_ci	 */
2539d722e3fbSopenharmony_ci	if (*tiling_mode == I915_TILING_NONE)
2540d722e3fbSopenharmony_ci		stride = 0;
2541d722e3fbSopenharmony_ci
2542d722e3fbSopenharmony_ci	ret = drm_intel_gem_bo_set_tiling_internal(bo, *tiling_mode, stride);
2543d722e3fbSopenharmony_ci	if (ret == 0)
2544d722e3fbSopenharmony_ci		drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
2545d722e3fbSopenharmony_ci
2546d722e3fbSopenharmony_ci	*tiling_mode = bo_gem->tiling_mode;
2547d722e3fbSopenharmony_ci	return ret;
2548d722e3fbSopenharmony_ci}
2549d722e3fbSopenharmony_ci
2550d722e3fbSopenharmony_cistatic int
2551d722e3fbSopenharmony_cidrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
2552d722e3fbSopenharmony_ci			    uint32_t * swizzle_mode)
2553d722e3fbSopenharmony_ci{
2554d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2555d722e3fbSopenharmony_ci
2556d722e3fbSopenharmony_ci	*tiling_mode = bo_gem->tiling_mode;
2557d722e3fbSopenharmony_ci	*swizzle_mode = bo_gem->swizzle_mode;
2558d722e3fbSopenharmony_ci	return 0;
2559d722e3fbSopenharmony_ci}
2560d722e3fbSopenharmony_ci
2561d722e3fbSopenharmony_cistatic int
2562d722e3fbSopenharmony_cidrm_intel_gem_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset)
2563d722e3fbSopenharmony_ci{
2564d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2565d722e3fbSopenharmony_ci
2566d722e3fbSopenharmony_ci	bo->offset64 = offset;
2567d722e3fbSopenharmony_ci	bo->offset = offset;
2568d722e3fbSopenharmony_ci	bo_gem->kflags |= EXEC_OBJECT_PINNED;
2569d722e3fbSopenharmony_ci
2570d722e3fbSopenharmony_ci	return 0;
2571d722e3fbSopenharmony_ci}
2572d722e3fbSopenharmony_ci
2573d722e3fbSopenharmony_cidrm_public drm_intel_bo *
2574d722e3fbSopenharmony_cidrm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size)
2575d722e3fbSopenharmony_ci{
2576d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
2577d722e3fbSopenharmony_ci	int ret;
2578d722e3fbSopenharmony_ci	uint32_t handle;
2579d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem;
2580d722e3fbSopenharmony_ci
2581d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
2582d722e3fbSopenharmony_ci	ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle);
2583d722e3fbSopenharmony_ci	if (ret) {
2584d722e3fbSopenharmony_ci		DBG("create_from_prime: failed to obtain handle from fd: %s\n", strerror(errno));
2585d722e3fbSopenharmony_ci		pthread_mutex_unlock(&bufmgr_gem->lock);
2586d722e3fbSopenharmony_ci		return NULL;
2587d722e3fbSopenharmony_ci	}
2588d722e3fbSopenharmony_ci
2589d722e3fbSopenharmony_ci	/*
2590d722e3fbSopenharmony_ci	 * See if the kernel has already returned this buffer to us. Just as
2591d722e3fbSopenharmony_ci	 * for named buffers, we must not create two bo's pointing at the same
2592d722e3fbSopenharmony_ci	 * kernel object
2593d722e3fbSopenharmony_ci	 */
2594d722e3fbSopenharmony_ci	HASH_FIND(handle_hh, bufmgr_gem->handle_table,
2595d722e3fbSopenharmony_ci		  &handle, sizeof(handle), bo_gem);
2596d722e3fbSopenharmony_ci	if (bo_gem) {
2597d722e3fbSopenharmony_ci		drm_intel_gem_bo_reference(&bo_gem->bo);
2598d722e3fbSopenharmony_ci		goto out;
2599d722e3fbSopenharmony_ci	}
2600d722e3fbSopenharmony_ci
2601d722e3fbSopenharmony_ci	bo_gem = calloc(1, sizeof(*bo_gem));
2602d722e3fbSopenharmony_ci	if (!bo_gem)
2603d722e3fbSopenharmony_ci		goto out;
2604d722e3fbSopenharmony_ci
2605d722e3fbSopenharmony_ci	atomic_set(&bo_gem->refcount, 1);
2606d722e3fbSopenharmony_ci	DRMINITLISTHEAD(&bo_gem->vma_list);
2607d722e3fbSopenharmony_ci
2608d722e3fbSopenharmony_ci	/* Determine size of bo.  The fd-to-handle ioctl really should
2609d722e3fbSopenharmony_ci	 * return the size, but it doesn't.  If we have kernel 3.12 or
2610d722e3fbSopenharmony_ci	 * later, we can lseek on the prime fd to get the size.  Older
2611d722e3fbSopenharmony_ci	 * kernels will just fail, in which case we fall back to the
2612d722e3fbSopenharmony_ci	 * provided (estimated or guess size). */
2613d722e3fbSopenharmony_ci	ret = lseek(prime_fd, 0, SEEK_END);
2614d722e3fbSopenharmony_ci	if (ret != -1)
2615d722e3fbSopenharmony_ci		bo_gem->bo.size = ret;
2616d722e3fbSopenharmony_ci	else
2617d722e3fbSopenharmony_ci		bo_gem->bo.size = size;
2618d722e3fbSopenharmony_ci
2619d722e3fbSopenharmony_ci	bo_gem->bo.handle = handle;
2620d722e3fbSopenharmony_ci	bo_gem->bo.bufmgr = bufmgr;
2621d722e3fbSopenharmony_ci
2622d722e3fbSopenharmony_ci	bo_gem->gem_handle = handle;
2623d722e3fbSopenharmony_ci	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
2624d722e3fbSopenharmony_ci		 gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
2625d722e3fbSopenharmony_ci
2626d722e3fbSopenharmony_ci	bo_gem->name = "prime";
2627d722e3fbSopenharmony_ci	bo_gem->validate_index = -1;
2628d722e3fbSopenharmony_ci	bo_gem->reloc_tree_fences = 0;
2629d722e3fbSopenharmony_ci	bo_gem->used_as_reloc_target = false;
2630d722e3fbSopenharmony_ci	bo_gem->has_error = false;
2631d722e3fbSopenharmony_ci	bo_gem->reusable = false;
2632d722e3fbSopenharmony_ci
2633d722e3fbSopenharmony_ci	ret = get_tiling_mode(bufmgr_gem, handle,
2634d722e3fbSopenharmony_ci			      &bo_gem->tiling_mode, &bo_gem->swizzle_mode);
2635d722e3fbSopenharmony_ci	if (ret)
2636d722e3fbSopenharmony_ci		goto err;
2637d722e3fbSopenharmony_ci
2638d722e3fbSopenharmony_ci	/* XXX stride is unknown */
2639d722e3fbSopenharmony_ci	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
2640d722e3fbSopenharmony_ci
2641d722e3fbSopenharmony_ciout:
2642d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
2643d722e3fbSopenharmony_ci	return &bo_gem->bo;
2644d722e3fbSopenharmony_ci
2645d722e3fbSopenharmony_cierr:
2646d722e3fbSopenharmony_ci	drm_intel_gem_bo_free(&bo_gem->bo);
2647d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
2648d722e3fbSopenharmony_ci	return NULL;
2649d722e3fbSopenharmony_ci}
2650d722e3fbSopenharmony_ci
2651d722e3fbSopenharmony_cidrm_public int
2652d722e3fbSopenharmony_cidrm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd)
2653d722e3fbSopenharmony_ci{
2654d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2655d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2656d722e3fbSopenharmony_ci
2657d722e3fbSopenharmony_ci	if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle,
2658d722e3fbSopenharmony_ci			       DRM_CLOEXEC | DRM_RDWR, prime_fd) != 0)
2659d722e3fbSopenharmony_ci		return -errno;
2660d722e3fbSopenharmony_ci
2661d722e3fbSopenharmony_ci	bo_gem->reusable = false;
2662d722e3fbSopenharmony_ci
2663d722e3fbSopenharmony_ci	return 0;
2664d722e3fbSopenharmony_ci}
2665d722e3fbSopenharmony_ci
2666d722e3fbSopenharmony_cistatic int
2667d722e3fbSopenharmony_cidrm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name)
2668d722e3fbSopenharmony_ci{
2669d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2670d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2671d722e3fbSopenharmony_ci
2672d722e3fbSopenharmony_ci	if (!bo_gem->global_name) {
2673d722e3fbSopenharmony_ci		struct drm_gem_flink flink;
2674d722e3fbSopenharmony_ci
2675d722e3fbSopenharmony_ci		memclear(flink);
2676d722e3fbSopenharmony_ci		flink.handle = bo_gem->gem_handle;
2677d722e3fbSopenharmony_ci		if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink))
2678d722e3fbSopenharmony_ci			return -errno;
2679d722e3fbSopenharmony_ci
2680d722e3fbSopenharmony_ci		pthread_mutex_lock(&bufmgr_gem->lock);
2681d722e3fbSopenharmony_ci		if (!bo_gem->global_name) {
2682d722e3fbSopenharmony_ci			bo_gem->global_name = flink.name;
2683d722e3fbSopenharmony_ci			bo_gem->reusable = false;
2684d722e3fbSopenharmony_ci
2685d722e3fbSopenharmony_ci			HASH_ADD(name_hh, bufmgr_gem->name_table,
2686d722e3fbSopenharmony_ci				 global_name, sizeof(bo_gem->global_name),
2687d722e3fbSopenharmony_ci				 bo_gem);
2688d722e3fbSopenharmony_ci		}
2689d722e3fbSopenharmony_ci		pthread_mutex_unlock(&bufmgr_gem->lock);
2690d722e3fbSopenharmony_ci	}
2691d722e3fbSopenharmony_ci
2692d722e3fbSopenharmony_ci	*name = bo_gem->global_name;
2693d722e3fbSopenharmony_ci	return 0;
2694d722e3fbSopenharmony_ci}
2695d722e3fbSopenharmony_ci
2696d722e3fbSopenharmony_ci/**
2697d722e3fbSopenharmony_ci * Enables unlimited caching of buffer objects for reuse.
2698d722e3fbSopenharmony_ci *
2699d722e3fbSopenharmony_ci * This is potentially very memory expensive, as the cache at each bucket
2700d722e3fbSopenharmony_ci * size is only bounded by how many buffers of that size we've managed to have
2701d722e3fbSopenharmony_ci * in flight at once.
2702d722e3fbSopenharmony_ci */
2703d722e3fbSopenharmony_cidrm_public void
2704d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr)
2705d722e3fbSopenharmony_ci{
2706d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
2707d722e3fbSopenharmony_ci
2708d722e3fbSopenharmony_ci	bufmgr_gem->bo_reuse = true;
2709d722e3fbSopenharmony_ci}
2710d722e3fbSopenharmony_ci
2711d722e3fbSopenharmony_ci/**
2712d722e3fbSopenharmony_ci * Disables implicit synchronisation before executing the bo
2713d722e3fbSopenharmony_ci *
2714d722e3fbSopenharmony_ci * This will cause rendering corruption unless you correctly manage explicit
2715d722e3fbSopenharmony_ci * fences for all rendering involving this buffer - including use by others.
2716d722e3fbSopenharmony_ci * Disabling the implicit serialisation is only required if that serialisation
2717d722e3fbSopenharmony_ci * is too coarse (for example, you have split the buffer into many
2718d722e3fbSopenharmony_ci * non-overlapping regions and are sharing the whole buffer between concurrent
2719d722e3fbSopenharmony_ci * independent command streams).
2720d722e3fbSopenharmony_ci *
2721d722e3fbSopenharmony_ci * Note the kernel must advertise support via I915_PARAM_HAS_EXEC_ASYNC,
2722d722e3fbSopenharmony_ci * which can be checked using drm_intel_bufmgr_can_disable_implicit_sync,
2723d722e3fbSopenharmony_ci * or subsequent execbufs involving the bo will generate EINVAL.
2724d722e3fbSopenharmony_ci */
2725d722e3fbSopenharmony_cidrm_public void
2726d722e3fbSopenharmony_cidrm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo)
2727d722e3fbSopenharmony_ci{
2728d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2729d722e3fbSopenharmony_ci
2730d722e3fbSopenharmony_ci	bo_gem->kflags |= EXEC_OBJECT_ASYNC;
2731d722e3fbSopenharmony_ci}
2732d722e3fbSopenharmony_ci
2733d722e3fbSopenharmony_ci/**
2734d722e3fbSopenharmony_ci * Enables implicit synchronisation before executing the bo
2735d722e3fbSopenharmony_ci *
2736d722e3fbSopenharmony_ci * This is the default behaviour of the kernel, to wait upon prior writes
2737d722e3fbSopenharmony_ci * completing on the object before rendering with it, or to wait for prior
2738d722e3fbSopenharmony_ci * reads to complete before writing into the object.
2739d722e3fbSopenharmony_ci * drm_intel_gem_bo_disable_implicit_sync() can stop this behaviour, telling
2740d722e3fbSopenharmony_ci * the kernel never to insert a stall before using the object. Then this
2741d722e3fbSopenharmony_ci * function can be used to restore the implicit sync before subsequent
2742d722e3fbSopenharmony_ci * rendering.
2743d722e3fbSopenharmony_ci */
2744d722e3fbSopenharmony_cidrm_public void
2745d722e3fbSopenharmony_cidrm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo)
2746d722e3fbSopenharmony_ci{
2747d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2748d722e3fbSopenharmony_ci
2749d722e3fbSopenharmony_ci	bo_gem->kflags &= ~EXEC_OBJECT_ASYNC;
2750d722e3fbSopenharmony_ci}
2751d722e3fbSopenharmony_ci
2752d722e3fbSopenharmony_ci/**
2753d722e3fbSopenharmony_ci * Query whether the kernel supports disabling of its implicit synchronisation
2754d722e3fbSopenharmony_ci * before execbuf. See drm_intel_gem_bo_disable_implicit_sync()
2755d722e3fbSopenharmony_ci */
2756d722e3fbSopenharmony_cidrm_public int
2757d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr)
2758d722e3fbSopenharmony_ci{
2759d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
2760d722e3fbSopenharmony_ci
2761d722e3fbSopenharmony_ci	return bufmgr_gem->has_exec_async;
2762d722e3fbSopenharmony_ci}
2763d722e3fbSopenharmony_ci
2764d722e3fbSopenharmony_ci/**
2765d722e3fbSopenharmony_ci * Enable use of fenced reloc type.
2766d722e3fbSopenharmony_ci *
2767d722e3fbSopenharmony_ci * New code should enable this to avoid unnecessary fence register
2768d722e3fbSopenharmony_ci * allocation.  If this option is not enabled, all relocs will have fence
2769d722e3fbSopenharmony_ci * register allocated.
2770d722e3fbSopenharmony_ci */
2771d722e3fbSopenharmony_cidrm_public void
2772d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr)
2773d722e3fbSopenharmony_ci{
2774d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
2775d722e3fbSopenharmony_ci	bufmgr_gem->fenced_relocs = true;
2776d722e3fbSopenharmony_ci}
2777d722e3fbSopenharmony_ci
2778d722e3fbSopenharmony_ci/**
2779d722e3fbSopenharmony_ci * Return the additional aperture space required by the tree of buffer objects
2780d722e3fbSopenharmony_ci * rooted at bo.
2781d722e3fbSopenharmony_ci */
2782d722e3fbSopenharmony_cistatic int
2783d722e3fbSopenharmony_cidrm_intel_gem_bo_get_aperture_space(drm_intel_bo *bo)
2784d722e3fbSopenharmony_ci{
2785d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2786d722e3fbSopenharmony_ci	int i;
2787d722e3fbSopenharmony_ci	int total = 0;
2788d722e3fbSopenharmony_ci
2789d722e3fbSopenharmony_ci	if (bo == NULL || bo_gem->included_in_check_aperture)
2790d722e3fbSopenharmony_ci		return 0;
2791d722e3fbSopenharmony_ci
2792d722e3fbSopenharmony_ci	total += bo->size;
2793d722e3fbSopenharmony_ci	bo_gem->included_in_check_aperture = true;
2794d722e3fbSopenharmony_ci
2795d722e3fbSopenharmony_ci	for (i = 0; i < bo_gem->reloc_count; i++)
2796d722e3fbSopenharmony_ci		total +=
2797d722e3fbSopenharmony_ci		    drm_intel_gem_bo_get_aperture_space(bo_gem->
2798d722e3fbSopenharmony_ci							reloc_target_info[i].bo);
2799d722e3fbSopenharmony_ci
2800d722e3fbSopenharmony_ci	return total;
2801d722e3fbSopenharmony_ci}
2802d722e3fbSopenharmony_ci
2803d722e3fbSopenharmony_ci/**
2804d722e3fbSopenharmony_ci * Count the number of buffers in this list that need a fence reg
2805d722e3fbSopenharmony_ci *
2806d722e3fbSopenharmony_ci * If the count is greater than the number of available regs, we'll have
2807d722e3fbSopenharmony_ci * to ask the caller to resubmit a batch with fewer tiled buffers.
2808d722e3fbSopenharmony_ci *
2809d722e3fbSopenharmony_ci * This function over-counts if the same buffer is used multiple times.
2810d722e3fbSopenharmony_ci */
2811d722e3fbSopenharmony_cistatic unsigned int
2812d722e3fbSopenharmony_cidrm_intel_gem_total_fences(drm_intel_bo ** bo_array, int count)
2813d722e3fbSopenharmony_ci{
2814d722e3fbSopenharmony_ci	int i;
2815d722e3fbSopenharmony_ci	unsigned int total = 0;
2816d722e3fbSopenharmony_ci
2817d722e3fbSopenharmony_ci	for (i = 0; i < count; i++) {
2818d722e3fbSopenharmony_ci		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i];
2819d722e3fbSopenharmony_ci
2820d722e3fbSopenharmony_ci		if (bo_gem == NULL)
2821d722e3fbSopenharmony_ci			continue;
2822d722e3fbSopenharmony_ci
2823d722e3fbSopenharmony_ci		total += bo_gem->reloc_tree_fences;
2824d722e3fbSopenharmony_ci	}
2825d722e3fbSopenharmony_ci	return total;
2826d722e3fbSopenharmony_ci}
2827d722e3fbSopenharmony_ci
2828d722e3fbSopenharmony_ci/**
2829d722e3fbSopenharmony_ci * Clear the flag set by drm_intel_gem_bo_get_aperture_space() so we're ready
2830d722e3fbSopenharmony_ci * for the next drm_intel_bufmgr_check_aperture_space() call.
2831d722e3fbSopenharmony_ci */
2832d722e3fbSopenharmony_cistatic void
2833d722e3fbSopenharmony_cidrm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo)
2834d722e3fbSopenharmony_ci{
2835d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2836d722e3fbSopenharmony_ci	int i;
2837d722e3fbSopenharmony_ci
2838d722e3fbSopenharmony_ci	if (bo == NULL || !bo_gem->included_in_check_aperture)
2839d722e3fbSopenharmony_ci		return;
2840d722e3fbSopenharmony_ci
2841d722e3fbSopenharmony_ci	bo_gem->included_in_check_aperture = false;
2842d722e3fbSopenharmony_ci
2843d722e3fbSopenharmony_ci	for (i = 0; i < bo_gem->reloc_count; i++)
2844d722e3fbSopenharmony_ci		drm_intel_gem_bo_clear_aperture_space_flag(bo_gem->
2845d722e3fbSopenharmony_ci							   reloc_target_info[i].bo);
2846d722e3fbSopenharmony_ci}
2847d722e3fbSopenharmony_ci
2848d722e3fbSopenharmony_ci/**
2849d722e3fbSopenharmony_ci * Return a conservative estimate for the amount of aperture required
2850d722e3fbSopenharmony_ci * for a collection of buffers. This may double-count some buffers.
2851d722e3fbSopenharmony_ci */
2852d722e3fbSopenharmony_cistatic unsigned int
2853d722e3fbSopenharmony_cidrm_intel_gem_estimate_batch_space(drm_intel_bo **bo_array, int count)
2854d722e3fbSopenharmony_ci{
2855d722e3fbSopenharmony_ci	int i;
2856d722e3fbSopenharmony_ci	unsigned int total = 0;
2857d722e3fbSopenharmony_ci
2858d722e3fbSopenharmony_ci	for (i = 0; i < count; i++) {
2859d722e3fbSopenharmony_ci		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i];
2860d722e3fbSopenharmony_ci		if (bo_gem != NULL)
2861d722e3fbSopenharmony_ci			total += bo_gem->reloc_tree_size;
2862d722e3fbSopenharmony_ci	}
2863d722e3fbSopenharmony_ci	return total;
2864d722e3fbSopenharmony_ci}
2865d722e3fbSopenharmony_ci
2866d722e3fbSopenharmony_ci/**
2867d722e3fbSopenharmony_ci * Return the amount of aperture needed for a collection of buffers.
2868d722e3fbSopenharmony_ci * This avoids double counting any buffers, at the cost of looking
2869d722e3fbSopenharmony_ci * at every buffer in the set.
2870d722e3fbSopenharmony_ci */
2871d722e3fbSopenharmony_cistatic unsigned int
2872d722e3fbSopenharmony_cidrm_intel_gem_compute_batch_space(drm_intel_bo **bo_array, int count)
2873d722e3fbSopenharmony_ci{
2874d722e3fbSopenharmony_ci	int i;
2875d722e3fbSopenharmony_ci	unsigned int total = 0;
2876d722e3fbSopenharmony_ci
2877d722e3fbSopenharmony_ci	for (i = 0; i < count; i++) {
2878d722e3fbSopenharmony_ci		total += drm_intel_gem_bo_get_aperture_space(bo_array[i]);
2879d722e3fbSopenharmony_ci		/* For the first buffer object in the array, we get an
2880d722e3fbSopenharmony_ci		 * accurate count back for its reloc_tree size (since nothing
2881d722e3fbSopenharmony_ci		 * had been flagged as being counted yet).  We can save that
2882d722e3fbSopenharmony_ci		 * value out as a more conservative reloc_tree_size that
2883d722e3fbSopenharmony_ci		 * avoids double-counting target buffers.  Since the first
2884d722e3fbSopenharmony_ci		 * buffer happens to usually be the batch buffer in our
2885d722e3fbSopenharmony_ci		 * callers, this can pull us back from doing the tree
2886d722e3fbSopenharmony_ci		 * walk on every new batch emit.
2887d722e3fbSopenharmony_ci		 */
2888d722e3fbSopenharmony_ci		if (i == 0) {
2889d722e3fbSopenharmony_ci			drm_intel_bo_gem *bo_gem =
2890d722e3fbSopenharmony_ci			    (drm_intel_bo_gem *) bo_array[i];
2891d722e3fbSopenharmony_ci			bo_gem->reloc_tree_size = total;
2892d722e3fbSopenharmony_ci		}
2893d722e3fbSopenharmony_ci	}
2894d722e3fbSopenharmony_ci
2895d722e3fbSopenharmony_ci	for (i = 0; i < count; i++)
2896d722e3fbSopenharmony_ci		drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]);
2897d722e3fbSopenharmony_ci	return total;
2898d722e3fbSopenharmony_ci}
2899d722e3fbSopenharmony_ci
2900d722e3fbSopenharmony_ci/**
2901d722e3fbSopenharmony_ci * Return -1 if the batchbuffer should be flushed before attempting to
2902d722e3fbSopenharmony_ci * emit rendering referencing the buffers pointed to by bo_array.
2903d722e3fbSopenharmony_ci *
2904d722e3fbSopenharmony_ci * This is required because if we try to emit a batchbuffer with relocations
2905d722e3fbSopenharmony_ci * to a tree of buffers that won't simultaneously fit in the aperture,
2906d722e3fbSopenharmony_ci * the rendering will return an error at a point where the software is not
2907d722e3fbSopenharmony_ci * prepared to recover from it.
2908d722e3fbSopenharmony_ci *
2909d722e3fbSopenharmony_ci * However, we also want to emit the batchbuffer significantly before we reach
2910d722e3fbSopenharmony_ci * the limit, as a series of batchbuffers each of which references buffers
2911d722e3fbSopenharmony_ci * covering almost all of the aperture means that at each emit we end up
2912d722e3fbSopenharmony_ci * waiting to evict a buffer from the last rendering, and we get synchronous
2913d722e3fbSopenharmony_ci * performance.  By emitting smaller batchbuffers, we eat some CPU overhead to
2914d722e3fbSopenharmony_ci * get better parallelism.
2915d722e3fbSopenharmony_ci */
2916d722e3fbSopenharmony_cistatic int
2917d722e3fbSopenharmony_cidrm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count)
2918d722e3fbSopenharmony_ci{
2919d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem =
2920d722e3fbSopenharmony_ci	    (drm_intel_bufmgr_gem *) bo_array[0]->bufmgr;
2921d722e3fbSopenharmony_ci	unsigned int total = 0;
2922d722e3fbSopenharmony_ci	unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4;
2923d722e3fbSopenharmony_ci	int total_fences;
2924d722e3fbSopenharmony_ci
2925d722e3fbSopenharmony_ci	/* Check for fence reg constraints if necessary */
2926d722e3fbSopenharmony_ci	if (bufmgr_gem->available_fences) {
2927d722e3fbSopenharmony_ci		total_fences = drm_intel_gem_total_fences(bo_array, count);
2928d722e3fbSopenharmony_ci		if (total_fences > bufmgr_gem->available_fences)
2929d722e3fbSopenharmony_ci			return -ENOSPC;
2930d722e3fbSopenharmony_ci	}
2931d722e3fbSopenharmony_ci
2932d722e3fbSopenharmony_ci	total = drm_intel_gem_estimate_batch_space(bo_array, count);
2933d722e3fbSopenharmony_ci
2934d722e3fbSopenharmony_ci	if (total > threshold)
2935d722e3fbSopenharmony_ci		total = drm_intel_gem_compute_batch_space(bo_array, count);
2936d722e3fbSopenharmony_ci
2937d722e3fbSopenharmony_ci	if (total > threshold) {
2938d722e3fbSopenharmony_ci		DBG("check_space: overflowed available aperture, "
2939d722e3fbSopenharmony_ci		    "%dkb vs %dkb\n",
2940d722e3fbSopenharmony_ci		    total / 1024, (int)bufmgr_gem->gtt_size / 1024);
2941d722e3fbSopenharmony_ci		return -ENOSPC;
2942d722e3fbSopenharmony_ci	} else {
2943d722e3fbSopenharmony_ci		DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024,
2944d722e3fbSopenharmony_ci		    (int)bufmgr_gem->gtt_size / 1024);
2945d722e3fbSopenharmony_ci		return 0;
2946d722e3fbSopenharmony_ci	}
2947d722e3fbSopenharmony_ci}
2948d722e3fbSopenharmony_ci
2949d722e3fbSopenharmony_ci/*
2950d722e3fbSopenharmony_ci * Disable buffer reuse for objects which are shared with the kernel
2951d722e3fbSopenharmony_ci * as scanout buffers
2952d722e3fbSopenharmony_ci */
2953d722e3fbSopenharmony_cistatic int
2954d722e3fbSopenharmony_cidrm_intel_gem_bo_disable_reuse(drm_intel_bo *bo)
2955d722e3fbSopenharmony_ci{
2956d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2957d722e3fbSopenharmony_ci
2958d722e3fbSopenharmony_ci	bo_gem->reusable = false;
2959d722e3fbSopenharmony_ci	return 0;
2960d722e3fbSopenharmony_ci}
2961d722e3fbSopenharmony_ci
2962d722e3fbSopenharmony_cistatic int
2963d722e3fbSopenharmony_cidrm_intel_gem_bo_is_reusable(drm_intel_bo *bo)
2964d722e3fbSopenharmony_ci{
2965d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2966d722e3fbSopenharmony_ci
2967d722e3fbSopenharmony_ci	return bo_gem->reusable;
2968d722e3fbSopenharmony_ci}
2969d722e3fbSopenharmony_ci
2970d722e3fbSopenharmony_cistatic int
2971d722e3fbSopenharmony_ci_drm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo)
2972d722e3fbSopenharmony_ci{
2973d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2974d722e3fbSopenharmony_ci	int i;
2975d722e3fbSopenharmony_ci
2976d722e3fbSopenharmony_ci	for (i = 0; i < bo_gem->reloc_count; i++) {
2977d722e3fbSopenharmony_ci		if (bo_gem->reloc_target_info[i].bo == target_bo)
2978d722e3fbSopenharmony_ci			return 1;
2979d722e3fbSopenharmony_ci		if (bo == bo_gem->reloc_target_info[i].bo)
2980d722e3fbSopenharmony_ci			continue;
2981d722e3fbSopenharmony_ci		if (_drm_intel_gem_bo_references(bo_gem->reloc_target_info[i].bo,
2982d722e3fbSopenharmony_ci						target_bo))
2983d722e3fbSopenharmony_ci			return 1;
2984d722e3fbSopenharmony_ci	}
2985d722e3fbSopenharmony_ci
2986d722e3fbSopenharmony_ci	for (i = 0; i< bo_gem->softpin_target_count; i++) {
2987d722e3fbSopenharmony_ci		if (bo_gem->softpin_target[i] == target_bo)
2988d722e3fbSopenharmony_ci			return 1;
2989d722e3fbSopenharmony_ci		if (_drm_intel_gem_bo_references(bo_gem->softpin_target[i], target_bo))
2990d722e3fbSopenharmony_ci			return 1;
2991d722e3fbSopenharmony_ci	}
2992d722e3fbSopenharmony_ci
2993d722e3fbSopenharmony_ci	return 0;
2994d722e3fbSopenharmony_ci}
2995d722e3fbSopenharmony_ci
2996d722e3fbSopenharmony_ci/** Return true if target_bo is referenced by bo's relocation tree. */
2997d722e3fbSopenharmony_cistatic int
2998d722e3fbSopenharmony_cidrm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo)
2999d722e3fbSopenharmony_ci{
3000d722e3fbSopenharmony_ci	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
3001d722e3fbSopenharmony_ci
3002d722e3fbSopenharmony_ci	if (bo == NULL || target_bo == NULL)
3003d722e3fbSopenharmony_ci		return 0;
3004d722e3fbSopenharmony_ci	if (target_bo_gem->used_as_reloc_target)
3005d722e3fbSopenharmony_ci		return _drm_intel_gem_bo_references(bo, target_bo);
3006d722e3fbSopenharmony_ci	return 0;
3007d722e3fbSopenharmony_ci}
3008d722e3fbSopenharmony_ci
3009d722e3fbSopenharmony_cistatic void
3010d722e3fbSopenharmony_ciadd_bucket(drm_intel_bufmgr_gem *bufmgr_gem, int size)
3011d722e3fbSopenharmony_ci{
3012d722e3fbSopenharmony_ci	unsigned int i = bufmgr_gem->num_buckets;
3013d722e3fbSopenharmony_ci
3014d722e3fbSopenharmony_ci	assert(i < ARRAY_SIZE(bufmgr_gem->cache_bucket));
3015d722e3fbSopenharmony_ci
3016d722e3fbSopenharmony_ci	DRMINITLISTHEAD(&bufmgr_gem->cache_bucket[i].head);
3017d722e3fbSopenharmony_ci	bufmgr_gem->cache_bucket[i].size = size;
3018d722e3fbSopenharmony_ci	bufmgr_gem->num_buckets++;
3019d722e3fbSopenharmony_ci}
3020d722e3fbSopenharmony_ci
3021d722e3fbSopenharmony_cistatic void
3022d722e3fbSopenharmony_ciinit_cache_buckets(drm_intel_bufmgr_gem *bufmgr_gem)
3023d722e3fbSopenharmony_ci{
3024d722e3fbSopenharmony_ci	unsigned long size, cache_max_size = 64 * 1024 * 1024;
3025d722e3fbSopenharmony_ci
3026d722e3fbSopenharmony_ci	/* OK, so power of two buckets was too wasteful of memory.
3027d722e3fbSopenharmony_ci	 * Give 3 other sizes between each power of two, to hopefully
3028d722e3fbSopenharmony_ci	 * cover things accurately enough.  (The alternative is
3029d722e3fbSopenharmony_ci	 * probably to just go for exact matching of sizes, and assume
3030d722e3fbSopenharmony_ci	 * that for things like composited window resize the tiled
3031d722e3fbSopenharmony_ci	 * width/height alignment and rounding of sizes to pages will
3032d722e3fbSopenharmony_ci	 * get us useful cache hit rates anyway)
3033d722e3fbSopenharmony_ci	 */
3034d722e3fbSopenharmony_ci	add_bucket(bufmgr_gem, 4096);
3035d722e3fbSopenharmony_ci	add_bucket(bufmgr_gem, 4096 * 2);
3036d722e3fbSopenharmony_ci	add_bucket(bufmgr_gem, 4096 * 3);
3037d722e3fbSopenharmony_ci
3038d722e3fbSopenharmony_ci	/* Initialize the linked lists for BO reuse cache. */
3039d722e3fbSopenharmony_ci	for (size = 4 * 4096; size <= cache_max_size; size *= 2) {
3040d722e3fbSopenharmony_ci		add_bucket(bufmgr_gem, size);
3041d722e3fbSopenharmony_ci
3042d722e3fbSopenharmony_ci		add_bucket(bufmgr_gem, size + size * 1 / 4);
3043d722e3fbSopenharmony_ci		add_bucket(bufmgr_gem, size + size * 2 / 4);
3044d722e3fbSopenharmony_ci		add_bucket(bufmgr_gem, size + size * 3 / 4);
3045d722e3fbSopenharmony_ci	}
3046d722e3fbSopenharmony_ci}
3047d722e3fbSopenharmony_ci
3048d722e3fbSopenharmony_cidrm_public void
3049d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit)
3050d722e3fbSopenharmony_ci{
3051d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
3052d722e3fbSopenharmony_ci
3053d722e3fbSopenharmony_ci	bufmgr_gem->vma_max = limit;
3054d722e3fbSopenharmony_ci
3055d722e3fbSopenharmony_ci	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
3056d722e3fbSopenharmony_ci}
3057d722e3fbSopenharmony_ci
3058d722e3fbSopenharmony_cistatic int
3059d722e3fbSopenharmony_ciparse_devid_override(const char *devid_override)
3060d722e3fbSopenharmony_ci{
3061d722e3fbSopenharmony_ci	static const struct {
3062d722e3fbSopenharmony_ci		const char *name;
3063d722e3fbSopenharmony_ci		int pci_id;
3064d722e3fbSopenharmony_ci	} name_map[] = {
3065d722e3fbSopenharmony_ci		{ "brw", PCI_CHIP_I965_GM },
3066d722e3fbSopenharmony_ci		{ "g4x", PCI_CHIP_GM45_GM },
3067d722e3fbSopenharmony_ci		{ "ilk", PCI_CHIP_ILD_G },
3068d722e3fbSopenharmony_ci		{ "snb", PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS },
3069d722e3fbSopenharmony_ci		{ "ivb", PCI_CHIP_IVYBRIDGE_S_GT2 },
3070d722e3fbSopenharmony_ci		{ "hsw", PCI_CHIP_HASWELL_CRW_E_GT3 },
3071d722e3fbSopenharmony_ci		{ "byt", PCI_CHIP_VALLEYVIEW_3 },
3072d722e3fbSopenharmony_ci		{ "bdw", 0x1620 | BDW_ULX },
3073d722e3fbSopenharmony_ci		{ "skl", PCI_CHIP_SKYLAKE_DT_GT2 },
3074d722e3fbSopenharmony_ci		{ "kbl", PCI_CHIP_KABYLAKE_DT_GT2 },
3075d722e3fbSopenharmony_ci	};
3076d722e3fbSopenharmony_ci	unsigned int i;
3077d722e3fbSopenharmony_ci
3078d722e3fbSopenharmony_ci	for (i = 0; i < ARRAY_SIZE(name_map); i++) {
3079d722e3fbSopenharmony_ci		if (!strcmp(name_map[i].name, devid_override))
3080d722e3fbSopenharmony_ci			return name_map[i].pci_id;
3081d722e3fbSopenharmony_ci	}
3082d722e3fbSopenharmony_ci
3083d722e3fbSopenharmony_ci	return strtod(devid_override, NULL);
3084d722e3fbSopenharmony_ci}
3085d722e3fbSopenharmony_ci
3086d722e3fbSopenharmony_ci/**
3087d722e3fbSopenharmony_ci * Get the PCI ID for the device.  This can be overridden by setting the
3088d722e3fbSopenharmony_ci * INTEL_DEVID_OVERRIDE environment variable to the desired ID.
3089d722e3fbSopenharmony_ci */
3090d722e3fbSopenharmony_cistatic int
3091d722e3fbSopenharmony_ciget_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem)
3092d722e3fbSopenharmony_ci{
3093d722e3fbSopenharmony_ci	char *devid_override;
3094d722e3fbSopenharmony_ci	int devid = 0;
3095d722e3fbSopenharmony_ci	int ret;
3096d722e3fbSopenharmony_ci	drm_i915_getparam_t gp;
3097d722e3fbSopenharmony_ci
3098d722e3fbSopenharmony_ci	if (geteuid() == getuid()) {
3099d722e3fbSopenharmony_ci		devid_override = getenv("INTEL_DEVID_OVERRIDE");
3100d722e3fbSopenharmony_ci		if (devid_override) {
3101d722e3fbSopenharmony_ci			bufmgr_gem->no_exec = true;
3102d722e3fbSopenharmony_ci			return parse_devid_override(devid_override);
3103d722e3fbSopenharmony_ci		}
3104d722e3fbSopenharmony_ci	}
3105d722e3fbSopenharmony_ci
3106d722e3fbSopenharmony_ci	memclear(gp);
3107d722e3fbSopenharmony_ci	gp.param = I915_PARAM_CHIPSET_ID;
3108d722e3fbSopenharmony_ci	gp.value = &devid;
3109d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3110d722e3fbSopenharmony_ci	if (ret) {
3111d722e3fbSopenharmony_ci		fprintf(stderr, "get chip id failed: %d [%d]\n", ret, errno);
3112d722e3fbSopenharmony_ci		fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value);
3113d722e3fbSopenharmony_ci	}
3114d722e3fbSopenharmony_ci	return devid;
3115d722e3fbSopenharmony_ci}
3116d722e3fbSopenharmony_ci
3117d722e3fbSopenharmony_cidrm_public int
3118d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr)
3119d722e3fbSopenharmony_ci{
3120d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
3121d722e3fbSopenharmony_ci
3122d722e3fbSopenharmony_ci	return bufmgr_gem->pci_device;
3123d722e3fbSopenharmony_ci}
3124d722e3fbSopenharmony_ci
3125d722e3fbSopenharmony_ci/**
3126d722e3fbSopenharmony_ci * Sets the AUB filename.
3127d722e3fbSopenharmony_ci *
3128d722e3fbSopenharmony_ci * This function has to be called before drm_intel_bufmgr_gem_set_aub_dump()
3129d722e3fbSopenharmony_ci * for it to have any effect.
3130d722e3fbSopenharmony_ci */
3131d722e3fbSopenharmony_cidrm_public void
3132d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr,
3133d722e3fbSopenharmony_ci				      const char *filename)
3134d722e3fbSopenharmony_ci{
3135d722e3fbSopenharmony_ci}
3136d722e3fbSopenharmony_ci
3137d722e3fbSopenharmony_ci/**
3138d722e3fbSopenharmony_ci * Sets up AUB dumping.
3139d722e3fbSopenharmony_ci *
3140d722e3fbSopenharmony_ci * This is a trace file format that can be used with the simulator.
3141d722e3fbSopenharmony_ci * Packets are emitted in a format somewhat like GPU command packets.
3142d722e3fbSopenharmony_ci * You can set up a GTT and upload your objects into the referenced
3143d722e3fbSopenharmony_ci * space, then send off batchbuffers and get BMPs out the other end.
3144d722e3fbSopenharmony_ci */
3145d722e3fbSopenharmony_cidrm_public void
3146d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable)
3147d722e3fbSopenharmony_ci{
3148d722e3fbSopenharmony_ci	fprintf(stderr, "libdrm aub dumping is deprecated.\n\n"
3149d722e3fbSopenharmony_ci		"Use intel_aubdump from intel-gpu-tools instead.  Install intel-gpu-tools,\n"
3150d722e3fbSopenharmony_ci		"then run (for example)\n\n"
3151d722e3fbSopenharmony_ci		"\t$ intel_aubdump --output=trace.aub glxgears -geometry 500x500\n\n"
3152d722e3fbSopenharmony_ci		"See the intel_aubdump man page for more details.\n");
3153d722e3fbSopenharmony_ci}
3154d722e3fbSopenharmony_ci
3155d722e3fbSopenharmony_cidrm_public drm_intel_context *
3156d722e3fbSopenharmony_cidrm_intel_gem_context_create(drm_intel_bufmgr *bufmgr)
3157d722e3fbSopenharmony_ci{
3158d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
3159d722e3fbSopenharmony_ci	struct drm_i915_gem_context_create create;
3160d722e3fbSopenharmony_ci	drm_intel_context *context = NULL;
3161d722e3fbSopenharmony_ci	int ret;
3162d722e3fbSopenharmony_ci
3163d722e3fbSopenharmony_ci	context = calloc(1, sizeof(*context));
3164d722e3fbSopenharmony_ci	if (!context)
3165d722e3fbSopenharmony_ci		return NULL;
3166d722e3fbSopenharmony_ci
3167d722e3fbSopenharmony_ci	memclear(create);
3168d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
3169d722e3fbSopenharmony_ci	if (ret != 0) {
3170d722e3fbSopenharmony_ci		DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n",
3171d722e3fbSopenharmony_ci		    strerror(errno));
3172d722e3fbSopenharmony_ci		free(context);
3173d722e3fbSopenharmony_ci		return NULL;
3174d722e3fbSopenharmony_ci	}
3175d722e3fbSopenharmony_ci
3176d722e3fbSopenharmony_ci	context->ctx_id = create.ctx_id;
3177d722e3fbSopenharmony_ci	context->bufmgr = bufmgr;
3178d722e3fbSopenharmony_ci
3179d722e3fbSopenharmony_ci	return context;
3180d722e3fbSopenharmony_ci}
3181d722e3fbSopenharmony_ci
3182d722e3fbSopenharmony_cidrm_public int
3183d722e3fbSopenharmony_cidrm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id)
3184d722e3fbSopenharmony_ci{
3185d722e3fbSopenharmony_ci	if (ctx == NULL)
3186d722e3fbSopenharmony_ci		return -EINVAL;
3187d722e3fbSopenharmony_ci
3188d722e3fbSopenharmony_ci	*ctx_id = ctx->ctx_id;
3189d722e3fbSopenharmony_ci
3190d722e3fbSopenharmony_ci	return 0;
3191d722e3fbSopenharmony_ci}
3192d722e3fbSopenharmony_ci
3193d722e3fbSopenharmony_cidrm_public void
3194d722e3fbSopenharmony_cidrm_intel_gem_context_destroy(drm_intel_context *ctx)
3195d722e3fbSopenharmony_ci{
3196d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem;
3197d722e3fbSopenharmony_ci	struct drm_i915_gem_context_destroy destroy;
3198d722e3fbSopenharmony_ci	int ret;
3199d722e3fbSopenharmony_ci
3200d722e3fbSopenharmony_ci	if (ctx == NULL)
3201d722e3fbSopenharmony_ci		return;
3202d722e3fbSopenharmony_ci
3203d722e3fbSopenharmony_ci	memclear(destroy);
3204d722e3fbSopenharmony_ci
3205d722e3fbSopenharmony_ci	bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
3206d722e3fbSopenharmony_ci	destroy.ctx_id = ctx->ctx_id;
3207d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY,
3208d722e3fbSopenharmony_ci		       &destroy);
3209d722e3fbSopenharmony_ci	if (ret != 0)
3210d722e3fbSopenharmony_ci		fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n",
3211d722e3fbSopenharmony_ci			strerror(errno));
3212d722e3fbSopenharmony_ci
3213d722e3fbSopenharmony_ci	free(ctx);
3214d722e3fbSopenharmony_ci}
3215d722e3fbSopenharmony_ci
3216d722e3fbSopenharmony_cidrm_public int
3217d722e3fbSopenharmony_cidrm_intel_get_reset_stats(drm_intel_context *ctx,
3218d722e3fbSopenharmony_ci			  uint32_t *reset_count,
3219d722e3fbSopenharmony_ci			  uint32_t *active,
3220d722e3fbSopenharmony_ci			  uint32_t *pending)
3221d722e3fbSopenharmony_ci{
3222d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem;
3223d722e3fbSopenharmony_ci	struct drm_i915_reset_stats stats;
3224d722e3fbSopenharmony_ci	int ret;
3225d722e3fbSopenharmony_ci
3226d722e3fbSopenharmony_ci	if (ctx == NULL)
3227d722e3fbSopenharmony_ci		return -EINVAL;
3228d722e3fbSopenharmony_ci
3229d722e3fbSopenharmony_ci	memclear(stats);
3230d722e3fbSopenharmony_ci
3231d722e3fbSopenharmony_ci	bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
3232d722e3fbSopenharmony_ci	stats.ctx_id = ctx->ctx_id;
3233d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
3234d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GET_RESET_STATS,
3235d722e3fbSopenharmony_ci		       &stats);
3236d722e3fbSopenharmony_ci	if (ret == 0) {
3237d722e3fbSopenharmony_ci		if (reset_count != NULL)
3238d722e3fbSopenharmony_ci			*reset_count = stats.reset_count;
3239d722e3fbSopenharmony_ci
3240d722e3fbSopenharmony_ci		if (active != NULL)
3241d722e3fbSopenharmony_ci			*active = stats.batch_active;
3242d722e3fbSopenharmony_ci
3243d722e3fbSopenharmony_ci		if (pending != NULL)
3244d722e3fbSopenharmony_ci			*pending = stats.batch_pending;
3245d722e3fbSopenharmony_ci	}
3246d722e3fbSopenharmony_ci
3247d722e3fbSopenharmony_ci	return ret;
3248d722e3fbSopenharmony_ci}
3249d722e3fbSopenharmony_ci
3250d722e3fbSopenharmony_cidrm_public int
3251d722e3fbSopenharmony_cidrm_intel_reg_read(drm_intel_bufmgr *bufmgr,
3252d722e3fbSopenharmony_ci		   uint32_t offset,
3253d722e3fbSopenharmony_ci		   uint64_t *result)
3254d722e3fbSopenharmony_ci{
3255d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
3256d722e3fbSopenharmony_ci	struct drm_i915_reg_read reg_read;
3257d722e3fbSopenharmony_ci	int ret;
3258d722e3fbSopenharmony_ci
3259d722e3fbSopenharmony_ci	memclear(reg_read);
3260d722e3fbSopenharmony_ci	reg_read.offset = offset;
3261d722e3fbSopenharmony_ci
3262d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, &reg_read);
3263d722e3fbSopenharmony_ci
3264d722e3fbSopenharmony_ci	*result = reg_read.val;
3265d722e3fbSopenharmony_ci	return ret;
3266d722e3fbSopenharmony_ci}
3267d722e3fbSopenharmony_ci
3268d722e3fbSopenharmony_cidrm_public int
3269d722e3fbSopenharmony_cidrm_intel_get_subslice_total(int fd, unsigned int *subslice_total)
3270d722e3fbSopenharmony_ci{
3271d722e3fbSopenharmony_ci	drm_i915_getparam_t gp;
3272d722e3fbSopenharmony_ci	int ret;
3273d722e3fbSopenharmony_ci
3274d722e3fbSopenharmony_ci	memclear(gp);
3275d722e3fbSopenharmony_ci	gp.value = (int*)subslice_total;
3276d722e3fbSopenharmony_ci	gp.param = I915_PARAM_SUBSLICE_TOTAL;
3277d722e3fbSopenharmony_ci	ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
3278d722e3fbSopenharmony_ci	if (ret)
3279d722e3fbSopenharmony_ci		return -errno;
3280d722e3fbSopenharmony_ci
3281d722e3fbSopenharmony_ci	return 0;
3282d722e3fbSopenharmony_ci}
3283d722e3fbSopenharmony_ci
3284d722e3fbSopenharmony_cidrm_public int
3285d722e3fbSopenharmony_cidrm_intel_get_eu_total(int fd, unsigned int *eu_total)
3286d722e3fbSopenharmony_ci{
3287d722e3fbSopenharmony_ci	drm_i915_getparam_t gp;
3288d722e3fbSopenharmony_ci	int ret;
3289d722e3fbSopenharmony_ci
3290d722e3fbSopenharmony_ci	memclear(gp);
3291d722e3fbSopenharmony_ci	gp.value = (int*)eu_total;
3292d722e3fbSopenharmony_ci	gp.param = I915_PARAM_EU_TOTAL;
3293d722e3fbSopenharmony_ci	ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
3294d722e3fbSopenharmony_ci	if (ret)
3295d722e3fbSopenharmony_ci		return -errno;
3296d722e3fbSopenharmony_ci
3297d722e3fbSopenharmony_ci	return 0;
3298d722e3fbSopenharmony_ci}
3299d722e3fbSopenharmony_ci
3300d722e3fbSopenharmony_cidrm_public int
3301d722e3fbSopenharmony_cidrm_intel_get_pooled_eu(int fd)
3302d722e3fbSopenharmony_ci{
3303d722e3fbSopenharmony_ci	drm_i915_getparam_t gp;
3304d722e3fbSopenharmony_ci	int ret = -1;
3305d722e3fbSopenharmony_ci
3306d722e3fbSopenharmony_ci	memclear(gp);
3307d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_POOLED_EU;
3308d722e3fbSopenharmony_ci	gp.value = &ret;
3309d722e3fbSopenharmony_ci	if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
3310d722e3fbSopenharmony_ci		return -errno;
3311d722e3fbSopenharmony_ci
3312d722e3fbSopenharmony_ci	return ret;
3313d722e3fbSopenharmony_ci}
3314d722e3fbSopenharmony_ci
3315d722e3fbSopenharmony_cidrm_public int
3316d722e3fbSopenharmony_cidrm_intel_get_min_eu_in_pool(int fd)
3317d722e3fbSopenharmony_ci{
3318d722e3fbSopenharmony_ci	drm_i915_getparam_t gp;
3319d722e3fbSopenharmony_ci	int ret = -1;
3320d722e3fbSopenharmony_ci
3321d722e3fbSopenharmony_ci	memclear(gp);
3322d722e3fbSopenharmony_ci	gp.param = I915_PARAM_MIN_EU_IN_POOL;
3323d722e3fbSopenharmony_ci	gp.value = &ret;
3324d722e3fbSopenharmony_ci	if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
3325d722e3fbSopenharmony_ci		return -errno;
3326d722e3fbSopenharmony_ci
3327d722e3fbSopenharmony_ci	return ret;
3328d722e3fbSopenharmony_ci}
3329d722e3fbSopenharmony_ci
3330d722e3fbSopenharmony_ci/**
3331d722e3fbSopenharmony_ci * Annotate the given bo for use in aub dumping.
3332d722e3fbSopenharmony_ci *
3333d722e3fbSopenharmony_ci * \param annotations is an array of drm_intel_aub_annotation objects
3334d722e3fbSopenharmony_ci * describing the type of data in various sections of the bo.  Each
3335d722e3fbSopenharmony_ci * element of the array specifies the type and subtype of a section of
3336d722e3fbSopenharmony_ci * the bo, and the past-the-end offset of that section.  The elements
3337d722e3fbSopenharmony_ci * of \c annotations must be sorted so that ending_offset is
3338d722e3fbSopenharmony_ci * increasing.
3339d722e3fbSopenharmony_ci *
3340d722e3fbSopenharmony_ci * \param count is the number of elements in the \c annotations array.
3341d722e3fbSopenharmony_ci * If \c count is zero, then \c annotations will not be dereferenced.
3342d722e3fbSopenharmony_ci *
3343d722e3fbSopenharmony_ci * Annotations are copied into a private data structure, so caller may
3344d722e3fbSopenharmony_ci * re-use the memory pointed to by \c annotations after the call
3345d722e3fbSopenharmony_ci * returns.
3346d722e3fbSopenharmony_ci *
3347d722e3fbSopenharmony_ci * Annotations are stored for the lifetime of the bo; to reset to the
3348d722e3fbSopenharmony_ci * default state (no annotations), call this function with a \c count
3349d722e3fbSopenharmony_ci * of zero.
3350d722e3fbSopenharmony_ci */
3351d722e3fbSopenharmony_cidrm_public void drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
3352d722e3fbSopenharmony_ci					 drm_intel_aub_annotation *annotations,
3353d722e3fbSopenharmony_ci					 unsigned count)
3354d722e3fbSopenharmony_ci{
3355d722e3fbSopenharmony_ci}
3356d722e3fbSopenharmony_ci
3357d722e3fbSopenharmony_cistatic pthread_mutex_t bufmgr_list_mutex = PTHREAD_MUTEX_INITIALIZER;
3358d722e3fbSopenharmony_cistatic drmMMListHead bufmgr_list = { &bufmgr_list, &bufmgr_list };
3359d722e3fbSopenharmony_ci
3360d722e3fbSopenharmony_cistatic drm_intel_bufmgr_gem *
3361d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_find(int fd)
3362d722e3fbSopenharmony_ci{
3363d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem;
3364d722e3fbSopenharmony_ci
3365d722e3fbSopenharmony_ci	DRMLISTFOREACHENTRY(bufmgr_gem, &bufmgr_list, managers) {
3366d722e3fbSopenharmony_ci		if (bufmgr_gem->fd == fd) {
3367d722e3fbSopenharmony_ci			atomic_inc(&bufmgr_gem->refcount);
3368d722e3fbSopenharmony_ci			return bufmgr_gem;
3369d722e3fbSopenharmony_ci		}
3370d722e3fbSopenharmony_ci	}
3371d722e3fbSopenharmony_ci
3372d722e3fbSopenharmony_ci	return NULL;
3373d722e3fbSopenharmony_ci}
3374d722e3fbSopenharmony_ci
3375d722e3fbSopenharmony_cistatic void
3376d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_unref(drm_intel_bufmgr *bufmgr)
3377d722e3fbSopenharmony_ci{
3378d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
3379d722e3fbSopenharmony_ci
3380d722e3fbSopenharmony_ci	if (atomic_add_unless(&bufmgr_gem->refcount, -1, 1)) {
3381d722e3fbSopenharmony_ci		pthread_mutex_lock(&bufmgr_list_mutex);
3382d722e3fbSopenharmony_ci
3383d722e3fbSopenharmony_ci		if (atomic_dec_and_test(&bufmgr_gem->refcount)) {
3384d722e3fbSopenharmony_ci			DRMLISTDEL(&bufmgr_gem->managers);
3385d722e3fbSopenharmony_ci			drm_intel_bufmgr_gem_destroy(bufmgr);
3386d722e3fbSopenharmony_ci		}
3387d722e3fbSopenharmony_ci
3388d722e3fbSopenharmony_ci		pthread_mutex_unlock(&bufmgr_list_mutex);
3389d722e3fbSopenharmony_ci	}
3390d722e3fbSopenharmony_ci}
3391d722e3fbSopenharmony_ci
3392d722e3fbSopenharmony_cidrm_public void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo)
3393d722e3fbSopenharmony_ci{
3394d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
3395d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
3396d722e3fbSopenharmony_ci
3397d722e3fbSopenharmony_ci	if (bo_gem->gtt_virtual)
3398d722e3fbSopenharmony_ci		return bo_gem->gtt_virtual;
3399d722e3fbSopenharmony_ci
3400d722e3fbSopenharmony_ci	if (bo_gem->is_userptr)
3401d722e3fbSopenharmony_ci		return NULL;
3402d722e3fbSopenharmony_ci
3403d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
3404d722e3fbSopenharmony_ci	if (bo_gem->gtt_virtual == NULL) {
3405d722e3fbSopenharmony_ci		struct drm_i915_gem_mmap_gtt mmap_arg;
3406d722e3fbSopenharmony_ci		void *ptr;
3407d722e3fbSopenharmony_ci
3408d722e3fbSopenharmony_ci		DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
3409d722e3fbSopenharmony_ci		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
3410d722e3fbSopenharmony_ci
3411d722e3fbSopenharmony_ci		if (bo_gem->map_count++ == 0)
3412d722e3fbSopenharmony_ci			drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
3413d722e3fbSopenharmony_ci
3414d722e3fbSopenharmony_ci		memclear(mmap_arg);
3415d722e3fbSopenharmony_ci		mmap_arg.handle = bo_gem->gem_handle;
3416d722e3fbSopenharmony_ci
3417d722e3fbSopenharmony_ci		/* Get the fake offset back... */
3418d722e3fbSopenharmony_ci		ptr = MAP_FAILED;
3419d722e3fbSopenharmony_ci		if (drmIoctl(bufmgr_gem->fd,
3420d722e3fbSopenharmony_ci			     DRM_IOCTL_I915_GEM_MMAP_GTT,
3421d722e3fbSopenharmony_ci			     &mmap_arg) == 0) {
3422d722e3fbSopenharmony_ci			/* and mmap it */
3423d722e3fbSopenharmony_ci			ptr = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE,
3424d722e3fbSopenharmony_ci				       MAP_SHARED, bufmgr_gem->fd,
3425d722e3fbSopenharmony_ci				       mmap_arg.offset);
3426d722e3fbSopenharmony_ci		}
3427d722e3fbSopenharmony_ci		if (ptr == MAP_FAILED) {
3428d722e3fbSopenharmony_ci			if (--bo_gem->map_count == 0)
3429d722e3fbSopenharmony_ci				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
3430d722e3fbSopenharmony_ci			ptr = NULL;
3431d722e3fbSopenharmony_ci		}
3432d722e3fbSopenharmony_ci
3433d722e3fbSopenharmony_ci		bo_gem->gtt_virtual = ptr;
3434d722e3fbSopenharmony_ci	}
3435d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
3436d722e3fbSopenharmony_ci
3437d722e3fbSopenharmony_ci	return bo_gem->gtt_virtual;
3438d722e3fbSopenharmony_ci}
3439d722e3fbSopenharmony_ci
3440d722e3fbSopenharmony_cidrm_public void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo)
3441d722e3fbSopenharmony_ci{
3442d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
3443d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
3444d722e3fbSopenharmony_ci
3445d722e3fbSopenharmony_ci	if (bo_gem->mem_virtual)
3446d722e3fbSopenharmony_ci		return bo_gem->mem_virtual;
3447d722e3fbSopenharmony_ci
3448d722e3fbSopenharmony_ci	if (bo_gem->is_userptr) {
3449d722e3fbSopenharmony_ci		/* Return the same user ptr */
3450d722e3fbSopenharmony_ci		return bo_gem->user_virtual;
3451d722e3fbSopenharmony_ci	}
3452d722e3fbSopenharmony_ci
3453d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
3454d722e3fbSopenharmony_ci	if (!bo_gem->mem_virtual) {
3455d722e3fbSopenharmony_ci		struct drm_i915_gem_mmap mmap_arg;
3456d722e3fbSopenharmony_ci
3457d722e3fbSopenharmony_ci		if (bo_gem->map_count++ == 0)
3458d722e3fbSopenharmony_ci			drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
3459d722e3fbSopenharmony_ci
3460d722e3fbSopenharmony_ci		DBG("bo_map: %d (%s), map_count=%d\n",
3461d722e3fbSopenharmony_ci		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
3462d722e3fbSopenharmony_ci
3463d722e3fbSopenharmony_ci		memclear(mmap_arg);
3464d722e3fbSopenharmony_ci		mmap_arg.handle = bo_gem->gem_handle;
3465d722e3fbSopenharmony_ci		mmap_arg.size = bo->size;
3466d722e3fbSopenharmony_ci		if (drmIoctl(bufmgr_gem->fd,
3467d722e3fbSopenharmony_ci			     DRM_IOCTL_I915_GEM_MMAP,
3468d722e3fbSopenharmony_ci			     &mmap_arg)) {
3469d722e3fbSopenharmony_ci			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
3470d722e3fbSopenharmony_ci			    __FILE__, __LINE__, bo_gem->gem_handle,
3471d722e3fbSopenharmony_ci			    bo_gem->name, strerror(errno));
3472d722e3fbSopenharmony_ci			if (--bo_gem->map_count == 0)
3473d722e3fbSopenharmony_ci				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
3474d722e3fbSopenharmony_ci		} else {
3475d722e3fbSopenharmony_ci			VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
3476d722e3fbSopenharmony_ci			bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
3477d722e3fbSopenharmony_ci		}
3478d722e3fbSopenharmony_ci	}
3479d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
3480d722e3fbSopenharmony_ci
3481d722e3fbSopenharmony_ci	return bo_gem->mem_virtual;
3482d722e3fbSopenharmony_ci}
3483d722e3fbSopenharmony_ci
3484d722e3fbSopenharmony_cidrm_public void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo)
3485d722e3fbSopenharmony_ci{
3486d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
3487d722e3fbSopenharmony_ci	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
3488d722e3fbSopenharmony_ci
3489d722e3fbSopenharmony_ci	if (bo_gem->wc_virtual)
3490d722e3fbSopenharmony_ci		return bo_gem->wc_virtual;
3491d722e3fbSopenharmony_ci
3492d722e3fbSopenharmony_ci	if (bo_gem->is_userptr)
3493d722e3fbSopenharmony_ci		return NULL;
3494d722e3fbSopenharmony_ci
3495d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_gem->lock);
3496d722e3fbSopenharmony_ci	if (!bo_gem->wc_virtual) {
3497d722e3fbSopenharmony_ci		struct drm_i915_gem_mmap mmap_arg;
3498d722e3fbSopenharmony_ci
3499d722e3fbSopenharmony_ci		if (bo_gem->map_count++ == 0)
3500d722e3fbSopenharmony_ci			drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
3501d722e3fbSopenharmony_ci
3502d722e3fbSopenharmony_ci		DBG("bo_map: %d (%s), map_count=%d\n",
3503d722e3fbSopenharmony_ci		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
3504d722e3fbSopenharmony_ci
3505d722e3fbSopenharmony_ci		memclear(mmap_arg);
3506d722e3fbSopenharmony_ci		mmap_arg.handle = bo_gem->gem_handle;
3507d722e3fbSopenharmony_ci		mmap_arg.size = bo->size;
3508d722e3fbSopenharmony_ci		mmap_arg.flags = I915_MMAP_WC;
3509d722e3fbSopenharmony_ci		if (drmIoctl(bufmgr_gem->fd,
3510d722e3fbSopenharmony_ci			     DRM_IOCTL_I915_GEM_MMAP,
3511d722e3fbSopenharmony_ci			     &mmap_arg)) {
3512d722e3fbSopenharmony_ci			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
3513d722e3fbSopenharmony_ci			    __FILE__, __LINE__, bo_gem->gem_handle,
3514d722e3fbSopenharmony_ci			    bo_gem->name, strerror(errno));
3515d722e3fbSopenharmony_ci			if (--bo_gem->map_count == 0)
3516d722e3fbSopenharmony_ci				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
3517d722e3fbSopenharmony_ci		} else {
3518d722e3fbSopenharmony_ci			VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
3519d722e3fbSopenharmony_ci			bo_gem->wc_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
3520d722e3fbSopenharmony_ci		}
3521d722e3fbSopenharmony_ci	}
3522d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_gem->lock);
3523d722e3fbSopenharmony_ci
3524d722e3fbSopenharmony_ci	return bo_gem->wc_virtual;
3525d722e3fbSopenharmony_ci}
3526d722e3fbSopenharmony_ci
3527d722e3fbSopenharmony_ci/**
3528d722e3fbSopenharmony_ci * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
3529d722e3fbSopenharmony_ci * and manage map buffer objections.
3530d722e3fbSopenharmony_ci *
3531d722e3fbSopenharmony_ci * \param fd File descriptor of the opened DRM device.
3532d722e3fbSopenharmony_ci */
3533d722e3fbSopenharmony_cidrm_public drm_intel_bufmgr *
3534d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_init(int fd, int batch_size)
3535d722e3fbSopenharmony_ci{
3536d722e3fbSopenharmony_ci	drm_intel_bufmgr_gem *bufmgr_gem;
3537d722e3fbSopenharmony_ci	struct drm_i915_gem_get_aperture aperture;
3538d722e3fbSopenharmony_ci	drm_i915_getparam_t gp;
3539d722e3fbSopenharmony_ci	int ret, tmp;
3540d722e3fbSopenharmony_ci
3541d722e3fbSopenharmony_ci	pthread_mutex_lock(&bufmgr_list_mutex);
3542d722e3fbSopenharmony_ci
3543d722e3fbSopenharmony_ci	bufmgr_gem = drm_intel_bufmgr_gem_find(fd);
3544d722e3fbSopenharmony_ci	if (bufmgr_gem)
3545d722e3fbSopenharmony_ci		goto exit;
3546d722e3fbSopenharmony_ci
3547d722e3fbSopenharmony_ci	bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
3548d722e3fbSopenharmony_ci	if (bufmgr_gem == NULL)
3549d722e3fbSopenharmony_ci		goto exit;
3550d722e3fbSopenharmony_ci
3551d722e3fbSopenharmony_ci	bufmgr_gem->fd = fd;
3552d722e3fbSopenharmony_ci	atomic_set(&bufmgr_gem->refcount, 1);
3553d722e3fbSopenharmony_ci
3554d722e3fbSopenharmony_ci	if (pthread_mutex_init(&bufmgr_gem->lock, NULL) != 0) {
3555d722e3fbSopenharmony_ci		free(bufmgr_gem);
3556d722e3fbSopenharmony_ci		bufmgr_gem = NULL;
3557d722e3fbSopenharmony_ci		goto exit;
3558d722e3fbSopenharmony_ci	}
3559d722e3fbSopenharmony_ci
3560d722e3fbSopenharmony_ci	memclear(aperture);
3561d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd,
3562d722e3fbSopenharmony_ci		       DRM_IOCTL_I915_GEM_GET_APERTURE,
3563d722e3fbSopenharmony_ci		       &aperture);
3564d722e3fbSopenharmony_ci
3565d722e3fbSopenharmony_ci	if (ret == 0)
3566d722e3fbSopenharmony_ci		bufmgr_gem->gtt_size = aperture.aper_available_size;
3567d722e3fbSopenharmony_ci	else {
3568d722e3fbSopenharmony_ci		fprintf(stderr, "DRM_IOCTL_I915_GEM_APERTURE failed: %s\n",
3569d722e3fbSopenharmony_ci			strerror(errno));
3570d722e3fbSopenharmony_ci		bufmgr_gem->gtt_size = 128 * 1024 * 1024;
3571d722e3fbSopenharmony_ci		fprintf(stderr, "Assuming %dkB available aperture size.\n"
3572d722e3fbSopenharmony_ci			"May lead to reduced performance or incorrect "
3573d722e3fbSopenharmony_ci			"rendering.\n",
3574d722e3fbSopenharmony_ci			(int)bufmgr_gem->gtt_size / 1024);
3575d722e3fbSopenharmony_ci	}
3576d722e3fbSopenharmony_ci
3577d722e3fbSopenharmony_ci	bufmgr_gem->pci_device = get_pci_device_id(bufmgr_gem);
3578d722e3fbSopenharmony_ci
3579d722e3fbSopenharmony_ci	if (IS_GEN2(bufmgr_gem->pci_device))
3580d722e3fbSopenharmony_ci		bufmgr_gem->gen = 2;
3581d722e3fbSopenharmony_ci	else if (IS_GEN3(bufmgr_gem->pci_device))
3582d722e3fbSopenharmony_ci		bufmgr_gem->gen = 3;
3583d722e3fbSopenharmony_ci	else if (IS_GEN4(bufmgr_gem->pci_device))
3584d722e3fbSopenharmony_ci		bufmgr_gem->gen = 4;
3585d722e3fbSopenharmony_ci	else if (IS_GEN5(bufmgr_gem->pci_device))
3586d722e3fbSopenharmony_ci		bufmgr_gem->gen = 5;
3587d722e3fbSopenharmony_ci	else if (IS_GEN6(bufmgr_gem->pci_device))
3588d722e3fbSopenharmony_ci		bufmgr_gem->gen = 6;
3589d722e3fbSopenharmony_ci	else if (IS_GEN7(bufmgr_gem->pci_device))
3590d722e3fbSopenharmony_ci		bufmgr_gem->gen = 7;
3591d722e3fbSopenharmony_ci	else if (IS_GEN8(bufmgr_gem->pci_device))
3592d722e3fbSopenharmony_ci		bufmgr_gem->gen = 8;
3593d722e3fbSopenharmony_ci	else if (!intel_get_genx(bufmgr_gem->pci_device, &bufmgr_gem->gen)) {
3594d722e3fbSopenharmony_ci		free(bufmgr_gem);
3595d722e3fbSopenharmony_ci		bufmgr_gem = NULL;
3596d722e3fbSopenharmony_ci		goto exit;
3597d722e3fbSopenharmony_ci	}
3598d722e3fbSopenharmony_ci
3599d722e3fbSopenharmony_ci	if (IS_GEN3(bufmgr_gem->pci_device) &&
3600d722e3fbSopenharmony_ci	    bufmgr_gem->gtt_size > 256*1024*1024) {
3601d722e3fbSopenharmony_ci		/* The unmappable part of gtt on gen 3 (i.e. above 256MB) can't
3602d722e3fbSopenharmony_ci		 * be used for tiled blits. To simplify the accounting, just
3603d722e3fbSopenharmony_ci		 * subtract the unmappable part (fixed to 256MB on all known
3604d722e3fbSopenharmony_ci		 * gen3 devices) if the kernel advertises it. */
3605d722e3fbSopenharmony_ci		bufmgr_gem->gtt_size -= 256*1024*1024;
3606d722e3fbSopenharmony_ci	}
3607d722e3fbSopenharmony_ci
3608d722e3fbSopenharmony_ci	memclear(gp);
3609d722e3fbSopenharmony_ci	gp.value = &tmp;
3610d722e3fbSopenharmony_ci
3611d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_EXECBUF2;
3612d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3613d722e3fbSopenharmony_ci	if (ret) {
3614d722e3fbSopenharmony_ci		fprintf(stderr, "i915 does not support EXECBUFER2\n");
3615d722e3fbSopenharmony_ci		free(bufmgr_gem);
3616d722e3fbSopenharmony_ci		bufmgr_gem = NULL;
3617d722e3fbSopenharmony_ci        goto exit;
3618d722e3fbSopenharmony_ci    }
3619d722e3fbSopenharmony_ci
3620d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_BSD;
3621d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3622d722e3fbSopenharmony_ci	bufmgr_gem->has_bsd = ret == 0;
3623d722e3fbSopenharmony_ci
3624d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_BLT;
3625d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3626d722e3fbSopenharmony_ci	bufmgr_gem->has_blt = ret == 0;
3627d722e3fbSopenharmony_ci
3628d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_RELAXED_FENCING;
3629d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3630d722e3fbSopenharmony_ci	bufmgr_gem->has_relaxed_fencing = ret == 0;
3631d722e3fbSopenharmony_ci
3632d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_EXEC_ASYNC;
3633d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3634d722e3fbSopenharmony_ci	bufmgr_gem->has_exec_async = ret == 0;
3635d722e3fbSopenharmony_ci
3636d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_alloc_userptr = check_bo_alloc_userptr;
3637d722e3fbSopenharmony_ci
3638d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_WAIT_TIMEOUT;
3639d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3640d722e3fbSopenharmony_ci	bufmgr_gem->has_wait_timeout = ret == 0;
3641d722e3fbSopenharmony_ci
3642d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_LLC;
3643d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3644d722e3fbSopenharmony_ci	if (ret != 0) {
3645d722e3fbSopenharmony_ci		/* Kernel does not supports HAS_LLC query, fallback to GPU
3646d722e3fbSopenharmony_ci		 * generation detection and assume that we have LLC on GEN6/7
3647d722e3fbSopenharmony_ci		 */
3648d722e3fbSopenharmony_ci		bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) |
3649d722e3fbSopenharmony_ci				IS_GEN7(bufmgr_gem->pci_device));
3650d722e3fbSopenharmony_ci	} else
3651d722e3fbSopenharmony_ci		bufmgr_gem->has_llc = *gp.value;
3652d722e3fbSopenharmony_ci
3653d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_VEBOX;
3654d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3655d722e3fbSopenharmony_ci	bufmgr_gem->has_vebox = (ret == 0) & (*gp.value > 0);
3656d722e3fbSopenharmony_ci
3657d722e3fbSopenharmony_ci	gp.param = I915_PARAM_HAS_EXEC_SOFTPIN;
3658d722e3fbSopenharmony_ci	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3659d722e3fbSopenharmony_ci	if (ret == 0 && *gp.value > 0)
3660d722e3fbSopenharmony_ci		bufmgr_gem->bufmgr.bo_set_softpin_offset = drm_intel_gem_bo_set_softpin_offset;
3661d722e3fbSopenharmony_ci
3662d722e3fbSopenharmony_ci	if (bufmgr_gem->gen < 4) {
3663d722e3fbSopenharmony_ci		gp.param = I915_PARAM_NUM_FENCES_AVAIL;
3664d722e3fbSopenharmony_ci		gp.value = &bufmgr_gem->available_fences;
3665d722e3fbSopenharmony_ci		ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3666d722e3fbSopenharmony_ci		if (ret) {
3667d722e3fbSopenharmony_ci			fprintf(stderr, "get fences failed: %d [%d]\n", ret,
3668d722e3fbSopenharmony_ci				errno);
3669d722e3fbSopenharmony_ci			fprintf(stderr, "param: %d, val: %d\n", gp.param,
3670d722e3fbSopenharmony_ci				*gp.value);
3671d722e3fbSopenharmony_ci			bufmgr_gem->available_fences = 0;
3672d722e3fbSopenharmony_ci		} else {
3673d722e3fbSopenharmony_ci			/* XXX The kernel reports the total number of fences,
3674d722e3fbSopenharmony_ci			 * including any that may be pinned.
3675d722e3fbSopenharmony_ci			 *
3676d722e3fbSopenharmony_ci			 * We presume that there will be at least one pinned
3677d722e3fbSopenharmony_ci			 * fence for the scanout buffer, but there may be more
3678d722e3fbSopenharmony_ci			 * than one scanout and the user may be manually
3679d722e3fbSopenharmony_ci			 * pinning buffers. Let's move to execbuffer2 and
3680d722e3fbSopenharmony_ci			 * thereby forget the insanity of using fences...
3681d722e3fbSopenharmony_ci			 */
3682d722e3fbSopenharmony_ci			bufmgr_gem->available_fences -= 2;
3683d722e3fbSopenharmony_ci			if (bufmgr_gem->available_fences < 0)
3684d722e3fbSopenharmony_ci				bufmgr_gem->available_fences = 0;
3685d722e3fbSopenharmony_ci		}
3686d722e3fbSopenharmony_ci	}
3687d722e3fbSopenharmony_ci
3688d722e3fbSopenharmony_ci	if (bufmgr_gem->gen >= 8) {
3689d722e3fbSopenharmony_ci		gp.param = I915_PARAM_HAS_ALIASING_PPGTT;
3690d722e3fbSopenharmony_ci		ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3691d722e3fbSopenharmony_ci		if (ret == 0 && *gp.value == 3)
3692d722e3fbSopenharmony_ci			bufmgr_gem->bufmgr.bo_use_48b_address_range = drm_intel_gem_bo_use_48b_address_range;
3693d722e3fbSopenharmony_ci	}
3694d722e3fbSopenharmony_ci
3695d722e3fbSopenharmony_ci	/* Let's go with one relocation per every 2 dwords (but round down a bit
3696d722e3fbSopenharmony_ci	 * since a power of two will mean an extra page allocation for the reloc
3697d722e3fbSopenharmony_ci	 * buffer).
3698d722e3fbSopenharmony_ci	 *
3699d722e3fbSopenharmony_ci	 * Every 4 was too few for the blender benchmark.
3700d722e3fbSopenharmony_ci	 */
3701d722e3fbSopenharmony_ci	bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2;
3702d722e3fbSopenharmony_ci
3703d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_alloc = drm_intel_gem_bo_alloc;
3704d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_alloc_for_render =
3705d722e3fbSopenharmony_ci	    drm_intel_gem_bo_alloc_for_render;
3706d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_alloc_tiled = drm_intel_gem_bo_alloc_tiled;
3707d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_reference = drm_intel_gem_bo_reference;
3708d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_unreference = drm_intel_gem_bo_unreference;
3709d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_map = drm_intel_gem_bo_map;
3710d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_unmap = drm_intel_gem_bo_unmap;
3711d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_subdata = drm_intel_gem_bo_subdata;
3712d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_get_subdata = drm_intel_gem_bo_get_subdata;
3713d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_wait_rendering = drm_intel_gem_bo_wait_rendering;
3714d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_emit_reloc = drm_intel_gem_bo_emit_reloc;
3715d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_emit_reloc_fence = drm_intel_gem_bo_emit_reloc_fence;
3716d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_pin = drm_intel_gem_bo_pin;
3717d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_unpin = drm_intel_gem_bo_unpin;
3718d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_get_tiling = drm_intel_gem_bo_get_tiling;
3719d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_set_tiling = drm_intel_gem_bo_set_tiling;
3720d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_flink = drm_intel_gem_bo_flink;
3721d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec2;
3722d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_mrb_exec = drm_intel_gem_bo_mrb_exec2;
3723d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_busy = drm_intel_gem_bo_busy;
3724d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_madvise = drm_intel_gem_bo_madvise;
3725d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.destroy = drm_intel_bufmgr_gem_unref;
3726d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.debug = 0;
3727d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.check_aperture_space =
3728d722e3fbSopenharmony_ci	    drm_intel_gem_check_aperture_space;
3729d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_disable_reuse = drm_intel_gem_bo_disable_reuse;
3730d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_is_reusable = drm_intel_gem_bo_is_reusable;
3731d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.get_pipe_from_crtc_id =
3732d722e3fbSopenharmony_ci	    drm_intel_gem_get_pipe_from_crtc_id;
3733d722e3fbSopenharmony_ci	bufmgr_gem->bufmgr.bo_references = drm_intel_gem_bo_references;
3734d722e3fbSopenharmony_ci
3735d722e3fbSopenharmony_ci	init_cache_buckets(bufmgr_gem);
3736d722e3fbSopenharmony_ci
3737d722e3fbSopenharmony_ci	DRMINITLISTHEAD(&bufmgr_gem->vma_cache);
3738d722e3fbSopenharmony_ci	bufmgr_gem->vma_max = -1; /* unlimited by default */
3739d722e3fbSopenharmony_ci
3740d722e3fbSopenharmony_ci	DRMLISTADD(&bufmgr_gem->managers, &bufmgr_list);
3741d722e3fbSopenharmony_ci
3742d722e3fbSopenharmony_ciexit:
3743d722e3fbSopenharmony_ci	pthread_mutex_unlock(&bufmgr_list_mutex);
3744d722e3fbSopenharmony_ci
3745d722e3fbSopenharmony_ci	return bufmgr_gem != NULL ? &bufmgr_gem->bufmgr : NULL;
3746d722e3fbSopenharmony_ci}
3747