diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 9b0aa4e5a2..59c9d66fa4 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -30,6 +30,7 @@ #include #include #include "wma_tgt_cfg.h" +#include "wlan_mlme_vdev_mgr_interface.h" /** * ucfg_mlme_init() - initialize mlme_ctx context. @@ -282,6 +283,19 @@ ucfg_mlme_peer_config_vlan(struct wlan_objmgr_vdev *vdev, return wlan_mlme_peer_config_vlan(vdev, macaddr); } +/** + * ucfg_mlme_get_tdls_prohibited() - get if TDLS prohibited is advertised by + * the connected AP. + * @vdev: vdev pointer + * + * Return: bool + */ +static inline +bool ucfg_mlme_get_tdls_prohibited(struct wlan_objmgr_vdev *vdev) +{ + return mlme_get_tdls_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/dispatcher/inc/wlan_tdls_cfg_api.h b/components/tdls/dispatcher/inc/wlan_tdls_cfg_api.h index 6468d739c3..084670626c 100644 --- a/components/tdls/dispatcher/inc/wlan_tdls_cfg_api.h +++ b/components/tdls/dispatcher/inc/wlan_tdls_cfg_api.h @@ -274,6 +274,14 @@ cfg_tdls_set_scan_enable(struct wlan_objmgr_psoc *psoc, * This function gets tdls max peer count */ uint16_t cfg_tdls_get_max_peer_count(struct wlan_objmgr_psoc *psoc); + +/** + * cfg_tdls_get_connected_peer_count() - get tdls connected peer count + * @psoc: pointer to psoc object + * + * This function gets tdls connected peer count + */ +uint16_t cfg_tdls_get_connected_peer_count(struct wlan_objmgr_psoc *psoc); #else static inline QDF_STATUS cfg_tdls_get_support_enable(struct wlan_objmgr_psoc *psoc, @@ -450,5 +458,12 @@ cfg_tdls_get_max_peer_count(struct wlan_objmgr_psoc *psoc) { return 0; } + +static inline uint16_t +cfg_tdls_get_connected_peer_count(struct wlan_objmgr_psoc *psoc) +{ + return 0; +} + #endif /* FEATURE_WLAN_TDLS */ #endif /* _WLAN_TDLS_CFG_API_H_ */ diff --git a/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h b/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h index 58608e773a..f9ea23e8b1 100644 --- a/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h +++ b/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h @@ -459,6 +459,16 @@ uint16_t ucfg_get_tdls_conn_peer_count(struct wlan_objmgr_vdev *vdev); struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc, wlan_objmgr_ref_dbgid dbg_id); +/** + * ucfg_tdls_check_is_tdls_allowed() - Ucfg api to check is tdls allowed or not + * @vdev: vdev object + * + * Function determines the whether TDLS allowed in the system + * + * Return: true or false + */ +bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev); + #else static inline bool ucfg_tdls_link_vdev_is_matching(struct wlan_objmgr_vdev *vdev) @@ -560,6 +570,12 @@ struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc, return NULL; } +static inline +bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev) +{ + return false; +} + 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_cfg.c b/components/tdls/dispatcher/src/wlan_tdls_cfg.c index c66e60864c..729f11f24c 100644 --- a/components/tdls/dispatcher/src/wlan_tdls_cfg.c +++ b/components/tdls/dispatcher/src/wlan_tdls_cfg.c @@ -413,3 +413,17 @@ cfg_tdls_get_max_peer_count(struct wlan_objmgr_psoc *psoc) return soc_obj->max_num_tdls_sta; } + +uint16_t +cfg_tdls_get_connected_peer_count(struct wlan_objmgr_psoc *psoc) +{ + struct tdls_soc_priv_obj *soc_obj; + + soc_obj = wlan_psoc_get_tdls_soc_obj(psoc); + if (!soc_obj) { + tdls_err("tdls soc null"); + return 0; + } + + return soc_obj->connected_peer_count; +} diff --git a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c b/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c index 9978fd3bc7..932c35593b 100644 --- a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c +++ b/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c @@ -1287,3 +1287,8 @@ struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc, { return tdls_get_vdev(psoc, dbg_id); } + +bool ucfg_tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev) +{ + return tdls_check_is_tdls_allowed(vdev); +} diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 60f6248f0d..bdce8c72a5 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -189,6 +189,70 @@ const struct nla_policy .type = NLA_S32}, }; +static bool wlan_hdd_is_tdls_allowed(struct hdd_context *hdd_ctx, + struct wlan_objmgr_vdev *vdev) +{ + bool tdls_support; + + if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) == + QDF_STATUS_SUCCESS) && !tdls_support) { + hdd_debug("TDLS feature not Enabled or Not supported in FW"); + return false; + } + + if (!wlan_cm_is_vdev_connected(vdev)) { + hdd_debug("Failed due to Not associated"); + return false; + } + + if (wlan_cm_roaming_in_progress(hdd_ctx->pdev, + wlan_vdev_get_id(vdev))) { + hdd_debug("Failed due to Roaming is in progress"); + return false; + } + + if (!ucfg_tdls_check_is_tdls_allowed(vdev)) { + hdd_debug("TDLS is not allowed"); + return false; + } + + if (ucfg_mlme_get_tdls_prohibited(vdev)) { + hdd_debug("TDLS is prohobited by AP"); + return false; + } + + return true; +} + +static bool wlan_hdd_get_tdls_allowed(struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter) +{ + struct wlan_hdd_link_info *link_info; + struct wlan_objmgr_vdev *vdev; + bool is_tdls_avail = false; + + 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 false; + + is_tdls_avail = wlan_hdd_is_tdls_allowed(hdd_ctx, vdev); + + /* Return is_tdls_avail for non-MLO case */ + if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { + hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID); + return is_tdls_avail; + } + + hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID); + + if (is_tdls_avail) + return is_tdls_avail; + } + + return false; +} + /** * __wlan_hdd_cfg80211_exttdls_get_status() - handle get status cfg80211 command * @wiphy: wiphy @@ -202,8 +266,74 @@ __wlan_hdd_cfg80211_exttdls_get_status(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); + struct sk_buff *skb; + uint32_t connected_peer_count = 0; + int status; + bool is_tdls_avail = true; + int ret = 0; + int attr; + + hdd_enter_dev(wdev->netdev); + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM mode"); + return -EPERM; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (status) + return -EINVAL; + + skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, + sizeof(u32) + sizeof(bool) + + NLMSG_HDRLEN); + + if (!skb) { + hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed"); + return -ENOMEM; + } + + 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); + ret = -EOPNOTSUPP; + goto fail; + } + + connected_peer_count = cfg_tdls_get_connected_peer_count(hdd_ctx->psoc); + is_tdls_avail = wlan_hdd_get_tdls_allowed(hdd_ctx, adapter); + + if (connected_peer_count >= + cfg_tdls_get_max_peer_count(hdd_ctx->psoc)) { + hdd_debug("Failed due to max no. of connected peer:%d reached", + connected_peer_count); + is_tdls_avail = false; + } + + hdd_debug("Send TDLS_available: %d, no. of connected peer:%d to userspace", + is_tdls_avail, connected_peer_count); + + attr = QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_NUM_SESSIONS; + if (nla_put_u32(skb, attr, connected_peer_count)) { + hdd_err("nla put fail"); + ret = -EINVAL; + goto fail; + } + + attr = QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_AVAILABLE; + if (is_tdls_avail && nla_put_flag(skb, attr)) { + hdd_err("nla put fail"); + ret = -EINVAL; + goto fail; + } + + return wlan_cfg80211_vendor_cmd_reply(skb); +fail: + wlan_cfg80211_vendor_free_skb(skb); + return ret; } static int