Browse Source

dataipa: adding new xr wlan filter reserve/install API's

changes to enable xr-wdi-opt-dpath and handle wlan filter
reserve/install/remove API's and it cb's accordingly.

Change-Id: I1c11e15d3b2af89318bc29d6afebdf6797cdd039
Signed-off-by: Prasad Arepalli <[email protected]>
Prasad Arepalli 1 năm trước cách đây
mục cha
commit
554231f83f

+ 59 - 1
drivers/platform/msm/include/linux/ipa_wdi3.h

@@ -2,7 +2,7 @@
 /*
  * Copyright (c) 2018 - 2021, The Linux Foundation. All rights reserved.
  *
- * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _IPA_WDI3_H_
@@ -447,6 +447,43 @@ int ipa_wdi_opt_dpath_remove_all_filter_req(
 		struct ipa_wlan_opt_dp_remove_all_filter_req_msg_v01 *req,
 		struct ipa_wlan_opt_dp_remove_all_filter_resp_msg_v01 *resp);
 
+/**
+ * ipa_xr_wdi_opt_dpath_rsrv_filter_req - Client should call this function to
+ * send filter reservation request to wlan
+ *
+ *
+ * @Return 0 on success, negative on failure
+ */
+int ipa_xr_wdi_opt_dpath_rsrv_filter_req(void);
+
+/**
+ * ipa_xr_wdi_opt_dpath_add_filter_req - Client should call this function to
+ * send filter add request to wlan
+ *
+ *
+ * @Return 0 on success, negative on failure
+ */
+int ipa_xr_wdi_opt_dpath_add_filter_req(struct ipa_wdi_opt_dpath_flt_add_cb_params *req,
+		u32 stream_id);
+
+/**
+ * ipa_xr_wdi_opt_dpath_remove_filter_req - Client should call this function to
+ * send filter remove request to wlan
+ *
+ *
+ * @Return 0 on success, negative on failure
+ */
+int ipa_xr_wdi_opt_dpath_remove_filter_req(u32 stream_id);
+
+/**
+ * ipa_xr_wdi_opt_dpath_remove_all_filter_req - Client should call this function to
+ * send release reservation request to wlan
+ *
+ *
+ * @Return 0 on success, negative on failure
+ */
+int ipa_xr_wdi_opt_dpath_remove_all_filter_req(void);
+
 /** ipa_get_wdi_version - return wdi version
  *
  * @Return void
@@ -941,6 +978,27 @@ static int ipa_wdi_opt_dpath_remove_all_filter_req(
 	return -EPERM;
 }
 
+static int ipa_xr_wdi_opt_dpath_rsrv_filter_req(void)
+{
+	return -EPERM;
+}
+
+static int ipa_xr_wdi_opt_dpath_add_filter_req(struct ipa_wdi_opt_dpath_flt_add_cb_params *req,
+		u32 stream_id)
+{
+	return -EPERM;
+}
+
+static int ipa_xr_wdi_opt_dpath_remove_filter_req(u32 stream_id)
+{
+	return -EPERM;
+}
+
+static int ipa_xr_wdi_opt_dpath_remove_all_filter_req(void)
+{
+	return -EPERM;
+}
+
 #endif /* IS_ENABLED(CONFIG_IPA3) */
 
 #endif /* _IPA_WDI3_H_ */

+ 211 - 1
drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c

@@ -2,12 +2,14 @@
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  *
- * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include "ipa_wdi3.h"
 #include <linux/msm_ipa.h>
 #include <linux/string.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
 #include "ipa_common_i.h"
 #include "ipa_pm.h"
 #include "ipa_i.h"
@@ -48,6 +50,20 @@
 #define DEFAULT_INSTANCE_ID (-1)
 #define INVALID_INSTANCE_ID (-2)
 
+/**
+ * Time delay value for delayed queue.
+ */
+#define QUEUE_DELAY_TIME	100
+
+/**
+ * No. of filters reserving at wlan for IPA-XR usecase.
+ */
+#define NO_OF_FILTERS		4
+
+static void ipa_xr_wdi_opt_dpath_rsrv_filter_wq_handler(struct work_struct *work);
+static struct workqueue_struct *wlan_flt_rsrv_wq = NULL;
+static DECLARE_DELAYED_WORK(wlan_flt_rsrv_handle, ipa_xr_wdi_opt_dpath_rsrv_filter_wq_handler);
+
 struct ipa_wdi_intf_info {
 	char netdev_name[IPA_RESOURCE_NAME_MAX];
 	u8 hdr_len;
@@ -63,6 +79,7 @@ struct ipa_wdi_opt_dpath_info {
 	u32 hdr_len;
 	atomic_t rsrv_req;
 	atomic_t is_opt_dp_cb_registered;
+	atomic_t is_xr_opt_dp_cb_registered;
 	void *priv;
 	int ipa_ep_idx_tx, ipa_ep_idx_rx;
 	u32 ipa_pm_hdl;
@@ -85,6 +102,13 @@ struct ipa_wdi_context {
 	ipa_wdi_meter_notifier_cb wdi_notify;
 #endif
 };
+
+struct ipa_wdi_opt_dpath_add_flt_handle {
+	uint64_t filter_handle;
+};
+
+struct ipa_wdi_opt_dpath_add_flt_handle  add_flt_hndl[4];
+
 /**
  * opt_dpath_info contains fn callbacks which are set by WLAN context and
  * accessed by QMI context. To avoid race condition between these 2,
@@ -850,6 +874,23 @@ int ipa_wdi_enable_pipes_per_inst(ipa_wdi_hdl_t hdl)
 		}
 	}
 
+	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_XR) {
+		if (wlan_flt_rsrv_wq == NULL) {
+			wlan_flt_rsrv_wq = create_singlethread_workqueue("wlan_flt_rsrv_wq");
+			if (wlan_flt_rsrv_wq) {
+				IPA_WDI_ERR("failed to create wq\n");
+				return 0;
+			}
+
+			ret = queue_delayed_work(wlan_flt_rsrv_wq, &wlan_flt_rsrv_handle,
+				msecs_to_jiffies(QUEUE_DELAY_TIME));
+			if (ret) {
+				IPA_WDI_ERR("failed to queue delayed wq\n");
+				return 0;
+			}
+		}
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL(ipa_wdi_enable_pipes_per_inst);
@@ -1056,6 +1097,12 @@ int ipa_wdi_opt_dpath_register_flt_cb_per_inst(
 	opt_dpath_info[hdl].flt_add_cb = flt_add_cb;
 	opt_dpath_info[hdl].flt_rem_cb = flt_rem_cb;
 
+	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_XR) {
+		IPADBG("wdi_xr_opt_dpath_register_flt_cb: callbacks registered.\n");
+		atomic_set(&opt_dpath_info[hdl].is_xr_opt_dp_cb_registered, 1);
+		return ret;
+	}
+
 	atomic_set(&opt_dpath_info[hdl].is_opt_dp_cb_registered, 1);
 
 	IPADBG("wdi_opt_dpath_register_flt_cb: callbacks registered.\n");
@@ -1096,6 +1143,11 @@ int ipa_wdi_opt_dpath_notify_flt_rsvd_per_inst
 		return -EPERM;
 	}
 
+	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_XR) {
+		ipa3_ctx->ipa_xr_wdi_flt_rsv_status = is_success;
+		return ret;
+	}
+
 	memset(&ind, 0, sizeof(ind));
 	ind.rsrv_filter_status.result = (is_success == true) ? IPA_QMI_RESULT_SUCCESS_V01:IPA_QMI_RESULT_FAILURE_V01;
 	ind.rsrv_filter_status.error = IPA_QMI_ERR_NONE_V01;
@@ -1130,6 +1182,8 @@ int ipa_wdi_opt_dpath_notify_flt_rlsd_per_inst
 	}
 
 	ret = ipa_pm_deferred_deactivate(ipa_wdi_ctx_list[0]->ipa_pm_hdl);
+	if (ipa3_ctx->platform_type == IPA_PLAT_TYPE_XR)
+		return ret;
 
 	memset(&ind, 0, sizeof(ind));
 	ind.filter_removal_all_status.result =
@@ -1411,6 +1465,157 @@ int ipa_wdi_opt_dpath_remove_all_filter_req(
 EXPORT_SYMBOL(ipa_wdi_opt_dpath_remove_all_filter_req);
 
 
+/**
+ * ipa_xr_wdi_opt_dpath_rsrv_filter_req() - Sends WLAN DP filter reservation
+ * from IPA Driver to WLAN
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ */
+int ipa_xr_wdi_opt_dpath_rsrv_filter_req(void)
+{
+	int ret = 0;
+	struct ipa_wdi_opt_dpath_flt_rsrv_cb_params rsrv_filter_req;
+
+	memset(&rsrv_filter_req, 0, sizeof(struct ipa_wdi_opt_dpath_flt_rsrv_cb_params));
+	if (!atomic_read(&opt_dpath_info[0].is_xr_opt_dp_cb_registered)) {
+		IPAERR("filter reserve cb not registered");
+		return -EPERM;
+	}
+
+	if (opt_dpath_info[0].ipa_ep_idx_tx <= 0 || opt_dpath_info[0].ipa_ep_idx_rx <= 0) {
+		IPA_WDI_ERR("Either TX/RX ep is not configured.\n");
+		return -EPERM;
+	}
+
+	ret = ipa_pm_activate_sync(opt_dpath_info[0].ipa_pm_hdl);
+	if (ret) {
+		IPA_WDI_DBG("fail to activate ipa pm\n");
+		return -EFAULT;
+	}
+
+	rsrv_filter_req.num_filters = NO_OF_FILTERS;
+	ret = opt_dpath_info[0].flt_rsrv_cb(
+			opt_dpath_info[0].priv, &rsrv_filter_req);
+	if (!ret) {
+		atomic_set(&opt_dpath_info[0].rsrv_req, 1);
+	} else {
+		if (ipa_pm_deferred_deactivate(opt_dpath_info[0].ipa_pm_hdl))
+			IPA_WDI_DBG("fail to deactivate ipa pm\n");
+	}
+
+	IPA_WDI_DBG("reserved filter callbacks called.\n");
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ipa_xr_wdi_opt_dpath_rsrv_filter_req);
+
+/**
+ * ipa_xr_wdi_opt_dpath_add_filter_req() - Sends WLAN DP filter info
+ * from IPA Driver to WLAN
+ * @req:	[in] filter add parameters from IPA Driver
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ *
+ */
+
+int ipa_xr_wdi_opt_dpath_add_filter_req(struct ipa_wdi_opt_dpath_flt_add_cb_params *req,
+		u32 stream_id)
+{
+	int ret = 0;
+
+	if (!atomic_read(&opt_dpath_info[0].is_xr_opt_dp_cb_registered)) {
+		IPAERR("filter add cb not registered");
+		return -EPERM;
+	}
+
+	ret =
+		opt_dpath_info[0].flt_add_cb
+			(opt_dpath_info[0].priv, req);
+	add_flt_hndl[stream_id].filter_handle = req->flt_info[0].out_hdl;
+	IPA_WDI_DBG("add filter callbacks called, stream id %d\n", stream_id);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ipa_xr_wdi_opt_dpath_add_filter_req);
+
+/**
+ * ipa_xr_wdi_opt_dpath_remove_filter_req() - Sends WLAN DP filter info
+ * from IPA Driver to WLAN
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ *
+ */
+
+int ipa_xr_wdi_opt_dpath_remove_filter_req(u32 stream_id)
+{
+	int ret = 0;
+	struct ipa_wdi_opt_dpath_flt_rem_cb_params flt_rem_req;
+
+	memset(&flt_rem_req, 0, sizeof(struct ipa_wdi_opt_dpath_flt_rem_cb_params));
+	if (!atomic_read(&opt_dpath_info[0].is_xr_opt_dp_cb_registered)) {
+		IPAERR("filter remove cb not registered");
+		return -EPERM;
+	}
+
+	flt_rem_req.num_tuples = 1;
+	flt_rem_req.hdl_info[0] = add_flt_hndl[stream_id].filter_handle;
+
+	ret = opt_dpath_info[0].flt_rem_cb
+			(opt_dpath_info[0].priv, &flt_rem_req);
+	IPA_WDI_DBG("remove filter callbacks called, stream id %d\n", stream_id);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ipa_xr_wdi_opt_dpath_remove_filter_req);
+
+/**
+ * ipa_xr_wdi_opt_dpath_remove_all_filter_req() - Sends WLAN DP filter info
+ * from IPAs to WLAN
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ *
+ */
+
+int ipa_xr_wdi_opt_dpath_remove_all_filter_req(void)
+{
+	int ret = 0;
+
+	if (!atomic_read(&opt_dpath_info[0].is_xr_opt_dp_cb_registered)) {
+		IPAERR("filter release cb not registered");
+		return -EPERM;
+	}
+
+	if (!atomic_read(&opt_dpath_info[0].rsrv_req)) {
+		IPAERR("Reservation request not sent. IGNORE");
+		return 0;
+	}
+
+	atomic_set(&opt_dpath_info[0].rsrv_req, 0);
+
+	ret = opt_dpath_info[0].flt_rsrv_rel_cb(
+			opt_dpath_info[0].priv);
+
+	if (opt_dpath_info[0].ipa_ep_idx_rx <= 0 || opt_dpath_info[0].ipa_ep_idx_tx <= 0) {
+		IPA_WDI_ERR("Either RX ep or TX ep is not configured.\n");
+		return 0;
+	}
+
+	IPA_WDI_DBG("remove all filter callbacks called.\n");
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ipa_xr_wdi_opt_dpath_remove_all_filter_req);
+
+
+static void ipa_xr_wdi_opt_dpath_rsrv_filter_wq_handler(struct work_struct *work)
+{
+	int res = 0;
+
+	res = ipa_xr_wdi_opt_dpath_rsrv_filter_req();
+	if (!res)
+		IPAERR("Failed to reserve the filters in wlan\n");
+}
+
 /**
  * clean up WDI IPA offload data path
  *
@@ -1450,6 +1655,7 @@ int ipa_wdi_cleanup_per_inst(ipa_wdi_hdl_t hdl)
 	}
 	mutex_destroy(&ipa_wdi_ctx_list[hdl]->lock);
 	kfree(ipa_wdi_ctx_list[hdl]);
+	atomic_set(&opt_dpath_info[hdl].is_xr_opt_dp_cb_registered, 0);
 	atomic_set(&opt_dpath_info[hdl].is_opt_dp_cb_registered, 0);
 	opt_dpath_info[0].ipa_ep_idx_rx = 0;
 	opt_dpath_info[0].ipa_ep_idx_tx = 0;
@@ -1567,6 +1773,10 @@ int ipa_wdi_disconn_pipes_per_inst(ipa_wdi_hdl_t hdl)
 		return -EPERM;
 	}
 
+	if (wlan_flt_rsrv_wq) {
+		destroy_workqueue(wlan_flt_rsrv_wq);
+		wlan_flt_rsrv_wq = NULL;
+	}
 
 	if (ipa_wdi_ctx_list[hdl]->wdi_version >= IPA_WDI_1 &&
 		ipa_wdi_ctx_list[hdl]->wdi_version < IPA_WDI_3 &&

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

@@ -1568,6 +1568,7 @@ enum ipa3_platform_type {
 	IPA_PLAT_TYPE_MDM	= 0,
 	IPA_PLAT_TYPE_MSM	= 1,
 	IPA_PLAT_TYPE_APQ	= 2,
+	IPA_PLAT_TYPE_XR	= 3,
 };
 
 enum ipa3_config_this_ep {
@@ -2426,6 +2427,7 @@ struct ipa3_context {
 	bool ipa_wdi2_over_gsi;
 	bool ipa_wdi3_over_gsi;
 	bool ipa_wdi_opt_dpath;
+	bool ipa_xr_wdi_flt_rsv_status;
 	u8 rtp_stream_id_cnt;
 	bool ipa_endp_delay_wa;
 	bool lan_coal_enable;