diff --git a/components/tdls/core/src/wlan_tdls_cmds_process.c b/components/tdls/core/src/wlan_tdls_cmds_process.c index 4ac3aa8ec3..44d5ac8aac 100644 --- a/components/tdls/core/src/wlan_tdls_cmds_process.c +++ b/components/tdls/core/src/wlan_tdls_cmds_process.c @@ -40,11 +40,23 @@ #include "nan_ucfg_api.h" #include "wlan_mlme_main.h" -static uint16_t tdls_get_connected_peer(struct tdls_soc_priv_obj *soc_obj) +static uint16_t tdls_get_connected_peer_count(struct tdls_soc_priv_obj *soc_obj) { return soc_obj->connected_peer_count; } +uint16_t tdls_get_connected_peer_count_from_vdev(struct wlan_objmgr_vdev *vdev) +{ + struct tdls_soc_priv_obj *soc_obj; + + soc_obj = wlan_vdev_get_tdls_soc_obj(vdev); + + if (!soc_obj) + return 0; + + return tdls_get_connected_peer_count(soc_obj); +} + #ifdef WLAN_FEATURE_11AX static uint8_t tdls_get_mlme_ch_power(struct vdev_mlme_obj *mlme_obj, qdf_freq_t freq) @@ -196,6 +208,10 @@ void tdls_decrement_peer_count(struct wlan_objmgr_vdev *vdev, tdls_debug("Connected peer count %d", soc_obj->connected_peer_count); + /* Need to update osif params when last peer gets disconnected */ + if (!soc_obj->connected_peer_count && + soc_obj->tdls_osif_update_cb.tdls_osif_disconn_update) + soc_obj->tdls_osif_update_cb.tdls_osif_disconn_update(vdev); tdls_update_6g_power(vdev, soc_obj, false); } @@ -637,7 +653,7 @@ static QDF_STATUS tdls_activate_add_peer(struct tdls_add_peer_request *req) } /* first to check if we reached to maximum supported TDLS peer. */ - curr_tdls_peers = tdls_get_connected_peer(soc_obj); + curr_tdls_peers = tdls_get_connected_peer_count(soc_obj); if (soc_obj->max_num_tdls_sta <= curr_tdls_peers) { tdls_err(QDF_MAC_ADDR_FMT " Request declined. Current %d, Max allowed %d.", @@ -1099,7 +1115,7 @@ tdls_activate_update_peer(struct tdls_update_peer_request *req) goto setlink; } - curr_tdls_peers = tdls_get_connected_peer(soc_obj); + curr_tdls_peers = tdls_get_connected_peer_count(soc_obj); if (soc_obj->max_num_tdls_sta <= curr_tdls_peers) { tdls_err(QDF_MAC_ADDR_FMT " Request declined. Current: %d, Max allowed: %d.", @@ -1811,6 +1827,10 @@ QDF_STATUS tdls_process_enable_link(struct tdls_oper_request *req) tdls_update_6g_power(vdev, soc_obj, true); tdls_increment_peer_count(soc_obj); + /* Need to update osif params when first peer gets connected */ + if (soc_obj->connected_peer_count == 1 && + soc_obj->tdls_osif_update_cb.tdls_osif_conn_update) + soc_obj->tdls_osif_update_cb.tdls_osif_conn_update(vdev); feature = soc_obj->tdls_configs.tdls_feature_flags; if (soc_obj->tdls_dp_vdev_update) diff --git a/components/tdls/core/src/wlan_tdls_cmds_process.h b/components/tdls/core/src/wlan_tdls_cmds_process.h index 689b85afad..ea9c9421ae 100644 --- a/components/tdls/core/src/wlan_tdls_cmds_process.h +++ b/components/tdls/core/src/wlan_tdls_cmds_process.h @@ -139,6 +139,14 @@ void tdls_release_serialization_command(struct wlan_objmgr_vdev *vdev, enum wlan_serialization_cmd_type type); +/** + * tdls_get_connected_peer_count_from_vdev() - Get TDLS connected peer count + * @tdls_vdev: Pointer to vdev obj + * + * Return: Connected peer count + */ +uint16_t tdls_get_connected_peer_count_from_vdev(struct wlan_objmgr_vdev *vdev); + /** * tdls_set_cap() - set TDLS capability type * @tdls_vdev: tdls vdev object diff --git a/components/tdls/core/src/wlan_tdls_main.h b/components/tdls/core/src/wlan_tdls_main.h index 7a086fed8c..51e88400e5 100644 --- a/components/tdls/core/src/wlan_tdls_main.h +++ b/components/tdls/core/src/wlan_tdls_main.h @@ -192,6 +192,7 @@ struct tdls_set_state_info { * @runtime_lock: runtime lock * @tdls_osif_init_cb: Callback to initialize the tdls private * @tdls_osif_deinit_cb: Callback to deinitialize the tdls private + * @tdls_osif_update_cb: Callback for updating osif params * @fw_tdls_11ax_capablity: bool for tdls 11ax fw capability * @fw_tdls_6g_capability: bool for tdls 6g fw capability * @bss_sta_power: bss sta power @@ -245,6 +246,7 @@ struct tdls_soc_priv_obj { #endif tdls_vdev_init_cb tdls_osif_init_cb; tdls_vdev_deinit_cb tdls_osif_deinit_cb; + struct tdls_osif_cb tdls_osif_update_cb; #ifdef WLAN_FEATURE_11AX bool fw_tdls_11ax_capability; bool fw_tdls_6g_capability; diff --git a/components/tdls/dispatcher/inc/wlan_tdls_public_structs.h b/components/tdls/dispatcher/inc/wlan_tdls_public_structs.h index 54f77c1f5a..46c59125cb 100644 --- a/components/tdls/dispatcher/inc/wlan_tdls_public_structs.h +++ b/components/tdls/dispatcher/inc/wlan_tdls_public_structs.h @@ -656,6 +656,18 @@ typedef QDF_STATUS (*tdls_vdev_init_cb)(struct wlan_objmgr_vdev *vdev); */ typedef void (*tdls_vdev_deinit_cb)(struct wlan_objmgr_vdev *vdev); +/** + * tdls_osif_cb() - Callbacks for updating osif params. + * @tdls_osif_conn_update: Update osif params when TDLS peer is connected + * @tdls_osif_disconn_update: Update osif params when TDLS peer is disconnected + * + * These callbacks will be used for updating osif params. + */ +struct tdls_osif_cb { + void (*tdls_osif_conn_update)(struct wlan_objmgr_vdev *vdev); + void (*tdls_osif_disconn_update)(struct wlan_objmgr_vdev *vdev); +}; + /** * struct tdls_start_params - tdls start params * @config: tdls user config @@ -672,6 +684,7 @@ typedef void (*tdls_vdev_deinit_cb)(struct wlan_objmgr_vdev *vdev); * @tdls_dp_vdev_update: update vdev flags in datapath * @tdls_osif_init_cb: callback to initialize the tdls priv * @tdls_osif_deinit_cb: callback to deinitialize the tdls priv + * @tdls_osif_cb: callback to update osif params */ struct tdls_start_params { struct tdls_user_config config; @@ -692,6 +705,7 @@ struct tdls_start_params { tdls_dp_vdev_update_flags_callback tdls_dp_vdev_update; tdls_vdev_init_cb tdls_osif_init_cb; tdls_vdev_deinit_cb tdls_osif_deinit_cb; + struct tdls_osif_cb tdls_osif_update_cb; }; /** diff --git a/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h b/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h index ce05c904e2..298904c199 100644 --- a/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h +++ b/components/tdls/dispatcher/inc/wlan_tdls_ucfg_api.h @@ -390,6 +390,15 @@ QDF_STATUS ucfg_tdls_set_rssi(struct wlan_objmgr_vdev *vdev, */ void ucfg_tdls_notify_connect_failure(struct wlan_objmgr_psoc *psoc); +/** + * ucfg_get_tdls_conn_peer_count() - This api is called to get number of + * connected TDLS peer + * @vdev: vdev object + * + * Return: tdls connected peer count + */ +uint16_t ucfg_get_tdls_conn_peer_count(struct wlan_objmgr_vdev *vdev); + /** * ucfg_get_tdls_vdev() - Ucfg api to get tdls specific vdev object * @psoc: wlan psoc object manager diff --git a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c b/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c index c8c7efe80b..ca82ee8b26 100644 --- a/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c +++ b/components/tdls/dispatcher/src/wlan_tdls_ucfg_api.c @@ -458,6 +458,10 @@ QDF_STATUS ucfg_tdls_update_config(struct wlan_objmgr_psoc *psoc, soc_obj->tdls_dp_vdev_update = req->tdls_dp_vdev_update; soc_obj->tdls_osif_init_cb = req->tdls_osif_init_cb; soc_obj->tdls_osif_deinit_cb = req->tdls_osif_deinit_cb; + soc_obj->tdls_osif_update_cb.tdls_osif_conn_update = + req->tdls_osif_update_cb.tdls_osif_conn_update; + soc_obj->tdls_osif_update_cb.tdls_osif_disconn_update = + req->tdls_osif_update_cb.tdls_osif_disconn_update; tdls_pm_call_backs.tdls_notify_increment_session = tdls_notify_increment_session; @@ -1215,6 +1219,11 @@ void ucfg_tdls_notify_connect_failure(struct wlan_objmgr_psoc *psoc) return wlan_tdls_notify_connect_failure(psoc); } +uint16_t ucfg_get_tdls_conn_peer_count(struct wlan_objmgr_vdev *vdev) +{ + return tdls_get_connected_peer_count_from_vdev(vdev); +} + struct wlan_objmgr_vdev *ucfg_get_tdls_vdev(struct wlan_objmgr_psoc *psoc, wlan_objmgr_ref_dbgid dbg_id) { diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h index 1f87d4d845..0636862b15 100644 --- a/core/hdd/inc/wlan_hdd_tdls.h +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -155,6 +156,47 @@ int hdd_set_tdls_offchannel(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter, int offchannel); +/** + * hdd_check_and_set_tdls_conn_params() - Gets conencted TDLS peer count. + * @adapter: Pointer to adapter + * + * This function return number of connected peer. + * + * Return: void + */ +uint16_t +hdd_get_tdls_connected_peer_count(struct hdd_adapter *adapter); + +/** + * hdd_check_and_set_tdls_conn_params() - Sets and Overwrite netdev params if + * stations is conencted in 11A, 11B and 11G mode. + * @vdev: Pointer to vdev objmgr + * + * This function updates the netdev params such as enabling checksum/tso + * if the feature "disable checksum/tso for 11abg connections" is enabled via + * INI. if INI is enabled then 11abg sta link will be created by disabling + * checksum/tso which are needed to be enabled for better thorughput + * for TDLS connected in 11AX, 11AC, 11N mode + * + * Return: void + */ +void hdd_check_and_set_tdls_conn_params(struct wlan_objmgr_vdev *vdev); + +/** + * hdd_check_and_set_tdls_disconn_params() - Overwrite netdev params if BSS + * STA link is 11A, 11B and 11G mode + * when TDLS is disconnected + * @vdev: Pointer to vdev objmgr + * + * During TDLS connection if STA-BSS link is in 11a, 11b, 11g mode, then + * legacy netdev features such as checksum/tso are enabled. This function will + * take care of disabling them during TDLS disconnection if the feature + * "disable checksum/tso for 11abg connections" is enabled via INI. + * + * Return: void + */ +void hdd_check_and_set_tdls_disconn_params(struct wlan_objmgr_vdev *vdev); + /** * hdd_set_tdls_secoffchanneloffset() - set secondary tdls off-channel offset * @hdd_ctx: Pointer to the HDD context @@ -258,5 +300,20 @@ static inline void hdd_config_tdls_with_band_switch(struct hdd_context *hdd_ctx) { } +static inline uint16_t +hdd_get_tdls_connected_peer_count(struct hdd_adapter *adapter) +{ + return 0; +} + +static inline void +hdd_check_and_set_tdls_conn_params(struct wlan_objmgr_vdev *vdev) +{ +} + +static inline void +hdd_check_and_set_tdls_disconn_params(struct wlan_objmgr_vdev *vdev) +{ +} #endif /* End of FEATURE_WLAN_TDLS */ #endif /* __HDD_TDLS_H */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index f77d8f39c3..5f5dc8deec 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -192,6 +192,7 @@ #include "os_if_dp_lro.h" #include "wlan_mlo_mgr_sta.h" #include "wlan_hdd_coap.h" +#include "wlan_hdd_tdls.h" #define g_mode_rates_size (12) #define a_mode_rates_size (8) @@ -24234,10 +24235,16 @@ hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode) bool hdd_is_legacy_connection(struct hdd_adapter *adapter) { struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); - int connection_mode; + int connection_mode = QCA_WLAN_802_11_MODE_INVALID; + enum csr_cfgdot11mode cfgmode; + uint16_t tdls_connected_peer; - connection_mode = hdd_convert_cfgdot11mode_to_80211mode( - sta_ctx->conn_info.dot11mode); + tdls_connected_peer = hdd_get_tdls_connected_peer_count(adapter); + if (tdls_connected_peer) + return false; + + cfgmode = sta_ctx->conn_info.dot11mode; + connection_mode = hdd_convert_cfgdot11mode_to_80211mode(cfgmode); if (connection_mode == QCA_WLAN_802_11_MODE_11A || connection_mode == QCA_WLAN_802_11_MODE_11B || connection_mode == QCA_WLAN_802_11_MODE_11G) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 33ca627f90..42c8473837 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1352,6 +1352,10 @@ static int hdd_update_tdls_config(struct hdd_context *hdd_ctx) tdls_cfg.tdls_dp_vdev_update = hdd_update_dp_vdev_flags; tdls_cfg.tdls_osif_init_cb = wlan_cfg80211_tdls_osif_priv_init; tdls_cfg.tdls_osif_deinit_cb = wlan_cfg80211_tdls_osif_priv_deinit; + tdls_cfg.tdls_osif_update_cb.tdls_osif_conn_update = + hdd_check_and_set_tdls_conn_params; + tdls_cfg.tdls_osif_update_cb.tdls_osif_disconn_update = + hdd_check_and_set_tdls_disconn_params; status = ucfg_tdls_update_config(psoc, &tdls_cfg); if (status != QDF_STATUS_SUCCESS) { diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index 72f0bab6e9..a186702a39 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -620,6 +621,113 @@ int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, return errno; } +static bool +hdd_is_sta_legacy(struct hdd_adapter *adapter) +{ + struct hdd_station_ctx *sta_ctx; + + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (!sta_ctx) + return false; + + if ((sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_AUTO) || + (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11N) || + (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11AC) || + (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11N_ONLY) || + (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11AC_ONLY) || + (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11AX) || + (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11AX_ONLY)) + return false; + + return true; +} + +uint16_t +hdd_get_tdls_connected_peer_count(struct hdd_adapter *adapter) +{ + struct wlan_objmgr_vdev *vdev; + uint16_t peer_count; + + vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_TDLS_ID); + + peer_count = ucfg_get_tdls_conn_peer_count(vdev); + wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_TDLS_ID); + + return peer_count; +} + +void +hdd_check_and_set_tdls_conn_params(struct wlan_objmgr_vdev *vdev) +{ + uint8_t vdev_id; + enum hdd_dot11_mode selfdot11mode; + struct hdd_adapter *adapter; + struct wlan_objmgr_psoc *psoc; + struct hdd_context *hdd_ctx; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) + return; + + vdev_id = wlan_vdev_get_id(vdev); + adapter = wlan_hdd_get_adapter_from_vdev(psoc, vdev_id); + if (!adapter) + return; + + /* + * Only need to set this if STA link is in legacy mode + */ + if (!hdd_is_sta_legacy(adapter)) + return; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (!hdd_ctx) + return; + + selfdot11mode = hdd_ctx->config->dot11Mode; + /* + * When STA connection is made in legacy mode (11a, 11b and 11g) and + * selfdot11Mode is either 11ax, 11ac or 11n, TDLS connection can be + * made upto supporting selfdot11mode. Since, TDLS shares same netdev + * that of STA, checksum/TSO will be disabled during STA connection. + * For better TDLS thorughput, enable checksum/TSO which were already + * disabled during STA connection. + */ + if (selfdot11mode == eHDD_DOT11_MODE_AUTO || + selfdot11mode == eHDD_DOT11_MODE_11ax || + selfdot11mode == eHDD_DOT11_MODE_11ax_ONLY || + selfdot11mode == eHDD_DOT11_MODE_11ac_ONLY || + selfdot11mode == eHDD_DOT11_MODE_11ac || + selfdot11mode == eHDD_DOT11_MODE_11n || + selfdot11mode == eHDD_DOT11_MODE_11n_ONLY) + hdd_cm_netif_queue_enable(adapter); +} + +void +hdd_check_and_set_tdls_disconn_params(struct wlan_objmgr_vdev *vdev) +{ + struct hdd_adapter *adapter; + uint8_t vdev_id; + struct wlan_objmgr_psoc *psoc; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) + return; + + vdev_id = wlan_vdev_get_id(vdev); + adapter = wlan_hdd_get_adapter_from_vdev(psoc, vdev_id); + if (!adapter) + return; + + /* + * Only need to set this if STA link is in legacy mode + */ + if (!hdd_is_sta_legacy(adapter)) + return; + + hdd_cm_netif_queue_enable(adapter); +} + /** * __wlan_hdd_cfg80211_tdls_oper() - helper function to handle cfg80211 operation * on an TDLS peer