diff options
Diffstat (limited to 'drivers/misc/fastrpc.c')
| -rw-r--r-- | drivers/misc/fastrpc.c | 98 | 
1 files changed, 54 insertions, 44 deletions
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index c9902a1dcf5d..a701132638cf 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -18,7 +18,7 @@  #include <linux/rpmsg.h>  #include <linux/scatterlist.h>  #include <linux/slab.h> -#include <linux/qcom_scm.h> +#include <linux/firmware/qcom/qcom_scm.h>  #include <uapi/misc/fastrpc.h>  #include <linux/of_reserved_mem.h> @@ -321,7 +321,7 @@ static void fastrpc_free_map(struct kref *ref)  			perm.vmid = QCOM_SCM_VMID_HLOS;  			perm.perm = QCOM_SCM_PERM_RWX;  			err = qcom_scm_assign_mem(map->phys, map->size, -				&(map->fl->cctx->vmperms[0].vmid), &perm, 1); +				&map->fl->cctx->perms, &perm, 1);  			if (err) {  				dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",  						map->phys, map->size, err); @@ -334,6 +334,13 @@ static void fastrpc_free_map(struct kref *ref)  		dma_buf_put(map->buf);  	} +	if (map->fl) { +		spin_lock(&map->fl->lock); +		list_del(&map->node); +		spin_unlock(&map->fl->lock); +		map->fl = NULL; +	} +  	kfree(map);  } @@ -343,38 +350,41 @@ static void fastrpc_map_put(struct fastrpc_map *map)  		kref_put(&map->refcount, fastrpc_free_map);  } -static void fastrpc_map_get(struct fastrpc_map *map) +static int fastrpc_map_get(struct fastrpc_map *map)  { -	if (map) -		kref_get(&map->refcount); +	if (!map) +		return -ENOENT; + +	return kref_get_unless_zero(&map->refcount) ? 0 : -ENOENT;  }  static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, -			    struct fastrpc_map **ppmap) +			    struct fastrpc_map **ppmap, bool take_ref)  { +	struct fastrpc_session_ctx *sess = fl->sctx;  	struct fastrpc_map *map = NULL; +	int ret = -ENOENT; -	mutex_lock(&fl->mutex); +	spin_lock(&fl->lock);  	list_for_each_entry(map, &fl->maps, node) { -		if (map->fd == fd) { -			*ppmap = map; -			mutex_unlock(&fl->mutex); -			return 0; -		} -	} -	mutex_unlock(&fl->mutex); - -	return -ENOENT; -} +		if (map->fd != fd) +			continue; -static int fastrpc_map_find(struct fastrpc_user *fl, int fd, -			    struct fastrpc_map **ppmap) -{ -	int ret = fastrpc_map_lookup(fl, fd, ppmap); +		if (take_ref) { +			ret = fastrpc_map_get(map); +			if (ret) { +				dev_dbg(sess->dev, "%s: Failed to get map fd=%d ret=%d\n", +					__func__, fd, ret); +				break; +			} +		} -	if (!ret) -		fastrpc_map_get(*ppmap); +		*ppmap = map; +		ret = 0; +		break; +	} +	spin_unlock(&fl->lock);  	return ret;  } @@ -746,7 +756,7 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,  	struct fastrpc_map *map = NULL;  	int err = 0; -	if (!fastrpc_map_find(fl, fd, ppmap)) +	if (!fastrpc_map_lookup(fl, fd, ppmap, true))  		return 0;  	map = kzalloc(sizeof(*map), GFP_KERNEL); @@ -788,10 +798,8 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,  		 * If subsystem VMIDs are defined in DTSI, then do  		 * hyp_assign from HLOS to those VM(s)  		 */ -		unsigned int perms = BIT(QCOM_SCM_VMID_HLOS); -  		map->attr = attr; -		err = qcom_scm_assign_mem(map->phys, (u64)map->size, &perms, +		err = qcom_scm_assign_mem(map->phys, (u64)map->size, &fl->cctx->perms,  				fl->cctx->vmperms, fl->cctx->vmcount);  		if (err) {  			dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d", @@ -1070,7 +1078,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,  	for (i = 0; i < FASTRPC_MAX_FDLIST; i++) {  		if (!fdlist[i])  			break; -		if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap)) +		if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false))  			fastrpc_map_put(mmap);  	} @@ -1258,10 +1266,9 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,  		/* Map if we have any heap VMIDs associated with this ADSP Static Process. */  		if (fl->cctx->vmcount) { -			unsigned int perms = BIT(QCOM_SCM_VMID_HLOS); -  			err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, -							(u64)fl->cctx->remote_heap->size, &perms, +							(u64)fl->cctx->remote_heap->size, +							&fl->cctx->perms,  							fl->cctx->vmperms, fl->cctx->vmcount);  			if (err) {  				dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d", @@ -1309,7 +1316,7 @@ err_invoke:  		perm.perm = QCOM_SCM_PERM_RWX;  		err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,  						(u64)fl->cctx->remote_heap->size, -						&(fl->cctx->vmperms[0].vmid), &perm, 1); +						&fl->cctx->perms, &perm, 1);  		if (err)  			dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",  				fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); @@ -1433,12 +1440,7 @@ err_invoke:  	fl->init_mem = NULL;  	fastrpc_buf_free(imem);  err_alloc: -	if (map) { -		spin_lock(&fl->lock); -		list_del(&map->node); -		spin_unlock(&fl->lock); -		fastrpc_map_put(map); -	} +	fastrpc_map_put(map);  err:  	kfree(args); @@ -1514,10 +1516,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)  		fastrpc_context_put(ctx);  	} -	list_for_each_entry_safe(map, m, &fl->maps, node) { -		list_del(&map->node); +	list_for_each_entry_safe(map, m, &fl->maps, node)  		fastrpc_map_put(map); -	}  	list_for_each_entry_safe(buf, b, &fl->mmaps, node) {  		list_del(&buf->node); @@ -1894,12 +1894,11 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)  	/* Add memory to static PD pool, protection thru hypervisor */  	if (req.flags != ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) {  		struct qcom_scm_vmperm perm; -		int err = 0;  		perm.vmid = QCOM_SCM_VMID_HLOS;  		perm.perm = QCOM_SCM_PERM_RWX;  		err = qcom_scm_assign_mem(buf->phys, buf->size, -			&(fl->cctx->vmperms[0].vmid), &perm, 1); +			&fl->cctx->perms, &perm, 1);  		if (err) {  			dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",  					buf->phys, buf->size, err); @@ -2316,7 +2315,18 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)  	data->domain_id = domain_id;  	data->rpdev = rpdev; -	return of_platform_populate(rdev->of_node, NULL, NULL, rdev); +	err = of_platform_populate(rdev->of_node, NULL, NULL, rdev); +	if (err) +		goto populate_error; + +	return 0; + +populate_error: +	if (data->fdevice) +		misc_deregister(&data->fdevice->miscdev); +	if (data->secure_fdevice) +		misc_deregister(&data->secure_fdevice->miscdev); +  fdev_error:  	kfree(data);  	return err;  |