etnaviv_device.c revision 7cdc0497
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> 28037b3c26Smrg#include <linux/stddef.h> 29037b3c26Smrg#include <linux/types.h> 30037b3c26Smrg#include <errno.h> 31037b3c26Smrg#include <sys/mman.h> 32037b3c26Smrg#include <fcntl.h> 33037b3c26Smrg#include <unistd.h> 34037b3c26Smrg#include <pthread.h> 35037b3c26Smrg 36037b3c26Smrg#include <xf86drm.h> 37037b3c26Smrg#include <xf86atomic.h> 38037b3c26Smrg 39037b3c26Smrg#include "etnaviv_priv.h" 40037b3c26Smrg#include "etnaviv_drmif.h" 41037b3c26Smrg 42037b3c26Smrgstatic pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER; 43037b3c26Smrg 447cdc0497Smrgdrm_public struct etna_device *etna_device_new(int fd) 45037b3c26Smrg{ 46037b3c26Smrg struct etna_device *dev = calloc(sizeof(*dev), 1); 47037b3c26Smrg 48037b3c26Smrg if (!dev) 49037b3c26Smrg return NULL; 50037b3c26Smrg 51037b3c26Smrg atomic_set(&dev->refcnt, 1); 52037b3c26Smrg dev->fd = fd; 53037b3c26Smrg dev->handle_table = drmHashCreate(); 54037b3c26Smrg dev->name_table = drmHashCreate(); 55037b3c26Smrg etna_bo_cache_init(&dev->bo_cache); 56037b3c26Smrg 57037b3c26Smrg return dev; 58037b3c26Smrg} 59037b3c26Smrg 60037b3c26Smrg/* like etna_device_new() but creates it's own private dup() of the fd 61037b3c26Smrg * which is close()d when the device is finalized. */ 627cdc0497Smrgdrm_public struct etna_device *etna_device_new_dup(int fd) 63037b3c26Smrg{ 64037b3c26Smrg int dup_fd = dup(fd); 65037b3c26Smrg struct etna_device *dev = etna_device_new(dup_fd); 66037b3c26Smrg 67037b3c26Smrg if (dev) 68037b3c26Smrg dev->closefd = 1; 69037b3c26Smrg else 70037b3c26Smrg close(dup_fd); 71037b3c26Smrg 72037b3c26Smrg return dev; 73037b3c26Smrg} 74037b3c26Smrg 757cdc0497Smrgdrm_public struct etna_device *etna_device_ref(struct etna_device *dev) 76037b3c26Smrg{ 77037b3c26Smrg atomic_inc(&dev->refcnt); 78037b3c26Smrg 79037b3c26Smrg return dev; 80037b3c26Smrg} 81037b3c26Smrg 82037b3c26Smrgstatic void etna_device_del_impl(struct etna_device *dev) 83037b3c26Smrg{ 84037b3c26Smrg etna_bo_cache_cleanup(&dev->bo_cache, 0); 85037b3c26Smrg drmHashDestroy(dev->handle_table); 86037b3c26Smrg drmHashDestroy(dev->name_table); 87037b3c26Smrg 88037b3c26Smrg if (dev->closefd) 89037b3c26Smrg close(dev->fd); 90037b3c26Smrg 91037b3c26Smrg free(dev); 92037b3c26Smrg} 93037b3c26Smrg 94037b3c26Smrgdrm_private void etna_device_del_locked(struct etna_device *dev) 95037b3c26Smrg{ 96037b3c26Smrg if (!atomic_dec_and_test(&dev->refcnt)) 97037b3c26Smrg return; 98037b3c26Smrg 99037b3c26Smrg etna_device_del_impl(dev); 100037b3c26Smrg} 101037b3c26Smrg 1027cdc0497Smrgdrm_public void etna_device_del(struct etna_device *dev) 103037b3c26Smrg{ 104037b3c26Smrg if (!atomic_dec_and_test(&dev->refcnt)) 105037b3c26Smrg return; 106037b3c26Smrg 107037b3c26Smrg pthread_mutex_lock(&table_lock); 108037b3c26Smrg etna_device_del_impl(dev); 109037b3c26Smrg pthread_mutex_unlock(&table_lock); 110037b3c26Smrg} 111037b3c26Smrg 1127cdc0497Smrgdrm_public int etna_device_fd(struct etna_device *dev) 113037b3c26Smrg{ 114037b3c26Smrg return dev->fd; 115037b3c26Smrg} 116