mirror of OpenBSD xenocara tree github.com/openbsd/xenocara
openbsd
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at jcs 327 lines 8.6 kB view raw
1/* 2 * Copyright 2014 Advanced Micro Devices, Inc. 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 shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 24/** 25 * \file amdgpu_device.c 26 * 27 * Implementation of functions for AMD GPU device 28 * 29 */ 30 31#include <sys/stat.h> 32#include <errno.h> 33#include <string.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <unistd.h> 37#include <fcntl.h> 38 39#include "xf86drm.h" 40#include "amdgpu_drm.h" 41#include "amdgpu_internal.h" 42#include "util_math.h" 43 44#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) 45 46static pthread_mutex_t dev_mutex = PTHREAD_MUTEX_INITIALIZER; 47static amdgpu_device_handle dev_list; 48 49static int fd_compare(int fd1, int fd2) 50{ 51 char *name1 = drmGetPrimaryDeviceNameFromFd(fd1); 52 char *name2 = drmGetPrimaryDeviceNameFromFd(fd2); 53 int result; 54 55 if (name1 == NULL || name2 == NULL) { 56 free(name1); 57 free(name2); 58 return 0; 59 } 60 61 result = strcmp(name1, name2); 62 free(name1); 63 free(name2); 64 65 return result; 66} 67 68/** 69* Get the authenticated form fd, 70* 71* \param fd - \c [in] File descriptor for AMD GPU device 72* \param auth - \c [out] Pointer to output the fd is authenticated or not 73* A render node fd, output auth = 0 74* A legacy fd, get the authenticated for compatibility root 75* 76* \return 0 on success\n 77* >0 - AMD specific error code\n 78* <0 - Negative POSIX Error code 79*/ 80static int amdgpu_get_auth(int fd, int *auth) 81{ 82 int r = 0; 83 drm_client_t client = {}; 84 85 if (drmGetNodeTypeFromFd(fd) == DRM_NODE_RENDER) 86 *auth = 0; 87 else { 88 client.idx = 0; 89 r = drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client); 90 if (!r) 91 *auth = client.auth; 92 } 93 return r; 94} 95 96static void amdgpu_device_free_internal(amdgpu_device_handle dev) 97{ 98 /* Remove dev from dev_list, if it was added there. */ 99 if (dev == dev_list) { 100 dev_list = dev->next; 101 } else { 102 for (amdgpu_device_handle node = dev_list; node; node = node->next) { 103 if (node->next == dev) { 104 node->next = dev->next; 105 break; 106 } 107 } 108 } 109 110 close(dev->fd); 111 if ((dev->flink_fd >= 0) && (dev->fd != dev->flink_fd)) 112 close(dev->flink_fd); 113 114 amdgpu_vamgr_deinit(&dev->va_mgr.vamgr_32); 115 amdgpu_vamgr_deinit(&dev->va_mgr.vamgr_low); 116 amdgpu_vamgr_deinit(&dev->va_mgr.vamgr_high_32); 117 amdgpu_vamgr_deinit(&dev->va_mgr.vamgr_high); 118 handle_table_fini(&dev->bo_handles); 119 handle_table_fini(&dev->bo_flink_names); 120 pthread_mutex_destroy(&dev->bo_table_mutex); 121 free(dev->marketing_name); 122 free(dev); 123} 124 125/** 126 * Assignment between two amdgpu_device pointers with reference counting. 127 * 128 * Usage: 129 * struct amdgpu_device *dst = ... , *src = ...; 130 * 131 * dst = src; 132 * // No reference counting. Only use this when you need to move 133 * // a reference from one pointer to another. 134 * 135 * amdgpu_device_reference(&dst, src); 136 * // Reference counters are updated. dst is decremented and src is 137 * // incremented. dst is freed if its reference counter is 0. 138 */ 139static void amdgpu_device_reference(struct amdgpu_device **dst, 140 struct amdgpu_device *src) 141{ 142 if (update_references(&(*dst)->refcount, &src->refcount)) 143 amdgpu_device_free_internal(*dst); 144 *dst = src; 145} 146 147static int _amdgpu_device_initialize(int fd, 148 uint32_t *major_version, 149 uint32_t *minor_version, 150 amdgpu_device_handle *device_handle, 151 bool deduplicate_device) 152{ 153 struct amdgpu_device *dev = NULL; 154 drmVersionPtr version; 155 int r; 156 int flag_auth = 0; 157 int flag_authexist=0; 158 uint32_t accel_working = 0; 159 160 *device_handle = NULL; 161 162 pthread_mutex_lock(&dev_mutex); 163 164 r = amdgpu_get_auth(fd, &flag_auth); 165 if (r) { 166 fprintf(stderr, "%s: amdgpu_get_auth (1) failed (%i)\n", 167 __func__, r); 168 pthread_mutex_unlock(&dev_mutex); 169 return r; 170 } 171 172 if (deduplicate_device) 173 for (dev = dev_list; dev; dev = dev->next) 174 if (fd_compare(dev->fd, fd) == 0) 175 break; 176 177 if (dev) { 178 r = amdgpu_get_auth(dev->fd, &flag_authexist); 179 if (r) { 180 fprintf(stderr, "%s: amdgpu_get_auth (2) failed (%i)\n", 181 __func__, r); 182 pthread_mutex_unlock(&dev_mutex); 183 return r; 184 } 185 if ((flag_auth) && (!flag_authexist)) { 186 dev->flink_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); 187 } 188 *major_version = dev->major_version; 189 *minor_version = dev->minor_version; 190 amdgpu_device_reference(device_handle, dev); 191 pthread_mutex_unlock(&dev_mutex); 192 return 0; 193 } 194 195 dev = calloc(1, sizeof(struct amdgpu_device)); 196 if (!dev) { 197 fprintf(stderr, "%s: calloc failed\n", __func__); 198 pthread_mutex_unlock(&dev_mutex); 199 return -ENOMEM; 200 } 201 202 dev->fd = -1; 203 dev->flink_fd = -1; 204 205 atomic_set(&dev->refcount, 1); 206 207 version = drmGetVersion(fd); 208 if (version->version_major != 3) { 209 fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is " 210 "only compatible with 3.x.x.\n", 211 __func__, 212 version->version_major, 213 version->version_minor, 214 version->version_patchlevel); 215 drmFreeVersion(version); 216 r = -EBADF; 217 goto cleanup; 218 } 219 220 dev->fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); 221 dev->flink_fd = dev->fd; 222 dev->major_version = version->version_major; 223 dev->minor_version = version->version_minor; 224 drmFreeVersion(version); 225 226 pthread_mutex_init(&dev->bo_table_mutex, NULL); 227 228 /* Check if acceleration is working. */ 229 r = amdgpu_query_info(dev, AMDGPU_INFO_ACCEL_WORKING, 4, &accel_working); 230 if (r) { 231 fprintf(stderr, "%s: amdgpu_query_info(ACCEL_WORKING) failed (%i)\n", 232 __func__, r); 233 goto cleanup; 234 } 235 if (!accel_working) { 236 fprintf(stderr, "%s: AMDGPU_INFO_ACCEL_WORKING = 0\n", __func__); 237 r = -EBADF; 238 goto cleanup; 239 } 240 241 r = amdgpu_query_gpu_info_init(dev); 242 if (r) { 243 fprintf(stderr, "%s: amdgpu_query_gpu_info_init failed\n", __func__); 244 goto cleanup; 245 } 246 247 amdgpu_va_manager_init(&dev->va_mgr, 248 dev->dev_info.virtual_address_offset, 249 dev->dev_info.virtual_address_max, 250 dev->dev_info.high_va_offset, 251 dev->dev_info.high_va_max, 252 dev->dev_info.virtual_address_alignment); 253 254 amdgpu_parse_asic_ids(dev); 255 256 *major_version = dev->major_version; 257 *minor_version = dev->minor_version; 258 *device_handle = dev; 259 if (deduplicate_device) { 260 dev->next = dev_list; 261 dev_list = dev; 262 } 263 pthread_mutex_unlock(&dev_mutex); 264 265 return 0; 266 267cleanup: 268 if (dev->fd >= 0) 269 close(dev->fd); 270 free(dev); 271 pthread_mutex_unlock(&dev_mutex); 272 return r; 273} 274 275drm_public int amdgpu_device_initialize(int fd, 276 uint32_t *major_version, 277 uint32_t *minor_version, 278 amdgpu_device_handle *device_handle) 279{ 280 return _amdgpu_device_initialize(fd, major_version, minor_version, device_handle, true); 281} 282 283drm_public int amdgpu_device_initialize2(int fd, bool deduplicate_device, 284 uint32_t *major_version, 285 uint32_t *minor_version, 286 amdgpu_device_handle *device_handle) 287{ 288 return _amdgpu_device_initialize(fd, major_version, minor_version, device_handle, deduplicate_device); 289} 290 291drm_public int amdgpu_device_deinitialize(amdgpu_device_handle dev) 292{ 293 pthread_mutex_lock(&dev_mutex); 294 amdgpu_device_reference(&dev, NULL); 295 pthread_mutex_unlock(&dev_mutex); 296 return 0; 297} 298 299drm_public int amdgpu_device_get_fd(amdgpu_device_handle device_handle) 300{ 301 return device_handle->fd; 302} 303 304drm_public const char *amdgpu_get_marketing_name(amdgpu_device_handle dev) 305{ 306 if (dev->marketing_name) 307 return dev->marketing_name; 308 else 309 return "AMD Radeon Graphics"; 310} 311 312drm_public int amdgpu_query_sw_info(amdgpu_device_handle dev, 313 enum amdgpu_sw_info info, 314 void *value) 315{ 316 uint32_t *val32 = (uint32_t*)value; 317 318 switch (info) { 319 case amdgpu_sw_info_address32_hi: 320 if (dev->va_mgr.vamgr_high_32.va_max) 321 *val32 = (dev->va_mgr.vamgr_high_32.va_max - 1) >> 32; 322 else 323 *val32 = (dev->va_mgr.vamgr_32.va_max - 1) >> 32; 324 return 0; 325 } 326 return -EINVAL; 327}