intel_bufmgr_gem.c revision fd815b59
122944501Smrg/************************************************************************** 222944501Smrg * 322944501Smrg * Copyright � 2007 Red Hat Inc. 420131375Smrg * Copyright � 2007-2012 Intel Corporation 522944501Smrg * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA 622944501Smrg * All Rights Reserved. 722944501Smrg * 822944501Smrg * Permission is hereby granted, free of charge, to any person obtaining a 922944501Smrg * copy of this software and associated documentation files (the 1022944501Smrg * "Software"), to deal in the Software without restriction, including 1122944501Smrg * without limitation the rights to use, copy, modify, merge, publish, 1222944501Smrg * distribute, sub license, and/or sell copies of the Software, and to 1322944501Smrg * permit persons to whom the Software is furnished to do so, subject to 1422944501Smrg * the following conditions: 1522944501Smrg * 1622944501Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1722944501Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1822944501Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 1922944501Smrg * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2022944501Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2122944501Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2222944501Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 2322944501Smrg * 2422944501Smrg * The above copyright notice and this permission notice (including the 2522944501Smrg * next paragraph) shall be included in all copies or substantial portions 2622944501Smrg * of the Software. 2722944501Smrg * 2822944501Smrg * 2922944501Smrg **************************************************************************/ 3022944501Smrg/* 3122944501Smrg * Authors: Thomas Hellstr�m <thomas-at-tungstengraphics-dot-com> 3222944501Smrg * Keith Whitwell <keithw-at-tungstengraphics-dot-com> 3322944501Smrg * Eric Anholt <eric@anholt.net> 3422944501Smrg * Dave Airlie <airlied@linux.ie> 3522944501Smrg */ 3622944501Smrg 3722944501Smrg#include <xf86drm.h> 3822944501Smrg#include <xf86atomic.h> 3922944501Smrg#include <fcntl.h> 4022944501Smrg#include <stdio.h> 4122944501Smrg#include <stdlib.h> 4222944501Smrg#include <string.h> 4322944501Smrg#include <unistd.h> 4422944501Smrg#include <assert.h> 4522944501Smrg#include <pthread.h> 4622944501Smrg#include <sys/ioctl.h> 4722944501Smrg#include <sys/stat.h> 4822944501Smrg#include <sys/types.h> 4920131375Smrg#include <stdbool.h> 5022944501Smrg 5122944501Smrg#include "errno.h" 5220131375Smrg#ifndef ETIME 5320131375Smrg#define ETIME ETIMEDOUT 5420131375Smrg#endif 55424e9256Smrg#include "libdrm_macros.h" 5622944501Smrg#include "libdrm_lists.h" 5722944501Smrg#include "intel_bufmgr.h" 5822944501Smrg#include "intel_bufmgr_priv.h" 5922944501Smrg#include "intel_chipset.h" 6022944501Smrg#include "string.h" 6122944501Smrg 6222944501Smrg#include "i915_drm.h" 632ee35494Smrg#include "uthash.h" 6422944501Smrg 652b90624aSmrg#if HAVE_VALGRIND 6620131375Smrg#include <valgrind.h> 6720131375Smrg#include <memcheck.h> 6820131375Smrg#define VG(x) x 6920131375Smrg#else 7020131375Smrg#define VG(x) 7120131375Smrg#endif 7220131375Smrg 73424e9256Smrg#define memclear(s) memset(&s, 0, sizeof(s)) 7420131375Smrg 7522944501Smrg#define DBG(...) do { \ 7622944501Smrg if (bufmgr_gem->bufmgr.debug) \ 7722944501Smrg fprintf(stderr, __VA_ARGS__); \ 7822944501Smrg} while (0) 7922944501Smrg 80aaba2545Smrg#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 81fe517fc9Smrg#define MAX2(A, B) ((A) > (B) ? (A) : (B)) 82fe517fc9Smrg 83fe517fc9Smrg/** 84fe517fc9Smrg * upper_32_bits - return bits 32-63 of a number 85fe517fc9Smrg * @n: the number we're accessing 86fe517fc9Smrg * 87fe517fc9Smrg * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress 88fe517fc9Smrg * the "right shift count >= width of type" warning when that quantity is 89fe517fc9Smrg * 32-bits. 90fe517fc9Smrg */ 91fe517fc9Smrg#define upper_32_bits(n) ((__u32)(((n) >> 16) >> 16)) 92fe517fc9Smrg 93fe517fc9Smrg/** 94fe517fc9Smrg * lower_32_bits - return bits 0-31 of a number 95fe517fc9Smrg * @n: the number we're accessing 96fe517fc9Smrg */ 97fe517fc9Smrg#define lower_32_bits(n) ((__u32)(n)) 98aaba2545Smrg 9922944501Smrgtypedef struct _drm_intel_bo_gem drm_intel_bo_gem; 10022944501Smrg 10122944501Smrgstruct drm_intel_gem_bo_bucket { 10222944501Smrg drmMMListHead head; 10322944501Smrg unsigned long size; 10422944501Smrg}; 10522944501Smrg 10622944501Smrgtypedef struct _drm_intel_bufmgr_gem { 10722944501Smrg drm_intel_bufmgr bufmgr; 10822944501Smrg 109a884aba1Smrg atomic_t refcount; 110a884aba1Smrg 11122944501Smrg int fd; 11222944501Smrg 11322944501Smrg int max_relocs; 11422944501Smrg 11522944501Smrg pthread_mutex_t lock; 11622944501Smrg 11722944501Smrg struct drm_i915_gem_exec_object *exec_objects; 11822944501Smrg struct drm_i915_gem_exec_object2 *exec2_objects; 11922944501Smrg drm_intel_bo **exec_bos; 12022944501Smrg int exec_size; 12122944501Smrg int exec_count; 12222944501Smrg 12322944501Smrg /** Array of lists of cached gem objects of power-of-two sizes */ 124aaba2545Smrg struct drm_intel_gem_bo_bucket cache_bucket[14 * 4]; 125aaba2545Smrg int num_buckets; 1266d98c517Smrg time_t time; 12722944501Smrg 128a884aba1Smrg drmMMListHead managers; 129a884aba1Smrg 1302ee35494Smrg drm_intel_bo_gem *name_table; 1312ee35494Smrg drm_intel_bo_gem *handle_table; 1322ee35494Smrg 13320131375Smrg drmMMListHead vma_cache; 13420131375Smrg int vma_count, vma_open, vma_max; 13520131375Smrg 13622944501Smrg uint64_t gtt_size; 13722944501Smrg int available_fences; 13822944501Smrg int pci_device; 13922944501Smrg int gen; 1409ce4edccSmrg unsigned int has_bsd : 1; 1419ce4edccSmrg unsigned int has_blt : 1; 1429ce4edccSmrg unsigned int has_relaxed_fencing : 1; 14320131375Smrg unsigned int has_llc : 1; 14420131375Smrg unsigned int has_wait_timeout : 1; 1459ce4edccSmrg unsigned int bo_reuse : 1; 14620131375Smrg unsigned int no_exec : 1; 14720131375Smrg unsigned int has_vebox : 1; 1482ee35494Smrg unsigned int has_exec_async : 1; 14920131375Smrg bool fenced_relocs; 15020131375Smrg 151424e9256Smrg struct { 152424e9256Smrg void *ptr; 153424e9256Smrg uint32_t handle; 154424e9256Smrg } userptr_active; 155424e9256Smrg 15622944501Smrg} drm_intel_bufmgr_gem; 15722944501Smrg 15822944501Smrg#define DRM_INTEL_RELOC_FENCE (1<<0) 15922944501Smrg 16022944501Smrgtypedef struct _drm_intel_reloc_target_info { 16122944501Smrg drm_intel_bo *bo; 16222944501Smrg int flags; 16322944501Smrg} drm_intel_reloc_target; 16422944501Smrg 16522944501Smrgstruct _drm_intel_bo_gem { 16622944501Smrg drm_intel_bo bo; 16722944501Smrg 16822944501Smrg atomic_t refcount; 16922944501Smrg uint32_t gem_handle; 17022944501Smrg const char *name; 17122944501Smrg 17222944501Smrg /** 17322944501Smrg * Kenel-assigned global name for this object 17420131375Smrg * 17520131375Smrg * List contains both flink named and prime fd'd objects 17622944501Smrg */ 17722944501Smrg unsigned int global_name; 1782ee35494Smrg 1792ee35494Smrg UT_hash_handle handle_hh; 1802ee35494Smrg UT_hash_handle name_hh; 18122944501Smrg 18222944501Smrg /** 18322944501Smrg * Index of the buffer within the validation list while preparing a 18422944501Smrg * batchbuffer execution. 18522944501Smrg */ 18622944501Smrg int validate_index; 18722944501Smrg 18822944501Smrg /** 18922944501Smrg * Current tiling mode 19022944501Smrg */ 19122944501Smrg uint32_t tiling_mode; 19222944501Smrg uint32_t swizzle_mode; 1936d98c517Smrg unsigned long stride; 19422944501Smrg 1952ee35494Smrg unsigned long kflags; 1962ee35494Smrg 19722944501Smrg time_t free_time; 19822944501Smrg 19922944501Smrg /** Array passed to the DRM containing relocation information. */ 20022944501Smrg struct drm_i915_gem_relocation_entry *relocs; 20122944501Smrg /** 20222944501Smrg * Array of info structs corresponding to relocs[i].target_handle etc 20322944501Smrg */ 20422944501Smrg drm_intel_reloc_target *reloc_target_info; 20522944501Smrg /** Number of entries in relocs */ 20622944501Smrg int reloc_count; 207fe517fc9Smrg /** Array of BOs that are referenced by this buffer and will be softpinned */ 208fe517fc9Smrg drm_intel_bo **softpin_target; 209fe517fc9Smrg /** Number softpinned BOs that are referenced by this buffer */ 210fe517fc9Smrg int softpin_target_count; 211fe517fc9Smrg /** Maximum amount of softpinned BOs that are referenced by this buffer */ 212fe517fc9Smrg int softpin_target_size; 213fe517fc9Smrg 21422944501Smrg /** Mapped address for the buffer, saved across map/unmap cycles */ 21522944501Smrg void *mem_virtual; 21622944501Smrg /** GTT virtual address for the buffer, saved across map/unmap cycles */ 21722944501Smrg void *gtt_virtual; 2182ee35494Smrg /** WC CPU address for the buffer, saved across map/unmap cycles */ 2192ee35494Smrg void *wc_virtual; 220a884aba1Smrg /** 221a884aba1Smrg * Virtual address of the buffer allocated by user, used for userptr 222a884aba1Smrg * objects only. 223a884aba1Smrg */ 224a884aba1Smrg void *user_virtual; 22520131375Smrg int map_count; 22620131375Smrg drmMMListHead vma_list; 22722944501Smrg 22822944501Smrg /** BO cache list */ 22922944501Smrg drmMMListHead head; 23022944501Smrg 23122944501Smrg /** 23222944501Smrg * Boolean of whether this BO and its children have been included in 23322944501Smrg * the current drm_intel_bufmgr_check_aperture_space() total. 23422944501Smrg */ 23520131375Smrg bool included_in_check_aperture; 23622944501Smrg 23722944501Smrg /** 23822944501Smrg * Boolean of whether this buffer has been used as a relocation 23922944501Smrg * target and had its size accounted for, and thus can't have any 24022944501Smrg * further relocations added to it. 24122944501Smrg */ 24220131375Smrg bool used_as_reloc_target; 24322944501Smrg 24422944501Smrg /** 24522944501Smrg * Boolean of whether we have encountered an error whilst building the relocation tree. 24622944501Smrg */ 24720131375Smrg bool has_error; 24822944501Smrg 24922944501Smrg /** 25022944501Smrg * Boolean of whether this buffer can be re-used 25122944501Smrg */ 25220131375Smrg bool reusable; 25320131375Smrg 25420131375Smrg /** 25520131375Smrg * Boolean of whether the GPU is definitely not accessing the buffer. 25620131375Smrg * 25720131375Smrg * This is only valid when reusable, since non-reusable 2582ee35494Smrg * buffers are those that have been shared with other 25920131375Smrg * processes, so we don't know their state. 26020131375Smrg */ 26120131375Smrg bool idle; 26222944501Smrg 263a884aba1Smrg /** 264a884aba1Smrg * Boolean of whether this buffer was allocated with userptr 265a884aba1Smrg */ 266a884aba1Smrg bool is_userptr; 267a884aba1Smrg 26822944501Smrg /** 26922944501Smrg * Size in bytes of this buffer and its relocation descendents. 27022944501Smrg * 27122944501Smrg * Used to avoid costly tree walking in 27222944501Smrg * drm_intel_bufmgr_check_aperture in the common case. 27322944501Smrg */ 27422944501Smrg int reloc_tree_size; 27522944501Smrg 27622944501Smrg /** 27722944501Smrg * Number of potential fence registers required by this buffer and its 27822944501Smrg * relocations. 27922944501Smrg */ 28022944501Smrg int reloc_tree_fences; 28120131375Smrg 2822ee35494Smrg /** Flags that we may need to do the SW_FINISH ioctl on unmap. */ 28320131375Smrg bool mapped_cpu_write; 28422944501Smrg}; 28522944501Smrg 28622944501Smrgstatic unsigned int 28722944501Smrgdrm_intel_gem_estimate_batch_space(drm_intel_bo ** bo_array, int count); 28822944501Smrg 28922944501Smrgstatic unsigned int 29022944501Smrgdrm_intel_gem_compute_batch_space(drm_intel_bo ** bo_array, int count); 29122944501Smrg 29222944501Smrgstatic int 29322944501Smrgdrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, 29422944501Smrg uint32_t * swizzle_mode); 29522944501Smrg 29622944501Smrgstatic int 2976d98c517Smrgdrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, 2986d98c517Smrg uint32_t tiling_mode, 2996d98c517Smrg uint32_t stride); 30022944501Smrg 30122944501Smrgstatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, 30222944501Smrg time_t time); 30322944501Smrg 30422944501Smrgstatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo); 30522944501Smrg 30622944501Smrgstatic void drm_intel_gem_bo_free(drm_intel_bo *bo); 30722944501Smrg 308fe517fc9Smrgstatic inline drm_intel_bo_gem *to_bo_gem(drm_intel_bo *bo) 309fe517fc9Smrg{ 310fe517fc9Smrg return (drm_intel_bo_gem *)bo; 311fe517fc9Smrg} 312fe517fc9Smrg 31322944501Smrgstatic unsigned long 31422944501Smrgdrm_intel_gem_bo_tile_size(drm_intel_bufmgr_gem *bufmgr_gem, unsigned long size, 31522944501Smrg uint32_t *tiling_mode) 31622944501Smrg{ 31722944501Smrg unsigned long min_size, max_size; 31822944501Smrg unsigned long i; 31922944501Smrg 32022944501Smrg if (*tiling_mode == I915_TILING_NONE) 32122944501Smrg return size; 32222944501Smrg 32322944501Smrg /* 965+ just need multiples of page size for tiling */ 32422944501Smrg if (bufmgr_gem->gen >= 4) 32522944501Smrg return ROUND_UP_TO(size, 4096); 32622944501Smrg 32722944501Smrg /* Older chips need powers of two, of at least 512k or 1M */ 32822944501Smrg if (bufmgr_gem->gen == 3) { 32922944501Smrg min_size = 1024*1024; 33022944501Smrg max_size = 128*1024*1024; 33122944501Smrg } else { 33222944501Smrg min_size = 512*1024; 33322944501Smrg max_size = 64*1024*1024; 33422944501Smrg } 33522944501Smrg 33622944501Smrg if (size > max_size) { 33722944501Smrg *tiling_mode = I915_TILING_NONE; 33822944501Smrg return size; 33922944501Smrg } 34022944501Smrg 3419ce4edccSmrg /* Do we need to allocate every page for the fence? */ 3429ce4edccSmrg if (bufmgr_gem->has_relaxed_fencing) 3439ce4edccSmrg return ROUND_UP_TO(size, 4096); 3449ce4edccSmrg 34522944501Smrg for (i = min_size; i < size; i <<= 1) 34622944501Smrg ; 34722944501Smrg 34822944501Smrg return i; 34922944501Smrg} 35022944501Smrg 35122944501Smrg/* 35222944501Smrg * Round a given pitch up to the minimum required for X tiling on a 35322944501Smrg * given chip. We use 512 as the minimum to allow for a later tiling 35422944501Smrg * change. 35522944501Smrg */ 35622944501Smrgstatic unsigned long 35722944501Smrgdrm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem, 3586d98c517Smrg unsigned long pitch, uint32_t *tiling_mode) 35922944501Smrg{ 36022944501Smrg unsigned long tile_width; 36122944501Smrg unsigned long i; 36222944501Smrg 36322944501Smrg /* If untiled, then just align it so that we can do rendering 36422944501Smrg * to it with the 3D engine. 36522944501Smrg */ 3666d98c517Smrg if (*tiling_mode == I915_TILING_NONE) 36722944501Smrg return ALIGN(pitch, 64); 36822944501Smrg 36920131375Smrg if (*tiling_mode == I915_TILING_X 37020131375Smrg || (IS_915(bufmgr_gem->pci_device) 37120131375Smrg && *tiling_mode == I915_TILING_Y)) 37222944501Smrg tile_width = 512; 37322944501Smrg else 37422944501Smrg tile_width = 128; 37522944501Smrg 37622944501Smrg /* 965 is flexible */ 37722944501Smrg if (bufmgr_gem->gen >= 4) 37822944501Smrg return ROUND_UP_TO(pitch, tile_width); 37922944501Smrg 3806d98c517Smrg /* The older hardware has a maximum pitch of 8192 with tiled 3816d98c517Smrg * surfaces, so fallback to untiled if it's too large. 3826d98c517Smrg */ 3836d98c517Smrg if (pitch > 8192) { 3846d98c517Smrg *tiling_mode = I915_TILING_NONE; 3856d98c517Smrg return ALIGN(pitch, 64); 3866d98c517Smrg } 3876d98c517Smrg 38822944501Smrg /* Pre-965 needs power of two tile width */ 38922944501Smrg for (i = tile_width; i < pitch; i <<= 1) 39022944501Smrg ; 39122944501Smrg 39222944501Smrg return i; 39322944501Smrg} 39422944501Smrg 39522944501Smrgstatic struct drm_intel_gem_bo_bucket * 39622944501Smrgdrm_intel_gem_bo_bucket_for_size(drm_intel_bufmgr_gem *bufmgr_gem, 39722944501Smrg unsigned long size) 39822944501Smrg{ 39922944501Smrg int i; 40022944501Smrg 401aaba2545Smrg for (i = 0; i < bufmgr_gem->num_buckets; i++) { 40222944501Smrg struct drm_intel_gem_bo_bucket *bucket = 40322944501Smrg &bufmgr_gem->cache_bucket[i]; 40422944501Smrg if (bucket->size >= size) { 40522944501Smrg return bucket; 40622944501Smrg } 40722944501Smrg } 40822944501Smrg 40922944501Smrg return NULL; 41022944501Smrg} 41122944501Smrg 41222944501Smrgstatic void 41322944501Smrgdrm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) 41422944501Smrg{ 41522944501Smrg int i, j; 41622944501Smrg 41722944501Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 41822944501Smrg drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; 41922944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 42022944501Smrg 421fe517fc9Smrg if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) { 422fe517fc9Smrg DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle, 4230655efefSmrg bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "", 42422944501Smrg bo_gem->name); 42522944501Smrg continue; 42622944501Smrg } 42722944501Smrg 42822944501Smrg for (j = 0; j < bo_gem->reloc_count; j++) { 42922944501Smrg drm_intel_bo *target_bo = bo_gem->reloc_target_info[j].bo; 43022944501Smrg drm_intel_bo_gem *target_gem = 43122944501Smrg (drm_intel_bo_gem *) target_bo; 43222944501Smrg 433fe517fc9Smrg DBG("%2d: %d %s(%s)@0x%08x %08x -> " 434fe517fc9Smrg "%d (%s)@0x%08x %08x + 0x%08x\n", 43522944501Smrg i, 436fe517fc9Smrg bo_gem->gem_handle, 4370655efefSmrg bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "", 438fe517fc9Smrg bo_gem->name, 439fe517fc9Smrg upper_32_bits(bo_gem->relocs[j].offset), 440fe517fc9Smrg lower_32_bits(bo_gem->relocs[j].offset), 44122944501Smrg target_gem->gem_handle, 44222944501Smrg target_gem->name, 443fe517fc9Smrg upper_32_bits(target_bo->offset64), 444fe517fc9Smrg lower_32_bits(target_bo->offset64), 44522944501Smrg bo_gem->relocs[j].delta); 44622944501Smrg } 447fe517fc9Smrg 448fe517fc9Smrg for (j = 0; j < bo_gem->softpin_target_count; j++) { 449fe517fc9Smrg drm_intel_bo *target_bo = bo_gem->softpin_target[j]; 450fe517fc9Smrg drm_intel_bo_gem *target_gem = 451fe517fc9Smrg (drm_intel_bo_gem *) target_bo; 452fe517fc9Smrg DBG("%2d: %d %s(%s) -> " 453fe517fc9Smrg "%d *(%s)@0x%08x %08x\n", 454fe517fc9Smrg i, 455fe517fc9Smrg bo_gem->gem_handle, 4560655efefSmrg bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "", 457fe517fc9Smrg bo_gem->name, 458fe517fc9Smrg target_gem->gem_handle, 459fe517fc9Smrg target_gem->name, 460fe517fc9Smrg upper_32_bits(target_bo->offset64), 461fe517fc9Smrg lower_32_bits(target_bo->offset64)); 462fe517fc9Smrg } 46322944501Smrg } 46422944501Smrg} 46522944501Smrg 46622944501Smrgstatic inline void 46722944501Smrgdrm_intel_gem_bo_reference(drm_intel_bo *bo) 46822944501Smrg{ 46922944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 47022944501Smrg 47122944501Smrg atomic_inc(&bo_gem->refcount); 47222944501Smrg} 47322944501Smrg 47422944501Smrg/** 47522944501Smrg * Adds the given buffer to the list of buffers to be validated (moved into the 47622944501Smrg * appropriate memory type) with the next batch submission. 47722944501Smrg * 47822944501Smrg * If a buffer is validated multiple times in a batch submission, it ends up 47922944501Smrg * with the intersection of the memory type flags and the union of the 48022944501Smrg * access flags. 48122944501Smrg */ 48222944501Smrgstatic void 48322944501Smrgdrm_intel_add_validate_buffer(drm_intel_bo *bo) 48422944501Smrg{ 48522944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 48622944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 48722944501Smrg int index; 48822944501Smrg 48922944501Smrg if (bo_gem->validate_index != -1) 49022944501Smrg return; 49122944501Smrg 49222944501Smrg /* Extend the array of validation entries as necessary. */ 49322944501Smrg if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) { 49422944501Smrg int new_size = bufmgr_gem->exec_size * 2; 49522944501Smrg 49622944501Smrg if (new_size == 0) 49722944501Smrg new_size = 5; 49822944501Smrg 49922944501Smrg bufmgr_gem->exec_objects = 50022944501Smrg realloc(bufmgr_gem->exec_objects, 50122944501Smrg sizeof(*bufmgr_gem->exec_objects) * new_size); 50222944501Smrg bufmgr_gem->exec_bos = 50322944501Smrg realloc(bufmgr_gem->exec_bos, 50422944501Smrg sizeof(*bufmgr_gem->exec_bos) * new_size); 50522944501Smrg bufmgr_gem->exec_size = new_size; 50622944501Smrg } 50722944501Smrg 50822944501Smrg index = bufmgr_gem->exec_count; 50922944501Smrg bo_gem->validate_index = index; 51022944501Smrg /* Fill in array entry */ 51122944501Smrg bufmgr_gem->exec_objects[index].handle = bo_gem->gem_handle; 51222944501Smrg bufmgr_gem->exec_objects[index].relocation_count = bo_gem->reloc_count; 51322944501Smrg bufmgr_gem->exec_objects[index].relocs_ptr = (uintptr_t) bo_gem->relocs; 514fe517fc9Smrg bufmgr_gem->exec_objects[index].alignment = bo->align; 51522944501Smrg bufmgr_gem->exec_objects[index].offset = 0; 51622944501Smrg bufmgr_gem->exec_bos[index] = bo; 51722944501Smrg bufmgr_gem->exec_count++; 51822944501Smrg} 51922944501Smrg 52022944501Smrgstatic void 52122944501Smrgdrm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence) 52222944501Smrg{ 52322944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; 52422944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; 52522944501Smrg int index; 5260655efefSmrg unsigned long flags; 527fe517fc9Smrg 5280655efefSmrg flags = 0; 529fe517fc9Smrg if (need_fence) 530fe517fc9Smrg flags |= EXEC_OBJECT_NEEDS_FENCE; 53122944501Smrg 53222944501Smrg if (bo_gem->validate_index != -1) { 533fe517fc9Smrg bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags; 53422944501Smrg return; 53522944501Smrg } 53622944501Smrg 53722944501Smrg /* Extend the array of validation entries as necessary. */ 53822944501Smrg if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) { 53922944501Smrg int new_size = bufmgr_gem->exec_size * 2; 54022944501Smrg 54122944501Smrg if (new_size == 0) 54222944501Smrg new_size = 5; 54322944501Smrg 54422944501Smrg bufmgr_gem->exec2_objects = 54522944501Smrg realloc(bufmgr_gem->exec2_objects, 54622944501Smrg sizeof(*bufmgr_gem->exec2_objects) * new_size); 54722944501Smrg bufmgr_gem->exec_bos = 54822944501Smrg realloc(bufmgr_gem->exec_bos, 54922944501Smrg sizeof(*bufmgr_gem->exec_bos) * new_size); 55022944501Smrg bufmgr_gem->exec_size = new_size; 55122944501Smrg } 55222944501Smrg 55322944501Smrg index = bufmgr_gem->exec_count; 55422944501Smrg bo_gem->validate_index = index; 55522944501Smrg /* Fill in array entry */ 55622944501Smrg bufmgr_gem->exec2_objects[index].handle = bo_gem->gem_handle; 55722944501Smrg bufmgr_gem->exec2_objects[index].relocation_count = bo_gem->reloc_count; 55822944501Smrg bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs; 559fe517fc9Smrg bufmgr_gem->exec2_objects[index].alignment = bo->align; 5602ee35494Smrg bufmgr_gem->exec2_objects[index].offset = bo->offset64; 5610655efefSmrg bufmgr_gem->exec2_objects[index].flags = bo_gem->kflags | flags; 56222944501Smrg bufmgr_gem->exec2_objects[index].rsvd1 = 0; 56322944501Smrg bufmgr_gem->exec2_objects[index].rsvd2 = 0; 5642ee35494Smrg bufmgr_gem->exec_bos[index] = bo; 56522944501Smrg bufmgr_gem->exec_count++; 56622944501Smrg} 56722944501Smrg 56822944501Smrg#define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \ 56922944501Smrg sizeof(uint32_t)) 57022944501Smrg 57122944501Smrgstatic void 57222944501Smrgdrm_intel_bo_gem_set_in_aperture_size(drm_intel_bufmgr_gem *bufmgr_gem, 573fe517fc9Smrg drm_intel_bo_gem *bo_gem, 574fe517fc9Smrg unsigned int alignment) 57522944501Smrg{ 576fe517fc9Smrg unsigned int size; 57722944501Smrg 57822944501Smrg assert(!bo_gem->used_as_reloc_target); 57922944501Smrg 58022944501Smrg /* The older chipsets are far-less flexible in terms of tiling, 58122944501Smrg * and require tiled buffer to be size aligned in the aperture. 58222944501Smrg * This means that in the worst possible case we will need a hole 58322944501Smrg * twice as large as the object in order for it to fit into the 58422944501Smrg * aperture. Optimal packing is for wimps. 58522944501Smrg */ 58622944501Smrg size = bo_gem->bo.size; 5879ce4edccSmrg if (bufmgr_gem->gen < 4 && bo_gem->tiling_mode != I915_TILING_NONE) { 588fe517fc9Smrg unsigned int min_size; 5899ce4edccSmrg 5909ce4edccSmrg if (bufmgr_gem->has_relaxed_fencing) { 5919ce4edccSmrg if (bufmgr_gem->gen == 3) 5929ce4edccSmrg min_size = 1024*1024; 5939ce4edccSmrg else 5949ce4edccSmrg min_size = 512*1024; 5959ce4edccSmrg 5969ce4edccSmrg while (min_size < size) 5979ce4edccSmrg min_size *= 2; 5989ce4edccSmrg } else 5999ce4edccSmrg min_size = size; 6009ce4edccSmrg 6019ce4edccSmrg /* Account for worst-case alignment. */ 602fe517fc9Smrg alignment = MAX2(alignment, min_size); 6039ce4edccSmrg } 60422944501Smrg 605fe517fc9Smrg bo_gem->reloc_tree_size = size + alignment; 60622944501Smrg} 60722944501Smrg 60822944501Smrgstatic int 60922944501Smrgdrm_intel_setup_reloc_list(drm_intel_bo *bo) 61022944501Smrg{ 61122944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 61222944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 61322944501Smrg unsigned int max_relocs = bufmgr_gem->max_relocs; 61422944501Smrg 61522944501Smrg if (bo->size / 4 < max_relocs) 61622944501Smrg max_relocs = bo->size / 4; 61722944501Smrg 61822944501Smrg bo_gem->relocs = malloc(max_relocs * 61922944501Smrg sizeof(struct drm_i915_gem_relocation_entry)); 62022944501Smrg bo_gem->reloc_target_info = malloc(max_relocs * 621aaba2545Smrg sizeof(drm_intel_reloc_target)); 62222944501Smrg if (bo_gem->relocs == NULL || bo_gem->reloc_target_info == NULL) { 62320131375Smrg bo_gem->has_error = true; 62422944501Smrg 62522944501Smrg free (bo_gem->relocs); 62622944501Smrg bo_gem->relocs = NULL; 62722944501Smrg 62822944501Smrg free (bo_gem->reloc_target_info); 62922944501Smrg bo_gem->reloc_target_info = NULL; 63022944501Smrg 63122944501Smrg return 1; 63222944501Smrg } 63322944501Smrg 63422944501Smrg return 0; 63522944501Smrg} 63622944501Smrg 63722944501Smrgstatic int 63822944501Smrgdrm_intel_gem_bo_busy(drm_intel_bo *bo) 63922944501Smrg{ 64022944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 64122944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 64222944501Smrg struct drm_i915_gem_busy busy; 64322944501Smrg int ret; 64422944501Smrg 64520131375Smrg if (bo_gem->reusable && bo_gem->idle) 64620131375Smrg return false; 64720131375Smrg 648424e9256Smrg memclear(busy); 64922944501Smrg busy.handle = bo_gem->gem_handle; 65022944501Smrg 6516d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy); 65220131375Smrg if (ret == 0) { 65320131375Smrg bo_gem->idle = !busy.busy; 65420131375Smrg return busy.busy; 65520131375Smrg } else { 65620131375Smrg return false; 65720131375Smrg } 65822944501Smrg} 65922944501Smrg 66022944501Smrgstatic int 66122944501Smrgdrm_intel_gem_bo_madvise_internal(drm_intel_bufmgr_gem *bufmgr_gem, 66222944501Smrg drm_intel_bo_gem *bo_gem, int state) 66322944501Smrg{ 66422944501Smrg struct drm_i915_gem_madvise madv; 66522944501Smrg 666424e9256Smrg memclear(madv); 66722944501Smrg madv.handle = bo_gem->gem_handle; 66822944501Smrg madv.madv = state; 66922944501Smrg madv.retained = 1; 6706d98c517Smrg drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv); 67122944501Smrg 67222944501Smrg return madv.retained; 67322944501Smrg} 67422944501Smrg 67522944501Smrgstatic int 67622944501Smrgdrm_intel_gem_bo_madvise(drm_intel_bo *bo, int madv) 67722944501Smrg{ 67822944501Smrg return drm_intel_gem_bo_madvise_internal 67922944501Smrg ((drm_intel_bufmgr_gem *) bo->bufmgr, 68022944501Smrg (drm_intel_bo_gem *) bo, 68122944501Smrg madv); 68222944501Smrg} 68322944501Smrg 68422944501Smrg/* drop the oldest entries that have been purged by the kernel */ 68522944501Smrgstatic void 68622944501Smrgdrm_intel_gem_bo_cache_purge_bucket(drm_intel_bufmgr_gem *bufmgr_gem, 68722944501Smrg struct drm_intel_gem_bo_bucket *bucket) 68822944501Smrg{ 68922944501Smrg while (!DRMLISTEMPTY(&bucket->head)) { 69022944501Smrg drm_intel_bo_gem *bo_gem; 69122944501Smrg 69222944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 69322944501Smrg bucket->head.next, head); 69422944501Smrg if (drm_intel_gem_bo_madvise_internal 69522944501Smrg (bufmgr_gem, bo_gem, I915_MADV_DONTNEED)) 69622944501Smrg break; 69722944501Smrg 69822944501Smrg DRMLISTDEL(&bo_gem->head); 69922944501Smrg drm_intel_gem_bo_free(&bo_gem->bo); 70022944501Smrg } 70122944501Smrg} 70222944501Smrg 70322944501Smrgstatic drm_intel_bo * 70422944501Smrgdrm_intel_gem_bo_alloc_internal(drm_intel_bufmgr *bufmgr, 70522944501Smrg const char *name, 70622944501Smrg unsigned long size, 7076d98c517Smrg unsigned long flags, 7086d98c517Smrg uint32_t tiling_mode, 709fe517fc9Smrg unsigned long stride, 710fe517fc9Smrg unsigned int alignment) 71122944501Smrg{ 71222944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 71322944501Smrg drm_intel_bo_gem *bo_gem; 71422944501Smrg unsigned int page_size = getpagesize(); 71522944501Smrg int ret; 71622944501Smrg struct drm_intel_gem_bo_bucket *bucket; 71720131375Smrg bool alloc_from_cache; 71822944501Smrg unsigned long bo_size; 71920131375Smrg bool for_render = false; 72022944501Smrg 72122944501Smrg if (flags & BO_ALLOC_FOR_RENDER) 72220131375Smrg for_render = true; 72322944501Smrg 72422944501Smrg /* Round the allocated size up to a power of two number of pages. */ 72522944501Smrg bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, size); 72622944501Smrg 72722944501Smrg /* If we don't have caching at this size, don't actually round the 72822944501Smrg * allocation up. 72922944501Smrg */ 73022944501Smrg if (bucket == NULL) { 73122944501Smrg bo_size = size; 73222944501Smrg if (bo_size < page_size) 73322944501Smrg bo_size = page_size; 73422944501Smrg } else { 73522944501Smrg bo_size = bucket->size; 73622944501Smrg } 73722944501Smrg 73822944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 73922944501Smrg /* Get a buffer out of the cache if available */ 74022944501Smrgretry: 74120131375Smrg alloc_from_cache = false; 74222944501Smrg if (bucket != NULL && !DRMLISTEMPTY(&bucket->head)) { 74322944501Smrg if (for_render) { 74422944501Smrg /* Allocate new render-target BOs from the tail (MRU) 74522944501Smrg * of the list, as it will likely be hot in the GPU 74622944501Smrg * cache and in the aperture for us. 74722944501Smrg */ 74822944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 74922944501Smrg bucket->head.prev, head); 75022944501Smrg DRMLISTDEL(&bo_gem->head); 75120131375Smrg alloc_from_cache = true; 752fe517fc9Smrg bo_gem->bo.align = alignment; 75322944501Smrg } else { 754fe517fc9Smrg assert(alignment == 0); 75522944501Smrg /* For non-render-target BOs (where we're probably 75622944501Smrg * going to map it first thing in order to fill it 75722944501Smrg * with data), check if the last BO in the cache is 75822944501Smrg * unbusy, and only reuse in that case. Otherwise, 75922944501Smrg * allocating a new buffer is probably faster than 76022944501Smrg * waiting for the GPU to finish. 76122944501Smrg */ 76222944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 76322944501Smrg bucket->head.next, head); 76422944501Smrg if (!drm_intel_gem_bo_busy(&bo_gem->bo)) { 76520131375Smrg alloc_from_cache = true; 76622944501Smrg DRMLISTDEL(&bo_gem->head); 76722944501Smrg } 76822944501Smrg } 76922944501Smrg 77022944501Smrg if (alloc_from_cache) { 77122944501Smrg if (!drm_intel_gem_bo_madvise_internal 77222944501Smrg (bufmgr_gem, bo_gem, I915_MADV_WILLNEED)) { 77322944501Smrg drm_intel_gem_bo_free(&bo_gem->bo); 77422944501Smrg drm_intel_gem_bo_cache_purge_bucket(bufmgr_gem, 77522944501Smrg bucket); 77622944501Smrg goto retry; 77722944501Smrg } 7786d98c517Smrg 7796d98c517Smrg if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, 7806d98c517Smrg tiling_mode, 7816d98c517Smrg stride)) { 7826d98c517Smrg drm_intel_gem_bo_free(&bo_gem->bo); 7836d98c517Smrg goto retry; 7846d98c517Smrg } 78522944501Smrg } 78622944501Smrg } 78722944501Smrg 78822944501Smrg if (!alloc_from_cache) { 78922944501Smrg struct drm_i915_gem_create create; 79022944501Smrg 79122944501Smrg bo_gem = calloc(1, sizeof(*bo_gem)); 79222944501Smrg if (!bo_gem) 7932ee35494Smrg goto err; 7942ee35494Smrg 7952ee35494Smrg /* drm_intel_gem_bo_free calls DRMLISTDEL() for an uninitialized 7962ee35494Smrg list (vma_list), so better set the list head here */ 7972ee35494Smrg DRMINITLISTHEAD(&bo_gem->vma_list); 79822944501Smrg 79922944501Smrg bo_gem->bo.size = bo_size; 80020131375Smrg 801424e9256Smrg memclear(create); 80222944501Smrg create.size = bo_size; 80322944501Smrg 8046d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 8056d98c517Smrg DRM_IOCTL_I915_GEM_CREATE, 8066d98c517Smrg &create); 80722944501Smrg if (ret != 0) { 80822944501Smrg free(bo_gem); 8092ee35494Smrg goto err; 81022944501Smrg } 8112ee35494Smrg 8122ee35494Smrg bo_gem->gem_handle = create.handle; 8130655efefSmrg HASH_ADD(handle_hh, bufmgr_gem->handle_table, 8140655efefSmrg gem_handle, sizeof(bo_gem->gem_handle), 8150655efefSmrg bo_gem); 8160655efefSmrg 8172ee35494Smrg bo_gem->bo.handle = bo_gem->gem_handle; 81822944501Smrg bo_gem->bo.bufmgr = bufmgr; 819fe517fc9Smrg bo_gem->bo.align = alignment; 8206d98c517Smrg 8216d98c517Smrg bo_gem->tiling_mode = I915_TILING_NONE; 8226d98c517Smrg bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 8236d98c517Smrg bo_gem->stride = 0; 8246d98c517Smrg 8256d98c517Smrg if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, 8266d98c517Smrg tiling_mode, 8272ee35494Smrg stride)) 8282ee35494Smrg goto err_free; 82922944501Smrg } 83022944501Smrg 83122944501Smrg bo_gem->name = name; 83222944501Smrg atomic_set(&bo_gem->refcount, 1); 83322944501Smrg bo_gem->validate_index = -1; 83422944501Smrg bo_gem->reloc_tree_fences = 0; 83520131375Smrg bo_gem->used_as_reloc_target = false; 83620131375Smrg bo_gem->has_error = false; 83720131375Smrg bo_gem->reusable = true; 83822944501Smrg 839fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment); 8402ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 84122944501Smrg 84222944501Smrg DBG("bo_create: buf %d (%s) %ldb\n", 84322944501Smrg bo_gem->gem_handle, bo_gem->name, size); 84422944501Smrg 84522944501Smrg return &bo_gem->bo; 8462ee35494Smrg 8472ee35494Smrgerr_free: 8482ee35494Smrg drm_intel_gem_bo_free(&bo_gem->bo); 8492ee35494Smrgerr: 8502ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 8512ee35494Smrg return NULL; 85222944501Smrg} 85322944501Smrg 85422944501Smrgstatic drm_intel_bo * 85522944501Smrgdrm_intel_gem_bo_alloc_for_render(drm_intel_bufmgr *bufmgr, 85622944501Smrg const char *name, 85722944501Smrg unsigned long size, 85822944501Smrg unsigned int alignment) 85922944501Smrg{ 86022944501Smrg return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 8616d98c517Smrg BO_ALLOC_FOR_RENDER, 862fe517fc9Smrg I915_TILING_NONE, 0, 863fe517fc9Smrg alignment); 86422944501Smrg} 86522944501Smrg 86622944501Smrgstatic drm_intel_bo * 86722944501Smrgdrm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, 86822944501Smrg const char *name, 86922944501Smrg unsigned long size, 87022944501Smrg unsigned int alignment) 87122944501Smrg{ 8726d98c517Smrg return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0, 873fe517fc9Smrg I915_TILING_NONE, 0, 0); 87422944501Smrg} 87522944501Smrg 87622944501Smrgstatic drm_intel_bo * 87722944501Smrgdrm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, 87822944501Smrg int x, int y, int cpp, uint32_t *tiling_mode, 87922944501Smrg unsigned long *pitch, unsigned long flags) 88022944501Smrg{ 88122944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 882aaba2545Smrg unsigned long size, stride; 883aaba2545Smrg uint32_t tiling; 88422944501Smrg 885aaba2545Smrg do { 88620131375Smrg unsigned long aligned_y, height_alignment; 887aaba2545Smrg 888aaba2545Smrg tiling = *tiling_mode; 889aaba2545Smrg 890aaba2545Smrg /* If we're tiled, our allocations are in 8 or 32-row blocks, 891aaba2545Smrg * so failure to align our height means that we won't allocate 892aaba2545Smrg * enough pages. 893aaba2545Smrg * 894aaba2545Smrg * If we're untiled, we still have to align to 2 rows high 895aaba2545Smrg * because the data port accesses 2x2 blocks even if the 896aaba2545Smrg * bottom row isn't to be rendered, so failure to align means 897aaba2545Smrg * we could walk off the end of the GTT and fault. This is 898aaba2545Smrg * documented on 965, and may be the case on older chipsets 899aaba2545Smrg * too so we try to be careful. 900aaba2545Smrg */ 901aaba2545Smrg aligned_y = y; 90220131375Smrg height_alignment = 2; 90320131375Smrg 90420131375Smrg if ((bufmgr_gem->gen == 2) && tiling != I915_TILING_NONE) 90520131375Smrg height_alignment = 16; 90620131375Smrg else if (tiling == I915_TILING_X 90720131375Smrg || (IS_915(bufmgr_gem->pci_device) 90820131375Smrg && tiling == I915_TILING_Y)) 90920131375Smrg height_alignment = 8; 910aaba2545Smrg else if (tiling == I915_TILING_Y) 91120131375Smrg height_alignment = 32; 91220131375Smrg aligned_y = ALIGN(y, height_alignment); 913aaba2545Smrg 914aaba2545Smrg stride = x * cpp; 9156d98c517Smrg stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling_mode); 916aaba2545Smrg size = stride * aligned_y; 917aaba2545Smrg size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode); 918aaba2545Smrg } while (*tiling_mode != tiling); 91922944501Smrg *pitch = stride; 92022944501Smrg 9216d98c517Smrg if (tiling == I915_TILING_NONE) 9226d98c517Smrg stride = 0; 9236d98c517Smrg 9246d98c517Smrg return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags, 925fe517fc9Smrg tiling, stride, 0); 92622944501Smrg} 92722944501Smrg 928a884aba1Smrgstatic drm_intel_bo * 929a884aba1Smrgdrm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, 930a884aba1Smrg const char *name, 931a884aba1Smrg void *addr, 932a884aba1Smrg uint32_t tiling_mode, 933a884aba1Smrg uint32_t stride, 934a884aba1Smrg unsigned long size, 935a884aba1Smrg unsigned long flags) 936a884aba1Smrg{ 937a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 938a884aba1Smrg drm_intel_bo_gem *bo_gem; 939a884aba1Smrg int ret; 940a884aba1Smrg struct drm_i915_gem_userptr userptr; 941a884aba1Smrg 942a884aba1Smrg /* Tiling with userptr surfaces is not supported 943a884aba1Smrg * on all hardware so refuse it for time being. 944a884aba1Smrg */ 945a884aba1Smrg if (tiling_mode != I915_TILING_NONE) 946a884aba1Smrg return NULL; 947a884aba1Smrg 948a884aba1Smrg bo_gem = calloc(1, sizeof(*bo_gem)); 949a884aba1Smrg if (!bo_gem) 950a884aba1Smrg return NULL; 951a884aba1Smrg 9522ee35494Smrg atomic_set(&bo_gem->refcount, 1); 9532ee35494Smrg DRMINITLISTHEAD(&bo_gem->vma_list); 9542ee35494Smrg 955a884aba1Smrg bo_gem->bo.size = size; 956a884aba1Smrg 957424e9256Smrg memclear(userptr); 958a884aba1Smrg userptr.user_ptr = (__u64)((unsigned long)addr); 959a884aba1Smrg userptr.user_size = size; 960a884aba1Smrg userptr.flags = flags; 961a884aba1Smrg 962a884aba1Smrg ret = drmIoctl(bufmgr_gem->fd, 963a884aba1Smrg DRM_IOCTL_I915_GEM_USERPTR, 964a884aba1Smrg &userptr); 965a884aba1Smrg if (ret != 0) { 966a884aba1Smrg DBG("bo_create_userptr: " 967a884aba1Smrg "ioctl failed with user ptr %p size 0x%lx, " 968a884aba1Smrg "user flags 0x%lx\n", addr, size, flags); 969a884aba1Smrg free(bo_gem); 970a884aba1Smrg return NULL; 971a884aba1Smrg } 972a884aba1Smrg 9732ee35494Smrg pthread_mutex_lock(&bufmgr_gem->lock); 9742ee35494Smrg 975a884aba1Smrg bo_gem->gem_handle = userptr.handle; 976a884aba1Smrg bo_gem->bo.handle = bo_gem->gem_handle; 977a884aba1Smrg bo_gem->bo.bufmgr = bufmgr; 978a884aba1Smrg bo_gem->is_userptr = true; 979a884aba1Smrg bo_gem->bo.virtual = addr; 980a884aba1Smrg /* Save the address provided by user */ 981a884aba1Smrg bo_gem->user_virtual = addr; 982a884aba1Smrg bo_gem->tiling_mode = I915_TILING_NONE; 983a884aba1Smrg bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 984a884aba1Smrg bo_gem->stride = 0; 985a884aba1Smrg 9862ee35494Smrg HASH_ADD(handle_hh, bufmgr_gem->handle_table, 9872ee35494Smrg gem_handle, sizeof(bo_gem->gem_handle), 9882ee35494Smrg bo_gem); 989a884aba1Smrg 990a884aba1Smrg bo_gem->name = name; 991a884aba1Smrg bo_gem->validate_index = -1; 992a884aba1Smrg bo_gem->reloc_tree_fences = 0; 993a884aba1Smrg bo_gem->used_as_reloc_target = false; 994a884aba1Smrg bo_gem->has_error = false; 995a884aba1Smrg bo_gem->reusable = false; 996a884aba1Smrg 997fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 9982ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 999a884aba1Smrg 1000a884aba1Smrg DBG("bo_create_userptr: " 1001a884aba1Smrg "ptr %p buf %d (%s) size %ldb, stride 0x%x, tile mode %d\n", 1002a884aba1Smrg addr, bo_gem->gem_handle, bo_gem->name, 1003a884aba1Smrg size, stride, tiling_mode); 1004a884aba1Smrg 1005a884aba1Smrg return &bo_gem->bo; 1006a884aba1Smrg} 1007a884aba1Smrg 1008424e9256Smrgstatic bool 1009424e9256Smrghas_userptr(drm_intel_bufmgr_gem *bufmgr_gem) 1010424e9256Smrg{ 1011424e9256Smrg int ret; 1012424e9256Smrg void *ptr; 1013424e9256Smrg long pgsz; 1014424e9256Smrg struct drm_i915_gem_userptr userptr; 1015424e9256Smrg 1016424e9256Smrg pgsz = sysconf(_SC_PAGESIZE); 1017424e9256Smrg assert(pgsz > 0); 1018424e9256Smrg 1019424e9256Smrg ret = posix_memalign(&ptr, pgsz, pgsz); 1020424e9256Smrg if (ret) { 1021424e9256Smrg DBG("Failed to get a page (%ld) for userptr detection!\n", 1022424e9256Smrg pgsz); 1023424e9256Smrg return false; 1024424e9256Smrg } 1025424e9256Smrg 1026424e9256Smrg memclear(userptr); 1027424e9256Smrg userptr.user_ptr = (__u64)(unsigned long)ptr; 1028424e9256Smrg userptr.user_size = pgsz; 1029424e9256Smrg 1030424e9256Smrgretry: 1031424e9256Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr); 1032424e9256Smrg if (ret) { 1033424e9256Smrg if (errno == ENODEV && userptr.flags == 0) { 1034424e9256Smrg userptr.flags = I915_USERPTR_UNSYNCHRONIZED; 1035424e9256Smrg goto retry; 1036424e9256Smrg } 1037424e9256Smrg free(ptr); 1038424e9256Smrg return false; 1039424e9256Smrg } 1040424e9256Smrg 1041424e9256Smrg /* We don't release the userptr bo here as we want to keep the 1042424e9256Smrg * kernel mm tracking alive for our lifetime. The first time we 1043424e9256Smrg * create a userptr object the kernel has to install a mmu_notifer 1044424e9256Smrg * which is a heavyweight operation (e.g. it requires taking all 1045424e9256Smrg * mm_locks and stop_machine()). 1046424e9256Smrg */ 1047424e9256Smrg 1048424e9256Smrg bufmgr_gem->userptr_active.ptr = ptr; 1049424e9256Smrg bufmgr_gem->userptr_active.handle = userptr.handle; 1050424e9256Smrg 1051424e9256Smrg return true; 1052424e9256Smrg} 1053424e9256Smrg 1054424e9256Smrgstatic drm_intel_bo * 1055424e9256Smrgcheck_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, 1056424e9256Smrg const char *name, 1057424e9256Smrg void *addr, 1058424e9256Smrg uint32_t tiling_mode, 1059424e9256Smrg uint32_t stride, 1060424e9256Smrg unsigned long size, 1061424e9256Smrg unsigned long flags) 1062424e9256Smrg{ 1063424e9256Smrg if (has_userptr((drm_intel_bufmgr_gem *)bufmgr)) 1064424e9256Smrg bufmgr->bo_alloc_userptr = drm_intel_gem_bo_alloc_userptr; 1065424e9256Smrg else 1066424e9256Smrg bufmgr->bo_alloc_userptr = NULL; 1067424e9256Smrg 1068424e9256Smrg return drm_intel_bo_alloc_userptr(bufmgr, name, addr, 1069424e9256Smrg tiling_mode, stride, size, flags); 1070424e9256Smrg} 1071424e9256Smrg 107222944501Smrg/** 107322944501Smrg * Returns a drm_intel_bo wrapping the given buffer object handle. 107422944501Smrg * 107522944501Smrg * This can be used when one application needs to pass a buffer object 107622944501Smrg * to another. 107722944501Smrg */ 10786260e5d5Smrgdrm_public drm_intel_bo * 107922944501Smrgdrm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, 108022944501Smrg const char *name, 108122944501Smrg unsigned int handle) 108222944501Smrg{ 108322944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 108422944501Smrg drm_intel_bo_gem *bo_gem; 108522944501Smrg int ret; 108622944501Smrg struct drm_gem_open open_arg; 108722944501Smrg struct drm_i915_gem_get_tiling get_tiling; 108822944501Smrg 108920131375Smrg /* At the moment most applications only have a few named bo. 109020131375Smrg * For instance, in a DRI client only the render buffers passed 109120131375Smrg * between X and the client are named. And since X returns the 109220131375Smrg * alternating names for the front/back buffer a linear search 109320131375Smrg * provides a sufficiently fast match. 109420131375Smrg */ 1095a884aba1Smrg pthread_mutex_lock(&bufmgr_gem->lock); 10962ee35494Smrg HASH_FIND(name_hh, bufmgr_gem->name_table, 10972ee35494Smrg &handle, sizeof(handle), bo_gem); 10982ee35494Smrg if (bo_gem) { 10992ee35494Smrg drm_intel_gem_bo_reference(&bo_gem->bo); 11002ee35494Smrg goto out; 110120131375Smrg } 110222944501Smrg 1103424e9256Smrg memclear(open_arg); 110422944501Smrg open_arg.name = handle; 11056d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 11066d98c517Smrg DRM_IOCTL_GEM_OPEN, 11076d98c517Smrg &open_arg); 110822944501Smrg if (ret != 0) { 11099ce4edccSmrg DBG("Couldn't reference %s handle 0x%08x: %s\n", 11109ce4edccSmrg name, handle, strerror(errno)); 11112ee35494Smrg bo_gem = NULL; 11122ee35494Smrg goto out; 111322944501Smrg } 111420131375Smrg /* Now see if someone has used a prime handle to get this 111520131375Smrg * object from the kernel before by looking through the list 111620131375Smrg * again for a matching gem_handle 111720131375Smrg */ 11182ee35494Smrg HASH_FIND(handle_hh, bufmgr_gem->handle_table, 11192ee35494Smrg &open_arg.handle, sizeof(open_arg.handle), bo_gem); 11202ee35494Smrg if (bo_gem) { 11212ee35494Smrg drm_intel_gem_bo_reference(&bo_gem->bo); 11222ee35494Smrg goto out; 112320131375Smrg } 112420131375Smrg 112520131375Smrg bo_gem = calloc(1, sizeof(*bo_gem)); 11262ee35494Smrg if (!bo_gem) 11272ee35494Smrg goto out; 11282ee35494Smrg 11292ee35494Smrg atomic_set(&bo_gem->refcount, 1); 11302ee35494Smrg DRMINITLISTHEAD(&bo_gem->vma_list); 113120131375Smrg 113222944501Smrg bo_gem->bo.size = open_arg.size; 113322944501Smrg bo_gem->bo.offset = 0; 113420131375Smrg bo_gem->bo.offset64 = 0; 113522944501Smrg bo_gem->bo.virtual = NULL; 113622944501Smrg bo_gem->bo.bufmgr = bufmgr; 113722944501Smrg bo_gem->name = name; 113822944501Smrg bo_gem->validate_index = -1; 113922944501Smrg bo_gem->gem_handle = open_arg.handle; 114020131375Smrg bo_gem->bo.handle = open_arg.handle; 114122944501Smrg bo_gem->global_name = handle; 114220131375Smrg bo_gem->reusable = false; 114322944501Smrg 11442ee35494Smrg HASH_ADD(handle_hh, bufmgr_gem->handle_table, 11452ee35494Smrg gem_handle, sizeof(bo_gem->gem_handle), bo_gem); 11462ee35494Smrg HASH_ADD(name_hh, bufmgr_gem->name_table, 11472ee35494Smrg global_name, sizeof(bo_gem->global_name), bo_gem); 11482ee35494Smrg 1149424e9256Smrg memclear(get_tiling); 115022944501Smrg get_tiling.handle = bo_gem->gem_handle; 11516d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 11526d98c517Smrg DRM_IOCTL_I915_GEM_GET_TILING, 11536d98c517Smrg &get_tiling); 11542ee35494Smrg if (ret != 0) 11552ee35494Smrg goto err_unref; 11562ee35494Smrg 115722944501Smrg bo_gem->tiling_mode = get_tiling.tiling_mode; 115822944501Smrg bo_gem->swizzle_mode = get_tiling.swizzle_mode; 11596d98c517Smrg /* XXX stride is unknown */ 1160fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 116122944501Smrg DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name); 116222944501Smrg 11632ee35494Smrgout: 11642ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 116522944501Smrg return &bo_gem->bo; 11662ee35494Smrg 11672ee35494Smrgerr_unref: 11682ee35494Smrg drm_intel_gem_bo_free(&bo_gem->bo); 11692ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 11702ee35494Smrg return NULL; 117122944501Smrg} 117222944501Smrg 117322944501Smrgstatic void 117422944501Smrgdrm_intel_gem_bo_free(drm_intel_bo *bo) 117522944501Smrg{ 117622944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 117722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 117822944501Smrg struct drm_gem_close close; 117922944501Smrg int ret; 118022944501Smrg 118120131375Smrg DRMLISTDEL(&bo_gem->vma_list); 118220131375Smrg if (bo_gem->mem_virtual) { 118320131375Smrg VG(VALGRIND_FREELIKE_BLOCK(bo_gem->mem_virtual, 0)); 1184a884aba1Smrg drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size); 118520131375Smrg bufmgr_gem->vma_count--; 118620131375Smrg } 11872ee35494Smrg if (bo_gem->wc_virtual) { 11882ee35494Smrg VG(VALGRIND_FREELIKE_BLOCK(bo_gem->wc_virtual, 0)); 11892ee35494Smrg drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size); 11902ee35494Smrg bufmgr_gem->vma_count--; 11912ee35494Smrg } 119220131375Smrg if (bo_gem->gtt_virtual) { 1193a884aba1Smrg drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size); 119420131375Smrg bufmgr_gem->vma_count--; 119520131375Smrg } 119622944501Smrg 11972ee35494Smrg if (bo_gem->global_name) 11982ee35494Smrg HASH_DELETE(name_hh, bufmgr_gem->name_table, bo_gem); 11992ee35494Smrg HASH_DELETE(handle_hh, bufmgr_gem->handle_table, bo_gem); 12002ee35494Smrg 120122944501Smrg /* Close this object */ 1202424e9256Smrg memclear(close); 120322944501Smrg close.handle = bo_gem->gem_handle; 12046d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close); 120522944501Smrg if (ret != 0) { 12069ce4edccSmrg DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n", 12079ce4edccSmrg bo_gem->gem_handle, bo_gem->name, strerror(errno)); 120822944501Smrg } 120922944501Smrg free(bo); 121022944501Smrg} 121122944501Smrg 121220131375Smrgstatic void 121320131375Smrgdrm_intel_gem_bo_mark_mmaps_incoherent(drm_intel_bo *bo) 121420131375Smrg{ 121520131375Smrg#if HAVE_VALGRIND 121620131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 121720131375Smrg 121820131375Smrg if (bo_gem->mem_virtual) 121920131375Smrg VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size); 122020131375Smrg 12212ee35494Smrg if (bo_gem->wc_virtual) 12222ee35494Smrg VALGRIND_MAKE_MEM_NOACCESS(bo_gem->wc_virtual, bo->size); 12232ee35494Smrg 122420131375Smrg if (bo_gem->gtt_virtual) 122520131375Smrg VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size); 122620131375Smrg#endif 122720131375Smrg} 122820131375Smrg 122922944501Smrg/** Frees all cached buffers significantly older than @time. */ 123022944501Smrgstatic void 123122944501Smrgdrm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time) 123222944501Smrg{ 123322944501Smrg int i; 123422944501Smrg 12356d98c517Smrg if (bufmgr_gem->time == time) 12366d98c517Smrg return; 12376d98c517Smrg 1238aaba2545Smrg for (i = 0; i < bufmgr_gem->num_buckets; i++) { 123922944501Smrg struct drm_intel_gem_bo_bucket *bucket = 124022944501Smrg &bufmgr_gem->cache_bucket[i]; 124122944501Smrg 124222944501Smrg while (!DRMLISTEMPTY(&bucket->head)) { 124322944501Smrg drm_intel_bo_gem *bo_gem; 124422944501Smrg 124522944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 124622944501Smrg bucket->head.next, head); 124722944501Smrg if (time - bo_gem->free_time <= 1) 124822944501Smrg break; 124922944501Smrg 125022944501Smrg DRMLISTDEL(&bo_gem->head); 125122944501Smrg 125222944501Smrg drm_intel_gem_bo_free(&bo_gem->bo); 125322944501Smrg } 125422944501Smrg } 12556d98c517Smrg 12566d98c517Smrg bufmgr_gem->time = time; 125722944501Smrg} 125822944501Smrg 125920131375Smrgstatic void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem) 126020131375Smrg{ 126120131375Smrg int limit; 126220131375Smrg 126320131375Smrg DBG("%s: cached=%d, open=%d, limit=%d\n", __FUNCTION__, 126420131375Smrg bufmgr_gem->vma_count, bufmgr_gem->vma_open, bufmgr_gem->vma_max); 126520131375Smrg 126620131375Smrg if (bufmgr_gem->vma_max < 0) 126720131375Smrg return; 126820131375Smrg 126920131375Smrg /* We may need to evict a few entries in order to create new mmaps */ 127020131375Smrg limit = bufmgr_gem->vma_max - 2*bufmgr_gem->vma_open; 127120131375Smrg if (limit < 0) 127220131375Smrg limit = 0; 127320131375Smrg 127420131375Smrg while (bufmgr_gem->vma_count > limit) { 127520131375Smrg drm_intel_bo_gem *bo_gem; 127620131375Smrg 127720131375Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 127820131375Smrg bufmgr_gem->vma_cache.next, 127920131375Smrg vma_list); 128020131375Smrg assert(bo_gem->map_count == 0); 128120131375Smrg DRMLISTDELINIT(&bo_gem->vma_list); 128220131375Smrg 128320131375Smrg if (bo_gem->mem_virtual) { 1284a884aba1Smrg drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size); 128520131375Smrg bo_gem->mem_virtual = NULL; 128620131375Smrg bufmgr_gem->vma_count--; 128720131375Smrg } 12882ee35494Smrg if (bo_gem->wc_virtual) { 12892ee35494Smrg drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size); 12902ee35494Smrg bo_gem->wc_virtual = NULL; 12912ee35494Smrg bufmgr_gem->vma_count--; 12922ee35494Smrg } 129320131375Smrg if (bo_gem->gtt_virtual) { 1294a884aba1Smrg drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size); 129520131375Smrg bo_gem->gtt_virtual = NULL; 129620131375Smrg bufmgr_gem->vma_count--; 129720131375Smrg } 129820131375Smrg } 129920131375Smrg} 130020131375Smrg 130120131375Smrgstatic void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem, 130220131375Smrg drm_intel_bo_gem *bo_gem) 130320131375Smrg{ 130420131375Smrg bufmgr_gem->vma_open--; 130520131375Smrg DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache); 130620131375Smrg if (bo_gem->mem_virtual) 130720131375Smrg bufmgr_gem->vma_count++; 13082ee35494Smrg if (bo_gem->wc_virtual) 13092ee35494Smrg bufmgr_gem->vma_count++; 131020131375Smrg if (bo_gem->gtt_virtual) 131120131375Smrg bufmgr_gem->vma_count++; 131220131375Smrg drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); 131320131375Smrg} 131420131375Smrg 131520131375Smrgstatic void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem, 131620131375Smrg drm_intel_bo_gem *bo_gem) 131720131375Smrg{ 131820131375Smrg bufmgr_gem->vma_open++; 131920131375Smrg DRMLISTDEL(&bo_gem->vma_list); 132020131375Smrg if (bo_gem->mem_virtual) 132120131375Smrg bufmgr_gem->vma_count--; 13222ee35494Smrg if (bo_gem->wc_virtual) 13232ee35494Smrg bufmgr_gem->vma_count--; 132420131375Smrg if (bo_gem->gtt_virtual) 132520131375Smrg bufmgr_gem->vma_count--; 132620131375Smrg drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); 132720131375Smrg} 132820131375Smrg 132922944501Smrgstatic void 133022944501Smrgdrm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) 133122944501Smrg{ 133222944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 133322944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 133422944501Smrg struct drm_intel_gem_bo_bucket *bucket; 133522944501Smrg int i; 133622944501Smrg 133722944501Smrg /* Unreference all the target buffers */ 133822944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) { 1339aaba2545Smrg if (bo_gem->reloc_target_info[i].bo != bo) { 1340aaba2545Smrg drm_intel_gem_bo_unreference_locked_timed(bo_gem-> 1341aaba2545Smrg reloc_target_info[i].bo, 1342aaba2545Smrg time); 1343aaba2545Smrg } 134422944501Smrg } 1345fe517fc9Smrg for (i = 0; i < bo_gem->softpin_target_count; i++) 1346fe517fc9Smrg drm_intel_gem_bo_unreference_locked_timed(bo_gem->softpin_target[i], 1347fe517fc9Smrg time); 13482ee35494Smrg bo_gem->kflags = 0; 134922944501Smrg bo_gem->reloc_count = 0; 135020131375Smrg bo_gem->used_as_reloc_target = false; 1351fe517fc9Smrg bo_gem->softpin_target_count = 0; 135222944501Smrg 135322944501Smrg DBG("bo_unreference final: %d (%s)\n", 135422944501Smrg bo_gem->gem_handle, bo_gem->name); 135522944501Smrg 135622944501Smrg /* release memory associated with this object */ 135722944501Smrg if (bo_gem->reloc_target_info) { 135822944501Smrg free(bo_gem->reloc_target_info); 135922944501Smrg bo_gem->reloc_target_info = NULL; 136022944501Smrg } 136122944501Smrg if (bo_gem->relocs) { 136222944501Smrg free(bo_gem->relocs); 136322944501Smrg bo_gem->relocs = NULL; 136422944501Smrg } 1365fe517fc9Smrg if (bo_gem->softpin_target) { 1366fe517fc9Smrg free(bo_gem->softpin_target); 1367fe517fc9Smrg bo_gem->softpin_target = NULL; 1368fe517fc9Smrg bo_gem->softpin_target_size = 0; 1369fe517fc9Smrg } 137022944501Smrg 137120131375Smrg /* Clear any left-over mappings */ 137220131375Smrg if (bo_gem->map_count) { 137320131375Smrg DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count); 137420131375Smrg bo_gem->map_count = 0; 137520131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 137620131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 137720131375Smrg } 137820131375Smrg 137922944501Smrg bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size); 138022944501Smrg /* Put the buffer into our internal cache for reuse if we can. */ 138122944501Smrg if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL && 138222944501Smrg drm_intel_gem_bo_madvise_internal(bufmgr_gem, bo_gem, 138322944501Smrg I915_MADV_DONTNEED)) { 138422944501Smrg bo_gem->free_time = time; 138522944501Smrg 138622944501Smrg bo_gem->name = NULL; 138722944501Smrg bo_gem->validate_index = -1; 138822944501Smrg 138922944501Smrg DRMLISTADDTAIL(&bo_gem->head, &bucket->head); 139022944501Smrg } else { 139122944501Smrg drm_intel_gem_bo_free(bo); 139222944501Smrg } 139322944501Smrg} 139422944501Smrg 139522944501Smrgstatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, 139622944501Smrg time_t time) 139722944501Smrg{ 139822944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 139922944501Smrg 140022944501Smrg assert(atomic_read(&bo_gem->refcount) > 0); 140122944501Smrg if (atomic_dec_and_test(&bo_gem->refcount)) 140222944501Smrg drm_intel_gem_bo_unreference_final(bo, time); 140322944501Smrg} 140422944501Smrg 140522944501Smrgstatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo) 140622944501Smrg{ 140722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 140822944501Smrg 140922944501Smrg assert(atomic_read(&bo_gem->refcount) > 0); 1410a884aba1Smrg 1411a884aba1Smrg if (atomic_add_unless(&bo_gem->refcount, -1, 1)) { 141222944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = 141322944501Smrg (drm_intel_bufmgr_gem *) bo->bufmgr; 141422944501Smrg struct timespec time; 141522944501Smrg 141622944501Smrg clock_gettime(CLOCK_MONOTONIC, &time); 141722944501Smrg 141822944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 1419a884aba1Smrg 1420a884aba1Smrg if (atomic_dec_and_test(&bo_gem->refcount)) { 1421a884aba1Smrg drm_intel_gem_bo_unreference_final(bo, time.tv_sec); 1422a884aba1Smrg drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec); 1423a884aba1Smrg } 1424a884aba1Smrg 142522944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 142622944501Smrg } 142722944501Smrg} 142822944501Smrg 142922944501Smrgstatic int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable) 143022944501Smrg{ 143122944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 143222944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 143322944501Smrg struct drm_i915_gem_set_domain set_domain; 143422944501Smrg int ret; 143522944501Smrg 1436a884aba1Smrg if (bo_gem->is_userptr) { 1437a884aba1Smrg /* Return the same user ptr */ 1438a884aba1Smrg bo->virtual = bo_gem->user_virtual; 1439a884aba1Smrg return 0; 1440a884aba1Smrg } 1441a884aba1Smrg 144222944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 144322944501Smrg 144420131375Smrg if (bo_gem->map_count++ == 0) 144520131375Smrg drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 144620131375Smrg 144722944501Smrg if (!bo_gem->mem_virtual) { 144822944501Smrg struct drm_i915_gem_mmap mmap_arg; 144922944501Smrg 145020131375Smrg DBG("bo_map: %d (%s), map_count=%d\n", 145120131375Smrg bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 145222944501Smrg 1453424e9256Smrg memclear(mmap_arg); 145422944501Smrg mmap_arg.handle = bo_gem->gem_handle; 145522944501Smrg mmap_arg.size = bo->size; 14566d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 14576d98c517Smrg DRM_IOCTL_I915_GEM_MMAP, 14586d98c517Smrg &mmap_arg); 145922944501Smrg if (ret != 0) { 146022944501Smrg ret = -errno; 14619ce4edccSmrg DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 14629ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, 14639ce4edccSmrg bo_gem->name, strerror(errno)); 146420131375Smrg if (--bo_gem->map_count == 0) 146520131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 146622944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 146722944501Smrg return ret; 146822944501Smrg } 146920131375Smrg VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1)); 147022944501Smrg bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr; 147122944501Smrg } 147222944501Smrg DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, 147322944501Smrg bo_gem->mem_virtual); 147422944501Smrg bo->virtual = bo_gem->mem_virtual; 147522944501Smrg 1476424e9256Smrg memclear(set_domain); 147722944501Smrg set_domain.handle = bo_gem->gem_handle; 147822944501Smrg set_domain.read_domains = I915_GEM_DOMAIN_CPU; 147922944501Smrg if (write_enable) 148022944501Smrg set_domain.write_domain = I915_GEM_DOMAIN_CPU; 148122944501Smrg else 148222944501Smrg set_domain.write_domain = 0; 14836d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 14846d98c517Smrg DRM_IOCTL_I915_GEM_SET_DOMAIN, 14856d98c517Smrg &set_domain); 148622944501Smrg if (ret != 0) { 14879ce4edccSmrg DBG("%s:%d: Error setting to CPU domain %d: %s\n", 14889ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, 14899ce4edccSmrg strerror(errno)); 149022944501Smrg } 149122944501Smrg 149220131375Smrg if (write_enable) 149320131375Smrg bo_gem->mapped_cpu_write = true; 149420131375Smrg 149520131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 149620131375Smrg VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->mem_virtual, bo->size)); 149722944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 149822944501Smrg 149922944501Smrg return 0; 150022944501Smrg} 150122944501Smrg 150220131375Smrgstatic int 150320131375Smrgmap_gtt(drm_intel_bo *bo) 150422944501Smrg{ 150522944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 150622944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 150722944501Smrg int ret; 150822944501Smrg 1509a884aba1Smrg if (bo_gem->is_userptr) 1510a884aba1Smrg return -EINVAL; 1511a884aba1Smrg 151220131375Smrg if (bo_gem->map_count++ == 0) 151320131375Smrg drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 151422944501Smrg 151522944501Smrg /* Get a mapping of the buffer if we haven't before. */ 151622944501Smrg if (bo_gem->gtt_virtual == NULL) { 151722944501Smrg struct drm_i915_gem_mmap_gtt mmap_arg; 151822944501Smrg 151920131375Smrg DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n", 152020131375Smrg bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 152122944501Smrg 1522424e9256Smrg memclear(mmap_arg); 152322944501Smrg mmap_arg.handle = bo_gem->gem_handle; 152422944501Smrg 152522944501Smrg /* Get the fake offset back... */ 15266d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 15276d98c517Smrg DRM_IOCTL_I915_GEM_MMAP_GTT, 15286d98c517Smrg &mmap_arg); 152922944501Smrg if (ret != 0) { 153022944501Smrg ret = -errno; 15319ce4edccSmrg DBG("%s:%d: Error preparing buffer map %d (%s): %s .\n", 15329ce4edccSmrg __FILE__, __LINE__, 15339ce4edccSmrg bo_gem->gem_handle, bo_gem->name, 15349ce4edccSmrg strerror(errno)); 153520131375Smrg if (--bo_gem->map_count == 0) 153620131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 153722944501Smrg return ret; 153822944501Smrg } 153922944501Smrg 154022944501Smrg /* and mmap it */ 1541fd815b59Smaya bo_gem->gtt_virtual = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, 1542fd815b59Smaya MAP_SHARED, bufmgr_gem->fd, 1543fd815b59Smaya mmap_arg.offset); 1544d6e8b34dStnn if (bo_gem->gtt_virtual == MAP_FAILED) { 154522944501Smrg bo_gem->gtt_virtual = NULL; 1546d6e8b34dStnn ret = -errno; 15479ce4edccSmrg DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 15489ce4edccSmrg __FILE__, __LINE__, 15499ce4edccSmrg bo_gem->gem_handle, bo_gem->name, 15509ce4edccSmrg strerror(errno)); 155120131375Smrg if (--bo_gem->map_count == 0) 155220131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 155322944501Smrg return ret; 155422944501Smrg } 155522944501Smrg } 155622944501Smrg 155722944501Smrg bo->virtual = bo_gem->gtt_virtual; 155822944501Smrg 155922944501Smrg DBG("bo_map_gtt: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, 156022944501Smrg bo_gem->gtt_virtual); 156122944501Smrg 156220131375Smrg return 0; 156320131375Smrg} 156420131375Smrg 15656260e5d5Smrgdrm_public int 1566a884aba1Smrgdrm_intel_gem_bo_map_gtt(drm_intel_bo *bo) 156720131375Smrg{ 156820131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 156920131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 157020131375Smrg struct drm_i915_gem_set_domain set_domain; 157120131375Smrg int ret; 157220131375Smrg 157320131375Smrg pthread_mutex_lock(&bufmgr_gem->lock); 157420131375Smrg 157520131375Smrg ret = map_gtt(bo); 157620131375Smrg if (ret) { 157720131375Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 157820131375Smrg return ret; 157920131375Smrg } 158020131375Smrg 158120131375Smrg /* Now move it to the GTT domain so that the GPU and CPU 158220131375Smrg * caches are flushed and the GPU isn't actively using the 158320131375Smrg * buffer. 158420131375Smrg * 158520131375Smrg * The pagefault handler does this domain change for us when 158620131375Smrg * it has unbound the BO from the GTT, but it's up to us to 158720131375Smrg * tell it when we're about to use things if we had done 158820131375Smrg * rendering and it still happens to be bound to the GTT. 158920131375Smrg */ 1590424e9256Smrg memclear(set_domain); 159122944501Smrg set_domain.handle = bo_gem->gem_handle; 159222944501Smrg set_domain.read_domains = I915_GEM_DOMAIN_GTT; 159322944501Smrg set_domain.write_domain = I915_GEM_DOMAIN_GTT; 15946d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 15956d98c517Smrg DRM_IOCTL_I915_GEM_SET_DOMAIN, 15966d98c517Smrg &set_domain); 159722944501Smrg if (ret != 0) { 15989ce4edccSmrg DBG("%s:%d: Error setting domain %d: %s\n", 15999ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, 16009ce4edccSmrg strerror(errno)); 160122944501Smrg } 160222944501Smrg 160320131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 160420131375Smrg VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size)); 160522944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 160622944501Smrg 16076d98c517Smrg return 0; 160822944501Smrg} 160922944501Smrg 161020131375Smrg/** 161120131375Smrg * Performs a mapping of the buffer object like the normal GTT 161220131375Smrg * mapping, but avoids waiting for the GPU to be done reading from or 161320131375Smrg * rendering to the buffer. 161420131375Smrg * 161520131375Smrg * This is used in the implementation of GL_ARB_map_buffer_range: The 161620131375Smrg * user asks to create a buffer, then does a mapping, fills some 161720131375Smrg * space, runs a drawing command, then asks to map it again without 161820131375Smrg * synchronizing because it guarantees that it won't write over the 161920131375Smrg * data that the GPU is busy using (or, more specifically, that if it 162020131375Smrg * does write over the data, it acknowledges that rendering is 162120131375Smrg * undefined). 162220131375Smrg */ 162320131375Smrg 16246260e5d5Smrgdrm_public int 1625a884aba1Smrgdrm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo) 162622944501Smrg{ 162722944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 16282b90624aSmrg#if HAVE_VALGRIND 162920131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 163020131375Smrg#endif 163120131375Smrg int ret; 163222944501Smrg 163320131375Smrg /* If the CPU cache isn't coherent with the GTT, then use a 163420131375Smrg * regular synchronized mapping. The problem is that we don't 163520131375Smrg * track where the buffer was last used on the CPU side in 163620131375Smrg * terms of drm_intel_bo_map vs drm_intel_gem_bo_map_gtt, so 163720131375Smrg * we would potentially corrupt the buffer even when the user 163820131375Smrg * does reasonable things. 163920131375Smrg */ 164020131375Smrg if (!bufmgr_gem->has_llc) 164120131375Smrg return drm_intel_gem_bo_map_gtt(bo); 164222944501Smrg 164322944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 164420131375Smrg 164520131375Smrg ret = map_gtt(bo); 164620131375Smrg if (ret == 0) { 164720131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 164820131375Smrg VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size)); 164920131375Smrg } 165020131375Smrg 165122944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 165222944501Smrg 165322944501Smrg return ret; 165422944501Smrg} 165522944501Smrg 165622944501Smrgstatic int drm_intel_gem_bo_unmap(drm_intel_bo *bo) 165722944501Smrg{ 1658a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem; 165922944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 166020131375Smrg int ret = 0; 166122944501Smrg 166222944501Smrg if (bo == NULL) 166322944501Smrg return 0; 166422944501Smrg 1665a884aba1Smrg if (bo_gem->is_userptr) 1666a884aba1Smrg return 0; 1667a884aba1Smrg 1668a884aba1Smrg bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1669a884aba1Smrg 167022944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 167122944501Smrg 167220131375Smrg if (bo_gem->map_count <= 0) { 167320131375Smrg DBG("attempted to unmap an unmapped bo\n"); 167420131375Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 167520131375Smrg /* Preserve the old behaviour of just treating this as a 167620131375Smrg * no-op rather than reporting the error. 167720131375Smrg */ 167820131375Smrg return 0; 167920131375Smrg } 168020131375Smrg 168120131375Smrg if (bo_gem->mapped_cpu_write) { 168220131375Smrg struct drm_i915_gem_sw_finish sw_finish; 168320131375Smrg 168420131375Smrg /* Cause a flush to happen if the buffer's pinned for 168520131375Smrg * scanout, so the results show up in a timely manner. 168620131375Smrg * Unlike GTT set domains, this only does work if the 168720131375Smrg * buffer should be scanout-related. 168820131375Smrg */ 1689424e9256Smrg memclear(sw_finish); 169020131375Smrg sw_finish.handle = bo_gem->gem_handle; 169120131375Smrg ret = drmIoctl(bufmgr_gem->fd, 169220131375Smrg DRM_IOCTL_I915_GEM_SW_FINISH, 169320131375Smrg &sw_finish); 169420131375Smrg ret = ret == -1 ? -errno : 0; 169520131375Smrg 169620131375Smrg bo_gem->mapped_cpu_write = false; 169720131375Smrg } 169822944501Smrg 169920131375Smrg /* We need to unmap after every innovation as we cannot track 17002ee35494Smrg * an open vma for every bo as that will exhaust the system 170120131375Smrg * limits and cause later failures. 170220131375Smrg */ 170320131375Smrg if (--bo_gem->map_count == 0) { 170420131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 170520131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 170620131375Smrg bo->virtual = NULL; 170720131375Smrg } 170822944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 170922944501Smrg 171022944501Smrg return ret; 171122944501Smrg} 171222944501Smrg 17136260e5d5Smrgdrm_public int 1714a884aba1Smrgdrm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo) 171520131375Smrg{ 171620131375Smrg return drm_intel_gem_bo_unmap(bo); 171720131375Smrg} 171820131375Smrg 171922944501Smrgstatic int 172022944501Smrgdrm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset, 172122944501Smrg unsigned long size, const void *data) 172222944501Smrg{ 172322944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 172422944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 172522944501Smrg struct drm_i915_gem_pwrite pwrite; 172622944501Smrg int ret; 172722944501Smrg 1728a884aba1Smrg if (bo_gem->is_userptr) 1729a884aba1Smrg return -EINVAL; 1730a884aba1Smrg 1731424e9256Smrg memclear(pwrite); 173222944501Smrg pwrite.handle = bo_gem->gem_handle; 173322944501Smrg pwrite.offset = offset; 173422944501Smrg pwrite.size = size; 173522944501Smrg pwrite.data_ptr = (uint64_t) (uintptr_t) data; 17366d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 17376d98c517Smrg DRM_IOCTL_I915_GEM_PWRITE, 17386d98c517Smrg &pwrite); 173922944501Smrg if (ret != 0) { 174022944501Smrg ret = -errno; 17419ce4edccSmrg DBG("%s:%d: Error writing data to buffer %d: (%d %d) %s .\n", 17429ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, (int)offset, 17439ce4edccSmrg (int)size, strerror(errno)); 174422944501Smrg } 174522944501Smrg 174622944501Smrg return ret; 174722944501Smrg} 174822944501Smrg 174922944501Smrgstatic int 175022944501Smrgdrm_intel_gem_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id) 175122944501Smrg{ 175222944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 175322944501Smrg struct drm_i915_get_pipe_from_crtc_id get_pipe_from_crtc_id; 175422944501Smrg int ret; 175522944501Smrg 1756424e9256Smrg memclear(get_pipe_from_crtc_id); 175722944501Smrg get_pipe_from_crtc_id.crtc_id = crtc_id; 17586d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 17596d98c517Smrg DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID, 17606d98c517Smrg &get_pipe_from_crtc_id); 176122944501Smrg if (ret != 0) { 176222944501Smrg /* We return -1 here to signal that we don't 176322944501Smrg * know which pipe is associated with this crtc. 176422944501Smrg * This lets the caller know that this information 176522944501Smrg * isn't available; using the wrong pipe for 176622944501Smrg * vblank waiting can cause the chipset to lock up 176722944501Smrg */ 176822944501Smrg return -1; 176922944501Smrg } 177022944501Smrg 177122944501Smrg return get_pipe_from_crtc_id.pipe; 177222944501Smrg} 177322944501Smrg 177422944501Smrgstatic int 177522944501Smrgdrm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, 177622944501Smrg unsigned long size, void *data) 177722944501Smrg{ 177822944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 177922944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 178022944501Smrg struct drm_i915_gem_pread pread; 178122944501Smrg int ret; 178222944501Smrg 1783a884aba1Smrg if (bo_gem->is_userptr) 1784a884aba1Smrg return -EINVAL; 1785a884aba1Smrg 1786424e9256Smrg memclear(pread); 178722944501Smrg pread.handle = bo_gem->gem_handle; 178822944501Smrg pread.offset = offset; 178922944501Smrg pread.size = size; 179022944501Smrg pread.data_ptr = (uint64_t) (uintptr_t) data; 17916d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 17926d98c517Smrg DRM_IOCTL_I915_GEM_PREAD, 17936d98c517Smrg &pread); 179422944501Smrg if (ret != 0) { 179522944501Smrg ret = -errno; 17969ce4edccSmrg DBG("%s:%d: Error reading data from buffer %d: (%d %d) %s .\n", 17979ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, (int)offset, 17989ce4edccSmrg (int)size, strerror(errno)); 179922944501Smrg } 180022944501Smrg 180122944501Smrg return ret; 180222944501Smrg} 180322944501Smrg 18049ce4edccSmrg/** Waits for all GPU rendering with the object to have completed. */ 180522944501Smrgstatic void 180622944501Smrgdrm_intel_gem_bo_wait_rendering(drm_intel_bo *bo) 180722944501Smrg{ 18089ce4edccSmrg drm_intel_gem_bo_start_gtt_access(bo, 1); 180922944501Smrg} 181022944501Smrg 181120131375Smrg/** 181220131375Smrg * Waits on a BO for the given amount of time. 181320131375Smrg * 181420131375Smrg * @bo: buffer object to wait for 181520131375Smrg * @timeout_ns: amount of time to wait in nanoseconds. 181620131375Smrg * If value is less than 0, an infinite wait will occur. 181720131375Smrg * 181820131375Smrg * Returns 0 if the wait was successful ie. the last batch referencing the 181920131375Smrg * object has completed within the allotted time. Otherwise some negative return 182020131375Smrg * value describes the error. Of particular interest is -ETIME when the wait has 182120131375Smrg * failed to yield the desired result. 182220131375Smrg * 182320131375Smrg * Similar to drm_intel_gem_bo_wait_rendering except a timeout parameter allows 182420131375Smrg * the operation to give up after a certain amount of time. Another subtle 182520131375Smrg * difference is the internal locking semantics are different (this variant does 182620131375Smrg * not hold the lock for the duration of the wait). This makes the wait subject 182720131375Smrg * to a larger userspace race window. 182820131375Smrg * 182920131375Smrg * The implementation shall wait until the object is no longer actively 183020131375Smrg * referenced within a batch buffer at the time of the call. The wait will 183120131375Smrg * not guarantee that the buffer is re-issued via another thread, or an flinked 183220131375Smrg * handle. Userspace must make sure this race does not occur if such precision 183320131375Smrg * is important. 1834424e9256Smrg * 1835424e9256Smrg * Note that some kernels have broken the inifite wait for negative values 1836424e9256Smrg * promise, upgrade to latest stable kernels if this is the case. 183720131375Smrg */ 18386260e5d5Smrgdrm_public int 1839a884aba1Smrgdrm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns) 184020131375Smrg{ 184120131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 184220131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 184320131375Smrg struct drm_i915_gem_wait wait; 184420131375Smrg int ret; 184520131375Smrg 184620131375Smrg if (!bufmgr_gem->has_wait_timeout) { 184720131375Smrg DBG("%s:%d: Timed wait is not supported. Falling back to " 184820131375Smrg "infinite wait\n", __FILE__, __LINE__); 184920131375Smrg if (timeout_ns) { 185020131375Smrg drm_intel_gem_bo_wait_rendering(bo); 185120131375Smrg return 0; 185220131375Smrg } else { 185320131375Smrg return drm_intel_gem_bo_busy(bo) ? -ETIME : 0; 185420131375Smrg } 185520131375Smrg } 185620131375Smrg 1857424e9256Smrg memclear(wait); 185820131375Smrg wait.bo_handle = bo_gem->gem_handle; 185920131375Smrg wait.timeout_ns = timeout_ns; 186020131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait); 186120131375Smrg if (ret == -1) 186220131375Smrg return -errno; 186320131375Smrg 186420131375Smrg return ret; 186520131375Smrg} 186620131375Smrg 186722944501Smrg/** 186822944501Smrg * Sets the object to the GTT read and possibly write domain, used by the X 186922944501Smrg * 2D driver in the absence of kernel support to do drm_intel_gem_bo_map_gtt(). 187022944501Smrg * 187122944501Smrg * In combination with drm_intel_gem_bo_pin() and manual fence management, we 187222944501Smrg * can do tiled pixmaps this way. 187322944501Smrg */ 18746260e5d5Smrgdrm_public void 187522944501Smrgdrm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable) 187622944501Smrg{ 187722944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 187822944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 187922944501Smrg struct drm_i915_gem_set_domain set_domain; 188022944501Smrg int ret; 188122944501Smrg 1882424e9256Smrg memclear(set_domain); 188322944501Smrg set_domain.handle = bo_gem->gem_handle; 188422944501Smrg set_domain.read_domains = I915_GEM_DOMAIN_GTT; 188522944501Smrg set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_GTT : 0; 18866d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 18876d98c517Smrg DRM_IOCTL_I915_GEM_SET_DOMAIN, 18886d98c517Smrg &set_domain); 188922944501Smrg if (ret != 0) { 18909ce4edccSmrg DBG("%s:%d: Error setting memory domains %d (%08x %08x): %s .\n", 18919ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, 18929ce4edccSmrg set_domain.read_domains, set_domain.write_domain, 18939ce4edccSmrg strerror(errno)); 189422944501Smrg } 189522944501Smrg} 189622944501Smrg 189722944501Smrgstatic void 189822944501Smrgdrm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr) 189922944501Smrg{ 190022944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 1901424e9256Smrg struct drm_gem_close close_bo; 1902424e9256Smrg int i, ret; 190322944501Smrg 190422944501Smrg free(bufmgr_gem->exec2_objects); 190522944501Smrg free(bufmgr_gem->exec_objects); 190622944501Smrg free(bufmgr_gem->exec_bos); 190722944501Smrg 190822944501Smrg pthread_mutex_destroy(&bufmgr_gem->lock); 190922944501Smrg 191022944501Smrg /* Free any cached buffer objects we were going to reuse */ 1911aaba2545Smrg for (i = 0; i < bufmgr_gem->num_buckets; i++) { 191222944501Smrg struct drm_intel_gem_bo_bucket *bucket = 191322944501Smrg &bufmgr_gem->cache_bucket[i]; 191422944501Smrg drm_intel_bo_gem *bo_gem; 191522944501Smrg 191622944501Smrg while (!DRMLISTEMPTY(&bucket->head)) { 191722944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 191822944501Smrg bucket->head.next, head); 191922944501Smrg DRMLISTDEL(&bo_gem->head); 192022944501Smrg 192122944501Smrg drm_intel_gem_bo_free(&bo_gem->bo); 192222944501Smrg } 192322944501Smrg } 192422944501Smrg 1925424e9256Smrg /* Release userptr bo kept hanging around for optimisation. */ 1926424e9256Smrg if (bufmgr_gem->userptr_active.ptr) { 1927424e9256Smrg memclear(close_bo); 1928424e9256Smrg close_bo.handle = bufmgr_gem->userptr_active.handle; 1929424e9256Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close_bo); 1930424e9256Smrg free(bufmgr_gem->userptr_active.ptr); 1931424e9256Smrg if (ret) 1932424e9256Smrg fprintf(stderr, 1933424e9256Smrg "Failed to release test userptr object! (%d) " 1934424e9256Smrg "i915 kernel driver may not be sane!\n", errno); 1935424e9256Smrg } 1936424e9256Smrg 193722944501Smrg free(bufmgr); 193822944501Smrg} 193922944501Smrg 194022944501Smrg/** 194122944501Smrg * Adds the target buffer to the validation list and adds the relocation 194222944501Smrg * to the reloc_buffer's relocation list. 194322944501Smrg * 194422944501Smrg * The relocation entry at the given offset must already contain the 194522944501Smrg * precomputed relocation value, because the kernel will optimize out 194622944501Smrg * the relocation entry write when the buffer hasn't moved from the 194722944501Smrg * last known offset in target_bo. 194822944501Smrg */ 194922944501Smrgstatic int 195022944501Smrgdo_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, 195122944501Smrg drm_intel_bo *target_bo, uint32_t target_offset, 195222944501Smrg uint32_t read_domains, uint32_t write_domain, 195320131375Smrg bool need_fence) 195422944501Smrg{ 195522944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 195622944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 195722944501Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; 195820131375Smrg bool fenced_command; 195922944501Smrg 196022944501Smrg if (bo_gem->has_error) 196122944501Smrg return -ENOMEM; 196222944501Smrg 196322944501Smrg if (target_bo_gem->has_error) { 196420131375Smrg bo_gem->has_error = true; 196522944501Smrg return -ENOMEM; 196622944501Smrg } 196722944501Smrg 196822944501Smrg /* We never use HW fences for rendering on 965+ */ 196922944501Smrg if (bufmgr_gem->gen >= 4) 197020131375Smrg need_fence = false; 197122944501Smrg 19729ce4edccSmrg fenced_command = need_fence; 19739ce4edccSmrg if (target_bo_gem->tiling_mode == I915_TILING_NONE) 197420131375Smrg need_fence = false; 19759ce4edccSmrg 197622944501Smrg /* Create a new relocation list if needed */ 197722944501Smrg if (bo_gem->relocs == NULL && drm_intel_setup_reloc_list(bo)) 197822944501Smrg return -ENOMEM; 197922944501Smrg 198022944501Smrg /* Check overflow */ 198122944501Smrg assert(bo_gem->reloc_count < bufmgr_gem->max_relocs); 198222944501Smrg 198322944501Smrg /* Check args */ 198422944501Smrg assert(offset <= bo->size - 4); 198522944501Smrg assert((write_domain & (write_domain - 1)) == 0); 198622944501Smrg 19873c748557Ssnj /* An object needing a fence is a tiled buffer, so it won't have 19883c748557Ssnj * relocs to other buffers. 19893c748557Ssnj */ 19903c748557Ssnj if (need_fence) { 19913c748557Ssnj assert(target_bo_gem->reloc_count == 0); 19923c748557Ssnj target_bo_gem->reloc_tree_fences = 1; 19933c748557Ssnj } 19943c748557Ssnj 199522944501Smrg /* Make sure that we're not adding a reloc to something whose size has 199622944501Smrg * already been accounted for. 199722944501Smrg */ 199822944501Smrg assert(!bo_gem->used_as_reloc_target); 1999aaba2545Smrg if (target_bo_gem != bo_gem) { 200020131375Smrg target_bo_gem->used_as_reloc_target = true; 2001aaba2545Smrg bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size; 20023c748557Ssnj bo_gem->reloc_tree_fences += target_bo_gem->reloc_tree_fences; 2003aaba2545Smrg } 200422944501Smrg 200522944501Smrg bo_gem->reloc_target_info[bo_gem->reloc_count].bo = target_bo; 2006aaba2545Smrg if (target_bo != bo) 2007aaba2545Smrg drm_intel_gem_bo_reference(target_bo); 20089ce4edccSmrg if (fenced_command) 200922944501Smrg bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 201022944501Smrg DRM_INTEL_RELOC_FENCE; 201122944501Smrg else 201222944501Smrg bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 0; 201322944501Smrg 2014fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].offset = offset; 2015fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].delta = target_offset; 2016fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].target_handle = 2017fe517fc9Smrg target_bo_gem->gem_handle; 2018fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains; 2019fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain; 2020fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset64; 202122944501Smrg bo_gem->reloc_count++; 202222944501Smrg 202322944501Smrg return 0; 202422944501Smrg} 202522944501Smrg 2026fe517fc9Smrgstatic void 2027fe517fc9Smrgdrm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable) 2028fe517fc9Smrg{ 2029fe517fc9Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 20300655efefSmrg 20310655efefSmrg if (enable) 20320655efefSmrg bo_gem->kflags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; 20330655efefSmrg else 20340655efefSmrg bo_gem->kflags &= ~EXEC_OBJECT_SUPPORTS_48B_ADDRESS; 2035fe517fc9Smrg} 2036fe517fc9Smrg 2037fe517fc9Smrgstatic int 2038fe517fc9Smrgdrm_intel_gem_bo_add_softpin_target(drm_intel_bo *bo, drm_intel_bo *target_bo) 2039fe517fc9Smrg{ 2040fe517fc9Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2041fe517fc9Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2042fe517fc9Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; 2043fe517fc9Smrg if (bo_gem->has_error) 2044fe517fc9Smrg return -ENOMEM; 2045fe517fc9Smrg 2046fe517fc9Smrg if (target_bo_gem->has_error) { 2047fe517fc9Smrg bo_gem->has_error = true; 2048fe517fc9Smrg return -ENOMEM; 2049fe517fc9Smrg } 2050fe517fc9Smrg 20510655efefSmrg if (!(target_bo_gem->kflags & EXEC_OBJECT_PINNED)) 2052fe517fc9Smrg return -EINVAL; 2053fe517fc9Smrg if (target_bo_gem == bo_gem) 2054fe517fc9Smrg return -EINVAL; 2055fe517fc9Smrg 2056fe517fc9Smrg if (bo_gem->softpin_target_count == bo_gem->softpin_target_size) { 2057fe517fc9Smrg int new_size = bo_gem->softpin_target_size * 2; 2058fe517fc9Smrg if (new_size == 0) 2059fe517fc9Smrg new_size = bufmgr_gem->max_relocs; 2060fe517fc9Smrg 2061fe517fc9Smrg bo_gem->softpin_target = realloc(bo_gem->softpin_target, new_size * 2062fe517fc9Smrg sizeof(drm_intel_bo *)); 2063fe517fc9Smrg if (!bo_gem->softpin_target) 2064fe517fc9Smrg return -ENOMEM; 2065fe517fc9Smrg 2066fe517fc9Smrg bo_gem->softpin_target_size = new_size; 2067fe517fc9Smrg } 2068fe517fc9Smrg bo_gem->softpin_target[bo_gem->softpin_target_count] = target_bo; 2069fe517fc9Smrg drm_intel_gem_bo_reference(target_bo); 2070fe517fc9Smrg bo_gem->softpin_target_count++; 2071fe517fc9Smrg 2072fe517fc9Smrg return 0; 2073fe517fc9Smrg} 2074fe517fc9Smrg 207522944501Smrgstatic int 207622944501Smrgdrm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, 207722944501Smrg drm_intel_bo *target_bo, uint32_t target_offset, 207822944501Smrg uint32_t read_domains, uint32_t write_domain) 207922944501Smrg{ 208022944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; 2081fe517fc9Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo; 208222944501Smrg 20830655efefSmrg if (target_bo_gem->kflags & EXEC_OBJECT_PINNED) 2084fe517fc9Smrg return drm_intel_gem_bo_add_softpin_target(bo, target_bo); 2085fe517fc9Smrg else 2086fe517fc9Smrg return do_bo_emit_reloc(bo, offset, target_bo, target_offset, 2087fe517fc9Smrg read_domains, write_domain, 2088fe517fc9Smrg !bufmgr_gem->fenced_relocs); 208922944501Smrg} 209022944501Smrg 209122944501Smrgstatic int 209222944501Smrgdrm_intel_gem_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset, 209322944501Smrg drm_intel_bo *target_bo, 209422944501Smrg uint32_t target_offset, 209522944501Smrg uint32_t read_domains, uint32_t write_domain) 209622944501Smrg{ 209722944501Smrg return do_bo_emit_reloc(bo, offset, target_bo, target_offset, 209820131375Smrg read_domains, write_domain, true); 209920131375Smrg} 210020131375Smrg 21016260e5d5Smrgdrm_public int 210220131375Smrgdrm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo) 210320131375Smrg{ 210420131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 210520131375Smrg 210620131375Smrg return bo_gem->reloc_count; 210720131375Smrg} 210820131375Smrg 210920131375Smrg/** 211020131375Smrg * Removes existing relocation entries in the BO after "start". 211120131375Smrg * 211220131375Smrg * This allows a user to avoid a two-step process for state setup with 211320131375Smrg * counting up all the buffer objects and doing a 211420131375Smrg * drm_intel_bufmgr_check_aperture_space() before emitting any of the 211520131375Smrg * relocations for the state setup. Instead, save the state of the 211620131375Smrg * batchbuffer including drm_intel_gem_get_reloc_count(), emit all the 211720131375Smrg * state, and then check if it still fits in the aperture. 211820131375Smrg * 211920131375Smrg * Any further drm_intel_bufmgr_check_aperture_space() queries 212020131375Smrg * involving this buffer in the tree are undefined after this call. 2121fe517fc9Smrg * 2122fe517fc9Smrg * This also removes all softpinned targets being referenced by the BO. 212320131375Smrg */ 21246260e5d5Smrgdrm_public void 212520131375Smrgdrm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start) 212620131375Smrg{ 2127a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 212820131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 212920131375Smrg int i; 213020131375Smrg struct timespec time; 213120131375Smrg 213220131375Smrg clock_gettime(CLOCK_MONOTONIC, &time); 213320131375Smrg 213420131375Smrg assert(bo_gem->reloc_count >= start); 2135a884aba1Smrg 213620131375Smrg /* Unreference the cleared target buffers */ 2137a884aba1Smrg pthread_mutex_lock(&bufmgr_gem->lock); 2138a884aba1Smrg 213920131375Smrg for (i = start; i < bo_gem->reloc_count; i++) { 214020131375Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->reloc_target_info[i].bo; 214120131375Smrg if (&target_bo_gem->bo != bo) { 214220131375Smrg bo_gem->reloc_tree_fences -= target_bo_gem->reloc_tree_fences; 214320131375Smrg drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, 214420131375Smrg time.tv_sec); 214520131375Smrg } 214620131375Smrg } 214720131375Smrg bo_gem->reloc_count = start; 2148a884aba1Smrg 2149fe517fc9Smrg for (i = 0; i < bo_gem->softpin_target_count; i++) { 2150fe517fc9Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->softpin_target[i]; 2151fe517fc9Smrg drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, time.tv_sec); 2152fe517fc9Smrg } 2153fe517fc9Smrg bo_gem->softpin_target_count = 0; 2154fe517fc9Smrg 2155a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 2156a884aba1Smrg 215722944501Smrg} 215822944501Smrg 215922944501Smrg/** 216022944501Smrg * Walk the tree of relocations rooted at BO and accumulate the list of 216122944501Smrg * validations to be performed and update the relocation buffers with 216222944501Smrg * index values into the validation list. 216322944501Smrg */ 216422944501Smrgstatic void 216522944501Smrgdrm_intel_gem_bo_process_reloc(drm_intel_bo *bo) 216622944501Smrg{ 216722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 216822944501Smrg int i; 216922944501Smrg 217022944501Smrg if (bo_gem->relocs == NULL) 217122944501Smrg return; 217222944501Smrg 217322944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) { 217422944501Smrg drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo; 217522944501Smrg 2176aaba2545Smrg if (target_bo == bo) 2177aaba2545Smrg continue; 2178aaba2545Smrg 217920131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 218020131375Smrg 218122944501Smrg /* Continue walking the tree depth-first. */ 218222944501Smrg drm_intel_gem_bo_process_reloc(target_bo); 218322944501Smrg 218422944501Smrg /* Add the target to the validate list */ 218522944501Smrg drm_intel_add_validate_buffer(target_bo); 218622944501Smrg } 218722944501Smrg} 218822944501Smrg 218922944501Smrgstatic void 219022944501Smrgdrm_intel_gem_bo_process_reloc2(drm_intel_bo *bo) 219122944501Smrg{ 219222944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; 219322944501Smrg int i; 219422944501Smrg 2195fe517fc9Smrg if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) 219622944501Smrg return; 219722944501Smrg 219822944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) { 219922944501Smrg drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo; 220022944501Smrg int need_fence; 220122944501Smrg 2202aaba2545Smrg if (target_bo == bo) 2203aaba2545Smrg continue; 2204aaba2545Smrg 220520131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 220620131375Smrg 220722944501Smrg /* Continue walking the tree depth-first. */ 220822944501Smrg drm_intel_gem_bo_process_reloc2(target_bo); 220922944501Smrg 221022944501Smrg need_fence = (bo_gem->reloc_target_info[i].flags & 221122944501Smrg DRM_INTEL_RELOC_FENCE); 221222944501Smrg 221322944501Smrg /* Add the target to the validate list */ 221422944501Smrg drm_intel_add_validate_buffer2(target_bo, need_fence); 221522944501Smrg } 2216fe517fc9Smrg 2217fe517fc9Smrg for (i = 0; i < bo_gem->softpin_target_count; i++) { 2218fe517fc9Smrg drm_intel_bo *target_bo = bo_gem->softpin_target[i]; 2219fe517fc9Smrg 2220fe517fc9Smrg if (target_bo == bo) 2221fe517fc9Smrg continue; 2222fe517fc9Smrg 2223fe517fc9Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 2224fe517fc9Smrg drm_intel_gem_bo_process_reloc2(target_bo); 2225fe517fc9Smrg drm_intel_add_validate_buffer2(target_bo, false); 2226fe517fc9Smrg } 222722944501Smrg} 222822944501Smrg 222922944501Smrg 223022944501Smrgstatic void 223122944501Smrgdrm_intel_update_buffer_offsets(drm_intel_bufmgr_gem *bufmgr_gem) 223222944501Smrg{ 223322944501Smrg int i; 223422944501Smrg 223522944501Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 223622944501Smrg drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; 223722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 223822944501Smrg 223922944501Smrg /* Update the buffer offset */ 224020131375Smrg if (bufmgr_gem->exec_objects[i].offset != bo->offset64) { 2241fe517fc9Smrg DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n", 2242d82d45b3Sjoerg bo_gem->gem_handle, bo_gem->name, 2243fe517fc9Smrg upper_32_bits(bo->offset64), 2244fe517fc9Smrg lower_32_bits(bo->offset64), 2245fe517fc9Smrg upper_32_bits(bufmgr_gem->exec_objects[i].offset), 2246fe517fc9Smrg lower_32_bits(bufmgr_gem->exec_objects[i].offset)); 224720131375Smrg bo->offset64 = bufmgr_gem->exec_objects[i].offset; 224822944501Smrg bo->offset = bufmgr_gem->exec_objects[i].offset; 224922944501Smrg } 225022944501Smrg } 225122944501Smrg} 225222944501Smrg 225322944501Smrgstatic void 225422944501Smrgdrm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem) 225522944501Smrg{ 225622944501Smrg int i; 225722944501Smrg 225822944501Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 225922944501Smrg drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; 226022944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; 226122944501Smrg 226222944501Smrg /* Update the buffer offset */ 226320131375Smrg if (bufmgr_gem->exec2_objects[i].offset != bo->offset64) { 2264fe517fc9Smrg /* If we're seeing softpinned object here it means that the kernel 2265fe517fc9Smrg * has relocated our object... Indicating a programming error 2266fe517fc9Smrg */ 22670655efefSmrg assert(!(bo_gem->kflags & EXEC_OBJECT_PINNED)); 2268fe517fc9Smrg DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n", 2269d82d45b3Sjoerg bo_gem->gem_handle, bo_gem->name, 2270fe517fc9Smrg upper_32_bits(bo->offset64), 2271fe517fc9Smrg lower_32_bits(bo->offset64), 2272fe517fc9Smrg upper_32_bits(bufmgr_gem->exec2_objects[i].offset), 2273fe517fc9Smrg lower_32_bits(bufmgr_gem->exec2_objects[i].offset)); 227420131375Smrg bo->offset64 = bufmgr_gem->exec2_objects[i].offset; 227522944501Smrg bo->offset = bufmgr_gem->exec2_objects[i].offset; 227622944501Smrg } 227722944501Smrg } 227822944501Smrg} 227922944501Smrg 22806260e5d5Smrgdrm_public void 228120131375Smrgdrm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo, 228220131375Smrg int x1, int y1, int width, int height, 228320131375Smrg enum aub_dump_bmp_format format, 228420131375Smrg int pitch, int offset) 228520131375Smrg{ 228620131375Smrg} 228720131375Smrg 228820131375Smrgstatic int 228920131375Smrgdrm_intel_gem_bo_exec(drm_intel_bo *bo, int used, 229020131375Smrg drm_clip_rect_t * cliprects, int num_cliprects, int DR4) 229120131375Smrg{ 229220131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 229320131375Smrg struct drm_i915_gem_execbuffer execbuf; 229420131375Smrg int ret, i; 229520131375Smrg 2296fe517fc9Smrg if (to_bo_gem(bo)->has_error) 229720131375Smrg return -ENOMEM; 229820131375Smrg 229920131375Smrg pthread_mutex_lock(&bufmgr_gem->lock); 230020131375Smrg /* Update indices and set up the validate list. */ 230120131375Smrg drm_intel_gem_bo_process_reloc(bo); 230220131375Smrg 230320131375Smrg /* Add the batch buffer to the validation list. There are no 230420131375Smrg * relocations pointing to it. 230520131375Smrg */ 230620131375Smrg drm_intel_add_validate_buffer(bo); 230720131375Smrg 2308424e9256Smrg memclear(execbuf); 230920131375Smrg execbuf.buffers_ptr = (uintptr_t) bufmgr_gem->exec_objects; 231020131375Smrg execbuf.buffer_count = bufmgr_gem->exec_count; 231120131375Smrg execbuf.batch_start_offset = 0; 231220131375Smrg execbuf.batch_len = used; 231320131375Smrg execbuf.cliprects_ptr = (uintptr_t) cliprects; 231420131375Smrg execbuf.num_cliprects = num_cliprects; 231520131375Smrg execbuf.DR1 = 0; 231620131375Smrg execbuf.DR4 = DR4; 231720131375Smrg 231820131375Smrg ret = drmIoctl(bufmgr_gem->fd, 231920131375Smrg DRM_IOCTL_I915_GEM_EXECBUFFER, 232020131375Smrg &execbuf); 232120131375Smrg if (ret != 0) { 232220131375Smrg ret = -errno; 232320131375Smrg if (errno == ENOSPC) { 232420131375Smrg DBG("Execbuffer fails to pin. " 232520131375Smrg "Estimate: %u. Actual: %u. Available: %u\n", 232620131375Smrg drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos, 232720131375Smrg bufmgr_gem-> 232820131375Smrg exec_count), 232920131375Smrg drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos, 233020131375Smrg bufmgr_gem-> 233120131375Smrg exec_count), 233220131375Smrg (unsigned int)bufmgr_gem->gtt_size); 233320131375Smrg } 233420131375Smrg } 233520131375Smrg drm_intel_update_buffer_offsets(bufmgr_gem); 233620131375Smrg 233720131375Smrg if (bufmgr_gem->bufmgr.debug) 233820131375Smrg drm_intel_gem_dump_validation_list(bufmgr_gem); 233920131375Smrg 234020131375Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 2341fe517fc9Smrg drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]); 234220131375Smrg 234320131375Smrg bo_gem->idle = false; 234420131375Smrg 234520131375Smrg /* Disconnect the buffer from the validate list */ 234620131375Smrg bo_gem->validate_index = -1; 234720131375Smrg bufmgr_gem->exec_bos[i] = NULL; 234820131375Smrg } 234920131375Smrg bufmgr_gem->exec_count = 0; 235020131375Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 235120131375Smrg 235220131375Smrg return ret; 235320131375Smrg} 235420131375Smrg 235520131375Smrgstatic int 235620131375Smrgdo_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx, 235720131375Smrg drm_clip_rect_t *cliprects, int num_cliprects, int DR4, 23582ee35494Smrg int in_fence, int *out_fence, 235920131375Smrg unsigned int flags) 236020131375Smrg{ 236120131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; 236220131375Smrg struct drm_i915_gem_execbuffer2 execbuf; 236320131375Smrg int ret = 0; 236420131375Smrg int i; 236520131375Smrg 2366fe517fc9Smrg if (to_bo_gem(bo)->has_error) 2367fe517fc9Smrg return -ENOMEM; 2368fe517fc9Smrg 236920131375Smrg switch (flags & 0x7) { 237020131375Smrg default: 237120131375Smrg return -EINVAL; 237220131375Smrg case I915_EXEC_BLT: 23739ce4edccSmrg if (!bufmgr_gem->has_blt) 23749ce4edccSmrg return -EINVAL; 23759ce4edccSmrg break; 23769ce4edccSmrg case I915_EXEC_BSD: 23779ce4edccSmrg if (!bufmgr_gem->has_bsd) 23789ce4edccSmrg return -EINVAL; 23799ce4edccSmrg break; 238020131375Smrg case I915_EXEC_VEBOX: 238120131375Smrg if (!bufmgr_gem->has_vebox) 238220131375Smrg return -EINVAL; 238320131375Smrg break; 23849ce4edccSmrg case I915_EXEC_RENDER: 23859ce4edccSmrg case I915_EXEC_DEFAULT: 23869ce4edccSmrg break; 23879ce4edccSmrg } 2388aaba2545Smrg 238922944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 239022944501Smrg /* Update indices and set up the validate list. */ 239122944501Smrg drm_intel_gem_bo_process_reloc2(bo); 239222944501Smrg 239322944501Smrg /* Add the batch buffer to the validation list. There are no relocations 239422944501Smrg * pointing to it. 239522944501Smrg */ 239622944501Smrg drm_intel_add_validate_buffer2(bo, 0); 239722944501Smrg 2398424e9256Smrg memclear(execbuf); 239922944501Smrg execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec2_objects; 240022944501Smrg execbuf.buffer_count = bufmgr_gem->exec_count; 240122944501Smrg execbuf.batch_start_offset = 0; 240222944501Smrg execbuf.batch_len = used; 240322944501Smrg execbuf.cliprects_ptr = (uintptr_t)cliprects; 240422944501Smrg execbuf.num_cliprects = num_cliprects; 240522944501Smrg execbuf.DR1 = 0; 240622944501Smrg execbuf.DR4 = DR4; 240720131375Smrg execbuf.flags = flags; 240820131375Smrg if (ctx == NULL) 240920131375Smrg i915_execbuffer2_set_context_id(execbuf, 0); 241020131375Smrg else 241120131375Smrg i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id); 241222944501Smrg execbuf.rsvd2 = 0; 24132ee35494Smrg if (in_fence != -1) { 24142ee35494Smrg execbuf.rsvd2 = in_fence; 24152ee35494Smrg execbuf.flags |= I915_EXEC_FENCE_IN; 24162ee35494Smrg } 24172ee35494Smrg if (out_fence != NULL) { 24182ee35494Smrg *out_fence = -1; 24192ee35494Smrg execbuf.flags |= I915_EXEC_FENCE_OUT; 24202ee35494Smrg } 242122944501Smrg 242220131375Smrg if (bufmgr_gem->no_exec) 242320131375Smrg goto skip_execution; 242420131375Smrg 24256d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 24262ee35494Smrg DRM_IOCTL_I915_GEM_EXECBUFFER2_WR, 24276d98c517Smrg &execbuf); 242822944501Smrg if (ret != 0) { 242922944501Smrg ret = -errno; 24306d98c517Smrg if (ret == -ENOSPC) { 24319ce4edccSmrg DBG("Execbuffer fails to pin. " 24329ce4edccSmrg "Estimate: %u. Actual: %u. Available: %u\n", 24339ce4edccSmrg drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos, 24349ce4edccSmrg bufmgr_gem->exec_count), 24359ce4edccSmrg drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos, 24369ce4edccSmrg bufmgr_gem->exec_count), 24379ce4edccSmrg (unsigned int) bufmgr_gem->gtt_size); 243822944501Smrg } 243922944501Smrg } 244022944501Smrg drm_intel_update_buffer_offsets2(bufmgr_gem); 244122944501Smrg 24422ee35494Smrg if (ret == 0 && out_fence != NULL) 24432ee35494Smrg *out_fence = execbuf.rsvd2 >> 32; 24442ee35494Smrg 244520131375Smrgskip_execution: 244622944501Smrg if (bufmgr_gem->bufmgr.debug) 244722944501Smrg drm_intel_gem_dump_validation_list(bufmgr_gem); 244822944501Smrg 244922944501Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 2450fe517fc9Smrg drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]); 245122944501Smrg 245220131375Smrg bo_gem->idle = false; 245320131375Smrg 245422944501Smrg /* Disconnect the buffer from the validate list */ 245522944501Smrg bo_gem->validate_index = -1; 245622944501Smrg bufmgr_gem->exec_bos[i] = NULL; 245722944501Smrg } 245822944501Smrg bufmgr_gem->exec_count = 0; 245922944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 246022944501Smrg 246122944501Smrg return ret; 246222944501Smrg} 246322944501Smrg 2464aaba2545Smrgstatic int 2465aaba2545Smrgdrm_intel_gem_bo_exec2(drm_intel_bo *bo, int used, 2466aaba2545Smrg drm_clip_rect_t *cliprects, int num_cliprects, 2467aaba2545Smrg int DR4) 2468aaba2545Smrg{ 246920131375Smrg return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4, 24702ee35494Smrg -1, NULL, I915_EXEC_RENDER); 247120131375Smrg} 247220131375Smrg 247320131375Smrgstatic int 247420131375Smrgdrm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used, 247520131375Smrg drm_clip_rect_t *cliprects, int num_cliprects, int DR4, 247620131375Smrg unsigned int flags) 247720131375Smrg{ 247820131375Smrg return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4, 24792ee35494Smrg -1, NULL, flags); 248020131375Smrg} 248120131375Smrg 24826260e5d5Smrgdrm_public int 248320131375Smrgdrm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx, 248420131375Smrg int used, unsigned int flags) 248520131375Smrg{ 24862ee35494Smrg return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags); 24872ee35494Smrg} 24882ee35494Smrg 24896260e5d5Smrgdrm_public int 24902ee35494Smrgdrm_intel_gem_bo_fence_exec(drm_intel_bo *bo, 24912ee35494Smrg drm_intel_context *ctx, 24922ee35494Smrg int used, 24932ee35494Smrg int in_fence, 24942ee35494Smrg int *out_fence, 24952ee35494Smrg unsigned int flags) 24962ee35494Smrg{ 24972ee35494Smrg return do_exec2(bo, used, ctx, NULL, 0, 0, in_fence, out_fence, flags); 2498aaba2545Smrg} 2499aaba2545Smrg 250022944501Smrgstatic int 250122944501Smrgdrm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment) 250222944501Smrg{ 250322944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 250422944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 250522944501Smrg struct drm_i915_gem_pin pin; 250622944501Smrg int ret; 250722944501Smrg 2508424e9256Smrg memclear(pin); 250922944501Smrg pin.handle = bo_gem->gem_handle; 251022944501Smrg pin.alignment = alignment; 251122944501Smrg 25126d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 25136d98c517Smrg DRM_IOCTL_I915_GEM_PIN, 25146d98c517Smrg &pin); 251522944501Smrg if (ret != 0) 251622944501Smrg return -errno; 251722944501Smrg 251820131375Smrg bo->offset64 = pin.offset; 251922944501Smrg bo->offset = pin.offset; 252022944501Smrg return 0; 252122944501Smrg} 252222944501Smrg 252322944501Smrgstatic int 252422944501Smrgdrm_intel_gem_bo_unpin(drm_intel_bo *bo) 252522944501Smrg{ 252622944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 252722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 252822944501Smrg struct drm_i915_gem_unpin unpin; 252922944501Smrg int ret; 253022944501Smrg 2531424e9256Smrg memclear(unpin); 253222944501Smrg unpin.handle = bo_gem->gem_handle; 253322944501Smrg 25346d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin); 253522944501Smrg if (ret != 0) 253622944501Smrg return -errno; 253722944501Smrg 253822944501Smrg return 0; 253922944501Smrg} 254022944501Smrg 254122944501Smrgstatic int 25426d98c517Smrgdrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, 25436d98c517Smrg uint32_t tiling_mode, 25446d98c517Smrg uint32_t stride) 254522944501Smrg{ 254622944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 254722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 254822944501Smrg struct drm_i915_gem_set_tiling set_tiling; 254922944501Smrg int ret; 255022944501Smrg 25516d98c517Smrg if (bo_gem->global_name == 0 && 25526d98c517Smrg tiling_mode == bo_gem->tiling_mode && 25536d98c517Smrg stride == bo_gem->stride) 255422944501Smrg return 0; 255522944501Smrg 255622944501Smrg memset(&set_tiling, 0, sizeof(set_tiling)); 255722944501Smrg do { 25586d98c517Smrg /* set_tiling is slightly broken and overwrites the 25596d98c517Smrg * input on the error path, so we have to open code 25606d98c517Smrg * rmIoctl. 25616d98c517Smrg */ 25626d98c517Smrg set_tiling.handle = bo_gem->gem_handle; 25636d98c517Smrg set_tiling.tiling_mode = tiling_mode; 256422944501Smrg set_tiling.stride = stride; 256522944501Smrg 256622944501Smrg ret = ioctl(bufmgr_gem->fd, 256722944501Smrg DRM_IOCTL_I915_GEM_SET_TILING, 256822944501Smrg &set_tiling); 25696d98c517Smrg } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 25706d98c517Smrg if (ret == -1) 25716d98c517Smrg return -errno; 25726d98c517Smrg 25736d98c517Smrg bo_gem->tiling_mode = set_tiling.tiling_mode; 25746d98c517Smrg bo_gem->swizzle_mode = set_tiling.swizzle_mode; 25756d98c517Smrg bo_gem->stride = set_tiling.stride; 25766d98c517Smrg return 0; 25776d98c517Smrg} 25786d98c517Smrg 25796d98c517Smrgstatic int 25806d98c517Smrgdrm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, 25816d98c517Smrg uint32_t stride) 25826d98c517Smrg{ 25836d98c517Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 25846d98c517Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 25856d98c517Smrg int ret; 25866d98c517Smrg 2587a884aba1Smrg /* Tiling with userptr surfaces is not supported 2588a884aba1Smrg * on all hardware so refuse it for time being. 2589a884aba1Smrg */ 2590a884aba1Smrg if (bo_gem->is_userptr) 2591a884aba1Smrg return -EINVAL; 2592a884aba1Smrg 25936d98c517Smrg /* Linear buffers have no stride. By ensuring that we only ever use 25946d98c517Smrg * stride 0 with linear buffers, we simplify our code. 25956d98c517Smrg */ 25966d98c517Smrg if (*tiling_mode == I915_TILING_NONE) 25976d98c517Smrg stride = 0; 25986d98c517Smrg 25996d98c517Smrg ret = drm_intel_gem_bo_set_tiling_internal(bo, *tiling_mode, stride); 26006d98c517Smrg if (ret == 0) 2601fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 260222944501Smrg 260322944501Smrg *tiling_mode = bo_gem->tiling_mode; 2604aaba2545Smrg return ret; 260522944501Smrg} 260622944501Smrg 260722944501Smrgstatic int 260822944501Smrgdrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, 260922944501Smrg uint32_t * swizzle_mode) 261022944501Smrg{ 261122944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 261222944501Smrg 261322944501Smrg *tiling_mode = bo_gem->tiling_mode; 261422944501Smrg *swizzle_mode = bo_gem->swizzle_mode; 261522944501Smrg return 0; 261622944501Smrg} 261722944501Smrg 2618fe517fc9Smrgstatic int 2619fe517fc9Smrgdrm_intel_gem_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset) 2620fe517fc9Smrg{ 2621fe517fc9Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2622fe517fc9Smrg 2623fe517fc9Smrg bo->offset64 = offset; 2624fe517fc9Smrg bo->offset = offset; 26250655efefSmrg bo_gem->kflags |= EXEC_OBJECT_PINNED; 26260655efefSmrg 2627fe517fc9Smrg return 0; 2628fe517fc9Smrg} 2629fe517fc9Smrg 26306260e5d5Smrgdrm_public drm_intel_bo * 263120131375Smrgdrm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size) 263220131375Smrg{ 263320131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 263420131375Smrg int ret; 263520131375Smrg uint32_t handle; 263620131375Smrg drm_intel_bo_gem *bo_gem; 263720131375Smrg struct drm_i915_gem_get_tiling get_tiling; 263820131375Smrg 2639fe517fc9Smrg pthread_mutex_lock(&bufmgr_gem->lock); 264020131375Smrg ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle); 2641fe517fc9Smrg if (ret) { 2642fe517fc9Smrg DBG("create_from_prime: failed to obtain handle from fd: %s\n", strerror(errno)); 2643fe517fc9Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 2644fe517fc9Smrg return NULL; 2645fe517fc9Smrg } 264620131375Smrg 264720131375Smrg /* 264820131375Smrg * See if the kernel has already returned this buffer to us. Just as 264920131375Smrg * for named buffers, we must not create two bo's pointing at the same 265020131375Smrg * kernel object 265120131375Smrg */ 26522ee35494Smrg HASH_FIND(handle_hh, bufmgr_gem->handle_table, 26532ee35494Smrg &handle, sizeof(handle), bo_gem); 26542ee35494Smrg if (bo_gem) { 26552ee35494Smrg drm_intel_gem_bo_reference(&bo_gem->bo); 26562ee35494Smrg goto out; 265720131375Smrg } 265820131375Smrg 265920131375Smrg bo_gem = calloc(1, sizeof(*bo_gem)); 26602ee35494Smrg if (!bo_gem) 26612ee35494Smrg goto out; 26622ee35494Smrg 26632ee35494Smrg atomic_set(&bo_gem->refcount, 1); 26642ee35494Smrg DRMINITLISTHEAD(&bo_gem->vma_list); 26652ee35494Smrg 266620131375Smrg /* Determine size of bo. The fd-to-handle ioctl really should 266720131375Smrg * return the size, but it doesn't. If we have kernel 3.12 or 266820131375Smrg * later, we can lseek on the prime fd to get the size. Older 266920131375Smrg * kernels will just fail, in which case we fall back to the 267020131375Smrg * provided (estimated or guess size). */ 267120131375Smrg ret = lseek(prime_fd, 0, SEEK_END); 267220131375Smrg if (ret != -1) 267320131375Smrg bo_gem->bo.size = ret; 267420131375Smrg else 267520131375Smrg bo_gem->bo.size = size; 267620131375Smrg 267720131375Smrg bo_gem->bo.handle = handle; 267820131375Smrg bo_gem->bo.bufmgr = bufmgr; 267920131375Smrg 268020131375Smrg bo_gem->gem_handle = handle; 26812ee35494Smrg HASH_ADD(handle_hh, bufmgr_gem->handle_table, 26822ee35494Smrg gem_handle, sizeof(bo_gem->gem_handle), bo_gem); 268320131375Smrg 268420131375Smrg bo_gem->name = "prime"; 268520131375Smrg bo_gem->validate_index = -1; 268620131375Smrg bo_gem->reloc_tree_fences = 0; 268720131375Smrg bo_gem->used_as_reloc_target = false; 268820131375Smrg bo_gem->has_error = false; 268920131375Smrg bo_gem->reusable = false; 269020131375Smrg 2691424e9256Smrg memclear(get_tiling); 269220131375Smrg get_tiling.handle = bo_gem->gem_handle; 26932ee35494Smrg if (drmIoctl(bufmgr_gem->fd, 26942ee35494Smrg DRM_IOCTL_I915_GEM_GET_TILING, 26952ee35494Smrg &get_tiling)) 26962ee35494Smrg goto err; 26972ee35494Smrg 269820131375Smrg bo_gem->tiling_mode = get_tiling.tiling_mode; 269920131375Smrg bo_gem->swizzle_mode = get_tiling.swizzle_mode; 270020131375Smrg /* XXX stride is unknown */ 2701fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 270220131375Smrg 27032ee35494Smrgout: 27042ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 270520131375Smrg return &bo_gem->bo; 27062ee35494Smrg 27072ee35494Smrgerr: 27082ee35494Smrg drm_intel_gem_bo_free(&bo_gem->bo); 27092ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 27102ee35494Smrg return NULL; 271120131375Smrg} 271220131375Smrg 27136260e5d5Smrgdrm_public int 271420131375Smrgdrm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd) 271520131375Smrg{ 271620131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 271720131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 271820131375Smrg 271920131375Smrg if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle, 272020131375Smrg DRM_CLOEXEC, prime_fd) != 0) 272120131375Smrg return -errno; 272220131375Smrg 272320131375Smrg bo_gem->reusable = false; 272420131375Smrg 272520131375Smrg return 0; 272620131375Smrg} 272720131375Smrg 272822944501Smrgstatic int 272922944501Smrgdrm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name) 273022944501Smrg{ 273122944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 273222944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 273322944501Smrg 273422944501Smrg if (!bo_gem->global_name) { 273520131375Smrg struct drm_gem_flink flink; 273620131375Smrg 2737424e9256Smrg memclear(flink); 273822944501Smrg flink.handle = bo_gem->gem_handle; 27392ee35494Smrg if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink)) 27402ee35494Smrg return -errno; 274122944501Smrg 2742a884aba1Smrg pthread_mutex_lock(&bufmgr_gem->lock); 27432ee35494Smrg if (!bo_gem->global_name) { 27442ee35494Smrg bo_gem->global_name = flink.name; 27452ee35494Smrg bo_gem->reusable = false; 2746a884aba1Smrg 27472ee35494Smrg HASH_ADD(name_hh, bufmgr_gem->name_table, 27482ee35494Smrg global_name, sizeof(bo_gem->global_name), 27492ee35494Smrg bo_gem); 2750a884aba1Smrg } 2751a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 275222944501Smrg } 275322944501Smrg 275422944501Smrg *name = bo_gem->global_name; 275522944501Smrg return 0; 275622944501Smrg} 275722944501Smrg 275822944501Smrg/** 275922944501Smrg * Enables unlimited caching of buffer objects for reuse. 276022944501Smrg * 276122944501Smrg * This is potentially very memory expensive, as the cache at each bucket 276222944501Smrg * size is only bounded by how many buffers of that size we've managed to have 276322944501Smrg * in flight at once. 276422944501Smrg */ 27656260e5d5Smrgdrm_public void 276622944501Smrgdrm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr) 276722944501Smrg{ 276822944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 276922944501Smrg 277020131375Smrg bufmgr_gem->bo_reuse = true; 277122944501Smrg} 277222944501Smrg 27732ee35494Smrg/** 27742ee35494Smrg * Disables implicit synchronisation before executing the bo 27752ee35494Smrg * 27762ee35494Smrg * This will cause rendering corruption unless you correctly manage explicit 27772ee35494Smrg * fences for all rendering involving this buffer - including use by others. 27782ee35494Smrg * Disabling the implicit serialisation is only required if that serialisation 27792ee35494Smrg * is too coarse (for example, you have split the buffer into many 27802ee35494Smrg * non-overlapping regions and are sharing the whole buffer between concurrent 27812ee35494Smrg * independent command streams). 27822ee35494Smrg * 27832ee35494Smrg * Note the kernel must advertise support via I915_PARAM_HAS_EXEC_ASYNC, 27842ee35494Smrg * which can be checked using drm_intel_bufmgr_can_disable_implicit_sync, 27852ee35494Smrg * or subsequent execbufs involving the bo will generate EINVAL. 27862ee35494Smrg */ 27876260e5d5Smrgdrm_public void 27882ee35494Smrgdrm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo) 27892ee35494Smrg{ 27902ee35494Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 27912ee35494Smrg 27922ee35494Smrg bo_gem->kflags |= EXEC_OBJECT_ASYNC; 27932ee35494Smrg} 27942ee35494Smrg 27952ee35494Smrg/** 27962ee35494Smrg * Enables implicit synchronisation before executing the bo 27972ee35494Smrg * 27982ee35494Smrg * This is the default behaviour of the kernel, to wait upon prior writes 27992ee35494Smrg * completing on the object before rendering with it, or to wait for prior 28002ee35494Smrg * reads to complete before writing into the object. 28012ee35494Smrg * drm_intel_gem_bo_disable_implicit_sync() can stop this behaviour, telling 28022ee35494Smrg * the kernel never to insert a stall before using the object. Then this 28032ee35494Smrg * function can be used to restore the implicit sync before subsequent 28042ee35494Smrg * rendering. 28052ee35494Smrg */ 28066260e5d5Smrgdrm_public void 28072ee35494Smrgdrm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo) 28082ee35494Smrg{ 28092ee35494Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 28102ee35494Smrg 28112ee35494Smrg bo_gem->kflags &= ~EXEC_OBJECT_ASYNC; 28122ee35494Smrg} 28132ee35494Smrg 28142ee35494Smrg/** 28152ee35494Smrg * Query whether the kernel supports disabling of its implicit synchronisation 28162ee35494Smrg * before execbuf. See drm_intel_gem_bo_disable_implicit_sync() 28172ee35494Smrg */ 28186260e5d5Smrgdrm_public int 28192ee35494Smrgdrm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr) 28202ee35494Smrg{ 28212ee35494Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 28222ee35494Smrg 28232ee35494Smrg return bufmgr_gem->has_exec_async; 28242ee35494Smrg} 28252ee35494Smrg 282622944501Smrg/** 282722944501Smrg * Enable use of fenced reloc type. 282822944501Smrg * 282922944501Smrg * New code should enable this to avoid unnecessary fence register 283022944501Smrg * allocation. If this option is not enabled, all relocs will have fence 283122944501Smrg * register allocated. 283222944501Smrg */ 28336260e5d5Smrgdrm_public void 283422944501Smrgdrm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr) 283522944501Smrg{ 283622944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 283722944501Smrg 283822944501Smrg if (bufmgr_gem->bufmgr.bo_exec == drm_intel_gem_bo_exec2) 283920131375Smrg bufmgr_gem->fenced_relocs = true; 284022944501Smrg} 284122944501Smrg 284222944501Smrg/** 284322944501Smrg * Return the additional aperture space required by the tree of buffer objects 284422944501Smrg * rooted at bo. 284522944501Smrg */ 284622944501Smrgstatic int 284722944501Smrgdrm_intel_gem_bo_get_aperture_space(drm_intel_bo *bo) 284822944501Smrg{ 284922944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 285022944501Smrg int i; 285122944501Smrg int total = 0; 285222944501Smrg 285322944501Smrg if (bo == NULL || bo_gem->included_in_check_aperture) 285422944501Smrg return 0; 285522944501Smrg 285622944501Smrg total += bo->size; 285720131375Smrg bo_gem->included_in_check_aperture = true; 285822944501Smrg 285922944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) 286022944501Smrg total += 286122944501Smrg drm_intel_gem_bo_get_aperture_space(bo_gem-> 286222944501Smrg reloc_target_info[i].bo); 286322944501Smrg 286422944501Smrg return total; 286522944501Smrg} 286622944501Smrg 286722944501Smrg/** 286822944501Smrg * Count the number of buffers in this list that need a fence reg 286922944501Smrg * 287022944501Smrg * If the count is greater than the number of available regs, we'll have 287122944501Smrg * to ask the caller to resubmit a batch with fewer tiled buffers. 287222944501Smrg * 287322944501Smrg * This function over-counts if the same buffer is used multiple times. 287422944501Smrg */ 287522944501Smrgstatic unsigned int 287622944501Smrgdrm_intel_gem_total_fences(drm_intel_bo ** bo_array, int count) 287722944501Smrg{ 287822944501Smrg int i; 287922944501Smrg unsigned int total = 0; 288022944501Smrg 288122944501Smrg for (i = 0; i < count; i++) { 288222944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i]; 288322944501Smrg 288422944501Smrg if (bo_gem == NULL) 288522944501Smrg continue; 288622944501Smrg 288722944501Smrg total += bo_gem->reloc_tree_fences; 288822944501Smrg } 288922944501Smrg return total; 289022944501Smrg} 289122944501Smrg 289222944501Smrg/** 289322944501Smrg * Clear the flag set by drm_intel_gem_bo_get_aperture_space() so we're ready 289422944501Smrg * for the next drm_intel_bufmgr_check_aperture_space() call. 289522944501Smrg */ 289622944501Smrgstatic void 289722944501Smrgdrm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo) 289822944501Smrg{ 289922944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 290022944501Smrg int i; 290122944501Smrg 290222944501Smrg if (bo == NULL || !bo_gem->included_in_check_aperture) 290322944501Smrg return; 290422944501Smrg 290520131375Smrg bo_gem->included_in_check_aperture = false; 290622944501Smrg 290722944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) 290822944501Smrg drm_intel_gem_bo_clear_aperture_space_flag(bo_gem-> 290922944501Smrg reloc_target_info[i].bo); 291022944501Smrg} 291122944501Smrg 291222944501Smrg/** 291322944501Smrg * Return a conservative estimate for the amount of aperture required 291422944501Smrg * for a collection of buffers. This may double-count some buffers. 291522944501Smrg */ 291622944501Smrgstatic unsigned int 291722944501Smrgdrm_intel_gem_estimate_batch_space(drm_intel_bo **bo_array, int count) 291822944501Smrg{ 291922944501Smrg int i; 292022944501Smrg unsigned int total = 0; 292122944501Smrg 292222944501Smrg for (i = 0; i < count; i++) { 292322944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i]; 292422944501Smrg if (bo_gem != NULL) 292522944501Smrg total += bo_gem->reloc_tree_size; 292622944501Smrg } 292722944501Smrg return total; 292822944501Smrg} 292922944501Smrg 293022944501Smrg/** 293122944501Smrg * Return the amount of aperture needed for a collection of buffers. 293222944501Smrg * This avoids double counting any buffers, at the cost of looking 293322944501Smrg * at every buffer in the set. 293422944501Smrg */ 293522944501Smrgstatic unsigned int 293622944501Smrgdrm_intel_gem_compute_batch_space(drm_intel_bo **bo_array, int count) 293722944501Smrg{ 293822944501Smrg int i; 293922944501Smrg unsigned int total = 0; 294022944501Smrg 294122944501Smrg for (i = 0; i < count; i++) { 294222944501Smrg total += drm_intel_gem_bo_get_aperture_space(bo_array[i]); 294322944501Smrg /* For the first buffer object in the array, we get an 294422944501Smrg * accurate count back for its reloc_tree size (since nothing 294522944501Smrg * had been flagged as being counted yet). We can save that 294622944501Smrg * value out as a more conservative reloc_tree_size that 294722944501Smrg * avoids double-counting target buffers. Since the first 294822944501Smrg * buffer happens to usually be the batch buffer in our 294922944501Smrg * callers, this can pull us back from doing the tree 295022944501Smrg * walk on every new batch emit. 295122944501Smrg */ 295222944501Smrg if (i == 0) { 295322944501Smrg drm_intel_bo_gem *bo_gem = 295422944501Smrg (drm_intel_bo_gem *) bo_array[i]; 295522944501Smrg bo_gem->reloc_tree_size = total; 295622944501Smrg } 295722944501Smrg } 295822944501Smrg 295922944501Smrg for (i = 0; i < count; i++) 296022944501Smrg drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]); 296122944501Smrg return total; 296222944501Smrg} 296322944501Smrg 296422944501Smrg/** 296522944501Smrg * Return -1 if the batchbuffer should be flushed before attempting to 296622944501Smrg * emit rendering referencing the buffers pointed to by bo_array. 296722944501Smrg * 296822944501Smrg * This is required because if we try to emit a batchbuffer with relocations 296922944501Smrg * to a tree of buffers that won't simultaneously fit in the aperture, 297022944501Smrg * the rendering will return an error at a point where the software is not 297122944501Smrg * prepared to recover from it. 297222944501Smrg * 297322944501Smrg * However, we also want to emit the batchbuffer significantly before we reach 297422944501Smrg * the limit, as a series of batchbuffers each of which references buffers 297522944501Smrg * covering almost all of the aperture means that at each emit we end up 297622944501Smrg * waiting to evict a buffer from the last rendering, and we get synchronous 297722944501Smrg * performance. By emitting smaller batchbuffers, we eat some CPU overhead to 297822944501Smrg * get better parallelism. 297922944501Smrg */ 298022944501Smrgstatic int 298122944501Smrgdrm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count) 298222944501Smrg{ 298322944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = 298422944501Smrg (drm_intel_bufmgr_gem *) bo_array[0]->bufmgr; 298522944501Smrg unsigned int total = 0; 298622944501Smrg unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4; 298722944501Smrg int total_fences; 298822944501Smrg 298922944501Smrg /* Check for fence reg constraints if necessary */ 299022944501Smrg if (bufmgr_gem->available_fences) { 299122944501Smrg total_fences = drm_intel_gem_total_fences(bo_array, count); 299222944501Smrg if (total_fences > bufmgr_gem->available_fences) 299322944501Smrg return -ENOSPC; 299422944501Smrg } 299522944501Smrg 299622944501Smrg total = drm_intel_gem_estimate_batch_space(bo_array, count); 299722944501Smrg 299822944501Smrg if (total > threshold) 299922944501Smrg total = drm_intel_gem_compute_batch_space(bo_array, count); 300022944501Smrg 300122944501Smrg if (total > threshold) { 300222944501Smrg DBG("check_space: overflowed available aperture, " 300322944501Smrg "%dkb vs %dkb\n", 300422944501Smrg total / 1024, (int)bufmgr_gem->gtt_size / 1024); 300522944501Smrg return -ENOSPC; 300622944501Smrg } else { 300722944501Smrg DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024, 300822944501Smrg (int)bufmgr_gem->gtt_size / 1024); 300922944501Smrg return 0; 301022944501Smrg } 301122944501Smrg} 301222944501Smrg 301322944501Smrg/* 301422944501Smrg * Disable buffer reuse for objects which are shared with the kernel 301522944501Smrg * as scanout buffers 301622944501Smrg */ 301722944501Smrgstatic int 301822944501Smrgdrm_intel_gem_bo_disable_reuse(drm_intel_bo *bo) 301922944501Smrg{ 302022944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 302122944501Smrg 302220131375Smrg bo_gem->reusable = false; 302322944501Smrg return 0; 302422944501Smrg} 302522944501Smrg 3026aaba2545Smrgstatic int 3027aaba2545Smrgdrm_intel_gem_bo_is_reusable(drm_intel_bo *bo) 3028aaba2545Smrg{ 3029aaba2545Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 3030aaba2545Smrg 3031aaba2545Smrg return bo_gem->reusable; 3032aaba2545Smrg} 3033aaba2545Smrg 303422944501Smrgstatic int 303522944501Smrg_drm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo) 303622944501Smrg{ 303722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 303822944501Smrg int i; 303922944501Smrg 304022944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) { 304122944501Smrg if (bo_gem->reloc_target_info[i].bo == target_bo) 304222944501Smrg return 1; 3043aaba2545Smrg if (bo == bo_gem->reloc_target_info[i].bo) 3044aaba2545Smrg continue; 304522944501Smrg if (_drm_intel_gem_bo_references(bo_gem->reloc_target_info[i].bo, 304622944501Smrg target_bo)) 304722944501Smrg return 1; 304822944501Smrg } 304922944501Smrg 3050fe517fc9Smrg for (i = 0; i< bo_gem->softpin_target_count; i++) { 3051fe517fc9Smrg if (bo_gem->softpin_target[i] == target_bo) 3052fe517fc9Smrg return 1; 3053fe517fc9Smrg if (_drm_intel_gem_bo_references(bo_gem->softpin_target[i], target_bo)) 3054fe517fc9Smrg return 1; 3055fe517fc9Smrg } 3056fe517fc9Smrg 305722944501Smrg return 0; 305822944501Smrg} 305922944501Smrg 306022944501Smrg/** Return true if target_bo is referenced by bo's relocation tree. */ 306122944501Smrgstatic int 306222944501Smrgdrm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo) 306322944501Smrg{ 306422944501Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; 306522944501Smrg 306622944501Smrg if (bo == NULL || target_bo == NULL) 306722944501Smrg return 0; 306822944501Smrg if (target_bo_gem->used_as_reloc_target) 306922944501Smrg return _drm_intel_gem_bo_references(bo, target_bo); 307022944501Smrg return 0; 307122944501Smrg} 307222944501Smrg 3073aaba2545Smrgstatic void 3074aaba2545Smrgadd_bucket(drm_intel_bufmgr_gem *bufmgr_gem, int size) 3075aaba2545Smrg{ 3076aaba2545Smrg unsigned int i = bufmgr_gem->num_buckets; 3077aaba2545Smrg 3078aaba2545Smrg assert(i < ARRAY_SIZE(bufmgr_gem->cache_bucket)); 3079aaba2545Smrg 3080aaba2545Smrg DRMINITLISTHEAD(&bufmgr_gem->cache_bucket[i].head); 3081aaba2545Smrg bufmgr_gem->cache_bucket[i].size = size; 3082aaba2545Smrg bufmgr_gem->num_buckets++; 3083aaba2545Smrg} 3084aaba2545Smrg 3085aaba2545Smrgstatic void 3086aaba2545Smrginit_cache_buckets(drm_intel_bufmgr_gem *bufmgr_gem) 3087aaba2545Smrg{ 3088aaba2545Smrg unsigned long size, cache_max_size = 64 * 1024 * 1024; 3089aaba2545Smrg 3090aaba2545Smrg /* OK, so power of two buckets was too wasteful of memory. 3091aaba2545Smrg * Give 3 other sizes between each power of two, to hopefully 3092aaba2545Smrg * cover things accurately enough. (The alternative is 3093aaba2545Smrg * probably to just go for exact matching of sizes, and assume 3094aaba2545Smrg * that for things like composited window resize the tiled 3095aaba2545Smrg * width/height alignment and rounding of sizes to pages will 3096aaba2545Smrg * get us useful cache hit rates anyway) 3097aaba2545Smrg */ 3098aaba2545Smrg add_bucket(bufmgr_gem, 4096); 3099aaba2545Smrg add_bucket(bufmgr_gem, 4096 * 2); 3100aaba2545Smrg add_bucket(bufmgr_gem, 4096 * 3); 3101aaba2545Smrg 3102aaba2545Smrg /* Initialize the linked lists for BO reuse cache. */ 3103aaba2545Smrg for (size = 4 * 4096; size <= cache_max_size; size *= 2) { 3104aaba2545Smrg add_bucket(bufmgr_gem, size); 3105aaba2545Smrg 3106aaba2545Smrg add_bucket(bufmgr_gem, size + size * 1 / 4); 3107aaba2545Smrg add_bucket(bufmgr_gem, size + size * 2 / 4); 3108aaba2545Smrg add_bucket(bufmgr_gem, size + size * 3 / 4); 3109aaba2545Smrg } 3110aaba2545Smrg} 3111aaba2545Smrg 31126260e5d5Smrgdrm_public void 311320131375Smrgdrm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit) 311420131375Smrg{ 311520131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 311620131375Smrg 311720131375Smrg bufmgr_gem->vma_max = limit; 311820131375Smrg 311920131375Smrg drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); 312020131375Smrg} 312120131375Smrg 31222ee35494Smrgstatic int 31232ee35494Smrgparse_devid_override(const char *devid_override) 31242ee35494Smrg{ 31252ee35494Smrg static const struct { 31262ee35494Smrg const char *name; 31272ee35494Smrg int pci_id; 31282ee35494Smrg } name_map[] = { 31292ee35494Smrg { "brw", PCI_CHIP_I965_GM }, 31302ee35494Smrg { "g4x", PCI_CHIP_GM45_GM }, 31312ee35494Smrg { "ilk", PCI_CHIP_ILD_G }, 31322ee35494Smrg { "snb", PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS }, 31332ee35494Smrg { "ivb", PCI_CHIP_IVYBRIDGE_S_GT2 }, 31342ee35494Smrg { "hsw", PCI_CHIP_HASWELL_CRW_E_GT3 }, 31352ee35494Smrg { "byt", PCI_CHIP_VALLEYVIEW_3 }, 31362ee35494Smrg { "bdw", 0x1620 | BDW_ULX }, 31372ee35494Smrg { "skl", PCI_CHIP_SKYLAKE_DT_GT2 }, 31382ee35494Smrg { "kbl", PCI_CHIP_KABYLAKE_DT_GT2 }, 31392ee35494Smrg }; 31402ee35494Smrg unsigned int i; 31412ee35494Smrg 31422ee35494Smrg for (i = 0; i < ARRAY_SIZE(name_map); i++) { 31432ee35494Smrg if (!strcmp(name_map[i].name, devid_override)) 31442ee35494Smrg return name_map[i].pci_id; 31452ee35494Smrg } 31462ee35494Smrg 31472ee35494Smrg return strtod(devid_override, NULL); 31482ee35494Smrg} 31492ee35494Smrg 315020131375Smrg/** 315120131375Smrg * Get the PCI ID for the device. This can be overridden by setting the 315220131375Smrg * INTEL_DEVID_OVERRIDE environment variable to the desired ID. 315320131375Smrg */ 315420131375Smrgstatic int 315520131375Smrgget_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem) 315620131375Smrg{ 315720131375Smrg char *devid_override; 3158424e9256Smrg int devid = 0; 315920131375Smrg int ret; 316020131375Smrg drm_i915_getparam_t gp; 316120131375Smrg 316220131375Smrg if (geteuid() == getuid()) { 316320131375Smrg devid_override = getenv("INTEL_DEVID_OVERRIDE"); 316420131375Smrg if (devid_override) { 316520131375Smrg bufmgr_gem->no_exec = true; 31662ee35494Smrg return parse_devid_override(devid_override); 316720131375Smrg } 316820131375Smrg } 316920131375Smrg 3170424e9256Smrg memclear(gp); 317120131375Smrg gp.param = I915_PARAM_CHIPSET_ID; 317220131375Smrg gp.value = &devid; 317320131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 317420131375Smrg if (ret) { 317520131375Smrg fprintf(stderr, "get chip id failed: %d [%d]\n", ret, errno); 317620131375Smrg fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value); 317720131375Smrg } 317820131375Smrg return devid; 317920131375Smrg} 318020131375Smrg 31816260e5d5Smrgdrm_public int 318220131375Smrgdrm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr) 318320131375Smrg{ 318420131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 318520131375Smrg 318620131375Smrg return bufmgr_gem->pci_device; 318720131375Smrg} 318820131375Smrg 318920131375Smrg/** 319020131375Smrg * Sets the AUB filename. 319120131375Smrg * 319220131375Smrg * This function has to be called before drm_intel_bufmgr_gem_set_aub_dump() 319320131375Smrg * for it to have any effect. 319420131375Smrg */ 31956260e5d5Smrgdrm_public void 319620131375Smrgdrm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr, 319720131375Smrg const char *filename) 319820131375Smrg{ 319920131375Smrg} 320020131375Smrg 320120131375Smrg/** 320220131375Smrg * Sets up AUB dumping. 320320131375Smrg * 320420131375Smrg * This is a trace file format that can be used with the simulator. 320520131375Smrg * Packets are emitted in a format somewhat like GPU command packets. 320620131375Smrg * You can set up a GTT and upload your objects into the referenced 320720131375Smrg * space, then send off batchbuffers and get BMPs out the other end. 320820131375Smrg */ 32096260e5d5Smrgdrm_public void 321020131375Smrgdrm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable) 321120131375Smrg{ 3212fe517fc9Smrg fprintf(stderr, "libdrm aub dumping is deprecated.\n\n" 3213fe517fc9Smrg "Use intel_aubdump from intel-gpu-tools instead. Install intel-gpu-tools,\n" 3214fe517fc9Smrg "then run (for example)\n\n" 3215fe517fc9Smrg "\t$ intel_aubdump --output=trace.aub glxgears -geometry 500x500\n\n" 3216fe517fc9Smrg "See the intel_aubdump man page for more details.\n"); 321720131375Smrg} 321820131375Smrg 32196260e5d5Smrgdrm_public drm_intel_context * 322020131375Smrgdrm_intel_gem_context_create(drm_intel_bufmgr *bufmgr) 322120131375Smrg{ 322220131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 322320131375Smrg struct drm_i915_gem_context_create create; 322420131375Smrg drm_intel_context *context = NULL; 322520131375Smrg int ret; 322620131375Smrg 322720131375Smrg context = calloc(1, sizeof(*context)); 322820131375Smrg if (!context) 322920131375Smrg return NULL; 323020131375Smrg 3231424e9256Smrg memclear(create); 323220131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create); 323320131375Smrg if (ret != 0) { 323420131375Smrg DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n", 323520131375Smrg strerror(errno)); 323620131375Smrg free(context); 323720131375Smrg return NULL; 323820131375Smrg } 323920131375Smrg 324020131375Smrg context->ctx_id = create.ctx_id; 324120131375Smrg context->bufmgr = bufmgr; 324220131375Smrg 324320131375Smrg return context; 324420131375Smrg} 324520131375Smrg 32466260e5d5Smrgdrm_public int 32472ee35494Smrgdrm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id) 32482ee35494Smrg{ 32492ee35494Smrg if (ctx == NULL) 32502ee35494Smrg return -EINVAL; 32512ee35494Smrg 32522ee35494Smrg *ctx_id = ctx->ctx_id; 32532ee35494Smrg 32542ee35494Smrg return 0; 32552ee35494Smrg} 32562ee35494Smrg 32576260e5d5Smrgdrm_public void 325820131375Smrgdrm_intel_gem_context_destroy(drm_intel_context *ctx) 325920131375Smrg{ 326020131375Smrg drm_intel_bufmgr_gem *bufmgr_gem; 326120131375Smrg struct drm_i915_gem_context_destroy destroy; 326220131375Smrg int ret; 326320131375Smrg 326420131375Smrg if (ctx == NULL) 326520131375Smrg return; 326620131375Smrg 3267424e9256Smrg memclear(destroy); 326820131375Smrg 326920131375Smrg bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr; 327020131375Smrg destroy.ctx_id = ctx->ctx_id; 327120131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, 327220131375Smrg &destroy); 327320131375Smrg if (ret != 0) 327420131375Smrg fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n", 327520131375Smrg strerror(errno)); 327620131375Smrg 327720131375Smrg free(ctx); 327820131375Smrg} 327920131375Smrg 32806260e5d5Smrgdrm_public int 328120131375Smrgdrm_intel_get_reset_stats(drm_intel_context *ctx, 328220131375Smrg uint32_t *reset_count, 328320131375Smrg uint32_t *active, 328420131375Smrg uint32_t *pending) 328520131375Smrg{ 328620131375Smrg drm_intel_bufmgr_gem *bufmgr_gem; 328720131375Smrg struct drm_i915_reset_stats stats; 328820131375Smrg int ret; 328920131375Smrg 329020131375Smrg if (ctx == NULL) 329120131375Smrg return -EINVAL; 329220131375Smrg 3293424e9256Smrg memclear(stats); 329420131375Smrg 329520131375Smrg bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr; 329620131375Smrg stats.ctx_id = ctx->ctx_id; 329720131375Smrg ret = drmIoctl(bufmgr_gem->fd, 329820131375Smrg DRM_IOCTL_I915_GET_RESET_STATS, 329920131375Smrg &stats); 330020131375Smrg if (ret == 0) { 330120131375Smrg if (reset_count != NULL) 330220131375Smrg *reset_count = stats.reset_count; 330320131375Smrg 330420131375Smrg if (active != NULL) 330520131375Smrg *active = stats.batch_active; 330620131375Smrg 330720131375Smrg if (pending != NULL) 330820131375Smrg *pending = stats.batch_pending; 330920131375Smrg } 331020131375Smrg 331120131375Smrg return ret; 331220131375Smrg} 331320131375Smrg 33146260e5d5Smrgdrm_public int 331520131375Smrgdrm_intel_reg_read(drm_intel_bufmgr *bufmgr, 331620131375Smrg uint32_t offset, 331720131375Smrg uint64_t *result) 331820131375Smrg{ 331920131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 332020131375Smrg struct drm_i915_reg_read reg_read; 332120131375Smrg int ret; 332220131375Smrg 3323424e9256Smrg memclear(reg_read); 332420131375Smrg reg_read.offset = offset; 332520131375Smrg 332620131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, ®_read); 332720131375Smrg 332820131375Smrg *result = reg_read.val; 332920131375Smrg return ret; 333020131375Smrg} 333120131375Smrg 33326260e5d5Smrgdrm_public int 3333424e9256Smrgdrm_intel_get_subslice_total(int fd, unsigned int *subslice_total) 3334424e9256Smrg{ 3335424e9256Smrg drm_i915_getparam_t gp; 3336424e9256Smrg int ret; 3337424e9256Smrg 3338424e9256Smrg memclear(gp); 3339424e9256Smrg gp.value = (int*)subslice_total; 3340424e9256Smrg gp.param = I915_PARAM_SUBSLICE_TOTAL; 3341424e9256Smrg ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); 3342424e9256Smrg if (ret) 3343424e9256Smrg return -errno; 3344424e9256Smrg 3345424e9256Smrg return 0; 3346424e9256Smrg} 3347424e9256Smrg 33486260e5d5Smrgdrm_public int 3349424e9256Smrgdrm_intel_get_eu_total(int fd, unsigned int *eu_total) 3350424e9256Smrg{ 3351424e9256Smrg drm_i915_getparam_t gp; 3352424e9256Smrg int ret; 3353424e9256Smrg 3354424e9256Smrg memclear(gp); 3355424e9256Smrg gp.value = (int*)eu_total; 3356424e9256Smrg gp.param = I915_PARAM_EU_TOTAL; 3357424e9256Smrg ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); 3358424e9256Smrg if (ret) 3359424e9256Smrg return -errno; 3360424e9256Smrg 3361424e9256Smrg return 0; 3362424e9256Smrg} 336320131375Smrg 33646260e5d5Smrgdrm_public int 33652ee35494Smrgdrm_intel_get_pooled_eu(int fd) 33662ee35494Smrg{ 33672ee35494Smrg drm_i915_getparam_t gp; 33682ee35494Smrg int ret = -1; 33692ee35494Smrg 33702ee35494Smrg memclear(gp); 33712ee35494Smrg gp.param = I915_PARAM_HAS_POOLED_EU; 33722ee35494Smrg gp.value = &ret; 33732ee35494Smrg if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp)) 33742ee35494Smrg return -errno; 33752ee35494Smrg 33762ee35494Smrg return ret; 33772ee35494Smrg} 33782ee35494Smrg 33796260e5d5Smrgdrm_public int 33802ee35494Smrgdrm_intel_get_min_eu_in_pool(int fd) 33812ee35494Smrg{ 33822ee35494Smrg drm_i915_getparam_t gp; 33832ee35494Smrg int ret = -1; 33842ee35494Smrg 33852ee35494Smrg memclear(gp); 33862ee35494Smrg gp.param = I915_PARAM_MIN_EU_IN_POOL; 33872ee35494Smrg gp.value = &ret; 33882ee35494Smrg if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp)) 33892ee35494Smrg return -errno; 33902ee35494Smrg 33912ee35494Smrg return ret; 33922ee35494Smrg} 33932ee35494Smrg 339420131375Smrg/** 339520131375Smrg * Annotate the given bo for use in aub dumping. 339620131375Smrg * 339720131375Smrg * \param annotations is an array of drm_intel_aub_annotation objects 339820131375Smrg * describing the type of data in various sections of the bo. Each 339920131375Smrg * element of the array specifies the type and subtype of a section of 340020131375Smrg * the bo, and the past-the-end offset of that section. The elements 340120131375Smrg * of \c annotations must be sorted so that ending_offset is 340220131375Smrg * increasing. 340320131375Smrg * 340420131375Smrg * \param count is the number of elements in the \c annotations array. 340520131375Smrg * If \c count is zero, then \c annotations will not be dereferenced. 340620131375Smrg * 340720131375Smrg * Annotations are copied into a private data structure, so caller may 340820131375Smrg * re-use the memory pointed to by \c annotations after the call 340920131375Smrg * returns. 341020131375Smrg * 341120131375Smrg * Annotations are stored for the lifetime of the bo; to reset to the 341220131375Smrg * default state (no annotations), call this function with a \c count 341320131375Smrg * of zero. 341420131375Smrg */ 34156260e5d5Smrgdrm_public void drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo, 341620131375Smrg drm_intel_aub_annotation *annotations, 341720131375Smrg unsigned count) 341820131375Smrg{ 341920131375Smrg} 342020131375Smrg 3421a884aba1Smrgstatic pthread_mutex_t bufmgr_list_mutex = PTHREAD_MUTEX_INITIALIZER; 3422a884aba1Smrgstatic drmMMListHead bufmgr_list = { &bufmgr_list, &bufmgr_list }; 3423a884aba1Smrg 3424a884aba1Smrgstatic drm_intel_bufmgr_gem * 3425a884aba1Smrgdrm_intel_bufmgr_gem_find(int fd) 3426a884aba1Smrg{ 3427a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem; 3428a884aba1Smrg 3429a884aba1Smrg DRMLISTFOREACHENTRY(bufmgr_gem, &bufmgr_list, managers) { 3430a884aba1Smrg if (bufmgr_gem->fd == fd) { 3431a884aba1Smrg atomic_inc(&bufmgr_gem->refcount); 3432a884aba1Smrg return bufmgr_gem; 3433a884aba1Smrg } 3434a884aba1Smrg } 3435a884aba1Smrg 3436a884aba1Smrg return NULL; 3437a884aba1Smrg} 3438a884aba1Smrg 3439a884aba1Smrgstatic void 3440a884aba1Smrgdrm_intel_bufmgr_gem_unref(drm_intel_bufmgr *bufmgr) 3441a884aba1Smrg{ 3442a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 3443a884aba1Smrg 3444a884aba1Smrg if (atomic_add_unless(&bufmgr_gem->refcount, -1, 1)) { 3445a884aba1Smrg pthread_mutex_lock(&bufmgr_list_mutex); 3446a884aba1Smrg 3447a884aba1Smrg if (atomic_dec_and_test(&bufmgr_gem->refcount)) { 3448a884aba1Smrg DRMLISTDEL(&bufmgr_gem->managers); 3449a884aba1Smrg drm_intel_bufmgr_gem_destroy(bufmgr); 3450a884aba1Smrg } 3451a884aba1Smrg 3452a884aba1Smrg pthread_mutex_unlock(&bufmgr_list_mutex); 3453a884aba1Smrg } 3454a884aba1Smrg} 3455a884aba1Smrg 34566260e5d5Smrgdrm_public void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo) 34572ee35494Smrg{ 34582ee35494Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 34592ee35494Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 34602ee35494Smrg 34612ee35494Smrg if (bo_gem->gtt_virtual) 34622ee35494Smrg return bo_gem->gtt_virtual; 34632ee35494Smrg 34642ee35494Smrg if (bo_gem->is_userptr) 34652ee35494Smrg return NULL; 34662ee35494Smrg 34672ee35494Smrg pthread_mutex_lock(&bufmgr_gem->lock); 34682ee35494Smrg if (bo_gem->gtt_virtual == NULL) { 34692ee35494Smrg struct drm_i915_gem_mmap_gtt mmap_arg; 34702ee35494Smrg void *ptr; 34712ee35494Smrg 34722ee35494Smrg DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n", 34732ee35494Smrg bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 34742ee35494Smrg 34752ee35494Smrg if (bo_gem->map_count++ == 0) 34762ee35494Smrg drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 34772ee35494Smrg 34782ee35494Smrg memclear(mmap_arg); 34792ee35494Smrg mmap_arg.handle = bo_gem->gem_handle; 34802ee35494Smrg 34812ee35494Smrg /* Get the fake offset back... */ 34822ee35494Smrg ptr = MAP_FAILED; 34832ee35494Smrg if (drmIoctl(bufmgr_gem->fd, 34842ee35494Smrg DRM_IOCTL_I915_GEM_MMAP_GTT, 34852ee35494Smrg &mmap_arg) == 0) { 34862ee35494Smrg /* and mmap it */ 34872ee35494Smrg ptr = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, 34882ee35494Smrg MAP_SHARED, bufmgr_gem->fd, 34892ee35494Smrg mmap_arg.offset); 34902ee35494Smrg } 34912ee35494Smrg if (ptr == MAP_FAILED) { 34922ee35494Smrg if (--bo_gem->map_count == 0) 34932ee35494Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 34942ee35494Smrg ptr = NULL; 34952ee35494Smrg } 34962ee35494Smrg 34972ee35494Smrg bo_gem->gtt_virtual = ptr; 34982ee35494Smrg } 34992ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 35002ee35494Smrg 35012ee35494Smrg return bo_gem->gtt_virtual; 35022ee35494Smrg} 35032ee35494Smrg 35046260e5d5Smrgdrm_public void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo) 35052ee35494Smrg{ 35062ee35494Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 35072ee35494Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 35082ee35494Smrg 35092ee35494Smrg if (bo_gem->mem_virtual) 35102ee35494Smrg return bo_gem->mem_virtual; 35112ee35494Smrg 35122ee35494Smrg if (bo_gem->is_userptr) { 35132ee35494Smrg /* Return the same user ptr */ 35142ee35494Smrg return bo_gem->user_virtual; 35152ee35494Smrg } 35162ee35494Smrg 35172ee35494Smrg pthread_mutex_lock(&bufmgr_gem->lock); 35182ee35494Smrg if (!bo_gem->mem_virtual) { 35192ee35494Smrg struct drm_i915_gem_mmap mmap_arg; 35202ee35494Smrg 35212ee35494Smrg if (bo_gem->map_count++ == 0) 35222ee35494Smrg drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 35232ee35494Smrg 35242ee35494Smrg DBG("bo_map: %d (%s), map_count=%d\n", 35252ee35494Smrg bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 35262ee35494Smrg 35272ee35494Smrg memclear(mmap_arg); 35282ee35494Smrg mmap_arg.handle = bo_gem->gem_handle; 35292ee35494Smrg mmap_arg.size = bo->size; 35302ee35494Smrg if (drmIoctl(bufmgr_gem->fd, 35312ee35494Smrg DRM_IOCTL_I915_GEM_MMAP, 35322ee35494Smrg &mmap_arg)) { 35332ee35494Smrg DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 35342ee35494Smrg __FILE__, __LINE__, bo_gem->gem_handle, 35352ee35494Smrg bo_gem->name, strerror(errno)); 35362ee35494Smrg if (--bo_gem->map_count == 0) 35372ee35494Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 35382ee35494Smrg } else { 35392ee35494Smrg VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1)); 35402ee35494Smrg bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr; 35412ee35494Smrg } 35422ee35494Smrg } 35432ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 35442ee35494Smrg 35452ee35494Smrg return bo_gem->mem_virtual; 35462ee35494Smrg} 35472ee35494Smrg 35486260e5d5Smrgdrm_public void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo) 35492ee35494Smrg{ 35502ee35494Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 35512ee35494Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 35522ee35494Smrg 35532ee35494Smrg if (bo_gem->wc_virtual) 35542ee35494Smrg return bo_gem->wc_virtual; 35552ee35494Smrg 35562ee35494Smrg if (bo_gem->is_userptr) 35572ee35494Smrg return NULL; 35582ee35494Smrg 35592ee35494Smrg pthread_mutex_lock(&bufmgr_gem->lock); 35602ee35494Smrg if (!bo_gem->wc_virtual) { 35612ee35494Smrg struct drm_i915_gem_mmap mmap_arg; 35622ee35494Smrg 35632ee35494Smrg if (bo_gem->map_count++ == 0) 35642ee35494Smrg drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 35652ee35494Smrg 35662ee35494Smrg DBG("bo_map: %d (%s), map_count=%d\n", 35672ee35494Smrg bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 35682ee35494Smrg 35692ee35494Smrg memclear(mmap_arg); 35702ee35494Smrg mmap_arg.handle = bo_gem->gem_handle; 35712ee35494Smrg mmap_arg.size = bo->size; 35722ee35494Smrg mmap_arg.flags = I915_MMAP_WC; 35732ee35494Smrg if (drmIoctl(bufmgr_gem->fd, 35742ee35494Smrg DRM_IOCTL_I915_GEM_MMAP, 35752ee35494Smrg &mmap_arg)) { 35762ee35494Smrg DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 35772ee35494Smrg __FILE__, __LINE__, bo_gem->gem_handle, 35782ee35494Smrg bo_gem->name, strerror(errno)); 35792ee35494Smrg if (--bo_gem->map_count == 0) 35802ee35494Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 35812ee35494Smrg } else { 35822ee35494Smrg VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1)); 35832ee35494Smrg bo_gem->wc_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr; 35842ee35494Smrg } 35852ee35494Smrg } 35862ee35494Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 35872ee35494Smrg 35882ee35494Smrg return bo_gem->wc_virtual; 35892ee35494Smrg} 35902ee35494Smrg 359122944501Smrg/** 359222944501Smrg * Initializes the GEM buffer manager, which uses the kernel to allocate, map, 359322944501Smrg * and manage map buffer objections. 359422944501Smrg * 359522944501Smrg * \param fd File descriptor of the opened DRM device. 359622944501Smrg */ 35976260e5d5Smrgdrm_public drm_intel_bufmgr * 359822944501Smrgdrm_intel_bufmgr_gem_init(int fd, int batch_size) 359922944501Smrg{ 360022944501Smrg drm_intel_bufmgr_gem *bufmgr_gem; 360122944501Smrg struct drm_i915_gem_get_aperture aperture; 360222944501Smrg drm_i915_getparam_t gp; 360320131375Smrg int ret, tmp; 360420131375Smrg bool exec2 = false; 360522944501Smrg 3606a884aba1Smrg pthread_mutex_lock(&bufmgr_list_mutex); 3607a884aba1Smrg 3608a884aba1Smrg bufmgr_gem = drm_intel_bufmgr_gem_find(fd); 3609a884aba1Smrg if (bufmgr_gem) 3610a884aba1Smrg goto exit; 3611a884aba1Smrg 361222944501Smrg bufmgr_gem = calloc(1, sizeof(*bufmgr_gem)); 361322944501Smrg if (bufmgr_gem == NULL) 3614a884aba1Smrg goto exit; 361522944501Smrg 361622944501Smrg bufmgr_gem->fd = fd; 3617a884aba1Smrg atomic_set(&bufmgr_gem->refcount, 1); 361822944501Smrg 361922944501Smrg if (pthread_mutex_init(&bufmgr_gem->lock, NULL) != 0) { 362022944501Smrg free(bufmgr_gem); 3621a884aba1Smrg bufmgr_gem = NULL; 3622a884aba1Smrg goto exit; 362322944501Smrg } 362422944501Smrg 3625424e9256Smrg memclear(aperture); 36266d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 36276d98c517Smrg DRM_IOCTL_I915_GEM_GET_APERTURE, 36286d98c517Smrg &aperture); 362922944501Smrg 363022944501Smrg if (ret == 0) 363122944501Smrg bufmgr_gem->gtt_size = aperture.aper_available_size; 363222944501Smrg else { 363322944501Smrg fprintf(stderr, "DRM_IOCTL_I915_GEM_APERTURE failed: %s\n", 363422944501Smrg strerror(errno)); 363522944501Smrg bufmgr_gem->gtt_size = 128 * 1024 * 1024; 363622944501Smrg fprintf(stderr, "Assuming %dkB available aperture size.\n" 363722944501Smrg "May lead to reduced performance or incorrect " 363822944501Smrg "rendering.\n", 363922944501Smrg (int)bufmgr_gem->gtt_size / 1024); 364022944501Smrg } 364122944501Smrg 364220131375Smrg bufmgr_gem->pci_device = get_pci_device_id(bufmgr_gem); 364322944501Smrg 364420131375Smrg if (IS_GEN2(bufmgr_gem->pci_device)) 364522944501Smrg bufmgr_gem->gen = 2; 364620131375Smrg else if (IS_GEN3(bufmgr_gem->pci_device)) 364722944501Smrg bufmgr_gem->gen = 3; 364820131375Smrg else if (IS_GEN4(bufmgr_gem->pci_device)) 364922944501Smrg bufmgr_gem->gen = 4; 365020131375Smrg else if (IS_GEN5(bufmgr_gem->pci_device)) 365120131375Smrg bufmgr_gem->gen = 5; 365220131375Smrg else if (IS_GEN6(bufmgr_gem->pci_device)) 365322944501Smrg bufmgr_gem->gen = 6; 365420131375Smrg else if (IS_GEN7(bufmgr_gem->pci_device)) 365520131375Smrg bufmgr_gem->gen = 7; 365620131375Smrg else if (IS_GEN8(bufmgr_gem->pci_device)) 365720131375Smrg bufmgr_gem->gen = 8; 36586260e5d5Smrg else if (!intel_get_genx(bufmgr_gem->pci_device, &bufmgr_gem->gen)) { 365920131375Smrg free(bufmgr_gem); 3660a884aba1Smrg bufmgr_gem = NULL; 3661a884aba1Smrg goto exit; 366220131375Smrg } 366320131375Smrg 366420131375Smrg if (IS_GEN3(bufmgr_gem->pci_device) && 366520131375Smrg bufmgr_gem->gtt_size > 256*1024*1024) { 366620131375Smrg /* The unmappable part of gtt on gen 3 (i.e. above 256MB) can't 366720131375Smrg * be used for tiled blits. To simplify the accounting, just 3668fe517fc9Smrg * subtract the unmappable part (fixed to 256MB on all known 366920131375Smrg * gen3 devices) if the kernel advertises it. */ 367020131375Smrg bufmgr_gem->gtt_size -= 256*1024*1024; 367120131375Smrg } 367220131375Smrg 3673424e9256Smrg memclear(gp); 367420131375Smrg gp.value = &tmp; 367522944501Smrg 367622944501Smrg gp.param = I915_PARAM_HAS_EXECBUF2; 36776d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 367822944501Smrg if (!ret) 367920131375Smrg exec2 = true; 368022944501Smrg 3681aaba2545Smrg gp.param = I915_PARAM_HAS_BSD; 36826d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 36839ce4edccSmrg bufmgr_gem->has_bsd = ret == 0; 36849ce4edccSmrg 36859ce4edccSmrg gp.param = I915_PARAM_HAS_BLT; 36869ce4edccSmrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 36879ce4edccSmrg bufmgr_gem->has_blt = ret == 0; 36889ce4edccSmrg 36899ce4edccSmrg gp.param = I915_PARAM_HAS_RELAXED_FENCING; 36909ce4edccSmrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 36919ce4edccSmrg bufmgr_gem->has_relaxed_fencing = ret == 0; 3692aaba2545Smrg 36932ee35494Smrg gp.param = I915_PARAM_HAS_EXEC_ASYNC; 36942ee35494Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 36952ee35494Smrg bufmgr_gem->has_exec_async = ret == 0; 36962ee35494Smrg 3697424e9256Smrg bufmgr_gem->bufmgr.bo_alloc_userptr = check_bo_alloc_userptr; 3698a884aba1Smrg 369920131375Smrg gp.param = I915_PARAM_HAS_WAIT_TIMEOUT; 370020131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 370120131375Smrg bufmgr_gem->has_wait_timeout = ret == 0; 370220131375Smrg 370320131375Smrg gp.param = I915_PARAM_HAS_LLC; 370420131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 370520131375Smrg if (ret != 0) { 370620131375Smrg /* Kernel does not supports HAS_LLC query, fallback to GPU 370720131375Smrg * generation detection and assume that we have LLC on GEN6/7 370820131375Smrg */ 370920131375Smrg bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) | 371020131375Smrg IS_GEN7(bufmgr_gem->pci_device)); 371120131375Smrg } else 371220131375Smrg bufmgr_gem->has_llc = *gp.value; 371320131375Smrg 371420131375Smrg gp.param = I915_PARAM_HAS_VEBOX; 371520131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 371620131375Smrg bufmgr_gem->has_vebox = (ret == 0) & (*gp.value > 0); 371720131375Smrg 3718fe517fc9Smrg gp.param = I915_PARAM_HAS_EXEC_SOFTPIN; 3719fe517fc9Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3720fe517fc9Smrg if (ret == 0 && *gp.value > 0) 3721fe517fc9Smrg bufmgr_gem->bufmgr.bo_set_softpin_offset = drm_intel_gem_bo_set_softpin_offset; 3722fe517fc9Smrg 372322944501Smrg if (bufmgr_gem->gen < 4) { 372422944501Smrg gp.param = I915_PARAM_NUM_FENCES_AVAIL; 372522944501Smrg gp.value = &bufmgr_gem->available_fences; 37266d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 372722944501Smrg if (ret) { 372822944501Smrg fprintf(stderr, "get fences failed: %d [%d]\n", ret, 372922944501Smrg errno); 373022944501Smrg fprintf(stderr, "param: %d, val: %d\n", gp.param, 373122944501Smrg *gp.value); 373222944501Smrg bufmgr_gem->available_fences = 0; 373322944501Smrg } else { 373422944501Smrg /* XXX The kernel reports the total number of fences, 373522944501Smrg * including any that may be pinned. 373622944501Smrg * 373722944501Smrg * We presume that there will be at least one pinned 373822944501Smrg * fence for the scanout buffer, but there may be more 373922944501Smrg * than one scanout and the user may be manually 374022944501Smrg * pinning buffers. Let's move to execbuffer2 and 374122944501Smrg * thereby forget the insanity of using fences... 374222944501Smrg */ 374322944501Smrg bufmgr_gem->available_fences -= 2; 374422944501Smrg if (bufmgr_gem->available_fences < 0) 374522944501Smrg bufmgr_gem->available_fences = 0; 374622944501Smrg } 374722944501Smrg } 374822944501Smrg 3749fe517fc9Smrg if (bufmgr_gem->gen >= 8) { 3750fe517fc9Smrg gp.param = I915_PARAM_HAS_ALIASING_PPGTT; 3751fe517fc9Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3752fe517fc9Smrg if (ret == 0 && *gp.value == 3) 3753fe517fc9Smrg bufmgr_gem->bufmgr.bo_use_48b_address_range = drm_intel_gem_bo_use_48b_address_range; 3754fe517fc9Smrg } 3755fe517fc9Smrg 375622944501Smrg /* Let's go with one relocation per every 2 dwords (but round down a bit 375722944501Smrg * since a power of two will mean an extra page allocation for the reloc 375822944501Smrg * buffer). 375922944501Smrg * 376022944501Smrg * Every 4 was too few for the blender benchmark. 376122944501Smrg */ 376222944501Smrg bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2; 376322944501Smrg 376422944501Smrg bufmgr_gem->bufmgr.bo_alloc = drm_intel_gem_bo_alloc; 376522944501Smrg bufmgr_gem->bufmgr.bo_alloc_for_render = 376622944501Smrg drm_intel_gem_bo_alloc_for_render; 376722944501Smrg bufmgr_gem->bufmgr.bo_alloc_tiled = drm_intel_gem_bo_alloc_tiled; 376822944501Smrg bufmgr_gem->bufmgr.bo_reference = drm_intel_gem_bo_reference; 376922944501Smrg bufmgr_gem->bufmgr.bo_unreference = drm_intel_gem_bo_unreference; 377022944501Smrg bufmgr_gem->bufmgr.bo_map = drm_intel_gem_bo_map; 377122944501Smrg bufmgr_gem->bufmgr.bo_unmap = drm_intel_gem_bo_unmap; 377222944501Smrg bufmgr_gem->bufmgr.bo_subdata = drm_intel_gem_bo_subdata; 377322944501Smrg bufmgr_gem->bufmgr.bo_get_subdata = drm_intel_gem_bo_get_subdata; 377422944501Smrg bufmgr_gem->bufmgr.bo_wait_rendering = drm_intel_gem_bo_wait_rendering; 377522944501Smrg bufmgr_gem->bufmgr.bo_emit_reloc = drm_intel_gem_bo_emit_reloc; 377622944501Smrg bufmgr_gem->bufmgr.bo_emit_reloc_fence = drm_intel_gem_bo_emit_reloc_fence; 377722944501Smrg bufmgr_gem->bufmgr.bo_pin = drm_intel_gem_bo_pin; 377822944501Smrg bufmgr_gem->bufmgr.bo_unpin = drm_intel_gem_bo_unpin; 377922944501Smrg bufmgr_gem->bufmgr.bo_get_tiling = drm_intel_gem_bo_get_tiling; 378022944501Smrg bufmgr_gem->bufmgr.bo_set_tiling = drm_intel_gem_bo_set_tiling; 378122944501Smrg bufmgr_gem->bufmgr.bo_flink = drm_intel_gem_bo_flink; 378222944501Smrg /* Use the new one if available */ 3783aaba2545Smrg if (exec2) { 378422944501Smrg bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec2; 37859ce4edccSmrg bufmgr_gem->bufmgr.bo_mrb_exec = drm_intel_gem_bo_mrb_exec2; 3786aaba2545Smrg } else 378722944501Smrg bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec; 378822944501Smrg bufmgr_gem->bufmgr.bo_busy = drm_intel_gem_bo_busy; 378922944501Smrg bufmgr_gem->bufmgr.bo_madvise = drm_intel_gem_bo_madvise; 3790a884aba1Smrg bufmgr_gem->bufmgr.destroy = drm_intel_bufmgr_gem_unref; 379122944501Smrg bufmgr_gem->bufmgr.debug = 0; 379222944501Smrg bufmgr_gem->bufmgr.check_aperture_space = 379322944501Smrg drm_intel_gem_check_aperture_space; 379422944501Smrg bufmgr_gem->bufmgr.bo_disable_reuse = drm_intel_gem_bo_disable_reuse; 3795aaba2545Smrg bufmgr_gem->bufmgr.bo_is_reusable = drm_intel_gem_bo_is_reusable; 379622944501Smrg bufmgr_gem->bufmgr.get_pipe_from_crtc_id = 379722944501Smrg drm_intel_gem_get_pipe_from_crtc_id; 379822944501Smrg bufmgr_gem->bufmgr.bo_references = drm_intel_gem_bo_references; 379922944501Smrg 3800aaba2545Smrg init_cache_buckets(bufmgr_gem); 380122944501Smrg 380220131375Smrg DRMINITLISTHEAD(&bufmgr_gem->vma_cache); 380320131375Smrg bufmgr_gem->vma_max = -1; /* unlimited by default */ 380420131375Smrg 3805a884aba1Smrg DRMLISTADD(&bufmgr_gem->managers, &bufmgr_list); 3806a884aba1Smrg 3807a884aba1Smrgexit: 3808a884aba1Smrg pthread_mutex_unlock(&bufmgr_list_mutex); 3809a884aba1Smrg 3810a884aba1Smrg return bufmgr_gem != NULL ? &bufmgr_gem->bufmgr : NULL; 381122944501Smrg} 3812