Loading drivers/char/adsprpc.c +57 −25 Original line number Diff line number Diff line Loading @@ -774,6 +774,53 @@ static int get_page_list(uint32_t kernel, struct smq_invoke_ctx *ctx) return err; } static inline int is_overlapped_outbuf(struct smq_invoke_ctx *ctx, int oix) { int inbufs, outbufs; inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); if (!ctx->overps[oix]->mstart) return 1; oix = oix + 1; if ((oix < inbufs + outbufs) && !ctx->overps[oix]->mstart && ctx->overps[oix]->raix < inbufs) return 1; return 0; } static int clear_user_outbufs(struct smq_invoke_ctx *ctx) { remote_arg_t *pra = ctx->pra; remote_arg_t *rpra = ctx->rpra; uintptr_t ptr, end; int oix, err = 0; int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); for (oix = 0; oix < inbufs + outbufs; ++oix) { int i = ctx->overps[oix]->raix; if ((i < inbufs) || (pra[i].buf.pv != rpra[i].buf.pv) || is_overlapped_outbuf(ctx, oix)) continue; VERIFY(err, 0 == clear_user(rpra[i].buf.pv, (rpra[i].buf.len < 8) ? rpra[i].buf.len : 8)); if (err) goto bail; ptr = buf_page_start(rpra[i].buf.pv) + PAGE_SIZE; end = (uintptr_t)rpra[i].buf.pv + rpra[i].buf.len; for (; ptr < end; ptr += PAGE_SIZE) { VERIFY(err, 0 == clear_user((void *)ptr, ((end - ptr) < 8) ? end - ptr : 8)); if (err) goto bail; } } bail: return err; } static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx, remote_arg_t *upra) { Loading Loading @@ -906,8 +953,14 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx, rlen -= mlen; } for (i = 0; i < inbufs; ++i) { if (rpra[i].buf.len) if (!kernel) { VERIFY(err, 0 == clear_user_outbufs(ctx)); if (err) goto bail; } for (oix = 0; oix < inbufs + outbufs; ++oix) { int i = ctx->overps[oix]->raix; if (rpra[i].buf.len && ctx->overps[oix]->mstart) dmac_flush_range(rpra[i].buf.pv, (char *)rpra[i].buf.pv + rpra[i].buf.len); } Loading Loading @@ -990,28 +1043,6 @@ static void inv_args_pre(uint32_t sc, remote_arg_t *rpra) } } static void inv_args_idx(struct smq_invoke_ctx *ctx, int id) { struct fastrpc_apps *me = &gfa; struct smq_invoke_buf *list; struct smq_phy_page *pages; struct page *page; struct scatterlist sg; if (me->channel[ctx->fdata->cid].smmu.enabled) { dmac_inv_range(ctx->rpra[id].buf.pv, (char *)ctx->rpra[id].buf.pv + ctx->rpra[id].buf.len); return; } list = smq_invoke_buf_start(ctx->rpra, ctx->sc); pages = smq_phy_page_start(ctx->sc, list); page = phys_to_page(pages[list[id].pgidx].addr); sg_init_table(&sg, 1); sg_set_page(&sg, page, pages[list[id].pgidx].size, 0); sg_dma_address(&sg) = pages[list[id].pgidx].addr; dma_sync_sg_for_cpu(NULL, &sg, 1, DMA_FROM_DEVICE); } static void inv_args(struct smq_invoke_ctx *ctx) { uint32_t sc = ctx->sc; Loading @@ -1026,7 +1057,8 @@ static void inv_args(struct smq_invoke_ctx *ctx) if (buf_page_start(rpra) == buf_page_start(rpra[i].buf.pv)) inv = 1; else if (rpra[i].buf.len) inv_args_idx(ctx, i); dmac_inv_range(rpra[i].buf.pv, (char *)rpra[i].buf.pv + rpra[i].buf.len); } if (inv || REMOTE_SCALARS_OUTHANDLES(sc)) Loading Loading
drivers/char/adsprpc.c +57 −25 Original line number Diff line number Diff line Loading @@ -774,6 +774,53 @@ static int get_page_list(uint32_t kernel, struct smq_invoke_ctx *ctx) return err; } static inline int is_overlapped_outbuf(struct smq_invoke_ctx *ctx, int oix) { int inbufs, outbufs; inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); if (!ctx->overps[oix]->mstart) return 1; oix = oix + 1; if ((oix < inbufs + outbufs) && !ctx->overps[oix]->mstart && ctx->overps[oix]->raix < inbufs) return 1; return 0; } static int clear_user_outbufs(struct smq_invoke_ctx *ctx) { remote_arg_t *pra = ctx->pra; remote_arg_t *rpra = ctx->rpra; uintptr_t ptr, end; int oix, err = 0; int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); for (oix = 0; oix < inbufs + outbufs; ++oix) { int i = ctx->overps[oix]->raix; if ((i < inbufs) || (pra[i].buf.pv != rpra[i].buf.pv) || is_overlapped_outbuf(ctx, oix)) continue; VERIFY(err, 0 == clear_user(rpra[i].buf.pv, (rpra[i].buf.len < 8) ? rpra[i].buf.len : 8)); if (err) goto bail; ptr = buf_page_start(rpra[i].buf.pv) + PAGE_SIZE; end = (uintptr_t)rpra[i].buf.pv + rpra[i].buf.len; for (; ptr < end; ptr += PAGE_SIZE) { VERIFY(err, 0 == clear_user((void *)ptr, ((end - ptr) < 8) ? end - ptr : 8)); if (err) goto bail; } } bail: return err; } static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx, remote_arg_t *upra) { Loading Loading @@ -906,8 +953,14 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx, rlen -= mlen; } for (i = 0; i < inbufs; ++i) { if (rpra[i].buf.len) if (!kernel) { VERIFY(err, 0 == clear_user_outbufs(ctx)); if (err) goto bail; } for (oix = 0; oix < inbufs + outbufs; ++oix) { int i = ctx->overps[oix]->raix; if (rpra[i].buf.len && ctx->overps[oix]->mstart) dmac_flush_range(rpra[i].buf.pv, (char *)rpra[i].buf.pv + rpra[i].buf.len); } Loading Loading @@ -990,28 +1043,6 @@ static void inv_args_pre(uint32_t sc, remote_arg_t *rpra) } } static void inv_args_idx(struct smq_invoke_ctx *ctx, int id) { struct fastrpc_apps *me = &gfa; struct smq_invoke_buf *list; struct smq_phy_page *pages; struct page *page; struct scatterlist sg; if (me->channel[ctx->fdata->cid].smmu.enabled) { dmac_inv_range(ctx->rpra[id].buf.pv, (char *)ctx->rpra[id].buf.pv + ctx->rpra[id].buf.len); return; } list = smq_invoke_buf_start(ctx->rpra, ctx->sc); pages = smq_phy_page_start(ctx->sc, list); page = phys_to_page(pages[list[id].pgidx].addr); sg_init_table(&sg, 1); sg_set_page(&sg, page, pages[list[id].pgidx].size, 0); sg_dma_address(&sg) = pages[list[id].pgidx].addr; dma_sync_sg_for_cpu(NULL, &sg, 1, DMA_FROM_DEVICE); } static void inv_args(struct smq_invoke_ctx *ctx) { uint32_t sc = ctx->sc; Loading @@ -1026,7 +1057,8 @@ static void inv_args(struct smq_invoke_ctx *ctx) if (buf_page_start(rpra) == buf_page_start(rpra[i].buf.pv)) inv = 1; else if (rpra[i].buf.len) inv_args_idx(ctx, i); dmac_inv_range(rpra[i].buf.pv, (char *)rpra[i].buf.pv + rpra[i].buf.len); } if (inv || REMOTE_SCALARS_OUTHANDLES(sc)) Loading