1d722e3fbSopenharmony_ci/************************************************************************** 2d722e3fbSopenharmony_ci * 3d722e3fbSopenharmony_ci * Copyright � 2007 Red Hat Inc. 4d722e3fbSopenharmony_ci * Copyright � 2007-2012 Intel Corporation 5d722e3fbSopenharmony_ci * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA 6d722e3fbSopenharmony_ci * All Rights Reserved. 7d722e3fbSopenharmony_ci * 8d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 9d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the 10d722e3fbSopenharmony_ci * "Software"), to deal in the Software without restriction, including 11d722e3fbSopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 12d722e3fbSopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 13d722e3fbSopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 14d722e3fbSopenharmony_ci * the following conditions: 15d722e3fbSopenharmony_ci * 16d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19d722e3fbSopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 20d722e3fbSopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21d722e3fbSopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22d722e3fbSopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 23d722e3fbSopenharmony_ci * 24d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the 25d722e3fbSopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 26d722e3fbSopenharmony_ci * of the Software. 27d722e3fbSopenharmony_ci * 28d722e3fbSopenharmony_ci * 29d722e3fbSopenharmony_ci **************************************************************************/ 30d722e3fbSopenharmony_ci/* 31d722e3fbSopenharmony_ci * Authors: Thomas Hellstr�m <thomas-at-tungstengraphics-dot-com> 32d722e3fbSopenharmony_ci * Keith Whitwell <keithw-at-tungstengraphics-dot-com> 33d722e3fbSopenharmony_ci * Eric Anholt <eric@anholt.net> 34d722e3fbSopenharmony_ci * Dave Airlie <airlied@linux.ie> 35d722e3fbSopenharmony_ci */ 36d722e3fbSopenharmony_ci 37d722e3fbSopenharmony_ci#include <xf86drm.h> 38d722e3fbSopenharmony_ci#include <xf86atomic.h> 39d722e3fbSopenharmony_ci#include <fcntl.h> 40d722e3fbSopenharmony_ci#include <stdio.h> 41d722e3fbSopenharmony_ci#include <stdlib.h> 42d722e3fbSopenharmony_ci#include <string.h> 43d722e3fbSopenharmony_ci#include <unistd.h> 44d722e3fbSopenharmony_ci#include <assert.h> 45d722e3fbSopenharmony_ci#include <pthread.h> 46d722e3fbSopenharmony_ci#include <sys/ioctl.h> 47d722e3fbSopenharmony_ci#include <sys/stat.h> 48d722e3fbSopenharmony_ci#include <sys/types.h> 49d722e3fbSopenharmony_ci#include <stdbool.h> 50d722e3fbSopenharmony_ci 51d722e3fbSopenharmony_ci#include "errno.h" 52d722e3fbSopenharmony_ci#ifndef ETIME 53d722e3fbSopenharmony_ci#define ETIME ETIMEDOUT 54d722e3fbSopenharmony_ci#endif 55d722e3fbSopenharmony_ci#include "libdrm_macros.h" 56d722e3fbSopenharmony_ci#include "libdrm_lists.h" 57d722e3fbSopenharmony_ci#include "intel_bufmgr.h" 58d722e3fbSopenharmony_ci#include "intel_bufmgr_priv.h" 59d722e3fbSopenharmony_ci#include "intel_chipset.h" 60d722e3fbSopenharmony_ci#include "string.h" 61d722e3fbSopenharmony_ci 62d722e3fbSopenharmony_ci#include "i915_drm.h" 63d722e3fbSopenharmony_ci#include "uthash.h" 64d722e3fbSopenharmony_ci 65d722e3fbSopenharmony_ci#if HAVE_VALGRIND 66d722e3fbSopenharmony_ci#include <valgrind.h> 67d722e3fbSopenharmony_ci#include <memcheck.h> 68d722e3fbSopenharmony_ci#define VG(x) x 69d722e3fbSopenharmony_ci#else 70d722e3fbSopenharmony_ci#define VG(x) 71d722e3fbSopenharmony_ci#endif 72d722e3fbSopenharmony_ci 73d722e3fbSopenharmony_ci#define memclear(s) memset(&s, 0, sizeof(s)) 74d722e3fbSopenharmony_ci 75d722e3fbSopenharmony_ci#define DBG(...) do { \ 76d722e3fbSopenharmony_ci if (bufmgr_gem->bufmgr.debug) \ 77d722e3fbSopenharmony_ci fprintf(stderr, __VA_ARGS__); \ 78d722e3fbSopenharmony_ci} while (0) 79d722e3fbSopenharmony_ci 80d722e3fbSopenharmony_ci#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 81d722e3fbSopenharmony_ci#define MAX2(A, B) ((A) > (B) ? (A) : (B)) 82d722e3fbSopenharmony_ci 83d722e3fbSopenharmony_ci/** 84d722e3fbSopenharmony_ci * upper_32_bits - return bits 32-63 of a number 85d722e3fbSopenharmony_ci * @n: the number we're accessing 86d722e3fbSopenharmony_ci * 87d722e3fbSopenharmony_ci * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress 88d722e3fbSopenharmony_ci * the "right shift count >= width of type" warning when that quantity is 89d722e3fbSopenharmony_ci * 32-bits. 90d722e3fbSopenharmony_ci */ 91d722e3fbSopenharmony_ci#define upper_32_bits(n) ((__u32)(((n) >> 16) >> 16)) 92d722e3fbSopenharmony_ci 93d722e3fbSopenharmony_ci/** 94d722e3fbSopenharmony_ci * lower_32_bits - return bits 0-31 of a number 95d722e3fbSopenharmony_ci * @n: the number we're accessing 96d722e3fbSopenharmony_ci */ 97d722e3fbSopenharmony_ci#define lower_32_bits(n) ((__u32)(n)) 98d722e3fbSopenharmony_ci 99d722e3fbSopenharmony_citypedef struct _drm_intel_bo_gem drm_intel_bo_gem; 100d722e3fbSopenharmony_ci 101d722e3fbSopenharmony_cistruct drm_intel_gem_bo_bucket { 102d722e3fbSopenharmony_ci drmMMListHead head; 103d722e3fbSopenharmony_ci unsigned long size; 104d722e3fbSopenharmony_ci}; 105d722e3fbSopenharmony_ci 106d722e3fbSopenharmony_citypedef struct _drm_intel_bufmgr_gem { 107d722e3fbSopenharmony_ci drm_intel_bufmgr bufmgr; 108d722e3fbSopenharmony_ci 109d722e3fbSopenharmony_ci atomic_t refcount; 110d722e3fbSopenharmony_ci 111d722e3fbSopenharmony_ci int fd; 112d722e3fbSopenharmony_ci 113d722e3fbSopenharmony_ci int max_relocs; 114d722e3fbSopenharmony_ci 115d722e3fbSopenharmony_ci pthread_mutex_t lock; 116d722e3fbSopenharmony_ci 117d722e3fbSopenharmony_ci struct drm_i915_gem_exec_object2 *exec2_objects; 118d722e3fbSopenharmony_ci drm_intel_bo **exec_bos; 119d722e3fbSopenharmony_ci int exec_size; 120d722e3fbSopenharmony_ci int exec_count; 121d722e3fbSopenharmony_ci 122d722e3fbSopenharmony_ci /** Array of lists of cached gem objects of power-of-two sizes */ 123d722e3fbSopenharmony_ci struct drm_intel_gem_bo_bucket cache_bucket[14 * 4]; 124d722e3fbSopenharmony_ci int num_buckets; 125d722e3fbSopenharmony_ci time_t time; 126d722e3fbSopenharmony_ci 127d722e3fbSopenharmony_ci drmMMListHead managers; 128d722e3fbSopenharmony_ci 129d722e3fbSopenharmony_ci drm_intel_bo_gem *name_table; 130d722e3fbSopenharmony_ci drm_intel_bo_gem *handle_table; 131d722e3fbSopenharmony_ci 132d722e3fbSopenharmony_ci drmMMListHead vma_cache; 133d722e3fbSopenharmony_ci int vma_count, vma_open, vma_max; 134d722e3fbSopenharmony_ci 135d722e3fbSopenharmony_ci uint64_t gtt_size; 136d722e3fbSopenharmony_ci int available_fences; 137d722e3fbSopenharmony_ci int pci_device; 138d722e3fbSopenharmony_ci int gen; 139d722e3fbSopenharmony_ci unsigned int has_bsd : 1; 140d722e3fbSopenharmony_ci unsigned int has_blt : 1; 141d722e3fbSopenharmony_ci unsigned int has_relaxed_fencing : 1; 142d722e3fbSopenharmony_ci unsigned int has_llc : 1; 143d722e3fbSopenharmony_ci unsigned int has_wait_timeout : 1; 144d722e3fbSopenharmony_ci unsigned int bo_reuse : 1; 145d722e3fbSopenharmony_ci unsigned int no_exec : 1; 146d722e3fbSopenharmony_ci unsigned int has_vebox : 1; 147d722e3fbSopenharmony_ci unsigned int has_exec_async : 1; 148d722e3fbSopenharmony_ci bool fenced_relocs; 149d722e3fbSopenharmony_ci 150d722e3fbSopenharmony_ci struct { 151d722e3fbSopenharmony_ci void *ptr; 152d722e3fbSopenharmony_ci uint32_t handle; 153d722e3fbSopenharmony_ci } userptr_active; 154d722e3fbSopenharmony_ci 155d722e3fbSopenharmony_ci} drm_intel_bufmgr_gem; 156d722e3fbSopenharmony_ci 157d722e3fbSopenharmony_ci#define DRM_INTEL_RELOC_FENCE (1<<0) 158d722e3fbSopenharmony_ci 159d722e3fbSopenharmony_citypedef struct _drm_intel_reloc_target_info { 160d722e3fbSopenharmony_ci drm_intel_bo *bo; 161d722e3fbSopenharmony_ci int flags; 162d722e3fbSopenharmony_ci} drm_intel_reloc_target; 163d722e3fbSopenharmony_ci 164d722e3fbSopenharmony_cistruct _drm_intel_bo_gem { 165d722e3fbSopenharmony_ci drm_intel_bo bo; 166d722e3fbSopenharmony_ci 167d722e3fbSopenharmony_ci atomic_t refcount; 168d722e3fbSopenharmony_ci uint32_t gem_handle; 169d722e3fbSopenharmony_ci const char *name; 170d722e3fbSopenharmony_ci 171d722e3fbSopenharmony_ci /** 172d722e3fbSopenharmony_ci * Kenel-assigned global name for this object 173d722e3fbSopenharmony_ci * 174d722e3fbSopenharmony_ci * List contains both flink named and prime fd'd objects 175d722e3fbSopenharmony_ci */ 176d722e3fbSopenharmony_ci unsigned int global_name; 177d722e3fbSopenharmony_ci 178d722e3fbSopenharmony_ci UT_hash_handle handle_hh; 179d722e3fbSopenharmony_ci UT_hash_handle name_hh; 180d722e3fbSopenharmony_ci 181d722e3fbSopenharmony_ci /** 182d722e3fbSopenharmony_ci * Index of the buffer within the validation list while preparing a 183d722e3fbSopenharmony_ci * batchbuffer execution. 184d722e3fbSopenharmony_ci */ 185d722e3fbSopenharmony_ci int validate_index; 186d722e3fbSopenharmony_ci 187d722e3fbSopenharmony_ci /** 188d722e3fbSopenharmony_ci * Current tiling mode 189d722e3fbSopenharmony_ci */ 190d722e3fbSopenharmony_ci uint32_t tiling_mode; 191d722e3fbSopenharmony_ci uint32_t swizzle_mode; 192d722e3fbSopenharmony_ci unsigned long stride; 193d722e3fbSopenharmony_ci 194d722e3fbSopenharmony_ci unsigned long kflags; 195d722e3fbSopenharmony_ci 196d722e3fbSopenharmony_ci time_t free_time; 197d722e3fbSopenharmony_ci 198d722e3fbSopenharmony_ci /** Array passed to the DRM containing relocation information. */ 199d722e3fbSopenharmony_ci struct drm_i915_gem_relocation_entry *relocs; 200d722e3fbSopenharmony_ci /** 201d722e3fbSopenharmony_ci * Array of info structs corresponding to relocs[i].target_handle etc 202d722e3fbSopenharmony_ci */ 203d722e3fbSopenharmony_ci drm_intel_reloc_target *reloc_target_info; 204d722e3fbSopenharmony_ci /** Number of entries in relocs */ 205d722e3fbSopenharmony_ci int reloc_count; 206d722e3fbSopenharmony_ci /** Array of BOs that are referenced by this buffer and will be softpinned */ 207d722e3fbSopenharmony_ci drm_intel_bo **softpin_target; 208d722e3fbSopenharmony_ci /** Number softpinned BOs that are referenced by this buffer */ 209d722e3fbSopenharmony_ci int softpin_target_count; 210d722e3fbSopenharmony_ci /** Maximum amount of softpinned BOs that are referenced by this buffer */ 211d722e3fbSopenharmony_ci int softpin_target_size; 212d722e3fbSopenharmony_ci 213d722e3fbSopenharmony_ci /** Mapped address for the buffer, saved across map/unmap cycles */ 214d722e3fbSopenharmony_ci void *mem_virtual; 215d722e3fbSopenharmony_ci /** GTT virtual address for the buffer, saved across map/unmap cycles */ 216d722e3fbSopenharmony_ci void *gtt_virtual; 217d722e3fbSopenharmony_ci /** WC CPU address for the buffer, saved across map/unmap cycles */ 218d722e3fbSopenharmony_ci void *wc_virtual; 219d722e3fbSopenharmony_ci /** 220d722e3fbSopenharmony_ci * Virtual address of the buffer allocated by user, used for userptr 221d722e3fbSopenharmony_ci * objects only. 222d722e3fbSopenharmony_ci */ 223d722e3fbSopenharmony_ci void *user_virtual; 224d722e3fbSopenharmony_ci int map_count; 225d722e3fbSopenharmony_ci drmMMListHead vma_list; 226d722e3fbSopenharmony_ci 227d722e3fbSopenharmony_ci /** BO cache list */ 228d722e3fbSopenharmony_ci drmMMListHead head; 229d722e3fbSopenharmony_ci 230d722e3fbSopenharmony_ci /** 231d722e3fbSopenharmony_ci * Boolean of whether this BO and its children have been included in 232d722e3fbSopenharmony_ci * the current drm_intel_bufmgr_check_aperture_space() total. 233d722e3fbSopenharmony_ci */ 234d722e3fbSopenharmony_ci bool included_in_check_aperture; 235d722e3fbSopenharmony_ci 236d722e3fbSopenharmony_ci /** 237d722e3fbSopenharmony_ci * Boolean of whether this buffer has been used as a relocation 238d722e3fbSopenharmony_ci * target and had its size accounted for, and thus can't have any 239d722e3fbSopenharmony_ci * further relocations added to it. 240d722e3fbSopenharmony_ci */ 241d722e3fbSopenharmony_ci bool used_as_reloc_target; 242d722e3fbSopenharmony_ci 243d722e3fbSopenharmony_ci /** 244d722e3fbSopenharmony_ci * Boolean of whether we have encountered an error whilst building the relocation tree. 245d722e3fbSopenharmony_ci */ 246d722e3fbSopenharmony_ci bool has_error; 247d722e3fbSopenharmony_ci 248d722e3fbSopenharmony_ci /** 249d722e3fbSopenharmony_ci * Boolean of whether this buffer can be re-used 250d722e3fbSopenharmony_ci */ 251d722e3fbSopenharmony_ci bool reusable; 252d722e3fbSopenharmony_ci 253d722e3fbSopenharmony_ci /** 254d722e3fbSopenharmony_ci * Boolean of whether the GPU is definitely not accessing the buffer. 255d722e3fbSopenharmony_ci * 256d722e3fbSopenharmony_ci * This is only valid when reusable, since non-reusable 257d722e3fbSopenharmony_ci * buffers are those that have been shared with other 258d722e3fbSopenharmony_ci * processes, so we don't know their state. 259d722e3fbSopenharmony_ci */ 260d722e3fbSopenharmony_ci bool idle; 261d722e3fbSopenharmony_ci 262d722e3fbSopenharmony_ci /** 263d722e3fbSopenharmony_ci * Boolean of whether this buffer was allocated with userptr 264d722e3fbSopenharmony_ci */ 265d722e3fbSopenharmony_ci bool is_userptr; 266d722e3fbSopenharmony_ci 267d722e3fbSopenharmony_ci /** 268d722e3fbSopenharmony_ci * Size in bytes of this buffer and its relocation descendents. 269d722e3fbSopenharmony_ci * 270d722e3fbSopenharmony_ci * Used to avoid costly tree walking in 271d722e3fbSopenharmony_ci * drm_intel_bufmgr_check_aperture in the common case. 272d722e3fbSopenharmony_ci */ 273d722e3fbSopenharmony_ci int reloc_tree_size; 274d722e3fbSopenharmony_ci 275d722e3fbSopenharmony_ci /** 276d722e3fbSopenharmony_ci * Number of potential fence registers required by this buffer and its 277d722e3fbSopenharmony_ci * relocations. 278d722e3fbSopenharmony_ci */ 279d722e3fbSopenharmony_ci int reloc_tree_fences; 280d722e3fbSopenharmony_ci 281d722e3fbSopenharmony_ci /** Flags that we may need to do the SW_FINISH ioctl on unmap. */ 282d722e3fbSopenharmony_ci bool mapped_cpu_write; 283d722e3fbSopenharmony_ci}; 284d722e3fbSopenharmony_ci 285d722e3fbSopenharmony_cistatic unsigned int 286d722e3fbSopenharmony_cidrm_intel_gem_estimate_batch_space(drm_intel_bo ** bo_array, int count); 287d722e3fbSopenharmony_ci 288d722e3fbSopenharmony_cistatic unsigned int 289d722e3fbSopenharmony_cidrm_intel_gem_compute_batch_space(drm_intel_bo ** bo_array, int count); 290d722e3fbSopenharmony_ci 291d722e3fbSopenharmony_cistatic int 292d722e3fbSopenharmony_cidrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, 293d722e3fbSopenharmony_ci uint32_t * swizzle_mode); 294d722e3fbSopenharmony_ci 295d722e3fbSopenharmony_cistatic int 296d722e3fbSopenharmony_cidrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, 297d722e3fbSopenharmony_ci uint32_t tiling_mode, 298d722e3fbSopenharmony_ci uint32_t stride); 299d722e3fbSopenharmony_ci 300d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, 301d722e3fbSopenharmony_ci time_t time); 302d722e3fbSopenharmony_ci 303d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo); 304d722e3fbSopenharmony_ci 305d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_free(drm_intel_bo *bo); 306d722e3fbSopenharmony_ci 307d722e3fbSopenharmony_cistatic inline drm_intel_bo_gem *to_bo_gem(drm_intel_bo *bo) 308d722e3fbSopenharmony_ci{ 309d722e3fbSopenharmony_ci return (drm_intel_bo_gem *)bo; 310d722e3fbSopenharmony_ci} 311d722e3fbSopenharmony_ci 312d722e3fbSopenharmony_cistatic unsigned long 313d722e3fbSopenharmony_cidrm_intel_gem_bo_tile_size(drm_intel_bufmgr_gem *bufmgr_gem, unsigned long size, 314d722e3fbSopenharmony_ci uint32_t *tiling_mode) 315d722e3fbSopenharmony_ci{ 316d722e3fbSopenharmony_ci unsigned long min_size, max_size; 317d722e3fbSopenharmony_ci unsigned long i; 318d722e3fbSopenharmony_ci 319d722e3fbSopenharmony_ci if (*tiling_mode == I915_TILING_NONE) 320d722e3fbSopenharmony_ci return size; 321d722e3fbSopenharmony_ci 322d722e3fbSopenharmony_ci /* 965+ just need multiples of page size for tiling */ 323d722e3fbSopenharmony_ci if (bufmgr_gem->gen >= 4) 324d722e3fbSopenharmony_ci return ROUND_UP_TO(size, 4096); 325d722e3fbSopenharmony_ci 326d722e3fbSopenharmony_ci /* Older chips need powers of two, of at least 512k or 1M */ 327d722e3fbSopenharmony_ci if (bufmgr_gem->gen == 3) { 328d722e3fbSopenharmony_ci min_size = 1024*1024; 329d722e3fbSopenharmony_ci max_size = 128*1024*1024; 330d722e3fbSopenharmony_ci } else { 331d722e3fbSopenharmony_ci min_size = 512*1024; 332d722e3fbSopenharmony_ci max_size = 64*1024*1024; 333d722e3fbSopenharmony_ci } 334d722e3fbSopenharmony_ci 335d722e3fbSopenharmony_ci if (size > max_size) { 336d722e3fbSopenharmony_ci *tiling_mode = I915_TILING_NONE; 337d722e3fbSopenharmony_ci return size; 338d722e3fbSopenharmony_ci } 339d722e3fbSopenharmony_ci 340d722e3fbSopenharmony_ci /* Do we need to allocate every page for the fence? */ 341d722e3fbSopenharmony_ci if (bufmgr_gem->has_relaxed_fencing) 342d722e3fbSopenharmony_ci return ROUND_UP_TO(size, 4096); 343d722e3fbSopenharmony_ci 344d722e3fbSopenharmony_ci for (i = min_size; i < size; i <<= 1) 345d722e3fbSopenharmony_ci ; 346d722e3fbSopenharmony_ci 347d722e3fbSopenharmony_ci return i; 348d722e3fbSopenharmony_ci} 349d722e3fbSopenharmony_ci 350d722e3fbSopenharmony_ci/* 351d722e3fbSopenharmony_ci * Round a given pitch up to the minimum required for X tiling on a 352d722e3fbSopenharmony_ci * given chip. We use 512 as the minimum to allow for a later tiling 353d722e3fbSopenharmony_ci * change. 354d722e3fbSopenharmony_ci */ 355d722e3fbSopenharmony_cistatic unsigned long 356d722e3fbSopenharmony_cidrm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem, 357d722e3fbSopenharmony_ci unsigned long pitch, uint32_t *tiling_mode) 358d722e3fbSopenharmony_ci{ 359d722e3fbSopenharmony_ci unsigned long tile_width; 360d722e3fbSopenharmony_ci unsigned long i; 361d722e3fbSopenharmony_ci 362d722e3fbSopenharmony_ci /* If untiled, then just align it so that we can do rendering 363d722e3fbSopenharmony_ci * to it with the 3D engine. 364d722e3fbSopenharmony_ci */ 365d722e3fbSopenharmony_ci if (*tiling_mode == I915_TILING_NONE) 366d722e3fbSopenharmony_ci return ALIGN(pitch, 64); 367d722e3fbSopenharmony_ci 368d722e3fbSopenharmony_ci if (*tiling_mode == I915_TILING_X 369d722e3fbSopenharmony_ci || (IS_915(bufmgr_gem->pci_device) 370d722e3fbSopenharmony_ci && *tiling_mode == I915_TILING_Y)) 371d722e3fbSopenharmony_ci tile_width = 512; 372d722e3fbSopenharmony_ci else 373d722e3fbSopenharmony_ci tile_width = 128; 374d722e3fbSopenharmony_ci 375d722e3fbSopenharmony_ci /* 965 is flexible */ 376d722e3fbSopenharmony_ci if (bufmgr_gem->gen >= 4) 377d722e3fbSopenharmony_ci return ROUND_UP_TO(pitch, tile_width); 378d722e3fbSopenharmony_ci 379d722e3fbSopenharmony_ci /* The older hardware has a maximum pitch of 8192 with tiled 380d722e3fbSopenharmony_ci * surfaces, so fallback to untiled if it's too large. 381d722e3fbSopenharmony_ci */ 382d722e3fbSopenharmony_ci if (pitch > 8192) { 383d722e3fbSopenharmony_ci *tiling_mode = I915_TILING_NONE; 384d722e3fbSopenharmony_ci return ALIGN(pitch, 64); 385d722e3fbSopenharmony_ci } 386d722e3fbSopenharmony_ci 387d722e3fbSopenharmony_ci /* Pre-965 needs power of two tile width */ 388d722e3fbSopenharmony_ci for (i = tile_width; i < pitch; i <<= 1) 389d722e3fbSopenharmony_ci ; 390d722e3fbSopenharmony_ci 391d722e3fbSopenharmony_ci return i; 392d722e3fbSopenharmony_ci} 393d722e3fbSopenharmony_ci 394d722e3fbSopenharmony_cistatic struct drm_intel_gem_bo_bucket * 395d722e3fbSopenharmony_cidrm_intel_gem_bo_bucket_for_size(drm_intel_bufmgr_gem *bufmgr_gem, 396d722e3fbSopenharmony_ci unsigned long size) 397d722e3fbSopenharmony_ci{ 398d722e3fbSopenharmony_ci int i; 399d722e3fbSopenharmony_ci 400d722e3fbSopenharmony_ci for (i = 0; i < bufmgr_gem->num_buckets; i++) { 401d722e3fbSopenharmony_ci struct drm_intel_gem_bo_bucket *bucket = 402d722e3fbSopenharmony_ci &bufmgr_gem->cache_bucket[i]; 403d722e3fbSopenharmony_ci if (bucket->size >= size) { 404d722e3fbSopenharmony_ci return bucket; 405d722e3fbSopenharmony_ci } 406d722e3fbSopenharmony_ci } 407d722e3fbSopenharmony_ci 408d722e3fbSopenharmony_ci return NULL; 409d722e3fbSopenharmony_ci} 410d722e3fbSopenharmony_ci 411d722e3fbSopenharmony_cistatic void 412d722e3fbSopenharmony_cidrm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem) 413d722e3fbSopenharmony_ci{ 414d722e3fbSopenharmony_ci int i, j; 415d722e3fbSopenharmony_ci 416d722e3fbSopenharmony_ci for (i = 0; i < bufmgr_gem->exec_count; i++) { 417d722e3fbSopenharmony_ci drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; 418d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 419d722e3fbSopenharmony_ci 420d722e3fbSopenharmony_ci if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) { 421d722e3fbSopenharmony_ci DBG("%2d: %d %s(%s)\n", i, bo_gem->gem_handle, 422d722e3fbSopenharmony_ci bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "", 423d722e3fbSopenharmony_ci bo_gem->name); 424d722e3fbSopenharmony_ci continue; 425d722e3fbSopenharmony_ci } 426d722e3fbSopenharmony_ci 427d722e3fbSopenharmony_ci for (j = 0; j < bo_gem->reloc_count; j++) { 428d722e3fbSopenharmony_ci drm_intel_bo *target_bo = bo_gem->reloc_target_info[j].bo; 429d722e3fbSopenharmony_ci drm_intel_bo_gem *target_gem = 430d722e3fbSopenharmony_ci (drm_intel_bo_gem *) target_bo; 431d722e3fbSopenharmony_ci 432d722e3fbSopenharmony_ci DBG("%2d: %d %s(%s)@0x%08x %08x -> " 433d722e3fbSopenharmony_ci "%d (%s)@0x%08x %08x + 0x%08x\n", 434d722e3fbSopenharmony_ci i, 435d722e3fbSopenharmony_ci bo_gem->gem_handle, 436d722e3fbSopenharmony_ci bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "", 437d722e3fbSopenharmony_ci bo_gem->name, 438d722e3fbSopenharmony_ci upper_32_bits(bo_gem->relocs[j].offset), 439d722e3fbSopenharmony_ci lower_32_bits(bo_gem->relocs[j].offset), 440d722e3fbSopenharmony_ci target_gem->gem_handle, 441d722e3fbSopenharmony_ci target_gem->name, 442d722e3fbSopenharmony_ci upper_32_bits(target_bo->offset64), 443d722e3fbSopenharmony_ci lower_32_bits(target_bo->offset64), 444d722e3fbSopenharmony_ci bo_gem->relocs[j].delta); 445d722e3fbSopenharmony_ci } 446d722e3fbSopenharmony_ci 447d722e3fbSopenharmony_ci for (j = 0; j < bo_gem->softpin_target_count; j++) { 448d722e3fbSopenharmony_ci drm_intel_bo *target_bo = bo_gem->softpin_target[j]; 449d722e3fbSopenharmony_ci drm_intel_bo_gem *target_gem = 450d722e3fbSopenharmony_ci (drm_intel_bo_gem *) target_bo; 451d722e3fbSopenharmony_ci DBG("%2d: %d %s(%s) -> " 452d722e3fbSopenharmony_ci "%d *(%s)@0x%08x %08x\n", 453d722e3fbSopenharmony_ci i, 454d722e3fbSopenharmony_ci bo_gem->gem_handle, 455d722e3fbSopenharmony_ci bo_gem->kflags & EXEC_OBJECT_PINNED ? "*" : "", 456d722e3fbSopenharmony_ci bo_gem->name, 457d722e3fbSopenharmony_ci target_gem->gem_handle, 458d722e3fbSopenharmony_ci target_gem->name, 459d722e3fbSopenharmony_ci upper_32_bits(target_bo->offset64), 460d722e3fbSopenharmony_ci lower_32_bits(target_bo->offset64)); 461d722e3fbSopenharmony_ci } 462d722e3fbSopenharmony_ci } 463d722e3fbSopenharmony_ci} 464d722e3fbSopenharmony_ci 465d722e3fbSopenharmony_cistatic inline void 466d722e3fbSopenharmony_cidrm_intel_gem_bo_reference(drm_intel_bo *bo) 467d722e3fbSopenharmony_ci{ 468d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 469d722e3fbSopenharmony_ci 470d722e3fbSopenharmony_ci atomic_inc(&bo_gem->refcount); 471d722e3fbSopenharmony_ci} 472d722e3fbSopenharmony_ci 473d722e3fbSopenharmony_ci/** 474d722e3fbSopenharmony_ci * Adds the given buffer to the list of buffers to be validated (moved into the 475d722e3fbSopenharmony_ci * appropriate memory type) with the next batch submission. 476d722e3fbSopenharmony_ci * 477d722e3fbSopenharmony_ci * If a buffer is validated multiple times in a batch submission, it ends up 478d722e3fbSopenharmony_ci * with the intersection of the memory type flags and the union of the 479d722e3fbSopenharmony_ci * access flags. 480d722e3fbSopenharmony_ci */ 481d722e3fbSopenharmony_cistatic void 482d722e3fbSopenharmony_cidrm_intel_add_validate_buffer2(drm_intel_bo *bo, int need_fence) 483d722e3fbSopenharmony_ci{ 484d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; 485d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; 486d722e3fbSopenharmony_ci int index; 487d722e3fbSopenharmony_ci unsigned long flags; 488d722e3fbSopenharmony_ci 489d722e3fbSopenharmony_ci flags = 0; 490d722e3fbSopenharmony_ci if (need_fence) 491d722e3fbSopenharmony_ci flags |= EXEC_OBJECT_NEEDS_FENCE; 492d722e3fbSopenharmony_ci 493d722e3fbSopenharmony_ci if (bo_gem->validate_index != -1) { 494d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects[bo_gem->validate_index].flags |= flags; 495d722e3fbSopenharmony_ci return; 496d722e3fbSopenharmony_ci } 497d722e3fbSopenharmony_ci 498d722e3fbSopenharmony_ci /* Extend the array of validation entries as necessary. */ 499d722e3fbSopenharmony_ci if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) { 500d722e3fbSopenharmony_ci int new_size = bufmgr_gem->exec_size * 2; 501d722e3fbSopenharmony_ci 502d722e3fbSopenharmony_ci if (new_size == 0) 503d722e3fbSopenharmony_ci new_size = 5; 504d722e3fbSopenharmony_ci 505d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects = 506d722e3fbSopenharmony_ci realloc(bufmgr_gem->exec2_objects, 507d722e3fbSopenharmony_ci sizeof(*bufmgr_gem->exec2_objects) * new_size); 508d722e3fbSopenharmony_ci bufmgr_gem->exec_bos = 509d722e3fbSopenharmony_ci realloc(bufmgr_gem->exec_bos, 510d722e3fbSopenharmony_ci sizeof(*bufmgr_gem->exec_bos) * new_size); 511d722e3fbSopenharmony_ci bufmgr_gem->exec_size = new_size; 512d722e3fbSopenharmony_ci } 513d722e3fbSopenharmony_ci 514d722e3fbSopenharmony_ci index = bufmgr_gem->exec_count; 515d722e3fbSopenharmony_ci bo_gem->validate_index = index; 516d722e3fbSopenharmony_ci /* Fill in array entry */ 517d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects[index].handle = bo_gem->gem_handle; 518d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects[index].relocation_count = bo_gem->reloc_count; 519d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs; 520d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects[index].alignment = bo->align; 521d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects[index].offset = bo->offset64; 522d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects[index].flags = bo_gem->kflags | flags; 523d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects[index].rsvd1 = 0; 524d722e3fbSopenharmony_ci bufmgr_gem->exec2_objects[index].rsvd2 = 0; 525d722e3fbSopenharmony_ci bufmgr_gem->exec_bos[index] = bo; 526d722e3fbSopenharmony_ci bufmgr_gem->exec_count++; 527d722e3fbSopenharmony_ci} 528d722e3fbSopenharmony_ci 529d722e3fbSopenharmony_ci#define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \ 530d722e3fbSopenharmony_ci sizeof(uint32_t)) 531d722e3fbSopenharmony_ci 532d722e3fbSopenharmony_cistatic void 533d722e3fbSopenharmony_cidrm_intel_bo_gem_set_in_aperture_size(drm_intel_bufmgr_gem *bufmgr_gem, 534d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem, 535d722e3fbSopenharmony_ci unsigned int alignment) 536d722e3fbSopenharmony_ci{ 537d722e3fbSopenharmony_ci unsigned int size; 538d722e3fbSopenharmony_ci 539d722e3fbSopenharmony_ci assert(!bo_gem->used_as_reloc_target); 540d722e3fbSopenharmony_ci 541d722e3fbSopenharmony_ci /* The older chipsets are far-less flexible in terms of tiling, 542d722e3fbSopenharmony_ci * and require tiled buffer to be size aligned in the aperture. 543d722e3fbSopenharmony_ci * This means that in the worst possible case we will need a hole 544d722e3fbSopenharmony_ci * twice as large as the object in order for it to fit into the 545d722e3fbSopenharmony_ci * aperture. Optimal packing is for wimps. 546d722e3fbSopenharmony_ci */ 547d722e3fbSopenharmony_ci size = bo_gem->bo.size; 548d722e3fbSopenharmony_ci if (bufmgr_gem->gen < 4 && bo_gem->tiling_mode != I915_TILING_NONE) { 549d722e3fbSopenharmony_ci unsigned int min_size; 550d722e3fbSopenharmony_ci 551d722e3fbSopenharmony_ci if (bufmgr_gem->has_relaxed_fencing) { 552d722e3fbSopenharmony_ci if (bufmgr_gem->gen == 3) 553d722e3fbSopenharmony_ci min_size = 1024*1024; 554d722e3fbSopenharmony_ci else 555d722e3fbSopenharmony_ci min_size = 512*1024; 556d722e3fbSopenharmony_ci 557d722e3fbSopenharmony_ci while (min_size < size) 558d722e3fbSopenharmony_ci min_size *= 2; 559d722e3fbSopenharmony_ci } else 560d722e3fbSopenharmony_ci min_size = size; 561d722e3fbSopenharmony_ci 562d722e3fbSopenharmony_ci /* Account for worst-case alignment. */ 563d722e3fbSopenharmony_ci alignment = MAX2(alignment, min_size); 564d722e3fbSopenharmony_ci } 565d722e3fbSopenharmony_ci 566d722e3fbSopenharmony_ci bo_gem->reloc_tree_size = size + alignment; 567d722e3fbSopenharmony_ci} 568d722e3fbSopenharmony_ci 569d722e3fbSopenharmony_cistatic int 570d722e3fbSopenharmony_cidrm_intel_setup_reloc_list(drm_intel_bo *bo) 571d722e3fbSopenharmony_ci{ 572d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 573d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 574d722e3fbSopenharmony_ci unsigned int max_relocs = bufmgr_gem->max_relocs; 575d722e3fbSopenharmony_ci 576d722e3fbSopenharmony_ci if (bo->size / 4 < max_relocs) 577d722e3fbSopenharmony_ci max_relocs = bo->size / 4; 578d722e3fbSopenharmony_ci 579d722e3fbSopenharmony_ci bo_gem->relocs = malloc(max_relocs * 580d722e3fbSopenharmony_ci sizeof(struct drm_i915_gem_relocation_entry)); 581d722e3fbSopenharmony_ci bo_gem->reloc_target_info = malloc(max_relocs * 582d722e3fbSopenharmony_ci sizeof(drm_intel_reloc_target)); 583d722e3fbSopenharmony_ci if (bo_gem->relocs == NULL || bo_gem->reloc_target_info == NULL) { 584d722e3fbSopenharmony_ci bo_gem->has_error = true; 585d722e3fbSopenharmony_ci 586d722e3fbSopenharmony_ci free (bo_gem->relocs); 587d722e3fbSopenharmony_ci bo_gem->relocs = NULL; 588d722e3fbSopenharmony_ci 589d722e3fbSopenharmony_ci free (bo_gem->reloc_target_info); 590d722e3fbSopenharmony_ci bo_gem->reloc_target_info = NULL; 591d722e3fbSopenharmony_ci 592d722e3fbSopenharmony_ci return 1; 593d722e3fbSopenharmony_ci } 594d722e3fbSopenharmony_ci 595d722e3fbSopenharmony_ci return 0; 596d722e3fbSopenharmony_ci} 597d722e3fbSopenharmony_ci 598d722e3fbSopenharmony_cistatic int 599d722e3fbSopenharmony_cidrm_intel_gem_bo_busy(drm_intel_bo *bo) 600d722e3fbSopenharmony_ci{ 601d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 602d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 603d722e3fbSopenharmony_ci struct drm_i915_gem_busy busy; 604d722e3fbSopenharmony_ci int ret; 605d722e3fbSopenharmony_ci 606d722e3fbSopenharmony_ci if (bo_gem->reusable && bo_gem->idle) 607d722e3fbSopenharmony_ci return false; 608d722e3fbSopenharmony_ci 609d722e3fbSopenharmony_ci memclear(busy); 610d722e3fbSopenharmony_ci busy.handle = bo_gem->gem_handle; 611d722e3fbSopenharmony_ci 612d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy); 613d722e3fbSopenharmony_ci if (ret == 0) { 614d722e3fbSopenharmony_ci bo_gem->idle = !busy.busy; 615d722e3fbSopenharmony_ci return busy.busy; 616d722e3fbSopenharmony_ci } else { 617d722e3fbSopenharmony_ci return false; 618d722e3fbSopenharmony_ci } 619d722e3fbSopenharmony_ci} 620d722e3fbSopenharmony_ci 621d722e3fbSopenharmony_cistatic int 622d722e3fbSopenharmony_cidrm_intel_gem_bo_madvise_internal(drm_intel_bufmgr_gem *bufmgr_gem, 623d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem, int state) 624d722e3fbSopenharmony_ci{ 625d722e3fbSopenharmony_ci struct drm_i915_gem_madvise madv; 626d722e3fbSopenharmony_ci 627d722e3fbSopenharmony_ci memclear(madv); 628d722e3fbSopenharmony_ci madv.handle = bo_gem->gem_handle; 629d722e3fbSopenharmony_ci madv.madv = state; 630d722e3fbSopenharmony_ci madv.retained = 1; 631d722e3fbSopenharmony_ci drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv); 632d722e3fbSopenharmony_ci 633d722e3fbSopenharmony_ci return madv.retained; 634d722e3fbSopenharmony_ci} 635d722e3fbSopenharmony_ci 636d722e3fbSopenharmony_cistatic int 637d722e3fbSopenharmony_cidrm_intel_gem_bo_madvise(drm_intel_bo *bo, int madv) 638d722e3fbSopenharmony_ci{ 639d722e3fbSopenharmony_ci return drm_intel_gem_bo_madvise_internal 640d722e3fbSopenharmony_ci ((drm_intel_bufmgr_gem *) bo->bufmgr, 641d722e3fbSopenharmony_ci (drm_intel_bo_gem *) bo, 642d722e3fbSopenharmony_ci madv); 643d722e3fbSopenharmony_ci} 644d722e3fbSopenharmony_ci 645d722e3fbSopenharmony_ci/* drop the oldest entries that have been purged by the kernel */ 646d722e3fbSopenharmony_cistatic void 647d722e3fbSopenharmony_cidrm_intel_gem_bo_cache_purge_bucket(drm_intel_bufmgr_gem *bufmgr_gem, 648d722e3fbSopenharmony_ci struct drm_intel_gem_bo_bucket *bucket) 649d722e3fbSopenharmony_ci{ 650d722e3fbSopenharmony_ci while (!DRMLISTEMPTY(&bucket->head)) { 651d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem; 652d722e3fbSopenharmony_ci 653d722e3fbSopenharmony_ci bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 654d722e3fbSopenharmony_ci bucket->head.next, head); 655d722e3fbSopenharmony_ci if (drm_intel_gem_bo_madvise_internal 656d722e3fbSopenharmony_ci (bufmgr_gem, bo_gem, I915_MADV_DONTNEED)) 657d722e3fbSopenharmony_ci break; 658d722e3fbSopenharmony_ci 659d722e3fbSopenharmony_ci DRMLISTDEL(&bo_gem->head); 660d722e3fbSopenharmony_ci drm_intel_gem_bo_free(&bo_gem->bo); 661d722e3fbSopenharmony_ci } 662d722e3fbSopenharmony_ci} 663d722e3fbSopenharmony_ci 664d722e3fbSopenharmony_cistatic drm_intel_bo * 665d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc_internal(drm_intel_bufmgr *bufmgr, 666d722e3fbSopenharmony_ci const char *name, 667d722e3fbSopenharmony_ci unsigned long size, 668d722e3fbSopenharmony_ci unsigned long flags, 669d722e3fbSopenharmony_ci uint32_t tiling_mode, 670d722e3fbSopenharmony_ci unsigned long stride, 671d722e3fbSopenharmony_ci unsigned int alignment) 672d722e3fbSopenharmony_ci{ 673d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 674d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem; 675d722e3fbSopenharmony_ci unsigned int page_size = getpagesize(); 676d722e3fbSopenharmony_ci int ret; 677d722e3fbSopenharmony_ci struct drm_intel_gem_bo_bucket *bucket; 678d722e3fbSopenharmony_ci bool alloc_from_cache; 679d722e3fbSopenharmony_ci unsigned long bo_size; 680d722e3fbSopenharmony_ci bool for_render = false; 681d722e3fbSopenharmony_ci 682d722e3fbSopenharmony_ci if (flags & BO_ALLOC_FOR_RENDER) 683d722e3fbSopenharmony_ci for_render = true; 684d722e3fbSopenharmony_ci 685d722e3fbSopenharmony_ci /* Round the allocated size up to a power of two number of pages. */ 686d722e3fbSopenharmony_ci bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, size); 687d722e3fbSopenharmony_ci 688d722e3fbSopenharmony_ci /* If we don't have caching at this size, don't actually round the 689d722e3fbSopenharmony_ci * allocation up. 690d722e3fbSopenharmony_ci */ 691d722e3fbSopenharmony_ci if (bucket == NULL) { 692d722e3fbSopenharmony_ci bo_size = size; 693d722e3fbSopenharmony_ci if (bo_size < page_size) 694d722e3fbSopenharmony_ci bo_size = page_size; 695d722e3fbSopenharmony_ci } else { 696d722e3fbSopenharmony_ci bo_size = bucket->size; 697d722e3fbSopenharmony_ci } 698d722e3fbSopenharmony_ci 699d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 700d722e3fbSopenharmony_ci /* Get a buffer out of the cache if available */ 701d722e3fbSopenharmony_ciretry: 702d722e3fbSopenharmony_ci alloc_from_cache = false; 703d722e3fbSopenharmony_ci if (bucket != NULL && !DRMLISTEMPTY(&bucket->head)) { 704d722e3fbSopenharmony_ci if (for_render) { 705d722e3fbSopenharmony_ci /* Allocate new render-target BOs from the tail (MRU) 706d722e3fbSopenharmony_ci * of the list, as it will likely be hot in the GPU 707d722e3fbSopenharmony_ci * cache and in the aperture for us. 708d722e3fbSopenharmony_ci */ 709d722e3fbSopenharmony_ci bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 710d722e3fbSopenharmony_ci bucket->head.prev, head); 711d722e3fbSopenharmony_ci DRMLISTDEL(&bo_gem->head); 712d722e3fbSopenharmony_ci alloc_from_cache = true; 713d722e3fbSopenharmony_ci bo_gem->bo.align = alignment; 714d722e3fbSopenharmony_ci } else { 715d722e3fbSopenharmony_ci assert(alignment == 0); 716d722e3fbSopenharmony_ci /* For non-render-target BOs (where we're probably 717d722e3fbSopenharmony_ci * going to map it first thing in order to fill it 718d722e3fbSopenharmony_ci * with data), check if the last BO in the cache is 719d722e3fbSopenharmony_ci * unbusy, and only reuse in that case. Otherwise, 720d722e3fbSopenharmony_ci * allocating a new buffer is probably faster than 721d722e3fbSopenharmony_ci * waiting for the GPU to finish. 722d722e3fbSopenharmony_ci */ 723d722e3fbSopenharmony_ci bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 724d722e3fbSopenharmony_ci bucket->head.next, head); 725d722e3fbSopenharmony_ci if (!drm_intel_gem_bo_busy(&bo_gem->bo)) { 726d722e3fbSopenharmony_ci alloc_from_cache = true; 727d722e3fbSopenharmony_ci DRMLISTDEL(&bo_gem->head); 728d722e3fbSopenharmony_ci } 729d722e3fbSopenharmony_ci } 730d722e3fbSopenharmony_ci 731d722e3fbSopenharmony_ci if (alloc_from_cache) { 732d722e3fbSopenharmony_ci if (!drm_intel_gem_bo_madvise_internal 733d722e3fbSopenharmony_ci (bufmgr_gem, bo_gem, I915_MADV_WILLNEED)) { 734d722e3fbSopenharmony_ci drm_intel_gem_bo_free(&bo_gem->bo); 735d722e3fbSopenharmony_ci drm_intel_gem_bo_cache_purge_bucket(bufmgr_gem, 736d722e3fbSopenharmony_ci bucket); 737d722e3fbSopenharmony_ci goto retry; 738d722e3fbSopenharmony_ci } 739d722e3fbSopenharmony_ci 740d722e3fbSopenharmony_ci if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, 741d722e3fbSopenharmony_ci tiling_mode, 742d722e3fbSopenharmony_ci stride)) { 743d722e3fbSopenharmony_ci drm_intel_gem_bo_free(&bo_gem->bo); 744d722e3fbSopenharmony_ci goto retry; 745d722e3fbSopenharmony_ci } 746d722e3fbSopenharmony_ci } 747d722e3fbSopenharmony_ci } 748d722e3fbSopenharmony_ci 749d722e3fbSopenharmony_ci if (!alloc_from_cache) { 750d722e3fbSopenharmony_ci struct drm_i915_gem_create create; 751d722e3fbSopenharmony_ci 752d722e3fbSopenharmony_ci bo_gem = calloc(1, sizeof(*bo_gem)); 753d722e3fbSopenharmony_ci if (!bo_gem) 754d722e3fbSopenharmony_ci goto err; 755d722e3fbSopenharmony_ci 756d722e3fbSopenharmony_ci /* drm_intel_gem_bo_free calls DRMLISTDEL() for an uninitialized 757d722e3fbSopenharmony_ci list (vma_list), so better set the list head here */ 758d722e3fbSopenharmony_ci DRMINITLISTHEAD(&bo_gem->vma_list); 759d722e3fbSopenharmony_ci 760d722e3fbSopenharmony_ci bo_gem->bo.size = bo_size; 761d722e3fbSopenharmony_ci 762d722e3fbSopenharmony_ci memclear(create); 763d722e3fbSopenharmony_ci create.size = bo_size; 764d722e3fbSopenharmony_ci 765d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 766d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_CREATE, 767d722e3fbSopenharmony_ci &create); 768d722e3fbSopenharmony_ci if (ret != 0) { 769d722e3fbSopenharmony_ci free(bo_gem); 770d722e3fbSopenharmony_ci goto err; 771d722e3fbSopenharmony_ci } 772d722e3fbSopenharmony_ci 773d722e3fbSopenharmony_ci bo_gem->gem_handle = create.handle; 774d722e3fbSopenharmony_ci HASH_ADD(handle_hh, bufmgr_gem->handle_table, 775d722e3fbSopenharmony_ci gem_handle, sizeof(bo_gem->gem_handle), 776d722e3fbSopenharmony_ci bo_gem); 777d722e3fbSopenharmony_ci 778d722e3fbSopenharmony_ci bo_gem->bo.handle = bo_gem->gem_handle; 779d722e3fbSopenharmony_ci bo_gem->bo.bufmgr = bufmgr; 780d722e3fbSopenharmony_ci bo_gem->bo.align = alignment; 781d722e3fbSopenharmony_ci 782d722e3fbSopenharmony_ci bo_gem->tiling_mode = I915_TILING_NONE; 783d722e3fbSopenharmony_ci bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 784d722e3fbSopenharmony_ci bo_gem->stride = 0; 785d722e3fbSopenharmony_ci 786d722e3fbSopenharmony_ci if (drm_intel_gem_bo_set_tiling_internal(&bo_gem->bo, 787d722e3fbSopenharmony_ci tiling_mode, 788d722e3fbSopenharmony_ci stride)) 789d722e3fbSopenharmony_ci goto err_free; 790d722e3fbSopenharmony_ci } 791d722e3fbSopenharmony_ci 792d722e3fbSopenharmony_ci bo_gem->name = name; 793d722e3fbSopenharmony_ci atomic_set(&bo_gem->refcount, 1); 794d722e3fbSopenharmony_ci bo_gem->validate_index = -1; 795d722e3fbSopenharmony_ci bo_gem->reloc_tree_fences = 0; 796d722e3fbSopenharmony_ci bo_gem->used_as_reloc_target = false; 797d722e3fbSopenharmony_ci bo_gem->has_error = false; 798d722e3fbSopenharmony_ci bo_gem->reusable = true; 799d722e3fbSopenharmony_ci 800d722e3fbSopenharmony_ci drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, alignment); 801d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 802d722e3fbSopenharmony_ci 803d722e3fbSopenharmony_ci DBG("bo_create: buf %d (%s) %ldb\n", 804d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, size); 805d722e3fbSopenharmony_ci 806d722e3fbSopenharmony_ci return &bo_gem->bo; 807d722e3fbSopenharmony_ci 808d722e3fbSopenharmony_cierr_free: 809d722e3fbSopenharmony_ci drm_intel_gem_bo_free(&bo_gem->bo); 810d722e3fbSopenharmony_cierr: 811d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 812d722e3fbSopenharmony_ci return NULL; 813d722e3fbSopenharmony_ci} 814d722e3fbSopenharmony_ci 815d722e3fbSopenharmony_cistatic drm_intel_bo * 816d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc_for_render(drm_intel_bufmgr *bufmgr, 817d722e3fbSopenharmony_ci const char *name, 818d722e3fbSopenharmony_ci unsigned long size, 819d722e3fbSopenharmony_ci unsigned int alignment) 820d722e3fbSopenharmony_ci{ 821d722e3fbSopenharmony_ci return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 822d722e3fbSopenharmony_ci BO_ALLOC_FOR_RENDER, 823d722e3fbSopenharmony_ci I915_TILING_NONE, 0, 824d722e3fbSopenharmony_ci alignment); 825d722e3fbSopenharmony_ci} 826d722e3fbSopenharmony_ci 827d722e3fbSopenharmony_cistatic drm_intel_bo * 828d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, 829d722e3fbSopenharmony_ci const char *name, 830d722e3fbSopenharmony_ci unsigned long size, 831d722e3fbSopenharmony_ci unsigned int alignment) 832d722e3fbSopenharmony_ci{ 833d722e3fbSopenharmony_ci return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, 0, 834d722e3fbSopenharmony_ci I915_TILING_NONE, 0, 0); 835d722e3fbSopenharmony_ci} 836d722e3fbSopenharmony_ci 837d722e3fbSopenharmony_cistatic drm_intel_bo * 838d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name, 839d722e3fbSopenharmony_ci int x, int y, int cpp, uint32_t *tiling_mode, 840d722e3fbSopenharmony_ci unsigned long *pitch, unsigned long flags) 841d722e3fbSopenharmony_ci{ 842d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 843d722e3fbSopenharmony_ci unsigned long size, stride; 844d722e3fbSopenharmony_ci uint32_t tiling; 845d722e3fbSopenharmony_ci 846d722e3fbSopenharmony_ci do { 847d722e3fbSopenharmony_ci unsigned long aligned_y, height_alignment; 848d722e3fbSopenharmony_ci 849d722e3fbSopenharmony_ci tiling = *tiling_mode; 850d722e3fbSopenharmony_ci 851d722e3fbSopenharmony_ci /* If we're tiled, our allocations are in 8 or 32-row blocks, 852d722e3fbSopenharmony_ci * so failure to align our height means that we won't allocate 853d722e3fbSopenharmony_ci * enough pages. 854d722e3fbSopenharmony_ci * 855d722e3fbSopenharmony_ci * If we're untiled, we still have to align to 2 rows high 856d722e3fbSopenharmony_ci * because the data port accesses 2x2 blocks even if the 857d722e3fbSopenharmony_ci * bottom row isn't to be rendered, so failure to align means 858d722e3fbSopenharmony_ci * we could walk off the end of the GTT and fault. This is 859d722e3fbSopenharmony_ci * documented on 965, and may be the case on older chipsets 860d722e3fbSopenharmony_ci * too so we try to be careful. 861d722e3fbSopenharmony_ci */ 862d722e3fbSopenharmony_ci aligned_y = y; 863d722e3fbSopenharmony_ci height_alignment = 2; 864d722e3fbSopenharmony_ci 865d722e3fbSopenharmony_ci if ((bufmgr_gem->gen == 2) && tiling != I915_TILING_NONE) 866d722e3fbSopenharmony_ci height_alignment = 16; 867d722e3fbSopenharmony_ci else if (tiling == I915_TILING_X 868d722e3fbSopenharmony_ci || (IS_915(bufmgr_gem->pci_device) 869d722e3fbSopenharmony_ci && tiling == I915_TILING_Y)) 870d722e3fbSopenharmony_ci height_alignment = 8; 871d722e3fbSopenharmony_ci else if (tiling == I915_TILING_Y) 872d722e3fbSopenharmony_ci height_alignment = 32; 873d722e3fbSopenharmony_ci aligned_y = ALIGN(y, height_alignment); 874d722e3fbSopenharmony_ci 875d722e3fbSopenharmony_ci stride = x * cpp; 876d722e3fbSopenharmony_ci stride = drm_intel_gem_bo_tile_pitch(bufmgr_gem, stride, tiling_mode); 877d722e3fbSopenharmony_ci size = stride * aligned_y; 878d722e3fbSopenharmony_ci size = drm_intel_gem_bo_tile_size(bufmgr_gem, size, tiling_mode); 879d722e3fbSopenharmony_ci } while (*tiling_mode != tiling); 880d722e3fbSopenharmony_ci *pitch = stride; 881d722e3fbSopenharmony_ci 882d722e3fbSopenharmony_ci if (tiling == I915_TILING_NONE) 883d722e3fbSopenharmony_ci stride = 0; 884d722e3fbSopenharmony_ci 885d722e3fbSopenharmony_ci return drm_intel_gem_bo_alloc_internal(bufmgr, name, size, flags, 886d722e3fbSopenharmony_ci tiling, stride, 0); 887d722e3fbSopenharmony_ci} 888d722e3fbSopenharmony_ci 889d722e3fbSopenharmony_cistatic drm_intel_bo * 890d722e3fbSopenharmony_cidrm_intel_gem_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, 891d722e3fbSopenharmony_ci const char *name, 892d722e3fbSopenharmony_ci void *addr, 893d722e3fbSopenharmony_ci uint32_t tiling_mode, 894d722e3fbSopenharmony_ci uint32_t stride, 895d722e3fbSopenharmony_ci unsigned long size, 896d722e3fbSopenharmony_ci unsigned long flags) 897d722e3fbSopenharmony_ci{ 898d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 899d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem; 900d722e3fbSopenharmony_ci int ret; 901d722e3fbSopenharmony_ci struct drm_i915_gem_userptr userptr; 902d722e3fbSopenharmony_ci 903d722e3fbSopenharmony_ci /* Tiling with userptr surfaces is not supported 904d722e3fbSopenharmony_ci * on all hardware so refuse it for time being. 905d722e3fbSopenharmony_ci */ 906d722e3fbSopenharmony_ci if (tiling_mode != I915_TILING_NONE) 907d722e3fbSopenharmony_ci return NULL; 908d722e3fbSopenharmony_ci 909d722e3fbSopenharmony_ci bo_gem = calloc(1, sizeof(*bo_gem)); 910d722e3fbSopenharmony_ci if (!bo_gem) 911d722e3fbSopenharmony_ci return NULL; 912d722e3fbSopenharmony_ci 913d722e3fbSopenharmony_ci atomic_set(&bo_gem->refcount, 1); 914d722e3fbSopenharmony_ci DRMINITLISTHEAD(&bo_gem->vma_list); 915d722e3fbSopenharmony_ci 916d722e3fbSopenharmony_ci bo_gem->bo.size = size; 917d722e3fbSopenharmony_ci 918d722e3fbSopenharmony_ci memclear(userptr); 919d722e3fbSopenharmony_ci userptr.user_ptr = (__u64)((unsigned long)addr); 920d722e3fbSopenharmony_ci userptr.user_size = size; 921d722e3fbSopenharmony_ci userptr.flags = flags; 922d722e3fbSopenharmony_ci 923d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 924d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_USERPTR, 925d722e3fbSopenharmony_ci &userptr); 926d722e3fbSopenharmony_ci if (ret != 0) { 927d722e3fbSopenharmony_ci DBG("bo_create_userptr: " 928d722e3fbSopenharmony_ci "ioctl failed with user ptr %p size 0x%lx, " 929d722e3fbSopenharmony_ci "user flags 0x%lx\n", addr, size, flags); 930d722e3fbSopenharmony_ci free(bo_gem); 931d722e3fbSopenharmony_ci return NULL; 932d722e3fbSopenharmony_ci } 933d722e3fbSopenharmony_ci 934d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 935d722e3fbSopenharmony_ci 936d722e3fbSopenharmony_ci bo_gem->gem_handle = userptr.handle; 937d722e3fbSopenharmony_ci bo_gem->bo.handle = bo_gem->gem_handle; 938d722e3fbSopenharmony_ci bo_gem->bo.bufmgr = bufmgr; 939d722e3fbSopenharmony_ci bo_gem->is_userptr = true; 940d722e3fbSopenharmony_ci bo_gem->bo.virtual = addr; 941d722e3fbSopenharmony_ci /* Save the address provided by user */ 942d722e3fbSopenharmony_ci bo_gem->user_virtual = addr; 943d722e3fbSopenharmony_ci bo_gem->tiling_mode = I915_TILING_NONE; 944d722e3fbSopenharmony_ci bo_gem->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 945d722e3fbSopenharmony_ci bo_gem->stride = 0; 946d722e3fbSopenharmony_ci 947d722e3fbSopenharmony_ci HASH_ADD(handle_hh, bufmgr_gem->handle_table, 948d722e3fbSopenharmony_ci gem_handle, sizeof(bo_gem->gem_handle), 949d722e3fbSopenharmony_ci bo_gem); 950d722e3fbSopenharmony_ci 951d722e3fbSopenharmony_ci bo_gem->name = name; 952d722e3fbSopenharmony_ci bo_gem->validate_index = -1; 953d722e3fbSopenharmony_ci bo_gem->reloc_tree_fences = 0; 954d722e3fbSopenharmony_ci bo_gem->used_as_reloc_target = false; 955d722e3fbSopenharmony_ci bo_gem->has_error = false; 956d722e3fbSopenharmony_ci bo_gem->reusable = false; 957d722e3fbSopenharmony_ci 958d722e3fbSopenharmony_ci drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 959d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 960d722e3fbSopenharmony_ci 961d722e3fbSopenharmony_ci DBG("bo_create_userptr: " 962d722e3fbSopenharmony_ci "ptr %p buf %d (%s) size %ldb, stride 0x%x, tile mode %d\n", 963d722e3fbSopenharmony_ci addr, bo_gem->gem_handle, bo_gem->name, 964d722e3fbSopenharmony_ci size, stride, tiling_mode); 965d722e3fbSopenharmony_ci 966d722e3fbSopenharmony_ci return &bo_gem->bo; 967d722e3fbSopenharmony_ci} 968d722e3fbSopenharmony_ci 969d722e3fbSopenharmony_cistatic bool 970d722e3fbSopenharmony_cihas_userptr(drm_intel_bufmgr_gem *bufmgr_gem) 971d722e3fbSopenharmony_ci{ 972d722e3fbSopenharmony_ci int ret; 973d722e3fbSopenharmony_ci void *ptr; 974d722e3fbSopenharmony_ci long pgsz; 975d722e3fbSopenharmony_ci struct drm_i915_gem_userptr userptr; 976d722e3fbSopenharmony_ci 977d722e3fbSopenharmony_ci pgsz = sysconf(_SC_PAGESIZE); 978d722e3fbSopenharmony_ci assert(pgsz > 0); 979d722e3fbSopenharmony_ci 980d722e3fbSopenharmony_ci ret = posix_memalign(&ptr, pgsz, pgsz); 981d722e3fbSopenharmony_ci if (ret) { 982d722e3fbSopenharmony_ci DBG("Failed to get a page (%ld) for userptr detection!\n", 983d722e3fbSopenharmony_ci pgsz); 984d722e3fbSopenharmony_ci return false; 985d722e3fbSopenharmony_ci } 986d722e3fbSopenharmony_ci 987d722e3fbSopenharmony_ci memclear(userptr); 988d722e3fbSopenharmony_ci userptr.user_ptr = (__u64)(unsigned long)ptr; 989d722e3fbSopenharmony_ci userptr.user_size = pgsz; 990d722e3fbSopenharmony_ci 991d722e3fbSopenharmony_ciretry: 992d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr); 993d722e3fbSopenharmony_ci if (ret) { 994d722e3fbSopenharmony_ci if (errno == ENODEV && userptr.flags == 0) { 995d722e3fbSopenharmony_ci userptr.flags = I915_USERPTR_UNSYNCHRONIZED; 996d722e3fbSopenharmony_ci goto retry; 997d722e3fbSopenharmony_ci } 998d722e3fbSopenharmony_ci free(ptr); 999d722e3fbSopenharmony_ci return false; 1000d722e3fbSopenharmony_ci } 1001d722e3fbSopenharmony_ci 1002d722e3fbSopenharmony_ci /* We don't release the userptr bo here as we want to keep the 1003d722e3fbSopenharmony_ci * kernel mm tracking alive for our lifetime. The first time we 1004d722e3fbSopenharmony_ci * create a userptr object the kernel has to install a mmu_notifer 1005d722e3fbSopenharmony_ci * which is a heavyweight operation (e.g. it requires taking all 1006d722e3fbSopenharmony_ci * mm_locks and stop_machine()). 1007d722e3fbSopenharmony_ci */ 1008d722e3fbSopenharmony_ci 1009d722e3fbSopenharmony_ci bufmgr_gem->userptr_active.ptr = ptr; 1010d722e3fbSopenharmony_ci bufmgr_gem->userptr_active.handle = userptr.handle; 1011d722e3fbSopenharmony_ci 1012d722e3fbSopenharmony_ci return true; 1013d722e3fbSopenharmony_ci} 1014d722e3fbSopenharmony_ci 1015d722e3fbSopenharmony_cistatic drm_intel_bo * 1016d722e3fbSopenharmony_cicheck_bo_alloc_userptr(drm_intel_bufmgr *bufmgr, 1017d722e3fbSopenharmony_ci const char *name, 1018d722e3fbSopenharmony_ci void *addr, 1019d722e3fbSopenharmony_ci uint32_t tiling_mode, 1020d722e3fbSopenharmony_ci uint32_t stride, 1021d722e3fbSopenharmony_ci unsigned long size, 1022d722e3fbSopenharmony_ci unsigned long flags) 1023d722e3fbSopenharmony_ci{ 1024d722e3fbSopenharmony_ci if (has_userptr((drm_intel_bufmgr_gem *)bufmgr)) 1025d722e3fbSopenharmony_ci bufmgr->bo_alloc_userptr = drm_intel_gem_bo_alloc_userptr; 1026d722e3fbSopenharmony_ci else 1027d722e3fbSopenharmony_ci bufmgr->bo_alloc_userptr = NULL; 1028d722e3fbSopenharmony_ci 1029d722e3fbSopenharmony_ci return drm_intel_bo_alloc_userptr(bufmgr, name, addr, 1030d722e3fbSopenharmony_ci tiling_mode, stride, size, flags); 1031d722e3fbSopenharmony_ci} 1032d722e3fbSopenharmony_ci 1033d722e3fbSopenharmony_cistatic int get_tiling_mode(drm_intel_bufmgr_gem *bufmgr_gem, 1034d722e3fbSopenharmony_ci uint32_t gem_handle, 1035d722e3fbSopenharmony_ci uint32_t *tiling_mode, 1036d722e3fbSopenharmony_ci uint32_t *swizzle_mode) 1037d722e3fbSopenharmony_ci{ 1038d722e3fbSopenharmony_ci struct drm_i915_gem_get_tiling get_tiling = { 1039d722e3fbSopenharmony_ci .handle = gem_handle, 1040d722e3fbSopenharmony_ci }; 1041d722e3fbSopenharmony_ci int ret; 1042d722e3fbSopenharmony_ci 1043d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1044d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_GET_TILING, 1045d722e3fbSopenharmony_ci &get_tiling); 1046d722e3fbSopenharmony_ci if (ret != 0 && errno != EOPNOTSUPP) 1047d722e3fbSopenharmony_ci return ret; 1048d722e3fbSopenharmony_ci 1049d722e3fbSopenharmony_ci *tiling_mode = get_tiling.tiling_mode; 1050d722e3fbSopenharmony_ci *swizzle_mode = get_tiling.swizzle_mode; 1051d722e3fbSopenharmony_ci 1052d722e3fbSopenharmony_ci return 0; 1053d722e3fbSopenharmony_ci} 1054d722e3fbSopenharmony_ci 1055d722e3fbSopenharmony_ci/** 1056d722e3fbSopenharmony_ci * Returns a drm_intel_bo wrapping the given buffer object handle. 1057d722e3fbSopenharmony_ci * 1058d722e3fbSopenharmony_ci * This can be used when one application needs to pass a buffer object 1059d722e3fbSopenharmony_ci * to another. 1060d722e3fbSopenharmony_ci */ 1061d722e3fbSopenharmony_cidrm_public drm_intel_bo * 1062d722e3fbSopenharmony_cidrm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, 1063d722e3fbSopenharmony_ci const char *name, 1064d722e3fbSopenharmony_ci unsigned int handle) 1065d722e3fbSopenharmony_ci{ 1066d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 1067d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem; 1068d722e3fbSopenharmony_ci int ret; 1069d722e3fbSopenharmony_ci struct drm_gem_open open_arg; 1070d722e3fbSopenharmony_ci 1071d722e3fbSopenharmony_ci /* At the moment most applications only have a few named bo. 1072d722e3fbSopenharmony_ci * For instance, in a DRI client only the render buffers passed 1073d722e3fbSopenharmony_ci * between X and the client are named. And since X returns the 1074d722e3fbSopenharmony_ci * alternating names for the front/back buffer a linear search 1075d722e3fbSopenharmony_ci * provides a sufficiently fast match. 1076d722e3fbSopenharmony_ci */ 1077d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 1078d722e3fbSopenharmony_ci HASH_FIND(name_hh, bufmgr_gem->name_table, 1079d722e3fbSopenharmony_ci &handle, sizeof(handle), bo_gem); 1080d722e3fbSopenharmony_ci if (bo_gem) { 1081d722e3fbSopenharmony_ci drm_intel_gem_bo_reference(&bo_gem->bo); 1082d722e3fbSopenharmony_ci goto out; 1083d722e3fbSopenharmony_ci } 1084d722e3fbSopenharmony_ci 1085d722e3fbSopenharmony_ci memclear(open_arg); 1086d722e3fbSopenharmony_ci open_arg.name = handle; 1087d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1088d722e3fbSopenharmony_ci DRM_IOCTL_GEM_OPEN, 1089d722e3fbSopenharmony_ci &open_arg); 1090d722e3fbSopenharmony_ci if (ret != 0) { 1091d722e3fbSopenharmony_ci DBG("Couldn't reference %s handle 0x%08x: %s\n", 1092d722e3fbSopenharmony_ci name, handle, strerror(errno)); 1093d722e3fbSopenharmony_ci bo_gem = NULL; 1094d722e3fbSopenharmony_ci goto out; 1095d722e3fbSopenharmony_ci } 1096d722e3fbSopenharmony_ci /* Now see if someone has used a prime handle to get this 1097d722e3fbSopenharmony_ci * object from the kernel before by looking through the list 1098d722e3fbSopenharmony_ci * again for a matching gem_handle 1099d722e3fbSopenharmony_ci */ 1100d722e3fbSopenharmony_ci HASH_FIND(handle_hh, bufmgr_gem->handle_table, 1101d722e3fbSopenharmony_ci &open_arg.handle, sizeof(open_arg.handle), bo_gem); 1102d722e3fbSopenharmony_ci if (bo_gem) { 1103d722e3fbSopenharmony_ci drm_intel_gem_bo_reference(&bo_gem->bo); 1104d722e3fbSopenharmony_ci goto out; 1105d722e3fbSopenharmony_ci } 1106d722e3fbSopenharmony_ci 1107d722e3fbSopenharmony_ci bo_gem = calloc(1, sizeof(*bo_gem)); 1108d722e3fbSopenharmony_ci if (!bo_gem) 1109d722e3fbSopenharmony_ci goto out; 1110d722e3fbSopenharmony_ci 1111d722e3fbSopenharmony_ci atomic_set(&bo_gem->refcount, 1); 1112d722e3fbSopenharmony_ci DRMINITLISTHEAD(&bo_gem->vma_list); 1113d722e3fbSopenharmony_ci 1114d722e3fbSopenharmony_ci bo_gem->bo.size = open_arg.size; 1115d722e3fbSopenharmony_ci bo_gem->bo.offset = 0; 1116d722e3fbSopenharmony_ci bo_gem->bo.offset64 = 0; 1117d722e3fbSopenharmony_ci bo_gem->bo.virtual = NULL; 1118d722e3fbSopenharmony_ci bo_gem->bo.bufmgr = bufmgr; 1119d722e3fbSopenharmony_ci bo_gem->name = name; 1120d722e3fbSopenharmony_ci bo_gem->validate_index = -1; 1121d722e3fbSopenharmony_ci bo_gem->gem_handle = open_arg.handle; 1122d722e3fbSopenharmony_ci bo_gem->bo.handle = open_arg.handle; 1123d722e3fbSopenharmony_ci bo_gem->global_name = handle; 1124d722e3fbSopenharmony_ci bo_gem->reusable = false; 1125d722e3fbSopenharmony_ci 1126d722e3fbSopenharmony_ci HASH_ADD(handle_hh, bufmgr_gem->handle_table, 1127d722e3fbSopenharmony_ci gem_handle, sizeof(bo_gem->gem_handle), bo_gem); 1128d722e3fbSopenharmony_ci HASH_ADD(name_hh, bufmgr_gem->name_table, 1129d722e3fbSopenharmony_ci global_name, sizeof(bo_gem->global_name), bo_gem); 1130d722e3fbSopenharmony_ci 1131d722e3fbSopenharmony_ci ret = get_tiling_mode(bufmgr_gem, bo_gem->gem_handle, 1132d722e3fbSopenharmony_ci &bo_gem->tiling_mode, &bo_gem->swizzle_mode); 1133d722e3fbSopenharmony_ci if (ret != 0) 1134d722e3fbSopenharmony_ci goto err_unref; 1135d722e3fbSopenharmony_ci 1136d722e3fbSopenharmony_ci /* XXX stride is unknown */ 1137d722e3fbSopenharmony_ci drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 1138d722e3fbSopenharmony_ci DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name); 1139d722e3fbSopenharmony_ci 1140d722e3fbSopenharmony_ciout: 1141d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1142d722e3fbSopenharmony_ci return &bo_gem->bo; 1143d722e3fbSopenharmony_ci 1144d722e3fbSopenharmony_cierr_unref: 1145d722e3fbSopenharmony_ci drm_intel_gem_bo_free(&bo_gem->bo); 1146d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1147d722e3fbSopenharmony_ci return NULL; 1148d722e3fbSopenharmony_ci} 1149d722e3fbSopenharmony_ci 1150d722e3fbSopenharmony_cistatic void 1151d722e3fbSopenharmony_cidrm_intel_gem_bo_free(drm_intel_bo *bo) 1152d722e3fbSopenharmony_ci{ 1153d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1154d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1155d722e3fbSopenharmony_ci int ret; 1156d722e3fbSopenharmony_ci 1157d722e3fbSopenharmony_ci DRMLISTDEL(&bo_gem->vma_list); 1158d722e3fbSopenharmony_ci if (bo_gem->mem_virtual) { 1159d722e3fbSopenharmony_ci VG(VALGRIND_FREELIKE_BLOCK(bo_gem->mem_virtual, 0)); 1160d722e3fbSopenharmony_ci drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size); 1161d722e3fbSopenharmony_ci bufmgr_gem->vma_count--; 1162d722e3fbSopenharmony_ci } 1163d722e3fbSopenharmony_ci if (bo_gem->wc_virtual) { 1164d722e3fbSopenharmony_ci VG(VALGRIND_FREELIKE_BLOCK(bo_gem->wc_virtual, 0)); 1165d722e3fbSopenharmony_ci drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size); 1166d722e3fbSopenharmony_ci bufmgr_gem->vma_count--; 1167d722e3fbSopenharmony_ci } 1168d722e3fbSopenharmony_ci if (bo_gem->gtt_virtual) { 1169d722e3fbSopenharmony_ci drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size); 1170d722e3fbSopenharmony_ci bufmgr_gem->vma_count--; 1171d722e3fbSopenharmony_ci } 1172d722e3fbSopenharmony_ci 1173d722e3fbSopenharmony_ci if (bo_gem->global_name) 1174d722e3fbSopenharmony_ci HASH_DELETE(name_hh, bufmgr_gem->name_table, bo_gem); 1175d722e3fbSopenharmony_ci HASH_DELETE(handle_hh, bufmgr_gem->handle_table, bo_gem); 1176d722e3fbSopenharmony_ci 1177d722e3fbSopenharmony_ci /* Close this object */ 1178d722e3fbSopenharmony_ci ret = drmCloseBufferHandle(bufmgr_gem->fd, bo_gem->gem_handle); 1179d722e3fbSopenharmony_ci if (ret != 0) { 1180d722e3fbSopenharmony_ci DBG("drmCloseBufferHandle %d failed (%s): %s\n", 1181d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, strerror(errno)); 1182d722e3fbSopenharmony_ci } 1183d722e3fbSopenharmony_ci free(bo); 1184d722e3fbSopenharmony_ci} 1185d722e3fbSopenharmony_ci 1186d722e3fbSopenharmony_cistatic void 1187d722e3fbSopenharmony_cidrm_intel_gem_bo_mark_mmaps_incoherent(drm_intel_bo *bo) 1188d722e3fbSopenharmony_ci{ 1189d722e3fbSopenharmony_ci#if HAVE_VALGRIND 1190d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1191d722e3fbSopenharmony_ci 1192d722e3fbSopenharmony_ci if (bo_gem->mem_virtual) 1193d722e3fbSopenharmony_ci VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size); 1194d722e3fbSopenharmony_ci 1195d722e3fbSopenharmony_ci if (bo_gem->wc_virtual) 1196d722e3fbSopenharmony_ci VALGRIND_MAKE_MEM_NOACCESS(bo_gem->wc_virtual, bo->size); 1197d722e3fbSopenharmony_ci 1198d722e3fbSopenharmony_ci if (bo_gem->gtt_virtual) 1199d722e3fbSopenharmony_ci VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size); 1200d722e3fbSopenharmony_ci#endif 1201d722e3fbSopenharmony_ci} 1202d722e3fbSopenharmony_ci 1203d722e3fbSopenharmony_ci/** Frees all cached buffers significantly older than @time. */ 1204d722e3fbSopenharmony_cistatic void 1205d722e3fbSopenharmony_cidrm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time) 1206d722e3fbSopenharmony_ci{ 1207d722e3fbSopenharmony_ci int i; 1208d722e3fbSopenharmony_ci 1209d722e3fbSopenharmony_ci if (bufmgr_gem->time == time) 1210d722e3fbSopenharmony_ci return; 1211d722e3fbSopenharmony_ci 1212d722e3fbSopenharmony_ci for (i = 0; i < bufmgr_gem->num_buckets; i++) { 1213d722e3fbSopenharmony_ci struct drm_intel_gem_bo_bucket *bucket = 1214d722e3fbSopenharmony_ci &bufmgr_gem->cache_bucket[i]; 1215d722e3fbSopenharmony_ci 1216d722e3fbSopenharmony_ci while (!DRMLISTEMPTY(&bucket->head)) { 1217d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem; 1218d722e3fbSopenharmony_ci 1219d722e3fbSopenharmony_ci bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 1220d722e3fbSopenharmony_ci bucket->head.next, head); 1221d722e3fbSopenharmony_ci if (time - bo_gem->free_time <= 1) 1222d722e3fbSopenharmony_ci break; 1223d722e3fbSopenharmony_ci 1224d722e3fbSopenharmony_ci DRMLISTDEL(&bo_gem->head); 1225d722e3fbSopenharmony_ci 1226d722e3fbSopenharmony_ci drm_intel_gem_bo_free(&bo_gem->bo); 1227d722e3fbSopenharmony_ci } 1228d722e3fbSopenharmony_ci } 1229d722e3fbSopenharmony_ci 1230d722e3fbSopenharmony_ci bufmgr_gem->time = time; 1231d722e3fbSopenharmony_ci} 1232d722e3fbSopenharmony_ci 1233d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem) 1234d722e3fbSopenharmony_ci{ 1235d722e3fbSopenharmony_ci int limit; 1236d722e3fbSopenharmony_ci 1237d722e3fbSopenharmony_ci DBG("%s: cached=%d, open=%d, limit=%d\n", __FUNCTION__, 1238d722e3fbSopenharmony_ci bufmgr_gem->vma_count, bufmgr_gem->vma_open, bufmgr_gem->vma_max); 1239d722e3fbSopenharmony_ci 1240d722e3fbSopenharmony_ci if (bufmgr_gem->vma_max < 0) 1241d722e3fbSopenharmony_ci return; 1242d722e3fbSopenharmony_ci 1243d722e3fbSopenharmony_ci /* We may need to evict a few entries in order to create new mmaps */ 1244d722e3fbSopenharmony_ci limit = bufmgr_gem->vma_max - 2*bufmgr_gem->vma_open; 1245d722e3fbSopenharmony_ci if (limit < 0) 1246d722e3fbSopenharmony_ci limit = 0; 1247d722e3fbSopenharmony_ci 1248d722e3fbSopenharmony_ci while (bufmgr_gem->vma_count > limit) { 1249d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem; 1250d722e3fbSopenharmony_ci 1251d722e3fbSopenharmony_ci bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 1252d722e3fbSopenharmony_ci bufmgr_gem->vma_cache.next, 1253d722e3fbSopenharmony_ci vma_list); 1254d722e3fbSopenharmony_ci assert(bo_gem->map_count == 0); 1255d722e3fbSopenharmony_ci DRMLISTDELINIT(&bo_gem->vma_list); 1256d722e3fbSopenharmony_ci 1257d722e3fbSopenharmony_ci if (bo_gem->mem_virtual) { 1258d722e3fbSopenharmony_ci drm_munmap(bo_gem->mem_virtual, bo_gem->bo.size); 1259d722e3fbSopenharmony_ci bo_gem->mem_virtual = NULL; 1260d722e3fbSopenharmony_ci bufmgr_gem->vma_count--; 1261d722e3fbSopenharmony_ci } 1262d722e3fbSopenharmony_ci if (bo_gem->wc_virtual) { 1263d722e3fbSopenharmony_ci drm_munmap(bo_gem->wc_virtual, bo_gem->bo.size); 1264d722e3fbSopenharmony_ci bo_gem->wc_virtual = NULL; 1265d722e3fbSopenharmony_ci bufmgr_gem->vma_count--; 1266d722e3fbSopenharmony_ci } 1267d722e3fbSopenharmony_ci if (bo_gem->gtt_virtual) { 1268d722e3fbSopenharmony_ci drm_munmap(bo_gem->gtt_virtual, bo_gem->bo.size); 1269d722e3fbSopenharmony_ci bo_gem->gtt_virtual = NULL; 1270d722e3fbSopenharmony_ci bufmgr_gem->vma_count--; 1271d722e3fbSopenharmony_ci } 1272d722e3fbSopenharmony_ci } 1273d722e3fbSopenharmony_ci} 1274d722e3fbSopenharmony_ci 1275d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem, 1276d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem) 1277d722e3fbSopenharmony_ci{ 1278d722e3fbSopenharmony_ci bufmgr_gem->vma_open--; 1279d722e3fbSopenharmony_ci DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache); 1280d722e3fbSopenharmony_ci if (bo_gem->mem_virtual) 1281d722e3fbSopenharmony_ci bufmgr_gem->vma_count++; 1282d722e3fbSopenharmony_ci if (bo_gem->wc_virtual) 1283d722e3fbSopenharmony_ci bufmgr_gem->vma_count++; 1284d722e3fbSopenharmony_ci if (bo_gem->gtt_virtual) 1285d722e3fbSopenharmony_ci bufmgr_gem->vma_count++; 1286d722e3fbSopenharmony_ci drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); 1287d722e3fbSopenharmony_ci} 1288d722e3fbSopenharmony_ci 1289d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem, 1290d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem) 1291d722e3fbSopenharmony_ci{ 1292d722e3fbSopenharmony_ci bufmgr_gem->vma_open++; 1293d722e3fbSopenharmony_ci DRMLISTDEL(&bo_gem->vma_list); 1294d722e3fbSopenharmony_ci if (bo_gem->mem_virtual) 1295d722e3fbSopenharmony_ci bufmgr_gem->vma_count--; 1296d722e3fbSopenharmony_ci if (bo_gem->wc_virtual) 1297d722e3fbSopenharmony_ci bufmgr_gem->vma_count--; 1298d722e3fbSopenharmony_ci if (bo_gem->gtt_virtual) 1299d722e3fbSopenharmony_ci bufmgr_gem->vma_count--; 1300d722e3fbSopenharmony_ci drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); 1301d722e3fbSopenharmony_ci} 1302d722e3fbSopenharmony_ci 1303d722e3fbSopenharmony_cistatic void 1304d722e3fbSopenharmony_cidrm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time) 1305d722e3fbSopenharmony_ci{ 1306d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1307d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1308d722e3fbSopenharmony_ci struct drm_intel_gem_bo_bucket *bucket; 1309d722e3fbSopenharmony_ci int i; 1310d722e3fbSopenharmony_ci 1311d722e3fbSopenharmony_ci /* Unreference all the target buffers */ 1312d722e3fbSopenharmony_ci for (i = 0; i < bo_gem->reloc_count; i++) { 1313d722e3fbSopenharmony_ci if (bo_gem->reloc_target_info[i].bo != bo) { 1314d722e3fbSopenharmony_ci drm_intel_gem_bo_unreference_locked_timed(bo_gem-> 1315d722e3fbSopenharmony_ci reloc_target_info[i].bo, 1316d722e3fbSopenharmony_ci time); 1317d722e3fbSopenharmony_ci } 1318d722e3fbSopenharmony_ci } 1319d722e3fbSopenharmony_ci for (i = 0; i < bo_gem->softpin_target_count; i++) 1320d722e3fbSopenharmony_ci drm_intel_gem_bo_unreference_locked_timed(bo_gem->softpin_target[i], 1321d722e3fbSopenharmony_ci time); 1322d722e3fbSopenharmony_ci bo_gem->kflags = 0; 1323d722e3fbSopenharmony_ci bo_gem->reloc_count = 0; 1324d722e3fbSopenharmony_ci bo_gem->used_as_reloc_target = false; 1325d722e3fbSopenharmony_ci bo_gem->softpin_target_count = 0; 1326d722e3fbSopenharmony_ci 1327d722e3fbSopenharmony_ci DBG("bo_unreference final: %d (%s)\n", 1328d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name); 1329d722e3fbSopenharmony_ci 1330d722e3fbSopenharmony_ci /* release memory associated with this object */ 1331d722e3fbSopenharmony_ci if (bo_gem->reloc_target_info) { 1332d722e3fbSopenharmony_ci free(bo_gem->reloc_target_info); 1333d722e3fbSopenharmony_ci bo_gem->reloc_target_info = NULL; 1334d722e3fbSopenharmony_ci } 1335d722e3fbSopenharmony_ci if (bo_gem->relocs) { 1336d722e3fbSopenharmony_ci free(bo_gem->relocs); 1337d722e3fbSopenharmony_ci bo_gem->relocs = NULL; 1338d722e3fbSopenharmony_ci } 1339d722e3fbSopenharmony_ci if (bo_gem->softpin_target) { 1340d722e3fbSopenharmony_ci free(bo_gem->softpin_target); 1341d722e3fbSopenharmony_ci bo_gem->softpin_target = NULL; 1342d722e3fbSopenharmony_ci bo_gem->softpin_target_size = 0; 1343d722e3fbSopenharmony_ci } 1344d722e3fbSopenharmony_ci 1345d722e3fbSopenharmony_ci /* Clear any left-over mappings */ 1346d722e3fbSopenharmony_ci if (bo_gem->map_count) { 1347d722e3fbSopenharmony_ci DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count); 1348d722e3fbSopenharmony_ci bo_gem->map_count = 0; 1349d722e3fbSopenharmony_ci drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 1350d722e3fbSopenharmony_ci drm_intel_gem_bo_mark_mmaps_incoherent(bo); 1351d722e3fbSopenharmony_ci } 1352d722e3fbSopenharmony_ci 1353d722e3fbSopenharmony_ci bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size); 1354d722e3fbSopenharmony_ci /* Put the buffer into our internal cache for reuse if we can. */ 1355d722e3fbSopenharmony_ci if (bufmgr_gem->bo_reuse && bo_gem->reusable && bucket != NULL && 1356d722e3fbSopenharmony_ci drm_intel_gem_bo_madvise_internal(bufmgr_gem, bo_gem, 1357d722e3fbSopenharmony_ci I915_MADV_DONTNEED)) { 1358d722e3fbSopenharmony_ci bo_gem->free_time = time; 1359d722e3fbSopenharmony_ci 1360d722e3fbSopenharmony_ci bo_gem->name = NULL; 1361d722e3fbSopenharmony_ci bo_gem->validate_index = -1; 1362d722e3fbSopenharmony_ci 1363d722e3fbSopenharmony_ci DRMLISTADDTAIL(&bo_gem->head, &bucket->head); 1364d722e3fbSopenharmony_ci } else { 1365d722e3fbSopenharmony_ci drm_intel_gem_bo_free(bo); 1366d722e3fbSopenharmony_ci } 1367d722e3fbSopenharmony_ci} 1368d722e3fbSopenharmony_ci 1369d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_unreference_locked_timed(drm_intel_bo *bo, 1370d722e3fbSopenharmony_ci time_t time) 1371d722e3fbSopenharmony_ci{ 1372d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1373d722e3fbSopenharmony_ci 1374d722e3fbSopenharmony_ci assert(atomic_read(&bo_gem->refcount) > 0); 1375d722e3fbSopenharmony_ci if (atomic_dec_and_test(&bo_gem->refcount)) 1376d722e3fbSopenharmony_ci drm_intel_gem_bo_unreference_final(bo, time); 1377d722e3fbSopenharmony_ci} 1378d722e3fbSopenharmony_ci 1379d722e3fbSopenharmony_cistatic void drm_intel_gem_bo_unreference(drm_intel_bo *bo) 1380d722e3fbSopenharmony_ci{ 1381d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1382d722e3fbSopenharmony_ci 1383d722e3fbSopenharmony_ci assert(atomic_read(&bo_gem->refcount) > 0); 1384d722e3fbSopenharmony_ci 1385d722e3fbSopenharmony_ci if (atomic_add_unless(&bo_gem->refcount, -1, 1)) { 1386d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = 1387d722e3fbSopenharmony_ci (drm_intel_bufmgr_gem *) bo->bufmgr; 1388d722e3fbSopenharmony_ci struct timespec time; 1389d722e3fbSopenharmony_ci 1390d722e3fbSopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &time); 1391d722e3fbSopenharmony_ci 1392d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 1393d722e3fbSopenharmony_ci 1394d722e3fbSopenharmony_ci if (atomic_dec_and_test(&bo_gem->refcount)) { 1395d722e3fbSopenharmony_ci drm_intel_gem_bo_unreference_final(bo, time.tv_sec); 1396d722e3fbSopenharmony_ci drm_intel_gem_cleanup_bo_cache(bufmgr_gem, time.tv_sec); 1397d722e3fbSopenharmony_ci } 1398d722e3fbSopenharmony_ci 1399d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1400d722e3fbSopenharmony_ci } 1401d722e3fbSopenharmony_ci} 1402d722e3fbSopenharmony_ci 1403d722e3fbSopenharmony_cistatic int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable) 1404d722e3fbSopenharmony_ci{ 1405d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1406d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1407d722e3fbSopenharmony_ci struct drm_i915_gem_set_domain set_domain; 1408d722e3fbSopenharmony_ci int ret; 1409d722e3fbSopenharmony_ci 1410d722e3fbSopenharmony_ci if (bo_gem->is_userptr) { 1411d722e3fbSopenharmony_ci /* Return the same user ptr */ 1412d722e3fbSopenharmony_ci bo->virtual = bo_gem->user_virtual; 1413d722e3fbSopenharmony_ci return 0; 1414d722e3fbSopenharmony_ci } 1415d722e3fbSopenharmony_ci 1416d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 1417d722e3fbSopenharmony_ci 1418d722e3fbSopenharmony_ci if (bo_gem->map_count++ == 0) 1419d722e3fbSopenharmony_ci drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 1420d722e3fbSopenharmony_ci 1421d722e3fbSopenharmony_ci if (!bo_gem->mem_virtual) { 1422d722e3fbSopenharmony_ci struct drm_i915_gem_mmap mmap_arg; 1423d722e3fbSopenharmony_ci 1424d722e3fbSopenharmony_ci DBG("bo_map: %d (%s), map_count=%d\n", 1425d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 1426d722e3fbSopenharmony_ci 1427d722e3fbSopenharmony_ci memclear(mmap_arg); 1428d722e3fbSopenharmony_ci mmap_arg.handle = bo_gem->gem_handle; 1429d722e3fbSopenharmony_ci mmap_arg.size = bo->size; 1430d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1431d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_MMAP, 1432d722e3fbSopenharmony_ci &mmap_arg); 1433d722e3fbSopenharmony_ci if (ret != 0) { 1434d722e3fbSopenharmony_ci ret = -errno; 1435d722e3fbSopenharmony_ci DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 1436d722e3fbSopenharmony_ci __FILE__, __LINE__, bo_gem->gem_handle, 1437d722e3fbSopenharmony_ci bo_gem->name, strerror(errno)); 1438d722e3fbSopenharmony_ci if (--bo_gem->map_count == 0) 1439d722e3fbSopenharmony_ci drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 1440d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1441d722e3fbSopenharmony_ci return ret; 1442d722e3fbSopenharmony_ci } 1443d722e3fbSopenharmony_ci VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1)); 1444d722e3fbSopenharmony_ci bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr; 1445d722e3fbSopenharmony_ci } 1446d722e3fbSopenharmony_ci DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, 1447d722e3fbSopenharmony_ci bo_gem->mem_virtual); 1448d722e3fbSopenharmony_ci bo->virtual = bo_gem->mem_virtual; 1449d722e3fbSopenharmony_ci 1450d722e3fbSopenharmony_ci memclear(set_domain); 1451d722e3fbSopenharmony_ci set_domain.handle = bo_gem->gem_handle; 1452d722e3fbSopenharmony_ci set_domain.read_domains = I915_GEM_DOMAIN_CPU; 1453d722e3fbSopenharmony_ci if (write_enable) 1454d722e3fbSopenharmony_ci set_domain.write_domain = I915_GEM_DOMAIN_CPU; 1455d722e3fbSopenharmony_ci else 1456d722e3fbSopenharmony_ci set_domain.write_domain = 0; 1457d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1458d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_SET_DOMAIN, 1459d722e3fbSopenharmony_ci &set_domain); 1460d722e3fbSopenharmony_ci if (ret != 0) { 1461d722e3fbSopenharmony_ci DBG("%s:%d: Error setting to CPU domain %d: %s\n", 1462d722e3fbSopenharmony_ci __FILE__, __LINE__, bo_gem->gem_handle, 1463d722e3fbSopenharmony_ci strerror(errno)); 1464d722e3fbSopenharmony_ci } 1465d722e3fbSopenharmony_ci 1466d722e3fbSopenharmony_ci if (write_enable) 1467d722e3fbSopenharmony_ci bo_gem->mapped_cpu_write = true; 1468d722e3fbSopenharmony_ci 1469d722e3fbSopenharmony_ci drm_intel_gem_bo_mark_mmaps_incoherent(bo); 1470d722e3fbSopenharmony_ci VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->mem_virtual, bo->size)); 1471d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1472d722e3fbSopenharmony_ci 1473d722e3fbSopenharmony_ci return 0; 1474d722e3fbSopenharmony_ci} 1475d722e3fbSopenharmony_ci 1476d722e3fbSopenharmony_cistatic int 1477d722e3fbSopenharmony_cimap_gtt(drm_intel_bo *bo) 1478d722e3fbSopenharmony_ci{ 1479d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1480d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1481d722e3fbSopenharmony_ci int ret; 1482d722e3fbSopenharmony_ci 1483d722e3fbSopenharmony_ci if (bo_gem->is_userptr) 1484d722e3fbSopenharmony_ci return -EINVAL; 1485d722e3fbSopenharmony_ci 1486d722e3fbSopenharmony_ci if (bo_gem->map_count++ == 0) 1487d722e3fbSopenharmony_ci drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 1488d722e3fbSopenharmony_ci 1489d722e3fbSopenharmony_ci /* Get a mapping of the buffer if we haven't before. */ 1490d722e3fbSopenharmony_ci if (bo_gem->gtt_virtual == NULL) { 1491d722e3fbSopenharmony_ci struct drm_i915_gem_mmap_gtt mmap_arg; 1492d722e3fbSopenharmony_ci 1493d722e3fbSopenharmony_ci DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n", 1494d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 1495d722e3fbSopenharmony_ci 1496d722e3fbSopenharmony_ci memclear(mmap_arg); 1497d722e3fbSopenharmony_ci mmap_arg.handle = bo_gem->gem_handle; 1498d722e3fbSopenharmony_ci 1499d722e3fbSopenharmony_ci /* Get the fake offset back... */ 1500d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1501d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_MMAP_GTT, 1502d722e3fbSopenharmony_ci &mmap_arg); 1503d722e3fbSopenharmony_ci if (ret != 0) { 1504d722e3fbSopenharmony_ci ret = -errno; 1505d722e3fbSopenharmony_ci DBG("%s:%d: Error preparing buffer map %d (%s): %s .\n", 1506d722e3fbSopenharmony_ci __FILE__, __LINE__, 1507d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, 1508d722e3fbSopenharmony_ci strerror(errno)); 1509d722e3fbSopenharmony_ci if (--bo_gem->map_count == 0) 1510d722e3fbSopenharmony_ci drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 1511d722e3fbSopenharmony_ci return ret; 1512d722e3fbSopenharmony_ci } 1513d722e3fbSopenharmony_ci 1514d722e3fbSopenharmony_ci /* and mmap it */ 1515d722e3fbSopenharmony_ci bo_gem->gtt_virtual = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, 1516d722e3fbSopenharmony_ci MAP_SHARED, bufmgr_gem->fd, 1517d722e3fbSopenharmony_ci mmap_arg.offset); 1518d722e3fbSopenharmony_ci if (bo_gem->gtt_virtual == MAP_FAILED) { 1519d722e3fbSopenharmony_ci bo_gem->gtt_virtual = NULL; 1520d722e3fbSopenharmony_ci ret = -errno; 1521d722e3fbSopenharmony_ci DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 1522d722e3fbSopenharmony_ci __FILE__, __LINE__, 1523d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, 1524d722e3fbSopenharmony_ci strerror(errno)); 1525d722e3fbSopenharmony_ci if (--bo_gem->map_count == 0) 1526d722e3fbSopenharmony_ci drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 1527d722e3fbSopenharmony_ci return ret; 1528d722e3fbSopenharmony_ci } 1529d722e3fbSopenharmony_ci } 1530d722e3fbSopenharmony_ci 1531d722e3fbSopenharmony_ci bo->virtual = bo_gem->gtt_virtual; 1532d722e3fbSopenharmony_ci 1533d722e3fbSopenharmony_ci DBG("bo_map_gtt: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, 1534d722e3fbSopenharmony_ci bo_gem->gtt_virtual); 1535d722e3fbSopenharmony_ci 1536d722e3fbSopenharmony_ci return 0; 1537d722e3fbSopenharmony_ci} 1538d722e3fbSopenharmony_ci 1539d722e3fbSopenharmony_cidrm_public int 1540d722e3fbSopenharmony_cidrm_intel_gem_bo_map_gtt(drm_intel_bo *bo) 1541d722e3fbSopenharmony_ci{ 1542d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1543d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1544d722e3fbSopenharmony_ci struct drm_i915_gem_set_domain set_domain; 1545d722e3fbSopenharmony_ci int ret; 1546d722e3fbSopenharmony_ci 1547d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 1548d722e3fbSopenharmony_ci 1549d722e3fbSopenharmony_ci ret = map_gtt(bo); 1550d722e3fbSopenharmony_ci if (ret) { 1551d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1552d722e3fbSopenharmony_ci return ret; 1553d722e3fbSopenharmony_ci } 1554d722e3fbSopenharmony_ci 1555d722e3fbSopenharmony_ci /* Now move it to the GTT domain so that the GPU and CPU 1556d722e3fbSopenharmony_ci * caches are flushed and the GPU isn't actively using the 1557d722e3fbSopenharmony_ci * buffer. 1558d722e3fbSopenharmony_ci * 1559d722e3fbSopenharmony_ci * The pagefault handler does this domain change for us when 1560d722e3fbSopenharmony_ci * it has unbound the BO from the GTT, but it's up to us to 1561d722e3fbSopenharmony_ci * tell it when we're about to use things if we had done 1562d722e3fbSopenharmony_ci * rendering and it still happens to be bound to the GTT. 1563d722e3fbSopenharmony_ci */ 1564d722e3fbSopenharmony_ci memclear(set_domain); 1565d722e3fbSopenharmony_ci set_domain.handle = bo_gem->gem_handle; 1566d722e3fbSopenharmony_ci set_domain.read_domains = I915_GEM_DOMAIN_GTT; 1567d722e3fbSopenharmony_ci set_domain.write_domain = I915_GEM_DOMAIN_GTT; 1568d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1569d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_SET_DOMAIN, 1570d722e3fbSopenharmony_ci &set_domain); 1571d722e3fbSopenharmony_ci if (ret != 0) { 1572d722e3fbSopenharmony_ci DBG("%s:%d: Error setting domain %d: %s\n", 1573d722e3fbSopenharmony_ci __FILE__, __LINE__, bo_gem->gem_handle, 1574d722e3fbSopenharmony_ci strerror(errno)); 1575d722e3fbSopenharmony_ci } 1576d722e3fbSopenharmony_ci 1577d722e3fbSopenharmony_ci drm_intel_gem_bo_mark_mmaps_incoherent(bo); 1578d722e3fbSopenharmony_ci VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size)); 1579d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1580d722e3fbSopenharmony_ci 1581d722e3fbSopenharmony_ci return 0; 1582d722e3fbSopenharmony_ci} 1583d722e3fbSopenharmony_ci 1584d722e3fbSopenharmony_ci/** 1585d722e3fbSopenharmony_ci * Performs a mapping of the buffer object like the normal GTT 1586d722e3fbSopenharmony_ci * mapping, but avoids waiting for the GPU to be done reading from or 1587d722e3fbSopenharmony_ci * rendering to the buffer. 1588d722e3fbSopenharmony_ci * 1589d722e3fbSopenharmony_ci * This is used in the implementation of GL_ARB_map_buffer_range: The 1590d722e3fbSopenharmony_ci * user asks to create a buffer, then does a mapping, fills some 1591d722e3fbSopenharmony_ci * space, runs a drawing command, then asks to map it again without 1592d722e3fbSopenharmony_ci * synchronizing because it guarantees that it won't write over the 1593d722e3fbSopenharmony_ci * data that the GPU is busy using (or, more specifically, that if it 1594d722e3fbSopenharmony_ci * does write over the data, it acknowledges that rendering is 1595d722e3fbSopenharmony_ci * undefined). 1596d722e3fbSopenharmony_ci */ 1597d722e3fbSopenharmony_ci 1598d722e3fbSopenharmony_cidrm_public int 1599d722e3fbSopenharmony_cidrm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo) 1600d722e3fbSopenharmony_ci{ 1601d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1602d722e3fbSopenharmony_ci#if HAVE_VALGRIND 1603d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1604d722e3fbSopenharmony_ci#endif 1605d722e3fbSopenharmony_ci int ret; 1606d722e3fbSopenharmony_ci 1607d722e3fbSopenharmony_ci /* If the CPU cache isn't coherent with the GTT, then use a 1608d722e3fbSopenharmony_ci * regular synchronized mapping. The problem is that we don't 1609d722e3fbSopenharmony_ci * track where the buffer was last used on the CPU side in 1610d722e3fbSopenharmony_ci * terms of drm_intel_bo_map vs drm_intel_gem_bo_map_gtt, so 1611d722e3fbSopenharmony_ci * we would potentially corrupt the buffer even when the user 1612d722e3fbSopenharmony_ci * does reasonable things. 1613d722e3fbSopenharmony_ci */ 1614d722e3fbSopenharmony_ci if (!bufmgr_gem->has_llc) 1615d722e3fbSopenharmony_ci return drm_intel_gem_bo_map_gtt(bo); 1616d722e3fbSopenharmony_ci 1617d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 1618d722e3fbSopenharmony_ci 1619d722e3fbSopenharmony_ci ret = map_gtt(bo); 1620d722e3fbSopenharmony_ci if (ret == 0) { 1621d722e3fbSopenharmony_ci drm_intel_gem_bo_mark_mmaps_incoherent(bo); 1622d722e3fbSopenharmony_ci VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size)); 1623d722e3fbSopenharmony_ci } 1624d722e3fbSopenharmony_ci 1625d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1626d722e3fbSopenharmony_ci 1627d722e3fbSopenharmony_ci return ret; 1628d722e3fbSopenharmony_ci} 1629d722e3fbSopenharmony_ci 1630d722e3fbSopenharmony_cistatic int drm_intel_gem_bo_unmap(drm_intel_bo *bo) 1631d722e3fbSopenharmony_ci{ 1632d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem; 1633d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1634d722e3fbSopenharmony_ci int ret = 0; 1635d722e3fbSopenharmony_ci 1636d722e3fbSopenharmony_ci if (bo == NULL) 1637d722e3fbSopenharmony_ci return 0; 1638d722e3fbSopenharmony_ci 1639d722e3fbSopenharmony_ci if (bo_gem->is_userptr) 1640d722e3fbSopenharmony_ci return 0; 1641d722e3fbSopenharmony_ci 1642d722e3fbSopenharmony_ci bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1643d722e3fbSopenharmony_ci 1644d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 1645d722e3fbSopenharmony_ci 1646d722e3fbSopenharmony_ci if (bo_gem->map_count <= 0) { 1647d722e3fbSopenharmony_ci DBG("attempted to unmap an unmapped bo\n"); 1648d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1649d722e3fbSopenharmony_ci /* Preserve the old behaviour of just treating this as a 1650d722e3fbSopenharmony_ci * no-op rather than reporting the error. 1651d722e3fbSopenharmony_ci */ 1652d722e3fbSopenharmony_ci return 0; 1653d722e3fbSopenharmony_ci } 1654d722e3fbSopenharmony_ci 1655d722e3fbSopenharmony_ci if (bo_gem->mapped_cpu_write) { 1656d722e3fbSopenharmony_ci struct drm_i915_gem_sw_finish sw_finish; 1657d722e3fbSopenharmony_ci 1658d722e3fbSopenharmony_ci /* Cause a flush to happen if the buffer's pinned for 1659d722e3fbSopenharmony_ci * scanout, so the results show up in a timely manner. 1660d722e3fbSopenharmony_ci * Unlike GTT set domains, this only does work if the 1661d722e3fbSopenharmony_ci * buffer should be scanout-related. 1662d722e3fbSopenharmony_ci */ 1663d722e3fbSopenharmony_ci memclear(sw_finish); 1664d722e3fbSopenharmony_ci sw_finish.handle = bo_gem->gem_handle; 1665d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1666d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_SW_FINISH, 1667d722e3fbSopenharmony_ci &sw_finish); 1668d722e3fbSopenharmony_ci ret = ret == -1 ? -errno : 0; 1669d722e3fbSopenharmony_ci 1670d722e3fbSopenharmony_ci bo_gem->mapped_cpu_write = false; 1671d722e3fbSopenharmony_ci } 1672d722e3fbSopenharmony_ci 1673d722e3fbSopenharmony_ci /* We need to unmap after every innovation as we cannot track 1674d722e3fbSopenharmony_ci * an open vma for every bo as that will exhaust the system 1675d722e3fbSopenharmony_ci * limits and cause later failures. 1676d722e3fbSopenharmony_ci */ 1677d722e3fbSopenharmony_ci if (--bo_gem->map_count == 0) { 1678d722e3fbSopenharmony_ci drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 1679d722e3fbSopenharmony_ci drm_intel_gem_bo_mark_mmaps_incoherent(bo); 1680d722e3fbSopenharmony_ci bo->virtual = NULL; 1681d722e3fbSopenharmony_ci } 1682d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 1683d722e3fbSopenharmony_ci 1684d722e3fbSopenharmony_ci return ret; 1685d722e3fbSopenharmony_ci} 1686d722e3fbSopenharmony_ci 1687d722e3fbSopenharmony_cidrm_public int 1688d722e3fbSopenharmony_cidrm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo) 1689d722e3fbSopenharmony_ci{ 1690d722e3fbSopenharmony_ci return drm_intel_gem_bo_unmap(bo); 1691d722e3fbSopenharmony_ci} 1692d722e3fbSopenharmony_ci 1693d722e3fbSopenharmony_cistatic bool is_cache_coherent(drm_intel_bo *bo) 1694d722e3fbSopenharmony_ci{ 1695d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1696d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1697d722e3fbSopenharmony_ci struct drm_i915_gem_caching arg = {}; 1698d722e3fbSopenharmony_ci 1699d722e3fbSopenharmony_ci arg.handle = bo_gem->gem_handle; 1700d722e3fbSopenharmony_ci if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_CACHING, &arg)) 1701d722e3fbSopenharmony_ci assert(false); 1702d722e3fbSopenharmony_ci return arg.caching != I915_CACHING_NONE; 1703d722e3fbSopenharmony_ci} 1704d722e3fbSopenharmony_ci 1705d722e3fbSopenharmony_cistatic void set_domain(drm_intel_bo *bo, uint32_t read, uint32_t write) 1706d722e3fbSopenharmony_ci{ 1707d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1708d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1709d722e3fbSopenharmony_ci struct drm_i915_gem_set_domain arg = {}; 1710d722e3fbSopenharmony_ci 1711d722e3fbSopenharmony_ci arg.handle = bo_gem->gem_handle; 1712d722e3fbSopenharmony_ci arg.read_domains = read; 1713d722e3fbSopenharmony_ci arg.write_domain = write; 1714d722e3fbSopenharmony_ci if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &arg)) 1715d722e3fbSopenharmony_ci assert(false); 1716d722e3fbSopenharmony_ci} 1717d722e3fbSopenharmony_ci 1718d722e3fbSopenharmony_cistatic int mmap_write(drm_intel_bo *bo, unsigned long offset, 1719d722e3fbSopenharmony_ci unsigned long length, const void *buf) 1720d722e3fbSopenharmony_ci{ 1721d722e3fbSopenharmony_ci void *map = NULL; 1722d722e3fbSopenharmony_ci 1723d722e3fbSopenharmony_ci if (!length) 1724d722e3fbSopenharmony_ci return 0; 1725d722e3fbSopenharmony_ci 1726d722e3fbSopenharmony_ci if (is_cache_coherent(bo)) { 1727d722e3fbSopenharmony_ci map = drm_intel_gem_bo_map__cpu(bo); 1728d722e3fbSopenharmony_ci if (map) 1729d722e3fbSopenharmony_ci set_domain(bo, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); 1730d722e3fbSopenharmony_ci } 1731d722e3fbSopenharmony_ci if (!map) { 1732d722e3fbSopenharmony_ci map = drm_intel_gem_bo_map__wc(bo); 1733d722e3fbSopenharmony_ci if (map) 1734d722e3fbSopenharmony_ci set_domain(bo, I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC); 1735d722e3fbSopenharmony_ci } 1736d722e3fbSopenharmony_ci 1737d722e3fbSopenharmony_ci assert(map); 1738d722e3fbSopenharmony_ci memcpy((char *)map + offset, buf, length); 1739d722e3fbSopenharmony_ci drm_intel_gem_bo_unmap(bo); 1740d722e3fbSopenharmony_ci return 0; 1741d722e3fbSopenharmony_ci} 1742d722e3fbSopenharmony_ci 1743d722e3fbSopenharmony_cistatic int mmap_read(drm_intel_bo *bo, unsigned long offset, 1744d722e3fbSopenharmony_ci unsigned long length, void *buf) 1745d722e3fbSopenharmony_ci{ 1746d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1747d722e3fbSopenharmony_ci void *map = NULL; 1748d722e3fbSopenharmony_ci 1749d722e3fbSopenharmony_ci if (!length) 1750d722e3fbSopenharmony_ci return 0; 1751d722e3fbSopenharmony_ci 1752d722e3fbSopenharmony_ci if (bufmgr_gem->has_llc || is_cache_coherent(bo)) { 1753d722e3fbSopenharmony_ci map = drm_intel_gem_bo_map__cpu(bo); 1754d722e3fbSopenharmony_ci if (map) 1755d722e3fbSopenharmony_ci set_domain(bo, I915_GEM_DOMAIN_CPU, 0); 1756d722e3fbSopenharmony_ci } 1757d722e3fbSopenharmony_ci if (!map) { 1758d722e3fbSopenharmony_ci map = drm_intel_gem_bo_map__wc(bo); 1759d722e3fbSopenharmony_ci if (map) 1760d722e3fbSopenharmony_ci set_domain(bo, I915_GEM_DOMAIN_WC, 0); 1761d722e3fbSopenharmony_ci } 1762d722e3fbSopenharmony_ci 1763d722e3fbSopenharmony_ci assert(map); 1764d722e3fbSopenharmony_ci memcpy(buf, (char *)map + offset, length); 1765d722e3fbSopenharmony_ci drm_intel_gem_bo_unmap(bo); 1766d722e3fbSopenharmony_ci return 0; 1767d722e3fbSopenharmony_ci} 1768d722e3fbSopenharmony_ci 1769d722e3fbSopenharmony_cistatic int 1770d722e3fbSopenharmony_cidrm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset, 1771d722e3fbSopenharmony_ci unsigned long size, const void *data) 1772d722e3fbSopenharmony_ci{ 1773d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1774d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1775d722e3fbSopenharmony_ci struct drm_i915_gem_pwrite pwrite; 1776d722e3fbSopenharmony_ci int ret; 1777d722e3fbSopenharmony_ci 1778d722e3fbSopenharmony_ci if (bo_gem->is_userptr) 1779d722e3fbSopenharmony_ci return -EINVAL; 1780d722e3fbSopenharmony_ci 1781d722e3fbSopenharmony_ci memclear(pwrite); 1782d722e3fbSopenharmony_ci pwrite.handle = bo_gem->gem_handle; 1783d722e3fbSopenharmony_ci pwrite.offset = offset; 1784d722e3fbSopenharmony_ci pwrite.size = size; 1785d722e3fbSopenharmony_ci pwrite.data_ptr = (uint64_t) (uintptr_t) data; 1786d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1787d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_PWRITE, 1788d722e3fbSopenharmony_ci &pwrite); 1789d722e3fbSopenharmony_ci if (ret) 1790d722e3fbSopenharmony_ci ret = -errno; 1791d722e3fbSopenharmony_ci 1792d722e3fbSopenharmony_ci if (ret != 0 && ret != -EOPNOTSUPP) { 1793d722e3fbSopenharmony_ci DBG("%s:%d: Error writing data to buffer %d: (%d %d) %s .\n", 1794d722e3fbSopenharmony_ci __FILE__, __LINE__, bo_gem->gem_handle, (int)offset, 1795d722e3fbSopenharmony_ci (int)size, strerror(errno)); 1796d722e3fbSopenharmony_ci return ret; 1797d722e3fbSopenharmony_ci } 1798d722e3fbSopenharmony_ci 1799d722e3fbSopenharmony_ci if (ret == -EOPNOTSUPP) 1800d722e3fbSopenharmony_ci mmap_write(bo, offset, size, data); 1801d722e3fbSopenharmony_ci 1802d722e3fbSopenharmony_ci return 0; 1803d722e3fbSopenharmony_ci} 1804d722e3fbSopenharmony_ci 1805d722e3fbSopenharmony_cistatic int 1806d722e3fbSopenharmony_cidrm_intel_gem_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id) 1807d722e3fbSopenharmony_ci{ 1808d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 1809d722e3fbSopenharmony_ci struct drm_i915_get_pipe_from_crtc_id get_pipe_from_crtc_id; 1810d722e3fbSopenharmony_ci int ret; 1811d722e3fbSopenharmony_ci 1812d722e3fbSopenharmony_ci memclear(get_pipe_from_crtc_id); 1813d722e3fbSopenharmony_ci get_pipe_from_crtc_id.crtc_id = crtc_id; 1814d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1815d722e3fbSopenharmony_ci DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID, 1816d722e3fbSopenharmony_ci &get_pipe_from_crtc_id); 1817d722e3fbSopenharmony_ci if (ret != 0) { 1818d722e3fbSopenharmony_ci /* We return -1 here to signal that we don't 1819d722e3fbSopenharmony_ci * know which pipe is associated with this crtc. 1820d722e3fbSopenharmony_ci * This lets the caller know that this information 1821d722e3fbSopenharmony_ci * isn't available; using the wrong pipe for 1822d722e3fbSopenharmony_ci * vblank waiting can cause the chipset to lock up 1823d722e3fbSopenharmony_ci */ 1824d722e3fbSopenharmony_ci return -1; 1825d722e3fbSopenharmony_ci } 1826d722e3fbSopenharmony_ci 1827d722e3fbSopenharmony_ci return get_pipe_from_crtc_id.pipe; 1828d722e3fbSopenharmony_ci} 1829d722e3fbSopenharmony_ci 1830d722e3fbSopenharmony_cistatic int 1831d722e3fbSopenharmony_cidrm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset, 1832d722e3fbSopenharmony_ci unsigned long size, void *data) 1833d722e3fbSopenharmony_ci{ 1834d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1835d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1836d722e3fbSopenharmony_ci struct drm_i915_gem_pread pread; 1837d722e3fbSopenharmony_ci int ret; 1838d722e3fbSopenharmony_ci 1839d722e3fbSopenharmony_ci if (bo_gem->is_userptr) 1840d722e3fbSopenharmony_ci return -EINVAL; 1841d722e3fbSopenharmony_ci 1842d722e3fbSopenharmony_ci memclear(pread); 1843d722e3fbSopenharmony_ci pread.handle = bo_gem->gem_handle; 1844d722e3fbSopenharmony_ci pread.offset = offset; 1845d722e3fbSopenharmony_ci pread.size = size; 1846d722e3fbSopenharmony_ci pread.data_ptr = (uint64_t) (uintptr_t) data; 1847d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1848d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_PREAD, 1849d722e3fbSopenharmony_ci &pread); 1850d722e3fbSopenharmony_ci if (ret) 1851d722e3fbSopenharmony_ci ret = -errno; 1852d722e3fbSopenharmony_ci 1853d722e3fbSopenharmony_ci if (ret != 0 && ret != -EOPNOTSUPP) { 1854d722e3fbSopenharmony_ci DBG("%s:%d: Error reading data from buffer %d: (%d %d) %s .\n", 1855d722e3fbSopenharmony_ci __FILE__, __LINE__, bo_gem->gem_handle, (int)offset, 1856d722e3fbSopenharmony_ci (int)size, strerror(errno)); 1857d722e3fbSopenharmony_ci return ret; 1858d722e3fbSopenharmony_ci } 1859d722e3fbSopenharmony_ci 1860d722e3fbSopenharmony_ci if (ret == -EOPNOTSUPP) 1861d722e3fbSopenharmony_ci mmap_read(bo, offset, size, data); 1862d722e3fbSopenharmony_ci 1863d722e3fbSopenharmony_ci return 0; 1864d722e3fbSopenharmony_ci} 1865d722e3fbSopenharmony_ci 1866d722e3fbSopenharmony_ci/** Waits for all GPU rendering with the object to have completed. */ 1867d722e3fbSopenharmony_cistatic void 1868d722e3fbSopenharmony_cidrm_intel_gem_bo_wait_rendering(drm_intel_bo *bo) 1869d722e3fbSopenharmony_ci{ 1870d722e3fbSopenharmony_ci drm_intel_gem_bo_start_gtt_access(bo, 1); 1871d722e3fbSopenharmony_ci} 1872d722e3fbSopenharmony_ci 1873d722e3fbSopenharmony_ci/** 1874d722e3fbSopenharmony_ci * Waits on a BO for the given amount of time. 1875d722e3fbSopenharmony_ci * 1876d722e3fbSopenharmony_ci * @bo: buffer object to wait for 1877d722e3fbSopenharmony_ci * @timeout_ns: amount of time to wait in nanoseconds. 1878d722e3fbSopenharmony_ci * If value is less than 0, an infinite wait will occur. 1879d722e3fbSopenharmony_ci * 1880d722e3fbSopenharmony_ci * Returns 0 if the wait was successful ie. the last batch referencing the 1881d722e3fbSopenharmony_ci * object has completed within the allotted time. Otherwise some negative return 1882d722e3fbSopenharmony_ci * value describes the error. Of particular interest is -ETIME when the wait has 1883d722e3fbSopenharmony_ci * failed to yield the desired result. 1884d722e3fbSopenharmony_ci * 1885d722e3fbSopenharmony_ci * Similar to drm_intel_gem_bo_wait_rendering except a timeout parameter allows 1886d722e3fbSopenharmony_ci * the operation to give up after a certain amount of time. Another subtle 1887d722e3fbSopenharmony_ci * difference is the internal locking semantics are different (this variant does 1888d722e3fbSopenharmony_ci * not hold the lock for the duration of the wait). This makes the wait subject 1889d722e3fbSopenharmony_ci * to a larger userspace race window. 1890d722e3fbSopenharmony_ci * 1891d722e3fbSopenharmony_ci * The implementation shall wait until the object is no longer actively 1892d722e3fbSopenharmony_ci * referenced within a batch buffer at the time of the call. The wait will 1893d722e3fbSopenharmony_ci * not guarantee that the buffer is re-issued via another thread, or an flinked 1894d722e3fbSopenharmony_ci * handle. Userspace must make sure this race does not occur if such precision 1895d722e3fbSopenharmony_ci * is important. 1896d722e3fbSopenharmony_ci * 1897d722e3fbSopenharmony_ci * Note that some kernels have broken the inifite wait for negative values 1898d722e3fbSopenharmony_ci * promise, upgrade to latest stable kernels if this is the case. 1899d722e3fbSopenharmony_ci */ 1900d722e3fbSopenharmony_cidrm_public int 1901d722e3fbSopenharmony_cidrm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns) 1902d722e3fbSopenharmony_ci{ 1903d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1904d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1905d722e3fbSopenharmony_ci struct drm_i915_gem_wait wait; 1906d722e3fbSopenharmony_ci int ret; 1907d722e3fbSopenharmony_ci 1908d722e3fbSopenharmony_ci if (!bufmgr_gem->has_wait_timeout) { 1909d722e3fbSopenharmony_ci DBG("%s:%d: Timed wait is not supported. Falling back to " 1910d722e3fbSopenharmony_ci "infinite wait\n", __FILE__, __LINE__); 1911d722e3fbSopenharmony_ci if (timeout_ns) { 1912d722e3fbSopenharmony_ci drm_intel_gem_bo_wait_rendering(bo); 1913d722e3fbSopenharmony_ci return 0; 1914d722e3fbSopenharmony_ci } else { 1915d722e3fbSopenharmony_ci return drm_intel_gem_bo_busy(bo) ? -ETIME : 0; 1916d722e3fbSopenharmony_ci } 1917d722e3fbSopenharmony_ci } 1918d722e3fbSopenharmony_ci 1919d722e3fbSopenharmony_ci memclear(wait); 1920d722e3fbSopenharmony_ci wait.bo_handle = bo_gem->gem_handle; 1921d722e3fbSopenharmony_ci wait.timeout_ns = timeout_ns; 1922d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait); 1923d722e3fbSopenharmony_ci if (ret == -1) 1924d722e3fbSopenharmony_ci return -errno; 1925d722e3fbSopenharmony_ci 1926d722e3fbSopenharmony_ci return ret; 1927d722e3fbSopenharmony_ci} 1928d722e3fbSopenharmony_ci 1929d722e3fbSopenharmony_ci/** 1930d722e3fbSopenharmony_ci * Sets the object to the GTT read and possibly write domain, used by the X 1931d722e3fbSopenharmony_ci * 2D driver in the absence of kernel support to do drm_intel_gem_bo_map_gtt(). 1932d722e3fbSopenharmony_ci * 1933d722e3fbSopenharmony_ci * In combination with drm_intel_gem_bo_pin() and manual fence management, we 1934d722e3fbSopenharmony_ci * can do tiled pixmaps this way. 1935d722e3fbSopenharmony_ci */ 1936d722e3fbSopenharmony_cidrm_public void 1937d722e3fbSopenharmony_cidrm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable) 1938d722e3fbSopenharmony_ci{ 1939d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 1940d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 1941d722e3fbSopenharmony_ci struct drm_i915_gem_set_domain set_domain; 1942d722e3fbSopenharmony_ci int ret; 1943d722e3fbSopenharmony_ci 1944d722e3fbSopenharmony_ci memclear(set_domain); 1945d722e3fbSopenharmony_ci set_domain.handle = bo_gem->gem_handle; 1946d722e3fbSopenharmony_ci set_domain.read_domains = I915_GEM_DOMAIN_GTT; 1947d722e3fbSopenharmony_ci set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_GTT : 0; 1948d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 1949d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_SET_DOMAIN, 1950d722e3fbSopenharmony_ci &set_domain); 1951d722e3fbSopenharmony_ci if (ret != 0) { 1952d722e3fbSopenharmony_ci DBG("%s:%d: Error setting memory domains %d (%08x %08x): %s .\n", 1953d722e3fbSopenharmony_ci __FILE__, __LINE__, bo_gem->gem_handle, 1954d722e3fbSopenharmony_ci set_domain.read_domains, set_domain.write_domain, 1955d722e3fbSopenharmony_ci strerror(errno)); 1956d722e3fbSopenharmony_ci } 1957d722e3fbSopenharmony_ci} 1958d722e3fbSopenharmony_ci 1959d722e3fbSopenharmony_cistatic void 1960d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr) 1961d722e3fbSopenharmony_ci{ 1962d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 1963d722e3fbSopenharmony_ci int i, ret; 1964d722e3fbSopenharmony_ci 1965d722e3fbSopenharmony_ci free(bufmgr_gem->exec2_objects); 1966d722e3fbSopenharmony_ci free(bufmgr_gem->exec_bos); 1967d722e3fbSopenharmony_ci 1968d722e3fbSopenharmony_ci pthread_mutex_destroy(&bufmgr_gem->lock); 1969d722e3fbSopenharmony_ci 1970d722e3fbSopenharmony_ci /* Free any cached buffer objects we were going to reuse */ 1971d722e3fbSopenharmony_ci for (i = 0; i < bufmgr_gem->num_buckets; i++) { 1972d722e3fbSopenharmony_ci struct drm_intel_gem_bo_bucket *bucket = 1973d722e3fbSopenharmony_ci &bufmgr_gem->cache_bucket[i]; 1974d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem; 1975d722e3fbSopenharmony_ci 1976d722e3fbSopenharmony_ci while (!DRMLISTEMPTY(&bucket->head)) { 1977d722e3fbSopenharmony_ci bo_gem = DRMLISTENTRY(drm_intel_bo_gem, 1978d722e3fbSopenharmony_ci bucket->head.next, head); 1979d722e3fbSopenharmony_ci DRMLISTDEL(&bo_gem->head); 1980d722e3fbSopenharmony_ci 1981d722e3fbSopenharmony_ci drm_intel_gem_bo_free(&bo_gem->bo); 1982d722e3fbSopenharmony_ci } 1983d722e3fbSopenharmony_ci } 1984d722e3fbSopenharmony_ci 1985d722e3fbSopenharmony_ci /* Release userptr bo kept hanging around for optimisation. */ 1986d722e3fbSopenharmony_ci if (bufmgr_gem->userptr_active.ptr) { 1987d722e3fbSopenharmony_ci ret = drmCloseBufferHandle(bufmgr_gem->fd, 1988d722e3fbSopenharmony_ci bufmgr_gem->userptr_active.handle); 1989d722e3fbSopenharmony_ci free(bufmgr_gem->userptr_active.ptr); 1990d722e3fbSopenharmony_ci if (ret) 1991d722e3fbSopenharmony_ci fprintf(stderr, 1992d722e3fbSopenharmony_ci "Failed to release test userptr object! (%d) " 1993d722e3fbSopenharmony_ci "i915 kernel driver may not be sane!\n", errno); 1994d722e3fbSopenharmony_ci } 1995d722e3fbSopenharmony_ci 1996d722e3fbSopenharmony_ci free(bufmgr); 1997d722e3fbSopenharmony_ci} 1998d722e3fbSopenharmony_ci 1999d722e3fbSopenharmony_ci/** 2000d722e3fbSopenharmony_ci * Adds the target buffer to the validation list and adds the relocation 2001d722e3fbSopenharmony_ci * to the reloc_buffer's relocation list. 2002d722e3fbSopenharmony_ci * 2003d722e3fbSopenharmony_ci * The relocation entry at the given offset must already contain the 2004d722e3fbSopenharmony_ci * precomputed relocation value, because the kernel will optimize out 2005d722e3fbSopenharmony_ci * the relocation entry write when the buffer hasn't moved from the 2006d722e3fbSopenharmony_ci * last known offset in target_bo. 2007d722e3fbSopenharmony_ci */ 2008d722e3fbSopenharmony_cistatic int 2009d722e3fbSopenharmony_cido_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, 2010d722e3fbSopenharmony_ci drm_intel_bo *target_bo, uint32_t target_offset, 2011d722e3fbSopenharmony_ci uint32_t read_domains, uint32_t write_domain, 2012d722e3fbSopenharmony_ci bool need_fence) 2013d722e3fbSopenharmony_ci{ 2014d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2015d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2016d722e3fbSopenharmony_ci drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; 2017d722e3fbSopenharmony_ci bool fenced_command; 2018d722e3fbSopenharmony_ci 2019d722e3fbSopenharmony_ci if (bo_gem->has_error) 2020d722e3fbSopenharmony_ci return -ENOMEM; 2021d722e3fbSopenharmony_ci 2022d722e3fbSopenharmony_ci if (target_bo_gem->has_error) { 2023d722e3fbSopenharmony_ci bo_gem->has_error = true; 2024d722e3fbSopenharmony_ci return -ENOMEM; 2025d722e3fbSopenharmony_ci } 2026d722e3fbSopenharmony_ci 2027d722e3fbSopenharmony_ci /* We never use HW fences for rendering on 965+ */ 2028d722e3fbSopenharmony_ci if (bufmgr_gem->gen >= 4) 2029d722e3fbSopenharmony_ci need_fence = false; 2030d722e3fbSopenharmony_ci 2031d722e3fbSopenharmony_ci fenced_command = need_fence; 2032d722e3fbSopenharmony_ci if (target_bo_gem->tiling_mode == I915_TILING_NONE) 2033d722e3fbSopenharmony_ci need_fence = false; 2034d722e3fbSopenharmony_ci 2035d722e3fbSopenharmony_ci /* Create a new relocation list if needed */ 2036d722e3fbSopenharmony_ci if (bo_gem->relocs == NULL && drm_intel_setup_reloc_list(bo)) 2037d722e3fbSopenharmony_ci return -ENOMEM; 2038d722e3fbSopenharmony_ci 2039d722e3fbSopenharmony_ci /* Check overflow */ 2040d722e3fbSopenharmony_ci assert(bo_gem->reloc_count < bufmgr_gem->max_relocs); 2041d722e3fbSopenharmony_ci 2042d722e3fbSopenharmony_ci /* Check args */ 2043d722e3fbSopenharmony_ci assert(offset <= bo->size - 4); 2044d722e3fbSopenharmony_ci assert((write_domain & (write_domain - 1)) == 0); 2045d722e3fbSopenharmony_ci 2046d722e3fbSopenharmony_ci /* An object needing a fence is a tiled buffer, so it won't have 2047d722e3fbSopenharmony_ci * relocs to other buffers. 2048d722e3fbSopenharmony_ci */ 2049d722e3fbSopenharmony_ci if (need_fence) { 2050d722e3fbSopenharmony_ci assert(target_bo_gem->reloc_count == 0); 2051d722e3fbSopenharmony_ci target_bo_gem->reloc_tree_fences = 1; 2052d722e3fbSopenharmony_ci } 2053d722e3fbSopenharmony_ci 2054d722e3fbSopenharmony_ci /* Make sure that we're not adding a reloc to something whose size has 2055d722e3fbSopenharmony_ci * already been accounted for. 2056d722e3fbSopenharmony_ci */ 2057d722e3fbSopenharmony_ci assert(!bo_gem->used_as_reloc_target); 2058d722e3fbSopenharmony_ci if (target_bo_gem != bo_gem) { 2059d722e3fbSopenharmony_ci target_bo_gem->used_as_reloc_target = true; 2060d722e3fbSopenharmony_ci bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size; 2061d722e3fbSopenharmony_ci bo_gem->reloc_tree_fences += target_bo_gem->reloc_tree_fences; 2062d722e3fbSopenharmony_ci } 2063d722e3fbSopenharmony_ci 2064d722e3fbSopenharmony_ci bo_gem->reloc_target_info[bo_gem->reloc_count].bo = target_bo; 2065d722e3fbSopenharmony_ci if (target_bo != bo) 2066d722e3fbSopenharmony_ci drm_intel_gem_bo_reference(target_bo); 2067d722e3fbSopenharmony_ci if (fenced_command) 2068d722e3fbSopenharmony_ci bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 2069d722e3fbSopenharmony_ci DRM_INTEL_RELOC_FENCE; 2070d722e3fbSopenharmony_ci else 2071d722e3fbSopenharmony_ci bo_gem->reloc_target_info[bo_gem->reloc_count].flags = 0; 2072d722e3fbSopenharmony_ci 2073d722e3fbSopenharmony_ci bo_gem->relocs[bo_gem->reloc_count].offset = offset; 2074d722e3fbSopenharmony_ci bo_gem->relocs[bo_gem->reloc_count].delta = target_offset; 2075d722e3fbSopenharmony_ci bo_gem->relocs[bo_gem->reloc_count].target_handle = 2076d722e3fbSopenharmony_ci target_bo_gem->gem_handle; 2077d722e3fbSopenharmony_ci bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains; 2078d722e3fbSopenharmony_ci bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain; 2079d722e3fbSopenharmony_ci bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset64; 2080d722e3fbSopenharmony_ci bo_gem->reloc_count++; 2081d722e3fbSopenharmony_ci 2082d722e3fbSopenharmony_ci return 0; 2083d722e3fbSopenharmony_ci} 2084d722e3fbSopenharmony_ci 2085d722e3fbSopenharmony_cistatic void 2086d722e3fbSopenharmony_cidrm_intel_gem_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable) 2087d722e3fbSopenharmony_ci{ 2088d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2089d722e3fbSopenharmony_ci 2090d722e3fbSopenharmony_ci if (enable) 2091d722e3fbSopenharmony_ci bo_gem->kflags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; 2092d722e3fbSopenharmony_ci else 2093d722e3fbSopenharmony_ci bo_gem->kflags &= ~EXEC_OBJECT_SUPPORTS_48B_ADDRESS; 2094d722e3fbSopenharmony_ci} 2095d722e3fbSopenharmony_ci 2096d722e3fbSopenharmony_cistatic int 2097d722e3fbSopenharmony_cidrm_intel_gem_bo_add_softpin_target(drm_intel_bo *bo, drm_intel_bo *target_bo) 2098d722e3fbSopenharmony_ci{ 2099d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2100d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2101d722e3fbSopenharmony_ci drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; 2102d722e3fbSopenharmony_ci if (bo_gem->has_error) 2103d722e3fbSopenharmony_ci return -ENOMEM; 2104d722e3fbSopenharmony_ci 2105d722e3fbSopenharmony_ci if (target_bo_gem->has_error) { 2106d722e3fbSopenharmony_ci bo_gem->has_error = true; 2107d722e3fbSopenharmony_ci return -ENOMEM; 2108d722e3fbSopenharmony_ci } 2109d722e3fbSopenharmony_ci 2110d722e3fbSopenharmony_ci if (!(target_bo_gem->kflags & EXEC_OBJECT_PINNED)) 2111d722e3fbSopenharmony_ci return -EINVAL; 2112d722e3fbSopenharmony_ci if (target_bo_gem == bo_gem) 2113d722e3fbSopenharmony_ci return -EINVAL; 2114d722e3fbSopenharmony_ci 2115d722e3fbSopenharmony_ci if (bo_gem->softpin_target_count == bo_gem->softpin_target_size) { 2116d722e3fbSopenharmony_ci int new_size = bo_gem->softpin_target_size * 2; 2117d722e3fbSopenharmony_ci if (new_size == 0) 2118d722e3fbSopenharmony_ci new_size = bufmgr_gem->max_relocs; 2119d722e3fbSopenharmony_ci 2120d722e3fbSopenharmony_ci bo_gem->softpin_target = realloc(bo_gem->softpin_target, new_size * 2121d722e3fbSopenharmony_ci sizeof(drm_intel_bo *)); 2122d722e3fbSopenharmony_ci if (!bo_gem->softpin_target) 2123d722e3fbSopenharmony_ci return -ENOMEM; 2124d722e3fbSopenharmony_ci 2125d722e3fbSopenharmony_ci bo_gem->softpin_target_size = new_size; 2126d722e3fbSopenharmony_ci } 2127d722e3fbSopenharmony_ci bo_gem->softpin_target[bo_gem->softpin_target_count] = target_bo; 2128d722e3fbSopenharmony_ci drm_intel_gem_bo_reference(target_bo); 2129d722e3fbSopenharmony_ci bo_gem->softpin_target_count++; 2130d722e3fbSopenharmony_ci 2131d722e3fbSopenharmony_ci return 0; 2132d722e3fbSopenharmony_ci} 2133d722e3fbSopenharmony_ci 2134d722e3fbSopenharmony_cistatic int 2135d722e3fbSopenharmony_cidrm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset, 2136d722e3fbSopenharmony_ci drm_intel_bo *target_bo, uint32_t target_offset, 2137d722e3fbSopenharmony_ci uint32_t read_domains, uint32_t write_domain) 2138d722e3fbSopenharmony_ci{ 2139d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; 2140d722e3fbSopenharmony_ci drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo; 2141d722e3fbSopenharmony_ci 2142d722e3fbSopenharmony_ci if (target_bo_gem->kflags & EXEC_OBJECT_PINNED) 2143d722e3fbSopenharmony_ci return drm_intel_gem_bo_add_softpin_target(bo, target_bo); 2144d722e3fbSopenharmony_ci else 2145d722e3fbSopenharmony_ci return do_bo_emit_reloc(bo, offset, target_bo, target_offset, 2146d722e3fbSopenharmony_ci read_domains, write_domain, 2147d722e3fbSopenharmony_ci !bufmgr_gem->fenced_relocs); 2148d722e3fbSopenharmony_ci} 2149d722e3fbSopenharmony_ci 2150d722e3fbSopenharmony_cistatic int 2151d722e3fbSopenharmony_cidrm_intel_gem_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset, 2152d722e3fbSopenharmony_ci drm_intel_bo *target_bo, 2153d722e3fbSopenharmony_ci uint32_t target_offset, 2154d722e3fbSopenharmony_ci uint32_t read_domains, uint32_t write_domain) 2155d722e3fbSopenharmony_ci{ 2156d722e3fbSopenharmony_ci return do_bo_emit_reloc(bo, offset, target_bo, target_offset, 2157d722e3fbSopenharmony_ci read_domains, write_domain, true); 2158d722e3fbSopenharmony_ci} 2159d722e3fbSopenharmony_ci 2160d722e3fbSopenharmony_cidrm_public int 2161d722e3fbSopenharmony_cidrm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo) 2162d722e3fbSopenharmony_ci{ 2163d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2164d722e3fbSopenharmony_ci 2165d722e3fbSopenharmony_ci return bo_gem->reloc_count; 2166d722e3fbSopenharmony_ci} 2167d722e3fbSopenharmony_ci 2168d722e3fbSopenharmony_ci/** 2169d722e3fbSopenharmony_ci * Removes existing relocation entries in the BO after "start". 2170d722e3fbSopenharmony_ci * 2171d722e3fbSopenharmony_ci * This allows a user to avoid a two-step process for state setup with 2172d722e3fbSopenharmony_ci * counting up all the buffer objects and doing a 2173d722e3fbSopenharmony_ci * drm_intel_bufmgr_check_aperture_space() before emitting any of the 2174d722e3fbSopenharmony_ci * relocations for the state setup. Instead, save the state of the 2175d722e3fbSopenharmony_ci * batchbuffer including drm_intel_gem_get_reloc_count(), emit all the 2176d722e3fbSopenharmony_ci * state, and then check if it still fits in the aperture. 2177d722e3fbSopenharmony_ci * 2178d722e3fbSopenharmony_ci * Any further drm_intel_bufmgr_check_aperture_space() queries 2179d722e3fbSopenharmony_ci * involving this buffer in the tree are undefined after this call. 2180d722e3fbSopenharmony_ci * 2181d722e3fbSopenharmony_ci * This also removes all softpinned targets being referenced by the BO. 2182d722e3fbSopenharmony_ci */ 2183d722e3fbSopenharmony_cidrm_public void 2184d722e3fbSopenharmony_cidrm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start) 2185d722e3fbSopenharmony_ci{ 2186d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2187d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2188d722e3fbSopenharmony_ci int i; 2189d722e3fbSopenharmony_ci struct timespec time; 2190d722e3fbSopenharmony_ci 2191d722e3fbSopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &time); 2192d722e3fbSopenharmony_ci 2193d722e3fbSopenharmony_ci assert(bo_gem->reloc_count >= start); 2194d722e3fbSopenharmony_ci 2195d722e3fbSopenharmony_ci /* Unreference the cleared target buffers */ 2196d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 2197d722e3fbSopenharmony_ci 2198d722e3fbSopenharmony_ci for (i = start; i < bo_gem->reloc_count; i++) { 2199d722e3fbSopenharmony_ci drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->reloc_target_info[i].bo; 2200d722e3fbSopenharmony_ci if (&target_bo_gem->bo != bo) { 2201d722e3fbSopenharmony_ci bo_gem->reloc_tree_fences -= target_bo_gem->reloc_tree_fences; 2202d722e3fbSopenharmony_ci drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, 2203d722e3fbSopenharmony_ci time.tv_sec); 2204d722e3fbSopenharmony_ci } 2205d722e3fbSopenharmony_ci } 2206d722e3fbSopenharmony_ci bo_gem->reloc_count = start; 2207d722e3fbSopenharmony_ci 2208d722e3fbSopenharmony_ci for (i = 0; i < bo_gem->softpin_target_count; i++) { 2209d722e3fbSopenharmony_ci drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) bo_gem->softpin_target[i]; 2210d722e3fbSopenharmony_ci drm_intel_gem_bo_unreference_locked_timed(&target_bo_gem->bo, time.tv_sec); 2211d722e3fbSopenharmony_ci } 2212d722e3fbSopenharmony_ci bo_gem->softpin_target_count = 0; 2213d722e3fbSopenharmony_ci 2214d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 2215d722e3fbSopenharmony_ci 2216d722e3fbSopenharmony_ci} 2217d722e3fbSopenharmony_ci 2218d722e3fbSopenharmony_ci/** 2219d722e3fbSopenharmony_ci * Walk the tree of relocations rooted at BO and accumulate the list of 2220d722e3fbSopenharmony_ci * validations to be performed and update the relocation buffers with 2221d722e3fbSopenharmony_ci * index values into the validation list. 2222d722e3fbSopenharmony_ci */ 2223d722e3fbSopenharmony_cistatic void 2224d722e3fbSopenharmony_cidrm_intel_gem_bo_process_reloc2(drm_intel_bo *bo) 2225d722e3fbSopenharmony_ci{ 2226d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; 2227d722e3fbSopenharmony_ci int i; 2228d722e3fbSopenharmony_ci 2229d722e3fbSopenharmony_ci if (bo_gem->relocs == NULL && bo_gem->softpin_target == NULL) 2230d722e3fbSopenharmony_ci return; 2231d722e3fbSopenharmony_ci 2232d722e3fbSopenharmony_ci for (i = 0; i < bo_gem->reloc_count; i++) { 2233d722e3fbSopenharmony_ci drm_intel_bo *target_bo = bo_gem->reloc_target_info[i].bo; 2234d722e3fbSopenharmony_ci int need_fence; 2235d722e3fbSopenharmony_ci 2236d722e3fbSopenharmony_ci if (target_bo == bo) 2237d722e3fbSopenharmony_ci continue; 2238d722e3fbSopenharmony_ci 2239d722e3fbSopenharmony_ci drm_intel_gem_bo_mark_mmaps_incoherent(bo); 2240d722e3fbSopenharmony_ci 2241d722e3fbSopenharmony_ci /* Continue walking the tree depth-first. */ 2242d722e3fbSopenharmony_ci drm_intel_gem_bo_process_reloc2(target_bo); 2243d722e3fbSopenharmony_ci 2244d722e3fbSopenharmony_ci need_fence = (bo_gem->reloc_target_info[i].flags & 2245d722e3fbSopenharmony_ci DRM_INTEL_RELOC_FENCE); 2246d722e3fbSopenharmony_ci 2247d722e3fbSopenharmony_ci /* Add the target to the validate list */ 2248d722e3fbSopenharmony_ci drm_intel_add_validate_buffer2(target_bo, need_fence); 2249d722e3fbSopenharmony_ci } 2250d722e3fbSopenharmony_ci 2251d722e3fbSopenharmony_ci for (i = 0; i < bo_gem->softpin_target_count; i++) { 2252d722e3fbSopenharmony_ci drm_intel_bo *target_bo = bo_gem->softpin_target[i]; 2253d722e3fbSopenharmony_ci 2254d722e3fbSopenharmony_ci if (target_bo == bo) 2255d722e3fbSopenharmony_ci continue; 2256d722e3fbSopenharmony_ci 2257d722e3fbSopenharmony_ci drm_intel_gem_bo_mark_mmaps_incoherent(bo); 2258d722e3fbSopenharmony_ci drm_intel_gem_bo_process_reloc2(target_bo); 2259d722e3fbSopenharmony_ci drm_intel_add_validate_buffer2(target_bo, false); 2260d722e3fbSopenharmony_ci } 2261d722e3fbSopenharmony_ci} 2262d722e3fbSopenharmony_ci 2263d722e3fbSopenharmony_cistatic void 2264d722e3fbSopenharmony_cidrm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem) 2265d722e3fbSopenharmony_ci{ 2266d722e3fbSopenharmony_ci int i; 2267d722e3fbSopenharmony_ci 2268d722e3fbSopenharmony_ci for (i = 0; i < bufmgr_gem->exec_count; i++) { 2269d722e3fbSopenharmony_ci drm_intel_bo *bo = bufmgr_gem->exec_bos[i]; 2270d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo; 2271d722e3fbSopenharmony_ci 2272d722e3fbSopenharmony_ci /* Update the buffer offset */ 2273d722e3fbSopenharmony_ci if (bufmgr_gem->exec2_objects[i].offset != bo->offset64) { 2274d722e3fbSopenharmony_ci /* If we're seeing softpinned object here it means that the kernel 2275d722e3fbSopenharmony_ci * has relocated our object... Indicating a programming error 2276d722e3fbSopenharmony_ci */ 2277d722e3fbSopenharmony_ci assert(!(bo_gem->kflags & EXEC_OBJECT_PINNED)); 2278d722e3fbSopenharmony_ci DBG("BO %d (%s) migrated: 0x%08x %08x -> 0x%08x %08x\n", 2279d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, 2280d722e3fbSopenharmony_ci upper_32_bits(bo->offset64), 2281d722e3fbSopenharmony_ci lower_32_bits(bo->offset64), 2282d722e3fbSopenharmony_ci upper_32_bits(bufmgr_gem->exec2_objects[i].offset), 2283d722e3fbSopenharmony_ci lower_32_bits(bufmgr_gem->exec2_objects[i].offset)); 2284d722e3fbSopenharmony_ci bo->offset64 = bufmgr_gem->exec2_objects[i].offset; 2285d722e3fbSopenharmony_ci bo->offset = bufmgr_gem->exec2_objects[i].offset; 2286d722e3fbSopenharmony_ci } 2287d722e3fbSopenharmony_ci } 2288d722e3fbSopenharmony_ci} 2289d722e3fbSopenharmony_ci 2290d722e3fbSopenharmony_cidrm_public void 2291d722e3fbSopenharmony_cidrm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo, 2292d722e3fbSopenharmony_ci int x1, int y1, int width, int height, 2293d722e3fbSopenharmony_ci enum aub_dump_bmp_format format, 2294d722e3fbSopenharmony_ci int pitch, int offset) 2295d722e3fbSopenharmony_ci{ 2296d722e3fbSopenharmony_ci} 2297d722e3fbSopenharmony_ci 2298d722e3fbSopenharmony_cistatic int 2299d722e3fbSopenharmony_cido_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx, 2300d722e3fbSopenharmony_ci drm_clip_rect_t *cliprects, int num_cliprects, int DR4, 2301d722e3fbSopenharmony_ci int in_fence, int *out_fence, 2302d722e3fbSopenharmony_ci unsigned int flags) 2303d722e3fbSopenharmony_ci{ 2304d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr; 2305d722e3fbSopenharmony_ci struct drm_i915_gem_execbuffer2 execbuf; 2306d722e3fbSopenharmony_ci int ret = 0; 2307d722e3fbSopenharmony_ci int i; 2308d722e3fbSopenharmony_ci 2309d722e3fbSopenharmony_ci if (to_bo_gem(bo)->has_error) 2310d722e3fbSopenharmony_ci return -ENOMEM; 2311d722e3fbSopenharmony_ci 2312d722e3fbSopenharmony_ci switch (flags & 0x7) { 2313d722e3fbSopenharmony_ci default: 2314d722e3fbSopenharmony_ci return -EINVAL; 2315d722e3fbSopenharmony_ci case I915_EXEC_BLT: 2316d722e3fbSopenharmony_ci if (!bufmgr_gem->has_blt) 2317d722e3fbSopenharmony_ci return -EINVAL; 2318d722e3fbSopenharmony_ci break; 2319d722e3fbSopenharmony_ci case I915_EXEC_BSD: 2320d722e3fbSopenharmony_ci if (!bufmgr_gem->has_bsd) 2321d722e3fbSopenharmony_ci return -EINVAL; 2322d722e3fbSopenharmony_ci break; 2323d722e3fbSopenharmony_ci case I915_EXEC_VEBOX: 2324d722e3fbSopenharmony_ci if (!bufmgr_gem->has_vebox) 2325d722e3fbSopenharmony_ci return -EINVAL; 2326d722e3fbSopenharmony_ci break; 2327d722e3fbSopenharmony_ci case I915_EXEC_RENDER: 2328d722e3fbSopenharmony_ci case I915_EXEC_DEFAULT: 2329d722e3fbSopenharmony_ci break; 2330d722e3fbSopenharmony_ci } 2331d722e3fbSopenharmony_ci 2332d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 2333d722e3fbSopenharmony_ci /* Update indices and set up the validate list. */ 2334d722e3fbSopenharmony_ci drm_intel_gem_bo_process_reloc2(bo); 2335d722e3fbSopenharmony_ci 2336d722e3fbSopenharmony_ci /* Add the batch buffer to the validation list. There are no relocations 2337d722e3fbSopenharmony_ci * pointing to it. 2338d722e3fbSopenharmony_ci */ 2339d722e3fbSopenharmony_ci drm_intel_add_validate_buffer2(bo, 0); 2340d722e3fbSopenharmony_ci 2341d722e3fbSopenharmony_ci memclear(execbuf); 2342d722e3fbSopenharmony_ci execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec2_objects; 2343d722e3fbSopenharmony_ci execbuf.buffer_count = bufmgr_gem->exec_count; 2344d722e3fbSopenharmony_ci execbuf.batch_start_offset = 0; 2345d722e3fbSopenharmony_ci execbuf.batch_len = used; 2346d722e3fbSopenharmony_ci execbuf.cliprects_ptr = (uintptr_t)cliprects; 2347d722e3fbSopenharmony_ci execbuf.num_cliprects = num_cliprects; 2348d722e3fbSopenharmony_ci execbuf.DR1 = 0; 2349d722e3fbSopenharmony_ci execbuf.DR4 = DR4; 2350d722e3fbSopenharmony_ci execbuf.flags = flags; 2351d722e3fbSopenharmony_ci if (ctx == NULL) 2352d722e3fbSopenharmony_ci i915_execbuffer2_set_context_id(execbuf, 0); 2353d722e3fbSopenharmony_ci else 2354d722e3fbSopenharmony_ci i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id); 2355d722e3fbSopenharmony_ci execbuf.rsvd2 = 0; 2356d722e3fbSopenharmony_ci if (in_fence != -1) { 2357d722e3fbSopenharmony_ci execbuf.rsvd2 = in_fence; 2358d722e3fbSopenharmony_ci execbuf.flags |= I915_EXEC_FENCE_IN; 2359d722e3fbSopenharmony_ci } 2360d722e3fbSopenharmony_ci if (out_fence != NULL) { 2361d722e3fbSopenharmony_ci *out_fence = -1; 2362d722e3fbSopenharmony_ci execbuf.flags |= I915_EXEC_FENCE_OUT; 2363d722e3fbSopenharmony_ci } 2364d722e3fbSopenharmony_ci 2365d722e3fbSopenharmony_ci if (bufmgr_gem->no_exec) 2366d722e3fbSopenharmony_ci goto skip_execution; 2367d722e3fbSopenharmony_ci 2368d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 2369d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_EXECBUFFER2_WR, 2370d722e3fbSopenharmony_ci &execbuf); 2371d722e3fbSopenharmony_ci if (ret != 0) { 2372d722e3fbSopenharmony_ci ret = -errno; 2373d722e3fbSopenharmony_ci if (ret == -ENOSPC) { 2374d722e3fbSopenharmony_ci DBG("Execbuffer fails to pin. " 2375d722e3fbSopenharmony_ci "Estimate: %u. Actual: %u. Available: %u\n", 2376d722e3fbSopenharmony_ci drm_intel_gem_estimate_batch_space(bufmgr_gem->exec_bos, 2377d722e3fbSopenharmony_ci bufmgr_gem->exec_count), 2378d722e3fbSopenharmony_ci drm_intel_gem_compute_batch_space(bufmgr_gem->exec_bos, 2379d722e3fbSopenharmony_ci bufmgr_gem->exec_count), 2380d722e3fbSopenharmony_ci (unsigned int) bufmgr_gem->gtt_size); 2381d722e3fbSopenharmony_ci } 2382d722e3fbSopenharmony_ci } 2383d722e3fbSopenharmony_ci drm_intel_update_buffer_offsets2(bufmgr_gem); 2384d722e3fbSopenharmony_ci 2385d722e3fbSopenharmony_ci if (ret == 0 && out_fence != NULL) 2386d722e3fbSopenharmony_ci *out_fence = execbuf.rsvd2 >> 32; 2387d722e3fbSopenharmony_ci 2388d722e3fbSopenharmony_ciskip_execution: 2389d722e3fbSopenharmony_ci if (bufmgr_gem->bufmgr.debug) 2390d722e3fbSopenharmony_ci drm_intel_gem_dump_validation_list(bufmgr_gem); 2391d722e3fbSopenharmony_ci 2392d722e3fbSopenharmony_ci for (i = 0; i < bufmgr_gem->exec_count; i++) { 2393d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = to_bo_gem(bufmgr_gem->exec_bos[i]); 2394d722e3fbSopenharmony_ci 2395d722e3fbSopenharmony_ci bo_gem->idle = false; 2396d722e3fbSopenharmony_ci 2397d722e3fbSopenharmony_ci /* Disconnect the buffer from the validate list */ 2398d722e3fbSopenharmony_ci bo_gem->validate_index = -1; 2399d722e3fbSopenharmony_ci bufmgr_gem->exec_bos[i] = NULL; 2400d722e3fbSopenharmony_ci } 2401d722e3fbSopenharmony_ci bufmgr_gem->exec_count = 0; 2402d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 2403d722e3fbSopenharmony_ci 2404d722e3fbSopenharmony_ci return ret; 2405d722e3fbSopenharmony_ci} 2406d722e3fbSopenharmony_ci 2407d722e3fbSopenharmony_cistatic int 2408d722e3fbSopenharmony_cidrm_intel_gem_bo_exec2(drm_intel_bo *bo, int used, 2409d722e3fbSopenharmony_ci drm_clip_rect_t *cliprects, int num_cliprects, 2410d722e3fbSopenharmony_ci int DR4) 2411d722e3fbSopenharmony_ci{ 2412d722e3fbSopenharmony_ci return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4, 2413d722e3fbSopenharmony_ci -1, NULL, I915_EXEC_RENDER); 2414d722e3fbSopenharmony_ci} 2415d722e3fbSopenharmony_ci 2416d722e3fbSopenharmony_cistatic int 2417d722e3fbSopenharmony_cidrm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used, 2418d722e3fbSopenharmony_ci drm_clip_rect_t *cliprects, int num_cliprects, int DR4, 2419d722e3fbSopenharmony_ci unsigned int flags) 2420d722e3fbSopenharmony_ci{ 2421d722e3fbSopenharmony_ci return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4, 2422d722e3fbSopenharmony_ci -1, NULL, flags); 2423d722e3fbSopenharmony_ci} 2424d722e3fbSopenharmony_ci 2425d722e3fbSopenharmony_cidrm_public int 2426d722e3fbSopenharmony_cidrm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx, 2427d722e3fbSopenharmony_ci int used, unsigned int flags) 2428d722e3fbSopenharmony_ci{ 2429d722e3fbSopenharmony_ci return do_exec2(bo, used, ctx, NULL, 0, 0, -1, NULL, flags); 2430d722e3fbSopenharmony_ci} 2431d722e3fbSopenharmony_ci 2432d722e3fbSopenharmony_cidrm_public int 2433d722e3fbSopenharmony_cidrm_intel_gem_bo_fence_exec(drm_intel_bo *bo, 2434d722e3fbSopenharmony_ci drm_intel_context *ctx, 2435d722e3fbSopenharmony_ci int used, 2436d722e3fbSopenharmony_ci int in_fence, 2437d722e3fbSopenharmony_ci int *out_fence, 2438d722e3fbSopenharmony_ci unsigned int flags) 2439d722e3fbSopenharmony_ci{ 2440d722e3fbSopenharmony_ci return do_exec2(bo, used, ctx, NULL, 0, 0, in_fence, out_fence, flags); 2441d722e3fbSopenharmony_ci} 2442d722e3fbSopenharmony_ci 2443d722e3fbSopenharmony_cistatic int 2444d722e3fbSopenharmony_cidrm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment) 2445d722e3fbSopenharmony_ci{ 2446d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2447d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2448d722e3fbSopenharmony_ci struct drm_i915_gem_pin pin; 2449d722e3fbSopenharmony_ci int ret; 2450d722e3fbSopenharmony_ci 2451d722e3fbSopenharmony_ci memclear(pin); 2452d722e3fbSopenharmony_ci pin.handle = bo_gem->gem_handle; 2453d722e3fbSopenharmony_ci pin.alignment = alignment; 2454d722e3fbSopenharmony_ci 2455d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 2456d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_PIN, 2457d722e3fbSopenharmony_ci &pin); 2458d722e3fbSopenharmony_ci if (ret != 0) 2459d722e3fbSopenharmony_ci return -errno; 2460d722e3fbSopenharmony_ci 2461d722e3fbSopenharmony_ci bo->offset64 = pin.offset; 2462d722e3fbSopenharmony_ci bo->offset = pin.offset; 2463d722e3fbSopenharmony_ci return 0; 2464d722e3fbSopenharmony_ci} 2465d722e3fbSopenharmony_ci 2466d722e3fbSopenharmony_cistatic int 2467d722e3fbSopenharmony_cidrm_intel_gem_bo_unpin(drm_intel_bo *bo) 2468d722e3fbSopenharmony_ci{ 2469d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2470d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2471d722e3fbSopenharmony_ci struct drm_i915_gem_unpin unpin; 2472d722e3fbSopenharmony_ci int ret; 2473d722e3fbSopenharmony_ci 2474d722e3fbSopenharmony_ci memclear(unpin); 2475d722e3fbSopenharmony_ci unpin.handle = bo_gem->gem_handle; 2476d722e3fbSopenharmony_ci 2477d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin); 2478d722e3fbSopenharmony_ci if (ret != 0) 2479d722e3fbSopenharmony_ci return -errno; 2480d722e3fbSopenharmony_ci 2481d722e3fbSopenharmony_ci return 0; 2482d722e3fbSopenharmony_ci} 2483d722e3fbSopenharmony_ci 2484d722e3fbSopenharmony_cistatic int 2485d722e3fbSopenharmony_cidrm_intel_gem_bo_set_tiling_internal(drm_intel_bo *bo, 2486d722e3fbSopenharmony_ci uint32_t tiling_mode, 2487d722e3fbSopenharmony_ci uint32_t stride) 2488d722e3fbSopenharmony_ci{ 2489d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2490d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2491d722e3fbSopenharmony_ci struct drm_i915_gem_set_tiling set_tiling; 2492d722e3fbSopenharmony_ci int ret; 2493d722e3fbSopenharmony_ci 2494d722e3fbSopenharmony_ci if (bo_gem->global_name == 0 && 2495d722e3fbSopenharmony_ci tiling_mode == bo_gem->tiling_mode && 2496d722e3fbSopenharmony_ci stride == bo_gem->stride) 2497d722e3fbSopenharmony_ci return 0; 2498d722e3fbSopenharmony_ci 2499d722e3fbSopenharmony_ci memset(&set_tiling, 0, sizeof(set_tiling)); 2500d722e3fbSopenharmony_ci do { 2501d722e3fbSopenharmony_ci /* set_tiling is slightly broken and overwrites the 2502d722e3fbSopenharmony_ci * input on the error path, so we have to open code 2503d722e3fbSopenharmony_ci * rmIoctl. 2504d722e3fbSopenharmony_ci */ 2505d722e3fbSopenharmony_ci set_tiling.handle = bo_gem->gem_handle; 2506d722e3fbSopenharmony_ci set_tiling.tiling_mode = tiling_mode; 2507d722e3fbSopenharmony_ci set_tiling.stride = stride; 2508d722e3fbSopenharmony_ci 2509d722e3fbSopenharmony_ci ret = ioctl(bufmgr_gem->fd, 2510d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_SET_TILING, 2511d722e3fbSopenharmony_ci &set_tiling); 2512d722e3fbSopenharmony_ci } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 2513d722e3fbSopenharmony_ci if (ret == -1) 2514d722e3fbSopenharmony_ci return -errno; 2515d722e3fbSopenharmony_ci 2516d722e3fbSopenharmony_ci bo_gem->tiling_mode = set_tiling.tiling_mode; 2517d722e3fbSopenharmony_ci bo_gem->swizzle_mode = set_tiling.swizzle_mode; 2518d722e3fbSopenharmony_ci bo_gem->stride = set_tiling.stride; 2519d722e3fbSopenharmony_ci return 0; 2520d722e3fbSopenharmony_ci} 2521d722e3fbSopenharmony_ci 2522d722e3fbSopenharmony_cistatic int 2523d722e3fbSopenharmony_cidrm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, 2524d722e3fbSopenharmony_ci uint32_t stride) 2525d722e3fbSopenharmony_ci{ 2526d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2527d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2528d722e3fbSopenharmony_ci int ret; 2529d722e3fbSopenharmony_ci 2530d722e3fbSopenharmony_ci /* Tiling with userptr surfaces is not supported 2531d722e3fbSopenharmony_ci * on all hardware so refuse it for time being. 2532d722e3fbSopenharmony_ci */ 2533d722e3fbSopenharmony_ci if (bo_gem->is_userptr) 2534d722e3fbSopenharmony_ci return -EINVAL; 2535d722e3fbSopenharmony_ci 2536d722e3fbSopenharmony_ci /* Linear buffers have no stride. By ensuring that we only ever use 2537d722e3fbSopenharmony_ci * stride 0 with linear buffers, we simplify our code. 2538d722e3fbSopenharmony_ci */ 2539d722e3fbSopenharmony_ci if (*tiling_mode == I915_TILING_NONE) 2540d722e3fbSopenharmony_ci stride = 0; 2541d722e3fbSopenharmony_ci 2542d722e3fbSopenharmony_ci ret = drm_intel_gem_bo_set_tiling_internal(bo, *tiling_mode, stride); 2543d722e3fbSopenharmony_ci if (ret == 0) 2544d722e3fbSopenharmony_ci drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 2545d722e3fbSopenharmony_ci 2546d722e3fbSopenharmony_ci *tiling_mode = bo_gem->tiling_mode; 2547d722e3fbSopenharmony_ci return ret; 2548d722e3fbSopenharmony_ci} 2549d722e3fbSopenharmony_ci 2550d722e3fbSopenharmony_cistatic int 2551d722e3fbSopenharmony_cidrm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode, 2552d722e3fbSopenharmony_ci uint32_t * swizzle_mode) 2553d722e3fbSopenharmony_ci{ 2554d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2555d722e3fbSopenharmony_ci 2556d722e3fbSopenharmony_ci *tiling_mode = bo_gem->tiling_mode; 2557d722e3fbSopenharmony_ci *swizzle_mode = bo_gem->swizzle_mode; 2558d722e3fbSopenharmony_ci return 0; 2559d722e3fbSopenharmony_ci} 2560d722e3fbSopenharmony_ci 2561d722e3fbSopenharmony_cistatic int 2562d722e3fbSopenharmony_cidrm_intel_gem_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset) 2563d722e3fbSopenharmony_ci{ 2564d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2565d722e3fbSopenharmony_ci 2566d722e3fbSopenharmony_ci bo->offset64 = offset; 2567d722e3fbSopenharmony_ci bo->offset = offset; 2568d722e3fbSopenharmony_ci bo_gem->kflags |= EXEC_OBJECT_PINNED; 2569d722e3fbSopenharmony_ci 2570d722e3fbSopenharmony_ci return 0; 2571d722e3fbSopenharmony_ci} 2572d722e3fbSopenharmony_ci 2573d722e3fbSopenharmony_cidrm_public drm_intel_bo * 2574d722e3fbSopenharmony_cidrm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size) 2575d722e3fbSopenharmony_ci{ 2576d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 2577d722e3fbSopenharmony_ci int ret; 2578d722e3fbSopenharmony_ci uint32_t handle; 2579d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem; 2580d722e3fbSopenharmony_ci 2581d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 2582d722e3fbSopenharmony_ci ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle); 2583d722e3fbSopenharmony_ci if (ret) { 2584d722e3fbSopenharmony_ci DBG("create_from_prime: failed to obtain handle from fd: %s\n", strerror(errno)); 2585d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 2586d722e3fbSopenharmony_ci return NULL; 2587d722e3fbSopenharmony_ci } 2588d722e3fbSopenharmony_ci 2589d722e3fbSopenharmony_ci /* 2590d722e3fbSopenharmony_ci * See if the kernel has already returned this buffer to us. Just as 2591d722e3fbSopenharmony_ci * for named buffers, we must not create two bo's pointing at the same 2592d722e3fbSopenharmony_ci * kernel object 2593d722e3fbSopenharmony_ci */ 2594d722e3fbSopenharmony_ci HASH_FIND(handle_hh, bufmgr_gem->handle_table, 2595d722e3fbSopenharmony_ci &handle, sizeof(handle), bo_gem); 2596d722e3fbSopenharmony_ci if (bo_gem) { 2597d722e3fbSopenharmony_ci drm_intel_gem_bo_reference(&bo_gem->bo); 2598d722e3fbSopenharmony_ci goto out; 2599d722e3fbSopenharmony_ci } 2600d722e3fbSopenharmony_ci 2601d722e3fbSopenharmony_ci bo_gem = calloc(1, sizeof(*bo_gem)); 2602d722e3fbSopenharmony_ci if (!bo_gem) 2603d722e3fbSopenharmony_ci goto out; 2604d722e3fbSopenharmony_ci 2605d722e3fbSopenharmony_ci atomic_set(&bo_gem->refcount, 1); 2606d722e3fbSopenharmony_ci DRMINITLISTHEAD(&bo_gem->vma_list); 2607d722e3fbSopenharmony_ci 2608d722e3fbSopenharmony_ci /* Determine size of bo. The fd-to-handle ioctl really should 2609d722e3fbSopenharmony_ci * return the size, but it doesn't. If we have kernel 3.12 or 2610d722e3fbSopenharmony_ci * later, we can lseek on the prime fd to get the size. Older 2611d722e3fbSopenharmony_ci * kernels will just fail, in which case we fall back to the 2612d722e3fbSopenharmony_ci * provided (estimated or guess size). */ 2613d722e3fbSopenharmony_ci ret = lseek(prime_fd, 0, SEEK_END); 2614d722e3fbSopenharmony_ci if (ret != -1) 2615d722e3fbSopenharmony_ci bo_gem->bo.size = ret; 2616d722e3fbSopenharmony_ci else 2617d722e3fbSopenharmony_ci bo_gem->bo.size = size; 2618d722e3fbSopenharmony_ci 2619d722e3fbSopenharmony_ci bo_gem->bo.handle = handle; 2620d722e3fbSopenharmony_ci bo_gem->bo.bufmgr = bufmgr; 2621d722e3fbSopenharmony_ci 2622d722e3fbSopenharmony_ci bo_gem->gem_handle = handle; 2623d722e3fbSopenharmony_ci HASH_ADD(handle_hh, bufmgr_gem->handle_table, 2624d722e3fbSopenharmony_ci gem_handle, sizeof(bo_gem->gem_handle), bo_gem); 2625d722e3fbSopenharmony_ci 2626d722e3fbSopenharmony_ci bo_gem->name = "prime"; 2627d722e3fbSopenharmony_ci bo_gem->validate_index = -1; 2628d722e3fbSopenharmony_ci bo_gem->reloc_tree_fences = 0; 2629d722e3fbSopenharmony_ci bo_gem->used_as_reloc_target = false; 2630d722e3fbSopenharmony_ci bo_gem->has_error = false; 2631d722e3fbSopenharmony_ci bo_gem->reusable = false; 2632d722e3fbSopenharmony_ci 2633d722e3fbSopenharmony_ci ret = get_tiling_mode(bufmgr_gem, handle, 2634d722e3fbSopenharmony_ci &bo_gem->tiling_mode, &bo_gem->swizzle_mode); 2635d722e3fbSopenharmony_ci if (ret) 2636d722e3fbSopenharmony_ci goto err; 2637d722e3fbSopenharmony_ci 2638d722e3fbSopenharmony_ci /* XXX stride is unknown */ 2639d722e3fbSopenharmony_ci drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem, 0); 2640d722e3fbSopenharmony_ci 2641d722e3fbSopenharmony_ciout: 2642d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 2643d722e3fbSopenharmony_ci return &bo_gem->bo; 2644d722e3fbSopenharmony_ci 2645d722e3fbSopenharmony_cierr: 2646d722e3fbSopenharmony_ci drm_intel_gem_bo_free(&bo_gem->bo); 2647d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 2648d722e3fbSopenharmony_ci return NULL; 2649d722e3fbSopenharmony_ci} 2650d722e3fbSopenharmony_ci 2651d722e3fbSopenharmony_cidrm_public int 2652d722e3fbSopenharmony_cidrm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd) 2653d722e3fbSopenharmony_ci{ 2654d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2655d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2656d722e3fbSopenharmony_ci 2657d722e3fbSopenharmony_ci if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle, 2658d722e3fbSopenharmony_ci DRM_CLOEXEC | DRM_RDWR, prime_fd) != 0) 2659d722e3fbSopenharmony_ci return -errno; 2660d722e3fbSopenharmony_ci 2661d722e3fbSopenharmony_ci bo_gem->reusable = false; 2662d722e3fbSopenharmony_ci 2663d722e3fbSopenharmony_ci return 0; 2664d722e3fbSopenharmony_ci} 2665d722e3fbSopenharmony_ci 2666d722e3fbSopenharmony_cistatic int 2667d722e3fbSopenharmony_cidrm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name) 2668d722e3fbSopenharmony_ci{ 2669d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 2670d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2671d722e3fbSopenharmony_ci 2672d722e3fbSopenharmony_ci if (!bo_gem->global_name) { 2673d722e3fbSopenharmony_ci struct drm_gem_flink flink; 2674d722e3fbSopenharmony_ci 2675d722e3fbSopenharmony_ci memclear(flink); 2676d722e3fbSopenharmony_ci flink.handle = bo_gem->gem_handle; 2677d722e3fbSopenharmony_ci if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink)) 2678d722e3fbSopenharmony_ci return -errno; 2679d722e3fbSopenharmony_ci 2680d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 2681d722e3fbSopenharmony_ci if (!bo_gem->global_name) { 2682d722e3fbSopenharmony_ci bo_gem->global_name = flink.name; 2683d722e3fbSopenharmony_ci bo_gem->reusable = false; 2684d722e3fbSopenharmony_ci 2685d722e3fbSopenharmony_ci HASH_ADD(name_hh, bufmgr_gem->name_table, 2686d722e3fbSopenharmony_ci global_name, sizeof(bo_gem->global_name), 2687d722e3fbSopenharmony_ci bo_gem); 2688d722e3fbSopenharmony_ci } 2689d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 2690d722e3fbSopenharmony_ci } 2691d722e3fbSopenharmony_ci 2692d722e3fbSopenharmony_ci *name = bo_gem->global_name; 2693d722e3fbSopenharmony_ci return 0; 2694d722e3fbSopenharmony_ci} 2695d722e3fbSopenharmony_ci 2696d722e3fbSopenharmony_ci/** 2697d722e3fbSopenharmony_ci * Enables unlimited caching of buffer objects for reuse. 2698d722e3fbSopenharmony_ci * 2699d722e3fbSopenharmony_ci * This is potentially very memory expensive, as the cache at each bucket 2700d722e3fbSopenharmony_ci * size is only bounded by how many buffers of that size we've managed to have 2701d722e3fbSopenharmony_ci * in flight at once. 2702d722e3fbSopenharmony_ci */ 2703d722e3fbSopenharmony_cidrm_public void 2704d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr) 2705d722e3fbSopenharmony_ci{ 2706d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 2707d722e3fbSopenharmony_ci 2708d722e3fbSopenharmony_ci bufmgr_gem->bo_reuse = true; 2709d722e3fbSopenharmony_ci} 2710d722e3fbSopenharmony_ci 2711d722e3fbSopenharmony_ci/** 2712d722e3fbSopenharmony_ci * Disables implicit synchronisation before executing the bo 2713d722e3fbSopenharmony_ci * 2714d722e3fbSopenharmony_ci * This will cause rendering corruption unless you correctly manage explicit 2715d722e3fbSopenharmony_ci * fences for all rendering involving this buffer - including use by others. 2716d722e3fbSopenharmony_ci * Disabling the implicit serialisation is only required if that serialisation 2717d722e3fbSopenharmony_ci * is too coarse (for example, you have split the buffer into many 2718d722e3fbSopenharmony_ci * non-overlapping regions and are sharing the whole buffer between concurrent 2719d722e3fbSopenharmony_ci * independent command streams). 2720d722e3fbSopenharmony_ci * 2721d722e3fbSopenharmony_ci * Note the kernel must advertise support via I915_PARAM_HAS_EXEC_ASYNC, 2722d722e3fbSopenharmony_ci * which can be checked using drm_intel_bufmgr_can_disable_implicit_sync, 2723d722e3fbSopenharmony_ci * or subsequent execbufs involving the bo will generate EINVAL. 2724d722e3fbSopenharmony_ci */ 2725d722e3fbSopenharmony_cidrm_public void 2726d722e3fbSopenharmony_cidrm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo) 2727d722e3fbSopenharmony_ci{ 2728d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2729d722e3fbSopenharmony_ci 2730d722e3fbSopenharmony_ci bo_gem->kflags |= EXEC_OBJECT_ASYNC; 2731d722e3fbSopenharmony_ci} 2732d722e3fbSopenharmony_ci 2733d722e3fbSopenharmony_ci/** 2734d722e3fbSopenharmony_ci * Enables implicit synchronisation before executing the bo 2735d722e3fbSopenharmony_ci * 2736d722e3fbSopenharmony_ci * This is the default behaviour of the kernel, to wait upon prior writes 2737d722e3fbSopenharmony_ci * completing on the object before rendering with it, or to wait for prior 2738d722e3fbSopenharmony_ci * reads to complete before writing into the object. 2739d722e3fbSopenharmony_ci * drm_intel_gem_bo_disable_implicit_sync() can stop this behaviour, telling 2740d722e3fbSopenharmony_ci * the kernel never to insert a stall before using the object. Then this 2741d722e3fbSopenharmony_ci * function can be used to restore the implicit sync before subsequent 2742d722e3fbSopenharmony_ci * rendering. 2743d722e3fbSopenharmony_ci */ 2744d722e3fbSopenharmony_cidrm_public void 2745d722e3fbSopenharmony_cidrm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo) 2746d722e3fbSopenharmony_ci{ 2747d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2748d722e3fbSopenharmony_ci 2749d722e3fbSopenharmony_ci bo_gem->kflags &= ~EXEC_OBJECT_ASYNC; 2750d722e3fbSopenharmony_ci} 2751d722e3fbSopenharmony_ci 2752d722e3fbSopenharmony_ci/** 2753d722e3fbSopenharmony_ci * Query whether the kernel supports disabling of its implicit synchronisation 2754d722e3fbSopenharmony_ci * before execbuf. See drm_intel_gem_bo_disable_implicit_sync() 2755d722e3fbSopenharmony_ci */ 2756d722e3fbSopenharmony_cidrm_public int 2757d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr) 2758d722e3fbSopenharmony_ci{ 2759d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr; 2760d722e3fbSopenharmony_ci 2761d722e3fbSopenharmony_ci return bufmgr_gem->has_exec_async; 2762d722e3fbSopenharmony_ci} 2763d722e3fbSopenharmony_ci 2764d722e3fbSopenharmony_ci/** 2765d722e3fbSopenharmony_ci * Enable use of fenced reloc type. 2766d722e3fbSopenharmony_ci * 2767d722e3fbSopenharmony_ci * New code should enable this to avoid unnecessary fence register 2768d722e3fbSopenharmony_ci * allocation. If this option is not enabled, all relocs will have fence 2769d722e3fbSopenharmony_ci * register allocated. 2770d722e3fbSopenharmony_ci */ 2771d722e3fbSopenharmony_cidrm_public void 2772d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr) 2773d722e3fbSopenharmony_ci{ 2774d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 2775d722e3fbSopenharmony_ci bufmgr_gem->fenced_relocs = true; 2776d722e3fbSopenharmony_ci} 2777d722e3fbSopenharmony_ci 2778d722e3fbSopenharmony_ci/** 2779d722e3fbSopenharmony_ci * Return the additional aperture space required by the tree of buffer objects 2780d722e3fbSopenharmony_ci * rooted at bo. 2781d722e3fbSopenharmony_ci */ 2782d722e3fbSopenharmony_cistatic int 2783d722e3fbSopenharmony_cidrm_intel_gem_bo_get_aperture_space(drm_intel_bo *bo) 2784d722e3fbSopenharmony_ci{ 2785d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2786d722e3fbSopenharmony_ci int i; 2787d722e3fbSopenharmony_ci int total = 0; 2788d722e3fbSopenharmony_ci 2789d722e3fbSopenharmony_ci if (bo == NULL || bo_gem->included_in_check_aperture) 2790d722e3fbSopenharmony_ci return 0; 2791d722e3fbSopenharmony_ci 2792d722e3fbSopenharmony_ci total += bo->size; 2793d722e3fbSopenharmony_ci bo_gem->included_in_check_aperture = true; 2794d722e3fbSopenharmony_ci 2795d722e3fbSopenharmony_ci for (i = 0; i < bo_gem->reloc_count; i++) 2796d722e3fbSopenharmony_ci total += 2797d722e3fbSopenharmony_ci drm_intel_gem_bo_get_aperture_space(bo_gem-> 2798d722e3fbSopenharmony_ci reloc_target_info[i].bo); 2799d722e3fbSopenharmony_ci 2800d722e3fbSopenharmony_ci return total; 2801d722e3fbSopenharmony_ci} 2802d722e3fbSopenharmony_ci 2803d722e3fbSopenharmony_ci/** 2804d722e3fbSopenharmony_ci * Count the number of buffers in this list that need a fence reg 2805d722e3fbSopenharmony_ci * 2806d722e3fbSopenharmony_ci * If the count is greater than the number of available regs, we'll have 2807d722e3fbSopenharmony_ci * to ask the caller to resubmit a batch with fewer tiled buffers. 2808d722e3fbSopenharmony_ci * 2809d722e3fbSopenharmony_ci * This function over-counts if the same buffer is used multiple times. 2810d722e3fbSopenharmony_ci */ 2811d722e3fbSopenharmony_cistatic unsigned int 2812d722e3fbSopenharmony_cidrm_intel_gem_total_fences(drm_intel_bo ** bo_array, int count) 2813d722e3fbSopenharmony_ci{ 2814d722e3fbSopenharmony_ci int i; 2815d722e3fbSopenharmony_ci unsigned int total = 0; 2816d722e3fbSopenharmony_ci 2817d722e3fbSopenharmony_ci for (i = 0; i < count; i++) { 2818d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i]; 2819d722e3fbSopenharmony_ci 2820d722e3fbSopenharmony_ci if (bo_gem == NULL) 2821d722e3fbSopenharmony_ci continue; 2822d722e3fbSopenharmony_ci 2823d722e3fbSopenharmony_ci total += bo_gem->reloc_tree_fences; 2824d722e3fbSopenharmony_ci } 2825d722e3fbSopenharmony_ci return total; 2826d722e3fbSopenharmony_ci} 2827d722e3fbSopenharmony_ci 2828d722e3fbSopenharmony_ci/** 2829d722e3fbSopenharmony_ci * Clear the flag set by drm_intel_gem_bo_get_aperture_space() so we're ready 2830d722e3fbSopenharmony_ci * for the next drm_intel_bufmgr_check_aperture_space() call. 2831d722e3fbSopenharmony_ci */ 2832d722e3fbSopenharmony_cistatic void 2833d722e3fbSopenharmony_cidrm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo) 2834d722e3fbSopenharmony_ci{ 2835d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2836d722e3fbSopenharmony_ci int i; 2837d722e3fbSopenharmony_ci 2838d722e3fbSopenharmony_ci if (bo == NULL || !bo_gem->included_in_check_aperture) 2839d722e3fbSopenharmony_ci return; 2840d722e3fbSopenharmony_ci 2841d722e3fbSopenharmony_ci bo_gem->included_in_check_aperture = false; 2842d722e3fbSopenharmony_ci 2843d722e3fbSopenharmony_ci for (i = 0; i < bo_gem->reloc_count; i++) 2844d722e3fbSopenharmony_ci drm_intel_gem_bo_clear_aperture_space_flag(bo_gem-> 2845d722e3fbSopenharmony_ci reloc_target_info[i].bo); 2846d722e3fbSopenharmony_ci} 2847d722e3fbSopenharmony_ci 2848d722e3fbSopenharmony_ci/** 2849d722e3fbSopenharmony_ci * Return a conservative estimate for the amount of aperture required 2850d722e3fbSopenharmony_ci * for a collection of buffers. This may double-count some buffers. 2851d722e3fbSopenharmony_ci */ 2852d722e3fbSopenharmony_cistatic unsigned int 2853d722e3fbSopenharmony_cidrm_intel_gem_estimate_batch_space(drm_intel_bo **bo_array, int count) 2854d722e3fbSopenharmony_ci{ 2855d722e3fbSopenharmony_ci int i; 2856d722e3fbSopenharmony_ci unsigned int total = 0; 2857d722e3fbSopenharmony_ci 2858d722e3fbSopenharmony_ci for (i = 0; i < count; i++) { 2859d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo_array[i]; 2860d722e3fbSopenharmony_ci if (bo_gem != NULL) 2861d722e3fbSopenharmony_ci total += bo_gem->reloc_tree_size; 2862d722e3fbSopenharmony_ci } 2863d722e3fbSopenharmony_ci return total; 2864d722e3fbSopenharmony_ci} 2865d722e3fbSopenharmony_ci 2866d722e3fbSopenharmony_ci/** 2867d722e3fbSopenharmony_ci * Return the amount of aperture needed for a collection of buffers. 2868d722e3fbSopenharmony_ci * This avoids double counting any buffers, at the cost of looking 2869d722e3fbSopenharmony_ci * at every buffer in the set. 2870d722e3fbSopenharmony_ci */ 2871d722e3fbSopenharmony_cistatic unsigned int 2872d722e3fbSopenharmony_cidrm_intel_gem_compute_batch_space(drm_intel_bo **bo_array, int count) 2873d722e3fbSopenharmony_ci{ 2874d722e3fbSopenharmony_ci int i; 2875d722e3fbSopenharmony_ci unsigned int total = 0; 2876d722e3fbSopenharmony_ci 2877d722e3fbSopenharmony_ci for (i = 0; i < count; i++) { 2878d722e3fbSopenharmony_ci total += drm_intel_gem_bo_get_aperture_space(bo_array[i]); 2879d722e3fbSopenharmony_ci /* For the first buffer object in the array, we get an 2880d722e3fbSopenharmony_ci * accurate count back for its reloc_tree size (since nothing 2881d722e3fbSopenharmony_ci * had been flagged as being counted yet). We can save that 2882d722e3fbSopenharmony_ci * value out as a more conservative reloc_tree_size that 2883d722e3fbSopenharmony_ci * avoids double-counting target buffers. Since the first 2884d722e3fbSopenharmony_ci * buffer happens to usually be the batch buffer in our 2885d722e3fbSopenharmony_ci * callers, this can pull us back from doing the tree 2886d722e3fbSopenharmony_ci * walk on every new batch emit. 2887d722e3fbSopenharmony_ci */ 2888d722e3fbSopenharmony_ci if (i == 0) { 2889d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = 2890d722e3fbSopenharmony_ci (drm_intel_bo_gem *) bo_array[i]; 2891d722e3fbSopenharmony_ci bo_gem->reloc_tree_size = total; 2892d722e3fbSopenharmony_ci } 2893d722e3fbSopenharmony_ci } 2894d722e3fbSopenharmony_ci 2895d722e3fbSopenharmony_ci for (i = 0; i < count; i++) 2896d722e3fbSopenharmony_ci drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]); 2897d722e3fbSopenharmony_ci return total; 2898d722e3fbSopenharmony_ci} 2899d722e3fbSopenharmony_ci 2900d722e3fbSopenharmony_ci/** 2901d722e3fbSopenharmony_ci * Return -1 if the batchbuffer should be flushed before attempting to 2902d722e3fbSopenharmony_ci * emit rendering referencing the buffers pointed to by bo_array. 2903d722e3fbSopenharmony_ci * 2904d722e3fbSopenharmony_ci * This is required because if we try to emit a batchbuffer with relocations 2905d722e3fbSopenharmony_ci * to a tree of buffers that won't simultaneously fit in the aperture, 2906d722e3fbSopenharmony_ci * the rendering will return an error at a point where the software is not 2907d722e3fbSopenharmony_ci * prepared to recover from it. 2908d722e3fbSopenharmony_ci * 2909d722e3fbSopenharmony_ci * However, we also want to emit the batchbuffer significantly before we reach 2910d722e3fbSopenharmony_ci * the limit, as a series of batchbuffers each of which references buffers 2911d722e3fbSopenharmony_ci * covering almost all of the aperture means that at each emit we end up 2912d722e3fbSopenharmony_ci * waiting to evict a buffer from the last rendering, and we get synchronous 2913d722e3fbSopenharmony_ci * performance. By emitting smaller batchbuffers, we eat some CPU overhead to 2914d722e3fbSopenharmony_ci * get better parallelism. 2915d722e3fbSopenharmony_ci */ 2916d722e3fbSopenharmony_cistatic int 2917d722e3fbSopenharmony_cidrm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count) 2918d722e3fbSopenharmony_ci{ 2919d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = 2920d722e3fbSopenharmony_ci (drm_intel_bufmgr_gem *) bo_array[0]->bufmgr; 2921d722e3fbSopenharmony_ci unsigned int total = 0; 2922d722e3fbSopenharmony_ci unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4; 2923d722e3fbSopenharmony_ci int total_fences; 2924d722e3fbSopenharmony_ci 2925d722e3fbSopenharmony_ci /* Check for fence reg constraints if necessary */ 2926d722e3fbSopenharmony_ci if (bufmgr_gem->available_fences) { 2927d722e3fbSopenharmony_ci total_fences = drm_intel_gem_total_fences(bo_array, count); 2928d722e3fbSopenharmony_ci if (total_fences > bufmgr_gem->available_fences) 2929d722e3fbSopenharmony_ci return -ENOSPC; 2930d722e3fbSopenharmony_ci } 2931d722e3fbSopenharmony_ci 2932d722e3fbSopenharmony_ci total = drm_intel_gem_estimate_batch_space(bo_array, count); 2933d722e3fbSopenharmony_ci 2934d722e3fbSopenharmony_ci if (total > threshold) 2935d722e3fbSopenharmony_ci total = drm_intel_gem_compute_batch_space(bo_array, count); 2936d722e3fbSopenharmony_ci 2937d722e3fbSopenharmony_ci if (total > threshold) { 2938d722e3fbSopenharmony_ci DBG("check_space: overflowed available aperture, " 2939d722e3fbSopenharmony_ci "%dkb vs %dkb\n", 2940d722e3fbSopenharmony_ci total / 1024, (int)bufmgr_gem->gtt_size / 1024); 2941d722e3fbSopenharmony_ci return -ENOSPC; 2942d722e3fbSopenharmony_ci } else { 2943d722e3fbSopenharmony_ci DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024, 2944d722e3fbSopenharmony_ci (int)bufmgr_gem->gtt_size / 1024); 2945d722e3fbSopenharmony_ci return 0; 2946d722e3fbSopenharmony_ci } 2947d722e3fbSopenharmony_ci} 2948d722e3fbSopenharmony_ci 2949d722e3fbSopenharmony_ci/* 2950d722e3fbSopenharmony_ci * Disable buffer reuse for objects which are shared with the kernel 2951d722e3fbSopenharmony_ci * as scanout buffers 2952d722e3fbSopenharmony_ci */ 2953d722e3fbSopenharmony_cistatic int 2954d722e3fbSopenharmony_cidrm_intel_gem_bo_disable_reuse(drm_intel_bo *bo) 2955d722e3fbSopenharmony_ci{ 2956d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2957d722e3fbSopenharmony_ci 2958d722e3fbSopenharmony_ci bo_gem->reusable = false; 2959d722e3fbSopenharmony_ci return 0; 2960d722e3fbSopenharmony_ci} 2961d722e3fbSopenharmony_ci 2962d722e3fbSopenharmony_cistatic int 2963d722e3fbSopenharmony_cidrm_intel_gem_bo_is_reusable(drm_intel_bo *bo) 2964d722e3fbSopenharmony_ci{ 2965d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2966d722e3fbSopenharmony_ci 2967d722e3fbSopenharmony_ci return bo_gem->reusable; 2968d722e3fbSopenharmony_ci} 2969d722e3fbSopenharmony_ci 2970d722e3fbSopenharmony_cistatic int 2971d722e3fbSopenharmony_ci_drm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo) 2972d722e3fbSopenharmony_ci{ 2973d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 2974d722e3fbSopenharmony_ci int i; 2975d722e3fbSopenharmony_ci 2976d722e3fbSopenharmony_ci for (i = 0; i < bo_gem->reloc_count; i++) { 2977d722e3fbSopenharmony_ci if (bo_gem->reloc_target_info[i].bo == target_bo) 2978d722e3fbSopenharmony_ci return 1; 2979d722e3fbSopenharmony_ci if (bo == bo_gem->reloc_target_info[i].bo) 2980d722e3fbSopenharmony_ci continue; 2981d722e3fbSopenharmony_ci if (_drm_intel_gem_bo_references(bo_gem->reloc_target_info[i].bo, 2982d722e3fbSopenharmony_ci target_bo)) 2983d722e3fbSopenharmony_ci return 1; 2984d722e3fbSopenharmony_ci } 2985d722e3fbSopenharmony_ci 2986d722e3fbSopenharmony_ci for (i = 0; i< bo_gem->softpin_target_count; i++) { 2987d722e3fbSopenharmony_ci if (bo_gem->softpin_target[i] == target_bo) 2988d722e3fbSopenharmony_ci return 1; 2989d722e3fbSopenharmony_ci if (_drm_intel_gem_bo_references(bo_gem->softpin_target[i], target_bo)) 2990d722e3fbSopenharmony_ci return 1; 2991d722e3fbSopenharmony_ci } 2992d722e3fbSopenharmony_ci 2993d722e3fbSopenharmony_ci return 0; 2994d722e3fbSopenharmony_ci} 2995d722e3fbSopenharmony_ci 2996d722e3fbSopenharmony_ci/** Return true if target_bo is referenced by bo's relocation tree. */ 2997d722e3fbSopenharmony_cistatic int 2998d722e3fbSopenharmony_cidrm_intel_gem_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo) 2999d722e3fbSopenharmony_ci{ 3000d722e3fbSopenharmony_ci drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *) target_bo; 3001d722e3fbSopenharmony_ci 3002d722e3fbSopenharmony_ci if (bo == NULL || target_bo == NULL) 3003d722e3fbSopenharmony_ci return 0; 3004d722e3fbSopenharmony_ci if (target_bo_gem->used_as_reloc_target) 3005d722e3fbSopenharmony_ci return _drm_intel_gem_bo_references(bo, target_bo); 3006d722e3fbSopenharmony_ci return 0; 3007d722e3fbSopenharmony_ci} 3008d722e3fbSopenharmony_ci 3009d722e3fbSopenharmony_cistatic void 3010d722e3fbSopenharmony_ciadd_bucket(drm_intel_bufmgr_gem *bufmgr_gem, int size) 3011d722e3fbSopenharmony_ci{ 3012d722e3fbSopenharmony_ci unsigned int i = bufmgr_gem->num_buckets; 3013d722e3fbSopenharmony_ci 3014d722e3fbSopenharmony_ci assert(i < ARRAY_SIZE(bufmgr_gem->cache_bucket)); 3015d722e3fbSopenharmony_ci 3016d722e3fbSopenharmony_ci DRMINITLISTHEAD(&bufmgr_gem->cache_bucket[i].head); 3017d722e3fbSopenharmony_ci bufmgr_gem->cache_bucket[i].size = size; 3018d722e3fbSopenharmony_ci bufmgr_gem->num_buckets++; 3019d722e3fbSopenharmony_ci} 3020d722e3fbSopenharmony_ci 3021d722e3fbSopenharmony_cistatic void 3022d722e3fbSopenharmony_ciinit_cache_buckets(drm_intel_bufmgr_gem *bufmgr_gem) 3023d722e3fbSopenharmony_ci{ 3024d722e3fbSopenharmony_ci unsigned long size, cache_max_size = 64 * 1024 * 1024; 3025d722e3fbSopenharmony_ci 3026d722e3fbSopenharmony_ci /* OK, so power of two buckets was too wasteful of memory. 3027d722e3fbSopenharmony_ci * Give 3 other sizes between each power of two, to hopefully 3028d722e3fbSopenharmony_ci * cover things accurately enough. (The alternative is 3029d722e3fbSopenharmony_ci * probably to just go for exact matching of sizes, and assume 3030d722e3fbSopenharmony_ci * that for things like composited window resize the tiled 3031d722e3fbSopenharmony_ci * width/height alignment and rounding of sizes to pages will 3032d722e3fbSopenharmony_ci * get us useful cache hit rates anyway) 3033d722e3fbSopenharmony_ci */ 3034d722e3fbSopenharmony_ci add_bucket(bufmgr_gem, 4096); 3035d722e3fbSopenharmony_ci add_bucket(bufmgr_gem, 4096 * 2); 3036d722e3fbSopenharmony_ci add_bucket(bufmgr_gem, 4096 * 3); 3037d722e3fbSopenharmony_ci 3038d722e3fbSopenharmony_ci /* Initialize the linked lists for BO reuse cache. */ 3039d722e3fbSopenharmony_ci for (size = 4 * 4096; size <= cache_max_size; size *= 2) { 3040d722e3fbSopenharmony_ci add_bucket(bufmgr_gem, size); 3041d722e3fbSopenharmony_ci 3042d722e3fbSopenharmony_ci add_bucket(bufmgr_gem, size + size * 1 / 4); 3043d722e3fbSopenharmony_ci add_bucket(bufmgr_gem, size + size * 2 / 4); 3044d722e3fbSopenharmony_ci add_bucket(bufmgr_gem, size + size * 3 / 4); 3045d722e3fbSopenharmony_ci } 3046d722e3fbSopenharmony_ci} 3047d722e3fbSopenharmony_ci 3048d722e3fbSopenharmony_cidrm_public void 3049d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit) 3050d722e3fbSopenharmony_ci{ 3051d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 3052d722e3fbSopenharmony_ci 3053d722e3fbSopenharmony_ci bufmgr_gem->vma_max = limit; 3054d722e3fbSopenharmony_ci 3055d722e3fbSopenharmony_ci drm_intel_gem_bo_purge_vma_cache(bufmgr_gem); 3056d722e3fbSopenharmony_ci} 3057d722e3fbSopenharmony_ci 3058d722e3fbSopenharmony_cistatic int 3059d722e3fbSopenharmony_ciparse_devid_override(const char *devid_override) 3060d722e3fbSopenharmony_ci{ 3061d722e3fbSopenharmony_ci static const struct { 3062d722e3fbSopenharmony_ci const char *name; 3063d722e3fbSopenharmony_ci int pci_id; 3064d722e3fbSopenharmony_ci } name_map[] = { 3065d722e3fbSopenharmony_ci { "brw", PCI_CHIP_I965_GM }, 3066d722e3fbSopenharmony_ci { "g4x", PCI_CHIP_GM45_GM }, 3067d722e3fbSopenharmony_ci { "ilk", PCI_CHIP_ILD_G }, 3068d722e3fbSopenharmony_ci { "snb", PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS }, 3069d722e3fbSopenharmony_ci { "ivb", PCI_CHIP_IVYBRIDGE_S_GT2 }, 3070d722e3fbSopenharmony_ci { "hsw", PCI_CHIP_HASWELL_CRW_E_GT3 }, 3071d722e3fbSopenharmony_ci { "byt", PCI_CHIP_VALLEYVIEW_3 }, 3072d722e3fbSopenharmony_ci { "bdw", 0x1620 | BDW_ULX }, 3073d722e3fbSopenharmony_ci { "skl", PCI_CHIP_SKYLAKE_DT_GT2 }, 3074d722e3fbSopenharmony_ci { "kbl", PCI_CHIP_KABYLAKE_DT_GT2 }, 3075d722e3fbSopenharmony_ci }; 3076d722e3fbSopenharmony_ci unsigned int i; 3077d722e3fbSopenharmony_ci 3078d722e3fbSopenharmony_ci for (i = 0; i < ARRAY_SIZE(name_map); i++) { 3079d722e3fbSopenharmony_ci if (!strcmp(name_map[i].name, devid_override)) 3080d722e3fbSopenharmony_ci return name_map[i].pci_id; 3081d722e3fbSopenharmony_ci } 3082d722e3fbSopenharmony_ci 3083d722e3fbSopenharmony_ci return strtod(devid_override, NULL); 3084d722e3fbSopenharmony_ci} 3085d722e3fbSopenharmony_ci 3086d722e3fbSopenharmony_ci/** 3087d722e3fbSopenharmony_ci * Get the PCI ID for the device. This can be overridden by setting the 3088d722e3fbSopenharmony_ci * INTEL_DEVID_OVERRIDE environment variable to the desired ID. 3089d722e3fbSopenharmony_ci */ 3090d722e3fbSopenharmony_cistatic int 3091d722e3fbSopenharmony_ciget_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem) 3092d722e3fbSopenharmony_ci{ 3093d722e3fbSopenharmony_ci char *devid_override; 3094d722e3fbSopenharmony_ci int devid = 0; 3095d722e3fbSopenharmony_ci int ret; 3096d722e3fbSopenharmony_ci drm_i915_getparam_t gp; 3097d722e3fbSopenharmony_ci 3098d722e3fbSopenharmony_ci if (geteuid() == getuid()) { 3099d722e3fbSopenharmony_ci devid_override = getenv("INTEL_DEVID_OVERRIDE"); 3100d722e3fbSopenharmony_ci if (devid_override) { 3101d722e3fbSopenharmony_ci bufmgr_gem->no_exec = true; 3102d722e3fbSopenharmony_ci return parse_devid_override(devid_override); 3103d722e3fbSopenharmony_ci } 3104d722e3fbSopenharmony_ci } 3105d722e3fbSopenharmony_ci 3106d722e3fbSopenharmony_ci memclear(gp); 3107d722e3fbSopenharmony_ci gp.param = I915_PARAM_CHIPSET_ID; 3108d722e3fbSopenharmony_ci gp.value = &devid; 3109d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3110d722e3fbSopenharmony_ci if (ret) { 3111d722e3fbSopenharmony_ci fprintf(stderr, "get chip id failed: %d [%d]\n", ret, errno); 3112d722e3fbSopenharmony_ci fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value); 3113d722e3fbSopenharmony_ci } 3114d722e3fbSopenharmony_ci return devid; 3115d722e3fbSopenharmony_ci} 3116d722e3fbSopenharmony_ci 3117d722e3fbSopenharmony_cidrm_public int 3118d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr) 3119d722e3fbSopenharmony_ci{ 3120d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 3121d722e3fbSopenharmony_ci 3122d722e3fbSopenharmony_ci return bufmgr_gem->pci_device; 3123d722e3fbSopenharmony_ci} 3124d722e3fbSopenharmony_ci 3125d722e3fbSopenharmony_ci/** 3126d722e3fbSopenharmony_ci * Sets the AUB filename. 3127d722e3fbSopenharmony_ci * 3128d722e3fbSopenharmony_ci * This function has to be called before drm_intel_bufmgr_gem_set_aub_dump() 3129d722e3fbSopenharmony_ci * for it to have any effect. 3130d722e3fbSopenharmony_ci */ 3131d722e3fbSopenharmony_cidrm_public void 3132d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr, 3133d722e3fbSopenharmony_ci const char *filename) 3134d722e3fbSopenharmony_ci{ 3135d722e3fbSopenharmony_ci} 3136d722e3fbSopenharmony_ci 3137d722e3fbSopenharmony_ci/** 3138d722e3fbSopenharmony_ci * Sets up AUB dumping. 3139d722e3fbSopenharmony_ci * 3140d722e3fbSopenharmony_ci * This is a trace file format that can be used with the simulator. 3141d722e3fbSopenharmony_ci * Packets are emitted in a format somewhat like GPU command packets. 3142d722e3fbSopenharmony_ci * You can set up a GTT and upload your objects into the referenced 3143d722e3fbSopenharmony_ci * space, then send off batchbuffers and get BMPs out the other end. 3144d722e3fbSopenharmony_ci */ 3145d722e3fbSopenharmony_cidrm_public void 3146d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable) 3147d722e3fbSopenharmony_ci{ 3148d722e3fbSopenharmony_ci fprintf(stderr, "libdrm aub dumping is deprecated.\n\n" 3149d722e3fbSopenharmony_ci "Use intel_aubdump from intel-gpu-tools instead. Install intel-gpu-tools,\n" 3150d722e3fbSopenharmony_ci "then run (for example)\n\n" 3151d722e3fbSopenharmony_ci "\t$ intel_aubdump --output=trace.aub glxgears -geometry 500x500\n\n" 3152d722e3fbSopenharmony_ci "See the intel_aubdump man page for more details.\n"); 3153d722e3fbSopenharmony_ci} 3154d722e3fbSopenharmony_ci 3155d722e3fbSopenharmony_cidrm_public drm_intel_context * 3156d722e3fbSopenharmony_cidrm_intel_gem_context_create(drm_intel_bufmgr *bufmgr) 3157d722e3fbSopenharmony_ci{ 3158d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 3159d722e3fbSopenharmony_ci struct drm_i915_gem_context_create create; 3160d722e3fbSopenharmony_ci drm_intel_context *context = NULL; 3161d722e3fbSopenharmony_ci int ret; 3162d722e3fbSopenharmony_ci 3163d722e3fbSopenharmony_ci context = calloc(1, sizeof(*context)); 3164d722e3fbSopenharmony_ci if (!context) 3165d722e3fbSopenharmony_ci return NULL; 3166d722e3fbSopenharmony_ci 3167d722e3fbSopenharmony_ci memclear(create); 3168d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create); 3169d722e3fbSopenharmony_ci if (ret != 0) { 3170d722e3fbSopenharmony_ci DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n", 3171d722e3fbSopenharmony_ci strerror(errno)); 3172d722e3fbSopenharmony_ci free(context); 3173d722e3fbSopenharmony_ci return NULL; 3174d722e3fbSopenharmony_ci } 3175d722e3fbSopenharmony_ci 3176d722e3fbSopenharmony_ci context->ctx_id = create.ctx_id; 3177d722e3fbSopenharmony_ci context->bufmgr = bufmgr; 3178d722e3fbSopenharmony_ci 3179d722e3fbSopenharmony_ci return context; 3180d722e3fbSopenharmony_ci} 3181d722e3fbSopenharmony_ci 3182d722e3fbSopenharmony_cidrm_public int 3183d722e3fbSopenharmony_cidrm_intel_gem_context_get_id(drm_intel_context *ctx, uint32_t *ctx_id) 3184d722e3fbSopenharmony_ci{ 3185d722e3fbSopenharmony_ci if (ctx == NULL) 3186d722e3fbSopenharmony_ci return -EINVAL; 3187d722e3fbSopenharmony_ci 3188d722e3fbSopenharmony_ci *ctx_id = ctx->ctx_id; 3189d722e3fbSopenharmony_ci 3190d722e3fbSopenharmony_ci return 0; 3191d722e3fbSopenharmony_ci} 3192d722e3fbSopenharmony_ci 3193d722e3fbSopenharmony_cidrm_public void 3194d722e3fbSopenharmony_cidrm_intel_gem_context_destroy(drm_intel_context *ctx) 3195d722e3fbSopenharmony_ci{ 3196d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem; 3197d722e3fbSopenharmony_ci struct drm_i915_gem_context_destroy destroy; 3198d722e3fbSopenharmony_ci int ret; 3199d722e3fbSopenharmony_ci 3200d722e3fbSopenharmony_ci if (ctx == NULL) 3201d722e3fbSopenharmony_ci return; 3202d722e3fbSopenharmony_ci 3203d722e3fbSopenharmony_ci memclear(destroy); 3204d722e3fbSopenharmony_ci 3205d722e3fbSopenharmony_ci bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr; 3206d722e3fbSopenharmony_ci destroy.ctx_id = ctx->ctx_id; 3207d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, 3208d722e3fbSopenharmony_ci &destroy); 3209d722e3fbSopenharmony_ci if (ret != 0) 3210d722e3fbSopenharmony_ci fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n", 3211d722e3fbSopenharmony_ci strerror(errno)); 3212d722e3fbSopenharmony_ci 3213d722e3fbSopenharmony_ci free(ctx); 3214d722e3fbSopenharmony_ci} 3215d722e3fbSopenharmony_ci 3216d722e3fbSopenharmony_cidrm_public int 3217d722e3fbSopenharmony_cidrm_intel_get_reset_stats(drm_intel_context *ctx, 3218d722e3fbSopenharmony_ci uint32_t *reset_count, 3219d722e3fbSopenharmony_ci uint32_t *active, 3220d722e3fbSopenharmony_ci uint32_t *pending) 3221d722e3fbSopenharmony_ci{ 3222d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem; 3223d722e3fbSopenharmony_ci struct drm_i915_reset_stats stats; 3224d722e3fbSopenharmony_ci int ret; 3225d722e3fbSopenharmony_ci 3226d722e3fbSopenharmony_ci if (ctx == NULL) 3227d722e3fbSopenharmony_ci return -EINVAL; 3228d722e3fbSopenharmony_ci 3229d722e3fbSopenharmony_ci memclear(stats); 3230d722e3fbSopenharmony_ci 3231d722e3fbSopenharmony_ci bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr; 3232d722e3fbSopenharmony_ci stats.ctx_id = ctx->ctx_id; 3233d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 3234d722e3fbSopenharmony_ci DRM_IOCTL_I915_GET_RESET_STATS, 3235d722e3fbSopenharmony_ci &stats); 3236d722e3fbSopenharmony_ci if (ret == 0) { 3237d722e3fbSopenharmony_ci if (reset_count != NULL) 3238d722e3fbSopenharmony_ci *reset_count = stats.reset_count; 3239d722e3fbSopenharmony_ci 3240d722e3fbSopenharmony_ci if (active != NULL) 3241d722e3fbSopenharmony_ci *active = stats.batch_active; 3242d722e3fbSopenharmony_ci 3243d722e3fbSopenharmony_ci if (pending != NULL) 3244d722e3fbSopenharmony_ci *pending = stats.batch_pending; 3245d722e3fbSopenharmony_ci } 3246d722e3fbSopenharmony_ci 3247d722e3fbSopenharmony_ci return ret; 3248d722e3fbSopenharmony_ci} 3249d722e3fbSopenharmony_ci 3250d722e3fbSopenharmony_cidrm_public int 3251d722e3fbSopenharmony_cidrm_intel_reg_read(drm_intel_bufmgr *bufmgr, 3252d722e3fbSopenharmony_ci uint32_t offset, 3253d722e3fbSopenharmony_ci uint64_t *result) 3254d722e3fbSopenharmony_ci{ 3255d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 3256d722e3fbSopenharmony_ci struct drm_i915_reg_read reg_read; 3257d722e3fbSopenharmony_ci int ret; 3258d722e3fbSopenharmony_ci 3259d722e3fbSopenharmony_ci memclear(reg_read); 3260d722e3fbSopenharmony_ci reg_read.offset = offset; 3261d722e3fbSopenharmony_ci 3262d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, ®_read); 3263d722e3fbSopenharmony_ci 3264d722e3fbSopenharmony_ci *result = reg_read.val; 3265d722e3fbSopenharmony_ci return ret; 3266d722e3fbSopenharmony_ci} 3267d722e3fbSopenharmony_ci 3268d722e3fbSopenharmony_cidrm_public int 3269d722e3fbSopenharmony_cidrm_intel_get_subslice_total(int fd, unsigned int *subslice_total) 3270d722e3fbSopenharmony_ci{ 3271d722e3fbSopenharmony_ci drm_i915_getparam_t gp; 3272d722e3fbSopenharmony_ci int ret; 3273d722e3fbSopenharmony_ci 3274d722e3fbSopenharmony_ci memclear(gp); 3275d722e3fbSopenharmony_ci gp.value = (int*)subslice_total; 3276d722e3fbSopenharmony_ci gp.param = I915_PARAM_SUBSLICE_TOTAL; 3277d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); 3278d722e3fbSopenharmony_ci if (ret) 3279d722e3fbSopenharmony_ci return -errno; 3280d722e3fbSopenharmony_ci 3281d722e3fbSopenharmony_ci return 0; 3282d722e3fbSopenharmony_ci} 3283d722e3fbSopenharmony_ci 3284d722e3fbSopenharmony_cidrm_public int 3285d722e3fbSopenharmony_cidrm_intel_get_eu_total(int fd, unsigned int *eu_total) 3286d722e3fbSopenharmony_ci{ 3287d722e3fbSopenharmony_ci drm_i915_getparam_t gp; 3288d722e3fbSopenharmony_ci int ret; 3289d722e3fbSopenharmony_ci 3290d722e3fbSopenharmony_ci memclear(gp); 3291d722e3fbSopenharmony_ci gp.value = (int*)eu_total; 3292d722e3fbSopenharmony_ci gp.param = I915_PARAM_EU_TOTAL; 3293d722e3fbSopenharmony_ci ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); 3294d722e3fbSopenharmony_ci if (ret) 3295d722e3fbSopenharmony_ci return -errno; 3296d722e3fbSopenharmony_ci 3297d722e3fbSopenharmony_ci return 0; 3298d722e3fbSopenharmony_ci} 3299d722e3fbSopenharmony_ci 3300d722e3fbSopenharmony_cidrm_public int 3301d722e3fbSopenharmony_cidrm_intel_get_pooled_eu(int fd) 3302d722e3fbSopenharmony_ci{ 3303d722e3fbSopenharmony_ci drm_i915_getparam_t gp; 3304d722e3fbSopenharmony_ci int ret = -1; 3305d722e3fbSopenharmony_ci 3306d722e3fbSopenharmony_ci memclear(gp); 3307d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_POOLED_EU; 3308d722e3fbSopenharmony_ci gp.value = &ret; 3309d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp)) 3310d722e3fbSopenharmony_ci return -errno; 3311d722e3fbSopenharmony_ci 3312d722e3fbSopenharmony_ci return ret; 3313d722e3fbSopenharmony_ci} 3314d722e3fbSopenharmony_ci 3315d722e3fbSopenharmony_cidrm_public int 3316d722e3fbSopenharmony_cidrm_intel_get_min_eu_in_pool(int fd) 3317d722e3fbSopenharmony_ci{ 3318d722e3fbSopenharmony_ci drm_i915_getparam_t gp; 3319d722e3fbSopenharmony_ci int ret = -1; 3320d722e3fbSopenharmony_ci 3321d722e3fbSopenharmony_ci memclear(gp); 3322d722e3fbSopenharmony_ci gp.param = I915_PARAM_MIN_EU_IN_POOL; 3323d722e3fbSopenharmony_ci gp.value = &ret; 3324d722e3fbSopenharmony_ci if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp)) 3325d722e3fbSopenharmony_ci return -errno; 3326d722e3fbSopenharmony_ci 3327d722e3fbSopenharmony_ci return ret; 3328d722e3fbSopenharmony_ci} 3329d722e3fbSopenharmony_ci 3330d722e3fbSopenharmony_ci/** 3331d722e3fbSopenharmony_ci * Annotate the given bo for use in aub dumping. 3332d722e3fbSopenharmony_ci * 3333d722e3fbSopenharmony_ci * \param annotations is an array of drm_intel_aub_annotation objects 3334d722e3fbSopenharmony_ci * describing the type of data in various sections of the bo. Each 3335d722e3fbSopenharmony_ci * element of the array specifies the type and subtype of a section of 3336d722e3fbSopenharmony_ci * the bo, and the past-the-end offset of that section. The elements 3337d722e3fbSopenharmony_ci * of \c annotations must be sorted so that ending_offset is 3338d722e3fbSopenharmony_ci * increasing. 3339d722e3fbSopenharmony_ci * 3340d722e3fbSopenharmony_ci * \param count is the number of elements in the \c annotations array. 3341d722e3fbSopenharmony_ci * If \c count is zero, then \c annotations will not be dereferenced. 3342d722e3fbSopenharmony_ci * 3343d722e3fbSopenharmony_ci * Annotations are copied into a private data structure, so caller may 3344d722e3fbSopenharmony_ci * re-use the memory pointed to by \c annotations after the call 3345d722e3fbSopenharmony_ci * returns. 3346d722e3fbSopenharmony_ci * 3347d722e3fbSopenharmony_ci * Annotations are stored for the lifetime of the bo; to reset to the 3348d722e3fbSopenharmony_ci * default state (no annotations), call this function with a \c count 3349d722e3fbSopenharmony_ci * of zero. 3350d722e3fbSopenharmony_ci */ 3351d722e3fbSopenharmony_cidrm_public void drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo, 3352d722e3fbSopenharmony_ci drm_intel_aub_annotation *annotations, 3353d722e3fbSopenharmony_ci unsigned count) 3354d722e3fbSopenharmony_ci{ 3355d722e3fbSopenharmony_ci} 3356d722e3fbSopenharmony_ci 3357d722e3fbSopenharmony_cistatic pthread_mutex_t bufmgr_list_mutex = PTHREAD_MUTEX_INITIALIZER; 3358d722e3fbSopenharmony_cistatic drmMMListHead bufmgr_list = { &bufmgr_list, &bufmgr_list }; 3359d722e3fbSopenharmony_ci 3360d722e3fbSopenharmony_cistatic drm_intel_bufmgr_gem * 3361d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_find(int fd) 3362d722e3fbSopenharmony_ci{ 3363d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem; 3364d722e3fbSopenharmony_ci 3365d722e3fbSopenharmony_ci DRMLISTFOREACHENTRY(bufmgr_gem, &bufmgr_list, managers) { 3366d722e3fbSopenharmony_ci if (bufmgr_gem->fd == fd) { 3367d722e3fbSopenharmony_ci atomic_inc(&bufmgr_gem->refcount); 3368d722e3fbSopenharmony_ci return bufmgr_gem; 3369d722e3fbSopenharmony_ci } 3370d722e3fbSopenharmony_ci } 3371d722e3fbSopenharmony_ci 3372d722e3fbSopenharmony_ci return NULL; 3373d722e3fbSopenharmony_ci} 3374d722e3fbSopenharmony_ci 3375d722e3fbSopenharmony_cistatic void 3376d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_unref(drm_intel_bufmgr *bufmgr) 3377d722e3fbSopenharmony_ci{ 3378d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr; 3379d722e3fbSopenharmony_ci 3380d722e3fbSopenharmony_ci if (atomic_add_unless(&bufmgr_gem->refcount, -1, 1)) { 3381d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_list_mutex); 3382d722e3fbSopenharmony_ci 3383d722e3fbSopenharmony_ci if (atomic_dec_and_test(&bufmgr_gem->refcount)) { 3384d722e3fbSopenharmony_ci DRMLISTDEL(&bufmgr_gem->managers); 3385d722e3fbSopenharmony_ci drm_intel_bufmgr_gem_destroy(bufmgr); 3386d722e3fbSopenharmony_ci } 3387d722e3fbSopenharmony_ci 3388d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_list_mutex); 3389d722e3fbSopenharmony_ci } 3390d722e3fbSopenharmony_ci} 3391d722e3fbSopenharmony_ci 3392d722e3fbSopenharmony_cidrm_public void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo) 3393d722e3fbSopenharmony_ci{ 3394d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 3395d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 3396d722e3fbSopenharmony_ci 3397d722e3fbSopenharmony_ci if (bo_gem->gtt_virtual) 3398d722e3fbSopenharmony_ci return bo_gem->gtt_virtual; 3399d722e3fbSopenharmony_ci 3400d722e3fbSopenharmony_ci if (bo_gem->is_userptr) 3401d722e3fbSopenharmony_ci return NULL; 3402d722e3fbSopenharmony_ci 3403d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 3404d722e3fbSopenharmony_ci if (bo_gem->gtt_virtual == NULL) { 3405d722e3fbSopenharmony_ci struct drm_i915_gem_mmap_gtt mmap_arg; 3406d722e3fbSopenharmony_ci void *ptr; 3407d722e3fbSopenharmony_ci 3408d722e3fbSopenharmony_ci DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n", 3409d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 3410d722e3fbSopenharmony_ci 3411d722e3fbSopenharmony_ci if (bo_gem->map_count++ == 0) 3412d722e3fbSopenharmony_ci drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 3413d722e3fbSopenharmony_ci 3414d722e3fbSopenharmony_ci memclear(mmap_arg); 3415d722e3fbSopenharmony_ci mmap_arg.handle = bo_gem->gem_handle; 3416d722e3fbSopenharmony_ci 3417d722e3fbSopenharmony_ci /* Get the fake offset back... */ 3418d722e3fbSopenharmony_ci ptr = MAP_FAILED; 3419d722e3fbSopenharmony_ci if (drmIoctl(bufmgr_gem->fd, 3420d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_MMAP_GTT, 3421d722e3fbSopenharmony_ci &mmap_arg) == 0) { 3422d722e3fbSopenharmony_ci /* and mmap it */ 3423d722e3fbSopenharmony_ci ptr = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, 3424d722e3fbSopenharmony_ci MAP_SHARED, bufmgr_gem->fd, 3425d722e3fbSopenharmony_ci mmap_arg.offset); 3426d722e3fbSopenharmony_ci } 3427d722e3fbSopenharmony_ci if (ptr == MAP_FAILED) { 3428d722e3fbSopenharmony_ci if (--bo_gem->map_count == 0) 3429d722e3fbSopenharmony_ci drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 3430d722e3fbSopenharmony_ci ptr = NULL; 3431d722e3fbSopenharmony_ci } 3432d722e3fbSopenharmony_ci 3433d722e3fbSopenharmony_ci bo_gem->gtt_virtual = ptr; 3434d722e3fbSopenharmony_ci } 3435d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 3436d722e3fbSopenharmony_ci 3437d722e3fbSopenharmony_ci return bo_gem->gtt_virtual; 3438d722e3fbSopenharmony_ci} 3439d722e3fbSopenharmony_ci 3440d722e3fbSopenharmony_cidrm_public void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo) 3441d722e3fbSopenharmony_ci{ 3442d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 3443d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 3444d722e3fbSopenharmony_ci 3445d722e3fbSopenharmony_ci if (bo_gem->mem_virtual) 3446d722e3fbSopenharmony_ci return bo_gem->mem_virtual; 3447d722e3fbSopenharmony_ci 3448d722e3fbSopenharmony_ci if (bo_gem->is_userptr) { 3449d722e3fbSopenharmony_ci /* Return the same user ptr */ 3450d722e3fbSopenharmony_ci return bo_gem->user_virtual; 3451d722e3fbSopenharmony_ci } 3452d722e3fbSopenharmony_ci 3453d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 3454d722e3fbSopenharmony_ci if (!bo_gem->mem_virtual) { 3455d722e3fbSopenharmony_ci struct drm_i915_gem_mmap mmap_arg; 3456d722e3fbSopenharmony_ci 3457d722e3fbSopenharmony_ci if (bo_gem->map_count++ == 0) 3458d722e3fbSopenharmony_ci drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 3459d722e3fbSopenharmony_ci 3460d722e3fbSopenharmony_ci DBG("bo_map: %d (%s), map_count=%d\n", 3461d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 3462d722e3fbSopenharmony_ci 3463d722e3fbSopenharmony_ci memclear(mmap_arg); 3464d722e3fbSopenharmony_ci mmap_arg.handle = bo_gem->gem_handle; 3465d722e3fbSopenharmony_ci mmap_arg.size = bo->size; 3466d722e3fbSopenharmony_ci if (drmIoctl(bufmgr_gem->fd, 3467d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_MMAP, 3468d722e3fbSopenharmony_ci &mmap_arg)) { 3469d722e3fbSopenharmony_ci DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 3470d722e3fbSopenharmony_ci __FILE__, __LINE__, bo_gem->gem_handle, 3471d722e3fbSopenharmony_ci bo_gem->name, strerror(errno)); 3472d722e3fbSopenharmony_ci if (--bo_gem->map_count == 0) 3473d722e3fbSopenharmony_ci drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 3474d722e3fbSopenharmony_ci } else { 3475d722e3fbSopenharmony_ci VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1)); 3476d722e3fbSopenharmony_ci bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr; 3477d722e3fbSopenharmony_ci } 3478d722e3fbSopenharmony_ci } 3479d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 3480d722e3fbSopenharmony_ci 3481d722e3fbSopenharmony_ci return bo_gem->mem_virtual; 3482d722e3fbSopenharmony_ci} 3483d722e3fbSopenharmony_ci 3484d722e3fbSopenharmony_cidrm_public void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo) 3485d722e3fbSopenharmony_ci{ 3486d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr; 3487d722e3fbSopenharmony_ci drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo; 3488d722e3fbSopenharmony_ci 3489d722e3fbSopenharmony_ci if (bo_gem->wc_virtual) 3490d722e3fbSopenharmony_ci return bo_gem->wc_virtual; 3491d722e3fbSopenharmony_ci 3492d722e3fbSopenharmony_ci if (bo_gem->is_userptr) 3493d722e3fbSopenharmony_ci return NULL; 3494d722e3fbSopenharmony_ci 3495d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_gem->lock); 3496d722e3fbSopenharmony_ci if (!bo_gem->wc_virtual) { 3497d722e3fbSopenharmony_ci struct drm_i915_gem_mmap mmap_arg; 3498d722e3fbSopenharmony_ci 3499d722e3fbSopenharmony_ci if (bo_gem->map_count++ == 0) 3500d722e3fbSopenharmony_ci drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem); 3501d722e3fbSopenharmony_ci 3502d722e3fbSopenharmony_ci DBG("bo_map: %d (%s), map_count=%d\n", 3503d722e3fbSopenharmony_ci bo_gem->gem_handle, bo_gem->name, bo_gem->map_count); 3504d722e3fbSopenharmony_ci 3505d722e3fbSopenharmony_ci memclear(mmap_arg); 3506d722e3fbSopenharmony_ci mmap_arg.handle = bo_gem->gem_handle; 3507d722e3fbSopenharmony_ci mmap_arg.size = bo->size; 3508d722e3fbSopenharmony_ci mmap_arg.flags = I915_MMAP_WC; 3509d722e3fbSopenharmony_ci if (drmIoctl(bufmgr_gem->fd, 3510d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_MMAP, 3511d722e3fbSopenharmony_ci &mmap_arg)) { 3512d722e3fbSopenharmony_ci DBG("%s:%d: Error mapping buffer %d (%s): %s .\n", 3513d722e3fbSopenharmony_ci __FILE__, __LINE__, bo_gem->gem_handle, 3514d722e3fbSopenharmony_ci bo_gem->name, strerror(errno)); 3515d722e3fbSopenharmony_ci if (--bo_gem->map_count == 0) 3516d722e3fbSopenharmony_ci drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem); 3517d722e3fbSopenharmony_ci } else { 3518d722e3fbSopenharmony_ci VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1)); 3519d722e3fbSopenharmony_ci bo_gem->wc_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr; 3520d722e3fbSopenharmony_ci } 3521d722e3fbSopenharmony_ci } 3522d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_gem->lock); 3523d722e3fbSopenharmony_ci 3524d722e3fbSopenharmony_ci return bo_gem->wc_virtual; 3525d722e3fbSopenharmony_ci} 3526d722e3fbSopenharmony_ci 3527d722e3fbSopenharmony_ci/** 3528d722e3fbSopenharmony_ci * Initializes the GEM buffer manager, which uses the kernel to allocate, map, 3529d722e3fbSopenharmony_ci * and manage map buffer objections. 3530d722e3fbSopenharmony_ci * 3531d722e3fbSopenharmony_ci * \param fd File descriptor of the opened DRM device. 3532d722e3fbSopenharmony_ci */ 3533d722e3fbSopenharmony_cidrm_public drm_intel_bufmgr * 3534d722e3fbSopenharmony_cidrm_intel_bufmgr_gem_init(int fd, int batch_size) 3535d722e3fbSopenharmony_ci{ 3536d722e3fbSopenharmony_ci drm_intel_bufmgr_gem *bufmgr_gem; 3537d722e3fbSopenharmony_ci struct drm_i915_gem_get_aperture aperture; 3538d722e3fbSopenharmony_ci drm_i915_getparam_t gp; 3539d722e3fbSopenharmony_ci int ret, tmp; 3540d722e3fbSopenharmony_ci 3541d722e3fbSopenharmony_ci pthread_mutex_lock(&bufmgr_list_mutex); 3542d722e3fbSopenharmony_ci 3543d722e3fbSopenharmony_ci bufmgr_gem = drm_intel_bufmgr_gem_find(fd); 3544d722e3fbSopenharmony_ci if (bufmgr_gem) 3545d722e3fbSopenharmony_ci goto exit; 3546d722e3fbSopenharmony_ci 3547d722e3fbSopenharmony_ci bufmgr_gem = calloc(1, sizeof(*bufmgr_gem)); 3548d722e3fbSopenharmony_ci if (bufmgr_gem == NULL) 3549d722e3fbSopenharmony_ci goto exit; 3550d722e3fbSopenharmony_ci 3551d722e3fbSopenharmony_ci bufmgr_gem->fd = fd; 3552d722e3fbSopenharmony_ci atomic_set(&bufmgr_gem->refcount, 1); 3553d722e3fbSopenharmony_ci 3554d722e3fbSopenharmony_ci if (pthread_mutex_init(&bufmgr_gem->lock, NULL) != 0) { 3555d722e3fbSopenharmony_ci free(bufmgr_gem); 3556d722e3fbSopenharmony_ci bufmgr_gem = NULL; 3557d722e3fbSopenharmony_ci goto exit; 3558d722e3fbSopenharmony_ci } 3559d722e3fbSopenharmony_ci 3560d722e3fbSopenharmony_ci memclear(aperture); 3561d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, 3562d722e3fbSopenharmony_ci DRM_IOCTL_I915_GEM_GET_APERTURE, 3563d722e3fbSopenharmony_ci &aperture); 3564d722e3fbSopenharmony_ci 3565d722e3fbSopenharmony_ci if (ret == 0) 3566d722e3fbSopenharmony_ci bufmgr_gem->gtt_size = aperture.aper_available_size; 3567d722e3fbSopenharmony_ci else { 3568d722e3fbSopenharmony_ci fprintf(stderr, "DRM_IOCTL_I915_GEM_APERTURE failed: %s\n", 3569d722e3fbSopenharmony_ci strerror(errno)); 3570d722e3fbSopenharmony_ci bufmgr_gem->gtt_size = 128 * 1024 * 1024; 3571d722e3fbSopenharmony_ci fprintf(stderr, "Assuming %dkB available aperture size.\n" 3572d722e3fbSopenharmony_ci "May lead to reduced performance or incorrect " 3573d722e3fbSopenharmony_ci "rendering.\n", 3574d722e3fbSopenharmony_ci (int)bufmgr_gem->gtt_size / 1024); 3575d722e3fbSopenharmony_ci } 3576d722e3fbSopenharmony_ci 3577d722e3fbSopenharmony_ci bufmgr_gem->pci_device = get_pci_device_id(bufmgr_gem); 3578d722e3fbSopenharmony_ci 3579d722e3fbSopenharmony_ci if (IS_GEN2(bufmgr_gem->pci_device)) 3580d722e3fbSopenharmony_ci bufmgr_gem->gen = 2; 3581d722e3fbSopenharmony_ci else if (IS_GEN3(bufmgr_gem->pci_device)) 3582d722e3fbSopenharmony_ci bufmgr_gem->gen = 3; 3583d722e3fbSopenharmony_ci else if (IS_GEN4(bufmgr_gem->pci_device)) 3584d722e3fbSopenharmony_ci bufmgr_gem->gen = 4; 3585d722e3fbSopenharmony_ci else if (IS_GEN5(bufmgr_gem->pci_device)) 3586d722e3fbSopenharmony_ci bufmgr_gem->gen = 5; 3587d722e3fbSopenharmony_ci else if (IS_GEN6(bufmgr_gem->pci_device)) 3588d722e3fbSopenharmony_ci bufmgr_gem->gen = 6; 3589d722e3fbSopenharmony_ci else if (IS_GEN7(bufmgr_gem->pci_device)) 3590d722e3fbSopenharmony_ci bufmgr_gem->gen = 7; 3591d722e3fbSopenharmony_ci else if (IS_GEN8(bufmgr_gem->pci_device)) 3592d722e3fbSopenharmony_ci bufmgr_gem->gen = 8; 3593d722e3fbSopenharmony_ci else if (!intel_get_genx(bufmgr_gem->pci_device, &bufmgr_gem->gen)) { 3594d722e3fbSopenharmony_ci free(bufmgr_gem); 3595d722e3fbSopenharmony_ci bufmgr_gem = NULL; 3596d722e3fbSopenharmony_ci goto exit; 3597d722e3fbSopenharmony_ci } 3598d722e3fbSopenharmony_ci 3599d722e3fbSopenharmony_ci if (IS_GEN3(bufmgr_gem->pci_device) && 3600d722e3fbSopenharmony_ci bufmgr_gem->gtt_size > 256*1024*1024) { 3601d722e3fbSopenharmony_ci /* The unmappable part of gtt on gen 3 (i.e. above 256MB) can't 3602d722e3fbSopenharmony_ci * be used for tiled blits. To simplify the accounting, just 3603d722e3fbSopenharmony_ci * subtract the unmappable part (fixed to 256MB on all known 3604d722e3fbSopenharmony_ci * gen3 devices) if the kernel advertises it. */ 3605d722e3fbSopenharmony_ci bufmgr_gem->gtt_size -= 256*1024*1024; 3606d722e3fbSopenharmony_ci } 3607d722e3fbSopenharmony_ci 3608d722e3fbSopenharmony_ci memclear(gp); 3609d722e3fbSopenharmony_ci gp.value = &tmp; 3610d722e3fbSopenharmony_ci 3611d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_EXECBUF2; 3612d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3613d722e3fbSopenharmony_ci if (ret) { 3614d722e3fbSopenharmony_ci fprintf(stderr, "i915 does not support EXECBUFER2\n"); 3615d722e3fbSopenharmony_ci free(bufmgr_gem); 3616d722e3fbSopenharmony_ci bufmgr_gem = NULL; 3617d722e3fbSopenharmony_ci goto exit; 3618d722e3fbSopenharmony_ci } 3619d722e3fbSopenharmony_ci 3620d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_BSD; 3621d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3622d722e3fbSopenharmony_ci bufmgr_gem->has_bsd = ret == 0; 3623d722e3fbSopenharmony_ci 3624d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_BLT; 3625d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3626d722e3fbSopenharmony_ci bufmgr_gem->has_blt = ret == 0; 3627d722e3fbSopenharmony_ci 3628d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_RELAXED_FENCING; 3629d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3630d722e3fbSopenharmony_ci bufmgr_gem->has_relaxed_fencing = ret == 0; 3631d722e3fbSopenharmony_ci 3632d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_EXEC_ASYNC; 3633d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3634d722e3fbSopenharmony_ci bufmgr_gem->has_exec_async = ret == 0; 3635d722e3fbSopenharmony_ci 3636d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_alloc_userptr = check_bo_alloc_userptr; 3637d722e3fbSopenharmony_ci 3638d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_WAIT_TIMEOUT; 3639d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3640d722e3fbSopenharmony_ci bufmgr_gem->has_wait_timeout = ret == 0; 3641d722e3fbSopenharmony_ci 3642d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_LLC; 3643d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3644d722e3fbSopenharmony_ci if (ret != 0) { 3645d722e3fbSopenharmony_ci /* Kernel does not supports HAS_LLC query, fallback to GPU 3646d722e3fbSopenharmony_ci * generation detection and assume that we have LLC on GEN6/7 3647d722e3fbSopenharmony_ci */ 3648d722e3fbSopenharmony_ci bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) | 3649d722e3fbSopenharmony_ci IS_GEN7(bufmgr_gem->pci_device)); 3650d722e3fbSopenharmony_ci } else 3651d722e3fbSopenharmony_ci bufmgr_gem->has_llc = *gp.value; 3652d722e3fbSopenharmony_ci 3653d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_VEBOX; 3654d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3655d722e3fbSopenharmony_ci bufmgr_gem->has_vebox = (ret == 0) & (*gp.value > 0); 3656d722e3fbSopenharmony_ci 3657d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_EXEC_SOFTPIN; 3658d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3659d722e3fbSopenharmony_ci if (ret == 0 && *gp.value > 0) 3660d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_set_softpin_offset = drm_intel_gem_bo_set_softpin_offset; 3661d722e3fbSopenharmony_ci 3662d722e3fbSopenharmony_ci if (bufmgr_gem->gen < 4) { 3663d722e3fbSopenharmony_ci gp.param = I915_PARAM_NUM_FENCES_AVAIL; 3664d722e3fbSopenharmony_ci gp.value = &bufmgr_gem->available_fences; 3665d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3666d722e3fbSopenharmony_ci if (ret) { 3667d722e3fbSopenharmony_ci fprintf(stderr, "get fences failed: %d [%d]\n", ret, 3668d722e3fbSopenharmony_ci errno); 3669d722e3fbSopenharmony_ci fprintf(stderr, "param: %d, val: %d\n", gp.param, 3670d722e3fbSopenharmony_ci *gp.value); 3671d722e3fbSopenharmony_ci bufmgr_gem->available_fences = 0; 3672d722e3fbSopenharmony_ci } else { 3673d722e3fbSopenharmony_ci /* XXX The kernel reports the total number of fences, 3674d722e3fbSopenharmony_ci * including any that may be pinned. 3675d722e3fbSopenharmony_ci * 3676d722e3fbSopenharmony_ci * We presume that there will be at least one pinned 3677d722e3fbSopenharmony_ci * fence for the scanout buffer, but there may be more 3678d722e3fbSopenharmony_ci * than one scanout and the user may be manually 3679d722e3fbSopenharmony_ci * pinning buffers. Let's move to execbuffer2 and 3680d722e3fbSopenharmony_ci * thereby forget the insanity of using fences... 3681d722e3fbSopenharmony_ci */ 3682d722e3fbSopenharmony_ci bufmgr_gem->available_fences -= 2; 3683d722e3fbSopenharmony_ci if (bufmgr_gem->available_fences < 0) 3684d722e3fbSopenharmony_ci bufmgr_gem->available_fences = 0; 3685d722e3fbSopenharmony_ci } 3686d722e3fbSopenharmony_ci } 3687d722e3fbSopenharmony_ci 3688d722e3fbSopenharmony_ci if (bufmgr_gem->gen >= 8) { 3689d722e3fbSopenharmony_ci gp.param = I915_PARAM_HAS_ALIASING_PPGTT; 3690d722e3fbSopenharmony_ci ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp); 3691d722e3fbSopenharmony_ci if (ret == 0 && *gp.value == 3) 3692d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_use_48b_address_range = drm_intel_gem_bo_use_48b_address_range; 3693d722e3fbSopenharmony_ci } 3694d722e3fbSopenharmony_ci 3695d722e3fbSopenharmony_ci /* Let's go with one relocation per every 2 dwords (but round down a bit 3696d722e3fbSopenharmony_ci * since a power of two will mean an extra page allocation for the reloc 3697d722e3fbSopenharmony_ci * buffer). 3698d722e3fbSopenharmony_ci * 3699d722e3fbSopenharmony_ci * Every 4 was too few for the blender benchmark. 3700d722e3fbSopenharmony_ci */ 3701d722e3fbSopenharmony_ci bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2; 3702d722e3fbSopenharmony_ci 3703d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_alloc = drm_intel_gem_bo_alloc; 3704d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_alloc_for_render = 3705d722e3fbSopenharmony_ci drm_intel_gem_bo_alloc_for_render; 3706d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_alloc_tiled = drm_intel_gem_bo_alloc_tiled; 3707d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_reference = drm_intel_gem_bo_reference; 3708d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_unreference = drm_intel_gem_bo_unreference; 3709d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_map = drm_intel_gem_bo_map; 3710d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_unmap = drm_intel_gem_bo_unmap; 3711d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_subdata = drm_intel_gem_bo_subdata; 3712d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_get_subdata = drm_intel_gem_bo_get_subdata; 3713d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_wait_rendering = drm_intel_gem_bo_wait_rendering; 3714d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_emit_reloc = drm_intel_gem_bo_emit_reloc; 3715d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_emit_reloc_fence = drm_intel_gem_bo_emit_reloc_fence; 3716d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_pin = drm_intel_gem_bo_pin; 3717d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_unpin = drm_intel_gem_bo_unpin; 3718d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_get_tiling = drm_intel_gem_bo_get_tiling; 3719d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_set_tiling = drm_intel_gem_bo_set_tiling; 3720d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_flink = drm_intel_gem_bo_flink; 3721d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec2; 3722d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_mrb_exec = drm_intel_gem_bo_mrb_exec2; 3723d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_busy = drm_intel_gem_bo_busy; 3724d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_madvise = drm_intel_gem_bo_madvise; 3725d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.destroy = drm_intel_bufmgr_gem_unref; 3726d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.debug = 0; 3727d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.check_aperture_space = 3728d722e3fbSopenharmony_ci drm_intel_gem_check_aperture_space; 3729d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_disable_reuse = drm_intel_gem_bo_disable_reuse; 3730d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_is_reusable = drm_intel_gem_bo_is_reusable; 3731d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.get_pipe_from_crtc_id = 3732d722e3fbSopenharmony_ci drm_intel_gem_get_pipe_from_crtc_id; 3733d722e3fbSopenharmony_ci bufmgr_gem->bufmgr.bo_references = drm_intel_gem_bo_references; 3734d722e3fbSopenharmony_ci 3735d722e3fbSopenharmony_ci init_cache_buckets(bufmgr_gem); 3736d722e3fbSopenharmony_ci 3737d722e3fbSopenharmony_ci DRMINITLISTHEAD(&bufmgr_gem->vma_cache); 3738d722e3fbSopenharmony_ci bufmgr_gem->vma_max = -1; /* unlimited by default */ 3739d722e3fbSopenharmony_ci 3740d722e3fbSopenharmony_ci DRMLISTADD(&bufmgr_gem->managers, &bufmgr_list); 3741d722e3fbSopenharmony_ci 3742d722e3fbSopenharmony_ciexit: 3743d722e3fbSopenharmony_ci pthread_mutex_unlock(&bufmgr_list_mutex); 3744d722e3fbSopenharmony_ci 3745d722e3fbSopenharmony_ci return bufmgr_gem != NULL ? &bufmgr_gem->bufmgr : NULL; 3746d722e3fbSopenharmony_ci} 3747