Merge tag 'soc-drivers-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-microblaze.git] / drivers / misc / fastrpc.c
index 04f80e7..a701132 100644 (file)
@@ -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;