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