diff options
Diffstat (limited to 'drivers/misc/fastrpc.c')
| -rw-r--r-- | drivers/misc/fastrpc.c | 79 | 
1 files changed, 47 insertions, 32 deletions
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 98603e235cf0..47ae84afac2e 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -33,7 +33,6 @@  #define FASTRPC_INIT_HANDLE	1  #define FASTRPC_CTXID_MASK (0xFF0)  #define INIT_FILELEN_MAX (64 * 1024 * 1024) -#define INIT_MEMLEN_MAX  (8 * 1024 * 1024)  #define FASTRPC_DEVICE_NAME	"fastrpc"  /* Retrives number of input buffers from the scalars parameter */ @@ -186,6 +185,7 @@ struct fastrpc_channel_ctx {  	struct idr ctx_idr;  	struct list_head users;  	struct miscdevice miscdev; +	struct kref refcount;  };  struct fastrpc_user { @@ -279,8 +279,11 @@ static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,  	buf->virt = dma_alloc_coherent(dev, buf->size, (dma_addr_t *)&buf->phys,  				       GFP_KERNEL); -	if (!buf->virt) +	if (!buf->virt) { +		mutex_destroy(&buf->lock); +		kfree(buf);  		return -ENOMEM; +	}  	if (fl->sctx && fl->sctx->sid)  		buf->phys += ((u64)fl->sctx->sid << 32); @@ -290,6 +293,25 @@ static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,  	return 0;  } +static void fastrpc_channel_ctx_free(struct kref *ref) +{ +	struct fastrpc_channel_ctx *cctx; + +	cctx = container_of(ref, struct fastrpc_channel_ctx, refcount); + +	kfree(cctx); +} + +static void fastrpc_channel_ctx_get(struct fastrpc_channel_ctx *cctx) +{ +	kref_get(&cctx->refcount); +} + +static void fastrpc_channel_ctx_put(struct fastrpc_channel_ctx *cctx) +{ +	kref_put(&cctx->refcount, fastrpc_channel_ctx_free); +} +  static void fastrpc_context_free(struct kref *ref)  {  	struct fastrpc_invoke_ctx *ctx; @@ -313,6 +335,8 @@ static void fastrpc_context_free(struct kref *ref)  	kfree(ctx->maps);  	kfree(ctx->olaps);  	kfree(ctx); + +	fastrpc_channel_ctx_put(cctx);  }  static void fastrpc_context_get(struct fastrpc_invoke_ctx *ctx) @@ -419,6 +443,9 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(  		fastrpc_get_buff_overlaps(ctx);  	} +	/* Released in fastrpc_context_put() */ +	fastrpc_channel_ctx_get(cctx); +  	ctx->sc = sc;  	ctx->retval = -1;  	ctx->pid = current->pid; @@ -448,6 +475,7 @@ err_idr:  	spin_lock(&user->lock);  	list_del(&ctx->node);  	spin_unlock(&user->lock); +	fastrpc_channel_ctx_put(cctx);  	kfree(ctx->maps);  	kfree(ctx->olaps);  	kfree(ctx); @@ -522,6 +550,7 @@ static void fastrpc_dma_buf_detatch(struct dma_buf *dmabuf,  	mutex_lock(&buffer->lock);  	list_del(&a->node);  	mutex_unlock(&buffer->lock); +	sg_free_table(&a->sgt);  	kfree(a);  } @@ -884,6 +913,9 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl,  u32 kernel,  	if (!fl->sctx)  		return -EINVAL; +	if (!fl->cctx->rpdev) +		return -EPIPE; +  	ctx = fastrpc_context_alloc(fl, kernel, sc, args);  	if (IS_ERR(ctx))  		return PTR_ERR(ctx); @@ -1120,6 +1152,7 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)  	}  	fastrpc_session_free(cctx, fl->sctx); +	fastrpc_channel_ctx_put(cctx);  	mutex_destroy(&fl->mutex);  	kfree(fl); @@ -1138,6 +1171,9 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)  	if (!fl)  		return -ENOMEM; +	/* Released in fastrpc_device_release() */ +	fastrpc_channel_ctx_get(cctx); +  	filp->private_data = fl;  	spin_lock_init(&fl->lock);  	mutex_init(&fl->mutex); @@ -1163,26 +1199,6 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)  	return 0;  } -static int fastrpc_dmabuf_free(struct fastrpc_user *fl, char __user *argp) -{ -	struct dma_buf *buf; -	int info; - -	if (copy_from_user(&info, argp, sizeof(info))) -		return -EFAULT; - -	buf = dma_buf_get(info); -	if (IS_ERR_OR_NULL(buf)) -		return -EINVAL; -	/* -	 * one for the last get and other for the ALLOC_DMA_BUFF ioctl -	 */ -	dma_buf_put(buf); -	dma_buf_put(buf); - -	return 0; -} -  static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp)  {  	struct fastrpc_alloc_dma_buf bp; @@ -1218,8 +1234,6 @@ static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp)  		return -EFAULT;  	} -	get_dma_buf(buf->dmabuf); -  	return 0;  } @@ -1287,9 +1301,6 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,  	case FASTRPC_IOCTL_INIT_CREATE:  		err = fastrpc_init_create_process(fl, argp);  		break; -	case FASTRPC_IOCTL_FREE_DMA_BUFF: -		err = fastrpc_dmabuf_free(fl, argp); -		break;  	case FASTRPC_IOCTL_ALLOC_DMA_BUFF:  		err = fastrpc_dmabuf_alloc(fl, argp);  		break; @@ -1395,10 +1406,6 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)  	int i, err, domain_id = -1;  	const char *domain; -	data = devm_kzalloc(rdev, sizeof(*data), GFP_KERNEL); -	if (!data) -		return -ENOMEM; -  	err = of_property_read_string(rdev->of_node, "label", &domain);  	if (err) {  		dev_info(rdev, "FastRPC Domain not specified in DT\n"); @@ -1417,6 +1424,10 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)  		return -EINVAL;  	} +	data = kzalloc(sizeof(*data), GFP_KERNEL); +	if (!data) +		return -ENOMEM; +  	data->miscdev.minor = MISC_DYNAMIC_MINOR;  	data->miscdev.name = kasprintf(GFP_KERNEL, "fastrpc-%s",  				domains[domain_id]); @@ -1425,6 +1436,8 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)  	if (err)  		return err; +	kref_init(&data->refcount); +  	dev_set_drvdata(&rpdev->dev, data);  	dma_set_mask_and_coherent(rdev, DMA_BIT_MASK(32));  	INIT_LIST_HEAD(&data->users); @@ -1459,7 +1472,9 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)  	misc_deregister(&cctx->miscdev);  	of_platform_depopulate(&rpdev->dev); -	kfree(cctx); + +	cctx->rpdev = NULL; +	fastrpc_channel_ctx_put(cctx);  }  static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data,  |