Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 36a3236d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ADSPRPC: Clear output buffers before cache invalidation"

parents 8242fceb 367ed6a7
Loading
Loading
Loading
Loading
+57 −25
Original line number Diff line number Diff line
@@ -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)
{
@@ -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);
	}
@@ -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;
@@ -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))