Procházet zdrojové kódy

qcacld-3.0: Disable legacy netdev params for TDLS

Since TDLS and STA share a common netdev interface,
when STA connection is made in 11a, 11b, 11g mode,
netdev parameters such as TSO/checksum are disabled.
If TDLS connection is formed over this Station,
TSO remains disabled as STA netdev is used.

This might result in loss of throughput when TDLS
connection is made with 11n, 11ac, 11ax dot11mode and
with wider bandwidth TDLS, this loss is more prominent.

Hence, overwrite the netdev params to enable TSO when
TDLS connection is formed in 11ax, 11ac, 11n mode if
the station is in 11a, 11b, 11g mode.
Also, disable the TSO params when TDLS tearsdown when
STA is in 11a, 11b, 11g mode.

Change-Id: I80deaef40d70030211e75a63e1339b1407627b52
CRs-Fixed: 3245258
Utkarsh Bhatnagar před 2 roky
rodič
revize
33f9595701

+ 23 - 3
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)

+ 8 - 0
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

+ 2 - 0
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;

+ 14 - 0
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;
 };
 
 /**

+ 9 - 0
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

+ 9 - 0
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)
 {

+ 57 - 0
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 */

+ 10 - 3
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;
+
+	tdls_connected_peer = hdd_get_tdls_connected_peer_count(adapter);
+	if (tdls_connected_peer)
+		return false;
 
-	connection_mode = hdd_convert_cfgdot11mode_to_80211mode(
-						sta_ctx->conn_info.dot11mode);
+	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)

+ 4 - 0
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) {

+ 108 - 0
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