Path: blob/21.2-virgl/src/etnaviv/drm/etnaviv_priv.h
4564 views
/*1* Copyright (C) 2014-2015 Etnaviv Project2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*22* Authors:23* Christian Gmeiner <[email protected]>24*/2526#ifndef ETNAVIV_PRIV_H_27#define ETNAVIV_PRIV_H_2829#include <stdlib.h>30#include <errno.h>31#include <string.h>32#include <unistd.h>33#include <errno.h>34#include <fcntl.h>35#include <sys/ioctl.h>36#include <stdio.h>37#include <assert.h>3839#include <xf86drm.h>4041#include "util/list.h"42#include "util/macros.h"43#include "util/simple_mtx.h"44#include "util/timespec.h"45#include "util/u_atomic.h"46#include "util/u_debug.h"47#include "util/vma.h"4849#include "etnaviv_drmif.h"50#include "drm-uapi/etnaviv_drm.h"5152extern simple_mtx_t etna_drm_table_lock;5354struct etna_bo_bucket {55uint32_t size;56struct list_head list;57};5859struct etna_bo_cache {60struct etna_bo_bucket cache_bucket[14 * 4];61unsigned num_buckets;62time_t time;63};6465struct etna_device {66int fd;67int refcnt;6869/* tables to keep track of bo's, to avoid "evil-twin" etna_bo objects:70*71* handle_table: maps handle to etna_bo72* name_table: maps flink name to etna_bo73*74* We end up needing two tables, because DRM_IOCTL_GEM_OPEN always75* returns a new handle. So we need to figure out if the bo is already76* open in the process first, before calling gem-open.77*/78void *handle_table, *name_table;7980struct etna_bo_cache bo_cache;8182int use_softpin;83struct util_vma_heap address_space;8485int closefd; /* call close(fd) upon destruction */86};8788void etna_bo_cache_init(struct etna_bo_cache *cache);89void etna_bo_cache_cleanup(struct etna_bo_cache *cache, time_t time);90struct etna_bo *etna_bo_cache_alloc(struct etna_bo_cache *cache,91uint32_t *size, uint32_t flags);92int etna_bo_cache_free(struct etna_bo_cache *cache, struct etna_bo *bo);9394/* for where @etna_drm_table_lock is already held: */95void etna_device_del_locked(struct etna_device *dev);9697/* a GEM buffer object allocated from the DRM device */98struct etna_bo {99struct etna_device *dev;100void *map; /* userspace mmap'ing (if there is one) */101uint32_t size;102uint32_t handle;103uint32_t flags;104uint32_t name; /* flink global handle (DRI2 name) */105uint64_t offset; /* offset to mmap() */106uint32_t va; /* GPU virtual address */107int refcnt;108109/*110* To avoid excess hashtable lookups, cache the stream this bo was111* last emitted on (since that will probably also be the next ring112* it is emitted on).113*/114struct etna_cmd_stream *current_stream;115uint32_t idx;116117int reuse;118struct list_head list; /* bucket-list entry */119time_t free_time; /* time when added to bucket-list */120};121122struct etna_gpu {123struct etna_device *dev;124uint32_t core;125uint32_t model;126uint32_t revision;127};128129struct etna_pipe {130enum etna_pipe_id id;131struct etna_gpu *gpu;132};133134struct etna_cmd_stream_priv {135struct etna_cmd_stream base;136struct etna_pipe *pipe;137138uint32_t last_timestamp;139140/* submit ioctl related tables: */141struct {142/* bo's table: */143struct drm_etnaviv_gem_submit_bo *bos;144uint32_t nr_bos, max_bos;145146/* reloc's table: */147struct drm_etnaviv_gem_submit_reloc *relocs;148uint32_t nr_relocs, max_relocs;149150/* perf's table: */151struct drm_etnaviv_gem_submit_pmr *pmrs;152uint32_t nr_pmrs, max_pmrs;153} submit;154155/* should have matching entries in submit.bos: */156struct etna_bo **bos;157uint32_t nr_bos, max_bos;158159/* notify callback if buffer reset happened */160void (*force_flush)(struct etna_cmd_stream *stream, void *priv);161void *force_flush_priv;162163void *bo_table;164};165166struct etna_perfmon {167struct list_head domains;168struct etna_pipe *pipe;169};170171struct etna_perfmon_domain172{173struct list_head head;174struct list_head signals;175uint8_t id;176char name[64];177};178179struct etna_perfmon_signal180{181struct list_head head;182struct etna_perfmon_domain *domain;183uint8_t signal;184char name[64];185};186187#define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1))188189#define enable_debug 0 /* TODO make dynamic */190191#define INFO_MSG(fmt, ...) \192do { debug_printf("[I] "fmt " (%s:%d)\n", \193##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)194#define DEBUG_MSG(fmt, ...) \195do if (enable_debug) { debug_printf("[D] "fmt " (%s:%d)\n", \196##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)197#define WARN_MSG(fmt, ...) \198do { debug_printf("[W] "fmt " (%s:%d)\n", \199##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)200#define ERROR_MSG(fmt, ...) \201do { debug_printf("[E] " fmt " (%s:%d)\n", \202##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)203204#define VOID2U64(x) ((uint64_t)(unsigned long)(x))205206static inline void get_abs_timeout(struct drm_etnaviv_timespec *tv, uint64_t ns)207{208struct timespec t;209clock_gettime(CLOCK_MONOTONIC, &t);210tv->tv_sec = t.tv_sec + ns / NSEC_PER_SEC;211tv->tv_nsec = t.tv_nsec + ns % NSEC_PER_SEC;212if (tv->tv_nsec >= NSEC_PER_SEC) {213tv->tv_nsec -= NSEC_PER_SEC;214tv->tv_sec++;215}216}217218#if HAVE_VALGRIND219# include <memcheck.h>220221/*222* For tracking the backing memory (if valgrind enabled, we force a mmap223* for the purposes of tracking)224*/225static inline void VG_BO_ALLOC(struct etna_bo *bo)226{227if (bo && RUNNING_ON_VALGRIND) {228VALGRIND_MALLOCLIKE_BLOCK(etna_bo_map(bo), bo->size, 0, 1);229}230}231232static inline void VG_BO_FREE(struct etna_bo *bo)233{234VALGRIND_FREELIKE_BLOCK(bo->map, 0);235}236237/*238* For tracking bo structs that are in the buffer-cache, so that valgrind239* doesn't attribute ownership to the first one to allocate the recycled240* bo.241*242* Note that the list_head in etna_bo is used to track the buffers in cache243* so disable error reporting on the range while they are in cache so244* valgrind doesn't squawk about list traversal.245*246*/247static inline void VG_BO_RELEASE(struct etna_bo *bo)248{249if (RUNNING_ON_VALGRIND) {250VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, sizeof(*bo));251VALGRIND_MAKE_MEM_NOACCESS(bo, sizeof(*bo));252VALGRIND_FREELIKE_BLOCK(bo->map, 0);253}254}255static inline void VG_BO_OBTAIN(struct etna_bo *bo)256{257if (RUNNING_ON_VALGRIND) {258VALGRIND_MAKE_MEM_DEFINED(bo, sizeof(*bo));259VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(bo, sizeof(*bo));260VALGRIND_MALLOCLIKE_BLOCK(bo->map, bo->size, 0, 1);261}262}263#else264static inline void VG_BO_ALLOC(struct etna_bo *bo) {}265static inline void VG_BO_FREE(struct etna_bo *bo) {}266static inline void VG_BO_RELEASE(struct etna_bo *bo) {}267static inline void VG_BO_OBTAIN(struct etna_bo *bo) {}268#endif269270#endif /* ETNAVIV_PRIV_H_ */271272273