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