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

Commit 654b35ec authored by Amir Levy's avatar Amir Levy Committed by Gerrit - the friendly Code Review server
Browse files

msm: ipa3: remove support for global filter table



IPAv3 HW does not support global filter rules. Consequently, remove
the support from IPA driver and prevent user space from configuring
such rules.

Change-Id: I29a2b2f7119e10993f91e9f1239921a234a870f7
Signed-off-by: default avatarGhanim Fodi <gfodi@codeaurora.org>
Signed-off-by: default avatarAmir Levy <alevy@codeaurora.org>
Signed-off-by: default avatarGidon Studinski <gidons@codeaurora.org>
parent a2a5c5a0
Loading
Loading
Loading
Loading
+0 −92
Original line number Diff line number Diff line
@@ -2651,84 +2651,6 @@ int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
	return 0;
}

static int ipa3_init_flt_block(void)
{
	int result = 0;

	/*
	 * SW workaround for Improper Filter Behavior when neither Global nor
	 * Pipe Rules are present => configure dummy global filter rule
	 * always which results in a miss
	 */
	struct ipa_ioc_add_flt_rule *rules;
	struct ipa_flt_rule_add *rule;
	struct ipa_ioc_get_rt_tbl rt_lookup;
	enum ipa_ip_type ip;

	size_t sz = sizeof(struct ipa_ioc_add_flt_rule) +
		   sizeof(struct ipa_flt_rule_add);

	rules = kmalloc(sz, GFP_KERNEL);
	if (rules == NULL) {
		IPAERR("fail to alloc mem for dummy filter rule\n");
		return -ENOMEM;
	}

	IPADBG("Adding global rules for IPv4 and IPv6");
	for (ip = IPA_IP_v4; ip < IPA_IP_MAX; ip++) {
		memset(&rt_lookup, 0,
				sizeof(struct ipa_ioc_get_rt_tbl));
		rt_lookup.ip = ip;
		strlcpy(rt_lookup.name, IPA_DFLT_RT_TBL_NAME,
				IPA_RESOURCE_NAME_MAX);
		ipa3_get_rt_tbl(&rt_lookup);
		ipa3_put_rt_tbl(rt_lookup.hdl);
		memset(rules, 0, sz);
		rule = &rules->rules[0];
		rules->commit = 1;
		rules->ip = ip;
		rules->global = 1;
		rules->num_rules = 1;
		rule->at_rear = 1;
		if (ip == IPA_IP_v4) {
			rule->rule.attrib.attrib_mask =
				IPA_FLT_PROTOCOL | IPA_FLT_DST_ADDR;
			rule->rule.attrib.u.v4.protocol =
			   IPA_INVALID_L4_PROTOCOL;
			rule->rule.attrib.u.v4.dst_addr_mask = ~0;
			rule->rule.attrib.u.v4.dst_addr = ~0;
		} else if (ip == IPA_IP_v6) {
			rule->rule.attrib.attrib_mask =
				IPA_FLT_NEXT_HDR | IPA_FLT_DST_ADDR;
			rule->rule.attrib.u.v6.next_hdr =
				IPA_INVALID_L4_PROTOCOL;
			rule->rule.attrib.u.v6.dst_addr_mask[0] = ~0;
			rule->rule.attrib.u.v6.dst_addr_mask[1] = ~0;
			rule->rule.attrib.u.v6.dst_addr_mask[2] = ~0;
			rule->rule.attrib.u.v6.dst_addr_mask[3] = ~0;
			rule->rule.attrib.u.v6.dst_addr[0] = ~0;
			rule->rule.attrib.u.v6.dst_addr[1] = ~0;
			rule->rule.attrib.u.v6.dst_addr[2] = ~0;
			rule->rule.attrib.u.v6.dst_addr[3] = ~0;
		} else {
			result = -EINVAL;
			WARN_ON(1);
			break;
		}
		rule->rule.action = IPA_PASS_TO_ROUTING;
		rule->rule.rt_tbl_hdl = rt_lookup.hdl;
		rule->rule.retain_hdr = true;

		if (ipa3_add_flt_rule(rules) || rules->rules[0].status) {
			result = -EINVAL;
			WARN_ON(1);
			break;
		}
	}
	kfree(rules);
	return result;
}

/**
* ipa3_suspend_handler() - Handles the suspend interrupt:
* wakes up the suspended peripheral by requesting its consumer
@@ -3205,14 +3127,7 @@ static int ipa3_init(const struct ipa3_plat_drv_res *resource_p,
		goto fail_dma_pool;
	}

	ipa3_ctx->glob_flt_tbl[IPA_IP_v4].in_sys =
		!ipa3_ctx->ip4_flt_tbl_nhash_lcl;
	ipa3_ctx->glob_flt_tbl[IPA_IP_v6].in_sys =
		!ipa3_ctx->ip6_flt_tbl_nhash_lcl;

	/* init the various list heads */
	INIT_LIST_HEAD(&ipa3_ctx->glob_flt_tbl[IPA_IP_v4].head_flt_rule_list);
	INIT_LIST_HEAD(&ipa3_ctx->glob_flt_tbl[IPA_IP_v6].head_flt_rule_list);
	INIT_LIST_HEAD(&ipa3_ctx->hdr_tbl.head_hdr_entry_list);
	for (i = 0; i < IPA_HDR_BIN_MAX; i++) {
		INIT_LIST_HEAD(&ipa3_ctx->hdr_tbl.head_offset_list[i]);
@@ -3297,13 +3212,6 @@ static int ipa3_init(const struct ipa3_plat_drv_res *resource_p,
	}
	IPADBG("IPA System2Bam pipes were connected\n");

	if (ipa3_init_flt_block()) {
		IPAERR("fail to setup dummy filter rules\n");
		result = -ENODEV;
		goto fail_empty_rt_tbl;
	}
	IPADBG("filter block was set with dummy filter rules");

	/* setup the IPA pipe mem pool */
	if (resource_p->ipa_pipe_mem_size)
		ipa3_pipe_mem_init(resource_p->ipa_pipe_mem_start_ofst,
+0 −28
Original line number Diff line number Diff line
@@ -748,35 +748,7 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count,
	u32 bitmap;
	bool eq;

	tbl = &ipa3_ctx->glob_flt_tbl[ip];
	mutex_lock(&ipa3_ctx->lock);
	i = 0;
	list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
		if (entry->rule.eq_attrib_type) {
			rt_tbl_idx = entry->rule.rt_tbl_idx;
			bitmap = entry->rule.eq_attrib.rule_eq_bitmap;
			eq = true;
		} else {
			rt_tbl = ipa3_id_find(entry->rule.rt_tbl_hdl);
			if (rt_tbl)
				rt_tbl_idx = rt_tbl->idx;
			else
				rt_tbl_idx = ~0;
			bitmap = entry->rule.attrib.attrib_mask;
			eq = false;
		}
		pr_err("ep_idx:global rule_idx:%d act:%d rt_tbl_idx:%d ",
			i, entry->rule.action, rt_tbl_idx);
		pr_err("attrib_mask:%08x to_uc:%d, retain_hdr:%d eq:%d ",
			bitmap, entry->rule.to_uc, entry->rule.retain_hdr, eq);
		if (eq)
			ipa3_attrib_dump_eq(
				&entry->rule.eq_attrib);
		else
			ipa3_attrib_dump(
				&entry->rule.attrib, ip);
		i++;
	}

	for (j = 0; j < ipa3_ctx->ipa_num_pipes; j++) {
		tbl = &ipa3_ctx->flt_tbl[j][ip];
+5 −181
Original line number Diff line number Diff line
@@ -251,29 +251,6 @@ static int ipa3_get_flt_hw_tbl_size(enum ipa_ip_type ip, u32 *hdr_sz)
	int i;

	*hdr_sz = 0;
	tbl = &ipa3_ctx->glob_flt_tbl[ip];
	rule_set_sz = 0;
	list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
		if (ipa3_generate_flt_hw_rule(ip, entry, NULL)) {
			IPAERR("failed to find HW FLT rule size\n");
			return -EPERM;
		}
		IPADBG("glob ip %d len %d\n", ip, entry->hw_len);
		rule_set_sz += entry->hw_len;
	}

	if (rule_set_sz) {
		tbl->sz = rule_set_sz + IPA_FLT_TABLE_WORD_SIZE;
		/* this rule-set uses a word in header block */
		*hdr_sz += IPA_FLT_TABLE_WORD_SIZE;
		if (!tbl->in_sys) {
			/* add the terminator */
			total_sz += (rule_set_sz + IPA_FLT_TABLE_WORD_SIZE);
			total_sz = (total_sz +
					IPA_FLT_ENTRY_MEMORY_ALLIGNMENT) &
					~IPA_FLT_ENTRY_MEMORY_ALLIGNMENT;
		}
	}

	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
		tbl = &ipa3_ctx->flt_tbl[i][ip];
@@ -335,92 +312,6 @@ static int ipa3_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base,
	}						\
}

	tbl = &ipa3_ctx->glob_flt_tbl[ip];

	if (!list_empty(&tbl->head_flt_rule_list)) {
		*hdr_top |= IPA_FLT_BIT_MASK;

		if (!tbl->in_sys) {
			offset = body - base + body_start_offset;
			if (offset & IPA_FLT_ENTRY_MEMORY_ALLIGNMENT) {
				IPAERR("offset is not word multiple %d\n",
						offset);
				goto proc_err;
			}

			offset &= ~IPA_FLT_ENTRY_MEMORY_ALLIGNMENT;
			/* rule is at an offset from base */
			offset |= IPA_FLT_BIT_MASK;

			if (hdr2)
				*(u32 *)hdr = offset;
			else
				hdr = ipa3_write_32(offset, hdr);

			/* generate the rule-set */
			list_for_each_entry(entry, &tbl->head_flt_rule_list,
					link) {
				if (ipa3_generate_flt_hw_rule(ip,
							entry,
							body)) {
					IPAERR("failed to gen HW FLT rule\n");
					goto proc_err;
				}
				body += entry->hw_len;
			}

			/* write the rule-set terminator */
			body = ipa3_write_32(0, body);
			if ((long)body & IPA_FLT_ENTRY_MEMORY_ALLIGNMENT)
				/* advance body to next word boundary */
				body = body + (IPA_FLT_TABLE_WORD_SIZE -
					((long)body &
					IPA_FLT_ENTRY_MEMORY_ALLIGNMENT));
		} else {
			WARN_ON(tbl->sz == 0);
			/* allocate memory for the flt tbl */
			flt_tbl_mem.size = tbl->sz;
			flt_tbl_mem.base =
			   dma_alloc_coherent(ipa3_ctx->pdev, flt_tbl_mem.size,
					   &flt_tbl_mem.phys_base, GFP_KERNEL);
			if (!flt_tbl_mem.base) {
				IPAERR("fail to alloc DMA buff of size %d\n",
						flt_tbl_mem.size);
				WARN_ON(1);
				goto proc_err;
			}

			WARN_ON(flt_tbl_mem.phys_base &
				IPA_FLT_ENTRY_MEMORY_ALLIGNMENT);
			ftbl_membody = flt_tbl_mem.base;
			memset(flt_tbl_mem.base, 0, flt_tbl_mem.size);

			if (hdr2)
				*(u32 *)hdr = flt_tbl_mem.phys_base;
			else
				hdr = ipa3_write_32(flt_tbl_mem.phys_base, hdr);

			/* generate the rule-set */
			list_for_each_entry(entry, &tbl->head_flt_rule_list,
					link) {
				if (ipa3_generate_flt_hw_rule(ip, entry,
							ftbl_membody)) {
					IPAERR("failed to gen HW FLT rule\n");
					WARN_ON(1);
				}
				ftbl_membody += entry->hw_len;
			}

			/* write the rule-set terminator */
			ftbl_membody = ipa3_write_32(0, ftbl_membody);
			if (tbl->curr_mem.phys_base) {
				WARN_ON(tbl->prev_mem.phys_base);
				tbl->prev_mem = tbl->curr_mem;
			}
			tbl->curr_mem = flt_tbl_mem;
		}
	}

	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
		tbl = &ipa3_ctx->flt_tbl[i][ip];
		if (!list_empty(&tbl->head_flt_rule_list)) {
@@ -528,24 +419,6 @@ static void __ipa_reap_sys_flt_tbls(enum ipa_ip_type ip)
	struct ipa3_flt_tbl *tbl;
	int i;

	tbl = &ipa3_ctx->glob_flt_tbl[ip];
	if (tbl->prev_mem.phys_base) {
		IPADBG("reaping glob flt tbl (prev) ip=%d\n", ip);
		dma_free_coherent(ipa3_ctx->pdev, tbl->prev_mem.size,
				tbl->prev_mem.base, tbl->prev_mem.phys_base);
		memset(&tbl->prev_mem, 0, sizeof(tbl->prev_mem));
	}

	if (list_empty(&tbl->head_flt_rule_list)) {
		if (tbl->curr_mem.phys_base) {
			IPADBG("reaping glob flt tbl (curr) ip=%d\n", ip);
			dma_free_coherent(ipa3_ctx->pdev, tbl->curr_mem.size,
					tbl->curr_mem.base,
					tbl->curr_mem.phys_base);
			memset(&tbl->curr_mem, 0, sizeof(tbl->curr_mem));
		}
	}

	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
		tbl = &ipa3_ctx->flt_tbl[i][ip];
		if (tbl->prev_mem.phys_base) {
@@ -1014,23 +887,6 @@ error:
	return -EPERM;
}

static int __ipa_add_global_flt_rule(enum ipa_ip_type ip,
		const struct ipa_flt_rule *rule, u8 add_rear, u32 *rule_hdl)
{
	struct ipa3_flt_tbl *tbl;

	if (rule == NULL || rule_hdl == NULL) {
		IPAERR("bad parms rule=%p rule_hdl=%p\n", rule, rule_hdl);

		return -EINVAL;
	}

	tbl = &ipa3_ctx->glob_flt_tbl[ip];
	IPADBG("add global flt rule ip=%d\n", ip);

	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl);
}

static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep,
				 const struct ipa_flt_rule *rule, u8 add_rear,
				 u32 *rule_hdl)
@@ -1082,16 +938,15 @@ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules)

	mutex_lock(&ipa3_ctx->lock);
	for (i = 0; i < rules->num_rules; i++) {
		if (rules->global)
			result = __ipa_add_global_flt_rule(rules->ip,
					&rules->rules[i].rule,
					rules->rules[i].at_rear,
					&rules->rules[i].flt_rule_hdl);
		else
		if (rules->global) {
			IPAERR("no support for global filter rules %d\n", i);
			result = -EPERM;
		} else
			result = __ipa_add_ep_flt_rule(rules->ip, rules->ep,
					&rules->rules[i].rule,
					rules->rules[i].at_rear,
					&rules->rules[i].flt_rule_hdl);

		if (result) {
			IPAERR("failed to add flt rule %d\n", i);
			rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED;
@@ -1255,38 +1110,7 @@ int ipa3_reset_flt(enum ipa_ip_type ip)
		return -EINVAL;
	}

	tbl = &ipa3_ctx->glob_flt_tbl[ip];
	mutex_lock(&ipa3_ctx->lock);
	IPADBG("reset flt ip=%d\n", ip);
	list_for_each_entry_safe(entry, next, &tbl->head_flt_rule_list, link) {
		if (ipa3_id_find(entry->id) == NULL) {
			WARN_ON(1);
			mutex_unlock(&ipa3_ctx->lock);
			return -EFAULT;
		}

		if ((ip == IPA_IP_v4 &&
		     entry->rule.attrib.attrib_mask == IPA_FLT_PROTOCOL &&
		     entry->rule.attrib.u.v4.protocol ==
		      IPA_INVALID_L4_PROTOCOL) ||
		    (ip == IPA_IP_v6 &&
		     entry->rule.attrib.attrib_mask == IPA_FLT_NEXT_HDR &&
		     entry->rule.attrib.u.v6.next_hdr ==
		      IPA_INVALID_L4_PROTOCOL))
			continue;

		list_del(&entry->link);
		entry->tbl->rule_cnt--;
		if (entry->rt_tbl)
			entry->rt_tbl->ref_cnt--;
		entry->cookie = 0;
		id = entry->id;
		kmem_cache_free(ipa3_ctx->flt_rule_cache, entry);

		/* remove the handle from the database */
		ipa3_id_remove(id);
	}

	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
		tbl = &ipa3_ctx->flt_tbl[i][ip];
		list_for_each_entry_safe(entry, next, &tbl->head_flt_rule_list,
+0 −2
Original line number Diff line number Diff line
@@ -1074,7 +1074,6 @@ struct ipa3_sps_pm {
 * @mode: IPA operating mode
 * @mmio: iomem
 * @ipa_wrapper_base: IPA wrapper base address
 * @glob_flt_tbl: global filter table
 * @hdr_tbl: IPA header table
 * @hdr_proc_ctx_tbl: IPA processing context table
 * @rt_tbl_set: list of routing tables each of which is a list of rules
@@ -1150,7 +1149,6 @@ struct ipa3_context {
	struct ipa3_flt_tbl flt_tbl[IPA3_MAX_NUM_PIPES][IPA_IP_MAX];
	void __iomem *mmio;
	u32 ipa_wrapper_base;
	struct ipa3_flt_tbl glob_flt_tbl[IPA_IP_MAX];
	struct ipa3_hdr_tbl hdr_tbl;
	struct ipa3_hdr_proc_ctx_tbl hdr_proc_ctx_tbl;
	struct ipa3_rt_tbl_set rt_tbl_set[IPA_IP_MAX];