Kaynağa Gözat

ipa: flt\rt changes for IPAv5

adapt flt\rt rules and headers structures to IPAv5

Change-Id: Ib44550ff9639a53aad49cf599e9877de4ad8a701
Acked-by: Nadav Levintov <[email protected]>
Signed-off-by: Amir Levy <[email protected]>
Signed-off-by: Ilia Lin <[email protected]>
Signed-off-by: Sivan Reinstein <[email protected]>
Ilia Lin 4 yıl önce
ebeveyn
işleme
7645eed7c2

+ 21 - 7
drivers/platform/msm/ipa/ipa_v3/ipa.c

@@ -3730,7 +3730,6 @@ static int ipa3_q6_clean_q6_tables(void)
 	struct ipahal_imm_cmd_register_write reg_write_cmd = {0};
 	int retval = 0;
 	int num_cmds = 0;
-	struct ipahal_reg_fltrt_hash_flush flush;
 	struct ipahal_reg_valmask valmask;
 	struct ipahal_imm_cmd_register_write reg_write_coal_close;
 	int i;
@@ -3818,14 +3817,29 @@ static int ipa3_q6_clean_q6_tables(void)
 		++num_cmds;
 	}
 
-	flush.v4_flt = true;
-	flush.v4_rt = true;
-	flush.v6_flt = true;
-	flush.v6_rt = true;
-	ipahal_get_fltrt_hash_flush_valmask(&flush, &valmask);
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0) {
+		struct ipahal_reg_fltrt_cache_flush flush_cache;
+
+		memset(&flush_cache, 0, sizeof(flush_cache));
+		flush_cache.flt = true;
+		flush_cache.rt = true;
+		ipahal_get_fltrt_cache_flush_valmask(
+			&flush_cache, &valmask);
+		reg_write_cmd.offset = ipahal_get_reg_ofst(
+			IPA_FILT_ROUT_CACHE_FLUSH);
+	} else {
+		struct ipahal_reg_fltrt_hash_flush flush_hash;
+
+		flush_hash.v4_flt = true;
+		flush_hash.v4_rt = true;
+		flush_hash.v6_flt = true;
+		flush_hash.v6_rt = true;
+		ipahal_get_fltrt_hash_flush_valmask(&flush_hash, &valmask);
+		reg_write_cmd.offset = ipahal_get_reg_ofst(
+			IPA_FILT_ROUT_HASH_FLUSH);
+	}
 	reg_write_cmd.skip_pipeline_clear = false;
 	reg_write_cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
-	reg_write_cmd.offset = ipahal_get_reg_ofst(IPA_FILT_ROUT_HASH_FLUSH);
 	reg_write_cmd.value = valmask.val;
 	reg_write_cmd.value_mask = valmask.mask;
 	cmd_pyld[num_cmds] = ipahal_construct_imm_cmd(

+ 28 - 26
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c

@@ -887,6 +887,9 @@ static ssize_t ipa3_read_rt(struct file *file, char __user *ubuf, size_t count,
 	list_for_each_entry(tbl, &set->head_rt_tbl_list, link) {
 		i = 0;
 		list_for_each_entry(entry, &tbl->head_rt_rule_list, link) {
+			pr_err("tbl_idx:%d tbl_name:%s tbl_ref:%u ",
+				entry->tbl->idx, entry->tbl->name,
+				entry->tbl->ref_cnt);
 			if (entry->proc_ctx &&
 				(!ipa3_check_idr_if_freed(entry->proc_ctx))) {
 				ofst = entry->proc_ctx->offset_entry->offset;
@@ -894,10 +897,6 @@ static ssize_t ipa3_read_rt(struct file *file, char __user *ubuf, size_t count,
 					(ofst +
 					ipa3_ctx->hdr_proc_ctx_tbl.start_offset)
 					>> 5;
-
-				pr_err("tbl_idx:%d tbl_name:%s tbl_ref:%u ",
-					entry->tbl->idx, entry->tbl->name,
-					entry->tbl->ref_cnt);
 				pr_err("rule_idx:%d dst:%d ep:%d S:%u ",
 					i, entry->rule.dst,
 					ipa3_get_ep_mapping(entry->rule.dst),
@@ -905,24 +904,11 @@ static ssize_t ipa3_read_rt(struct file *file, char __user *ubuf, size_t count,
 				pr_err("proc_ctx[32B]:%u attrib_mask:%08x ",
 					ofst_words,
 					entry->rule.attrib.attrib_mask);
-				pr_err("rule_id:%u max_prio:%u prio:%u ",
-					entry->rule_id, entry->rule.max_prio,
-					entry->prio);
-				pr_err("enable_stats:%u counter_id:%u\n",
-					entry->rule.enable_stats,
-					entry->rule.cnt_idx);
-				pr_err("hashable:%u retain_hdr:%u ",
-					entry->rule.hashable,
-					entry->rule.retain_hdr);
 			} else {
 				if (entry->hdr)
 					ofst = entry->hdr->offset_entry->offset;
 				else
 					ofst = 0;
-
-				pr_err("tbl_idx:%d tbl_name:%s tbl_ref:%u ",
-					entry->tbl->idx, entry->tbl->name,
-					entry->tbl->ref_cnt);
 				pr_err("rule_idx:%d dst:%d ep:%d S:%u ",
 					i, entry->rule.dst,
 					ipa3_get_ep_mapping(entry->rule.dst),
@@ -930,16 +916,19 @@ static ssize_t ipa3_read_rt(struct file *file, char __user *ubuf, size_t count,
 				pr_err("hdr_ofst[words]:%u attrib_mask:%08x ",
 					ofst >> 2,
 					entry->rule.attrib.attrib_mask);
-				pr_err("rule_id:%u max_prio:%u prio:%u ",
-					entry->rule_id, entry->rule.max_prio,
-					entry->prio);
-				pr_err("enable_stats:%u counter_id:%u\n",
-					entry->rule.enable_stats,
-					entry->rule.cnt_idx);
-				pr_err("hashable:%u retain_hdr:%u ",
-					entry->rule.hashable,
-					entry->rule.retain_hdr);
 			}
+			pr_err("rule_id:%u max_prio:%u prio:%u ",
+				entry->rule_id, entry->rule.max_prio,
+				entry->prio);
+			pr_err("enable_stats:%u counter_id:%u ",
+				entry->rule.enable_stats,
+				entry->rule.cnt_idx);
+			pr_err("hashable:%u retain_hdr:%u ",
+				entry->rule.hashable,
+				entry->rule.retain_hdr);
+			if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0)
+				pr_err("close_aggr_irq_mod: %u\n",
+					entry->rule.close_aggr_irq_mod);
 
 			ipa3_attrib_dump(&entry->rule.attrib, ip);
 			i++;
@@ -1001,6 +990,10 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf,
 			pr_err("rule_idx:%d dst ep:%d L:%u ",
 				rl, rules[rl].dst_pipe_idx, rules[rl].hdr_lcl);
 
+			if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0)
+				pr_err("close_aggr_irq_mod: %u ",
+					rules[rl].close_aggr_irq_mod);
+
 			if (rules[rl].hdr_type == IPAHAL_RT_RULE_HDR_PROC_CTX)
 				pr_err("proc_ctx:%u attrib_mask:%08x ",
 					rules[rl].hdr_ofst,
@@ -1166,6 +1159,9 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count,
 				pr_err("pdn index %d, set metadata %d ",
 					entry->rule.pdn_idx,
 					entry->rule.set_metadata);
+			if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0)
+				pr_err("close_aggr_irq_mod %u ",
+					entry->rule.close_aggr_irq_mod);
 			if (eq) {
 				res = ipa3_attrib_dump_eq(
 						&entry->rule.eq_attrib);
@@ -1232,6 +1228,9 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
 			pr_err("rule_id:%u cnt_id:%hhu prio:%u\n",
 				rules[rl].id, rules[rl].cnt_idx,
 				rules[rl].priority);
+			if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0)
+				pr_err("close_aggr_irq_mod %u\n",
+					rules[rl].rule.close_aggr_irq_mod);
 			if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
 				pr_err("pdn: %u, set_metadata: %u ",
 					rules[rl].rule.pdn_idx,
@@ -1264,6 +1263,9 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
 			pr_err("rule_id:%u cnt_id:%hhu prio:%u\n",
 				rules[rl].id, rules[rl].cnt_idx,
 				rules[rl].priority);
+			if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0)
+				pr_err("close_aggr_irq_mod %u\n",
+					rules[rl].rule.close_aggr_irq_mod);
 			if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
 				pr_err("pdn: %u, set_metadata: %u ",
 					rules[rl].rule.pdn_idx,

+ 6 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_defs.h

@@ -28,6 +28,8 @@
  * rt rule.
  * @cnt_idx: if enable_stats is 1 and cnt_idx is 0, then cnt_idx
  * will be assigned by ipa driver.
+ * @close_aggr_irq_mod: close aggregation/coalescing and close GSI
+ *  interrupt moderation
  */
 struct ipa_rt_rule_i {
 	enum ipa_client_type dst;
@@ -40,6 +42,7 @@ struct ipa_rt_rule_i {
 	u8 coalesce;
 	u8 enable_stats;
 	u8 cnt_idx;
+	u8 close_aggr_irq_mod;
 };
 
 /**
@@ -72,6 +75,8 @@ struct ipa_rt_rule_i {
  * flt rule.
  * @cnt_idx: if 0 means disable, otherwise use for index.
  * will be assigned by ipa driver.
+ * @close_aggr_irq_mod: close aggregation/coalescing and close GSI
+ *  interrupt moderation
  */
 struct ipa_flt_rule_i {
 	u8 retain_hdr;
@@ -89,6 +94,7 @@ struct ipa_flt_rule_i {
 	u8 pdn_idx;
 	u8 enable_stats;
 	u8 cnt_idx;
+	u8 close_aggr_irq_mod;
 };
 
 #endif /* _IPA_DEFS_H_ */

+ 39 - 16
drivers/platform/msm/ipa/ipa_v3/ipa_flt.c

@@ -486,7 +486,6 @@ int __ipa_commit_flt_v3(enum ipa_ip_type ip)
 	u32 lcl_hash_hdr, lcl_nhash_hdr;
 	u32 lcl_hash_bdy, lcl_nhash_bdy;
 	bool lcl_hash, lcl_nhash;
-	struct ipahal_reg_fltrt_hash_flush flush;
 	struct ipahal_reg_valmask valmask;
 	u32 tbl_hdr_width;
 	struct ipa3_flt_tbl *tbl;
@@ -613,16 +612,30 @@ int __ipa_commit_flt_v3(enum ipa_ip_type ip)
 	 */
 	if (!ipa3_ctx->ipa_fltrt_not_hashable) {
 		/* flushing ipa internal hashable flt rules cache */
-		memset(&flush, 0, sizeof(flush));
-		if (ip == IPA_IP_v4)
-			flush.v4_flt = true;
-		else
-			flush.v6_flt = true;
-		ipahal_get_fltrt_hash_flush_valmask(&flush, &valmask);
+		if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0) {
+			struct ipahal_reg_fltrt_cache_flush flush_cache;
+
+			memset(&flush_cache, 0, sizeof(flush_cache));
+			flush_cache.flt = true;
+			ipahal_get_fltrt_cache_flush_valmask(
+				&flush_cache, &valmask);
+			reg_write_cmd.offset = ipahal_get_reg_ofst(
+				IPA_FILT_ROUT_CACHE_FLUSH);
+		} else {
+			struct ipahal_reg_fltrt_hash_flush flush_hash;
+
+			memset(&flush_hash, 0, sizeof(flush_hash));
+			if (ip == IPA_IP_v4)
+				flush_hash.v4_flt = true;
+			else
+				flush_hash.v6_flt = true;
+			ipahal_get_fltrt_hash_flush_valmask(
+				&flush_hash, &valmask);
+			reg_write_cmd.offset = ipahal_get_reg_ofst(
+				IPA_FILT_ROUT_HASH_FLUSH);
+		}
 		reg_write_cmd.skip_pipeline_clear = false;
 		reg_write_cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
-		reg_write_cmd.offset = ipahal_get_reg_ofst(
-					IPA_FILT_ROUT_HASH_FLUSH);
 		reg_write_cmd.value = valmask.val;
 		reg_write_cmd.value_mask = valmask.mask;
 		cmd_pyld[num_cmd] = ipahal_construct_imm_cmd(
@@ -1962,8 +1975,6 @@ void ipa3_delete_dflt_flt_rules(u32 ipa_ep_idx)
  */
 int ipa3_set_flt_tuple_mask(int pipe_idx, struct ipahal_reg_hash_tuple *tuple)
 {
-	struct ipahal_reg_fltrt_hash_tuple fltrt_tuple;
-
 	if (!tuple) {
 		IPAERR_RL("bad tuple\n");
 		return -EINVAL;
@@ -1984,11 +1995,23 @@ int ipa3_set_flt_tuple_mask(int pipe_idx, struct ipahal_reg_hash_tuple *tuple)
 		return -EINVAL;
 	}
 
-	ipahal_read_reg_n_fields(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n,
-		pipe_idx, &fltrt_tuple);
-	fltrt_tuple.flt = *tuple;
-	ipahal_write_reg_n_fields(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n,
-		pipe_idx, &fltrt_tuple);
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0) {
+		struct ipahal_reg_fltrt_cache_tuple cache_tuple;
+
+		ipahal_read_reg_n_fields(IPA_FILTER_CACHE_CFG_n,
+			pipe_idx, &cache_tuple);
+		cache_tuple.tuple = *tuple;
+		ipahal_write_reg_n_fields(IPA_FILTER_CACHE_CFG_n,
+			pipe_idx, &cache_tuple);
+	} else {
+		struct ipahal_reg_fltrt_hash_tuple hash_tuple;
+
+		ipahal_read_reg_n_fields(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n,
+			pipe_idx, &hash_tuple);
+		hash_tuple.flt = *tuple;
+		ipahal_write_reg_n_fields(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n,
+			pipe_idx, &hash_tuple);
+	}
 
 	return 0;
 }

+ 39 - 16
drivers/platform/msm/ipa/ipa_v3/ipa_rt.c

@@ -471,7 +471,6 @@ int __ipa_commit_rt_v3(enum ipa_ip_type ip)
 	u32 lcl_hash_hdr, lcl_nhash_hdr;
 	u32 lcl_hash_bdy, lcl_nhash_bdy;
 	bool lcl_hash, lcl_nhash;
-	struct ipahal_reg_fltrt_hash_flush flush;
 	struct ipahal_reg_valmask valmask;
 	int i;
 	struct ipa3_rt_tbl_set *set;
@@ -602,16 +601,30 @@ int __ipa_commit_rt_v3(enum ipa_ip_type ip)
 	 */
 	if (!ipa3_ctx->ipa_fltrt_not_hashable) {
 		/* flushing ipa internal hashable rt rules cache */
-		memset(&flush, 0, sizeof(flush));
-		if (ip == IPA_IP_v4)
-			flush.v4_rt = true;
-		else
-			flush.v6_rt = true;
-		ipahal_get_fltrt_hash_flush_valmask(&flush, &valmask);
+		if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0) {
+			struct ipahal_reg_fltrt_cache_flush flush_cache;
+
+			memset(&flush_cache, 0, sizeof(flush_cache));
+			flush_cache.rt = true;
+			ipahal_get_fltrt_cache_flush_valmask(
+				&flush_cache, &valmask);
+			reg_write_cmd.offset = ipahal_get_reg_ofst(
+				IPA_FILT_ROUT_CACHE_FLUSH);
+		} else {
+			struct ipahal_reg_fltrt_hash_flush flush_hash;
+
+			memset(&flush_hash, 0, sizeof(flush_hash));
+			if (ip == IPA_IP_v4)
+				flush_hash.v4_rt = true;
+			else
+				flush_hash.v6_rt = true;
+			ipahal_get_fltrt_hash_flush_valmask(
+				&flush_hash, &valmask);
+			reg_write_cmd.offset = ipahal_get_reg_ofst(
+				IPA_FILT_ROUT_HASH_FLUSH);
+		}
 		reg_write_cmd.skip_pipeline_clear = false;
 		reg_write_cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
-		reg_write_cmd.offset = ipahal_get_reg_ofst(
-					IPA_FILT_ROUT_HASH_FLUSH);
 		reg_write_cmd.value = valmask.val;
 		reg_write_cmd.value_mask = valmask.mask;
 		cmd_pyld[num_cmd] = ipahal_construct_imm_cmd(
@@ -2330,8 +2343,6 @@ bail:
  */
 int ipa3_set_rt_tuple_mask(int tbl_idx, struct ipahal_reg_hash_tuple *tuple)
 {
-	struct ipahal_reg_fltrt_hash_tuple fltrt_tuple;
-
 	if (!tuple) {
 		IPAERR_RL("bad tuple\n");
 		return -EINVAL;
@@ -2357,11 +2368,23 @@ int ipa3_set_rt_tuple_mask(int tbl_idx, struct ipahal_reg_hash_tuple *tuple)
 		return -EINVAL;
 	}
 
-	ipahal_read_reg_n_fields(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n,
-		tbl_idx, &fltrt_tuple);
-	fltrt_tuple.rt = *tuple;
-	ipahal_write_reg_n_fields(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n,
-		tbl_idx, &fltrt_tuple);
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0) {
+		struct ipahal_reg_fltrt_cache_tuple cache_tuple;
+
+		ipahal_read_reg_n_fields(IPA_ROUTER_CACHE_CFG_n,
+			tbl_idx, &cache_tuple);
+		cache_tuple.tuple = *tuple;
+		ipahal_write_reg_n_fields(IPA_ROUTER_CACHE_CFG_n,
+			tbl_idx, &cache_tuple);
+	} else {
+		struct ipahal_reg_fltrt_hash_tuple hash_tuple;
+
+		ipahal_read_reg_n_fields(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n,
+			tbl_idx, &hash_tuple);
+		hash_tuple.rt = *tuple;
+		ipahal_write_reg_n_fields(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n,
+			tbl_idx, &hash_tuple);
+	}
 
 	return 0;
 }

+ 9 - 1
drivers/platform/msm/ipa/ipa_v3/ipa_utils.c

@@ -4583,7 +4583,15 @@ int ipa3_cfg_filter(u32 disable)
  */
 static int ipa_disable_hashing_rt_flt_v4_2(void)
 {
-
+	/*
+	 * note this register deprecated starting IPAv5 if need to disable
+	 * use alternative
+	 */
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v5_0) {
+		IPAERR("reg deprecated\n");
+		WARN_ON(1);
+		return -EPERM;
+	}
 	IPADBG("Disable hashing for filter and route table in IPA 4.2 HW\n");
 	ipahal_write_reg(IPA_FILT_ROUT_HASH_EN,
 					IPA_FILT_ROUT_HASH_REG_VAL_v4_2);

+ 365 - 60
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c

@@ -18,70 +18,18 @@
 		IPA_FLT_MAC_SRC_ADDR_802_3 | IPA_FLT_MAC_DST_ADDR_802_1Q | \
 		IPA_FLT_MAC_SRC_ADDR_802_1Q)
 
-/*
- * struct ipahal_fltrt_obj - Flt/Rt H/W information for specific IPA version
- * @support_hash: Is hashable tables supported
- * @tbl_width: Width of table in bytes
- * @sysaddr_alignment: System table address alignment
- * @lcladdr_alignment: Local table offset alignment
- * @blk_sz_alignment: Rules block size alignment
- * @rule_start_alignment: Rule start address alignment
- * @tbl_hdr_width: Width of the header structure in bytes
- * @tbl_addr_mask: Masking for Table address
- * @rule_max_prio: Max possible priority of a rule
- * @rule_min_prio: Min possible priority of a rule
- * @low_rule_id: Low value of Rule ID that can be used
- * @rule_id_bit_len: Rule is high (MSB) bit len
- * @rule_buf_size: Max size rule may utilize.
- * @write_val_to_hdr: Write address or offset to header entry
- * @create_flt_bitmap: Create bitmap in H/W format using given bitmap
- * @create_tbl_addr: Given raw table address, create H/W formated one
- * @parse_tbl_addr: Parse the given H/W address (hdr format)
- * @rt_generate_hw_rule: Generate RT rule in H/W format
- * @flt_generate_hw_rule: Generate FLT rule in H/W format
- * @flt_generate_eq: Generate flt equation attributes from rule attributes
- * @rt_parse_hw_rule: Parse rt rule read from H/W
- * @flt_parse_hw_rule: Parse flt rule read from H/W
- * @eq_bitfield: Array of the bit fields of the support equations.
- *	0xFF means the equation is not supported
- */
-struct ipahal_fltrt_obj {
-	bool support_hash;
-	u32 tbl_width;
-	u32 sysaddr_alignment;
-	u32 lcladdr_alignment;
-	u32 blk_sz_alignment;
-	u32 rule_start_alignment;
-	u32 tbl_hdr_width;
-	u32 tbl_addr_mask;
-	int rule_max_prio;
-	int rule_min_prio;
-	u32 low_rule_id;
-	u32 rule_id_bit_len;
-	u32 rule_buf_size;
-	u8* (*write_val_to_hdr)(u64 val, u8 *hdr);
-	u64 (*create_flt_bitmap)(u64 ep_bitmap);
-	u64 (*create_tbl_addr)(bool is_sys, u64 addr);
-	void (*parse_tbl_addr)(u64 hwaddr, u64 *addr, bool *is_sys);
-	int (*rt_generate_hw_rule)(struct ipahal_rt_rule_gen_params *params,
-		u32 *hw_len, u8 *buf);
-	int (*flt_generate_hw_rule)(struct ipahal_flt_rule_gen_params *params,
-		u32 *hw_len, u8 *buf);
-	int (*flt_generate_eq)(enum ipa_ip_type ipt,
-		const struct ipa_rule_attrib *attrib,
-		struct ipa_ipfltri_rule_eq *eq_atrb);
-	int (*rt_parse_hw_rule)(u8 *addr, struct ipahal_rt_rule_entry *rule);
-	int (*flt_parse_hw_rule)(u8 *addr, struct ipahal_flt_rule_entry *rule);
-	u8 eq_bitfield[IPA_EQ_MAX];
-};
-
-
 static u64 ipa_fltrt_create_flt_bitmap(u64 ep_bitmap)
 {
 	/* At IPA3, there global configuration is possible but not used */
 	return (ep_bitmap << 1) & ~0x1;
 }
 
+static u64 ipa_fltrt_create_flt_bitmap_v5_0(u64 ep_bitmap)
+{
+	/* At IPA5, ep_bitmap is all 64 bits bit map */
+	return ep_bitmap;
+}
+
 static u64 ipa_fltrt_create_tbl_addr(bool is_sys, u64 addr)
 {
 	if (is_sys) {
@@ -162,12 +110,16 @@ static int ipa_rt_parse_hw_rule(u8 *addr,
 		struct ipahal_rt_rule_entry *rule);
 static int ipa_rt_parse_hw_rule_ipav4_5(u8 *addr,
 		struct ipahal_rt_rule_entry *rule);
+static int ipa_rt_parse_hw_rule_ipav5_0(u8 *addr,
+	struct ipahal_rt_rule_entry *rule);
 static int ipa_flt_parse_hw_rule(u8 *addr,
 		struct ipahal_flt_rule_entry *rule);
 static int ipa_flt_parse_hw_rule_ipav4(u8 *addr,
 		struct ipahal_flt_rule_entry *rule);
 static int ipa_flt_parse_hw_rule_ipav4_5(u8 *addr,
 	struct ipahal_flt_rule_entry *rule);
+static int ipa_flt_parse_hw_rule_ipav5_0(u8 *addr,
+	struct ipahal_flt_rule_entry *rule);
 
 #define IPA_IS_RAN_OUT_OF_EQ(__eq_array, __eq_index) \
 	(ARRAY_SIZE(__eq_array) <= (__eq_index))
@@ -345,6 +297,75 @@ static int ipa_rt_gen_hw_rule_ipav4_5(struct ipahal_rt_rule_gen_params *params,
 	return 0;
 }
 
+static int ipa_rt_gen_hw_rule_ipav5_0(struct ipahal_rt_rule_gen_params *params,
+	u32 *hw_len, u8 *buf)
+{
+	struct ipa5_0_rt_rule_hw_hdr *rule_hdr;
+	u8 *start;
+	u16 en_rule = 0;
+
+	start = buf;
+	rule_hdr = (struct ipa5_0_rt_rule_hw_hdr *)buf;
+
+	ipa_assert_on(params->dst_pipe_idx & ~0xFF);
+	rule_hdr->u.hdr.pipe_dest_idx = params->dst_pipe_idx;
+	switch (params->hdr_type) {
+	case IPAHAL_RT_RULE_HDR_PROC_CTX:
+		rule_hdr->u.hdr.system = !params->hdr_lcl;
+		rule_hdr->u.hdr.proc_ctx = 1;
+		ipa_assert_on(params->hdr_ofst & 31);
+		rule_hdr->u.hdr.hdr_offset = (params->hdr_ofst) >> 5;
+		break;
+	case IPAHAL_RT_RULE_HDR_RAW:
+		rule_hdr->u.hdr.system = !params->hdr_lcl;
+		rule_hdr->u.hdr.proc_ctx = 0;
+		ipa_assert_on(params->hdr_ofst & 3);
+		rule_hdr->u.hdr.hdr_offset = (params->hdr_ofst) >> 2;
+		break;
+	case IPAHAL_RT_RULE_HDR_NONE:
+		rule_hdr->u.hdr.system = !params->hdr_lcl;
+		rule_hdr->u.hdr.proc_ctx = 0;
+		rule_hdr->u.hdr.hdr_offset = 0;
+		break;
+	default:
+		IPAHAL_ERR("Invalid HDR type %d\n", params->hdr_type);
+		WARN_ON_RATELIMIT_IPA(1);
+		return -EINVAL;
+	}
+
+	ipa_assert_on(params->priority & ~0xFF);
+	rule_hdr->u.hdr.priority = params->priority;
+	rule_hdr->u.hdr.retain_hdr = params->rule->retain_hdr ? 0x1 : 0x0;
+	ipa_assert_on(params->id & ~((1 << IPA3_0_RULE_ID_BIT_LEN) - 1));
+	ipa_assert_on(params->id == ((1 << IPA3_0_RULE_ID_BIT_LEN) - 1));
+	rule_hdr->u.hdr.rule_id = params->id;
+	rule_hdr->u.hdr.stats_cnt_idx = params->cnt_idx;
+	rule_hdr->u.hdr.close_aggr_irq_mod =
+		params->rule->close_aggr_irq_mod ? 0x1 : 0x0;
+
+	buf += sizeof(struct ipa5_0_rt_rule_hw_hdr);
+
+	if (ipa_fltrt_generate_hw_rule_bdy(params->ipt, &params->rule->attrib,
+		&buf, &en_rule)) {
+		IPAHAL_ERR("fail to generate hw rule\n");
+		return -EPERM;
+	}
+	rule_hdr->u.hdr.en_rule = en_rule;
+
+	IPAHAL_DBG_LOW("en_rule 0x%x\n", en_rule);
+	ipa_write_64(rule_hdr->u.word, (u8 *)rule_hdr);
+
+	if (*hw_len == 0) {
+		*hw_len = buf - start;
+	} else if (*hw_len != (buf - start)) {
+		IPAHAL_ERR("hw_len differs b/w passed=0x%x calc=%td\n",
+			*hw_len, (buf - start));
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static int ipa_flt_gen_hw_rule(struct ipahal_flt_rule_gen_params *params,
 	u32 *hw_len, u8 *buf)
 {
@@ -602,6 +623,154 @@ static int ipa_flt_gen_hw_rule_ipav4_5(
 	return 0;
 }
 
+static int ipa_flt_gen_hw_rule_ipav5_0(
+	struct ipahal_flt_rule_gen_params *params,
+	u32 *hw_len, u8 *buf)
+{
+	struct ipa5_0_flt_rule_hw_hdr *rule_hdr;
+	u8 *start;
+	u16 en_rule = 0;
+
+	start = buf;
+	rule_hdr = (struct ipa5_0_flt_rule_hw_hdr *)buf;
+
+	switch (params->rule->action) {
+	case IPA_PASS_TO_ROUTING:
+		rule_hdr->u.hdr.action = 0x0;
+		break;
+	case IPA_PASS_TO_SRC_NAT:
+		rule_hdr->u.hdr.action = 0x1;
+		break;
+	case IPA_PASS_TO_DST_NAT:
+		rule_hdr->u.hdr.action = 0x2;
+		break;
+	case IPA_PASS_TO_EXCEPTION:
+		rule_hdr->u.hdr.action = 0x3;
+		break;
+	default:
+		IPAHAL_ERR("Invalid Rule Action %d\n", params->rule->action);
+		WARN_ON_RATELIMIT_IPA(1);
+		return -EINVAL;
+	}
+
+	ipa_assert_on(params->rt_tbl_idx & ~0xFF);
+	rule_hdr->u.hdr.rt_tbl_idx = params->rt_tbl_idx;
+	rule_hdr->u.hdr.retain_hdr = params->rule->retain_hdr ? 0x1 : 0x0;
+
+	ipa_assert_on(params->rule->pdn_idx & ~0xF);
+	rule_hdr->u.hdr.pdn_idx = params->rule->pdn_idx;
+	rule_hdr->u.hdr.set_metadata = params->rule->set_metadata ? 0x1 : 0x0;
+	rule_hdr->u.hdr.rsvd1 = 0;
+	rule_hdr->u.hdr.rsvd2 = 0;
+
+	ipa_assert_on(params->priority & ~0xFF);
+	rule_hdr->u.hdr.priority = params->priority;
+	ipa_assert_on(params->id & ~((1 << IPA3_0_RULE_ID_BIT_LEN) - 1));
+	ipa_assert_on(params->id == ((1 << IPA3_0_RULE_ID_BIT_LEN) - 1));
+	rule_hdr->u.hdr.rule_id = params->id;
+	rule_hdr->u.hdr.stats_cnt_idx = params->cnt_idx;
+	rule_hdr->u.hdr.close_aggr_irq_mod =
+		params->rule->close_aggr_irq_mod ? 0x1 : 0x0;
+
+	buf += sizeof(struct ipa5_0_flt_rule_hw_hdr);
+
+	if (params->rule->eq_attrib_type) {
+		if (ipa_fltrt_generate_hw_rule_bdy_from_eq(
+			&params->rule->eq_attrib, &buf)) {
+			IPAHAL_ERR("fail to generate hw rule from eq\n");
+			return -EPERM;
+		}
+		en_rule = params->rule->eq_attrib.rule_eq_bitmap;
+	} else {
+		if (ipa_fltrt_generate_hw_rule_bdy(params->ipt,
+			&params->rule->attrib, &buf, &en_rule)) {
+			IPAHAL_ERR("fail to generate hw rule\n");
+			return -EPERM;
+		}
+	}
+	rule_hdr->u.hdr.en_rule = en_rule;
+
+	IPAHAL_DBG_LOW("en_rule=0x%x, action=%d, rt_idx=%d, retain_hdr=%d\n",
+		en_rule,
+		rule_hdr->u.hdr.action,
+		rule_hdr->u.hdr.rt_tbl_idx,
+		rule_hdr->u.hdr.retain_hdr);
+	IPAHAL_DBG_LOW("priority=%d, rule_id=%d, pdn=%d, set_metadata=%d\n",
+		rule_hdr->u.hdr.priority,
+		rule_hdr->u.hdr.rule_id,
+		rule_hdr->u.hdr.pdn_idx,
+		rule_hdr->u.hdr.set_metadata);
+
+	ipa_write_64(rule_hdr->u.word, (u8 *)rule_hdr);
+
+	if (*hw_len == 0) {
+		*hw_len = buf - start;
+	} else if (*hw_len != (buf - start)) {
+		IPAHAL_ERR("hw_len differs b/w passed=0x%x calc=%td\n",
+			*hw_len, (buf - start));
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+/*
+* struct ipahal_fltrt_obj - Flt/Rt H/W information for specific IPA version
+* @support_hash: Is hashable tables supported
+* @tbl_width: Width of table in bytes
+* @sysaddr_alignment: System table address alignment
+* @lcladdr_alignment: Local table offset alignment
+* @blk_sz_alignment: Rules block size alignment
+* @rule_start_alignment: Rule start address alignment
+* @tbl_hdr_width: Width of the header structure in bytes
+* @tbl_addr_mask: Masking for Table address
+* @rule_max_prio: Max possible priority of a rule
+* @rule_min_prio: Min possible priority of a rule
+* @low_rule_id: Low value of Rule ID that can be used
+* @rule_id_bit_len: Rule is high (MSB) bit len
+* @rule_buf_size: Max size rule may utilize.
+* @write_val_to_hdr: Write address or offset to header entry
+* @create_flt_bitmap: Create bitmap in H/W format using given bitmap
+* @create_tbl_addr: Given raw table address, create H/W formated one
+* @parse_tbl_addr: Parse the given H/W address (hdr format)
+* @rt_generate_hw_rule: Generate RT rule in H/W format
+* @flt_generate_hw_rule: Generate FLT rule in H/W format
+* @flt_generate_eq: Generate flt equation attributes from rule attributes
+* @rt_parse_hw_rule: Parse rt rule read from H/W
+* @flt_parse_hw_rule: Parse flt rule read from H/W
+* @eq_bitfield: Array of the bit fields of the support equations.
+*	0xFF means the equation is not supported
+*/
+struct ipahal_fltrt_obj {
+	bool support_hash;
+	u32 tbl_width;
+	u32 sysaddr_alignment;
+	u32 lcladdr_alignment;
+	u32 blk_sz_alignment;
+	u32 rule_start_alignment;
+	u32 tbl_hdr_width;
+	u32 tbl_addr_mask;
+	int rule_max_prio;
+	int rule_min_prio;
+	u32 low_rule_id;
+	u32 rule_id_bit_len;
+	u32 rule_buf_size;
+	u8* (*write_val_to_hdr)(u64 val, u8 *hdr);
+	u64(*create_flt_bitmap)(u64 ep_bitmap);
+	u64(*create_tbl_addr)(bool is_sys, u64 addr);
+	void(*parse_tbl_addr)(u64 hwaddr, u64 *addr, bool *is_sys);
+	int(*rt_generate_hw_rule)(struct ipahal_rt_rule_gen_params *params,
+		u32 *hw_len, u8 *buf);
+	int(*flt_generate_hw_rule)(struct ipahal_flt_rule_gen_params *params,
+		u32 *hw_len, u8 *buf);
+	int(*flt_generate_eq)(enum ipa_ip_type ipt,
+		const struct ipa_rule_attrib *attrib,
+		struct ipa_ipfltri_rule_eq *eq_atrb);
+	int(*rt_parse_hw_rule)(u8 *addr, struct ipahal_rt_rule_entry *rule);
+	int(*flt_parse_hw_rule)(u8 *addr, struct ipahal_flt_rule_entry *rule);
+	u8 eq_bitfield[IPA_EQ_MAX];
+};
+
 /*
  * This array contains the FLT/RT info for IPAv3 and later.
  * All the information on IPAv3 are statically defined below.
@@ -790,6 +959,51 @@ static struct ipahal_fltrt_obj ipahal_fltrt_objs[IPA_HW_MAX] = {
 			[IPA_IS_PURE_ACK]		= 0,
 		},
 	},
+
+	/* IPAv5 */
+	[IPA_HW_v5_0] = {
+			true,
+			IPA3_0_HW_TBL_WIDTH,
+			IPA3_0_HW_TBL_SYSADDR_ALIGNMENT,
+			IPA3_0_HW_TBL_LCLADDR_ALIGNMENT,
+			IPA3_0_HW_TBL_BLK_SIZE_ALIGNMENT,
+			IPA3_0_HW_RULE_START_ALIGNMENT,
+			IPA3_0_HW_TBL_HDR_WIDTH,
+			IPA3_0_HW_TBL_ADDR_MASK,
+			IPA3_0_RULE_MAX_PRIORITY,
+			IPA3_0_RULE_MIN_PRIORITY,
+			IPA3_0_LOW_RULE_ID,
+			IPA3_0_RULE_ID_BIT_LEN,
+			IPA3_0_HW_RULE_BUF_SIZE,
+			ipa_write_64,
+			ipa_fltrt_create_flt_bitmap_v5_0,
+			ipa_fltrt_create_tbl_addr,
+			ipa_fltrt_parse_tbl_addr,
+			ipa_rt_gen_hw_rule_ipav5_0,
+			ipa_flt_gen_hw_rule_ipav5_0,
+			ipa_flt_generate_eq,
+			ipa_rt_parse_hw_rule_ipav5_0,
+			ipa_flt_parse_hw_rule_ipav5_0,
+			{
+				[IPA_TOS_EQ] = 0xFF,
+				[IPA_PROTOCOL_EQ] = 1,
+				[IPA_TC_EQ] = 2,
+				[IPA_OFFSET_MEQ128_0] = 3,
+				[IPA_OFFSET_MEQ128_1] = 4,
+				[IPA_OFFSET_MEQ32_0] = 5,
+				[IPA_OFFSET_MEQ32_1] = 6,
+				[IPA_IHL_OFFSET_MEQ32_0] = 7,
+				[IPA_IHL_OFFSET_MEQ32_1] = 8,
+				[IPA_METADATA_COMPARE] = 9,
+				[IPA_IHL_OFFSET_RANGE16_0] = 10,
+				[IPA_IHL_OFFSET_RANGE16_1] = 11,
+				[IPA_IHL_OFFSET_EQ_32] = 12,
+				[IPA_IHL_OFFSET_EQ_16] = 13,
+				[IPA_FL_EQ] = 14,
+				[IPA_IS_FRAG] = 15,
+				[IPA_IS_PURE_ACK] = 0,
+			},
+	},
 };
 
 static int ipa_flt_generate_eq(enum ipa_ip_type ipt,
@@ -3202,7 +3416,7 @@ static int ipa_rt_parse_hw_rule_ipav4_5(u8 *addr,
 	IPAHAL_DBG_LOW("read hdr 0x%llx\n", rule_hdr->u.word);
 
 	if (rule_hdr->u.word == 0) {
-		/* table termintator - empty table */
+		/* table terminator - empty table */
 		rule->rule_size = 0;
 		return 0;
 	}
@@ -3228,6 +3442,46 @@ static int ipa_rt_parse_hw_rule_ipav4_5(u8 *addr,
 		atrb, &rule->rule_size);
 }
 
+static int ipa_rt_parse_hw_rule_ipav5_0(u8 *addr,
+	struct ipahal_rt_rule_entry *rule)
+{
+	struct ipa5_0_rt_rule_hw_hdr *rule_hdr;
+	struct ipa_ipfltri_rule_eq *atrb;
+
+	IPAHAL_DBG_LOW("Entry\n");
+
+	rule_hdr = (struct ipa5_0_rt_rule_hw_hdr *)addr;
+	atrb = &rule->eq_attrib;
+
+	IPAHAL_DBG_LOW("read hdr 0x%llx\n", rule_hdr->u.word);
+
+	if (rule_hdr->u.word == 0) {
+		/* table terminator - empty table */
+		rule->rule_size = 0;
+		return 0;
+	}
+
+	rule->dst_pipe_idx = rule_hdr->u.hdr.pipe_dest_idx;
+	if (rule_hdr->u.hdr.proc_ctx) {
+		rule->hdr_type = IPAHAL_RT_RULE_HDR_PROC_CTX;
+		rule->hdr_ofst = (rule_hdr->u.hdr.hdr_offset) << 5;
+	} else {
+		rule->hdr_type = IPAHAL_RT_RULE_HDR_RAW;
+		rule->hdr_ofst = (rule_hdr->u.hdr.hdr_offset) << 2;
+	}
+	rule->hdr_lcl = !rule_hdr->u.hdr.system;
+
+	rule->priority = rule_hdr->u.hdr.priority;
+	rule->retain_hdr = rule_hdr->u.hdr.retain_hdr;
+	rule->cnt_idx = rule_hdr->u.hdr.stats_cnt_idx;
+	rule->id = rule_hdr->u.hdr.rule_id;
+	rule->close_aggr_irq_mod = rule_hdr->u.hdr.close_aggr_irq_mod;
+
+	atrb->rule_eq_bitmap = rule_hdr->u.hdr.en_rule;
+	return ipa_fltrt_parse_hw_rule_eq(addr, sizeof(*rule_hdr),
+		atrb, &rule->rule_size);
+}
+
 static int ipa_flt_parse_hw_rule(u8 *addr, struct ipahal_flt_rule_entry *rule)
 {
 	struct ipa3_0_flt_rule_hw_hdr *rule_hdr;
@@ -3335,7 +3589,7 @@ static int ipa_flt_parse_hw_rule_ipav4_5(u8 *addr,
 	atrb = &rule->rule.eq_attrib;
 
 	if (rule_hdr->u.word == 0) {
-		/* table termintator - empty table */
+		/* table terminator - empty table */
 		rule->rule_size = 0;
 		return 0;
 	}
@@ -3374,6 +3628,57 @@ static int ipa_flt_parse_hw_rule_ipav4_5(u8 *addr,
 		atrb, &rule->rule_size);
 }
 
+static int ipa_flt_parse_hw_rule_ipav5_0(u8 *addr,
+	struct ipahal_flt_rule_entry *rule)
+{
+	struct ipa5_0_flt_rule_hw_hdr *rule_hdr;
+	struct ipa_ipfltri_rule_eq *atrb;
+
+	IPAHAL_DBG_LOW("Entry\n");
+
+	rule_hdr = (struct ipa5_0_flt_rule_hw_hdr *)addr;
+	atrb = &rule->rule.eq_attrib;
+
+	if (rule_hdr->u.word == 0) {
+		/* table terminator - empty table */
+		rule->rule_size = 0;
+		return 0;
+	}
+
+	switch (rule_hdr->u.hdr.action) {
+	case 0x0:
+		rule->rule.action = IPA_PASS_TO_ROUTING;
+		break;
+	case 0x1:
+		rule->rule.action = IPA_PASS_TO_SRC_NAT;
+		break;
+	case 0x2:
+		rule->rule.action = IPA_PASS_TO_DST_NAT;
+		break;
+	case 0x3:
+		rule->rule.action = IPA_PASS_TO_EXCEPTION;
+		break;
+	default:
+		IPAHAL_ERR("Invalid Rule Action %d\n", rule_hdr->u.hdr.action);
+		WARN_ON_RATELIMIT_IPA(1);
+		rule->rule.action = rule_hdr->u.hdr.action;
+	}
+
+	rule->rule.rt_tbl_idx = rule_hdr->u.hdr.rt_tbl_idx;
+	rule->rule.retain_hdr = rule_hdr->u.hdr.retain_hdr;
+	rule->priority = rule_hdr->u.hdr.priority;
+	rule->id = rule_hdr->u.hdr.rule_id;
+	rule->rule.pdn_idx = rule_hdr->u.hdr.pdn_idx;
+	rule->rule.set_metadata = rule_hdr->u.hdr.set_metadata;
+	rule->cnt_idx = rule_hdr->u.hdr.stats_cnt_idx;
+	rule->rule.close_aggr_irq_mod = rule_hdr->u.hdr.close_aggr_irq_mod;
+
+	atrb->rule_eq_bitmap = rule_hdr->u.hdr.en_rule;
+	rule->rule.eq_attrib_type = 1;
+	return ipa_fltrt_parse_hw_rule_eq(addr, sizeof(*rule_hdr),
+		atrb, &rule->rule_size);
+}
+
 /*
  * ipahal_fltrt_init() - Build the FLT/RT information table
  *  See ipahal_fltrt_objs[] comments

+ 3 - 0
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.h

@@ -81,6 +81,8 @@ struct ipahal_rt_rule_gen_params {
  * @retain_hdr: to retain the removed header in header removal
  * @id: Rule ID
  * @cnt_idx: stats counter index
+ * @close_aggr_irq_mod: close aggregation/coalescing and close GSI
+ *  interrupt moderation
  * @eq_attrib: Equations and their params in the rule
  * @rule_size: Rule size in memory
  */
@@ -93,6 +95,7 @@ struct ipahal_rt_rule_entry {
 	bool retain_hdr;
 	u32 id;
 	u8 cnt_idx;
+	u8 close_aggr_irq_mod;
 	struct ipa_ipfltri_rule_eq eq_attrib;
 	u32 rule_size;
 };

+ 82 - 1
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt_i.h

@@ -103,7 +103,7 @@ struct ipa3_0_rt_rule_hw_hdr {
 };
 
 /**
- * struct ipa3_0_rt_rule_hw_hdr - HW header of IPA routing rule
+ * struct ipa4_5_rt_rule_hw_hdr - HW header of IPA routing rule
  * @word: routing rule header properties
  * @en_rule: enable rule - Equation bit fields
  * @pipe_dest_idx: destination pipe index
@@ -141,6 +141,46 @@ struct ipa4_5_rt_rule_hw_hdr {
 	} u;
 };
 
+/**
+ * struct ipa5_0_rt_rule_hw_hdr - HW header of IPA routing rule
+ * @word: routing rule header properties
+ * @en_rule: enable rule - Equation bit fields
+ * @pipe_dest_idx: destination pipe index
+ * @stats_cnt_idx_lsb: stats cnt index
+ * @priority: Rule priority. Added to distinguish rules order
+ *  at the integrated table consisting from hashable and
+ *  non-hashable parts
+ * @rsvd: reserved bit
+ * @close_aggr_irq_mod: close aggregation/coalescing and close GSI
+ *  interrupt moderation
+ * @rule_id: rule ID that will be returned in the packet status
+ * @hdr_offset: header offset
+ * @proc_ctx: whether hdr_offset points to header table or to
+ *	header processing context table
+ * @retain_hdr: added to add back to the packet the header removed
+ *  as part of header removal. This will be done as part of
+ *  header insertion block.
+ * @system: Is referenced header is lcl or sys memory
+ */
+struct ipa5_0_rt_rule_hw_hdr {
+	union {
+		u64 word;
+		struct {
+			u64 en_rule : 16;
+			u64 pipe_dest_idx : 8;
+			u64 stats_cnt_idx : 8;
+			u64 priority : 8;
+			u64 rsvd : 1;
+			u64 close_aggr_irq_mod : 1;
+			u64 rule_id : 10;
+			u64 hdr_offset : 9;
+			u64 proc_ctx : 1;
+			u64 retain_hdr : 1;
+			u64 system : 1;
+		} hdr;
+	} u;
+};
+
 /**
  * struct ipa3_0_flt_rule_hw_hdr - HW header of IPA filter rule
  * @word: filtering rule properties
@@ -251,6 +291,47 @@ struct ipa4_5_flt_rule_hw_hdr {
 	} u;
 };
 
+/**
+ * struct ipa5_0_flt_rule_hw_hdr - HW header of IPA filter rule
+ * @word: filtering rule properties
+ * @en_rule: enable rule
+ * @rt_tbl_idx: index in routing table
+ * @stats_cnt_idx: stats cnt index
+ * @priority: Rule priority. Added to distinguish rules order
+ *  at the integrated table consisting from hashable and
+ *  non-hashable parts
+ * @close_aggr_irq_mod: close aggregation/coalescing and close GSI
+ *  interrupt moderation
+ * @rule_id: rule ID that will be returned in the packet status
+ * @action: post filtering action
+ * @pdn_idx: in case of go to src nat action possible to input the pdn index to
+ *  the NAT block
+ * @set_metadata: enable metadata replacement in the NAT block
+ * @retain_hdr: added to add back to the packet the header removed
+ *  as part of header removal. This will be done as part of
+ *  header insertion block.
+ * @rsvd1\rsvd2: reserved bits
+ */
+struct ipa5_0_flt_rule_hw_hdr {
+	union {
+		u64 word;
+		struct {
+			u64 en_rule : 16;
+			u64 rt_tbl_idx : 8;
+			u64 stats_cnt_idx : 8;
+			u64 priority : 8;
+			u64 rsvd1 : 1;
+			u64 close_aggr_irq_mod : 1;
+			u64 rule_id : 10;
+			u64 action : 5;
+			u64 pdn_idx : 4;
+			u64 set_metadata : 1;
+			u64 retain_hdr : 1;
+			u64 rsvd2 : 1;
+		} hdr;
+	} u;
+};
+
 int ipahal_fltrt_init(enum ipa_hw_type ipa_hw_type);
 void ipahal_fltrt_destroy(void);
 

+ 105 - 1
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c

@@ -154,6 +154,9 @@ static const char *ipareg_name_to_str[IPA_REG_MAX] = {
 	__stringify(IPA_SUSPEND_IRQ_EN_EE_n_REG_k),
 	__stringify(IPA_STAT_TETHERING_MASK_EE_n_REG_k),
 	__stringify(IPA_STAT_DROP_CNT_MASK_EE_n_REG_k),
+	__stringify(IPA_FILT_ROUT_CACHE_FLUSH),
+	__stringify(IPA_FILTER_CACHE_CFG_n),
+	__stringify(IPA_ROUTER_CACHE_CFG_n),
 };
 
 static void ipareg_construct_dummy(enum ipahal_reg_name reg,
@@ -408,6 +411,37 @@ static void ipareg_construct_hash_cfg_n(
 		IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED2_BMSK);
 }
 
+static void ipareg_construct_cache_cfg_n(
+	enum ipahal_reg_name reg, const void *fields, u32 *val)
+{
+	struct ipahal_reg_fltrt_cache_tuple *tuple =
+		(struct ipahal_reg_fltrt_cache_tuple *)fields;
+
+	IPA_SETFIELD_IN_REG(*val, tuple->tuple.src_id,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_ID_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_ID_BMSK);
+	IPA_SETFIELD_IN_REG(*val, tuple->tuple.src_ip_addr,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_IP_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_IP_BMSK);
+	IPA_SETFIELD_IN_REG(*val, tuple->tuple.dst_ip_addr,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_IP_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_IP_BMSK);
+	IPA_SETFIELD_IN_REG(*val, tuple->tuple.src_port,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_PORT_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_PORT_BMSK);
+	IPA_SETFIELD_IN_REG(*val, tuple->tuple.dst_port,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_PORT_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_PORT_BMSK);
+	IPA_SETFIELD_IN_REG(*val, tuple->tuple.protocol,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_PROTOCOL_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_PROTOCOL_BMSK);
+	IPA_SETFIELD_IN_REG(*val, tuple->tuple.meta_data,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_METADATA_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_METADATA_BMSK);
+	IPA_SETFIELD_IN_REG(*val, tuple->undefined,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_UNDEFINED_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_UNDEFINED_BMSK);
+}
 static void ipareg_parse_hash_cfg_n(
 	enum ipahal_reg_name reg, void *fields, u32 val)
 {
@@ -480,6 +514,46 @@ static void ipareg_parse_hash_cfg_n(
 		IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED2_BMSK);
 }
 
+static void ipareg_parse_cache_cfg_n(
+	enum ipahal_reg_name reg, void *fields, u32 val)
+{
+	struct ipahal_reg_fltrt_cache_tuple *tuple =
+		(struct ipahal_reg_fltrt_cache_tuple *)fields;
+
+	tuple->tuple.src_id =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_ID_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_ID_BMSK);
+	tuple->tuple.src_ip_addr =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_IP_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_IP_BMSK);
+	tuple->tuple.dst_ip_addr =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_IP_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_IP_BMSK);
+	tuple->tuple.src_port =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_PORT_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_PORT_BMSK);
+	tuple->tuple.dst_port =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_PORT_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_PORT_BMSK);
+	tuple->tuple.protocol =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_PROTOCOL_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_PROTOCOL_BMSK);
+	tuple->tuple.meta_data =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_METADATA_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_METADATA_BMSK);
+	tuple->undefined =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_UNDEFINED_SHFT,
+		IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_UNDEFINED_BMSK);
+}
+
 static void ipareg_construct_endp_status_n_common(
 	const struct ipahal_reg_ep_cfg_status *ep_status, u32 *val)
 {
@@ -4030,6 +4104,9 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = {
 	[IPA_HW_v5_0][IPA_FILT_ROUT_HASH_FLUSH] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
 		-1, 0, 0, 0, 0, 0},
+	[IPA_HW_v5_0][IPA_FILT_ROUT_CACHE_FLUSH] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000404, 0, 0, 0, 0, 0 },
 	[IPA_HW_v5_0][IPA_SYS_PKT_PROC_CNTXT_BASE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
 		0x00000470, 0, 0, 0, 0, 0},
@@ -4170,8 +4247,14 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = {
 		ipareg_parse_dummy,
 		0x00001050, 0x80, 0, 10, 0, 0},
 	[IPA_HW_v5_0][IPA_ENDP_FILTER_ROUTER_HSH_CFG_n] = {
-		ipareg_construct_hash_cfg_n, ipareg_parse_hash_cfg_n,
+		ipareg_construct_dummy, ipareg_parse_dummy,
 		-1, 0x70, 0, 31, 1, 0},
+	[IPA_HW_v5_0][IPA_FILTER_CACHE_CFG_n] = {
+		ipareg_construct_cache_cfg_n, ipareg_parse_cache_cfg_n,
+		0x0000105C , 0x80, 0, 31, 1, 0},
+	[IPA_HW_v5_0][IPA_ROUTER_CACHE_CFG_n] = {
+		ipareg_construct_cache_cfg_n, ipareg_parse_cache_cfg_n,
+		0x00001070 , 0x80, 0, 31, 1, 0},
 	[IPA_HW_v5_0][IPA_ENDP_INIT_CTRL_STATUS_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
 		0x00001064, 0x80, 0, 30, 1, 0},
@@ -4783,3 +4866,24 @@ void ipahal_get_fltrt_hash_flush_valmask(
 
 	valmask->mask = valmask->val;
 }
+
+void ipahal_get_fltrt_cache_flush_valmask(
+	struct ipahal_reg_fltrt_cache_flush *flush,
+	struct ipahal_reg_valmask *valmask)
+{
+	if (!flush || !valmask) {
+		IPAHAL_ERR("Input error: flush=%pK ; valmask=%pK\n",
+			flush, valmask);
+		return;
+	}
+
+	memset(valmask, 0, sizeof(struct ipahal_reg_valmask));
+
+	if (flush->rt)
+		valmask->val |=
+		(1 << IPA_FILT_ROUT_CACHE_FLUSH_ROUT_SHFT);
+	if (flush->flt)
+		valmask->val |=
+		(1 << IPA_FILT_ROUT_CACHE_FLUSH_FILT_SHFT);
+	valmask->mask = valmask->val;
+}

+ 27 - 0
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h

@@ -151,6 +151,9 @@ enum ipahal_reg_name {
 	IPA_SUSPEND_IRQ_EN_EE_n_REG_k,
 	IPA_STAT_TETHERING_MASK_EE_n_REG_k,
 	IPA_STAT_DROP_CNT_MASK_EE_n_REG_k,
+	IPA_FILT_ROUT_CACHE_FLUSH,
+	IPA_FILTER_CACHE_CFG_n,
+	IPA_ROUTER_CACHE_CFG_n,
 	IPA_REG_MAX,
 };
 
@@ -452,6 +455,16 @@ struct ipahal_reg_fltrt_hash_tuple {
 	u32 undefined2;
 };
 
+/*
+* struct ipahal_reg_fltrt_cache_tuple - IPA cache tuple register
+* @flt: cache tuple info for flt\rt
+* @undefinedX: Undefined/Unused bit fields set of the register
+*/
+struct ipahal_reg_fltrt_cache_tuple {
+	struct ipahal_reg_hash_tuple tuple;
+	u32 undefined;
+};
+
 /*
  * enum ipahal_reg_dbg_cnt_type - Debug Counter Type
  * DBG_CNT_TYPE_IPV4_FLTR - Count IPv4 filtering rules
@@ -567,6 +580,16 @@ struct ipahal_reg_fltrt_hash_flush {
 	bool v4_flt;
 };
 
+/*
+* struct ipahal_reg_fltrt_cache_flush - Flt/Rt flush configuration
+* @rt - Flush Routing cache
+* @flt - Flush Filtering cache
+*/
+struct ipahal_reg_fltrt_cache_flush {
+	bool rt;
+	bool flt;
+};
+
 /*
  * struct ipahal_reg_single_ndp_mode - IPA SINGLE_NDP_MODE register
  * @single_ndp_en: When set to '1', IPA builds MBIM frames with up to 1
@@ -894,4 +917,8 @@ void ipahal_get_fltrt_hash_flush_valmask(
 	struct ipahal_reg_fltrt_hash_flush *flush,
 	struct ipahal_reg_valmask *valmask);
 
+void ipahal_get_fltrt_cache_flush_valmask(
+	struct ipahal_reg_fltrt_cache_flush *flush,
+	struct ipahal_reg_valmask *valmask);
+
 #endif /* _IPAHAL_REG_H_ */

+ 23 - 0
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h

@@ -327,6 +327,10 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type);
 #define IPA_FILT_ROUT_HASH_FLUSH_IPv6_FILT_SHFT 4
 #define IPA_FILT_ROUT_HASH_FLUSH_IPv6_ROUT_SHFT 0
 
+/* IPA_FILT_ROUT_CACHE_FLUSH register */
+#define IPA_FILT_ROUT_CACHE_FLUSH_FILT_SHFT 4
+#define IPA_FILT_ROUT_CACHE_FLUSH_ROUT_SHFT 0
+
 /* IPA_SINGLE_NDP_MODE register */
 #define IPA_SINGLE_NDP_MODE_UNDEFINED_BMSK 0xfffffffe
 #define IPA_SINGLE_NDP_MODE_UNDEFINED_SHFT 0x1
@@ -474,6 +478,25 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type);
 #define IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED2_SHFT 23
 #define IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED2_BMSK 0xff800000
 
+/* IPA_FILTER_CACHE_CFG_n and IPA_ROUTER_CACHE_CFG_n registers*/
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_ID_SHFT 0
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_ID_BMSK 0x1
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_IP_SHFT 1
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_IP_BMSK 0x2
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_IP_SHFT 2
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_IP_BMSK 0x4
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_PORT_SHFT 3
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_SRC_PORT_BMSK 0x8
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_PORT_SHFT 4
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_DST_PORT_BMSK 0x10
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_PROTOCOL_SHFT 5
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_PROTOCOL_BMSK 0x20
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_METADATA_SHFT 6
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_CACHE_MSK_METADATA_BMSK 0x40
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_UNDEFINED_SHFT 7
+#define IPA_ENDP_FILTER_ROUTER_CACHE_CFG_n_UNDEFINED_BMSK 0xffffff80
+
+
 /* IPA_RSRC_GRP_XY_RSRC_TYPE_n register */
 #define IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MAX_LIM_BMSK 0xFF000000
 #define IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MAX_LIM_SHFT 24