amdgpu_device.c revision 5324fb0d
13f012e29Smrg/* 23f012e29Smrg * Copyright 2014 Advanced Micro Devices, Inc. 33f012e29Smrg * 43f012e29Smrg * Permission is hereby granted, free of charge, to any person obtaining a 53f012e29Smrg * copy of this software and associated documentation files (the "Software"), 63f012e29Smrg * to deal in the Software without restriction, including without limitation 73f012e29Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 83f012e29Smrg * and/or sell copies of the Software, and to permit persons to whom the 93f012e29Smrg * Software is furnished to do so, subject to the following conditions: 103f012e29Smrg * 113f012e29Smrg * The above copyright notice and this permission notice shall be included in 123f012e29Smrg * all copies or substantial portions of the Software. 133f012e29Smrg * 143f012e29Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 153f012e29Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 163f012e29Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 173f012e29Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 183f012e29Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 193f012e29Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 203f012e29Smrg * OTHER DEALINGS IN THE SOFTWARE. 213f012e29Smrg * 223f012e29Smrg */ 233f012e29Smrg 243f012e29Smrg/** 253f012e29Smrg * \file amdgpu_device.c 263f012e29Smrg * 273f012e29Smrg * Implementation of functions for AMD GPU device 283f012e29Smrg * 293f012e29Smrg */ 303f012e29Smrg 313f012e29Smrg#include <sys/stat.h> 323f012e29Smrg#include <errno.h> 333f012e29Smrg#include <string.h> 343f012e29Smrg#include <stdio.h> 353f012e29Smrg#include <stdlib.h> 363f012e29Smrg#include <unistd.h> 377cdc0497Smrg#include <fcntl.h> 383f012e29Smrg 393f012e29Smrg#include "xf86drm.h" 403f012e29Smrg#include "amdgpu_drm.h" 413f012e29Smrg#include "amdgpu_internal.h" 423f012e29Smrg#include "util_math.h" 433f012e29Smrg 443f012e29Smrg#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) 453f012e29Smrg 465324fb0dSmrgstatic pthread_mutex_t dev_mutex = PTHREAD_MUTEX_INITIALIZER; 475324fb0dSmrgstatic amdgpu_device_handle dev_list; 483f012e29Smrg 497cdc0497Smrgstatic int fd_compare(int fd1, int fd2) 503f012e29Smrg{ 513f012e29Smrg char *name1 = drmGetPrimaryDeviceNameFromFd(fd1); 523f012e29Smrg char *name2 = drmGetPrimaryDeviceNameFromFd(fd2); 533f012e29Smrg int result; 543f012e29Smrg 553f012e29Smrg if (name1 == NULL || name2 == NULL) { 563f012e29Smrg free(name1); 573f012e29Smrg free(name2); 583f012e29Smrg return 0; 593f012e29Smrg } 603f012e29Smrg 613f012e29Smrg result = strcmp(name1, name2); 623f012e29Smrg free(name1); 633f012e29Smrg free(name2); 643f012e29Smrg 653f012e29Smrg return result; 663f012e29Smrg} 673f012e29Smrg 683f012e29Smrg/** 693f012e29Smrg* Get the authenticated form fd, 703f012e29Smrg* 713f012e29Smrg* \param fd - \c [in] File descriptor for AMD GPU device 723f012e29Smrg* \param auth - \c [out] Pointer to output the fd is authenticated or not 733f012e29Smrg* A render node fd, output auth = 0 743f012e29Smrg* A legacy fd, get the authenticated for compatibility root 753f012e29Smrg* 763f012e29Smrg* \return 0 on success\n 773f012e29Smrg* >0 - AMD specific error code\n 783f012e29Smrg* <0 - Negative POSIX Error code 793f012e29Smrg*/ 803f012e29Smrgstatic int amdgpu_get_auth(int fd, int *auth) 813f012e29Smrg{ 823f012e29Smrg int r = 0; 833f012e29Smrg drm_client_t client = {}; 843f012e29Smrg 853f012e29Smrg if (drmGetNodeTypeFromFd(fd) == DRM_NODE_RENDER) 863f012e29Smrg *auth = 0; 873f012e29Smrg else { 883f012e29Smrg client.idx = 0; 893f012e29Smrg r = drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client); 903f012e29Smrg if (!r) 913f012e29Smrg *auth = client.auth; 923f012e29Smrg } 933f012e29Smrg return r; 943f012e29Smrg} 953f012e29Smrg 963f012e29Smrgstatic void amdgpu_device_free_internal(amdgpu_device_handle dev) 973f012e29Smrg{ 985324fb0dSmrg amdgpu_device_handle *node = &dev_list; 997cdc0497Smrg 1005324fb0dSmrg pthread_mutex_lock(&dev_mutex); 1017cdc0497Smrg while (*node != dev && (*node)->next) 1027cdc0497Smrg node = &(*node)->next; 1037cdc0497Smrg *node = (*node)->next; 1045324fb0dSmrg pthread_mutex_unlock(&dev_mutex); 1057cdc0497Smrg 1063f012e29Smrg close(dev->fd); 1073f012e29Smrg if ((dev->flink_fd >= 0) && (dev->fd != dev->flink_fd)) 1083f012e29Smrg close(dev->flink_fd); 1097cdc0497Smrg 1107cdc0497Smrg amdgpu_vamgr_deinit(&dev->vamgr_32); 1117cdc0497Smrg amdgpu_vamgr_deinit(&dev->vamgr); 1127cdc0497Smrg amdgpu_vamgr_deinit(&dev->vamgr_high_32); 1137cdc0497Smrg amdgpu_vamgr_deinit(&dev->vamgr_high); 1147cdc0497Smrg handle_table_fini(&dev->bo_handles); 1157cdc0497Smrg handle_table_fini(&dev->bo_flink_names); 1167cdc0497Smrg pthread_mutex_destroy(&dev->bo_table_mutex); 11700a23bdaSmrg free(dev->marketing_name); 1183f012e29Smrg free(dev); 1193f012e29Smrg} 1203f012e29Smrg 1213f012e29Smrg/** 1223f012e29Smrg * Assignment between two amdgpu_device pointers with reference counting. 1233f012e29Smrg * 1243f012e29Smrg * Usage: 1253f012e29Smrg * struct amdgpu_device *dst = ... , *src = ...; 1263f012e29Smrg * 1273f012e29Smrg * dst = src; 1283f012e29Smrg * // No reference counting. Only use this when you need to move 1293f012e29Smrg * // a reference from one pointer to another. 1303f012e29Smrg * 1313f012e29Smrg * amdgpu_device_reference(&dst, src); 1323f012e29Smrg * // Reference counters are updated. dst is decremented and src is 1333f012e29Smrg * // incremented. dst is freed if its reference counter is 0. 1343f012e29Smrg */ 1353f012e29Smrgstatic void amdgpu_device_reference(struct amdgpu_device **dst, 1367cdc0497Smrg struct amdgpu_device *src) 1373f012e29Smrg{ 1383f012e29Smrg if (update_references(&(*dst)->refcount, &src->refcount)) 1393f012e29Smrg amdgpu_device_free_internal(*dst); 1403f012e29Smrg *dst = src; 1413f012e29Smrg} 1423f012e29Smrg 1437cdc0497Smrgdrm_public int amdgpu_device_initialize(int fd, 1447cdc0497Smrg uint32_t *major_version, 1457cdc0497Smrg uint32_t *minor_version, 1467cdc0497Smrg amdgpu_device_handle *device_handle) 1473f012e29Smrg{ 1483f012e29Smrg struct amdgpu_device *dev; 1493f012e29Smrg drmVersionPtr version; 1503f012e29Smrg int r; 1513f012e29Smrg int flag_auth = 0; 1523f012e29Smrg int flag_authexist=0; 1533f012e29Smrg uint32_t accel_working = 0; 1543f012e29Smrg uint64_t start, max; 1553f012e29Smrg 1563f012e29Smrg *device_handle = NULL; 1573f012e29Smrg 1585324fb0dSmrg pthread_mutex_lock(&dev_mutex); 1593f012e29Smrg r = amdgpu_get_auth(fd, &flag_auth); 1603f012e29Smrg if (r) { 16100a23bdaSmrg fprintf(stderr, "%s: amdgpu_get_auth (1) failed (%i)\n", 16200a23bdaSmrg __func__, r); 1635324fb0dSmrg pthread_mutex_unlock(&dev_mutex); 1643f012e29Smrg return r; 1653f012e29Smrg } 1667cdc0497Smrg 1675324fb0dSmrg for (dev = dev_list; dev; dev = dev->next) 1687cdc0497Smrg if (fd_compare(dev->fd, fd) == 0) 1697cdc0497Smrg break; 1707cdc0497Smrg 1713f012e29Smrg if (dev) { 1723f012e29Smrg r = amdgpu_get_auth(dev->fd, &flag_authexist); 1733f012e29Smrg if (r) { 17400a23bdaSmrg fprintf(stderr, "%s: amdgpu_get_auth (2) failed (%i)\n", 17500a23bdaSmrg __func__, r); 1765324fb0dSmrg pthread_mutex_unlock(&dev_mutex); 1773f012e29Smrg return r; 1783f012e29Smrg } 1793f012e29Smrg if ((flag_auth) && (!flag_authexist)) { 1807cdc0497Smrg dev->flink_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); 1813f012e29Smrg } 1823f012e29Smrg *major_version = dev->major_version; 1833f012e29Smrg *minor_version = dev->minor_version; 1843f012e29Smrg amdgpu_device_reference(device_handle, dev); 1855324fb0dSmrg pthread_mutex_unlock(&dev_mutex); 1863f012e29Smrg return 0; 1873f012e29Smrg } 1883f012e29Smrg 1893f012e29Smrg dev = calloc(1, sizeof(struct amdgpu_device)); 1903f012e29Smrg if (!dev) { 19100a23bdaSmrg fprintf(stderr, "%s: calloc failed\n", __func__); 1925324fb0dSmrg pthread_mutex_unlock(&dev_mutex); 1933f012e29Smrg return -ENOMEM; 1943f012e29Smrg } 1953f012e29Smrg 1963f012e29Smrg dev->fd = -1; 1973f012e29Smrg dev->flink_fd = -1; 1983f012e29Smrg 1993f012e29Smrg atomic_set(&dev->refcount, 1); 2003f012e29Smrg 2013f012e29Smrg version = drmGetVersion(fd); 2023f012e29Smrg if (version->version_major != 3) { 2033f012e29Smrg fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is " 2043f012e29Smrg "only compatible with 3.x.x.\n", 2053f012e29Smrg __func__, 2063f012e29Smrg version->version_major, 2073f012e29Smrg version->version_minor, 2083f012e29Smrg version->version_patchlevel); 2093f012e29Smrg drmFreeVersion(version); 2103f012e29Smrg r = -EBADF; 2113f012e29Smrg goto cleanup; 2123f012e29Smrg } 2133f012e29Smrg 2147cdc0497Smrg dev->fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); 2153f012e29Smrg dev->flink_fd = dev->fd; 2163f012e29Smrg dev->major_version = version->version_major; 2173f012e29Smrg dev->minor_version = version->version_minor; 2183f012e29Smrg drmFreeVersion(version); 2193f012e29Smrg 2203f012e29Smrg pthread_mutex_init(&dev->bo_table_mutex, NULL); 2213f012e29Smrg 2223f012e29Smrg /* Check if acceleration is working. */ 2233f012e29Smrg r = amdgpu_query_info(dev, AMDGPU_INFO_ACCEL_WORKING, 4, &accel_working); 22400a23bdaSmrg if (r) { 22500a23bdaSmrg fprintf(stderr, "%s: amdgpu_query_info(ACCEL_WORKING) failed (%i)\n", 22600a23bdaSmrg __func__, r); 2273f012e29Smrg goto cleanup; 22800a23bdaSmrg } 2293f012e29Smrg if (!accel_working) { 23000a23bdaSmrg fprintf(stderr, "%s: AMDGPU_INFO_ACCEL_WORKING = 0\n", __func__); 2313f012e29Smrg r = -EBADF; 2323f012e29Smrg goto cleanup; 2333f012e29Smrg } 2343f012e29Smrg 2353f012e29Smrg r = amdgpu_query_gpu_info_init(dev); 23600a23bdaSmrg if (r) { 23700a23bdaSmrg fprintf(stderr, "%s: amdgpu_query_gpu_info_init failed\n", __func__); 2383f012e29Smrg goto cleanup; 23900a23bdaSmrg } 2403f012e29Smrg 24100a23bdaSmrg start = dev->dev_info.virtual_address_offset; 24200a23bdaSmrg max = MIN2(dev->dev_info.virtual_address_max, 0x100000000ULL); 24300a23bdaSmrg amdgpu_vamgr_init(&dev->vamgr_32, start, max, 2443f012e29Smrg dev->dev_info.virtual_address_alignment); 2453f012e29Smrg 24600a23bdaSmrg start = max; 24700a23bdaSmrg max = MAX2(dev->dev_info.virtual_address_max, 0x100000000ULL); 24800a23bdaSmrg amdgpu_vamgr_init(&dev->vamgr, start, max, 24900a23bdaSmrg dev->dev_info.virtual_address_alignment); 2503f012e29Smrg 25100a23bdaSmrg start = dev->dev_info.high_va_offset; 25200a23bdaSmrg max = MIN2(dev->dev_info.high_va_max, (start & ~0xffffffffULL) + 25300a23bdaSmrg 0x100000000ULL); 25400a23bdaSmrg amdgpu_vamgr_init(&dev->vamgr_high_32, start, max, 2553f012e29Smrg dev->dev_info.virtual_address_alignment); 2563f012e29Smrg 25700a23bdaSmrg start = max; 25800a23bdaSmrg max = MAX2(dev->dev_info.high_va_max, (start & ~0xffffffffULL) + 25900a23bdaSmrg 0x100000000ULL); 26000a23bdaSmrg amdgpu_vamgr_init(&dev->vamgr_high, start, max, 26100a23bdaSmrg dev->dev_info.virtual_address_alignment); 26200a23bdaSmrg 26300a23bdaSmrg amdgpu_parse_asic_ids(dev); 264d8807b2fSmrg 2653f012e29Smrg *major_version = dev->major_version; 2663f012e29Smrg *minor_version = dev->minor_version; 2673f012e29Smrg *device_handle = dev; 2685324fb0dSmrg dev->next = dev_list; 2695324fb0dSmrg dev_list = dev; 2705324fb0dSmrg pthread_mutex_unlock(&dev_mutex); 2713f012e29Smrg 2723f012e29Smrg return 0; 2733f012e29Smrg 2743f012e29Smrgcleanup: 2753f012e29Smrg if (dev->fd >= 0) 2763f012e29Smrg close(dev->fd); 2773f012e29Smrg free(dev); 2785324fb0dSmrg pthread_mutex_unlock(&dev_mutex); 2793f012e29Smrg return r; 2803f012e29Smrg} 2813f012e29Smrg 2827cdc0497Smrgdrm_public int amdgpu_device_deinitialize(amdgpu_device_handle dev) 2833f012e29Smrg{ 2843f012e29Smrg amdgpu_device_reference(&dev, NULL); 2853f012e29Smrg return 0; 2863f012e29Smrg} 287037b3c26Smrg 2887cdc0497Smrgdrm_public const char *amdgpu_get_marketing_name(amdgpu_device_handle dev) 289037b3c26Smrg{ 29000a23bdaSmrg return dev->marketing_name; 29100a23bdaSmrg} 292037b3c26Smrg 2937cdc0497Smrgdrm_public int amdgpu_query_sw_info(amdgpu_device_handle dev, 2947cdc0497Smrg enum amdgpu_sw_info info, 2957cdc0497Smrg void *value) 29600a23bdaSmrg{ 29700a23bdaSmrg uint32_t *val32 = (uint32_t*)value; 29800a23bdaSmrg 29900a23bdaSmrg switch (info) { 30000a23bdaSmrg case amdgpu_sw_info_address32_hi: 30100a23bdaSmrg if (dev->vamgr_high_32.va_max) 30200a23bdaSmrg *val32 = (dev->vamgr_high_32.va_max - 1) >> 32; 30300a23bdaSmrg else 30400a23bdaSmrg *val32 = (dev->vamgr_32.va_max - 1) >> 32; 30500a23bdaSmrg return 0; 306037b3c26Smrg } 30700a23bdaSmrg return -EINVAL; 308037b3c26Smrg} 309