1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2014 Etnaviv Project 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Christian Gmeiner <christian.gmeiner@gmail.com> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "util/hash_table.h" 28bf215546Sopenharmony_ci#include "util/os_file.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "etnaviv_priv.h" 31bf215546Sopenharmony_ci#include "etnaviv_drmif.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci/* Declare symbol in case we don't link with etnaviv's gallium driver */ 34bf215546Sopenharmony_ciint etna_mesa_debug __attribute__((weak)) = 0; 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_cistruct etna_device *etna_device_new(int fd) 37bf215546Sopenharmony_ci{ 38bf215546Sopenharmony_ci struct etna_device *dev; 39bf215546Sopenharmony_ci struct drm_etnaviv_param req = { 40bf215546Sopenharmony_ci .param = ETNAVIV_PARAM_SOFTPIN_START_ADDR, 41bf215546Sopenharmony_ci }; 42bf215546Sopenharmony_ci drmVersionPtr version; 43bf215546Sopenharmony_ci int ret; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci version = drmGetVersion(fd); 46bf215546Sopenharmony_ci if (!version) { 47bf215546Sopenharmony_ci ERROR_MSG("cannot get version: %s", strerror(errno)); 48bf215546Sopenharmony_ci return NULL; 49bf215546Sopenharmony_ci } 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci dev = calloc(sizeof(*dev), 1); 52bf215546Sopenharmony_ci if (!dev) { 53bf215546Sopenharmony_ci goto out; 54bf215546Sopenharmony_ci } 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci dev->drm_version = ETNA_DRM_VERSION(version->version_major, 57bf215546Sopenharmony_ci version->version_minor); 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ciout: 60bf215546Sopenharmony_ci drmFreeVersion(version); 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci if (!dev) 63bf215546Sopenharmony_ci return NULL; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci p_atomic_set(&dev->refcnt, 1); 66bf215546Sopenharmony_ci dev->fd = fd; 67bf215546Sopenharmony_ci dev->handle_table = _mesa_hash_table_create(NULL, _mesa_hash_u32, _mesa_key_u32_equal); 68bf215546Sopenharmony_ci dev->name_table = _mesa_hash_table_create(NULL, _mesa_hash_u32, _mesa_key_u32_equal); 69bf215546Sopenharmony_ci etna_bo_cache_init(&dev->bo_cache); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_GET_PARAM, &req, sizeof(req)); 72bf215546Sopenharmony_ci if (!ret && req.value != ~0ULL) { 73bf215546Sopenharmony_ci const uint64_t _4GB = 1ull << 32; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci list_inithead(&dev->zombie_list); 76bf215546Sopenharmony_ci util_vma_heap_init(&dev->address_space, req.value, _4GB - req.value); 77bf215546Sopenharmony_ci dev->use_softpin = 1; 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci return dev; 81bf215546Sopenharmony_ci} 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci/* like etna_device_new() but creates it's own private dup() of the fd 84bf215546Sopenharmony_ci * which is close()d when the device is finalized. */ 85bf215546Sopenharmony_cistruct etna_device *etna_device_new_dup(int fd) 86bf215546Sopenharmony_ci{ 87bf215546Sopenharmony_ci int dup_fd = os_dupfd_cloexec(fd); 88bf215546Sopenharmony_ci struct etna_device *dev = etna_device_new(dup_fd); 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci if (dev) 91bf215546Sopenharmony_ci dev->closefd = 1; 92bf215546Sopenharmony_ci else 93bf215546Sopenharmony_ci close(dup_fd); 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci return dev; 96bf215546Sopenharmony_ci} 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_cistruct etna_device *etna_device_ref(struct etna_device *dev) 99bf215546Sopenharmony_ci{ 100bf215546Sopenharmony_ci p_atomic_inc(&dev->refcnt); 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci return dev; 103bf215546Sopenharmony_ci} 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_cistatic void etna_device_del_impl(struct etna_device *dev) 106bf215546Sopenharmony_ci{ 107bf215546Sopenharmony_ci etna_bo_cache_cleanup(&dev->bo_cache, 0); 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci if (dev->use_softpin) { 110bf215546Sopenharmony_ci etna_bo_kill_zombies(dev); 111bf215546Sopenharmony_ci util_vma_heap_finish(&dev->address_space); 112bf215546Sopenharmony_ci } 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci _mesa_hash_table_destroy(dev->handle_table, NULL); 115bf215546Sopenharmony_ci _mesa_hash_table_destroy(dev->name_table, NULL); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (dev->closefd) 118bf215546Sopenharmony_ci close(dev->fd); 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci free(dev); 121bf215546Sopenharmony_ci} 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_civoid etna_device_del_locked(struct etna_device *dev) 124bf215546Sopenharmony_ci{ 125bf215546Sopenharmony_ci simple_mtx_assert_locked(&etna_device_lock); 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci if (!p_atomic_dec_zero(&dev->refcnt)) 128bf215546Sopenharmony_ci return; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci etna_device_del_impl(dev); 131bf215546Sopenharmony_ci} 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_civoid etna_device_del(struct etna_device *dev) 134bf215546Sopenharmony_ci{ 135bf215546Sopenharmony_ci if (!p_atomic_dec_zero(&dev->refcnt)) 136bf215546Sopenharmony_ci return; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci simple_mtx_lock(&etna_device_lock); 139bf215546Sopenharmony_ci etna_device_del_impl(dev); 140bf215546Sopenharmony_ci simple_mtx_unlock(&etna_device_lock); 141bf215546Sopenharmony_ci} 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ciint etna_device_fd(struct etna_device *dev) 144bf215546Sopenharmony_ci{ 145bf215546Sopenharmony_ci return dev->fd; 146bf215546Sopenharmony_ci} 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_cibool etnaviv_device_softpin_capable(struct etna_device *dev) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci return !!dev->use_softpin; 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ciuint32_t etnaviv_device_version(struct etna_device *dev) 154bf215546Sopenharmony_ci{ 155bf215546Sopenharmony_ci return dev->drm_version; 156bf215546Sopenharmony_ci} 157