Skip to content

Commit e459680

Browse files
committed
minigbm: Use dmabuf inode as unique buffer id instead of handle
Handle has some limits and can't be used as unique buffer ID on systems where display controller can scanout from CMA but GPU can work with both CMA and VRAM. Such systems have DRM/KMS and DRM/GPU drivers separated. GBM frontend is always expecting handle for DRM/KMS driver. In such system any attempt of importing the buffer with more than 1 contiguous chunk into DRM/KMS driver will fail. Using dma-buf inode as unique buffer ID is a common practice for a last several years starting from [this kernel patch][1]. [1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ed63bb1d1f8469586006a9ca63c42344401aa2ab Change-Id: Ic3a69010d5da2f866a2252fc7e9eb29d67f8e1ed Signed-off-by: Roman Stratiienko <[email protected]> For reviews, comments, suggestions and questions visit: #10
1 parent 3abb792 commit e459680

File tree

6 files changed

+41
-16
lines changed

6 files changed

+41
-16
lines changed

drv.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ static void drv_bo_mapping_destroy(struct bo *bo)
253253
while (idx < drv_array_size(drv->mappings)) {
254254
struct mapping *mapping =
255255
(struct mapping *)drv_array_at_idx(drv->mappings, idx);
256-
if (mapping->vma->handle != bo->handle.u32) {
256+
if (mapping->vma->inode != bo->inode) {
257257
idx++;
258258
continue;
259259
}
@@ -287,11 +287,16 @@ static void drv_bo_acquire(struct bo *bo)
287287
pthread_mutex_lock(&drv->buffer_table_lock);
288288
for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
289289
uintptr_t num = 0;
290+
if (!bo->inode) {
291+
int fd = drv_bo_get_plane_fd(bo, plane);
292+
bo->inode = drv_get_inode(fd);
293+
close(fd);
294+
}
290295

291-
if (!drmHashLookup(drv->buffer_table, bo->handle.u32, (void **)&num))
292-
drmHashDelete(drv->buffer_table, bo->handle.u32);
296+
if (!drmHashLookup(drv->buffer_table, bo->inode, (void **)&num))
297+
drmHashDelete(drv->buffer_table, bo->inode);
293298

294-
drmHashInsert(drv->buffer_table, bo->handle.u32, (void *)(num + 1));
299+
drmHashInsert(drv->buffer_table, bo->inode, (void *)(num + 1));
295300
}
296301
pthread_mutex_unlock(&drv->buffer_table_lock);
297302
}
@@ -310,18 +315,18 @@ static bool drv_bo_release(struct bo *bo)
310315

311316
pthread_mutex_lock(&drv->buffer_table_lock);
312317
for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
313-
if (!drmHashLookup(drv->buffer_table, bo->handle.u32, (void **)&num)) {
314-
drmHashDelete(drv->buffer_table, bo->handle.u32);
318+
if (!drmHashLookup(drv->buffer_table, bo->inode, (void **)&num)) {
319+
drmHashDelete(drv->buffer_table, bo->inode);
315320

316321
if (num > 1) {
317-
drmHashInsert(drv->buffer_table, bo->handle.u32, (void *)(num - 1));
322+
drmHashInsert(drv->buffer_table, bo->inode, (void *)(num - 1));
318323
}
319324
}
320325
}
321326

322327
/* The same buffer can back multiple planes with different offsets. */
323328
for (size_t plane = 0; plane < bo->meta.num_planes; plane++) {
324-
if (!drmHashLookup(drv->buffer_table, bo->handle.u32, (void **)&num)) {
329+
if (!drmHashLookup(drv->buffer_table, bo->inode, (void **)&num)) {
325330
/* num is positive if found in the hashmap. */
326331
pthread_mutex_unlock(&drv->buffer_table_lock);
327332
return false;
@@ -433,6 +438,8 @@ struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data)
433438
return NULL;
434439
}
435440

441+
bo->inode = drv_get_inode(data->fds[0]);
442+
436443
drv_bo_acquire(bo);
437444

438445
bo->meta.format_modifier = data->format_modifier;
@@ -493,7 +500,7 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags
493500

494501
for (i = 0; i < drv_array_size(drv->mappings); i++) {
495502
struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i);
496-
if (prior->vma->handle != bo->handle.u32 || prior->vma->map_flags != map_flags)
503+
if (prior->vma->inode != bo->inode || prior->vma->map_flags != map_flags)
497504
continue;
498505

499506
if (rect->x != prior->rect.x || rect->y != prior->rect.y ||
@@ -507,7 +514,7 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags
507514

508515
for (i = 0; i < drv_array_size(drv->mappings); i++) {
509516
struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i);
510-
if (prior->vma->handle != bo->handle.u32 || prior->vma->map_flags != map_flags)
517+
if (prior->vma->inode != bo->inode || prior->vma->map_flags != map_flags)
511518
continue;
512519

513520
prior->vma->refcount++;
@@ -533,7 +540,7 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags
533540

534541
mapping.vma->refcount = 1;
535542
mapping.vma->addr = addr;
536-
mapping.vma->handle = bo->handle.u32;
543+
mapping.vma->inode = bo->inode;
537544
mapping.vma->map_flags = map_flags;
538545

539546
success:

drv.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ struct drv_import_fd_data {
126126
struct vma {
127127
void *addr;
128128
size_t length;
129-
uint32_t handle;
129+
130+
uint32_t inode;
130131
uint32_t map_flags;
131132
int32_t refcount;
132133
uint32_t map_strides[DRV_MAX_PLANES];

drv_helpers.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <stdlib.h>
1313
#include <string.h>
1414
#include <sys/mman.h>
15+
#include <sys/stat.h>
1516
#include <sys/types.h>
1617
#include <unistd.h>
1718
#include <xf86drm.h>
@@ -616,6 +617,18 @@ void drv_resolve_format_and_use_flags_helper(struct driver *drv, uint32_t format
616617
}
617618
}
618619

620+
uint32_t drv_get_inode(int dmabuf_fd)
621+
{
622+
struct stat sb = { 0 };
623+
int ret = 0;
624+
625+
ret = fstat(dmabuf_fd, &sb);
626+
if (ret)
627+
drv_loge("Failed to fstat dmabuf %d: %s\n", dmabuf_fd, strerror(errno));
628+
629+
return sb.st_ino;
630+
}
631+
619632
const char *drv_get_os_option(const char *name)
620633
{
621634
const char *ret = getenv(name);

drv_helpers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ void drv_resolve_format_and_use_flags_helper(struct driver *drv, uint32_t format
5151
uint64_t use_flags, uint32_t *out_format,
5252
uint64_t *out_use_flags);
5353

54+
uint32_t drv_get_inode(int dmabuf_fd);
55+
5456
/*
5557
* Get an option. Should return NULL if specified option is not set.
5658
*/

drv_priv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ struct bo {
4444
struct driver *drv;
4545
struct bo_metadata meta;
4646
bool is_test_buffer;
47+
/* handle are mandatory only for SCANOUT buffers */
4748
union bo_handle handle;
49+
uint32_t inode;
4850
void *priv;
4951
};
5052

virtgpu_virgl.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,7 @@ static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping)
10211021
if (params[param_resource_blob].value && (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
10221022
return 0;
10231023

1024-
xfer.bo_handle = mapping->vma->handle;
1024+
xfer.bo_handle = bo->handle.u32;
10251025

10261026
if (mapping->rect.x || mapping->rect.y) {
10271027
/*
@@ -1075,7 +1075,7 @@ static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping)
10751075
// The transfer needs to complete before invalidate returns so that any host changes
10761076
// are visible and to ensure the host doesn't overwrite subsequent guest changes.
10771077
// TODO(b/136733358): Support returning fences from transfers
1078-
waitcmd.handle = mapping->vma->handle;
1078+
waitcmd.handle = bo->handle.u32;
10791079
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd);
10801080
if (ret) {
10811081
drv_loge("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno));
@@ -1103,7 +1103,7 @@ static int virgl_bo_flush(struct bo *bo, struct mapping *mapping)
11031103
if (params[param_resource_blob].value && (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
11041104
return 0;
11051105

1106-
xfer.bo_handle = mapping->vma->handle;
1106+
xfer.bo_handle = bo->handle.u32;
11071107

11081108
if (mapping->rect.x || mapping->rect.y) {
11091109
/*
@@ -1153,7 +1153,7 @@ static int virgl_bo_flush(struct bo *bo, struct mapping *mapping)
11531153
// buffer, we need to wait for the transfer to complete for consistency.
11541154
// TODO(b/136733358): Support returning fences from transfers
11551155
if (bo->meta.use_flags & BO_USE_NON_GPU_HW) {
1156-
waitcmd.handle = mapping->vma->handle;
1156+
waitcmd.handle = bo->handle.u32;
11571157

11581158
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd);
11591159
if (ret) {

0 commit comments

Comments
 (0)