17e102996Smaya/* 27e102996Smaya * Copyright (C) 2012-2018 Rob Clark <robclark@freedesktop.org> 37e102996Smaya * 47e102996Smaya * Permission is hereby granted, free of charge, to any person obtaining a 57e102996Smaya * copy of this software and associated documentation files (the "Software"), 67e102996Smaya * to deal in the Software without restriction, including without limitation 77e102996Smaya * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87e102996Smaya * and/or sell copies of the Software, and to permit persons to whom the 97e102996Smaya * Software is furnished to do so, subject to the following conditions: 107e102996Smaya * 117e102996Smaya * The above copyright notice and this permission notice (including the next 127e102996Smaya * paragraph) shall be included in all copies or substantial portions of the 137e102996Smaya * Software. 147e102996Smaya * 157e102996Smaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167e102996Smaya * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177e102996Smaya * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187e102996Smaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197e102996Smaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 207e102996Smaya * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 217e102996Smaya * SOFTWARE. 227e102996Smaya * 237e102996Smaya * Authors: 247e102996Smaya * Rob Clark <robclark@freedesktop.org> 257e102996Smaya */ 267e102996Smaya 277e102996Smaya#include <unistd.h> 287ec681f3Smrg#include <sys/stat.h> 297ec681f3Smrg#include <sys/types.h> 307ec681f3Smrg 317ec681f3Smrg#include "util/os_file.h" 327e102996Smaya 337e102996Smaya#include "freedreno_drmif.h" 347e102996Smaya#include "freedreno_priv.h" 357e102996Smaya 367ec681f3Smrgstruct fd_device *msm_device_new(int fd, drmVersionPtr version); 377e102996Smaya 387ec681f3Smrgstruct fd_device * 397ec681f3Smrgfd_device_new(int fd) 407e102996Smaya{ 417ec681f3Smrg struct fd_device *dev; 427ec681f3Smrg drmVersionPtr version; 437ec681f3Smrg 447ec681f3Smrg /* figure out if we are kgsl or msm drm driver: */ 457ec681f3Smrg version = drmGetVersion(fd); 467ec681f3Smrg if (!version) { 477ec681f3Smrg ERROR_MSG("cannot get version: %s", strerror(errno)); 487ec681f3Smrg return NULL; 497ec681f3Smrg } 507ec681f3Smrg 517ec681f3Smrg if (!strcmp(version->name, "msm")) { 527ec681f3Smrg DEBUG_MSG("msm DRM device"); 537ec681f3Smrg if (version->version_major != 1) { 547ec681f3Smrg ERROR_MSG("unsupported version: %u.%u.%u", version->version_major, 557ec681f3Smrg version->version_minor, version->version_patchlevel); 567ec681f3Smrg dev = NULL; 577ec681f3Smrg goto out; 587ec681f3Smrg } 597ec681f3Smrg 607ec681f3Smrg dev = msm_device_new(fd, version); 617ec681f3Smrg dev->version = version->version_minor; 627e102996Smaya#if HAVE_FREEDRENO_KGSL 637ec681f3Smrg } else if (!strcmp(version->name, "kgsl")) { 647ec681f3Smrg DEBUG_MSG("kgsl DRM device"); 657ec681f3Smrg dev = kgsl_device_new(fd); 667e102996Smaya#endif 677ec681f3Smrg } else { 687ec681f3Smrg ERROR_MSG("unknown device: %s", version->name); 697ec681f3Smrg dev = NULL; 707ec681f3Smrg } 717e102996Smaya 727e102996Smayaout: 737ec681f3Smrg drmFreeVersion(version); 747ec681f3Smrg 757ec681f3Smrg if (!dev) 767ec681f3Smrg return NULL; 777e102996Smaya 787ec681f3Smrg p_atomic_set(&dev->refcnt, 1); 797ec681f3Smrg dev->fd = fd; 807ec681f3Smrg dev->handle_table = 817ec681f3Smrg _mesa_hash_table_create(NULL, _mesa_hash_u32, _mesa_key_u32_equal); 827ec681f3Smrg dev->name_table = 837ec681f3Smrg _mesa_hash_table_create(NULL, _mesa_hash_u32, _mesa_key_u32_equal); 847ec681f3Smrg fd_bo_cache_init(&dev->bo_cache, false); 857ec681f3Smrg fd_bo_cache_init(&dev->ring_cache, true); 867e102996Smaya 877ec681f3Smrg list_inithead(&dev->deferred_submits); 887ec681f3Smrg simple_mtx_init(&dev->submit_lock, mtx_plain); 897e102996Smaya 907ec681f3Smrg return dev; 917e102996Smaya} 927e102996Smaya 937e102996Smaya/* like fd_device_new() but creates it's own private dup() of the fd 947e102996Smaya * which is close()d when the device is finalized. 957e102996Smaya */ 967ec681f3Smrgstruct fd_device * 977ec681f3Smrgfd_device_new_dup(int fd) 987e102996Smaya{ 997ec681f3Smrg int dup_fd = os_dupfd_cloexec(fd); 1007ec681f3Smrg struct fd_device *dev = fd_device_new(dup_fd); 1017ec681f3Smrg if (dev) 1027ec681f3Smrg dev->closefd = 1; 1037ec681f3Smrg else 1047ec681f3Smrg close(dup_fd); 1057ec681f3Smrg return dev; 1067e102996Smaya} 1077e102996Smaya 1087ec681f3Smrgstruct fd_device * 1097ec681f3Smrgfd_device_ref(struct fd_device *dev) 1107e102996Smaya{ 1117ec681f3Smrg p_atomic_inc(&dev->refcnt); 1127ec681f3Smrg return dev; 1137e102996Smaya} 1147e102996Smaya 1157ec681f3Smrgvoid 1167ec681f3Smrgfd_device_purge(struct fd_device *dev) 1177e102996Smaya{ 1187ec681f3Smrg simple_mtx_lock(&table_lock); 1197ec681f3Smrg fd_bo_cache_cleanup(&dev->bo_cache, 0); 1207ec681f3Smrg fd_bo_cache_cleanup(&dev->ring_cache, 0); 1217ec681f3Smrg simple_mtx_unlock(&table_lock); 1227e102996Smaya} 1237e102996Smaya 1247ec681f3Smrgstatic void 1257ec681f3Smrgfd_device_del_impl(struct fd_device *dev) 1267e102996Smaya{ 1277ec681f3Smrg int close_fd = dev->closefd ? dev->fd : -1; 1287ec681f3Smrg 1297ec681f3Smrg simple_mtx_assert_locked(&table_lock); 1307ec681f3Smrg 1317ec681f3Smrg assert(list_is_empty(&dev->deferred_submits)); 1327ec681f3Smrg 1337ec681f3Smrg fd_bo_cache_cleanup(&dev->bo_cache, 0); 1347ec681f3Smrg fd_bo_cache_cleanup(&dev->ring_cache, 0); 1357ec681f3Smrg _mesa_hash_table_destroy(dev->handle_table, NULL); 1367ec681f3Smrg _mesa_hash_table_destroy(dev->name_table, NULL); 1377ec681f3Smrg dev->funcs->destroy(dev); 1387ec681f3Smrg if (close_fd >= 0) 1397ec681f3Smrg close(close_fd); 1407ec681f3Smrg} 1417ec681f3Smrg 1427ec681f3Smrgvoid 1437ec681f3Smrgfd_device_del_locked(struct fd_device *dev) 1447ec681f3Smrg{ 1457ec681f3Smrg if (!p_atomic_dec_zero(&dev->refcnt)) 1467ec681f3Smrg return; 1477ec681f3Smrg fd_device_del_impl(dev); 1487ec681f3Smrg} 1497ec681f3Smrg 1507ec681f3Smrgvoid 1517ec681f3Smrgfd_device_del(struct fd_device *dev) 1527ec681f3Smrg{ 1537ec681f3Smrg if (!p_atomic_dec_zero(&dev->refcnt)) 1547ec681f3Smrg return; 1557ec681f3Smrg simple_mtx_lock(&table_lock); 1567ec681f3Smrg fd_device_del_impl(dev); 1577ec681f3Smrg simple_mtx_unlock(&table_lock); 1587e102996Smaya} 1597e102996Smaya 1607ec681f3Smrgint 1617ec681f3Smrgfd_device_fd(struct fd_device *dev) 1627e102996Smaya{ 1637ec681f3Smrg return dev->fd; 1647e102996Smaya} 1657e102996Smaya 1667ec681f3Smrgenum fd_version 1677ec681f3Smrgfd_device_version(struct fd_device *dev) 1687e102996Smaya{ 1697ec681f3Smrg return dev->version; 1707ec681f3Smrg} 1717ec681f3Smrg 1727ec681f3Smrgbool 1737ec681f3Smrgfd_dbg(void) 1747ec681f3Smrg{ 1757ec681f3Smrg static int dbg; 1767ec681f3Smrg 1777ec681f3Smrg if (!dbg) 1787ec681f3Smrg dbg = getenv("LIBGL_DEBUG") ? 1 : -1; 1797ec681f3Smrg 1807ec681f3Smrg return dbg == 1; 1817e102996Smaya} 1827e102996Smaya 1837ec681f3Smrgbool 1847ec681f3Smrgfd_has_syncobj(struct fd_device *dev) 1857e102996Smaya{ 1867ec681f3Smrg uint64_t value; 1877ec681f3Smrg if (drmGetCap(dev->fd, DRM_CAP_SYNCOBJ, &value)) 1887ec681f3Smrg return false; 1897ec681f3Smrg return value && dev->version >= FD_VERSION_FENCE_FD; 1907e102996Smaya} 191