Parcourir la source

qcacld-3.0: Add support to Dynamic TDLS enable

Add support to dynamic enabling the TDLS.

Vendor subcmd: QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE

Change-Id: I3b9164ba04a4d9c23d7f580020966c222f8bd359
CRs-Fixed: 3562148
Deeksha Gupta il y a 1 an
Parent
commit
bbece0a981

+ 11 - 0
components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h

@@ -296,6 +296,17 @@ bool ucfg_mlme_get_tdls_prohibited(struct wlan_objmgr_vdev *vdev)
 	return mlme_get_tdls_prohibited(vdev);
 }
 
+/**
+ * ucfg_mlme_get_tdls_chan_switch_prohibited() - get tdls chan switch prohibited
+ * @vdev: vdev pointer
+ *
+ * Return: bool
+ */
+static inline
+bool ucfg_mlme_get_tdls_chan_switch_prohibited(struct wlan_objmgr_vdev *vdev)
+{
+	return mlme_get_tdls_chan_switch_prohibited(vdev);
+}
 #ifdef MULTI_CLIENT_LL_SUPPORT
 /**
  * ucfg_mlme_get_wlm_multi_client_ll_caps() - Get multi client latency level

+ 35 - 0
components/tdls/core/src/wlan_tdls_main.c

@@ -927,6 +927,11 @@ uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
 }
 #endif
 
+bool tdls_check_is_user_tdls_enable(struct tdls_soc_priv_obj *tdls_soc_obj)
+{
+	return tdls_soc_obj->is_user_tdls_enable;
+}
+
 bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
 {
 	struct tdls_vdev_priv_obj *tdls_vdev_obj;
@@ -958,6 +963,11 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
 		goto exit;
 	}
 
+	if (!tdls_check_is_user_tdls_enable(tdls_soc_obj)) {
+		tdls_err("TDLS Disabled from userspace");
+		goto exit;
+	}
+
 	connection_count =
 		policy_mgr_get_connection_count_with_mlo(tdls_soc_obj->soc);
 	sta_count =
@@ -1090,6 +1100,31 @@ set_state:
 		   tdls_soc_obj->tdls_current_mode, tdls_feature_flags);
 }
 
+void tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+			       bool is_user_tdls_enable)
+{
+	QDF_STATUS status;
+	struct tdls_vdev_priv_obj *tdls_vdev_obj;
+	struct tdls_soc_priv_obj *tdls_soc_obj;
+
+	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
+	if (QDF_IS_STATUS_ERROR(status))
+		return;
+
+	status = tdls_get_vdev_objects(vdev, &tdls_vdev_obj, &tdls_soc_obj);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		tdls_err("Failed to get TDLS objects");
+		goto exit;
+	}
+
+	tdls_soc_obj->is_user_tdls_enable = is_user_tdls_enable;
+	tdls_debug("TDLS enable:%d via userspace",
+		   tdls_soc_obj->is_user_tdls_enable);
+
+exit:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
+}
+
 QDF_STATUS
 tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
 {

+ 21 - 2
components/tdls/core/src/wlan_tdls_main.h

@@ -197,6 +197,7 @@ struct tdls_set_state_info {
  * @bss_sta_power_type: bss sta power type
  * @timer_cnt: used for mlo tdls to monitor discovery response
  * @fw_tdls_wideband_capability: bool for tdls wideband fw capability
+ * @is_user_tdls_enable: bool to check whether TDLS enable through userspace
  */
 struct tdls_soc_priv_obj {
 	struct wlan_objmgr_psoc *soc;
@@ -256,6 +257,7 @@ struct tdls_soc_priv_obj {
 #endif
 	qdf_atomic_t timer_cnt;
 	bool fw_tdls_wideband_capability;
+	bool is_user_tdls_enable;
 };
 
 /**
@@ -576,6 +578,15 @@ QDF_STATUS tdls_get_vdev_objects(struct wlan_objmgr_vdev *vdev,
 void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc,
 		      struct wlan_objmgr_vdev *vdev);
 
+/**
+ * tdls_set_user_tdls_enable()- Set the tdls enable from userspace
+ * @vdev: Pointer to vdev object
+ * @is_user_tdls_enable: true if tdls is enable from userspace
+ *
+ * return: NONE
+ */
+void tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+			       bool is_user_tdls_enable);
 /**
  * tdls_set_operation_mode() - set tdls operating mode
  * @tdls_set_mode: tdls mode set params
@@ -602,7 +613,7 @@ QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify);
  * connection tracker
  * @vdev: Pointer to vdev object
  *
- * Return: None
+ * Return: void
  */
 void tdls_process_enable_for_vdev(struct wlan_objmgr_vdev *vdev);
 
@@ -671,7 +682,7 @@ void tdls_notify_decrement_session(struct wlan_objmgr_psoc *psoc);
  * bits set in Ext Cap IE in received Assoc/Re-assoc response
  * from AP.
  *
- * Return: None.
+ * Return: void
  */
 void tdls_send_update_to_fw(struct tdls_vdev_priv_obj *tdls_vdev_obj,
 			    struct tdls_soc_priv_obj *tdls_soc_obj,
@@ -716,6 +727,14 @@ uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
  */
 bool tdls_is_6g_freq_allowed(struct wlan_objmgr_vdev *vdev, qdf_freq_t freq);
 
+/**
+ * tdls_check_is_user_tdls_enable() - Check is tdls enabled or not
+ * @tdls_soc_obj: TDLS soc object
+ *
+ * Return: true or false
+ */
+bool tdls_check_is_user_tdls_enable(struct tdls_soc_priv_obj *tdls_soc_obj);
+
 /**
  * tdls_check_is_tdls_allowed() - check is tdls allowed or not
  * @vdev: vdev object

+ 17 - 0
components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h

@@ -469,6 +469,17 @@ struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc,
  */
 bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * ucfg_tdls_set_user_tdls_enable() - ucfg api to set tdls is enable or not
+ * from userspace
+ * @vdev: vdev object
+ * @is_user_tdls_enable: true if tdls is enabled from userspace
+ *
+ * Return: void
+ */
+void ucfg_tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+				    bool is_user_tdls_enable);
+
 #else
 static inline
 bool ucfg_tdls_link_vdev_is_matching(struct wlan_objmgr_vdev *vdev)
@@ -576,6 +587,12 @@ bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
 	return false;
 }
 
+static inline
+void ucfg_tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+				    bool is_user_tdls_enable)
+{
+}
+
 static inline
 void ucfg_tdls_update_fw_11ax_capability(struct wlan_objmgr_psoc *psoc,
 					 bool is_fw_tdls_11ax_capable)

+ 7 - 0
components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c

@@ -289,6 +289,7 @@ static QDF_STATUS tdls_global_init(struct tdls_soc_priv_obj *soc_obj)
 	soc_obj->tdls_nss_transition_mode = TDLS_NSS_TRANSITION_S_UNKNOWN;
 	soc_obj->enable_tdls_connection_tracker = false;
 	soc_obj->tdls_external_peer_count = 0;
+	soc_obj->is_user_tdls_enable = true;
 
 	qdf_spinlock_create(&soc_obj->tdls_ct_spinlock);
 	tdls_wow_init(soc_obj);
@@ -1292,3 +1293,9 @@ bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
 {
 	return tdls_check_is_tdls_allowed(vdev);
 }
+
+void ucfg_tdls_set_user_tdls_enable(struct wlan_objmgr_vdev *vdev,
+				    bool is_user_tdls_enable)
+{
+	return tdls_set_user_tdls_enable(vdev, is_user_tdls_enable);
+}

+ 58 - 2
core/hdd/src/wlan_hdd_tdls.c

@@ -45,6 +45,7 @@
 #include "wlan_tdls_cfg_api.h"
 #include "wlan_hdd_object_manager.h"
 #include <wlan_reg_ucfg_api.h>
+#include "wlan_tdls_api.h"
 
 /**
  * enum qca_wlan_vendor_tdls_trigger_mode_hdd_map: Maps the user space TDLS
@@ -526,6 +527,39 @@ int wlan_hdd_cfg80211_exttdls_set_link_id(struct wiphy *wiphy,
 	return errno;
 }
 
+static int wlan_hdd_tdls_enable(struct hdd_context *hdd_ctx,
+				struct hdd_adapter *adapter)
+{
+	struct wlan_hdd_link_info *link_info;
+	struct wlan_objmgr_vdev *vdev;
+	bool tdls_chan_switch_prohibited;
+	bool tdls_prohibited;
+
+	hdd_adapter_for_each_active_link_info(adapter, link_info) {
+		vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_TDLS_NB_ID);
+		if (!vdev)
+			return -EINVAL;
+
+		tdls_chan_switch_prohibited =
+			ucfg_mlme_get_tdls_chan_switch_prohibited(vdev);
+		tdls_prohibited = ucfg_mlme_get_tdls_prohibited(vdev);
+
+		ucfg_tdls_set_user_tdls_enable(vdev, true);
+
+		wlan_tdls_notify_sta_connect(wlan_vdev_get_id(vdev),
+					     tdls_chan_switch_prohibited,
+					     tdls_prohibited, vdev);
+		if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
+			hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
+			return 0;
+		}
+
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
+	}
+
+	return 0;
+}
+
 /**
  * __wlan_hdd_cfg80211_exttdls_enable() - enable an externally controllable
  *                                      TDLS peer and set parameters
@@ -545,8 +579,30 @@ __wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy,
 				     const void *data,
 				     int data_len)
 {
-	/* TODO */
-	return 0;
+	struct net_device *dev = wdev->netdev;
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	int ret = 0;
+
+	hdd_enter_dev(wdev->netdev);
+	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	if (wlan_hdd_validate_context(hdd_ctx))
+		return -EINVAL;
+
+	if (adapter->device_mode != QDF_STA_MODE &&
+	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
+		hdd_debug("Failed to get TDLS info due to opmode:%d",
+			  adapter->device_mode);
+		return -EOPNOTSUPP;
+	}
+
+	ret = wlan_hdd_tdls_enable(hdd_ctx, adapter);
+
+	return ret;
 }
 
 /**