diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index 59a35923c4b..a816e9c81a5 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -45,6 +45,38 @@ radeon_bo_ref_existing(struct radeon_bo *bo) return true; } +/* GEM handles are only valid for the DRM file that created/imported them. + * When internal work uses a render-node FD, KMS/shared exports still need a + * handle for the original app FD, so translate it once and cache the result. + */ +static bool +radeon_bo_get_display_handle(struct radeon_bo *bo, uint32_t *handle) +{ + struct radeon_drm_winsys *ws = bo->rws; + int dma_fd; + + if (ws->fd == ws->ioctl_fd) { + *handle = bo->handle; + return true; + } + + if (!bo->display_handle) { + if (drmPrimeHandleToFD(ws->ioctl_fd, bo->handle, + DRM_CLOEXEC | DRM_RDWR, &dma_fd)) + return false; + + if (drmPrimeFDToHandle(ws->fd, dma_fd, &bo->display_handle)) { + close(dma_fd); + return false; + } + + close(dma_fd); + } + + *handle = bo->display_handle; + return true; +} + struct radeon_bo_va_hole { struct list_head list; uint64_t offset; @@ -56,7 +88,7 @@ static bool radeon_real_bo_is_busy(struct radeon_bo *bo) struct drm_radeon_gem_busy args = {0}; args.handle = bo->handle; - return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY, + return drmCommandWriteRead(bo->rws->ioctl_fd, DRM_RADEON_GEM_BUSY, &args, sizeof(args)) != 0; } @@ -89,7 +121,7 @@ static void radeon_real_bo_wait_idle(struct radeon_bo *bo) struct drm_radeon_gem_wait_idle args = {0}; args.handle = bo->handle; - while (drmCommandWrite(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE, + while (drmCommandWrite(bo->rws->ioctl_fd, DRM_RADEON_GEM_WAIT_IDLE, &args, sizeof(args)) == -EBUSY); } @@ -175,7 +207,7 @@ static enum radeon_bo_domain radeon_bo_get_initial_domain( args.handle = bo->handle; args.op = RADEON_GEM_OP_GET_INITIAL_DOMAIN; - if (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_OP, + if (drmCommandWriteRead(bo->rws->ioctl_fd, DRM_RADEON_GEM_OP, &args, sizeof(args))) { fprintf(stderr, "radeon: failed to get initial domain: %p 0x%08X\n", bo, bo->handle); @@ -372,7 +404,7 @@ void radeon_bo_destroy(void *winsys, struct pb_buffer_lean *_buf) RADEON_VM_PAGE_SNOOPED; va.offset = bo->va; - if (drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_VA, &va, + if (drmCommandWriteRead(rws->ioctl_fd, DRM_RADEON_GEM_VA, &va, sizeof(va)) != 0 && va.operation == RADEON_VA_RESULT_ERROR) { fprintf(stderr, "radeon: Failed to deallocate virtual address for buffer:\n"); @@ -388,7 +420,12 @@ void radeon_bo_destroy(void *winsys, struct pb_buffer_lean *_buf) /* Close object. */ args.handle = bo->handle; - drmIoctl(rws->fd, DRM_IOCTL_GEM_CLOSE, &args); + drmIoctl(rws->ioctl_fd, DRM_IOCTL_GEM_CLOSE, &args); + + if (bo->display_handle) { + args.handle = bo->display_handle; + drmIoctl(rws->fd, DRM_IOCTL_GEM_CLOSE, &args); + } mtx_destroy(&bo->u.real.map_mutex); @@ -449,7 +486,7 @@ void *radeon_bo_do_map(struct radeon_bo *bo) args.handle = bo->handle; args.offset = 0; args.size = (uint64_t)bo->base.size; - if (drmCommandWriteRead(bo->rws->fd, + if (drmCommandWriteRead(bo->rws->ioctl_fd, DRM_RADEON_GEM_MMAP, &args, sizeof(args))) { @@ -460,13 +497,13 @@ void *radeon_bo_do_map(struct radeon_bo *bo) } ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, - bo->rws->fd, args.addr_ptr); + bo->rws->ioctl_fd, args.addr_ptr); if (ptr == MAP_FAILED) { /* Clear the cache and try again. */ pb_cache_release_all_buffers(&bo->rws->bo_cache); ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, - bo->rws->fd, args.addr_ptr); + bo->rws->ioctl_fd, args.addr_ptr); if (ptr == MAP_FAILED) { mtx_unlock(&bo->u.real.map_mutex); fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); @@ -636,7 +673,7 @@ static struct radeon_bo *radeon_create_bo(struct radeon_drm_winsys *rws, if (flags & RADEON_FLAG_NO_CPU_ACCESS) args.flags |= RADEON_GEM_NO_CPU_ACCESS; - if (drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_CREATE, + if (drmCommandWriteRead(rws->ioctl_fd, DRM_RADEON_GEM_CREATE, &args, sizeof(args))) { fprintf(stderr, "radeon: Failed to allocate a buffer:\n"); fprintf(stderr, "radeon: size : %u bytes\n", size); @@ -689,7 +726,7 @@ static struct radeon_bo *radeon_create_bo(struct radeon_drm_winsys *rws, RADEON_VM_PAGE_WRITEABLE | RADEON_VM_PAGE_SNOOPED; va.offset = bo->va; - r = drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_VA, &va, sizeof(va)); + r = drmCommandWriteRead(rws->ioctl_fd, DRM_RADEON_GEM_VA, &va, sizeof(va)); if (r && va.operation == RADEON_VA_RESULT_ERROR) { fprintf(stderr, "radeon: Failed to allocate virtual address for buffer:\n"); fprintf(stderr, "radeon: size : %d bytes\n", size); @@ -866,7 +903,7 @@ static void radeon_bo_get_metadata(struct radeon_winsys *rws, args.handle = bo->handle; - drmCommandWriteRead(bo->rws->fd, + drmCommandWriteRead(bo->rws->ioctl_fd, DRM_RADEON_GEM_GET_TILING, &args, sizeof(args)); @@ -975,7 +1012,7 @@ static void radeon_bo_set_metadata(struct radeon_winsys *rws, args.handle = bo->handle; - drmCommandWriteRead(bo->rws->fd, + drmCommandWriteRead(bo->rws->ioctl_fd, DRM_RADEON_GEM_SET_TILING, &args, sizeof(args)); @@ -1097,7 +1134,7 @@ static struct pb_buffer_lean *radeon_winsys_bo_from_ptr(struct radeon_winsys *rw RADEON_GEM_USERPTR_REGISTER | RADEON_GEM_USERPTR_VALIDATE; - if (drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_USERPTR, + if (drmCommandWriteRead(ws->ioctl_fd, DRM_RADEON_GEM_USERPTR, &args, sizeof(args))) { FREE(bo); return NULL; @@ -1136,7 +1173,7 @@ static struct pb_buffer_lean *radeon_winsys_bo_from_ptr(struct radeon_winsys *rw RADEON_VM_PAGE_WRITEABLE | RADEON_VM_PAGE_SNOOPED; va.offset = bo->va; - r = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_VA, &va, sizeof(va)); + r = drmCommandWriteRead(ws->ioctl_fd, DRM_RADEON_GEM_VA, &va, sizeof(va)); if (r && va.operation == RADEON_VA_RESULT_ERROR) { fprintf(stderr, "radeon: Failed to assign virtual address space\n"); radeon_bo_destroy(NULL, &bo->base); @@ -1185,8 +1222,10 @@ static struct pb_buffer_lean *radeon_winsys_bo_from_handle(struct radeon_winsys /* First check if there already is an existing bo for the handle. */ bo = util_hash_table_get(ws->bo_names, (void*)(uintptr_t)whandle->handle); } else if (whandle->type == WINSYS_HANDLE_TYPE_FD) { - /* We must first get the GEM handle, as fds are unreliable keys */ - r = drmPrimeFDToHandle(ws->fd, whandle->handle, &handle); + /* dma-buf FDs are process-local and unsuitable as cache keys. + * Look up the imported BO via its GEM handle on ws->ioctl_fd. + */ + r = drmPrimeFDToHandle(ws->ioctl_fd, whandle->handle, &handle); if (r) goto fail; bo = util_hash_table_get(ws->bo_handles, (void*)(uintptr_t)handle); @@ -1208,8 +1247,9 @@ static struct pb_buffer_lean *radeon_winsys_bo_from_handle(struct radeon_winsys if (whandle->type == WINSYS_HANDLE_TYPE_SHARED) { struct drm_gem_open open_arg = {}; + struct drm_gem_close close_arg = {}; memset(&open_arg, 0, sizeof(open_arg)); - /* Open the BO. */ + /* GEM flink names are tied to the original app FD, so open on ws->fd. */ open_arg.name = whandle->handle; if (drmIoctl(ws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) { FREE(bo); @@ -1218,6 +1258,55 @@ static struct pb_buffer_lean *radeon_winsys_bo_from_handle(struct radeon_winsys handle = open_arg.handle; size = open_arg.size; bo->flink_name = whandle->handle; + + if (ws->fd != ws->ioctl_fd) { + int dma_fd; + + /* Internal BO tracking and command submission use ws->ioctl_fd. + * When that differs from ws->fd, convert the temporary GEM handle + * from ws->fd into a dma-buf and re-import it on ws->ioctl_fd, so + * bo->handle always names the object on the internal ioctl fd. + */ + if (drmPrimeHandleToFD(ws->fd, open_arg.handle, DRM_CLOEXEC | DRM_RDWR, + &dma_fd)) { + close_arg.handle = open_arg.handle; + drmIoctl(ws->fd, DRM_IOCTL_GEM_CLOSE, &close_arg); + FREE(bo); + goto fail; + } + + r = drmPrimeFDToHandle(ws->ioctl_fd, dma_fd, &handle); + close(dma_fd); + + close_arg.handle = open_arg.handle; + drmIoctl(ws->fd, DRM_IOCTL_GEM_CLOSE, &close_arg); + + if (r) { + FREE(bo); + goto fail; + } + + /* Mixed legacy-name and dma-buf imports of the same object should + * still resolve to a single winsys BO keyed by the ioctl_fd handle. + */ + struct radeon_bo *existing = util_hash_table_get(ws->bo_handles, + (void*)(uintptr_t)handle); + if (existing) { + if (radeon_bo_ref_existing(existing)) { + FREE(bo); + assert(!existing->flink_name || + existing->flink_name == whandle->handle); + if (!existing->flink_name) { + existing->flink_name = whandle->handle; + _mesa_hash_table_insert(ws->bo_names, + (void*)(uintptr_t)existing->flink_name, + existing); + } + bo = existing; + goto done; + } + } + } } else if (whandle->type == WINSYS_HANDLE_TYPE_FD) { size = lseek(whandle->handle, 0, SEEK_END); /* @@ -1233,6 +1322,7 @@ static struct pb_buffer_lean *radeon_winsys_bo_from_handle(struct radeon_winsys assert(handle != 0); + /* bo->handle is always the GEM handle valid on ws->ioctl_fd. */ bo->handle = handle; /* Initialize it. */ @@ -1265,7 +1355,7 @@ done: RADEON_VM_PAGE_WRITEABLE | RADEON_VM_PAGE_SNOOPED; va.offset = bo->va; - r = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_VA, &va, sizeof(va)); + r = drmCommandWriteRead(ws->ioctl_fd, DRM_RADEON_GEM_VA, &va, sizeof(va)); if (r && va.operation == RADEON_VA_RESULT_ERROR) { fprintf(stderr, "radeon: Failed to assign virtual address space\n"); radeon_bo_destroy(NULL, &bo->base); @@ -1317,8 +1407,13 @@ static bool radeon_winsys_bo_get_handle(struct radeon_winsys *rws, bo->u.real.use_reusable_pool = false; if (whandle->type == WINSYS_HANDLE_TYPE_SHARED) { + uint32_t handle; + if (!bo->flink_name) { - flink.handle = bo->handle; + if (!radeon_bo_get_display_handle(bo, &handle)) + return false; + + flink.handle = handle; if (ioctl(ws->fd, DRM_IOCTL_GEM_FLINK, &flink)) { return false; @@ -1332,9 +1427,15 @@ static bool radeon_winsys_bo_get_handle(struct radeon_winsys *rws, } whandle->handle = bo->flink_name; } else if (whandle->type == WINSYS_HANDLE_TYPE_KMS) { - whandle->handle = bo->handle; + uint32_t handle; + + if (!radeon_bo_get_display_handle(bo, &handle)) + return false; + + whandle->handle = handle; } else if (whandle->type == WINSYS_HANDLE_TYPE_FD) { - if (drmPrimeHandleToFD(ws->fd, bo->handle, DRM_CLOEXEC | DRM_RDWR, (int*)&whandle->handle)) + if (drmPrimeHandleToFD(ws->ioctl_fd, bo->handle, + DRM_CLOEXEC | DRM_RDWR, (int*)&whandle->handle)) return false; } diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.h b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h index 5f4553edc42..9f909981c79 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h @@ -37,6 +37,7 @@ struct radeon_bo { void *user_ptr; /* from buffer_from_ptr */ uint32_t handle; /* 0 for slab entries */ + uint32_t display_handle; /* GEM handle valid for rws->fd when it differs. */ uint32_t flink_name; uint64_t va; uint32_t hash; diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c index 22e604fe8f2..fb3704a4e88 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c @@ -110,7 +110,7 @@ static bool radeon_init_cs_context(struct radeon_cs_context *csc, { int i; - csc->fd = ws->fd; + csc->fd = ws->ioctl_fd; csc->chunks[0].chunk_id = RADEON_CHUNK_ID_IB; csc->chunks[0].length_dw = 0; diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index e748eab22f9..f8180068030 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -31,6 +32,24 @@ static struct hash_table *fd_tab = NULL; static simple_mtx_t fd_tab_mutex = SIMPLE_MTX_INITIALIZER; +static int +radeon_open_render_node(int fd) +{ + char *render_device; + int render_fd = -1; + + if (drmGetNodeTypeFromFd(fd) == DRM_NODE_RENDER) + return -1; + + render_device = drmGetRenderDeviceNameFromFd(fd); + if (!render_device) + return -1; + + render_fd = open(render_device, O_RDWR | O_CLOEXEC); + free(render_device); + return render_fd; +} + /* Enable/disable feature access for one command stream. * If enable == true, return true on success. * Otherwise, return false. @@ -66,7 +85,7 @@ static bool radeon_set_fd_access(struct radeon_drm_cs *applier, /* Pass through the request to the kernel. */ info.value = (unsigned long)&value; info.request = request; - if (drmCommandWriteRead(applier->ws->fd, DRM_RADEON_INFO, + if (drmCommandWriteRead(applier->ws->ioctl_fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0) { mtx_unlock(&*mutex); return false; @@ -87,7 +106,7 @@ static bool radeon_set_fd_access(struct radeon_drm_cs *applier, return false; } -static bool radeon_get_drm_value(int fd, unsigned request, +static bool radeon_get_drm_value(struct radeon_drm_winsys *ws, unsigned request, const char *errname, uint32_t *out) { struct drm_radeon_info info; @@ -98,7 +117,7 @@ static bool radeon_get_drm_value(int fd, unsigned request, info.value = (unsigned long)out; info.request = request; - retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); + retval = drmCommandWriteRead(ws->ioctl_fd, DRM_RADEON_INFO, &info, sizeof(info)); if (retval) { if (errname) { fprintf(stderr, "radeon: Failed to get %s, error number %d\n", @@ -204,7 +223,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) */ /* Get DRM version. */ - version = drmGetVersion(ws->fd); + version = drmGetVersion(ws->ioctl_fd); if (!version) return false; @@ -227,7 +246,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) drmFreeVersion(version); /* Get PCI ID. */ - if (!radeon_get_drm_value(ws->fd, RADEON_INFO_DEVICE_ID, "PCI ID", + if (!radeon_get_drm_value(ws, RADEON_INFO_DEVICE_ID, "PCI ID", &ws->info.pci_id)) return false; @@ -371,16 +390,16 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) ws->info.vce_fw_version = 0x00000000; uint32_t value = RADEON_CS_RING_UVD; - if (radeon_get_drm_value(ws->fd, RADEON_INFO_RING_WORKING, + if (radeon_get_drm_value(ws, RADEON_INFO_RING_WORKING, "UVD Ring working", &value)) { ws->info.ip[AMD_IP_UVD].num_queues = 1; } value = RADEON_CS_RING_VCE; - if (radeon_get_drm_value(ws->fd, RADEON_INFO_RING_WORKING, + if (radeon_get_drm_value(ws, RADEON_INFO_RING_WORKING, NULL, &value) && value) { - if (radeon_get_drm_value(ws->fd, RADEON_INFO_VCE_FW_VERSION, + if (radeon_get_drm_value(ws, RADEON_INFO_VCE_FW_VERSION, "VCE FW version", &value)) { ws->info.vce_fw_version = value; ws->info.ip[AMD_IP_VCE].num_queues = 1; @@ -398,12 +417,12 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) * aren't set. */ ws->info.has_userptr = - drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_USERPTR, + drmCommandWriteRead(ws->ioctl_fd, DRM_RADEON_GEM_USERPTR, &args, sizeof(args)) == -EACCES; } /* Get GEM info. */ - retval = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_INFO, + retval = drmCommandWriteRead(ws->ioctl_fd, DRM_RADEON_GEM_INFO, &gem_info, sizeof(gem_info)); if (retval) { fprintf(stderr, "radeon: Failed to get MM info, error number %d\n", @@ -427,7 +446,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) ws->info.max_heap_size_kb = MIN2(ws->info.max_heap_size_kb, 4 * 1024 * 1024); /* 4 GB */ /* Get max clock frequency info and convert it to MHz */ - radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SCLK, NULL, + radeon_get_drm_value(ws, RADEON_INFO_MAX_SCLK, NULL, &ws->info.max_gpu_freq_mhz); ws->info.max_gpu_freq_mhz /= 1000; @@ -435,12 +454,12 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) /* Generation-specific queries. */ if (ws->gen == DRV_R300) { - if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_GB_PIPES, + if (!radeon_get_drm_value(ws, RADEON_INFO_NUM_GB_PIPES, "GB pipe count", &ws->info.r300_num_gb_pipes)) return false; - if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_Z_PIPES, + if (!radeon_get_drm_value(ws, RADEON_INFO_NUM_Z_PIPES, "Z pipe count", &ws->info.r300_num_z_pipes)) return false; @@ -448,16 +467,16 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) else if (ws->gen >= DRV_R600) { uint32_t tiling_config = 0; - if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_BACKENDS, + if (!radeon_get_drm_value(ws, RADEON_INFO_NUM_BACKENDS, "num backends", &ws->info.max_render_backends)) return false; /* get the GPU counter frequency, failure is not fatal */ - radeon_get_drm_value(ws->fd, RADEON_INFO_CLOCK_CRYSTAL_FREQ, NULL, + radeon_get_drm_value(ws, RADEON_INFO_CLOCK_CRYSTAL_FREQ, NULL, &ws->info.clock_crystal_freq); - radeon_get_drm_value(ws->fd, RADEON_INFO_TILING_CONFIG, NULL, + radeon_get_drm_value(ws, RADEON_INFO_TILING_CONFIG, NULL, &tiling_config); ws->info.r600_num_banks = @@ -474,7 +493,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) ws->info.r600_pipe_interleave_bytes = ws->info.gfx_level >= EVERGREEN ? 512 : 256; - radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_TILE_PIPES, NULL, + radeon_get_drm_value(ws, RADEON_INFO_NUM_TILE_PIPES, NULL, &ws->info.num_tile_pipes); /* "num_tiles_pipes" must be equal to the number of pipes (Px) in the @@ -485,7 +504,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) if (ws->gen == DRV_SI && ws->info.num_tile_pipes == 12) ws->info.num_tile_pipes = 8; - if (radeon_get_drm_value(ws->fd, RADEON_INFO_BACKEND_MAP, NULL, + if (radeon_get_drm_value(ws, RADEON_INFO_BACKEND_MAP, NULL, &ws->info.r600_gb_backend_map)) ws->info.r600_gb_backend_map_valid = true; @@ -498,7 +517,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) if (ws->gen >= DRV_SI) { uint32_t mask; - radeon_get_drm_value(ws->fd, RADEON_INFO_SI_BACKEND_ENABLED_MASK, NULL, &mask); + radeon_get_drm_value(ws, RADEON_INFO_SI_BACKEND_ENABLED_MASK, NULL, &mask); ws->info.enabled_rb_mask = mask; } @@ -507,13 +526,13 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) uint32_t ib_vm_max_size; ws->info.r600_has_virtual_memory = true; - if (!radeon_get_drm_value(ws->fd, RADEON_INFO_VA_START, NULL, + if (!radeon_get_drm_value(ws, RADEON_INFO_VA_START, NULL, &ws->va_start)) ws->info.r600_has_virtual_memory = false; - if (!radeon_get_drm_value(ws->fd, RADEON_INFO_IB_VM_MAX_SIZE, NULL, + if (!radeon_get_drm_value(ws, RADEON_INFO_IB_VM_MAX_SIZE, NULL, &ib_vm_max_size)) ws->info.r600_has_virtual_memory = false; - radeon_get_drm_value(ws->fd, RADEON_INFO_VA_UNMAP_WORKING, NULL, + radeon_get_drm_value(ws, RADEON_INFO_VA_UNMAP_WORKING, NULL, &ws->va_unmap_working); if (ws->gen == DRV_R600 && !debug_get_bool_option("RADEON_VA", false)) @@ -523,15 +542,15 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) /* Get max pipes, this is only needed for compute shaders. All evergreen+ * chips have at least 2 pipes, so we use 2 as a default. */ ws->info.r600_max_quad_pipes = 2; - radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_PIPES, NULL, + radeon_get_drm_value(ws, RADEON_INFO_MAX_PIPES, NULL, &ws->info.r600_max_quad_pipes); /* All GPUs have at least one compute unit */ ws->info.num_cu = 1; - radeon_get_drm_value(ws->fd, RADEON_INFO_ACTIVE_CU_COUNT, NULL, + radeon_get_drm_value(ws, RADEON_INFO_ACTIVE_CU_COUNT, NULL, &ws->info.num_cu); - radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SE, NULL, + radeon_get_drm_value(ws, RADEON_INFO_MAX_SE, NULL, &ws->info.max_se); switch (ws->info.family) { @@ -581,7 +600,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) ws->info.num_se = ws->info.max_se; - radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SH_PER_SE, NULL, + radeon_get_drm_value(ws, RADEON_INFO_MAX_SH_PER_SE, NULL, &ws->info.max_sa_per_se); if (ws->gen == DRV_SI) { ws->info.max_good_cu_per_sa = @@ -589,7 +608,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) (ws->info.max_se * ws->info.max_sa_per_se); } - radeon_get_drm_value(ws->fd, RADEON_INFO_ACCEL_WORKING2, NULL, + radeon_get_drm_value(ws, RADEON_INFO_ACCEL_WORKING2, NULL, &ws->accel_working2); if (ws->info.family == CHIP_HAWAII && ws->accel_working2 < 2) { fprintf(stderr, "radeon: GPU acceleration for Hawaii disabled, " @@ -600,7 +619,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) } if (ws->info.gfx_level == GFX7) { - if (!radeon_get_drm_value(ws->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, NULL, + if (!radeon_get_drm_value(ws, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, NULL, ws->info.cik_macrotile_mode_array)) { fprintf(stderr, "radeon: Kernel 3.13 is required for Sea Islands support.\n"); return false; @@ -608,7 +627,7 @@ static bool do_winsys_init(struct radeon_drm_winsys *ws) } if (ws->info.gfx_level >= GFX6) { - if (!radeon_get_drm_value(ws->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, NULL, + if (!radeon_get_drm_value(ws, RADEON_INFO_SI_TILE_MODE_ARRAY, NULL, ws->info.si_tile_mode_array)) { fprintf(stderr, "radeon: Kernel 3.10 is required for Southern Islands support.\n"); return false; @@ -738,6 +757,8 @@ static void radeon_winsys_destroy(struct radeon_winsys *rws) mtx_destroy(&ws->vm64.mutex); mtx_destroy(&ws->bo_fence_lock); + if (ws->ioctl_fd >= 0 && ws->ioctl_fd != ws->fd) + close(ws->ioctl_fd); if (ws->fd >= 0) close(ws->fd); @@ -775,7 +796,7 @@ uint32_t radeon_drm_get_gpu_reset_counter(struct radeon_drm_winsys *ws) { uint64_t retval = 0; - radeon_get_drm_value(ws->fd, RADEON_INFO_GPU_RESET_COUNTER, + radeon_get_drm_value(ws, RADEON_INFO_GPU_RESET_COUNTER, "gpu-reset-counter", (uint32_t*)&retval); return retval; } @@ -805,7 +826,7 @@ static uint64_t radeon_query_value(struct radeon_winsys *rws, return 0; } - radeon_get_drm_value(ws->fd, RADEON_INFO_TIMESTAMP, "timestamp", + radeon_get_drm_value(ws, RADEON_INFO_TIMESTAMP, "timestamp", (uint32_t*)&retval); return retval; case RADEON_NUM_GFX_IBS: @@ -813,7 +834,7 @@ static uint64_t radeon_query_value(struct radeon_winsys *rws, case RADEON_NUM_SDMA_IBS: return ws->num_sdma_IBs; case RADEON_NUM_BYTES_MOVED: - radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_BYTES_MOVED, + radeon_get_drm_value(ws, RADEON_INFO_NUM_BYTES_MOVED, "num-bytes-moved", (uint32_t*)&retval); return retval; case RADEON_NUM_EVICTIONS: @@ -825,23 +846,23 @@ static uint64_t radeon_query_value(struct radeon_winsys *rws, case RADEON_SLAB_WASTED_GTT: return 0; /* unimplemented */ case RADEON_VRAM_USAGE: - radeon_get_drm_value(ws->fd, RADEON_INFO_VRAM_USAGE, + radeon_get_drm_value(ws, RADEON_INFO_VRAM_USAGE, "vram-usage", (uint32_t*)&retval); return retval; case RADEON_GTT_USAGE: - radeon_get_drm_value(ws->fd, RADEON_INFO_GTT_USAGE, + radeon_get_drm_value(ws, RADEON_INFO_GTT_USAGE, "gtt-usage", (uint32_t*)&retval); return retval; case RADEON_GPU_TEMPERATURE: - radeon_get_drm_value(ws->fd, RADEON_INFO_CURRENT_GPU_TEMP, + radeon_get_drm_value(ws, RADEON_INFO_CURRENT_GPU_TEMP, "gpu-temp", (uint32_t*)&retval); return retval; case RADEON_CURRENT_SCLK: - radeon_get_drm_value(ws->fd, RADEON_INFO_CURRENT_GPU_SCLK, + radeon_get_drm_value(ws, RADEON_INFO_CURRENT_GPU_SCLK, "current-gpu-sclk", (uint32_t*)&retval); return retval; case RADEON_CURRENT_MCLK: - radeon_get_drm_value(ws->fd, RADEON_INFO_CURRENT_GPU_MCLK, + radeon_get_drm_value(ws, RADEON_INFO_CURRENT_GPU_MCLK, "current-gpu-mclk", (uint32_t*)&retval); return retval; case RADEON_CS_THREAD_TIME: @@ -860,7 +881,7 @@ static bool radeon_read_registers(struct radeon_winsys *rws, for (i = 0; i < num_registers; i++) { uint32_t reg = reg_offset + i*4; - if (!radeon_get_drm_value(ws->fd, RADEON_INFO_READ_REG, NULL, ®)) + if (!radeon_get_drm_value(ws, RADEON_INFO_READ_REG, NULL, ®)) return false; out[i] = reg; } @@ -946,7 +967,17 @@ radeon_drm_winsys_create(int fd, const struct pipe_screen_config *config, return NULL; } + ws->fd = -1; + ws->ioctl_fd = -1; ws->fd = os_dupfd_cloexec(fd); + if (ws->fd < 0) + goto fail1; + + ws->ioctl_fd = ws->fd; + + int render_fd = radeon_open_render_node(ws->fd); + if (render_fd >= 0) + ws->ioctl_fd = render_fd; if (!do_winsys_init(ws)) goto fail1; @@ -979,7 +1010,7 @@ radeon_drm_winsys_create(int fd, const struct pipe_screen_config *config, } if (ws->gen >= DRV_R600) { - ws->surf_man = radeon_surface_manager_new(ws->fd); + ws->surf_man = radeon_surface_manager_new(ws->ioctl_fd); if (!ws->surf_man) goto fail_slab; } @@ -1075,6 +1106,8 @@ fail1: simple_mtx_unlock(&fd_tab_mutex); if (ws->surf_man) radeon_surface_manager_free(ws->surf_man); + if (ws->ioctl_fd >= 0 && ws->ioctl_fd != ws->fd) + close(ws->ioctl_fd); if (ws->fd >= 0) close(ws->fd); diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h index 01f0bb5dd2b..fcd5dcffe3f 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h @@ -38,7 +38,8 @@ struct radeon_drm_winsys { struct pb_cache bo_cache; struct pb_slabs bo_slabs; - int fd; /* DRM file descriptor */ + int fd; /* Application-facing DRM file descriptor. */ + int ioctl_fd; /* Render-capable DRM file descriptor for GEM and CS ioctls. */ int num_cs; /* The number of command streams created. */ uint64_t allocated_vram; uint64_t allocated_gtt;