Browse Source

qcacld-3.0: Restore original EHT chan BW on disconnect

Userspace can dynamically modify association BW and as part of
disconnect need to reset the BW to original value, if not the
next connection will might happen with downgraded BW.

Currently the restore is happening on deflink VDEV instead of
actual disconnecting VDEV.

Fix this by changing function argument to accept link info
pointer in HDD adapter of that corresponding VDEV.

Additionally, the driver capability for 6 GHz-320 MHz is not
properly restored and further connections to 320 MHz are
happening on 160 MHz.

To fix the 160 MHz downgrade, use original EHT capabilities in
global MAC context instead of using modified EHT cap where
320 MHz support got reset on userspace dynamic BW update.

Change-Id: If2badb0a234f45d57dc186729bc529137d7a5131
CRs-Fixed: 3628940
Vinod Kumar Pirla 1 year ago
parent
commit
9e3ba566d9

+ 10 - 0
components/mlme/dispatcher/inc/wlan_mlme_api.h

@@ -4173,6 +4173,16 @@ bool wlan_mlme_skip_tpe(struct wlan_objmgr_psoc *psoc);
 bool
 wlan_mlme_is_data_stall_recovery_fw_supported(struct wlan_objmgr_psoc *psoc);
 
+/**
+ * mlme_cfg_get_orig_eht_caps() - Get the original EHT capability info
+ * @psoc: pointer to psoc object
+ * @eht_cap: Caps that needs to be filled.
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS mlme_cfg_get_orig_eht_caps(struct wlan_objmgr_psoc *psoc,
+				      tDot11fIEeht_cap *eht_cap);
+
 /**
  * mlme_cfg_get_eht_caps() - Get the EHT capability info
  * @psoc: pointer to psoc object

+ 14 - 0
components/mlme/dispatcher/src/wlan_mlme_api.c

@@ -6514,6 +6514,20 @@ bool wlan_mlme_skip_tpe(struct wlan_objmgr_psoc *psoc)
 }
 
 #ifdef WLAN_FEATURE_11BE
+QDF_STATUS mlme_cfg_get_orig_eht_caps(struct wlan_objmgr_psoc *psoc,
+				      tDot11fIEeht_cap *eht_cap)
+{
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj)
+		return QDF_STATUS_E_FAILURE;
+
+	*eht_cap = mlme_obj->cfg.eht_caps.eht_cap_orig;
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS mlme_cfg_get_eht_caps(struct wlan_objmgr_psoc *psoc,
 				 tDot11fIEeht_cap *eht_cap)
 {

+ 2 - 2
core/hdd/inc/wlan_hdd_cfg.h

@@ -490,7 +490,7 @@ int hdd_set_rx_stbc(struct wlan_hdd_link_info *link_info, int value);
 
 /**
  * hdd_update_channel_width() - Update adapter channel width settings
- * @adapter: adapter being modified
+ * @link_info: Link info in HDD adapter
  * @chwidth: new channel width of enum eSirMacHTChannelWidth
  * @bonding_mode: channel bonding mode of the new channel width
  * @link_id: mlo link id
@@ -498,7 +498,7 @@ int hdd_set_rx_stbc(struct wlan_hdd_link_info *link_info, int value);
  *
  * Return: 0 on success, negative errno on failure
  */
-int hdd_update_channel_width(struct hdd_adapter *adapter,
+int hdd_update_channel_width(struct wlan_hdd_link_info *link_info,
 			     enum eSirMacHTChannelWidth chwidth,
 			     uint32_t bonding_mode, uint8_t link_id,
 			     bool is_restore);

+ 22 - 29
core/hdd/src/wlan_hdd_cfg.c

@@ -2412,36 +2412,32 @@ hdd_convert_chwidth_to_phy_chwidth(enum eSirMacHTChannelWidth chwidth)
 
 /**
  * hdd_update_bss_rate_flags() - update bss rate flag as per new channel width
- * @adapter: adapter being modified
+ * @link_info: Link info in HDD adapter
  * @psoc: psoc common object
  * @cw: channel width for which bss rate flag being updated
  *
  * Return: QDF_STATUS
  */
-static QDF_STATUS hdd_update_bss_rate_flags(struct hdd_adapter *adapter,
-					    struct wlan_objmgr_psoc *psoc,
-					    enum phy_ch_width cw)
+static QDF_STATUS
+hdd_update_bss_rate_flags(struct wlan_hdd_link_info *link_info,
+			  struct wlan_objmgr_psoc *psoc, enum phy_ch_width cw)
 {
 	struct hdd_station_ctx *hdd_sta_ctx;
 	uint8_t eht_present, he_present, vht_present, ht_present;
 
-	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
-	if (!hdd_sta_ctx) {
-		hdd_err("hdd_sta_ctx is null");
-		return QDF_STATUS_E_INVAL;
-	}
+	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
 
 	eht_present = hdd_sta_ctx->conn_info.conn_flag.eht_present;
 	he_present = hdd_sta_ctx->conn_info.conn_flag.he_present;
 	vht_present = hdd_sta_ctx->conn_info.conn_flag.vht_present;
 	ht_present = hdd_sta_ctx->conn_info.conn_flag.ht_present;
 
-	return ucfg_mlme_update_bss_rate_flags(psoc, adapter->deflink->vdev_id,
+	return ucfg_mlme_update_bss_rate_flags(psoc, link_info->vdev_id,
 					       cw, eht_present, he_present,
 					       vht_present, ht_present);
 }
 
-int hdd_update_channel_width(struct hdd_adapter *adapter,
+int hdd_update_channel_width(struct wlan_hdd_link_info *link_info,
 			     enum eSirMacHTChannelWidth chwidth,
 			     uint32_t bonding_mode, uint8_t link_id,
 			     bool is_restore)
@@ -2451,25 +2447,26 @@ int hdd_update_channel_width(struct hdd_adapter *adapter,
 	int ret;
 	enum phy_ch_width ch_width = CH_WIDTH_INVALID;
 	QDF_STATUS status;
+	uint8_t vdev_id = link_info->vdev_id;
 
-	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
 	if (!hdd_ctx) {
 		hdd_err("hdd_ctx failure");
 		return -EINVAL;
 	}
 
 	if (ucfg_mlme_is_chwidth_with_notify_supported(hdd_ctx->psoc) &&
-	    hdd_cm_is_vdev_connected(adapter->deflink)) {
+	    hdd_cm_is_vdev_connected(link_info)) {
 		ch_width = hdd_convert_chwidth_to_phy_chwidth(chwidth);
 		hdd_debug("vdev %d : process update ch width request to %d",
-			  adapter->deflink->vdev_id, ch_width);
-		status =
-		    ucfg_mlme_send_ch_width_update_with_notify(hdd_ctx->psoc,
-					adapter->deflink->vdev_id, ch_width,
-					link_id);
+			  vdev_id, ch_width);
+		status = ucfg_mlme_send_ch_width_update_with_notify(hdd_ctx->psoc,
+								    vdev_id,
+								    ch_width,
+								    link_id);
 		if (QDF_IS_STATUS_ERROR(status))
 			return -EIO;
-		status = hdd_update_bss_rate_flags(adapter, hdd_ctx->psoc,
+		status = hdd_update_bss_rate_flags(link_info, hdd_ctx->psoc,
 						   ch_width);
 		if (QDF_IS_STATUS_ERROR(status))
 			return -EIO;
@@ -2479,28 +2476,24 @@ int hdd_update_channel_width(struct hdd_adapter *adapter,
 	if (!sme_config)
 		return -ENOMEM;
 
-	ret = wma_cli_set_command(adapter->deflink->vdev_id,
-				  wmi_vdev_param_chwidth, chwidth, VDEV_CMD);
+	ret = wma_cli_set_command(vdev_id, wmi_vdev_param_chwidth,
+				  chwidth, VDEV_CMD);
 	if (ret)
 		goto free_config;
 
 	sme_get_config_param(hdd_ctx->mac_handle, sme_config);
 	if (is_restore) {
 		sme_config->csr_config.channelBondingMode5GHz =
-			cfg_get(adapter->hdd_ctx->psoc,
-				CFG_CHANNEL_BONDING_MODE_5GHZ);
+			cfg_get(hdd_ctx->psoc, CFG_CHANNEL_BONDING_MODE_5GHZ);
 		sme_config->csr_config.channelBondingMode24GHz =
-			cfg_get(adapter->hdd_ctx->psoc,
-				CFG_CHANNEL_BONDING_MODE_24GHZ);
+			cfg_get(hdd_ctx->psoc, CFG_CHANNEL_BONDING_MODE_24GHZ);
 	} else {
 		sme_config->csr_config.channelBondingMode5GHz = bonding_mode;
 		sme_config->csr_config.channelBondingMode24GHz = bonding_mode;
 	}
 	sme_update_config(hdd_ctx->mac_handle, sme_config);
-	sme_set_he_bw_cap(hdd_ctx->mac_handle,
-			  adapter->deflink->vdev_id, chwidth);
-	sme_set_eht_bw_cap(hdd_ctx->mac_handle,
-			   adapter->deflink->vdev_id, chwidth);
+	sme_set_he_bw_cap(hdd_ctx->mac_handle, vdev_id, chwidth);
+	sme_set_eht_bw_cap(hdd_ctx->mac_handle, vdev_id, chwidth);
 free_config:
 	qdf_mem_free(sme_config);
 	return ret;

+ 8 - 10
core/hdd/src/wlan_hdd_cfg80211.c

@@ -10988,16 +10988,15 @@ static uint32_t hdd_mac_chwidth_to_bonding_mode(
 	return bonding_mode;
 }
 
-int hdd_set_mac_chan_width(struct hdd_adapter *adapter,
+int hdd_set_mac_chan_width(struct wlan_hdd_link_info *link_info,
 			   enum eSirMacHTChannelWidth chwidth,
-			   uint8_t link_id,
-			   bool is_restore)
+			   uint8_t link_id, bool is_restore)
 {
 	uint32_t bonding_mode;
 
 	bonding_mode = hdd_mac_chwidth_to_bonding_mode(chwidth);
 
-	return hdd_update_channel_width(adapter, chwidth,
+	return hdd_update_channel_width(link_info, chwidth,
 					bonding_mode, link_id, is_restore);
 }
 
@@ -11072,8 +11071,7 @@ skip_mlo:
 		return -EINVAL;
 	}
 set_chan_width:
-	return hdd_set_mac_chan_width(link_info->adapter,
-				      chwidth, link_id, false);
+	return hdd_set_mac_chan_width(link_info, chwidth, link_id, false);
 }
 
 /**
@@ -13353,7 +13351,7 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 	uint8_t link_id = 0xFF;
 	struct keep_alive_req keep_alive_req = {0};
 	struct set_wfatest_params wfa_param = {0};
-	struct wlan_hdd_link_info *link_info = adapter->link_info;
+	struct wlan_hdd_link_info *link_info = adapter->deflink;
 	struct hdd_station_ctx *hdd_sta_ctx =
 			WLAN_HDD_GET_STATION_CTX_PTR(link_info);
 	uint8_t op_mode;
@@ -14067,7 +14065,7 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 		sme_set_ru_242_tone_tx_cfg(hdd_ctx->mac_handle, cfg_val);
 		if (cfg_val)
 			hdd_update_channel_width(
-					adapter, eHT_CHANNEL_WIDTH_20MHZ,
+					link_info, eHT_CHANNEL_WIDTH_20MHZ,
 					WNI_CFG_CHANNEL_BONDING_MODE_DISABLE,
 					link_id, false);
 	}
@@ -14078,7 +14076,7 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 		hdd_debug("EU SU PPDU type Tx enable: %d", cfg_val);
 		if (cfg_val) {
 			hdd_update_channel_width(
-					adapter, eHT_CHANNEL_WIDTH_20MHZ,
+					link_info, eHT_CHANNEL_WIDTH_20MHZ,
 					WNI_CFG_CHANNEL_BONDING_MODE_DISABLE,
 					link_id, false);
 			hdd_set_tx_stbc(link_info, 0);
@@ -14099,7 +14097,7 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 					status);
 		} else {
 			hdd_update_channel_width(
-					adapter, eHT_CHANNEL_WIDTH_160MHZ,
+					link_info, eHT_CHANNEL_WIDTH_160MHZ,
 					link_id,
 					WNI_CFG_CHANNEL_BONDING_MODE_ENABLE,
 					false);

+ 3 - 4
core/hdd/src/wlan_hdd_cfg80211.h

@@ -975,17 +975,16 @@ int hdd_set_phy_mode(struct hdd_adapter *adapter,
 
 /**
  * hdd_set_mac_chan_width() - set channel width
- * @adapter: Handle to hdd_adapter
+ * @link_info: Link info in HDD adapter
  * @chwidth: given channel width
  * @link_id: mlo link id
  * @is_restore: is restore
  *
  * Return: 0 on success, negative errno on failure
  */
-int hdd_set_mac_chan_width(struct hdd_adapter *adapter,
+int hdd_set_mac_chan_width(struct wlan_hdd_link_info *link_info,
 			   enum eSirMacHTChannelWidth chwidth,
-			   uint8_t link_id,
-			   bool is_restore);
+			   uint8_t link_id, bool is_restore);
 
 /**
  * hdd_is_legacy_connection() - Is adapter connection is legacy

+ 5 - 5
core/hdd/src/wlan_hdd_cm_disconnect.c

@@ -482,7 +482,7 @@ static void hdd_cm_reset_udp_qos_upgrade_config(struct hdd_adapter *adapter)
 #ifdef WLAN_FEATURE_11BE
 static inline enum eSirMacHTChannelWidth get_max_bw(void)
 {
-	uint32_t max_bw = wma_get_eht_ch_width();
+	uint32_t max_bw = wma_get_orig_eht_ch_width();
 
 	if (max_bw == WNI_CFG_EHT_CHANNEL_WIDTH_320MHZ)
 		return eHT_CHANNEL_WIDTH_320MHZ;
@@ -539,9 +539,9 @@ void wlan_hdd_re_enable_320mhz_6g_conection(struct hdd_context *hdd_ctx,
 #endif
 
 static void hdd_cm_restore_ch_width(struct wlan_objmgr_vdev *vdev,
-				    struct hdd_adapter *adapter)
+				    struct wlan_hdd_link_info *link_info)
 {
-	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
 	struct mlme_legacy_priv *mlme_priv;
 	enum eSirMacHTChannelWidth max_bw;
 	struct wlan_channel *des_chan;
@@ -569,7 +569,7 @@ static void hdd_cm_restore_ch_width(struct wlan_objmgr_vdev *vdev,
 		wlan_hdd_re_enable_320mhz_6g_conection(hdd_ctx, assoc_ch_width);
 
 	max_bw = get_max_bw();
-	ret = hdd_set_mac_chan_width(adapter, max_bw, link_id, true);
+	ret = hdd_set_mac_chan_width(link_info, max_bw, link_id, true);
 	if (ret) {
 		hdd_err("vdev %d : fail to set max ch width", vdev_id);
 		return;
@@ -611,7 +611,7 @@ hdd_cm_disconnect_complete_post_user_update(struct wlan_objmgr_vdev *vdev,
 	 * bandwidth on disconnection so that post disconnection DUT can
 	 * connect in max BW.
 	 */
-	hdd_cm_restore_ch_width(vdev, adapter);
+	hdd_cm_restore_ch_width(vdev, link_info);
 	hdd_cm_set_default_wlm_mode(adapter);
 	__hdd_cm_disconnect_handler_post_user_update(link_info, vdev,
 						     rsp->req.req.source);

+ 2 - 3
core/hdd/src/wlan_hdd_main.c

@@ -21647,10 +21647,9 @@ int hdd_we_set_ch_width(struct wlan_hdd_link_info *link_info, int ch_width)
 		    chwidth_info[i].sir_chwidth != ch_width)
 			continue;
 
-		return hdd_update_channel_width(link_info->adapter, ch_width,
+		return hdd_update_channel_width(link_info, ch_width,
 						chwidth_info[i].bonding_mode,
-						link_id,
-						false);
+						link_id, false);
 	}
 
 	hdd_err("Invalid ch_width %d", ch_width);

+ 2 - 2
core/hdd/src/wlan_hdd_son.c

@@ -154,13 +154,13 @@ static int hdd_son_set_chwidth(struct wlan_objmgr_vdev *vdev,
 
 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
 	if (!link_info) {
-		hdd_err("null adapter");
+		hdd_err("null adapter for %d", wlan_vdev_get_id(vdev));
 		return -EINVAL;
 	}
 
 	chwidth = hdd_son_chan_width_to_chan_width(son_chwidth);
 
-	return hdd_set_mac_chan_width(link_info->adapter, chwidth, link_id, false);
+	return hdd_set_mac_chan_width(link_info, chwidth, link_id, false);
 }
 
 /**

+ 21 - 0
core/wma/inc/wma.h

@@ -1478,8 +1478,29 @@ int wma_mgmt_tx_bundle_completion_handler(void *handle,
 uint32_t wma_get_vht_ch_width(void);
 
 #ifdef WLAN_FEATURE_11BE
+/**
+ * wma_get_orig_eht_ch_width() - Get original EHT channel width supported
+ *
+ * API to get original EHT channel width
+ *
+ * Return: void
+ */
+uint32_t wma_get_orig_eht_ch_width(void);
+
+/**
+ * wma_get_orig_eht_ch_width() - Get current EHT channel width supported
+ *
+ * API to get current EHT channel width
+ *
+ * Return: void
+ */
 uint32_t wma_get_eht_ch_width(void);
 #else
+static inline uint32_t wma_get_orig_eht_ch_width(void)
+{
+	return 0;
+}
+
 static inline uint32_t wma_get_eht_ch_width(void)
 {
 	return 0;

+ 25 - 5
core/wma/src/wma_utils.c

@@ -5169,12 +5169,32 @@ int wma_oem_event_handler(void *wma_ctx, uint8_t *event_buff, uint32_t len)
 }
 #endif
 
-/**
- * wma_get_eht_ch_width - return eht channel width
- *
- * Return: return eht channel width
- */
 #ifdef WLAN_FEATURE_11BE
+uint32_t wma_get_orig_eht_ch_width(void)
+{
+	tDot11fIEeht_cap eht_cap;
+	tp_wma_handle wma;
+	QDF_STATUS status;
+
+	wma = cds_get_context(QDF_MODULE_ID_WMA);
+	if (qdf_unlikely(!wma)) {
+		wma_err_rl("wma handle is NULL");
+		goto vht_ch_width;
+	}
+
+	status = mlme_cfg_get_orig_eht_caps(wma->psoc, &eht_cap);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		wma_err_rl("Failed to get eht caps");
+		goto vht_ch_width;
+	}
+
+	if (eht_cap.support_320mhz_6ghz)
+		return WNI_CFG_EHT_CHANNEL_WIDTH_320MHZ;
+
+vht_ch_width:
+	return wma_get_vht_ch_width();
+}
+
 uint32_t wma_get_eht_ch_width(void)
 {
 	tDot11fIEeht_cap eht_cap;