intel_bufmgr_gem.c revision 2ee35494
122944501Smrg/**************************************************************************
222944501Smrg *
322944501Smrg * Copyright � 2007 Red Hat Inc.
420131375Smrg * Copyright � 2007-2012 Intel Corporation
522944501Smrg * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
622944501Smrg * All Rights Reserved.
722944501Smrg *
822944501Smrg * Permission is hereby granted, free of charge, to any person obtaining a
922944501Smrg * copy of this software and associated documentation files (the
1022944501Smrg * "Software"), to deal in the Software without restriction, including
1122944501Smrg * without limitation the rights to use, copy, modify, merge, publish,
1222944501Smrg * distribute, sub license, and/or sell copies of the Software, and to
1322944501Smrg * permit persons to whom the Software is furnished to do so, subject to
1422944501Smrg * the following conditions:
1522944501Smrg *
1622944501Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1722944501Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1822944501Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
1922944501Smrg * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
2022944501Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2122944501Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2222944501Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
2322944501Smrg *
2422944501Smrg * The above copyright notice and this permission notice (including the
2522944501Smrg * next paragraph) shall be included in all copies or substantial portions
2622944501Smrg * of the Software.
2722944501Smrg *
2822944501Smrg *
2922944501Smrg **************************************************************************/
3022944501Smrg/*
3122944501Smrg * Authors: Thomas Hellstr�m <thomas-at-tungstengraphics-dot-com>
3222944501Smrg *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
3322944501Smrg *	    Eric Anholt <eric@anholt.net>
3422944501Smrg *	    Dave Airlie <airlied@linux.ie>
3522944501Smrg */
3622944501Smrg
3722944501Smrg#ifdef HAVE_CONFIG_H
3822944501Smrg#include "config.h"
3922944501Smrg#endif
4022944501Smrg
4122944501Smrg#include <xf86drm.h>
4222944501Smrg#include <xf86atomic.h>
4322944501Smrg#include <fcntl.h>
4422944501Smrg#include <stdio.h>
4522944501Smrg#include <stdlib.h>
4622944501Smrg#include <string.h>
4722944501Smrg#include <unistd.h>
4822944501Smrg#include <assert.h>
4922944501Smrg#include <pthread.h>
502e6867f6Smrg#include <stddef.h>
5122944501Smrg#include <sys/ioctl.h>
5222944501Smrg#include <sys/stat.h>
5322944501Smrg#include <sys/types.h>
5420131375Smrg#include <stdbool.h>
5522944501Smrg
5622944501Smrg#include "errno.h"
5720131375Smrg#ifndef ETIME
5820131375Smrg#define ETIME ETIMEDOUT
5920131375Smrg#endif
60424e9256Smrg#include "libdrm_macros.h"
6122944501Smrg#include "libdrm_lists.h"
6222944501Smrg#include "intel_bufmgr.h"
6322944501Smrg#include "intel_bufmgr_priv.h"
6422944501Smrg#include "intel_chipset.h"
6522944501Smrg#include "string.h"
6622944501Smrg
6722944501Smrg#include "i915_drm.h"
682ee35494Smrg#include "uthash.h"
6922944501Smrg
7020131375Smrg#ifdef HAVE_VALGRIND
7120131375Smrg#include <valgrind.h>
7220131375Smrg#include <memcheck.h>
7320131375Smrg#define VG(x) x
7420131375Smrg#else
7520131375Smrg#define VG(x)
7620131375Smrg#endif
7720131375Smrg
78424e9256Smrg#define memclear(s) memset(&s, 0, sizeof(s))
7920131375Smrg
8022944501Smrg#define DBG(...) do {					\
8122944501Smrg	if (bufmgr_gem->bufmgr.debug)			\
8222944501Smrg		fprintf(stderr, __VA_ARGS__);		\
8322944501Smrg} while (0)
8422944501Smrg
85aaba2545Smrg#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
86fe517fc9Smrg#define MAX2(A, B) ((A) > (B) ? (A) : (B))
87fe517fc9Smrg
88fe517fc9Smrg/**
89fe517fc9Smrg * upper_32_bits - return bits 32-63 of a number
90fe517fc9Smrg * @n: the number we're accessing
91fe517fc9Smrg *
92fe517fc9Smrg * A basic shift-right of a 64- or 32-bit quantity.  Use this to suppress
93fe517fc9Smrg * the "right shift count >= width of type" warning when that quantity is
94fe517fc9Smrg * 32-bits.
95fe517fc9Smrg */
96fe517fc9Smrg#define upper_32_bits(n) ((__u32)(((n) >> 16) >> 16))
97fe517fc9Smrg
98fe517fc9Smrg/**
99fe517fc9Smrg * lower_32_bits - return bits 0-31 of a number
100fe517fc9Smrg * @n: the number we're accessing
101fe517fc9Smrg */
102fe517fc9Smrg#define lower_32_bits(n) ((__u32)(n))
103aaba2545Smrg
10422944501Smrgtypedef struct _drm_intel_bo_gem drm_intel_bo_gem;
10522944501Smrg
10622944501Smrgstruct drm_intel_gem_bo_bucket {
10722944501Smrg	drmMMListHead head;
10822944501Smrg	unsigned long size;
10922944501Smrg};
11022944501Smrg
11122944501Smrgtypedef struct _drm_intel_bufmgr_gem {
11222944501Smrg	drm_intel_bufmgr bufmgr;
11322944501Smrg
114a884aba1Smrg	atomic_t refcount;
115a884aba1Smrg
11622944501Smrg	int fd;
11722944501Smrg
11822944501Smrg	int max_relocs;
11922944501Smrg
12022944501Smrg	pthread_mutex_t lock;
12122944501Smrg
12222944501Smrg	struct drm_i915_gem_exec_object *exec_objects;
12322944501Smrg	struct drm_i915_gem_exec_object2 *exec2_objects;
12422944501Smrg	drm_intel_bo **exec_bos;
12522944501Smrg	int exec_size;
12622944501Smrg	int exec_count;
12722944501Smrg
12822944501Smrg	/** Array of lists of cached gem objects of power-of-two sizes */
129aaba2545Smrg	struct drm_intel_gem_bo_bucket cache_bucket[14 * 4];
130aaba2545Smrg	int num_buckets;
1316d98c517Smrg	time_t time;
13222944501Smrg
133a884aba1Smrg	drmMMListHead managers;
134a884aba1Smrg
1352ee35494Smrg	drm_intel_bo_gem *name_table;
1362ee35494Smrg	drm_intel_bo_gem *handle_table;
1372ee35494Smrg
13820131375Smrg	drmMMListHead vma_cache;
13920131375Smrg	int vma_count, vma_open, vma_max;
14020131375Smrg
14122944501Smrg	uint64_t gtt_size;
14222944501Smrg	int available_fences;
14322944501Smrg	int pci_device;
14422944501Smrg	int gen;
1459ce4edccSmrg	unsigned int has_bsd : 1;
1469ce4edccSmrg	unsigned int has_blt : 1;
1479ce4edccSmrg	unsigned int has_relaxed_fencing : 1;
14820131375Smrg	unsigned int has_llc : 1;
14920131375Smrg	unsigned int has_wait_timeout : 1;
1509ce4edccSmrg	unsigned int bo_reuse : 1;
15120131375Smrg	unsigned int no_exec : 1;
15220131375Smrg	unsigned int has_vebox : 1;
1532ee35494Smrg	unsigned int has_exec_async : 1;
15420131375Smrg	bool fenced_relocs;
15520131375Smrg
156424e9256Smrg	struct {
157424e9256Smrg		void *ptr;
158424e9256Smrg		uint32_t handle;
159424e9256Smrg	} userptr_active;
160424e9256Smrg
16122944501Smrg} drm_intel_bufmgr_gem;
16222944501Smrg
16322944501Smrg#define DRM_INTEL_RELOC_FENCE (1<<0)
16422944501Smrg
16522944501Smrgtypedef struct _drm_intel_reloc_target_info {
16622944501Smrg	drm_intel_bo *bo;
16722944501Smrg	int flags;
16822944501Smrg} drm_intel_reloc_target;
16922944501Smrg
17022944501Smrgstruct _drm_intel_bo_gem {
17122944501Smrg	drm_intel_bo bo;
17222944501Smrg
17322944501Smrg	atomic_t refcount;
17422944501Smrg	uint32_t gem_handle;
17522944501Smrg	const char *name;
17622944501Smrg
17722944501Smrg	/**
17822944501Smrg	 * Kenel-assigned global name for this object
17920131375Smrg         *
18020131375Smrg         * List contains both flink named and prime fd'd objects
18122944501Smrg	 */
18222944501Smrg	unsigned int global_name;
1832ee35494Smrg
1842ee35494Smrg	UT_hash_handle handle_hh;
1852ee35494Smrg	UT_hash_handle name_hh;
18622944501Smrg
18722944501Smrg	/**
18822944501Smrg	 * Index of the buffer within the validation list while preparing a
18922944501Smrg	 * batchbuffer execution.
19022944501Smrg	 */
19122944501Smrg	int validate_index;
19222944501Smrg
19322944501Smrg	/**
19422944501Smrg	 * Current tiling mode
19522944501Smrg	 */
19622944501Smrg	uint32_t tiling_mode;
19722944501Smrg	uint32_t swizzle_mode;
1986d98c517Smrg	unsigned long stride;
19922944501Smrg
2002ee35494Smrg	unsigned long kflags;
2012ee35494Smrg
20222944501Smrg	time_t free_time;
20322944501Smrg
20422944501Smrg	/** Array passed to the DRM containing relocation information. */
20522944501Smrg	struct drm_i915_gem_relocation_entry *relocs;
20622944501Smrg	/**
20722944501Smrg	 * Array of info structs corresponding to relocs[i].target_handle etc
20822944501Smrg	 */
20922944501Smrg	drm_intel_reloc_target *reloc_target_info;
21022944501Smrg	/** Number of entries in relocs */
21122944501Smrg	int reloc_count;
212fe517fc9Smrg	/** Array of BOs that are referenced by this buffer and will be softpinned */
213fe517fc9Smrg	drm_intel_bo **softpin_target;
214fe517fc9Smrg	/** Number softpinned BOs that are referenced by this buffer */
215fe517fc9Smrg	int softpin_target_count;
216fe517fc9Smrg	/** Maximum amount of softpinned BOs that are referenced by this buffer */
217fe517fc9Smrg	int softpin_target_size;
218fe517fc9Smrg
21922944501Smrg	/** Mapped address for the buffer, saved across map/unmap cycles */
22022944501Smrg	void *mem_virtual;
22122944501Smrg	/** GTT virtual address for the buffer, saved across map/unmap cycles */
22222944501Smrg	void *gtt_virtual;
2232ee35494Smrg	/** WC CPU address for the buffer, saved across map/unmap cycles */
2242ee35494Smrg	void *wc_virtual;
225a884aba1Smrg	/**
226a884aba1Smrg	 * Virtual address of the buffer allocated by user, used for userptr
227a884aba1Smrg	 * objects only.
228a884aba1Smrg	 */
229a884aba1Smrg	void *user_virtual;
23020131375Smrg	int map_count;
23120131375Smrg	drmMMListHead vma_list;
23222944501Smrg
23322944501Smrg	/** BO cache list */
23422944501Smrg	drmMMListHead head;
23522944501Smrg
23622944501Smrg	/**
23722944501Smrg	 * Boolean of whether this BO and its children have been included in
23822944501Smrg	 * the current drm_intel_bufmgr_check_aperture_space() total.
23922944501Smrg	 */
24020131375Smrg	bool included_in_check_aperture;
24122944501Smrg
24222944501Smrg	/**
24322944501Smrg	 * Boolean of whether this buffer has been used as a relocation
24422944501Smrg	 * target and had its size accounted for, and thus can't have any
24522944501Smrg	 * further relocations added to it.
24622944501Smrg	 */
24720131375Smrg	bool used_as_reloc_target;
24822944501Smrg
24922944501Smrg	/**
25022944501Smrg	 * Boolean of whether we have encountered an error whilst building the relocation tree.
25122944501Smrg	 */
25220131375Smrg	bool has_error;
25322944501Smrg
25422944501Smrg	/**
25522944501Smrg	 * Boolean of whether this buffer can be re-used
25622944501Smrg	 */
25720131375Smrg	bool reusable;
25820131375Smrg
25920131375Smrg	/**
26020131375Smrg	 * Boolean of whether the GPU is definitely not accessing the buffer.
26120131375Smrg	 *
26220131375Smrg	 * This is only valid when reusable, since non-reusable
2632ee35494Smrg	 * buffers are those that have been shared with other
26420131375Smrg	 * processes, so we don't know their state.
26520131375Smrg	 */
26620131375Smrg	bool idle;
26722944501Smrg
268a884aba1Smrg	/**
269a884aba1Smrg	 * Boolean of whether this buffer was allocated with userptr
270a884aba1Smrg	 */
271a884aba1Smrg	bool is_userptr;
272a884aba1Smrg
273fe517fc9Smrg	/**
274fe517fc9Smrg	 * Boolean of whether this buffer can be placed in the full 48-bit
275fe517fc9Smrg	 * address range on gen8+.
276fe517fc9Smrg	 *
277fe517fc9Smrg	 * By default, buffers will be keep in a 32-bit range, unless this
278fe517fc9Smrg	 * flag is explicitly set.
279fe517fc9Smrg	 */
280fe517fc9Smrg	bool use_48b_address_range;
281fe517fc9Smrg
282fe517fc9Smrg	/**
283fe517fc9Smrg	 * Whether this buffer is softpinned at offset specified by the user
284fe517fc9Smrg	 */
285fe517fc9Smrg	bool is_softpin;
286fe517fc9Smrg
28722944501Smrg	/**
28822944501Smrg	 * Size in bytes of this buffer and its relocation descendents.
28922944501Smrg	 *
29022944501Smrg	 * Used to avoid costly tree walking in
29122944501Smrg	 * drm_intel_bufmgr_check_aperture in the common case.
29222944501Smrg	 */
29322944501Smrg	int reloc_tree_size;
29422944501Smrg
29522944501Smrg	/**
29622944501Smrg	 * Number of potential fence registers required by this buffer and its
29722944501Smrg	 * relocations.
29822944501Smrg	 */
29922944501Smrg	int reloc_tree_fences;
30020131375Smrg
3012ee35494Smrg	/** Flags that we may need to do the SW_FINISH ioctl on unmap. */
30220131375Smrg	bool mapped_cpu_write;
30322944501Smrg};
30422944501Smrg
30522944501Smrgstatic unsigned int
30622944501Smrgdrm_intel_gem_estimate_batch_space(drm_intel_bo ** bo_array, int count);
30722944501Smrg
30822944501Smrgstatic unsigned int
30922944501Smrgdrm_intel_gem_compute_batch_space(drm_intel_bo ** bo_array, int count);
31022944501Smrg
31122944501Smrgstatic int
31222944501Smrgdrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
31322944501Smrg			    uint32_t * swizzle_mode);
31422944501Smrg
31522944501Smrgstatic int
3166d98c517Smrgdrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo,
3176d98c517Smrg				     uint32_t tiling_mode,
3186d98c517Smrg				     uint32_t stride);
31922944501Smrg
32022944501Smrgstatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo,
32122944501Smrg						      time_t time);
32222944501Smrg
32322944501Smrgstatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo);
32422944501Smrg
32522944501Smrgstatic void drm_intel_gem_bo_free(drm_intel_bo *bo);
32622944501Smrg
327fe517fc9Smrgstatic inline drm_intel_bo_gem *to_bo_gem(drm_intel_bo *bo)
328fe517fc9Smrg{
329fe517fc9Smrg        return (drm_intel_bo_gem *)bo;
330fe517fc9Smrg}
331fe517fc9Smrg
33222944501Smrgstatic unsigned long
33322944501Smrgdrm_intel_gem_bo_tile_size(drm_intel_bufmgr_gem *bufmgr_gem, unsigned long size,
33422944501Smrg			   uint32_t *tiling_mode)
33522944501Smrg{
33622944501Smrg	unsigned long min_size, max_size;
33722944501Smrg	unsigned long i;
33822944501Smrg
33922944501Smrg	if (*tiling_mode == I915_TILING_NONE)
34022944501Smrg		return size;
34122944501Smrg
34222944501Smrg	/* 965+ just need multiples of page size for tiling */
34322944501Smrg	if (bufmgr_gem->gen >= 4)
34422944501Smrg		return ROUND_UP_TO(size, 4096);
34522944501Smrg
34622944501Smrg	/* Older chips need powers of two, of at least 512k or 1M */
34722944501Smrg	if (bufmgr_gem->gen == 3) {
34822944501Smrg		min_size = 1024*1024;
34922944501Smrg		max_size = 128*1024*1024;
35022944501Smrg	} else {
35122944501Smrg		min_size = 512*1024;
35222944501Smrg		max_size = 64*1024*1024;
35322944501Smrg	}
35422944501Smrg
35522944501Smrg	if (size > max_size) {
35622944501Smrg		*tiling_mode = I915_TILING_NONE;
35722944501Smrg		return size;
35822944501Smrg	}
35922944501Smrg
3609ce4edccSmrg	/* Do we need to allocate every page for the fence? */
3619ce4edccSmrg	if (bufmgr_gem->has_relaxed_fencing)
3629ce4edccSmrg		return ROUND_UP_TO(size, 4096);
3639ce4edccSmrg
36422944501Smrg	for (i = min_size; i < size; i <<= 1)
36522944501Smrg		;
36622944501Smrg
36722944501Smrg	return i;
36822944501Smrg}
36922944501Smrg
37022944501Smrg/*
37122944501Smrg * Round a given pitch up to the minimum required for X tiling on a
37222944501Smrg * given chip.  We use 512 as the minimum to allow for a later tiling
37322944501Smrg * change.
37422944501Smrg */
37522944501Smrgstatic unsigned long
37622944501Smrgdrm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem,
3776d98c517Smrg			    unsigned long pitch, uint32_t *tiling_mode)
37822944501Smrg{
37922944501Smrg	unsigned long tile_width;
38022944501Smrg	unsigned long i;
38122944501Smrg
38222944501Smrg	/* If untiled, then just align it so that we can do rendering
38322944501Smrg	 * to it with the 3D engine.
38422944501Smrg	 */
3856d98c517Smrg	if (*tiling_mode == I915_TILING_NONE)
38622944501Smrg		return ALIGN(pitch, 64);
38722944501Smrg
38820131375Smrg	if (*tiling_mode == I915_TILING_X
38920131375Smrg			|| (IS_915(bufmgr_gem->pci_device)
39020131375Smrg			    && *tiling_mode == I915_TILING_Y))
39122944501Smrg		tile_width = 512;
39222944501Smrg	else
39322944501Smrg		tile_width = 128;
39422944501Smrg
39522944501Smrg	/* 965 is flexible */
39622944501Smrg	if (bufmgr_gem->gen >= 4)
39722944501Smrg		return ROUND_UP_TO(pitch, tile_width);
39822944501Smrg
3996d98c517Smrg	/* The older hardware has a maximum pitch of 8192 with tiled
4006d98c517Smrg	 * surfaces, so fallback to untiled if it's too large.
4016d98c517Smrg	 */
4026d98c517Smrg	if (pitch > 8192) {
4036d98c517Smrg		*tiling_mode = I915_TILING_NONE;
4046d98c517Smrg		return ALIGN(pitch, 64);
4056d98c517Smrg	}
4066d98c517Smrg
40722944501Smrg	/* Pre-965 needs power of two tile width */
40822944501Smrg	for (i = tile_width; i < pitch; i <<= 1)
40922944501Smrg		;
41022944501Smrg
41122944501Smrg	return i;
41222944501Smrg}
41322944501Smrg
41422944501Smrgstatic struct drm_intel_gem_bo_bucket *
41522944501Smrgdrm_intel_gem_bo_bucket_for_size(drm_intel_bufmgr_gem *bufmgr_gem,
41622944501Smrg				 unsigned long size)
41722944501Smrg{
41822944501Smrg	int i;
41922944501Smrg
420aaba2545Smrg	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
42122944501Smrg		struct drm_intel_gem_bo_bucket *bucket =
42222944501Smrg		    &bufmgr_gem->cache_bucket[i];
42322944501Smrg		if (bucket->size >= size) {
42422944501Smrg			return bucket;
42522944501Smrg		}
42622944501Smrg	}
42722944501Smrg
42822944501Smrg	return NULL;
42922944501Smrg}
43022944501Smrg
43122944501Smrgstatic void
43222944501Smrgdrm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem)
43322944501Smrg{
43422944501Smrg	int i, j;
43522944501Smrg
43622944501Smrg	for (i = 0; i < bufmgr_gem->exec_count; i++) {
43722944501Smrg		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
43822944501Smrg		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
43922944501Smrg
440fe517fc9Smrg		if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) {
441fe517fc9Smrg			DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle,
442fe517fc9Smrg			    bo_gem->is_softpin ? "*" : "",
44322944501Smrg			    bo_gem->name);
44422944501Smrg			continue;
44522944501Smrg		}
44622944501Smrg
44722944501Smrg		for (j = 0; j < bo_gem->reloc_count; j++) {
44822944501Smrg			drm_intel_bo *target_bo = bo_gem->reloc_target_info[j].bo;
44922944501Smrg			drm_intel_bo_gem *target_gem =
45022944501Smrg			    (drm_intel_bo_gem *) target_bo;
45122944501Smrg
452fe517fc9Smrg			DBG("%2d: %d %s(%s)@0x%08x %08x -> "
453fe517fc9Smrg			    "%d (%s)@0x%08x %08x + 0x%08x\n",
45422944501Smrg			    i,
455fe517fc9Smrg			    bo_gem->gem_handle,
456fe517fc9Smrg			    bo_gem->is_softpin ? "*" : "",
457fe517fc9Smrg			    bo_gem->name,
458fe517fc9Smrg			    upper_32_bits(bo_gem->relocs[j].offset),
459fe517fc9Smrg			    lower_32_bits(bo_gem->relocs[j].offset),
46022944501Smrg			    target_gem->gem_handle,
46122944501Smrg			    target_gem->name,
462fe517fc9Smrg			    upper_32_bits(target_bo->offset64),
463fe517fc9Smrg			    lower_32_bits(target_bo->offset64),
46422944501Smrg			    bo_gem->relocs[j].delta);
46522944501Smrg		}
466fe517fc9Smrg
467fe517fc9Smrg		for (j = 0; j < bo_gem->softpin_target_count; j++) {
468fe517fc9Smrg			drm_intel_bo *target_bo = bo_gem->softpin_target[j];
469fe517fc9Smrg			drm_intel_bo_gem *target_gem =
470fe517fc9Smrg			    (drm_intel_bo_gem *) target_bo;
471fe517fc9Smrg			DBG("%2d: %d %s(%s) -> "
472fe517fc9Smrg			    "%d *(%s)@0x%08x %08x\n",
473fe517fc9Smrg			    i,
474fe517fc9Smrg			    bo_gem->gem_handle,
475fe517fc9Smrg			    bo_gem->is_softpin ? "*" : "",
476fe517fc9Smrg			    bo_gem->name,
477fe517fc9Smrg			    target_gem->gem_handle,
478fe517fc9Smrg			    target_gem->name,
479fe517fc9Smrg			    upper_32_bits(target_bo->offset64),
480fe517fc9Smrg			    lower_32_bits(target_bo->offset64));
481fe517fc9Smrg		}
48222944501Smrg	}
48322944501Smrg}
48422944501Smrg
48522944501Smrgstatic inline void
48622944501Smrgdrm_intel_gem_bo_reference(drm_intel_bo *bo)
48722944501Smrg{
48822944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
48922944501Smrg
49022944501Smrg	atomic_inc(&bo_gem->refcount);
49122944501Smrg}
49222944501Smrg
49322944501Smrg/**
49422944501Smrg * Adds the given buffer to the list of buffers to be validated (moved into the
49522944501Smrg * appropriate memory type) with the next batch submission.
49622944501Smrg *
49722944501Smrg * If a buffer is validated multiple times in a batch submission, it ends up
49822944501Smrg * with the intersection of the memory type flags and the union of the
49922944501Smrg * access flags.
50022944501Smrg */
50122944501Smrgstatic void
50222944501Smrgdrm_intel_add_validate_buffer(drm_intel_bo *bo)
50322944501Smrg{
50422944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
50522944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
50622944501Smrg	int index;
50722944501Smrg
50822944501Smrg	if (bo_gem->validate_index != -1)
50922944501Smrg		return;
51022944501Smrg
51122944501Smrg	/* Extend the array of validation entries as necessary. */
51222944501Smrg	if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
51322944501Smrg		int new_size = bufmgr_gem->exec_size * 2;
51422944501Smrg
51522944501Smrg		if (new_size == 0)
51622944501Smrg			new_size = 5;
51722944501Smrg
51822944501Smrg		bufmgr_gem->exec_objects =
51922944501Smrg		    realloc(bufmgr_gem->exec_objects,
52022944501Smrg			    sizeof(*bufmgr_gem->exec_objects) * new_size);
52122944501Smrg		bufmgr_gem->exec_bos =
52222944501Smrg		    realloc(bufmgr_gem->exec_bos,
52322944501Smrg			    sizeof(*bufmgr_gem->exec_bos) * new_size);
52422944501Smrg		bufmgr_gem->exec_size = new_size;
52522944501Smrg	}
52622944501Smrg
52722944501Smrg	index = bufmgr_gem->exec_count;
52822944501Smrg	bo_gem->validate_index = index;
52922944501Smrg	/* Fill in array entry */
53022944501Smrg	bufmgr_gem->exec_objects[index].handle = bo_gem->gem_handle;
53122944501Smrg	bufmgr_gem->exec_objects[index].relocation_count = bo_gem->reloc_count;
53222944501Smrg	bufmgr_gem->exec_objects[index].relocs_ptr = (uintptr_t) bo_gem->relocs;
533fe517fc9Smrg	bufmgr_gem->exec_objects[index].alignment = bo->align;
53422944501Smrg	bufmgr_gem->exec_objects[index].offset = 0;
53522944501Smrg	bufmgr_gem->exec_bos[index] = bo;
53622944501Smrg	bufmgr_gem->exec_count++;
53722944501Smrg}
53822944501Smrg
53922944501Smrgstatic void
54022944501Smrgdrm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence)
54122944501Smrg{
54222944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
54322944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
54422944501Smrg	int index;
545fe517fc9Smrg	int flags = 0;
546fe517fc9Smrg
547fe517fc9Smrg	if (need_fence)
548fe517fc9Smrg		flags |= EXEC_OBJECT_NEEDS_FENCE;
549fe517fc9Smrg	if (bo_gem->use_48b_address_range)
550fe517fc9Smrg		flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
551fe517fc9Smrg	if (bo_gem->is_softpin)
552fe517fc9Smrg		flags |= EXEC_OBJECT_PINNED;
55322944501Smrg
55422944501Smrg	if (bo_gem->validate_index != -1) {
555fe517fc9Smrg		bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags;
55622944501Smrg		return;
55722944501Smrg	}
55822944501Smrg
55922944501Smrg	/* Extend the array of validation entries as necessary. */
56022944501Smrg	if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
56122944501Smrg		int new_size = bufmgr_gem->exec_size * 2;
56222944501Smrg
56322944501Smrg		if (new_size == 0)
56422944501Smrg			new_size = 5;
56522944501Smrg
56622944501Smrg		bufmgr_gem->exec2_objects =
56722944501Smrg			realloc(bufmgr_gem->exec2_objects,
56822944501Smrg				sizeof(*bufmgr_gem->exec2_objects) * new_size);
56922944501Smrg		bufmgr_gem->exec_bos =
57022944501Smrg			realloc(bufmgr_gem->exec_bos,
57122944501Smrg				sizeof(*bufmgr_gem->exec_bos) * new_size);
57222944501Smrg		bufmgr_gem->exec_size = new_size;
57322944501Smrg	}
57422944501Smrg
57522944501Smrg	index = bufmgr_gem->exec_count;
57622944501Smrg	bo_gem->validate_index = index;
57722944501Smrg	/* Fill in array entry */
57822944501Smrg	bufmgr_gem->exec2_objects[index].handle = bo_gem->gem_handle;
57922944501Smrg	bufmgr_gem->exec2_objects[index].relocation_count = bo_gem->reloc_count;
58022944501Smrg	bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
581fe517fc9Smrg	bufmgr_gem->exec2_objects[index].alignment = bo->align;
5822ee35494Smrg	bufmgr_gem->exec2_objects[index].offset = bo->offset64;
5832ee35494Smrg	bufmgr_gem->exec2_objects[index].flags = flags | bo_gem->kflags;
58422944501Smrg	bufmgr_gem->exec2_objects[index].rsvd1 = 0;
58522944501Smrg	bufmgr_gem->exec2_objects[index].rsvd2 = 0;
5862ee35494Smrg	bufmgr_gem->exec_bos[index] = bo;
58722944501Smrg	bufmgr_gem->exec_count++;
58822944501Smrg}
58922944501Smrg
59022944501Smrg#define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \
59122944501Smrg	sizeof(uint32_t))
59222944501Smrg
59322944501Smrgstatic void
59422944501Smrgdrm_intel_bo_gem_set_in_aperture_size(drm_intel_bufmgr_gem *bufmgr_gem,
595fe517fc9Smrg				      drm_intel_bo_gem *bo_gem,
596fe517fc9Smrg				      unsigned int alignment)
59722944501Smrg{
598fe517fc9Smrg	unsigned int size;
59922944501Smrg
60022944501Smrg	assert(!bo_gem->used_as_reloc_target);
60122944501Smrg
60222944501Smrg	/* The older chipsets are far-less flexible in terms of tiling,
60322944501Smrg	 * and require tiled buffer to be size aligned in the aperture.
60422944501Smrg	 * This means that in the worst possible case we will need a hole
60522944501Smrg	 * twice as large as the object in order for it to fit into the
60622944501Smrg	 * aperture. Optimal packing is for wimps.
60722944501Smrg	 */
60822944501Smrg	size = bo_gem->bo.size;
6099ce4edccSmrg	if (bufmgr_gem->gen < 4 && bo_gem->tiling_mode != I915_TILING_NONE) {
610fe517fc9Smrg		unsigned int min_size;
6119ce4edccSmrg
6129ce4edccSmrg		if (bufmgr_gem->has_relaxed_fencing) {
6139ce4edccSmrg			if (bufmgr_gem->gen == 3)
6149ce4edccSmrg				min_size = 1024*1024;
6159ce4edccSmrg			else
6169ce4edccSmrg				min_size = 512*1024;
6179ce4edccSmrg
6189ce4edccSmrg			while (min_size < size)
6199ce4edccSmrg				min_size *= 2;
6209ce4edccSmrg		} else
6219ce4edccSmrg			min_size = size;
6229ce4edccSmrg
6239ce4edccSmrg		/* Account for worst-case alignment. */
624fe517fc9Smrg		alignment = MAX2(alignment, min_size);
6259ce4edccSmrg	}
62622944501Smrg
627fe517fc9Smrg	bo_gem->reloc_tree_size = size + alignment;
62822944501Smrg}
62922944501Smrg
63022944501Smrgstatic int
63122944501Smrgdrm_intel_setup_reloc_list(drm_intel_bo *bo)
63222944501Smrg{
63322944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
63422944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
63522944501Smrg	unsigned int max_relocs = bufmgr_gem->max_relocs;
63622944501Smrg
63722944501Smrg	if (bo->size / 4 < max_relocs)
63822944501Smrg		max_relocs = bo->size / 4;
63922944501Smrg
64022944501Smrg	bo_gem->relocs = malloc(max_relocs *
64122944501Smrg				sizeof(struct drm_i915_gem_relocation_entry));
64222944501Smrg	bo_gem->reloc_target_info = malloc(max_relocs *
643aaba2545Smrg					   sizeof(drm_intel_reloc_target));
64422944501Smrg	if (bo_gem->relocs == NULL || bo_gem->reloc_target_info == NULL) {
64520131375Smrg		bo_gem->has_error = true;
64622944501Smrg
64722944501Smrg		free (bo_gem->relocs);
64822944501Smrg		bo_gem->relocs = NULL;
64922944501Smrg
65022944501Smrg		free (bo_gem->reloc_target_info);
65122944501Smrg		bo_gem->reloc_target_info = NULL;
65222944501Smrg
65322944501Smrg		return 1;
65422944501Smrg	}
65522944501Smrg
65622944501Smrg	return 0;
65722944501Smrg}
65822944501Smrg
65922944501Smrgstatic int
66022944501Smrgdrm_intel_gem_bo_busy(drm_intel_bo *bo)
66122944501Smrg{
66222944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
66322944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
66422944501Smrg	struct drm_i915_gem_busy busy;
66522944501Smrg	int ret;
66622944501Smrg
66720131375Smrg	if (bo_gem->reusable && bo_gem->idle)
66820131375Smrg		return false;
66920131375Smrg
670424e9256Smrg	memclear(busy);
67122944501Smrg	busy.handle = bo_gem->gem_handle;
67222944501Smrg
6736d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
67420131375Smrg	if (ret == 0) {
67520131375Smrg		bo_gem->idle = !busy.busy;
67620131375Smrg		return busy.busy;
67720131375Smrg	} else {
67820131375Smrg		return false;
67920131375Smrg	}
68022944501Smrg	return (ret == 0 && busy.busy);
68122944501Smrg}
68222944501Smrg
68322944501Smrgstatic int
68422944501Smrgdrm_intel_gem_bo_madvise_internal(drm_intel_bufmgr_gem *bufmgr_gem,
68522944501Smrg				  drm_intel_bo_gem *bo_gem, int state)
68622944501Smrg{
68722944501Smrg	struct drm_i915_gem_madvise madv;
68822944501Smrg
689424e9256Smrg	memclear(madv);
69022944501Smrg	madv.handle = bo_gem->gem_handle;
69122944501Smrg	madv.madv = state;
69222944501Smrg	madv.retained = 1;
6936d98c517Smrg	drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv);
69422944501Smrg
69522944501Smrg	return madv.retained;
69622944501Smrg}
69722944501Smrg
69822944501Smrgstatic int
69922944501Smrgdrm_intel_gem_bo_madvise(drm_intel_bo *bo, int madv)
70022944501Smrg{
70122944501Smrg	return drm_intel_gem_bo_madvise_internal
70222944501Smrg		((drm_intel_bufmgr_gem *) bo->bufmgr,
70322944501Smrg		 (drm_intel_bo_gem *) bo,
70422944501Smrg		 madv);
70522944501Smrg}
70622944501Smrg
70722944501Smrg/* drop the oldest entries that have been purged by the kernel */
70822944501Smrgstatic void
70922944501Smrgdrm_intel_gem_bo_cache_purge_bucket(drm_intel_bufmgr_gem *bufmgr_gem,
71022944501Smrg				    struct drm_intel_gem_bo_bucket *bucket)
71122944501Smrg{
71222944501Smrg	while (!DRMLISTEMPTY(&bucket->head)) {
71322944501Smrg		drm_intel_bo_gem *bo_gem;
71422944501Smrg
71522944501Smrg		bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
71622944501Smrg				      bucket->head.next, head);
71722944501Smrg		if (drm_intel_gem_bo_madvise_internal
71822944501Smrg		    (bufmgr_gem, bo_gem, I915_MADV_DONTNEED))
71922944501Smrg			break;
72022944501Smrg
72122944501Smrg		DRMLISTDEL(&bo_gem->head);
72222944501Smrg		drm_intel_gem_bo_free(&bo_gem->bo);
72322944501Smrg	}
72422944501Smrg}
72522944501Smrg
72622944501Smrgstatic drm_intel_bo *
72722944501Smrgdrm_intel_gem_bo_alloc_internal(drm_intel_bufmgr *bufmgr,
72822944501Smrg				const char *name,
72922944501Smrg				unsigned long size,
7306d98c517Smrg				unsigned long flags,
7316d98c517Smrg				uint32_t tiling_mode,
732fe517fc9Smrg				unsigned long stride,
733fe517fc9Smrg				unsigned int alignment)
73422944501Smrg{
73522944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
73622944501Smrg	drm_intel_bo_gem *bo_gem;
73722944501Smrg	unsigned int page_size = getpagesize();
73822944501Smrg	int ret;
73922944501Smrg	struct drm_intel_gem_bo_bucket *bucket;
74020131375Smrg	bool alloc_from_cache;
74122944501Smrg	unsigned long bo_size;
74220131375Smrg	bool for_render = false;
74322944501Smrg
74422944501Smrg	if (flags & BO_ALLOC_FOR_RENDER)
74520131375Smrg		for_render = true;
74622944501Smrg
74722944501Smrg	/* Round the allocated size up to a power of two number of pages. */
74822944501Smrg	bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, size);
74922944501Smrg
75022944501Smrg	/* If we don't have caching at this size, don't actually round the
75122944501Smrg	 * allocation up.
75222944501Smrg	 */
75322944501Smrg	if (bucket == NULL) {
75422944501Smrg		bo_size = size;
75522944501Smrg		if (bo_size < page_size)
75622944501Smrg			bo_size = page_size;
75722944501Smrg	} else {
75822944501Smrg		bo_size = bucket->size;
75922944501Smrg	}
76022944501Smrg
76122944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
76222944501Smrg	/* Get a buffer out of the cache if available */
76322944501Smrgretry:
76420131375Smrg	alloc_from_cache = false;
76522944501Smrg	if (bucket != NULL && !DRMLISTEMPTY(&bucket->head)) {
76622944501Smrg		if (for_render) {
76722944501Smrg			/* Allocate new render-target BOs from the tail (MRU)
76822944501Smrg			 * of the list, as it will likely be hot in the GPU
76922944501Smrg			 * cache and in the aperture for us.
77022944501Smrg			 */
77122944501Smrg			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
77222944501Smrg					      bucket->head.prev, head);
77322944501Smrg			DRMLISTDEL(&bo_gem->head);
77420131375Smrg			alloc_from_cache = true;
775fe517fc9Smrg			bo_gem->bo.align = alignment;
77622944501Smrg		} else {
777fe517fc9Smrg			assert(alignment == 0);
77822944501Smrg			/* For non-render-target BOs (where we're probably
77922944501Smrg			 * going to map it first thing in order to fill it
78022944501Smrg			 * with data), check if the last BO in the cache is
78122944501Smrg			 * unbusy, and only reuse in that case. Otherwise,
78222944501Smrg			 * allocating a new buffer is probably faster than
78322944501Smrg			 * waiting for the GPU to finish.
78422944501Smrg			 */
78522944501Smrg			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
78622944501Smrg					      bucket->head.next, head);
78722944501Smrg			if (!drm_intel_gem_bo_busy(&bo_gem->bo)) {
78820131375Smrg				alloc_from_cache = true;
78922944501Smrg				DRMLISTDEL(&bo_gem->head);
79022944501Smrg			}
79122944501Smrg		}
79222944501Smrg
79322944501Smrg		if (alloc_from_cache) {
79422944501Smrg			if (!drm_intel_gem_bo_madvise_internal
79522944501Smrg			    (bufmgr_gem, bo_gem, I915_MADV_WILLNEED)) {
79622944501Smrg				drm_intel_gem_bo_free(&bo_gem->bo);
79722944501Smrg				drm_intel_gem_bo_cache_purge_bucket(bufmgr_gem,
79822944501Smrg								    bucket);
79922944501Smrg				goto retry;
80022944501Smrg			}
8016d98c517Smrg
8026d98c517Smrg			if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo,
8036d98c517Smrg								 tiling_mode,
8046d98c517Smrg								 stride)) {
8056d98c517Smrg				drm_intel_gem_bo_free(&bo_gem->bo);
8066d98c517Smrg				goto retry;
8076d98c517Smrg			}
80822944501Smrg		}
80922944501Smrg	}
81022944501Smrg
81122944501Smrg	if (!alloc_from_cache) {
81222944501Smrg		struct drm_i915_gem_create create;
81322944501Smrg
81422944501Smrg		bo_gem = calloc(1, sizeof(*bo_gem));
81522944501Smrg		if (!bo_gem)
8162ee35494Smrg			goto err;
8172ee35494Smrg
8182ee35494Smrg		/* drm_intel_gem_bo_free calls DRMLISTDEL() for an uninitialized
8192ee35494Smrg		   list (vma_list), so better set the list head here */
8202ee35494Smrg		DRMINITLISTHEAD(&bo_gem->vma_list);
82122944501Smrg
82222944501Smrg		bo_gem->bo.size = bo_size;
82320131375Smrg
824424e9256Smrg		memclear(create);
82522944501Smrg		create.size = bo_size;
82622944501Smrg
8276d98c517Smrg		ret = drmIoctl(bufmgr_gem->fd,
8286d98c517Smrg			       DRM_IOCTL_I915_GEM_CREATE,
8296d98c517Smrg			       &create);
83022944501Smrg		if (ret != 0) {
83122944501Smrg			free(bo_gem);
8322ee35494Smrg			goto err;
83322944501Smrg		}
8342ee35494Smrg
8352ee35494Smrg		bo_gem->gem_handle = create.handle;
8362ee35494Smrg		bo_gem->bo.handle = bo_gem->gem_handle;
83722944501Smrg		bo_gem->bo.bufmgr = bufmgr;
838fe517fc9Smrg		bo_gem->bo.align = alignment;
8396d98c517Smrg
8406d98c517Smrg		bo_gem->tiling_mode = I915_TILING_NONE;
8416d98c517Smrg		bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
8426d98c517Smrg		bo_gem->stride = 0;
8436d98c517Smrg
8446d98c517Smrg		if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo,
8456d98c517Smrg							 tiling_mode,
8462ee35494Smrg							 stride))
8472ee35494Smrg			goto err_free;
8482ee35494Smrg
8492ee35494Smrg		HASH_ADD(handle_hh, bufmgr_gem->handle_table,
8502ee35494Smrg			 gem_handle, sizeof(bo_gem->gem_handle),
8512ee35494Smrg			 bo_gem);
85222944501Smrg	}
85322944501Smrg
85422944501Smrg	bo_gem->name = name;
85522944501Smrg	atomic_set(&bo_gem->refcount, 1);
85622944501Smrg	bo_gem->validate_index = -1;
85722944501Smrg	bo_gem->reloc_tree_fences = 0;
85820131375Smrg	bo_gem->used_as_reloc_target = false;
85920131375Smrg	bo_gem->has_error = false;
86020131375Smrg	bo_gem->reusable = true;
861fe517fc9Smrg	bo_gem->use_48b_address_range = false;
86222944501Smrg
863fe517fc9Smrg	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment);
8642ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
86522944501Smrg
86622944501Smrg	DBG("bo_create: buf %d (%s) %ldb\n",
86722944501Smrg	    bo_gem->gem_handle, bo_gem->name, size);
86822944501Smrg
86922944501Smrg	return &bo_gem->bo;
8702ee35494Smrg
8712ee35494Smrgerr_free:
8722ee35494Smrg	drm_intel_gem_bo_free(&bo_gem->bo);
8732ee35494Smrgerr:
8742ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
8752ee35494Smrg	return NULL;
87622944501Smrg}
87722944501Smrg
87822944501Smrgstatic drm_intel_bo *
87922944501Smrgdrm_intel_gem_bo_alloc_for_render(drm_intel_bufmgr *bufmgr,
88022944501Smrg				  const char *name,
88122944501Smrg				  unsigned long size,
88222944501Smrg				  unsigned int alignment)
88322944501Smrg{
88422944501Smrg	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size,
8856d98c517Smrg					       BO_ALLOC_FOR_RENDER,
886fe517fc9Smrg					       I915_TILING_NONE, 0,
887fe517fc9Smrg					       alignment);
88822944501Smrg}
88922944501Smrg
89022944501Smrgstatic drm_intel_bo *
89122944501Smrgdrm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr,
89222944501Smrg		       const char *name,
89322944501Smrg		       unsigned long size,
89422944501Smrg		       unsigned int alignment)
89522944501Smrg{
8966d98c517Smrg	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0,
897fe517fc9Smrg					       I915_TILING_NONE, 0, 0);
89822944501Smrg}
89922944501Smrg
90022944501Smrgstatic drm_intel_bo *
90122944501Smrgdrm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name,
90222944501Smrg			     int x, int y, int cpp, uint32_t *tiling_mode,
90322944501Smrg			     unsigned long *pitch, unsigned long flags)
90422944501Smrg{
90522944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
906aaba2545Smrg	unsigned long size, stride;
907aaba2545Smrg	uint32_t tiling;
90822944501Smrg
909aaba2545Smrg	do {
91020131375Smrg		unsigned long aligned_y, height_alignment;
911aaba2545Smrg
912aaba2545Smrg		tiling = *tiling_mode;
913aaba2545Smrg
914aaba2545Smrg		/* If we're tiled, our allocations are in 8 or 32-row blocks,
915aaba2545Smrg		 * so failure to align our height means that we won't allocate
916aaba2545Smrg		 * enough pages.
917aaba2545Smrg		 *
918aaba2545Smrg		 * If we're untiled, we still have to align to 2 rows high
919aaba2545Smrg		 * because the data port accesses 2x2 blocks even if the
920aaba2545Smrg		 * bottom row isn't to be rendered, so failure to align means
921aaba2545Smrg		 * we could walk off the end of the GTT and fault.  This is
922aaba2545Smrg		 * documented on 965, and may be the case on older chipsets
923aaba2545Smrg		 * too so we try to be careful.
924aaba2545Smrg		 */
925aaba2545Smrg		aligned_y = y;
92620131375Smrg		height_alignment = 2;
92720131375Smrg
92820131375Smrg		if ((bufmgr_gem->gen == 2) && tiling != I915_TILING_NONE)
92920131375Smrg			height_alignment = 16;
93020131375Smrg		else if (tiling == I915_TILING_X
93120131375Smrg			|| (IS_915(bufmgr_gem->pci_device)
93220131375Smrg			    && tiling == I915_TILING_Y))
93320131375Smrg			height_alignment = 8;
934aaba2545Smrg		else if (tiling == I915_TILING_Y)
93520131375Smrg			height_alignment = 32;
93620131375Smrg		aligned_y = ALIGN(y, height_alignment);
937aaba2545Smrg
938aaba2545Smrg		stride = x * cpp;
9396d98c517Smrg		stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling_mode);
940aaba2545Smrg		size = stride * aligned_y;
941aaba2545Smrg		size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode);
942aaba2545Smrg	} while (*tiling_mode != tiling);
94322944501Smrg	*pitch = stride;
94422944501Smrg
9456d98c517Smrg	if (tiling == I915_TILING_NONE)
9466d98c517Smrg		stride = 0;
9476d98c517Smrg
9486d98c517Smrg	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags,
949fe517fc9Smrg					       tiling, stride, 0);
95022944501Smrg}
95122944501Smrg
952a884aba1Smrgstatic drm_intel_bo *
953a884aba1Smrgdrm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
954a884aba1Smrg				const char *name,
955a884aba1Smrg				void *addr,
956a884aba1Smrg				uint32_t tiling_mode,
957a884aba1Smrg				uint32_t stride,
958a884aba1Smrg				unsigned long size,
959a884aba1Smrg				unsigned long flags)
960a884aba1Smrg{
961a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
962a884aba1Smrg	drm_intel_bo_gem *bo_gem;
963a884aba1Smrg	int ret;
964a884aba1Smrg	struct drm_i915_gem_userptr userptr;
965a884aba1Smrg
966a884aba1Smrg	/* Tiling with userptr surfaces is not supported
967a884aba1Smrg	 * on all hardware so refuse it for time being.
968a884aba1Smrg	 */
969a884aba1Smrg	if (tiling_mode != I915_TILING_NONE)
970a884aba1Smrg		return NULL;
971a884aba1Smrg
972a884aba1Smrg	bo_gem = calloc(1, sizeof(*bo_gem));
973a884aba1Smrg	if (!bo_gem)
974a884aba1Smrg		return NULL;
975a884aba1Smrg
9762ee35494Smrg	atomic_set(&bo_gem->refcount, 1);
9772ee35494Smrg	DRMINITLISTHEAD(&bo_gem->vma_list);
9782ee35494Smrg
979a884aba1Smrg	bo_gem->bo.size = size;
980a884aba1Smrg
981424e9256Smrg	memclear(userptr);
982a884aba1Smrg	userptr.user_ptr = (__u64)((unsigned long)addr);
983a884aba1Smrg	userptr.user_size = size;
984a884aba1Smrg	userptr.flags = flags;
985a884aba1Smrg
986a884aba1Smrg	ret = drmIoctl(bufmgr_gem->fd,
987a884aba1Smrg			DRM_IOCTL_I915_GEM_USERPTR,
988a884aba1Smrg			&userptr);
989a884aba1Smrg	if (ret != 0) {
990a884aba1Smrg		DBG("bo_create_userptr: "
991a884aba1Smrg		    "ioctl failed with user ptr %p size 0x%lx, "
992a884aba1Smrg		    "user flags 0x%lx\n", addr, size, flags);
993a884aba1Smrg		free(bo_gem);
994a884aba1Smrg		return NULL;
995a884aba1Smrg	}
996a884aba1Smrg
9972ee35494Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
9982ee35494Smrg
999a884aba1Smrg	bo_gem->gem_handle = userptr.handle;
1000a884aba1Smrg	bo_gem->bo.handle = bo_gem->gem_handle;
1001a884aba1Smrg	bo_gem->bo.bufmgr    = bufmgr;
1002a884aba1Smrg	bo_gem->is_userptr   = true;
1003a884aba1Smrg	bo_gem->bo.virtual   = addr;
1004a884aba1Smrg	/* Save the address provided by user */
1005a884aba1Smrg	bo_gem->user_virtual = addr;
1006a884aba1Smrg	bo_gem->tiling_mode  = I915_TILING_NONE;
1007a884aba1Smrg	bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
1008a884aba1Smrg	bo_gem->stride       = 0;
1009a884aba1Smrg
10102ee35494Smrg	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
10112ee35494Smrg		 gem_handle, sizeof(bo_gem->gem_handle),
10122ee35494Smrg		 bo_gem);
1013a884aba1Smrg
1014a884aba1Smrg	bo_gem->name = name;
1015a884aba1Smrg	bo_gem->validate_index = -1;
1016a884aba1Smrg	bo_gem->reloc_tree_fences = 0;
1017a884aba1Smrg	bo_gem->used_as_reloc_target = false;
1018a884aba1Smrg	bo_gem->has_error = false;
1019a884aba1Smrg	bo_gem->reusable = false;
1020fe517fc9Smrg	bo_gem->use_48b_address_range = false;
1021a884aba1Smrg
1022fe517fc9Smrg	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
10232ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
1024a884aba1Smrg
1025a884aba1Smrg	DBG("bo_create_userptr: "
1026a884aba1Smrg	    "ptr %p buf %d (%s) size %ldb, stride 0x%x, tile mode %d\n",
1027a884aba1Smrg		addr, bo_gem->gem_handle, bo_gem->name,
1028a884aba1Smrg		size, stride, tiling_mode);
1029a884aba1Smrg
1030a884aba1Smrg	return &bo_gem->bo;
1031a884aba1Smrg}
1032a884aba1Smrg
1033424e9256Smrgstatic bool
1034424e9256Smrghas_userptr(drm_intel_bufmgr_gem *bufmgr_gem)
1035424e9256Smrg{
1036424e9256Smrg	int ret;
1037424e9256Smrg	void *ptr;
1038424e9256Smrg	long pgsz;
1039424e9256Smrg	struct drm_i915_gem_userptr userptr;
1040424e9256Smrg
1041424e9256Smrg	pgsz = sysconf(_SC_PAGESIZE);
1042424e9256Smrg	assert(pgsz > 0);
1043424e9256Smrg
1044424e9256Smrg	ret = posix_memalign(&ptr, pgsz, pgsz);
1045424e9256Smrg	if (ret) {
1046424e9256Smrg		DBG("Failed to get a page (%ld) for userptr detection!\n",
1047424e9256Smrg			pgsz);
1048424e9256Smrg		return false;
1049424e9256Smrg	}
1050424e9256Smrg
1051424e9256Smrg	memclear(userptr);
1052424e9256Smrg	userptr.user_ptr = (__u64)(unsigned long)ptr;
1053424e9256Smrg	userptr.user_size = pgsz;
1054424e9256Smrg
1055424e9256Smrgretry:
1056424e9256Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr);
1057424e9256Smrg	if (ret) {
1058424e9256Smrg		if (errno == ENODEV && userptr.flags == 0) {
1059424e9256Smrg			userptr.flags = I915_USERPTR_UNSYNCHRONIZED;
1060424e9256Smrg			goto retry;
1061424e9256Smrg		}
1062424e9256Smrg		free(ptr);
1063424e9256Smrg		return false;
1064424e9256Smrg	}
1065424e9256Smrg
1066424e9256Smrg	/* We don't release the userptr bo here as we want to keep the
1067424e9256Smrg	 * kernel mm tracking alive for our lifetime. The first time we
1068424e9256Smrg	 * create a userptr object the kernel has to install a mmu_notifer
1069424e9256Smrg	 * which is a heavyweight operation (e.g. it requires taking all
1070424e9256Smrg	 * mm_locks and stop_machine()).
1071424e9256Smrg	 */
1072424e9256Smrg
1073424e9256Smrg	bufmgr_gem->userptr_active.ptr = ptr;
1074424e9256Smrg	bufmgr_gem->userptr_active.handle = userptr.handle;
1075424e9256Smrg
1076424e9256Smrg	return true;
1077424e9256Smrg}
1078424e9256Smrg
1079424e9256Smrgstatic drm_intel_bo *
1080424e9256Smrgcheck_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
1081424e9256Smrg		       const char *name,
1082424e9256Smrg		       void *addr,
1083424e9256Smrg		       uint32_t tiling_mode,
1084424e9256Smrg		       uint32_t stride,
1085424e9256Smrg		       unsigned long size,
1086424e9256Smrg		       unsigned long flags)
1087424e9256Smrg{
1088424e9256Smrg	if (has_userptr((drm_intel_bufmgr_gem *)bufmgr))
1089424e9256Smrg		bufmgr->bo_alloc_userptr = drm_intel_gem_bo_alloc_userptr;
1090424e9256Smrg	else
1091424e9256Smrg		bufmgr->bo_alloc_userptr = NULL;
1092424e9256Smrg
1093424e9256Smrg	return drm_intel_bo_alloc_userptr(bufmgr, name, addr,
1094424e9256Smrg					  tiling_mode, stride, size, flags);
1095424e9256Smrg}
1096424e9256Smrg
109722944501Smrg/**
109822944501Smrg * Returns a drm_intel_bo wrapping the given buffer object handle.
109922944501Smrg *
110022944501Smrg * This can be used when one application needs to pass a buffer object
110122944501Smrg * to another.
110222944501Smrg */
1103424e9256Smrgdrm_intel_bo *
110422944501Smrgdrm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr,
110522944501Smrg				  const char *name,
110622944501Smrg				  unsigned int handle)
110722944501Smrg{
110822944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
110922944501Smrg	drm_intel_bo_gem *bo_gem;
111022944501Smrg	int ret;
111122944501Smrg	struct drm_gem_open open_arg;
111222944501Smrg	struct drm_i915_gem_get_tiling get_tiling;
111322944501Smrg
111420131375Smrg	/* At the moment most applications only have a few named bo.
111520131375Smrg	 * For instance, in a DRI client only the render buffers passed
111620131375Smrg	 * between X and the client are named. And since X returns the
111720131375Smrg	 * alternating names for the front/back buffer a linear search
111820131375Smrg	 * provides a sufficiently fast match.
111920131375Smrg	 */
1120a884aba1Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
11212ee35494Smrg	HASH_FIND(name_hh, bufmgr_gem->name_table,
11222ee35494Smrg		  &handle, sizeof(handle), bo_gem);
11232ee35494Smrg	if (bo_gem) {
11242ee35494Smrg		drm_intel_gem_bo_reference(&bo_gem->bo);
11252ee35494Smrg		goto out;
112620131375Smrg	}
112722944501Smrg
1128424e9256Smrg	memclear(open_arg);
112922944501Smrg	open_arg.name = handle;
11306d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
11316d98c517Smrg		       DRM_IOCTL_GEM_OPEN,
11326d98c517Smrg		       &open_arg);
113322944501Smrg	if (ret != 0) {
11349ce4edccSmrg		DBG("Couldn't reference %s handle 0x%08x: %s\n",
11359ce4edccSmrg		    name, handle, strerror(errno));
11362ee35494Smrg		bo_gem = NULL;
11372ee35494Smrg		goto out;
113822944501Smrg	}
113920131375Smrg        /* Now see if someone has used a prime handle to get this
114020131375Smrg         * object from the kernel before by looking through the list
114120131375Smrg         * again for a matching gem_handle
114220131375Smrg         */
11432ee35494Smrg	HASH_FIND(handle_hh, bufmgr_gem->handle_table,
11442ee35494Smrg		  &open_arg.handle, sizeof(open_arg.handle), bo_gem);
11452ee35494Smrg	if (bo_gem) {
11462ee35494Smrg		drm_intel_gem_bo_reference(&bo_gem->bo);
11472ee35494Smrg		goto out;
114820131375Smrg	}
114920131375Smrg
115020131375Smrg	bo_gem = calloc(1, sizeof(*bo_gem));
11512ee35494Smrg	if (!bo_gem)
11522ee35494Smrg		goto out;
11532ee35494Smrg
11542ee35494Smrg	atomic_set(&bo_gem->refcount, 1);
11552ee35494Smrg	DRMINITLISTHEAD(&bo_gem->vma_list);
115620131375Smrg
115722944501Smrg	bo_gem->bo.size = open_arg.size;
115822944501Smrg	bo_gem->bo.offset = 0;
115920131375Smrg	bo_gem->bo.offset64 = 0;
116022944501Smrg	bo_gem->bo.virtual = NULL;
116122944501Smrg	bo_gem->bo.bufmgr = bufmgr;
116222944501Smrg	bo_gem->name = name;
116322944501Smrg	bo_gem->validate_index = -1;
116422944501Smrg	bo_gem->gem_handle = open_arg.handle;
116520131375Smrg	bo_gem->bo.handle = open_arg.handle;
116622944501Smrg	bo_gem->global_name = handle;
116720131375Smrg	bo_gem->reusable = false;
1168fe517fc9Smrg	bo_gem->use_48b_address_range = false;
116922944501Smrg
11702ee35494Smrg	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
11712ee35494Smrg		 gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
11722ee35494Smrg	HASH_ADD(name_hh, bufmgr_gem->name_table,
11732ee35494Smrg		 global_name, sizeof(bo_gem->global_name), bo_gem);
11742ee35494Smrg
1175424e9256Smrg	memclear(get_tiling);
117622944501Smrg	get_tiling.handle = bo_gem->gem_handle;
11776d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
11786d98c517Smrg		       DRM_IOCTL_I915_GEM_GET_TILING,
11796d98c517Smrg		       &get_tiling);
11802ee35494Smrg	if (ret != 0)
11812ee35494Smrg		goto err_unref;
11822ee35494Smrg
118322944501Smrg	bo_gem->tiling_mode = get_tiling.tiling_mode;
118422944501Smrg	bo_gem->swizzle_mode = get_tiling.swizzle_mode;
11856d98c517Smrg	/* XXX stride is unknown */
1186fe517fc9Smrg	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
118722944501Smrg	DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
118822944501Smrg
11892ee35494Smrgout:
11902ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
119122944501Smrg	return &bo_gem->bo;
11922ee35494Smrg
11932ee35494Smrgerr_unref:
11942ee35494Smrg	drm_intel_gem_bo_free(&bo_gem->bo);
11952ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
11962ee35494Smrg	return NULL;
119722944501Smrg}
119822944501Smrg
119922944501Smrgstatic void
120022944501Smrgdrm_intel_gem_bo_free(drm_intel_bo *bo)
120122944501Smrg{
120222944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
120322944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
120422944501Smrg	struct drm_gem_close close;
120522944501Smrg	int ret;
120622944501Smrg
120720131375Smrg	DRMLISTDEL(&bo_gem->vma_list);
120820131375Smrg	if (bo_gem->mem_virtual) {
120920131375Smrg		VG(VALGRIND_FREELIKE_BLOCK(bo_gem->mem_virtual, 0));
1210a884aba1Smrg		drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
121120131375Smrg		bufmgr_gem->vma_count--;
121220131375Smrg	}
12132ee35494Smrg	if (bo_gem->wc_virtual) {
12142ee35494Smrg		VG(VALGRIND_FREELIKE_BLOCK(bo_gem->wc_virtual, 0));
12152ee35494Smrg		drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
12162ee35494Smrg		bufmgr_gem->vma_count--;
12172ee35494Smrg	}
121820131375Smrg	if (bo_gem->gtt_virtual) {
1219a884aba1Smrg		drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
122020131375Smrg		bufmgr_gem->vma_count--;
122120131375Smrg	}
122222944501Smrg
12232ee35494Smrg	if (bo_gem->global_name)
12242ee35494Smrg		HASH_DELETE(name_hh, bufmgr_gem->name_table, bo_gem);
12252ee35494Smrg	HASH_DELETE(handle_hh, bufmgr_gem->handle_table, bo_gem);
12262ee35494Smrg
122722944501Smrg	/* Close this object */
1228424e9256Smrg	memclear(close);
122922944501Smrg	close.handle = bo_gem->gem_handle;
12306d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
123122944501Smrg	if (ret != 0) {
12329ce4edccSmrg		DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
12339ce4edccSmrg		    bo_gem->gem_handle, bo_gem->name, strerror(errno));
123422944501Smrg	}
123522944501Smrg	free(bo);
123622944501Smrg}
123722944501Smrg
123820131375Smrgstatic void
123920131375Smrgdrm_intel_gem_bo_mark_mmaps_incoherent(drm_intel_bo *bo)
124020131375Smrg{
124120131375Smrg#if HAVE_VALGRIND
124220131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
124320131375Smrg
124420131375Smrg	if (bo_gem->mem_virtual)
124520131375Smrg		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size);
124620131375Smrg
12472ee35494Smrg	if (bo_gem->wc_virtual)
12482ee35494Smrg		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->wc_virtual, bo->size);
12492ee35494Smrg
125020131375Smrg	if (bo_gem->gtt_virtual)
125120131375Smrg		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size);
125220131375Smrg#endif
125320131375Smrg}
125420131375Smrg
125522944501Smrg/** Frees all cached buffers significantly older than @time. */
125622944501Smrgstatic void
125722944501Smrgdrm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time)
125822944501Smrg{
125922944501Smrg	int i;
126022944501Smrg
12616d98c517Smrg	if (bufmgr_gem->time == time)
12626d98c517Smrg		return;
12636d98c517Smrg
1264aaba2545Smrg	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
126522944501Smrg		struct drm_intel_gem_bo_bucket *bucket =
126622944501Smrg		    &bufmgr_gem->cache_bucket[i];
126722944501Smrg
126822944501Smrg		while (!DRMLISTEMPTY(&bucket->head)) {
126922944501Smrg			drm_intel_bo_gem *bo_gem;
127022944501Smrg
127122944501Smrg			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
127222944501Smrg					      bucket->head.next, head);
127322944501Smrg			if (time - bo_gem->free_time <= 1)
127422944501Smrg				break;
127522944501Smrg
127622944501Smrg			DRMLISTDEL(&bo_gem->head);
127722944501Smrg
127822944501Smrg			drm_intel_gem_bo_free(&bo_gem->bo);
127922944501Smrg		}
128022944501Smrg	}
12816d98c517Smrg
12826d98c517Smrg	bufmgr_gem->time = time;
128322944501Smrg}
128422944501Smrg
128520131375Smrgstatic void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem)
128620131375Smrg{
128720131375Smrg	int limit;
128820131375Smrg
128920131375Smrg	DBG("%s: cached=%d, open=%d, limit=%d\n", __FUNCTION__,
129020131375Smrg	    bufmgr_gem->vma_count, bufmgr_gem->vma_open, bufmgr_gem->vma_max);
129120131375Smrg
129220131375Smrg	if (bufmgr_gem->vma_max < 0)
129320131375Smrg		return;
129420131375Smrg
129520131375Smrg	/* We may need to evict a few entries in order to create new mmaps */
129620131375Smrg	limit = bufmgr_gem->vma_max - 2*bufmgr_gem->vma_open;
129720131375Smrg	if (limit < 0)
129820131375Smrg		limit = 0;
129920131375Smrg
130020131375Smrg	while (bufmgr_gem->vma_count > limit) {
130120131375Smrg		drm_intel_bo_gem *bo_gem;
130220131375Smrg
130320131375Smrg		bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
130420131375Smrg				      bufmgr_gem->vma_cache.next,
130520131375Smrg				      vma_list);
130620131375Smrg		assert(bo_gem->map_count == 0);
130720131375Smrg		DRMLISTDELINIT(&bo_gem->vma_list);
130820131375Smrg
130920131375Smrg		if (bo_gem->mem_virtual) {
1310a884aba1Smrg			drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
131120131375Smrg			bo_gem->mem_virtual = NULL;
131220131375Smrg			bufmgr_gem->vma_count--;
131320131375Smrg		}
13142ee35494Smrg		if (bo_gem->wc_virtual) {
13152ee35494Smrg			drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
13162ee35494Smrg			bo_gem->wc_virtual = NULL;
13172ee35494Smrg			bufmgr_gem->vma_count--;
13182ee35494Smrg		}
131920131375Smrg		if (bo_gem->gtt_virtual) {
1320a884aba1Smrg			drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
132120131375Smrg			bo_gem->gtt_virtual = NULL;
132220131375Smrg			bufmgr_gem->vma_count--;
132320131375Smrg		}
132420131375Smrg	}
132520131375Smrg}
132620131375Smrg
132720131375Smrgstatic void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem,
132820131375Smrg				       drm_intel_bo_gem *bo_gem)
132920131375Smrg{
133020131375Smrg	bufmgr_gem->vma_open--;
133120131375Smrg	DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache);
133220131375Smrg	if (bo_gem->mem_virtual)
133320131375Smrg		bufmgr_gem->vma_count++;
13342ee35494Smrg	if (bo_gem->wc_virtual)
13352ee35494Smrg		bufmgr_gem->vma_count++;
133620131375Smrg	if (bo_gem->gtt_virtual)
133720131375Smrg		bufmgr_gem->vma_count++;
133820131375Smrg	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
133920131375Smrg}
134020131375Smrg
134120131375Smrgstatic void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem,
134220131375Smrg				      drm_intel_bo_gem *bo_gem)
134320131375Smrg{
134420131375Smrg	bufmgr_gem->vma_open++;
134520131375Smrg	DRMLISTDEL(&bo_gem->vma_list);
134620131375Smrg	if (bo_gem->mem_virtual)
134720131375Smrg		bufmgr_gem->vma_count--;
13482ee35494Smrg	if (bo_gem->wc_virtual)
13492ee35494Smrg		bufmgr_gem->vma_count--;
135020131375Smrg	if (bo_gem->gtt_virtual)
135120131375Smrg		bufmgr_gem->vma_count--;
135220131375Smrg	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
135320131375Smrg}
135420131375Smrg
135522944501Smrgstatic void
135622944501Smrgdrm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time)
135722944501Smrg{
135822944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
135922944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
136022944501Smrg	struct drm_intel_gem_bo_bucket *bucket;
136122944501Smrg	int i;
136222944501Smrg
136322944501Smrg	/* Unreference all the target buffers */
136422944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++) {
1365aaba2545Smrg		if (bo_gem->reloc_target_info[i].bo != bo) {
1366aaba2545Smrg			drm_intel_gem_bo_unreference_locked_timed(bo_gem->
1367aaba2545Smrg								  reloc_target_info[i].bo,
1368aaba2545Smrg								  time);
1369aaba2545Smrg		}
137022944501Smrg	}
1371fe517fc9Smrg	for (i = 0; i < bo_gem->softpin_target_count; i++)
1372fe517fc9Smrg		drm_intel_gem_bo_unreference_locked_timed(bo_gem->softpin_target[i],
1373fe517fc9Smrg								  time);
13742ee35494Smrg	bo_gem->kflags = 0;
137522944501Smrg	bo_gem->reloc_count = 0;
137620131375Smrg	bo_gem->used_as_reloc_target = false;
1377fe517fc9Smrg	bo_gem->softpin_target_count = 0;
137822944501Smrg
137922944501Smrg	DBG("bo_unreference final: %d (%s)\n",
138022944501Smrg	    bo_gem->gem_handle, bo_gem->name);
138122944501Smrg
138222944501Smrg	/* release memory associated with this object */
138322944501Smrg	if (bo_gem->reloc_target_info) {
138422944501Smrg		free(bo_gem->reloc_target_info);
138522944501Smrg		bo_gem->reloc_target_info = NULL;
138622944501Smrg	}
138722944501Smrg	if (bo_gem->relocs) {
138822944501Smrg		free(bo_gem->relocs);
138922944501Smrg		bo_gem->relocs = NULL;
139022944501Smrg	}
1391fe517fc9Smrg	if (bo_gem->softpin_target) {
1392fe517fc9Smrg		free(bo_gem->softpin_target);
1393fe517fc9Smrg		bo_gem->softpin_target = NULL;
1394fe517fc9Smrg		bo_gem->softpin_target_size = 0;
1395fe517fc9Smrg	}
139622944501Smrg
139720131375Smrg	/* Clear any left-over mappings */
139820131375Smrg	if (bo_gem->map_count) {
139920131375Smrg		DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count);
140020131375Smrg		bo_gem->map_count = 0;
140120131375Smrg		drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
140220131375Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
140320131375Smrg	}
140420131375Smrg
140522944501Smrg	bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
140622944501Smrg	/* Put the buffer into our internal cache for reuse if we can. */
140722944501Smrg	if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL &&
140822944501Smrg	    drm_intel_gem_bo_madvise_internal(bufmgr_gem, bo_gem,
140922944501Smrg					      I915_MADV_DONTNEED)) {
141022944501Smrg		bo_gem->free_time = time;
141122944501Smrg
141222944501Smrg		bo_gem->name = NULL;
141322944501Smrg		bo_gem->validate_index = -1;
141422944501Smrg
14152ee35494Smrg		bo_gem->kflags = 0;
14162ee35494Smrg
141722944501Smrg		DRMLISTADDTAIL(&bo_gem->head, &bucket->head);
141822944501Smrg	} else {
141922944501Smrg		drm_intel_gem_bo_free(bo);
142022944501Smrg	}
142122944501Smrg}
142222944501Smrg
142322944501Smrgstatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo,
142422944501Smrg						      time_t time)
142522944501Smrg{
142622944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
142722944501Smrg
142822944501Smrg	assert(atomic_read(&bo_gem->refcount) > 0);
142922944501Smrg	if (atomic_dec_and_test(&bo_gem->refcount))
143022944501Smrg		drm_intel_gem_bo_unreference_final(bo, time);
143122944501Smrg}
143222944501Smrg
143322944501Smrgstatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo)
143422944501Smrg{
143522944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
143622944501Smrg
143722944501Smrg	assert(atomic_read(&bo_gem->refcount) > 0);
1438a884aba1Smrg
1439a884aba1Smrg	if (atomic_add_unless(&bo_gem->refcount, -1, 1)) {
144022944501Smrg		drm_intel_bufmgr_gem *bufmgr_gem =
144122944501Smrg		    (drm_intel_bufmgr_gem *) bo->bufmgr;
144222944501Smrg		struct timespec time;
144322944501Smrg
144422944501Smrg		clock_gettime(CLOCK_MONOTONIC, &time);
144522944501Smrg
144622944501Smrg		pthread_mutex_lock(&bufmgr_gem->lock);
1447a884aba1Smrg
1448a884aba1Smrg		if (atomic_dec_and_test(&bo_gem->refcount)) {
1449a884aba1Smrg			drm_intel_gem_bo_unreference_final(bo, time.tv_sec);
1450a884aba1Smrg			drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec);
1451a884aba1Smrg		}
1452a884aba1Smrg
145322944501Smrg		pthread_mutex_unlock(&bufmgr_gem->lock);
145422944501Smrg	}
145522944501Smrg}
145622944501Smrg
145722944501Smrgstatic int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
145822944501Smrg{
145922944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
146022944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
146122944501Smrg	struct drm_i915_gem_set_domain set_domain;
146222944501Smrg	int ret;
146322944501Smrg
1464a884aba1Smrg	if (bo_gem->is_userptr) {
1465a884aba1Smrg		/* Return the same user ptr */
1466a884aba1Smrg		bo->virtual = bo_gem->user_virtual;
1467a884aba1Smrg		return 0;
1468a884aba1Smrg	}
1469a884aba1Smrg
147022944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
147122944501Smrg
147220131375Smrg	if (bo_gem->map_count++ == 0)
147320131375Smrg		drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
147420131375Smrg
147522944501Smrg	if (!bo_gem->mem_virtual) {
147622944501Smrg		struct drm_i915_gem_mmap mmap_arg;
147722944501Smrg
147820131375Smrg		DBG("bo_map: %d (%s), map_count=%d\n",
147920131375Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
148022944501Smrg
1481424e9256Smrg		memclear(mmap_arg);
148222944501Smrg		mmap_arg.handle = bo_gem->gem_handle;
148322944501Smrg		mmap_arg.size = bo->size;
14846d98c517Smrg		ret = drmIoctl(bufmgr_gem->fd,
14856d98c517Smrg			       DRM_IOCTL_I915_GEM_MMAP,
14866d98c517Smrg			       &mmap_arg);
148722944501Smrg		if (ret != 0) {
148822944501Smrg			ret = -errno;
14899ce4edccSmrg			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
14909ce4edccSmrg			    __FILE__, __LINE__, bo_gem->gem_handle,
14919ce4edccSmrg			    bo_gem->name, strerror(errno));
149220131375Smrg			if (--bo_gem->map_count == 0)
149320131375Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
149422944501Smrg			pthread_mutex_unlock(&bufmgr_gem->lock);
149522944501Smrg			return ret;
149622944501Smrg		}
149720131375Smrg		VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
149822944501Smrg		bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
149922944501Smrg	}
150022944501Smrg	DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
150122944501Smrg	    bo_gem->mem_virtual);
150222944501Smrg	bo->virtual = bo_gem->mem_virtual;
150322944501Smrg
1504424e9256Smrg	memclear(set_domain);
150522944501Smrg	set_domain.handle = bo_gem->gem_handle;
150622944501Smrg	set_domain.read_domains = I915_GEM_DOMAIN_CPU;
150722944501Smrg	if (write_enable)
150822944501Smrg		set_domain.write_domain = I915_GEM_DOMAIN_CPU;
150922944501Smrg	else
151022944501Smrg		set_domain.write_domain = 0;
15116d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
15126d98c517Smrg		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
15136d98c517Smrg		       &set_domain);
151422944501Smrg	if (ret != 0) {
15159ce4edccSmrg		DBG("%s:%d: Error setting to CPU domain %d: %s\n",
15169ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle,
15179ce4edccSmrg		    strerror(errno));
151822944501Smrg	}
151922944501Smrg
152020131375Smrg	if (write_enable)
152120131375Smrg		bo_gem->mapped_cpu_write = true;
152220131375Smrg
152320131375Smrg	drm_intel_gem_bo_mark_mmaps_incoherent(bo);
152420131375Smrg	VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->mem_virtual, bo->size));
152522944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
152622944501Smrg
152722944501Smrg	return 0;
152822944501Smrg}
152922944501Smrg
153020131375Smrgstatic int
153120131375Smrgmap_gtt(drm_intel_bo *bo)
153222944501Smrg{
153322944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
153422944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
153522944501Smrg	int ret;
153622944501Smrg
1537a884aba1Smrg	if (bo_gem->is_userptr)
1538a884aba1Smrg		return -EINVAL;
1539a884aba1Smrg
154020131375Smrg	if (bo_gem->map_count++ == 0)
154120131375Smrg		drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
154222944501Smrg
154322944501Smrg	/* Get a mapping of the buffer if we haven't before. */
154422944501Smrg	if (bo_gem->gtt_virtual == NULL) {
154522944501Smrg		struct drm_i915_gem_mmap_gtt mmap_arg;
154622944501Smrg
154720131375Smrg		DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
154820131375Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
154922944501Smrg
1550424e9256Smrg		memclear(mmap_arg);
155122944501Smrg		mmap_arg.handle = bo_gem->gem_handle;
155222944501Smrg
155322944501Smrg		/* Get the fake offset back... */
15546d98c517Smrg		ret = drmIoctl(bufmgr_gem->fd,
15556d98c517Smrg			       DRM_IOCTL_I915_GEM_MMAP_GTT,
15566d98c517Smrg			       &mmap_arg);
155722944501Smrg		if (ret != 0) {
155822944501Smrg			ret = -errno;
15599ce4edccSmrg			DBG("%s:%d: Error preparing buffer map %d (%s): %s .\n",
15609ce4edccSmrg			    __FILE__, __LINE__,
15619ce4edccSmrg			    bo_gem->gem_handle, bo_gem->name,
15629ce4edccSmrg			    strerror(errno));
156320131375Smrg			if (--bo_gem->map_count == 0)
156420131375Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
156522944501Smrg			return ret;
156622944501Smrg		}
156722944501Smrg
156822944501Smrg		/* and mmap it */
1569aec75c42Sriastradh		ret = drmMap(bufmgr_gem->fd, mmap_arg.offset, bo->size,
1570aec75c42Sriastradh		    &bo_gem->gtt_virtual);
1571aec75c42Sriastradh		if (ret) {
157222944501Smrg			bo_gem->gtt_virtual = NULL;
15739ce4edccSmrg			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
15749ce4edccSmrg			    __FILE__, __LINE__,
15759ce4edccSmrg			    bo_gem->gem_handle, bo_gem->name,
15769ce4edccSmrg			    strerror(errno));
157720131375Smrg			if (--bo_gem->map_count == 0)
157820131375Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
157922944501Smrg			return ret;
158022944501Smrg		}
158122944501Smrg	}
158222944501Smrg
158322944501Smrg	bo->virtual = bo_gem->gtt_virtual;
158422944501Smrg
158522944501Smrg	DBG("bo_map_gtt: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
158622944501Smrg	    bo_gem->gtt_virtual);
158722944501Smrg
158820131375Smrg	return 0;
158920131375Smrg}
159020131375Smrg
1591424e9256Smrgint
1592a884aba1Smrgdrm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
159320131375Smrg{
159420131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
159520131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
159620131375Smrg	struct drm_i915_gem_set_domain set_domain;
159720131375Smrg	int ret;
159820131375Smrg
159920131375Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
160020131375Smrg
160120131375Smrg	ret = map_gtt(bo);
160220131375Smrg	if (ret) {
160320131375Smrg		pthread_mutex_unlock(&bufmgr_gem->lock);
160420131375Smrg		return ret;
160520131375Smrg	}
160620131375Smrg
160720131375Smrg	/* Now move it to the GTT domain so that the GPU and CPU
160820131375Smrg	 * caches are flushed and the GPU isn't actively using the
160920131375Smrg	 * buffer.
161020131375Smrg	 *
161120131375Smrg	 * The pagefault handler does this domain change for us when
161220131375Smrg	 * it has unbound the BO from the GTT, but it's up to us to
161320131375Smrg	 * tell it when we're about to use things if we had done
161420131375Smrg	 * rendering and it still happens to be bound to the GTT.
161520131375Smrg	 */
1616424e9256Smrg	memclear(set_domain);
161722944501Smrg	set_domain.handle = bo_gem->gem_handle;
161822944501Smrg	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
161922944501Smrg	set_domain.write_domain = I915_GEM_DOMAIN_GTT;
16206d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
16216d98c517Smrg		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
16226d98c517Smrg		       &set_domain);
162322944501Smrg	if (ret != 0) {
16249ce4edccSmrg		DBG("%s:%d: Error setting domain %d: %s\n",
16259ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle,
16269ce4edccSmrg		    strerror(errno));
162722944501Smrg	}
162822944501Smrg
162920131375Smrg	drm_intel_gem_bo_mark_mmaps_incoherent(bo);
163020131375Smrg	VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size));
163122944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
163222944501Smrg
16336d98c517Smrg	return 0;
163422944501Smrg}
163522944501Smrg
163620131375Smrg/**
163720131375Smrg * Performs a mapping of the buffer object like the normal GTT
163820131375Smrg * mapping, but avoids waiting for the GPU to be done reading from or
163920131375Smrg * rendering to the buffer.
164020131375Smrg *
164120131375Smrg * This is used in the implementation of GL_ARB_map_buffer_range: The
164220131375Smrg * user asks to create a buffer, then does a mapping, fills some
164320131375Smrg * space, runs a drawing command, then asks to map it again without
164420131375Smrg * synchronizing because it guarantees that it won't write over the
164520131375Smrg * data that the GPU is busy using (or, more specifically, that if it
164620131375Smrg * does write over the data, it acknowledges that rendering is
164720131375Smrg * undefined).
164820131375Smrg */
164920131375Smrg
1650424e9256Smrgint
1651a884aba1Smrgdrm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo)
165222944501Smrg{
165322944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
165420131375Smrg#ifdef HAVE_VALGRIND
165520131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
165620131375Smrg#endif
165720131375Smrg	int ret;
165822944501Smrg
165920131375Smrg	/* If the CPU cache isn't coherent with the GTT, then use a
166020131375Smrg	 * regular synchronized mapping.  The problem is that we don't
166120131375Smrg	 * track where the buffer was last used on the CPU side in
166220131375Smrg	 * terms of drm_intel_bo_map vs drm_intel_gem_bo_map_gtt, so
166320131375Smrg	 * we would potentially corrupt the buffer even when the user
166420131375Smrg	 * does reasonable things.
166520131375Smrg	 */
166620131375Smrg	if (!bufmgr_gem->has_llc)
166720131375Smrg		return drm_intel_gem_bo_map_gtt(bo);
166822944501Smrg
166922944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
167020131375Smrg
167120131375Smrg	ret = map_gtt(bo);
167220131375Smrg	if (ret == 0) {
167320131375Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
167420131375Smrg		VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size));
167520131375Smrg	}
167620131375Smrg
167722944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
167822944501Smrg
167922944501Smrg	return ret;
168022944501Smrg}
168122944501Smrg
168222944501Smrgstatic int drm_intel_gem_bo_unmap(drm_intel_bo *bo)
168322944501Smrg{
1684a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
168522944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
168620131375Smrg	int ret = 0;
168722944501Smrg
168822944501Smrg	if (bo == NULL)
168922944501Smrg		return 0;
169022944501Smrg
1691a884aba1Smrg	if (bo_gem->is_userptr)
1692a884aba1Smrg		return 0;
1693a884aba1Smrg
1694a884aba1Smrg	bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1695a884aba1Smrg
169622944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
169722944501Smrg
169820131375Smrg	if (bo_gem->map_count <= 0) {
169920131375Smrg		DBG("attempted to unmap an unmapped bo\n");
170020131375Smrg		pthread_mutex_unlock(&bufmgr_gem->lock);
170120131375Smrg		/* Preserve the old behaviour of just treating this as a
170220131375Smrg		 * no-op rather than reporting the error.
170320131375Smrg		 */
170420131375Smrg		return 0;
170520131375Smrg	}
170620131375Smrg
170720131375Smrg	if (bo_gem->mapped_cpu_write) {
170820131375Smrg		struct drm_i915_gem_sw_finish sw_finish;
170920131375Smrg
171020131375Smrg		/* Cause a flush to happen if the buffer's pinned for
171120131375Smrg		 * scanout, so the results show up in a timely manner.
171220131375Smrg		 * Unlike GTT set domains, this only does work if the
171320131375Smrg		 * buffer should be scanout-related.
171420131375Smrg		 */
1715424e9256Smrg		memclear(sw_finish);
171620131375Smrg		sw_finish.handle = bo_gem->gem_handle;
171720131375Smrg		ret = drmIoctl(bufmgr_gem->fd,
171820131375Smrg			       DRM_IOCTL_I915_GEM_SW_FINISH,
171920131375Smrg			       &sw_finish);
172020131375Smrg		ret = ret == -1 ? -errno : 0;
172120131375Smrg
172220131375Smrg		bo_gem->mapped_cpu_write = false;
172320131375Smrg	}
172422944501Smrg
172520131375Smrg	/* We need to unmap after every innovation as we cannot track
17262ee35494Smrg	 * an open vma for every bo as that will exhaust the system
172720131375Smrg	 * limits and cause later failures.
172820131375Smrg	 */
172920131375Smrg	if (--bo_gem->map_count == 0) {
173020131375Smrg		drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
173120131375Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
173220131375Smrg		bo->virtual = NULL;
173320131375Smrg	}
173422944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
173522944501Smrg
173622944501Smrg	return ret;
173722944501Smrg}
173822944501Smrg
1739424e9256Smrgint
1740a884aba1Smrgdrm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo)
174120131375Smrg{
174220131375Smrg	return drm_intel_gem_bo_unmap(bo);
174320131375Smrg}
174420131375Smrg
174522944501Smrgstatic int
174622944501Smrgdrm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset,
174722944501Smrg			 unsigned long size, const void *data)
174822944501Smrg{
174922944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
175022944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
175122944501Smrg	struct drm_i915_gem_pwrite pwrite;
175222944501Smrg	int ret;
175322944501Smrg
1754a884aba1Smrg	if (bo_gem->is_userptr)
1755a884aba1Smrg		return -EINVAL;
1756a884aba1Smrg
1757424e9256Smrg	memclear(pwrite);
175822944501Smrg	pwrite.handle = bo_gem->gem_handle;
175922944501Smrg	pwrite.offset = offset;
176022944501Smrg	pwrite.size = size;
176122944501Smrg	pwrite.data_ptr = (uint64_t) (uintptr_t) data;
17626d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
17636d98c517Smrg		       DRM_IOCTL_I915_GEM_PWRITE,
17646d98c517Smrg		       &pwrite);
176522944501Smrg	if (ret != 0) {
176622944501Smrg		ret = -errno;
17679ce4edccSmrg		DBG("%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
17689ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
17699ce4edccSmrg		    (int)size, strerror(errno));
177022944501Smrg	}
177122944501Smrg
177222944501Smrg	return ret;
177322944501Smrg}
177422944501Smrg
177522944501Smrgstatic int
177622944501Smrgdrm_intel_gem_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id)
177722944501Smrg{
177822944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
177922944501Smrg	struct drm_i915_get_pipe_from_crtc_id get_pipe_from_crtc_id;
178022944501Smrg	int ret;
178122944501Smrg
1782424e9256Smrg	memclear(get_pipe_from_crtc_id);
178322944501Smrg	get_pipe_from_crtc_id.crtc_id = crtc_id;
17846d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
17856d98c517Smrg		       DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID,
17866d98c517Smrg		       &get_pipe_from_crtc_id);
178722944501Smrg	if (ret != 0) {
178822944501Smrg		/* We return -1 here to signal that we don't
178922944501Smrg		 * know which pipe is associated with this crtc.
179022944501Smrg		 * This lets the caller know that this information
179122944501Smrg		 * isn't available; using the wrong pipe for
179222944501Smrg		 * vblank waiting can cause the chipset to lock up
179322944501Smrg		 */
179422944501Smrg		return -1;
179522944501Smrg	}
179622944501Smrg
179722944501Smrg	return get_pipe_from_crtc_id.pipe;
179822944501Smrg}
179922944501Smrg
180022944501Smrgstatic int
180122944501Smrgdrm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset,
180222944501Smrg			     unsigned long size, void *data)
180322944501Smrg{
180422944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
180522944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
180622944501Smrg	struct drm_i915_gem_pread pread;
180722944501Smrg	int ret;
180822944501Smrg
1809a884aba1Smrg	if (bo_gem->is_userptr)
1810a884aba1Smrg		return -EINVAL;
1811a884aba1Smrg
1812424e9256Smrg	memclear(pread);
181322944501Smrg	pread.handle = bo_gem->gem_handle;
181422944501Smrg	pread.offset = offset;
181522944501Smrg	pread.size = size;
181622944501Smrg	pread.data_ptr = (uint64_t) (uintptr_t) data;
18176d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
18186d98c517Smrg		       DRM_IOCTL_I915_GEM_PREAD,
18196d98c517Smrg		       &pread);
182022944501Smrg	if (ret != 0) {
182122944501Smrg		ret = -errno;
18229ce4edccSmrg		DBG("%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
18239ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
18249ce4edccSmrg		    (int)size, strerror(errno));
182522944501Smrg	}
182622944501Smrg
182722944501Smrg	return ret;
182822944501Smrg}
182922944501Smrg
18309ce4edccSmrg/** Waits for all GPU rendering with the object to have completed. */
183122944501Smrgstatic void
183222944501Smrgdrm_intel_gem_bo_wait_rendering(drm_intel_bo *bo)
183322944501Smrg{
18349ce4edccSmrg	drm_intel_gem_bo_start_gtt_access(bo, 1);
183522944501Smrg}
183622944501Smrg
183720131375Smrg/**
183820131375Smrg * Waits on a BO for the given amount of time.
183920131375Smrg *
184020131375Smrg * @bo: buffer object to wait for
184120131375Smrg * @timeout_ns: amount of time to wait in nanoseconds.
184220131375Smrg *   If value is less than 0, an infinite wait will occur.
184320131375Smrg *
184420131375Smrg * Returns 0 if the wait was successful ie. the last batch referencing the
184520131375Smrg * object has completed within the allotted time. Otherwise some negative return
184620131375Smrg * value describes the error. Of particular interest is -ETIME when the wait has
184720131375Smrg * failed to yield the desired result.
184820131375Smrg *
184920131375Smrg * Similar to drm_intel_gem_bo_wait_rendering except a timeout parameter allows
185020131375Smrg * the operation to give up after a certain amount of time. Another subtle
185120131375Smrg * difference is the internal locking semantics are different (this variant does
185220131375Smrg * not hold the lock for the duration of the wait). This makes the wait subject
185320131375Smrg * to a larger userspace race window.
185420131375Smrg *
185520131375Smrg * The implementation shall wait until the object is no longer actively
185620131375Smrg * referenced within a batch buffer at the time of the call. The wait will
185720131375Smrg * not guarantee that the buffer is re-issued via another thread, or an flinked
185820131375Smrg * handle. Userspace must make sure this race does not occur if such precision
185920131375Smrg * is important.
1860424e9256Smrg *
1861424e9256Smrg * Note that some kernels have broken the inifite wait for negative values
1862424e9256Smrg * promise, upgrade to latest stable kernels if this is the case.
186320131375Smrg */
1864424e9256Smrgint
1865a884aba1Smrgdrm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns)
186620131375Smrg{
186720131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
186820131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
186920131375Smrg	struct drm_i915_gem_wait wait;
187020131375Smrg	int ret;
187120131375Smrg
187220131375Smrg	if (!bufmgr_gem->has_wait_timeout) {
187320131375Smrg		DBG("%s:%d: Timed wait is not supported. Falling back to "
187420131375Smrg		    "infinite wait\n", __FILE__, __LINE__);
187520131375Smrg		if (timeout_ns) {
187620131375Smrg			drm_intel_gem_bo_wait_rendering(bo);
187720131375Smrg			return 0;
187820131375Smrg		} else {
187920131375Smrg			return drm_intel_gem_bo_busy(bo) ? -ETIME : 0;
188020131375Smrg		}
188120131375Smrg	}
188220131375Smrg
1883424e9256Smrg	memclear(wait);
188420131375Smrg	wait.bo_handle = bo_gem->gem_handle;
188520131375Smrg	wait.timeout_ns = timeout_ns;
188620131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
188720131375Smrg	if (ret == -1)
188820131375Smrg		return -errno;
188920131375Smrg
189020131375Smrg	return ret;
189120131375Smrg}
189220131375Smrg
189322944501Smrg/**
189422944501Smrg * Sets the object to the GTT read and possibly write domain, used by the X
189522944501Smrg * 2D driver in the absence of kernel support to do drm_intel_gem_bo_map_gtt().
189622944501Smrg *
189722944501Smrg * In combination with drm_intel_gem_bo_pin() and manual fence management, we
189822944501Smrg * can do tiled pixmaps this way.
189922944501Smrg */
1900424e9256Smrgvoid
190122944501Smrgdrm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable)
190222944501Smrg{
190322944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
190422944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
190522944501Smrg	struct drm_i915_gem_set_domain set_domain;
190622944501Smrg	int ret;
190722944501Smrg
1908424e9256Smrg	memclear(set_domain);
190922944501Smrg	set_domain.handle = bo_gem->gem_handle;
191022944501Smrg	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
191122944501Smrg	set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_GTT : 0;
19126d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
19136d98c517Smrg		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
19146d98c517Smrg		       &set_domain);
191522944501Smrg	if (ret != 0) {
19169ce4edccSmrg		DBG("%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
19179ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle,
19189ce4edccSmrg		    set_domain.read_domains, set_domain.write_domain,
19199ce4edccSmrg		    strerror(errno));
192022944501Smrg	}
192122944501Smrg}
192222944501Smrg
192322944501Smrgstatic void
192422944501Smrgdrm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr)
192522944501Smrg{
192622944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
1927424e9256Smrg	struct drm_gem_close close_bo;
1928424e9256Smrg	int i, ret;
192922944501Smrg
193022944501Smrg	free(bufmgr_gem->exec2_objects);
193122944501Smrg	free(bufmgr_gem->exec_objects);
193222944501Smrg	free(bufmgr_gem->exec_bos);
193322944501Smrg
193422944501Smrg	pthread_mutex_destroy(&bufmgr_gem->lock);
193522944501Smrg
193622944501Smrg	/* Free any cached buffer objects we were going to reuse */
1937aaba2545Smrg	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
193822944501Smrg		struct drm_intel_gem_bo_bucket *bucket =
193922944501Smrg		    &bufmgr_gem->cache_bucket[i];
194022944501Smrg		drm_intel_bo_gem *bo_gem;
194122944501Smrg
194222944501Smrg		while (!DRMLISTEMPTY(&bucket->head)) {
194322944501Smrg			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
194422944501Smrg					      bucket->head.next, head);
194522944501Smrg			DRMLISTDEL(&bo_gem->head);
194622944501Smrg
194722944501Smrg			drm_intel_gem_bo_free(&bo_gem->bo);
194822944501Smrg		}
194922944501Smrg	}
195022944501Smrg
1951424e9256Smrg	/* Release userptr bo kept hanging around for optimisation. */
1952424e9256Smrg	if (bufmgr_gem->userptr_active.ptr) {
1953424e9256Smrg		memclear(close_bo);
1954424e9256Smrg		close_bo.handle = bufmgr_gem->userptr_active.handle;
1955424e9256Smrg		ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
1956424e9256Smrg		free(bufmgr_gem->userptr_active.ptr);
1957424e9256Smrg		if (ret)
1958424e9256Smrg			fprintf(stderr,
1959424e9256Smrg				"Failed to release test userptr object! (%d) "
1960424e9256Smrg				"i915 kernel driver may not be sane!\n", errno);
1961424e9256Smrg	}
1962424e9256Smrg
196322944501Smrg	free(bufmgr);
196422944501Smrg}
196522944501Smrg
196622944501Smrg/**
196722944501Smrg * Adds the target buffer to the validation list and adds the relocation
196822944501Smrg * to the reloc_buffer's relocation list.
196922944501Smrg *
197022944501Smrg * The relocation entry at the given offset must already contain the
197122944501Smrg * precomputed relocation value, because the kernel will optimize out
197222944501Smrg * the relocation entry write when the buffer hasn't moved from the
197322944501Smrg * last known offset in target_bo.
197422944501Smrg */
197522944501Smrgstatic int
197622944501Smrgdo_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
197722944501Smrg		 drm_intel_bo *target_bo, uint32_t target_offset,
197822944501Smrg		 uint32_t read_domains, uint32_t write_domain,
197920131375Smrg		 bool need_fence)
198022944501Smrg{
198122944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
198222944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
198322944501Smrg	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
198420131375Smrg	bool fenced_command;
198522944501Smrg
198622944501Smrg	if (bo_gem->has_error)
198722944501Smrg		return -ENOMEM;
198822944501Smrg
198922944501Smrg	if (target_bo_gem->has_error) {
199020131375Smrg		bo_gem->has_error = true;
199122944501Smrg		return -ENOMEM;
199222944501Smrg	}
199322944501Smrg
199422944501Smrg	/* We never use HW fences for rendering on 965+ */
199522944501Smrg	if (bufmgr_gem->gen >= 4)
199620131375Smrg		need_fence = false;
199722944501Smrg
19989ce4edccSmrg	fenced_command = need_fence;
19999ce4edccSmrg	if (target_bo_gem->tiling_mode == I915_TILING_NONE)
200020131375Smrg		need_fence = false;
20019ce4edccSmrg
200222944501Smrg	/* Create a new relocation list if needed */
200322944501Smrg	if (bo_gem->relocs == NULL && drm_intel_setup_reloc_list(bo))
200422944501Smrg		return -ENOMEM;
200522944501Smrg
200622944501Smrg	/* Check overflow */
200722944501Smrg	assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
200822944501Smrg
200922944501Smrg	/* Check args */
201022944501Smrg	assert(offset <= bo->size - 4);
201122944501Smrg	assert((write_domain & (write_domain - 1)) == 0);
201222944501Smrg
20133c748557Ssnj	/* An object needing a fence is a tiled buffer, so it won't have
20143c748557Ssnj	 * relocs to other buffers.
20153c748557Ssnj	 */
20163c748557Ssnj	if (need_fence) {
20173c748557Ssnj		assert(target_bo_gem->reloc_count == 0);
20183c748557Ssnj		target_bo_gem->reloc_tree_fences = 1;
20193c748557Ssnj	}
20203c748557Ssnj
202122944501Smrg	/* Make sure that we're not adding a reloc to something whose size has
202222944501Smrg	 * already been accounted for.
202322944501Smrg	 */
202422944501Smrg	assert(!bo_gem->used_as_reloc_target);
2025aaba2545Smrg	if (target_bo_gem != bo_gem) {
202620131375Smrg		target_bo_gem->used_as_reloc_target = true;
2027aaba2545Smrg		bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size;
20283c748557Ssnj		bo_gem->reloc_tree_fences += target_bo_gem->reloc_tree_fences;
2029aaba2545Smrg	}
203022944501Smrg
203122944501Smrg	bo_gem->reloc_target_info[bo_gem->reloc_count].bo = target_bo;
2032aaba2545Smrg	if (target_bo != bo)
2033aaba2545Smrg		drm_intel_gem_bo_reference(target_bo);
20349ce4edccSmrg	if (fenced_command)
203522944501Smrg		bo_gem->reloc_target_info[bo_gem->reloc_count].flags =
203622944501Smrg			DRM_INTEL_RELOC_FENCE;
203722944501Smrg	else
203822944501Smrg		bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 0;
203922944501Smrg
2040fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].offset = offset;
2041fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].delta = target_offset;
2042fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].target_handle =
2043fe517fc9Smrg	    target_bo_gem->gem_handle;
2044fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
2045fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
2046fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset64;
204722944501Smrg	bo_gem->reloc_count++;
204822944501Smrg
204922944501Smrg	return 0;
205022944501Smrg}
205122944501Smrg
2052fe517fc9Smrgstatic void
2053fe517fc9Smrgdrm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable)
2054fe517fc9Smrg{
2055fe517fc9Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2056fe517fc9Smrg	bo_gem->use_48b_address_range = enable;
2057fe517fc9Smrg}
2058fe517fc9Smrg
2059fe517fc9Smrgstatic int
2060fe517fc9Smrgdrm_intel_gem_bo_add_softpin_target(drm_intel_bo *bo, drm_intel_bo *target_bo)
2061fe517fc9Smrg{
2062fe517fc9Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2063fe517fc9Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2064fe517fc9Smrg	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
2065fe517fc9Smrg	if (bo_gem->has_error)
2066fe517fc9Smrg		return -ENOMEM;
2067fe517fc9Smrg
2068fe517fc9Smrg	if (target_bo_gem->has_error) {
2069fe517fc9Smrg		bo_gem->has_error = true;
2070fe517fc9Smrg		return -ENOMEM;
2071fe517fc9Smrg	}
2072fe517fc9Smrg
2073fe517fc9Smrg	if (!target_bo_gem->is_softpin)
2074fe517fc9Smrg		return -EINVAL;
2075fe517fc9Smrg	if (target_bo_gem == bo_gem)
2076fe517fc9Smrg		return -EINVAL;
2077fe517fc9Smrg
2078fe517fc9Smrg	if (bo_gem->softpin_target_count == bo_gem->softpin_target_size) {
2079fe517fc9Smrg		int new_size = bo_gem->softpin_target_size * 2;
2080fe517fc9Smrg		if (new_size == 0)
2081fe517fc9Smrg			new_size = bufmgr_gem->max_relocs;
2082fe517fc9Smrg
2083fe517fc9Smrg		bo_gem->softpin_target = realloc(bo_gem->softpin_target, new_size *
2084fe517fc9Smrg				sizeof(drm_intel_bo *));
2085fe517fc9Smrg		if (!bo_gem->softpin_target)
2086fe517fc9Smrg			return -ENOMEM;
2087fe517fc9Smrg
2088fe517fc9Smrg		bo_gem->softpin_target_size = new_size;
2089fe517fc9Smrg	}
2090fe517fc9Smrg	bo_gem->softpin_target[bo_gem->softpin_target_count] = target_bo;
2091fe517fc9Smrg	drm_intel_gem_bo_reference(target_bo);
2092fe517fc9Smrg	bo_gem->softpin_target_count++;
2093fe517fc9Smrg
2094fe517fc9Smrg	return 0;
2095fe517fc9Smrg}
2096fe517fc9Smrg
209722944501Smrgstatic int
209822944501Smrgdrm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
209922944501Smrg			    drm_intel_bo *target_bo, uint32_t target_offset,
210022944501Smrg			    uint32_t read_domains, uint32_t write_domain)
210122944501Smrg{
210222944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
2103fe517fc9Smrg	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo;
210422944501Smrg
2105fe517fc9Smrg	if (target_bo_gem->is_softpin)
2106fe517fc9Smrg		return drm_intel_gem_bo_add_softpin_target(bo, target_bo);
2107fe517fc9Smrg	else
2108fe517fc9Smrg		return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
2109fe517fc9Smrg					read_domains, write_domain,
2110fe517fc9Smrg					!bufmgr_gem->fenced_relocs);
211122944501Smrg}
211222944501Smrg
211322944501Smrgstatic int
211422944501Smrgdrm_intel_gem_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset,
211522944501Smrg				  drm_intel_bo *target_bo,
211622944501Smrg				  uint32_t target_offset,
211722944501Smrg				  uint32_t read_domains, uint32_t write_domain)
211822944501Smrg{
211922944501Smrg	return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
212020131375Smrg				read_domains, write_domain, true);
212120131375Smrg}
212220131375Smrg
2123424e9256Smrgint
212420131375Smrgdrm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo)
212520131375Smrg{
212620131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
212720131375Smrg
212820131375Smrg	return bo_gem->reloc_count;
212920131375Smrg}
213020131375Smrg
213120131375Smrg/**
213220131375Smrg * Removes existing relocation entries in the BO after "start".
213320131375Smrg *
213420131375Smrg * This allows a user to avoid a two-step process for state setup with
213520131375Smrg * counting up all the buffer objects and doing a
213620131375Smrg * drm_intel_bufmgr_check_aperture_space() before emitting any of the
213720131375Smrg * relocations for the state setup.  Instead, save the state of the
213820131375Smrg * batchbuffer including drm_intel_gem_get_reloc_count(), emit all the
213920131375Smrg * state, and then check if it still fits in the aperture.
214020131375Smrg *
214120131375Smrg * Any further drm_intel_bufmgr_check_aperture_space() queries
214220131375Smrg * involving this buffer in the tree are undefined after this call.
2143fe517fc9Smrg *
2144fe517fc9Smrg * This also removes all softpinned targets being referenced by the BO.
214520131375Smrg */
2146424e9256Smrgvoid
214720131375Smrgdrm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start)
214820131375Smrg{
2149a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
215020131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
215120131375Smrg	int i;
215220131375Smrg	struct timespec time;
215320131375Smrg
215420131375Smrg	clock_gettime(CLOCK_MONOTONIC, &time);
215520131375Smrg
215620131375Smrg	assert(bo_gem->reloc_count >= start);
2157a884aba1Smrg
215820131375Smrg	/* Unreference the cleared target buffers */
2159a884aba1Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
2160a884aba1Smrg
216120131375Smrg	for (i = start; i < bo_gem->reloc_count; i++) {
216220131375Smrg		drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->reloc_target_info[i].bo;
216320131375Smrg		if (&target_bo_gem->bo != bo) {
216420131375Smrg			bo_gem->reloc_tree_fences -= target_bo_gem->reloc_tree_fences;
216520131375Smrg			drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo,
216620131375Smrg								  time.tv_sec);
216720131375Smrg		}
216820131375Smrg	}
216920131375Smrg	bo_gem->reloc_count = start;
2170a884aba1Smrg
2171fe517fc9Smrg	for (i = 0; i < bo_gem->softpin_target_count; i++) {
2172fe517fc9Smrg		drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->softpin_target[i];
2173fe517fc9Smrg		drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, time.tv_sec);
2174fe517fc9Smrg	}
2175fe517fc9Smrg	bo_gem->softpin_target_count = 0;
2176fe517fc9Smrg
2177a884aba1Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
2178a884aba1Smrg
217922944501Smrg}
218022944501Smrg
218122944501Smrg/**
218222944501Smrg * Walk the tree of relocations rooted at BO and accumulate the list of
218322944501Smrg * validations to be performed and update the relocation buffers with
218422944501Smrg * index values into the validation list.
218522944501Smrg */
218622944501Smrgstatic void
218722944501Smrgdrm_intel_gem_bo_process_reloc(drm_intel_bo *bo)
218822944501Smrg{
218922944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
219022944501Smrg	int i;
219122944501Smrg
219222944501Smrg	if (bo_gem->relocs == NULL)
219322944501Smrg		return;
219422944501Smrg
219522944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++) {
219622944501Smrg		drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo;
219722944501Smrg
2198aaba2545Smrg		if (target_bo == bo)
2199aaba2545Smrg			continue;
2200aaba2545Smrg
220120131375Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
220220131375Smrg
220322944501Smrg		/* Continue walking the tree depth-first. */
220422944501Smrg		drm_intel_gem_bo_process_reloc(target_bo);
220522944501Smrg
220622944501Smrg		/* Add the target to the validate list */
220722944501Smrg		drm_intel_add_validate_buffer(target_bo);
220822944501Smrg	}
220922944501Smrg}
221022944501Smrg
221122944501Smrgstatic void
221222944501Smrgdrm_intel_gem_bo_process_reloc2(drm_intel_bo *bo)
221322944501Smrg{
221422944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
221522944501Smrg	int i;
221622944501Smrg
2217fe517fc9Smrg	if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL)
221822944501Smrg		return;
221922944501Smrg
222022944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++) {
222122944501Smrg		drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo;
222222944501Smrg		int need_fence;
222322944501Smrg
2224aaba2545Smrg		if (target_bo == bo)
2225aaba2545Smrg			continue;
2226aaba2545Smrg
222720131375Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
222820131375Smrg
222922944501Smrg		/* Continue walking the tree depth-first. */
223022944501Smrg		drm_intel_gem_bo_process_reloc2(target_bo);
223122944501Smrg
223222944501Smrg		need_fence = (bo_gem->reloc_target_info[i].flags &
223322944501Smrg			      DRM_INTEL_RELOC_FENCE);
223422944501Smrg
223522944501Smrg		/* Add the target to the validate list */
223622944501Smrg		drm_intel_add_validate_buffer2(target_bo, need_fence);
223722944501Smrg	}
2238fe517fc9Smrg
2239fe517fc9Smrg	for (i = 0; i < bo_gem->softpin_target_count; i++) {
2240fe517fc9Smrg		drm_intel_bo *target_bo = bo_gem->softpin_target[i];
2241fe517fc9Smrg
2242fe517fc9Smrg		if (target_bo == bo)
2243fe517fc9Smrg			continue;
2244fe517fc9Smrg
2245fe517fc9Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
2246fe517fc9Smrg		drm_intel_gem_bo_process_reloc2(target_bo);
2247fe517fc9Smrg		drm_intel_add_validate_buffer2(target_bo, false);
2248fe517fc9Smrg	}
224922944501Smrg}
225022944501Smrg
225122944501Smrg
225222944501Smrgstatic void
225322944501Smrgdrm_intel_update_buffer_offsets(drm_intel_bufmgr_gem *bufmgr_gem)
225422944501Smrg{
225522944501Smrg	int i;
225622944501Smrg
225722944501Smrg	for (i = 0; i < bufmgr_gem->exec_count; i++) {
225822944501Smrg		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
225922944501Smrg		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
226022944501Smrg
226122944501Smrg		/* Update the buffer offset */
226220131375Smrg		if (bufmgr_gem->exec_objects[i].offset != bo->offset64) {
2263fe517fc9Smrg			DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n",
2264d82d45b3Sjoerg			    bo_gem->gem_handle, bo_gem->name,
2265fe517fc9Smrg			    upper_32_bits(bo->offset64),
2266fe517fc9Smrg			    lower_32_bits(bo->offset64),
2267fe517fc9Smrg			    upper_32_bits(bufmgr_gem->exec_objects[i].offset),
2268fe517fc9Smrg			    lower_32_bits(bufmgr_gem->exec_objects[i].offset));
226920131375Smrg			bo->offset64 = bufmgr_gem->exec_objects[i].offset;
227022944501Smrg			bo->offset = bufmgr_gem->exec_objects[i].offset;
227122944501Smrg		}
227222944501Smrg	}
227322944501Smrg}
227422944501Smrg
227522944501Smrgstatic void
227622944501Smrgdrm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem)
227722944501Smrg{
227822944501Smrg	int i;
227922944501Smrg
228022944501Smrg	for (i = 0; i < bufmgr_gem->exec_count; i++) {
228122944501Smrg		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
228222944501Smrg		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
228322944501Smrg
228422944501Smrg		/* Update the buffer offset */
228520131375Smrg		if (bufmgr_gem->exec2_objects[i].offset != bo->offset64) {
2286fe517fc9Smrg			/* If we're seeing softpinned object here it means that the kernel
2287fe517fc9Smrg			 * has relocated our object... Indicating a programming error
2288fe517fc9Smrg			 */
2289fe517fc9Smrg			assert(!bo_gem->is_softpin);
2290fe517fc9Smrg			DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n",
2291d82d45b3Sjoerg			    bo_gem->gem_handle, bo_gem->name,
2292fe517fc9Smrg			    upper_32_bits(bo->offset64),
2293fe517fc9Smrg			    lower_32_bits(bo->offset64),
2294fe517fc9Smrg			    upper_32_bits(bufmgr_gem->exec2_objects[i].offset),
2295fe517fc9Smrg			    lower_32_bits(bufmgr_gem->exec2_objects[i].offset));
229620131375Smrg			bo->offset64 = bufmgr_gem->exec2_objects[i].offset;
229722944501Smrg			bo->offset = bufmgr_gem->exec2_objects[i].offset;
229822944501Smrg		}
229922944501Smrg	}
230022944501Smrg}
230122944501Smrg
2302424e9256Smrgvoid
230320131375Smrgdrm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo,
230420131375Smrg			      int x1, int y1, int width, int height,
230520131375Smrg			      enum aub_dump_bmp_format format,
230620131375Smrg			      int pitch, int offset)
230720131375Smrg{
230820131375Smrg}
230920131375Smrg
231020131375Smrgstatic int
231120131375Smrgdrm_intel_gem_bo_exec(drm_intel_bo *bo, int used,
231220131375Smrg		      drm_clip_rect_t * cliprects, int num_cliprects, int DR4)
231320131375Smrg{
231420131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
231520131375Smrg	struct drm_i915_gem_execbuffer execbuf;
231620131375Smrg	int ret, i;
231720131375Smrg
2318fe517fc9Smrg	if (to_bo_gem(bo)->has_error)
231920131375Smrg		return -ENOMEM;
232020131375Smrg
232120131375Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
232220131375Smrg	/* Update indices and set up the validate list. */
232320131375Smrg	drm_intel_gem_bo_process_reloc(bo);
232420131375Smrg
232520131375Smrg	/* Add the batch buffer to the validation list.  There are no
232620131375Smrg	 * relocations pointing to it.
232720131375Smrg	 */
232820131375Smrg	drm_intel_add_validate_buffer(bo);
232920131375Smrg
2330424e9256Smrg	memclear(execbuf);
233120131375Smrg	execbuf.buffers_ptr = (uintptr_t) bufmgr_gem->exec_objects;
233220131375Smrg	execbuf.buffer_count = bufmgr_gem->exec_count;
233320131375Smrg	execbuf.batch_start_offset = 0;
233420131375Smrg	execbuf.batch_len = used;
233520131375Smrg	execbuf.cliprects_ptr = (uintptr_t) cliprects;
233620131375Smrg	execbuf.num_cliprects = num_cliprects;
233720131375Smrg	execbuf.DR1 = 0;
233820131375Smrg	execbuf.DR4 = DR4;
233920131375Smrg
234020131375Smrg	ret = drmIoctl(bufmgr_gem->fd,
234120131375Smrg		       DRM_IOCTL_I915_GEM_EXECBUFFER,
234220131375Smrg		       &execbuf);
234320131375Smrg	if (ret != 0) {
234420131375Smrg		ret = -errno;
234520131375Smrg		if (errno == ENOSPC) {
234620131375Smrg			DBG("Execbuffer fails to pin. "
234720131375Smrg			    "Estimate: %u. Actual: %u. Available: %u\n",
234820131375Smrg			    drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos,
234920131375Smrg							       bufmgr_gem->
235020131375Smrg							       exec_count),
235120131375Smrg			    drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos,
235220131375Smrg							      bufmgr_gem->
235320131375Smrg							      exec_count),
235420131375Smrg			    (unsigned int)bufmgr_gem->gtt_size);
235520131375Smrg		}
235620131375Smrg	}
235720131375Smrg	drm_intel_update_buffer_offsets(bufmgr_gem);
235820131375Smrg
235920131375Smrg	if (bufmgr_gem->bufmgr.debug)
236020131375Smrg		drm_intel_gem_dump_validation_list(bufmgr_gem);
236120131375Smrg
236220131375Smrg	for (i = 0; i < bufmgr_gem->exec_count; i++) {
2363fe517fc9Smrg		drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]);
236420131375Smrg
236520131375Smrg		bo_gem->idle = false;
236620131375Smrg
236720131375Smrg		/* Disconnect the buffer from the validate list */
236820131375Smrg		bo_gem->validate_index = -1;
236920131375Smrg		bufmgr_gem->exec_bos[i] = NULL;
237020131375Smrg	}
237120131375Smrg	bufmgr_gem->exec_count = 0;
237220131375Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
237320131375Smrg
237420131375Smrg	return ret;
237520131375Smrg}
237620131375Smrg
237720131375Smrgstatic int
237820131375Smrgdo_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
237920131375Smrg	 drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
23802ee35494Smrg	 int in_fence, int *out_fence,
238120131375Smrg	 unsigned int flags)
238220131375Smrg{
238320131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
238420131375Smrg	struct drm_i915_gem_execbuffer2 execbuf;
238520131375Smrg	int ret = 0;
238620131375Smrg	int i;
238720131375Smrg
2388fe517fc9Smrg	if (to_bo_gem(bo)->has_error)
2389fe517fc9Smrg		return -ENOMEM;
2390fe517fc9Smrg
239120131375Smrg	switch (flags & 0x7) {
239220131375Smrg	default:
239320131375Smrg		return -EINVAL;
239420131375Smrg	case I915_EXEC_BLT:
23959ce4edccSmrg		if (!bufmgr_gem->has_blt)
23969ce4edccSmrg			return -EINVAL;
23979ce4edccSmrg		break;
23989ce4edccSmrg	case I915_EXEC_BSD:
23999ce4edccSmrg		if (!bufmgr_gem->has_bsd)
24009ce4edccSmrg			return -EINVAL;
24019ce4edccSmrg		break;
240220131375Smrg	case I915_EXEC_VEBOX:
240320131375Smrg		if (!bufmgr_gem->has_vebox)
240420131375Smrg			return -EINVAL;
240520131375Smrg		break;
24069ce4edccSmrg	case I915_EXEC_RENDER:
24079ce4edccSmrg	case I915_EXEC_DEFAULT:
24089ce4edccSmrg		break;
24099ce4edccSmrg	}
2410aaba2545Smrg
241122944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
241222944501Smrg	/* Update indices and set up the validate list. */
241322944501Smrg	drm_intel_gem_bo_process_reloc2(bo);
241422944501Smrg
241522944501Smrg	/* Add the batch buffer to the validation list.  There are no relocations
241622944501Smrg	 * pointing to it.
241722944501Smrg	 */
241822944501Smrg	drm_intel_add_validate_buffer2(bo, 0);
241922944501Smrg
2420424e9256Smrg	memclear(execbuf);
242122944501Smrg	execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec2_objects;
242222944501Smrg	execbuf.buffer_count = bufmgr_gem->exec_count;
242322944501Smrg	execbuf.batch_start_offset = 0;
242422944501Smrg	execbuf.batch_len = used;
242522944501Smrg	execbuf.cliprects_ptr = (uintptr_t)cliprects;
242622944501Smrg	execbuf.num_cliprects = num_cliprects;
242722944501Smrg	execbuf.DR1 = 0;
242822944501Smrg	execbuf.DR4 = DR4;
242920131375Smrg	execbuf.flags = flags;
243020131375Smrg	if (ctx == NULL)
243120131375Smrg		i915_execbuffer2_set_context_id(execbuf, 0);
243220131375Smrg	else
243320131375Smrg		i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
243422944501Smrg	execbuf.rsvd2 = 0;
24352ee35494Smrg	if (in_fence != -1) {
24362ee35494Smrg		execbuf.rsvd2 = in_fence;
24372ee35494Smrg		execbuf.flags |= I915_EXEC_FENCE_IN;
24382ee35494Smrg	}
24392ee35494Smrg	if (out_fence != NULL) {
24402ee35494Smrg		*out_fence = -1;
24412ee35494Smrg		execbuf.flags |= I915_EXEC_FENCE_OUT;
24422ee35494Smrg	}
244322944501Smrg
244420131375Smrg	if (bufmgr_gem->no_exec)
244520131375Smrg		goto skip_execution;
244620131375Smrg
24476d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
24482ee35494Smrg		       DRM_IOCTL_I915_GEM_EXECBUFFER2_WR,
24496d98c517Smrg		       &execbuf);
245022944501Smrg	if (ret != 0) {
245122944501Smrg		ret = -errno;
24526d98c517Smrg		if (ret == -ENOSPC) {
24539ce4edccSmrg			DBG("Execbuffer fails to pin. "
24549ce4edccSmrg			    "Estimate: %u. Actual: %u. Available: %u\n",
24559ce4edccSmrg			    drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos,
24569ce4edccSmrg							       bufmgr_gem->exec_count),
24579ce4edccSmrg			    drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos,
24589ce4edccSmrg							      bufmgr_gem->exec_count),
24599ce4edccSmrg			    (unsigned int) bufmgr_gem->gtt_size);
246022944501Smrg		}
246122944501Smrg	}
246222944501Smrg	drm_intel_update_buffer_offsets2(bufmgr_gem);
246322944501Smrg
24642ee35494Smrg	if (ret == 0 && out_fence != NULL)
24652ee35494Smrg		*out_fence = execbuf.rsvd2 >> 32;
24662ee35494Smrg
246720131375Smrgskip_execution:
246822944501Smrg	if (bufmgr_gem->bufmgr.debug)
246922944501Smrg		drm_intel_gem_dump_validation_list(bufmgr_gem);
247022944501Smrg
247122944501Smrg	for (i = 0; i < bufmgr_gem->exec_count; i++) {
2472fe517fc9Smrg		drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]);
247322944501Smrg
247420131375Smrg		bo_gem->idle = false;
247520131375Smrg
247622944501Smrg		/* Disconnect the buffer from the validate list */
247722944501Smrg		bo_gem->validate_index = -1;
247822944501Smrg		bufmgr_gem->exec_bos[i] = NULL;
247922944501Smrg	}
248022944501Smrg	bufmgr_gem->exec_count = 0;
248122944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
248222944501Smrg
248322944501Smrg	return ret;
248422944501Smrg}
248522944501Smrg
2486aaba2545Smrgstatic int
2487aaba2545Smrgdrm_intel_gem_bo_exec2(drm_intel_bo *bo, int used,
2488aaba2545Smrg		       drm_clip_rect_t *cliprects, int num_cliprects,
2489aaba2545Smrg		       int DR4)
2490aaba2545Smrg{
249120131375Smrg	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
24922ee35494Smrg			-1, NULL, I915_EXEC_RENDER);
249320131375Smrg}
249420131375Smrg
249520131375Smrgstatic int
249620131375Smrgdrm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
249720131375Smrg			drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
249820131375Smrg			unsigned int flags)
249920131375Smrg{
250020131375Smrg	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
25012ee35494Smrg			-1, NULL, flags);
250220131375Smrg}
250320131375Smrg
2504424e9256Smrgint
250520131375Smrgdrm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
250620131375Smrg			      int used, unsigned int flags)
250720131375Smrg{
25082ee35494Smrg	return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags);
25092ee35494Smrg}
25102ee35494Smrg
25112ee35494Smrgint
25122ee35494Smrgdrm_intel_gem_bo_fence_exec(drm_intel_bo *bo,
25132ee35494Smrg			    drm_intel_context *ctx,
25142ee35494Smrg			    int used,
25152ee35494Smrg			    int in_fence,
25162ee35494Smrg			    int *out_fence,
25172ee35494Smrg			    unsigned int flags)
25182ee35494Smrg{
25192ee35494Smrg	return do_exec2(bo, used, ctx, NULL, 0, 0, in_fence, out_fence, flags);
2520aaba2545Smrg}
2521aaba2545Smrg
252222944501Smrgstatic int
252322944501Smrgdrm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment)
252422944501Smrg{
252522944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
252622944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
252722944501Smrg	struct drm_i915_gem_pin pin;
252822944501Smrg	int ret;
252922944501Smrg
2530424e9256Smrg	memclear(pin);
253122944501Smrg	pin.handle = bo_gem->gem_handle;
253222944501Smrg	pin.alignment = alignment;
253322944501Smrg
25346d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
25356d98c517Smrg		       DRM_IOCTL_I915_GEM_PIN,
25366d98c517Smrg		       &pin);
253722944501Smrg	if (ret != 0)
253822944501Smrg		return -errno;
253922944501Smrg
254020131375Smrg	bo->offset64 = pin.offset;
254122944501Smrg	bo->offset = pin.offset;
254222944501Smrg	return 0;
254322944501Smrg}
254422944501Smrg
254522944501Smrgstatic int
254622944501Smrgdrm_intel_gem_bo_unpin(drm_intel_bo *bo)
254722944501Smrg{
254822944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
254922944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
255022944501Smrg	struct drm_i915_gem_unpin unpin;
255122944501Smrg	int ret;
255222944501Smrg
2553424e9256Smrg	memclear(unpin);
255422944501Smrg	unpin.handle = bo_gem->gem_handle;
255522944501Smrg
25566d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
255722944501Smrg	if (ret != 0)
255822944501Smrg		return -errno;
255922944501Smrg
256022944501Smrg	return 0;
256122944501Smrg}
256222944501Smrg
256322944501Smrgstatic int
25646d98c517Smrgdrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo,
25656d98c517Smrg				     uint32_t tiling_mode,
25666d98c517Smrg				     uint32_t stride)
256722944501Smrg{
256822944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
256922944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
257022944501Smrg	struct drm_i915_gem_set_tiling set_tiling;
257122944501Smrg	int ret;
257222944501Smrg
25736d98c517Smrg	if (bo_gem->global_name == 0 &&
25746d98c517Smrg	    tiling_mode == bo_gem->tiling_mode &&
25756d98c517Smrg	    stride == bo_gem->stride)
257622944501Smrg		return 0;
257722944501Smrg
257822944501Smrg	memset(&set_tiling, 0, sizeof(set_tiling));
257922944501Smrg	do {
25806d98c517Smrg		/* set_tiling is slightly broken and overwrites the
25816d98c517Smrg		 * input on the error path, so we have to open code
25826d98c517Smrg		 * rmIoctl.
25836d98c517Smrg		 */
25846d98c517Smrg		set_tiling.handle = bo_gem->gem_handle;
25856d98c517Smrg		set_tiling.tiling_mode = tiling_mode;
258622944501Smrg		set_tiling.stride = stride;
258722944501Smrg
258822944501Smrg		ret = ioctl(bufmgr_gem->fd,
258922944501Smrg			    DRM_IOCTL_I915_GEM_SET_TILING,
259022944501Smrg			    &set_tiling);
25916d98c517Smrg	} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
25926d98c517Smrg	if (ret == -1)
25936d98c517Smrg		return -errno;
25946d98c517Smrg
25956d98c517Smrg	bo_gem->tiling_mode = set_tiling.tiling_mode;
25966d98c517Smrg	bo_gem->swizzle_mode = set_tiling.swizzle_mode;
25976d98c517Smrg	bo_gem->stride = set_tiling.stride;
25986d98c517Smrg	return 0;
25996d98c517Smrg}
26006d98c517Smrg
26016d98c517Smrgstatic int
26026d98c517Smrgdrm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
26036d98c517Smrg			    uint32_t stride)
26046d98c517Smrg{
26056d98c517Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
26066d98c517Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
26076d98c517Smrg	int ret;
26086d98c517Smrg
2609a884aba1Smrg	/* Tiling with userptr surfaces is not supported
2610a884aba1Smrg	 * on all hardware so refuse it for time being.
2611a884aba1Smrg	 */
2612a884aba1Smrg	if (bo_gem->is_userptr)
2613a884aba1Smrg		return -EINVAL;
2614a884aba1Smrg
26156d98c517Smrg	/* Linear buffers have no stride. By ensuring that we only ever use
26166d98c517Smrg	 * stride 0 with linear buffers, we simplify our code.
26176d98c517Smrg	 */
26186d98c517Smrg	if (*tiling_mode == I915_TILING_NONE)
26196d98c517Smrg		stride = 0;
26206d98c517Smrg
26216d98c517Smrg	ret = drm_intel_gem_bo_set_tiling_internal(bo, *tiling_mode, stride);
26226d98c517Smrg	if (ret == 0)
2623fe517fc9Smrg		drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
262422944501Smrg
262522944501Smrg	*tiling_mode = bo_gem->tiling_mode;
2626aaba2545Smrg	return ret;
262722944501Smrg}
262822944501Smrg
262922944501Smrgstatic int
263022944501Smrgdrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
263122944501Smrg			    uint32_t * swizzle_mode)
263222944501Smrg{
263322944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
263422944501Smrg
263522944501Smrg	*tiling_mode = bo_gem->tiling_mode;
263622944501Smrg	*swizzle_mode = bo_gem->swizzle_mode;
263722944501Smrg	return 0;
263822944501Smrg}
263922944501Smrg
2640fe517fc9Smrgstatic int
2641fe517fc9Smrgdrm_intel_gem_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset)
2642fe517fc9Smrg{
2643fe517fc9Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2644fe517fc9Smrg
2645fe517fc9Smrg	bo_gem->is_softpin = true;
2646fe517fc9Smrg	bo->offset64 = offset;
2647fe517fc9Smrg	bo->offset = offset;
2648fe517fc9Smrg	return 0;
2649fe517fc9Smrg}
2650fe517fc9Smrg
2651424e9256Smrgdrm_intel_bo *
265220131375Smrgdrm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size)
265320131375Smrg{
265420131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
265520131375Smrg	int ret;
265620131375Smrg	uint32_t handle;
265720131375Smrg	drm_intel_bo_gem *bo_gem;
265820131375Smrg	struct drm_i915_gem_get_tiling get_tiling;
265920131375Smrg
2660fe517fc9Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
266120131375Smrg	ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle);
2662fe517fc9Smrg	if (ret) {
2663fe517fc9Smrg		DBG("create_from_prime: failed to obtain handle from fd: %s\n", strerror(errno));
2664fe517fc9Smrg		pthread_mutex_unlock(&bufmgr_gem->lock);
2665fe517fc9Smrg		return NULL;
2666fe517fc9Smrg	}
266720131375Smrg
266820131375Smrg	/*
266920131375Smrg	 * See if the kernel has already returned this buffer to us. Just as
267020131375Smrg	 * for named buffers, we must not create two bo's pointing at the same
267120131375Smrg	 * kernel object
267220131375Smrg	 */
26732ee35494Smrg	HASH_FIND(handle_hh, bufmgr_gem->handle_table,
26742ee35494Smrg		  &handle, sizeof(handle), bo_gem);
26752ee35494Smrg	if (bo_gem) {
26762ee35494Smrg		drm_intel_gem_bo_reference(&bo_gem->bo);
26772ee35494Smrg		goto out;
267820131375Smrg	}
267920131375Smrg
268020131375Smrg	bo_gem = calloc(1, sizeof(*bo_gem));
26812ee35494Smrg	if (!bo_gem)
26822ee35494Smrg		goto out;
26832ee35494Smrg
26842ee35494Smrg	atomic_set(&bo_gem->refcount, 1);
26852ee35494Smrg	DRMINITLISTHEAD(&bo_gem->vma_list);
26862ee35494Smrg
268720131375Smrg	/* Determine size of bo.  The fd-to-handle ioctl really should
268820131375Smrg	 * return the size, but it doesn't.  If we have kernel 3.12 or
268920131375Smrg	 * later, we can lseek on the prime fd to get the size.  Older
269020131375Smrg	 * kernels will just fail, in which case we fall back to the
269120131375Smrg	 * provided (estimated or guess size). */
269220131375Smrg	ret = lseek(prime_fd, 0, SEEK_END);
269320131375Smrg	if (ret != -1)
269420131375Smrg		bo_gem->bo.size = ret;
269520131375Smrg	else
269620131375Smrg		bo_gem->bo.size = size;
269720131375Smrg
269820131375Smrg	bo_gem->bo.handle = handle;
269920131375Smrg	bo_gem->bo.bufmgr = bufmgr;
270020131375Smrg
270120131375Smrg	bo_gem->gem_handle = handle;
27022ee35494Smrg	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
27032ee35494Smrg		 gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
270420131375Smrg
270520131375Smrg	bo_gem->name = "prime";
270620131375Smrg	bo_gem->validate_index = -1;
270720131375Smrg	bo_gem->reloc_tree_fences = 0;
270820131375Smrg	bo_gem->used_as_reloc_target = false;
270920131375Smrg	bo_gem->has_error = false;
271020131375Smrg	bo_gem->reusable = false;
2711fe517fc9Smrg	bo_gem->use_48b_address_range = false;
271220131375Smrg
2713424e9256Smrg	memclear(get_tiling);
271420131375Smrg	get_tiling.handle = bo_gem->gem_handle;
27152ee35494Smrg	if (drmIoctl(bufmgr_gem->fd,
27162ee35494Smrg		     DRM_IOCTL_I915_GEM_GET_TILING,
27172ee35494Smrg		     &get_tiling))
27182ee35494Smrg		goto err;
27192ee35494Smrg
272020131375Smrg	bo_gem->tiling_mode = get_tiling.tiling_mode;
272120131375Smrg	bo_gem->swizzle_mode = get_tiling.swizzle_mode;
272220131375Smrg	/* XXX stride is unknown */
2723fe517fc9Smrg	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
272420131375Smrg
27252ee35494Smrgout:
27262ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
272720131375Smrg	return &bo_gem->bo;
27282ee35494Smrg
27292ee35494Smrgerr:
27302ee35494Smrg	drm_intel_gem_bo_free(&bo_gem->bo);
27312ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
27322ee35494Smrg	return NULL;
273320131375Smrg}
273420131375Smrg
2735424e9256Smrgint
273620131375Smrgdrm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd)
273720131375Smrg{
273820131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
273920131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
274020131375Smrg
274120131375Smrg	if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle,
274220131375Smrg			       DRM_CLOEXEC, prime_fd) != 0)
274320131375Smrg		return -errno;
274420131375Smrg
274520131375Smrg	bo_gem->reusable = false;
274620131375Smrg
274720131375Smrg	return 0;
274820131375Smrg}
274920131375Smrg
275022944501Smrgstatic int
275122944501Smrgdrm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name)
275222944501Smrg{
275322944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
275422944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
275522944501Smrg
275622944501Smrg	if (!bo_gem->global_name) {
275720131375Smrg		struct drm_gem_flink flink;
275820131375Smrg
2759424e9256Smrg		memclear(flink);
276022944501Smrg		flink.handle = bo_gem->gem_handle;
27612ee35494Smrg		if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink))
27622ee35494Smrg			return -errno;
276322944501Smrg
2764a884aba1Smrg		pthread_mutex_lock(&bufmgr_gem->lock);
27652ee35494Smrg		if (!bo_gem->global_name) {
27662ee35494Smrg			bo_gem->global_name = flink.name;
27672ee35494Smrg			bo_gem->reusable = false;
2768a884aba1Smrg
27692ee35494Smrg			HASH_ADD(name_hh, bufmgr_gem->name_table,
27702ee35494Smrg				 global_name, sizeof(bo_gem->global_name),
27712ee35494Smrg				 bo_gem);
2772a884aba1Smrg		}
2773a884aba1Smrg		pthread_mutex_unlock(&bufmgr_gem->lock);
277422944501Smrg	}
277522944501Smrg
277622944501Smrg	*name = bo_gem->global_name;
277722944501Smrg	return 0;
277822944501Smrg}
277922944501Smrg
278022944501Smrg/**
278122944501Smrg * Enables unlimited caching of buffer objects for reuse.
278222944501Smrg *
278322944501Smrg * This is potentially very memory expensive, as the cache at each bucket
278422944501Smrg * size is only bounded by how many buffers of that size we've managed to have
278522944501Smrg * in flight at once.
278622944501Smrg */
2787424e9256Smrgvoid
278822944501Smrgdrm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr)
278922944501Smrg{
279022944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
279122944501Smrg
279220131375Smrg	bufmgr_gem->bo_reuse = true;
279322944501Smrg}
279422944501Smrg
27952ee35494Smrg/**
27962ee35494Smrg * Disables implicit synchronisation before executing the bo
27972ee35494Smrg *
27982ee35494Smrg * This will cause rendering corruption unless you correctly manage explicit
27992ee35494Smrg * fences for all rendering involving this buffer - including use by others.
28002ee35494Smrg * Disabling the implicit serialisation is only required if that serialisation
28012ee35494Smrg * is too coarse (for example, you have split the buffer into many
28022ee35494Smrg * non-overlapping regions and are sharing the whole buffer between concurrent
28032ee35494Smrg * independent command streams).
28042ee35494Smrg *
28052ee35494Smrg * Note the kernel must advertise support via I915_PARAM_HAS_EXEC_ASYNC,
28062ee35494Smrg * which can be checked using drm_intel_bufmgr_can_disable_implicit_sync,
28072ee35494Smrg * or subsequent execbufs involving the bo will generate EINVAL.
28082ee35494Smrg */
28092ee35494Smrgvoid
28102ee35494Smrgdrm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo)
28112ee35494Smrg{
28122ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
28132ee35494Smrg
28142ee35494Smrg	bo_gem->kflags |= EXEC_OBJECT_ASYNC;
28152ee35494Smrg}
28162ee35494Smrg
28172ee35494Smrg/**
28182ee35494Smrg * Enables implicit synchronisation before executing the bo
28192ee35494Smrg *
28202ee35494Smrg * This is the default behaviour of the kernel, to wait upon prior writes
28212ee35494Smrg * completing on the object before rendering with it, or to wait for prior
28222ee35494Smrg * reads to complete before writing into the object.
28232ee35494Smrg * drm_intel_gem_bo_disable_implicit_sync() can stop this behaviour, telling
28242ee35494Smrg * the kernel never to insert a stall before using the object. Then this
28252ee35494Smrg * function can be used to restore the implicit sync before subsequent
28262ee35494Smrg * rendering.
28272ee35494Smrg */
28282ee35494Smrgvoid
28292ee35494Smrgdrm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo)
28302ee35494Smrg{
28312ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
28322ee35494Smrg
28332ee35494Smrg	bo_gem->kflags &= ~EXEC_OBJECT_ASYNC;
28342ee35494Smrg}
28352ee35494Smrg
28362ee35494Smrg/**
28372ee35494Smrg * Query whether the kernel supports disabling of its implicit synchronisation
28382ee35494Smrg * before execbuf. See drm_intel_gem_bo_disable_implicit_sync()
28392ee35494Smrg */
28402ee35494Smrgint
28412ee35494Smrgdrm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr)
28422ee35494Smrg{
28432ee35494Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
28442ee35494Smrg
28452ee35494Smrg	return bufmgr_gem->has_exec_async;
28462ee35494Smrg}
28472ee35494Smrg
284822944501Smrg/**
284922944501Smrg * Enable use of fenced reloc type.
285022944501Smrg *
285122944501Smrg * New code should enable this to avoid unnecessary fence register
285222944501Smrg * allocation.  If this option is not enabled, all relocs will have fence
285322944501Smrg * register allocated.
285422944501Smrg */
2855424e9256Smrgvoid
285622944501Smrgdrm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr)
285722944501Smrg{
285822944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
285922944501Smrg
286022944501Smrg	if (bufmgr_gem->bufmgr.bo_exec == drm_intel_gem_bo_exec2)
286120131375Smrg		bufmgr_gem->fenced_relocs = true;
286222944501Smrg}
286322944501Smrg
286422944501Smrg/**
286522944501Smrg * Return the additional aperture space required by the tree of buffer objects
286622944501Smrg * rooted at bo.
286722944501Smrg */
286822944501Smrgstatic int
286922944501Smrgdrm_intel_gem_bo_get_aperture_space(drm_intel_bo *bo)
287022944501Smrg{
287122944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
287222944501Smrg	int i;
287322944501Smrg	int total = 0;
287422944501Smrg
287522944501Smrg	if (bo == NULL || bo_gem->included_in_check_aperture)
287622944501Smrg		return 0;
287722944501Smrg
287822944501Smrg	total += bo->size;
287920131375Smrg	bo_gem->included_in_check_aperture = true;
288022944501Smrg
288122944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++)
288222944501Smrg		total +=
288322944501Smrg		    drm_intel_gem_bo_get_aperture_space(bo_gem->
288422944501Smrg							reloc_target_info[i].bo);
288522944501Smrg
288622944501Smrg	return total;
288722944501Smrg}
288822944501Smrg
288922944501Smrg/**
289022944501Smrg * Count the number of buffers in this list that need a fence reg
289122944501Smrg *
289222944501Smrg * If the count is greater than the number of available regs, we'll have
289322944501Smrg * to ask the caller to resubmit a batch with fewer tiled buffers.
289422944501Smrg *
289522944501Smrg * This function over-counts if the same buffer is used multiple times.
289622944501Smrg */
289722944501Smrgstatic unsigned int
289822944501Smrgdrm_intel_gem_total_fences(drm_intel_bo ** bo_array, int count)
289922944501Smrg{
290022944501Smrg	int i;
290122944501Smrg	unsigned int total = 0;
290222944501Smrg
290322944501Smrg	for (i = 0; i < count; i++) {
290422944501Smrg		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i];
290522944501Smrg
290622944501Smrg		if (bo_gem == NULL)
290722944501Smrg			continue;
290822944501Smrg
290922944501Smrg		total += bo_gem->reloc_tree_fences;
291022944501Smrg	}
291122944501Smrg	return total;
291222944501Smrg}
291322944501Smrg
291422944501Smrg/**
291522944501Smrg * Clear the flag set by drm_intel_gem_bo_get_aperture_space() so we're ready
291622944501Smrg * for the next drm_intel_bufmgr_check_aperture_space() call.
291722944501Smrg */
291822944501Smrgstatic void
291922944501Smrgdrm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo)
292022944501Smrg{
292122944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
292222944501Smrg	int i;
292322944501Smrg
292422944501Smrg	if (bo == NULL || !bo_gem->included_in_check_aperture)
292522944501Smrg		return;
292622944501Smrg
292720131375Smrg	bo_gem->included_in_check_aperture = false;
292822944501Smrg
292922944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++)
293022944501Smrg		drm_intel_gem_bo_clear_aperture_space_flag(bo_gem->
293122944501Smrg							   reloc_target_info[i].bo);
293222944501Smrg}
293322944501Smrg
293422944501Smrg/**
293522944501Smrg * Return a conservative estimate for the amount of aperture required
293622944501Smrg * for a collection of buffers. This may double-count some buffers.
293722944501Smrg */
293822944501Smrgstatic unsigned int
293922944501Smrgdrm_intel_gem_estimate_batch_space(drm_intel_bo **bo_array, int count)
294022944501Smrg{
294122944501Smrg	int i;
294222944501Smrg	unsigned int total = 0;
294322944501Smrg
294422944501Smrg	for (i = 0; i < count; i++) {
294522944501Smrg		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i];
294622944501Smrg		if (bo_gem != NULL)
294722944501Smrg			total += bo_gem->reloc_tree_size;
294822944501Smrg	}
294922944501Smrg	return total;
295022944501Smrg}
295122944501Smrg
295222944501Smrg/**
295322944501Smrg * Return the amount of aperture needed for a collection of buffers.
295422944501Smrg * This avoids double counting any buffers, at the cost of looking
295522944501Smrg * at every buffer in the set.
295622944501Smrg */
295722944501Smrgstatic unsigned int
295822944501Smrgdrm_intel_gem_compute_batch_space(drm_intel_bo **bo_array, int count)
295922944501Smrg{
296022944501Smrg	int i;
296122944501Smrg	unsigned int total = 0;
296222944501Smrg
296322944501Smrg	for (i = 0; i < count; i++) {
296422944501Smrg		total += drm_intel_gem_bo_get_aperture_space(bo_array[i]);
296522944501Smrg		/* For the first buffer object in the array, we get an
296622944501Smrg		 * accurate count back for its reloc_tree size (since nothing
296722944501Smrg		 * had been flagged as being counted yet).  We can save that
296822944501Smrg		 * value out as a more conservative reloc_tree_size that
296922944501Smrg		 * avoids double-counting target buffers.  Since the first
297022944501Smrg		 * buffer happens to usually be the batch buffer in our
297122944501Smrg		 * callers, this can pull us back from doing the tree
297222944501Smrg		 * walk on every new batch emit.
297322944501Smrg		 */
297422944501Smrg		if (i == 0) {
297522944501Smrg			drm_intel_bo_gem *bo_gem =
297622944501Smrg			    (drm_intel_bo_gem *) bo_array[i];
297722944501Smrg			bo_gem->reloc_tree_size = total;
297822944501Smrg		}
297922944501Smrg	}
298022944501Smrg
298122944501Smrg	for (i = 0; i < count; i++)
298222944501Smrg		drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]);
298322944501Smrg	return total;
298422944501Smrg}
298522944501Smrg
298622944501Smrg/**
298722944501Smrg * Return -1 if the batchbuffer should be flushed before attempting to
298822944501Smrg * emit rendering referencing the buffers pointed to by bo_array.
298922944501Smrg *
299022944501Smrg * This is required because if we try to emit a batchbuffer with relocations
299122944501Smrg * to a tree of buffers that won't simultaneously fit in the aperture,
299222944501Smrg * the rendering will return an error at a point where the software is not
299322944501Smrg * prepared to recover from it.
299422944501Smrg *
299522944501Smrg * However, we also want to emit the batchbuffer significantly before we reach
299622944501Smrg * the limit, as a series of batchbuffers each of which references buffers
299722944501Smrg * covering almost all of the aperture means that at each emit we end up
299822944501Smrg * waiting to evict a buffer from the last rendering, and we get synchronous
299922944501Smrg * performance.  By emitting smaller batchbuffers, we eat some CPU overhead to
300022944501Smrg * get better parallelism.
300122944501Smrg */
300222944501Smrgstatic int
300322944501Smrgdrm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count)
300422944501Smrg{
300522944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem =
300622944501Smrg	    (drm_intel_bufmgr_gem *) bo_array[0]->bufmgr;
300722944501Smrg	unsigned int total = 0;
300822944501Smrg	unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4;
300922944501Smrg	int total_fences;
301022944501Smrg
301122944501Smrg	/* Check for fence reg constraints if necessary */
301222944501Smrg	if (bufmgr_gem->available_fences) {
301322944501Smrg		total_fences = drm_intel_gem_total_fences(bo_array, count);
301422944501Smrg		if (total_fences > bufmgr_gem->available_fences)
301522944501Smrg			return -ENOSPC;
301622944501Smrg	}
301722944501Smrg
301822944501Smrg	total = drm_intel_gem_estimate_batch_space(bo_array, count);
301922944501Smrg
302022944501Smrg	if (total > threshold)
302122944501Smrg		total = drm_intel_gem_compute_batch_space(bo_array, count);
302222944501Smrg
302322944501Smrg	if (total > threshold) {
302422944501Smrg		DBG("check_space: overflowed available aperture, "
302522944501Smrg		    "%dkb vs %dkb\n",
302622944501Smrg		    total / 1024, (int)bufmgr_gem->gtt_size / 1024);
302722944501Smrg		return -ENOSPC;
302822944501Smrg	} else {
302922944501Smrg		DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024,
303022944501Smrg		    (int)bufmgr_gem->gtt_size / 1024);
303122944501Smrg		return 0;
303222944501Smrg	}
303322944501Smrg}
303422944501Smrg
303522944501Smrg/*
303622944501Smrg * Disable buffer reuse for objects which are shared with the kernel
303722944501Smrg * as scanout buffers
303822944501Smrg */
303922944501Smrgstatic int
304022944501Smrgdrm_intel_gem_bo_disable_reuse(drm_intel_bo *bo)
304122944501Smrg{
304222944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
304322944501Smrg
304420131375Smrg	bo_gem->reusable = false;
304522944501Smrg	return 0;
304622944501Smrg}
304722944501Smrg
3048aaba2545Smrgstatic int
3049aaba2545Smrgdrm_intel_gem_bo_is_reusable(drm_intel_bo *bo)
3050aaba2545Smrg{
3051aaba2545Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
3052aaba2545Smrg
3053aaba2545Smrg	return bo_gem->reusable;
3054aaba2545Smrg}
3055aaba2545Smrg
305622944501Smrgstatic int
305722944501Smrg_drm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo)
305822944501Smrg{
305922944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
306022944501Smrg	int i;
306122944501Smrg
306222944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++) {
306322944501Smrg		if (bo_gem->reloc_target_info[i].bo == target_bo)
306422944501Smrg			return 1;
3065aaba2545Smrg		if (bo == bo_gem->reloc_target_info[i].bo)
3066aaba2545Smrg			continue;
306722944501Smrg		if (_drm_intel_gem_bo_references(bo_gem->reloc_target_info[i].bo,
306822944501Smrg						target_bo))
306922944501Smrg			return 1;
307022944501Smrg	}
307122944501Smrg
3072fe517fc9Smrg	for (i = 0; i< bo_gem->softpin_target_count; i++) {
3073fe517fc9Smrg		if (bo_gem->softpin_target[i] == target_bo)
3074fe517fc9Smrg			return 1;
3075fe517fc9Smrg		if (_drm_intel_gem_bo_references(bo_gem->softpin_target[i], target_bo))
3076fe517fc9Smrg			return 1;
3077fe517fc9Smrg	}
3078fe517fc9Smrg
307922944501Smrg	return 0;
308022944501Smrg}
308122944501Smrg
308222944501Smrg/** Return true if target_bo is referenced by bo's relocation tree. */
308322944501Smrgstatic int
308422944501Smrgdrm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo)
308522944501Smrg{
308622944501Smrg	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
308722944501Smrg
308822944501Smrg	if (bo == NULL || target_bo == NULL)
308922944501Smrg		return 0;
309022944501Smrg	if (target_bo_gem->used_as_reloc_target)
309122944501Smrg		return _drm_intel_gem_bo_references(bo, target_bo);
309222944501Smrg	return 0;
309322944501Smrg}
309422944501Smrg
3095aaba2545Smrgstatic void
3096aaba2545Smrgadd_bucket(drm_intel_bufmgr_gem *bufmgr_gem, int size)
3097aaba2545Smrg{
3098aaba2545Smrg	unsigned int i = bufmgr_gem->num_buckets;
3099aaba2545Smrg
3100aaba2545Smrg	assert(i < ARRAY_SIZE(bufmgr_gem->cache_bucket));
3101aaba2545Smrg
3102aaba2545Smrg	DRMINITLISTHEAD(&bufmgr_gem->cache_bucket[i].head);
3103aaba2545Smrg	bufmgr_gem->cache_bucket[i].size = size;
3104aaba2545Smrg	bufmgr_gem->num_buckets++;
3105aaba2545Smrg}
3106aaba2545Smrg
3107aaba2545Smrgstatic void
3108aaba2545Smrginit_cache_buckets(drm_intel_bufmgr_gem *bufmgr_gem)
3109aaba2545Smrg{
3110aaba2545Smrg	unsigned long size, cache_max_size = 64 * 1024 * 1024;
3111aaba2545Smrg
3112aaba2545Smrg	/* OK, so power of two buckets was too wasteful of memory.
3113aaba2545Smrg	 * Give 3 other sizes between each power of two, to hopefully
3114aaba2545Smrg	 * cover things accurately enough.  (The alternative is
3115aaba2545Smrg	 * probably to just go for exact matching of sizes, and assume
3116aaba2545Smrg	 * that for things like composited window resize the tiled
3117aaba2545Smrg	 * width/height alignment and rounding of sizes to pages will
3118aaba2545Smrg	 * get us useful cache hit rates anyway)
3119aaba2545Smrg	 */
3120aaba2545Smrg	add_bucket(bufmgr_gem, 4096);
3121aaba2545Smrg	add_bucket(bufmgr_gem, 4096 * 2);
3122aaba2545Smrg	add_bucket(bufmgr_gem, 4096 * 3);
3123aaba2545Smrg
3124aaba2545Smrg	/* Initialize the linked lists for BO reuse cache. */
3125aaba2545Smrg	for (size = 4 * 4096; size <= cache_max_size; size *= 2) {
3126aaba2545Smrg		add_bucket(bufmgr_gem, size);
3127aaba2545Smrg
3128aaba2545Smrg		add_bucket(bufmgr_gem, size + size * 1 / 4);
3129aaba2545Smrg		add_bucket(bufmgr_gem, size + size * 2 / 4);
3130aaba2545Smrg		add_bucket(bufmgr_gem, size + size * 3 / 4);
3131aaba2545Smrg	}
3132aaba2545Smrg}
3133aaba2545Smrg
3134424e9256Smrgvoid
313520131375Smrgdrm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit)
313620131375Smrg{
313720131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
313820131375Smrg
313920131375Smrg	bufmgr_gem->vma_max = limit;
314020131375Smrg
314120131375Smrg	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
314220131375Smrg}
314320131375Smrg
31442ee35494Smrgstatic int
31452ee35494Smrgparse_devid_override(const char *devid_override)
31462ee35494Smrg{
31472ee35494Smrg	static const struct {
31482ee35494Smrg		const char *name;
31492ee35494Smrg		int pci_id;
31502ee35494Smrg	} name_map[] = {
31512ee35494Smrg		{ "brw", PCI_CHIP_I965_GM },
31522ee35494Smrg		{ "g4x", PCI_CHIP_GM45_GM },
31532ee35494Smrg		{ "ilk", PCI_CHIP_ILD_G },
31542ee35494Smrg		{ "snb", PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS },
31552ee35494Smrg		{ "ivb", PCI_CHIP_IVYBRIDGE_S_GT2 },
31562ee35494Smrg		{ "hsw", PCI_CHIP_HASWELL_CRW_E_GT3 },
31572ee35494Smrg		{ "byt", PCI_CHIP_VALLEYVIEW_3 },
31582ee35494Smrg		{ "bdw", 0x1620 | BDW_ULX },
31592ee35494Smrg		{ "skl", PCI_CHIP_SKYLAKE_DT_GT2 },
31602ee35494Smrg		{ "kbl", PCI_CHIP_KABYLAKE_DT_GT2 },
31612ee35494Smrg	};
31622ee35494Smrg	unsigned int i;
31632ee35494Smrg
31642ee35494Smrg	for (i = 0; i < ARRAY_SIZE(name_map); i++) {
31652ee35494Smrg		if (!strcmp(name_map[i].name, devid_override))
31662ee35494Smrg			return name_map[i].pci_id;
31672ee35494Smrg	}
31682ee35494Smrg
31692ee35494Smrg	return strtod(devid_override, NULL);
31702ee35494Smrg}
31712ee35494Smrg
317220131375Smrg/**
317320131375Smrg * Get the PCI ID for the device.  This can be overridden by setting the
317420131375Smrg * INTEL_DEVID_OVERRIDE environment variable to the desired ID.
317520131375Smrg */
317620131375Smrgstatic int
317720131375Smrgget_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem)
317820131375Smrg{
317920131375Smrg	char *devid_override;
3180424e9256Smrg	int devid = 0;
318120131375Smrg	int ret;
318220131375Smrg	drm_i915_getparam_t gp;
318320131375Smrg
318420131375Smrg	if (geteuid() == getuid()) {
318520131375Smrg		devid_override = getenv("INTEL_DEVID_OVERRIDE");
318620131375Smrg		if (devid_override) {
318720131375Smrg			bufmgr_gem->no_exec = true;
31882ee35494Smrg			return parse_devid_override(devid_override);
318920131375Smrg		}
319020131375Smrg	}
319120131375Smrg
3192424e9256Smrg	memclear(gp);
319320131375Smrg	gp.param = I915_PARAM_CHIPSET_ID;
319420131375Smrg	gp.value = &devid;
319520131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
319620131375Smrg	if (ret) {
319720131375Smrg		fprintf(stderr, "get chip id failed: %d [%d]\n", ret, errno);
319820131375Smrg		fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value);
319920131375Smrg	}
320020131375Smrg	return devid;
320120131375Smrg}
320220131375Smrg
3203424e9256Smrgint
320420131375Smrgdrm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr)
320520131375Smrg{
320620131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
320720131375Smrg
320820131375Smrg	return bufmgr_gem->pci_device;
320920131375Smrg}
321020131375Smrg
321120131375Smrg/**
321220131375Smrg * Sets the AUB filename.
321320131375Smrg *
321420131375Smrg * This function has to be called before drm_intel_bufmgr_gem_set_aub_dump()
321520131375Smrg * for it to have any effect.
321620131375Smrg */
3217424e9256Smrgvoid
321820131375Smrgdrm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr,
321920131375Smrg				      const char *filename)
322020131375Smrg{
322120131375Smrg}
322220131375Smrg
322320131375Smrg/**
322420131375Smrg * Sets up AUB dumping.
322520131375Smrg *
322620131375Smrg * This is a trace file format that can be used with the simulator.
322720131375Smrg * Packets are emitted in a format somewhat like GPU command packets.
322820131375Smrg * You can set up a GTT and upload your objects into the referenced
322920131375Smrg * space, then send off batchbuffers and get BMPs out the other end.
323020131375Smrg */
3231424e9256Smrgvoid
323220131375Smrgdrm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable)
323320131375Smrg{
3234fe517fc9Smrg	fprintf(stderr, "libdrm aub dumping is deprecated.\n\n"
3235fe517fc9Smrg		"Use intel_aubdump from intel-gpu-tools instead.  Install intel-gpu-tools,\n"
3236fe517fc9Smrg		"then run (for example)\n\n"
3237fe517fc9Smrg		"\t$ intel_aubdump --output=trace.aub glxgears -geometry 500x500\n\n"
3238fe517fc9Smrg		"See the intel_aubdump man page for more details.\n");
323920131375Smrg}
324020131375Smrg
3241424e9256Smrgdrm_intel_context *
324220131375Smrgdrm_intel_gem_context_create(drm_intel_bufmgr *bufmgr)
324320131375Smrg{
324420131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
324520131375Smrg	struct drm_i915_gem_context_create create;
324620131375Smrg	drm_intel_context *context = NULL;
324720131375Smrg	int ret;
324820131375Smrg
324920131375Smrg	context = calloc(1, sizeof(*context));
325020131375Smrg	if (!context)
325120131375Smrg		return NULL;
325220131375Smrg
3253424e9256Smrg	memclear(create);
325420131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
325520131375Smrg	if (ret != 0) {
325620131375Smrg		DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n",
325720131375Smrg		    strerror(errno));
325820131375Smrg		free(context);
325920131375Smrg		return NULL;
326020131375Smrg	}
326120131375Smrg
326220131375Smrg	context->ctx_id = create.ctx_id;
326320131375Smrg	context->bufmgr = bufmgr;
326420131375Smrg
326520131375Smrg	return context;
326620131375Smrg}
326720131375Smrg
32682ee35494Smrgint
32692ee35494Smrgdrm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id)
32702ee35494Smrg{
32712ee35494Smrg	if (ctx == NULL)
32722ee35494Smrg		return -EINVAL;
32732ee35494Smrg
32742ee35494Smrg	*ctx_id = ctx->ctx_id;
32752ee35494Smrg
32762ee35494Smrg	return 0;
32772ee35494Smrg}
32782ee35494Smrg
3279424e9256Smrgvoid
328020131375Smrgdrm_intel_gem_context_destroy(drm_intel_context *ctx)
328120131375Smrg{
328220131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
328320131375Smrg	struct drm_i915_gem_context_destroy destroy;
328420131375Smrg	int ret;
328520131375Smrg
328620131375Smrg	if (ctx == NULL)
328720131375Smrg		return;
328820131375Smrg
3289424e9256Smrg	memclear(destroy);
329020131375Smrg
329120131375Smrg	bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
329220131375Smrg	destroy.ctx_id = ctx->ctx_id;
329320131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY,
329420131375Smrg		       &destroy);
329520131375Smrg	if (ret != 0)
329620131375Smrg		fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n",
329720131375Smrg			strerror(errno));
329820131375Smrg
329920131375Smrg	free(ctx);
330020131375Smrg}
330120131375Smrg
3302424e9256Smrgint
330320131375Smrgdrm_intel_get_reset_stats(drm_intel_context *ctx,
330420131375Smrg			  uint32_t *reset_count,
330520131375Smrg			  uint32_t *active,
330620131375Smrg			  uint32_t *pending)
330720131375Smrg{
330820131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
330920131375Smrg	struct drm_i915_reset_stats stats;
331020131375Smrg	int ret;
331120131375Smrg
331220131375Smrg	if (ctx == NULL)
331320131375Smrg		return -EINVAL;
331420131375Smrg
3315424e9256Smrg	memclear(stats);
331620131375Smrg
331720131375Smrg	bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
331820131375Smrg	stats.ctx_id = ctx->ctx_id;
331920131375Smrg	ret = drmIoctl(bufmgr_gem->fd,
332020131375Smrg		       DRM_IOCTL_I915_GET_RESET_STATS,
332120131375Smrg		       &stats);
332220131375Smrg	if (ret == 0) {
332320131375Smrg		if (reset_count != NULL)
332420131375Smrg			*reset_count = stats.reset_count;
332520131375Smrg
332620131375Smrg		if (active != NULL)
332720131375Smrg			*active = stats.batch_active;
332820131375Smrg
332920131375Smrg		if (pending != NULL)
333020131375Smrg			*pending = stats.batch_pending;
333120131375Smrg	}
333220131375Smrg
333320131375Smrg	return ret;
333420131375Smrg}
333520131375Smrg
3336424e9256Smrgint
333720131375Smrgdrm_intel_reg_read(drm_intel_bufmgr *bufmgr,
333820131375Smrg		   uint32_t offset,
333920131375Smrg		   uint64_t *result)
334020131375Smrg{
334120131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
334220131375Smrg	struct drm_i915_reg_read reg_read;
334320131375Smrg	int ret;
334420131375Smrg
3345424e9256Smrg	memclear(reg_read);
334620131375Smrg	reg_read.offset = offset;
334720131375Smrg
334820131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, &reg_read);
334920131375Smrg
335020131375Smrg	*result = reg_read.val;
335120131375Smrg	return ret;
335220131375Smrg}
335320131375Smrg
3354424e9256Smrgint
3355424e9256Smrgdrm_intel_get_subslice_total(int fd, unsigned int *subslice_total)
3356424e9256Smrg{
3357424e9256Smrg	drm_i915_getparam_t gp;
3358424e9256Smrg	int ret;
3359424e9256Smrg
3360424e9256Smrg	memclear(gp);
3361424e9256Smrg	gp.value = (int*)subslice_total;
3362424e9256Smrg	gp.param = I915_PARAM_SUBSLICE_TOTAL;
3363424e9256Smrg	ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
3364424e9256Smrg	if (ret)
3365424e9256Smrg		return -errno;
3366424e9256Smrg
3367424e9256Smrg	return 0;
3368424e9256Smrg}
3369424e9256Smrg
3370424e9256Smrgint
3371424e9256Smrgdrm_intel_get_eu_total(int fd, unsigned int *eu_total)
3372424e9256Smrg{
3373424e9256Smrg	drm_i915_getparam_t gp;
3374424e9256Smrg	int ret;
3375424e9256Smrg
3376424e9256Smrg	memclear(gp);
3377424e9256Smrg	gp.value = (int*)eu_total;
3378424e9256Smrg	gp.param = I915_PARAM_EU_TOTAL;
3379424e9256Smrg	ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
3380424e9256Smrg	if (ret)
3381424e9256Smrg		return -errno;
3382424e9256Smrg
3383424e9256Smrg	return 0;
3384424e9256Smrg}
338520131375Smrg
33862ee35494Smrgint
33872ee35494Smrgdrm_intel_get_pooled_eu(int fd)
33882ee35494Smrg{
33892ee35494Smrg	drm_i915_getparam_t gp;
33902ee35494Smrg	int ret = -1;
33912ee35494Smrg
33922ee35494Smrg	memclear(gp);
33932ee35494Smrg	gp.param = I915_PARAM_HAS_POOLED_EU;
33942ee35494Smrg	gp.value = &ret;
33952ee35494Smrg	if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
33962ee35494Smrg		return -errno;
33972ee35494Smrg
33982ee35494Smrg	return ret;
33992ee35494Smrg}
34002ee35494Smrg
34012ee35494Smrgint
34022ee35494Smrgdrm_intel_get_min_eu_in_pool(int fd)
34032ee35494Smrg{
34042ee35494Smrg	drm_i915_getparam_t gp;
34052ee35494Smrg	int ret = -1;
34062ee35494Smrg
34072ee35494Smrg	memclear(gp);
34082ee35494Smrg	gp.param = I915_PARAM_MIN_EU_IN_POOL;
34092ee35494Smrg	gp.value = &ret;
34102ee35494Smrg	if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
34112ee35494Smrg		return -errno;
34122ee35494Smrg
34132ee35494Smrg	return ret;
34142ee35494Smrg}
34152ee35494Smrg
341620131375Smrg/**
341720131375Smrg * Annotate the given bo for use in aub dumping.
341820131375Smrg *
341920131375Smrg * \param annotations is an array of drm_intel_aub_annotation objects
342020131375Smrg * describing the type of data in various sections of the bo.  Each
342120131375Smrg * element of the array specifies the type and subtype of a section of
342220131375Smrg * the bo, and the past-the-end offset of that section.  The elements
342320131375Smrg * of \c annotations must be sorted so that ending_offset is
342420131375Smrg * increasing.
342520131375Smrg *
342620131375Smrg * \param count is the number of elements in the \c annotations array.
342720131375Smrg * If \c count is zero, then \c annotations will not be dereferenced.
342820131375Smrg *
342920131375Smrg * Annotations are copied into a private data structure, so caller may
343020131375Smrg * re-use the memory pointed to by \c annotations after the call
343120131375Smrg * returns.
343220131375Smrg *
343320131375Smrg * Annotations are stored for the lifetime of the bo; to reset to the
343420131375Smrg * default state (no annotations), call this function with a \c count
343520131375Smrg * of zero.
343620131375Smrg */
3437424e9256Smrgvoid
343820131375Smrgdrm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
343920131375Smrg					 drm_intel_aub_annotation *annotations,
344020131375Smrg					 unsigned count)
344120131375Smrg{
344220131375Smrg}
344320131375Smrg
3444a884aba1Smrgstatic pthread_mutex_t bufmgr_list_mutex = PTHREAD_MUTEX_INITIALIZER;
3445a884aba1Smrgstatic drmMMListHead bufmgr_list = { &bufmgr_list, &bufmgr_list };
3446a884aba1Smrg
3447a884aba1Smrgstatic drm_intel_bufmgr_gem *
3448a884aba1Smrgdrm_intel_bufmgr_gem_find(int fd)
3449a884aba1Smrg{
3450a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
3451a884aba1Smrg
3452a884aba1Smrg	DRMLISTFOREACHENTRY(bufmgr_gem, &bufmgr_list, managers) {
3453a884aba1Smrg		if (bufmgr_gem->fd == fd) {
3454a884aba1Smrg			atomic_inc(&bufmgr_gem->refcount);
3455a884aba1Smrg			return bufmgr_gem;
3456a884aba1Smrg		}
3457a884aba1Smrg	}
3458a884aba1Smrg
3459a884aba1Smrg	return NULL;
3460a884aba1Smrg}
3461a884aba1Smrg
3462a884aba1Smrgstatic void
3463a884aba1Smrgdrm_intel_bufmgr_gem_unref(drm_intel_bufmgr *bufmgr)
3464a884aba1Smrg{
3465a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
3466a884aba1Smrg
3467a884aba1Smrg	if (atomic_add_unless(&bufmgr_gem->refcount, -1, 1)) {
3468a884aba1Smrg		pthread_mutex_lock(&bufmgr_list_mutex);
3469a884aba1Smrg
3470a884aba1Smrg		if (atomic_dec_and_test(&bufmgr_gem->refcount)) {
3471a884aba1Smrg			DRMLISTDEL(&bufmgr_gem->managers);
3472a884aba1Smrg			drm_intel_bufmgr_gem_destroy(bufmgr);
3473a884aba1Smrg		}
3474a884aba1Smrg
3475a884aba1Smrg		pthread_mutex_unlock(&bufmgr_list_mutex);
3476a884aba1Smrg	}
3477a884aba1Smrg}
3478a884aba1Smrg
34792ee35494Smrgvoid *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo)
34802ee35494Smrg{
34812ee35494Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
34822ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
34832ee35494Smrg
34842ee35494Smrg	if (bo_gem->gtt_virtual)
34852ee35494Smrg		return bo_gem->gtt_virtual;
34862ee35494Smrg
34872ee35494Smrg	if (bo_gem->is_userptr)
34882ee35494Smrg		return NULL;
34892ee35494Smrg
34902ee35494Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
34912ee35494Smrg	if (bo_gem->gtt_virtual == NULL) {
34922ee35494Smrg		struct drm_i915_gem_mmap_gtt mmap_arg;
34932ee35494Smrg		void *ptr;
34942ee35494Smrg
34952ee35494Smrg		DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
34962ee35494Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
34972ee35494Smrg
34982ee35494Smrg		if (bo_gem->map_count++ == 0)
34992ee35494Smrg			drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
35002ee35494Smrg
35012ee35494Smrg		memclear(mmap_arg);
35022ee35494Smrg		mmap_arg.handle = bo_gem->gem_handle;
35032ee35494Smrg
35042ee35494Smrg		/* Get the fake offset back... */
35052ee35494Smrg		ptr = MAP_FAILED;
35062ee35494Smrg		if (drmIoctl(bufmgr_gem->fd,
35072ee35494Smrg			     DRM_IOCTL_I915_GEM_MMAP_GTT,
35082ee35494Smrg			     &mmap_arg) == 0) {
35092ee35494Smrg			/* and mmap it */
35102ee35494Smrg			ptr = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE,
35112ee35494Smrg				       MAP_SHARED, bufmgr_gem->fd,
35122ee35494Smrg				       mmap_arg.offset);
35132ee35494Smrg		}
35142ee35494Smrg		if (ptr == MAP_FAILED) {
35152ee35494Smrg			if (--bo_gem->map_count == 0)
35162ee35494Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
35172ee35494Smrg			ptr = NULL;
35182ee35494Smrg		}
35192ee35494Smrg
35202ee35494Smrg		bo_gem->gtt_virtual = ptr;
35212ee35494Smrg	}
35222ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
35232ee35494Smrg
35242ee35494Smrg	return bo_gem->gtt_virtual;
35252ee35494Smrg}
35262ee35494Smrg
35272ee35494Smrgvoid *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo)
35282ee35494Smrg{
35292ee35494Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
35302ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
35312ee35494Smrg
35322ee35494Smrg	if (bo_gem->mem_virtual)
35332ee35494Smrg		return bo_gem->mem_virtual;
35342ee35494Smrg
35352ee35494Smrg	if (bo_gem->is_userptr) {
35362ee35494Smrg		/* Return the same user ptr */
35372ee35494Smrg		return bo_gem->user_virtual;
35382ee35494Smrg	}
35392ee35494Smrg
35402ee35494Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
35412ee35494Smrg	if (!bo_gem->mem_virtual) {
35422ee35494Smrg		struct drm_i915_gem_mmap mmap_arg;
35432ee35494Smrg
35442ee35494Smrg		if (bo_gem->map_count++ == 0)
35452ee35494Smrg			drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
35462ee35494Smrg
35472ee35494Smrg		DBG("bo_map: %d (%s), map_count=%d\n",
35482ee35494Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
35492ee35494Smrg
35502ee35494Smrg		memclear(mmap_arg);
35512ee35494Smrg		mmap_arg.handle = bo_gem->gem_handle;
35522ee35494Smrg		mmap_arg.size = bo->size;
35532ee35494Smrg		if (drmIoctl(bufmgr_gem->fd,
35542ee35494Smrg			     DRM_IOCTL_I915_GEM_MMAP,
35552ee35494Smrg			     &mmap_arg)) {
35562ee35494Smrg			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
35572ee35494Smrg			    __FILE__, __LINE__, bo_gem->gem_handle,
35582ee35494Smrg			    bo_gem->name, strerror(errno));
35592ee35494Smrg			if (--bo_gem->map_count == 0)
35602ee35494Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
35612ee35494Smrg		} else {
35622ee35494Smrg			VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
35632ee35494Smrg			bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
35642ee35494Smrg		}
35652ee35494Smrg	}
35662ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
35672ee35494Smrg
35682ee35494Smrg	return bo_gem->mem_virtual;
35692ee35494Smrg}
35702ee35494Smrg
35712ee35494Smrgvoid *drm_intel_gem_bo_map__wc(drm_intel_bo *bo)
35722ee35494Smrg{
35732ee35494Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
35742ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
35752ee35494Smrg
35762ee35494Smrg	if (bo_gem->wc_virtual)
35772ee35494Smrg		return bo_gem->wc_virtual;
35782ee35494Smrg
35792ee35494Smrg	if (bo_gem->is_userptr)
35802ee35494Smrg		return NULL;
35812ee35494Smrg
35822ee35494Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
35832ee35494Smrg	if (!bo_gem->wc_virtual) {
35842ee35494Smrg		struct drm_i915_gem_mmap mmap_arg;
35852ee35494Smrg
35862ee35494Smrg		if (bo_gem->map_count++ == 0)
35872ee35494Smrg			drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
35882ee35494Smrg
35892ee35494Smrg		DBG("bo_map: %d (%s), map_count=%d\n",
35902ee35494Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
35912ee35494Smrg
35922ee35494Smrg		memclear(mmap_arg);
35932ee35494Smrg		mmap_arg.handle = bo_gem->gem_handle;
35942ee35494Smrg		mmap_arg.size = bo->size;
35952ee35494Smrg		mmap_arg.flags = I915_MMAP_WC;
35962ee35494Smrg		if (drmIoctl(bufmgr_gem->fd,
35972ee35494Smrg			     DRM_IOCTL_I915_GEM_MMAP,
35982ee35494Smrg			     &mmap_arg)) {
35992ee35494Smrg			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
36002ee35494Smrg			    __FILE__, __LINE__, bo_gem->gem_handle,
36012ee35494Smrg			    bo_gem->name, strerror(errno));
36022ee35494Smrg			if (--bo_gem->map_count == 0)
36032ee35494Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
36042ee35494Smrg		} else {
36052ee35494Smrg			VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
36062ee35494Smrg			bo_gem->wc_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
36072ee35494Smrg		}
36082ee35494Smrg	}
36092ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
36102ee35494Smrg
36112ee35494Smrg	return bo_gem->wc_virtual;
36122ee35494Smrg}
36132ee35494Smrg
361422944501Smrg/**
361522944501Smrg * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
361622944501Smrg * and manage map buffer objections.
361722944501Smrg *
361822944501Smrg * \param fd File descriptor of the opened DRM device.
361922944501Smrg */
3620424e9256Smrgdrm_intel_bufmgr *
362122944501Smrgdrm_intel_bufmgr_gem_init(int fd, int batch_size)
362222944501Smrg{
362322944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
362422944501Smrg	struct drm_i915_gem_get_aperture aperture;
362522944501Smrg	drm_i915_getparam_t gp;
362620131375Smrg	int ret, tmp;
362720131375Smrg	bool exec2 = false;
362822944501Smrg
3629a884aba1Smrg	pthread_mutex_lock(&bufmgr_list_mutex);
3630a884aba1Smrg
3631a884aba1Smrg	bufmgr_gem = drm_intel_bufmgr_gem_find(fd);
3632a884aba1Smrg	if (bufmgr_gem)
3633a884aba1Smrg		goto exit;
3634a884aba1Smrg
363522944501Smrg	bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
363622944501Smrg	if (bufmgr_gem == NULL)
3637a884aba1Smrg		goto exit;
363822944501Smrg
363922944501Smrg	bufmgr_gem->fd = fd;
3640a884aba1Smrg	atomic_set(&bufmgr_gem->refcount, 1);
364122944501Smrg
364222944501Smrg	if (pthread_mutex_init(&bufmgr_gem->lock, NULL) != 0) {
364322944501Smrg		free(bufmgr_gem);
3644a884aba1Smrg		bufmgr_gem = NULL;
3645a884aba1Smrg		goto exit;
364622944501Smrg	}
364722944501Smrg
3648424e9256Smrg	memclear(aperture);
36496d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
36506d98c517Smrg		       DRM_IOCTL_I915_GEM_GET_APERTURE,
36516d98c517Smrg		       &aperture);
365222944501Smrg
365322944501Smrg	if (ret == 0)
365422944501Smrg		bufmgr_gem->gtt_size = aperture.aper_available_size;
365522944501Smrg	else {
365622944501Smrg		fprintf(stderr, "DRM_IOCTL_I915_GEM_APERTURE failed: %s\n",
365722944501Smrg			strerror(errno));
365822944501Smrg		bufmgr_gem->gtt_size = 128 * 1024 * 1024;
365922944501Smrg		fprintf(stderr, "Assuming %dkB available aperture size.\n"
366022944501Smrg			"May lead to reduced performance or incorrect "
366122944501Smrg			"rendering.\n",
366222944501Smrg			(int)bufmgr_gem->gtt_size / 1024);
366322944501Smrg	}
366422944501Smrg
366520131375Smrg	bufmgr_gem->pci_device = get_pci_device_id(bufmgr_gem);
366622944501Smrg
366720131375Smrg	if (IS_GEN2(bufmgr_gem->pci_device))
366822944501Smrg		bufmgr_gem->gen = 2;
366920131375Smrg	else if (IS_GEN3(bufmgr_gem->pci_device))
367022944501Smrg		bufmgr_gem->gen = 3;
367120131375Smrg	else if (IS_GEN4(bufmgr_gem->pci_device))
367222944501Smrg		bufmgr_gem->gen = 4;
367320131375Smrg	else if (IS_GEN5(bufmgr_gem->pci_device))
367420131375Smrg		bufmgr_gem->gen = 5;
367520131375Smrg	else if (IS_GEN6(bufmgr_gem->pci_device))
367622944501Smrg		bufmgr_gem->gen = 6;
367720131375Smrg	else if (IS_GEN7(bufmgr_gem->pci_device))
367820131375Smrg		bufmgr_gem->gen = 7;
367920131375Smrg	else if (IS_GEN8(bufmgr_gem->pci_device))
368020131375Smrg		bufmgr_gem->gen = 8;
36813c748557Ssnj	else if (IS_GEN9(bufmgr_gem->pci_device))
36823c748557Ssnj		bufmgr_gem->gen = 9;
368320131375Smrg	else {
368420131375Smrg		free(bufmgr_gem);
3685a884aba1Smrg		bufmgr_gem = NULL;
3686a884aba1Smrg		goto exit;
368720131375Smrg	}
368820131375Smrg
368920131375Smrg	if (IS_GEN3(bufmgr_gem->pci_device) &&
369020131375Smrg	    bufmgr_gem->gtt_size > 256*1024*1024) {
369120131375Smrg		/* The unmappable part of gtt on gen 3 (i.e. above 256MB) can't
369220131375Smrg		 * be used for tiled blits. To simplify the accounting, just
3693fe517fc9Smrg		 * subtract the unmappable part (fixed to 256MB on all known
369420131375Smrg		 * gen3 devices) if the kernel advertises it. */
369520131375Smrg		bufmgr_gem->gtt_size -= 256*1024*1024;
369620131375Smrg	}
369720131375Smrg
3698424e9256Smrg	memclear(gp);
369920131375Smrg	gp.value = &tmp;
370022944501Smrg
370122944501Smrg	gp.param = I915_PARAM_HAS_EXECBUF2;
37026d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
370322944501Smrg	if (!ret)
370420131375Smrg		exec2 = true;
370522944501Smrg
3706aaba2545Smrg	gp.param = I915_PARAM_HAS_BSD;
37076d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
37089ce4edccSmrg	bufmgr_gem->has_bsd = ret == 0;
37099ce4edccSmrg
37109ce4edccSmrg	gp.param = I915_PARAM_HAS_BLT;
37119ce4edccSmrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
37129ce4edccSmrg	bufmgr_gem->has_blt = ret == 0;
37139ce4edccSmrg
37149ce4edccSmrg	gp.param = I915_PARAM_HAS_RELAXED_FENCING;
37159ce4edccSmrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
37169ce4edccSmrg	bufmgr_gem->has_relaxed_fencing = ret == 0;
3717aaba2545Smrg
37182ee35494Smrg	gp.param = I915_PARAM_HAS_EXEC_ASYNC;
37192ee35494Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
37202ee35494Smrg	bufmgr_gem->has_exec_async = ret == 0;
37212ee35494Smrg
3722424e9256Smrg	bufmgr_gem->bufmgr.bo_alloc_userptr = check_bo_alloc_userptr;
3723a884aba1Smrg
372420131375Smrg	gp.param = I915_PARAM_HAS_WAIT_TIMEOUT;
372520131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
372620131375Smrg	bufmgr_gem->has_wait_timeout = ret == 0;
372720131375Smrg
372820131375Smrg	gp.param = I915_PARAM_HAS_LLC;
372920131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
373020131375Smrg	if (ret != 0) {
373120131375Smrg		/* Kernel does not supports HAS_LLC query, fallback to GPU
373220131375Smrg		 * generation detection and assume that we have LLC on GEN6/7
373320131375Smrg		 */
373420131375Smrg		bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) |
373520131375Smrg				IS_GEN7(bufmgr_gem->pci_device));
373620131375Smrg	} else
373720131375Smrg		bufmgr_gem->has_llc = *gp.value;
373820131375Smrg
373920131375Smrg	gp.param = I915_PARAM_HAS_VEBOX;
374020131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
374120131375Smrg	bufmgr_gem->has_vebox = (ret == 0) & (*gp.value > 0);
374220131375Smrg
3743fe517fc9Smrg	gp.param = I915_PARAM_HAS_EXEC_SOFTPIN;
3744fe517fc9Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3745fe517fc9Smrg	if (ret == 0 && *gp.value > 0)
3746fe517fc9Smrg		bufmgr_gem->bufmgr.bo_set_softpin_offset = drm_intel_gem_bo_set_softpin_offset;
3747fe517fc9Smrg
374822944501Smrg	if (bufmgr_gem->gen < 4) {
374922944501Smrg		gp.param = I915_PARAM_NUM_FENCES_AVAIL;
375022944501Smrg		gp.value = &bufmgr_gem->available_fences;
37516d98c517Smrg		ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
375222944501Smrg		if (ret) {
375322944501Smrg			fprintf(stderr, "get fences failed: %d [%d]\n", ret,
375422944501Smrg				errno);
375522944501Smrg			fprintf(stderr, "param: %d, val: %d\n", gp.param,
375622944501Smrg				*gp.value);
375722944501Smrg			bufmgr_gem->available_fences = 0;
375822944501Smrg		} else {
375922944501Smrg			/* XXX The kernel reports the total number of fences,
376022944501Smrg			 * including any that may be pinned.
376122944501Smrg			 *
376222944501Smrg			 * We presume that there will be at least one pinned
376322944501Smrg			 * fence for the scanout buffer, but there may be more
376422944501Smrg			 * than one scanout and the user may be manually
376522944501Smrg			 * pinning buffers. Let's move to execbuffer2 and
376622944501Smrg			 * thereby forget the insanity of using fences...
376722944501Smrg			 */
376822944501Smrg			bufmgr_gem->available_fences -= 2;
376922944501Smrg			if (bufmgr_gem->available_fences < 0)
377022944501Smrg				bufmgr_gem->available_fences = 0;
377122944501Smrg		}
377222944501Smrg	}
377322944501Smrg
3774fe517fc9Smrg	if (bufmgr_gem->gen >= 8) {
3775fe517fc9Smrg		gp.param = I915_PARAM_HAS_ALIASING_PPGTT;
3776fe517fc9Smrg		ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3777fe517fc9Smrg		if (ret == 0 && *gp.value == 3)
3778fe517fc9Smrg			bufmgr_gem->bufmgr.bo_use_48b_address_range = drm_intel_gem_bo_use_48b_address_range;
3779fe517fc9Smrg	}
3780fe517fc9Smrg
378122944501Smrg	/* Let's go with one relocation per every 2 dwords (but round down a bit
378222944501Smrg	 * since a power of two will mean an extra page allocation for the reloc
378322944501Smrg	 * buffer).
378422944501Smrg	 *
378522944501Smrg	 * Every 4 was too few for the blender benchmark.
378622944501Smrg	 */
378722944501Smrg	bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2;
378822944501Smrg
378922944501Smrg	bufmgr_gem->bufmgr.bo_alloc = drm_intel_gem_bo_alloc;
379022944501Smrg	bufmgr_gem->bufmgr.bo_alloc_for_render =
379122944501Smrg	    drm_intel_gem_bo_alloc_for_render;
379222944501Smrg	bufmgr_gem->bufmgr.bo_alloc_tiled = drm_intel_gem_bo_alloc_tiled;
379322944501Smrg	bufmgr_gem->bufmgr.bo_reference = drm_intel_gem_bo_reference;
379422944501Smrg	bufmgr_gem->bufmgr.bo_unreference = drm_intel_gem_bo_unreference;
379522944501Smrg	bufmgr_gem->bufmgr.bo_map = drm_intel_gem_bo_map;
379622944501Smrg	bufmgr_gem->bufmgr.bo_unmap = drm_intel_gem_bo_unmap;
379722944501Smrg	bufmgr_gem->bufmgr.bo_subdata = drm_intel_gem_bo_subdata;
379822944501Smrg	bufmgr_gem->bufmgr.bo_get_subdata = drm_intel_gem_bo_get_subdata;
379922944501Smrg	bufmgr_gem->bufmgr.bo_wait_rendering = drm_intel_gem_bo_wait_rendering;
380022944501Smrg	bufmgr_gem->bufmgr.bo_emit_reloc = drm_intel_gem_bo_emit_reloc;
380122944501Smrg	bufmgr_gem->bufmgr.bo_emit_reloc_fence = drm_intel_gem_bo_emit_reloc_fence;
380222944501Smrg	bufmgr_gem->bufmgr.bo_pin = drm_intel_gem_bo_pin;
380322944501Smrg	bufmgr_gem->bufmgr.bo_unpin = drm_intel_gem_bo_unpin;
380422944501Smrg	bufmgr_gem->bufmgr.bo_get_tiling = drm_intel_gem_bo_get_tiling;
380522944501Smrg	bufmgr_gem->bufmgr.bo_set_tiling = drm_intel_gem_bo_set_tiling;
380622944501Smrg	bufmgr_gem->bufmgr.bo_flink = drm_intel_gem_bo_flink;
380722944501Smrg	/* Use the new one if available */
3808aaba2545Smrg	if (exec2) {
380922944501Smrg		bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec2;
38109ce4edccSmrg		bufmgr_gem->bufmgr.bo_mrb_exec = drm_intel_gem_bo_mrb_exec2;
3811aaba2545Smrg	} else
381222944501Smrg		bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec;
381322944501Smrg	bufmgr_gem->bufmgr.bo_busy = drm_intel_gem_bo_busy;
381422944501Smrg	bufmgr_gem->bufmgr.bo_madvise = drm_intel_gem_bo_madvise;
3815a884aba1Smrg	bufmgr_gem->bufmgr.destroy = drm_intel_bufmgr_gem_unref;
381622944501Smrg	bufmgr_gem->bufmgr.debug = 0;
381722944501Smrg	bufmgr_gem->bufmgr.check_aperture_space =
381822944501Smrg	    drm_intel_gem_check_aperture_space;
381922944501Smrg	bufmgr_gem->bufmgr.bo_disable_reuse = drm_intel_gem_bo_disable_reuse;
3820aaba2545Smrg	bufmgr_gem->bufmgr.bo_is_reusable = drm_intel_gem_bo_is_reusable;
382122944501Smrg	bufmgr_gem->bufmgr.get_pipe_from_crtc_id =
382222944501Smrg	    drm_intel_gem_get_pipe_from_crtc_id;
382322944501Smrg	bufmgr_gem->bufmgr.bo_references = drm_intel_gem_bo_references;
382422944501Smrg
3825aaba2545Smrg	init_cache_buckets(bufmgr_gem);
382622944501Smrg
382720131375Smrg	DRMINITLISTHEAD(&bufmgr_gem->vma_cache);
382820131375Smrg	bufmgr_gem->vma_max = -1; /* unlimited by default */
382920131375Smrg
3830a884aba1Smrg	DRMLISTADD(&bufmgr_gem->managers, &bufmgr_list);
3831a884aba1Smrg
3832a884aba1Smrgexit:
3833a884aba1Smrg	pthread_mutex_unlock(&bufmgr_list_mutex);
3834a884aba1Smrg
3835a884aba1Smrg	return bufmgr_gem != NULL ? &bufmgr_gem->bufmgr : NULL;
383622944501Smrg}
3837