11a3679e3aba3524cf987f1f808d92c25f16e080 — Michel Dänzer 4 months ago cb446dc
winsys/amdgpu: Make KMS handles valid for original DRM file descriptor

Getting a DMA-buf fd and converting that to a handle using our duplicate
of that file descriptor (getting at which requires passing a
radeon_winsys pointer to the buffer_get_handle hook) makes sure of this,
since duplicated file descriptors reference the same file description
and therefore the same GEM handle namespace.

This is necessary because libdrm_amdgpu may use a different DRM file
descriptor with a separate handle namespace internally, e.g. because it
always reuses any existing amdgpu_device_handle for the same device.
amdgpu_bo_export returns a handle which is valid for that internal
file descriptor.

Bugzilla: https://bugs.freedesktop.org/110903
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Tested-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
M src/gallium/drivers/r300/r300_texture.c => src/gallium/drivers/r300/r300_texture.c +1 -1
@@ 1048,7 1048,7 @@
         return FALSE;
     }
 
-    return rws->buffer_get_handle(tex->buf, tex->tex.stride_in_bytes[0],
+    return rws->buffer_get_handle(rws, tex->buf, tex->tex.stride_in_bytes[0],
                                   0, 0, whandle);
 }
 

M src/gallium/drivers/r600/r600_texture.c => src/gallium/drivers/r600/r600_texture.c +2 -2
@@ 572,8 572,8 @@
 		res->external_usage = usage;
 	}
 
-	return rscreen->ws->buffer_get_handle(res->buf, stride, offset,
-					      slice_size, whandle);
+	return rscreen->ws->buffer_get_handle(rscreen->ws, res->buf, stride,
+					      offset, slice_size, whandle);
 }
 
 static void r600_texture_destroy(struct pipe_screen *screen,

M src/gallium/drivers/radeon/radeon_winsys.h => src/gallium/drivers/radeon/radeon_winsys.h +3 -1
@@ 411,12 411,14 @@
      * Get a winsys handle from a winsys buffer. The internal structure
      * of the handle is platform-specific and only a winsys should access it.
      *
+     * \param ws        The winsys instance for which the handle is to be valid
      * \param buf       A winsys buffer object to get the handle from.
      * \param whandle   A winsys handle pointer.
      * \param stride    A stride of the buffer in bytes, for texturing.
      * \return          true on success.
      */
-    bool (*buffer_get_handle)(struct pb_buffer *buf,
+    bool (*buffer_get_handle)(struct radeon_winsys *ws,
+                              struct pb_buffer *buf,
                               unsigned stride, unsigned offset,
                               unsigned slice_size,
                               struct winsys_handle *whandle);

M src/gallium/drivers/radeonsi/si_texture.c => src/gallium/drivers/radeonsi/si_texture.c +2 -2
@@ 944,8 944,8 @@
 		res->external_usage = usage;
 	}
 
-	return sscreen->ws->buffer_get_handle(res->buf, stride, offset,
-					      slice_size, whandle);
+	return sscreen->ws->buffer_get_handle(sscreen->ws, res->buf, stride,
+					      offset, slice_size, whandle);
 }
 
 static void si_texture_destroy(struct pipe_screen *screen,

M src/gallium/winsys/amdgpu/drm/amdgpu_bo.c => src/gallium/winsys/amdgpu/drm/amdgpu_bo.c +14 -4
@@ 1524,11 1524,13 @@
    return NULL;
 }
 
-static bool amdgpu_bo_get_handle(struct pb_buffer *buffer,
+static bool amdgpu_bo_get_handle(struct radeon_winsys *rws,
+                                 struct pb_buffer *buffer,
                                  unsigned stride, unsigned offset,
                                  unsigned slice_size,
                                  struct winsys_handle *whandle)
 {
+   struct amdgpu_screen_winsys *sws = amdgpu_screen_winsys(rws);
    struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(buffer);
    struct amdgpu_winsys *ws = bo->ws;
    enum amdgpu_bo_handle_type type;


@@ 1544,12 1546,10 @@
    case WINSYS_HANDLE_TYPE_SHARED:
       type = amdgpu_bo_handle_type_gem_flink_name;
       break;
+   case WINSYS_HANDLE_TYPE_KMS:
    case WINSYS_HANDLE_TYPE_FD:
       type = amdgpu_bo_handle_type_dma_buf_fd;
       break;
-   case WINSYS_HANDLE_TYPE_KMS:
-      type = amdgpu_bo_handle_type_kms;
-      break;
    default:
       return false;
    }


@@ 1558,6 1558,16 @@
    if (r)
       return false;
 
+   if (whandle->type == WINSYS_HANDLE_TYPE_KMS) {
+      int dma_fd = whandle->handle;
+
+      r = drmPrimeFDToHandle(sws->fd, dma_fd, &whandle->handle);
+      close(dma_fd);
+
+      if (r)
+         return false;
+   }
+
    simple_mtx_lock(&ws->bo_export_table_lock);
    util_hash_table_set(ws->bo_export_table, bo->bo, bo);
    simple_mtx_unlock(&ws->bo_export_table_lock);

M src/gallium/winsys/radeon/drm/radeon_drm_bo.c => src/gallium/winsys/radeon/drm/radeon_drm_bo.c +2 -1
@@ 1285,7 1285,8 @@
     return NULL;
 }
 
-static bool radeon_winsys_bo_get_handle(struct pb_buffer *buffer,
+static bool radeon_winsys_bo_get_handle(struct radeon_winsys *rws,
+                                        struct pb_buffer *buffer,
                                         unsigned stride, unsigned offset,
                                         unsigned slice_size,
                                         struct winsys_handle *whandle)