Blame intel/intel_bufmgr_gem.c

Packit 631bab
/**************************************************************************
Packit 631bab
 *
Packit 631bab
 * Copyright © 2007 Red Hat Inc.
Packit 631bab
 * Copyright © 2007-2012 Intel Corporation
Packit 631bab
 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
Packit 631bab
 * All Rights Reserved.
Packit 631bab
 *
Packit 631bab
 * Permission is hereby granted, free of charge, to any person obtaining a
Packit 631bab
 * copy of this software and associated documentation files (the
Packit 631bab
 * "Software"), to deal in the Software without restriction, including
Packit 631bab
 * without limitation the rights to use, copy, modify, merge, publish,
Packit 631bab
 * distribute, sub license, and/or sell copies of the Software, and to
Packit 631bab
 * permit persons to whom the Software is furnished to do so, subject to
Packit 631bab
 * the following conditions:
Packit 631bab
 *
Packit 631bab
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit 631bab
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit 631bab
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
Packit 631bab
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
Packit 631bab
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
Packit 631bab
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
Packit 631bab
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit 631bab
 *
Packit 631bab
 * The above copyright notice and this permission notice (including the
Packit 631bab
 * next paragraph) shall be included in all copies or substantial portions
Packit 631bab
 * of the Software.
Packit 631bab
 *
Packit 631bab
 *
Packit 631bab
 **************************************************************************/
Packit 631bab
/*
Packit 631bab
 * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
Packit 631bab
 *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
Packit 631bab
 *	    Eric Anholt <eric@anholt.net>
Packit 631bab
 *	    Dave Airlie <airlied@linux.ie>
Packit 631bab
 */
Packit 631bab
Packit 631bab
#include <xf86drm.h>
Packit 631bab
#include <xf86atomic.h>
Packit 631bab
#include <fcntl.h>
Packit 631bab
#include <stdio.h>
Packit 631bab
#include <stdlib.h>
Packit 631bab
#include <string.h>
Packit 631bab
#include <unistd.h>
Packit 631bab
#include <assert.h>
Packit 631bab
#include <pthread.h>
Packit 631bab
#include <sys/ioctl.h>
Packit 631bab
#include <sys/stat.h>
Packit 631bab
#include <sys/types.h>
Packit 631bab
#include <stdbool.h>
Packit 631bab
Packit 631bab
#include "errno.h"
Packit 631bab
#ifndef ETIME
Packit 631bab
#define ETIME ETIMEDOUT
Packit 631bab
#endif
Packit 631bab
#include "libdrm_macros.h"
Packit 631bab
#include "libdrm_lists.h"
Packit 631bab
#include "intel_bufmgr.h"
Packit 631bab
#include "intel_bufmgr_priv.h"
Packit 631bab
#include "intel_chipset.h"
Packit 631bab
#include "string.h"
Packit 631bab
Packit 631bab
#include "i915_drm.h"
Packit 631bab
#include "uthash.h"
Packit 631bab
Packit 631bab
#if HAVE_VALGRIND
Packit 631bab
#include <valgrind.h>
Packit 631bab
#include <memcheck.h>
Packit 631bab
#define VG(x) x
Packit 631bab
#else
Packit 631bab
#define VG(x)
Packit 631bab
#endif
Packit 631bab
Packit 631bab
#define memclear(s) memset(&s, 0, sizeof(s))
Packit 631bab
Packit 631bab
#define DBG(...) do {					\
Packit 631bab
	if (bufmgr_gem->bufmgr.debug)			\
Packit 631bab
		fprintf(stderr, __VA_ARGS__);		\
Packit 631bab
} while (0)
Packit 631bab
Packit 631bab
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
Packit 631bab
#define MAX2(A, B) ((A) > (B) ? (A) : (B))
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * upper_32_bits - return bits 32-63 of a number
Packit 631bab
 * @n: the number we're accessing
Packit 631bab
 *
Packit 631bab
 * A basic shift-right of a 64- or 32-bit quantity.  Use this to suppress
Packit 631bab
 * the "right shift count >= width of type" warning when that quantity is
Packit 631bab
 * 32-bits.
Packit 631bab
 */
Packit 631bab
#define upper_32_bits(n) ((__u32)(((n) >> 16) >> 16))
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * lower_32_bits - return bits 0-31 of a number
Packit 631bab
 * @n: the number we're accessing
Packit 631bab
 */
Packit 631bab
#define lower_32_bits(n) ((__u32)(n))
Packit 631bab
Packit 631bab
typedef struct _drm_intel_bo_gem drm_intel_bo_gem;
Packit 631bab
Packit 631bab
struct drm_intel_gem_bo_bucket {
Packit 631bab
	drmMMListHead head;
Packit 631bab
	unsigned long size;
Packit 631bab
};
Packit 631bab
Packit 631bab
typedef struct _drm_intel_bufmgr_gem {
Packit 631bab
	drm_intel_bufmgr bufmgr;
Packit 631bab
Packit 631bab
	atomic_t refcount;
Packit 631bab
Packit 631bab
	int fd;
Packit 631bab
Packit 631bab
	int max_relocs;
Packit 631bab
Packit 631bab
	pthread_mutex_t lock;
Packit 631bab
Packit 631bab
	struct drm_i915_gem_exec_object *exec_objects;
Packit 631bab
	struct drm_i915_gem_exec_object2 *exec2_objects;
Packit 631bab
	drm_intel_bo **exec_bos;
Packit 631bab
	int exec_size;
Packit 631bab
	int exec_count;
Packit 631bab
Packit 631bab
	/** Array of lists of cached gem objects of power-of-two sizes */
Packit 631bab
	struct drm_intel_gem_bo_bucket cache_bucket[14 * 4];
Packit 631bab
	int num_buckets;
Packit 631bab
	time_t time;
Packit 631bab
Packit 631bab
	drmMMListHead managers;
Packit 631bab
Packit 631bab
	drm_intel_bo_gem *name_table;
Packit 631bab
	drm_intel_bo_gem *handle_table;
Packit 631bab
Packit 631bab
	drmMMListHead vma_cache;
Packit 631bab
	int vma_count, vma_open, vma_max;
Packit 631bab
Packit 631bab
	uint64_t gtt_size;
Packit 631bab
	int available_fences;
Packit 631bab
	int pci_device;
Packit 631bab
	int gen;
Packit 631bab
	unsigned int has_bsd : 1;
Packit 631bab
	unsigned int has_blt : 1;
Packit 631bab
	unsigned int has_relaxed_fencing : 1;
Packit 631bab
	unsigned int has_llc : 1;
Packit 631bab
	unsigned int has_wait_timeout : 1;
Packit 631bab
	unsigned int bo_reuse : 1;
Packit 631bab
	unsigned int no_exec : 1;
Packit 631bab
	unsigned int has_vebox : 1;
Packit 631bab
	unsigned int has_exec_async : 1;
Packit 631bab
	bool fenced_relocs;
Packit 631bab
Packit 631bab
	struct {
Packit 631bab
		void *ptr;
Packit 631bab
		uint32_t handle;
Packit 631bab
	} userptr_active;
Packit 631bab
Packit 631bab
} drm_intel_bufmgr_gem;
Packit 631bab
Packit 631bab
#define DRM_INTEL_RELOC_FENCE (1<<0)
Packit 631bab
Packit 631bab
typedef struct _drm_intel_reloc_target_info {
Packit 631bab
	drm_intel_bo *bo;
Packit 631bab
	int flags;
Packit 631bab
} drm_intel_reloc_target;
Packit 631bab
Packit 631bab
struct _drm_intel_bo_gem {
Packit 631bab
	drm_intel_bo bo;
Packit 631bab
Packit 631bab
	atomic_t refcount;
Packit 631bab
	uint32_t gem_handle;
Packit 631bab
	const char *name;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Kenel-assigned global name for this object
Packit 631bab
         *
Packit 631bab
         * List contains both flink named and prime fd'd objects
Packit 631bab
	 */
Packit 631bab
	unsigned int global_name;
Packit 631bab
Packit 631bab
	UT_hash_handle handle_hh;
Packit 631bab
	UT_hash_handle name_hh;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Index of the buffer within the validation list while preparing a
Packit 631bab
	 * batchbuffer execution.
Packit 631bab
	 */
Packit 631bab
	int validate_index;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Current tiling mode
Packit 631bab
	 */
Packit 631bab
	uint32_t tiling_mode;
Packit 631bab
	uint32_t swizzle_mode;
Packit 631bab
	unsigned long stride;
Packit 631bab
Packit 631bab
	unsigned long kflags;
Packit 631bab
Packit 631bab
	time_t free_time;
Packit 631bab
Packit 631bab
	/** Array passed to the DRM containing relocation information. */
Packit 631bab
	struct drm_i915_gem_relocation_entry *relocs;
Packit 631bab
	/**
Packit 631bab
	 * Array of info structs corresponding to relocs[i].target_handle etc
Packit 631bab
	 */
Packit 631bab
	drm_intel_reloc_target *reloc_target_info;
Packit 631bab
	/** Number of entries in relocs */
Packit 631bab
	int reloc_count;
Packit 631bab
	/** Array of BOs that are referenced by this buffer and will be softpinned */
Packit 631bab
	drm_intel_bo **softpin_target;
Packit 631bab
	/** Number softpinned BOs that are referenced by this buffer */
Packit 631bab
	int softpin_target_count;
Packit 631bab
	/** Maximum amount of softpinned BOs that are referenced by this buffer */
Packit 631bab
	int softpin_target_size;
Packit 631bab
Packit 631bab
	/** Mapped address for the buffer, saved across map/unmap cycles */
Packit 631bab
	void *mem_virtual;
Packit 631bab
	/** GTT virtual address for the buffer, saved across map/unmap cycles */
Packit 631bab
	void *gtt_virtual;
Packit 631bab
	/** WC CPU address for the buffer, saved across map/unmap cycles */
Packit 631bab
	void *wc_virtual;
Packit 631bab
	/**
Packit 631bab
	 * Virtual address of the buffer allocated by user, used for userptr
Packit 631bab
	 * objects only.
Packit 631bab
	 */
Packit 631bab
	void *user_virtual;
Packit 631bab
	int map_count;
Packit 631bab
	drmMMListHead vma_list;
Packit 631bab
Packit 631bab
	/** BO cache list */
Packit 631bab
	drmMMListHead head;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Boolean of whether this BO and its children have been included in
Packit 631bab
	 * the current drm_intel_bufmgr_check_aperture_space() total.
Packit 631bab
	 */
Packit 631bab
	bool included_in_check_aperture;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Boolean of whether this buffer has been used as a relocation
Packit 631bab
	 * target and had its size accounted for, and thus can't have any
Packit 631bab
	 * further relocations added to it.
Packit 631bab
	 */
Packit 631bab
	bool used_as_reloc_target;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Boolean of whether we have encountered an error whilst building the relocation tree.
Packit 631bab
	 */
Packit 631bab
	bool has_error;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Boolean of whether this buffer can be re-used
Packit 631bab
	 */
Packit 631bab
	bool reusable;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Boolean of whether the GPU is definitely not accessing the buffer.
Packit 631bab
	 *
Packit 631bab
	 * This is only valid when reusable, since non-reusable
Packit 631bab
	 * buffers are those that have been shared with other
Packit 631bab
	 * processes, so we don't know their state.
Packit 631bab
	 */
Packit 631bab
	bool idle;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Boolean of whether this buffer was allocated with userptr
Packit 631bab
	 */
Packit 631bab
	bool is_userptr;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Size in bytes of this buffer and its relocation descendents.
Packit 631bab
	 *
Packit 631bab
	 * Used to avoid costly tree walking in
Packit 631bab
	 * drm_intel_bufmgr_check_aperture in the common case.
Packit 631bab
	 */
Packit 631bab
	int reloc_tree_size;
Packit 631bab
Packit 631bab
	/**
Packit 631bab
	 * Number of potential fence registers required by this buffer and its
Packit 631bab
	 * relocations.
Packit 631bab
	 */
Packit 631bab
	int reloc_tree_fences;
Packit 631bab
Packit 631bab
	/** Flags that we may need to do the SW_FINISH ioctl on unmap. */
Packit 631bab
	bool mapped_cpu_write;
Packit 631bab
};
Packit 631bab
Packit 631bab
static unsigned int
Packit 631bab
drm_intel_gem_estimate_batch_space(drm_intel_bo ** bo_array, int count);
Packit 631bab
Packit 631bab
static unsigned int
Packit 631bab
drm_intel_gem_compute_batch_space(drm_intel_bo ** bo_array, int count);
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
Packit 631bab
			    uint32_t * swizzle_mode);
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo,
Packit 631bab
				     uint32_t tiling_mode,
Packit 631bab
				     uint32_t stride);
Packit 631bab
Packit 631bab
static void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo,
Packit 631bab
						      time_t time);
Packit 631bab
Packit 631bab
static void drm_intel_gem_bo_unreference(drm_intel_bo *bo);
Packit 631bab
Packit 631bab
static void drm_intel_gem_bo_free(drm_intel_bo *bo);
Packit 631bab
Packit 631bab
static inline drm_intel_bo_gem *to_bo_gem(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
        return (drm_intel_bo_gem *)bo;
Packit 631bab
}
Packit 631bab
Packit 631bab
static unsigned long
Packit 631bab
drm_intel_gem_bo_tile_size(drm_intel_bufmgr_gem *bufmgr_gem, unsigned long size,
Packit 631bab
			   uint32_t *tiling_mode)
Packit 631bab
{
Packit 631bab
	unsigned long min_size, max_size;
Packit 631bab
	unsigned long i;
Packit 631bab
Packit 631bab
	if (*tiling_mode == I915_TILING_NONE)
Packit 631bab
		return size;
Packit 631bab
Packit 631bab
	/* 965+ just need multiples of page size for tiling */
Packit 631bab
	if (bufmgr_gem->gen >= 4)
Packit 631bab
		return ROUND_UP_TO(size, 4096);
Packit 631bab
Packit 631bab
	/* Older chips need powers of two, of at least 512k or 1M */
Packit 631bab
	if (bufmgr_gem->gen == 3) {
Packit 631bab
		min_size = 1024*1024;
Packit 631bab
		max_size = 128*1024*1024;
Packit 631bab
	} else {
Packit 631bab
		min_size = 512*1024;
Packit 631bab
		max_size = 64*1024*1024;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (size > max_size) {
Packit 631bab
		*tiling_mode = I915_TILING_NONE;
Packit 631bab
		return size;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* Do we need to allocate every page for the fence? */
Packit 631bab
	if (bufmgr_gem->has_relaxed_fencing)
Packit 631bab
		return ROUND_UP_TO(size, 4096);
Packit 631bab
Packit 631bab
	for (i = min_size; i < size; i <<= 1)
Packit 631bab
		;
Packit 631bab
Packit 631bab
	return i;
Packit 631bab
}
Packit 631bab
Packit 631bab
/*
Packit 631bab
 * Round a given pitch up to the minimum required for X tiling on a
Packit 631bab
 * given chip.  We use 512 as the minimum to allow for a later tiling
Packit 631bab
 * change.
Packit 631bab
 */
Packit 631bab
static unsigned long
Packit 631bab
drm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem,
Packit 631bab
			    unsigned long pitch, uint32_t *tiling_mode)
Packit 631bab
{
Packit 631bab
	unsigned long tile_width;
Packit 631bab
	unsigned long i;
Packit 631bab
Packit 631bab
	/* If untiled, then just align it so that we can do rendering
Packit 631bab
	 * to it with the 3D engine.
Packit 631bab
	 */
Packit 631bab
	if (*tiling_mode == I915_TILING_NONE)
Packit 631bab
		return ALIGN(pitch, 64);
Packit 631bab
Packit 631bab
	if (*tiling_mode == I915_TILING_X
Packit 631bab
			|| (IS_915(bufmgr_gem->pci_device)
Packit 631bab
			    && *tiling_mode == I915_TILING_Y))
Packit 631bab
		tile_width = 512;
Packit 631bab
	else
Packit 631bab
		tile_width = 128;
Packit 631bab
Packit 631bab
	/* 965 is flexible */
Packit 631bab
	if (bufmgr_gem->gen >= 4)
Packit 631bab
		return ROUND_UP_TO(pitch, tile_width);
Packit 631bab
Packit 631bab
	/* The older hardware has a maximum pitch of 8192 with tiled
Packit 631bab
	 * surfaces, so fallback to untiled if it's too large.
Packit 631bab
	 */
Packit 631bab
	if (pitch > 8192) {
Packit 631bab
		*tiling_mode = I915_TILING_NONE;
Packit 631bab
		return ALIGN(pitch, 64);
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* Pre-965 needs power of two tile width */
Packit 631bab
	for (i = tile_width; i < pitch; i <<= 1)
Packit 631bab
		;
Packit 631bab
Packit 631bab
	return i;
Packit 631bab
}
Packit 631bab
Packit 631bab
static struct drm_intel_gem_bo_bucket *
Packit 631bab
drm_intel_gem_bo_bucket_for_size(drm_intel_bufmgr_gem *bufmgr_gem,
Packit 631bab
				 unsigned long size)
Packit 631bab
{
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
Packit 631bab
		struct drm_intel_gem_bo_bucket *bucket =
Packit 631bab
		    &bufmgr_gem->cache_bucket[i];
Packit 631bab
		if (bucket->size >= size) {
Packit 631bab
			return bucket;
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	return NULL;
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem)
Packit 631bab
{
Packit 631bab
	int i, j;
Packit 631bab
Packit 631bab
	for (i = 0; i < bufmgr_gem->exec_count; i++) {
Packit 631bab
		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
Packit 631bab
		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
		if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) {
Packit 631bab
			DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle,
Packit 631bab
			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
Packit 631bab
			    bo_gem->name);
Packit 631bab
			continue;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		for (j = 0; j < bo_gem->reloc_count; j++) {
Packit 631bab
			drm_intel_bo *target_bo = bo_gem->reloc_target_info[j].bo;
Packit 631bab
			drm_intel_bo_gem *target_gem =
Packit 631bab
			    (drm_intel_bo_gem *) target_bo;
Packit 631bab
Packit 631bab
			DBG("%2d: %d %s(%s)@0x%08x %08x -> "
Packit 631bab
			    "%d (%s)@0x%08x %08x + 0x%08x\n",
Packit 631bab
			    i,
Packit 631bab
			    bo_gem->gem_handle,
Packit 631bab
			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
Packit 631bab
			    bo_gem->name,
Packit 631bab
			    upper_32_bits(bo_gem->relocs[j].offset),
Packit 631bab
			    lower_32_bits(bo_gem->relocs[j].offset),
Packit 631bab
			    target_gem->gem_handle,
Packit 631bab
			    target_gem->name,
Packit 631bab
			    upper_32_bits(target_bo->offset64),
Packit 631bab
			    lower_32_bits(target_bo->offset64),
Packit 631bab
			    bo_gem->relocs[j].delta);
Packit 631bab
		}
Packit 631bab
Packit 631bab
		for (j = 0; j < bo_gem->softpin_target_count; j++) {
Packit 631bab
			drm_intel_bo *target_bo = bo_gem->softpin_target[j];
Packit 631bab
			drm_intel_bo_gem *target_gem =
Packit 631bab
			    (drm_intel_bo_gem *) target_bo;
Packit 631bab
			DBG("%2d: %d %s(%s) -> "
Packit 631bab
			    "%d *(%s)@0x%08x %08x\n",
Packit 631bab
			    i,
Packit 631bab
			    bo_gem->gem_handle,
Packit 631bab
			    bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "",
Packit 631bab
			    bo_gem->name,
Packit 631bab
			    target_gem->gem_handle,
Packit 631bab
			    target_gem->name,
Packit 631bab
			    upper_32_bits(target_bo->offset64),
Packit 631bab
			    lower_32_bits(target_bo->offset64));
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
static inline void
Packit 631bab
drm_intel_gem_bo_reference(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	atomic_inc(&bo_gem->refcount);
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Adds the given buffer to the list of buffers to be validated (moved into the
Packit 631bab
 * appropriate memory type) with the next batch submission.
Packit 631bab
 *
Packit 631bab
 * If a buffer is validated multiple times in a batch submission, it ends up
Packit 631bab
 * with the intersection of the memory type flags and the union of the
Packit 631bab
 * access flags.
Packit 631bab
 */
Packit 631bab
static void
Packit 631bab
drm_intel_add_validate_buffer(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	int index;
Packit 631bab
Packit 631bab
	if (bo_gem->validate_index != -1)
Packit 631bab
		return;
Packit 631bab
Packit 631bab
	/* Extend the array of validation entries as necessary. */
Packit 631bab
	if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
Packit 631bab
		int new_size = bufmgr_gem->exec_size * 2;
Packit 631bab
Packit 631bab
		if (new_size == 0)
Packit 631bab
			new_size = 5;
Packit 631bab
Packit 631bab
		bufmgr_gem->exec_objects =
Packit 631bab
		    realloc(bufmgr_gem->exec_objects,
Packit 631bab
			    sizeof(*bufmgr_gem->exec_objects) * new_size);
Packit 631bab
		bufmgr_gem->exec_bos =
Packit 631bab
		    realloc(bufmgr_gem->exec_bos,
Packit 631bab
			    sizeof(*bufmgr_gem->exec_bos) * new_size);
Packit 631bab
		bufmgr_gem->exec_size = new_size;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	index = bufmgr_gem->exec_count;
Packit 631bab
	bo_gem->validate_index = index;
Packit 631bab
	/* Fill in array entry */
Packit 631bab
	bufmgr_gem->exec_objects[index].handle = bo_gem->gem_handle;
Packit 631bab
	bufmgr_gem->exec_objects[index].relocation_count = bo_gem->reloc_count;
Packit 631bab
	bufmgr_gem->exec_objects[index].relocs_ptr = (uintptr_t) bo_gem->relocs;
Packit 631bab
	bufmgr_gem->exec_objects[index].alignment = bo->align;
Packit 631bab
	bufmgr_gem->exec_objects[index].offset = 0;
Packit 631bab
	bufmgr_gem->exec_bos[index] = bo;
Packit 631bab
	bufmgr_gem->exec_count++;
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
Packit 631bab
	int index;
Packit 631bab
	unsigned long flags;
Packit 631bab
Packit 631bab
	flags = 0;
Packit 631bab
	if (need_fence)
Packit 631bab
		flags |= EXEC_OBJECT_NEEDS_FENCE;
Packit 631bab
Packit 631bab
	if (bo_gem->validate_index != -1) {
Packit 631bab
		bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags;
Packit 631bab
		return;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* Extend the array of validation entries as necessary. */
Packit 631bab
	if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
Packit 631bab
		int new_size = bufmgr_gem->exec_size * 2;
Packit 631bab
Packit 631bab
		if (new_size == 0)
Packit 631bab
			new_size = 5;
Packit 631bab
Packit 631bab
		bufmgr_gem->exec2_objects =
Packit 631bab
			realloc(bufmgr_gem->exec2_objects,
Packit 631bab
				sizeof(*bufmgr_gem->exec2_objects) * new_size);
Packit 631bab
		bufmgr_gem->exec_bos =
Packit 631bab
			realloc(bufmgr_gem->exec_bos,
Packit 631bab
				sizeof(*bufmgr_gem->exec_bos) * new_size);
Packit 631bab
		bufmgr_gem->exec_size = new_size;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	index = bufmgr_gem->exec_count;
Packit 631bab
	bo_gem->validate_index = index;
Packit 631bab
	/* Fill in array entry */
Packit 631bab
	bufmgr_gem->exec2_objects[index].handle = bo_gem->gem_handle;
Packit 631bab
	bufmgr_gem->exec2_objects[index].relocation_count = bo_gem->reloc_count;
Packit 631bab
	bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
Packit 631bab
	bufmgr_gem->exec2_objects[index].alignment = bo->align;
Packit 631bab
	bufmgr_gem->exec2_objects[index].offset = bo->offset64;
Packit 631bab
	bufmgr_gem->exec2_objects[index].flags = bo_gem->kflags | flags;
Packit 631bab
	bufmgr_gem->exec2_objects[index].rsvd1 = 0;
Packit 631bab
	bufmgr_gem->exec2_objects[index].rsvd2 = 0;
Packit 631bab
	bufmgr_gem->exec_bos[index] = bo;
Packit 631bab
	bufmgr_gem->exec_count++;
Packit 631bab
}
Packit 631bab
Packit 631bab
#define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \
Packit 631bab
	sizeof(uint32_t))
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_bo_gem_set_in_aperture_size(drm_intel_bufmgr_gem *bufmgr_gem,
Packit 631bab
				      drm_intel_bo_gem *bo_gem,
Packit 631bab
				      unsigned int alignment)
Packit 631bab
{
Packit 631bab
	unsigned int size;
Packit 631bab
Packit 631bab
	assert(!bo_gem->used_as_reloc_target);
Packit 631bab
Packit 631bab
	/* The older chipsets are far-less flexible in terms of tiling,
Packit 631bab
	 * and require tiled buffer to be size aligned in the aperture.
Packit 631bab
	 * This means that in the worst possible case we will need a hole
Packit 631bab
	 * twice as large as the object in order for it to fit into the
Packit 631bab
	 * aperture. Optimal packing is for wimps.
Packit 631bab
	 */
Packit 631bab
	size = bo_gem->bo.size;
Packit 631bab
	if (bufmgr_gem->gen < 4 && bo_gem->tiling_mode != I915_TILING_NONE) {
Packit 631bab
		unsigned int min_size;
Packit 631bab
Packit 631bab
		if (bufmgr_gem->has_relaxed_fencing) {
Packit 631bab
			if (bufmgr_gem->gen == 3)
Packit 631bab
				min_size = 1024*1024;
Packit 631bab
			else
Packit 631bab
				min_size = 512*1024;
Packit 631bab
Packit 631bab
			while (min_size < size)
Packit 631bab
				min_size *= 2;
Packit 631bab
		} else
Packit 631bab
			min_size = size;
Packit 631bab
Packit 631bab
		/* Account for worst-case alignment. */
Packit 631bab
		alignment = MAX2(alignment, min_size);
Packit 631bab
	}
Packit 631bab
Packit 631bab
	bo_gem->reloc_tree_size = size + alignment;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_setup_reloc_list(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	unsigned int max_relocs = bufmgr_gem->max_relocs;
Packit 631bab
Packit 631bab
	if (bo->size / 4 < max_relocs)
Packit 631bab
		max_relocs = bo->size / 4;
Packit 631bab
Packit 631bab
	bo_gem->relocs = malloc(max_relocs *
Packit 631bab
				sizeof(struct drm_i915_gem_relocation_entry));
Packit 631bab
	bo_gem->reloc_target_info = malloc(max_relocs *
Packit 631bab
					   sizeof(drm_intel_reloc_target));
Packit 631bab
	if (bo_gem->relocs == NULL || bo_gem->reloc_target_info == NULL) {
Packit 631bab
		bo_gem->has_error = true;
Packit 631bab
Packit 631bab
		free (bo_gem->relocs);
Packit 631bab
		bo_gem->relocs = NULL;
Packit 631bab
Packit 631bab
		free (bo_gem->reloc_target_info);
Packit 631bab
		bo_gem->reloc_target_info = NULL;
Packit 631bab
Packit 631bab
		return 1;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_busy(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_busy busy;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	if (bo_gem->reusable && bo_gem->idle)
Packit 631bab
		return false;
Packit 631bab
Packit 631bab
	memclear(busy);
Packit 631bab
	busy.handle = bo_gem->gem_handle;
Packit 631bab
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
Packit 631bab
	if (ret == 0) {
Packit 631bab
		bo_gem->idle = !busy.busy;
Packit 631bab
		return busy.busy;
Packit 631bab
	} else {
Packit 631bab
		return false;
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_madvise_internal(drm_intel_bufmgr_gem *bufmgr_gem,
Packit 631bab
				  drm_intel_bo_gem *bo_gem, int state)
Packit 631bab
{
Packit 631bab
	struct drm_i915_gem_madvise madv;
Packit 631bab
Packit 631bab
	memclear(madv);
Packit 631bab
	madv.handle = bo_gem->gem_handle;
Packit 631bab
	madv.madv = state;
Packit 631bab
	madv.retained = 1;
Packit 631bab
	drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv);
Packit 631bab
Packit 631bab
	return madv.retained;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_madvise(drm_intel_bo *bo, int madv)
Packit 631bab
{
Packit 631bab
	return drm_intel_gem_bo_madvise_internal
Packit 631bab
		((drm_intel_bufmgr_gem *) bo->bufmgr,
Packit 631bab
		 (drm_intel_bo_gem *) bo,
Packit 631bab
		 madv);
Packit 631bab
}
Packit 631bab
Packit 631bab
/* drop the oldest entries that have been purged by the kernel */
Packit 631bab
static void
Packit 631bab
drm_intel_gem_bo_cache_purge_bucket(drm_intel_bufmgr_gem *bufmgr_gem,
Packit 631bab
				    struct drm_intel_gem_bo_bucket *bucket)
Packit 631bab
{
Packit 631bab
	while (!DRMLISTEMPTY(&bucket->head)) {
Packit 631bab
		drm_intel_bo_gem *bo_gem;
Packit 631bab
Packit 631bab
		bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
Packit 631bab
				      bucket->head.next, head);
Packit 631bab
		if (drm_intel_gem_bo_madvise_internal
Packit 631bab
		    (bufmgr_gem, bo_gem, I915_MADV_DONTNEED))
Packit 631bab
			break;
Packit 631bab
Packit 631bab
		DRMLISTDEL(&bo_gem->head);
Packit 631bab
		drm_intel_gem_bo_free(&bo_gem->bo);
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
static drm_intel_bo *
Packit 631bab
drm_intel_gem_bo_alloc_internal(drm_intel_bufmgr *bufmgr,
Packit 631bab
				const char *name,
Packit 631bab
				unsigned long size,
Packit 631bab
				unsigned long flags,
Packit 631bab
				uint32_t tiling_mode,
Packit 631bab
				unsigned long stride,
Packit 631bab
				unsigned int alignment)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem;
Packit 631bab
	unsigned int page_size = getpagesize();
Packit 631bab
	int ret;
Packit 631bab
	struct drm_intel_gem_bo_bucket *bucket;
Packit 631bab
	bool alloc_from_cache;
Packit 631bab
	unsigned long bo_size;
Packit 631bab
	bool for_render = false;
Packit 631bab
Packit 631bab
	if (flags & BO_ALLOC_FOR_RENDER)
Packit 631bab
		for_render = true;
Packit 631bab
Packit 631bab
	/* Round the allocated size up to a power of two number of pages. */
Packit 631bab
	bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, size);
Packit 631bab
Packit 631bab
	/* If we don't have caching at this size, don't actually round the
Packit 631bab
	 * allocation up.
Packit 631bab
	 */
Packit 631bab
	if (bucket == NULL) {
Packit 631bab
		bo_size = size;
Packit 631bab
		if (bo_size < page_size)
Packit 631bab
			bo_size = page_size;
Packit 631bab
	} else {
Packit 631bab
		bo_size = bucket->size;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
	/* Get a buffer out of the cache if available */
Packit 631bab
retry:
Packit 631bab
	alloc_from_cache = false;
Packit 631bab
	if (bucket != NULL && !DRMLISTEMPTY(&bucket->head)) {
Packit 631bab
		if (for_render) {
Packit 631bab
			/* Allocate new render-target BOs from the tail (MRU)
Packit 631bab
			 * of the list, as it will likely be hot in the GPU
Packit 631bab
			 * cache and in the aperture for us.
Packit 631bab
			 */
Packit 631bab
			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
Packit 631bab
					      bucket->head.prev, head);
Packit 631bab
			DRMLISTDEL(&bo_gem->head);
Packit 631bab
			alloc_from_cache = true;
Packit 631bab
			bo_gem->bo.align = alignment;
Packit 631bab
		} else {
Packit 631bab
			assert(alignment == 0);
Packit 631bab
			/* For non-render-target BOs (where we're probably
Packit 631bab
			 * going to map it first thing in order to fill it
Packit 631bab
			 * with data), check if the last BO in the cache is
Packit 631bab
			 * unbusy, and only reuse in that case. Otherwise,
Packit 631bab
			 * allocating a new buffer is probably faster than
Packit 631bab
			 * waiting for the GPU to finish.
Packit 631bab
			 */
Packit 631bab
			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
Packit 631bab
					      bucket->head.next, head);
Packit 631bab
			if (!drm_intel_gem_bo_busy(&bo_gem->bo)) {
Packit 631bab
				alloc_from_cache = true;
Packit 631bab
				DRMLISTDEL(&bo_gem->head);
Packit 631bab
			}
Packit 631bab
		}
Packit 631bab
Packit 631bab
		if (alloc_from_cache) {
Packit 631bab
			if (!drm_intel_gem_bo_madvise_internal
Packit 631bab
			    (bufmgr_gem, bo_gem, I915_MADV_WILLNEED)) {
Packit 631bab
				drm_intel_gem_bo_free(&bo_gem->bo);
Packit 631bab
				drm_intel_gem_bo_cache_purge_bucket(bufmgr_gem,
Packit 631bab
								    bucket);
Packit 631bab
				goto retry;
Packit 631bab
			}
Packit 631bab
Packit 631bab
			if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo,
Packit 631bab
								 tiling_mode,
Packit 631bab
								 stride)) {
Packit 631bab
				drm_intel_gem_bo_free(&bo_gem->bo);
Packit 631bab
				goto retry;
Packit 631bab
			}
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (!alloc_from_cache) {
Packit 631bab
		struct drm_i915_gem_create create;
Packit 631bab
Packit 631bab
		bo_gem = calloc(1, sizeof(*bo_gem));
Packit 631bab
		if (!bo_gem)
Packit 631bab
			goto err;
Packit 631bab
Packit 631bab
		/* drm_intel_gem_bo_free calls DRMLISTDEL() for an uninitialized
Packit 631bab
		   list (vma_list), so better set the list head here */
Packit 631bab
		DRMINITLISTHEAD(&bo_gem->vma_list);
Packit 631bab
Packit 631bab
		bo_gem->bo.size = bo_size;
Packit 631bab
Packit 631bab
		memclear(create);
Packit 631bab
		create.size = bo_size;
Packit 631bab
Packit 631bab
		ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
			       DRM_IOCTL_I915_GEM_CREATE,
Packit 631bab
			       &create);
Packit 631bab
		if (ret != 0) {
Packit 631bab
			free(bo_gem);
Packit 631bab
			goto err;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		bo_gem->gem_handle = create.handle;
Packit 631bab
		HASH_ADD(handle_hh, bufmgr_gem->handle_table,
Packit 631bab
			 gem_handle, sizeof(bo_gem->gem_handle),
Packit 631bab
			 bo_gem);
Packit 631bab
Packit 631bab
		bo_gem->bo.handle = bo_gem->gem_handle;
Packit 631bab
		bo_gem->bo.bufmgr = bufmgr;
Packit 631bab
		bo_gem->bo.align = alignment;
Packit 631bab
Packit 631bab
		bo_gem->tiling_mode = I915_TILING_NONE;
Packit 631bab
		bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
Packit 631bab
		bo_gem->stride = 0;
Packit 631bab
Packit 631bab
		if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo,
Packit 631bab
							 tiling_mode,
Packit 631bab
							 stride))
Packit 631bab
			goto err_free;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	bo_gem->name = name;
Packit 631bab
	atomic_set(&bo_gem->refcount, 1);
Packit 631bab
	bo_gem->validate_index = -1;
Packit 631bab
	bo_gem->reloc_tree_fences = 0;
Packit 631bab
	bo_gem->used_as_reloc_target = false;
Packit 631bab
	bo_gem->has_error = false;
Packit 631bab
	bo_gem->reusable = true;
Packit 631bab
Packit 631bab
	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment);
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	DBG("bo_create: buf %d (%s) %ldb\n",
Packit 631bab
	    bo_gem->gem_handle, bo_gem->name, size);
Packit 631bab
Packit 631bab
	return &bo_gem->bo;
Packit 631bab
Packit 631bab
err_free:
Packit 631bab
	drm_intel_gem_bo_free(&bo_gem->bo);
Packit 631bab
err:
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
	return NULL;
Packit 631bab
}
Packit 631bab
Packit 631bab
static drm_intel_bo *
Packit 631bab
drm_intel_gem_bo_alloc_for_render(drm_intel_bufmgr *bufmgr,
Packit 631bab
				  const char *name,
Packit 631bab
				  unsigned long size,
Packit 631bab
				  unsigned int alignment)
Packit 631bab
{
Packit 631bab
	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size,
Packit 631bab
					       BO_ALLOC_FOR_RENDER,
Packit 631bab
					       I915_TILING_NONE, 0,
Packit 631bab
					       alignment);
Packit 631bab
}
Packit 631bab
Packit 631bab
static drm_intel_bo *
Packit 631bab
drm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr,
Packit 631bab
		       const char *name,
Packit 631bab
		       unsigned long size,
Packit 631bab
		       unsigned int alignment)
Packit 631bab
{
Packit 631bab
	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0,
Packit 631bab
					       I915_TILING_NONE, 0, 0);
Packit 631bab
}
Packit 631bab
Packit 631bab
static drm_intel_bo *
Packit 631bab
drm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name,
Packit 631bab
			     int x, int y, int cpp, uint32_t *tiling_mode,
Packit 631bab
			     unsigned long *pitch, unsigned long flags)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
Packit 631bab
	unsigned long size, stride;
Packit 631bab
	uint32_t tiling;
Packit 631bab
Packit 631bab
	do {
Packit 631bab
		unsigned long aligned_y, height_alignment;
Packit 631bab
Packit 631bab
		tiling = *tiling_mode;
Packit 631bab
Packit 631bab
		/* If we're tiled, our allocations are in 8 or 32-row blocks,
Packit 631bab
		 * so failure to align our height means that we won't allocate
Packit 631bab
		 * enough pages.
Packit 631bab
		 *
Packit 631bab
		 * If we're untiled, we still have to align to 2 rows high
Packit 631bab
		 * because the data port accesses 2x2 blocks even if the
Packit 631bab
		 * bottom row isn't to be rendered, so failure to align means
Packit 631bab
		 * we could walk off the end of the GTT and fault.  This is
Packit 631bab
		 * documented on 965, and may be the case on older chipsets
Packit 631bab
		 * too so we try to be careful.
Packit 631bab
		 */
Packit 631bab
		aligned_y = y;
Packit 631bab
		height_alignment = 2;
Packit 631bab
Packit 631bab
		if ((bufmgr_gem->gen == 2) && tiling != I915_TILING_NONE)
Packit 631bab
			height_alignment = 16;
Packit 631bab
		else if (tiling == I915_TILING_X
Packit 631bab
			|| (IS_915(bufmgr_gem->pci_device)
Packit 631bab
			    && tiling == I915_TILING_Y))
Packit 631bab
			height_alignment = 8;
Packit 631bab
		else if (tiling == I915_TILING_Y)
Packit 631bab
			height_alignment = 32;
Packit 631bab
		aligned_y = ALIGN(y, height_alignment);
Packit 631bab
Packit 631bab
		stride = x * cpp;
Packit 631bab
		stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling_mode);
Packit 631bab
		size = stride * aligned_y;
Packit 631bab
		size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode);
Packit 631bab
	} while (*tiling_mode != tiling);
Packit 631bab
	*pitch = stride;
Packit 631bab
Packit 631bab
	if (tiling == I915_TILING_NONE)
Packit 631bab
		stride = 0;
Packit 631bab
Packit 631bab
	return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags,
Packit 631bab
					       tiling, stride, 0);
Packit 631bab
}
Packit 631bab
Packit 631bab
static drm_intel_bo *
Packit 631bab
drm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
Packit 631bab
				const char *name,
Packit 631bab
				void *addr,
Packit 631bab
				uint32_t tiling_mode,
Packit 631bab
				uint32_t stride,
Packit 631bab
				unsigned long size,
Packit 631bab
				unsigned long flags)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem;
Packit 631bab
	int ret;
Packit 631bab
	struct drm_i915_gem_userptr userptr;
Packit 631bab
Packit 631bab
	/* Tiling with userptr surfaces is not supported
Packit 631bab
	 * on all hardware so refuse it for time being.
Packit 631bab
	 */
Packit 631bab
	if (tiling_mode != I915_TILING_NONE)
Packit 631bab
		return NULL;
Packit 631bab
Packit 631bab
	bo_gem = calloc(1, sizeof(*bo_gem));
Packit 631bab
	if (!bo_gem)
Packit 631bab
		return NULL;
Packit 631bab
Packit 631bab
	atomic_set(&bo_gem->refcount, 1);
Packit 631bab
	DRMINITLISTHEAD(&bo_gem->vma_list);
Packit 631bab
Packit 631bab
	bo_gem->bo.size = size;
Packit 631bab
Packit 631bab
	memclear(userptr);
Packit 631bab
	userptr.user_ptr = (__u64)((unsigned long)addr);
Packit 631bab
	userptr.user_size = size;
Packit 631bab
	userptr.flags = flags;
Packit 631bab
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
			DRM_IOCTL_I915_GEM_USERPTR,
Packit 631bab
			&userptr);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		DBG("bo_create_userptr: "
Packit 631bab
		    "ioctl failed with user ptr %p size 0x%lx, "
Packit 631bab
		    "user flags 0x%lx\n", addr, size, flags);
Packit 631bab
		free(bo_gem);
Packit 631bab
		return NULL;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	bo_gem->gem_handle = userptr.handle;
Packit 631bab
	bo_gem->bo.handle = bo_gem->gem_handle;
Packit 631bab
	bo_gem->bo.bufmgr    = bufmgr;
Packit 631bab
	bo_gem->is_userptr   = true;
Packit 631bab
	bo_gem->bo.virtual   = addr;
Packit 631bab
	/* Save the address provided by user */
Packit 631bab
	bo_gem->user_virtual = addr;
Packit 631bab
	bo_gem->tiling_mode  = I915_TILING_NONE;
Packit 631bab
	bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
Packit 631bab
	bo_gem->stride       = 0;
Packit 631bab
Packit 631bab
	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
Packit 631bab
		 gem_handle, sizeof(bo_gem->gem_handle),
Packit 631bab
		 bo_gem);
Packit 631bab
Packit 631bab
	bo_gem->name = name;
Packit 631bab
	bo_gem->validate_index = -1;
Packit 631bab
	bo_gem->reloc_tree_fences = 0;
Packit 631bab
	bo_gem->used_as_reloc_target = false;
Packit 631bab
	bo_gem->has_error = false;
Packit 631bab
	bo_gem->reusable = false;
Packit 631bab
Packit 631bab
	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	DBG("bo_create_userptr: "
Packit 631bab
	    "ptr %p buf %d (%s) size %ldb, stride 0x%x, tile mode %d\n",
Packit 631bab
		addr, bo_gem->gem_handle, bo_gem->name,
Packit 631bab
		size, stride, tiling_mode);
Packit 631bab
Packit 631bab
	return &bo_gem->bo;
Packit 631bab
}
Packit 631bab
Packit 631bab
static bool
Packit 631bab
has_userptr(drm_intel_bufmgr_gem *bufmgr_gem)
Packit 631bab
{
Packit 631bab
	int ret;
Packit 631bab
	void *ptr;
Packit 631bab
	long pgsz;
Packit 631bab
	struct drm_i915_gem_userptr userptr;
Packit 631bab
Packit 631bab
	pgsz = sysconf(_SC_PAGESIZE);
Packit 631bab
	assert(pgsz > 0);
Packit 631bab
Packit 631bab
	ret = posix_memalign(&ptr, pgsz, pgsz);
Packit 631bab
	if (ret) {
Packit 631bab
		DBG("Failed to get a page (%ld) for userptr detection!\n",
Packit 631bab
			pgsz);
Packit 631bab
		return false;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	memclear(userptr);
Packit 631bab
	userptr.user_ptr = (__u64)(unsigned long)ptr;
Packit 631bab
	userptr.user_size = pgsz;
Packit 631bab
Packit 631bab
retry:
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr);
Packit 631bab
	if (ret) {
Packit 631bab
		if (errno == ENODEV && userptr.flags == 0) {
Packit 631bab
			userptr.flags = I915_USERPTR_UNSYNCHRONIZED;
Packit 631bab
			goto retry;
Packit 631bab
		}
Packit 631bab
		free(ptr);
Packit 631bab
		return false;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* We don't release the userptr bo here as we want to keep the
Packit 631bab
	 * kernel mm tracking alive for our lifetime. The first time we
Packit 631bab
	 * create a userptr object the kernel has to install a mmu_notifer
Packit 631bab
	 * which is a heavyweight operation (e.g. it requires taking all
Packit 631bab
	 * mm_locks and stop_machine()).
Packit 631bab
	 */
Packit 631bab
Packit 631bab
	bufmgr_gem->userptr_active.ptr = ptr;
Packit 631bab
	bufmgr_gem->userptr_active.handle = userptr.handle;
Packit 631bab
Packit 631bab
	return true;
Packit 631bab
}
Packit 631bab
Packit 631bab
static drm_intel_bo *
Packit 631bab
check_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
Packit 631bab
		       const char *name,
Packit 631bab
		       void *addr,
Packit 631bab
		       uint32_t tiling_mode,
Packit 631bab
		       uint32_t stride,
Packit 631bab
		       unsigned long size,
Packit 631bab
		       unsigned long flags)
Packit 631bab
{
Packit 631bab
	if (has_userptr((drm_intel_bufmgr_gem *)bufmgr))
Packit 631bab
		bufmgr->bo_alloc_userptr = drm_intel_gem_bo_alloc_userptr;
Packit 631bab
	else
Packit 631bab
		bufmgr->bo_alloc_userptr = NULL;
Packit 631bab
Packit 631bab
	return drm_intel_bo_alloc_userptr(bufmgr, name, addr,
Packit 631bab
					  tiling_mode, stride, size, flags);
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Returns a drm_intel_bo wrapping the given buffer object handle.
Packit 631bab
 *
Packit 631bab
 * This can be used when one application needs to pass a buffer object
Packit 631bab
 * to another.
Packit 631bab
 */
Packit 631bab
drm_public drm_intel_bo *
Packit 631bab
drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr,
Packit 631bab
				  const char *name,
Packit 631bab
				  unsigned int handle)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem;
Packit 631bab
	int ret;
Packit 631bab
	struct drm_gem_open open_arg;
Packit 631bab
	struct drm_i915_gem_get_tiling get_tiling;
Packit 631bab
Packit 631bab
	/* At the moment most applications only have a few named bo.
Packit 631bab
	 * For instance, in a DRI client only the render buffers passed
Packit 631bab
	 * between X and the client are named. And since X returns the
Packit 631bab
	 * alternating names for the front/back buffer a linear search
Packit 631bab
	 * provides a sufficiently fast match.
Packit 631bab
	 */
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
	HASH_FIND(name_hh, bufmgr_gem->name_table,
Packit 631bab
		  &handle, sizeof(handle), bo_gem);
Packit 631bab
	if (bo_gem) {
Packit 631bab
		drm_intel_gem_bo_reference(&bo_gem->bo);
Packit 631bab
		goto out;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	memclear(open_arg);
Packit 631bab
	open_arg.name = handle;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_GEM_OPEN,
Packit 631bab
		       &open_arg);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		DBG("Couldn't reference %s handle 0x%08x: %s\n",
Packit 631bab
		    name, handle, strerror(errno));
Packit 631bab
		bo_gem = NULL;
Packit 631bab
		goto out;
Packit 631bab
	}
Packit 631bab
        /* Now see if someone has used a prime handle to get this
Packit 631bab
         * object from the kernel before by looking through the list
Packit 631bab
         * again for a matching gem_handle
Packit 631bab
         */
Packit 631bab
	HASH_FIND(handle_hh, bufmgr_gem->handle_table,
Packit 631bab
		  &open_arg.handle, sizeof(open_arg.handle), bo_gem);
Packit 631bab
	if (bo_gem) {
Packit 631bab
		drm_intel_gem_bo_reference(&bo_gem->bo);
Packit 631bab
		goto out;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	bo_gem = calloc(1, sizeof(*bo_gem));
Packit 631bab
	if (!bo_gem)
Packit 631bab
		goto out;
Packit 631bab
Packit 631bab
	atomic_set(&bo_gem->refcount, 1);
Packit 631bab
	DRMINITLISTHEAD(&bo_gem->vma_list);
Packit 631bab
Packit 631bab
	bo_gem->bo.size = open_arg.size;
Packit 631bab
	bo_gem->bo.offset = 0;
Packit 631bab
	bo_gem->bo.offset64 = 0;
Packit 631bab
	bo_gem->bo.virtual = NULL;
Packit 631bab
	bo_gem->bo.bufmgr = bufmgr;
Packit 631bab
	bo_gem->name = name;
Packit 631bab
	bo_gem->validate_index = -1;
Packit 631bab
	bo_gem->gem_handle = open_arg.handle;
Packit 631bab
	bo_gem->bo.handle = open_arg.handle;
Packit 631bab
	bo_gem->global_name = handle;
Packit 631bab
	bo_gem->reusable = false;
Packit 631bab
Packit 631bab
	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
Packit 631bab
		 gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
Packit 631bab
	HASH_ADD(name_hh, bufmgr_gem->name_table,
Packit 631bab
		 global_name, sizeof(bo_gem->global_name), bo_gem);
Packit 631bab
Packit 631bab
	memclear(get_tiling);
Packit 631bab
	get_tiling.handle = bo_gem->gem_handle;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GEM_GET_TILING,
Packit 631bab
		       &get_tiling);
Packit 631bab
	if (ret != 0)
Packit 631bab
		goto err_unref;
Packit 631bab
Packit 631bab
	bo_gem->tiling_mode = get_tiling.tiling_mode;
Packit 631bab
	bo_gem->swizzle_mode = get_tiling.swizzle_mode;
Packit 631bab
	/* XXX stride is unknown */
Packit 631bab
	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
Packit 631bab
	DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
Packit 631bab
Packit 631bab
out:
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
	return &bo_gem->bo;
Packit 631bab
Packit 631bab
err_unref:
Packit 631bab
	drm_intel_gem_bo_free(&bo_gem->bo);
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
	return NULL;
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_gem_bo_free(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_gem_close close;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	DRMLISTDEL(&bo_gem->vma_list);
Packit 631bab
	if (bo_gem->mem_virtual) {
Packit 631bab
		VG(VALGRIND_FREELIKE_BLOCK(bo_gem->mem_virtual, 0));
Packit 631bab
		drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
Packit 631bab
		bufmgr_gem->vma_count--;
Packit 631bab
	}
Packit 631bab
	if (bo_gem->wc_virtual) {
Packit 631bab
		VG(VALGRIND_FREELIKE_BLOCK(bo_gem->wc_virtual, 0));
Packit 631bab
		drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
Packit 631bab
		bufmgr_gem->vma_count--;
Packit 631bab
	}
Packit 631bab
	if (bo_gem->gtt_virtual) {
Packit 631bab
		drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
Packit 631bab
		bufmgr_gem->vma_count--;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (bo_gem->global_name)
Packit 631bab
		HASH_DELETE(name_hh, bufmgr_gem->name_table, bo_gem);
Packit 631bab
	HASH_DELETE(handle_hh, bufmgr_gem->handle_table, bo_gem);
Packit 631bab
Packit 631bab
	/* Close this object */
Packit 631bab
	memclear(close);
Packit 631bab
	close.handle = bo_gem->gem_handle;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
Packit 631bab
		    bo_gem->gem_handle, bo_gem->name, strerror(errno));
Packit 631bab
	}
Packit 631bab
	free(bo);
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_gem_bo_mark_mmaps_incoherent(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
#if HAVE_VALGRIND
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	if (bo_gem->mem_virtual)
Packit 631bab
		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size);
Packit 631bab
Packit 631bab
	if (bo_gem->wc_virtual)
Packit 631bab
		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->wc_virtual, bo->size);
Packit 631bab
Packit 631bab
	if (bo_gem->gtt_virtual)
Packit 631bab
		VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size);
Packit 631bab
#endif
Packit 631bab
}
Packit 631bab
Packit 631bab
/** Frees all cached buffers significantly older than @time. */
Packit 631bab
static void
Packit 631bab
drm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time)
Packit 631bab
{
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	if (bufmgr_gem->time == time)
Packit 631bab
		return;
Packit 631bab
Packit 631bab
	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
Packit 631bab
		struct drm_intel_gem_bo_bucket *bucket =
Packit 631bab
		    &bufmgr_gem->cache_bucket[i];
Packit 631bab
Packit 631bab
		while (!DRMLISTEMPTY(&bucket->head)) {
Packit 631bab
			drm_intel_bo_gem *bo_gem;
Packit 631bab
Packit 631bab
			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
Packit 631bab
					      bucket->head.next, head);
Packit 631bab
			if (time - bo_gem->free_time <= 1)
Packit 631bab
				break;
Packit 631bab
Packit 631bab
			DRMLISTDEL(&bo_gem->head);
Packit 631bab
Packit 631bab
			drm_intel_gem_bo_free(&bo_gem->bo);
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	bufmgr_gem->time = time;
Packit 631bab
}
Packit 631bab
Packit 631bab
static void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem)
Packit 631bab
{
Packit 631bab
	int limit;
Packit 631bab
Packit 631bab
	DBG("%s: cached=%d, open=%d, limit=%d\n", __FUNCTION__,
Packit 631bab
	    bufmgr_gem->vma_count, bufmgr_gem->vma_open, bufmgr_gem->vma_max);
Packit 631bab
Packit 631bab
	if (bufmgr_gem->vma_max < 0)
Packit 631bab
		return;
Packit 631bab
Packit 631bab
	/* We may need to evict a few entries in order to create new mmaps */
Packit 631bab
	limit = bufmgr_gem->vma_max - 2*bufmgr_gem->vma_open;
Packit 631bab
	if (limit < 0)
Packit 631bab
		limit = 0;
Packit 631bab
Packit 631bab
	while (bufmgr_gem->vma_count > limit) {
Packit 631bab
		drm_intel_bo_gem *bo_gem;
Packit 631bab
Packit 631bab
		bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
Packit 631bab
				      bufmgr_gem->vma_cache.next,
Packit 631bab
				      vma_list);
Packit 631bab
		assert(bo_gem->map_count == 0);
Packit 631bab
		DRMLISTDELINIT(&bo_gem->vma_list);
Packit 631bab
Packit 631bab
		if (bo_gem->mem_virtual) {
Packit 631bab
			drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size);
Packit 631bab
			bo_gem->mem_virtual = NULL;
Packit 631bab
			bufmgr_gem->vma_count--;
Packit 631bab
		}
Packit 631bab
		if (bo_gem->wc_virtual) {
Packit 631bab
			drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size);
Packit 631bab
			bo_gem->wc_virtual = NULL;
Packit 631bab
			bufmgr_gem->vma_count--;
Packit 631bab
		}
Packit 631bab
		if (bo_gem->gtt_virtual) {
Packit 631bab
			drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
Packit 631bab
			bo_gem->gtt_virtual = NULL;
Packit 631bab
			bufmgr_gem->vma_count--;
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
static void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem,
Packit 631bab
				       drm_intel_bo_gem *bo_gem)
Packit 631bab
{
Packit 631bab
	bufmgr_gem->vma_open--;
Packit 631bab
	DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache);
Packit 631bab
	if (bo_gem->mem_virtual)
Packit 631bab
		bufmgr_gem->vma_count++;
Packit 631bab
	if (bo_gem->wc_virtual)
Packit 631bab
		bufmgr_gem->vma_count++;
Packit 631bab
	if (bo_gem->gtt_virtual)
Packit 631bab
		bufmgr_gem->vma_count++;
Packit 631bab
	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
Packit 631bab
}
Packit 631bab
Packit 631bab
static void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem,
Packit 631bab
				      drm_intel_bo_gem *bo_gem)
Packit 631bab
{
Packit 631bab
	bufmgr_gem->vma_open++;
Packit 631bab
	DRMLISTDEL(&bo_gem->vma_list);
Packit 631bab
	if (bo_gem->mem_virtual)
Packit 631bab
		bufmgr_gem->vma_count--;
Packit 631bab
	if (bo_gem->wc_virtual)
Packit 631bab
		bufmgr_gem->vma_count--;
Packit 631bab
	if (bo_gem->gtt_virtual)
Packit 631bab
		bufmgr_gem->vma_count--;
Packit 631bab
	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_intel_gem_bo_bucket *bucket;
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	/* Unreference all the target buffers */
Packit 631bab
	for (i = 0; i < bo_gem->reloc_count; i++) {
Packit 631bab
		if (bo_gem->reloc_target_info[i].bo != bo) {
Packit 631bab
			drm_intel_gem_bo_unreference_locked_timed(bo_gem->
Packit 631bab
								  reloc_target_info[i].bo,
Packit 631bab
								  time);
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
	for (i = 0; i < bo_gem->softpin_target_count; i++)
Packit 631bab
		drm_intel_gem_bo_unreference_locked_timed(bo_gem->softpin_target[i],
Packit 631bab
								  time);
Packit 631bab
	bo_gem->kflags = 0;
Packit 631bab
	bo_gem->reloc_count = 0;
Packit 631bab
	bo_gem->used_as_reloc_target = false;
Packit 631bab
	bo_gem->softpin_target_count = 0;
Packit 631bab
Packit 631bab
	DBG("bo_unreference final: %d (%s)\n",
Packit 631bab
	    bo_gem->gem_handle, bo_gem->name);
Packit 631bab
Packit 631bab
	/* release memory associated with this object */
Packit 631bab
	if (bo_gem->reloc_target_info) {
Packit 631bab
		free(bo_gem->reloc_target_info);
Packit 631bab
		bo_gem->reloc_target_info = NULL;
Packit 631bab
	}
Packit 631bab
	if (bo_gem->relocs) {
Packit 631bab
		free(bo_gem->relocs);
Packit 631bab
		bo_gem->relocs = NULL;
Packit 631bab
	}
Packit 631bab
	if (bo_gem->softpin_target) {
Packit 631bab
		free(bo_gem->softpin_target);
Packit 631bab
		bo_gem->softpin_target = NULL;
Packit 631bab
		bo_gem->softpin_target_size = 0;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* Clear any left-over mappings */
Packit 631bab
	if (bo_gem->map_count) {
Packit 631bab
		DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count);
Packit 631bab
		bo_gem->map_count = 0;
Packit 631bab
		drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
Packit 631bab
		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
Packit 631bab
	}
Packit 631bab
Packit 631bab
	bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
Packit 631bab
	/* Put the buffer into our internal cache for reuse if we can. */
Packit 631bab
	if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL &&
Packit 631bab
	    drm_intel_gem_bo_madvise_internal(bufmgr_gem, bo_gem,
Packit 631bab
					      I915_MADV_DONTNEED)) {
Packit 631bab
		bo_gem->free_time = time;
Packit 631bab
Packit 631bab
		bo_gem->name = NULL;
Packit 631bab
		bo_gem->validate_index = -1;
Packit 631bab
Packit 631bab
		DRMLISTADDTAIL(&bo_gem->head, &bucket->head);
Packit 631bab
	} else {
Packit 631bab
		drm_intel_gem_bo_free(bo);
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
static void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo,
Packit 631bab
						      time_t time)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	assert(atomic_read(&bo_gem->refcount) > 0);
Packit 631bab
	if (atomic_dec_and_test(&bo_gem->refcount))
Packit 631bab
		drm_intel_gem_bo_unreference_final(bo, time);
Packit 631bab
}
Packit 631bab
Packit 631bab
static void drm_intel_gem_bo_unreference(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	assert(atomic_read(&bo_gem->refcount) > 0);
Packit 631bab
Packit 631bab
	if (atomic_add_unless(&bo_gem->refcount, -1, 1)) {
Packit 631bab
		drm_intel_bufmgr_gem *bufmgr_gem =
Packit 631bab
		    (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
		struct timespec time;
Packit 631bab
Packit 631bab
		clock_gettime(CLOCK_MONOTONIC, &time);
Packit 631bab
Packit 631bab
		pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
		if (atomic_dec_and_test(&bo_gem->refcount)) {
Packit 631bab
			drm_intel_gem_bo_unreference_final(bo, time.tv_sec);
Packit 631bab
			drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec);
Packit 631bab
		}
Packit 631bab
Packit 631bab
		pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_set_domain set_domain;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	if (bo_gem->is_userptr) {
Packit 631bab
		/* Return the same user ptr */
Packit 631bab
		bo->virtual = bo_gem->user_virtual;
Packit 631bab
		return 0;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	if (bo_gem->map_count++ == 0)
Packit 631bab
		drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
Packit 631bab
Packit 631bab
	if (!bo_gem->mem_virtual) {
Packit 631bab
		struct drm_i915_gem_mmap mmap_arg;
Packit 631bab
Packit 631bab
		DBG("bo_map: %d (%s), map_count=%d\n",
Packit 631bab
		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
Packit 631bab
Packit 631bab
		memclear(mmap_arg);
Packit 631bab
		mmap_arg.handle = bo_gem->gem_handle;
Packit 631bab
		mmap_arg.size = bo->size;
Packit 631bab
		ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
			       DRM_IOCTL_I915_GEM_MMAP,
Packit 631bab
			       &mmap_arg);
Packit 631bab
		if (ret != 0) {
Packit 631bab
			ret = -errno;
Packit 631bab
			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
Packit 631bab
			    __FILE__, __LINE__, bo_gem->gem_handle,
Packit 631bab
			    bo_gem->name, strerror(errno));
Packit 631bab
			if (--bo_gem->map_count == 0)
Packit 631bab
				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
Packit 631bab
			pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
			return ret;
Packit 631bab
		}
Packit 631bab
		VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
Packit 631bab
		bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
Packit 631bab
	}
Packit 631bab
	DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
Packit 631bab
	    bo_gem->mem_virtual);
Packit 631bab
	bo->virtual = bo_gem->mem_virtual;
Packit 631bab
Packit 631bab
	memclear(set_domain);
Packit 631bab
	set_domain.handle = bo_gem->gem_handle;
Packit 631bab
	set_domain.read_domains = I915_GEM_DOMAIN_CPU;
Packit 631bab
	if (write_enable)
Packit 631bab
		set_domain.write_domain = I915_GEM_DOMAIN_CPU;
Packit 631bab
	else
Packit 631bab
		set_domain.write_domain = 0;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
Packit 631bab
		       &set_domain);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		DBG("%s:%d: Error setting to CPU domain %d: %s\n",
Packit 631bab
		    __FILE__, __LINE__, bo_gem->gem_handle,
Packit 631bab
		    strerror(errno));
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (write_enable)
Packit 631bab
		bo_gem->mapped_cpu_write = true;
Packit 631bab
Packit 631bab
	drm_intel_gem_bo_mark_mmaps_incoherent(bo);
Packit 631bab
	VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->mem_virtual, bo->size));
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
map_gtt(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	if (bo_gem->is_userptr)
Packit 631bab
		return -EINVAL;
Packit 631bab
Packit 631bab
	if (bo_gem->map_count++ == 0)
Packit 631bab
		drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
Packit 631bab
Packit 631bab
	/* Get a mapping of the buffer if we haven't before. */
Packit 631bab
	if (bo_gem->gtt_virtual == NULL) {
Packit 631bab
		struct drm_i915_gem_mmap_gtt mmap_arg;
Packit 631bab
Packit 631bab
		DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
Packit 631bab
		    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
Packit 631bab
Packit 631bab
		memclear(mmap_arg);
Packit 631bab
		mmap_arg.handle = bo_gem->gem_handle;
Packit 631bab
Packit 631bab
		/* Get the fake offset back... */
Packit 631bab
		ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
			       DRM_IOCTL_I915_GEM_MMAP_GTT,
Packit 631bab
			       &mmap_arg);
Packit 631bab
		if (ret != 0) {
Packit 631bab
			ret = -errno;
Packit 631bab
			DBG("%s:%d: Error preparing buffer map %d (%s): %s .\n",
Packit 631bab
			    __FILE__, __LINE__,
Packit 631bab
			    bo_gem->gem_handle, bo_gem->name,
Packit 631bab
			    strerror(errno));
Packit 631bab
			if (--bo_gem->map_count == 0)
Packit 631bab
				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
Packit 631bab
			return ret;
Packit 631bab
		}
Packit 631bab
Packit 631bab
		/* and mmap it */
Packit 631bab
		bo_gem->gtt_virtual = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE,
Packit 631bab
					       MAP_SHARED, bufmgr_gem->fd,
Packit 631bab
					       mmap_arg.offset);
Packit 631bab
		if (bo_gem->gtt_virtual == MAP_FAILED) {
Packit 631bab
			bo_gem->gtt_virtual = NULL;
Packit 631bab
			ret = -errno;
Packit 631bab
			DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
Packit 631bab
			    __FILE__, __LINE__,
Packit 631bab
			    bo_gem->gem_handle, bo_gem->name,
Packit 631bab
			    strerror(errno));
Packit 631bab
			if (--bo_gem->map_count == 0)
Packit 631bab
				drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
Packit 631bab
			return ret;
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	bo->virtual = bo_gem->gtt_virtual;
Packit 631bab
Packit 631bab
	DBG("bo_map_gtt: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
Packit 631bab
	    bo_gem->gtt_virtual);
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_set_domain set_domain;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	ret = map_gtt(bo);
Packit 631bab
	if (ret) {
Packit 631bab
		pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
		return ret;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* Now move it to the GTT domain so that the GPU and CPU
Packit 631bab
	 * caches are flushed and the GPU isn't actively using the
Packit 631bab
	 * buffer.
Packit 631bab
	 *
Packit 631bab
	 * The pagefault handler does this domain change for us when
Packit 631bab
	 * it has unbound the BO from the GTT, but it's up to us to
Packit 631bab
	 * tell it when we're about to use things if we had done
Packit 631bab
	 * rendering and it still happens to be bound to the GTT.
Packit 631bab
	 */
Packit 631bab
	memclear(set_domain);
Packit 631bab
	set_domain.handle = bo_gem->gem_handle;
Packit 631bab
	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
Packit 631bab
	set_domain.write_domain = I915_GEM_DOMAIN_GTT;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
Packit 631bab
		       &set_domain);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		DBG("%s:%d: Error setting domain %d: %s\n",
Packit 631bab
		    __FILE__, __LINE__, bo_gem->gem_handle,
Packit 631bab
		    strerror(errno));
Packit 631bab
	}
Packit 631bab
Packit 631bab
	drm_intel_gem_bo_mark_mmaps_incoherent(bo);
Packit 631bab
	VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size));
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Performs a mapping of the buffer object like the normal GTT
Packit 631bab
 * mapping, but avoids waiting for the GPU to be done reading from or
Packit 631bab
 * rendering to the buffer.
Packit 631bab
 *
Packit 631bab
 * This is used in the implementation of GL_ARB_map_buffer_range: The
Packit 631bab
 * user asks to create a buffer, then does a mapping, fills some
Packit 631bab
 * space, runs a drawing command, then asks to map it again without
Packit 631bab
 * synchronizing because it guarantees that it won't write over the
Packit 631bab
 * data that the GPU is busy using (or, more specifically, that if it
Packit 631bab
 * does write over the data, it acknowledges that rendering is
Packit 631bab
 * undefined).
Packit 631bab
 */
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
#if HAVE_VALGRIND
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
#endif
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	/* If the CPU cache isn't coherent with the GTT, then use a
Packit 631bab
	 * regular synchronized mapping.  The problem is that we don't
Packit 631bab
	 * track where the buffer was last used on the CPU side in
Packit 631bab
	 * terms of drm_intel_bo_map vs drm_intel_gem_bo_map_gtt, so
Packit 631bab
	 * we would potentially corrupt the buffer even when the user
Packit 631bab
	 * does reasonable things.
Packit 631bab
	 */
Packit 631bab
	if (!bufmgr_gem->has_llc)
Packit 631bab
		return drm_intel_gem_bo_map_gtt(bo);
Packit 631bab
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	ret = map_gtt(bo);
Packit 631bab
	if (ret == 0) {
Packit 631bab
		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
Packit 631bab
		VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size));
Packit 631bab
	}
Packit 631bab
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int drm_intel_gem_bo_unmap(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	int ret = 0;
Packit 631bab
Packit 631bab
	if (bo == NULL)
Packit 631bab
		return 0;
Packit 631bab
Packit 631bab
	if (bo_gem->is_userptr)
Packit 631bab
		return 0;
Packit 631bab
Packit 631bab
	bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	if (bo_gem->map_count <= 0) {
Packit 631bab
		DBG("attempted to unmap an unmapped bo\n");
Packit 631bab
		pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
		/* Preserve the old behaviour of just treating this as a
Packit 631bab
		 * no-op rather than reporting the error.
Packit 631bab
		 */
Packit 631bab
		return 0;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (bo_gem->mapped_cpu_write) {
Packit 631bab
		struct drm_i915_gem_sw_finish sw_finish;
Packit 631bab
Packit 631bab
		/* Cause a flush to happen if the buffer's pinned for
Packit 631bab
		 * scanout, so the results show up in a timely manner.
Packit 631bab
		 * Unlike GTT set domains, this only does work if the
Packit 631bab
		 * buffer should be scanout-related.
Packit 631bab
		 */
Packit 631bab
		memclear(sw_finish);
Packit 631bab
		sw_finish.handle = bo_gem->gem_handle;
Packit 631bab
		ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
			       DRM_IOCTL_I915_GEM_SW_FINISH,
Packit 631bab
			       &sw_finish);
Packit 631bab
		ret = ret == -1 ? -errno : 0;
Packit 631bab
Packit 631bab
		bo_gem->mapped_cpu_write = false;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* We need to unmap after every innovation as we cannot track
Packit 631bab
	 * an open vma for every bo as that will exhaust the system
Packit 631bab
	 * limits and cause later failures.
Packit 631bab
	 */
Packit 631bab
	if (--bo_gem->map_count == 0) {
Packit 631bab
		drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
Packit 631bab
		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
Packit 631bab
		bo->virtual = NULL;
Packit 631bab
	}
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	return drm_intel_gem_bo_unmap(bo);
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset,
Packit 631bab
			 unsigned long size, const void *data)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_pwrite pwrite;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	if (bo_gem->is_userptr)
Packit 631bab
		return -EINVAL;
Packit 631bab
Packit 631bab
	memclear(pwrite);
Packit 631bab
	pwrite.handle = bo_gem->gem_handle;
Packit 631bab
	pwrite.offset = offset;
Packit 631bab
	pwrite.size = size;
Packit 631bab
	pwrite.data_ptr = (uint64_t) (uintptr_t) data;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GEM_PWRITE,
Packit 631bab
		       &pwrite);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		ret = -errno;
Packit 631bab
		DBG("%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
Packit 631bab
		    __FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
Packit 631bab
		    (int)size, strerror(errno));
Packit 631bab
	}
Packit 631bab
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
Packit 631bab
	struct drm_i915_get_pipe_from_crtc_id get_pipe_from_crtc_id;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	memclear(get_pipe_from_crtc_id);
Packit 631bab
	get_pipe_from_crtc_id.crtc_id = crtc_id;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID,
Packit 631bab
		       &get_pipe_from_crtc_id);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		/* We return -1 here to signal that we don't
Packit 631bab
		 * know which pipe is associated with this crtc.
Packit 631bab
		 * This lets the caller know that this information
Packit 631bab
		 * isn't available; using the wrong pipe for
Packit 631bab
		 * vblank waiting can cause the chipset to lock up
Packit 631bab
		 */
Packit 631bab
		return -1;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	return get_pipe_from_crtc_id.pipe;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset,
Packit 631bab
			     unsigned long size, void *data)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_pread pread;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	if (bo_gem->is_userptr)
Packit 631bab
		return -EINVAL;
Packit 631bab
Packit 631bab
	memclear(pread);
Packit 631bab
	pread.handle = bo_gem->gem_handle;
Packit 631bab
	pread.offset = offset;
Packit 631bab
	pread.size = size;
Packit 631bab
	pread.data_ptr = (uint64_t) (uintptr_t) data;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GEM_PREAD,
Packit 631bab
		       &pread);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		ret = -errno;
Packit 631bab
		DBG("%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
Packit 631bab
		    __FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
Packit 631bab
		    (int)size, strerror(errno));
Packit 631bab
	}
Packit 631bab
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
/** Waits for all GPU rendering with the object to have completed. */
Packit 631bab
static void
Packit 631bab
drm_intel_gem_bo_wait_rendering(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_gem_bo_start_gtt_access(bo, 1);
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Waits on a BO for the given amount of time.
Packit 631bab
 *
Packit 631bab
 * @bo: buffer object to wait for
Packit 631bab
 * @timeout_ns: amount of time to wait in nanoseconds.
Packit 631bab
 *   If value is less than 0, an infinite wait will occur.
Packit 631bab
 *
Packit 631bab
 * Returns 0 if the wait was successful ie. the last batch referencing the
Packit 631bab
 * object has completed within the allotted time. Otherwise some negative return
Packit 631bab
 * value describes the error. Of particular interest is -ETIME when the wait has
Packit 631bab
 * failed to yield the desired result.
Packit 631bab
 *
Packit 631bab
 * Similar to drm_intel_gem_bo_wait_rendering except a timeout parameter allows
Packit 631bab
 * the operation to give up after a certain amount of time. Another subtle
Packit 631bab
 * difference is the internal locking semantics are different (this variant does
Packit 631bab
 * not hold the lock for the duration of the wait). This makes the wait subject
Packit 631bab
 * to a larger userspace race window.
Packit 631bab
 *
Packit 631bab
 * The implementation shall wait until the object is no longer actively
Packit 631bab
 * referenced within a batch buffer at the time of the call. The wait will
Packit 631bab
 * not guarantee that the buffer is re-issued via another thread, or an flinked
Packit 631bab
 * handle. Userspace must make sure this race does not occur if such precision
Packit 631bab
 * is important.
Packit 631bab
 *
Packit 631bab
 * Note that some kernels have broken the inifite wait for negative values
Packit 631bab
 * promise, upgrade to latest stable kernels if this is the case.
Packit 631bab
 */
Packit 631bab
drm_public int
Packit 631bab
drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_wait wait;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	if (!bufmgr_gem->has_wait_timeout) {
Packit 631bab
		DBG("%s:%d: Timed wait is not supported. Falling back to "
Packit 631bab
		    "infinite wait\n", __FILE__, __LINE__);
Packit 631bab
		if (timeout_ns) {
Packit 631bab
			drm_intel_gem_bo_wait_rendering(bo);
Packit 631bab
			return 0;
Packit 631bab
		} else {
Packit 631bab
			return drm_intel_gem_bo_busy(bo) ? -ETIME : 0;
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	memclear(wait);
Packit 631bab
	wait.bo_handle = bo_gem->gem_handle;
Packit 631bab
	wait.timeout_ns = timeout_ns;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
Packit 631bab
	if (ret == -1)
Packit 631bab
		return -errno;
Packit 631bab
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Sets the object to the GTT read and possibly write domain, used by the X
Packit 631bab
 * 2D driver in the absence of kernel support to do drm_intel_gem_bo_map_gtt().
Packit 631bab
 *
Packit 631bab
 * In combination with drm_intel_gem_bo_pin() and manual fence management, we
Packit 631bab
 * can do tiled pixmaps this way.
Packit 631bab
 */
Packit 631bab
drm_public void
Packit 631bab
drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_set_domain set_domain;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	memclear(set_domain);
Packit 631bab
	set_domain.handle = bo_gem->gem_handle;
Packit 631bab
	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
Packit 631bab
	set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_GTT : 0;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GEM_SET_DOMAIN,
Packit 631bab
		       &set_domain);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		DBG("%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
Packit 631bab
		    __FILE__, __LINE__, bo_gem->gem_handle,
Packit 631bab
		    set_domain.read_domains, set_domain.write_domain,
Packit 631bab
		    strerror(errno));
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
Packit 631bab
	struct drm_gem_close close_bo;
Packit 631bab
	int i, ret;
Packit 631bab
Packit 631bab
	free(bufmgr_gem->exec2_objects);
Packit 631bab
	free(bufmgr_gem->exec_objects);
Packit 631bab
	free(bufmgr_gem->exec_bos);
Packit 631bab
Packit 631bab
	pthread_mutex_destroy(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	/* Free any cached buffer objects we were going to reuse */
Packit 631bab
	for (i = 0; i < bufmgr_gem->num_buckets; i++) {
Packit 631bab
		struct drm_intel_gem_bo_bucket *bucket =
Packit 631bab
		    &bufmgr_gem->cache_bucket[i];
Packit 631bab
		drm_intel_bo_gem *bo_gem;
Packit 631bab
Packit 631bab
		while (!DRMLISTEMPTY(&bucket->head)) {
Packit 631bab
			bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
Packit 631bab
					      bucket->head.next, head);
Packit 631bab
			DRMLISTDEL(&bo_gem->head);
Packit 631bab
Packit 631bab
			drm_intel_gem_bo_free(&bo_gem->bo);
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* Release userptr bo kept hanging around for optimisation. */
Packit 631bab
	if (bufmgr_gem->userptr_active.ptr) {
Packit 631bab
		memclear(close_bo);
Packit 631bab
		close_bo.handle = bufmgr_gem->userptr_active.handle;
Packit 631bab
		ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
Packit 631bab
		free(bufmgr_gem->userptr_active.ptr);
Packit 631bab
		if (ret)
Packit 631bab
			fprintf(stderr,
Packit 631bab
				"Failed to release test userptr object! (%d) "
Packit 631bab
				"i915 kernel driver may not be sane!\n", errno);
Packit 631bab
	}
Packit 631bab
Packit 631bab
	free(bufmgr);
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Adds the target buffer to the validation list and adds the relocation
Packit 631bab
 * to the reloc_buffer's relocation list.
Packit 631bab
 *
Packit 631bab
 * The relocation entry at the given offset must already contain the
Packit 631bab
 * precomputed relocation value, because the kernel will optimize out
Packit 631bab
 * the relocation entry write when the buffer hasn't moved from the
Packit 631bab
 * last known offset in target_bo.
Packit 631bab
 */
Packit 631bab
static int
Packit 631bab
do_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
Packit 631bab
		 drm_intel_bo *target_bo, uint32_t target_offset,
Packit 631bab
		 uint32_t read_domains, uint32_t write_domain,
Packit 631bab
		 bool need_fence)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
Packit 631bab
	bool fenced_command;
Packit 631bab
Packit 631bab
	if (bo_gem->has_error)
Packit 631bab
		return -ENOMEM;
Packit 631bab
Packit 631bab
	if (target_bo_gem->has_error) {
Packit 631bab
		bo_gem->has_error = true;
Packit 631bab
		return -ENOMEM;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* We never use HW fences for rendering on 965+ */
Packit 631bab
	if (bufmgr_gem->gen >= 4)
Packit 631bab
		need_fence = false;
Packit 631bab
Packit 631bab
	fenced_command = need_fence;
Packit 631bab
	if (target_bo_gem->tiling_mode == I915_TILING_NONE)
Packit 631bab
		need_fence = false;
Packit 631bab
Packit 631bab
	/* Create a new relocation list if needed */
Packit 631bab
	if (bo_gem->relocs == NULL && drm_intel_setup_reloc_list(bo))
Packit 631bab
		return -ENOMEM;
Packit 631bab
Packit 631bab
	/* Check overflow */
Packit 631bab
	assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
Packit 631bab
Packit 631bab
	/* Check args */
Packit 631bab
	assert(offset <= bo->size - 4);
Packit 631bab
	assert((write_domain & (write_domain - 1)) == 0);
Packit 631bab
Packit 631bab
	/* An object needing a fence is a tiled buffer, so it won't have
Packit 631bab
	 * relocs to other buffers.
Packit 631bab
	 */
Packit 631bab
	if (need_fence) {
Packit 631bab
		assert(target_bo_gem->reloc_count == 0);
Packit 631bab
		target_bo_gem->reloc_tree_fences = 1;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/* Make sure that we're not adding a reloc to something whose size has
Packit 631bab
	 * already been accounted for.
Packit 631bab
	 */
Packit 631bab
	assert(!bo_gem->used_as_reloc_target);
Packit 631bab
	if (target_bo_gem != bo_gem) {
Packit 631bab
		target_bo_gem->used_as_reloc_target = true;
Packit 631bab
		bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size;
Packit 631bab
		bo_gem->reloc_tree_fences += target_bo_gem->reloc_tree_fences;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	bo_gem->reloc_target_info[bo_gem->reloc_count].bo = target_bo;
Packit 631bab
	if (target_bo != bo)
Packit 631bab
		drm_intel_gem_bo_reference(target_bo);
Packit 631bab
	if (fenced_command)
Packit 631bab
		bo_gem->reloc_target_info[bo_gem->reloc_count].flags =
Packit 631bab
			DRM_INTEL_RELOC_FENCE;
Packit 631bab
	else
Packit 631bab
		bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 0;
Packit 631bab
Packit 631bab
	bo_gem->relocs[bo_gem->reloc_count].offset = offset;
Packit 631bab
	bo_gem->relocs[bo_gem->reloc_count].delta = target_offset;
Packit 631bab
	bo_gem->relocs[bo_gem->reloc_count].target_handle =
Packit 631bab
	    target_bo_gem->gem_handle;
Packit 631bab
	bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
Packit 631bab
	bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
Packit 631bab
	bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset64;
Packit 631bab
	bo_gem->reloc_count++;
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	if (enable)
Packit 631bab
		bo_gem->kflags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
Packit 631bab
	else
Packit 631bab
		bo_gem->kflags &= ~EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_add_softpin_target(drm_intel_bo *bo, drm_intel_bo *target_bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
Packit 631bab
	if (bo_gem->has_error)
Packit 631bab
		return -ENOMEM;
Packit 631bab
Packit 631bab
	if (target_bo_gem->has_error) {
Packit 631bab
		bo_gem->has_error = true;
Packit 631bab
		return -ENOMEM;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (!(target_bo_gem->kflags & EXEC_OBJECT_PINNED))
Packit 631bab
		return -EINVAL;
Packit 631bab
	if (target_bo_gem == bo_gem)
Packit 631bab
		return -EINVAL;
Packit 631bab
Packit 631bab
	if (bo_gem->softpin_target_count == bo_gem->softpin_target_size) {
Packit 631bab
		int new_size = bo_gem->softpin_target_size * 2;
Packit 631bab
		if (new_size == 0)
Packit 631bab
			new_size = bufmgr_gem->max_relocs;
Packit 631bab
Packit 631bab
		bo_gem->softpin_target = realloc(bo_gem->softpin_target, new_size *
Packit 631bab
				sizeof(drm_intel_bo *));
Packit 631bab
		if (!bo_gem->softpin_target)
Packit 631bab
			return -ENOMEM;
Packit 631bab
Packit 631bab
		bo_gem->softpin_target_size = new_size;
Packit 631bab
	}
Packit 631bab
	bo_gem->softpin_target[bo_gem->softpin_target_count] = target_bo;
Packit 631bab
	drm_intel_gem_bo_reference(target_bo);
Packit 631bab
	bo_gem->softpin_target_count++;
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
Packit 631bab
			    drm_intel_bo *target_bo, uint32_t target_offset,
Packit 631bab
			    uint32_t read_domains, uint32_t write_domain)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo;
Packit 631bab
Packit 631bab
	if (target_bo_gem->kflags & EXEC_OBJECT_PINNED)
Packit 631bab
		return drm_intel_gem_bo_add_softpin_target(bo, target_bo);
Packit 631bab
	else
Packit 631bab
		return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
Packit 631bab
					read_domains, write_domain,
Packit 631bab
					!bufmgr_gem->fenced_relocs);
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset,
Packit 631bab
				  drm_intel_bo *target_bo,
Packit 631bab
				  uint32_t target_offset,
Packit 631bab
				  uint32_t read_domains, uint32_t write_domain)
Packit 631bab
{
Packit 631bab
	return do_bo_emit_reloc(bo, offset, target_bo, target_offset,
Packit 631bab
				read_domains, write_domain, true);
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	return bo_gem->reloc_count;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Removes existing relocation entries in the BO after "start".
Packit 631bab
 *
Packit 631bab
 * This allows a user to avoid a two-step process for state setup with
Packit 631bab
 * counting up all the buffer objects and doing a
Packit 631bab
 * drm_intel_bufmgr_check_aperture_space() before emitting any of the
Packit 631bab
 * relocations for the state setup.  Instead, save the state of the
Packit 631bab
 * batchbuffer including drm_intel_gem_get_reloc_count(), emit all the
Packit 631bab
 * state, and then check if it still fits in the aperture.
Packit 631bab
 *
Packit 631bab
 * Any further drm_intel_bufmgr_check_aperture_space() queries
Packit 631bab
 * involving this buffer in the tree are undefined after this call.
Packit 631bab
 *
Packit 631bab
 * This also removes all softpinned targets being referenced by the BO.
Packit 631bab
 */
Packit 631bab
drm_public void
Packit 631bab
drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	int i;
Packit 631bab
	struct timespec time;
Packit 631bab
Packit 631bab
	clock_gettime(CLOCK_MONOTONIC, &time);
Packit 631bab
Packit 631bab
	assert(bo_gem->reloc_count >= start);
Packit 631bab
Packit 631bab
	/* Unreference the cleared target buffers */
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	for (i = start; i < bo_gem->reloc_count; i++) {
Packit 631bab
		drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->reloc_target_info[i].bo;
Packit 631bab
		if (&target_bo_gem->bo != bo) {
Packit 631bab
			bo_gem->reloc_tree_fences -= target_bo_gem->reloc_tree_fences;
Packit 631bab
			drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo,
Packit 631bab
								  time.tv_sec);
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
	bo_gem->reloc_count = start;
Packit 631bab
Packit 631bab
	for (i = 0; i < bo_gem->softpin_target_count; i++) {
Packit 631bab
		drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->softpin_target[i];
Packit 631bab
		drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, time.tv_sec);
Packit 631bab
	}
Packit 631bab
	bo_gem->softpin_target_count = 0;
Packit 631bab
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Walk the tree of relocations rooted at BO and accumulate the list of
Packit 631bab
 * validations to be performed and update the relocation buffers with
Packit 631bab
 * index values into the validation list.
Packit 631bab
 */
Packit 631bab
static void
Packit 631bab
drm_intel_gem_bo_process_reloc(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	if (bo_gem->relocs == NULL)
Packit 631bab
		return;
Packit 631bab
Packit 631bab
	for (i = 0; i < bo_gem->reloc_count; i++) {
Packit 631bab
		drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo;
Packit 631bab
Packit 631bab
		if (target_bo == bo)
Packit 631bab
			continue;
Packit 631bab
Packit 631bab
		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
Packit 631bab
Packit 631bab
		/* Continue walking the tree depth-first. */
Packit 631bab
		drm_intel_gem_bo_process_reloc(target_bo);
Packit 631bab
Packit 631bab
		/* Add the target to the validate list */
Packit 631bab
		drm_intel_add_validate_buffer(target_bo);
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_gem_bo_process_reloc2(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL)
Packit 631bab
		return;
Packit 631bab
Packit 631bab
	for (i = 0; i < bo_gem->reloc_count; i++) {
Packit 631bab
		drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo;
Packit 631bab
		int need_fence;
Packit 631bab
Packit 631bab
		if (target_bo == bo)
Packit 631bab
			continue;
Packit 631bab
Packit 631bab
		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
Packit 631bab
Packit 631bab
		/* Continue walking the tree depth-first. */
Packit 631bab
		drm_intel_gem_bo_process_reloc2(target_bo);
Packit 631bab
Packit 631bab
		need_fence = (bo_gem->reloc_target_info[i].flags &
Packit 631bab
			      DRM_INTEL_RELOC_FENCE);
Packit 631bab
Packit 631bab
		/* Add the target to the validate list */
Packit 631bab
		drm_intel_add_validate_buffer2(target_bo, need_fence);
Packit 631bab
	}
Packit 631bab
Packit 631bab
	for (i = 0; i < bo_gem->softpin_target_count; i++) {
Packit 631bab
		drm_intel_bo *target_bo = bo_gem->softpin_target[i];
Packit 631bab
Packit 631bab
		if (target_bo == bo)
Packit 631bab
			continue;
Packit 631bab
Packit 631bab
		drm_intel_gem_bo_mark_mmaps_incoherent(bo);
Packit 631bab
		drm_intel_gem_bo_process_reloc2(target_bo);
Packit 631bab
		drm_intel_add_validate_buffer2(target_bo, false);
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_update_buffer_offsets(drm_intel_bufmgr_gem *bufmgr_gem)
Packit 631bab
{
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	for (i = 0; i < bufmgr_gem->exec_count; i++) {
Packit 631bab
		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
Packit 631bab
		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
		/* Update the buffer offset */
Packit 631bab
		if (bufmgr_gem->exec_objects[i].offset != bo->offset64) {
Packit 631bab
			DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n",
Packit 631bab
			    bo_gem->gem_handle, bo_gem->name,
Packit 631bab
			    upper_32_bits(bo->offset64),
Packit 631bab
			    lower_32_bits(bo->offset64),
Packit 631bab
			    upper_32_bits(bufmgr_gem->exec_objects[i].offset),
Packit 631bab
			    lower_32_bits(bufmgr_gem->exec_objects[i].offset));
Packit 631bab
			bo->offset64 = bufmgr_gem->exec_objects[i].offset;
Packit 631bab
			bo->offset = bufmgr_gem->exec_objects[i].offset;
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
drm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem)
Packit 631bab
{
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	for (i = 0; i < bufmgr_gem->exec_count; i++) {
Packit 631bab
		drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
Packit 631bab
		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
Packit 631bab
Packit 631bab
		/* Update the buffer offset */
Packit 631bab
		if (bufmgr_gem->exec2_objects[i].offset != bo->offset64) {
Packit 631bab
			/* If we're seeing softpinned object here it means that the kernel
Packit 631bab
			 * has relocated our object... Indicating a programming error
Packit 631bab
			 */
Packit 631bab
			assert(!(bo_gem->kflags & EXEC_OBJECT_PINNED));
Packit 631bab
			DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n",
Packit 631bab
			    bo_gem->gem_handle, bo_gem->name,
Packit 631bab
			    upper_32_bits(bo->offset64),
Packit 631bab
			    lower_32_bits(bo->offset64),
Packit 631bab
			    upper_32_bits(bufmgr_gem->exec2_objects[i].offset),
Packit 631bab
			    lower_32_bits(bufmgr_gem->exec2_objects[i].offset));
Packit 631bab
			bo->offset64 = bufmgr_gem->exec2_objects[i].offset;
Packit 631bab
			bo->offset = bufmgr_gem->exec2_objects[i].offset;
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public void
Packit 631bab
drm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo,
Packit 631bab
			      int x1, int y1, int width, int height,
Packit 631bab
			      enum aub_dump_bmp_format format,
Packit 631bab
			      int pitch, int offset)
Packit 631bab
{
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_exec(drm_intel_bo *bo, int used,
Packit 631bab
		      drm_clip_rect_t * cliprects, int num_cliprects, int DR4)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	struct drm_i915_gem_execbuffer execbuf;
Packit 631bab
	int ret, i;
Packit 631bab
Packit 631bab
	if (to_bo_gem(bo)->has_error)
Packit 631bab
		return -ENOMEM;
Packit 631bab
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
	/* Update indices and set up the validate list. */
Packit 631bab
	drm_intel_gem_bo_process_reloc(bo);
Packit 631bab
Packit 631bab
	/* Add the batch buffer to the validation list.  There are no
Packit 631bab
	 * relocations pointing to it.
Packit 631bab
	 */
Packit 631bab
	drm_intel_add_validate_buffer(bo);
Packit 631bab
Packit 631bab
	memclear(execbuf);
Packit 631bab
	execbuf.buffers_ptr = (uintptr_t) bufmgr_gem->exec_objects;
Packit 631bab
	execbuf.buffer_count = bufmgr_gem->exec_count;
Packit 631bab
	execbuf.batch_start_offset = 0;
Packit 631bab
	execbuf.batch_len = used;
Packit 631bab
	execbuf.cliprects_ptr = (uintptr_t) cliprects;
Packit 631bab
	execbuf.num_cliprects = num_cliprects;
Packit 631bab
	execbuf.DR1 = 0;
Packit 631bab
	execbuf.DR4 = DR4;
Packit 631bab
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GEM_EXECBUFFER,
Packit 631bab
		       &execbuf);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		ret = -errno;
Packit 631bab
		if (errno == ENOSPC) {
Packit 631bab
			DBG("Execbuffer fails to pin. "
Packit 631bab
			    "Estimate: %u. Actual: %u. Available: %u\n",
Packit 631bab
			    drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos,
Packit 631bab
							       bufmgr_gem->
Packit 631bab
							       exec_count),
Packit 631bab
			    drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos,
Packit 631bab
							      bufmgr_gem->
Packit 631bab
							      exec_count),
Packit 631bab
			    (unsigned int)bufmgr_gem->gtt_size);
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
	drm_intel_update_buffer_offsets(bufmgr_gem);
Packit 631bab
Packit 631bab
	if (bufmgr_gem->bufmgr.debug)
Packit 631bab
		drm_intel_gem_dump_validation_list(bufmgr_gem);
Packit 631bab
Packit 631bab
	for (i = 0; i < bufmgr_gem->exec_count; i++) {
Packit 631bab
		drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]);
Packit 631bab
Packit 631bab
		bo_gem->idle = false;
Packit 631bab
Packit 631bab
		/* Disconnect the buffer from the validate list */
Packit 631bab
		bo_gem->validate_index = -1;
Packit 631bab
		bufmgr_gem->exec_bos[i] = NULL;
Packit 631bab
	}
Packit 631bab
	bufmgr_gem->exec_count = 0;
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
Packit 631bab
	 drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
Packit 631bab
	 int in_fence, int *out_fence,
Packit 631bab
	 unsigned int flags)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
Packit 631bab
	struct drm_i915_gem_execbuffer2 execbuf;
Packit 631bab
	int ret = 0;
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	if (to_bo_gem(bo)->has_error)
Packit 631bab
		return -ENOMEM;
Packit 631bab
Packit 631bab
	switch (flags & 0x7) {
Packit 631bab
	default:
Packit 631bab
		return -EINVAL;
Packit 631bab
	case I915_EXEC_BLT:
Packit 631bab
		if (!bufmgr_gem->has_blt)
Packit 631bab
			return -EINVAL;
Packit 631bab
		break;
Packit 631bab
	case I915_EXEC_BSD:
Packit 631bab
		if (!bufmgr_gem->has_bsd)
Packit 631bab
			return -EINVAL;
Packit 631bab
		break;
Packit 631bab
	case I915_EXEC_VEBOX:
Packit 631bab
		if (!bufmgr_gem->has_vebox)
Packit 631bab
			return -EINVAL;
Packit 631bab
		break;
Packit 631bab
	case I915_EXEC_RENDER:
Packit 631bab
	case I915_EXEC_DEFAULT:
Packit 631bab
		break;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
	/* Update indices and set up the validate list. */
Packit 631bab
	drm_intel_gem_bo_process_reloc2(bo);
Packit 631bab
Packit 631bab
	/* Add the batch buffer to the validation list.  There are no relocations
Packit 631bab
	 * pointing to it.
Packit 631bab
	 */
Packit 631bab
	drm_intel_add_validate_buffer2(bo, 0);
Packit 631bab
Packit 631bab
	memclear(execbuf);
Packit 631bab
	execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec2_objects;
Packit 631bab
	execbuf.buffer_count = bufmgr_gem->exec_count;
Packit 631bab
	execbuf.batch_start_offset = 0;
Packit 631bab
	execbuf.batch_len = used;
Packit 631bab
	execbuf.cliprects_ptr = (uintptr_t)cliprects;
Packit 631bab
	execbuf.num_cliprects = num_cliprects;
Packit 631bab
	execbuf.DR1 = 0;
Packit 631bab
	execbuf.DR4 = DR4;
Packit 631bab
	execbuf.flags = flags;
Packit 631bab
	if (ctx == NULL)
Packit 631bab
		i915_execbuffer2_set_context_id(execbuf, 0);
Packit 631bab
	else
Packit 631bab
		i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
Packit 631bab
	execbuf.rsvd2 = 0;
Packit 631bab
	if (in_fence != -1) {
Packit 631bab
		execbuf.rsvd2 = in_fence;
Packit 631bab
		execbuf.flags |= I915_EXEC_FENCE_IN;
Packit 631bab
	}
Packit 631bab
	if (out_fence != NULL) {
Packit 631bab
		*out_fence = -1;
Packit 631bab
		execbuf.flags |= I915_EXEC_FENCE_OUT;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	if (bufmgr_gem->no_exec)
Packit 631bab
		goto skip_execution;
Packit 631bab
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GEM_EXECBUFFER2_WR,
Packit 631bab
		       &execbuf);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		ret = -errno;
Packit 631bab
		if (ret == -ENOSPC) {
Packit 631bab
			DBG("Execbuffer fails to pin. "
Packit 631bab
			    "Estimate: %u. Actual: %u. Available: %u\n",
Packit 631bab
			    drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos,
Packit 631bab
							       bufmgr_gem->exec_count),
Packit 631bab
			    drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos,
Packit 631bab
							      bufmgr_gem->exec_count),
Packit 631bab
			    (unsigned int) bufmgr_gem->gtt_size);
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
	drm_intel_update_buffer_offsets2(bufmgr_gem);
Packit 631bab
Packit 631bab
	if (ret == 0 && out_fence != NULL)
Packit 631bab
		*out_fence = execbuf.rsvd2 >> 32;
Packit 631bab
Packit 631bab
skip_execution:
Packit 631bab
	if (bufmgr_gem->bufmgr.debug)
Packit 631bab
		drm_intel_gem_dump_validation_list(bufmgr_gem);
Packit 631bab
Packit 631bab
	for (i = 0; i < bufmgr_gem->exec_count; i++) {
Packit 631bab
		drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]);
Packit 631bab
Packit 631bab
		bo_gem->idle = false;
Packit 631bab
Packit 631bab
		/* Disconnect the buffer from the validate list */
Packit 631bab
		bo_gem->validate_index = -1;
Packit 631bab
		bufmgr_gem->exec_bos[i] = NULL;
Packit 631bab
	}
Packit 631bab
	bufmgr_gem->exec_count = 0;
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_exec2(drm_intel_bo *bo, int used,
Packit 631bab
		       drm_clip_rect_t *cliprects, int num_cliprects,
Packit 631bab
		       int DR4)
Packit 631bab
{
Packit 631bab
	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
Packit 631bab
			-1, NULL, I915_EXEC_RENDER);
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
Packit 631bab
			drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
Packit 631bab
			unsigned int flags)
Packit 631bab
{
Packit 631bab
	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
Packit 631bab
			-1, NULL, flags);
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
Packit 631bab
			      int used, unsigned int flags)
Packit 631bab
{
Packit 631bab
	return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags);
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_gem_bo_fence_exec(drm_intel_bo *bo,
Packit 631bab
			    drm_intel_context *ctx,
Packit 631bab
			    int used,
Packit 631bab
			    int in_fence,
Packit 631bab
			    int *out_fence,
Packit 631bab
			    unsigned int flags)
Packit 631bab
{
Packit 631bab
	return do_exec2(bo, used, ctx, NULL, 0, 0, in_fence, out_fence, flags);
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_pin pin;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	memclear(pin);
Packit 631bab
	pin.handle = bo_gem->gem_handle;
Packit 631bab
	pin.alignment = alignment;
Packit 631bab
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GEM_PIN,
Packit 631bab
		       &pin;;
Packit 631bab
	if (ret != 0)
Packit 631bab
		return -errno;
Packit 631bab
Packit 631bab
	bo->offset64 = pin.offset;
Packit 631bab
	bo->offset = pin.offset;
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_unpin(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_unpin unpin;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	memclear(unpin);
Packit 631bab
	unpin.handle = bo_gem->gem_handle;
Packit 631bab
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
Packit 631bab
	if (ret != 0)
Packit 631bab
		return -errno;
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo,
Packit 631bab
				     uint32_t tiling_mode,
Packit 631bab
				     uint32_t stride)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	struct drm_i915_gem_set_tiling set_tiling;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	if (bo_gem->global_name == 0 &&
Packit 631bab
	    tiling_mode == bo_gem->tiling_mode &&
Packit 631bab
	    stride == bo_gem->stride)
Packit 631bab
		return 0;
Packit 631bab
Packit 631bab
	memset(&set_tiling, 0, sizeof(set_tiling));
Packit 631bab
	do {
Packit 631bab
		/* set_tiling is slightly broken and overwrites the
Packit 631bab
		 * input on the error path, so we have to open code
Packit 631bab
		 * rmIoctl.
Packit 631bab
		 */
Packit 631bab
		set_tiling.handle = bo_gem->gem_handle;
Packit 631bab
		set_tiling.tiling_mode = tiling_mode;
Packit 631bab
		set_tiling.stride = stride;
Packit 631bab
Packit 631bab
		ret = ioctl(bufmgr_gem->fd,
Packit 631bab
			    DRM_IOCTL_I915_GEM_SET_TILING,
Packit 631bab
			    &set_tiling);
Packit 631bab
	} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
Packit 631bab
	if (ret == -1)
Packit 631bab
		return -errno;
Packit 631bab
Packit 631bab
	bo_gem->tiling_mode = set_tiling.tiling_mode;
Packit 631bab
	bo_gem->swizzle_mode = set_tiling.swizzle_mode;
Packit 631bab
	bo_gem->stride = set_tiling.stride;
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
Packit 631bab
			    uint32_t stride)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	/* Tiling with userptr surfaces is not supported
Packit 631bab
	 * on all hardware so refuse it for time being.
Packit 631bab
	 */
Packit 631bab
	if (bo_gem->is_userptr)
Packit 631bab
		return -EINVAL;
Packit 631bab
Packit 631bab
	/* Linear buffers have no stride. By ensuring that we only ever use
Packit 631bab
	 * stride 0 with linear buffers, we simplify our code.
Packit 631bab
	 */
Packit 631bab
	if (*tiling_mode == I915_TILING_NONE)
Packit 631bab
		stride = 0;
Packit 631bab
Packit 631bab
	ret = drm_intel_gem_bo_set_tiling_internal(bo, *tiling_mode, stride);
Packit 631bab
	if (ret == 0)
Packit 631bab
		drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
Packit 631bab
Packit 631bab
	*tiling_mode = bo_gem->tiling_mode;
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
Packit 631bab
			    uint32_t * swizzle_mode)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	*tiling_mode = bo_gem->tiling_mode;
Packit 631bab
	*swizzle_mode = bo_gem->swizzle_mode;
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	bo->offset64 = offset;
Packit 631bab
	bo->offset = offset;
Packit 631bab
	bo_gem->kflags |= EXEC_OBJECT_PINNED;
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public drm_intel_bo *
Packit 631bab
drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
Packit 631bab
	int ret;
Packit 631bab
	uint32_t handle;
Packit 631bab
	drm_intel_bo_gem *bo_gem;
Packit 631bab
	struct drm_i915_gem_get_tiling get_tiling;
Packit 631bab
Packit 631bab
	pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
	ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle);
Packit 631bab
	if (ret) {
Packit 631bab
		DBG("create_from_prime: failed to obtain handle from fd: %s\n", strerror(errno));
Packit 631bab
		pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
		return NULL;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	/*
Packit 631bab
	 * See if the kernel has already returned this buffer to us. Just as
Packit 631bab
	 * for named buffers, we must not create two bo's pointing at the same
Packit 631bab
	 * kernel object
Packit 631bab
	 */
Packit 631bab
	HASH_FIND(handle_hh, bufmgr_gem->handle_table,
Packit 631bab
		  &handle, sizeof(handle), bo_gem);
Packit 631bab
	if (bo_gem) {
Packit 631bab
		drm_intel_gem_bo_reference(&bo_gem->bo);
Packit 631bab
		goto out;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	bo_gem = calloc(1, sizeof(*bo_gem));
Packit 631bab
	if (!bo_gem)
Packit 631bab
		goto out;
Packit 631bab
Packit 631bab
	atomic_set(&bo_gem->refcount, 1);
Packit 631bab
	DRMINITLISTHEAD(&bo_gem->vma_list);
Packit 631bab
Packit 631bab
	/* Determine size of bo.  The fd-to-handle ioctl really should
Packit 631bab
	 * return the size, but it doesn't.  If we have kernel 3.12 or
Packit 631bab
	 * later, we can lseek on the prime fd to get the size.  Older
Packit 631bab
	 * kernels will just fail, in which case we fall back to the
Packit 631bab
	 * provided (estimated or guess size). */
Packit 631bab
	ret = lseek(prime_fd, 0, SEEK_END);
Packit 631bab
	if (ret != -1)
Packit 631bab
		bo_gem->bo.size = ret;
Packit 631bab
	else
Packit 631bab
		bo_gem->bo.size = size;
Packit 631bab
Packit 631bab
	bo_gem->bo.handle = handle;
Packit 631bab
	bo_gem->bo.bufmgr = bufmgr;
Packit 631bab
Packit 631bab
	bo_gem->gem_handle = handle;
Packit 631bab
	HASH_ADD(handle_hh, bufmgr_gem->handle_table,
Packit 631bab
		 gem_handle, sizeof(bo_gem->gem_handle), bo_gem);
Packit 631bab
Packit 631bab
	bo_gem->name = "prime";
Packit 631bab
	bo_gem->validate_index = -1;
Packit 631bab
	bo_gem->reloc_tree_fences = 0;
Packit 631bab
	bo_gem->used_as_reloc_target = false;
Packit 631bab
	bo_gem->has_error = false;
Packit 631bab
	bo_gem->reusable = false;
Packit 631bab
Packit 631bab
	memclear(get_tiling);
Packit 631bab
	get_tiling.handle = bo_gem->gem_handle;
Packit 631bab
	if (drmIoctl(bufmgr_gem->fd,
Packit 631bab
		     DRM_IOCTL_I915_GEM_GET_TILING,
Packit 631bab
		     &get_tiling))
Packit 631bab
		goto err;
Packit 631bab
Packit 631bab
	bo_gem->tiling_mode = get_tiling.tiling_mode;
Packit 631bab
	bo_gem->swizzle_mode = get_tiling.swizzle_mode;
Packit 631bab
	/* XXX stride is unknown */
Packit 631bab
	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0);
Packit 631bab
Packit 631bab
out:
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
	return &bo_gem->bo;
Packit 631bab
Packit 631bab
err:
Packit 631bab
	drm_intel_gem_bo_free(&bo_gem->bo);
Packit 631bab
	pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
	return NULL;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle,
Packit 631bab
			       DRM_CLOEXEC, prime_fd) != 0)
Packit 631bab
		return -errno;
Packit 631bab
Packit 631bab
	bo_gem->reusable = false;
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	if (!bo_gem->global_name) {
Packit 631bab
		struct drm_gem_flink flink;
Packit 631bab
Packit 631bab
		memclear(flink);
Packit 631bab
		flink.handle = bo_gem->gem_handle;
Packit 631bab
		if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink))
Packit 631bab
			return -errno;
Packit 631bab
Packit 631bab
		pthread_mutex_lock(&bufmgr_gem->lock);
Packit 631bab
		if (!bo_gem->global_name) {
Packit 631bab
			bo_gem->global_name = flink.name;
Packit 631bab
			bo_gem->reusable = false;
Packit 631bab
Packit 631bab
			HASH_ADD(name_hh, bufmgr_gem->name_table,
Packit 631bab
				 global_name, sizeof(bo_gem->global_name),
Packit 631bab
				 bo_gem);
Packit 631bab
		}
Packit 631bab
		pthread_mutex_unlock(&bufmgr_gem->lock);
Packit 631bab
	}
Packit 631bab
Packit 631bab
	*name = bo_gem->global_name;
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Enables unlimited caching of buffer objects for reuse.
Packit 631bab
 *
Packit 631bab
 * This is potentially very memory expensive, as the cache at each bucket
Packit 631bab
 * size is only bounded by how many buffers of that size we've managed to have
Packit 631bab
 * in flight at once.
Packit 631bab
 */
Packit 631bab
drm_public void
Packit 631bab
drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
Packit 631bab
Packit 631bab
	bufmgr_gem->bo_reuse = true;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Disables implicit synchronisation before executing the bo
Packit 631bab
 *
Packit 631bab
 * This will cause rendering corruption unless you correctly manage explicit
Packit 631bab
 * fences for all rendering involving this buffer - including use by others.
Packit 631bab
 * Disabling the implicit serialisation is only required if that serialisation
Packit 631bab
 * is too coarse (for example, you have split the buffer into many
Packit 631bab
 * non-overlapping regions and are sharing the whole buffer between concurrent
Packit 631bab
 * independent command streams).
Packit 631bab
 *
Packit 631bab
 * Note the kernel must advertise support via I915_PARAM_HAS_EXEC_ASYNC,
Packit 631bab
 * which can be checked using drm_intel_bufmgr_can_disable_implicit_sync,
Packit 631bab
 * or subsequent execbufs involving the bo will generate EINVAL.
Packit 631bab
 */
Packit 631bab
drm_public void
Packit 631bab
drm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	bo_gem->kflags |= EXEC_OBJECT_ASYNC;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Enables implicit synchronisation before executing the bo
Packit 631bab
 *
Packit 631bab
 * This is the default behaviour of the kernel, to wait upon prior writes
Packit 631bab
 * completing on the object before rendering with it, or to wait for prior
Packit 631bab
 * reads to complete before writing into the object.
Packit 631bab
 * drm_intel_gem_bo_disable_implicit_sync() can stop this behaviour, telling
Packit 631bab
 * the kernel never to insert a stall before using the object. Then this
Packit 631bab
 * function can be used to restore the implicit sync before subsequent
Packit 631bab
 * rendering.
Packit 631bab
 */
Packit 631bab
drm_public void
Packit 631bab
drm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	bo_gem->kflags &= ~EXEC_OBJECT_ASYNC;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Query whether the kernel supports disabling of its implicit synchronisation
Packit 631bab
 * before execbuf. See drm_intel_gem_bo_disable_implicit_sync()
Packit 631bab
 */
Packit 631bab
drm_public int
Packit 631bab
drm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
Packit 631bab
Packit 631bab
	return bufmgr_gem->has_exec_async;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Enable use of fenced reloc type.
Packit 631bab
 *
Packit 631bab
 * New code should enable this to avoid unnecessary fence register
Packit 631bab
 * allocation.  If this option is not enabled, all relocs will have fence
Packit 631bab
 * register allocated.
Packit 631bab
 */
Packit 631bab
drm_public void
Packit 631bab
drm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
Packit 631bab
Packit 631bab
	if (bufmgr_gem->bufmgr.bo_exec == drm_intel_gem_bo_exec2)
Packit 631bab
		bufmgr_gem->fenced_relocs = true;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Return the additional aperture space required by the tree of buffer objects
Packit 631bab
 * rooted at bo.
Packit 631bab
 */
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_get_aperture_space(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	int i;
Packit 631bab
	int total = 0;
Packit 631bab
Packit 631bab
	if (bo == NULL || bo_gem->included_in_check_aperture)
Packit 631bab
		return 0;
Packit 631bab
Packit 631bab
	total += bo->size;
Packit 631bab
	bo_gem->included_in_check_aperture = true;
Packit 631bab
Packit 631bab
	for (i = 0; i < bo_gem->reloc_count; i++)
Packit 631bab
		total +=
Packit 631bab
		    drm_intel_gem_bo_get_aperture_space(bo_gem->
Packit 631bab
							reloc_target_info[i].bo);
Packit 631bab
Packit 631bab
	return total;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Count the number of buffers in this list that need a fence reg
Packit 631bab
 *
Packit 631bab
 * If the count is greater than the number of available regs, we'll have
Packit 631bab
 * to ask the caller to resubmit a batch with fewer tiled buffers.
Packit 631bab
 *
Packit 631bab
 * This function over-counts if the same buffer is used multiple times.
Packit 631bab
 */
Packit 631bab
static unsigned int
Packit 631bab
drm_intel_gem_total_fences(drm_intel_bo ** bo_array, int count)
Packit 631bab
{
Packit 631bab
	int i;
Packit 631bab
	unsigned int total = 0;
Packit 631bab
Packit 631bab
	for (i = 0; i < count; i++) {
Packit 631bab
		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i];
Packit 631bab
Packit 631bab
		if (bo_gem == NULL)
Packit 631bab
			continue;
Packit 631bab
Packit 631bab
		total += bo_gem->reloc_tree_fences;
Packit 631bab
	}
Packit 631bab
	return total;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Clear the flag set by drm_intel_gem_bo_get_aperture_space() so we're ready
Packit 631bab
 * for the next drm_intel_bufmgr_check_aperture_space() call.
Packit 631bab
 */
Packit 631bab
static void
Packit 631bab
drm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	if (bo == NULL || !bo_gem->included_in_check_aperture)
Packit 631bab
		return;
Packit 631bab
Packit 631bab
	bo_gem->included_in_check_aperture = false;
Packit 631bab
Packit 631bab
	for (i = 0; i < bo_gem->reloc_count; i++)
Packit 631bab
		drm_intel_gem_bo_clear_aperture_space_flag(bo_gem->
Packit 631bab
							   reloc_target_info[i].bo);
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Return a conservative estimate for the amount of aperture required
Packit 631bab
 * for a collection of buffers. This may double-count some buffers.
Packit 631bab
 */
Packit 631bab
static unsigned int
Packit 631bab
drm_intel_gem_estimate_batch_space(drm_intel_bo **bo_array, int count)
Packit 631bab
{
Packit 631bab
	int i;
Packit 631bab
	unsigned int total = 0;
Packit 631bab
Packit 631bab
	for (i = 0; i < count; i++) {
Packit 631bab
		drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i];
Packit 631bab
		if (bo_gem != NULL)
Packit 631bab
			total += bo_gem->reloc_tree_size;
Packit 631bab
	}
Packit 631bab
	return total;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Return the amount of aperture needed for a collection of buffers.
Packit 631bab
 * This avoids double counting any buffers, at the cost of looking
Packit 631bab
 * at every buffer in the set.
Packit 631bab
 */
Packit 631bab
static unsigned int
Packit 631bab
drm_intel_gem_compute_batch_space(drm_intel_bo **bo_array, int count)
Packit 631bab
{
Packit 631bab
	int i;
Packit 631bab
	unsigned int total = 0;
Packit 631bab
Packit 631bab
	for (i = 0; i < count; i++) {
Packit 631bab
		total += drm_intel_gem_bo_get_aperture_space(bo_array[i]);
Packit 631bab
		/* For the first buffer object in the array, we get an
Packit 631bab
		 * accurate count back for its reloc_tree size (since nothing
Packit 631bab
		 * had been flagged as being counted yet).  We can save that
Packit 631bab
		 * value out as a more conservative reloc_tree_size that
Packit 631bab
		 * avoids double-counting target buffers.  Since the first
Packit 631bab
		 * buffer happens to usually be the batch buffer in our
Packit 631bab
		 * callers, this can pull us back from doing the tree
Packit 631bab
		 * walk on every new batch emit.
Packit 631bab
		 */
Packit 631bab
		if (i == 0) {
Packit 631bab
			drm_intel_bo_gem *bo_gem =
Packit 631bab
			    (drm_intel_bo_gem *) bo_array[i];
Packit 631bab
			bo_gem->reloc_tree_size = total;
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	for (i = 0; i < count; i++)
Packit 631bab
		drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]);
Packit 631bab
	return total;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Return -1 if the batchbuffer should be flushed before attempting to
Packit 631bab
 * emit rendering referencing the buffers pointed to by bo_array.
Packit 631bab
 *
Packit 631bab
 * This is required because if we try to emit a batchbuffer with relocations
Packit 631bab
 * to a tree of buffers that won't simultaneously fit in the aperture,
Packit 631bab
 * the rendering will return an error at a point where the software is not
Packit 631bab
 * prepared to recover from it.
Packit 631bab
 *
Packit 631bab
 * However, we also want to emit the batchbuffer significantly before we reach
Packit 631bab
 * the limit, as a series of batchbuffers each of which references buffers
Packit 631bab
 * covering almost all of the aperture means that at each emit we end up
Packit 631bab
 * waiting to evict a buffer from the last rendering, and we get synchronous
Packit 631bab
 * performance.  By emitting smaller batchbuffers, we eat some CPU overhead to
Packit 631bab
 * get better parallelism.
Packit 631bab
 */
Packit 631bab
static int
Packit 631bab
drm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem =
Packit 631bab
	    (drm_intel_bufmgr_gem *) bo_array[0]->bufmgr;
Packit 631bab
	unsigned int total = 0;
Packit 631bab
	unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4;
Packit 631bab
	int total_fences;
Packit 631bab
Packit 631bab
	/* Check for fence reg constraints if necessary */
Packit 631bab
	if (bufmgr_gem->available_fences) {
Packit 631bab
		total_fences = drm_intel_gem_total_fences(bo_array, count);
Packit 631bab
		if (total_fences > bufmgr_gem->available_fences)
Packit 631bab
			return -ENOSPC;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	total = drm_intel_gem_estimate_batch_space(bo_array, count);
Packit 631bab
Packit 631bab
	if (total > threshold)
Packit 631bab
		total = drm_intel_gem_compute_batch_space(bo_array, count);
Packit 631bab
Packit 631bab
	if (total > threshold) {
Packit 631bab
		DBG("check_space: overflowed available aperture, "
Packit 631bab
		    "%dkb vs %dkb\n",
Packit 631bab
		    total / 1024, (int)bufmgr_gem->gtt_size / 1024);
Packit 631bab
		return -ENOSPC;
Packit 631bab
	} else {
Packit 631bab
		DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024,
Packit 631bab
		    (int)bufmgr_gem->gtt_size / 1024);
Packit 631bab
		return 0;
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
/*
Packit 631bab
 * Disable buffer reuse for objects which are shared with the kernel
Packit 631bab
 * as scanout buffers
Packit 631bab
 */
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_disable_reuse(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	bo_gem->reusable = false;
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_is_reusable(drm_intel_bo *bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
Packit 631bab
	return bo_gem->reusable;
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
_drm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
Packit 631bab
	int i;
Packit 631bab
Packit 631bab
	for (i = 0; i < bo_gem->reloc_count; i++) {
Packit 631bab
		if (bo_gem->reloc_target_info[i].bo == target_bo)
Packit 631bab
			return 1;
Packit 631bab
		if (bo == bo_gem->reloc_target_info[i].bo)
Packit 631bab
			continue;
Packit 631bab
		if (_drm_intel_gem_bo_references(bo_gem->reloc_target_info[i].bo,
Packit 631bab
						target_bo))
Packit 631bab
			return 1;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	for (i = 0; i< bo_gem->softpin_target_count; i++) {
Packit 631bab
		if (bo_gem->softpin_target[i] == target_bo)
Packit 631bab
			return 1;
Packit 631bab
		if (_drm_intel_gem_bo_references(bo_gem->softpin_target[i], target_bo))
Packit 631bab
			return 1;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
/** Return true if target_bo is referenced by bo's relocation tree. */
Packit 631bab
static int
Packit 631bab
drm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo)
Packit 631bab
{
Packit 631bab
	drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo;
Packit 631bab
Packit 631bab
	if (bo == NULL || target_bo == NULL)
Packit 631bab
		return 0;
Packit 631bab
	if (target_bo_gem->used_as_reloc_target)
Packit 631bab
		return _drm_intel_gem_bo_references(bo, target_bo);
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
add_bucket(drm_intel_bufmgr_gem *bufmgr_gem, int size)
Packit 631bab
{
Packit 631bab
	unsigned int i = bufmgr_gem->num_buckets;
Packit 631bab
Packit 631bab
	assert(i < ARRAY_SIZE(bufmgr_gem->cache_bucket));
Packit 631bab
Packit 631bab
	DRMINITLISTHEAD(&bufmgr_gem->cache_bucket[i].head);
Packit 631bab
	bufmgr_gem->cache_bucket[i].size = size;
Packit 631bab
	bufmgr_gem->num_buckets++;
Packit 631bab
}
Packit 631bab
Packit 631bab
static void
Packit 631bab
init_cache_buckets(drm_intel_bufmgr_gem *bufmgr_gem)
Packit 631bab
{
Packit 631bab
	unsigned long size, cache_max_size = 64 * 1024 * 1024;
Packit 631bab
Packit 631bab
	/* OK, so power of two buckets was too wasteful of memory.
Packit 631bab
	 * Give 3 other sizes between each power of two, to hopefully
Packit 631bab
	 * cover things accurately enough.  (The alternative is
Packit 631bab
	 * probably to just go for exact matching of sizes, and assume
Packit 631bab
	 * that for things like composited window resize the tiled
Packit 631bab
	 * width/height alignment and rounding of sizes to pages will
Packit 631bab
	 * get us useful cache hit rates anyway)
Packit 631bab
	 */
Packit 631bab
	add_bucket(bufmgr_gem, 4096);
Packit 631bab
	add_bucket(bufmgr_gem, 4096 * 2);
Packit 631bab
	add_bucket(bufmgr_gem, 4096 * 3);
Packit 631bab
Packit 631bab
	/* Initialize the linked lists for BO reuse cache. */
Packit 631bab
	for (size = 4 * 4096; size <= cache_max_size; size *= 2) {
Packit 631bab
		add_bucket(bufmgr_gem, size);
Packit 631bab
Packit 631bab
		add_bucket(bufmgr_gem, size + size * 1 / 4);
Packit 631bab
		add_bucket(bufmgr_gem, size + size * 2 / 4);
Packit 631bab
		add_bucket(bufmgr_gem, size + size * 3 / 4);
Packit 631bab
	}
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public void
Packit 631bab
drm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
Packit 631bab
Packit 631bab
	bufmgr_gem->vma_max = limit;
Packit 631bab
Packit 631bab
	drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
Packit 631bab
}
Packit 631bab
Packit 631bab
static int
Packit 631bab
parse_devid_override(const char *devid_override)
Packit 631bab
{
Packit 631bab
	static const struct {
Packit 631bab
		const char *name;
Packit 631bab
		int pci_id;
Packit 631bab
	} name_map[] = {
Packit 631bab
		{ "brw", PCI_CHIP_I965_GM },
Packit 631bab
		{ "g4x", PCI_CHIP_GM45_GM },
Packit 631bab
		{ "ilk", PCI_CHIP_ILD_G },
Packit 631bab
		{ "snb", PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS },
Packit 631bab
		{ "ivb", PCI_CHIP_IVYBRIDGE_S_GT2 },
Packit 631bab
		{ "hsw", PCI_CHIP_HASWELL_CRW_E_GT3 },
Packit 631bab
		{ "byt", PCI_CHIP_VALLEYVIEW_3 },
Packit 631bab
		{ "bdw", 0x1620 | BDW_ULX },
Packit 631bab
		{ "skl", PCI_CHIP_SKYLAKE_DT_GT2 },
Packit 631bab
		{ "kbl", PCI_CHIP_KABYLAKE_DT_GT2 },
Packit 631bab
	};
Packit 631bab
	unsigned int i;
Packit 631bab
Packit 631bab
	for (i = 0; i < ARRAY_SIZE(name_map); i++) {
Packit 631bab
		if (!strcmp(name_map[i].name, devid_override))
Packit 631bab
			return name_map[i].pci_id;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	return strtod(devid_override, NULL);
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Get the PCI ID for the device.  This can be overridden by setting the
Packit 631bab
 * INTEL_DEVID_OVERRIDE environment variable to the desired ID.
Packit 631bab
 */
Packit 631bab
static int
Packit 631bab
get_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem)
Packit 631bab
{
Packit 631bab
	char *devid_override;
Packit 631bab
	int devid = 0;
Packit 631bab
	int ret;
Packit 631bab
	drm_i915_getparam_t gp;
Packit 631bab
Packit 631bab
	if (geteuid() == getuid()) {
Packit 631bab
		devid_override = getenv("INTEL_DEVID_OVERRIDE");
Packit 631bab
		if (devid_override) {
Packit 631bab
			bufmgr_gem->no_exec = true;
Packit 631bab
			return parse_devid_override(devid_override);
Packit 631bab
		}
Packit 631bab
	}
Packit 631bab
Packit 631bab
	memclear(gp);
Packit 631bab
	gp.param = I915_PARAM_CHIPSET_ID;
Packit 631bab
	gp.value = &devid;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp;;
Packit 631bab
	if (ret) {
Packit 631bab
		fprintf(stderr, "get chip id failed: %d [%d]\n", ret, errno);
Packit 631bab
		fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value);
Packit 631bab
	}
Packit 631bab
	return devid;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
Packit 631bab
Packit 631bab
	return bufmgr_gem->pci_device;
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Sets the AUB filename.
Packit 631bab
 *
Packit 631bab
 * This function has to be called before drm_intel_bufmgr_gem_set_aub_dump()
Packit 631bab
 * for it to have any effect.
Packit 631bab
 */
Packit 631bab
drm_public void
Packit 631bab
drm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr,
Packit 631bab
				      const char *filename)
Packit 631bab
{
Packit 631bab
}
Packit 631bab
Packit 631bab
/**
Packit 631bab
 * Sets up AUB dumping.
Packit 631bab
 *
Packit 631bab
 * This is a trace file format that can be used with the simulator.
Packit 631bab
 * Packets are emitted in a format somewhat like GPU command packets.
Packit 631bab
 * You can set up a GTT and upload your objects into the referenced
Packit 631bab
 * space, then send off batchbuffers and get BMPs out the other end.
Packit 631bab
 */
Packit 631bab
drm_public void
Packit 631bab
drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable)
Packit 631bab
{
Packit 631bab
	fprintf(stderr, "libdrm aub dumping is deprecated.\n\n"
Packit 631bab
		"Use intel_aubdump from intel-gpu-tools instead.  Install intel-gpu-tools,\n"
Packit 631bab
		"then run (for example)\n\n"
Packit 631bab
		"\t$ intel_aubdump --output=trace.aub glxgears -geometry 500x500\n\n"
Packit 631bab
		"See the intel_aubdump man page for more details.\n");
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public drm_intel_context *
Packit 631bab
drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
Packit 631bab
	struct drm_i915_gem_context_create create;
Packit 631bab
	drm_intel_context *context = NULL;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	context = calloc(1, sizeof(*context));
Packit 631bab
	if (!context)
Packit 631bab
		return NULL;
Packit 631bab
Packit 631bab
	memclear(create);
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
Packit 631bab
	if (ret != 0) {
Packit 631bab
		DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n",
Packit 631bab
		    strerror(errno));
Packit 631bab
		free(context);
Packit 631bab
		return NULL;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	context->ctx_id = create.ctx_id;
Packit 631bab
	context->bufmgr = bufmgr;
Packit 631bab
Packit 631bab
	return context;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id)
Packit 631bab
{
Packit 631bab
	if (ctx == NULL)
Packit 631bab
		return -EINVAL;
Packit 631bab
Packit 631bab
	*ctx_id = ctx->ctx_id;
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public void
Packit 631bab
drm_intel_gem_context_destroy(drm_intel_context *ctx)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem;
Packit 631bab
	struct drm_i915_gem_context_destroy destroy;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	if (ctx == NULL)
Packit 631bab
		return;
Packit 631bab
Packit 631bab
	memclear(destroy);
Packit 631bab
Packit 631bab
	bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
Packit 631bab
	destroy.ctx_id = ctx->ctx_id;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY,
Packit 631bab
		       &destroy);
Packit 631bab
	if (ret != 0)
Packit 631bab
		fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n",
Packit 631bab
			strerror(errno));
Packit 631bab
Packit 631bab
	free(ctx);
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_get_reset_stats(drm_intel_context *ctx,
Packit 631bab
			  uint32_t *reset_count,
Packit 631bab
			  uint32_t *active,
Packit 631bab
			  uint32_t *pending)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem;
Packit 631bab
	struct drm_i915_reset_stats stats;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	if (ctx == NULL)
Packit 631bab
		return -EINVAL;
Packit 631bab
Packit 631bab
	memclear(stats);
Packit 631bab
Packit 631bab
	bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
Packit 631bab
	stats.ctx_id = ctx->ctx_id;
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd,
Packit 631bab
		       DRM_IOCTL_I915_GET_RESET_STATS,
Packit 631bab
		       &stats);
Packit 631bab
	if (ret == 0) {
Packit 631bab
		if (reset_count != NULL)
Packit 631bab
			*reset_count = stats.reset_count;
Packit 631bab
Packit 631bab
		if (active != NULL)
Packit 631bab
			*active = stats.batch_active;
Packit 631bab
Packit 631bab
		if (pending != NULL)
Packit 631bab
			*pending = stats.batch_pending;
Packit 631bab
	}
Packit 631bab
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_reg_read(drm_intel_bufmgr *bufmgr,
Packit 631bab
		   uint32_t offset,
Packit 631bab
		   uint64_t *result)
Packit 631bab
{
Packit 631bab
	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
Packit 631bab
	struct drm_i915_reg_read reg_read;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	memclear(reg_read);
Packit 631bab
	reg_read.offset = offset;
Packit 631bab
Packit 631bab
	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, &reg_read);
Packit 631bab
Packit 631bab
	*result = reg_read.val;
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_get_subslice_total(int fd, unsigned int *subslice_total)
Packit 631bab
{
Packit 631bab
	drm_i915_getparam_t gp;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	memclear(gp);
Packit 631bab
	gp.value = (int*)subslice_total;
Packit 631bab
	gp.param = I915_PARAM_SUBSLICE_TOTAL;
Packit 631bab
	ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp;;
Packit 631bab
	if (ret)
Packit 631bab
		return -errno;
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_get_eu_total(int fd, unsigned int *eu_total)
Packit 631bab
{
Packit 631bab
	drm_i915_getparam_t gp;
Packit 631bab
	int ret;
Packit 631bab
Packit 631bab
	memclear(gp);
Packit 631bab
	gp.value = (int*)eu_total;
Packit 631bab
	gp.param = I915_PARAM_EU_TOTAL;
Packit 631bab
	ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp;;
Packit 631bab
	if (ret)
Packit 631bab
		return -errno;
Packit 631bab
Packit 631bab
	return 0;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_get_pooled_eu(int fd)
Packit 631bab
{
Packit 631bab
	drm_i915_getparam_t gp;
Packit 631bab
	int ret = -1;
Packit 631bab
Packit 631bab
	memclear(gp);
Packit 631bab
	gp.param = I915_PARAM_HAS_POOLED_EU;
Packit 631bab
	gp.value = &ret;
Packit 631bab
	if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
Packit 631bab
		return -errno;
Packit 631bab
Packit 631bab
	return ret;
Packit 631bab
}
Packit 631bab
Packit 631bab
drm_public int
Packit 631bab
drm_intel_get_min_eu_in_pool(int fd)