intel_bufmgr_gem.c revision fe517fc9
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" 6822944501Smrg 6920131375Smrg#ifdef HAVE_VALGRIND 7020131375Smrg#include <valgrind.h> 7120131375Smrg#include <memcheck.h> 7220131375Smrg#define VG(x) x 7320131375Smrg#else 7420131375Smrg#define VG(x) 7520131375Smrg#endif 7620131375Smrg 77424e9256Smrg#define memclear(s) memset(&s, 0, sizeof(s)) 7820131375Smrg 7922944501Smrg#define DBG(...) do { \ 8022944501Smrg if (bufmgr_gem->bufmgr.debug) \ 8122944501Smrg fprintf(stderr, __VA_ARGS__); \ 8222944501Smrg} while (0) 8322944501Smrg 84aaba2545Smrg#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 85fe517fc9Smrg#define MAX2(A, B) ((A) > (B) ? (A) : (B)) 86fe517fc9Smrg 87fe517fc9Smrg/** 88fe517fc9Smrg * upper_32_bits - return bits 32-63 of a number 89fe517fc9Smrg * @n: the number we're accessing 90fe517fc9Smrg * 91fe517fc9Smrg * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress 92fe517fc9Smrg * the "right shift count >= width of type" warning when that quantity is 93fe517fc9Smrg * 32-bits. 94fe517fc9Smrg */ 95fe517fc9Smrg#define upper_32_bits(n) ((__u32)(((n) >> 16) >> 16)) 96fe517fc9Smrg 97fe517fc9Smrg/** 98fe517fc9Smrg * lower_32_bits - return bits 0-31 of a number 99fe517fc9Smrg * @n: the number we're accessing 100fe517fc9Smrg */ 101fe517fc9Smrg#define lower_32_bits(n) ((__u32)(n)) 102aaba2545Smrg 10322944501Smrgtypedef struct _drm_intel_bo_gem drm_intel_bo_gem; 10422944501Smrg 10522944501Smrgstruct drm_intel_gem_bo_bucket { 10622944501Smrg drmMMListHead head; 10722944501Smrg unsigned long size; 10822944501Smrg}; 10922944501Smrg 11022944501Smrgtypedef struct _drm_intel_bufmgr_gem { 11122944501Smrg drm_intel_bufmgr bufmgr; 11222944501Smrg 113a884aba1Smrg atomic_t refcount; 114a884aba1Smrg 11522944501Smrg int fd; 11622944501Smrg 11722944501Smrg int max_relocs; 11822944501Smrg 11922944501Smrg pthread_mutex_t lock; 12022944501Smrg 12122944501Smrg struct drm_i915_gem_exec_object *exec_objects; 12222944501Smrg struct drm_i915_gem_exec_object2 *exec2_objects; 12322944501Smrg drm_intel_bo **exec_bos; 12422944501Smrg int exec_size; 12522944501Smrg int exec_count; 12622944501Smrg 12722944501Smrg /** Array of lists of cached gem objects of power-of-two sizes */ 128aaba2545Smrg struct drm_intel_gem_bo_bucket cache_bucket[14 * 4]; 129aaba2545Smrg int num_buckets; 1306d98c517Smrg time_t time; 13122944501Smrg 132a884aba1Smrg drmMMListHead managers; 133a884aba1Smrg 13420131375Smrg drmMMListHead named; 13520131375Smrg drmMMListHead vma_cache; 13620131375Smrg int vma_count, vma_open, vma_max; 13720131375Smrg 13822944501Smrg uint64_t gtt_size; 13922944501Smrg int available_fences; 14022944501Smrg int pci_device; 14122944501Smrg int gen; 1429ce4edccSmrg unsigned int has_bsd : 1; 1439ce4edccSmrg unsigned int has_blt : 1; 1449ce4edccSmrg unsigned int has_relaxed_fencing : 1; 14520131375Smrg unsigned int has_llc : 1; 14620131375Smrg unsigned int has_wait_timeout : 1; 1479ce4edccSmrg unsigned int bo_reuse : 1; 14820131375Smrg unsigned int no_exec : 1; 14920131375Smrg unsigned int has_vebox : 1; 15020131375Smrg bool fenced_relocs; 15120131375Smrg 152424e9256Smrg struct { 153424e9256Smrg void *ptr; 154424e9256Smrg uint32_t handle; 155424e9256Smrg } userptr_active; 156424e9256Smrg 15722944501Smrg} drm_intel_bufmgr_gem; 15822944501Smrg 15922944501Smrg#define DRM_INTEL_RELOC_FENCE (1<<0) 16022944501Smrg 16122944501Smrgtypedef struct _drm_intel_reloc_target_info { 16222944501Smrg drm_intel_bo *bo; 16322944501Smrg int flags; 16422944501Smrg} drm_intel_reloc_target; 16522944501Smrg 16622944501Smrgstruct _drm_intel_bo_gem { 16722944501Smrg drm_intel_bo bo; 16822944501Smrg 16922944501Smrg atomic_t refcount; 17022944501Smrg uint32_t gem_handle; 17122944501Smrg const char *name; 17222944501Smrg 17322944501Smrg /** 17422944501Smrg * Kenel-assigned global name for this object 17520131375Smrg * 17620131375Smrg * List contains both flink named and prime fd'd objects 17722944501Smrg */ 17822944501Smrg unsigned int global_name; 17920131375Smrg drmMMListHead name_list; 18022944501Smrg 18122944501Smrg /** 18222944501Smrg * Index of the buffer within the validation list while preparing a 18322944501Smrg * batchbuffer execution. 18422944501Smrg */ 18522944501Smrg int validate_index; 18622944501Smrg 18722944501Smrg /** 18822944501Smrg * Current tiling mode 18922944501Smrg */ 19022944501Smrg uint32_t tiling_mode; 19122944501Smrg uint32_t swizzle_mode; 1926d98c517Smrg unsigned long stride; 19322944501Smrg 19422944501Smrg time_t free_time; 19522944501Smrg 19622944501Smrg /** Array passed to the DRM containing relocation information. */ 19722944501Smrg struct drm_i915_gem_relocation_entry *relocs; 19822944501Smrg /** 19922944501Smrg * Array of info structs corresponding to relocs[i].target_handle etc 20022944501Smrg */ 20122944501Smrg drm_intel_reloc_target *reloc_target_info; 20222944501Smrg /** Number of entries in relocs */ 20322944501Smrg int reloc_count; 204fe517fc9Smrg /** Array of BOs that are referenced by this buffer and will be softpinned */ 205fe517fc9Smrg drm_intel_bo **softpin_target; 206fe517fc9Smrg /** Number softpinned BOs that are referenced by this buffer */ 207fe517fc9Smrg int softpin_target_count; 208fe517fc9Smrg /** Maximum amount of softpinned BOs that are referenced by this buffer */ 209fe517fc9Smrg int softpin_target_size; 210fe517fc9Smrg 21122944501Smrg /** Mapped address for the buffer, saved across map/unmap cycles */ 21222944501Smrg void *mem_virtual; 21322944501Smrg /** GTT virtual address for the buffer, saved across map/unmap cycles */ 21422944501Smrg void *gtt_virtual; 215a884aba1Smrg /** 216a884aba1Smrg * Virtual address of the buffer allocated by user, used for userptr 217a884aba1Smrg * objects only. 218a884aba1Smrg */ 219a884aba1Smrg void *user_virtual; 22020131375Smrg int map_count; 22120131375Smrg drmMMListHead vma_list; 22222944501Smrg 22322944501Smrg /** BO cache list */ 22422944501Smrg drmMMListHead head; 22522944501Smrg 22622944501Smrg /** 22722944501Smrg * Boolean of whether this BO and its children have been included in 22822944501Smrg * the current drm_intel_bufmgr_check_aperture_space() total. 22922944501Smrg */ 23020131375Smrg bool included_in_check_aperture; 23122944501Smrg 23222944501Smrg /** 23322944501Smrg * Boolean of whether this buffer has been used as a relocation 23422944501Smrg * target and had its size accounted for, and thus can't have any 23522944501Smrg * further relocations added to it. 23622944501Smrg */ 23720131375Smrg bool used_as_reloc_target; 23822944501Smrg 23922944501Smrg /** 24022944501Smrg * Boolean of whether we have encountered an error whilst building the relocation tree. 24122944501Smrg */ 24220131375Smrg bool has_error; 24322944501Smrg 24422944501Smrg /** 24522944501Smrg * Boolean of whether this buffer can be re-used 24622944501Smrg */ 24720131375Smrg bool reusable; 24820131375Smrg 24920131375Smrg /** 25020131375Smrg * Boolean of whether the GPU is definitely not accessing the buffer. 25120131375Smrg * 25220131375Smrg * This is only valid when reusable, since non-reusable 25320131375Smrg * buffers are those that have been shared wth other 25420131375Smrg * processes, so we don't know their state. 25520131375Smrg */ 25620131375Smrg bool idle; 25722944501Smrg 258a884aba1Smrg /** 259a884aba1Smrg * Boolean of whether this buffer was allocated with userptr 260a884aba1Smrg */ 261a884aba1Smrg bool is_userptr; 262a884aba1Smrg 263fe517fc9Smrg /** 264fe517fc9Smrg * Boolean of whether this buffer can be placed in the full 48-bit 265fe517fc9Smrg * address range on gen8+. 266fe517fc9Smrg * 267fe517fc9Smrg * By default, buffers will be keep in a 32-bit range, unless this 268fe517fc9Smrg * flag is explicitly set. 269fe517fc9Smrg */ 270fe517fc9Smrg bool use_48b_address_range; 271fe517fc9Smrg 272fe517fc9Smrg /** 273fe517fc9Smrg * Whether this buffer is softpinned at offset specified by the user 274fe517fc9Smrg */ 275fe517fc9Smrg bool is_softpin; 276fe517fc9Smrg 27722944501Smrg /** 27822944501Smrg * Size in bytes of this buffer and its relocation descendents. 27922944501Smrg * 28022944501Smrg * Used to avoid costly tree walking in 28122944501Smrg * drm_intel_bufmgr_check_aperture in the common case. 28222944501Smrg */ 28322944501Smrg int reloc_tree_size; 28422944501Smrg 28522944501Smrg /** 28622944501Smrg * Number of potential fence registers required by this buffer and its 28722944501Smrg * relocations. 28822944501Smrg */ 28922944501Smrg int reloc_tree_fences; 29020131375Smrg 29120131375Smrg /** Flags that we may need to do the SW_FINSIH ioctl on unmap. */ 29220131375Smrg bool mapped_cpu_write; 29322944501Smrg}; 29422944501Smrg 29522944501Smrgstatic unsigned int 29622944501Smrgdrm_intel_gem_estimate_batch_space(drm_intel_bo ** bo_array, int count); 29722944501Smrg 29822944501Smrgstatic unsigned int 29922944501Smrgdrm_intel_gem_compute_batch_space(drm_intel_bo ** bo_array, int count); 30022944501Smrg 30122944501Smrgstatic int 30222944501Smrgdrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, 30322944501Smrg uint32_t * swizzle_mode); 30422944501Smrg 30522944501Smrgstatic int 3066d98c517Smrgdrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, 3076d98c517Smrg uint32_t tiling_mode, 3086d98c517Smrg uint32_t stride); 30922944501Smrg 31022944501Smrgstatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, 31122944501Smrg time_t time); 31222944501Smrg 31322944501Smrgstatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo); 31422944501Smrg 31522944501Smrgstatic void drm_intel_gem_bo_free(drm_intel_bo *bo); 31622944501Smrg 317fe517fc9Smrgstatic inline drm_intel_bo_gem *to_bo_gem(drm_intel_bo *bo) 318fe517fc9Smrg{ 319fe517fc9Smrg return (drm_intel_bo_gem *)bo; 320fe517fc9Smrg} 321fe517fc9Smrg 32222944501Smrgstatic unsigned long 32322944501Smrgdrm_intel_gem_bo_tile_size(drm_intel_bufmgr_gem *bufmgr_gem, unsigned long size, 32422944501Smrg uint32_t *tiling_mode) 32522944501Smrg{ 32622944501Smrg unsigned long min_size, max_size; 32722944501Smrg unsigned long i; 32822944501Smrg 32922944501Smrg if (*tiling_mode == I915_TILING_NONE) 33022944501Smrg return size; 33122944501Smrg 33222944501Smrg /* 965+ just need multiples of page size for tiling */ 33322944501Smrg if (bufmgr_gem->gen >= 4) 33422944501Smrg return ROUND_UP_TO(size, 4096); 33522944501Smrg 33622944501Smrg /* Older chips need powers of two, of at least 512k or 1M */ 33722944501Smrg if (bufmgr_gem->gen == 3) { 33822944501Smrg min_size = 1024*1024; 33922944501Smrg max_size = 128*1024*1024; 34022944501Smrg } else { 34122944501Smrg min_size = 512*1024; 34222944501Smrg max_size = 64*1024*1024; 34322944501Smrg } 34422944501Smrg 34522944501Smrg if (size > max_size) { 34622944501Smrg *tiling_mode = I915_TILING_NONE; 34722944501Smrg return size; 34822944501Smrg } 34922944501Smrg 3509ce4edccSmrg /* Do we need to allocate every page for the fence? */ 3519ce4edccSmrg if (bufmgr_gem->has_relaxed_fencing) 3529ce4edccSmrg return ROUND_UP_TO(size, 4096); 3539ce4edccSmrg 35422944501Smrg for (i = min_size; i < size; i <<= 1) 35522944501Smrg ; 35622944501Smrg 35722944501Smrg return i; 35822944501Smrg} 35922944501Smrg 36022944501Smrg/* 36122944501Smrg * Round a given pitch up to the minimum required for X tiling on a 36222944501Smrg * given chip. We use 512 as the minimum to allow for a later tiling 36322944501Smrg * change. 36422944501Smrg */ 36522944501Smrgstatic unsigned long 36622944501Smrgdrm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem, 3676d98c517Smrg unsigned long pitch, uint32_t *tiling_mode) 36822944501Smrg{ 36922944501Smrg unsigned long tile_width; 37022944501Smrg unsigned long i; 37122944501Smrg 37222944501Smrg /* If untiled, then just align it so that we can do rendering 37322944501Smrg * to it with the 3D engine. 37422944501Smrg */ 3756d98c517Smrg if (*tiling_mode == I915_TILING_NONE) 37622944501Smrg return ALIGN(pitch, 64); 37722944501Smrg 37820131375Smrg if (*tiling_mode == I915_TILING_X 37920131375Smrg || (IS_915(bufmgr_gem->pci_device) 38020131375Smrg && *tiling_mode == I915_TILING_Y)) 38122944501Smrg tile_width = 512; 38222944501Smrg else 38322944501Smrg tile_width = 128; 38422944501Smrg 38522944501Smrg /* 965 is flexible */ 38622944501Smrg if (bufmgr_gem->gen >= 4) 38722944501Smrg return ROUND_UP_TO(pitch, tile_width); 38822944501Smrg 3896d98c517Smrg /* The older hardware has a maximum pitch of 8192 with tiled 3906d98c517Smrg * surfaces, so fallback to untiled if it's too large. 3916d98c517Smrg */ 3926d98c517Smrg if (pitch > 8192) { 3936d98c517Smrg *tiling_mode = I915_TILING_NONE; 3946d98c517Smrg return ALIGN(pitch, 64); 3956d98c517Smrg } 3966d98c517Smrg 39722944501Smrg /* Pre-965 needs power of two tile width */ 39822944501Smrg for (i = tile_width; i < pitch; i <<= 1) 39922944501Smrg ; 40022944501Smrg 40122944501Smrg return i; 40222944501Smrg} 40322944501Smrg 40422944501Smrgstatic struct drm_intel_gem_bo_bucket * 40522944501Smrgdrm_intel_gem_bo_bucket_for_size(drm_intel_bufmgr_gem *bufmgr_gem, 40622944501Smrg unsigned long size) 40722944501Smrg{ 40822944501Smrg int i; 40922944501Smrg 410aaba2545Smrg for (i = 0; i < bufmgr_gem->num_buckets; i++) { 41122944501Smrg struct drm_intel_gem_bo_bucket *bucket = 41222944501Smrg &bufmgr_gem->cache_bucket[i]; 41322944501Smrg if (bucket->size >= size) { 41422944501Smrg return bucket; 41522944501Smrg } 41622944501Smrg } 41722944501Smrg 41822944501Smrg return NULL; 41922944501Smrg} 42022944501Smrg 42122944501Smrgstatic void 42222944501Smrgdrm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) 42322944501Smrg{ 42422944501Smrg int i, j; 42522944501Smrg 42622944501Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 42722944501Smrg drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; 42822944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 42922944501Smrg 430fe517fc9Smrg if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) { 431fe517fc9Smrg DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle, 432fe517fc9Smrg bo_gem->is_softpin ? "*" : "", 43322944501Smrg bo_gem->name); 43422944501Smrg continue; 43522944501Smrg } 43622944501Smrg 43722944501Smrg for (j = 0; j < bo_gem->reloc_count; j++) { 43822944501Smrg drm_intel_bo *target_bo = bo_gem->reloc_target_info[j].bo; 43922944501Smrg drm_intel_bo_gem *target_gem = 44022944501Smrg (drm_intel_bo_gem *) target_bo; 44122944501Smrg 442fe517fc9Smrg DBG("%2d: %d %s(%s)@0x%08x %08x -> " 443fe517fc9Smrg "%d (%s)@0x%08x %08x + 0x%08x\n", 44422944501Smrg i, 445fe517fc9Smrg bo_gem->gem_handle, 446fe517fc9Smrg bo_gem->is_softpin ? "*" : "", 447fe517fc9Smrg bo_gem->name, 448fe517fc9Smrg upper_32_bits(bo_gem->relocs[j].offset), 449fe517fc9Smrg lower_32_bits(bo_gem->relocs[j].offset), 45022944501Smrg target_gem->gem_handle, 45122944501Smrg target_gem->name, 452fe517fc9Smrg upper_32_bits(target_bo->offset64), 453fe517fc9Smrg lower_32_bits(target_bo->offset64), 45422944501Smrg bo_gem->relocs[j].delta); 45522944501Smrg } 456fe517fc9Smrg 457fe517fc9Smrg for (j = 0; j < bo_gem->softpin_target_count; j++) { 458fe517fc9Smrg drm_intel_bo *target_bo = bo_gem->softpin_target[j]; 459fe517fc9Smrg drm_intel_bo_gem *target_gem = 460fe517fc9Smrg (drm_intel_bo_gem *) target_bo; 461fe517fc9Smrg DBG("%2d: %d %s(%s) -> " 462fe517fc9Smrg "%d *(%s)@0x%08x %08x\n", 463fe517fc9Smrg i, 464fe517fc9Smrg bo_gem->gem_handle, 465fe517fc9Smrg bo_gem->is_softpin ? "*" : "", 466fe517fc9Smrg bo_gem->name, 467fe517fc9Smrg target_gem->gem_handle, 468fe517fc9Smrg target_gem->name, 469fe517fc9Smrg upper_32_bits(target_bo->offset64), 470fe517fc9Smrg lower_32_bits(target_bo->offset64)); 471fe517fc9Smrg } 47222944501Smrg } 47322944501Smrg} 47422944501Smrg 47522944501Smrgstatic inline void 47622944501Smrgdrm_intel_gem_bo_reference(drm_intel_bo *bo) 47722944501Smrg{ 47822944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 47922944501Smrg 48022944501Smrg atomic_inc(&bo_gem->refcount); 48122944501Smrg} 48222944501Smrg 48322944501Smrg/** 48422944501Smrg * Adds the given buffer to the list of buffers to be validated (moved into the 48522944501Smrg * appropriate memory type) with the next batch submission. 48622944501Smrg * 48722944501Smrg * If a buffer is validated multiple times in a batch submission, it ends up 48822944501Smrg * with the intersection of the memory type flags and the union of the 48922944501Smrg * access flags. 49022944501Smrg */ 49122944501Smrgstatic void 49222944501Smrgdrm_intel_add_validate_buffer(drm_intel_bo *bo) 49322944501Smrg{ 49422944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 49522944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 49622944501Smrg int index; 49722944501Smrg 49822944501Smrg if (bo_gem->validate_index != -1) 49922944501Smrg return; 50022944501Smrg 50122944501Smrg /* Extend the array of validation entries as necessary. */ 50222944501Smrg if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) { 50322944501Smrg int new_size = bufmgr_gem->exec_size * 2; 50422944501Smrg 50522944501Smrg if (new_size == 0) 50622944501Smrg new_size = 5; 50722944501Smrg 50822944501Smrg bufmgr_gem->exec_objects = 50922944501Smrg realloc(bufmgr_gem->exec_objects, 51022944501Smrg sizeof(*bufmgr_gem->exec_objects) * new_size); 51122944501Smrg bufmgr_gem->exec_bos = 51222944501Smrg realloc(bufmgr_gem->exec_bos, 51322944501Smrg sizeof(*bufmgr_gem->exec_bos) * new_size); 51422944501Smrg bufmgr_gem->exec_size = new_size; 51522944501Smrg } 51622944501Smrg 51722944501Smrg index = bufmgr_gem->exec_count; 51822944501Smrg bo_gem->validate_index = index; 51922944501Smrg /* Fill in array entry */ 52022944501Smrg bufmgr_gem->exec_objects[index].handle = bo_gem->gem_handle; 52122944501Smrg bufmgr_gem->exec_objects[index].relocation_count = bo_gem->reloc_count; 52222944501Smrg bufmgr_gem->exec_objects[index].relocs_ptr = (uintptr_t) bo_gem->relocs; 523fe517fc9Smrg bufmgr_gem->exec_objects[index].alignment = bo->align; 52422944501Smrg bufmgr_gem->exec_objects[index].offset = 0; 52522944501Smrg bufmgr_gem->exec_bos[index] = bo; 52622944501Smrg bufmgr_gem->exec_count++; 52722944501Smrg} 52822944501Smrg 52922944501Smrgstatic void 53022944501Smrgdrm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence) 53122944501Smrg{ 53222944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; 53322944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; 53422944501Smrg int index; 535fe517fc9Smrg int flags = 0; 536fe517fc9Smrg 537fe517fc9Smrg if (need_fence) 538fe517fc9Smrg flags |= EXEC_OBJECT_NEEDS_FENCE; 539fe517fc9Smrg if (bo_gem->use_48b_address_range) 540fe517fc9Smrg flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; 541fe517fc9Smrg if (bo_gem->is_softpin) 542fe517fc9Smrg flags |= EXEC_OBJECT_PINNED; 54322944501Smrg 54422944501Smrg if (bo_gem->validate_index != -1) { 545fe517fc9Smrg bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags; 54622944501Smrg return; 54722944501Smrg } 54822944501Smrg 54922944501Smrg /* Extend the array of validation entries as necessary. */ 55022944501Smrg if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) { 55122944501Smrg int new_size = bufmgr_gem->exec_size * 2; 55222944501Smrg 55322944501Smrg if (new_size == 0) 55422944501Smrg new_size = 5; 55522944501Smrg 55622944501Smrg bufmgr_gem->exec2_objects = 55722944501Smrg realloc(bufmgr_gem->exec2_objects, 55822944501Smrg sizeof(*bufmgr_gem->exec2_objects) * new_size); 55922944501Smrg bufmgr_gem->exec_bos = 56022944501Smrg realloc(bufmgr_gem->exec_bos, 56122944501Smrg sizeof(*bufmgr_gem->exec_bos) * new_size); 56222944501Smrg bufmgr_gem->exec_size = new_size; 56322944501Smrg } 56422944501Smrg 56522944501Smrg index = bufmgr_gem->exec_count; 56622944501Smrg bo_gem->validate_index = index; 56722944501Smrg /* Fill in array entry */ 56822944501Smrg bufmgr_gem->exec2_objects[index].handle = bo_gem->gem_handle; 56922944501Smrg bufmgr_gem->exec2_objects[index].relocation_count = bo_gem->reloc_count; 57022944501Smrg bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs; 571fe517fc9Smrg bufmgr_gem->exec2_objects[index].alignment = bo->align; 572fe517fc9Smrg bufmgr_gem->exec2_objects[index].offset = bo_gem->is_softpin ? 573fe517fc9Smrg bo->offset64 : 0; 57422944501Smrg bufmgr_gem->exec_bos[index] = bo; 575fe517fc9Smrg bufmgr_gem->exec2_objects[index].flags = flags; 57622944501Smrg bufmgr_gem->exec2_objects[index].rsvd1 = 0; 57722944501Smrg bufmgr_gem->exec2_objects[index].rsvd2 = 0; 57822944501Smrg bufmgr_gem->exec_count++; 57922944501Smrg} 58022944501Smrg 58122944501Smrg#define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \ 58222944501Smrg sizeof(uint32_t)) 58322944501Smrg 58422944501Smrgstatic void 58522944501Smrgdrm_intel_bo_gem_set_in_aperture_size(drm_intel_bufmgr_gem *bufmgr_gem, 586fe517fc9Smrg drm_intel_bo_gem *bo_gem, 587fe517fc9Smrg unsigned int alignment) 58822944501Smrg{ 589fe517fc9Smrg unsigned int size; 59022944501Smrg 59122944501Smrg assert(!bo_gem->used_as_reloc_target); 59222944501Smrg 59322944501Smrg /* The older chipsets are far-less flexible in terms of tiling, 59422944501Smrg * and require tiled buffer to be size aligned in the aperture. 59522944501Smrg * This means that in the worst possible case we will need a hole 59622944501Smrg * twice as large as the object in order for it to fit into the 59722944501Smrg * aperture. Optimal packing is for wimps. 59822944501Smrg */ 59922944501Smrg size = bo_gem->bo.size; 6009ce4edccSmrg if (bufmgr_gem->gen < 4 && bo_gem->tiling_mode != I915_TILING_NONE) { 601fe517fc9Smrg unsigned int min_size; 6029ce4edccSmrg 6039ce4edccSmrg if (bufmgr_gem->has_relaxed_fencing) { 6049ce4edccSmrg if (bufmgr_gem->gen == 3) 6059ce4edccSmrg min_size = 1024*1024; 6069ce4edccSmrg else 6079ce4edccSmrg min_size = 512*1024; 6089ce4edccSmrg 6099ce4edccSmrg while (min_size < size) 6109ce4edccSmrg min_size *= 2; 6119ce4edccSmrg } else 6129ce4edccSmrg min_size = size; 6139ce4edccSmrg 6149ce4edccSmrg /* Account for worst-case alignment. */ 615fe517fc9Smrg alignment = MAX2(alignment, min_size); 6169ce4edccSmrg } 61722944501Smrg 618fe517fc9Smrg bo_gem->reloc_tree_size = size + alignment; 61922944501Smrg} 62022944501Smrg 62122944501Smrgstatic int 62222944501Smrgdrm_intel_setup_reloc_list(drm_intel_bo *bo) 62322944501Smrg{ 62422944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 62522944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 62622944501Smrg unsigned int max_relocs = bufmgr_gem->max_relocs; 62722944501Smrg 62822944501Smrg if (bo->size / 4 < max_relocs) 62922944501Smrg max_relocs = bo->size / 4; 63022944501Smrg 63122944501Smrg bo_gem->relocs = malloc(max_relocs * 63222944501Smrg sizeof(struct drm_i915_gem_relocation_entry)); 63322944501Smrg bo_gem->reloc_target_info = malloc(max_relocs * 634aaba2545Smrg sizeof(drm_intel_reloc_target)); 63522944501Smrg if (bo_gem->relocs == NULL || bo_gem->reloc_target_info == NULL) { 63620131375Smrg bo_gem->has_error = true; 63722944501Smrg 63822944501Smrg free (bo_gem->relocs); 63922944501Smrg bo_gem->relocs = NULL; 64022944501Smrg 64122944501Smrg free (bo_gem->reloc_target_info); 64222944501Smrg bo_gem->reloc_target_info = NULL; 64322944501Smrg 64422944501Smrg return 1; 64522944501Smrg } 64622944501Smrg 64722944501Smrg return 0; 64822944501Smrg} 64922944501Smrg 65022944501Smrgstatic int 65122944501Smrgdrm_intel_gem_bo_busy(drm_intel_bo *bo) 65222944501Smrg{ 65322944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 65422944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 65522944501Smrg struct drm_i915_gem_busy busy; 65622944501Smrg int ret; 65722944501Smrg 65820131375Smrg if (bo_gem->reusable && bo_gem->idle) 65920131375Smrg return false; 66020131375Smrg 661424e9256Smrg memclear(busy); 66222944501Smrg busy.handle = bo_gem->gem_handle; 66322944501Smrg 6646d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy); 66520131375Smrg if (ret == 0) { 66620131375Smrg bo_gem->idle = !busy.busy; 66720131375Smrg return busy.busy; 66820131375Smrg } else { 66920131375Smrg return false; 67020131375Smrg } 67122944501Smrg return (ret == 0 && busy.busy); 67222944501Smrg} 67322944501Smrg 67422944501Smrgstatic int 67522944501Smrgdrm_intel_gem_bo_madvise_internal(drm_intel_bufmgr_gem *bufmgr_gem, 67622944501Smrg drm_intel_bo_gem *bo_gem, int state) 67722944501Smrg{ 67822944501Smrg struct drm_i915_gem_madvise madv; 67922944501Smrg 680424e9256Smrg memclear(madv); 68122944501Smrg madv.handle = bo_gem->gem_handle; 68222944501Smrg madv.madv = state; 68322944501Smrg madv.retained = 1; 6846d98c517Smrg drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv); 68522944501Smrg 68622944501Smrg return madv.retained; 68722944501Smrg} 68822944501Smrg 68922944501Smrgstatic int 69022944501Smrgdrm_intel_gem_bo_madvise(drm_intel_bo *bo, int madv) 69122944501Smrg{ 69222944501Smrg return drm_intel_gem_bo_madvise_internal 69322944501Smrg ((drm_intel_bufmgr_gem *) bo->bufmgr, 69422944501Smrg (drm_intel_bo_gem *) bo, 69522944501Smrg madv); 69622944501Smrg} 69722944501Smrg 69822944501Smrg/* drop the oldest entries that have been purged by the kernel */ 69922944501Smrgstatic void 70022944501Smrgdrm_intel_gem_bo_cache_purge_bucket(drm_intel_bufmgr_gem *bufmgr_gem, 70122944501Smrg struct drm_intel_gem_bo_bucket *bucket) 70222944501Smrg{ 70322944501Smrg while (!DRMLISTEMPTY(&bucket->head)) { 70422944501Smrg drm_intel_bo_gem *bo_gem; 70522944501Smrg 70622944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 70722944501Smrg bucket->head.next, head); 70822944501Smrg if (drm_intel_gem_bo_madvise_internal 70922944501Smrg (bufmgr_gem, bo_gem, I915_MADV_DONTNEED)) 71022944501Smrg break; 71122944501Smrg 71222944501Smrg DRMLISTDEL(&bo_gem->head); 71322944501Smrg drm_intel_gem_bo_free(&bo_gem->bo); 71422944501Smrg } 71522944501Smrg} 71622944501Smrg 71722944501Smrgstatic drm_intel_bo * 71822944501Smrgdrm_intel_gem_bo_alloc_internal(drm_intel_bufmgr *bufmgr, 71922944501Smrg const char *name, 72022944501Smrg unsigned long size, 7216d98c517Smrg unsigned long flags, 7226d98c517Smrg uint32_t tiling_mode, 723fe517fc9Smrg unsigned long stride, 724fe517fc9Smrg unsigned int alignment) 72522944501Smrg{ 72622944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 72722944501Smrg drm_intel_bo_gem *bo_gem; 72822944501Smrg unsigned int page_size = getpagesize(); 72922944501Smrg int ret; 73022944501Smrg struct drm_intel_gem_bo_bucket *bucket; 73120131375Smrg bool alloc_from_cache; 73222944501Smrg unsigned long bo_size; 73320131375Smrg bool for_render = false; 73422944501Smrg 73522944501Smrg if (flags & BO_ALLOC_FOR_RENDER) 73620131375Smrg for_render = true; 73722944501Smrg 73822944501Smrg /* Round the allocated size up to a power of two number of pages. */ 73922944501Smrg bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, size); 74022944501Smrg 74122944501Smrg /* If we don't have caching at this size, don't actually round the 74222944501Smrg * allocation up. 74322944501Smrg */ 74422944501Smrg if (bucket == NULL) { 74522944501Smrg bo_size = size; 74622944501Smrg if (bo_size < page_size) 74722944501Smrg bo_size = page_size; 74822944501Smrg } else { 74922944501Smrg bo_size = bucket->size; 75022944501Smrg } 75122944501Smrg 75222944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 75322944501Smrg /* Get a buffer out of the cache if available */ 75422944501Smrgretry: 75520131375Smrg alloc_from_cache = false; 75622944501Smrg if (bucket != NULL && !DRMLISTEMPTY(&bucket->head)) { 75722944501Smrg if (for_render) { 75822944501Smrg /* Allocate new render-target BOs from the tail (MRU) 75922944501Smrg * of the list, as it will likely be hot in the GPU 76022944501Smrg * cache and in the aperture for us. 76122944501Smrg */ 76222944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 76322944501Smrg bucket->head.prev, head); 76422944501Smrg DRMLISTDEL(&bo_gem->head); 76520131375Smrg alloc_from_cache = true; 766fe517fc9Smrg bo_gem->bo.align = alignment; 76722944501Smrg } else { 768fe517fc9Smrg assert(alignment == 0); 76922944501Smrg /* For non-render-target BOs (where we're probably 77022944501Smrg * going to map it first thing in order to fill it 77122944501Smrg * with data), check if the last BO in the cache is 77222944501Smrg * unbusy, and only reuse in that case. Otherwise, 77322944501Smrg * allocating a new buffer is probably faster than 77422944501Smrg * waiting for the GPU to finish. 77522944501Smrg */ 77622944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 77722944501Smrg bucket->head.next, head); 77822944501Smrg if (!drm_intel_gem_bo_busy(&bo_gem->bo)) { 77920131375Smrg alloc_from_cache = true; 78022944501Smrg DRMLISTDEL(&bo_gem->head); 78122944501Smrg } 78222944501Smrg } 78322944501Smrg 78422944501Smrg if (alloc_from_cache) { 78522944501Smrg if (!drm_intel_gem_bo_madvise_internal 78622944501Smrg (bufmgr_gem, bo_gem, I915_MADV_WILLNEED)) { 78722944501Smrg drm_intel_gem_bo_free(&bo_gem->bo); 78822944501Smrg drm_intel_gem_bo_cache_purge_bucket(bufmgr_gem, 78922944501Smrg bucket); 79022944501Smrg goto retry; 79122944501Smrg } 7926d98c517Smrg 7936d98c517Smrg if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, 7946d98c517Smrg tiling_mode, 7956d98c517Smrg stride)) { 7966d98c517Smrg drm_intel_gem_bo_free(&bo_gem->bo); 7976d98c517Smrg goto retry; 7986d98c517Smrg } 79922944501Smrg } 80022944501Smrg } 80122944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 80222944501Smrg 80322944501Smrg if (!alloc_from_cache) { 80422944501Smrg struct drm_i915_gem_create create; 80522944501Smrg 80622944501Smrg bo_gem = calloc(1, sizeof(*bo_gem)); 80722944501Smrg if (!bo_gem) 80822944501Smrg return NULL; 80922944501Smrg 81022944501Smrg bo_gem->bo.size = bo_size; 81120131375Smrg 812424e9256Smrg memclear(create); 81322944501Smrg create.size = bo_size; 81422944501Smrg 8156d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 8166d98c517Smrg DRM_IOCTL_I915_GEM_CREATE, 8176d98c517Smrg &create); 81822944501Smrg bo_gem->gem_handle = create.handle; 81922944501Smrg bo_gem->bo.handle = bo_gem->gem_handle; 82022944501Smrg if (ret != 0) { 82122944501Smrg free(bo_gem); 82222944501Smrg return NULL; 82322944501Smrg } 82422944501Smrg bo_gem->bo.bufmgr = bufmgr; 825fe517fc9Smrg bo_gem->bo.align = alignment; 8266d98c517Smrg 8276d98c517Smrg bo_gem->tiling_mode = I915_TILING_NONE; 8286d98c517Smrg bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 8296d98c517Smrg bo_gem->stride = 0; 8306d98c517Smrg 8313c748557Ssnj /* drm_intel_gem_bo_free calls DRMLISTDEL() for an uninitialized 8323c748557Ssnj list (vma_list), so better set the list head here */ 8333c748557Ssnj DRMINITLISTHEAD(&bo_gem->name_list); 8343c748557Ssnj DRMINITLISTHEAD(&bo_gem->vma_list); 8356d98c517Smrg if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, 8366d98c517Smrg tiling_mode, 8376d98c517Smrg stride)) { 8386d98c517Smrg drm_intel_gem_bo_free(&bo_gem->bo); 8396d98c517Smrg return NULL; 8406d98c517Smrg } 84122944501Smrg } 84222944501Smrg 84322944501Smrg bo_gem->name = name; 84422944501Smrg atomic_set(&bo_gem->refcount, 1); 84522944501Smrg bo_gem->validate_index = -1; 84622944501Smrg bo_gem->reloc_tree_fences = 0; 84720131375Smrg bo_gem->used_as_reloc_target = false; 84820131375Smrg bo_gem->has_error = false; 84920131375Smrg bo_gem->reusable = true; 850fe517fc9Smrg bo_gem->use_48b_address_range = false; 85122944501Smrg 852fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment); 85322944501Smrg 85422944501Smrg DBG("bo_create: buf %d (%s) %ldb\n", 85522944501Smrg bo_gem->gem_handle, bo_gem->name, size); 85622944501Smrg 85722944501Smrg return &bo_gem->bo; 85822944501Smrg} 85922944501Smrg 86022944501Smrgstatic drm_intel_bo * 86122944501Smrgdrm_intel_gem_bo_alloc_for_render(drm_intel_bufmgr *bufmgr, 86222944501Smrg const char *name, 86322944501Smrg unsigned long size, 86422944501Smrg unsigned int alignment) 86522944501Smrg{ 86622944501Smrg return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 8676d98c517Smrg BO_ALLOC_FOR_RENDER, 868fe517fc9Smrg I915_TILING_NONE, 0, 869fe517fc9Smrg alignment); 87022944501Smrg} 87122944501Smrg 87222944501Smrgstatic drm_intel_bo * 87322944501Smrgdrm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, 87422944501Smrg const char *name, 87522944501Smrg unsigned long size, 87622944501Smrg unsigned int alignment) 87722944501Smrg{ 8786d98c517Smrg return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0, 879fe517fc9Smrg I915_TILING_NONE, 0, 0); 88022944501Smrg} 88122944501Smrg 88222944501Smrgstatic drm_intel_bo * 88322944501Smrgdrm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, 88422944501Smrg int x, int y, int cpp, uint32_t *tiling_mode, 88522944501Smrg unsigned long *pitch, unsigned long flags) 88622944501Smrg{ 88722944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 888aaba2545Smrg unsigned long size, stride; 889aaba2545Smrg uint32_t tiling; 89022944501Smrg 891aaba2545Smrg do { 89220131375Smrg unsigned long aligned_y, height_alignment; 893aaba2545Smrg 894aaba2545Smrg tiling = *tiling_mode; 895aaba2545Smrg 896aaba2545Smrg /* If we're tiled, our allocations are in 8 or 32-row blocks, 897aaba2545Smrg * so failure to align our height means that we won't allocate 898aaba2545Smrg * enough pages. 899aaba2545Smrg * 900aaba2545Smrg * If we're untiled, we still have to align to 2 rows high 901aaba2545Smrg * because the data port accesses 2x2 blocks even if the 902aaba2545Smrg * bottom row isn't to be rendered, so failure to align means 903aaba2545Smrg * we could walk off the end of the GTT and fault. This is 904aaba2545Smrg * documented on 965, and may be the case on older chipsets 905aaba2545Smrg * too so we try to be careful. 906aaba2545Smrg */ 907aaba2545Smrg aligned_y = y; 90820131375Smrg height_alignment = 2; 90920131375Smrg 91020131375Smrg if ((bufmgr_gem->gen == 2) && tiling != I915_TILING_NONE) 91120131375Smrg height_alignment = 16; 91220131375Smrg else if (tiling == I915_TILING_X 91320131375Smrg || (IS_915(bufmgr_gem->pci_device) 91420131375Smrg && tiling == I915_TILING_Y)) 91520131375Smrg height_alignment = 8; 916aaba2545Smrg else if (tiling == I915_TILING_Y) 91720131375Smrg height_alignment = 32; 91820131375Smrg aligned_y = ALIGN(y, height_alignment); 919aaba2545Smrg 920aaba2545Smrg stride = x * cpp; 9216d98c517Smrg stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling_mode); 922aaba2545Smrg size = stride * aligned_y; 923aaba2545Smrg size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode); 924aaba2545Smrg } while (*tiling_mode != tiling); 92522944501Smrg *pitch = stride; 92622944501Smrg 9276d98c517Smrg if (tiling == I915_TILING_NONE) 9286d98c517Smrg stride = 0; 9296d98c517Smrg 9306d98c517Smrg return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags, 931fe517fc9Smrg tiling, stride, 0); 93222944501Smrg} 93322944501Smrg 934a884aba1Smrgstatic drm_intel_bo * 935a884aba1Smrgdrm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, 936a884aba1Smrg const char *name, 937a884aba1Smrg void *addr, 938a884aba1Smrg uint32_t tiling_mode, 939a884aba1Smrg uint32_t stride, 940a884aba1Smrg unsigned long size, 941a884aba1Smrg unsigned long flags) 942a884aba1Smrg{ 943a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 944a884aba1Smrg drm_intel_bo_gem *bo_gem; 945a884aba1Smrg int ret; 946a884aba1Smrg struct drm_i915_gem_userptr userptr; 947a884aba1Smrg 948a884aba1Smrg /* Tiling with userptr surfaces is not supported 949a884aba1Smrg * on all hardware so refuse it for time being. 950a884aba1Smrg */ 951a884aba1Smrg if (tiling_mode != I915_TILING_NONE) 952a884aba1Smrg return NULL; 953a884aba1Smrg 954a884aba1Smrg bo_gem = calloc(1, sizeof(*bo_gem)); 955a884aba1Smrg if (!bo_gem) 956a884aba1Smrg return NULL; 957a884aba1Smrg 958a884aba1Smrg bo_gem->bo.size = size; 959a884aba1Smrg 960424e9256Smrg memclear(userptr); 961a884aba1Smrg userptr.user_ptr = (__u64)((unsigned long)addr); 962a884aba1Smrg userptr.user_size = size; 963a884aba1Smrg userptr.flags = flags; 964a884aba1Smrg 965a884aba1Smrg ret = drmIoctl(bufmgr_gem->fd, 966a884aba1Smrg DRM_IOCTL_I915_GEM_USERPTR, 967a884aba1Smrg &userptr); 968a884aba1Smrg if (ret != 0) { 969a884aba1Smrg DBG("bo_create_userptr: " 970a884aba1Smrg "ioctl failed with user ptr %p size 0x%lx, " 971a884aba1Smrg "user flags 0x%lx\n", addr, size, flags); 972a884aba1Smrg free(bo_gem); 973a884aba1Smrg return NULL; 974a884aba1Smrg } 975a884aba1Smrg 976a884aba1Smrg bo_gem->gem_handle = userptr.handle; 977a884aba1Smrg bo_gem->bo.handle = bo_gem->gem_handle; 978a884aba1Smrg bo_gem->bo.bufmgr = bufmgr; 979a884aba1Smrg bo_gem->is_userptr = true; 980a884aba1Smrg bo_gem->bo.virtual = addr; 981a884aba1Smrg /* Save the address provided by user */ 982a884aba1Smrg bo_gem->user_virtual = addr; 983a884aba1Smrg bo_gem->tiling_mode = I915_TILING_NONE; 984a884aba1Smrg bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 985a884aba1Smrg bo_gem->stride = 0; 986a884aba1Smrg 987a884aba1Smrg DRMINITLISTHEAD(&bo_gem->name_list); 988a884aba1Smrg DRMINITLISTHEAD(&bo_gem->vma_list); 989a884aba1Smrg 990a884aba1Smrg bo_gem->name = name; 991a884aba1Smrg atomic_set(&bo_gem->refcount, 1); 992a884aba1Smrg bo_gem->validate_index = -1; 993a884aba1Smrg bo_gem->reloc_tree_fences = 0; 994a884aba1Smrg bo_gem->used_as_reloc_target = false; 995a884aba1Smrg bo_gem->has_error = false; 996a884aba1Smrg bo_gem->reusable = false; 997fe517fc9Smrg bo_gem->use_48b_address_range = false; 998a884aba1Smrg 999fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 1000a884aba1Smrg 1001a884aba1Smrg DBG("bo_create_userptr: " 1002a884aba1Smrg "ptr %p buf %d (%s) size %ldb, stride 0x%x, tile mode %d\n", 1003a884aba1Smrg addr, bo_gem->gem_handle, bo_gem->name, 1004a884aba1Smrg size, stride, tiling_mode); 1005a884aba1Smrg 1006a884aba1Smrg return &bo_gem->bo; 1007a884aba1Smrg} 1008a884aba1Smrg 1009424e9256Smrgstatic bool 1010424e9256Smrghas_userptr(drm_intel_bufmgr_gem *bufmgr_gem) 1011424e9256Smrg{ 1012424e9256Smrg int ret; 1013424e9256Smrg void *ptr; 1014424e9256Smrg long pgsz; 1015424e9256Smrg struct drm_i915_gem_userptr userptr; 1016424e9256Smrg 1017424e9256Smrg pgsz = sysconf(_SC_PAGESIZE); 1018424e9256Smrg assert(pgsz > 0); 1019424e9256Smrg 1020424e9256Smrg ret = posix_memalign(&ptr, pgsz, pgsz); 1021424e9256Smrg if (ret) { 1022424e9256Smrg DBG("Failed to get a page (%ld) for userptr detection!\n", 1023424e9256Smrg pgsz); 1024424e9256Smrg return false; 1025424e9256Smrg } 1026424e9256Smrg 1027424e9256Smrg memclear(userptr); 1028424e9256Smrg userptr.user_ptr = (__u64)(unsigned long)ptr; 1029424e9256Smrg userptr.user_size = pgsz; 1030424e9256Smrg 1031424e9256Smrgretry: 1032424e9256Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr); 1033424e9256Smrg if (ret) { 1034424e9256Smrg if (errno == ENODEV && userptr.flags == 0) { 1035424e9256Smrg userptr.flags = I915_USERPTR_UNSYNCHRONIZED; 1036424e9256Smrg goto retry; 1037424e9256Smrg } 1038424e9256Smrg free(ptr); 1039424e9256Smrg return false; 1040424e9256Smrg } 1041424e9256Smrg 1042424e9256Smrg /* We don't release the userptr bo here as we want to keep the 1043424e9256Smrg * kernel mm tracking alive for our lifetime. The first time we 1044424e9256Smrg * create a userptr object the kernel has to install a mmu_notifer 1045424e9256Smrg * which is a heavyweight operation (e.g. it requires taking all 1046424e9256Smrg * mm_locks and stop_machine()). 1047424e9256Smrg */ 1048424e9256Smrg 1049424e9256Smrg bufmgr_gem->userptr_active.ptr = ptr; 1050424e9256Smrg bufmgr_gem->userptr_active.handle = userptr.handle; 1051424e9256Smrg 1052424e9256Smrg return true; 1053424e9256Smrg} 1054424e9256Smrg 1055424e9256Smrgstatic drm_intel_bo * 1056424e9256Smrgcheck_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, 1057424e9256Smrg const char *name, 1058424e9256Smrg void *addr, 1059424e9256Smrg uint32_t tiling_mode, 1060424e9256Smrg uint32_t stride, 1061424e9256Smrg unsigned long size, 1062424e9256Smrg unsigned long flags) 1063424e9256Smrg{ 1064424e9256Smrg if (has_userptr((drm_intel_bufmgr_gem *)bufmgr)) 1065424e9256Smrg bufmgr->bo_alloc_userptr = drm_intel_gem_bo_alloc_userptr; 1066424e9256Smrg else 1067424e9256Smrg bufmgr->bo_alloc_userptr = NULL; 1068424e9256Smrg 1069424e9256Smrg return drm_intel_bo_alloc_userptr(bufmgr, name, addr, 1070424e9256Smrg tiling_mode, stride, size, flags); 1071424e9256Smrg} 1072424e9256Smrg 107322944501Smrg/** 107422944501Smrg * Returns a drm_intel_bo wrapping the given buffer object handle. 107522944501Smrg * 107622944501Smrg * This can be used when one application needs to pass a buffer object 107722944501Smrg * to another. 107822944501Smrg */ 1079424e9256Smrgdrm_intel_bo * 108022944501Smrgdrm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, 108122944501Smrg const char *name, 108222944501Smrg unsigned int handle) 108322944501Smrg{ 108422944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 108522944501Smrg drm_intel_bo_gem *bo_gem; 108622944501Smrg int ret; 108722944501Smrg struct drm_gem_open open_arg; 108822944501Smrg struct drm_i915_gem_get_tiling get_tiling; 108920131375Smrg drmMMListHead *list; 109022944501Smrg 109120131375Smrg /* At the moment most applications only have a few named bo. 109220131375Smrg * For instance, in a DRI client only the render buffers passed 109320131375Smrg * between X and the client are named. And since X returns the 109420131375Smrg * alternating names for the front/back buffer a linear search 109520131375Smrg * provides a sufficiently fast match. 109620131375Smrg */ 1097a884aba1Smrg pthread_mutex_lock(&bufmgr_gem->lock); 109820131375Smrg for (list = bufmgr_gem->named.next; 109920131375Smrg list != &bufmgr_gem->named; 110020131375Smrg list = list->next) { 110120131375Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, list, name_list); 110220131375Smrg if (bo_gem->global_name == handle) { 110320131375Smrg drm_intel_gem_bo_reference(&bo_gem->bo); 1104a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 110520131375Smrg return &bo_gem->bo; 110620131375Smrg } 110720131375Smrg } 110822944501Smrg 1109424e9256Smrg memclear(open_arg); 111022944501Smrg open_arg.name = handle; 11116d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 11126d98c517Smrg DRM_IOCTL_GEM_OPEN, 11136d98c517Smrg &open_arg); 111422944501Smrg if (ret != 0) { 11159ce4edccSmrg DBG("Couldn't reference %s handle 0x%08x: %s\n", 11169ce4edccSmrg name, handle, strerror(errno)); 1117a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 111822944501Smrg return NULL; 111922944501Smrg } 112020131375Smrg /* Now see if someone has used a prime handle to get this 112120131375Smrg * object from the kernel before by looking through the list 112220131375Smrg * again for a matching gem_handle 112320131375Smrg */ 112420131375Smrg for (list = bufmgr_gem->named.next; 112520131375Smrg list != &bufmgr_gem->named; 112620131375Smrg list = list->next) { 112720131375Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, list, name_list); 112820131375Smrg if (bo_gem->gem_handle == open_arg.handle) { 112920131375Smrg drm_intel_gem_bo_reference(&bo_gem->bo); 1130a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 113120131375Smrg return &bo_gem->bo; 113220131375Smrg } 113320131375Smrg } 113420131375Smrg 113520131375Smrg bo_gem = calloc(1, sizeof(*bo_gem)); 1136a884aba1Smrg if (!bo_gem) { 1137a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 113820131375Smrg return NULL; 1139a884aba1Smrg } 114020131375Smrg 114122944501Smrg bo_gem->bo.size = open_arg.size; 114222944501Smrg bo_gem->bo.offset = 0; 114320131375Smrg bo_gem->bo.offset64 = 0; 114422944501Smrg bo_gem->bo.virtual = NULL; 114522944501Smrg bo_gem->bo.bufmgr = bufmgr; 114622944501Smrg bo_gem->name = name; 114722944501Smrg atomic_set(&bo_gem->refcount, 1); 114822944501Smrg bo_gem->validate_index = -1; 114922944501Smrg bo_gem->gem_handle = open_arg.handle; 115020131375Smrg bo_gem->bo.handle = open_arg.handle; 115122944501Smrg bo_gem->global_name = handle; 115220131375Smrg bo_gem->reusable = false; 1153fe517fc9Smrg bo_gem->use_48b_address_range = false; 115422944501Smrg 1155424e9256Smrg memclear(get_tiling); 115622944501Smrg get_tiling.handle = bo_gem->gem_handle; 11576d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 11586d98c517Smrg DRM_IOCTL_I915_GEM_GET_TILING, 11596d98c517Smrg &get_tiling); 116022944501Smrg if (ret != 0) { 116122944501Smrg drm_intel_gem_bo_unreference(&bo_gem->bo); 1162a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 116322944501Smrg return NULL; 116422944501Smrg } 116522944501Smrg bo_gem->tiling_mode = get_tiling.tiling_mode; 116622944501Smrg bo_gem->swizzle_mode = get_tiling.swizzle_mode; 11676d98c517Smrg /* XXX stride is unknown */ 1168fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 116922944501Smrg 117020131375Smrg DRMINITLISTHEAD(&bo_gem->vma_list); 117120131375Smrg DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named); 1172a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 117322944501Smrg DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name); 117422944501Smrg 117522944501Smrg return &bo_gem->bo; 117622944501Smrg} 117722944501Smrg 117822944501Smrgstatic void 117922944501Smrgdrm_intel_gem_bo_free(drm_intel_bo *bo) 118022944501Smrg{ 118122944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 118222944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 118322944501Smrg struct drm_gem_close close; 118422944501Smrg int ret; 118522944501Smrg 118620131375Smrg DRMLISTDEL(&bo_gem->vma_list); 118720131375Smrg if (bo_gem->mem_virtual) { 118820131375Smrg VG(VALGRIND_FREELIKE_BLOCK(bo_gem->mem_virtual, 0)); 1189a884aba1Smrg drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size); 119020131375Smrg bufmgr_gem->vma_count--; 119120131375Smrg } 119220131375Smrg if (bo_gem->gtt_virtual) { 1193a884aba1Smrg drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size); 119420131375Smrg bufmgr_gem->vma_count--; 119520131375Smrg } 119622944501Smrg 119722944501Smrg /* Close this object */ 1198424e9256Smrg memclear(close); 119922944501Smrg close.handle = bo_gem->gem_handle; 12006d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close); 120122944501Smrg if (ret != 0) { 12029ce4edccSmrg DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n", 12039ce4edccSmrg bo_gem->gem_handle, bo_gem->name, strerror(errno)); 120422944501Smrg } 120522944501Smrg free(bo); 120622944501Smrg} 120722944501Smrg 120820131375Smrgstatic void 120920131375Smrgdrm_intel_gem_bo_mark_mmaps_incoherent(drm_intel_bo *bo) 121020131375Smrg{ 121120131375Smrg#if HAVE_VALGRIND 121220131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 121320131375Smrg 121420131375Smrg if (bo_gem->mem_virtual) 121520131375Smrg VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size); 121620131375Smrg 121720131375Smrg if (bo_gem->gtt_virtual) 121820131375Smrg VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size); 121920131375Smrg#endif 122020131375Smrg} 122120131375Smrg 122222944501Smrg/** Frees all cached buffers significantly older than @time. */ 122322944501Smrgstatic void 122422944501Smrgdrm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time) 122522944501Smrg{ 122622944501Smrg int i; 122722944501Smrg 12286d98c517Smrg if (bufmgr_gem->time == time) 12296d98c517Smrg return; 12306d98c517Smrg 1231aaba2545Smrg for (i = 0; i < bufmgr_gem->num_buckets; i++) { 123222944501Smrg struct drm_intel_gem_bo_bucket *bucket = 123322944501Smrg &bufmgr_gem->cache_bucket[i]; 123422944501Smrg 123522944501Smrg while (!DRMLISTEMPTY(&bucket->head)) { 123622944501Smrg drm_intel_bo_gem *bo_gem; 123722944501Smrg 123822944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 123922944501Smrg bucket->head.next, head); 124022944501Smrg if (time - bo_gem->free_time <= 1) 124122944501Smrg break; 124222944501Smrg 124322944501Smrg DRMLISTDEL(&bo_gem->head); 124422944501Smrg 124522944501Smrg drm_intel_gem_bo_free(&bo_gem->bo); 124622944501Smrg } 124722944501Smrg } 12486d98c517Smrg 12496d98c517Smrg bufmgr_gem->time = time; 125022944501Smrg} 125122944501Smrg 125220131375Smrgstatic void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem) 125320131375Smrg{ 125420131375Smrg int limit; 125520131375Smrg 125620131375Smrg DBG("%s: cached=%d, open=%d, limit=%d\n", __FUNCTION__, 125720131375Smrg bufmgr_gem->vma_count, bufmgr_gem->vma_open, bufmgr_gem->vma_max); 125820131375Smrg 125920131375Smrg if (bufmgr_gem->vma_max < 0) 126020131375Smrg return; 126120131375Smrg 126220131375Smrg /* We may need to evict a few entries in order to create new mmaps */ 126320131375Smrg limit = bufmgr_gem->vma_max - 2*bufmgr_gem->vma_open; 126420131375Smrg if (limit < 0) 126520131375Smrg limit = 0; 126620131375Smrg 126720131375Smrg while (bufmgr_gem->vma_count > limit) { 126820131375Smrg drm_intel_bo_gem *bo_gem; 126920131375Smrg 127020131375Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 127120131375Smrg bufmgr_gem->vma_cache.next, 127220131375Smrg vma_list); 127320131375Smrg assert(bo_gem->map_count == 0); 127420131375Smrg DRMLISTDELINIT(&bo_gem->vma_list); 127520131375Smrg 127620131375Smrg if (bo_gem->mem_virtual) { 1277a884aba1Smrg drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size); 127820131375Smrg bo_gem->mem_virtual = NULL; 127920131375Smrg bufmgr_gem->vma_count--; 128020131375Smrg } 128120131375Smrg if (bo_gem->gtt_virtual) { 1282a884aba1Smrg drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size); 128320131375Smrg bo_gem->gtt_virtual = NULL; 128420131375Smrg bufmgr_gem->vma_count--; 128520131375Smrg } 128620131375Smrg } 128720131375Smrg} 128820131375Smrg 128920131375Smrgstatic void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem, 129020131375Smrg drm_intel_bo_gem *bo_gem) 129120131375Smrg{ 129220131375Smrg bufmgr_gem->vma_open--; 129320131375Smrg DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache); 129420131375Smrg if (bo_gem->mem_virtual) 129520131375Smrg bufmgr_gem->vma_count++; 129620131375Smrg if (bo_gem->gtt_virtual) 129720131375Smrg bufmgr_gem->vma_count++; 129820131375Smrg drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); 129920131375Smrg} 130020131375Smrg 130120131375Smrgstatic void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem, 130220131375Smrg drm_intel_bo_gem *bo_gem) 130320131375Smrg{ 130420131375Smrg bufmgr_gem->vma_open++; 130520131375Smrg DRMLISTDEL(&bo_gem->vma_list); 130620131375Smrg if (bo_gem->mem_virtual) 130720131375Smrg bufmgr_gem->vma_count--; 130820131375Smrg if (bo_gem->gtt_virtual) 130920131375Smrg bufmgr_gem->vma_count--; 131020131375Smrg drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); 131120131375Smrg} 131220131375Smrg 131322944501Smrgstatic void 131422944501Smrgdrm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) 131522944501Smrg{ 131622944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 131722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 131822944501Smrg struct drm_intel_gem_bo_bucket *bucket; 131922944501Smrg int i; 132022944501Smrg 132122944501Smrg /* Unreference all the target buffers */ 132222944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) { 1323aaba2545Smrg if (bo_gem->reloc_target_info[i].bo != bo) { 1324aaba2545Smrg drm_intel_gem_bo_unreference_locked_timed(bo_gem-> 1325aaba2545Smrg reloc_target_info[i].bo, 1326aaba2545Smrg time); 1327aaba2545Smrg } 132822944501Smrg } 1329fe517fc9Smrg for (i = 0; i < bo_gem->softpin_target_count; i++) 1330fe517fc9Smrg drm_intel_gem_bo_unreference_locked_timed(bo_gem->softpin_target[i], 1331fe517fc9Smrg time); 133222944501Smrg bo_gem->reloc_count = 0; 133320131375Smrg bo_gem->used_as_reloc_target = false; 1334fe517fc9Smrg bo_gem->softpin_target_count = 0; 133522944501Smrg 133622944501Smrg DBG("bo_unreference final: %d (%s)\n", 133722944501Smrg bo_gem->gem_handle, bo_gem->name); 133822944501Smrg 133922944501Smrg /* release memory associated with this object */ 134022944501Smrg if (bo_gem->reloc_target_info) { 134122944501Smrg free(bo_gem->reloc_target_info); 134222944501Smrg bo_gem->reloc_target_info = NULL; 134322944501Smrg } 134422944501Smrg if (bo_gem->relocs) { 134522944501Smrg free(bo_gem->relocs); 134622944501Smrg bo_gem->relocs = NULL; 134722944501Smrg } 1348fe517fc9Smrg if (bo_gem->softpin_target) { 1349fe517fc9Smrg free(bo_gem->softpin_target); 1350fe517fc9Smrg bo_gem->softpin_target = NULL; 1351fe517fc9Smrg bo_gem->softpin_target_size = 0; 1352fe517fc9Smrg } 135322944501Smrg 135420131375Smrg /* Clear any left-over mappings */ 135520131375Smrg if (bo_gem->map_count) { 135620131375Smrg DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count); 135720131375Smrg bo_gem->map_count = 0; 135820131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 135920131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 136020131375Smrg } 136120131375Smrg 136220131375Smrg DRMLISTDEL(&bo_gem->name_list); 136320131375Smrg 136422944501Smrg bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size); 136522944501Smrg /* Put the buffer into our internal cache for reuse if we can. */ 136622944501Smrg if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL && 136722944501Smrg drm_intel_gem_bo_madvise_internal(bufmgr_gem, bo_gem, 136822944501Smrg I915_MADV_DONTNEED)) { 136922944501Smrg bo_gem->free_time = time; 137022944501Smrg 137122944501Smrg bo_gem->name = NULL; 137222944501Smrg bo_gem->validate_index = -1; 137322944501Smrg 137422944501Smrg DRMLISTADDTAIL(&bo_gem->head, &bucket->head); 137522944501Smrg } else { 137622944501Smrg drm_intel_gem_bo_free(bo); 137722944501Smrg } 137822944501Smrg} 137922944501Smrg 138022944501Smrgstatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, 138122944501Smrg time_t time) 138222944501Smrg{ 138322944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 138422944501Smrg 138522944501Smrg assert(atomic_read(&bo_gem->refcount) > 0); 138622944501Smrg if (atomic_dec_and_test(&bo_gem->refcount)) 138722944501Smrg drm_intel_gem_bo_unreference_final(bo, time); 138822944501Smrg} 138922944501Smrg 139022944501Smrgstatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo) 139122944501Smrg{ 139222944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 139322944501Smrg 139422944501Smrg assert(atomic_read(&bo_gem->refcount) > 0); 1395a884aba1Smrg 1396a884aba1Smrg if (atomic_add_unless(&bo_gem->refcount, -1, 1)) { 139722944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = 139822944501Smrg (drm_intel_bufmgr_gem *) bo->bufmgr; 139922944501Smrg struct timespec time; 140022944501Smrg 140122944501Smrg clock_gettime(CLOCK_MONOTONIC, &time); 140222944501Smrg 140322944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 1404a884aba1Smrg 1405a884aba1Smrg if (atomic_dec_and_test(&bo_gem->refcount)) { 1406a884aba1Smrg drm_intel_gem_bo_unreference_final(bo, time.tv_sec); 1407a884aba1Smrg drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec); 1408a884aba1Smrg } 1409a884aba1Smrg 141022944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 141122944501Smrg } 141222944501Smrg} 141322944501Smrg 141422944501Smrgstatic int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable) 141522944501Smrg{ 141622944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 141722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 141822944501Smrg struct drm_i915_gem_set_domain set_domain; 141922944501Smrg int ret; 142022944501Smrg 1421a884aba1Smrg if (bo_gem->is_userptr) { 1422a884aba1Smrg /* Return the same user ptr */ 1423a884aba1Smrg bo->virtual = bo_gem->user_virtual; 1424a884aba1Smrg return 0; 1425a884aba1Smrg } 1426a884aba1Smrg 142722944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 142822944501Smrg 142920131375Smrg if (bo_gem->map_count++ == 0) 143020131375Smrg drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 143120131375Smrg 143222944501Smrg if (!bo_gem->mem_virtual) { 143322944501Smrg struct drm_i915_gem_mmap mmap_arg; 143422944501Smrg 143520131375Smrg DBG("bo_map: %d (%s), map_count=%d\n", 143620131375Smrg bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 143722944501Smrg 1438424e9256Smrg memclear(mmap_arg); 143922944501Smrg mmap_arg.handle = bo_gem->gem_handle; 144022944501Smrg mmap_arg.size = bo->size; 14416d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 14426d98c517Smrg DRM_IOCTL_I915_GEM_MMAP, 14436d98c517Smrg &mmap_arg); 144422944501Smrg if (ret != 0) { 144522944501Smrg ret = -errno; 14469ce4edccSmrg DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 14479ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, 14489ce4edccSmrg bo_gem->name, strerror(errno)); 144920131375Smrg if (--bo_gem->map_count == 0) 145020131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 145122944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 145222944501Smrg return ret; 145322944501Smrg } 145420131375Smrg VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1)); 145522944501Smrg bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr; 145622944501Smrg } 145722944501Smrg DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, 145822944501Smrg bo_gem->mem_virtual); 145922944501Smrg bo->virtual = bo_gem->mem_virtual; 146022944501Smrg 1461424e9256Smrg memclear(set_domain); 146222944501Smrg set_domain.handle = bo_gem->gem_handle; 146322944501Smrg set_domain.read_domains = I915_GEM_DOMAIN_CPU; 146422944501Smrg if (write_enable) 146522944501Smrg set_domain.write_domain = I915_GEM_DOMAIN_CPU; 146622944501Smrg else 146722944501Smrg set_domain.write_domain = 0; 14686d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 14696d98c517Smrg DRM_IOCTL_I915_GEM_SET_DOMAIN, 14706d98c517Smrg &set_domain); 147122944501Smrg if (ret != 0) { 14729ce4edccSmrg DBG("%s:%d: Error setting to CPU domain %d: %s\n", 14739ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, 14749ce4edccSmrg strerror(errno)); 147522944501Smrg } 147622944501Smrg 147720131375Smrg if (write_enable) 147820131375Smrg bo_gem->mapped_cpu_write = true; 147920131375Smrg 148020131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 148120131375Smrg VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->mem_virtual, bo->size)); 148222944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 148322944501Smrg 148422944501Smrg return 0; 148522944501Smrg} 148622944501Smrg 148720131375Smrgstatic int 148820131375Smrgmap_gtt(drm_intel_bo *bo) 148922944501Smrg{ 149022944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 149122944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 149222944501Smrg int ret; 149322944501Smrg 1494a884aba1Smrg if (bo_gem->is_userptr) 1495a884aba1Smrg return -EINVAL; 1496a884aba1Smrg 149720131375Smrg if (bo_gem->map_count++ == 0) 149820131375Smrg drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 149922944501Smrg 150022944501Smrg /* Get a mapping of the buffer if we haven't before. */ 150122944501Smrg if (bo_gem->gtt_virtual == NULL) { 150222944501Smrg struct drm_i915_gem_mmap_gtt mmap_arg; 150322944501Smrg 150420131375Smrg DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n", 150520131375Smrg bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 150622944501Smrg 1507424e9256Smrg memclear(mmap_arg); 150822944501Smrg mmap_arg.handle = bo_gem->gem_handle; 150922944501Smrg 151022944501Smrg /* Get the fake offset back... */ 15116d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 15126d98c517Smrg DRM_IOCTL_I915_GEM_MMAP_GTT, 15136d98c517Smrg &mmap_arg); 151422944501Smrg if (ret != 0) { 151522944501Smrg ret = -errno; 15169ce4edccSmrg DBG("%s:%d: Error preparing buffer map %d (%s): %s .\n", 15179ce4edccSmrg __FILE__, __LINE__, 15189ce4edccSmrg bo_gem->gem_handle, bo_gem->name, 15199ce4edccSmrg strerror(errno)); 152020131375Smrg if (--bo_gem->map_count == 0) 152120131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 152222944501Smrg return ret; 152322944501Smrg } 152422944501Smrg 152522944501Smrg /* and mmap it */ 1526aec75c42Sriastradh ret = drmMap(bufmgr_gem->fd, mmap_arg.offset, bo->size, 1527aec75c42Sriastradh &bo_gem->gtt_virtual); 1528aec75c42Sriastradh if (ret) { 152922944501Smrg bo_gem->gtt_virtual = NULL; 15309ce4edccSmrg DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 15319ce4edccSmrg __FILE__, __LINE__, 15329ce4edccSmrg bo_gem->gem_handle, bo_gem->name, 15339ce4edccSmrg strerror(errno)); 153420131375Smrg if (--bo_gem->map_count == 0) 153520131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 153622944501Smrg return ret; 153722944501Smrg } 153822944501Smrg } 153922944501Smrg 154022944501Smrg bo->virtual = bo_gem->gtt_virtual; 154122944501Smrg 154222944501Smrg DBG("bo_map_gtt: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, 154322944501Smrg bo_gem->gtt_virtual); 154422944501Smrg 154520131375Smrg return 0; 154620131375Smrg} 154720131375Smrg 1548424e9256Smrgint 1549a884aba1Smrgdrm_intel_gem_bo_map_gtt(drm_intel_bo *bo) 155020131375Smrg{ 155120131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 155220131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 155320131375Smrg struct drm_i915_gem_set_domain set_domain; 155420131375Smrg int ret; 155520131375Smrg 155620131375Smrg pthread_mutex_lock(&bufmgr_gem->lock); 155720131375Smrg 155820131375Smrg ret = map_gtt(bo); 155920131375Smrg if (ret) { 156020131375Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 156120131375Smrg return ret; 156220131375Smrg } 156320131375Smrg 156420131375Smrg /* Now move it to the GTT domain so that the GPU and CPU 156520131375Smrg * caches are flushed and the GPU isn't actively using the 156620131375Smrg * buffer. 156720131375Smrg * 156820131375Smrg * The pagefault handler does this domain change for us when 156920131375Smrg * it has unbound the BO from the GTT, but it's up to us to 157020131375Smrg * tell it when we're about to use things if we had done 157120131375Smrg * rendering and it still happens to be bound to the GTT. 157220131375Smrg */ 1573424e9256Smrg memclear(set_domain); 157422944501Smrg set_domain.handle = bo_gem->gem_handle; 157522944501Smrg set_domain.read_domains = I915_GEM_DOMAIN_GTT; 157622944501Smrg set_domain.write_domain = I915_GEM_DOMAIN_GTT; 15776d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 15786d98c517Smrg DRM_IOCTL_I915_GEM_SET_DOMAIN, 15796d98c517Smrg &set_domain); 158022944501Smrg if (ret != 0) { 15819ce4edccSmrg DBG("%s:%d: Error setting domain %d: %s\n", 15829ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, 15839ce4edccSmrg strerror(errno)); 158422944501Smrg } 158522944501Smrg 158620131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 158720131375Smrg VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size)); 158822944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 158922944501Smrg 15906d98c517Smrg return 0; 159122944501Smrg} 159222944501Smrg 159320131375Smrg/** 159420131375Smrg * Performs a mapping of the buffer object like the normal GTT 159520131375Smrg * mapping, but avoids waiting for the GPU to be done reading from or 159620131375Smrg * rendering to the buffer. 159720131375Smrg * 159820131375Smrg * This is used in the implementation of GL_ARB_map_buffer_range: The 159920131375Smrg * user asks to create a buffer, then does a mapping, fills some 160020131375Smrg * space, runs a drawing command, then asks to map it again without 160120131375Smrg * synchronizing because it guarantees that it won't write over the 160220131375Smrg * data that the GPU is busy using (or, more specifically, that if it 160320131375Smrg * does write over the data, it acknowledges that rendering is 160420131375Smrg * undefined). 160520131375Smrg */ 160620131375Smrg 1607424e9256Smrgint 1608a884aba1Smrgdrm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo) 160922944501Smrg{ 161022944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 161120131375Smrg#ifdef HAVE_VALGRIND 161220131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 161320131375Smrg#endif 161420131375Smrg int ret; 161522944501Smrg 161620131375Smrg /* If the CPU cache isn't coherent with the GTT, then use a 161720131375Smrg * regular synchronized mapping. The problem is that we don't 161820131375Smrg * track where the buffer was last used on the CPU side in 161920131375Smrg * terms of drm_intel_bo_map vs drm_intel_gem_bo_map_gtt, so 162020131375Smrg * we would potentially corrupt the buffer even when the user 162120131375Smrg * does reasonable things. 162220131375Smrg */ 162320131375Smrg if (!bufmgr_gem->has_llc) 162420131375Smrg return drm_intel_gem_bo_map_gtt(bo); 162522944501Smrg 162622944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 162720131375Smrg 162820131375Smrg ret = map_gtt(bo); 162920131375Smrg if (ret == 0) { 163020131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 163120131375Smrg VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size)); 163220131375Smrg } 163320131375Smrg 163422944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 163522944501Smrg 163622944501Smrg return ret; 163722944501Smrg} 163822944501Smrg 163922944501Smrgstatic int drm_intel_gem_bo_unmap(drm_intel_bo *bo) 164022944501Smrg{ 1641a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem; 164222944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 164320131375Smrg int ret = 0; 164422944501Smrg 164522944501Smrg if (bo == NULL) 164622944501Smrg return 0; 164722944501Smrg 1648a884aba1Smrg if (bo_gem->is_userptr) 1649a884aba1Smrg return 0; 1650a884aba1Smrg 1651a884aba1Smrg bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1652a884aba1Smrg 165322944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 165422944501Smrg 165520131375Smrg if (bo_gem->map_count <= 0) { 165620131375Smrg DBG("attempted to unmap an unmapped bo\n"); 165720131375Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 165820131375Smrg /* Preserve the old behaviour of just treating this as a 165920131375Smrg * no-op rather than reporting the error. 166020131375Smrg */ 166120131375Smrg return 0; 166220131375Smrg } 166320131375Smrg 166420131375Smrg if (bo_gem->mapped_cpu_write) { 166520131375Smrg struct drm_i915_gem_sw_finish sw_finish; 166620131375Smrg 166720131375Smrg /* Cause a flush to happen if the buffer's pinned for 166820131375Smrg * scanout, so the results show up in a timely manner. 166920131375Smrg * Unlike GTT set domains, this only does work if the 167020131375Smrg * buffer should be scanout-related. 167120131375Smrg */ 1672424e9256Smrg memclear(sw_finish); 167320131375Smrg sw_finish.handle = bo_gem->gem_handle; 167420131375Smrg ret = drmIoctl(bufmgr_gem->fd, 167520131375Smrg DRM_IOCTL_I915_GEM_SW_FINISH, 167620131375Smrg &sw_finish); 167720131375Smrg ret = ret == -1 ? -errno : 0; 167820131375Smrg 167920131375Smrg bo_gem->mapped_cpu_write = false; 168020131375Smrg } 168122944501Smrg 168220131375Smrg /* We need to unmap after every innovation as we cannot track 168320131375Smrg * an open vma for every bo as that will exhaasut the system 168420131375Smrg * limits and cause later failures. 168520131375Smrg */ 168620131375Smrg if (--bo_gem->map_count == 0) { 168720131375Smrg drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 168820131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 168920131375Smrg bo->virtual = NULL; 169020131375Smrg } 169122944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 169222944501Smrg 169322944501Smrg return ret; 169422944501Smrg} 169522944501Smrg 1696424e9256Smrgint 1697a884aba1Smrgdrm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo) 169820131375Smrg{ 169920131375Smrg return drm_intel_gem_bo_unmap(bo); 170020131375Smrg} 170120131375Smrg 170222944501Smrgstatic int 170322944501Smrgdrm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset, 170422944501Smrg unsigned long size, const void *data) 170522944501Smrg{ 170622944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 170722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 170822944501Smrg struct drm_i915_gem_pwrite pwrite; 170922944501Smrg int ret; 171022944501Smrg 1711a884aba1Smrg if (bo_gem->is_userptr) 1712a884aba1Smrg return -EINVAL; 1713a884aba1Smrg 1714424e9256Smrg memclear(pwrite); 171522944501Smrg pwrite.handle = bo_gem->gem_handle; 171622944501Smrg pwrite.offset = offset; 171722944501Smrg pwrite.size = size; 171822944501Smrg pwrite.data_ptr = (uint64_t) (uintptr_t) data; 17196d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 17206d98c517Smrg DRM_IOCTL_I915_GEM_PWRITE, 17216d98c517Smrg &pwrite); 172222944501Smrg if (ret != 0) { 172322944501Smrg ret = -errno; 17249ce4edccSmrg DBG("%s:%d: Error writing data to buffer %d: (%d %d) %s .\n", 17259ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, (int)offset, 17269ce4edccSmrg (int)size, strerror(errno)); 172722944501Smrg } 172822944501Smrg 172922944501Smrg return ret; 173022944501Smrg} 173122944501Smrg 173222944501Smrgstatic int 173322944501Smrgdrm_intel_gem_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id) 173422944501Smrg{ 173522944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 173622944501Smrg struct drm_i915_get_pipe_from_crtc_id get_pipe_from_crtc_id; 173722944501Smrg int ret; 173822944501Smrg 1739424e9256Smrg memclear(get_pipe_from_crtc_id); 174022944501Smrg get_pipe_from_crtc_id.crtc_id = crtc_id; 17416d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 17426d98c517Smrg DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID, 17436d98c517Smrg &get_pipe_from_crtc_id); 174422944501Smrg if (ret != 0) { 174522944501Smrg /* We return -1 here to signal that we don't 174622944501Smrg * know which pipe is associated with this crtc. 174722944501Smrg * This lets the caller know that this information 174822944501Smrg * isn't available; using the wrong pipe for 174922944501Smrg * vblank waiting can cause the chipset to lock up 175022944501Smrg */ 175122944501Smrg return -1; 175222944501Smrg } 175322944501Smrg 175422944501Smrg return get_pipe_from_crtc_id.pipe; 175522944501Smrg} 175622944501Smrg 175722944501Smrgstatic int 175822944501Smrgdrm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, 175922944501Smrg unsigned long size, void *data) 176022944501Smrg{ 176122944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 176222944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 176322944501Smrg struct drm_i915_gem_pread pread; 176422944501Smrg int ret; 176522944501Smrg 1766a884aba1Smrg if (bo_gem->is_userptr) 1767a884aba1Smrg return -EINVAL; 1768a884aba1Smrg 1769424e9256Smrg memclear(pread); 177022944501Smrg pread.handle = bo_gem->gem_handle; 177122944501Smrg pread.offset = offset; 177222944501Smrg pread.size = size; 177322944501Smrg pread.data_ptr = (uint64_t) (uintptr_t) data; 17746d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 17756d98c517Smrg DRM_IOCTL_I915_GEM_PREAD, 17766d98c517Smrg &pread); 177722944501Smrg if (ret != 0) { 177822944501Smrg ret = -errno; 17799ce4edccSmrg DBG("%s:%d: Error reading data from buffer %d: (%d %d) %s .\n", 17809ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, (int)offset, 17819ce4edccSmrg (int)size, strerror(errno)); 178222944501Smrg } 178322944501Smrg 178422944501Smrg return ret; 178522944501Smrg} 178622944501Smrg 17879ce4edccSmrg/** Waits for all GPU rendering with the object to have completed. */ 178822944501Smrgstatic void 178922944501Smrgdrm_intel_gem_bo_wait_rendering(drm_intel_bo *bo) 179022944501Smrg{ 17919ce4edccSmrg drm_intel_gem_bo_start_gtt_access(bo, 1); 179222944501Smrg} 179322944501Smrg 179420131375Smrg/** 179520131375Smrg * Waits on a BO for the given amount of time. 179620131375Smrg * 179720131375Smrg * @bo: buffer object to wait for 179820131375Smrg * @timeout_ns: amount of time to wait in nanoseconds. 179920131375Smrg * If value is less than 0, an infinite wait will occur. 180020131375Smrg * 180120131375Smrg * Returns 0 if the wait was successful ie. the last batch referencing the 180220131375Smrg * object has completed within the allotted time. Otherwise some negative return 180320131375Smrg * value describes the error. Of particular interest is -ETIME when the wait has 180420131375Smrg * failed to yield the desired result. 180520131375Smrg * 180620131375Smrg * Similar to drm_intel_gem_bo_wait_rendering except a timeout parameter allows 180720131375Smrg * the operation to give up after a certain amount of time. Another subtle 180820131375Smrg * difference is the internal locking semantics are different (this variant does 180920131375Smrg * not hold the lock for the duration of the wait). This makes the wait subject 181020131375Smrg * to a larger userspace race window. 181120131375Smrg * 181220131375Smrg * The implementation shall wait until the object is no longer actively 181320131375Smrg * referenced within a batch buffer at the time of the call. The wait will 181420131375Smrg * not guarantee that the buffer is re-issued via another thread, or an flinked 181520131375Smrg * handle. Userspace must make sure this race does not occur if such precision 181620131375Smrg * is important. 1817424e9256Smrg * 1818424e9256Smrg * Note that some kernels have broken the inifite wait for negative values 1819424e9256Smrg * promise, upgrade to latest stable kernels if this is the case. 182020131375Smrg */ 1821424e9256Smrgint 1822a884aba1Smrgdrm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns) 182320131375Smrg{ 182420131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 182520131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 182620131375Smrg struct drm_i915_gem_wait wait; 182720131375Smrg int ret; 182820131375Smrg 182920131375Smrg if (!bufmgr_gem->has_wait_timeout) { 183020131375Smrg DBG("%s:%d: Timed wait is not supported. Falling back to " 183120131375Smrg "infinite wait\n", __FILE__, __LINE__); 183220131375Smrg if (timeout_ns) { 183320131375Smrg drm_intel_gem_bo_wait_rendering(bo); 183420131375Smrg return 0; 183520131375Smrg } else { 183620131375Smrg return drm_intel_gem_bo_busy(bo) ? -ETIME : 0; 183720131375Smrg } 183820131375Smrg } 183920131375Smrg 1840424e9256Smrg memclear(wait); 184120131375Smrg wait.bo_handle = bo_gem->gem_handle; 184220131375Smrg wait.timeout_ns = timeout_ns; 184320131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait); 184420131375Smrg if (ret == -1) 184520131375Smrg return -errno; 184620131375Smrg 184720131375Smrg return ret; 184820131375Smrg} 184920131375Smrg 185022944501Smrg/** 185122944501Smrg * Sets the object to the GTT read and possibly write domain, used by the X 185222944501Smrg * 2D driver in the absence of kernel support to do drm_intel_gem_bo_map_gtt(). 185322944501Smrg * 185422944501Smrg * In combination with drm_intel_gem_bo_pin() and manual fence management, we 185522944501Smrg * can do tiled pixmaps this way. 185622944501Smrg */ 1857424e9256Smrgvoid 185822944501Smrgdrm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable) 185922944501Smrg{ 186022944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 186122944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 186222944501Smrg struct drm_i915_gem_set_domain set_domain; 186322944501Smrg int ret; 186422944501Smrg 1865424e9256Smrg memclear(set_domain); 186622944501Smrg set_domain.handle = bo_gem->gem_handle; 186722944501Smrg set_domain.read_domains = I915_GEM_DOMAIN_GTT; 186822944501Smrg set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_GTT : 0; 18696d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 18706d98c517Smrg DRM_IOCTL_I915_GEM_SET_DOMAIN, 18716d98c517Smrg &set_domain); 187222944501Smrg if (ret != 0) { 18739ce4edccSmrg DBG("%s:%d: Error setting memory domains %d (%08x %08x): %s .\n", 18749ce4edccSmrg __FILE__, __LINE__, bo_gem->gem_handle, 18759ce4edccSmrg set_domain.read_domains, set_domain.write_domain, 18769ce4edccSmrg strerror(errno)); 187722944501Smrg } 187822944501Smrg} 187922944501Smrg 188022944501Smrgstatic void 188122944501Smrgdrm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr) 188222944501Smrg{ 188322944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 1884424e9256Smrg struct drm_gem_close close_bo; 1885424e9256Smrg int i, ret; 188622944501Smrg 188722944501Smrg free(bufmgr_gem->exec2_objects); 188822944501Smrg free(bufmgr_gem->exec_objects); 188922944501Smrg free(bufmgr_gem->exec_bos); 189022944501Smrg 189122944501Smrg pthread_mutex_destroy(&bufmgr_gem->lock); 189222944501Smrg 189322944501Smrg /* Free any cached buffer objects we were going to reuse */ 1894aaba2545Smrg for (i = 0; i < bufmgr_gem->num_buckets; i++) { 189522944501Smrg struct drm_intel_gem_bo_bucket *bucket = 189622944501Smrg &bufmgr_gem->cache_bucket[i]; 189722944501Smrg drm_intel_bo_gem *bo_gem; 189822944501Smrg 189922944501Smrg while (!DRMLISTEMPTY(&bucket->head)) { 190022944501Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 190122944501Smrg bucket->head.next, head); 190222944501Smrg DRMLISTDEL(&bo_gem->head); 190322944501Smrg 190422944501Smrg drm_intel_gem_bo_free(&bo_gem->bo); 190522944501Smrg } 190622944501Smrg } 190722944501Smrg 1908424e9256Smrg /* Release userptr bo kept hanging around for optimisation. */ 1909424e9256Smrg if (bufmgr_gem->userptr_active.ptr) { 1910424e9256Smrg memclear(close_bo); 1911424e9256Smrg close_bo.handle = bufmgr_gem->userptr_active.handle; 1912424e9256Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close_bo); 1913424e9256Smrg free(bufmgr_gem->userptr_active.ptr); 1914424e9256Smrg if (ret) 1915424e9256Smrg fprintf(stderr, 1916424e9256Smrg "Failed to release test userptr object! (%d) " 1917424e9256Smrg "i915 kernel driver may not be sane!\n", errno); 1918424e9256Smrg } 1919424e9256Smrg 192022944501Smrg free(bufmgr); 192122944501Smrg} 192222944501Smrg 192322944501Smrg/** 192422944501Smrg * Adds the target buffer to the validation list and adds the relocation 192522944501Smrg * to the reloc_buffer's relocation list. 192622944501Smrg * 192722944501Smrg * The relocation entry at the given offset must already contain the 192822944501Smrg * precomputed relocation value, because the kernel will optimize out 192922944501Smrg * the relocation entry write when the buffer hasn't moved from the 193022944501Smrg * last known offset in target_bo. 193122944501Smrg */ 193222944501Smrgstatic int 193322944501Smrgdo_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, 193422944501Smrg drm_intel_bo *target_bo, uint32_t target_offset, 193522944501Smrg uint32_t read_domains, uint32_t write_domain, 193620131375Smrg bool need_fence) 193722944501Smrg{ 193822944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 193922944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 194022944501Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; 194120131375Smrg bool fenced_command; 194222944501Smrg 194322944501Smrg if (bo_gem->has_error) 194422944501Smrg return -ENOMEM; 194522944501Smrg 194622944501Smrg if (target_bo_gem->has_error) { 194720131375Smrg bo_gem->has_error = true; 194822944501Smrg return -ENOMEM; 194922944501Smrg } 195022944501Smrg 195122944501Smrg /* We never use HW fences for rendering on 965+ */ 195222944501Smrg if (bufmgr_gem->gen >= 4) 195320131375Smrg need_fence = false; 195422944501Smrg 19559ce4edccSmrg fenced_command = need_fence; 19569ce4edccSmrg if (target_bo_gem->tiling_mode == I915_TILING_NONE) 195720131375Smrg need_fence = false; 19589ce4edccSmrg 195922944501Smrg /* Create a new relocation list if needed */ 196022944501Smrg if (bo_gem->relocs == NULL && drm_intel_setup_reloc_list(bo)) 196122944501Smrg return -ENOMEM; 196222944501Smrg 196322944501Smrg /* Check overflow */ 196422944501Smrg assert(bo_gem->reloc_count < bufmgr_gem->max_relocs); 196522944501Smrg 196622944501Smrg /* Check args */ 196722944501Smrg assert(offset <= bo->size - 4); 196822944501Smrg assert((write_domain & (write_domain - 1)) == 0); 196922944501Smrg 19703c748557Ssnj /* An object needing a fence is a tiled buffer, so it won't have 19713c748557Ssnj * relocs to other buffers. 19723c748557Ssnj */ 19733c748557Ssnj if (need_fence) { 19743c748557Ssnj assert(target_bo_gem->reloc_count == 0); 19753c748557Ssnj target_bo_gem->reloc_tree_fences = 1; 19763c748557Ssnj } 19773c748557Ssnj 197822944501Smrg /* Make sure that we're not adding a reloc to something whose size has 197922944501Smrg * already been accounted for. 198022944501Smrg */ 198122944501Smrg assert(!bo_gem->used_as_reloc_target); 1982aaba2545Smrg if (target_bo_gem != bo_gem) { 198320131375Smrg target_bo_gem->used_as_reloc_target = true; 1984aaba2545Smrg bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size; 19853c748557Ssnj bo_gem->reloc_tree_fences += target_bo_gem->reloc_tree_fences; 1986aaba2545Smrg } 198722944501Smrg 198822944501Smrg bo_gem->reloc_target_info[bo_gem->reloc_count].bo = target_bo; 1989aaba2545Smrg if (target_bo != bo) 1990aaba2545Smrg drm_intel_gem_bo_reference(target_bo); 19919ce4edccSmrg if (fenced_command) 199222944501Smrg bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 199322944501Smrg DRM_INTEL_RELOC_FENCE; 199422944501Smrg else 199522944501Smrg bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 0; 199622944501Smrg 1997fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].offset = offset; 1998fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].delta = target_offset; 1999fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].target_handle = 2000fe517fc9Smrg target_bo_gem->gem_handle; 2001fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains; 2002fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain; 2003fe517fc9Smrg bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset64; 200422944501Smrg bo_gem->reloc_count++; 200522944501Smrg 200622944501Smrg return 0; 200722944501Smrg} 200822944501Smrg 2009fe517fc9Smrgstatic void 2010fe517fc9Smrgdrm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable) 2011fe517fc9Smrg{ 2012fe517fc9Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2013fe517fc9Smrg bo_gem->use_48b_address_range = enable; 2014fe517fc9Smrg} 2015fe517fc9Smrg 2016fe517fc9Smrgstatic int 2017fe517fc9Smrgdrm_intel_gem_bo_add_softpin_target(drm_intel_bo *bo, drm_intel_bo *target_bo) 2018fe517fc9Smrg{ 2019fe517fc9Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2020fe517fc9Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2021fe517fc9Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; 2022fe517fc9Smrg if (bo_gem->has_error) 2023fe517fc9Smrg return -ENOMEM; 2024fe517fc9Smrg 2025fe517fc9Smrg if (target_bo_gem->has_error) { 2026fe517fc9Smrg bo_gem->has_error = true; 2027fe517fc9Smrg return -ENOMEM; 2028fe517fc9Smrg } 2029fe517fc9Smrg 2030fe517fc9Smrg if (!target_bo_gem->is_softpin) 2031fe517fc9Smrg return -EINVAL; 2032fe517fc9Smrg if (target_bo_gem == bo_gem) 2033fe517fc9Smrg return -EINVAL; 2034fe517fc9Smrg 2035fe517fc9Smrg if (bo_gem->softpin_target_count == bo_gem->softpin_target_size) { 2036fe517fc9Smrg int new_size = bo_gem->softpin_target_size * 2; 2037fe517fc9Smrg if (new_size == 0) 2038fe517fc9Smrg new_size = bufmgr_gem->max_relocs; 2039fe517fc9Smrg 2040fe517fc9Smrg bo_gem->softpin_target = realloc(bo_gem->softpin_target, new_size * 2041fe517fc9Smrg sizeof(drm_intel_bo *)); 2042fe517fc9Smrg if (!bo_gem->softpin_target) 2043fe517fc9Smrg return -ENOMEM; 2044fe517fc9Smrg 2045fe517fc9Smrg bo_gem->softpin_target_size = new_size; 2046fe517fc9Smrg } 2047fe517fc9Smrg bo_gem->softpin_target[bo_gem->softpin_target_count] = target_bo; 2048fe517fc9Smrg drm_intel_gem_bo_reference(target_bo); 2049fe517fc9Smrg bo_gem->softpin_target_count++; 2050fe517fc9Smrg 2051fe517fc9Smrg return 0; 2052fe517fc9Smrg} 2053fe517fc9Smrg 205422944501Smrgstatic int 205522944501Smrgdrm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, 205622944501Smrg drm_intel_bo *target_bo, uint32_t target_offset, 205722944501Smrg uint32_t read_domains, uint32_t write_domain) 205822944501Smrg{ 205922944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; 2060fe517fc9Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo; 206122944501Smrg 2062fe517fc9Smrg if (target_bo_gem->is_softpin) 2063fe517fc9Smrg return drm_intel_gem_bo_add_softpin_target(bo, target_bo); 2064fe517fc9Smrg else 2065fe517fc9Smrg return do_bo_emit_reloc(bo, offset, target_bo, target_offset, 2066fe517fc9Smrg read_domains, write_domain, 2067fe517fc9Smrg !bufmgr_gem->fenced_relocs); 206822944501Smrg} 206922944501Smrg 207022944501Smrgstatic int 207122944501Smrgdrm_intel_gem_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset, 207222944501Smrg drm_intel_bo *target_bo, 207322944501Smrg uint32_t target_offset, 207422944501Smrg uint32_t read_domains, uint32_t write_domain) 207522944501Smrg{ 207622944501Smrg return do_bo_emit_reloc(bo, offset, target_bo, target_offset, 207720131375Smrg read_domains, write_domain, true); 207820131375Smrg} 207920131375Smrg 2080424e9256Smrgint 208120131375Smrgdrm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo) 208220131375Smrg{ 208320131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 208420131375Smrg 208520131375Smrg return bo_gem->reloc_count; 208620131375Smrg} 208720131375Smrg 208820131375Smrg/** 208920131375Smrg * Removes existing relocation entries in the BO after "start". 209020131375Smrg * 209120131375Smrg * This allows a user to avoid a two-step process for state setup with 209220131375Smrg * counting up all the buffer objects and doing a 209320131375Smrg * drm_intel_bufmgr_check_aperture_space() before emitting any of the 209420131375Smrg * relocations for the state setup. Instead, save the state of the 209520131375Smrg * batchbuffer including drm_intel_gem_get_reloc_count(), emit all the 209620131375Smrg * state, and then check if it still fits in the aperture. 209720131375Smrg * 209820131375Smrg * Any further drm_intel_bufmgr_check_aperture_space() queries 209920131375Smrg * involving this buffer in the tree are undefined after this call. 2100fe517fc9Smrg * 2101fe517fc9Smrg * This also removes all softpinned targets being referenced by the BO. 210220131375Smrg */ 2103424e9256Smrgvoid 210420131375Smrgdrm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start) 210520131375Smrg{ 2106a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 210720131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 210820131375Smrg int i; 210920131375Smrg struct timespec time; 211020131375Smrg 211120131375Smrg clock_gettime(CLOCK_MONOTONIC, &time); 211220131375Smrg 211320131375Smrg assert(bo_gem->reloc_count >= start); 2114a884aba1Smrg 211520131375Smrg /* Unreference the cleared target buffers */ 2116a884aba1Smrg pthread_mutex_lock(&bufmgr_gem->lock); 2117a884aba1Smrg 211820131375Smrg for (i = start; i < bo_gem->reloc_count; i++) { 211920131375Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->reloc_target_info[i].bo; 212020131375Smrg if (&target_bo_gem->bo != bo) { 212120131375Smrg bo_gem->reloc_tree_fences -= target_bo_gem->reloc_tree_fences; 212220131375Smrg drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, 212320131375Smrg time.tv_sec); 212420131375Smrg } 212520131375Smrg } 212620131375Smrg bo_gem->reloc_count = start; 2127a884aba1Smrg 2128fe517fc9Smrg for (i = 0; i < bo_gem->softpin_target_count; i++) { 2129fe517fc9Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->softpin_target[i]; 2130fe517fc9Smrg drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, time.tv_sec); 2131fe517fc9Smrg } 2132fe517fc9Smrg bo_gem->softpin_target_count = 0; 2133fe517fc9Smrg 2134a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 2135a884aba1Smrg 213622944501Smrg} 213722944501Smrg 213822944501Smrg/** 213922944501Smrg * Walk the tree of relocations rooted at BO and accumulate the list of 214022944501Smrg * validations to be performed and update the relocation buffers with 214122944501Smrg * index values into the validation list. 214222944501Smrg */ 214322944501Smrgstatic void 214422944501Smrgdrm_intel_gem_bo_process_reloc(drm_intel_bo *bo) 214522944501Smrg{ 214622944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 214722944501Smrg int i; 214822944501Smrg 214922944501Smrg if (bo_gem->relocs == NULL) 215022944501Smrg return; 215122944501Smrg 215222944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) { 215322944501Smrg drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo; 215422944501Smrg 2155aaba2545Smrg if (target_bo == bo) 2156aaba2545Smrg continue; 2157aaba2545Smrg 215820131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 215920131375Smrg 216022944501Smrg /* Continue walking the tree depth-first. */ 216122944501Smrg drm_intel_gem_bo_process_reloc(target_bo); 216222944501Smrg 216322944501Smrg /* Add the target to the validate list */ 216422944501Smrg drm_intel_add_validate_buffer(target_bo); 216522944501Smrg } 216622944501Smrg} 216722944501Smrg 216822944501Smrgstatic void 216922944501Smrgdrm_intel_gem_bo_process_reloc2(drm_intel_bo *bo) 217022944501Smrg{ 217122944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; 217222944501Smrg int i; 217322944501Smrg 2174fe517fc9Smrg if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) 217522944501Smrg return; 217622944501Smrg 217722944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) { 217822944501Smrg drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo; 217922944501Smrg int need_fence; 218022944501Smrg 2181aaba2545Smrg if (target_bo == bo) 2182aaba2545Smrg continue; 2183aaba2545Smrg 218420131375Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 218520131375Smrg 218622944501Smrg /* Continue walking the tree depth-first. */ 218722944501Smrg drm_intel_gem_bo_process_reloc2(target_bo); 218822944501Smrg 218922944501Smrg need_fence = (bo_gem->reloc_target_info[i].flags & 219022944501Smrg DRM_INTEL_RELOC_FENCE); 219122944501Smrg 219222944501Smrg /* Add the target to the validate list */ 219322944501Smrg drm_intel_add_validate_buffer2(target_bo, need_fence); 219422944501Smrg } 2195fe517fc9Smrg 2196fe517fc9Smrg for (i = 0; i < bo_gem->softpin_target_count; i++) { 2197fe517fc9Smrg drm_intel_bo *target_bo = bo_gem->softpin_target[i]; 2198fe517fc9Smrg 2199fe517fc9Smrg if (target_bo == bo) 2200fe517fc9Smrg continue; 2201fe517fc9Smrg 2202fe517fc9Smrg drm_intel_gem_bo_mark_mmaps_incoherent(bo); 2203fe517fc9Smrg drm_intel_gem_bo_process_reloc2(target_bo); 2204fe517fc9Smrg drm_intel_add_validate_buffer2(target_bo, false); 2205fe517fc9Smrg } 220622944501Smrg} 220722944501Smrg 220822944501Smrg 220922944501Smrgstatic void 221022944501Smrgdrm_intel_update_buffer_offsets(drm_intel_bufmgr_gem *bufmgr_gem) 221122944501Smrg{ 221222944501Smrg int i; 221322944501Smrg 221422944501Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 221522944501Smrg drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; 221622944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 221722944501Smrg 221822944501Smrg /* Update the buffer offset */ 221920131375Smrg if (bufmgr_gem->exec_objects[i].offset != bo->offset64) { 2220fe517fc9Smrg DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n", 2221d82d45b3Sjoerg bo_gem->gem_handle, bo_gem->name, 2222fe517fc9Smrg upper_32_bits(bo->offset64), 2223fe517fc9Smrg lower_32_bits(bo->offset64), 2224fe517fc9Smrg upper_32_bits(bufmgr_gem->exec_objects[i].offset), 2225fe517fc9Smrg lower_32_bits(bufmgr_gem->exec_objects[i].offset)); 222620131375Smrg bo->offset64 = bufmgr_gem->exec_objects[i].offset; 222722944501Smrg bo->offset = bufmgr_gem->exec_objects[i].offset; 222822944501Smrg } 222922944501Smrg } 223022944501Smrg} 223122944501Smrg 223222944501Smrgstatic void 223322944501Smrgdrm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem) 223422944501Smrg{ 223522944501Smrg int i; 223622944501Smrg 223722944501Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 223822944501Smrg drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; 223922944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; 224022944501Smrg 224122944501Smrg /* Update the buffer offset */ 224220131375Smrg if (bufmgr_gem->exec2_objects[i].offset != bo->offset64) { 2243fe517fc9Smrg /* If we're seeing softpinned object here it means that the kernel 2244fe517fc9Smrg * has relocated our object... Indicating a programming error 2245fe517fc9Smrg */ 2246fe517fc9Smrg assert(!bo_gem->is_softpin); 2247fe517fc9Smrg DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n", 2248d82d45b3Sjoerg bo_gem->gem_handle, bo_gem->name, 2249fe517fc9Smrg upper_32_bits(bo->offset64), 2250fe517fc9Smrg lower_32_bits(bo->offset64), 2251fe517fc9Smrg upper_32_bits(bufmgr_gem->exec2_objects[i].offset), 2252fe517fc9Smrg lower_32_bits(bufmgr_gem->exec2_objects[i].offset)); 225320131375Smrg bo->offset64 = bufmgr_gem->exec2_objects[i].offset; 225422944501Smrg bo->offset = bufmgr_gem->exec2_objects[i].offset; 225522944501Smrg } 225622944501Smrg } 225722944501Smrg} 225822944501Smrg 2259424e9256Smrgvoid 226020131375Smrgdrm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo, 226120131375Smrg int x1, int y1, int width, int height, 226220131375Smrg enum aub_dump_bmp_format format, 226320131375Smrg int pitch, int offset) 226420131375Smrg{ 226520131375Smrg} 226620131375Smrg 226720131375Smrgstatic int 226820131375Smrgdrm_intel_gem_bo_exec(drm_intel_bo *bo, int used, 226920131375Smrg drm_clip_rect_t * cliprects, int num_cliprects, int DR4) 227020131375Smrg{ 227120131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 227220131375Smrg struct drm_i915_gem_execbuffer execbuf; 227320131375Smrg int ret, i; 227420131375Smrg 2275fe517fc9Smrg if (to_bo_gem(bo)->has_error) 227620131375Smrg return -ENOMEM; 227720131375Smrg 227820131375Smrg pthread_mutex_lock(&bufmgr_gem->lock); 227920131375Smrg /* Update indices and set up the validate list. */ 228020131375Smrg drm_intel_gem_bo_process_reloc(bo); 228120131375Smrg 228220131375Smrg /* Add the batch buffer to the validation list. There are no 228320131375Smrg * relocations pointing to it. 228420131375Smrg */ 228520131375Smrg drm_intel_add_validate_buffer(bo); 228620131375Smrg 2287424e9256Smrg memclear(execbuf); 228820131375Smrg execbuf.buffers_ptr = (uintptr_t) bufmgr_gem->exec_objects; 228920131375Smrg execbuf.buffer_count = bufmgr_gem->exec_count; 229020131375Smrg execbuf.batch_start_offset = 0; 229120131375Smrg execbuf.batch_len = used; 229220131375Smrg execbuf.cliprects_ptr = (uintptr_t) cliprects; 229320131375Smrg execbuf.num_cliprects = num_cliprects; 229420131375Smrg execbuf.DR1 = 0; 229520131375Smrg execbuf.DR4 = DR4; 229620131375Smrg 229720131375Smrg ret = drmIoctl(bufmgr_gem->fd, 229820131375Smrg DRM_IOCTL_I915_GEM_EXECBUFFER, 229920131375Smrg &execbuf); 230020131375Smrg if (ret != 0) { 230120131375Smrg ret = -errno; 230220131375Smrg if (errno == ENOSPC) { 230320131375Smrg DBG("Execbuffer fails to pin. " 230420131375Smrg "Estimate: %u. Actual: %u. Available: %u\n", 230520131375Smrg drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos, 230620131375Smrg bufmgr_gem-> 230720131375Smrg exec_count), 230820131375Smrg drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos, 230920131375Smrg bufmgr_gem-> 231020131375Smrg exec_count), 231120131375Smrg (unsigned int)bufmgr_gem->gtt_size); 231220131375Smrg } 231320131375Smrg } 231420131375Smrg drm_intel_update_buffer_offsets(bufmgr_gem); 231520131375Smrg 231620131375Smrg if (bufmgr_gem->bufmgr.debug) 231720131375Smrg drm_intel_gem_dump_validation_list(bufmgr_gem); 231820131375Smrg 231920131375Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 2320fe517fc9Smrg drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]); 232120131375Smrg 232220131375Smrg bo_gem->idle = false; 232320131375Smrg 232420131375Smrg /* Disconnect the buffer from the validate list */ 232520131375Smrg bo_gem->validate_index = -1; 232620131375Smrg bufmgr_gem->exec_bos[i] = NULL; 232720131375Smrg } 232820131375Smrg bufmgr_gem->exec_count = 0; 232920131375Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 233020131375Smrg 233120131375Smrg return ret; 233220131375Smrg} 233320131375Smrg 233420131375Smrgstatic int 233520131375Smrgdo_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx, 233620131375Smrg drm_clip_rect_t *cliprects, int num_cliprects, int DR4, 233720131375Smrg unsigned int flags) 233820131375Smrg{ 233920131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; 234020131375Smrg struct drm_i915_gem_execbuffer2 execbuf; 234120131375Smrg int ret = 0; 234220131375Smrg int i; 234320131375Smrg 2344fe517fc9Smrg if (to_bo_gem(bo)->has_error) 2345fe517fc9Smrg return -ENOMEM; 2346fe517fc9Smrg 234720131375Smrg switch (flags & 0x7) { 234820131375Smrg default: 234920131375Smrg return -EINVAL; 235020131375Smrg case I915_EXEC_BLT: 23519ce4edccSmrg if (!bufmgr_gem->has_blt) 23529ce4edccSmrg return -EINVAL; 23539ce4edccSmrg break; 23549ce4edccSmrg case I915_EXEC_BSD: 23559ce4edccSmrg if (!bufmgr_gem->has_bsd) 23569ce4edccSmrg return -EINVAL; 23579ce4edccSmrg break; 235820131375Smrg case I915_EXEC_VEBOX: 235920131375Smrg if (!bufmgr_gem->has_vebox) 236020131375Smrg return -EINVAL; 236120131375Smrg break; 23629ce4edccSmrg case I915_EXEC_RENDER: 23639ce4edccSmrg case I915_EXEC_DEFAULT: 23649ce4edccSmrg break; 23659ce4edccSmrg } 2366aaba2545Smrg 236722944501Smrg pthread_mutex_lock(&bufmgr_gem->lock); 236822944501Smrg /* Update indices and set up the validate list. */ 236922944501Smrg drm_intel_gem_bo_process_reloc2(bo); 237022944501Smrg 237122944501Smrg /* Add the batch buffer to the validation list. There are no relocations 237222944501Smrg * pointing to it. 237322944501Smrg */ 237422944501Smrg drm_intel_add_validate_buffer2(bo, 0); 237522944501Smrg 2376424e9256Smrg memclear(execbuf); 237722944501Smrg execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec2_objects; 237822944501Smrg execbuf.buffer_count = bufmgr_gem->exec_count; 237922944501Smrg execbuf.batch_start_offset = 0; 238022944501Smrg execbuf.batch_len = used; 238122944501Smrg execbuf.cliprects_ptr = (uintptr_t)cliprects; 238222944501Smrg execbuf.num_cliprects = num_cliprects; 238322944501Smrg execbuf.DR1 = 0; 238422944501Smrg execbuf.DR4 = DR4; 238520131375Smrg execbuf.flags = flags; 238620131375Smrg if (ctx == NULL) 238720131375Smrg i915_execbuffer2_set_context_id(execbuf, 0); 238820131375Smrg else 238920131375Smrg i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id); 239022944501Smrg execbuf.rsvd2 = 0; 239122944501Smrg 239220131375Smrg if (bufmgr_gem->no_exec) 239320131375Smrg goto skip_execution; 239420131375Smrg 23956d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 23966d98c517Smrg DRM_IOCTL_I915_GEM_EXECBUFFER2, 23976d98c517Smrg &execbuf); 239822944501Smrg if (ret != 0) { 239922944501Smrg ret = -errno; 24006d98c517Smrg if (ret == -ENOSPC) { 24019ce4edccSmrg DBG("Execbuffer fails to pin. " 24029ce4edccSmrg "Estimate: %u. Actual: %u. Available: %u\n", 24039ce4edccSmrg drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos, 24049ce4edccSmrg bufmgr_gem->exec_count), 24059ce4edccSmrg drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos, 24069ce4edccSmrg bufmgr_gem->exec_count), 24079ce4edccSmrg (unsigned int) bufmgr_gem->gtt_size); 240822944501Smrg } 240922944501Smrg } 241022944501Smrg drm_intel_update_buffer_offsets2(bufmgr_gem); 241122944501Smrg 241220131375Smrgskip_execution: 241322944501Smrg if (bufmgr_gem->bufmgr.debug) 241422944501Smrg drm_intel_gem_dump_validation_list(bufmgr_gem); 241522944501Smrg 241622944501Smrg for (i = 0; i < bufmgr_gem->exec_count; i++) { 2417fe517fc9Smrg drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]); 241822944501Smrg 241920131375Smrg bo_gem->idle = false; 242020131375Smrg 242122944501Smrg /* Disconnect the buffer from the validate list */ 242222944501Smrg bo_gem->validate_index = -1; 242322944501Smrg bufmgr_gem->exec_bos[i] = NULL; 242422944501Smrg } 242522944501Smrg bufmgr_gem->exec_count = 0; 242622944501Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 242722944501Smrg 242822944501Smrg return ret; 242922944501Smrg} 243022944501Smrg 2431aaba2545Smrgstatic int 2432aaba2545Smrgdrm_intel_gem_bo_exec2(drm_intel_bo *bo, int used, 2433aaba2545Smrg drm_clip_rect_t *cliprects, int num_cliprects, 2434aaba2545Smrg int DR4) 2435aaba2545Smrg{ 243620131375Smrg return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4, 243720131375Smrg I915_EXEC_RENDER); 243820131375Smrg} 243920131375Smrg 244020131375Smrgstatic int 244120131375Smrgdrm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used, 244220131375Smrg drm_clip_rect_t *cliprects, int num_cliprects, int DR4, 244320131375Smrg unsigned int flags) 244420131375Smrg{ 244520131375Smrg return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4, 244620131375Smrg flags); 244720131375Smrg} 244820131375Smrg 2449424e9256Smrgint 245020131375Smrgdrm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx, 245120131375Smrg int used, unsigned int flags) 245220131375Smrg{ 245320131375Smrg return do_exec2(bo, used, ctx, NULL, 0, 0, flags); 2454aaba2545Smrg} 2455aaba2545Smrg 245622944501Smrgstatic int 245722944501Smrgdrm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment) 245822944501Smrg{ 245922944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 246022944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 246122944501Smrg struct drm_i915_gem_pin pin; 246222944501Smrg int ret; 246322944501Smrg 2464424e9256Smrg memclear(pin); 246522944501Smrg pin.handle = bo_gem->gem_handle; 246622944501Smrg pin.alignment = alignment; 246722944501Smrg 24686d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 24696d98c517Smrg DRM_IOCTL_I915_GEM_PIN, 24706d98c517Smrg &pin); 247122944501Smrg if (ret != 0) 247222944501Smrg return -errno; 247322944501Smrg 247420131375Smrg bo->offset64 = pin.offset; 247522944501Smrg bo->offset = pin.offset; 247622944501Smrg return 0; 247722944501Smrg} 247822944501Smrg 247922944501Smrgstatic int 248022944501Smrgdrm_intel_gem_bo_unpin(drm_intel_bo *bo) 248122944501Smrg{ 248222944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 248322944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 248422944501Smrg struct drm_i915_gem_unpin unpin; 248522944501Smrg int ret; 248622944501Smrg 2487424e9256Smrg memclear(unpin); 248822944501Smrg unpin.handle = bo_gem->gem_handle; 248922944501Smrg 24906d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin); 249122944501Smrg if (ret != 0) 249222944501Smrg return -errno; 249322944501Smrg 249422944501Smrg return 0; 249522944501Smrg} 249622944501Smrg 249722944501Smrgstatic int 24986d98c517Smrgdrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, 24996d98c517Smrg uint32_t tiling_mode, 25006d98c517Smrg uint32_t stride) 250122944501Smrg{ 250222944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 250322944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 250422944501Smrg struct drm_i915_gem_set_tiling set_tiling; 250522944501Smrg int ret; 250622944501Smrg 25076d98c517Smrg if (bo_gem->global_name == 0 && 25086d98c517Smrg tiling_mode == bo_gem->tiling_mode && 25096d98c517Smrg stride == bo_gem->stride) 251022944501Smrg return 0; 251122944501Smrg 251222944501Smrg memset(&set_tiling, 0, sizeof(set_tiling)); 251322944501Smrg do { 25146d98c517Smrg /* set_tiling is slightly broken and overwrites the 25156d98c517Smrg * input on the error path, so we have to open code 25166d98c517Smrg * rmIoctl. 25176d98c517Smrg */ 25186d98c517Smrg set_tiling.handle = bo_gem->gem_handle; 25196d98c517Smrg set_tiling.tiling_mode = tiling_mode; 252022944501Smrg set_tiling.stride = stride; 252122944501Smrg 252222944501Smrg ret = ioctl(bufmgr_gem->fd, 252322944501Smrg DRM_IOCTL_I915_GEM_SET_TILING, 252422944501Smrg &set_tiling); 25256d98c517Smrg } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 25266d98c517Smrg if (ret == -1) 25276d98c517Smrg return -errno; 25286d98c517Smrg 25296d98c517Smrg bo_gem->tiling_mode = set_tiling.tiling_mode; 25306d98c517Smrg bo_gem->swizzle_mode = set_tiling.swizzle_mode; 25316d98c517Smrg bo_gem->stride = set_tiling.stride; 25326d98c517Smrg return 0; 25336d98c517Smrg} 25346d98c517Smrg 25356d98c517Smrgstatic int 25366d98c517Smrgdrm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, 25376d98c517Smrg uint32_t stride) 25386d98c517Smrg{ 25396d98c517Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 25406d98c517Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 25416d98c517Smrg int ret; 25426d98c517Smrg 2543a884aba1Smrg /* Tiling with userptr surfaces is not supported 2544a884aba1Smrg * on all hardware so refuse it for time being. 2545a884aba1Smrg */ 2546a884aba1Smrg if (bo_gem->is_userptr) 2547a884aba1Smrg return -EINVAL; 2548a884aba1Smrg 25496d98c517Smrg /* Linear buffers have no stride. By ensuring that we only ever use 25506d98c517Smrg * stride 0 with linear buffers, we simplify our code. 25516d98c517Smrg */ 25526d98c517Smrg if (*tiling_mode == I915_TILING_NONE) 25536d98c517Smrg stride = 0; 25546d98c517Smrg 25556d98c517Smrg ret = drm_intel_gem_bo_set_tiling_internal(bo, *tiling_mode, stride); 25566d98c517Smrg if (ret == 0) 2557fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 255822944501Smrg 255922944501Smrg *tiling_mode = bo_gem->tiling_mode; 2560aaba2545Smrg return ret; 256122944501Smrg} 256222944501Smrg 256322944501Smrgstatic int 256422944501Smrgdrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, 256522944501Smrg uint32_t * swizzle_mode) 256622944501Smrg{ 256722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 256822944501Smrg 256922944501Smrg *tiling_mode = bo_gem->tiling_mode; 257022944501Smrg *swizzle_mode = bo_gem->swizzle_mode; 257122944501Smrg return 0; 257222944501Smrg} 257322944501Smrg 2574fe517fc9Smrgstatic int 2575fe517fc9Smrgdrm_intel_gem_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset) 2576fe517fc9Smrg{ 2577fe517fc9Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2578fe517fc9Smrg 2579fe517fc9Smrg bo_gem->is_softpin = true; 2580fe517fc9Smrg bo->offset64 = offset; 2581fe517fc9Smrg bo->offset = offset; 2582fe517fc9Smrg return 0; 2583fe517fc9Smrg} 2584fe517fc9Smrg 2585424e9256Smrgdrm_intel_bo * 258620131375Smrgdrm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size) 258720131375Smrg{ 258820131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 258920131375Smrg int ret; 259020131375Smrg uint32_t handle; 259120131375Smrg drm_intel_bo_gem *bo_gem; 259220131375Smrg struct drm_i915_gem_get_tiling get_tiling; 259320131375Smrg drmMMListHead *list; 259420131375Smrg 2595fe517fc9Smrg pthread_mutex_lock(&bufmgr_gem->lock); 259620131375Smrg ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle); 2597fe517fc9Smrg if (ret) { 2598fe517fc9Smrg DBG("create_from_prime: failed to obtain handle from fd: %s\n", strerror(errno)); 2599fe517fc9Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 2600fe517fc9Smrg return NULL; 2601fe517fc9Smrg } 260220131375Smrg 260320131375Smrg /* 260420131375Smrg * See if the kernel has already returned this buffer to us. Just as 260520131375Smrg * for named buffers, we must not create two bo's pointing at the same 260620131375Smrg * kernel object 260720131375Smrg */ 260820131375Smrg for (list = bufmgr_gem->named.next; 260920131375Smrg list != &bufmgr_gem->named; 261020131375Smrg list = list->next) { 261120131375Smrg bo_gem = DRMLISTENTRY(drm_intel_bo_gem, list, name_list); 261220131375Smrg if (bo_gem->gem_handle == handle) { 261320131375Smrg drm_intel_gem_bo_reference(&bo_gem->bo); 2614a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 261520131375Smrg return &bo_gem->bo; 261620131375Smrg } 261720131375Smrg } 261820131375Smrg 261920131375Smrg bo_gem = calloc(1, sizeof(*bo_gem)); 2620a884aba1Smrg if (!bo_gem) { 2621a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 262220131375Smrg return NULL; 2623a884aba1Smrg } 262420131375Smrg /* Determine size of bo. The fd-to-handle ioctl really should 262520131375Smrg * return the size, but it doesn't. If we have kernel 3.12 or 262620131375Smrg * later, we can lseek on the prime fd to get the size. Older 262720131375Smrg * kernels will just fail, in which case we fall back to the 262820131375Smrg * provided (estimated or guess size). */ 262920131375Smrg ret = lseek(prime_fd, 0, SEEK_END); 263020131375Smrg if (ret != -1) 263120131375Smrg bo_gem->bo.size = ret; 263220131375Smrg else 263320131375Smrg bo_gem->bo.size = size; 263420131375Smrg 263520131375Smrg bo_gem->bo.handle = handle; 263620131375Smrg bo_gem->bo.bufmgr = bufmgr; 263720131375Smrg 263820131375Smrg bo_gem->gem_handle = handle; 263920131375Smrg 264020131375Smrg atomic_set(&bo_gem->refcount, 1); 264120131375Smrg 264220131375Smrg bo_gem->name = "prime"; 264320131375Smrg bo_gem->validate_index = -1; 264420131375Smrg bo_gem->reloc_tree_fences = 0; 264520131375Smrg bo_gem->used_as_reloc_target = false; 264620131375Smrg bo_gem->has_error = false; 264720131375Smrg bo_gem->reusable = false; 2648fe517fc9Smrg bo_gem->use_48b_address_range = false; 264920131375Smrg 265020131375Smrg DRMINITLISTHEAD(&bo_gem->vma_list); 265120131375Smrg DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named); 2652a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 265320131375Smrg 2654424e9256Smrg memclear(get_tiling); 265520131375Smrg get_tiling.handle = bo_gem->gem_handle; 265620131375Smrg ret = drmIoctl(bufmgr_gem->fd, 265720131375Smrg DRM_IOCTL_I915_GEM_GET_TILING, 265820131375Smrg &get_tiling); 265920131375Smrg if (ret != 0) { 2660fe517fc9Smrg DBG("create_from_prime: failed to get tiling: %s\n", strerror(errno)); 266120131375Smrg drm_intel_gem_bo_unreference(&bo_gem->bo); 266220131375Smrg return NULL; 266320131375Smrg } 266420131375Smrg bo_gem->tiling_mode = get_tiling.tiling_mode; 266520131375Smrg bo_gem->swizzle_mode = get_tiling.swizzle_mode; 266620131375Smrg /* XXX stride is unknown */ 2667fe517fc9Smrg drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 266820131375Smrg 266920131375Smrg return &bo_gem->bo; 267020131375Smrg} 267120131375Smrg 2672424e9256Smrgint 267320131375Smrgdrm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd) 267420131375Smrg{ 267520131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 267620131375Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 267720131375Smrg 2678a884aba1Smrg pthread_mutex_lock(&bufmgr_gem->lock); 267920131375Smrg if (DRMLISTEMPTY(&bo_gem->name_list)) 268020131375Smrg DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named); 2681a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 268220131375Smrg 268320131375Smrg if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle, 268420131375Smrg DRM_CLOEXEC, prime_fd) != 0) 268520131375Smrg return -errno; 268620131375Smrg 268720131375Smrg bo_gem->reusable = false; 268820131375Smrg 268920131375Smrg return 0; 269020131375Smrg} 269120131375Smrg 269222944501Smrgstatic int 269322944501Smrgdrm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name) 269422944501Smrg{ 269522944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 269622944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 269722944501Smrg int ret; 269822944501Smrg 269922944501Smrg if (!bo_gem->global_name) { 270020131375Smrg struct drm_gem_flink flink; 270120131375Smrg 2702424e9256Smrg memclear(flink); 270322944501Smrg flink.handle = bo_gem->gem_handle; 270422944501Smrg 2705a884aba1Smrg pthread_mutex_lock(&bufmgr_gem->lock); 2706a884aba1Smrg 27076d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink); 2708a884aba1Smrg if (ret != 0) { 2709a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 271022944501Smrg return -errno; 2711a884aba1Smrg } 271220131375Smrg 271322944501Smrg bo_gem->global_name = flink.name; 271420131375Smrg bo_gem->reusable = false; 271520131375Smrg 271620131375Smrg if (DRMLISTEMPTY(&bo_gem->name_list)) 271720131375Smrg DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named); 2718a884aba1Smrg pthread_mutex_unlock(&bufmgr_gem->lock); 271922944501Smrg } 272022944501Smrg 272122944501Smrg *name = bo_gem->global_name; 272222944501Smrg return 0; 272322944501Smrg} 272422944501Smrg 272522944501Smrg/** 272622944501Smrg * Enables unlimited caching of buffer objects for reuse. 272722944501Smrg * 272822944501Smrg * This is potentially very memory expensive, as the cache at each bucket 272922944501Smrg * size is only bounded by how many buffers of that size we've managed to have 273022944501Smrg * in flight at once. 273122944501Smrg */ 2732424e9256Smrgvoid 273322944501Smrgdrm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr) 273422944501Smrg{ 273522944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 273622944501Smrg 273720131375Smrg bufmgr_gem->bo_reuse = true; 273822944501Smrg} 273922944501Smrg 274022944501Smrg/** 274122944501Smrg * Enable use of fenced reloc type. 274222944501Smrg * 274322944501Smrg * New code should enable this to avoid unnecessary fence register 274422944501Smrg * allocation. If this option is not enabled, all relocs will have fence 274522944501Smrg * register allocated. 274622944501Smrg */ 2747424e9256Smrgvoid 274822944501Smrgdrm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr) 274922944501Smrg{ 275022944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 275122944501Smrg 275222944501Smrg if (bufmgr_gem->bufmgr.bo_exec == drm_intel_gem_bo_exec2) 275320131375Smrg bufmgr_gem->fenced_relocs = true; 275422944501Smrg} 275522944501Smrg 275622944501Smrg/** 275722944501Smrg * Return the additional aperture space required by the tree of buffer objects 275822944501Smrg * rooted at bo. 275922944501Smrg */ 276022944501Smrgstatic int 276122944501Smrgdrm_intel_gem_bo_get_aperture_space(drm_intel_bo *bo) 276222944501Smrg{ 276322944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 276422944501Smrg int i; 276522944501Smrg int total = 0; 276622944501Smrg 276722944501Smrg if (bo == NULL || bo_gem->included_in_check_aperture) 276822944501Smrg return 0; 276922944501Smrg 277022944501Smrg total += bo->size; 277120131375Smrg bo_gem->included_in_check_aperture = true; 277222944501Smrg 277322944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) 277422944501Smrg total += 277522944501Smrg drm_intel_gem_bo_get_aperture_space(bo_gem-> 277622944501Smrg reloc_target_info[i].bo); 277722944501Smrg 277822944501Smrg return total; 277922944501Smrg} 278022944501Smrg 278122944501Smrg/** 278222944501Smrg * Count the number of buffers in this list that need a fence reg 278322944501Smrg * 278422944501Smrg * If the count is greater than the number of available regs, we'll have 278522944501Smrg * to ask the caller to resubmit a batch with fewer tiled buffers. 278622944501Smrg * 278722944501Smrg * This function over-counts if the same buffer is used multiple times. 278822944501Smrg */ 278922944501Smrgstatic unsigned int 279022944501Smrgdrm_intel_gem_total_fences(drm_intel_bo ** bo_array, int count) 279122944501Smrg{ 279222944501Smrg int i; 279322944501Smrg unsigned int total = 0; 279422944501Smrg 279522944501Smrg for (i = 0; i < count; i++) { 279622944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i]; 279722944501Smrg 279822944501Smrg if (bo_gem == NULL) 279922944501Smrg continue; 280022944501Smrg 280122944501Smrg total += bo_gem->reloc_tree_fences; 280222944501Smrg } 280322944501Smrg return total; 280422944501Smrg} 280522944501Smrg 280622944501Smrg/** 280722944501Smrg * Clear the flag set by drm_intel_gem_bo_get_aperture_space() so we're ready 280822944501Smrg * for the next drm_intel_bufmgr_check_aperture_space() call. 280922944501Smrg */ 281022944501Smrgstatic void 281122944501Smrgdrm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo) 281222944501Smrg{ 281322944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 281422944501Smrg int i; 281522944501Smrg 281622944501Smrg if (bo == NULL || !bo_gem->included_in_check_aperture) 281722944501Smrg return; 281822944501Smrg 281920131375Smrg bo_gem->included_in_check_aperture = false; 282022944501Smrg 282122944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) 282222944501Smrg drm_intel_gem_bo_clear_aperture_space_flag(bo_gem-> 282322944501Smrg reloc_target_info[i].bo); 282422944501Smrg} 282522944501Smrg 282622944501Smrg/** 282722944501Smrg * Return a conservative estimate for the amount of aperture required 282822944501Smrg * for a collection of buffers. This may double-count some buffers. 282922944501Smrg */ 283022944501Smrgstatic unsigned int 283122944501Smrgdrm_intel_gem_estimate_batch_space(drm_intel_bo **bo_array, int count) 283222944501Smrg{ 283322944501Smrg int i; 283422944501Smrg unsigned int total = 0; 283522944501Smrg 283622944501Smrg for (i = 0; i < count; i++) { 283722944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i]; 283822944501Smrg if (bo_gem != NULL) 283922944501Smrg total += bo_gem->reloc_tree_size; 284022944501Smrg } 284122944501Smrg return total; 284222944501Smrg} 284322944501Smrg 284422944501Smrg/** 284522944501Smrg * Return the amount of aperture needed for a collection of buffers. 284622944501Smrg * This avoids double counting any buffers, at the cost of looking 284722944501Smrg * at every buffer in the set. 284822944501Smrg */ 284922944501Smrgstatic unsigned int 285022944501Smrgdrm_intel_gem_compute_batch_space(drm_intel_bo **bo_array, int count) 285122944501Smrg{ 285222944501Smrg int i; 285322944501Smrg unsigned int total = 0; 285422944501Smrg 285522944501Smrg for (i = 0; i < count; i++) { 285622944501Smrg total += drm_intel_gem_bo_get_aperture_space(bo_array[i]); 285722944501Smrg /* For the first buffer object in the array, we get an 285822944501Smrg * accurate count back for its reloc_tree size (since nothing 285922944501Smrg * had been flagged as being counted yet). We can save that 286022944501Smrg * value out as a more conservative reloc_tree_size that 286122944501Smrg * avoids double-counting target buffers. Since the first 286222944501Smrg * buffer happens to usually be the batch buffer in our 286322944501Smrg * callers, this can pull us back from doing the tree 286422944501Smrg * walk on every new batch emit. 286522944501Smrg */ 286622944501Smrg if (i == 0) { 286722944501Smrg drm_intel_bo_gem *bo_gem = 286822944501Smrg (drm_intel_bo_gem *) bo_array[i]; 286922944501Smrg bo_gem->reloc_tree_size = total; 287022944501Smrg } 287122944501Smrg } 287222944501Smrg 287322944501Smrg for (i = 0; i < count; i++) 287422944501Smrg drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]); 287522944501Smrg return total; 287622944501Smrg} 287722944501Smrg 287822944501Smrg/** 287922944501Smrg * Return -1 if the batchbuffer should be flushed before attempting to 288022944501Smrg * emit rendering referencing the buffers pointed to by bo_array. 288122944501Smrg * 288222944501Smrg * This is required because if we try to emit a batchbuffer with relocations 288322944501Smrg * to a tree of buffers that won't simultaneously fit in the aperture, 288422944501Smrg * the rendering will return an error at a point where the software is not 288522944501Smrg * prepared to recover from it. 288622944501Smrg * 288722944501Smrg * However, we also want to emit the batchbuffer significantly before we reach 288822944501Smrg * the limit, as a series of batchbuffers each of which references buffers 288922944501Smrg * covering almost all of the aperture means that at each emit we end up 289022944501Smrg * waiting to evict a buffer from the last rendering, and we get synchronous 289122944501Smrg * performance. By emitting smaller batchbuffers, we eat some CPU overhead to 289222944501Smrg * get better parallelism. 289322944501Smrg */ 289422944501Smrgstatic int 289522944501Smrgdrm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count) 289622944501Smrg{ 289722944501Smrg drm_intel_bufmgr_gem *bufmgr_gem = 289822944501Smrg (drm_intel_bufmgr_gem *) bo_array[0]->bufmgr; 289922944501Smrg unsigned int total = 0; 290022944501Smrg unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4; 290122944501Smrg int total_fences; 290222944501Smrg 290322944501Smrg /* Check for fence reg constraints if necessary */ 290422944501Smrg if (bufmgr_gem->available_fences) { 290522944501Smrg total_fences = drm_intel_gem_total_fences(bo_array, count); 290622944501Smrg if (total_fences > bufmgr_gem->available_fences) 290722944501Smrg return -ENOSPC; 290822944501Smrg } 290922944501Smrg 291022944501Smrg total = drm_intel_gem_estimate_batch_space(bo_array, count); 291122944501Smrg 291222944501Smrg if (total > threshold) 291322944501Smrg total = drm_intel_gem_compute_batch_space(bo_array, count); 291422944501Smrg 291522944501Smrg if (total > threshold) { 291622944501Smrg DBG("check_space: overflowed available aperture, " 291722944501Smrg "%dkb vs %dkb\n", 291822944501Smrg total / 1024, (int)bufmgr_gem->gtt_size / 1024); 291922944501Smrg return -ENOSPC; 292022944501Smrg } else { 292122944501Smrg DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024, 292222944501Smrg (int)bufmgr_gem->gtt_size / 1024); 292322944501Smrg return 0; 292422944501Smrg } 292522944501Smrg} 292622944501Smrg 292722944501Smrg/* 292822944501Smrg * Disable buffer reuse for objects which are shared with the kernel 292922944501Smrg * as scanout buffers 293022944501Smrg */ 293122944501Smrgstatic int 293222944501Smrgdrm_intel_gem_bo_disable_reuse(drm_intel_bo *bo) 293322944501Smrg{ 293422944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 293522944501Smrg 293620131375Smrg bo_gem->reusable = false; 293722944501Smrg return 0; 293822944501Smrg} 293922944501Smrg 2940aaba2545Smrgstatic int 2941aaba2545Smrgdrm_intel_gem_bo_is_reusable(drm_intel_bo *bo) 2942aaba2545Smrg{ 2943aaba2545Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2944aaba2545Smrg 2945aaba2545Smrg return bo_gem->reusable; 2946aaba2545Smrg} 2947aaba2545Smrg 294822944501Smrgstatic int 294922944501Smrg_drm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo) 295022944501Smrg{ 295122944501Smrg drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 295222944501Smrg int i; 295322944501Smrg 295422944501Smrg for (i = 0; i < bo_gem->reloc_count; i++) { 295522944501Smrg if (bo_gem->reloc_target_info[i].bo == target_bo) 295622944501Smrg return 1; 2957aaba2545Smrg if (bo == bo_gem->reloc_target_info[i].bo) 2958aaba2545Smrg continue; 295922944501Smrg if (_drm_intel_gem_bo_references(bo_gem->reloc_target_info[i].bo, 296022944501Smrg target_bo)) 296122944501Smrg return 1; 296222944501Smrg } 296322944501Smrg 2964fe517fc9Smrg for (i = 0; i< bo_gem->softpin_target_count; i++) { 2965fe517fc9Smrg if (bo_gem->softpin_target[i] == target_bo) 2966fe517fc9Smrg return 1; 2967fe517fc9Smrg if (_drm_intel_gem_bo_references(bo_gem->softpin_target[i], target_bo)) 2968fe517fc9Smrg return 1; 2969fe517fc9Smrg } 2970fe517fc9Smrg 297122944501Smrg return 0; 297222944501Smrg} 297322944501Smrg 297422944501Smrg/** Return true if target_bo is referenced by bo's relocation tree. */ 297522944501Smrgstatic int 297622944501Smrgdrm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo) 297722944501Smrg{ 297822944501Smrg drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; 297922944501Smrg 298022944501Smrg if (bo == NULL || target_bo == NULL) 298122944501Smrg return 0; 298222944501Smrg if (target_bo_gem->used_as_reloc_target) 298322944501Smrg return _drm_intel_gem_bo_references(bo, target_bo); 298422944501Smrg return 0; 298522944501Smrg} 298622944501Smrg 2987aaba2545Smrgstatic void 2988aaba2545Smrgadd_bucket(drm_intel_bufmgr_gem *bufmgr_gem, int size) 2989aaba2545Smrg{ 2990aaba2545Smrg unsigned int i = bufmgr_gem->num_buckets; 2991aaba2545Smrg 2992aaba2545Smrg assert(i < ARRAY_SIZE(bufmgr_gem->cache_bucket)); 2993aaba2545Smrg 2994aaba2545Smrg DRMINITLISTHEAD(&bufmgr_gem->cache_bucket[i].head); 2995aaba2545Smrg bufmgr_gem->cache_bucket[i].size = size; 2996aaba2545Smrg bufmgr_gem->num_buckets++; 2997aaba2545Smrg} 2998aaba2545Smrg 2999aaba2545Smrgstatic void 3000aaba2545Smrginit_cache_buckets(drm_intel_bufmgr_gem *bufmgr_gem) 3001aaba2545Smrg{ 3002aaba2545Smrg unsigned long size, cache_max_size = 64 * 1024 * 1024; 3003aaba2545Smrg 3004aaba2545Smrg /* OK, so power of two buckets was too wasteful of memory. 3005aaba2545Smrg * Give 3 other sizes between each power of two, to hopefully 3006aaba2545Smrg * cover things accurately enough. (The alternative is 3007aaba2545Smrg * probably to just go for exact matching of sizes, and assume 3008aaba2545Smrg * that for things like composited window resize the tiled 3009aaba2545Smrg * width/height alignment and rounding of sizes to pages will 3010aaba2545Smrg * get us useful cache hit rates anyway) 3011aaba2545Smrg */ 3012aaba2545Smrg add_bucket(bufmgr_gem, 4096); 3013aaba2545Smrg add_bucket(bufmgr_gem, 4096 * 2); 3014aaba2545Smrg add_bucket(bufmgr_gem, 4096 * 3); 3015aaba2545Smrg 3016aaba2545Smrg /* Initialize the linked lists for BO reuse cache. */ 3017aaba2545Smrg for (size = 4 * 4096; size <= cache_max_size; size *= 2) { 3018aaba2545Smrg add_bucket(bufmgr_gem, size); 3019aaba2545Smrg 3020aaba2545Smrg add_bucket(bufmgr_gem, size + size * 1 / 4); 3021aaba2545Smrg add_bucket(bufmgr_gem, size + size * 2 / 4); 3022aaba2545Smrg add_bucket(bufmgr_gem, size + size * 3 / 4); 3023aaba2545Smrg } 3024aaba2545Smrg} 3025aaba2545Smrg 3026424e9256Smrgvoid 302720131375Smrgdrm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit) 302820131375Smrg{ 302920131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 303020131375Smrg 303120131375Smrg bufmgr_gem->vma_max = limit; 303220131375Smrg 303320131375Smrg drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); 303420131375Smrg} 303520131375Smrg 303620131375Smrg/** 303720131375Smrg * Get the PCI ID for the device. This can be overridden by setting the 303820131375Smrg * INTEL_DEVID_OVERRIDE environment variable to the desired ID. 303920131375Smrg */ 304020131375Smrgstatic int 304120131375Smrgget_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem) 304220131375Smrg{ 304320131375Smrg char *devid_override; 3044424e9256Smrg int devid = 0; 304520131375Smrg int ret; 304620131375Smrg drm_i915_getparam_t gp; 304720131375Smrg 304820131375Smrg if (geteuid() == getuid()) { 304920131375Smrg devid_override = getenv("INTEL_DEVID_OVERRIDE"); 305020131375Smrg if (devid_override) { 305120131375Smrg bufmgr_gem->no_exec = true; 305220131375Smrg return strtod(devid_override, NULL); 305320131375Smrg } 305420131375Smrg } 305520131375Smrg 3056424e9256Smrg memclear(gp); 305720131375Smrg gp.param = I915_PARAM_CHIPSET_ID; 305820131375Smrg gp.value = &devid; 305920131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 306020131375Smrg if (ret) { 306120131375Smrg fprintf(stderr, "get chip id failed: %d [%d]\n", ret, errno); 306220131375Smrg fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value); 306320131375Smrg } 306420131375Smrg return devid; 306520131375Smrg} 306620131375Smrg 3067424e9256Smrgint 306820131375Smrgdrm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr) 306920131375Smrg{ 307020131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 307120131375Smrg 307220131375Smrg return bufmgr_gem->pci_device; 307320131375Smrg} 307420131375Smrg 307520131375Smrg/** 307620131375Smrg * Sets the AUB filename. 307720131375Smrg * 307820131375Smrg * This function has to be called before drm_intel_bufmgr_gem_set_aub_dump() 307920131375Smrg * for it to have any effect. 308020131375Smrg */ 3081424e9256Smrgvoid 308220131375Smrgdrm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr, 308320131375Smrg const char *filename) 308420131375Smrg{ 308520131375Smrg} 308620131375Smrg 308720131375Smrg/** 308820131375Smrg * Sets up AUB dumping. 308920131375Smrg * 309020131375Smrg * This is a trace file format that can be used with the simulator. 309120131375Smrg * Packets are emitted in a format somewhat like GPU command packets. 309220131375Smrg * You can set up a GTT and upload your objects into the referenced 309320131375Smrg * space, then send off batchbuffers and get BMPs out the other end. 309420131375Smrg */ 3095424e9256Smrgvoid 309620131375Smrgdrm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable) 309720131375Smrg{ 3098fe517fc9Smrg fprintf(stderr, "libdrm aub dumping is deprecated.\n\n" 3099fe517fc9Smrg "Use intel_aubdump from intel-gpu-tools instead. Install intel-gpu-tools,\n" 3100fe517fc9Smrg "then run (for example)\n\n" 3101fe517fc9Smrg "\t$ intel_aubdump --output=trace.aub glxgears -geometry 500x500\n\n" 3102fe517fc9Smrg "See the intel_aubdump man page for more details.\n"); 310320131375Smrg} 310420131375Smrg 3105424e9256Smrgdrm_intel_context * 310620131375Smrgdrm_intel_gem_context_create(drm_intel_bufmgr *bufmgr) 310720131375Smrg{ 310820131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 310920131375Smrg struct drm_i915_gem_context_create create; 311020131375Smrg drm_intel_context *context = NULL; 311120131375Smrg int ret; 311220131375Smrg 311320131375Smrg context = calloc(1, sizeof(*context)); 311420131375Smrg if (!context) 311520131375Smrg return NULL; 311620131375Smrg 3117424e9256Smrg memclear(create); 311820131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create); 311920131375Smrg if (ret != 0) { 312020131375Smrg DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n", 312120131375Smrg strerror(errno)); 312220131375Smrg free(context); 312320131375Smrg return NULL; 312420131375Smrg } 312520131375Smrg 312620131375Smrg context->ctx_id = create.ctx_id; 312720131375Smrg context->bufmgr = bufmgr; 312820131375Smrg 312920131375Smrg return context; 313020131375Smrg} 313120131375Smrg 3132424e9256Smrgvoid 313320131375Smrgdrm_intel_gem_context_destroy(drm_intel_context *ctx) 313420131375Smrg{ 313520131375Smrg drm_intel_bufmgr_gem *bufmgr_gem; 313620131375Smrg struct drm_i915_gem_context_destroy destroy; 313720131375Smrg int ret; 313820131375Smrg 313920131375Smrg if (ctx == NULL) 314020131375Smrg return; 314120131375Smrg 3142424e9256Smrg memclear(destroy); 314320131375Smrg 314420131375Smrg bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr; 314520131375Smrg destroy.ctx_id = ctx->ctx_id; 314620131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, 314720131375Smrg &destroy); 314820131375Smrg if (ret != 0) 314920131375Smrg fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n", 315020131375Smrg strerror(errno)); 315120131375Smrg 315220131375Smrg free(ctx); 315320131375Smrg} 315420131375Smrg 3155424e9256Smrgint 315620131375Smrgdrm_intel_get_reset_stats(drm_intel_context *ctx, 315720131375Smrg uint32_t *reset_count, 315820131375Smrg uint32_t *active, 315920131375Smrg uint32_t *pending) 316020131375Smrg{ 316120131375Smrg drm_intel_bufmgr_gem *bufmgr_gem; 316220131375Smrg struct drm_i915_reset_stats stats; 316320131375Smrg int ret; 316420131375Smrg 316520131375Smrg if (ctx == NULL) 316620131375Smrg return -EINVAL; 316720131375Smrg 3168424e9256Smrg memclear(stats); 316920131375Smrg 317020131375Smrg bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr; 317120131375Smrg stats.ctx_id = ctx->ctx_id; 317220131375Smrg ret = drmIoctl(bufmgr_gem->fd, 317320131375Smrg DRM_IOCTL_I915_GET_RESET_STATS, 317420131375Smrg &stats); 317520131375Smrg if (ret == 0) { 317620131375Smrg if (reset_count != NULL) 317720131375Smrg *reset_count = stats.reset_count; 317820131375Smrg 317920131375Smrg if (active != NULL) 318020131375Smrg *active = stats.batch_active; 318120131375Smrg 318220131375Smrg if (pending != NULL) 318320131375Smrg *pending = stats.batch_pending; 318420131375Smrg } 318520131375Smrg 318620131375Smrg return ret; 318720131375Smrg} 318820131375Smrg 3189424e9256Smrgint 319020131375Smrgdrm_intel_reg_read(drm_intel_bufmgr *bufmgr, 319120131375Smrg uint32_t offset, 319220131375Smrg uint64_t *result) 319320131375Smrg{ 319420131375Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 319520131375Smrg struct drm_i915_reg_read reg_read; 319620131375Smrg int ret; 319720131375Smrg 3198424e9256Smrg memclear(reg_read); 319920131375Smrg reg_read.offset = offset; 320020131375Smrg 320120131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, ®_read); 320220131375Smrg 320320131375Smrg *result = reg_read.val; 320420131375Smrg return ret; 320520131375Smrg} 320620131375Smrg 3207424e9256Smrgint 3208424e9256Smrgdrm_intel_get_subslice_total(int fd, unsigned int *subslice_total) 3209424e9256Smrg{ 3210424e9256Smrg drm_i915_getparam_t gp; 3211424e9256Smrg int ret; 3212424e9256Smrg 3213424e9256Smrg memclear(gp); 3214424e9256Smrg gp.value = (int*)subslice_total; 3215424e9256Smrg gp.param = I915_PARAM_SUBSLICE_TOTAL; 3216424e9256Smrg ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); 3217424e9256Smrg if (ret) 3218424e9256Smrg return -errno; 3219424e9256Smrg 3220424e9256Smrg return 0; 3221424e9256Smrg} 3222424e9256Smrg 3223424e9256Smrgint 3224424e9256Smrgdrm_intel_get_eu_total(int fd, unsigned int *eu_total) 3225424e9256Smrg{ 3226424e9256Smrg drm_i915_getparam_t gp; 3227424e9256Smrg int ret; 3228424e9256Smrg 3229424e9256Smrg memclear(gp); 3230424e9256Smrg gp.value = (int*)eu_total; 3231424e9256Smrg gp.param = I915_PARAM_EU_TOTAL; 3232424e9256Smrg ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); 3233424e9256Smrg if (ret) 3234424e9256Smrg return -errno; 3235424e9256Smrg 3236424e9256Smrg return 0; 3237424e9256Smrg} 323820131375Smrg 323920131375Smrg/** 324020131375Smrg * Annotate the given bo for use in aub dumping. 324120131375Smrg * 324220131375Smrg * \param annotations is an array of drm_intel_aub_annotation objects 324320131375Smrg * describing the type of data in various sections of the bo. Each 324420131375Smrg * element of the array specifies the type and subtype of a section of 324520131375Smrg * the bo, and the past-the-end offset of that section. The elements 324620131375Smrg * of \c annotations must be sorted so that ending_offset is 324720131375Smrg * increasing. 324820131375Smrg * 324920131375Smrg * \param count is the number of elements in the \c annotations array. 325020131375Smrg * If \c count is zero, then \c annotations will not be dereferenced. 325120131375Smrg * 325220131375Smrg * Annotations are copied into a private data structure, so caller may 325320131375Smrg * re-use the memory pointed to by \c annotations after the call 325420131375Smrg * returns. 325520131375Smrg * 325620131375Smrg * Annotations are stored for the lifetime of the bo; to reset to the 325720131375Smrg * default state (no annotations), call this function with a \c count 325820131375Smrg * of zero. 325920131375Smrg */ 3260424e9256Smrgvoid 326120131375Smrgdrm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo, 326220131375Smrg drm_intel_aub_annotation *annotations, 326320131375Smrg unsigned count) 326420131375Smrg{ 326520131375Smrg} 326620131375Smrg 3267a884aba1Smrgstatic pthread_mutex_t bufmgr_list_mutex = PTHREAD_MUTEX_INITIALIZER; 3268a884aba1Smrgstatic drmMMListHead bufmgr_list = { &bufmgr_list, &bufmgr_list }; 3269a884aba1Smrg 3270a884aba1Smrgstatic drm_intel_bufmgr_gem * 3271a884aba1Smrgdrm_intel_bufmgr_gem_find(int fd) 3272a884aba1Smrg{ 3273a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem; 3274a884aba1Smrg 3275a884aba1Smrg DRMLISTFOREACHENTRY(bufmgr_gem, &bufmgr_list, managers) { 3276a884aba1Smrg if (bufmgr_gem->fd == fd) { 3277a884aba1Smrg atomic_inc(&bufmgr_gem->refcount); 3278a884aba1Smrg return bufmgr_gem; 3279a884aba1Smrg } 3280a884aba1Smrg } 3281a884aba1Smrg 3282a884aba1Smrg return NULL; 3283a884aba1Smrg} 3284a884aba1Smrg 3285a884aba1Smrgstatic void 3286a884aba1Smrgdrm_intel_bufmgr_gem_unref(drm_intel_bufmgr *bufmgr) 3287a884aba1Smrg{ 3288a884aba1Smrg drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 3289a884aba1Smrg 3290a884aba1Smrg if (atomic_add_unless(&bufmgr_gem->refcount, -1, 1)) { 3291a884aba1Smrg pthread_mutex_lock(&bufmgr_list_mutex); 3292a884aba1Smrg 3293a884aba1Smrg if (atomic_dec_and_test(&bufmgr_gem->refcount)) { 3294a884aba1Smrg DRMLISTDEL(&bufmgr_gem->managers); 3295a884aba1Smrg drm_intel_bufmgr_gem_destroy(bufmgr); 3296a884aba1Smrg } 3297a884aba1Smrg 3298a884aba1Smrg pthread_mutex_unlock(&bufmgr_list_mutex); 3299a884aba1Smrg } 3300a884aba1Smrg} 3301a884aba1Smrg 330222944501Smrg/** 330322944501Smrg * Initializes the GEM buffer manager, which uses the kernel to allocate, map, 330422944501Smrg * and manage map buffer objections. 330522944501Smrg * 330622944501Smrg * \param fd File descriptor of the opened DRM device. 330722944501Smrg */ 3308424e9256Smrgdrm_intel_bufmgr * 330922944501Smrgdrm_intel_bufmgr_gem_init(int fd, int batch_size) 331022944501Smrg{ 331122944501Smrg drm_intel_bufmgr_gem *bufmgr_gem; 331222944501Smrg struct drm_i915_gem_get_aperture aperture; 331322944501Smrg drm_i915_getparam_t gp; 331420131375Smrg int ret, tmp; 331520131375Smrg bool exec2 = false; 331622944501Smrg 3317a884aba1Smrg pthread_mutex_lock(&bufmgr_list_mutex); 3318a884aba1Smrg 3319a884aba1Smrg bufmgr_gem = drm_intel_bufmgr_gem_find(fd); 3320a884aba1Smrg if (bufmgr_gem) 3321a884aba1Smrg goto exit; 3322a884aba1Smrg 332322944501Smrg bufmgr_gem = calloc(1, sizeof(*bufmgr_gem)); 332422944501Smrg if (bufmgr_gem == NULL) 3325a884aba1Smrg goto exit; 332622944501Smrg 332722944501Smrg bufmgr_gem->fd = fd; 3328a884aba1Smrg atomic_set(&bufmgr_gem->refcount, 1); 332922944501Smrg 333022944501Smrg if (pthread_mutex_init(&bufmgr_gem->lock, NULL) != 0) { 333122944501Smrg free(bufmgr_gem); 3332a884aba1Smrg bufmgr_gem = NULL; 3333a884aba1Smrg goto exit; 333422944501Smrg } 333522944501Smrg 3336424e9256Smrg memclear(aperture); 33376d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, 33386d98c517Smrg DRM_IOCTL_I915_GEM_GET_APERTURE, 33396d98c517Smrg &aperture); 334022944501Smrg 334122944501Smrg if (ret == 0) 334222944501Smrg bufmgr_gem->gtt_size = aperture.aper_available_size; 334322944501Smrg else { 334422944501Smrg fprintf(stderr, "DRM_IOCTL_I915_GEM_APERTURE failed: %s\n", 334522944501Smrg strerror(errno)); 334622944501Smrg bufmgr_gem->gtt_size = 128 * 1024 * 1024; 334722944501Smrg fprintf(stderr, "Assuming %dkB available aperture size.\n" 334822944501Smrg "May lead to reduced performance or incorrect " 334922944501Smrg "rendering.\n", 335022944501Smrg (int)bufmgr_gem->gtt_size / 1024); 335122944501Smrg } 335222944501Smrg 335320131375Smrg bufmgr_gem->pci_device = get_pci_device_id(bufmgr_gem); 335422944501Smrg 335520131375Smrg if (IS_GEN2(bufmgr_gem->pci_device)) 335622944501Smrg bufmgr_gem->gen = 2; 335720131375Smrg else if (IS_GEN3(bufmgr_gem->pci_device)) 335822944501Smrg bufmgr_gem->gen = 3; 335920131375Smrg else if (IS_GEN4(bufmgr_gem->pci_device)) 336022944501Smrg bufmgr_gem->gen = 4; 336120131375Smrg else if (IS_GEN5(bufmgr_gem->pci_device)) 336220131375Smrg bufmgr_gem->gen = 5; 336320131375Smrg else if (IS_GEN6(bufmgr_gem->pci_device)) 336422944501Smrg bufmgr_gem->gen = 6; 336520131375Smrg else if (IS_GEN7(bufmgr_gem->pci_device)) 336620131375Smrg bufmgr_gem->gen = 7; 336720131375Smrg else if (IS_GEN8(bufmgr_gem->pci_device)) 336820131375Smrg bufmgr_gem->gen = 8; 33693c748557Ssnj else if (IS_GEN9(bufmgr_gem->pci_device)) 33703c748557Ssnj bufmgr_gem->gen = 9; 337120131375Smrg else { 337220131375Smrg free(bufmgr_gem); 3373a884aba1Smrg bufmgr_gem = NULL; 3374a884aba1Smrg goto exit; 337520131375Smrg } 337620131375Smrg 337720131375Smrg if (IS_GEN3(bufmgr_gem->pci_device) && 337820131375Smrg bufmgr_gem->gtt_size > 256*1024*1024) { 337920131375Smrg /* The unmappable part of gtt on gen 3 (i.e. above 256MB) can't 338020131375Smrg * be used for tiled blits. To simplify the accounting, just 3381fe517fc9Smrg * subtract the unmappable part (fixed to 256MB on all known 338220131375Smrg * gen3 devices) if the kernel advertises it. */ 338320131375Smrg bufmgr_gem->gtt_size -= 256*1024*1024; 338420131375Smrg } 338520131375Smrg 3386424e9256Smrg memclear(gp); 338720131375Smrg gp.value = &tmp; 338822944501Smrg 338922944501Smrg gp.param = I915_PARAM_HAS_EXECBUF2; 33906d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 339122944501Smrg if (!ret) 339220131375Smrg exec2 = true; 339322944501Smrg 3394aaba2545Smrg gp.param = I915_PARAM_HAS_BSD; 33956d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 33969ce4edccSmrg bufmgr_gem->has_bsd = ret == 0; 33979ce4edccSmrg 33989ce4edccSmrg gp.param = I915_PARAM_HAS_BLT; 33999ce4edccSmrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 34009ce4edccSmrg bufmgr_gem->has_blt = ret == 0; 34019ce4edccSmrg 34029ce4edccSmrg gp.param = I915_PARAM_HAS_RELAXED_FENCING; 34039ce4edccSmrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 34049ce4edccSmrg bufmgr_gem->has_relaxed_fencing = ret == 0; 3405aaba2545Smrg 3406424e9256Smrg bufmgr_gem->bufmgr.bo_alloc_userptr = check_bo_alloc_userptr; 3407a884aba1Smrg 340820131375Smrg gp.param = I915_PARAM_HAS_WAIT_TIMEOUT; 340920131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 341020131375Smrg bufmgr_gem->has_wait_timeout = ret == 0; 341120131375Smrg 341220131375Smrg gp.param = I915_PARAM_HAS_LLC; 341320131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 341420131375Smrg if (ret != 0) { 341520131375Smrg /* Kernel does not supports HAS_LLC query, fallback to GPU 341620131375Smrg * generation detection and assume that we have LLC on GEN6/7 341720131375Smrg */ 341820131375Smrg bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) | 341920131375Smrg IS_GEN7(bufmgr_gem->pci_device)); 342020131375Smrg } else 342120131375Smrg bufmgr_gem->has_llc = *gp.value; 342220131375Smrg 342320131375Smrg gp.param = I915_PARAM_HAS_VEBOX; 342420131375Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 342520131375Smrg bufmgr_gem->has_vebox = (ret == 0) & (*gp.value > 0); 342620131375Smrg 3427fe517fc9Smrg gp.param = I915_PARAM_HAS_EXEC_SOFTPIN; 3428fe517fc9Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3429fe517fc9Smrg if (ret == 0 && *gp.value > 0) 3430fe517fc9Smrg bufmgr_gem->bufmgr.bo_set_softpin_offset = drm_intel_gem_bo_set_softpin_offset; 3431fe517fc9Smrg 343222944501Smrg if (bufmgr_gem->gen < 4) { 343322944501Smrg gp.param = I915_PARAM_NUM_FENCES_AVAIL; 343422944501Smrg gp.value = &bufmgr_gem->available_fences; 34356d98c517Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 343622944501Smrg if (ret) { 343722944501Smrg fprintf(stderr, "get fences failed: %d [%d]\n", ret, 343822944501Smrg errno); 343922944501Smrg fprintf(stderr, "param: %d, val: %d\n", gp.param, 344022944501Smrg *gp.value); 344122944501Smrg bufmgr_gem->available_fences = 0; 344222944501Smrg } else { 344322944501Smrg /* XXX The kernel reports the total number of fences, 344422944501Smrg * including any that may be pinned. 344522944501Smrg * 344622944501Smrg * We presume that there will be at least one pinned 344722944501Smrg * fence for the scanout buffer, but there may be more 344822944501Smrg * than one scanout and the user may be manually 344922944501Smrg * pinning buffers. Let's move to execbuffer2 and 345022944501Smrg * thereby forget the insanity of using fences... 345122944501Smrg */ 345222944501Smrg bufmgr_gem->available_fences -= 2; 345322944501Smrg if (bufmgr_gem->available_fences < 0) 345422944501Smrg bufmgr_gem->available_fences = 0; 345522944501Smrg } 345622944501Smrg } 345722944501Smrg 3458fe517fc9Smrg if (bufmgr_gem->gen >= 8) { 3459fe517fc9Smrg gp.param = I915_PARAM_HAS_ALIASING_PPGTT; 3460fe517fc9Smrg ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3461fe517fc9Smrg if (ret == 0 && *gp.value == 3) 3462fe517fc9Smrg bufmgr_gem->bufmgr.bo_use_48b_address_range = drm_intel_gem_bo_use_48b_address_range; 3463fe517fc9Smrg } 3464fe517fc9Smrg 346522944501Smrg /* Let's go with one relocation per every 2 dwords (but round down a bit 346622944501Smrg * since a power of two will mean an extra page allocation for the reloc 346722944501Smrg * buffer). 346822944501Smrg * 346922944501Smrg * Every 4 was too few for the blender benchmark. 347022944501Smrg */ 347122944501Smrg bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2; 347222944501Smrg 347322944501Smrg bufmgr_gem->bufmgr.bo_alloc = drm_intel_gem_bo_alloc; 347422944501Smrg bufmgr_gem->bufmgr.bo_alloc_for_render = 347522944501Smrg drm_intel_gem_bo_alloc_for_render; 347622944501Smrg bufmgr_gem->bufmgr.bo_alloc_tiled = drm_intel_gem_bo_alloc_tiled; 347722944501Smrg bufmgr_gem->bufmgr.bo_reference = drm_intel_gem_bo_reference; 347822944501Smrg bufmgr_gem->bufmgr.bo_unreference = drm_intel_gem_bo_unreference; 347922944501Smrg bufmgr_gem->bufmgr.bo_map = drm_intel_gem_bo_map; 348022944501Smrg bufmgr_gem->bufmgr.bo_unmap = drm_intel_gem_bo_unmap; 348122944501Smrg bufmgr_gem->bufmgr.bo_subdata = drm_intel_gem_bo_subdata; 348222944501Smrg bufmgr_gem->bufmgr.bo_get_subdata = drm_intel_gem_bo_get_subdata; 348322944501Smrg bufmgr_gem->bufmgr.bo_wait_rendering = drm_intel_gem_bo_wait_rendering; 348422944501Smrg bufmgr_gem->bufmgr.bo_emit_reloc = drm_intel_gem_bo_emit_reloc; 348522944501Smrg bufmgr_gem->bufmgr.bo_emit_reloc_fence = drm_intel_gem_bo_emit_reloc_fence; 348622944501Smrg bufmgr_gem->bufmgr.bo_pin = drm_intel_gem_bo_pin; 348722944501Smrg bufmgr_gem->bufmgr.bo_unpin = drm_intel_gem_bo_unpin; 348822944501Smrg bufmgr_gem->bufmgr.bo_get_tiling = drm_intel_gem_bo_get_tiling; 348922944501Smrg bufmgr_gem->bufmgr.bo_set_tiling = drm_intel_gem_bo_set_tiling; 349022944501Smrg bufmgr_gem->bufmgr.bo_flink = drm_intel_gem_bo_flink; 349122944501Smrg /* Use the new one if available */ 3492aaba2545Smrg if (exec2) { 349322944501Smrg bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec2; 34949ce4edccSmrg bufmgr_gem->bufmgr.bo_mrb_exec = drm_intel_gem_bo_mrb_exec2; 3495aaba2545Smrg } else 349622944501Smrg bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec; 349722944501Smrg bufmgr_gem->bufmgr.bo_busy = drm_intel_gem_bo_busy; 349822944501Smrg bufmgr_gem->bufmgr.bo_madvise = drm_intel_gem_bo_madvise; 3499a884aba1Smrg bufmgr_gem->bufmgr.destroy = drm_intel_bufmgr_gem_unref; 350022944501Smrg bufmgr_gem->bufmgr.debug = 0; 350122944501Smrg bufmgr_gem->bufmgr.check_aperture_space = 350222944501Smrg drm_intel_gem_check_aperture_space; 350322944501Smrg bufmgr_gem->bufmgr.bo_disable_reuse = drm_intel_gem_bo_disable_reuse; 3504aaba2545Smrg bufmgr_gem->bufmgr.bo_is_reusable = drm_intel_gem_bo_is_reusable; 350522944501Smrg bufmgr_gem->bufmgr.get_pipe_from_crtc_id = 350622944501Smrg drm_intel_gem_get_pipe_from_crtc_id; 350722944501Smrg bufmgr_gem->bufmgr.bo_references = drm_intel_gem_bo_references; 350822944501Smrg 350920131375Smrg DRMINITLISTHEAD(&bufmgr_gem->named); 3510aaba2545Smrg init_cache_buckets(bufmgr_gem); 351122944501Smrg 351220131375Smrg DRMINITLISTHEAD(&bufmgr_gem->vma_cache); 351320131375Smrg bufmgr_gem->vma_max = -1; /* unlimited by default */ 351420131375Smrg 3515a884aba1Smrg DRMLISTADD(&bufmgr_gem->managers, &bufmgr_list); 3516a884aba1Smrg 3517a884aba1Smrgexit: 3518a884aba1Smrg pthread_mutex_unlock(&bufmgr_list_mutex); 3519a884aba1Smrg 3520a884aba1Smrg return bufmgr_gem != NULL ? &bufmgr_gem->bufmgr : NULL; 352122944501Smrg} 3522