Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 81 additions & 2 deletions drivers/dma-buf/dma-buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ __FBSDID("$FreeBSD$");

#include <linux/list.h>
#include <linux/dma-buf.h>
#include <linux/dma-fence-unwrap.h>
#include <linux/dma-resv.h>
#include <linux/sync_file.h>

#include <uapi/linux/dma-buf.h>

Expand Down Expand Up @@ -225,6 +227,78 @@ dma_buf_end_cpu_access(struct dma_buf *db, enum dma_data_direction dir)
return (0);
}

static int
dma_buf_export_sync_file(struct dma_buf *db, struct thread *td,
struct dma_buf_export_sync_file *export_sync_file)
{
int usage = dma_resv_usage_rw(export_sync_file->flags & DMA_BUF_SYNC_WRITE);
int fd, rc;
struct dma_fence *fence;
struct sync_file *sync_file;
struct file *file;

rc = dma_resv_get_singleton(db->resv, usage, &fence);
if (rc != 0)
return (rc);
if (fence == NULL)
return (-ENXIO);

sync_file = sync_file_create(fence);
if (sync_file == NULL)
return (-ENOMEM);

rc = falloc(td, &file, &fd, O_CLOEXEC);
if (rc != 0)
return (-rc);

sync_file->linux_file->_file = file;

/* We need to set these for linux_fget to work in sync_file_fdget. */
sync_file->linux_file->_file->f_ops = &linuxfileops;
sync_file->linux_file->_file->f_data = sync_file->linux_file;

/* Transfer reference count from Linux file to BSD file (cf fd_install). */
while (refcount_release(&sync_file->linux_file->f_count) == 0)
refcount_acquire(&file->f_count);
fput(sync_file->linux_file);

export_sync_file->fd = fd;
dma_fence_put(fence);

return (0);
}

static int
dma_buf_import_sync_file(struct dma_buf *db,
struct dma_buf_import_sync_file *import_sync_file)
{
int usage = dma_resv_usage_rw(import_sync_file->flags & DMA_BUF_SYNC_WRITE);
int rc = 0;
size_t fence_count = 0;
struct dma_fence_unwrap cursor;
struct dma_fence *f, *fence;

fence = sync_file_get_fence(import_sync_file->fd);
if (fence == NULL)
return (-EINVAL);

dma_fence_unwrap_for_each(f, &cursor, fence)
fence_count++;

dma_resv_lock(db->resv, NULL);

rc = dma_resv_reserve_fences(db->resv, fence_count);
if (rc != 0)
goto out;
dma_fence_unwrap_for_each(f, &cursor, fence)
dma_resv_add_fence(db->resv, f, usage);

out:
dma_resv_unlock(db->resv);
dma_fence_put(fence);
return (rc);
}

static int
dma_buf_ioctl(struct file *fp, u_long com, void *data,
struct ucred *active_cred, struct thread *td)
Expand All @@ -238,11 +312,12 @@ dma_buf_ioctl(struct file *fp, u_long com, void *data,
return (EINVAL);

db = fp->f_data;
sync = data;
rc = 0;

switch (com) {
case DMA_BUF_IOCTL_SYNC:
sync = data;

if (sync->flags & ~DMA_BUF_SYNC_VALID_FLAGS_MASK)
return (EINVAL);

Expand All @@ -264,6 +339,10 @@ dma_buf_ioctl(struct file *fp, u_long com, void *data,
else
rc = dma_buf_begin_cpu_access(db, dir);
return (-rc);
case DMA_BUF_IOCTL_EXPORT_SYNC_FILE:
return (-dma_buf_export_sync_file(db, td, data));
case DMA_BUF_IOCTL_IMPORT_SYNC_FILE:
return (-dma_buf_import_sync_file(db, data));
default:
return (ENOTTY);
}
Expand Down Expand Up @@ -465,7 +544,7 @@ dma_buf_export(const struct dma_buf_export_info *exp_info)
if ((err = falloc_noinstall(curthread, &fp)) != 0)
goto err;

finit(fp, 0, DTYPE_DMABUF, db, &dma_buf_fileops);
finit(fp, FREAD | FWRITE, DTYPE_DMABUF, db, &dma_buf_fileops);

db->linux_file = fp;
mutex_init(&db->lock);
Expand Down
14 changes: 14 additions & 0 deletions linuxkpi/bsd/include/uapi/linux/dma-buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,18 @@ struct dma_buf_sync {

#define DMA_BUF_IOCTL_SYNC _IOW('b', 0, struct dma_buf_sync)

struct dma_buf_export_sync_file {
__u32 flags;
__s32 fd;
};

#define DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR('b', 1, struct dma_buf_export_sync_file)

struct dma_buf_import_sync_file {
__u32 flags;
__s32 fd;
};

#define DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW('b', 2, struct dma_buf_import_sync_file)

#endif /* _BSD_LKPI_UAPI_LINUX_DMA_BUF_H_ */