aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/fastrpc.c184
-rw-r--r--include/uapi/misc/fastrpc.h8
2 files changed, 192 insertions, 0 deletions
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index ceb498487569..4b0db33896df 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -106,10 +106,20 @@ struct fastrpc_invoke_rsp {
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,
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:
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)
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,
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;
diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h
index 32d191c3b7bc..6d701af9fc42 100644
--- a/include/uapi/misc/fastrpc.h
+++ b/include/uapi/misc/fastrpc.h
@@ -5,6 +5,8 @@
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 {
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__ */