History

misc: fastrpc: Add support for dmabuf exporter

User process can involve dealing with big buffer sizes, and also passing buffers from one compute context bank to other compute context bank for complex dsp algorithms. This patch adds support to fastrpc to make it a proper dmabuf exporter to avoid making copies of buffers.

Srinivas Kandagatla committed 7 years ago

Commit 6cffd791 parent d73f71c2 files · +192 −0Browse files

Unified · Split

2 files
  1. drivers/misc/fastrpc.c +184 −0
  2. include/uapi/misc/fastrpc.h +8 −0
drivers/misc/fastrpc.c+184−0
@@ -106,10 +106,20 @@ struct fastrpc_invoke_rsp { · 105 unmodified lines
106106
107107 struct fastrpc_buf {
108108 struct fastrpc_user *fl;
109+ struct dma_buf *dmabuf;
109110 struct device *dev;
110111 void *virt;
111112 u64 phys;
112113 u64 size;
114+ /* Lock for dma buf attachments */
115+ struct mutex lock;
116+ struct list_head attachments;
117+};
118+
119+struct fastrpc_dma_buf_attachment {
120+ struct device *dev;
121+ struct sg_table sgt;
122+ struct list_head node;
113123 };
114124
115125 struct fastrpc_map {
@@ -246,6 +256,9 @@ static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev, · 130 unmodified lines
246256 if (!buf)
247257 return -ENOMEM;
248258
259+ INIT_LIST_HEAD(&buf->attachments);
260+ mutex_init(&buf->lock);
261+
249262 buf->fl = fl;
250263 buf->virt = NULL;
251264 buf->phys = 0;
@@ -360,6 +373,111 @@ err_idr: · 108 unmodified lines
360373 return ERR_PTR(ret);
361374 }
362375
376+static struct sg_table *
377+fastrpc_map_dma_buf(struct dma_buf_attachment *attachment,
378+ enum dma_data_direction dir)
379+{
380+ struct fastrpc_dma_buf_attachment *a = attachment->priv;
381+ struct sg_table *table;
382+
383+ table = &a->sgt;
384+
385+ if (!dma_map_sg(attachment->dev, table->sgl, table->nents, dir))
386+ return ERR_PTR(-ENOMEM);
387+
388+ return table;
389+}
390+
391+static void fastrpc_unmap_dma_buf(struct dma_buf_attachment *attach,
392+ struct sg_table *table,
393+ enum dma_data_direction dir)
394+{
395+ dma_unmap_sg(attach->dev, table->sgl, table->nents, dir);
396+}
397+
398+static void fastrpc_release(struct dma_buf *dmabuf)
399+{
400+ struct fastrpc_buf *buffer = dmabuf->priv;
401+
402+ fastrpc_buf_free(buffer);
403+}
404+
405+static int fastrpc_dma_buf_attach(struct dma_buf *dmabuf,
406+ struct dma_buf_attachment *attachment)
407+{
408+ struct fastrpc_dma_buf_attachment *a;
409+ struct fastrpc_buf *buffer = dmabuf->priv;
410+ int ret;
411+
412+ a = kzalloc(sizeof(*a), GFP_KERNEL);
413+ if (!a)
414+ return -ENOMEM;
415+
416+ ret = dma_get_sgtable(buffer->dev, &a->sgt, buffer->virt,
417+ FASTRPC_PHYS(buffer->phys), buffer->size);
418+ if (ret < 0) {
419+ dev_err(buffer->dev, "failed to get scatterlist from DMA API\n");
420+ return -EINVAL;
421+ }
422+
423+ a->dev = attachment->dev;
424+ INIT_LIST_HEAD(&a->node);
425+ attachment->priv = a;
426+
427+ mutex_lock(&buffer->lock);
428+ list_add(&a->node, &buffer->attachments);
429+ mutex_unlock(&buffer->lock);
430+
431+ return 0;
432+}
433+
434+static void fastrpc_dma_buf_detatch(struct dma_buf *dmabuf,
435+ struct dma_buf_attachment *attachment)
436+{
437+ struct fastrpc_dma_buf_attachment *a = attachment->priv;
438+ struct fastrpc_buf *buffer = dmabuf->priv;
439+
440+ mutex_lock(&buffer->lock);
441+ list_del(&a->node);
442+ mutex_unlock(&buffer->lock);
443+ kfree(a);
444+}
445+
446+static void *fastrpc_kmap(struct dma_buf *dmabuf, unsigned long pgnum)
447+{
448+ struct fastrpc_buf *buf = dmabuf->priv;
449+
450+ return buf->virt ? buf->virt + pgnum * PAGE_SIZE : NULL;
451+}
452+
453+static void *fastrpc_vmap(struct dma_buf *dmabuf)
454+{
455+ struct fastrpc_buf *buf = dmabuf->priv;
456+
457+ return buf->virt;
458+}
459+
460+static int fastrpc_mmap(struct dma_buf *dmabuf,
461+ struct vm_area_struct *vma)
462+{
463+ struct fastrpc_buf *buf = dmabuf->priv;
464+ size_t size = vma->vm_end - vma->vm_start;
465+
466+ return dma_mmap_coherent(buf->dev, vma, buf->virt,
467+ FASTRPC_PHYS(buf->phys), size);
468+}
469+
470+static const struct dma_buf_ops fastrpc_dma_buf_ops = {
471+ .attach = fastrpc_dma_buf_attach,
472+ .detach = fastrpc_dma_buf_detatch,
473+ .map_dma_buf = fastrpc_map_dma_buf,
474+ .unmap_dma_buf = fastrpc_unmap_dma_buf,
475+ .mmap = fastrpc_mmap,
476+ .map = fastrpc_kmap,
477+ .vmap = fastrpc_vmap,
478+ .release = fastrpc_release,
479+};
480+
363481 static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
364482 u64 len, struct fastrpc_map **ppmap)
365483 {
@@ -906,6 +1024,66 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) · 540 unmodified lines
9061024 return 0;
9071025 }
9081026
1027+static int fastrpc_dmabuf_free(struct fastrpc_user *fl, char __user *argp)
1028+{
1029+ struct dma_buf *buf;
1030+ int info;
1031+
1032+ if (copy_from_user(&info, argp, sizeof(info)))
1033+ return -EFAULT;
1034+
1035+ buf = dma_buf_get(info);
1036+ if (IS_ERR_OR_NULL(buf))
1037+ return -EINVAL;
1038+ /*
1039+ * one for the last get and other for the ALLOC_DMA_BUFF ioctl
1040+ */
1041+ dma_buf_put(buf);
1042+ dma_buf_put(buf);
1043+
1044+ return 0;
1045+}
1046+
1047+static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp)
1048+{
1049+ struct fastrpc_alloc_dma_buf bp;
1050+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
1051+ struct fastrpc_buf *buf = NULL;
1052+ int err;
1053+
1054+ if (copy_from_user(&bp, argp, sizeof(bp)))
1055+ return -EFAULT;
1056+
1057+ err = fastrpc_buf_alloc(fl, fl->sctx->dev, bp.size, &buf);
1058+ if (err)
1059+ return err;
1060+ exp_info.ops = &fastrpc_dma_buf_ops;
1061+ exp_info.size = bp.size;
1062+ exp_info.flags = O_RDWR;
1063+ exp_info.priv = buf;
1064+ buf->dmabuf = dma_buf_export(&exp_info);
1065+ if (IS_ERR(buf->dmabuf)) {
1066+ err = PTR_ERR(buf->dmabuf);
1067+ fastrpc_buf_free(buf);
1068+ return err;
1069+ }
1070+
1071+ bp.fd = dma_buf_fd(buf->dmabuf, O_ACCMODE);
1072+ if (bp.fd < 0) {
1073+ dma_buf_put(buf->dmabuf);
1074+ return -EINVAL;
1075+ }
1076+
1077+ if (copy_to_user(argp, &bp, sizeof(bp))) {
1078+ dma_buf_put(buf->dmabuf);
1079+ return -EFAULT;
1080+ }
1081+
1082+ get_dma_buf(buf->dmabuf);
1083+
1084+ return 0;
1085+}
1086+
9091087 static int fastrpc_init_attach(struct fastrpc_user *fl)
9101088 {
9111089 struct fastrpc_invoke_args args[1];
@@ -970,6 +1148,12 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, · 58 unmodified lines
9701148 case FASTRPC_IOCTL_INIT_CREATE:
9711149 err = fastrpc_init_create_process(fl, argp);
9721150 break;
1151+ case FASTRPC_IOCTL_FREE_DMA_BUFF:
1152+ err = fastrpc_dmabuf_free(fl, argp);
1153+ break;
1154+ case FASTRPC_IOCTL_ALLOC_DMA_BUFF:
1155+ err = fastrpc_dmabuf_alloc(fl, argp);
1156+ break;
9731157 default:
9741158 err = -ENOTTY;
9751159 break;
include/uapi/misc/fastrpc.h+8−0
@@ -5,6 +5,8 @@ · 4 unmodified lines
55
66 #include <linux/types.h>
77
8+#define FASTRPC_IOCTL_ALLOC_DMA_BUFF _IOWR('R', 1, struct fastrpc_alloc_dma_buf)
9+#define FASTRPC_IOCTL_FREE_DMA_BUFF _IOWR('R', 2, __u32)
810 #define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke)
911 #define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4)
1012 #define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create)
@@ -30,4 +32,10 @@ struct fastrpc_init_create { · 19 unmodified lines
3032 __u64 file; /* pointer to elf file */
3133 };
3234
35+struct fastrpc_alloc_dma_buf {
36+ __s32 fd; /* fd */
37+ __u32 flags; /* flags to map with */
38+ __u64 size; /* size */
39+};
40+
3341 #endif /* __QCOM_FASTRPC_H__ */