1037b3c26Smrg/* 2037b3c26Smrg * Copyright (C) 2014 Etnaviv Project 3037b3c26Smrg * 4037b3c26Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5037b3c26Smrg * copy of this software and associated documentation files (the "Software"), 6037b3c26Smrg * to deal in the Software without restriction, including without limitation 7037b3c26Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8037b3c26Smrg * and/or sell copies of the Software, and to permit persons to whom the 9037b3c26Smrg * Software is furnished to do so, subject to the following conditions: 10037b3c26Smrg * 11037b3c26Smrg * The above copyright notice and this permission notice (including the next 12037b3c26Smrg * paragraph) shall be included in all copies or substantial portions of the 13037b3c26Smrg * Software. 14037b3c26Smrg * 15037b3c26Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16037b3c26Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17037b3c26Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18037b3c26Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19037b3c26Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20037b3c26Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21037b3c26Smrg * SOFTWARE. 22037b3c26Smrg * 23037b3c26Smrg * Authors: 24037b3c26Smrg * Christian Gmeiner <christian.gmeiner@gmail.com> 25037b3c26Smrg */ 26037b3c26Smrg 27037b3c26Smrg#include <stdlib.h> 28bbff01ceSmrg#include <sys/types.h> 29037b3c26Smrg#include <errno.h> 30037b3c26Smrg#include <sys/mman.h> 31037b3c26Smrg#include <fcntl.h> 32037b3c26Smrg#include <unistd.h> 33037b3c26Smrg#include <pthread.h> 34037b3c26Smrg 35037b3c26Smrg#include <xf86drm.h> 36037b3c26Smrg#include <xf86atomic.h> 37037b3c26Smrg 38037b3c26Smrg#include "etnaviv_priv.h" 39037b3c26Smrg#include "etnaviv_drmif.h" 40037b3c26Smrg 41037b3c26Smrgstatic pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER; 42037b3c26Smrg 437cdc0497Smrgdrm_public struct etna_device *etna_device_new(int fd) 44037b3c26Smrg{ 45037b3c26Smrg struct etna_device *dev = calloc(sizeof(*dev), 1); 46037b3c26Smrg 47037b3c26Smrg if (!dev) 48037b3c26Smrg return NULL; 49037b3c26Smrg 50037b3c26Smrg atomic_set(&dev->refcnt, 1); 51037b3c26Smrg dev->fd = fd; 52037b3c26Smrg dev->handle_table = drmHashCreate(); 53037b3c26Smrg dev->name_table = drmHashCreate(); 54037b3c26Smrg etna_bo_cache_init(&dev->bo_cache); 55037b3c26Smrg 56037b3c26Smrg return dev; 57037b3c26Smrg} 58037b3c26Smrg 59037b3c26Smrg/* like etna_device_new() but creates it's own private dup() of the fd 60037b3c26Smrg * which is close()d when the device is finalized. */ 617cdc0497Smrgdrm_public struct etna_device *etna_device_new_dup(int fd) 62037b3c26Smrg{ 63037b3c26Smrg int dup_fd = dup(fd); 64037b3c26Smrg struct etna_device *dev = etna_device_new(dup_fd); 65037b3c26Smrg 66037b3c26Smrg if (dev) 67037b3c26Smrg dev->closefd = 1; 68037b3c26Smrg else 69037b3c26Smrg close(dup_fd); 70037b3c26Smrg 71037b3c26Smrg return dev; 72037b3c26Smrg} 73037b3c26Smrg 747cdc0497Smrgdrm_public struct etna_device *etna_device_ref(struct etna_device *dev) 75037b3c26Smrg{ 76037b3c26Smrg atomic_inc(&dev->refcnt); 77037b3c26Smrg 78037b3c26Smrg return dev; 79037b3c26Smrg} 80037b3c26Smrg 81037b3c26Smrgstatic void etna_device_del_impl(struct etna_device *dev) 82037b3c26Smrg{ 83037b3c26Smrg etna_bo_cache_cleanup(&dev->bo_cache, 0); 84037b3c26Smrg drmHashDestroy(dev->handle_table); 85037b3c26Smrg drmHashDestroy(dev->name_table); 86037b3c26Smrg 87037b3c26Smrg if (dev->closefd) 88037b3c26Smrg close(dev->fd); 89037b3c26Smrg 90037b3c26Smrg free(dev); 91037b3c26Smrg} 92037b3c26Smrg 93037b3c26Smrgdrm_private void etna_device_del_locked(struct etna_device *dev) 94037b3c26Smrg{ 95037b3c26Smrg if (!atomic_dec_and_test(&dev->refcnt)) 96037b3c26Smrg return; 97037b3c26Smrg 98037b3c26Smrg etna_device_del_impl(dev); 99037b3c26Smrg} 100037b3c26Smrg 1017cdc0497Smrgdrm_public void etna_device_del(struct etna_device *dev) 102037b3c26Smrg{ 103037b3c26Smrg if (!atomic_dec_and_test(&dev->refcnt)) 104037b3c26Smrg return; 105037b3c26Smrg 106037b3c26Smrg pthread_mutex_lock(&table_lock); 107037b3c26Smrg etna_device_del_impl(dev); 108037b3c26Smrg pthread_mutex_unlock(&table_lock); 109037b3c26Smrg} 110037b3c26Smrg 1117cdc0497Smrgdrm_public int etna_device_fd(struct etna_device *dev) 112037b3c26Smrg{ 113037b3c26Smrg return dev->fd; 114037b3c26Smrg} 115