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

Commit e0665778 authored by Ravi Gummadidala's avatar Ravi Gummadidala
Browse files

msm: ipa: fix filter table update bug



For RmNet and QCMAP concurrency scenario, filter table
update logic can override Q6 installed filter tables.
This breaks RmNet functionality. This commit fixes that
bug.

Change-Id: Iab1ff8c4531609df7a07e609da5c3b8669e3dd9c
Signed-off-by: default avatarRavi Gummadidala <rgummadi@codeaurora.org>
parent ce42a34f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -326,6 +326,7 @@ int ipa_connect(const struct ipa_connect_params *in, struct ipa_sps_params *sps,
	if (!ep->skip_ep_cfg && IPA_CLIENT_IS_PROD(in->client))
		ipa_install_dflt_flt_rules(ipa_ep_idx);

	ipa_ctx->skip_ep_cfg_shadow[ipa_ep_idx] = ep->skip_ep_cfg;
	IPADBG("client %d (ep: %d) connected\n", in->client, ipa_ep_idx);

	return 0;
+1 −0
Original line number Diff line number Diff line
@@ -1065,6 +1065,7 @@ int ipa_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl)
	if (!ep->skip_ep_cfg && IPA_CLIENT_IS_PROD(sys_in->client))
		ipa_install_dflt_flt_rules(ipa_ep_idx);

	ipa_ctx->skip_ep_cfg_shadow[ipa_ep_idx] = ep->skip_ep_cfg;
	IPADBG("client %d (ep: %d) connected sys=%p\n", sys_in->client,
			ipa_ep_idx, ep->sys);

+103 −44
Original line number Diff line number Diff line
@@ -323,10 +323,10 @@ static int ipa_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base,
#define IPA_WRITE_FLT_HDR(idx, val) {			\
	if (idx <= 5) {					\
		*((u32 *)hdr + 1 + idx) = val;		\
	} else if (idx >= 6 && idx <= 9) {		\
	} else if (idx >= 6 && idx <= 10) {		\
		WARN_ON(1);				\
	} else if (idx >= 10 && idx <= 19) {		\
		*((u32 *)hdr2 + idx - 10) = val;	\
	} else if (idx >= 11 && idx <= 19) {		\
		*((u32 *)hdr2 + idx - 11) = val;	\
	} else {					\
		WARN_ON(1);				\
	}						\
@@ -741,7 +741,7 @@ static int ipa_generate_flt_hw_tbl_v2(enum ipa_ip_type ip,
		entr++;
	}

	num_words = 10;
	num_words = 9;
	head2->size = num_words * 4;
	head2->base = dma_alloc_coherent(ipa_ctx->pdev, head2->size,
			&head2->phys_base, GFP_KERNEL);
@@ -803,40 +803,47 @@ err:

int __ipa_commit_flt_v2(enum ipa_ip_type ip)
{
	struct ipa_desc desc[3];
	struct ipa_desc *desc;
	struct ipa_hw_imm_cmd_dma_shared_mem *cmd;
	struct ipa_mem_buffer body;
	struct ipa_mem_buffer head1;
	struct ipa_mem_buffer head2;
	struct ipa_hw_imm_cmd_dma_shared_mem cmd1 = {0};
	struct ipa_hw_imm_cmd_dma_shared_mem cmd2 = {0};
	struct ipa_hw_imm_cmd_dma_shared_mem cmd3 = {0};
	u16 avail;
	int rc = 0;
	u32 local_addr1;
	u32 local_addr2;
	u32 local_addr3;
	u32 local_addrb;
	u32 local_addrh;
	bool lcl;
	int num_desc = 0;
	int i;
	u16 avail;

	memset(desc, 0, 3 * sizeof(struct ipa_desc));
	desc = kzalloc(16 * sizeof(*desc), GFP_ATOMIC);
	if (desc == NULL) {
		IPAERR("fail to alloc desc blob ip %d\n", ip);
		rc = -ENOMEM;
		goto fail_desc;
	}

	cmd = kzalloc(16 * sizeof(*cmd), GFP_ATOMIC);
	if (cmd == NULL) {
		IPAERR("fail to alloc cmd blob ip %d\n", ip);
		rc = -ENOMEM;
		goto fail_imm;
	}

	if (ip == IPA_IP_v4) {
		avail = ipa_ctx->ip4_flt_tbl_lcl ? IPA_v2_RAM_APPS_V4_FLT_SIZE :
			IPA_RAM_V4_FLT_SIZE_DDR;
		local_addr1 = ipa_ctx->smem_restricted_bytes +
		local_addrh = ipa_ctx->smem_restricted_bytes +
			IPA_v2_RAM_V4_FLT_OFST + 4;
		local_addr2 = ipa_ctx->smem_restricted_bytes +
			IPA_v2_RAM_V4_FLT_OFST + 12 * 4;
		local_addr3 = ipa_ctx->smem_restricted_bytes +
		local_addrb = ipa_ctx->smem_restricted_bytes +
			IPA_v2_RAM_APPS_V4_FLT_OFST;
		lcl = ipa_ctx->ip4_flt_tbl_lcl;
	} else {
		avail = ipa_ctx->ip6_flt_tbl_lcl ? IPA_v2_RAM_APPS_V6_FLT_SIZE :
			IPA_RAM_V6_FLT_SIZE_DDR;
		local_addr1 = ipa_ctx->smem_restricted_bytes +
		local_addrh = ipa_ctx->smem_restricted_bytes +
			IPA_v2_RAM_V6_FLT_OFST + 4;
		local_addr2 = ipa_ctx->smem_restricted_bytes +
			IPA_v2_RAM_V6_FLT_OFST + 12 * 4;
		local_addr3 = ipa_ctx->smem_restricted_bytes +
		local_addrb = ipa_ctx->smem_restricted_bytes +
			IPA_v2_RAM_APPS_V6_FLT_OFST;
		lcl = ipa_ctx->ip6_flt_tbl_lcl;
	}
@@ -852,41 +859,88 @@ int __ipa_commit_flt_v2(enum ipa_ip_type ip)
		goto fail_send_cmd;
	}

	cmd1.size = head1.size;
	cmd1.system_addr = head1.phys_base;
	cmd1.local_addr = local_addr1;
	cmd[num_desc].size = 4;
	cmd[num_desc].system_addr = head1.phys_base;
	cmd[num_desc].local_addr = local_addrh;

	desc[num_desc].opcode = IPA_DMA_SHARED_MEM;
	desc[num_desc].pyld = &cmd[num_desc];
	desc[num_desc].len = sizeof(struct ipa_hw_imm_cmd_dma_shared_mem);
	desc[num_desc++].type = IPA_IMM_CMD_DESC;

	desc[0].opcode = IPA_DMA_SHARED_MEM;
	desc[0].pyld = &cmd1;
	desc[0].len = sizeof(struct ipa_hw_imm_cmd_dma_shared_mem);
	desc[0].type = IPA_IMM_CMD_DESC;
	for (i = 0; i < 6; i++) {
		if (ipa_ctx->skip_ep_cfg_shadow[i]) {
			IPADBG("skip %d\n", i);
			continue;
		}

	cmd2.size = head2.size;
	cmd2.system_addr = head2.phys_base;
	cmd2.local_addr = local_addr2;
		if (ipa_get_ep_mapping(IPA_CLIENT_APPS_WAN_CONS) == i ||
			ipa_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS) == i ||
			ipa_get_ep_mapping(IPA_CLIENT_APPS_CMD_PROD) == i) {
			IPADBG("skip %d\n", i);
			continue;
		}

	desc[1].opcode = IPA_DMA_SHARED_MEM;
	desc[1].pyld = &cmd2;
	desc[1].len = sizeof(struct ipa_hw_imm_cmd_dma_shared_mem);
	desc[1].type = IPA_IMM_CMD_DESC;
		if (ip == IPA_IP_v4) {
			local_addrh = ipa_ctx->smem_restricted_bytes +
				IPA_v2_RAM_V4_FLT_OFST + 8 + i * 4;
		} else {
			local_addrh = ipa_ctx->smem_restricted_bytes +
				IPA_v2_RAM_V6_FLT_OFST + 8 + i * 4;
		}
		cmd[num_desc].size = 4;
		cmd[num_desc].system_addr = head1.phys_base + 4 + i * 4;
		cmd[num_desc].local_addr = local_addrh;

		desc[num_desc].opcode = IPA_DMA_SHARED_MEM;
		desc[num_desc].pyld = &cmd[num_desc];
		desc[num_desc].len =
			sizeof(struct ipa_hw_imm_cmd_dma_shared_mem);
		desc[num_desc++].type = IPA_IMM_CMD_DESC;
	}

	for (i = 11; i < IPA_NUM_PIPES; i++) {
		if (ipa_ctx->skip_ep_cfg_shadow[i]) {
			IPADBG("skip %d\n", i);
			continue;
		}

		if (ip == IPA_IP_v4) {
			local_addrh = ipa_ctx->smem_restricted_bytes +
				IPA_v2_RAM_V4_FLT_OFST + 13 * 4 + (i - 11) * 4;
		} else {
			local_addrh = ipa_ctx->smem_restricted_bytes +
				IPA_v2_RAM_V6_FLT_OFST + 13 * 4 + (i - 11) * 4;
		}
		cmd[num_desc].size = 4;
		cmd[num_desc].system_addr = head2.phys_base + (i - 11) * 4;
		cmd[num_desc].local_addr = local_addrh;

		desc[num_desc].opcode = IPA_DMA_SHARED_MEM;
		desc[num_desc].pyld = &cmd[num_desc];
		desc[num_desc].len =
			sizeof(struct ipa_hw_imm_cmd_dma_shared_mem);
		desc[num_desc++].type = IPA_IMM_CMD_DESC;
	}

	if (lcl) {
		cmd3.size = body.size;
		cmd3.system_addr = body.phys_base;
		cmd3.local_addr = local_addr3;
		cmd[num_desc].size = body.size;
		cmd[num_desc].system_addr = body.phys_base;
		cmd[num_desc].local_addr = local_addrb;

		desc[2].opcode = IPA_DMA_SHARED_MEM;
		desc[2].pyld = &cmd3;
		desc[2].len = sizeof(struct ipa_hw_imm_cmd_dma_shared_mem);
		desc[2].type = IPA_IMM_CMD_DESC;
		desc[num_desc].opcode = IPA_DMA_SHARED_MEM;
		desc[num_desc].pyld = &cmd[num_desc];
		desc[num_desc].len =
			sizeof(struct ipa_hw_imm_cmd_dma_shared_mem);
		desc[num_desc++].type = IPA_IMM_CMD_DESC;

		if (ipa_send_cmd(3, desc)) {
		if (ipa_send_cmd(num_desc, desc)) {
			IPAERR("fail to send immediate command\n");
			rc = -EFAULT;
			goto fail_send_cmd;
		}
	} else {
		if (ipa_send_cmd(2, desc)) {
		if (ipa_send_cmd(num_desc, desc)) {
			IPAERR("fail to send immediate command\n");
			rc = -EFAULT;
			goto fail_send_cmd;
@@ -894,6 +948,7 @@ int __ipa_commit_flt_v2(enum ipa_ip_type ip)
	}

	__ipa_reap_sys_flt_tbls(ip);

fail_send_cmd:
	if (body.size)
		dma_free_coherent(ipa_ctx->pdev, body.size, body.base,
@@ -903,6 +958,10 @@ fail_send_cmd:
	dma_free_coherent(ipa_ctx->pdev, head2.size, head2.base,
			head2.phys_base);
fail_gen:
	kfree(cmd);
fail_imm:
	kfree(desc);
fail_desc:
	return rc;
}

+3 −0
Original line number Diff line number Diff line
@@ -596,6 +596,8 @@ struct ipa_controller;
 * @cdev: cdev of the device
 * @bam_handle: IPA driver's BAM handle
 * @ep: list of all end points
 * @skip_ep_cfg_shadow: state to update filter table correctly across
  power-save
 * @flt_tbl: list of all IPA filter tables
 * @mode: IPA operating mode
 * @mmio: iomem
@@ -651,6 +653,7 @@ struct ipa_context {
	struct cdev cdev;
	unsigned long bam_handle;
	struct ipa_ep_context ep[IPA_NUM_PIPES];
	bool skip_ep_cfg_shadow[IPA_NUM_PIPES];
	struct ipa_flt_tbl flt_tbl[IPA_NUM_PIPES][IPA_IP_MAX];
	void __iomem *mmio;
	u32 ipa_wrapper_base;