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