intel_bufmgr_gem.c revision 48246ce7
122944501Smrg/**************************************************************************
222944501Smrg *
33b115362Smrg * Copyright © 2007 Red Hat Inc.
43b115362Smrg * 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/*
313b115362Smrg * 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#include <xf86drm.h>
3822944501Smrg#include <xf86atomic.h>
3922944501Smrg#include <fcntl.h>
4022944501Smrg#include <stdio.h>
4122944501Smrg#include <stdlib.h>
4222944501Smrg#include <string.h>
4322944501Smrg#include <unistd.h>
4422944501Smrg#include <assert.h>
4522944501Smrg#include <pthread.h>
4622944501Smrg#include <sys/ioctl.h>
4722944501Smrg#include <sys/stat.h>
4822944501Smrg#include <sys/types.h>
4920131375Smrg#include <stdbool.h>
5022944501Smrg
5122944501Smrg#include "errno.h"
5220131375Smrg#ifndef ETIME
5320131375Smrg#define ETIME ETIMEDOUT
5420131375Smrg#endif
55424e9256Smrg#include "libdrm_macros.h"
5622944501Smrg#include "libdrm_lists.h"
5722944501Smrg#include "intel_bufmgr.h"
5822944501Smrg#include "intel_bufmgr_priv.h"
5922944501Smrg#include "intel_chipset.h"
6022944501Smrg#include "string.h"
6122944501Smrg
6222944501Smrg#include "i915_drm.h"
632ee35494Smrg#include "uthash.h"
6422944501Smrg
652b90624aSmrg#if HAVE_VALGRIND
6620131375Smrg#include <valgrind.h>
6720131375Smrg#include <memcheck.h>
6820131375Smrg#define VG(x) x
6920131375Smrg#else
7020131375Smrg#define VG(x)
7120131375Smrg#endif
7220131375Smrg
73424e9256Smrg#define memclear(s) memset(&s, 0, sizeof(s))
7420131375Smrg
7522944501Smrg#define DBG(...) do {					\
7622944501Smrg	if (bufmgr_gem->bufmgr.debug)			\
7722944501Smrg		fprintf(stderr, __VA_ARGS__);		\
7822944501Smrg} while (0)
7922944501Smrg
80aaba2545Smrg#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
81fe517fc9Smrg#define MAX2(A, B) ((A) > (B) ? (A) : (B))
82fe517fc9Smrg
83fe517fc9Smrg/**
84fe517fc9Smrg * upper_32_bits - return bits 32-63 of a number
85fe517fc9Smrg * @n: the number we're accessing
86fe517fc9Smrg *
87fe517fc9Smrg * A basic shift-right of a 64- or 32-bit quantity.  Use this to suppress
88fe517fc9Smrg * the "right shift count >= width of type" warning when that quantity is
89fe517fc9Smrg * 32-bits.
90fe517fc9Smrg */
91fe517fc9Smrg#define upper_32_bits(n) ((__u32)(((n) >> 16) >> 16))
92fe517fc9Smrg
93fe517fc9Smrg/**
94fe517fc9Smrg * lower_32_bits - return bits 0-31 of a number
95fe517fc9Smrg * @n: the number we're accessing
96fe517fc9Smrg */
97fe517fc9Smrg#define lower_32_bits(n) ((__u32)(n))
98aaba2545Smrg
9922944501Smrgtypedef struct _drm_intel_bo_gem drm_intel_bo_gem;
10022944501Smrg
10122944501Smrgstruct drm_intel_gem_bo_bucket {
10222944501Smrg	drmMMListHead head;
10322944501Smrg	unsigned long size;
10422944501Smrg};
10522944501Smrg
10622944501Smrgtypedef struct _drm_intel_bufmgr_gem {
10722944501Smrg	drm_intel_bufmgr bufmgr;
10822944501Smrg
109a884aba1Smrg	atomic_t refcount;
110a884aba1Smrg
11122944501Smrg	int fd;
11222944501Smrg
11322944501Smrg	int max_relocs;
11422944501Smrg
11522944501Smrg	pthread_mutex_t lock;
11622944501Smrg
11722944501Smrg	struct drm_i915_gem_exec_object2 *exec2_objects;
11822944501Smrg	drm_intel_bo **exec_bos;
11922944501Smrg	int exec_size;
12022944501Smrg	int exec_count;
12122944501Smrg
12222944501Smrg	/** Array of lists of cached gem objects of power-of-two sizes */
123aaba2545Smrg	struct drm_intel_gem_bo_bucket cache_bucket[14 * 4];
124aaba2545Smrg	int num_buckets;
1256d98c517Smrg	time_t time;
12622944501Smrg
127a884aba1Smrg	drmMMListHead managers;
128a884aba1Smrg
1292ee35494Smrg	drm_intel_bo_gem *name_table;
1302ee35494Smrg	drm_intel_bo_gem *handle_table;
1312ee35494Smrg
13220131375Smrg	drmMMListHead vma_cache;
13320131375Smrg	int vma_count, vma_open, vma_max;
13420131375Smrg
13522944501Smrg	uint64_t gtt_size;
13622944501Smrg	int available_fences;
13722944501Smrg	int pci_device;
13822944501Smrg	int gen;
1399ce4edccSmrg	unsigned int has_bsd : 1;
1409ce4edccSmrg	unsigned int has_blt : 1;
1419ce4edccSmrg	unsigned int has_relaxed_fencing : 1;
14220131375Smrg	unsigned int has_llc : 1;
14320131375Smrg	unsigned int has_wait_timeout : 1;
1449ce4edccSmrg	unsigned int bo_reuse : 1;
14520131375Smrg	unsigned int no_exec : 1;
14620131375Smrg	unsigned int has_vebox : 1;
1472ee35494Smrg	unsigned int has_exec_async : 1;
14820131375Smrg	bool fenced_relocs;
14920131375Smrg
150424e9256Smrg	struct {
151424e9256Smrg		void *ptr;
152424e9256Smrg		uint32_t handle;
153424e9256Smrg	} userptr_active;
154424e9256Smrg
15522944501Smrg} drm_intel_bufmgr_gem;
15622944501Smrg
15722944501Smrg#define DRM_INTEL_RELOC_FENCE (1<<0)
15822944501Smrg
15922944501Smrgtypedef struct _drm_intel_reloc_target_info {
16022944501Smrg	drm_intel_bo *bo;
16122944501Smrg	int flags;
16222944501Smrg} drm_intel_reloc_target;
16322944501Smrg
16422944501Smrgstruct _drm_intel_bo_gem {
16522944501Smrg	drm_intel_bo bo;
16622944501Smrg
16722944501Smrg	atomic_t refcount;
16822944501Smrg	uint32_t gem_handle;
16922944501Smrg	const char *name;
17022944501Smrg
17122944501Smrg	/**
17222944501Smrg	 * Kenel-assigned global name for this object
17320131375Smrg         *
17420131375Smrg         * List contains both flink named and prime fd'd objects
17522944501Smrg	 */
17622944501Smrg	unsigned int global_name;
1772ee35494Smrg
1782ee35494Smrg	UT_hash_handle handle_hh;
1792ee35494Smrg	UT_hash_handle name_hh;
18022944501Smrg
18122944501Smrg	/**
18222944501Smrg	 * Index of the buffer within the validation list while preparing a
18322944501Smrg	 * batchbuffer execution.
18422944501Smrg	 */
18522944501Smrg	int validate_index;
18622944501Smrg
18722944501Smrg	/**
18822944501Smrg	 * Current tiling mode
18922944501Smrg	 */
19022944501Smrg	uint32_t tiling_mode;
19122944501Smrg	uint32_t swizzle_mode;
1926d98c517Smrg	unsigned long stride;
19322944501Smrg
1942ee35494Smrg	unsigned long kflags;
1952ee35494Smrg
19622944501Smrg	time_t free_time;
19722944501Smrg
19822944501Smrg	/** Array passed to the DRM containing relocation information. */
19922944501Smrg	struct drm_i915_gem_relocation_entry *relocs;
20022944501Smrg	/**
20122944501Smrg	 * Array of info structs corresponding to relocs[i].target_handle etc
20222944501Smrg	 */
20322944501Smrg	drm_intel_reloc_target *reloc_target_info;
20422944501Smrg	/** Number of entries in relocs */
20522944501Smrg	int reloc_count;
206fe517fc9Smrg	/** Array of BOs that are referenced by this buffer and will be softpinned */
207fe517fc9Smrg	drm_intel_bo **softpin_target;
208fe517fc9Smrg	/** Number softpinned BOs that are referenced by this buffer */
209fe517fc9Smrg	int softpin_target_count;
210fe517fc9Smrg	/** Maximum amount of softpinned BOs that are referenced by this buffer */
211fe517fc9Smrg	int softpin_target_size;
212fe517fc9Smrg
21322944501Smrg	/** Mapped address for the buffer, saved across map/unmap cycles */
21422944501Smrg	void *mem_virtual;
21522944501Smrg	/** GTT virtual address for the buffer, saved across map/unmap cycles */
21622944501Smrg	void *gtt_virtual;
2172ee35494Smrg	/** WC CPU address for the buffer, saved across map/unmap cycles */
2182ee35494Smrg	void *wc_virtual;
219a884aba1Smrg	/**
220a884aba1Smrg	 * Virtual address of the buffer allocated by user, used for userptr
221a884aba1Smrg	 * objects only.
222a884aba1Smrg	 */
223a884aba1Smrg	void *user_virtual;
22420131375Smrg	int map_count;
22520131375Smrg	drmMMListHead vma_list;
22622944501Smrg
22722944501Smrg	/** BO cache list */
22822944501Smrg	drmMMListHead head;
22922944501Smrg
23022944501Smrg	/**
23122944501Smrg	 * Boolean of whether this BO and its children have been included in
23222944501Smrg	 * the current drm_intel_bufmgr_check_aperture_space() total.
23322944501Smrg	 */
23420131375Smrg	bool included_in_check_aperture;
23522944501Smrg
23622944501Smrg	/**
23722944501Smrg	 * Boolean of whether this buffer has been used as a relocation
23822944501Smrg	 * target and had its size accounted for, and thus can't have any
23922944501Smrg	 * further relocations added to it.
24022944501Smrg	 */
24120131375Smrg	bool used_as_reloc_target;
24222944501Smrg
24322944501Smrg	/**
24422944501Smrg	 * Boolean of whether we have encountered an error whilst building the relocation tree.
24522944501Smrg	 */
24620131375Smrg	bool has_error;
24722944501Smrg
24822944501Smrg	/**
24922944501Smrg	 * Boolean of whether this buffer can be re-used
25022944501Smrg	 */
25120131375Smrg	bool reusable;
25220131375Smrg
25320131375Smrg	/**
25420131375Smrg	 * Boolean of whether the GPU is definitely not accessing the buffer.
25520131375Smrg	 *
25620131375Smrg	 * This is only valid when reusable, since non-reusable
2572ee35494Smrg	 * buffers are those that have been shared with other
25820131375Smrg	 * processes, so we don't know their state.
25920131375Smrg	 */
26020131375Smrg	bool idle;
26122944501Smrg
262a884aba1Smrg	/**
263a884aba1Smrg	 * Boolean of whether this buffer was allocated with userptr
264a884aba1Smrg	 */
265a884aba1Smrg	bool is_userptr;
266a884aba1Smrg
26722944501Smrg	/**
26822944501Smrg	 * Size in bytes of this buffer and its relocation descendents.
26922944501Smrg	 *
27022944501Smrg	 * Used to avoid costly tree walking in
27122944501Smrg	 * drm_intel_bufmgr_check_aperture in the common case.
27222944501Smrg	 */
27322944501Smrg	int reloc_tree_size;
27422944501Smrg
27522944501Smrg	/**
27622944501Smrg	 * Number of potential fence registers required by this buffer and its
27722944501Smrg	 * relocations.
27822944501Smrg	 */
27922944501Smrg	int reloc_tree_fences;
28020131375Smrg
2812ee35494Smrg	/** Flags that we may need to do the SW_FINISH ioctl on unmap. */
28220131375Smrg	bool mapped_cpu_write;
28322944501Smrg};
28422944501Smrg
28522944501Smrgstatic unsigned int
28622944501Smrgdrm_intel_gem_estimate_batch_space(drm_intel_bo ** bo_array, int count);
28722944501Smrg
28822944501Smrgstatic unsigned int
28922944501Smrgdrm_intel_gem_compute_batch_space(drm_intel_bo ** bo_array, int count);
29022944501Smrg
29122944501Smrgstatic int
29222944501Smrgdrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
29322944501Smrg			    uint32_t * swizzle_mode);
29422944501Smrg
29522944501Smrgstatic int
2966d98c517Smrgdrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo,
2976d98c517Smrg				     uint32_t tiling_mode,
2986d98c517Smrg				     uint32_t stride);
29922944501Smrg
30022944501Smrgstatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo,
30122944501Smrg						      time_t time);
30222944501Smrg
30322944501Smrgstatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo);
30422944501Smrg
30522944501Smrgstatic void drm_intel_gem_bo_free(drm_intel_bo *bo);
30622944501Smrg
307fe517fc9Smrgstatic inline drm_intel_bo_gem *to_bo_gem(drm_intel_bo *bo)
308fe517fc9Smrg{
309fe517fc9Smrg        return (drm_intel_bo_gem *)bo;
310fe517fc9Smrg}
311fe517fc9Smrg
31222944501Smrgstatic unsigned long
31322944501Smrgdrm_intel_gem_bo_tile_size(drm_intel_bufmgr_gem *bufmgr_gem, unsigned long size,
31422944501Smrg			   uint32_t *tiling_mode)
31522944501Smrg{
31622944501Smrg	unsigned long min_size, max_size;
31722944501Smrg	unsigned long i;
31822944501Smrg
31922944501Smrg	if (*tiling_mode == I915_TILING_NONE)
32022944501Smrg		return size;
32122944501Smrg
32222944501Smrg	/* 965+ just need multiples of page size for tiling */
32322944501Smrg	if (bufmgr_gem->gen >= 4)
32422944501Smrg		return ROUND_UP_TO(size, 4096);
32522944501Smrg
32622944501Smrg	/* Older chips need powers of two, of at least 512k or 1M */
32722944501Smrg	if (bufmgr_gem->gen == 3) {
32822944501Smrg		min_size = 1024*1024;
32922944501Smrg		max_size = 128*1024*1024;
33022944501Smrg	} else {
33122944501Smrg		min_size = 512*1024;
33222944501Smrg		max_size = 64*1024*1024;
33322944501Smrg	}
33422944501Smrg
33522944501Smrg	if (size > max_size) {
33622944501Smrg		*tiling_mode = I915_TILING_NONE;
33722944501Smrg		return size;
33822944501Smrg	}
33922944501Smrg
3409ce4edccSmrg	/* Do we need to allocate every page for the fence? */
3419ce4edccSmrg	if (bufmgr_gem->has_relaxed_fencing)
3429ce4edccSmrg		return ROUND_UP_TO(size, 4096);
3439ce4edccSmrg
34422944501Smrg	for (i = min_size; i < size; i <<= 1)
34522944501Smrg		;
34622944501Smrg
34722944501Smrg	return i;
34822944501Smrg}
34922944501Smrg
35022944501Smrg/*
35122944501Smrg * Round a given pitch up to the minimum required for X tiling on a
35222944501Smrg * given chip.  We use 512 as the minimum to allow for a later tiling
35322944501Smrg * change.
35422944501Smrg */
35522944501Smrgstatic unsigned long
35622944501Smrgdrm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem,
3576d98c517Smrg			    unsigned long pitch, uint32_t *tiling_mode)
35822944501Smrg{
35922944501Smrg	unsigned long tile_width;
36022944501Smrg	unsigned long i;
36122944501Smrg
36222944501Smrg	/* If untiled, then just align it so that we can do rendering
36322944501Smrg	 * to it with the 3D engine.
36422944501Smrg	 */
3656d98c517Smrg	if (*tiling_mode == I915_TILING_NONE)
36622944501Smrg		return ALIGN(pitch, 64);
36722944501Smrg
36820131375Smrg	if (*tiling_mode == I915_TILING_X
36920131375Smrg			|| (IS_915(bufmgr_gem->pci_device)
37020131375Smrg			    && *tiling_mode == I915_TILING_Y))
37122944501Smrg		tile_width = 512;
37222944501Smrg	else
37322944501Smrg		tile_width = 128;
37422944501Smrg
37522944501Smrg	/* 965 is flexible */
37622944501Smrg	if (bufmgr_gem->gen >= 4)
37722944501Smrg		return ROUND_UP_TO(pitch, tile_width);
37822944501Smrg
3796d98c517Smrg	/* The older hardware has a maximum pitch of 8192 with tiled
3806d98c517Smrg	 * surfaces, so fallback to untiled if it's too large.
3816d98c517Smrg	 */
3826d98c517Smrg	if (pitch > 8192) {
3836d98c517Smrg		*tiling_mode = I915_TILING_NONE;
3846d98c517Smrg		return ALIGN(pitch, 64);
3856d98c517Smrg	}
3866d98c517Smrg
38722944501Smrg	/* Pre-965 needs power of two tile width */
38822944501Smrg	for (i = tile_width; i < pitch; i <<= 1)
38922944501Smrg		;
39022944501Smrg
39122944501Smrg	return i;
39222944501Smrg}
39322944501Smrg
39422944501Smrgstatic struct drm_intel_gem_bo_bucket *
39522944501Smrgdrm_intel_gem_bo_bucket_for_size(drm_intel_bufmgr_gem *bufmgr_gem,
39622944501Smrg				 unsigned long size)
39722944501Smrg{
39822944501Smrg	int i;
39922944501Smrg
400aaba2545Smrg	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
40122944501Smrg		struct drm_intel_gem_bo_bucket *bucket =
40222944501Smrg		    &bufmgr_gem->cache_bucket[i];
40322944501Smrg		if (bucket->size >= size) {
40422944501Smrg			return bucket;
40522944501Smrg		}
40622944501Smrg	}
40722944501Smrg
40822944501Smrg	return NULL;
40922944501Smrg}
41022944501Smrg
41122944501Smrgstatic void
41222944501Smrgdrm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem)
41322944501Smrg{
41422944501Smrg	int i, j;
41522944501Smrg
41622944501Smrg	for (i = 0; i < bufmgr_gem->exec_count; i++) {
41722944501Smrg		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
41822944501Smrg		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
41922944501Smrg
420fe517fc9Smrg		if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) {
421fe517fc9Smrg			DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle,
4220655efefSmrg			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
42322944501Smrg			    bo_gem->name);
42422944501Smrg			continue;
42522944501Smrg		}
42622944501Smrg
42722944501Smrg		for (j = 0; j < bo_gem->reloc_count; j++) {
42822944501Smrg			drm_intel_bo *target_bo = bo_gem->reloc_target_info[j].bo;
42922944501Smrg			drm_intel_bo_gem *target_gem =
43022944501Smrg			    (drm_intel_bo_gem *) target_bo;
43122944501Smrg
432fe517fc9Smrg			DBG("%2d: %d %s(%s)@0x%08x %08x -> "
433fe517fc9Smrg			    "%d (%s)@0x%08x %08x + 0x%08x\n",
43422944501Smrg			    i,
435fe517fc9Smrg			    bo_gem->gem_handle,
4360655efefSmrg			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
437fe517fc9Smrg			    bo_gem->name,
438fe517fc9Smrg			    upper_32_bits(bo_gem->relocs[j].offset),
439fe517fc9Smrg			    lower_32_bits(bo_gem->relocs[j].offset),
44022944501Smrg			    target_gem->gem_handle,
44122944501Smrg			    target_gem->name,
442fe517fc9Smrg			    upper_32_bits(target_bo->offset64),
443fe517fc9Smrg			    lower_32_bits(target_bo->offset64),
44422944501Smrg			    bo_gem->relocs[j].delta);
44522944501Smrg		}
446fe517fc9Smrg
447fe517fc9Smrg		for (j = 0; j < bo_gem->softpin_target_count; j++) {
448fe517fc9Smrg			drm_intel_bo *target_bo = bo_gem->softpin_target[j];
449fe517fc9Smrg			drm_intel_bo_gem *target_gem =
450fe517fc9Smrg			    (drm_intel_bo_gem *) target_bo;
451fe517fc9Smrg			DBG("%2d: %d %s(%s) -> "
452fe517fc9Smrg			    "%d *(%s)@0x%08x %08x\n",
453fe517fc9Smrg			    i,
454fe517fc9Smrg			    bo_gem->gem_handle,
4550655efefSmrg			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
456fe517fc9Smrg			    bo_gem->name,
457fe517fc9Smrg			    target_gem->gem_handle,
458fe517fc9Smrg			    target_gem->name,
459fe517fc9Smrg			    upper_32_bits(target_bo->offset64),
460fe517fc9Smrg			    lower_32_bits(target_bo->offset64));
461fe517fc9Smrg		}
46222944501Smrg	}
46322944501Smrg}
46422944501Smrg
46522944501Smrgstatic inline void
46622944501Smrgdrm_intel_gem_bo_reference(drm_intel_bo *bo)
46722944501Smrg{
46822944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
46922944501Smrg
47022944501Smrg	atomic_inc(&bo_gem->refcount);
47122944501Smrg}
47222944501Smrg
47322944501Smrg/**
47422944501Smrg * Adds the given buffer to the list of buffers to be validated (moved into the
47522944501Smrg * appropriate memory type) with the next batch submission.
47622944501Smrg *
47722944501Smrg * If a buffer is validated multiple times in a batch submission, it ends up
47822944501Smrg * with the intersection of the memory type flags and the union of the
47922944501Smrg * access flags.
48022944501Smrg */
48122944501Smrgstatic void
48222944501Smrgdrm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence)
48322944501Smrg{
48422944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
48522944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
48622944501Smrg	int index;
4870655efefSmrg	unsigned long flags;
488fe517fc9Smrg
4890655efefSmrg	flags = 0;
490fe517fc9Smrg	if (need_fence)
491fe517fc9Smrg		flags |= EXEC_OBJECT_NEEDS_FENCE;
49222944501Smrg
49322944501Smrg	if (bo_gem->validate_index != -1) {
494fe517fc9Smrg		bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags;
49522944501Smrg		return;
49622944501Smrg	}
49722944501Smrg
49822944501Smrg	/* Extend the array of validation entries as necessary. */
49922944501Smrg	if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
50022944501Smrg		int new_size = bufmgr_gem->exec_size * 2;
50122944501Smrg
50222944501Smrg		if (new_size == 0)
50322944501Smrg			new_size = 5;
50422944501Smrg
50522944501Smrg		bufmgr_gem->exec2_objects =
50622944501Smrg			realloc(bufmgr_gem->exec2_objects,
50722944501Smrg				sizeof(*bufmgr_gem->exec2_objects) * new_size);
50822944501Smrg		bufmgr_gem->exec_bos =
50922944501Smrg			realloc(bufmgr_gem->exec_bos,
51022944501Smrg				sizeof(*bufmgr_gem->exec_bos) * new_size);
51122944501Smrg		bufmgr_gem->exec_size = new_size;
51222944501Smrg	}
51322944501Smrg
51422944501Smrg	index = bufmgr_gem->exec_count;
51522944501Smrg	bo_gem->validate_index = index;
51622944501Smrg	/* Fill in array entry */
51722944501Smrg	bufmgr_gem->exec2_objects[index].handle = bo_gem->gem_handle;
51822944501Smrg	bufmgr_gem->exec2_objects[index].relocation_count = bo_gem->reloc_count;
51922944501Smrg	bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
520fe517fc9Smrg	bufmgr_gem->exec2_objects[index].alignment = bo->align;
5212ee35494Smrg	bufmgr_gem->exec2_objects[index].offset = bo->offset64;
5220655efefSmrg	bufmgr_gem->exec2_objects[index].flags = bo_gem->kflags | flags;
52322944501Smrg	bufmgr_gem->exec2_objects[index].rsvd1 = 0;
52422944501Smrg	bufmgr_gem->exec2_objects[index].rsvd2 = 0;
5252ee35494Smrg	bufmgr_gem->exec_bos[index] = bo;
52622944501Smrg	bufmgr_gem->exec_count++;
52722944501Smrg}
52822944501Smrg
52922944501Smrg#define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \
53022944501Smrg	sizeof(uint32_t))
53122944501Smrg
53222944501Smrgstatic void
53322944501Smrgdrm_intel_bo_gem_set_in_aperture_size(drm_intel_bufmgr_gem *bufmgr_gem,
534fe517fc9Smrg				      drm_intel_bo_gem *bo_gem,
535fe517fc9Smrg				      unsigned int alignment)
53622944501Smrg{
537fe517fc9Smrg	unsigned int size;
53822944501Smrg
53922944501Smrg	assert(!bo_gem->used_as_reloc_target);
54022944501Smrg
54122944501Smrg	/* The older chipsets are far-less flexible in terms of tiling,
54222944501Smrg	 * and require tiled buffer to be size aligned in the aperture.
54322944501Smrg	 * This means that in the worst possible case we will need a hole
54422944501Smrg	 * twice as large as the object in order for it to fit into the
54522944501Smrg	 * aperture. Optimal packing is for wimps.
54622944501Smrg	 */
54722944501Smrg	size = bo_gem->bo.size;
5489ce4edccSmrg	if (bufmgr_gem->gen < 4 && bo_gem->tiling_mode != I915_TILING_NONE) {
549fe517fc9Smrg		unsigned int min_size;
5509ce4edccSmrg
5519ce4edccSmrg		if (bufmgr_gem->has_relaxed_fencing) {
5529ce4edccSmrg			if (bufmgr_gem->gen == 3)
5539ce4edccSmrg				min_size = 1024*1024;
5549ce4edccSmrg			else
5559ce4edccSmrg				min_size = 512*1024;
5569ce4edccSmrg
5579ce4edccSmrg			while (min_size < size)
5589ce4edccSmrg				min_size *= 2;
5599ce4edccSmrg		} else
5609ce4edccSmrg			min_size = size;
5619ce4edccSmrg
5629ce4edccSmrg		/* Account for worst-case alignment. */
563fe517fc9Smrg		alignment = MAX2(alignment, min_size);
5649ce4edccSmrg	}
56522944501Smrg
566fe517fc9Smrg	bo_gem->reloc_tree_size = size + alignment;
56722944501Smrg}
56822944501Smrg
56922944501Smrgstatic int
57022944501Smrgdrm_intel_setup_reloc_list(drm_intel_bo *bo)
57122944501Smrg{
57222944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
57322944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
57422944501Smrg	unsigned int max_relocs = bufmgr_gem->max_relocs;
57522944501Smrg
57622944501Smrg	if (bo->size / 4 < max_relocs)
57722944501Smrg		max_relocs = bo->size / 4;
57822944501Smrg
57922944501Smrg	bo_gem->relocs = malloc(max_relocs *
58022944501Smrg				sizeof(struct drm_i915_gem_relocation_entry));
58122944501Smrg	bo_gem->reloc_target_info = malloc(max_relocs *
582aaba2545Smrg					   sizeof(drm_intel_reloc_target));
58322944501Smrg	if (bo_gem->relocs == NULL || bo_gem->reloc_target_info == NULL) {
58420131375Smrg		bo_gem->has_error = true;
58522944501Smrg
58622944501Smrg		free (bo_gem->relocs);
58722944501Smrg		bo_gem->relocs = NULL;
58822944501Smrg
58922944501Smrg		free (bo_gem->reloc_target_info);
59022944501Smrg		bo_gem->reloc_target_info = NULL;
59122944501Smrg
59222944501Smrg		return 1;
59322944501Smrg	}
59422944501Smrg
59522944501Smrg	return 0;
59622944501Smrg}
59722944501Smrg
59822944501Smrgstatic int
59922944501Smrgdrm_intel_gem_bo_busy(drm_intel_bo *bo)
60022944501Smrg{
60122944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
60222944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
60322944501Smrg	struct drm_i915_gem_busy busy;
60422944501Smrg	int ret;
60522944501Smrg
60620131375Smrg	if (bo_gem->reusable && bo_gem->idle)
60720131375Smrg		return false;
60820131375Smrg
609424e9256Smrg	memclear(busy);
61022944501Smrg	busy.handle = bo_gem->gem_handle;
61122944501Smrg
6126d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
61320131375Smrg	if (ret == 0) {
61420131375Smrg		bo_gem->idle = !busy.busy;
61520131375Smrg		return busy.busy;
61620131375Smrg	} else {
61720131375Smrg		return false;
61820131375Smrg	}
61922944501Smrg}
62022944501Smrg
62122944501Smrgstatic int
62222944501Smrgdrm_intel_gem_bo_madvise_internal(drm_intel_bufmgr_gem *bufmgr_gem,
62322944501Smrg				  drm_intel_bo_gem *bo_gem, int state)
62422944501Smrg{
62522944501Smrg	struct drm_i915_gem_madvise madv;
62622944501Smrg
627424e9256Smrg	memclear(madv);
62822944501Smrg	madv.handle = bo_gem->gem_handle;
62922944501Smrg	madv.madv = state;
63022944501Smrg	madv.retained = 1;
6316d98c517Smrg	drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv);
63222944501Smrg
63322944501Smrg	return madv.retained;
63422944501Smrg}
63522944501Smrg
63622944501Smrgstatic int
63722944501Smrgdrm_intel_gem_bo_madvise(drm_intel_bo *bo, int madv)
63822944501Smrg{
63922944501Smrg	return drm_intel_gem_bo_madvise_internal
64022944501Smrg		((drm_intel_bufmgr_gem *) bo->bufmgr,
64122944501Smrg		 (drm_intel_bo_gem *) bo,
64222944501Smrg		 madv);
64322944501Smrg}
64422944501Smrg
64522944501Smrg/* drop the oldest entries that have been purged by the kernel */
64622944501Smrgstatic void
64722944501Smrgdrm_intel_gem_bo_cache_purge_bucket(drm_intel_bufmgr_gem *bufmgr_gem,
64822944501Smrg				    struct drm_intel_gem_bo_bucket *bucket)
64922944501Smrg{
65022944501Smrg	while (!DRMLISTEMPTY(&bucket->head)) {
65122944501Smrg		drm_intel_bo_gem *bo_gem;
65222944501Smrg
65322944501Smrg		bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
65422944501Smrg				      bucket->head.next, head);
65522944501Smrg		if (drm_intel_gem_bo_madvise_internal
65622944501Smrg		    (bufmgr_gem, bo_gem, I915_MADV_DONTNEED))
65722944501Smrg			break;
65822944501Smrg
65922944501Smrg		DRMLISTDEL(&bo_gem->head);
66022944501Smrg		drm_intel_gem_bo_free(&bo_gem->bo);
66122944501Smrg	}
66222944501Smrg}
66322944501Smrg
66422944501Smrgstatic drm_intel_bo *
66522944501Smrgdrm_intel_gem_bo_alloc_internal(drm_intel_bufmgr *bufmgr,
66622944501Smrg				const char *name,
66722944501Smrg				unsigned long size,
6686d98c517Smrg				unsigned long flags,
6696d98c517Smrg				uint32_t tiling_mode,
670fe517fc9Smrg				unsigned long stride,
671fe517fc9Smrg				unsigned int alignment)
67222944501Smrg{
67322944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
67422944501Smrg	drm_intel_bo_gem *bo_gem;
67522944501Smrg	unsigned int page_size = getpagesize();
67622944501Smrg	int ret;
67722944501Smrg	struct drm_intel_gem_bo_bucket *bucket;
67820131375Smrg	bool alloc_from_cache;
67922944501Smrg	unsigned long bo_size;
68020131375Smrg	bool for_render = false;
68122944501Smrg
68222944501Smrg	if (flags & BO_ALLOC_FOR_RENDER)
68320131375Smrg		for_render = true;
68422944501Smrg
68522944501Smrg	/* Round the allocated size up to a power of two number of pages. */
68622944501Smrg	bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, size);
68722944501Smrg
68822944501Smrg	/* If we don't have caching at this size, don't actually round the
68922944501Smrg	 * allocation up.
69022944501Smrg	 */
69122944501Smrg	if (bucket == NULL) {
69222944501Smrg		bo_size = size;
69322944501Smrg		if (bo_size < page_size)
69422944501Smrg			bo_size = page_size;
69522944501Smrg	} else {
69622944501Smrg		bo_size = bucket->size;
69722944501Smrg	}
69822944501Smrg
69922944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
70022944501Smrg	/* Get a buffer out of the cache if available */
70122944501Smrgretry:
70220131375Smrg	alloc_from_cache = false;
70322944501Smrg	if (bucket != NULL && !DRMLISTEMPTY(&bucket->head)) {
70422944501Smrg		if (for_render) {
70522944501Smrg			/* Allocate new render-target BOs from the tail (MRU)
70622944501Smrg			 * of the list, as it will likely be hot in the GPU
70722944501Smrg			 * cache and in the aperture for us.
70822944501Smrg			 */
70922944501Smrg			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
71022944501Smrg					      bucket->head.prev, head);
71122944501Smrg			DRMLISTDEL(&bo_gem->head);
71220131375Smrg			alloc_from_cache = true;
713fe517fc9Smrg			bo_gem->bo.align = alignment;
71422944501Smrg		} else {
715fe517fc9Smrg			assert(alignment == 0);
71622944501Smrg			/* For non-render-target BOs (where we're probably
71722944501Smrg			 * going to map it first thing in order to fill it
71822944501Smrg			 * with data), check if the last BO in the cache is
71922944501Smrg			 * unbusy, and only reuse in that case. Otherwise,
72022944501Smrg			 * allocating a new buffer is probably faster than
72122944501Smrg			 * waiting for the GPU to finish.
72222944501Smrg			 */
72322944501Smrg			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
72422944501Smrg					      bucket->head.next, head);
72522944501Smrg			if (!drm_intel_gem_bo_busy(&bo_gem->bo)) {
72620131375Smrg				alloc_from_cache = true;
72722944501Smrg				DRMLISTDEL(&bo_gem->head);
72822944501Smrg			}
72922944501Smrg		}
73022944501Smrg
73122944501Smrg		if (alloc_from_cache) {
73222944501Smrg			if (!drm_intel_gem_bo_madvise_internal
73322944501Smrg			    (bufmgr_gem, bo_gem, I915_MADV_WILLNEED)) {
73422944501Smrg				drm_intel_gem_bo_free(&bo_gem->bo);
73522944501Smrg				drm_intel_gem_bo_cache_purge_bucket(bufmgr_gem,
73622944501Smrg								    bucket);
73722944501Smrg				goto retry;
73822944501Smrg			}
7396d98c517Smrg
7406d98c517Smrg			if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo,
7416d98c517Smrg								 tiling_mode,
7426d98c517Smrg								 stride)) {
7436d98c517Smrg				drm_intel_gem_bo_free(&bo_gem->bo);
7446d98c517Smrg				goto retry;
7456d98c517Smrg			}
74622944501Smrg		}
74722944501Smrg	}
74822944501Smrg
74922944501Smrg	if (!alloc_from_cache) {
75022944501Smrg		struct drm_i915_gem_create create;
75122944501Smrg
75222944501Smrg		bo_gem = calloc(1, sizeof(*bo_gem));
75322944501Smrg		if (!bo_gem)
7542ee35494Smrg			goto err;
7552ee35494Smrg
7562ee35494Smrg		/* drm_intel_gem_bo_free calls DRMLISTDEL() for an uninitialized
7572ee35494Smrg		   list (vma_list), so better set the list head here */
7582ee35494Smrg		DRMINITLISTHEAD(&bo_gem->vma_list);
75922944501Smrg
76022944501Smrg		bo_gem->bo.size = bo_size;
76120131375Smrg
762424e9256Smrg		memclear(create);
76322944501Smrg		create.size = bo_size;
76422944501Smrg
7656d98c517Smrg		ret = drmIoctl(bufmgr_gem->fd,
7666d98c517Smrg			       DRM_IOCTL_I915_GEM_CREATE,
7676d98c517Smrg			       &create);
76822944501Smrg		if (ret != 0) {
76922944501Smrg			free(bo_gem);
7702ee35494Smrg			goto err;
77122944501Smrg		}
7722ee35494Smrg
7732ee35494Smrg		bo_gem->gem_handle = create.handle;
7740655efefSmrg		HASH_ADD(handle_hh, bufmgr_gem->handle_table,
7750655efefSmrg			 gem_handle, sizeof(bo_gem->gem_handle),
7760655efefSmrg			 bo_gem);
7770655efefSmrg
7782ee35494Smrg		bo_gem->bo.handle = bo_gem->gem_handle;
77922944501Smrg		bo_gem->bo.bufmgr = bufmgr;
780fe517fc9Smrg		bo_gem->bo.align = alignment;
7816d98c517Smrg
7826d98c517Smrg		bo_gem->tiling_mode = I915_TILING_NONE;
7836d98c517Smrg		bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
7846d98c517Smrg		bo_gem->stride = 0;
7856d98c517Smrg
7866d98c517Smrg		if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo,
7876d98c517Smrg							 tiling_mode,
7882ee35494Smrg							 stride))
7892ee35494Smrg			goto err_free;
79022944501Smrg	}
79122944501Smrg
79222944501Smrg	bo_gem->name = name;
79322944501Smrg	atomic_set(&bo_gem->refcount, 1);
79422944501Smrg	bo_gem->validate_index = -1;
79522944501Smrg	bo_gem->reloc_tree_fences = 0;
79620131375Smrg	bo_gem->used_as_reloc_target = false;
79720131375Smrg	bo_gem->has_error = false;
79820131375Smrg	bo_gem->reusable = true;
79922944501Smrg
800fe517fc9Smrg	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment);
8012ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
80222944501Smrg
80322944501Smrg	DBG("bo_create: buf %d (%s) %ldb\n",
80422944501Smrg	    bo_gem->gem_handle, bo_gem->name, size);
80522944501Smrg
80622944501Smrg	return &bo_gem->bo;
8072ee35494Smrg
8082ee35494Smrgerr_free:
8092ee35494Smrg	drm_intel_gem_bo_free(&bo_gem->bo);
8102ee35494Smrgerr:
8112ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
8122ee35494Smrg	return NULL;
81322944501Smrg}
81422944501Smrg
81522944501Smrgstatic drm_intel_bo *
81622944501Smrgdrm_intel_gem_bo_alloc_for_render(drm_intel_bufmgr *bufmgr,
81722944501Smrg				  const char *name,
81822944501Smrg				  unsigned long size,
81922944501Smrg				  unsigned int alignment)
82022944501Smrg{
82122944501Smrg	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size,
8226d98c517Smrg					       BO_ALLOC_FOR_RENDER,
823fe517fc9Smrg					       I915_TILING_NONE, 0,
824fe517fc9Smrg					       alignment);
82522944501Smrg}
82622944501Smrg
82722944501Smrgstatic drm_intel_bo *
82822944501Smrgdrm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr,
82922944501Smrg		       const char *name,
83022944501Smrg		       unsigned long size,
83122944501Smrg		       unsigned int alignment)
83222944501Smrg{
8336d98c517Smrg	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0,
834fe517fc9Smrg					       I915_TILING_NONE, 0, 0);
83522944501Smrg}
83622944501Smrg
83722944501Smrgstatic drm_intel_bo *
83822944501Smrgdrm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name,
83922944501Smrg			     int x, int y, int cpp, uint32_t *tiling_mode,
84022944501Smrg			     unsigned long *pitch, unsigned long flags)
84122944501Smrg{
84222944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
843aaba2545Smrg	unsigned long size, stride;
844aaba2545Smrg	uint32_t tiling;
84522944501Smrg
846aaba2545Smrg	do {
84720131375Smrg		unsigned long aligned_y, height_alignment;
848aaba2545Smrg
849aaba2545Smrg		tiling = *tiling_mode;
850aaba2545Smrg
851aaba2545Smrg		/* If we're tiled, our allocations are in 8 or 32-row blocks,
852aaba2545Smrg		 * so failure to align our height means that we won't allocate
853aaba2545Smrg		 * enough pages.
854aaba2545Smrg		 *
855aaba2545Smrg		 * If we're untiled, we still have to align to 2 rows high
856aaba2545Smrg		 * because the data port accesses 2x2 blocks even if the
857aaba2545Smrg		 * bottom row isn't to be rendered, so failure to align means
858aaba2545Smrg		 * we could walk off the end of the GTT and fault.  This is
859aaba2545Smrg		 * documented on 965, and may be the case on older chipsets
860aaba2545Smrg		 * too so we try to be careful.
861aaba2545Smrg		 */
862aaba2545Smrg		aligned_y = y;
86320131375Smrg		height_alignment = 2;
86420131375Smrg
86520131375Smrg		if ((bufmgr_gem->gen == 2) && tiling != I915_TILING_NONE)
86620131375Smrg			height_alignment = 16;
86720131375Smrg		else if (tiling == I915_TILING_X
86820131375Smrg			|| (IS_915(bufmgr_gem->pci_device)
86920131375Smrg			    && tiling == I915_TILING_Y))
87020131375Smrg			height_alignment = 8;
871aaba2545Smrg		else if (tiling == I915_TILING_Y)
87220131375Smrg			height_alignment = 32;
87320131375Smrg		aligned_y = ALIGN(y, height_alignment);
874aaba2545Smrg
875aaba2545Smrg		stride = x * cpp;
8766d98c517Smrg		stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling_mode);
877aaba2545Smrg		size = stride * aligned_y;
878aaba2545Smrg		size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode);
879aaba2545Smrg	} while (*tiling_mode != tiling);
88022944501Smrg	*pitch = stride;
88122944501Smrg
8826d98c517Smrg	if (tiling == I915_TILING_NONE)
8836d98c517Smrg		stride = 0;
8846d98c517Smrg
8856d98c517Smrg	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags,
886fe517fc9Smrg					       tiling, stride, 0);
88722944501Smrg}
88822944501Smrg
889a884aba1Smrgstatic drm_intel_bo *
890a884aba1Smrgdrm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
891a884aba1Smrg				const char *name,
892a884aba1Smrg				void *addr,
893a884aba1Smrg				uint32_t tiling_mode,
894a884aba1Smrg				uint32_t stride,
895a884aba1Smrg				unsigned long size,
896a884aba1Smrg				unsigned long flags)
897a884aba1Smrg{
898a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
899a884aba1Smrg	drm_intel_bo_gem *bo_gem;
900a884aba1Smrg	int ret;
901a884aba1Smrg	struct drm_i915_gem_userptr userptr;
902a884aba1Smrg
903a884aba1Smrg	/* Tiling with userptr surfaces is not supported
904a884aba1Smrg	 * on all hardware so refuse it for time being.
905a884aba1Smrg	 */
906a884aba1Smrg	if (tiling_mode != I915_TILING_NONE)
907a884aba1Smrg		return NULL;
908a884aba1Smrg
909a884aba1Smrg	bo_gem = calloc(1, sizeof(*bo_gem));
910a884aba1Smrg	if (!bo_gem)
911a884aba1Smrg		return NULL;
912a884aba1Smrg
9132ee35494Smrg	atomic_set(&bo_gem->refcount, 1);
9142ee35494Smrg	DRMINITLISTHEAD(&bo_gem->vma_list);
9152ee35494Smrg
916a884aba1Smrg	bo_gem->bo.size = size;
917a884aba1Smrg
918424e9256Smrg	memclear(userptr);
919a884aba1Smrg	userptr.user_ptr = (__u64)((unsigned long)addr);
920a884aba1Smrg	userptr.user_size = size;
921a884aba1Smrg	userptr.flags = flags;
922a884aba1Smrg
923a884aba1Smrg	ret = drmIoctl(bufmgr_gem->fd,
924a884aba1Smrg			DRM_IOCTL_I915_GEM_USERPTR,
925a884aba1Smrg			&userptr);
926a884aba1Smrg	if (ret != 0) {
927a884aba1Smrg		DBG("bo_create_userptr: "
928a884aba1Smrg		    "ioctl failed with user ptr %p size 0x%lx, "
929a884aba1Smrg		    "user flags 0x%lx\n", addr, size, flags);
930a884aba1Smrg		free(bo_gem);
931a884aba1Smrg		return NULL;
932a884aba1Smrg	}
933a884aba1Smrg
9342ee35494Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
9352ee35494Smrg
936a884aba1Smrg	bo_gem->gem_handle = userptr.handle;
937a884aba1Smrg	bo_gem->bo.handle = bo_gem->gem_handle;
938a884aba1Smrg	bo_gem->bo.bufmgr    = bufmgr;
939a884aba1Smrg	bo_gem->is_userptr   = true;
940a884aba1Smrg	bo_gem->bo.virtual   = addr;
941a884aba1Smrg	/* Save the address provided by user */
942a884aba1Smrg	bo_gem->user_virtual = addr;
943a884aba1Smrg	bo_gem->tiling_mode  = I915_TILING_NONE;
944a884aba1Smrg	bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
945a884aba1Smrg	bo_gem->stride       = 0;
946a884aba1Smrg
9472ee35494Smrg	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
9482ee35494Smrg		 gem_handle, sizeof(bo_gem->gem_handle),
9492ee35494Smrg		 bo_gem);
950a884aba1Smrg
951a884aba1Smrg	bo_gem->name = name;
952a884aba1Smrg	bo_gem->validate_index = -1;
953a884aba1Smrg	bo_gem->reloc_tree_fences = 0;
954a884aba1Smrg	bo_gem->used_as_reloc_target = false;
955a884aba1Smrg	bo_gem->has_error = false;
956a884aba1Smrg	bo_gem->reusable = false;
957a884aba1Smrg
958fe517fc9Smrg	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
9592ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
960a884aba1Smrg
961a884aba1Smrg	DBG("bo_create_userptr: "
962a884aba1Smrg	    "ptr %p buf %d (%s) size %ldb, stride 0x%x, tile mode %d\n",
963a884aba1Smrg		addr, bo_gem->gem_handle, bo_gem->name,
964a884aba1Smrg		size, stride, tiling_mode);
965a884aba1Smrg
966a884aba1Smrg	return &bo_gem->bo;
967a884aba1Smrg}
968a884aba1Smrg
969424e9256Smrgstatic bool
970424e9256Smrghas_userptr(drm_intel_bufmgr_gem *bufmgr_gem)
971424e9256Smrg{
972424e9256Smrg	int ret;
973424e9256Smrg	void *ptr;
974424e9256Smrg	long pgsz;
975424e9256Smrg	struct drm_i915_gem_userptr userptr;
976424e9256Smrg
977424e9256Smrg	pgsz = sysconf(_SC_PAGESIZE);
978424e9256Smrg	assert(pgsz > 0);
979424e9256Smrg
980424e9256Smrg	ret = posix_memalign(&ptr, pgsz, pgsz);
981424e9256Smrg	if (ret) {
982424e9256Smrg		DBG("Failed to get a page (%ld) for userptr detection!\n",
983424e9256Smrg			pgsz);
984424e9256Smrg		return false;
985424e9256Smrg	}
986424e9256Smrg
987424e9256Smrg	memclear(userptr);
988424e9256Smrg	userptr.user_ptr = (__u64)(unsigned long)ptr;
989424e9256Smrg	userptr.user_size = pgsz;
990424e9256Smrg
991424e9256Smrgretry:
992424e9256Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr);
993424e9256Smrg	if (ret) {
994424e9256Smrg		if (errno == ENODEV && userptr.flags == 0) {
995424e9256Smrg			userptr.flags = I915_USERPTR_UNSYNCHRONIZED;
996424e9256Smrg			goto retry;
997424e9256Smrg		}
998424e9256Smrg		free(ptr);
999424e9256Smrg		return false;
1000424e9256Smrg	}
1001424e9256Smrg
1002424e9256Smrg	/* We don't release the userptr bo here as we want to keep the
1003424e9256Smrg	 * kernel mm tracking alive for our lifetime. The first time we
1004424e9256Smrg	 * create a userptr object the kernel has to install a mmu_notifer
1005424e9256Smrg	 * which is a heavyweight operation (e.g. it requires taking all
1006424e9256Smrg	 * mm_locks and stop_machine()).
1007424e9256Smrg	 */
1008424e9256Smrg
1009424e9256Smrg	bufmgr_gem->userptr_active.ptr = ptr;
1010424e9256Smrg	bufmgr_gem->userptr_active.handle = userptr.handle;
1011424e9256Smrg
1012424e9256Smrg	return true;
1013424e9256Smrg}
1014424e9256Smrg
1015424e9256Smrgstatic drm_intel_bo *
1016424e9256Smrgcheck_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
1017424e9256Smrg		       const char *name,
1018424e9256Smrg		       void *addr,
1019424e9256Smrg		       uint32_t tiling_mode,
1020424e9256Smrg		       uint32_t stride,
1021424e9256Smrg		       unsigned long size,
1022424e9256Smrg		       unsigned long flags)
1023424e9256Smrg{
1024424e9256Smrg	if (has_userptr((drm_intel_bufmgr_gem *)bufmgr))
1025424e9256Smrg		bufmgr->bo_alloc_userptr = drm_intel_gem_bo_alloc_userptr;
1026424e9256Smrg	else
1027424e9256Smrg		bufmgr->bo_alloc_userptr = NULL;
1028424e9256Smrg
1029424e9256Smrg	return drm_intel_bo_alloc_userptr(bufmgr, name, addr,
1030424e9256Smrg					  tiling_mode, stride, size, flags);
1031424e9256Smrg}
1032424e9256Smrg
103387bf8e7cSmrgstatic int get_tiling_mode(drm_intel_bufmgr_gem *bufmgr_gem,
103487bf8e7cSmrg			   uint32_t gem_handle,
103587bf8e7cSmrg			   uint32_t *tiling_mode,
103687bf8e7cSmrg			   uint32_t *swizzle_mode)
103787bf8e7cSmrg{
103887bf8e7cSmrg	struct drm_i915_gem_get_tiling get_tiling = {
103987bf8e7cSmrg		.handle = gem_handle,
104087bf8e7cSmrg	};
104187bf8e7cSmrg	int ret;
104287bf8e7cSmrg
104387bf8e7cSmrg	ret = drmIoctl(bufmgr_gem->fd,
104487bf8e7cSmrg		       DRM_IOCTL_I915_GEM_GET_TILING,
104587bf8e7cSmrg		       &get_tiling);
104687bf8e7cSmrg	if (ret != 0 && errno != EOPNOTSUPP)
104787bf8e7cSmrg		return ret;
104887bf8e7cSmrg
104987bf8e7cSmrg	*tiling_mode = get_tiling.tiling_mode;
105087bf8e7cSmrg	*swizzle_mode = get_tiling.swizzle_mode;
105187bf8e7cSmrg
105287bf8e7cSmrg	return 0;
105387bf8e7cSmrg}
105487bf8e7cSmrg
105522944501Smrg/**
105622944501Smrg * Returns a drm_intel_bo wrapping the given buffer object handle.
105722944501Smrg *
105822944501Smrg * This can be used when one application needs to pass a buffer object
105922944501Smrg * to another.
106022944501Smrg */
10616260e5d5Smrgdrm_public drm_intel_bo *
106222944501Smrgdrm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr,
106322944501Smrg				  const char *name,
106422944501Smrg				  unsigned int handle)
106522944501Smrg{
106622944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
106722944501Smrg	drm_intel_bo_gem *bo_gem;
106822944501Smrg	int ret;
106922944501Smrg	struct drm_gem_open open_arg;
107022944501Smrg
107120131375Smrg	/* At the moment most applications only have a few named bo.
107220131375Smrg	 * For instance, in a DRI client only the render buffers passed
107320131375Smrg	 * between X and the client are named. And since X returns the
107420131375Smrg	 * alternating names for the front/back buffer a linear search
107520131375Smrg	 * provides a sufficiently fast match.
107620131375Smrg	 */
1077a884aba1Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
10782ee35494Smrg	HASH_FIND(name_hh, bufmgr_gem->name_table,
10792ee35494Smrg		  &handle, sizeof(handle), bo_gem);
10802ee35494Smrg	if (bo_gem) {
10812ee35494Smrg		drm_intel_gem_bo_reference(&bo_gem->bo);
10822ee35494Smrg		goto out;
108320131375Smrg	}
108422944501Smrg
1085424e9256Smrg	memclear(open_arg);
108622944501Smrg	open_arg.name = handle;
10876d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
10886d98c517Smrg		       DRM_IOCTL_GEM_OPEN,
10896d98c517Smrg		       &open_arg);
109022944501Smrg	if (ret != 0) {
10919ce4edccSmrg		DBG("Couldn't reference %s handle 0x%08x: %s\n",
10929ce4edccSmrg		    name, handle, strerror(errno));
10932ee35494Smrg		bo_gem = NULL;
10942ee35494Smrg		goto out;
109522944501Smrg	}
109620131375Smrg        /* Now see if someone has used a prime handle to get this
109720131375Smrg         * object from the kernel before by looking through the list
109820131375Smrg         * again for a matching gem_handle
109920131375Smrg         */
11002ee35494Smrg	HASH_FIND(handle_hh, bufmgr_gem->handle_table,
11012ee35494Smrg		  &open_arg.handle, sizeof(open_arg.handle), bo_gem);
11022ee35494Smrg	if (bo_gem) {
11032ee35494Smrg		drm_intel_gem_bo_reference(&bo_gem->bo);
11042ee35494Smrg		goto out;
110520131375Smrg	}
110620131375Smrg
110720131375Smrg	bo_gem = calloc(1, sizeof(*bo_gem));
11082ee35494Smrg	if (!bo_gem)
11092ee35494Smrg		goto out;
11102ee35494Smrg
11112ee35494Smrg	atomic_set(&bo_gem->refcount, 1);
11122ee35494Smrg	DRMINITLISTHEAD(&bo_gem->vma_list);
111320131375Smrg
111422944501Smrg	bo_gem->bo.size = open_arg.size;
111522944501Smrg	bo_gem->bo.offset = 0;
111620131375Smrg	bo_gem->bo.offset64 = 0;
111722944501Smrg	bo_gem->bo.virtual = NULL;
111822944501Smrg	bo_gem->bo.bufmgr = bufmgr;
111922944501Smrg	bo_gem->name = name;
112022944501Smrg	bo_gem->validate_index = -1;
112122944501Smrg	bo_gem->gem_handle = open_arg.handle;
112220131375Smrg	bo_gem->bo.handle = open_arg.handle;
112322944501Smrg	bo_gem->global_name = handle;
112420131375Smrg	bo_gem->reusable = false;
112522944501Smrg
11262ee35494Smrg	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
11272ee35494Smrg		 gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
11282ee35494Smrg	HASH_ADD(name_hh, bufmgr_gem->name_table,
11292ee35494Smrg		 global_name, sizeof(bo_gem->global_name), bo_gem);
11302ee35494Smrg
113187bf8e7cSmrg	ret = get_tiling_mode(bufmgr_gem, bo_gem->gem_handle,
113287bf8e7cSmrg			      &bo_gem->tiling_mode, &bo_gem->swizzle_mode);
11332ee35494Smrg	if (ret != 0)
11342ee35494Smrg		goto err_unref;
11352ee35494Smrg
11366d98c517Smrg	/* XXX stride is unknown */
1137fe517fc9Smrg	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
113822944501Smrg	DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
113922944501Smrg
11402ee35494Smrgout:
11412ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
114222944501Smrg	return &bo_gem->bo;
11432ee35494Smrg
11442ee35494Smrgerr_unref:
11452ee35494Smrg	drm_intel_gem_bo_free(&bo_gem->bo);
11462ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
11472ee35494Smrg	return NULL;
114822944501Smrg}
114922944501Smrg
115022944501Smrgstatic void
115122944501Smrgdrm_intel_gem_bo_free(drm_intel_bo *bo)
115222944501Smrg{
115322944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
115422944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
115522944501Smrg	int ret;
115622944501Smrg
115720131375Smrg	DRMLISTDEL(&bo_gem->vma_list);
115820131375Smrg	if (bo_gem->mem_virtual) {
115920131375Smrg		VG(VALGRIND_FREELIKE_BLOCK(bo_gem->mem_virtual, 0));
1160a884aba1Smrg		drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
116120131375Smrg		bufmgr_gem->vma_count--;
116220131375Smrg	}
11632ee35494Smrg	if (bo_gem->wc_virtual) {
11642ee35494Smrg		VG(VALGRIND_FREELIKE_BLOCK(bo_gem->wc_virtual, 0));
11652ee35494Smrg		drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
11662ee35494Smrg		bufmgr_gem->vma_count--;
11672ee35494Smrg	}
116820131375Smrg	if (bo_gem->gtt_virtual) {
1169a884aba1Smrg		drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
117020131375Smrg		bufmgr_gem->vma_count--;
117120131375Smrg	}
117222944501Smrg
11732ee35494Smrg	if (bo_gem->global_name)
11742ee35494Smrg		HASH_DELETE(name_hh, bufmgr_gem->name_table, bo_gem);
11752ee35494Smrg	HASH_DELETE(handle_hh, bufmgr_gem->handle_table, bo_gem);
11762ee35494Smrg
117722944501Smrg	/* Close this object */
1178adfa0b0cSmrg	ret = drmCloseBufferHandle(bufmgr_gem->fd, bo_gem->gem_handle);
117922944501Smrg	if (ret != 0) {
1180adfa0b0cSmrg		DBG("drmCloseBufferHandle %d failed (%s): %s\n",
11819ce4edccSmrg		    bo_gem->gem_handle, bo_gem->name, strerror(errno));
118222944501Smrg	}
118322944501Smrg	free(bo);
118422944501Smrg}
118522944501Smrg
118620131375Smrgstatic void
118720131375Smrgdrm_intel_gem_bo_mark_mmaps_incoherent(drm_intel_bo *bo)
118820131375Smrg{
118920131375Smrg#if HAVE_VALGRIND
119020131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
119120131375Smrg
119220131375Smrg	if (bo_gem->mem_virtual)
119320131375Smrg		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size);
119420131375Smrg
11952ee35494Smrg	if (bo_gem->wc_virtual)
11962ee35494Smrg		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->wc_virtual, bo->size);
11972ee35494Smrg
119820131375Smrg	if (bo_gem->gtt_virtual)
119920131375Smrg		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size);
120020131375Smrg#endif
120120131375Smrg}
120220131375Smrg
120322944501Smrg/** Frees all cached buffers significantly older than @time. */
120422944501Smrgstatic void
120522944501Smrgdrm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time)
120622944501Smrg{
120722944501Smrg	int i;
120822944501Smrg
12096d98c517Smrg	if (bufmgr_gem->time == time)
12106d98c517Smrg		return;
12116d98c517Smrg
1212aaba2545Smrg	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
121322944501Smrg		struct drm_intel_gem_bo_bucket *bucket =
121422944501Smrg		    &bufmgr_gem->cache_bucket[i];
121522944501Smrg
121622944501Smrg		while (!DRMLISTEMPTY(&bucket->head)) {
121722944501Smrg			drm_intel_bo_gem *bo_gem;
121822944501Smrg
121922944501Smrg			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
122022944501Smrg					      bucket->head.next, head);
122122944501Smrg			if (time - bo_gem->free_time <= 1)
122222944501Smrg				break;
122322944501Smrg
122422944501Smrg			DRMLISTDEL(&bo_gem->head);
122522944501Smrg
122622944501Smrg			drm_intel_gem_bo_free(&bo_gem->bo);
122722944501Smrg		}
122822944501Smrg	}
12296d98c517Smrg
12306d98c517Smrg	bufmgr_gem->time = time;
123122944501Smrg}
123222944501Smrg
123320131375Smrgstatic void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem)
123420131375Smrg{
123520131375Smrg	int limit;
123620131375Smrg
123720131375Smrg	DBG("%s: cached=%d, open=%d, limit=%d\n", __FUNCTION__,
123820131375Smrg	    bufmgr_gem->vma_count, bufmgr_gem->vma_open, bufmgr_gem->vma_max);
123920131375Smrg
124020131375Smrg	if (bufmgr_gem->vma_max < 0)
124120131375Smrg		return;
124220131375Smrg
124320131375Smrg	/* We may need to evict a few entries in order to create new mmaps */
124420131375Smrg	limit = bufmgr_gem->vma_max - 2*bufmgr_gem->vma_open;
124520131375Smrg	if (limit < 0)
124620131375Smrg		limit = 0;
124720131375Smrg
124820131375Smrg	while (bufmgr_gem->vma_count > limit) {
124920131375Smrg		drm_intel_bo_gem *bo_gem;
125020131375Smrg
125120131375Smrg		bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
125220131375Smrg				      bufmgr_gem->vma_cache.next,
125320131375Smrg				      vma_list);
125420131375Smrg		assert(bo_gem->map_count == 0);
125520131375Smrg		DRMLISTDELINIT(&bo_gem->vma_list);
125620131375Smrg
125720131375Smrg		if (bo_gem->mem_virtual) {
1258a884aba1Smrg			drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
125920131375Smrg			bo_gem->mem_virtual = NULL;
126020131375Smrg			bufmgr_gem->vma_count--;
126120131375Smrg		}
12622ee35494Smrg		if (bo_gem->wc_virtual) {
12632ee35494Smrg			drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
12642ee35494Smrg			bo_gem->wc_virtual = NULL;
12652ee35494Smrg			bufmgr_gem->vma_count--;
12662ee35494Smrg		}
126720131375Smrg		if (bo_gem->gtt_virtual) {
1268a884aba1Smrg			drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
126920131375Smrg			bo_gem->gtt_virtual = NULL;
127020131375Smrg			bufmgr_gem->vma_count--;
127120131375Smrg		}
127220131375Smrg	}
127320131375Smrg}
127420131375Smrg
127520131375Smrgstatic void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem,
127620131375Smrg				       drm_intel_bo_gem *bo_gem)
127720131375Smrg{
127820131375Smrg	bufmgr_gem->vma_open--;
127920131375Smrg	DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache);
128020131375Smrg	if (bo_gem->mem_virtual)
128120131375Smrg		bufmgr_gem->vma_count++;
12822ee35494Smrg	if (bo_gem->wc_virtual)
12832ee35494Smrg		bufmgr_gem->vma_count++;
128420131375Smrg	if (bo_gem->gtt_virtual)
128520131375Smrg		bufmgr_gem->vma_count++;
128620131375Smrg	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
128720131375Smrg}
128820131375Smrg
128920131375Smrgstatic void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem,
129020131375Smrg				      drm_intel_bo_gem *bo_gem)
129120131375Smrg{
129220131375Smrg	bufmgr_gem->vma_open++;
129320131375Smrg	DRMLISTDEL(&bo_gem->vma_list);
129420131375Smrg	if (bo_gem->mem_virtual)
129520131375Smrg		bufmgr_gem->vma_count--;
12962ee35494Smrg	if (bo_gem->wc_virtual)
12972ee35494Smrg		bufmgr_gem->vma_count--;
129820131375Smrg	if (bo_gem->gtt_virtual)
129920131375Smrg		bufmgr_gem->vma_count--;
130020131375Smrg	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
130120131375Smrg}
130220131375Smrg
130322944501Smrgstatic void
130422944501Smrgdrm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time)
130522944501Smrg{
130622944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
130722944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
130822944501Smrg	struct drm_intel_gem_bo_bucket *bucket;
130922944501Smrg	int i;
131022944501Smrg
131122944501Smrg	/* Unreference all the target buffers */
131222944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++) {
1313aaba2545Smrg		if (bo_gem->reloc_target_info[i].bo != bo) {
1314aaba2545Smrg			drm_intel_gem_bo_unreference_locked_timed(bo_gem->
1315aaba2545Smrg								  reloc_target_info[i].bo,
1316aaba2545Smrg								  time);
1317aaba2545Smrg		}
131822944501Smrg	}
1319fe517fc9Smrg	for (i = 0; i < bo_gem->softpin_target_count; i++)
1320fe517fc9Smrg		drm_intel_gem_bo_unreference_locked_timed(bo_gem->softpin_target[i],
1321fe517fc9Smrg								  time);
13222ee35494Smrg	bo_gem->kflags = 0;
132322944501Smrg	bo_gem->reloc_count = 0;
132420131375Smrg	bo_gem->used_as_reloc_target = false;
1325fe517fc9Smrg	bo_gem->softpin_target_count = 0;
132622944501Smrg
132722944501Smrg	DBG("bo_unreference final: %d (%s)\n",
132822944501Smrg	    bo_gem->gem_handle, bo_gem->name);
132922944501Smrg
133022944501Smrg	/* release memory associated with this object */
133122944501Smrg	if (bo_gem->reloc_target_info) {
133222944501Smrg		free(bo_gem->reloc_target_info);
133322944501Smrg		bo_gem->reloc_target_info = NULL;
133422944501Smrg	}
133522944501Smrg	if (bo_gem->relocs) {
133622944501Smrg		free(bo_gem->relocs);
133722944501Smrg		bo_gem->relocs = NULL;
133822944501Smrg	}
1339fe517fc9Smrg	if (bo_gem->softpin_target) {
1340fe517fc9Smrg		free(bo_gem->softpin_target);
1341fe517fc9Smrg		bo_gem->softpin_target = NULL;
1342fe517fc9Smrg		bo_gem->softpin_target_size = 0;
1343fe517fc9Smrg	}
134422944501Smrg
134520131375Smrg	/* Clear any left-over mappings */
134620131375Smrg	if (bo_gem->map_count) {
134720131375Smrg		DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count);
134820131375Smrg		bo_gem->map_count = 0;
134920131375Smrg		drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
135020131375Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
135120131375Smrg	}
135220131375Smrg
135322944501Smrg	bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
135422944501Smrg	/* Put the buffer into our internal cache for reuse if we can. */
135522944501Smrg	if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL &&
135622944501Smrg	    drm_intel_gem_bo_madvise_internal(bufmgr_gem, bo_gem,
135722944501Smrg					      I915_MADV_DONTNEED)) {
135822944501Smrg		bo_gem->free_time = time;
135922944501Smrg
136022944501Smrg		bo_gem->name = NULL;
136122944501Smrg		bo_gem->validate_index = -1;
136222944501Smrg
136322944501Smrg		DRMLISTADDTAIL(&bo_gem->head, &bucket->head);
136422944501Smrg	} else {
136522944501Smrg		drm_intel_gem_bo_free(bo);
136622944501Smrg	}
136722944501Smrg}
136822944501Smrg
136922944501Smrgstatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo,
137022944501Smrg						      time_t time)
137122944501Smrg{
137222944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
137322944501Smrg
137422944501Smrg	assert(atomic_read(&bo_gem->refcount) > 0);
137522944501Smrg	if (atomic_dec_and_test(&bo_gem->refcount))
137622944501Smrg		drm_intel_gem_bo_unreference_final(bo, time);
137722944501Smrg}
137822944501Smrg
137922944501Smrgstatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo)
138022944501Smrg{
138122944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
13823b115362Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
13833b115362Smrg	struct timespec time;
138422944501Smrg
138522944501Smrg	assert(atomic_read(&bo_gem->refcount) > 0);
1386a884aba1Smrg
13873b115362Smrg	if (atomic_add_unless(&bo_gem->refcount, -1, 1))
13883b115362Smrg		return;
138922944501Smrg
13903b115362Smrg	bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
139122944501Smrg
13923b115362Smrg	clock_gettime(CLOCK_MONOTONIC, &time);
1393a884aba1Smrg
13943b115362Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
1395a884aba1Smrg
13963b115362Smrg	if (atomic_dec_and_test(&bo_gem->refcount)) {
13973b115362Smrg		drm_intel_gem_bo_unreference_final(bo, time.tv_sec);
13983b115362Smrg		drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec);
139922944501Smrg	}
14003b115362Smrg
14013b115362Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
140222944501Smrg}
140322944501Smrg
140422944501Smrgstatic int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
140522944501Smrg{
140622944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
140722944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
140822944501Smrg	struct drm_i915_gem_set_domain set_domain;
140922944501Smrg	int ret;
141022944501Smrg
1411a884aba1Smrg	if (bo_gem->is_userptr) {
1412a884aba1Smrg		/* Return the same user ptr */
1413a884aba1Smrg		bo->virtual = bo_gem->user_virtual;
1414a884aba1Smrg		return 0;
1415a884aba1Smrg	}
1416a884aba1Smrg
141722944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
141822944501Smrg
141920131375Smrg	if (bo_gem->map_count++ == 0)
142020131375Smrg		drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
142120131375Smrg
142222944501Smrg	if (!bo_gem->mem_virtual) {
142322944501Smrg		struct drm_i915_gem_mmap mmap_arg;
142422944501Smrg
142520131375Smrg		DBG("bo_map: %d (%s), map_count=%d\n",
142620131375Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
142722944501Smrg
1428424e9256Smrg		memclear(mmap_arg);
142922944501Smrg		mmap_arg.handle = bo_gem->gem_handle;
143022944501Smrg		mmap_arg.size = bo->size;
14316d98c517Smrg		ret = drmIoctl(bufmgr_gem->fd,
14326d98c517Smrg			       DRM_IOCTL_I915_GEM_MMAP,
14336d98c517Smrg			       &mmap_arg);
143422944501Smrg		if (ret != 0) {
143522944501Smrg			ret = -errno;
14369ce4edccSmrg			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
14379ce4edccSmrg			    __FILE__, __LINE__, bo_gem->gem_handle,
14389ce4edccSmrg			    bo_gem->name, strerror(errno));
143920131375Smrg			if (--bo_gem->map_count == 0)
144020131375Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
144122944501Smrg			pthread_mutex_unlock(&bufmgr_gem->lock);
144222944501Smrg			return ret;
144322944501Smrg		}
144420131375Smrg		VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
144522944501Smrg		bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
144622944501Smrg	}
144722944501Smrg	DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
144822944501Smrg	    bo_gem->mem_virtual);
144922944501Smrg	bo->virtual = bo_gem->mem_virtual;
145022944501Smrg
1451424e9256Smrg	memclear(set_domain);
145222944501Smrg	set_domain.handle = bo_gem->gem_handle;
145322944501Smrg	set_domain.read_domains = I915_GEM_DOMAIN_CPU;
145422944501Smrg	if (write_enable)
145522944501Smrg		set_domain.write_domain = I915_GEM_DOMAIN_CPU;
145622944501Smrg	else
145722944501Smrg		set_domain.write_domain = 0;
14586d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
14596d98c517Smrg		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
14606d98c517Smrg		       &set_domain);
146122944501Smrg	if (ret != 0) {
14629ce4edccSmrg		DBG("%s:%d: Error setting to CPU domain %d: %s\n",
14639ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle,
14649ce4edccSmrg		    strerror(errno));
146522944501Smrg	}
146622944501Smrg
146720131375Smrg	if (write_enable)
146820131375Smrg		bo_gem->mapped_cpu_write = true;
146920131375Smrg
147020131375Smrg	drm_intel_gem_bo_mark_mmaps_incoherent(bo);
147120131375Smrg	VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->mem_virtual, bo->size));
147222944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
147322944501Smrg
147422944501Smrg	return 0;
147522944501Smrg}
147622944501Smrg
147720131375Smrgstatic int
147820131375Smrgmap_gtt(drm_intel_bo *bo)
147922944501Smrg{
148022944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
148122944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
148222944501Smrg	int ret;
148322944501Smrg
1484a884aba1Smrg	if (bo_gem->is_userptr)
1485a884aba1Smrg		return -EINVAL;
1486a884aba1Smrg
148720131375Smrg	if (bo_gem->map_count++ == 0)
148820131375Smrg		drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
148922944501Smrg
149022944501Smrg	/* Get a mapping of the buffer if we haven't before. */
149122944501Smrg	if (bo_gem->gtt_virtual == NULL) {
149222944501Smrg		struct drm_i915_gem_mmap_gtt mmap_arg;
149322944501Smrg
149420131375Smrg		DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
149520131375Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
149622944501Smrg
1497424e9256Smrg		memclear(mmap_arg);
149822944501Smrg		mmap_arg.handle = bo_gem->gem_handle;
149922944501Smrg
150022944501Smrg		/* Get the fake offset back... */
15016d98c517Smrg		ret = drmIoctl(bufmgr_gem->fd,
15026d98c517Smrg			       DRM_IOCTL_I915_GEM_MMAP_GTT,
15036d98c517Smrg			       &mmap_arg);
150422944501Smrg		if (ret != 0) {
150522944501Smrg			ret = -errno;
15069ce4edccSmrg			DBG("%s:%d: Error preparing buffer map %d (%s): %s .\n",
15079ce4edccSmrg			    __FILE__, __LINE__,
15089ce4edccSmrg			    bo_gem->gem_handle, bo_gem->name,
15099ce4edccSmrg			    strerror(errno));
151020131375Smrg			if (--bo_gem->map_count == 0)
151120131375Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
151222944501Smrg			return ret;
151322944501Smrg		}
151422944501Smrg
151522944501Smrg		/* and mmap it */
1516fd815b59Smaya		bo_gem->gtt_virtual = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE,
1517fd815b59Smaya					       MAP_SHARED, bufmgr_gem->fd,
1518fd815b59Smaya					       mmap_arg.offset);
1519d6e8b34dStnn		if (bo_gem->gtt_virtual == MAP_FAILED) {
152022944501Smrg			bo_gem->gtt_virtual = NULL;
1521d6e8b34dStnn			ret = -errno;
15229ce4edccSmrg			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
15239ce4edccSmrg			    __FILE__, __LINE__,
15249ce4edccSmrg			    bo_gem->gem_handle, bo_gem->name,
15259ce4edccSmrg			    strerror(errno));
152620131375Smrg			if (--bo_gem->map_count == 0)
152720131375Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
152822944501Smrg			return ret;
152922944501Smrg		}
153022944501Smrg	}
153122944501Smrg
153222944501Smrg	bo->virtual = bo_gem->gtt_virtual;
153322944501Smrg
153422944501Smrg	DBG("bo_map_gtt: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
153522944501Smrg	    bo_gem->gtt_virtual);
153622944501Smrg
153720131375Smrg	return 0;
153820131375Smrg}
153920131375Smrg
15406260e5d5Smrgdrm_public int
1541a884aba1Smrgdrm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
154220131375Smrg{
154320131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
154420131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
154520131375Smrg	struct drm_i915_gem_set_domain set_domain;
154620131375Smrg	int ret;
154720131375Smrg
154820131375Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
154920131375Smrg
155020131375Smrg	ret = map_gtt(bo);
155120131375Smrg	if (ret) {
155220131375Smrg		pthread_mutex_unlock(&bufmgr_gem->lock);
155320131375Smrg		return ret;
155420131375Smrg	}
155520131375Smrg
155620131375Smrg	/* Now move it to the GTT domain so that the GPU and CPU
155720131375Smrg	 * caches are flushed and the GPU isn't actively using the
155820131375Smrg	 * buffer.
155920131375Smrg	 *
156020131375Smrg	 * The pagefault handler does this domain change for us when
156120131375Smrg	 * it has unbound the BO from the GTT, but it's up to us to
156220131375Smrg	 * tell it when we're about to use things if we had done
156320131375Smrg	 * rendering and it still happens to be bound to the GTT.
156420131375Smrg	 */
1565424e9256Smrg	memclear(set_domain);
156622944501Smrg	set_domain.handle = bo_gem->gem_handle;
156722944501Smrg	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
156822944501Smrg	set_domain.write_domain = I915_GEM_DOMAIN_GTT;
15696d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
15706d98c517Smrg		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
15716d98c517Smrg		       &set_domain);
157222944501Smrg	if (ret != 0) {
15739ce4edccSmrg		DBG("%s:%d: Error setting domain %d: %s\n",
15749ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle,
15759ce4edccSmrg		    strerror(errno));
157622944501Smrg	}
157722944501Smrg
157820131375Smrg	drm_intel_gem_bo_mark_mmaps_incoherent(bo);
157920131375Smrg	VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size));
158022944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
158122944501Smrg
15826d98c517Smrg	return 0;
158322944501Smrg}
158422944501Smrg
158520131375Smrg/**
158620131375Smrg * Performs a mapping of the buffer object like the normal GTT
158720131375Smrg * mapping, but avoids waiting for the GPU to be done reading from or
158820131375Smrg * rendering to the buffer.
158920131375Smrg *
159020131375Smrg * This is used in the implementation of GL_ARB_map_buffer_range: The
159120131375Smrg * user asks to create a buffer, then does a mapping, fills some
159220131375Smrg * space, runs a drawing command, then asks to map it again without
159320131375Smrg * synchronizing because it guarantees that it won't write over the
159420131375Smrg * data that the GPU is busy using (or, more specifically, that if it
159520131375Smrg * does write over the data, it acknowledges that rendering is
159620131375Smrg * undefined).
159720131375Smrg */
159820131375Smrg
15996260e5d5Smrgdrm_public int
1600a884aba1Smrgdrm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo)
160122944501Smrg{
160222944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
16032b90624aSmrg#if HAVE_VALGRIND
160420131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
160520131375Smrg#endif
160620131375Smrg	int ret;
160722944501Smrg
160820131375Smrg	/* If the CPU cache isn't coherent with the GTT, then use a
160920131375Smrg	 * regular synchronized mapping.  The problem is that we don't
161020131375Smrg	 * track where the buffer was last used on the CPU side in
161120131375Smrg	 * terms of drm_intel_bo_map vs drm_intel_gem_bo_map_gtt, so
161220131375Smrg	 * we would potentially corrupt the buffer even when the user
161320131375Smrg	 * does reasonable things.
161420131375Smrg	 */
161520131375Smrg	if (!bufmgr_gem->has_llc)
161620131375Smrg		return drm_intel_gem_bo_map_gtt(bo);
161722944501Smrg
161822944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
161920131375Smrg
162020131375Smrg	ret = map_gtt(bo);
162120131375Smrg	if (ret == 0) {
162220131375Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
162320131375Smrg		VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size));
162420131375Smrg	}
162520131375Smrg
162622944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
162722944501Smrg
162822944501Smrg	return ret;
162922944501Smrg}
163022944501Smrg
163122944501Smrgstatic int drm_intel_gem_bo_unmap(drm_intel_bo *bo)
163222944501Smrg{
1633a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
163422944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
163520131375Smrg	int ret = 0;
163622944501Smrg
163722944501Smrg	if (bo == NULL)
163822944501Smrg		return 0;
163922944501Smrg
1640a884aba1Smrg	if (bo_gem->is_userptr)
1641a884aba1Smrg		return 0;
1642a884aba1Smrg
1643a884aba1Smrg	bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
1644a884aba1Smrg
164522944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
164622944501Smrg
164720131375Smrg	if (bo_gem->map_count <= 0) {
164820131375Smrg		DBG("attempted to unmap an unmapped bo\n");
164920131375Smrg		pthread_mutex_unlock(&bufmgr_gem->lock);
165020131375Smrg		/* Preserve the old behaviour of just treating this as a
165120131375Smrg		 * no-op rather than reporting the error.
165220131375Smrg		 */
165320131375Smrg		return 0;
165420131375Smrg	}
165520131375Smrg
165620131375Smrg	if (bo_gem->mapped_cpu_write) {
165720131375Smrg		struct drm_i915_gem_sw_finish sw_finish;
165820131375Smrg
165920131375Smrg		/* Cause a flush to happen if the buffer's pinned for
166020131375Smrg		 * scanout, so the results show up in a timely manner.
166120131375Smrg		 * Unlike GTT set domains, this only does work if the
166220131375Smrg		 * buffer should be scanout-related.
166320131375Smrg		 */
1664424e9256Smrg		memclear(sw_finish);
166520131375Smrg		sw_finish.handle = bo_gem->gem_handle;
166620131375Smrg		ret = drmIoctl(bufmgr_gem->fd,
166720131375Smrg			       DRM_IOCTL_I915_GEM_SW_FINISH,
166820131375Smrg			       &sw_finish);
166920131375Smrg		ret = ret == -1 ? -errno : 0;
167020131375Smrg
167120131375Smrg		bo_gem->mapped_cpu_write = false;
167220131375Smrg	}
167322944501Smrg
167420131375Smrg	/* We need to unmap after every innovation as we cannot track
16752ee35494Smrg	 * an open vma for every bo as that will exhaust the system
167620131375Smrg	 * limits and cause later failures.
167720131375Smrg	 */
167820131375Smrg	if (--bo_gem->map_count == 0) {
167920131375Smrg		drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
168020131375Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
168120131375Smrg		bo->virtual = NULL;
168220131375Smrg	}
168322944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
168422944501Smrg
168522944501Smrg	return ret;
168622944501Smrg}
168722944501Smrg
16886260e5d5Smrgdrm_public int
1689a884aba1Smrgdrm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo)
169020131375Smrg{
169120131375Smrg	return drm_intel_gem_bo_unmap(bo);
169220131375Smrg}
169320131375Smrg
16944b3d3f37Smrgstatic bool is_cache_coherent(drm_intel_bo *bo)
16954b3d3f37Smrg{
16964b3d3f37Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
16974b3d3f37Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
16984b3d3f37Smrg	struct drm_i915_gem_caching arg = {};
16994b3d3f37Smrg
17004b3d3f37Smrg	arg.handle = bo_gem->gem_handle;
17014b3d3f37Smrg	if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_CACHING, &arg))
17024b3d3f37Smrg		assert(false);
17034b3d3f37Smrg	return arg.caching != I915_CACHING_NONE;
17044b3d3f37Smrg}
17054b3d3f37Smrg
17064b3d3f37Smrgstatic void set_domain(drm_intel_bo *bo, uint32_t read, uint32_t write)
17074b3d3f37Smrg{
17084b3d3f37Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
17094b3d3f37Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
17104b3d3f37Smrg	struct drm_i915_gem_set_domain arg = {};
17114b3d3f37Smrg
17124b3d3f37Smrg	arg.handle = bo_gem->gem_handle;
17134b3d3f37Smrg	arg.read_domains = read;
17144b3d3f37Smrg	arg.write_domain = write;
17154b3d3f37Smrg	if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &arg))
17164b3d3f37Smrg		assert(false);
17174b3d3f37Smrg}
17184b3d3f37Smrg
17194b3d3f37Smrgstatic int mmap_write(drm_intel_bo *bo, unsigned long offset,
17204b3d3f37Smrg		      unsigned long length, const void *buf)
17214b3d3f37Smrg{
17224b3d3f37Smrg	void *map = NULL;
17234b3d3f37Smrg
17244b3d3f37Smrg	if (!length)
17254b3d3f37Smrg		return 0;
17264b3d3f37Smrg
17274b3d3f37Smrg	if (is_cache_coherent(bo)) {
17284b3d3f37Smrg		map = drm_intel_gem_bo_map__cpu(bo);
17294b3d3f37Smrg		if (map)
17304b3d3f37Smrg			set_domain(bo, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
17314b3d3f37Smrg	}
17324b3d3f37Smrg	if (!map) {
17334b3d3f37Smrg		map = drm_intel_gem_bo_map__wc(bo);
17344b3d3f37Smrg		if (map)
17354b3d3f37Smrg			set_domain(bo, I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
17364b3d3f37Smrg	}
17374b3d3f37Smrg
17384b3d3f37Smrg	assert(map);
17394b3d3f37Smrg	memcpy((char *)map + offset, buf, length);
17404b3d3f37Smrg	drm_intel_gem_bo_unmap(bo);
17414b3d3f37Smrg	return 0;
17424b3d3f37Smrg}
17434b3d3f37Smrg
17444b3d3f37Smrgstatic int mmap_read(drm_intel_bo *bo, unsigned long offset,
17454b3d3f37Smrg		      unsigned long length, void *buf)
17464b3d3f37Smrg{
17474b3d3f37Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
17484b3d3f37Smrg	void *map = NULL;
17494b3d3f37Smrg
17504b3d3f37Smrg	if (!length)
17514b3d3f37Smrg		return 0;
17524b3d3f37Smrg
17534b3d3f37Smrg	if (bufmgr_gem->has_llc || is_cache_coherent(bo)) {
17544b3d3f37Smrg		map = drm_intel_gem_bo_map__cpu(bo);
17554b3d3f37Smrg		if (map)
17564b3d3f37Smrg			set_domain(bo, I915_GEM_DOMAIN_CPU, 0);
17574b3d3f37Smrg	}
17584b3d3f37Smrg	if (!map) {
17594b3d3f37Smrg		map = drm_intel_gem_bo_map__wc(bo);
17604b3d3f37Smrg		if (map)
17614b3d3f37Smrg			set_domain(bo, I915_GEM_DOMAIN_WC, 0);
17624b3d3f37Smrg	}
17634b3d3f37Smrg
17644b3d3f37Smrg	assert(map);
17654b3d3f37Smrg	memcpy(buf, (char *)map + offset, length);
17664b3d3f37Smrg	drm_intel_gem_bo_unmap(bo);
17674b3d3f37Smrg	return 0;
17684b3d3f37Smrg}
17694b3d3f37Smrg
177022944501Smrgstatic int
177122944501Smrgdrm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset,
177222944501Smrg			 unsigned long size, const void *data)
177322944501Smrg{
177422944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
177522944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
177622944501Smrg	struct drm_i915_gem_pwrite pwrite;
177722944501Smrg	int ret;
177822944501Smrg
1779a884aba1Smrg	if (bo_gem->is_userptr)
1780a884aba1Smrg		return -EINVAL;
1781a884aba1Smrg
1782424e9256Smrg	memclear(pwrite);
178322944501Smrg	pwrite.handle = bo_gem->gem_handle;
178422944501Smrg	pwrite.offset = offset;
178522944501Smrg	pwrite.size = size;
178622944501Smrg	pwrite.data_ptr = (uint64_t) (uintptr_t) data;
17876d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
17886d98c517Smrg		       DRM_IOCTL_I915_GEM_PWRITE,
17896d98c517Smrg		       &pwrite);
17904b3d3f37Smrg	if (ret)
179122944501Smrg		ret = -errno;
17924b3d3f37Smrg
17934b3d3f37Smrg	if (ret != 0 && ret != -EOPNOTSUPP) {
17949ce4edccSmrg		DBG("%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
17959ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
17969ce4edccSmrg		    (int)size, strerror(errno));
17974b3d3f37Smrg		return ret;
179822944501Smrg	}
179922944501Smrg
18004b3d3f37Smrg	if (ret == -EOPNOTSUPP)
18014b3d3f37Smrg		mmap_write(bo, offset, size, data);
18024b3d3f37Smrg
18034b3d3f37Smrg	return 0;
180422944501Smrg}
180522944501Smrg
180622944501Smrgstatic int
180722944501Smrgdrm_intel_gem_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id)
180822944501Smrg{
180922944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
181022944501Smrg	struct drm_i915_get_pipe_from_crtc_id get_pipe_from_crtc_id;
181122944501Smrg	int ret;
181222944501Smrg
1813424e9256Smrg	memclear(get_pipe_from_crtc_id);
181422944501Smrg	get_pipe_from_crtc_id.crtc_id = crtc_id;
18156d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
18166d98c517Smrg		       DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID,
18176d98c517Smrg		       &get_pipe_from_crtc_id);
181822944501Smrg	if (ret != 0) {
181922944501Smrg		/* We return -1 here to signal that we don't
182022944501Smrg		 * know which pipe is associated with this crtc.
182122944501Smrg		 * This lets the caller know that this information
182222944501Smrg		 * isn't available; using the wrong pipe for
182322944501Smrg		 * vblank waiting can cause the chipset to lock up
182422944501Smrg		 */
182522944501Smrg		return -1;
182622944501Smrg	}
182722944501Smrg
182822944501Smrg	return get_pipe_from_crtc_id.pipe;
182922944501Smrg}
183022944501Smrg
183122944501Smrgstatic int
183222944501Smrgdrm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset,
183322944501Smrg			     unsigned long size, void *data)
183422944501Smrg{
183522944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
183622944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
183722944501Smrg	struct drm_i915_gem_pread pread;
183822944501Smrg	int ret;
183922944501Smrg
1840a884aba1Smrg	if (bo_gem->is_userptr)
1841a884aba1Smrg		return -EINVAL;
1842a884aba1Smrg
1843424e9256Smrg	memclear(pread);
184422944501Smrg	pread.handle = bo_gem->gem_handle;
184522944501Smrg	pread.offset = offset;
184622944501Smrg	pread.size = size;
184722944501Smrg	pread.data_ptr = (uint64_t) (uintptr_t) data;
18486d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
18496d98c517Smrg		       DRM_IOCTL_I915_GEM_PREAD,
18506d98c517Smrg		       &pread);
18514b3d3f37Smrg	if (ret)
185222944501Smrg		ret = -errno;
18534b3d3f37Smrg
18544b3d3f37Smrg	if (ret != 0 && ret != -EOPNOTSUPP) {
18559ce4edccSmrg		DBG("%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
18569ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
18579ce4edccSmrg		    (int)size, strerror(errno));
18584b3d3f37Smrg		return ret;
185922944501Smrg	}
186022944501Smrg
18614b3d3f37Smrg	if (ret == -EOPNOTSUPP)
18624b3d3f37Smrg		mmap_read(bo, offset, size, data);
18634b3d3f37Smrg
18644b3d3f37Smrg	return 0;
186522944501Smrg}
186622944501Smrg
18679ce4edccSmrg/** Waits for all GPU rendering with the object to have completed. */
186822944501Smrgstatic void
186922944501Smrgdrm_intel_gem_bo_wait_rendering(drm_intel_bo *bo)
187022944501Smrg{
18719ce4edccSmrg	drm_intel_gem_bo_start_gtt_access(bo, 1);
187222944501Smrg}
187322944501Smrg
187420131375Smrg/**
187520131375Smrg * Waits on a BO for the given amount of time.
187620131375Smrg *
187720131375Smrg * @bo: buffer object to wait for
187820131375Smrg * @timeout_ns: amount of time to wait in nanoseconds.
187920131375Smrg *   If value is less than 0, an infinite wait will occur.
188020131375Smrg *
188120131375Smrg * Returns 0 if the wait was successful ie. the last batch referencing the
188220131375Smrg * object has completed within the allotted time. Otherwise some negative return
188320131375Smrg * value describes the error. Of particular interest is -ETIME when the wait has
188420131375Smrg * failed to yield the desired result.
188520131375Smrg *
188620131375Smrg * Similar to drm_intel_gem_bo_wait_rendering except a timeout parameter allows
188720131375Smrg * the operation to give up after a certain amount of time. Another subtle
188820131375Smrg * difference is the internal locking semantics are different (this variant does
188920131375Smrg * not hold the lock for the duration of the wait). This makes the wait subject
189020131375Smrg * to a larger userspace race window.
189120131375Smrg *
189220131375Smrg * The implementation shall wait until the object is no longer actively
189320131375Smrg * referenced within a batch buffer at the time of the call. The wait will
189420131375Smrg * not guarantee that the buffer is re-issued via another thread, or an flinked
189520131375Smrg * handle. Userspace must make sure this race does not occur if such precision
189620131375Smrg * is important.
1897424e9256Smrg *
1898424e9256Smrg * Note that some kernels have broken the inifite wait for negative values
1899424e9256Smrg * promise, upgrade to latest stable kernels if this is the case.
190020131375Smrg */
19016260e5d5Smrgdrm_public int
1902a884aba1Smrgdrm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns)
190320131375Smrg{
190420131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
190520131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
190620131375Smrg	struct drm_i915_gem_wait wait;
190720131375Smrg	int ret;
190820131375Smrg
190920131375Smrg	if (!bufmgr_gem->has_wait_timeout) {
191020131375Smrg		DBG("%s:%d: Timed wait is not supported. Falling back to "
191120131375Smrg		    "infinite wait\n", __FILE__, __LINE__);
191220131375Smrg		if (timeout_ns) {
191320131375Smrg			drm_intel_gem_bo_wait_rendering(bo);
191420131375Smrg			return 0;
191520131375Smrg		} else {
191620131375Smrg			return drm_intel_gem_bo_busy(bo) ? -ETIME : 0;
191720131375Smrg		}
191820131375Smrg	}
191920131375Smrg
1920424e9256Smrg	memclear(wait);
192120131375Smrg	wait.bo_handle = bo_gem->gem_handle;
192220131375Smrg	wait.timeout_ns = timeout_ns;
192320131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
192420131375Smrg	if (ret == -1)
192520131375Smrg		return -errno;
192620131375Smrg
192720131375Smrg	return ret;
192820131375Smrg}
192920131375Smrg
193022944501Smrg/**
193122944501Smrg * Sets the object to the GTT read and possibly write domain, used by the X
193222944501Smrg * 2D driver in the absence of kernel support to do drm_intel_gem_bo_map_gtt().
193322944501Smrg *
193422944501Smrg * In combination with drm_intel_gem_bo_pin() and manual fence management, we
193522944501Smrg * can do tiled pixmaps this way.
193622944501Smrg */
19376260e5d5Smrgdrm_public void
193822944501Smrgdrm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable)
193922944501Smrg{
194022944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
194122944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
194222944501Smrg	struct drm_i915_gem_set_domain set_domain;
194322944501Smrg	int ret;
194422944501Smrg
1945424e9256Smrg	memclear(set_domain);
194622944501Smrg	set_domain.handle = bo_gem->gem_handle;
194722944501Smrg	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
194822944501Smrg	set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_GTT : 0;
19496d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
19506d98c517Smrg		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
19516d98c517Smrg		       &set_domain);
195222944501Smrg	if (ret != 0) {
19539ce4edccSmrg		DBG("%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
19549ce4edccSmrg		    __FILE__, __LINE__, bo_gem->gem_handle,
19559ce4edccSmrg		    set_domain.read_domains, set_domain.write_domain,
19569ce4edccSmrg		    strerror(errno));
195722944501Smrg	}
195822944501Smrg}
195922944501Smrg
196022944501Smrgstatic void
196122944501Smrgdrm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr)
196222944501Smrg{
196322944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
1964424e9256Smrg	int i, ret;
196522944501Smrg
196622944501Smrg	free(bufmgr_gem->exec2_objects);
196722944501Smrg	free(bufmgr_gem->exec_bos);
196822944501Smrg
196922944501Smrg	pthread_mutex_destroy(&bufmgr_gem->lock);
197022944501Smrg
197122944501Smrg	/* Free any cached buffer objects we were going to reuse */
1972aaba2545Smrg	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
197322944501Smrg		struct drm_intel_gem_bo_bucket *bucket =
197422944501Smrg		    &bufmgr_gem->cache_bucket[i];
197522944501Smrg		drm_intel_bo_gem *bo_gem;
197622944501Smrg
197722944501Smrg		while (!DRMLISTEMPTY(&bucket->head)) {
197822944501Smrg			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
197922944501Smrg					      bucket->head.next, head);
198022944501Smrg			DRMLISTDEL(&bo_gem->head);
198122944501Smrg
198222944501Smrg			drm_intel_gem_bo_free(&bo_gem->bo);
198322944501Smrg		}
198422944501Smrg	}
198522944501Smrg
1986424e9256Smrg	/* Release userptr bo kept hanging around for optimisation. */
1987424e9256Smrg	if (bufmgr_gem->userptr_active.ptr) {
1988adfa0b0cSmrg		ret = drmCloseBufferHandle(bufmgr_gem->fd,
1989adfa0b0cSmrg					   bufmgr_gem->userptr_active.handle);
1990424e9256Smrg		free(bufmgr_gem->userptr_active.ptr);
1991424e9256Smrg		if (ret)
1992424e9256Smrg			fprintf(stderr,
1993424e9256Smrg				"Failed to release test userptr object! (%d) "
1994424e9256Smrg				"i915 kernel driver may not be sane!\n", errno);
1995424e9256Smrg	}
1996424e9256Smrg
199722944501Smrg	free(bufmgr);
199822944501Smrg}
199922944501Smrg
200022944501Smrg/**
200122944501Smrg * Adds the target buffer to the validation list and adds the relocation
200222944501Smrg * to the reloc_buffer's relocation list.
200322944501Smrg *
200422944501Smrg * The relocation entry at the given offset must already contain the
200522944501Smrg * precomputed relocation value, because the kernel will optimize out
200622944501Smrg * the relocation entry write when the buffer hasn't moved from the
200722944501Smrg * last known offset in target_bo.
200822944501Smrg */
200922944501Smrgstatic int
201022944501Smrgdo_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
201122944501Smrg		 drm_intel_bo *target_bo, uint32_t target_offset,
201222944501Smrg		 uint32_t read_domains, uint32_t write_domain,
201320131375Smrg		 bool need_fence)
201422944501Smrg{
201522944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
201622944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
201722944501Smrg	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
201820131375Smrg	bool fenced_command;
201922944501Smrg
202022944501Smrg	if (bo_gem->has_error)
202122944501Smrg		return -ENOMEM;
202222944501Smrg
202322944501Smrg	if (target_bo_gem->has_error) {
202420131375Smrg		bo_gem->has_error = true;
202522944501Smrg		return -ENOMEM;
202622944501Smrg	}
202722944501Smrg
202822944501Smrg	/* We never use HW fences for rendering on 965+ */
202922944501Smrg	if (bufmgr_gem->gen >= 4)
203020131375Smrg		need_fence = false;
203122944501Smrg
20329ce4edccSmrg	fenced_command = need_fence;
20339ce4edccSmrg	if (target_bo_gem->tiling_mode == I915_TILING_NONE)
203420131375Smrg		need_fence = false;
20359ce4edccSmrg
203622944501Smrg	/* Create a new relocation list if needed */
203722944501Smrg	if (bo_gem->relocs == NULL && drm_intel_setup_reloc_list(bo))
203822944501Smrg		return -ENOMEM;
203922944501Smrg
204022944501Smrg	/* Check overflow */
204122944501Smrg	assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
204222944501Smrg
204322944501Smrg	/* Check args */
204422944501Smrg	assert(offset <= bo->size - 4);
204522944501Smrg	assert((write_domain & (write_domain - 1)) == 0);
204622944501Smrg
20473c748557Ssnj	/* An object needing a fence is a tiled buffer, so it won't have
20483c748557Ssnj	 * relocs to other buffers.
20493c748557Ssnj	 */
20503c748557Ssnj	if (need_fence) {
20513c748557Ssnj		assert(target_bo_gem->reloc_count == 0);
20523c748557Ssnj		target_bo_gem->reloc_tree_fences = 1;
20533c748557Ssnj	}
20543c748557Ssnj
205522944501Smrg	/* Make sure that we're not adding a reloc to something whose size has
205622944501Smrg	 * already been accounted for.
205722944501Smrg	 */
205822944501Smrg	assert(!bo_gem->used_as_reloc_target);
2059aaba2545Smrg	if (target_bo_gem != bo_gem) {
206020131375Smrg		target_bo_gem->used_as_reloc_target = true;
2061aaba2545Smrg		bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size;
20623c748557Ssnj		bo_gem->reloc_tree_fences += target_bo_gem->reloc_tree_fences;
2063aaba2545Smrg	}
206422944501Smrg
206522944501Smrg	bo_gem->reloc_target_info[bo_gem->reloc_count].bo = target_bo;
2066aaba2545Smrg	if (target_bo != bo)
2067aaba2545Smrg		drm_intel_gem_bo_reference(target_bo);
20689ce4edccSmrg	if (fenced_command)
206922944501Smrg		bo_gem->reloc_target_info[bo_gem->reloc_count].flags =
207022944501Smrg			DRM_INTEL_RELOC_FENCE;
207122944501Smrg	else
207222944501Smrg		bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 0;
207322944501Smrg
2074fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].offset = offset;
2075fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].delta = target_offset;
2076fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].target_handle =
2077fe517fc9Smrg	    target_bo_gem->gem_handle;
2078fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
2079fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
2080fe517fc9Smrg	bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset64;
208122944501Smrg	bo_gem->reloc_count++;
208222944501Smrg
208322944501Smrg	return 0;
208422944501Smrg}
208522944501Smrg
2086fe517fc9Smrgstatic void
2087fe517fc9Smrgdrm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable)
2088fe517fc9Smrg{
2089fe517fc9Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
20900655efefSmrg
20910655efefSmrg	if (enable)
20920655efefSmrg		bo_gem->kflags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
20930655efefSmrg	else
20940655efefSmrg		bo_gem->kflags &= ~EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
2095fe517fc9Smrg}
2096fe517fc9Smrg
2097fe517fc9Smrgstatic int
2098fe517fc9Smrgdrm_intel_gem_bo_add_softpin_target(drm_intel_bo *bo, drm_intel_bo *target_bo)
2099fe517fc9Smrg{
2100fe517fc9Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
2101fe517fc9Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2102fe517fc9Smrg	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
2103fe517fc9Smrg	if (bo_gem->has_error)
2104fe517fc9Smrg		return -ENOMEM;
2105fe517fc9Smrg
2106fe517fc9Smrg	if (target_bo_gem->has_error) {
2107fe517fc9Smrg		bo_gem->has_error = true;
2108fe517fc9Smrg		return -ENOMEM;
2109fe517fc9Smrg	}
2110fe517fc9Smrg
21110655efefSmrg	if (!(target_bo_gem->kflags & EXEC_OBJECT_PINNED))
2112fe517fc9Smrg		return -EINVAL;
2113fe517fc9Smrg	if (target_bo_gem == bo_gem)
2114fe517fc9Smrg		return -EINVAL;
2115fe517fc9Smrg
2116fe517fc9Smrg	if (bo_gem->softpin_target_count == bo_gem->softpin_target_size) {
2117fe517fc9Smrg		int new_size = bo_gem->softpin_target_size * 2;
2118fe517fc9Smrg		if (new_size == 0)
2119fe517fc9Smrg			new_size = bufmgr_gem->max_relocs;
2120fe517fc9Smrg
2121fe517fc9Smrg		bo_gem->softpin_target = realloc(bo_gem->softpin_target, new_size *
2122fe517fc9Smrg				sizeof(drm_intel_bo *));
2123fe517fc9Smrg		if (!bo_gem->softpin_target)
2124fe517fc9Smrg			return -ENOMEM;
2125fe517fc9Smrg
2126fe517fc9Smrg		bo_gem->softpin_target_size = new_size;
2127fe517fc9Smrg	}
2128fe517fc9Smrg	bo_gem->softpin_target[bo_gem->softpin_target_count] = target_bo;
2129fe517fc9Smrg	drm_intel_gem_bo_reference(target_bo);
2130fe517fc9Smrg	bo_gem->softpin_target_count++;
2131fe517fc9Smrg
2132fe517fc9Smrg	return 0;
2133fe517fc9Smrg}
2134fe517fc9Smrg
213522944501Smrgstatic int
213622944501Smrgdrm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
213722944501Smrg			    drm_intel_bo *target_bo, uint32_t target_offset,
213822944501Smrg			    uint32_t read_domains, uint32_t write_domain)
213922944501Smrg{
214022944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
2141fe517fc9Smrg	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo;
214222944501Smrg
21430655efefSmrg	if (target_bo_gem->kflags & EXEC_OBJECT_PINNED)
2144fe517fc9Smrg		return drm_intel_gem_bo_add_softpin_target(bo, target_bo);
2145fe517fc9Smrg	else
2146fe517fc9Smrg		return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
2147fe517fc9Smrg					read_domains, write_domain,
2148fe517fc9Smrg					!bufmgr_gem->fenced_relocs);
214922944501Smrg}
215022944501Smrg
215122944501Smrgstatic int
215222944501Smrgdrm_intel_gem_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset,
215322944501Smrg				  drm_intel_bo *target_bo,
215422944501Smrg				  uint32_t target_offset,
215522944501Smrg				  uint32_t read_domains, uint32_t write_domain)
215622944501Smrg{
215722944501Smrg	return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
215820131375Smrg				read_domains, write_domain, true);
215920131375Smrg}
216020131375Smrg
21616260e5d5Smrgdrm_public int
216220131375Smrgdrm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo)
216320131375Smrg{
216420131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
216520131375Smrg
216620131375Smrg	return bo_gem->reloc_count;
216720131375Smrg}
216820131375Smrg
216920131375Smrg/**
217020131375Smrg * Removes existing relocation entries in the BO after "start".
217120131375Smrg *
217220131375Smrg * This allows a user to avoid a two-step process for state setup with
217320131375Smrg * counting up all the buffer objects and doing a
217420131375Smrg * drm_intel_bufmgr_check_aperture_space() before emitting any of the
217520131375Smrg * relocations for the state setup.  Instead, save the state of the
217620131375Smrg * batchbuffer including drm_intel_gem_get_reloc_count(), emit all the
217720131375Smrg * state, and then check if it still fits in the aperture.
217820131375Smrg *
217920131375Smrg * Any further drm_intel_bufmgr_check_aperture_space() queries
218020131375Smrg * involving this buffer in the tree are undefined after this call.
2181fe517fc9Smrg *
2182fe517fc9Smrg * This also removes all softpinned targets being referenced by the BO.
218320131375Smrg */
21846260e5d5Smrgdrm_public void
218520131375Smrgdrm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start)
218620131375Smrg{
2187a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
218820131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
218920131375Smrg	int i;
219020131375Smrg	struct timespec time;
219120131375Smrg
219220131375Smrg	clock_gettime(CLOCK_MONOTONIC, &time);
219320131375Smrg
219420131375Smrg	assert(bo_gem->reloc_count >= start);
2195a884aba1Smrg
219620131375Smrg	/* Unreference the cleared target buffers */
2197a884aba1Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
2198a884aba1Smrg
219920131375Smrg	for (i = start; i < bo_gem->reloc_count; i++) {
220020131375Smrg		drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->reloc_target_info[i].bo;
220120131375Smrg		if (&target_bo_gem->bo != bo) {
220220131375Smrg			bo_gem->reloc_tree_fences -= target_bo_gem->reloc_tree_fences;
220320131375Smrg			drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo,
220420131375Smrg								  time.tv_sec);
220520131375Smrg		}
220620131375Smrg	}
220720131375Smrg	bo_gem->reloc_count = start;
2208a884aba1Smrg
2209fe517fc9Smrg	for (i = 0; i < bo_gem->softpin_target_count; i++) {
2210fe517fc9Smrg		drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->softpin_target[i];
2211fe517fc9Smrg		drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, time.tv_sec);
2212fe517fc9Smrg	}
2213fe517fc9Smrg	bo_gem->softpin_target_count = 0;
2214fe517fc9Smrg
2215a884aba1Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
2216a884aba1Smrg
221722944501Smrg}
221822944501Smrg
221922944501Smrg/**
222022944501Smrg * Walk the tree of relocations rooted at BO and accumulate the list of
222122944501Smrg * validations to be performed and update the relocation buffers with
222222944501Smrg * index values into the validation list.
222322944501Smrg */
222422944501Smrgstatic void
222522944501Smrgdrm_intel_gem_bo_process_reloc2(drm_intel_bo *bo)
222622944501Smrg{
222722944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
222822944501Smrg	int i;
222922944501Smrg
2230fe517fc9Smrg	if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL)
223122944501Smrg		return;
223222944501Smrg
223322944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++) {
223422944501Smrg		drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo;
223522944501Smrg		int need_fence;
223622944501Smrg
2237aaba2545Smrg		if (target_bo == bo)
2238aaba2545Smrg			continue;
2239aaba2545Smrg
224020131375Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
224120131375Smrg
224222944501Smrg		/* Continue walking the tree depth-first. */
224322944501Smrg		drm_intel_gem_bo_process_reloc2(target_bo);
224422944501Smrg
224522944501Smrg		need_fence = (bo_gem->reloc_target_info[i].flags &
224622944501Smrg			      DRM_INTEL_RELOC_FENCE);
224722944501Smrg
224822944501Smrg		/* Add the target to the validate list */
224922944501Smrg		drm_intel_add_validate_buffer2(target_bo, need_fence);
225022944501Smrg	}
2251fe517fc9Smrg
2252fe517fc9Smrg	for (i = 0; i < bo_gem->softpin_target_count; i++) {
2253fe517fc9Smrg		drm_intel_bo *target_bo = bo_gem->softpin_target[i];
2254fe517fc9Smrg
2255fe517fc9Smrg		if (target_bo == bo)
2256fe517fc9Smrg			continue;
2257fe517fc9Smrg
2258fe517fc9Smrg		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
2259fe517fc9Smrg		drm_intel_gem_bo_process_reloc2(target_bo);
2260fe517fc9Smrg		drm_intel_add_validate_buffer2(target_bo, false);
2261fe517fc9Smrg	}
226222944501Smrg}
226322944501Smrg
226422944501Smrgstatic void
226522944501Smrgdrm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem)
226622944501Smrg{
226722944501Smrg	int i;
226822944501Smrg
226922944501Smrg	for (i = 0; i < bufmgr_gem->exec_count; i++) {
227022944501Smrg		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
227122944501Smrg		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
227222944501Smrg
227322944501Smrg		/* Update the buffer offset */
227420131375Smrg		if (bufmgr_gem->exec2_objects[i].offset != bo->offset64) {
2275fe517fc9Smrg			/* If we're seeing softpinned object here it means that the kernel
2276fe517fc9Smrg			 * has relocated our object... Indicating a programming error
2277fe517fc9Smrg			 */
22780655efefSmrg			assert(!(bo_gem->kflags & EXEC_OBJECT_PINNED));
2279fe517fc9Smrg			DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n",
2280d82d45b3Sjoerg			    bo_gem->gem_handle, bo_gem->name,
2281fe517fc9Smrg			    upper_32_bits(bo->offset64),
2282fe517fc9Smrg			    lower_32_bits(bo->offset64),
2283fe517fc9Smrg			    upper_32_bits(bufmgr_gem->exec2_objects[i].offset),
2284fe517fc9Smrg			    lower_32_bits(bufmgr_gem->exec2_objects[i].offset));
228520131375Smrg			bo->offset64 = bufmgr_gem->exec2_objects[i].offset;
228622944501Smrg			bo->offset = bufmgr_gem->exec2_objects[i].offset;
228722944501Smrg		}
228822944501Smrg	}
228922944501Smrg}
229022944501Smrg
22916260e5d5Smrgdrm_public void
229220131375Smrgdrm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo,
229320131375Smrg			      int x1, int y1, int width, int height,
229420131375Smrg			      enum aub_dump_bmp_format format,
229520131375Smrg			      int pitch, int offset)
229620131375Smrg{
229720131375Smrg}
229820131375Smrg
229920131375Smrgstatic int
230020131375Smrgdo_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
230120131375Smrg	 drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
23022ee35494Smrg	 int in_fence, int *out_fence,
230320131375Smrg	 unsigned int flags)
230420131375Smrg{
230520131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
230620131375Smrg	struct drm_i915_gem_execbuffer2 execbuf;
230720131375Smrg	int ret = 0;
230820131375Smrg	int i;
230920131375Smrg
2310fe517fc9Smrg	if (to_bo_gem(bo)->has_error)
2311fe517fc9Smrg		return -ENOMEM;
2312fe517fc9Smrg
231320131375Smrg	switch (flags & 0x7) {
231420131375Smrg	default:
231520131375Smrg		return -EINVAL;
231620131375Smrg	case I915_EXEC_BLT:
23179ce4edccSmrg		if (!bufmgr_gem->has_blt)
23189ce4edccSmrg			return -EINVAL;
23199ce4edccSmrg		break;
23209ce4edccSmrg	case I915_EXEC_BSD:
23219ce4edccSmrg		if (!bufmgr_gem->has_bsd)
23229ce4edccSmrg			return -EINVAL;
23239ce4edccSmrg		break;
232420131375Smrg	case I915_EXEC_VEBOX:
232520131375Smrg		if (!bufmgr_gem->has_vebox)
232620131375Smrg			return -EINVAL;
232720131375Smrg		break;
23289ce4edccSmrg	case I915_EXEC_RENDER:
23299ce4edccSmrg	case I915_EXEC_DEFAULT:
23309ce4edccSmrg		break;
23319ce4edccSmrg	}
2332aaba2545Smrg
233322944501Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
233422944501Smrg	/* Update indices and set up the validate list. */
233522944501Smrg	drm_intel_gem_bo_process_reloc2(bo);
233622944501Smrg
233722944501Smrg	/* Add the batch buffer to the validation list.  There are no relocations
233822944501Smrg	 * pointing to it.
233922944501Smrg	 */
234022944501Smrg	drm_intel_add_validate_buffer2(bo, 0);
234122944501Smrg
2342424e9256Smrg	memclear(execbuf);
234322944501Smrg	execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec2_objects;
234422944501Smrg	execbuf.buffer_count = bufmgr_gem->exec_count;
234522944501Smrg	execbuf.batch_start_offset = 0;
234622944501Smrg	execbuf.batch_len = used;
234722944501Smrg	execbuf.cliprects_ptr = (uintptr_t)cliprects;
234822944501Smrg	execbuf.num_cliprects = num_cliprects;
234922944501Smrg	execbuf.DR1 = 0;
235022944501Smrg	execbuf.DR4 = DR4;
235120131375Smrg	execbuf.flags = flags;
235220131375Smrg	if (ctx == NULL)
235320131375Smrg		i915_execbuffer2_set_context_id(execbuf, 0);
235420131375Smrg	else
235520131375Smrg		i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
235622944501Smrg	execbuf.rsvd2 = 0;
23572ee35494Smrg	if (in_fence != -1) {
23582ee35494Smrg		execbuf.rsvd2 = in_fence;
23592ee35494Smrg		execbuf.flags |= I915_EXEC_FENCE_IN;
23602ee35494Smrg	}
23612ee35494Smrg	if (out_fence != NULL) {
23622ee35494Smrg		*out_fence = -1;
23632ee35494Smrg		execbuf.flags |= I915_EXEC_FENCE_OUT;
23642ee35494Smrg	}
236522944501Smrg
236620131375Smrg	if (bufmgr_gem->no_exec)
236720131375Smrg		goto skip_execution;
236820131375Smrg
23696d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
23702ee35494Smrg		       DRM_IOCTL_I915_GEM_EXECBUFFER2_WR,
23716d98c517Smrg		       &execbuf);
237222944501Smrg	if (ret != 0) {
237322944501Smrg		ret = -errno;
23746d98c517Smrg		if (ret == -ENOSPC) {
23759ce4edccSmrg			DBG("Execbuffer fails to pin. "
23769ce4edccSmrg			    "Estimate: %u. Actual: %u. Available: %u\n",
23779ce4edccSmrg			    drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos,
23789ce4edccSmrg							       bufmgr_gem->exec_count),
23799ce4edccSmrg			    drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos,
23809ce4edccSmrg							      bufmgr_gem->exec_count),
23819ce4edccSmrg			    (unsigned int) bufmgr_gem->gtt_size);
238222944501Smrg		}
238322944501Smrg	}
238422944501Smrg	drm_intel_update_buffer_offsets2(bufmgr_gem);
238522944501Smrg
23862ee35494Smrg	if (ret == 0 && out_fence != NULL)
23872ee35494Smrg		*out_fence = execbuf.rsvd2 >> 32;
23882ee35494Smrg
238920131375Smrgskip_execution:
239022944501Smrg	if (bufmgr_gem->bufmgr.debug)
239122944501Smrg		drm_intel_gem_dump_validation_list(bufmgr_gem);
239222944501Smrg
239322944501Smrg	for (i = 0; i < bufmgr_gem->exec_count; i++) {
2394fe517fc9Smrg		drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]);
239522944501Smrg
239620131375Smrg		bo_gem->idle = false;
239720131375Smrg
239822944501Smrg		/* Disconnect the buffer from the validate list */
239922944501Smrg		bo_gem->validate_index = -1;
240022944501Smrg		bufmgr_gem->exec_bos[i] = NULL;
240122944501Smrg	}
240222944501Smrg	bufmgr_gem->exec_count = 0;
240322944501Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
240422944501Smrg
240522944501Smrg	return ret;
240622944501Smrg}
240722944501Smrg
2408aaba2545Smrgstatic int
2409aaba2545Smrgdrm_intel_gem_bo_exec2(drm_intel_bo *bo, int used,
2410aaba2545Smrg		       drm_clip_rect_t *cliprects, int num_cliprects,
2411aaba2545Smrg		       int DR4)
2412aaba2545Smrg{
241320131375Smrg	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
24142ee35494Smrg			-1, NULL, I915_EXEC_RENDER);
241520131375Smrg}
241620131375Smrg
241720131375Smrgstatic int
241820131375Smrgdrm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
241920131375Smrg			drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
242020131375Smrg			unsigned int flags)
242120131375Smrg{
242220131375Smrg	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
24232ee35494Smrg			-1, NULL, flags);
242420131375Smrg}
242520131375Smrg
24266260e5d5Smrgdrm_public int
242720131375Smrgdrm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
242820131375Smrg			      int used, unsigned int flags)
242920131375Smrg{
24302ee35494Smrg	return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags);
24312ee35494Smrg}
24322ee35494Smrg
24336260e5d5Smrgdrm_public int
24342ee35494Smrgdrm_intel_gem_bo_fence_exec(drm_intel_bo *bo,
24352ee35494Smrg			    drm_intel_context *ctx,
24362ee35494Smrg			    int used,
24372ee35494Smrg			    int in_fence,
24382ee35494Smrg			    int *out_fence,
24392ee35494Smrg			    unsigned int flags)
24402ee35494Smrg{
24412ee35494Smrg	return do_exec2(bo, used, ctx, NULL, 0, 0, in_fence, out_fence, flags);
2442aaba2545Smrg}
2443aaba2545Smrg
244422944501Smrgstatic int
244522944501Smrgdrm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment)
244622944501Smrg{
244722944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
244822944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
244922944501Smrg	struct drm_i915_gem_pin pin;
245022944501Smrg	int ret;
245122944501Smrg
2452424e9256Smrg	memclear(pin);
245322944501Smrg	pin.handle = bo_gem->gem_handle;
245422944501Smrg	pin.alignment = alignment;
245522944501Smrg
24566d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
24576d98c517Smrg		       DRM_IOCTL_I915_GEM_PIN,
24586d98c517Smrg		       &pin);
245922944501Smrg	if (ret != 0)
246022944501Smrg		return -errno;
246122944501Smrg
246220131375Smrg	bo->offset64 = pin.offset;
246322944501Smrg	bo->offset = pin.offset;
246422944501Smrg	return 0;
246522944501Smrg}
246622944501Smrg
246722944501Smrgstatic int
246822944501Smrgdrm_intel_gem_bo_unpin(drm_intel_bo *bo)
246922944501Smrg{
247022944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
247122944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
247222944501Smrg	struct drm_i915_gem_unpin unpin;
247322944501Smrg	int ret;
247422944501Smrg
2475424e9256Smrg	memclear(unpin);
247622944501Smrg	unpin.handle = bo_gem->gem_handle;
247722944501Smrg
24786d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
247922944501Smrg	if (ret != 0)
248022944501Smrg		return -errno;
248122944501Smrg
248222944501Smrg	return 0;
248322944501Smrg}
248422944501Smrg
248522944501Smrgstatic int
24866d98c517Smrgdrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo,
24876d98c517Smrg				     uint32_t tiling_mode,
24886d98c517Smrg				     uint32_t stride)
248922944501Smrg{
249022944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
249122944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
249222944501Smrg	struct drm_i915_gem_set_tiling set_tiling;
249322944501Smrg	int ret;
249422944501Smrg
24956d98c517Smrg	if (bo_gem->global_name == 0 &&
24966d98c517Smrg	    tiling_mode == bo_gem->tiling_mode &&
24976d98c517Smrg	    stride == bo_gem->stride)
249822944501Smrg		return 0;
249922944501Smrg
250022944501Smrg	memset(&set_tiling, 0, sizeof(set_tiling));
250122944501Smrg	do {
25026d98c517Smrg		/* set_tiling is slightly broken and overwrites the
25036d98c517Smrg		 * input on the error path, so we have to open code
25046d98c517Smrg		 * rmIoctl.
25056d98c517Smrg		 */
25066d98c517Smrg		set_tiling.handle = bo_gem->gem_handle;
25076d98c517Smrg		set_tiling.tiling_mode = tiling_mode;
250822944501Smrg		set_tiling.stride = stride;
250922944501Smrg
251022944501Smrg		ret = ioctl(bufmgr_gem->fd,
251122944501Smrg			    DRM_IOCTL_I915_GEM_SET_TILING,
251222944501Smrg			    &set_tiling);
25136d98c517Smrg	} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
25146d98c517Smrg	if (ret == -1)
25156d98c517Smrg		return -errno;
25166d98c517Smrg
25176d98c517Smrg	bo_gem->tiling_mode = set_tiling.tiling_mode;
25186d98c517Smrg	bo_gem->swizzle_mode = set_tiling.swizzle_mode;
25196d98c517Smrg	bo_gem->stride = set_tiling.stride;
25206d98c517Smrg	return 0;
25216d98c517Smrg}
25226d98c517Smrg
25236d98c517Smrgstatic int
25246d98c517Smrgdrm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
25256d98c517Smrg			    uint32_t stride)
25266d98c517Smrg{
25276d98c517Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
25286d98c517Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
25296d98c517Smrg	int ret;
25306d98c517Smrg
2531a884aba1Smrg	/* Tiling with userptr surfaces is not supported
2532a884aba1Smrg	 * on all hardware so refuse it for time being.
2533a884aba1Smrg	 */
2534a884aba1Smrg	if (bo_gem->is_userptr)
2535a884aba1Smrg		return -EINVAL;
2536a884aba1Smrg
25376d98c517Smrg	/* Linear buffers have no stride. By ensuring that we only ever use
25386d98c517Smrg	 * stride 0 with linear buffers, we simplify our code.
25396d98c517Smrg	 */
25406d98c517Smrg	if (*tiling_mode == I915_TILING_NONE)
25416d98c517Smrg		stride = 0;
25426d98c517Smrg
25436d98c517Smrg	ret = drm_intel_gem_bo_set_tiling_internal(bo, *tiling_mode, stride);
25446d98c517Smrg	if (ret == 0)
2545fe517fc9Smrg		drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
254622944501Smrg
254722944501Smrg	*tiling_mode = bo_gem->tiling_mode;
2548aaba2545Smrg	return ret;
254922944501Smrg}
255022944501Smrg
255122944501Smrgstatic int
255222944501Smrgdrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
255322944501Smrg			    uint32_t * swizzle_mode)
255422944501Smrg{
255522944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
255622944501Smrg
255722944501Smrg	*tiling_mode = bo_gem->tiling_mode;
255822944501Smrg	*swizzle_mode = bo_gem->swizzle_mode;
255922944501Smrg	return 0;
256022944501Smrg}
256122944501Smrg
2562fe517fc9Smrgstatic int
2563fe517fc9Smrgdrm_intel_gem_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset)
2564fe517fc9Smrg{
2565fe517fc9Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2566fe517fc9Smrg
2567fe517fc9Smrg	bo->offset64 = offset;
2568fe517fc9Smrg	bo->offset = offset;
25690655efefSmrg	bo_gem->kflags |= EXEC_OBJECT_PINNED;
25700655efefSmrg
2571fe517fc9Smrg	return 0;
2572fe517fc9Smrg}
2573fe517fc9Smrg
25746260e5d5Smrgdrm_public drm_intel_bo *
257520131375Smrgdrm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size)
257620131375Smrg{
257720131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
257820131375Smrg	int ret;
257920131375Smrg	uint32_t handle;
258020131375Smrg	drm_intel_bo_gem *bo_gem;
258120131375Smrg
2582fe517fc9Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
258320131375Smrg	ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle);
2584fe517fc9Smrg	if (ret) {
2585fe517fc9Smrg		DBG("create_from_prime: failed to obtain handle from fd: %s\n", strerror(errno));
2586fe517fc9Smrg		pthread_mutex_unlock(&bufmgr_gem->lock);
2587fe517fc9Smrg		return NULL;
2588fe517fc9Smrg	}
258920131375Smrg
259020131375Smrg	/*
259120131375Smrg	 * See if the kernel has already returned this buffer to us. Just as
259220131375Smrg	 * for named buffers, we must not create two bo's pointing at the same
259320131375Smrg	 * kernel object
259420131375Smrg	 */
25952ee35494Smrg	HASH_FIND(handle_hh, bufmgr_gem->handle_table,
25962ee35494Smrg		  &handle, sizeof(handle), bo_gem);
25972ee35494Smrg	if (bo_gem) {
25982ee35494Smrg		drm_intel_gem_bo_reference(&bo_gem->bo);
25992ee35494Smrg		goto out;
260020131375Smrg	}
260120131375Smrg
260220131375Smrg	bo_gem = calloc(1, sizeof(*bo_gem));
26032ee35494Smrg	if (!bo_gem)
26042ee35494Smrg		goto out;
26052ee35494Smrg
26062ee35494Smrg	atomic_set(&bo_gem->refcount, 1);
26072ee35494Smrg	DRMINITLISTHEAD(&bo_gem->vma_list);
26082ee35494Smrg
260920131375Smrg	/* Determine size of bo.  The fd-to-handle ioctl really should
261020131375Smrg	 * return the size, but it doesn't.  If we have kernel 3.12 or
261120131375Smrg	 * later, we can lseek on the prime fd to get the size.  Older
261220131375Smrg	 * kernels will just fail, in which case we fall back to the
261320131375Smrg	 * provided (estimated or guess size). */
261420131375Smrg	ret = lseek(prime_fd, 0, SEEK_END);
261520131375Smrg	if (ret != -1)
261620131375Smrg		bo_gem->bo.size = ret;
261720131375Smrg	else
261820131375Smrg		bo_gem->bo.size = size;
261920131375Smrg
262020131375Smrg	bo_gem->bo.handle = handle;
262120131375Smrg	bo_gem->bo.bufmgr = bufmgr;
262220131375Smrg
262320131375Smrg	bo_gem->gem_handle = handle;
26242ee35494Smrg	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
26252ee35494Smrg		 gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
262620131375Smrg
262720131375Smrg	bo_gem->name = "prime";
262820131375Smrg	bo_gem->validate_index = -1;
262920131375Smrg	bo_gem->reloc_tree_fences = 0;
263020131375Smrg	bo_gem->used_as_reloc_target = false;
263120131375Smrg	bo_gem->has_error = false;
263220131375Smrg	bo_gem->reusable = false;
263320131375Smrg
263487bf8e7cSmrg	ret = get_tiling_mode(bufmgr_gem, handle,
263587bf8e7cSmrg			      &bo_gem->tiling_mode, &bo_gem->swizzle_mode);
263687bf8e7cSmrg	if (ret)
26372ee35494Smrg		goto err;
26382ee35494Smrg
263920131375Smrg	/* XXX stride is unknown */
2640fe517fc9Smrg	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
264120131375Smrg
26422ee35494Smrgout:
26432ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
264420131375Smrg	return &bo_gem->bo;
26452ee35494Smrg
26462ee35494Smrgerr:
26472ee35494Smrg	drm_intel_gem_bo_free(&bo_gem->bo);
26482ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
26492ee35494Smrg	return NULL;
265020131375Smrg}
265120131375Smrg
26526260e5d5Smrgdrm_public int
265320131375Smrgdrm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd)
265420131375Smrg{
265520131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
265620131375Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
265720131375Smrg
265820131375Smrg	if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle,
265987bf8e7cSmrg			       DRM_CLOEXEC | DRM_RDWR, prime_fd) != 0)
266020131375Smrg		return -errno;
266120131375Smrg
266220131375Smrg	bo_gem->reusable = false;
266320131375Smrg
266420131375Smrg	return 0;
266520131375Smrg}
266620131375Smrg
266722944501Smrgstatic int
266822944501Smrgdrm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name)
266922944501Smrg{
267022944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
267122944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
267222944501Smrg
267322944501Smrg	if (!bo_gem->global_name) {
267420131375Smrg		struct drm_gem_flink flink;
267520131375Smrg
2676424e9256Smrg		memclear(flink);
267722944501Smrg		flink.handle = bo_gem->gem_handle;
26782ee35494Smrg		if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink))
26792ee35494Smrg			return -errno;
268022944501Smrg
2681a884aba1Smrg		pthread_mutex_lock(&bufmgr_gem->lock);
26822ee35494Smrg		if (!bo_gem->global_name) {
26832ee35494Smrg			bo_gem->global_name = flink.name;
26842ee35494Smrg			bo_gem->reusable = false;
2685a884aba1Smrg
26862ee35494Smrg			HASH_ADD(name_hh, bufmgr_gem->name_table,
26872ee35494Smrg				 global_name, sizeof(bo_gem->global_name),
26882ee35494Smrg				 bo_gem);
2689a884aba1Smrg		}
2690a884aba1Smrg		pthread_mutex_unlock(&bufmgr_gem->lock);
269122944501Smrg	}
269222944501Smrg
269322944501Smrg	*name = bo_gem->global_name;
269422944501Smrg	return 0;
269522944501Smrg}
269622944501Smrg
269722944501Smrg/**
269822944501Smrg * Enables unlimited caching of buffer objects for reuse.
269922944501Smrg *
270022944501Smrg * This is potentially very memory expensive, as the cache at each bucket
270122944501Smrg * size is only bounded by how many buffers of that size we've managed to have
270222944501Smrg * in flight at once.
270322944501Smrg */
27046260e5d5Smrgdrm_public void
270522944501Smrgdrm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr)
270622944501Smrg{
270722944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
270822944501Smrg
270920131375Smrg	bufmgr_gem->bo_reuse = true;
271022944501Smrg}
271122944501Smrg
27122ee35494Smrg/**
27132ee35494Smrg * Disables implicit synchronisation before executing the bo
27142ee35494Smrg *
27152ee35494Smrg * This will cause rendering corruption unless you correctly manage explicit
27162ee35494Smrg * fences for all rendering involving this buffer - including use by others.
27172ee35494Smrg * Disabling the implicit serialisation is only required if that serialisation
27182ee35494Smrg * is too coarse (for example, you have split the buffer into many
27192ee35494Smrg * non-overlapping regions and are sharing the whole buffer between concurrent
27202ee35494Smrg * independent command streams).
27212ee35494Smrg *
27222ee35494Smrg * Note the kernel must advertise support via I915_PARAM_HAS_EXEC_ASYNC,
27232ee35494Smrg * which can be checked using drm_intel_bufmgr_can_disable_implicit_sync,
27242ee35494Smrg * or subsequent execbufs involving the bo will generate EINVAL.
27252ee35494Smrg */
27266260e5d5Smrgdrm_public void
27272ee35494Smrgdrm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo)
27282ee35494Smrg{
27292ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
27302ee35494Smrg
27312ee35494Smrg	bo_gem->kflags |= EXEC_OBJECT_ASYNC;
27322ee35494Smrg}
27332ee35494Smrg
27342ee35494Smrg/**
27352ee35494Smrg * Enables implicit synchronisation before executing the bo
27362ee35494Smrg *
27372ee35494Smrg * This is the default behaviour of the kernel, to wait upon prior writes
27382ee35494Smrg * completing on the object before rendering with it, or to wait for prior
27392ee35494Smrg * reads to complete before writing into the object.
27402ee35494Smrg * drm_intel_gem_bo_disable_implicit_sync() can stop this behaviour, telling
27412ee35494Smrg * the kernel never to insert a stall before using the object. Then this
27422ee35494Smrg * function can be used to restore the implicit sync before subsequent
27432ee35494Smrg * rendering.
27442ee35494Smrg */
27456260e5d5Smrgdrm_public void
27462ee35494Smrgdrm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo)
27472ee35494Smrg{
27482ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
27492ee35494Smrg
27502ee35494Smrg	bo_gem->kflags &= ~EXEC_OBJECT_ASYNC;
27512ee35494Smrg}
27522ee35494Smrg
27532ee35494Smrg/**
27542ee35494Smrg * Query whether the kernel supports disabling of its implicit synchronisation
27552ee35494Smrg * before execbuf. See drm_intel_gem_bo_disable_implicit_sync()
27562ee35494Smrg */
27576260e5d5Smrgdrm_public int
27582ee35494Smrgdrm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr)
27592ee35494Smrg{
27602ee35494Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
27612ee35494Smrg
27622ee35494Smrg	return bufmgr_gem->has_exec_async;
27632ee35494Smrg}
27642ee35494Smrg
276522944501Smrg/**
276622944501Smrg * Enable use of fenced reloc type.
276722944501Smrg *
276822944501Smrg * New code should enable this to avoid unnecessary fence register
276922944501Smrg * allocation.  If this option is not enabled, all relocs will have fence
277022944501Smrg * register allocated.
277122944501Smrg */
27726260e5d5Smrgdrm_public void
277322944501Smrgdrm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr)
277422944501Smrg{
277522944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
2776adfa0b0cSmrg	bufmgr_gem->fenced_relocs = true;
277722944501Smrg}
277822944501Smrg
277922944501Smrg/**
278022944501Smrg * Return the additional aperture space required by the tree of buffer objects
278122944501Smrg * rooted at bo.
278222944501Smrg */
278322944501Smrgstatic int
278422944501Smrgdrm_intel_gem_bo_get_aperture_space(drm_intel_bo *bo)
278522944501Smrg{
278622944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
278722944501Smrg	int i;
278822944501Smrg	int total = 0;
278922944501Smrg
279022944501Smrg	if (bo == NULL || bo_gem->included_in_check_aperture)
279122944501Smrg		return 0;
279222944501Smrg
279322944501Smrg	total += bo->size;
279420131375Smrg	bo_gem->included_in_check_aperture = true;
279522944501Smrg
279622944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++)
279722944501Smrg		total +=
279822944501Smrg		    drm_intel_gem_bo_get_aperture_space(bo_gem->
279922944501Smrg							reloc_target_info[i].bo);
280022944501Smrg
280122944501Smrg	return total;
280222944501Smrg}
280322944501Smrg
280422944501Smrg/**
280522944501Smrg * Count the number of buffers in this list that need a fence reg
280622944501Smrg *
280722944501Smrg * If the count is greater than the number of available regs, we'll have
280822944501Smrg * to ask the caller to resubmit a batch with fewer tiled buffers.
280922944501Smrg *
281022944501Smrg * This function over-counts if the same buffer is used multiple times.
281122944501Smrg */
281222944501Smrgstatic unsigned int
281322944501Smrgdrm_intel_gem_total_fences(drm_intel_bo ** bo_array, int count)
281422944501Smrg{
281522944501Smrg	int i;
281622944501Smrg	unsigned int total = 0;
281722944501Smrg
281822944501Smrg	for (i = 0; i < count; i++) {
281922944501Smrg		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i];
282022944501Smrg
282122944501Smrg		if (bo_gem == NULL)
282222944501Smrg			continue;
282322944501Smrg
282422944501Smrg		total += bo_gem->reloc_tree_fences;
282522944501Smrg	}
282622944501Smrg	return total;
282722944501Smrg}
282822944501Smrg
282922944501Smrg/**
283022944501Smrg * Clear the flag set by drm_intel_gem_bo_get_aperture_space() so we're ready
283122944501Smrg * for the next drm_intel_bufmgr_check_aperture_space() call.
283222944501Smrg */
283322944501Smrgstatic void
283422944501Smrgdrm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo)
283522944501Smrg{
283622944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
283722944501Smrg	int i;
283822944501Smrg
283922944501Smrg	if (bo == NULL || !bo_gem->included_in_check_aperture)
284022944501Smrg		return;
284122944501Smrg
284220131375Smrg	bo_gem->included_in_check_aperture = false;
284322944501Smrg
284422944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++)
284522944501Smrg		drm_intel_gem_bo_clear_aperture_space_flag(bo_gem->
284622944501Smrg							   reloc_target_info[i].bo);
284722944501Smrg}
284822944501Smrg
284922944501Smrg/**
285022944501Smrg * Return a conservative estimate for the amount of aperture required
285122944501Smrg * for a collection of buffers. This may double-count some buffers.
285222944501Smrg */
285322944501Smrgstatic unsigned int
285422944501Smrgdrm_intel_gem_estimate_batch_space(drm_intel_bo **bo_array, int count)
285522944501Smrg{
285622944501Smrg	int i;
285722944501Smrg	unsigned int total = 0;
285822944501Smrg
285922944501Smrg	for (i = 0; i < count; i++) {
286022944501Smrg		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i];
286122944501Smrg		if (bo_gem != NULL)
286222944501Smrg			total += bo_gem->reloc_tree_size;
286322944501Smrg	}
286422944501Smrg	return total;
286522944501Smrg}
286622944501Smrg
286722944501Smrg/**
286822944501Smrg * Return the amount of aperture needed for a collection of buffers.
286922944501Smrg * This avoids double counting any buffers, at the cost of looking
287022944501Smrg * at every buffer in the set.
287122944501Smrg */
287222944501Smrgstatic unsigned int
287322944501Smrgdrm_intel_gem_compute_batch_space(drm_intel_bo **bo_array, int count)
287422944501Smrg{
287522944501Smrg	int i;
287622944501Smrg	unsigned int total = 0;
287722944501Smrg
287822944501Smrg	for (i = 0; i < count; i++) {
287922944501Smrg		total += drm_intel_gem_bo_get_aperture_space(bo_array[i]);
288022944501Smrg		/* For the first buffer object in the array, we get an
288122944501Smrg		 * accurate count back for its reloc_tree size (since nothing
288222944501Smrg		 * had been flagged as being counted yet).  We can save that
288322944501Smrg		 * value out as a more conservative reloc_tree_size that
288422944501Smrg		 * avoids double-counting target buffers.  Since the first
288522944501Smrg		 * buffer happens to usually be the batch buffer in our
288622944501Smrg		 * callers, this can pull us back from doing the tree
288722944501Smrg		 * walk on every new batch emit.
288822944501Smrg		 */
288922944501Smrg		if (i == 0) {
289022944501Smrg			drm_intel_bo_gem *bo_gem =
289122944501Smrg			    (drm_intel_bo_gem *) bo_array[i];
289222944501Smrg			bo_gem->reloc_tree_size = total;
289322944501Smrg		}
289422944501Smrg	}
289522944501Smrg
289622944501Smrg	for (i = 0; i < count; i++)
289722944501Smrg		drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]);
289822944501Smrg	return total;
289922944501Smrg}
290022944501Smrg
290122944501Smrg/**
290222944501Smrg * Return -1 if the batchbuffer should be flushed before attempting to
290322944501Smrg * emit rendering referencing the buffers pointed to by bo_array.
290422944501Smrg *
290522944501Smrg * This is required because if we try to emit a batchbuffer with relocations
290622944501Smrg * to a tree of buffers that won't simultaneously fit in the aperture,
290722944501Smrg * the rendering will return an error at a point where the software is not
290822944501Smrg * prepared to recover from it.
290922944501Smrg *
291022944501Smrg * However, we also want to emit the batchbuffer significantly before we reach
291122944501Smrg * the limit, as a series of batchbuffers each of which references buffers
291222944501Smrg * covering almost all of the aperture means that at each emit we end up
291322944501Smrg * waiting to evict a buffer from the last rendering, and we get synchronous
291422944501Smrg * performance.  By emitting smaller batchbuffers, we eat some CPU overhead to
291522944501Smrg * get better parallelism.
291622944501Smrg */
291722944501Smrgstatic int
291822944501Smrgdrm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count)
291922944501Smrg{
292022944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem =
292122944501Smrg	    (drm_intel_bufmgr_gem *) bo_array[0]->bufmgr;
292222944501Smrg	unsigned int total = 0;
292322944501Smrg	unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4;
292422944501Smrg	int total_fences;
292522944501Smrg
292622944501Smrg	/* Check for fence reg constraints if necessary */
292722944501Smrg	if (bufmgr_gem->available_fences) {
292822944501Smrg		total_fences = drm_intel_gem_total_fences(bo_array, count);
292922944501Smrg		if (total_fences > bufmgr_gem->available_fences)
293022944501Smrg			return -ENOSPC;
293122944501Smrg	}
293222944501Smrg
293322944501Smrg	total = drm_intel_gem_estimate_batch_space(bo_array, count);
293422944501Smrg
293522944501Smrg	if (total > threshold)
293622944501Smrg		total = drm_intel_gem_compute_batch_space(bo_array, count);
293722944501Smrg
293822944501Smrg	if (total > threshold) {
293922944501Smrg		DBG("check_space: overflowed available aperture, "
294022944501Smrg		    "%dkb vs %dkb\n",
294122944501Smrg		    total / 1024, (int)bufmgr_gem->gtt_size / 1024);
294222944501Smrg		return -ENOSPC;
294322944501Smrg	} else {
294422944501Smrg		DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024,
294522944501Smrg		    (int)bufmgr_gem->gtt_size / 1024);
294622944501Smrg		return 0;
294722944501Smrg	}
294822944501Smrg}
294922944501Smrg
295022944501Smrg/*
295122944501Smrg * Disable buffer reuse for objects which are shared with the kernel
295222944501Smrg * as scanout buffers
295322944501Smrg */
295422944501Smrgstatic int
295522944501Smrgdrm_intel_gem_bo_disable_reuse(drm_intel_bo *bo)
295622944501Smrg{
295722944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
295822944501Smrg
295920131375Smrg	bo_gem->reusable = false;
296022944501Smrg	return 0;
296122944501Smrg}
296222944501Smrg
2963aaba2545Smrgstatic int
2964aaba2545Smrgdrm_intel_gem_bo_is_reusable(drm_intel_bo *bo)
2965aaba2545Smrg{
2966aaba2545Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
2967aaba2545Smrg
2968aaba2545Smrg	return bo_gem->reusable;
2969aaba2545Smrg}
2970aaba2545Smrg
297122944501Smrgstatic int
297222944501Smrg_drm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo)
297322944501Smrg{
297422944501Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
297522944501Smrg	int i;
297622944501Smrg
297722944501Smrg	for (i = 0; i < bo_gem->reloc_count; i++) {
297822944501Smrg		if (bo_gem->reloc_target_info[i].bo == target_bo)
297922944501Smrg			return 1;
2980aaba2545Smrg		if (bo == bo_gem->reloc_target_info[i].bo)
2981aaba2545Smrg			continue;
298222944501Smrg		if (_drm_intel_gem_bo_references(bo_gem->reloc_target_info[i].bo,
298322944501Smrg						target_bo))
298422944501Smrg			return 1;
298522944501Smrg	}
298622944501Smrg
2987fe517fc9Smrg	for (i = 0; i< bo_gem->softpin_target_count; i++) {
2988fe517fc9Smrg		if (bo_gem->softpin_target[i] == target_bo)
2989fe517fc9Smrg			return 1;
2990fe517fc9Smrg		if (_drm_intel_gem_bo_references(bo_gem->softpin_target[i], target_bo))
2991fe517fc9Smrg			return 1;
2992fe517fc9Smrg	}
2993fe517fc9Smrg
299422944501Smrg	return 0;
299522944501Smrg}
299622944501Smrg
299722944501Smrg/** Return true if target_bo is referenced by bo's relocation tree. */
299822944501Smrgstatic int
299922944501Smrgdrm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo)
300022944501Smrg{
300122944501Smrg	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
300222944501Smrg
300322944501Smrg	if (bo == NULL || target_bo == NULL)
300422944501Smrg		return 0;
300522944501Smrg	if (target_bo_gem->used_as_reloc_target)
300622944501Smrg		return _drm_intel_gem_bo_references(bo, target_bo);
300722944501Smrg	return 0;
300822944501Smrg}
300922944501Smrg
3010aaba2545Smrgstatic void
3011aaba2545Smrgadd_bucket(drm_intel_bufmgr_gem *bufmgr_gem, int size)
3012aaba2545Smrg{
3013aaba2545Smrg	unsigned int i = bufmgr_gem->num_buckets;
3014aaba2545Smrg
3015aaba2545Smrg	assert(i < ARRAY_SIZE(bufmgr_gem->cache_bucket));
3016aaba2545Smrg
3017aaba2545Smrg	DRMINITLISTHEAD(&bufmgr_gem->cache_bucket[i].head);
3018aaba2545Smrg	bufmgr_gem->cache_bucket[i].size = size;
3019aaba2545Smrg	bufmgr_gem->num_buckets++;
3020aaba2545Smrg}
3021aaba2545Smrg
3022aaba2545Smrgstatic void
3023aaba2545Smrginit_cache_buckets(drm_intel_bufmgr_gem *bufmgr_gem)
3024aaba2545Smrg{
3025aaba2545Smrg	unsigned long size, cache_max_size = 64 * 1024 * 1024;
3026aaba2545Smrg
3027aaba2545Smrg	/* OK, so power of two buckets was too wasteful of memory.
3028aaba2545Smrg	 * Give 3 other sizes between each power of two, to hopefully
3029aaba2545Smrg	 * cover things accurately enough.  (The alternative is
3030aaba2545Smrg	 * probably to just go for exact matching of sizes, and assume
3031aaba2545Smrg	 * that for things like composited window resize the tiled
3032aaba2545Smrg	 * width/height alignment and rounding of sizes to pages will
3033aaba2545Smrg	 * get us useful cache hit rates anyway)
3034aaba2545Smrg	 */
3035aaba2545Smrg	add_bucket(bufmgr_gem, 4096);
3036aaba2545Smrg	add_bucket(bufmgr_gem, 4096 * 2);
3037aaba2545Smrg	add_bucket(bufmgr_gem, 4096 * 3);
3038aaba2545Smrg
3039aaba2545Smrg	/* Initialize the linked lists for BO reuse cache. */
3040aaba2545Smrg	for (size = 4 * 4096; size <= cache_max_size; size *= 2) {
3041aaba2545Smrg		add_bucket(bufmgr_gem, size);
3042aaba2545Smrg
3043aaba2545Smrg		add_bucket(bufmgr_gem, size + size * 1 / 4);
3044aaba2545Smrg		add_bucket(bufmgr_gem, size + size * 2 / 4);
3045aaba2545Smrg		add_bucket(bufmgr_gem, size + size * 3 / 4);
3046aaba2545Smrg	}
3047aaba2545Smrg}
3048aaba2545Smrg
30496260e5d5Smrgdrm_public void
305020131375Smrgdrm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit)
305120131375Smrg{
305220131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
305320131375Smrg
305420131375Smrg	bufmgr_gem->vma_max = limit;
305520131375Smrg
305620131375Smrg	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
305720131375Smrg}
305820131375Smrg
30592ee35494Smrgstatic int
30602ee35494Smrgparse_devid_override(const char *devid_override)
30612ee35494Smrg{
30622ee35494Smrg	static const struct {
30632ee35494Smrg		const char *name;
30642ee35494Smrg		int pci_id;
30652ee35494Smrg	} name_map[] = {
30662ee35494Smrg		{ "brw", PCI_CHIP_I965_GM },
30672ee35494Smrg		{ "g4x", PCI_CHIP_GM45_GM },
30682ee35494Smrg		{ "ilk", PCI_CHIP_ILD_G },
30692ee35494Smrg		{ "snb", PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS },
30702ee35494Smrg		{ "ivb", PCI_CHIP_IVYBRIDGE_S_GT2 },
30712ee35494Smrg		{ "hsw", PCI_CHIP_HASWELL_CRW_E_GT3 },
30722ee35494Smrg		{ "byt", PCI_CHIP_VALLEYVIEW_3 },
30732ee35494Smrg		{ "bdw", 0x1620 | BDW_ULX },
30742ee35494Smrg		{ "skl", PCI_CHIP_SKYLAKE_DT_GT2 },
30752ee35494Smrg		{ "kbl", PCI_CHIP_KABYLAKE_DT_GT2 },
30762ee35494Smrg	};
30772ee35494Smrg	unsigned int i;
30782ee35494Smrg
30792ee35494Smrg	for (i = 0; i < ARRAY_SIZE(name_map); i++) {
30802ee35494Smrg		if (!strcmp(name_map[i].name, devid_override))
30812ee35494Smrg			return name_map[i].pci_id;
30822ee35494Smrg	}
30832ee35494Smrg
30842ee35494Smrg	return strtod(devid_override, NULL);
30852ee35494Smrg}
30862ee35494Smrg
308720131375Smrg/**
308820131375Smrg * Get the PCI ID for the device.  This can be overridden by setting the
308920131375Smrg * INTEL_DEVID_OVERRIDE environment variable to the desired ID.
309020131375Smrg */
309120131375Smrgstatic int
309220131375Smrgget_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem)
309320131375Smrg{
309420131375Smrg	char *devid_override;
3095424e9256Smrg	int devid = 0;
309620131375Smrg	int ret;
309720131375Smrg	drm_i915_getparam_t gp;
309820131375Smrg
309920131375Smrg	if (geteuid() == getuid()) {
310020131375Smrg		devid_override = getenv("INTEL_DEVID_OVERRIDE");
310120131375Smrg		if (devid_override) {
310220131375Smrg			bufmgr_gem->no_exec = true;
31032ee35494Smrg			return parse_devid_override(devid_override);
310420131375Smrg		}
310520131375Smrg	}
310620131375Smrg
3107424e9256Smrg	memclear(gp);
310820131375Smrg	gp.param = I915_PARAM_CHIPSET_ID;
310920131375Smrg	gp.value = &devid;
311020131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
311120131375Smrg	if (ret) {
311220131375Smrg		fprintf(stderr, "get chip id failed: %d [%d]\n", ret, errno);
311320131375Smrg		fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value);
311420131375Smrg	}
311520131375Smrg	return devid;
311620131375Smrg}
311720131375Smrg
31186260e5d5Smrgdrm_public int
311920131375Smrgdrm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr)
312020131375Smrg{
312120131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
312220131375Smrg
312320131375Smrg	return bufmgr_gem->pci_device;
312420131375Smrg}
312520131375Smrg
312620131375Smrg/**
312720131375Smrg * Sets the AUB filename.
312820131375Smrg *
312920131375Smrg * This function has to be called before drm_intel_bufmgr_gem_set_aub_dump()
313020131375Smrg * for it to have any effect.
313120131375Smrg */
31326260e5d5Smrgdrm_public void
313320131375Smrgdrm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr,
313420131375Smrg				      const char *filename)
313520131375Smrg{
313620131375Smrg}
313720131375Smrg
313820131375Smrg/**
313920131375Smrg * Sets up AUB dumping.
314020131375Smrg *
314120131375Smrg * This is a trace file format that can be used with the simulator.
314220131375Smrg * Packets are emitted in a format somewhat like GPU command packets.
314320131375Smrg * You can set up a GTT and upload your objects into the referenced
314420131375Smrg * space, then send off batchbuffers and get BMPs out the other end.
314520131375Smrg */
31466260e5d5Smrgdrm_public void
314720131375Smrgdrm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable)
314820131375Smrg{
3149fe517fc9Smrg	fprintf(stderr, "libdrm aub dumping is deprecated.\n\n"
3150fe517fc9Smrg		"Use intel_aubdump from intel-gpu-tools instead.  Install intel-gpu-tools,\n"
3151fe517fc9Smrg		"then run (for example)\n\n"
3152fe517fc9Smrg		"\t$ intel_aubdump --output=trace.aub glxgears -geometry 500x500\n\n"
3153fe517fc9Smrg		"See the intel_aubdump man page for more details.\n");
315420131375Smrg}
315520131375Smrg
31566260e5d5Smrgdrm_public drm_intel_context *
315720131375Smrgdrm_intel_gem_context_create(drm_intel_bufmgr *bufmgr)
315820131375Smrg{
315920131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
316020131375Smrg	struct drm_i915_gem_context_create create;
316120131375Smrg	drm_intel_context *context = NULL;
316220131375Smrg	int ret;
316320131375Smrg
316420131375Smrg	context = calloc(1, sizeof(*context));
316520131375Smrg	if (!context)
316620131375Smrg		return NULL;
316720131375Smrg
3168424e9256Smrg	memclear(create);
316920131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
317020131375Smrg	if (ret != 0) {
317120131375Smrg		DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n",
317220131375Smrg		    strerror(errno));
317320131375Smrg		free(context);
317420131375Smrg		return NULL;
317520131375Smrg	}
317620131375Smrg
317720131375Smrg	context->ctx_id = create.ctx_id;
317820131375Smrg	context->bufmgr = bufmgr;
317920131375Smrg
318020131375Smrg	return context;
318120131375Smrg}
318220131375Smrg
31836260e5d5Smrgdrm_public int
31842ee35494Smrgdrm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id)
31852ee35494Smrg{
31862ee35494Smrg	if (ctx == NULL)
31872ee35494Smrg		return -EINVAL;
31882ee35494Smrg
31892ee35494Smrg	*ctx_id = ctx->ctx_id;
31902ee35494Smrg
31912ee35494Smrg	return 0;
31922ee35494Smrg}
31932ee35494Smrg
31946260e5d5Smrgdrm_public void
319520131375Smrgdrm_intel_gem_context_destroy(drm_intel_context *ctx)
319620131375Smrg{
319720131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
319820131375Smrg	struct drm_i915_gem_context_destroy destroy;
319920131375Smrg	int ret;
320020131375Smrg
320120131375Smrg	if (ctx == NULL)
320220131375Smrg		return;
320320131375Smrg
3204424e9256Smrg	memclear(destroy);
320520131375Smrg
320620131375Smrg	bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
320720131375Smrg	destroy.ctx_id = ctx->ctx_id;
320820131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY,
320920131375Smrg		       &destroy);
321020131375Smrg	if (ret != 0)
321120131375Smrg		fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n",
321220131375Smrg			strerror(errno));
321320131375Smrg
321420131375Smrg	free(ctx);
321520131375Smrg}
321620131375Smrg
32176260e5d5Smrgdrm_public int
321820131375Smrgdrm_intel_get_reset_stats(drm_intel_context *ctx,
321920131375Smrg			  uint32_t *reset_count,
322020131375Smrg			  uint32_t *active,
322120131375Smrg			  uint32_t *pending)
322220131375Smrg{
322320131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
322420131375Smrg	struct drm_i915_reset_stats stats;
322520131375Smrg	int ret;
322620131375Smrg
322720131375Smrg	if (ctx == NULL)
322820131375Smrg		return -EINVAL;
322920131375Smrg
3230424e9256Smrg	memclear(stats);
323120131375Smrg
323220131375Smrg	bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
323320131375Smrg	stats.ctx_id = ctx->ctx_id;
323420131375Smrg	ret = drmIoctl(bufmgr_gem->fd,
323520131375Smrg		       DRM_IOCTL_I915_GET_RESET_STATS,
323620131375Smrg		       &stats);
323720131375Smrg	if (ret == 0) {
323820131375Smrg		if (reset_count != NULL)
323920131375Smrg			*reset_count = stats.reset_count;
324020131375Smrg
324120131375Smrg		if (active != NULL)
324220131375Smrg			*active = stats.batch_active;
324320131375Smrg
324420131375Smrg		if (pending != NULL)
324520131375Smrg			*pending = stats.batch_pending;
324620131375Smrg	}
324720131375Smrg
324820131375Smrg	return ret;
324920131375Smrg}
325020131375Smrg
32516260e5d5Smrgdrm_public int
325220131375Smrgdrm_intel_reg_read(drm_intel_bufmgr *bufmgr,
325320131375Smrg		   uint32_t offset,
325420131375Smrg		   uint64_t *result)
325520131375Smrg{
325620131375Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
325720131375Smrg	struct drm_i915_reg_read reg_read;
325820131375Smrg	int ret;
325920131375Smrg
3260424e9256Smrg	memclear(reg_read);
326120131375Smrg	reg_read.offset = offset;
326220131375Smrg
326320131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, &reg_read);
326420131375Smrg
326520131375Smrg	*result = reg_read.val;
326620131375Smrg	return ret;
326720131375Smrg}
326820131375Smrg
32696260e5d5Smrgdrm_public int
3270424e9256Smrgdrm_intel_get_subslice_total(int fd, unsigned int *subslice_total)
3271424e9256Smrg{
3272424e9256Smrg	drm_i915_getparam_t gp;
3273424e9256Smrg	int ret;
3274424e9256Smrg
3275424e9256Smrg	memclear(gp);
3276424e9256Smrg	gp.value = (int*)subslice_total;
3277424e9256Smrg	gp.param = I915_PARAM_SUBSLICE_TOTAL;
3278424e9256Smrg	ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
3279424e9256Smrg	if (ret)
3280424e9256Smrg		return -errno;
3281424e9256Smrg
3282424e9256Smrg	return 0;
3283424e9256Smrg}
3284424e9256Smrg
32856260e5d5Smrgdrm_public int
3286424e9256Smrgdrm_intel_get_eu_total(int fd, unsigned int *eu_total)
3287424e9256Smrg{
3288424e9256Smrg	drm_i915_getparam_t gp;
3289424e9256Smrg	int ret;
3290424e9256Smrg
3291424e9256Smrg	memclear(gp);
3292424e9256Smrg	gp.value = (int*)eu_total;
3293424e9256Smrg	gp.param = I915_PARAM_EU_TOTAL;
3294424e9256Smrg	ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
3295424e9256Smrg	if (ret)
3296424e9256Smrg		return -errno;
3297424e9256Smrg
3298424e9256Smrg	return 0;
3299424e9256Smrg}
330020131375Smrg
33016260e5d5Smrgdrm_public int
33022ee35494Smrgdrm_intel_get_pooled_eu(int fd)
33032ee35494Smrg{
33042ee35494Smrg	drm_i915_getparam_t gp;
33052ee35494Smrg	int ret = -1;
33062ee35494Smrg
33072ee35494Smrg	memclear(gp);
33082ee35494Smrg	gp.param = I915_PARAM_HAS_POOLED_EU;
33092ee35494Smrg	gp.value = &ret;
33102ee35494Smrg	if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
33112ee35494Smrg		return -errno;
33122ee35494Smrg
33132ee35494Smrg	return ret;
33142ee35494Smrg}
33152ee35494Smrg
33166260e5d5Smrgdrm_public int
33172ee35494Smrgdrm_intel_get_min_eu_in_pool(int fd)
33182ee35494Smrg{
33192ee35494Smrg	drm_i915_getparam_t gp;
33202ee35494Smrg	int ret = -1;
33212ee35494Smrg
33222ee35494Smrg	memclear(gp);
33232ee35494Smrg	gp.param = I915_PARAM_MIN_EU_IN_POOL;
33242ee35494Smrg	gp.value = &ret;
33252ee35494Smrg	if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
33262ee35494Smrg		return -errno;
33272ee35494Smrg
33282ee35494Smrg	return ret;
33292ee35494Smrg}
33302ee35494Smrg
333120131375Smrg/**
333220131375Smrg * Annotate the given bo for use in aub dumping.
333320131375Smrg *
333420131375Smrg * \param annotations is an array of drm_intel_aub_annotation objects
333520131375Smrg * describing the type of data in various sections of the bo.  Each
333620131375Smrg * element of the array specifies the type and subtype of a section of
333720131375Smrg * the bo, and the past-the-end offset of that section.  The elements
333820131375Smrg * of \c annotations must be sorted so that ending_offset is
333920131375Smrg * increasing.
334020131375Smrg *
334120131375Smrg * \param count is the number of elements in the \c annotations array.
334220131375Smrg * If \c count is zero, then \c annotations will not be dereferenced.
334320131375Smrg *
334420131375Smrg * Annotations are copied into a private data structure, so caller may
334520131375Smrg * re-use the memory pointed to by \c annotations after the call
334620131375Smrg * returns.
334720131375Smrg *
334820131375Smrg * Annotations are stored for the lifetime of the bo; to reset to the
334920131375Smrg * default state (no annotations), call this function with a \c count
335020131375Smrg * of zero.
335120131375Smrg */
33526260e5d5Smrgdrm_public void drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
335320131375Smrg					 drm_intel_aub_annotation *annotations,
335420131375Smrg					 unsigned count)
335520131375Smrg{
335620131375Smrg}
335720131375Smrg
3358a884aba1Smrgstatic pthread_mutex_t bufmgr_list_mutex = PTHREAD_MUTEX_INITIALIZER;
3359a884aba1Smrgstatic drmMMListHead bufmgr_list = { &bufmgr_list, &bufmgr_list };
3360a884aba1Smrg
3361a884aba1Smrgstatic drm_intel_bufmgr_gem *
3362a884aba1Smrgdrm_intel_bufmgr_gem_find(int fd)
3363a884aba1Smrg{
3364a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
3365a884aba1Smrg
3366a884aba1Smrg	DRMLISTFOREACHENTRY(bufmgr_gem, &bufmgr_list, managers) {
3367a884aba1Smrg		if (bufmgr_gem->fd == fd) {
3368a884aba1Smrg			atomic_inc(&bufmgr_gem->refcount);
3369a884aba1Smrg			return bufmgr_gem;
3370a884aba1Smrg		}
3371a884aba1Smrg	}
3372a884aba1Smrg
3373a884aba1Smrg	return NULL;
3374a884aba1Smrg}
3375a884aba1Smrg
3376a884aba1Smrgstatic void
3377a884aba1Smrgdrm_intel_bufmgr_gem_unref(drm_intel_bufmgr *bufmgr)
3378a884aba1Smrg{
3379a884aba1Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
3380a884aba1Smrg
33813b115362Smrg	if (atomic_add_unless(&bufmgr_gem->refcount, -1, 1))
33823b115362Smrg		return;
3383a884aba1Smrg
33843b115362Smrg	pthread_mutex_lock(&bufmgr_list_mutex);
3385a884aba1Smrg
33863b115362Smrg	if (atomic_dec_and_test(&bufmgr_gem->refcount)) {
33873b115362Smrg		DRMLISTDEL(&bufmgr_gem->managers);
33883b115362Smrg		drm_intel_bufmgr_gem_destroy(bufmgr);
3389a884aba1Smrg	}
33903b115362Smrg
33913b115362Smrg	pthread_mutex_unlock(&bufmgr_list_mutex);
3392a884aba1Smrg}
3393a884aba1Smrg
33946260e5d5Smrgdrm_public void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo)
33952ee35494Smrg{
33962ee35494Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
33972ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
33982ee35494Smrg
33992ee35494Smrg	if (bo_gem->gtt_virtual)
34002ee35494Smrg		return bo_gem->gtt_virtual;
34012ee35494Smrg
34022ee35494Smrg	if (bo_gem->is_userptr)
34032ee35494Smrg		return NULL;
34042ee35494Smrg
34052ee35494Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
34062ee35494Smrg	if (bo_gem->gtt_virtual == NULL) {
34072ee35494Smrg		struct drm_i915_gem_mmap_gtt mmap_arg;
34082ee35494Smrg		void *ptr;
34092ee35494Smrg
34102ee35494Smrg		DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
34112ee35494Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
34122ee35494Smrg
34132ee35494Smrg		if (bo_gem->map_count++ == 0)
34142ee35494Smrg			drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
34152ee35494Smrg
34162ee35494Smrg		memclear(mmap_arg);
34172ee35494Smrg		mmap_arg.handle = bo_gem->gem_handle;
34182ee35494Smrg
34192ee35494Smrg		/* Get the fake offset back... */
34202ee35494Smrg		ptr = MAP_FAILED;
34212ee35494Smrg		if (drmIoctl(bufmgr_gem->fd,
34222ee35494Smrg			     DRM_IOCTL_I915_GEM_MMAP_GTT,
34232ee35494Smrg			     &mmap_arg) == 0) {
34242ee35494Smrg			/* and mmap it */
34252ee35494Smrg			ptr = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE,
34262ee35494Smrg				       MAP_SHARED, bufmgr_gem->fd,
34272ee35494Smrg				       mmap_arg.offset);
34282ee35494Smrg		}
34292ee35494Smrg		if (ptr == MAP_FAILED) {
34302ee35494Smrg			if (--bo_gem->map_count == 0)
34312ee35494Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
34322ee35494Smrg			ptr = NULL;
34332ee35494Smrg		}
34342ee35494Smrg
34352ee35494Smrg		bo_gem->gtt_virtual = ptr;
34362ee35494Smrg	}
34372ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
34382ee35494Smrg
34392ee35494Smrg	return bo_gem->gtt_virtual;
34402ee35494Smrg}
34412ee35494Smrg
34426260e5d5Smrgdrm_public void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo)
34432ee35494Smrg{
34442ee35494Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
34452ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
34462ee35494Smrg
34472ee35494Smrg	if (bo_gem->mem_virtual)
34482ee35494Smrg		return bo_gem->mem_virtual;
34492ee35494Smrg
34502ee35494Smrg	if (bo_gem->is_userptr) {
34512ee35494Smrg		/* Return the same user ptr */
34522ee35494Smrg		return bo_gem->user_virtual;
34532ee35494Smrg	}
34542ee35494Smrg
34552ee35494Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
34562ee35494Smrg	if (!bo_gem->mem_virtual) {
34572ee35494Smrg		struct drm_i915_gem_mmap mmap_arg;
34582ee35494Smrg
34592ee35494Smrg		if (bo_gem->map_count++ == 0)
34602ee35494Smrg			drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
34612ee35494Smrg
34622ee35494Smrg		DBG("bo_map: %d (%s), map_count=%d\n",
34632ee35494Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
34642ee35494Smrg
34652ee35494Smrg		memclear(mmap_arg);
34662ee35494Smrg		mmap_arg.handle = bo_gem->gem_handle;
34672ee35494Smrg		mmap_arg.size = bo->size;
34682ee35494Smrg		if (drmIoctl(bufmgr_gem->fd,
34692ee35494Smrg			     DRM_IOCTL_I915_GEM_MMAP,
34702ee35494Smrg			     &mmap_arg)) {
34712ee35494Smrg			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
34722ee35494Smrg			    __FILE__, __LINE__, bo_gem->gem_handle,
34732ee35494Smrg			    bo_gem->name, strerror(errno));
34742ee35494Smrg			if (--bo_gem->map_count == 0)
34752ee35494Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
34762ee35494Smrg		} else {
34772ee35494Smrg			VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
34782ee35494Smrg			bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
34792ee35494Smrg		}
34802ee35494Smrg	}
34812ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
34822ee35494Smrg
34832ee35494Smrg	return bo_gem->mem_virtual;
34842ee35494Smrg}
34852ee35494Smrg
34866260e5d5Smrgdrm_public void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo)
34872ee35494Smrg{
34882ee35494Smrg	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
34892ee35494Smrg	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
34902ee35494Smrg
34912ee35494Smrg	if (bo_gem->wc_virtual)
34922ee35494Smrg		return bo_gem->wc_virtual;
34932ee35494Smrg
34942ee35494Smrg	if (bo_gem->is_userptr)
34952ee35494Smrg		return NULL;
34962ee35494Smrg
34972ee35494Smrg	pthread_mutex_lock(&bufmgr_gem->lock);
34982ee35494Smrg	if (!bo_gem->wc_virtual) {
34992ee35494Smrg		struct drm_i915_gem_mmap mmap_arg;
35002ee35494Smrg
35012ee35494Smrg		if (bo_gem->map_count++ == 0)
35022ee35494Smrg			drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
35032ee35494Smrg
35042ee35494Smrg		DBG("bo_map: %d (%s), map_count=%d\n",
35052ee35494Smrg		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
35062ee35494Smrg
35072ee35494Smrg		memclear(mmap_arg);
35082ee35494Smrg		mmap_arg.handle = bo_gem->gem_handle;
35092ee35494Smrg		mmap_arg.size = bo->size;
35102ee35494Smrg		mmap_arg.flags = I915_MMAP_WC;
35112ee35494Smrg		if (drmIoctl(bufmgr_gem->fd,
35122ee35494Smrg			     DRM_IOCTL_I915_GEM_MMAP,
35132ee35494Smrg			     &mmap_arg)) {
35142ee35494Smrg			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
35152ee35494Smrg			    __FILE__, __LINE__, bo_gem->gem_handle,
35162ee35494Smrg			    bo_gem->name, strerror(errno));
35172ee35494Smrg			if (--bo_gem->map_count == 0)
35182ee35494Smrg				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
35192ee35494Smrg		} else {
35202ee35494Smrg			VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
35212ee35494Smrg			bo_gem->wc_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
35222ee35494Smrg		}
35232ee35494Smrg	}
35242ee35494Smrg	pthread_mutex_unlock(&bufmgr_gem->lock);
35252ee35494Smrg
35262ee35494Smrg	return bo_gem->wc_virtual;
35272ee35494Smrg}
35282ee35494Smrg
352922944501Smrg/**
353022944501Smrg * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
353122944501Smrg * and manage map buffer objections.
353222944501Smrg *
353322944501Smrg * \param fd File descriptor of the opened DRM device.
353422944501Smrg */
35356260e5d5Smrgdrm_public drm_intel_bufmgr *
353622944501Smrgdrm_intel_bufmgr_gem_init(int fd, int batch_size)
353722944501Smrg{
353822944501Smrg	drm_intel_bufmgr_gem *bufmgr_gem;
353922944501Smrg	struct drm_i915_gem_get_aperture aperture;
354022944501Smrg	drm_i915_getparam_t gp;
354120131375Smrg	int ret, tmp;
354222944501Smrg
3543a884aba1Smrg	pthread_mutex_lock(&bufmgr_list_mutex);
3544a884aba1Smrg
3545a884aba1Smrg	bufmgr_gem = drm_intel_bufmgr_gem_find(fd);
3546a884aba1Smrg	if (bufmgr_gem)
3547a884aba1Smrg		goto exit;
3548a884aba1Smrg
354922944501Smrg	bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
355022944501Smrg	if (bufmgr_gem == NULL)
3551a884aba1Smrg		goto exit;
355222944501Smrg
355322944501Smrg	bufmgr_gem->fd = fd;
3554a884aba1Smrg	atomic_set(&bufmgr_gem->refcount, 1);
355522944501Smrg
355622944501Smrg	if (pthread_mutex_init(&bufmgr_gem->lock, NULL) != 0) {
355722944501Smrg		free(bufmgr_gem);
3558a884aba1Smrg		bufmgr_gem = NULL;
3559a884aba1Smrg		goto exit;
356022944501Smrg	}
356122944501Smrg
3562424e9256Smrg	memclear(aperture);
35636d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd,
35646d98c517Smrg		       DRM_IOCTL_I915_GEM_GET_APERTURE,
35656d98c517Smrg		       &aperture);
356622944501Smrg
356722944501Smrg	if (ret == 0)
356822944501Smrg		bufmgr_gem->gtt_size = aperture.aper_available_size;
356922944501Smrg	else {
357022944501Smrg		fprintf(stderr, "DRM_IOCTL_I915_GEM_APERTURE failed: %s\n",
357122944501Smrg			strerror(errno));
357222944501Smrg		bufmgr_gem->gtt_size = 128 * 1024 * 1024;
357322944501Smrg		fprintf(stderr, "Assuming %dkB available aperture size.\n"
357422944501Smrg			"May lead to reduced performance or incorrect "
357522944501Smrg			"rendering.\n",
357622944501Smrg			(int)bufmgr_gem->gtt_size / 1024);
357722944501Smrg	}
357822944501Smrg
357920131375Smrg	bufmgr_gem->pci_device = get_pci_device_id(bufmgr_gem);
358022944501Smrg
358120131375Smrg	if (IS_GEN2(bufmgr_gem->pci_device))
358222944501Smrg		bufmgr_gem->gen = 2;
358320131375Smrg	else if (IS_GEN3(bufmgr_gem->pci_device))
358422944501Smrg		bufmgr_gem->gen = 3;
358520131375Smrg	else if (IS_GEN4(bufmgr_gem->pci_device))
358622944501Smrg		bufmgr_gem->gen = 4;
358720131375Smrg	else if (IS_GEN5(bufmgr_gem->pci_device))
358820131375Smrg		bufmgr_gem->gen = 5;
358920131375Smrg	else if (IS_GEN6(bufmgr_gem->pci_device))
359022944501Smrg		bufmgr_gem->gen = 6;
359120131375Smrg	else if (IS_GEN7(bufmgr_gem->pci_device))
359220131375Smrg		bufmgr_gem->gen = 7;
359348246ce7Smrg	else
359448246ce7Smrg		/* Treat all further unmatched platforms the same as gen8 */
359520131375Smrg		bufmgr_gem->gen = 8;
359620131375Smrg
359720131375Smrg	if (IS_GEN3(bufmgr_gem->pci_device) &&
359820131375Smrg	    bufmgr_gem->gtt_size > 256*1024*1024) {
359920131375Smrg		/* The unmappable part of gtt on gen 3 (i.e. above 256MB) can't
360020131375Smrg		 * be used for tiled blits. To simplify the accounting, just
3601fe517fc9Smrg		 * subtract the unmappable part (fixed to 256MB on all known
360220131375Smrg		 * gen3 devices) if the kernel advertises it. */
360320131375Smrg		bufmgr_gem->gtt_size -= 256*1024*1024;
360420131375Smrg	}
360520131375Smrg
3606424e9256Smrg	memclear(gp);
360720131375Smrg	gp.value = &tmp;
360822944501Smrg
360922944501Smrg	gp.param = I915_PARAM_HAS_EXECBUF2;
36106d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3611adfa0b0cSmrg	if (ret) {
3612adfa0b0cSmrg		fprintf(stderr, "i915 does not support EXECBUFER2\n");
3613adfa0b0cSmrg		free(bufmgr_gem);
3614adfa0b0cSmrg		bufmgr_gem = NULL;
3615adfa0b0cSmrg        goto exit;
3616adfa0b0cSmrg    }
361722944501Smrg
3618aaba2545Smrg	gp.param = I915_PARAM_HAS_BSD;
36196d98c517Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
36209ce4edccSmrg	bufmgr_gem->has_bsd = ret == 0;
36219ce4edccSmrg
36229ce4edccSmrg	gp.param = I915_PARAM_HAS_BLT;
36239ce4edccSmrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
36249ce4edccSmrg	bufmgr_gem->has_blt = ret == 0;
36259ce4edccSmrg
36269ce4edccSmrg	gp.param = I915_PARAM_HAS_RELAXED_FENCING;
36279ce4edccSmrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
36289ce4edccSmrg	bufmgr_gem->has_relaxed_fencing = ret == 0;
3629aaba2545Smrg
36302ee35494Smrg	gp.param = I915_PARAM_HAS_EXEC_ASYNC;
36312ee35494Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
36322ee35494Smrg	bufmgr_gem->has_exec_async = ret == 0;
36332ee35494Smrg
3634424e9256Smrg	bufmgr_gem->bufmgr.bo_alloc_userptr = check_bo_alloc_userptr;
3635a884aba1Smrg
363620131375Smrg	gp.param = I915_PARAM_HAS_WAIT_TIMEOUT;
363720131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
363820131375Smrg	bufmgr_gem->has_wait_timeout = ret == 0;
363920131375Smrg
364020131375Smrg	gp.param = I915_PARAM_HAS_LLC;
364120131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
364220131375Smrg	if (ret != 0) {
364320131375Smrg		/* Kernel does not supports HAS_LLC query, fallback to GPU
364420131375Smrg		 * generation detection and assume that we have LLC on GEN6/7
364520131375Smrg		 */
364620131375Smrg		bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) |
364720131375Smrg				IS_GEN7(bufmgr_gem->pci_device));
364820131375Smrg	} else
364920131375Smrg		bufmgr_gem->has_llc = *gp.value;
365020131375Smrg
365120131375Smrg	gp.param = I915_PARAM_HAS_VEBOX;
365220131375Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
365320131375Smrg	bufmgr_gem->has_vebox = (ret == 0) & (*gp.value > 0);
365420131375Smrg
3655fe517fc9Smrg	gp.param = I915_PARAM_HAS_EXEC_SOFTPIN;
3656fe517fc9Smrg	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3657fe517fc9Smrg	if (ret == 0 && *gp.value > 0)
3658fe517fc9Smrg		bufmgr_gem->bufmgr.bo_set_softpin_offset = drm_intel_gem_bo_set_softpin_offset;
3659fe517fc9Smrg
366022944501Smrg	if (bufmgr_gem->gen < 4) {
366122944501Smrg		gp.param = I915_PARAM_NUM_FENCES_AVAIL;
366222944501Smrg		gp.value = &bufmgr_gem->available_fences;
36636d98c517Smrg		ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
366422944501Smrg		if (ret) {
366522944501Smrg			fprintf(stderr, "get fences failed: %d [%d]\n", ret,
366622944501Smrg				errno);
366722944501Smrg			fprintf(stderr, "param: %d, val: %d\n", gp.param,
366822944501Smrg				*gp.value);
366922944501Smrg			bufmgr_gem->available_fences = 0;
367022944501Smrg		} else {
367122944501Smrg			/* XXX The kernel reports the total number of fences,
367222944501Smrg			 * including any that may be pinned.
367322944501Smrg			 *
367422944501Smrg			 * We presume that there will be at least one pinned
367522944501Smrg			 * fence for the scanout buffer, but there may be more
367622944501Smrg			 * than one scanout and the user may be manually
367722944501Smrg			 * pinning buffers. Let's move to execbuffer2 and
367822944501Smrg			 * thereby forget the insanity of using fences...
367922944501Smrg			 */
368022944501Smrg			bufmgr_gem->available_fences -= 2;
368122944501Smrg			if (bufmgr_gem->available_fences < 0)
368222944501Smrg				bufmgr_gem->available_fences = 0;
368322944501Smrg		}
368422944501Smrg	}
368522944501Smrg
3686fe517fc9Smrg	if (bufmgr_gem->gen >= 8) {
3687fe517fc9Smrg		gp.param = I915_PARAM_HAS_ALIASING_PPGTT;
3688fe517fc9Smrg		ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
3689fe517fc9Smrg		if (ret == 0 && *gp.value == 3)
3690fe517fc9Smrg			bufmgr_gem->bufmgr.bo_use_48b_address_range = drm_intel_gem_bo_use_48b_address_range;
3691fe517fc9Smrg	}
3692fe517fc9Smrg
369322944501Smrg	/* Let's go with one relocation per every 2 dwords (but round down a bit
369422944501Smrg	 * since a power of two will mean an extra page allocation for the reloc
369522944501Smrg	 * buffer).
369622944501Smrg	 *
369722944501Smrg	 * Every 4 was too few for the blender benchmark.
369822944501Smrg	 */
369922944501Smrg	bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2;
370022944501Smrg
370122944501Smrg	bufmgr_gem->bufmgr.bo_alloc = drm_intel_gem_bo_alloc;
370222944501Smrg	bufmgr_gem->bufmgr.bo_alloc_for_render =
370322944501Smrg	    drm_intel_gem_bo_alloc_for_render;
370422944501Smrg	bufmgr_gem->bufmgr.bo_alloc_tiled = drm_intel_gem_bo_alloc_tiled;
370522944501Smrg	bufmgr_gem->bufmgr.bo_reference = drm_intel_gem_bo_reference;
370622944501Smrg	bufmgr_gem->bufmgr.bo_unreference = drm_intel_gem_bo_unreference;
370722944501Smrg	bufmgr_gem->bufmgr.bo_map = drm_intel_gem_bo_map;
370822944501Smrg	bufmgr_gem->bufmgr.bo_unmap = drm_intel_gem_bo_unmap;
370922944501Smrg	bufmgr_gem->bufmgr.bo_subdata = drm_intel_gem_bo_subdata;
371022944501Smrg	bufmgr_gem->bufmgr.bo_get_subdata = drm_intel_gem_bo_get_subdata;
371122944501Smrg	bufmgr_gem->bufmgr.bo_wait_rendering = drm_intel_gem_bo_wait_rendering;
371222944501Smrg	bufmgr_gem->bufmgr.bo_emit_reloc = drm_intel_gem_bo_emit_reloc;
371322944501Smrg	bufmgr_gem->bufmgr.bo_emit_reloc_fence = drm_intel_gem_bo_emit_reloc_fence;
371422944501Smrg	bufmgr_gem->bufmgr.bo_pin = drm_intel_gem_bo_pin;
371522944501Smrg	bufmgr_gem->bufmgr.bo_unpin = drm_intel_gem_bo_unpin;
371622944501Smrg	bufmgr_gem->bufmgr.bo_get_tiling = drm_intel_gem_bo_get_tiling;
371722944501Smrg	bufmgr_gem->bufmgr.bo_set_tiling = drm_intel_gem_bo_set_tiling;
371822944501Smrg	bufmgr_gem->bufmgr.bo_flink = drm_intel_gem_bo_flink;
3719adfa0b0cSmrg	bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec2;
3720adfa0b0cSmrg	bufmgr_gem->bufmgr.bo_mrb_exec = drm_intel_gem_bo_mrb_exec2;
372122944501Smrg	bufmgr_gem->bufmgr.bo_busy = drm_intel_gem_bo_busy;
372222944501Smrg	bufmgr_gem->bufmgr.bo_madvise = drm_intel_gem_bo_madvise;
3723a884aba1Smrg	bufmgr_gem->bufmgr.destroy = drm_intel_bufmgr_gem_unref;
372422944501Smrg	bufmgr_gem->bufmgr.debug = 0;
372522944501Smrg	bufmgr_gem->bufmgr.check_aperture_space =
372622944501Smrg	    drm_intel_gem_check_aperture_space;
372722944501Smrg	bufmgr_gem->bufmgr.bo_disable_reuse = drm_intel_gem_bo_disable_reuse;
3728aaba2545Smrg	bufmgr_gem->bufmgr.bo_is_reusable = drm_intel_gem_bo_is_reusable;
372922944501Smrg	bufmgr_gem->bufmgr.get_pipe_from_crtc_id =
373022944501Smrg	    drm_intel_gem_get_pipe_from_crtc_id;
373122944501Smrg	bufmgr_gem->bufmgr.bo_references = drm_intel_gem_bo_references;
373222944501Smrg
3733aaba2545Smrg	init_cache_buckets(bufmgr_gem);
373422944501Smrg
373520131375Smrg	DRMINITLISTHEAD(&bufmgr_gem->vma_cache);
373620131375Smrg	bufmgr_gem->vma_max = -1; /* unlimited by default */
373720131375Smrg
3738a884aba1Smrg	DRMLISTADD(&bufmgr_gem->managers, &bufmgr_list);
3739a884aba1Smrg
3740a884aba1Smrgexit:
3741a884aba1Smrg	pthread_mutex_unlock(&bufmgr_list_mutex);
3742a884aba1Smrg
3743a884aba1Smrg	return bufmgr_gem != NULL ? &bufmgr_gem->bufmgr : NULL;
374422944501Smrg}
3745