소스 검색

dataipa: install hpc commands & tuple info based filters over WLAN

changes to install tuple info based filters over WLAN and route to
uCP path or uC temp pipes to receive rtp packets over WLAN in niobe.

Change-Id: Ie456fe8983bc0f43b767f762a046d96f6e25bc1b
Signed-off-by: Jagadeesh Ponduru <[email protected]>
Jagadeesh Ponduru 1 년 전
부모
커밋
1f4753b99d

+ 6 - 1
drivers/platform/msm/include/uapi/linux/msm_ipa.h

@@ -1433,6 +1433,7 @@ enum ipa_hdr_l2_type {
  * IPA_HDR_PROC_SET_DSCP:
  * IPA_HDR_PROC_EoGRE_HEADER_ADD:       Add IPV[46] GRE header
  * IPA_HDR_PROC_EoGRE_HEADER_REMOVE:    Remove IPV[46] GRE header
+ * IPA_HDR_PROC_RTP_METADATA_STREAM:    Process RTP Frames at uCP
  */
 enum ipa_hdr_proc_type {
 	IPA_HDR_PROC_NONE,
@@ -1448,8 +1449,12 @@ enum ipa_hdr_proc_type {
 	IPA_HDR_PROC_SET_DSCP,
 	IPA_HDR_PROC_EoGRE_HEADER_ADD,
 	IPA_HDR_PROC_EoGRE_HEADER_REMOVE,
+	IPA_HDR_PROC_RTP_METADATA_STREAM0,
+	IPA_HDR_PROC_RTP_METADATA_STREAM1,
+	IPA_HDR_PROC_RTP_METADATA_STREAM2,
+	IPA_HDR_PROC_RTP_METADATA_STREAM3,
 };
-#define IPA_HDR_PROC_MAX (IPA_HDR_PROC_EoGRE_HEADER_REMOVE + 1)
+#define IPA_HDR_PROC_MAX (IPA_HDR_PROC_RTP_METADATA_STREAM3 + 1)
 
 /**
  * struct ipa_rt_rule - attributes of a routing rule

+ 19 - 1
drivers/platform/msm/ipa/ipa_common_i.h

@@ -2,7 +2,7 @@
 /*
  * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
  *
- * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _IPA_COMMON_I_H_
@@ -538,6 +538,21 @@ struct ipa_tx_suspend_irq_data {
 	u32 endpoints[IPA_EP_ARR_SIZE];
 };
 
+/**
+ * struct ipa_rtp_header_add_procparams
+ * @input_ip_version:  Specifies if Input header is IPV4(0) or IPV6(1)
+ * @reserved: for future use
+ */
+
+struct ipa_rtp_header_add_procparams {
+	uint32_t input_ip_version:1;
+	uint32_t reserved:31;
+};
+
+struct ipa_rtp_hdr_proc_ctx_params {
+	struct ipa_rtp_header_add_procparams hdr_add_param;
+};
+
 extern const char *ipa_clients_strings[];
 
 #define IPA_IPC_LOGGING(buf, fmt, args...) \
@@ -747,6 +762,9 @@ int ipa3_reset_hdr(bool user_only);
 int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
 	bool user_only);
 
+int ipa3_add_rtp_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+	struct ipa_rtp_hdr_proc_ctx_params rtp_params, bool user_only);
+
 int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls);
 
 /*

+ 5 - 1
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c

@@ -2,7 +2,7 @@
 /*
  * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
  *
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifdef CONFIG_DEBUG_FS
@@ -131,6 +131,10 @@ const char *ipa3_hdr_proc_type_name[] = {
 	__stringify(IPA_HDR_PROC_SET_DSCP),
 	__stringify(IPA_HDR_PROC_EoGRE_HEADER_ADD),
 	__stringify(IPA_HDR_PROC_EoGRE_HEADER_REMOVE),
+	__stringify(IPA_HDR_PROC_RTP_METADATA_STREAM0),
+	__stringify(IPA_HDR_PROC_RTP_METADATA_STREAM1),
+	__stringify(IPA_HDR_PROC_RTP_METADATA_STREAM2),
+	__stringify(IPA_HDR_PROC_RTP_METADATA_STREAM3),
 };
 
 static struct dentry *dent;

+ 182 - 1
drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include "ipa_i.h"
@@ -113,6 +113,7 @@ static int ipa3_hdr_proc_ctx_to_hw_format(struct ipa_mem_buffer *mem,
 				&entry->l2tp_params,
 				&entry->eogre_params,
 				&entry->generic_params,
+				&entry->rtp_params,
 				ipa3_ctx->use_64_bit_dma_mask);
 		if (ret)
 			return ret;
@@ -559,6 +560,138 @@ bad_len:
 	return -EPERM;
 }
 
+static int __ipa_add_rtp_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
+	struct ipa_rtp_hdr_proc_ctx_params rtp_params, bool add_ref_hdr, bool user_only)
+{
+	struct ipa3_hdr_entry *hdr_entry;
+	struct ipa3_hdr_proc_ctx_entry *entry;
+	struct ipa3_hdr_proc_ctx_offset_entry *offset;
+	u32 bin;
+	struct ipa3_hdr_proc_ctx_tbl *htbl = &ipa3_ctx->hdr_proc_ctx_tbl;
+	int id;
+	int needed_len;
+	int mem_size;
+
+	IPADBG_LOW("Add processing type %d hdr_hdl %d\n",
+		proc_ctx->type, proc_ctx->hdr_hdl);
+
+	if (!HDR_PROC_TYPE_IS_VALID(proc_ctx->type)) {
+		IPAERR_RL("invalid processing type %d\n", proc_ctx->type);
+		return -EINVAL;
+	}
+
+	hdr_entry = ipa3_id_find(proc_ctx->hdr_hdl);
+	if (!hdr_entry) {
+		IPAERR_RL("hdr_hdl is invalid\n");
+		return -EINVAL;
+	}
+	if (hdr_entry->cookie != IPA_HDR_COOKIE) {
+		IPAERR_RL("Invalid header cookie %u\n", hdr_entry->cookie);
+		WARN_ON_RATELIMIT_IPA(1);
+		return -EINVAL;
+	}
+	IPADBG("Associated header is name=%s\n", hdr_entry->name);
+
+	entry = kmem_cache_zalloc(ipa3_ctx->hdr_proc_ctx_cache, GFP_KERNEL);
+	if (!entry) {
+		IPAERR("failed to alloc proc_ctx object\n");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&entry->link);
+
+	entry->type = proc_ctx->type;
+	entry->hdr = hdr_entry;
+	entry->rtp_params = rtp_params;
+	if (add_ref_hdr)
+		hdr_entry->ref_cnt++;
+	entry->cookie = IPA_PROC_HDR_COOKIE;
+	entry->ipacm_installed = user_only;
+
+	needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type);
+	if ((needed_len < 0) ||
+		((needed_len > ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN0])
+			&&
+			(needed_len >
+			ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN1]))) {
+		IPAERR_RL("unexpected needed len %d\n", needed_len);
+		WARN_ON_RATELIMIT_IPA(1);
+		goto bad_len;
+	}
+
+	if (needed_len <= ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN0])
+		bin = IPA_HDR_PROC_CTX_BIN0;
+	else
+		bin = IPA_HDR_PROC_CTX_BIN1;
+
+	mem_size = (ipa3_ctx->hdr_proc_ctx_tbl_lcl) ?
+		IPA_MEM_PART(apps_hdr_proc_ctx_size) :
+		IPA_MEM_PART(apps_hdr_proc_ctx_size_ddr);
+	if (list_empty(&htbl->head_free_offset_list[bin])) {
+		if (htbl->end + ipa_hdr_proc_ctx_bin_sz[bin] > mem_size) {
+			IPAERR_RL("hdr proc ctx table overflow\n");
+			goto bad_len;
+		}
+
+		offset = kmem_cache_zalloc(ipa3_ctx->hdr_proc_ctx_offset_cache,
+					   GFP_KERNEL);
+		if (!offset) {
+			IPAERR("failed to alloc offset object\n");
+			goto bad_len;
+		}
+		INIT_LIST_HEAD(&offset->link);
+		/*
+		 * for a first item grow, set the bin and offset which are set
+		 * in stone
+		 */
+		offset->offset = htbl->end;
+		offset->bin = bin;
+		offset->ipacm_installed = user_only;
+		htbl->end += ipa_hdr_proc_ctx_bin_sz[bin];
+		list_add(&offset->link,
+				&htbl->head_offset_list[bin]);
+	} else {
+		/* get the first free slot */
+		offset =
+		    list_first_entry(&htbl->head_free_offset_list[bin],
+				struct ipa3_hdr_proc_ctx_offset_entry, link);
+		offset->ipacm_installed = user_only;
+		list_move(&offset->link, &htbl->head_offset_list[bin]);
+	}
+
+	entry->offset_entry = offset;
+	list_add(&entry->link, &htbl->head_proc_ctx_entry_list);
+	htbl->proc_ctx_cnt++;
+	IPADBG("add proc ctx of sz=%d cnt=%d ofst=%d\n", needed_len,
+			htbl->proc_ctx_cnt, offset->offset);
+
+	id = ipa3_id_alloc(entry);
+	if (id < 0) {
+		IPAERR_RL("failed to alloc id\n");
+		WARN_ON_RATELIMIT_IPA(1);
+		goto ipa_insert_failed;
+	}
+	entry->id = id;
+	proc_ctx->proc_ctx_hdl = id;
+	entry->ref_cnt++;
+
+	return 0;
+
+ipa_insert_failed:
+	list_move(&offset->link,
+		&htbl->head_free_offset_list[offset->bin]);
+	entry->offset_entry = NULL;
+	list_del(&entry->link);
+	htbl->proc_ctx_cnt--;
+
+bad_len:
+	if (add_ref_hdr)
+		hdr_entry->ref_cnt--;
+	entry->cookie = 0;
+	kmem_cache_free(ipa3_ctx->hdr_proc_ctx_cache, entry);
+	return -EPERM;
+}
+
 static int __ipa_add_hdr(struct ipa_hdr_add *hdr, bool user,
 	struct ipa3_hdr_entry **entry_out)
 {
@@ -1176,6 +1309,54 @@ bail:
 	return result;
 }
 
+/**
+ * ipa3_add_rtp_hdr_proc_ctx() - add the specified headers to SW
+ * and optionally commit them to IPA HW
+ * @proc_ctxs:	[inout] set of processing context headers to add
+ * @rtp_params: [in] set of rtp_params to be configured
+ * @user_only:	[in] indicate installed by user-space module
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa3_add_rtp_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+	struct ipa_rtp_hdr_proc_ctx_params rtp_params, bool user_only)
+{
+	int i;
+	int result = -EFAULT;
+
+	if (proc_ctxs == NULL || proc_ctxs->num_proc_ctxs == 0) {
+		IPAERR_RL("bad parm\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&ipa3_ctx->lock);
+	IPADBG("adding %d rtp header processing contexts to IPA driver\n",
+			proc_ctxs->num_proc_ctxs);
+	for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) {
+		if (__ipa_add_rtp_hdr_proc_ctx(&proc_ctxs->proc_ctx[i],
+				rtp_params, true, user_only)) {
+			IPAERR_RL("failed to add hdr proc ctx %d\n", i);
+			proc_ctxs->proc_ctx[i].status = -1;
+		} else {
+			proc_ctxs->proc_ctx[i].status = 0;
+		}
+	}
+
+	if (proc_ctxs->commit) {
+		IPADBG("committing all headers to IPA core");
+		if (ipa3_ctx->ctrl->ipa3_commit_hdr()) {
+			result = -EPERM;
+			goto bail;
+		}
+	}
+	result = 0;
+bail:
+	mutex_unlock(&ipa3_ctx->lock);
+	return result;
+}
+
 /**
  * ipa3_del_hdr_proc_ctx_by_user() -
  * Remove the specified processing context headers from SW and

+ 9 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_i.h

@@ -578,6 +578,8 @@ enum {
 #define TEMP_BUFF_SIZE	0x300000
 /* XR-IPA uC no. of temp buffers */
 #define NO_OF_BUFFS	0x04
+/* Max number of RTP streams supported */
+#define MAX_STREAMS 4
 
 /* miscellaneous for rmnet_ipa and qmi_service */
 enum ipa_type_mode {
@@ -901,6 +903,7 @@ struct ipa3_hdr_proc_ctx_offset_entry {
  * @type: header processing context type
  * @l2tp_params: L2TP parameters
  * @generic_params: generic proc_ctx params
+ * @rtp_params: ipa rtp proc_ctx params
  * @offset_entry: entry's offset
  * @hdr: the header
  * @cookie: cookie used for validity check
@@ -916,6 +919,7 @@ struct ipa3_hdr_proc_ctx_entry {
 	struct ipa_l2tp_hdr_proc_ctx_params l2tp_params;
 	struct ipa_eogre_hdr_proc_ctx_params eogre_params;
 	struct ipa_eth_II_to_eth_II_ex_procparams generic_params;
+	struct ipa_rtp_hdr_proc_ctx_params rtp_params;
 	struct ipa3_hdr_proc_ctx_offset_entry *offset_entry;
 	struct ipa3_hdr_entry *hdr;
 	u32 ref_cnt;
@@ -1123,6 +1127,7 @@ struct ipa3_ep_context {
 	u32 dflt_flt6_rule_hdl;
 	u32 dl_flt4_rule_hdl;
 	u32 dl_flt6_rule_hdl;
+	u32 rtp_flt4_rule_hdls[MAX_STREAMS];
 	bool skip_ep_cfg;
 	bool keep_ipa_awake;
 	struct ipa3_wlan_stats wstats;
@@ -2435,6 +2440,10 @@ struct ipa3_context {
 	bool ipa_wdi_opt_dpath;
 	bool ipa_xr_wdi_flt_rsv_status;
 	u8 rtp_stream_id_cnt;
+	u32 rtp_proc_hdls[MAX_STREAMS];
+	u32 rtp_rt4_tbl_hdls[MAX_STREAMS];
+	u32 rtp_rt4_tbl_idxs[MAX_STREAMS];
+	u32 rtp_rt4_rule_hdls[MAX_STREAMS];
 	bool ipa_endp_delay_wa;
 	bool lan_coal_enable;
 	bool ipa_fltrt_not_hashable;

+ 352 - 7
drivers/platform/msm/ipa/ipa_v3/ipa_rtp_genl.c

@@ -14,6 +14,8 @@
 #define MAX_STREAM_TYPES 2
 #define MAX_IP_TYPES 2
 
+#define IPA_RTP_RT_TBL_NAME "ipa_rtp_rt"
+
 #define IPA_RTP_GENL_OP(_cmd, _func)			\
 	{						\
 		.cmd	= _cmd,				\
@@ -62,6 +64,334 @@ struct genl_family ipa_rtp_genl_family = {
 	.n_ops   = ARRAY_SIZE(ipa_rtp_genl_ops),
 };
 
+static enum ipa_hdr_proc_type ipa3_get_rtp_hdr_proc_type(u32 stream_id)
+{
+	enum ipa_hdr_proc_type rtp_hdr_proc_type = IPA_HDR_PROC_MAX;
+
+	switch (stream_id) {
+	case 0:
+		rtp_hdr_proc_type = IPA_HDR_PROC_RTP_METADATA_STREAM0;
+		break;
+	case 1:
+		rtp_hdr_proc_type = IPA_HDR_PROC_RTP_METADATA_STREAM1;
+		break;
+	case 2:
+		rtp_hdr_proc_type = IPA_HDR_PROC_RTP_METADATA_STREAM2;
+		break;
+	case 3:
+		rtp_hdr_proc_type = IPA_HDR_PROC_RTP_METADATA_STREAM3;
+		break;
+	default:
+		IPAERR("invalid stream_id %u params\n", stream_id);
+		break;
+	}
+	return rtp_hdr_proc_type;
+}
+
+static enum ipa_client_type ipa3_get_rtp_dst_pipe(u32 stream_id)
+{
+	enum ipa_client_type dst_pipe_num = IPA_CLIENT_MAX;
+
+	switch (stream_id) {
+	case 0:
+		dst_pipe_num = IPA_CLIENT_UC_RTP1_CONS;
+		break;
+	case 1:
+		dst_pipe_num = IPA_CLIENT_UC_RTP2_CONS;
+		break;
+	case 2:
+		dst_pipe_num = IPA_CLIENT_UC_RTP3_CONS;
+		break;
+	case 3:
+		dst_pipe_num = IPA_CLIENT_UC_RTP4_CONS;
+		break;
+	default:
+		IPAERR("invalid stream_id %u params\n", stream_id);
+		break;
+	}
+	return dst_pipe_num;
+}
+
+static int ipa3_rtp_del_flt_rule(u32 stream_id)
+{
+	int rc = 0;
+	int ipa_ep_idx;
+	struct ipa3_ep_context *ep;
+	struct ipa_ioc_del_flt_rule *rtp_del_flt_rule = NULL;
+
+	IPADBG("Deleting rtp filter rules of stream_id: %u\n", stream_id);
+	rtp_del_flt_rule = kzalloc(sizeof(*rtp_del_flt_rule) +
+		1 * sizeof(struct ipa_flt_rule_del), GFP_KERNEL);
+	if (!rtp_del_flt_rule) {
+		IPAERR("failed at kzalloc of rtp_del_flt_rule\n");
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
+	ep = &ipa3_ctx->ep[ipa_ep_idx];
+	if (ep->rtp_flt4_rule_hdls[stream_id]) {
+		rtp_del_flt_rule->commit = 1;
+		rtp_del_flt_rule->ip = 0;
+		rtp_del_flt_rule->num_hdls = 1;
+		rtp_del_flt_rule->hdl[0].hdl = ep->rtp_flt4_rule_hdls[stream_id];
+		if (ipa3_del_flt_rule(rtp_del_flt_rule) || rtp_del_flt_rule->hdl[0].status) {
+			IPAERR("failed to del rtp_flt_rule\n");
+			kfree(rtp_del_flt_rule);
+			rc = -EPERM;
+			return rc;
+		}
+		ep->rtp_flt4_rule_hdls[stream_id] = 0;
+	}
+
+	kfree(rtp_del_flt_rule);
+	return rc;
+}
+
+static int ipa3_rtp_del_rt_rule(u32 stream_id)
+{
+	int rc = 0;
+	struct ipa_ioc_del_rt_rule *rtp_del_rt_rule = NULL;
+
+	IPADBG("Deleting rtp route rules of stream_id: %u\n", stream_id);
+	rtp_del_rt_rule = kzalloc(sizeof(*rtp_del_rt_rule) +
+		1 * sizeof(struct ipa_rt_rule_del), GFP_KERNEL);
+	if (!rtp_del_rt_rule) {
+		IPAERR("failed at kzalloc of rtp_del_rt_rule\n");
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	if (ipa3_ctx->rtp_rt4_rule_hdls[stream_id]) {
+		rtp_del_rt_rule->commit = 1;
+		rtp_del_rt_rule->ip = 0;
+		rtp_del_rt_rule->num_hdls = 1;
+		rtp_del_rt_rule->hdl[0].hdl = ipa3_ctx->rtp_rt4_rule_hdls[stream_id];
+		if (ipa3_del_rt_rule(rtp_del_rt_rule) || rtp_del_rt_rule->hdl[0].status) {
+			IPAERR("failed to del rtp_rt_rule\n");
+			kfree(rtp_del_rt_rule);
+			rc = -EPERM;
+			return rc;
+		}
+		ipa3_ctx->rtp_rt4_rule_hdls[stream_id] = -1;
+	}
+
+	kfree(rtp_del_rt_rule);
+	return rc;
+}
+
+static int ipa3_rtp_del_hdr_proc_ctx(u32 stream_id)
+{
+	int buf_size, rc = 0;
+
+	struct ipa_ioc_del_hdr_proc_ctx *rtp_del_proc_ctx = NULL;
+	struct ipa_hdr_proc_ctx_del *rtp_del_proc_ctx_entry = NULL;
+
+	IPADBG("Deleting rtp hdr proc ctx of stream_id: %u\n", stream_id);
+	buf_size = (sizeof(struct ipa_ioc_del_hdr_proc_ctx) +
+		(sizeof(struct ipa_hdr_proc_ctx_del)));
+	rtp_del_proc_ctx = kzalloc(buf_size, GFP_KERNEL);
+	if (!rtp_del_proc_ctx) {
+		IPAERR("failed at kzalloc of rtp_del_proc_ctx\n");
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	if (ipa3_ctx->rtp_proc_hdls[stream_id]) {
+		rtp_del_proc_ctx_entry = &(rtp_del_proc_ctx->hdl[0]);
+		rtp_del_proc_ctx->commit = 1;
+		rtp_del_proc_ctx->num_hdls = 1;
+		rtp_del_proc_ctx->hdl[0].hdl = ipa3_ctx->rtp_proc_hdls[stream_id];
+		if (ipa3_del_hdr_proc_ctx(rtp_del_proc_ctx) || rtp_del_proc_ctx->hdl[0].status) {
+			IPAERR("failed to del rtp proc ctx hdl\n");
+			kfree(rtp_del_proc_ctx);
+			rc = -EPERM;
+			return rc;
+		}
+		ipa3_ctx->rtp_proc_hdls[stream_id] = -1;
+	}
+
+	kfree(rtp_del_proc_ctx);
+	return rc;
+}
+
+int ipa3_install_rtp_hdr_proc_rt_flt_rules(struct traffic_tuple_info *tuple_info, u32 stream_id)
+{
+	int rc = 0;
+	int buf_size;
+	static const int num_of_proc_ctx = 1;
+	struct ipa_ioc_add_hdr_proc_ctx *rtp_proc_ctx = NULL;
+	struct ipa_hdr_proc_ctx_add *rtp_proc_ctx_entry = NULL;
+	struct ipa_rtp_hdr_proc_ctx_params rtp_params;
+
+	struct ipa_ioc_add_rt_rule *rtp_rt_rule = NULL;
+	struct ipa_rt_rule_add *rtp_rt_rule_entry = NULL;
+	struct ipa3_rt_tbl *entry = NULL;
+
+	struct ipa3_ep_context *ep;
+	struct ipa_ioc_add_flt_rule *rtp_flt_rule = NULL;
+	struct ipa_flt_rule_add *rtp_flt_rule_entry = NULL;
+	int ipa_ep_idx = 0;
+
+	IPADBG("adding rtp proc ctx entry\n");
+	buf_size = (sizeof(struct ipa_ioc_add_hdr_proc_ctx) +
+		(num_of_proc_ctx * sizeof(struct ipa_hdr_proc_ctx_add)));
+
+	rtp_proc_ctx = kzalloc(buf_size, GFP_KERNEL);
+	if (!rtp_proc_ctx) {
+		IPAERR("failed at kzalloc of rtp_proc_ctx\n");
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	memset(rtp_proc_ctx, 0, sizeof(*rtp_proc_ctx));
+
+	rtp_proc_ctx_entry = &(rtp_proc_ctx->proc_ctx[0]);
+	rtp_proc_ctx->commit = true;
+	rtp_proc_ctx->num_proc_ctxs = num_of_proc_ctx;
+	rtp_proc_ctx_entry->proc_ctx_hdl = -1;
+	rtp_proc_ctx_entry->status       = -1;
+	if (ipa3_get_rtp_hdr_proc_type(stream_id) >= IPA_HDR_PROC_MAX) {
+		IPAERR("invalid stream_id %u params\n", stream_id);
+		rc = -EPERM;
+		goto free_rtp_proc_ctx;
+	}
+	rtp_proc_ctx_entry->type  = ipa3_get_rtp_hdr_proc_type(stream_id);
+	rtp_params.hdr_add_param.input_ip_version = tuple_info->ip_type;
+
+	if (ipa3_add_rtp_hdr_proc_ctx(rtp_proc_ctx, rtp_params, false)
+					|| rtp_proc_ctx_entry->status) {
+		IPAERR("failed to add rtp hdr proc ctx hdl\n");
+		rc = -EPERM;
+		goto free_rtp_proc_ctx;
+	}
+
+	IPADBG("rtp proc ctx hdl = %u\n", rtp_proc_ctx_entry->proc_ctx_hdl);
+	ipa3_ctx->rtp_proc_hdls[stream_id] = rtp_proc_ctx_entry->proc_ctx_hdl;
+
+	IPADBG("adding rtp route rule entry\n");
+
+	rtp_rt_rule = kzalloc(sizeof(struct ipa_ioc_add_rt_rule) + 1 *
+			sizeof(struct ipa_rt_rule_add), GFP_KERNEL);
+	if (!rtp_rt_rule) {
+		IPAERR("failed at kzalloc of rtp_rt_rule\n");
+		rc = -ENOMEM;
+		goto free_rtp_proc_ctx;
+	}
+
+	memset(rtp_rt_rule, 0, sizeof(*rtp_rt_rule));
+	rtp_rt_rule->num_rules = 1;
+	rtp_rt_rule->commit = 1;
+	rtp_rt_rule->ip = tuple_info->ip_type;
+	strscpy(rtp_rt_rule->rt_tbl_name, IPA_RTP_RT_TBL_NAME,
+		IPA_RESOURCE_NAME_MAX);
+
+	rtp_rt_rule_entry = &rtp_rt_rule->rules[0];
+	rtp_rt_rule_entry->at_rear = 1;
+	if (ipa3_get_rtp_dst_pipe(stream_id) >= IPA_CLIENT_MAX) {
+		IPAERR("invalid stream_id %u params\n", stream_id);
+		rc = -EPERM;
+		goto free_rtp_rt_rule;
+	}
+	rtp_rt_rule_entry->rule.dst = ipa3_get_rtp_dst_pipe(stream_id);
+	rtp_rt_rule_entry->rule.hdr_hdl = 0;
+	rtp_rt_rule_entry->rule.hdr_proc_ctx_hdl = ipa3_ctx->rtp_proc_hdls[stream_id];
+	rtp_rt_rule_entry->rule.hashable = 1;
+	rtp_rt_rule_entry->rule.retain_hdr = 1;
+	rtp_rt_rule_entry->status = -1;
+
+	if (ipa_add_rt_rule(rtp_rt_rule) || rtp_rt_rule_entry->status) {
+		IPAERR("fail to add rtp_rt_rule\n");
+		rc = -EPERM;
+		goto free_rtp_rt_rule;
+	}
+
+	ipa3_ctx->rtp_rt4_rule_hdls[stream_id] = rtp_rt_rule_entry->rt_rule_hdl;
+	rtp_rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
+	entry = __ipa3_find_rt_tbl(tuple_info->ip_type, rtp_rt_rule->rt_tbl_name);
+	ipa3_ctx->rtp_rt4_tbl_idxs[stream_id] = entry->idx;
+	ipa3_ctx->rtp_rt4_tbl_hdls[stream_id] = entry->id;
+
+	IPADBG("rtp rt rule hdl %d\n", ipa3_ctx->rtp_rt4_rule_hdls[stream_id]);
+	IPADBG("rtp rt tbl idx %d\n", ipa3_ctx->rtp_rt4_tbl_idxs[stream_id]);
+	IPADBG("rtp rt tbl hdl %d\n", ipa3_ctx->rtp_rt4_tbl_hdls[stream_id]);
+
+	IPADBG("adding rtp flt rules for %d\n", ipa_ep_idx);
+
+	rtp_flt_rule = kzalloc(sizeof(*rtp_flt_rule) +
+		1 * sizeof(struct ipa_flt_rule_add), GFP_KERNEL);
+	if (!rtp_flt_rule) {
+		IPAERR("failed at kzalloc of rtp_flt_rule\n");
+		rc = -ENOMEM;
+		goto free_rtp_rt_rule;
+	}
+
+	memset(rtp_flt_rule, 0, sizeof(*rtp_flt_rule));
+	ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
+	ep = &ipa3_ctx->ep[ipa_ep_idx];
+
+	rtp_flt_rule->commit = 1;
+	rtp_flt_rule->ip = tuple_info->ip_type;
+	rtp_flt_rule->ep = IPA_CLIENT_WLAN2_PROD;
+	rtp_flt_rule->num_rules = 1;
+	rtp_flt_rule->rules[0].at_rear = 1;
+	rtp_flt_rule_entry = &rtp_flt_rule->rules[0];
+
+	rtp_flt_rule_entry->rule.hashable = 1;
+	rtp_flt_rule_entry->status =  -1;
+	rtp_flt_rule_entry->rule.action = IPA_PASS_TO_ROUTING;
+	rtp_flt_rule_entry->rule.rt_tbl_hdl = ipa3_ctx->rtp_rt4_tbl_hdls[stream_id];
+	rtp_flt_rule_entry->rule.rt_tbl_idx = ipa3_ctx->rtp_rt4_tbl_idxs[stream_id];
+
+	rtp_flt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
+	rtp_flt_rule_entry->rule.attrib.u.v4.dst_addr = tuple_info->ip_info.ipv4.dst_ip;
+	rtp_flt_rule_entry->rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF;
+	rtp_flt_rule_entry->rule.attrib.u.v4.src_addr = tuple_info->ip_info.ipv4.src_ip;
+	rtp_flt_rule_entry->rule.attrib.u.v4.protocol = tuple_info->ip_info.ipv4.protocol;
+	rtp_flt_rule_entry->rule.attrib.src_port = tuple_info->ip_info.ipv4.src_port_number;
+	rtp_flt_rule_entry->rule.attrib.dst_port = tuple_info->ip_info.ipv4.dst_port_number;
+
+	rtp_flt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
+	rtp_flt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+	rtp_flt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
+	rtp_flt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_SRC_PORT;
+	rtp_flt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_PORT;
+
+	if (ipa3_add_flt_rule(rtp_flt_rule) || rtp_flt_rule_entry->status) {
+		IPAERR("fail to add rtp_flt_rule\n");
+		rc = -EPERM;
+		goto free_rtp_flt_rule;
+	}
+
+	ep->rtp_flt4_rule_hdls[stream_id] = rtp_flt_rule->rules[0].flt_rule_hdl;
+	IPADBG("rtp flt rule hdl is %u\n", ep->rtp_flt4_rule_hdls[stream_id]);
+
+free_rtp_flt_rule:
+	kfree(rtp_flt_rule);
+free_rtp_rt_rule:
+	if (rc && !rtp_rt_rule_entry->status)
+		ipa3_rtp_del_rt_rule(stream_id);
+	kfree(rtp_rt_rule);
+free_rtp_proc_ctx:
+	if (rc && !rtp_proc_ctx_entry->status)
+		ipa3_rtp_del_hdr_proc_ctx(stream_id);
+	kfree(rtp_proc_ctx);
+	return rc;
+}
+
+int ipa3_delete_rtp_hdr_proc_rt_flt_rules(u32 stream_id)
+{
+	int rc = 0;
+
+	if (ipa3_rtp_del_flt_rule(stream_id) ||
+		ipa3_rtp_del_rt_rule(stream_id) ||
+		ipa3_rtp_del_hdr_proc_ctx(stream_id)) {
+		IPAERR("failed to delete rtp hdr proc rt flt rules\n");
+		rc = -EPERM;
+	}
+	return rc;
+}
+
 int ipa_rtp_send_tuple_info_resp(struct genl_info *info,
 			      struct assign_stream_id *tuple_info_resp)
 {
@@ -121,6 +451,7 @@ int ipa_rtp_tuple_info_req_hdlr(struct sk_buff *skb_2,
 	struct nlattr *na;
 	struct traffic_tuple_info tuple_info_req;
 	struct assign_stream_id tuple_info_resp;
+	struct remove_bitstream_buffers rmv_sid_req;
 	int is_req_valid = 0, i = 0;
 	int stream_id_available = 0, rc = -1;
 
@@ -191,7 +522,6 @@ int ipa_rtp_tuple_info_req_hdlr(struct sk_buff *skb_2,
 	IPADBG_LOW("dst_ip is %u\n", tuple_info_req.ip_info.ipv4.dst_ip);
 	IPADBG_LOW("protocol is %u\n", tuple_info_req.ip_info.ipv4.protocol);
 
-	/* Call IPA driver/uC tuple info API's here */
 	memset(&tuple_info_resp, 0, sizeof(tuple_info_resp));
 
 	for (i = 0; i < MAX_STREAMS; i++) {
@@ -208,10 +538,22 @@ int ipa_rtp_tuple_info_req_hdlr(struct sk_buff *skb_2,
 		return rc;
 	}
 
+	/* Call IPA driver/uC tuple info API's here */
+	if (ipa3_install_rtp_hdr_proc_rt_flt_rules(&tuple_info_req, tuple_info_resp.stream_id) ||
+		ipa3_tuple_info_cmd_to_wlan_uc(&tuple_info_req, tuple_info_resp.stream_id)) {
+		IPAERR("failed to install hdr proc and flt rules or filters at WLAN\n");
+		return rc;
+	}
+
 	if (is_req_valid &&
-		ipa_rtp_send_tuple_info_resp(info, &tuple_info_resp))
+		ipa_rtp_send_tuple_info_resp(info, &tuple_info_resp)) {
+		IPAERR("failed in sending stream_id response\n");
+		memset(&rmv_sid_req, 0, sizeof(rmv_sid_req));
+		rmv_sid_req.stream_id = tuple_info_resp.stream_id;
+		ipa3_uc_send_remove_stream_cmd(&rmv_sid_req);
+		ipa3_delete_rtp_hdr_proc_rt_flt_rules(rmv_sid_req.stream_id);
 		si[tuple_info_resp.stream_id] = 0;
-	else
+	} else
 		rc = 0;
 
 	IPADBG("Exit\n");
@@ -383,7 +725,7 @@ int ipa_rtp_smmu_unmap_buff_req_hdlr(struct sk_buff *skb_2,
 			unmap_buffer_req.buff_info[i].meta_buff_size);
 	}
 
-	/* Call IPA driver/uC tuple info API's here */
+	/* Call IPA driver/uC API's here */
 	if (is_req_valid)
 		rc = ipa3_unmap_buff_from_device_addr(&unmap_buffer_req);
 
@@ -526,9 +868,12 @@ int ipa_rtp_rmv_stream_id_req_hdlr(struct sk_buff *skb_2,
 		return rc;
 	}
 
-	/* Call IPA driver/uC tuple info API's here */
-	if (is_req_valid)
-		rc = ipa3_uc_send_remove_stream_cmd(&rmv_sid_req);
+	/* Call IPA driver/uC API's here */
+	if (is_req_valid && ipa3_uc_send_remove_stream_cmd(&rmv_sid_req)
+		&& ipa3_delete_rtp_hdr_proc_rt_flt_rules(rmv_sid_req.stream_id)) {
+		IPAERR("failed in removing stream-id, deleting hdr proc and flt rules\n");
+		return rc;
+	}
 
 	si[rmv_sid_req.stream_id] = 0;
 	ipa3_ctx->rtp_stream_id_cnt--;

+ 2 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_rtp_genl.h

@@ -259,6 +259,8 @@ enum {
 
 
 /* Function Prototypes */
+int ipa3_install_rtp_hdr_proc_rt_flt_rules(struct traffic_tuple_info *tuple_info, u32 stream_id);
+int ipa3_delete_rtp_hdr_proc_rt_flt_rules(u32 stream_id);
 
 /*
  * This handler will be invoked when IPA C2 sends TUPLE

+ 53 - 2
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/debugfs.h>
@@ -17,6 +17,18 @@
 		(p_cmd_data)->member = (p_params)->member;\
 	}
 
+#define IPA_GET_UCP_RTP_CMD(type) \
+	do {			  \
+		if (type == IPA_HDR_PROC_RTP_METADATA_STREAM0) \
+			type = IPA_HDR_UCP_RTP_METADATA_STREAM0; \
+		if (type == IPA_HDR_PROC_RTP_METADATA_STREAM1) \
+			type = IPA_HDR_UCP_RTP_METADATA_STREAM1; \
+		if (type == IPA_HDR_PROC_RTP_METADATA_STREAM2) \
+			type = IPA_HDR_UCP_RTP_METADATA_STREAM2; \
+		if (type == IPA_HDR_PROC_RTP_METADATA_STREAM3) \
+			type = IPA_HDR_UCP_RTP_METADATA_STREAM3; \
+	} while (0)
+
 struct ipahal_context *ipahal_ctx;
 
 static const char *ipahal_imm_cmd_name_to_str[IPA_IMM_CMD_MAX] = {
@@ -2048,6 +2060,7 @@ static void ipahal_cp_hdr_to_hw_buff_v3(void *const base, u32 offset,
  * @l2tp_params: l2tp parameters
  * @eogre_params: eogre parameters
  * @generic_params: generic proc_ctx params
+ * @rtp_params: rtp proc_ctx params
  * @is_64: Indicates whether header base address/dma base address is 64 bit.
  */
 static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
@@ -2057,6 +2070,7 @@ static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
 		struct ipa_l2tp_hdr_proc_ctx_params *l2tp_params,
 		struct ipa_eogre_hdr_proc_ctx_params *eogre_params,
 		struct ipa_eth_II_to_eth_II_ex_procparams *generic_params,
+		struct ipa_rtp_hdr_proc_ctx_params *rtp_params,
 		bool is_64)
 {
 	u64 hdr_addr;
@@ -2287,6 +2301,33 @@ static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
 		ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
 		ctx->end.length = 0;
 		ctx->end.value = 0;
+	} else if ((type == IPA_HDR_PROC_RTP_METADATA_STREAM0) ||
+		(type == IPA_HDR_PROC_RTP_METADATA_STREAM1) ||
+		(type == IPA_HDR_PROC_RTP_METADATA_STREAM2) ||
+		(type == IPA_HDR_PROC_RTP_METADATA_STREAM3)) {
+		struct ipa_hw_hdr_proc_ctx_rtp_hdr_cmd_seq *ctx =
+			(struct ipa_hw_hdr_proc_ctx_rtp_hdr_cmd_seq *)
+			(base + offset);
+		ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
+		ctx->hdr_add.tlv.length = 0;
+		ctx->hdr_add.tlv.value = 0;
+		hdr_addr = hdr_base_addr + offset_entry->offset;
+		IPAHAL_DBG("header address 0x%llx length %d\n",
+				   hdr_addr, ctx->hdr_add.tlv.value);
+		IPAHAL_CP_PROC_CTX_HEADER_UPDATE(
+			ctx->hdr_add.hdr_addr,
+			ctx->hdr_add.hdr_addr_hi, hdr_addr);
+		if (!is_64)
+			ctx->hdr_add.hdr_addr_hi = 0;
+		ctx->rtp_params.tlv.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
+		ctx->rtp_params.tlv.length = 1;
+		IPA_GET_UCP_RTP_CMD(type);
+		ctx->rtp_params.tlv.value = type;
+		ctx->rtp_params.rtp_params.input_ip_version =
+					rtp_params->hdr_add_param.input_ip_version;
+		ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
+		ctx->end.length = 0;
+		ctx->end.value = 0;
 	} else {
 		struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *ctx;
 
@@ -2379,6 +2420,13 @@ static int ipahal_get_proc_ctx_needed_len_v3(enum ipa_hdr_proc_type type)
 		ret =
 		sizeof(struct ipa_hw_hdr_proc_ctx_remove_eogre_hdr_cmd_seq);
 		break;
+	case IPA_HDR_PROC_RTP_METADATA_STREAM0:
+	case IPA_HDR_PROC_RTP_METADATA_STREAM1:
+	case IPA_HDR_PROC_RTP_METADATA_STREAM2:
+	case IPA_HDR_PROC_RTP_METADATA_STREAM3:
+		ret =
+		sizeof(struct ipa_hw_hdr_proc_ctx_rtp_hdr_cmd_seq);
+		break;
 	default:
 		/* invalid value to make sure failure */
 		IPAHAL_ERR_RL("invalid ipa_hdr_proc_type %d\n", type);
@@ -2405,6 +2453,7 @@ struct ipahal_hdr_funcs {
 			struct ipa_eogre_hdr_proc_ctx_params *eogre_params,
 			struct ipa_eth_II_to_eth_II_ex_procparams
 			*generic_params,
+			struct ipa_rtp_hdr_proc_ctx_params *rtp_params,
 			bool is_64);
 
 	int (*ipahal_get_proc_ctx_needed_len)(enum ipa_hdr_proc_type type);
@@ -2471,6 +2520,7 @@ void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *const hdr,
  * @l2tp_params: l2tp parameters
  * @eogre_params: eogre parameters
  * @generic_params: generic proc_ctx params
+ * @rtp_params: rtp proc_ctx params
  * @is_64: Indicates whether header base address/dma base address is 64 bit.
  */
 int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
@@ -2479,6 +2529,7 @@ int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
 		struct ipa_l2tp_hdr_proc_ctx_params *l2tp_params,
 		struct ipa_eogre_hdr_proc_ctx_params *eogre_params,
 		struct ipa_eth_II_to_eth_II_ex_procparams *generic_params,
+		struct ipa_rtp_hdr_proc_ctx_params *rtp_params,
 		bool is_64)
 {
 	IPAHAL_DBG(
@@ -2494,7 +2545,7 @@ int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
 
 	return hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff(type, base, offset,
 			hdr_len, hdr_base_addr, offset_entry, l2tp_params,
-			eogre_params, generic_params, is_64);
+			eogre_params, generic_params, rtp_params, is_64);
 }
 
 /*

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

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _IPAHAL_H_
@@ -804,6 +804,7 @@ void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *hdr, u32 hdr_len);
  * @l2tp_params: l2tp parameters
  * @eogre_params: eogre parameters
  * @generic_params: generic proc_ctx params
+ * @rtp_params: rtp proc_ctx params
  * @is_64: Indicates whether header base address/dma base address is 64 bit.
  */
 int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
@@ -813,6 +814,7 @@ int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
 		struct ipa_l2tp_hdr_proc_ctx_params *l2tp_params,
 		struct ipa_eogre_hdr_proc_ctx_params *eogre_params,
 		struct ipa_eth_II_to_eth_II_ex_procparams *generic_params,
+		struct ipa_rtp_hdr_proc_ctx_params *rtp_params,
 		bool is_64);
 
 /*

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

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _IPAHAL_I_H_
@@ -1126,6 +1127,10 @@ union ipa_pkt_status_hw_v5_5 {
 /* Headers and processing context H/W structures and definitions */
 
 /* uCP command numbers */
+#define IPA_HDR_UCP_RTP_METADATA_STREAM0    0
+#define IPA_HDR_UCP_RTP_METADATA_STREAM1    1
+#define IPA_HDR_UCP_RTP_METADATA_STREAM2    2
+#define IPA_HDR_UCP_RTP_METADATA_STREAM3    3
 #define IPA_HDR_UCP_802_3_TO_802_3          6
 #define IPA_HDR_UCP_802_3_TO_ETHII          7
 #define IPA_HDR_UCP_ETHII_TO_802_3          8
@@ -1179,6 +1184,11 @@ struct ipa_hw_hdr_proc_ctx_hdr_add {
 	u32 hdr_addr_hi;
 };
 
+struct ipa_hw_hdr_proc_ctx_rtp_add_hdr {
+	struct ipa_hw_hdr_proc_ctx_tlv tlv;
+	struct ipa_rtp_header_add_procparams rtp_params;
+};
+
 /**
  * struct ipa_hw_hdr_proc_ctx_l2tp_add_hdr -
  * HW structure of IPA processing context - add l2tp header tlv
@@ -1334,4 +1344,17 @@ struct ipa_hw_hdr_proc_ctx_remove_eogre_hdr_cmd_seq {
 	struct ipa_hw_hdr_proc_ctx_tlv end;
 };
 
+/**
+ * struct ipa_hw_hdr_proc_ctx_rtp_hdr_cmd_seq -
+ * IPA processing context header - process command sequence
+ * @hdr_add: add header command
+ * @rtp_params: rtp params for header addition
+ * @end: tlv end command (cmd.type must be 0)
+ */
+struct ipa_hw_hdr_proc_ctx_rtp_hdr_cmd_seq {
+	struct ipa_hw_hdr_proc_ctx_hdr_add hdr_add;
+	struct ipa_hw_hdr_proc_ctx_rtp_add_hdr rtp_params;
+	struct ipa_hw_hdr_proc_ctx_tlv end;
+};
+
 #endif /* _IPAHAL_I_H_ */