diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 59c9d66fa4..102707c1c0 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/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 diff --git a/components/tdls/core/src/wlan_tdls_main.c b/components/tdls/core/src/wlan_tdls_main.c index b3236bd9aa..d2c81cf23f 100644 --- a/components/tdls/core/src/wlan_tdls_main.c +++ b/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) { diff --git a/components/tdls/core/src/wlan_tdls_main.h b/components/tdls/core/src/wlan_tdls_main.h index 6993bf4dd5..73f0caaf74 100644 --- a/components/tdls/core/src/wlan_tdls_main.h +++ b/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 diff --git a/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h b/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h index f9ea23e8b1..b031b7d497 100644 --- a/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h +++ b/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) diff --git a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c b/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c index 932c35593b..87471e0d67 100644 --- a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c +++ b/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); +} diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index bdce8c72a5..4d7f52d77f 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -45,6 +45,7 @@ #include "wlan_tdls_cfg_api.h" #include "wlan_hdd_object_manager.h" #include +#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; } /**