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
106 106
107struct fastrpc_buf {107struct fastrpc_buf {
108 struct fastrpc_user *fl;108 struct fastrpc_user *fl;
109 struct dma_buf *dmabuf;
109 struct device *dev;110 struct device *dev;
110 void *virt;111 void *virt;
111 u64 phys;112 u64 phys;
112 u64 size;113 u64 size;
114 /* Lock for dma buf attachments */
115 struct mutex lock;
116 struct list_head attachments;
117};
118
119struct fastrpc_dma_buf_attachment {
120 struct device *dev;
121 struct sg_table sgt;
122 struct list_head node;
113};123};
114 124
115struct fastrpc_map {125struct fastrpc_map {
@@ -246,6 +256,9 @@ static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev, · 130 unmodified lines
246 if (!buf)256 if (!buf)
247 return -ENOMEM;257 return -ENOMEM;
248 258
259 INIT_LIST_HEAD(&buf->attachments);
260 mutex_init(&buf->lock);
261
249 buf->fl = fl;262 buf->fl = fl;
250 buf->virt = NULL;263 buf->virt = NULL;
251 buf->phys = 0;264 buf->phys = 0;
@@ -360,6 +373,111 @@ err_idr: · 108 unmodified lines
360 return ERR_PTR(ret);373 return ERR_PTR(ret);
361}374}
362 375
376static struct sg_table *
377fastrpc_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
391static 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
398static void fastrpc_release(struct dma_buf *dmabuf)
399{
400 struct fastrpc_buf *buffer = dmabuf->priv;
401
402 fastrpc_buf_free(buffer);
403}
404
405static 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
434static 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
446static 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
453static void *fastrpc_vmap(struct dma_buf *dmabuf)
454{
455 struct fastrpc_buf *buf = dmabuf->priv;
456
457 return buf->virt;
458}
459
460static 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
470static 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
363static int fastrpc_map_create(struct fastrpc_user *fl, int fd,481static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
364 u64 len, struct fastrpc_map **ppmap)482 u64 len, struct fastrpc_map **ppmap)
365{483{
@@ -906,6 +1024,66 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) · 540 unmodified lines
906 return 0;1024 return 0;
907}1025}
908 1026
1027static 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
1047static 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
909static int fastrpc_init_attach(struct fastrpc_user *fl)1087static int fastrpc_init_attach(struct fastrpc_user *fl)
910{1088{
911 struct fastrpc_invoke_args args[1];1089 struct fastrpc_invoke_args args[1];
@@ -970,6 +1148,12 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, · 58 unmodified lines
970 case FASTRPC_IOCTL_INIT_CREATE:1148 case FASTRPC_IOCTL_INIT_CREATE:
971 err = fastrpc_init_create_process(fl, argp);1149 err = fastrpc_init_create_process(fl, argp);
972 break;1150 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;
973 default:1157 default:
974 err = -ENOTTY;1158 err = -ENOTTY;
975 break;1159 break;
include/uapi/misc/fastrpc.h+8−0
@@ -5,6 +5,8 @@ · 4 unmodified lines
5 5
6#include <linux/types.h>6#include <linux/types.h>
7 7
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)
8#define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke)10#define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke)
9#define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4)11#define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4)
10#define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create)12#define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create)
@@ -30,4 +32,10 @@ struct fastrpc_init_create { · 19 unmodified lines
30 __u64 file; /* pointer to elf file */32 __u64 file; /* pointer to elf file */
31};33};
32 34
35struct fastrpc_alloc_dma_buf {
36 __s32 fd; /* fd */
37 __u32 flags; /* flags to map with */
38 __u64 size; /* size */
39};
40
33#endif /* __QCOM_FASTRPC_H__ */41#endif /* __QCOM_FASTRPC_H__ */