Loading drivers/char/adsprpc.c +190 −133 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #define RPC_HASH_BITS 5 #define RPC_HASH_SZ (1 << RPC_HASH_BITS) #define BALIGN 32 #define NUM_CHANNELS 2 #define LOCK_MMAP(kernel)\ do {\ Loading Loading @@ -127,6 +128,7 @@ static inline int buf_get_pages(void *addr, int sz, int nr_pages, int access, struct smq_invoke_ctx { struct completion work; int retval; int cid; atomic_t free; }; Loading @@ -143,20 +145,24 @@ struct fastrpc_smmu { bool enabled; }; struct fastrpc_apps { struct fastrpc_channel_context { smd_channel_t *chan; struct smq_context_list clst; struct device *dev; struct completion work; struct fastrpc_smmu smmu; struct kref kref; }; struct fastrpc_apps { struct fastrpc_channel_context channel[NUM_CHANNELS]; struct smq_context_list clst; struct ion_client *iclient; struct cdev cdev; struct class *class; struct device *dev; struct fastrpc_smmu smmu; struct mutex smd_mutex; dev_t dev_no; spinlock_t wrlock; spinlock_t hlock; struct kref kref; struct hlist_head htbl[RPC_HASH_SZ]; }; Loading @@ -181,6 +187,7 @@ struct file_data { spinlock_t hlock; struct hlist_head hlst; uint32_t mode; int cid; }; struct fastrpc_device { Loading @@ -189,16 +196,36 @@ struct fastrpc_device { struct fastrpc_buf buf; }; struct fastrpc_channel_info { char *name; char *node; char *group; int channel; }; static struct fastrpc_apps gfa; static void free_mem(struct fastrpc_buf *buf) static const struct fastrpc_channel_info gcinfo[NUM_CHANNELS] = { { .name = "adsprpc-smd", .node = "qcom,msm-audio-ion", .group = "lpass_audio", .channel = SMD_APPS_QDSP, }, { .name = "mdsprpc-smd", .channel = SMD_APPS_MODEM, }, }; static void free_mem(struct fastrpc_buf *buf, int cid) { struct fastrpc_apps *me = &gfa; if (!IS_ERR_OR_NULL(buf->handle)) { if (me->smmu.enabled && buf->phys) { if (me->channel[cid].smmu.enabled && buf->phys) { ion_unmap_iommu(me->iclient, buf->handle, me->smmu.domain_id, 0); me->channel[cid].smmu.domain_id, 0); buf->phys = 0; } if (!IS_ERR_OR_NULL(buf->virt)) { Loading @@ -223,7 +250,7 @@ static void free_map(struct fastrpc_mmap *map) map->handle = 0; } static int alloc_mem(struct fastrpc_buf *buf) static int alloc_mem(struct fastrpc_buf *buf, int cid) { struct fastrpc_apps *me = &gfa; struct ion_client *clnt = gfa.iclient; Loading @@ -234,7 +261,7 @@ static int alloc_mem(struct fastrpc_buf *buf) buf->handle = 0; buf->virt = 0; buf->phys = 0; heap = me->smmu.enabled ? ION_HEAP(ION_IOMMU_HEAP_ID) : heap = me->channel[cid].smmu.enabled ? ION_HEAP(ION_IOMMU_HEAP_ID) : ION_HEAP(ION_ADSP_HEAP_ID) | ION_HEAP(ION_AUDIO_HEAP_ID); buf->handle = ion_alloc(clnt, buf->size, SZ_4K, heap, ION_FLAG_CACHED); VERIFY(err, 0 == IS_ERR_OR_NULL(buf->handle)); Loading @@ -244,11 +271,11 @@ static int alloc_mem(struct fastrpc_buf *buf) VERIFY(err, 0 == IS_ERR_OR_NULL(buf->virt)); if (err) goto bail; if (me->smmu.enabled) { if (me->channel[cid].smmu.enabled) { len = buf->size; VERIFY(err, 0 == ion_map_iommu(clnt, buf->handle, me->smmu.domain_id, 0, SZ_4K, 0, &buf->phys, &len, 0, 0)); me->channel[cid].smmu.domain_id, 0, SZ_4K, 0, &buf->phys, &len, 0, 0)); if (err) goto bail; } else { Loading @@ -259,7 +286,7 @@ static int alloc_mem(struct fastrpc_buf *buf) } bail: if (err && !IS_ERR_OR_NULL(buf->handle)) free_mem(buf); free_mem(buf, cid); return err; } Loading @@ -281,7 +308,7 @@ static void context_list_dtor(struct smq_context_list *me) } static void context_list_alloc_ctx(struct smq_context_list *me, struct smq_invoke_ctx **po) struct smq_invoke_ctx **po, int cid) { int i = me->last; struct smq_invoke_ctx *ctx; Loading @@ -296,6 +323,7 @@ static void context_list_alloc_ctx(struct smq_context_list *me, } me->last = i; ctx->retval = -1; ctx->cid = cid; init_completion(&ctx->work); *po = ctx; } Loading @@ -312,20 +340,21 @@ static void context_notify_user(struct smq_invoke_ctx *me, int retval) complete(&me->work); } static void context_notify_all_users(struct smq_context_list *me) static void context_notify_all_users(struct smq_context_list *me, int cid) { int i; if (!me->ls) return; for (i = 0; i < me->size; ++i) { if (atomic_read(&me->ls[i].free) != 0) if ((atomic_read(&me->ls[i].free) != 0) && (me->ls[i].cid == cid)) complete(&me->ls[i].work); } } static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, struct fastrpc_buf *ibuf, struct fastrpc_buf *obuf) struct fastrpc_buf *ibuf, struct fastrpc_buf *obuf, int cid) { struct smq_phy_page *pgstart, *pages; struct smq_invoke_buf *list; Loading @@ -343,7 +372,7 @@ static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, if (rlen < 0) { rlen = ((uint32_t)pages - (uint32_t)obuf->virt) - obuf->size; obuf->size += buf_page_size(rlen); VERIFY(err, 0 == alloc_mem(obuf)); VERIFY(err, 0 == alloc_mem(obuf, cid)); if (err) goto bail; goto retry; Loading Loading @@ -380,9 +409,9 @@ static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, pages = pages + 1; } else { if (obuf->handle != ibuf->handle) free_mem(obuf); free_mem(obuf, cid); obuf->size += buf_page_size(sizeof(*pages)); VERIFY(err, 0 == alloc_mem(obuf)); VERIFY(err, 0 == alloc_mem(obuf, cid)); if (err) goto bail; goto retry; Loading @@ -392,7 +421,7 @@ static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, obuf->used = obuf->size - rlen; bail: if (err && (obuf->handle != ibuf->handle)) free_mem(obuf); free_mem(obuf, cid); UNLOCK_MMAP(kernel); return err; } Loading @@ -400,7 +429,7 @@ static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra, remote_arg_t *rpra, remote_arg_t *upra, struct fastrpc_buf *ibuf, struct fastrpc_buf **abufs, int *nbufs, int *fds) int *nbufs, int *fds, int cid) { struct fastrpc_apps *me = &gfa; struct smq_invoke_buf *list; Loading Loading @@ -429,15 +458,16 @@ static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra, if (list[i].num) { rpra[i].buf.pv = pra[i].buf.pv; continue; } else if (me->smmu.enabled && fds && (fds[i] >= 0)) { } else if (me->channel[cid].smmu.enabled && fds && (fds[i] >= 0)) { len = buf_page_size(pra[i].buf.len); handles[i] = ion_import_dma_buf(me->iclient, fds[i]); VERIFY(err, 0 == IS_ERR_OR_NULL(handles[i])); if (err) goto bail; VERIFY(err, 0 == ion_map_iommu(me->iclient, handles[i], me->smmu.domain_id, 0, SZ_4K, 0, &iova, &len, 0, 0)); me->channel[cid].smmu.domain_id, 0, SZ_4K, 0, &iova, &len, 0, 0)); if (err) goto bail; rpra[i].buf.pv = pra[i].buf.pv; Loading @@ -457,7 +487,7 @@ static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra, pbuf = obufs + bufs; pbuf->size = buf_num_pages(0, pra[i].buf.len) * PAGE_SIZE; VERIFY(err, 0 == alloc_mem(pbuf)); VERIFY(err, 0 == alloc_mem(pbuf, cid)); if (err) goto bail; bufs++; Loading Loading @@ -604,7 +634,7 @@ static int fastrpc_invoke_send(struct fastrpc_apps *me, msg.invoke.page.addr = buf->phys; msg.invoke.page.size = buf_page_size(buf->used); spin_lock(&me->wrlock); len = smd_write(me->chan, &msg, sizeof(msg)); len = smd_write(me->channel[ctx->cid].chan, &msg, sizeof(msg)); spin_unlock(&me->wrlock); VERIFY(err, len == sizeof(msg)); return err; Loading @@ -613,23 +643,29 @@ static int fastrpc_invoke_send(struct fastrpc_apps *me, static void fastrpc_deinit(void) { struct fastrpc_apps *me = &gfa; int i; smd_close(me->chan); for (i = 0; i < NUM_CHANNELS; i++) { if (me->channel[i].chan) { (void)smd_close(me->channel[i].chan); me->channel[i].chan = 0; } } context_list_dtor(&me->clst); ion_client_destroy(me->iclient); me->iclient = 0; me->chan = 0; } static void fastrpc_read_handler(void) static void fastrpc_read_handler(int cid) { struct fastrpc_apps *me = &gfa; struct smq_invoke_rsp rsp; int err = 0; do { VERIFY(err, sizeof(rsp) == smd_read_from_cb(me->chan, &rsp, sizeof(rsp))); VERIFY(err, sizeof(rsp) == smd_read_from_cb( me->channel[cid].chan, &rsp, sizeof(rsp))); if (err) goto bail; context_notify_user(rsp.ctx, rsp.retval); Loading @@ -640,33 +676,32 @@ static void fastrpc_read_handler(void) static void smd_event_handler(void *priv, unsigned event) { struct fastrpc_apps *me = (struct fastrpc_apps *)priv; struct fastrpc_apps *me = &gfa; int cid = (int)priv; switch (event) { case SMD_EVENT_OPEN: complete(&(me->work)); complete(&me->channel[cid].work); break; case SMD_EVENT_CLOSE: context_notify_all_users(&me->clst); context_notify_all_users(&me->clst, cid); break; case SMD_EVENT_DATA: fastrpc_read_handler(); fastrpc_read_handler(cid); break; } } static int fastrpc_init(void) { int err = 0; int i, err = 0; struct fastrpc_apps *me = &gfa; struct device_node *node; struct fastrpc_smmu *smmu; bool enabled = 0; if (me->chan == 0) { int i; spin_lock_init(&me->hlock); spin_lock_init(&me->wrlock); init_completion(&me->work); mutex_init(&me->smd_mutex); for (i = 0; i < RPC_HASH_SZ; ++i) INIT_HLIST_HEAD(&me->htbl[i]); Loading @@ -678,24 +713,25 @@ static int fastrpc_init(void) VERIFY(err, 0 == IS_ERR_OR_NULL(me->iclient)); if (err) goto ion_bail; node = of_find_compatible_node(NULL, NULL, "qcom,msm-audio-ion"); for (i = 0; i < NUM_CHANNELS; i++) { init_completion(&me->channel[i].work); if (!gcinfo[i].node) continue; smmu = &me->channel[i].smmu; node = of_find_compatible_node(NULL, NULL, gcinfo[i].node); if (node) enabled = of_property_read_bool(node, "qcom,smmu-enabled"); if (enabled) me->smmu.group = iommu_group_find("lpass_audio"); if (me->smmu.group) me->smmu.domain = iommu_group_get_iommudata( me->smmu.group); if (!IS_ERR_OR_NULL(me->smmu.domain)) { me->smmu.domain_id = msm_find_domain_no( me->smmu.domain); if (me->smmu.domain_id >= 0) me->smmu.enabled = enabled; smmu->group = iommu_group_find(gcinfo[i].group); if (smmu->group) smmu->domain = iommu_group_get_iommudata(smmu->group); if (!IS_ERR_OR_NULL(smmu->domain)) { smmu->domain_id = msm_find_domain_no(smmu->domain); if (smmu->domain_id >= 0) smmu->enabled = enabled; } } return 0; ion_bail: Loading @@ -704,16 +740,16 @@ context_list_bail: return err; } static void free_dev(struct fastrpc_device *dev) static void free_dev(struct fastrpc_device *dev, int cid) { if (dev) { free_mem(&dev->buf); free_mem(&dev->buf, cid); kfree(dev); module_put(THIS_MODULE); } } static int alloc_dev(struct fastrpc_device **dev) static int alloc_dev(struct fastrpc_device **dev, int cid) { int err = 0; struct fastrpc_device *fd = 0; Loading @@ -728,7 +764,7 @@ static int alloc_dev(struct fastrpc_device **dev) INIT_HLIST_NODE(&fd->hn); fd->buf.size = PAGE_SIZE; VERIFY(err, 0 == alloc_mem(&fd->buf)); VERIFY(err, 0 == alloc_mem(&fd->buf, cid)); if (err) goto bail; fd->tgid = current->tgid; Loading @@ -736,11 +772,12 @@ static int alloc_dev(struct fastrpc_device **dev) *dev = fd; bail: if (err) free_dev(fd); free_dev(fd, cid); return err; } static int get_dev(struct fastrpc_apps *me, struct fastrpc_device **rdev) static int get_dev(struct fastrpc_apps *me, int cid, struct fastrpc_device **rdev) { struct hlist_head *head; struct fastrpc_device *dev = 0, *devfree = 0; Loading @@ -764,8 +801,8 @@ static int get_dev(struct fastrpc_apps *me, struct fastrpc_device **rdev) *rdev = devfree; bail: if (err) { free_dev(devfree); err = alloc_dev(rdev); free_dev(devfree, cid); err = alloc_dev(rdev, cid); } return err; } Loading @@ -782,11 +819,11 @@ static void add_dev(struct fastrpc_apps *me, struct fastrpc_device *dev) return; } static int fastrpc_release_current_dsp_process(void); static int fastrpc_release_current_dsp_process(int cid); static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t mode, uint32_t kernel, struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra, int *fds) remote_arg_t *pra, int *fds, int cid) { remote_arg_t *rpra = 0; struct fastrpc_device *dev = 0; Loading @@ -799,28 +836,29 @@ static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t mode, sc = invoke->sc; obuf.handle = 0; if (me->smmu.enabled) { VERIFY(err, 0 == iommu_attach_group(me->smmu.domain, me->smmu.group)); if (me->channel[cid].smmu.enabled) { VERIFY(err, 0 == iommu_attach_group( me->channel[cid].smmu.domain, me->channel[cid].smmu.group)); if (err) return err; } if (REMOTE_SCALARS_LENGTH(sc)) { VERIFY(err, 0 == get_dev(me, &dev)); VERIFY(err, 0 == get_dev(me, cid, &dev)); if (err) goto bail; VERIFY(err, 0 == get_page_list(kernel, sc, pra, &dev->buf, &obuf)); &obuf, cid)); if (err) goto bail; rpra = (remote_arg_t *)obuf.virt; VERIFY(err, 0 == get_args(kernel, sc, pra, rpra, invoke->pra, &obuf, &abufs, &nbufs, fds)); &obuf, &abufs, &nbufs, fds, cid)); if (err) goto bail; } context_list_alloc_ctx(&me->clst, &ctx); context_list_alloc_ctx(&me->clst, &ctx, cid); inv_args_pre(sc, rpra); if (FASTRPC_MODE_SERIAL == mode) inv_args(sc, rpra, obuf.used); Loading @@ -847,32 +885,34 @@ static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t mode, } context_free(ctx); if (me->smmu.enabled) { if (me->channel[cid].smmu.enabled) { bufs = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc); if (fds) { handles = (struct ion_handle **)(fds + bufs); for (i = 0; i < bufs; i++) if (!IS_ERR_OR_NULL(handles[i])) { ion_unmap_iommu(me->iclient, handles[i], me->smmu.domain_id, 0); me->channel[cid].smmu.domain_id, 0); ion_free(me->iclient, handles[i]); } } iommu_detach_group(me->smmu.domain, me->smmu.group); iommu_detach_group(me->channel[cid].smmu.domain, me->channel[cid].smmu.group); } for (i = 0, b = abufs; i < nbufs; ++i, ++b) free_mem(b); free_mem(b, cid); kfree(abufs); if (dev) { add_dev(me, dev); if (obuf.handle != dev->buf.handle) free_mem(&obuf); free_mem(&obuf, cid); } return err; } static int fastrpc_create_current_dsp_process(void) static int fastrpc_create_current_dsp_process(int cid) { int err = 0; struct fastrpc_ioctl_invoke ioctl; Loading @@ -887,11 +927,11 @@ static int fastrpc_create_current_dsp_process(void) ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0); ioctl.pra = ra; VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0))); FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0, cid))); return err; } static int fastrpc_release_current_dsp_process(void) static int fastrpc_release_current_dsp_process(int cid) { int err = 0; struct fastrpc_apps *me = &gfa; Loading @@ -906,14 +946,14 @@ static int fastrpc_release_current_dsp_process(void) ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0); ioctl.pra = ra; VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0))); FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0, cid))); return err; } static int fastrpc_mmap_on_dsp(struct fastrpc_apps *me, struct fastrpc_ioctl_mmap *mmap, struct smq_phy_page *pages, int num) int cid, int num) { struct fastrpc_ioctl_invoke ioctl; remote_arg_t ra[3]; Loading Loading @@ -945,7 +985,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_apps *me, ioctl.sc = REMOTE_SCALARS_MAKE(2, 2, 1); ioctl.pra = ra; VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0))); FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0, cid))); mmap->vaddrout = routargs.vaddrout; if (err) goto bail; Loading @@ -954,7 +994,7 @@ bail: } static int fastrpc_munmap_on_dsp(struct fastrpc_apps *me, struct fastrpc_ioctl_munmap *munmap) struct fastrpc_ioctl_munmap *munmap, int cid) { struct fastrpc_ioctl_invoke ioctl; remote_arg_t ra[1]; Loading @@ -975,7 +1015,7 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_apps *me, ioctl.sc = REMOTE_SCALARS_MAKE(3, 1, 0); ioctl.pra = ra; VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0))); FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0, cid))); return err; } Loading @@ -986,7 +1026,7 @@ static int fastrpc_internal_munmap(struct fastrpc_apps *me, int err = 0; struct fastrpc_mmap *map = 0, *mapfree = 0; struct hlist_node *n; VERIFY(err, 0 == (err = fastrpc_munmap_on_dsp(me, munmap))); VERIFY(err, 0 == (err = fastrpc_munmap_on_dsp(me, munmap, fdata->cid))); if (err) goto bail; spin_lock(&fdata->hlock); Loading Loading @@ -1042,7 +1082,7 @@ static int fastrpc_internal_mmap(struct fastrpc_apps *me, if (err) goto bail; VERIFY(err, 0 == fastrpc_mmap_on_dsp(me, mmap, pages, num)); VERIFY(err, 0 == fastrpc_mmap_on_dsp(me, mmap, pages, fdata->cid, num)); if (err) goto bail; map->vaddrin = mmap->vaddrin; Loading @@ -1061,7 +1101,7 @@ static int fastrpc_internal_mmap(struct fastrpc_apps *me, return err; } static void cleanup_current_dev(void) static void cleanup_current_dev(int cid) { struct fastrpc_apps *me = &gfa; uint32_t h = hash_32(current->tgid, RPC_HASH_BITS); Loading @@ -1082,7 +1122,7 @@ static void cleanup_current_dev(void) } spin_unlock(&me->hlock); if (devfree) { free_dev(devfree); free_dev(devfree, cid); goto rnext; } return; Loading @@ -1091,21 +1131,26 @@ static void cleanup_current_dev(void) static void fastrpc_channel_close(struct kref *kref) { struct fastrpc_apps *me = &gfa; struct fastrpc_channel_context *ctx; int cid; smd_close(me->chan); me->chan = 0; ctx = container_of(kref, struct fastrpc_channel_context, kref); smd_close(ctx->chan); ctx->chan = 0; mutex_unlock(&me->smd_mutex); pr_info("'closed /dev/%s c %d 0'\n", DEVICE_NAME, MAJOR(me->dev_no)); cid = ctx - &me->channel[0]; pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name, MAJOR(me->dev_no), cid); } static int fastrpc_device_release(struct inode *inode, struct file *file) { struct file_data *fdata = (struct file_data *)file->private_data; struct fastrpc_apps *me = &gfa; int cid = MINOR(inode->i_rdev); (void)fastrpc_release_current_dsp_process(); cleanup_current_dev(); (void)fastrpc_release_current_dsp_process(cid); cleanup_current_dev(cid); if (fdata) { struct fastrpc_mmap *map; struct hlist_node *n; Loading @@ -1116,7 +1161,7 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) kfree(map); } kfree(fdata); kref_put_mutex(&me->kref, fastrpc_channel_close, kref_put_mutex(&me->channel[cid].kref, fastrpc_channel_close, &me->smd_mutex); } return 0; Loading @@ -1124,23 +1169,27 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) static int fastrpc_device_open(struct inode *inode, struct file *filp) { int cid = MINOR(inode->i_rdev); int err = 0; struct fastrpc_apps *me = &gfa; mutex_lock(&me->smd_mutex); if (kref_get_unless_zero(&me->kref) == 0) { VERIFY(err, 0 == smd_named_open_on_edge(FASTRPC_SMD_GUID, SMD_APPS_QDSP, &me->chan, me, smd_event_handler)); if (kref_get_unless_zero(&me->channel[cid].kref) == 0) { VERIFY(err, 0 == smd_named_open_on_edge( FASTRPC_SMD_GUID, gcinfo[cid].channel, &me->channel[cid].chan, (void *)cid, smd_event_handler)); if (err) goto smd_bail; VERIFY(err, 0 != wait_for_completion_timeout(&me->work, VERIFY(err, 0 != wait_for_completion_timeout( &me->channel[cid].work, RPC_TIMEOUT)); if (err) goto completion_bail; kref_init(&me->kref); pr_info("'opened /dev/%s c %d 0'\n", DEVICE_NAME, MAJOR(me->dev_no)); kref_init(&me->channel[cid].kref); pr_info("'opened /dev/%s c %d %d'\n", gcinfo[cid].name, MAJOR(me->dev_no), cid); } mutex_unlock(&me->smd_mutex); Loading @@ -1156,25 +1205,26 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) spin_lock_init(&fdata->hlock); INIT_HLIST_HEAD(&fdata->hlst); fdata->cid = cid; VERIFY(err, 0 == fastrpc_create_current_dsp_process()); VERIFY(err, 0 == fastrpc_create_current_dsp_process(cid)); if (err) goto bail; filp->private_data = fdata; bail: if (err) { cleanup_current_dev(); cleanup_current_dev(cid); kfree(fdata); kref_put_mutex(&me->kref, fastrpc_channel_close, &me->smd_mutex); kref_put_mutex(&me->channel[cid].kref, fastrpc_channel_close, &me->smd_mutex); } module_put(THIS_MODULE); } return err; completion_bail: smd_close(me->chan); me->chan = 0; smd_close(me->channel[cid].chan); me->channel[cid].chan = 0; smd_bail: mutex_unlock(&me->smd_mutex); return err; Loading Loading @@ -1227,7 +1277,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, goto bail; } VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, fdata->mode, 0, invoke, pra, fds))); 0, invoke, pra, fds, fdata->cid))); if (err) goto bail; break; Loading Loading @@ -1283,29 +1333,34 @@ static const struct file_operations fops = { static int __init fastrpc_device_init(void) { struct fastrpc_apps *me = &gfa; int err = 0; int i, err = 0; memset(me, 0, sizeof(*me)); VERIFY(err, 0 == fastrpc_init()); if (err) goto fastrpc_bail; VERIFY(err, 0 == alloc_chrdev_region(&me->dev_no, 0, 1, DEVICE_NAME)); VERIFY(err, 0 == alloc_chrdev_region(&me->dev_no, 0, NUM_CHANNELS, DEVICE_NAME)); if (err) goto alloc_chrdev_bail; cdev_init(&me->cdev, &fops); me->cdev.owner = THIS_MODULE; VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), 1)); VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), NUM_CHANNELS)); if (err) goto cdev_init_bail; me->class = class_create(THIS_MODULE, "fastrpc"); VERIFY(err, !IS_ERR(me->class)); if (err) goto class_create_bail; me->dev = device_create(me->class, NULL, MKDEV(MAJOR(me->dev_no), 0), NULL, DEVICE_NAME); VERIFY(err, !IS_ERR(me->dev)); for (i = 0; i < NUM_CHANNELS; i++) { me->channel[i].dev = device_create(me->class, NULL, MKDEV(MAJOR(me->dev_no), i), NULL, gcinfo[i].name); VERIFY(err, !IS_ERR(me->channel[i].dev)); if (err) goto device_create_bail; } return 0; Loading @@ -1314,7 +1369,7 @@ device_create_bail: class_create_bail: cdev_del(&me->cdev); cdev_init_bail: unregister_chrdev_region(me->dev_no, 1); unregister_chrdev_region(me->dev_no, NUM_CHANNELS); alloc_chrdev_bail: fastrpc_deinit(); fastrpc_bail: Loading @@ -1324,12 +1379,14 @@ fastrpc_bail: static void __exit fastrpc_device_exit(void) { struct fastrpc_apps *me = &gfa; int i; fastrpc_deinit(); device_destroy(me->class, MKDEV(MAJOR(me->dev_no), 0)); for (i = 0; i < NUM_CHANNELS; i++) device_destroy(me->class, MKDEV(MAJOR(me->dev_no), i)); class_destroy(me->class); cdev_del(&me->cdev); unregister_chrdev_region(me->dev_no, 1); unregister_chrdev_region(me->dev_no, NUM_CHANNELS); } module_init(fastrpc_device_init); Loading Loading
drivers/char/adsprpc.c +190 −133 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #define RPC_HASH_BITS 5 #define RPC_HASH_SZ (1 << RPC_HASH_BITS) #define BALIGN 32 #define NUM_CHANNELS 2 #define LOCK_MMAP(kernel)\ do {\ Loading Loading @@ -127,6 +128,7 @@ static inline int buf_get_pages(void *addr, int sz, int nr_pages, int access, struct smq_invoke_ctx { struct completion work; int retval; int cid; atomic_t free; }; Loading @@ -143,20 +145,24 @@ struct fastrpc_smmu { bool enabled; }; struct fastrpc_apps { struct fastrpc_channel_context { smd_channel_t *chan; struct smq_context_list clst; struct device *dev; struct completion work; struct fastrpc_smmu smmu; struct kref kref; }; struct fastrpc_apps { struct fastrpc_channel_context channel[NUM_CHANNELS]; struct smq_context_list clst; struct ion_client *iclient; struct cdev cdev; struct class *class; struct device *dev; struct fastrpc_smmu smmu; struct mutex smd_mutex; dev_t dev_no; spinlock_t wrlock; spinlock_t hlock; struct kref kref; struct hlist_head htbl[RPC_HASH_SZ]; }; Loading @@ -181,6 +187,7 @@ struct file_data { spinlock_t hlock; struct hlist_head hlst; uint32_t mode; int cid; }; struct fastrpc_device { Loading @@ -189,16 +196,36 @@ struct fastrpc_device { struct fastrpc_buf buf; }; struct fastrpc_channel_info { char *name; char *node; char *group; int channel; }; static struct fastrpc_apps gfa; static void free_mem(struct fastrpc_buf *buf) static const struct fastrpc_channel_info gcinfo[NUM_CHANNELS] = { { .name = "adsprpc-smd", .node = "qcom,msm-audio-ion", .group = "lpass_audio", .channel = SMD_APPS_QDSP, }, { .name = "mdsprpc-smd", .channel = SMD_APPS_MODEM, }, }; static void free_mem(struct fastrpc_buf *buf, int cid) { struct fastrpc_apps *me = &gfa; if (!IS_ERR_OR_NULL(buf->handle)) { if (me->smmu.enabled && buf->phys) { if (me->channel[cid].smmu.enabled && buf->phys) { ion_unmap_iommu(me->iclient, buf->handle, me->smmu.domain_id, 0); me->channel[cid].smmu.domain_id, 0); buf->phys = 0; } if (!IS_ERR_OR_NULL(buf->virt)) { Loading @@ -223,7 +250,7 @@ static void free_map(struct fastrpc_mmap *map) map->handle = 0; } static int alloc_mem(struct fastrpc_buf *buf) static int alloc_mem(struct fastrpc_buf *buf, int cid) { struct fastrpc_apps *me = &gfa; struct ion_client *clnt = gfa.iclient; Loading @@ -234,7 +261,7 @@ static int alloc_mem(struct fastrpc_buf *buf) buf->handle = 0; buf->virt = 0; buf->phys = 0; heap = me->smmu.enabled ? ION_HEAP(ION_IOMMU_HEAP_ID) : heap = me->channel[cid].smmu.enabled ? ION_HEAP(ION_IOMMU_HEAP_ID) : ION_HEAP(ION_ADSP_HEAP_ID) | ION_HEAP(ION_AUDIO_HEAP_ID); buf->handle = ion_alloc(clnt, buf->size, SZ_4K, heap, ION_FLAG_CACHED); VERIFY(err, 0 == IS_ERR_OR_NULL(buf->handle)); Loading @@ -244,11 +271,11 @@ static int alloc_mem(struct fastrpc_buf *buf) VERIFY(err, 0 == IS_ERR_OR_NULL(buf->virt)); if (err) goto bail; if (me->smmu.enabled) { if (me->channel[cid].smmu.enabled) { len = buf->size; VERIFY(err, 0 == ion_map_iommu(clnt, buf->handle, me->smmu.domain_id, 0, SZ_4K, 0, &buf->phys, &len, 0, 0)); me->channel[cid].smmu.domain_id, 0, SZ_4K, 0, &buf->phys, &len, 0, 0)); if (err) goto bail; } else { Loading @@ -259,7 +286,7 @@ static int alloc_mem(struct fastrpc_buf *buf) } bail: if (err && !IS_ERR_OR_NULL(buf->handle)) free_mem(buf); free_mem(buf, cid); return err; } Loading @@ -281,7 +308,7 @@ static void context_list_dtor(struct smq_context_list *me) } static void context_list_alloc_ctx(struct smq_context_list *me, struct smq_invoke_ctx **po) struct smq_invoke_ctx **po, int cid) { int i = me->last; struct smq_invoke_ctx *ctx; Loading @@ -296,6 +323,7 @@ static void context_list_alloc_ctx(struct smq_context_list *me, } me->last = i; ctx->retval = -1; ctx->cid = cid; init_completion(&ctx->work); *po = ctx; } Loading @@ -312,20 +340,21 @@ static void context_notify_user(struct smq_invoke_ctx *me, int retval) complete(&me->work); } static void context_notify_all_users(struct smq_context_list *me) static void context_notify_all_users(struct smq_context_list *me, int cid) { int i; if (!me->ls) return; for (i = 0; i < me->size; ++i) { if (atomic_read(&me->ls[i].free) != 0) if ((atomic_read(&me->ls[i].free) != 0) && (me->ls[i].cid == cid)) complete(&me->ls[i].work); } } static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, struct fastrpc_buf *ibuf, struct fastrpc_buf *obuf) struct fastrpc_buf *ibuf, struct fastrpc_buf *obuf, int cid) { struct smq_phy_page *pgstart, *pages; struct smq_invoke_buf *list; Loading @@ -343,7 +372,7 @@ static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, if (rlen < 0) { rlen = ((uint32_t)pages - (uint32_t)obuf->virt) - obuf->size; obuf->size += buf_page_size(rlen); VERIFY(err, 0 == alloc_mem(obuf)); VERIFY(err, 0 == alloc_mem(obuf, cid)); if (err) goto bail; goto retry; Loading Loading @@ -380,9 +409,9 @@ static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, pages = pages + 1; } else { if (obuf->handle != ibuf->handle) free_mem(obuf); free_mem(obuf, cid); obuf->size += buf_page_size(sizeof(*pages)); VERIFY(err, 0 == alloc_mem(obuf)); VERIFY(err, 0 == alloc_mem(obuf, cid)); if (err) goto bail; goto retry; Loading @@ -392,7 +421,7 @@ static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, obuf->used = obuf->size - rlen; bail: if (err && (obuf->handle != ibuf->handle)) free_mem(obuf); free_mem(obuf, cid); UNLOCK_MMAP(kernel); return err; } Loading @@ -400,7 +429,7 @@ static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra, remote_arg_t *rpra, remote_arg_t *upra, struct fastrpc_buf *ibuf, struct fastrpc_buf **abufs, int *nbufs, int *fds) int *nbufs, int *fds, int cid) { struct fastrpc_apps *me = &gfa; struct smq_invoke_buf *list; Loading Loading @@ -429,15 +458,16 @@ static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra, if (list[i].num) { rpra[i].buf.pv = pra[i].buf.pv; continue; } else if (me->smmu.enabled && fds && (fds[i] >= 0)) { } else if (me->channel[cid].smmu.enabled && fds && (fds[i] >= 0)) { len = buf_page_size(pra[i].buf.len); handles[i] = ion_import_dma_buf(me->iclient, fds[i]); VERIFY(err, 0 == IS_ERR_OR_NULL(handles[i])); if (err) goto bail; VERIFY(err, 0 == ion_map_iommu(me->iclient, handles[i], me->smmu.domain_id, 0, SZ_4K, 0, &iova, &len, 0, 0)); me->channel[cid].smmu.domain_id, 0, SZ_4K, 0, &iova, &len, 0, 0)); if (err) goto bail; rpra[i].buf.pv = pra[i].buf.pv; Loading @@ -457,7 +487,7 @@ static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra, pbuf = obufs + bufs; pbuf->size = buf_num_pages(0, pra[i].buf.len) * PAGE_SIZE; VERIFY(err, 0 == alloc_mem(pbuf)); VERIFY(err, 0 == alloc_mem(pbuf, cid)); if (err) goto bail; bufs++; Loading Loading @@ -604,7 +634,7 @@ static int fastrpc_invoke_send(struct fastrpc_apps *me, msg.invoke.page.addr = buf->phys; msg.invoke.page.size = buf_page_size(buf->used); spin_lock(&me->wrlock); len = smd_write(me->chan, &msg, sizeof(msg)); len = smd_write(me->channel[ctx->cid].chan, &msg, sizeof(msg)); spin_unlock(&me->wrlock); VERIFY(err, len == sizeof(msg)); return err; Loading @@ -613,23 +643,29 @@ static int fastrpc_invoke_send(struct fastrpc_apps *me, static void fastrpc_deinit(void) { struct fastrpc_apps *me = &gfa; int i; smd_close(me->chan); for (i = 0; i < NUM_CHANNELS; i++) { if (me->channel[i].chan) { (void)smd_close(me->channel[i].chan); me->channel[i].chan = 0; } } context_list_dtor(&me->clst); ion_client_destroy(me->iclient); me->iclient = 0; me->chan = 0; } static void fastrpc_read_handler(void) static void fastrpc_read_handler(int cid) { struct fastrpc_apps *me = &gfa; struct smq_invoke_rsp rsp; int err = 0; do { VERIFY(err, sizeof(rsp) == smd_read_from_cb(me->chan, &rsp, sizeof(rsp))); VERIFY(err, sizeof(rsp) == smd_read_from_cb( me->channel[cid].chan, &rsp, sizeof(rsp))); if (err) goto bail; context_notify_user(rsp.ctx, rsp.retval); Loading @@ -640,33 +676,32 @@ static void fastrpc_read_handler(void) static void smd_event_handler(void *priv, unsigned event) { struct fastrpc_apps *me = (struct fastrpc_apps *)priv; struct fastrpc_apps *me = &gfa; int cid = (int)priv; switch (event) { case SMD_EVENT_OPEN: complete(&(me->work)); complete(&me->channel[cid].work); break; case SMD_EVENT_CLOSE: context_notify_all_users(&me->clst); context_notify_all_users(&me->clst, cid); break; case SMD_EVENT_DATA: fastrpc_read_handler(); fastrpc_read_handler(cid); break; } } static int fastrpc_init(void) { int err = 0; int i, err = 0; struct fastrpc_apps *me = &gfa; struct device_node *node; struct fastrpc_smmu *smmu; bool enabled = 0; if (me->chan == 0) { int i; spin_lock_init(&me->hlock); spin_lock_init(&me->wrlock); init_completion(&me->work); mutex_init(&me->smd_mutex); for (i = 0; i < RPC_HASH_SZ; ++i) INIT_HLIST_HEAD(&me->htbl[i]); Loading @@ -678,24 +713,25 @@ static int fastrpc_init(void) VERIFY(err, 0 == IS_ERR_OR_NULL(me->iclient)); if (err) goto ion_bail; node = of_find_compatible_node(NULL, NULL, "qcom,msm-audio-ion"); for (i = 0; i < NUM_CHANNELS; i++) { init_completion(&me->channel[i].work); if (!gcinfo[i].node) continue; smmu = &me->channel[i].smmu; node = of_find_compatible_node(NULL, NULL, gcinfo[i].node); if (node) enabled = of_property_read_bool(node, "qcom,smmu-enabled"); if (enabled) me->smmu.group = iommu_group_find("lpass_audio"); if (me->smmu.group) me->smmu.domain = iommu_group_get_iommudata( me->smmu.group); if (!IS_ERR_OR_NULL(me->smmu.domain)) { me->smmu.domain_id = msm_find_domain_no( me->smmu.domain); if (me->smmu.domain_id >= 0) me->smmu.enabled = enabled; smmu->group = iommu_group_find(gcinfo[i].group); if (smmu->group) smmu->domain = iommu_group_get_iommudata(smmu->group); if (!IS_ERR_OR_NULL(smmu->domain)) { smmu->domain_id = msm_find_domain_no(smmu->domain); if (smmu->domain_id >= 0) smmu->enabled = enabled; } } return 0; ion_bail: Loading @@ -704,16 +740,16 @@ context_list_bail: return err; } static void free_dev(struct fastrpc_device *dev) static void free_dev(struct fastrpc_device *dev, int cid) { if (dev) { free_mem(&dev->buf); free_mem(&dev->buf, cid); kfree(dev); module_put(THIS_MODULE); } } static int alloc_dev(struct fastrpc_device **dev) static int alloc_dev(struct fastrpc_device **dev, int cid) { int err = 0; struct fastrpc_device *fd = 0; Loading @@ -728,7 +764,7 @@ static int alloc_dev(struct fastrpc_device **dev) INIT_HLIST_NODE(&fd->hn); fd->buf.size = PAGE_SIZE; VERIFY(err, 0 == alloc_mem(&fd->buf)); VERIFY(err, 0 == alloc_mem(&fd->buf, cid)); if (err) goto bail; fd->tgid = current->tgid; Loading @@ -736,11 +772,12 @@ static int alloc_dev(struct fastrpc_device **dev) *dev = fd; bail: if (err) free_dev(fd); free_dev(fd, cid); return err; } static int get_dev(struct fastrpc_apps *me, struct fastrpc_device **rdev) static int get_dev(struct fastrpc_apps *me, int cid, struct fastrpc_device **rdev) { struct hlist_head *head; struct fastrpc_device *dev = 0, *devfree = 0; Loading @@ -764,8 +801,8 @@ static int get_dev(struct fastrpc_apps *me, struct fastrpc_device **rdev) *rdev = devfree; bail: if (err) { free_dev(devfree); err = alloc_dev(rdev); free_dev(devfree, cid); err = alloc_dev(rdev, cid); } return err; } Loading @@ -782,11 +819,11 @@ static void add_dev(struct fastrpc_apps *me, struct fastrpc_device *dev) return; } static int fastrpc_release_current_dsp_process(void); static int fastrpc_release_current_dsp_process(int cid); static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t mode, uint32_t kernel, struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra, int *fds) remote_arg_t *pra, int *fds, int cid) { remote_arg_t *rpra = 0; struct fastrpc_device *dev = 0; Loading @@ -799,28 +836,29 @@ static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t mode, sc = invoke->sc; obuf.handle = 0; if (me->smmu.enabled) { VERIFY(err, 0 == iommu_attach_group(me->smmu.domain, me->smmu.group)); if (me->channel[cid].smmu.enabled) { VERIFY(err, 0 == iommu_attach_group( me->channel[cid].smmu.domain, me->channel[cid].smmu.group)); if (err) return err; } if (REMOTE_SCALARS_LENGTH(sc)) { VERIFY(err, 0 == get_dev(me, &dev)); VERIFY(err, 0 == get_dev(me, cid, &dev)); if (err) goto bail; VERIFY(err, 0 == get_page_list(kernel, sc, pra, &dev->buf, &obuf)); &obuf, cid)); if (err) goto bail; rpra = (remote_arg_t *)obuf.virt; VERIFY(err, 0 == get_args(kernel, sc, pra, rpra, invoke->pra, &obuf, &abufs, &nbufs, fds)); &obuf, &abufs, &nbufs, fds, cid)); if (err) goto bail; } context_list_alloc_ctx(&me->clst, &ctx); context_list_alloc_ctx(&me->clst, &ctx, cid); inv_args_pre(sc, rpra); if (FASTRPC_MODE_SERIAL == mode) inv_args(sc, rpra, obuf.used); Loading @@ -847,32 +885,34 @@ static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t mode, } context_free(ctx); if (me->smmu.enabled) { if (me->channel[cid].smmu.enabled) { bufs = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc); if (fds) { handles = (struct ion_handle **)(fds + bufs); for (i = 0; i < bufs; i++) if (!IS_ERR_OR_NULL(handles[i])) { ion_unmap_iommu(me->iclient, handles[i], me->smmu.domain_id, 0); me->channel[cid].smmu.domain_id, 0); ion_free(me->iclient, handles[i]); } } iommu_detach_group(me->smmu.domain, me->smmu.group); iommu_detach_group(me->channel[cid].smmu.domain, me->channel[cid].smmu.group); } for (i = 0, b = abufs; i < nbufs; ++i, ++b) free_mem(b); free_mem(b, cid); kfree(abufs); if (dev) { add_dev(me, dev); if (obuf.handle != dev->buf.handle) free_mem(&obuf); free_mem(&obuf, cid); } return err; } static int fastrpc_create_current_dsp_process(void) static int fastrpc_create_current_dsp_process(int cid) { int err = 0; struct fastrpc_ioctl_invoke ioctl; Loading @@ -887,11 +927,11 @@ static int fastrpc_create_current_dsp_process(void) ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0); ioctl.pra = ra; VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0))); FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0, cid))); return err; } static int fastrpc_release_current_dsp_process(void) static int fastrpc_release_current_dsp_process(int cid) { int err = 0; struct fastrpc_apps *me = &gfa; Loading @@ -906,14 +946,14 @@ static int fastrpc_release_current_dsp_process(void) ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0); ioctl.pra = ra; VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0))); FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0, cid))); return err; } static int fastrpc_mmap_on_dsp(struct fastrpc_apps *me, struct fastrpc_ioctl_mmap *mmap, struct smq_phy_page *pages, int num) int cid, int num) { struct fastrpc_ioctl_invoke ioctl; remote_arg_t ra[3]; Loading Loading @@ -945,7 +985,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_apps *me, ioctl.sc = REMOTE_SCALARS_MAKE(2, 2, 1); ioctl.pra = ra; VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0))); FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0, cid))); mmap->vaddrout = routargs.vaddrout; if (err) goto bail; Loading @@ -954,7 +994,7 @@ bail: } static int fastrpc_munmap_on_dsp(struct fastrpc_apps *me, struct fastrpc_ioctl_munmap *munmap) struct fastrpc_ioctl_munmap *munmap, int cid) { struct fastrpc_ioctl_invoke ioctl; remote_arg_t ra[1]; Loading @@ -975,7 +1015,7 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_apps *me, ioctl.sc = REMOTE_SCALARS_MAKE(3, 1, 0); ioctl.pra = ra; VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0))); FASTRPC_MODE_PARALLEL, 1, &ioctl, ra, 0, cid))); return err; } Loading @@ -986,7 +1026,7 @@ static int fastrpc_internal_munmap(struct fastrpc_apps *me, int err = 0; struct fastrpc_mmap *map = 0, *mapfree = 0; struct hlist_node *n; VERIFY(err, 0 == (err = fastrpc_munmap_on_dsp(me, munmap))); VERIFY(err, 0 == (err = fastrpc_munmap_on_dsp(me, munmap, fdata->cid))); if (err) goto bail; spin_lock(&fdata->hlock); Loading Loading @@ -1042,7 +1082,7 @@ static int fastrpc_internal_mmap(struct fastrpc_apps *me, if (err) goto bail; VERIFY(err, 0 == fastrpc_mmap_on_dsp(me, mmap, pages, num)); VERIFY(err, 0 == fastrpc_mmap_on_dsp(me, mmap, pages, fdata->cid, num)); if (err) goto bail; map->vaddrin = mmap->vaddrin; Loading @@ -1061,7 +1101,7 @@ static int fastrpc_internal_mmap(struct fastrpc_apps *me, return err; } static void cleanup_current_dev(void) static void cleanup_current_dev(int cid) { struct fastrpc_apps *me = &gfa; uint32_t h = hash_32(current->tgid, RPC_HASH_BITS); Loading @@ -1082,7 +1122,7 @@ static void cleanup_current_dev(void) } spin_unlock(&me->hlock); if (devfree) { free_dev(devfree); free_dev(devfree, cid); goto rnext; } return; Loading @@ -1091,21 +1131,26 @@ static void cleanup_current_dev(void) static void fastrpc_channel_close(struct kref *kref) { struct fastrpc_apps *me = &gfa; struct fastrpc_channel_context *ctx; int cid; smd_close(me->chan); me->chan = 0; ctx = container_of(kref, struct fastrpc_channel_context, kref); smd_close(ctx->chan); ctx->chan = 0; mutex_unlock(&me->smd_mutex); pr_info("'closed /dev/%s c %d 0'\n", DEVICE_NAME, MAJOR(me->dev_no)); cid = ctx - &me->channel[0]; pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name, MAJOR(me->dev_no), cid); } static int fastrpc_device_release(struct inode *inode, struct file *file) { struct file_data *fdata = (struct file_data *)file->private_data; struct fastrpc_apps *me = &gfa; int cid = MINOR(inode->i_rdev); (void)fastrpc_release_current_dsp_process(); cleanup_current_dev(); (void)fastrpc_release_current_dsp_process(cid); cleanup_current_dev(cid); if (fdata) { struct fastrpc_mmap *map; struct hlist_node *n; Loading @@ -1116,7 +1161,7 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) kfree(map); } kfree(fdata); kref_put_mutex(&me->kref, fastrpc_channel_close, kref_put_mutex(&me->channel[cid].kref, fastrpc_channel_close, &me->smd_mutex); } return 0; Loading @@ -1124,23 +1169,27 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) static int fastrpc_device_open(struct inode *inode, struct file *filp) { int cid = MINOR(inode->i_rdev); int err = 0; struct fastrpc_apps *me = &gfa; mutex_lock(&me->smd_mutex); if (kref_get_unless_zero(&me->kref) == 0) { VERIFY(err, 0 == smd_named_open_on_edge(FASTRPC_SMD_GUID, SMD_APPS_QDSP, &me->chan, me, smd_event_handler)); if (kref_get_unless_zero(&me->channel[cid].kref) == 0) { VERIFY(err, 0 == smd_named_open_on_edge( FASTRPC_SMD_GUID, gcinfo[cid].channel, &me->channel[cid].chan, (void *)cid, smd_event_handler)); if (err) goto smd_bail; VERIFY(err, 0 != wait_for_completion_timeout(&me->work, VERIFY(err, 0 != wait_for_completion_timeout( &me->channel[cid].work, RPC_TIMEOUT)); if (err) goto completion_bail; kref_init(&me->kref); pr_info("'opened /dev/%s c %d 0'\n", DEVICE_NAME, MAJOR(me->dev_no)); kref_init(&me->channel[cid].kref); pr_info("'opened /dev/%s c %d %d'\n", gcinfo[cid].name, MAJOR(me->dev_no), cid); } mutex_unlock(&me->smd_mutex); Loading @@ -1156,25 +1205,26 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) spin_lock_init(&fdata->hlock); INIT_HLIST_HEAD(&fdata->hlst); fdata->cid = cid; VERIFY(err, 0 == fastrpc_create_current_dsp_process()); VERIFY(err, 0 == fastrpc_create_current_dsp_process(cid)); if (err) goto bail; filp->private_data = fdata; bail: if (err) { cleanup_current_dev(); cleanup_current_dev(cid); kfree(fdata); kref_put_mutex(&me->kref, fastrpc_channel_close, &me->smd_mutex); kref_put_mutex(&me->channel[cid].kref, fastrpc_channel_close, &me->smd_mutex); } module_put(THIS_MODULE); } return err; completion_bail: smd_close(me->chan); me->chan = 0; smd_close(me->channel[cid].chan); me->channel[cid].chan = 0; smd_bail: mutex_unlock(&me->smd_mutex); return err; Loading Loading @@ -1227,7 +1277,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, goto bail; } VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, fdata->mode, 0, invoke, pra, fds))); 0, invoke, pra, fds, fdata->cid))); if (err) goto bail; break; Loading Loading @@ -1283,29 +1333,34 @@ static const struct file_operations fops = { static int __init fastrpc_device_init(void) { struct fastrpc_apps *me = &gfa; int err = 0; int i, err = 0; memset(me, 0, sizeof(*me)); VERIFY(err, 0 == fastrpc_init()); if (err) goto fastrpc_bail; VERIFY(err, 0 == alloc_chrdev_region(&me->dev_no, 0, 1, DEVICE_NAME)); VERIFY(err, 0 == alloc_chrdev_region(&me->dev_no, 0, NUM_CHANNELS, DEVICE_NAME)); if (err) goto alloc_chrdev_bail; cdev_init(&me->cdev, &fops); me->cdev.owner = THIS_MODULE; VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), 1)); VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), NUM_CHANNELS)); if (err) goto cdev_init_bail; me->class = class_create(THIS_MODULE, "fastrpc"); VERIFY(err, !IS_ERR(me->class)); if (err) goto class_create_bail; me->dev = device_create(me->class, NULL, MKDEV(MAJOR(me->dev_no), 0), NULL, DEVICE_NAME); VERIFY(err, !IS_ERR(me->dev)); for (i = 0; i < NUM_CHANNELS; i++) { me->channel[i].dev = device_create(me->class, NULL, MKDEV(MAJOR(me->dev_no), i), NULL, gcinfo[i].name); VERIFY(err, !IS_ERR(me->channel[i].dev)); if (err) goto device_create_bail; } return 0; Loading @@ -1314,7 +1369,7 @@ device_create_bail: class_create_bail: cdev_del(&me->cdev); cdev_init_bail: unregister_chrdev_region(me->dev_no, 1); unregister_chrdev_region(me->dev_no, NUM_CHANNELS); alloc_chrdev_bail: fastrpc_deinit(); fastrpc_bail: Loading @@ -1324,12 +1379,14 @@ fastrpc_bail: static void __exit fastrpc_device_exit(void) { struct fastrpc_apps *me = &gfa; int i; fastrpc_deinit(); device_destroy(me->class, MKDEV(MAJOR(me->dev_no), 0)); for (i = 0; i < NUM_CHANNELS; i++) device_destroy(me->class, MKDEV(MAJOR(me->dev_no), i)); class_destroy(me->class); cdev_del(&me->cdev); unregister_chrdev_region(me->dev_no, 1); unregister_chrdev_region(me->dev_no, NUM_CHANNELS); } module_init(fastrpc_device_init); Loading