Browse Source

qcacld-3.0: Add support to update dot11mode based on regdb

Certain countries have dot11mode restrictions such as no
11be mode support, in which case the regdb updates the
phymode and sends to Host.
Add support to use this value to limit and update the
internal dot11mode to allow connection in corresponding
phymode.

Change-Id: If7dd8c261fbe61e96c7749dd1457713502409fa6
CRs-Fixed: 3747811
Gururaj Pandurangi 1 year ago
parent
commit
ec54ce1398

+ 3 - 2
components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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 above
@@ -814,7 +814,8 @@ static void if_mgr_update_candidate(struct wlan_objmgr_psoc *psoc,
 
 	if (!mlme_get_bss_11be_allowed(psoc, &candidate_info->peer_addr,
 				       attr.ie_data, attr.ie_length) ||
-	    wlan_vdev_mlme_get_user_dis_eht_flag(vdev)) {
+	    wlan_vdev_mlme_get_user_dis_eht_flag(vdev) ||
+	    !wlan_reg_phybitmap_support_11be(wlan_vdev_get_pdev(vdev))) {
 		scan_entry->ie_list.multi_link_bv = NULL;
 		scan_entry->ie_list.ehtcap = NULL;
 		scan_entry->ie_list.ehtop = NULL;

+ 10 - 0
core/hdd/inc/wlan_hdd_cfg.h

@@ -387,6 +387,16 @@ void hdd_override_all_ps(struct hdd_context *hdd_ctx);
 int hdd_vendor_mode_to_phymode(enum qca_wlan_vendor_phy_mode vendor_phy_mode,
 			       eCsrPhyMode *csr_phy_mode);
 
+/**
+ * hdd_phymode_to_vendor_mode() - Get vendor phy mode according to CSR phy mode.
+ * @csr_phy_mode: phy mode of eCsrPhyMode
+ * @vendor_phy_mode: vendor phy mode
+ *
+ * Return: 0 on success, negative error value on failure
+ */
+int hdd_phymode_to_vendor_mode(eCsrPhyMode csr_phy_mode,
+			       enum qca_wlan_vendor_phy_mode *vendor_phy_mode);
+
 /**
  * hdd_vendor_mode_to_band() - Get band_info according to vendor phy mode
  * @vendor_phy_mode: vendor phy mode

+ 43 - 1
core/hdd/src/wlan_hdd_cfg.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1863,6 +1863,47 @@ QDF_STATUS hdd_get_rx_nss(struct wlan_hdd_link_info *link_info, uint8_t *rx_nss)
 	return status;
 }
 
+int hdd_phymode_to_vendor_mode(eCsrPhyMode csr_phy_mode,
+			       enum qca_wlan_vendor_phy_mode *vendor_phy_mode)
+{
+	switch (csr_phy_mode) {
+	case eCSR_DOT11_MODE_AUTO:
+	case eCSR_DOT11_MODE_11be:
+	case eCSR_DOT11_MODE_11be_ONLY:
+		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_AUTO;
+		break;
+	case eCSR_DOT11_MODE_11a:
+		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11A;
+		break;
+	case eCSR_DOT11_MODE_11b:
+	case eCSR_DOT11_MODE_11b_ONLY:
+		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11B;
+		break;
+	case eCSR_DOT11_MODE_11g:
+	case eCSR_DOT11_MODE_11g_ONLY:
+		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11G;
+		break;
+	case eCSR_DOT11_MODE_11n:
+	case eCSR_DOT11_MODE_11n_ONLY:
+		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11AGN;
+		break;
+	case eCSR_DOT11_MODE_11ac:
+	case eCSR_DOT11_MODE_11ac_ONLY:
+		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160;
+		break;
+	case eCSR_DOT11_MODE_11ax:
+	case eCSR_DOT11_MODE_11ax_ONLY:
+		*vendor_phy_mode = QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160;
+		break;
+	case eCSR_DOT11_MODE_abg:
+	default:
+		hdd_err("Not supported mode %d", csr_phy_mode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 int hdd_vendor_mode_to_phymode(enum qca_wlan_vendor_phy_mode vendor_phy_mode,
 			       eCsrPhyMode *csr_phy_mode)
 {
@@ -2027,6 +2068,7 @@ int hdd_phymode_to_dot11_mode(eCsrPhyMode phymode,
 {
 	switch (phymode) {
 	case eCSR_DOT11_MODE_AUTO:
+	case eCSR_DOT11_MODE_11be:
 		*dot11_mode = eHDD_DOT11_MODE_AUTO;
 		break;
 	case eCSR_DOT11_MODE_11a:

+ 57 - 16
core/hdd/src/wlan_hdd_cfg80211.c

@@ -9056,7 +9056,9 @@ int hdd_set_vdev_phy_mode(struct hdd_adapter *adapter,
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
 	struct wlan_hdd_link_info *link_info = adapter->deflink;
-	eCsrPhyMode phymode;
+	eCsrPhyMode csr_req_phymode, csr_max_phymode;
+	enum reg_phymode reg_req_phymode, reg_max_phymode;
+	enum qca_wlan_vendor_phy_mode max_vendor_phy_mode;
 	WMI_HOST_WIFI_STANDARD std;
 	enum hdd_dot11_mode dot11_mode;
 	uint8_t supported_band;
@@ -9066,24 +9068,41 @@ int hdd_set_vdev_phy_mode(struct hdd_adapter *adapter,
 		hdd_err("Station is connected, command is not supported");
 		return -EINVAL;
 	}
+	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &csr_req_phymode);
+	if (ret < 0)
+		return ret;
 
-	adapter->user_phy_mode = vendor_phy_mode;
+	reg_req_phymode = csr_convert_to_reg_phy_mode(csr_req_phymode, 0);
+	reg_max_phymode = wlan_reg_get_max_phymode(hdd_ctx->pdev,
+						   reg_req_phymode, 0);
+	if (reg_req_phymode != reg_max_phymode) {
+		hdd_debug("reg_max_phymode %d, req_req_phymode %d",
+			  reg_max_phymode, reg_req_phymode);
+		csr_max_phymode =
+			csr_convert_from_reg_phy_mode(reg_max_phymode);
+		ret = hdd_phymode_to_vendor_mode(csr_max_phymode,
+						 &max_vendor_phy_mode);
+		if (ret)
+			return ret;
+	} else {
+		csr_max_phymode = csr_req_phymode;
+		max_vendor_phy_mode = vendor_phy_mode;
+	}
 
-	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &phymode);
-	if (ret)
-		return ret;
+	adapter->user_phy_mode = max_vendor_phy_mode;
 
-	ret = hdd_phymode_to_dot11_mode(phymode, &dot11_mode);
+	ret = hdd_phymode_to_dot11_mode(csr_max_phymode, &dot11_mode);
 	if (ret)
 		return ret;
 
-	ret = hdd_vendor_mode_to_band(vendor_phy_mode, &supported_band,
+	ret = hdd_vendor_mode_to_band(max_vendor_phy_mode, &supported_band,
 				      wlan_reg_is_6ghz_supported(psoc));
 	if (ret)
 		return ret;
 
 	std = hdd_get_wifi_standard(hdd_ctx, dot11_mode, supported_band);
-	hdd_debug("wifi_standard %d, vendor_phy_mode %d", std, vendor_phy_mode);
+	hdd_debug("wifi_standard %d, vendor_phy_mode %d",
+		  std, max_vendor_phy_mode);
 
 	ret = sme_cli_set_command(link_info->vdev_id,
 				  wmi_vdev_param_wifi_standard_version,
@@ -9103,7 +9122,9 @@ int hdd_set_phy_mode(struct hdd_adapter *adapter,
 {
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
-	eCsrPhyMode phymode;
+	eCsrPhyMode csr_req_phymode, csr_max_phymode;
+	enum reg_phymode reg_req_phymode, reg_max_phymode;
+	enum qca_wlan_vendor_phy_mode max_vendor_phy_mode = vendor_phy_mode;
 	uint8_t supported_band;
 	uint32_t bonding_mode;
 	int ret = 0;
@@ -9115,20 +9136,39 @@ int hdd_set_phy_mode(struct hdd_adapter *adapter,
 		return -EINVAL;
 	}
 
-	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &phymode);
+	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &csr_req_phymode);
 	if (ret < 0)
 		return ret;
 
-	ret = hdd_vendor_mode_to_band(vendor_phy_mode, &supported_band,
+	reg_req_phymode = csr_convert_to_reg_phy_mode(csr_req_phymode, 0);
+	reg_max_phymode = wlan_reg_get_max_phymode(hdd_ctx->pdev,
+						   reg_req_phymode, 0);
+
+	if (reg_req_phymode != reg_max_phymode) {
+		hdd_debug("reg_max_phymode %d, req_req_phymode %d",
+			  reg_max_phymode, reg_req_phymode);
+		csr_max_phymode =
+			csr_convert_from_reg_phy_mode(reg_max_phymode);
+		ret = hdd_phymode_to_vendor_mode(csr_max_phymode,
+						 &max_vendor_phy_mode);
+		if (ret)
+			return ret;
+	} else {
+		csr_max_phymode = csr_req_phymode;
+		max_vendor_phy_mode = vendor_phy_mode;
+	}
+
+	ret = hdd_vendor_mode_to_band(max_vendor_phy_mode, &supported_band,
 				      wlan_reg_is_6ghz_supported(psoc));
 	if (ret < 0)
 		return ret;
 
-	ret = hdd_vendor_mode_to_bonding_mode(vendor_phy_mode, &bonding_mode);
+	ret = hdd_vendor_mode_to_bonding_mode(max_vendor_phy_mode,
+					      &bonding_mode);
 	if (ret < 0)
 		return ret;
 
-	ret = hdd_update_phymode(adapter, phymode, supported_band,
+	ret = hdd_update_phymode(adapter, csr_max_phymode, supported_band,
 				 bonding_mode);
 	if (ret)
 		return ret;
@@ -9136,9 +9176,10 @@ int hdd_set_phy_mode(struct hdd_adapter *adapter,
 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, curr_adapter, next_adapter,
 					   dbgid) {
 		if (curr_adapter->device_mode == QDF_STA_MODE &&
-		    !hdd_cm_is_vdev_connected(curr_adapter->deflink))
-			hdd_set_vdev_phy_mode(curr_adapter, vendor_phy_mode);
-
+		    !hdd_cm_is_vdev_connected(curr_adapter->deflink)) {
+			hdd_set_vdev_phy_mode(curr_adapter,
+					      max_vendor_phy_mode);
+		}
 		hdd_adapter_dev_put_debug(curr_adapter, dbgid);
 	}
 

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

@@ -1941,9 +1941,11 @@ static void hdd_update_tgt_services(struct hdd_context *hdd_ctx,
 	if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
 	     config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
 		config->dot11Mode = eHDD_DOT11_MODE_AUTO;
+
 	/* 11BE mode support */
-	if (!hdd_dot11Mode_support_11be(config->dot11Mode) &&
-	    cfg->en_11be) {
+	if (cfg->en_11be &&
+	    (!hdd_dot11Mode_support_11be(config->dot11Mode) ||
+	     !wlan_reg_phybitmap_support_11be(hdd_ctx->pdev))) {
 		hdd_debug("dot11Mode %d override target en_11be to false",
 			  config->dot11Mode);
 		cfg->en_11be = false;

+ 8 - 1
core/hdd/src/wlan_hdd_regulatory.c

@@ -1656,6 +1656,8 @@ static void hdd_country_change_update_sta(struct hdd_context *hdd_ctx)
 	eCsrPhyMode csr_phy_mode;
 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_STA;
 	struct wlan_hdd_link_info *link_info;
+	enum qca_wlan_vendor_phy_mode vendor_phy_mode =
+						QCA_WLAN_VENDOR_PHY_MODE_AUTO;
 
 	pdev = hdd_ctx->pdev;
 
@@ -1692,8 +1694,11 @@ static void hdd_country_change_update_sta(struct hdd_context *hdd_ctx)
 					hdd_country_change_bw_check(link_info,
 								    oper_freq);
 
-				if (!hdd_is_vdev_in_conn_state(link_info))
+				if (!hdd_is_vdev_in_conn_state(link_info)) {
+					hdd_set_vdev_phy_mode(adapter,
+							      vendor_phy_mode);
 					continue;
+				}
 
 				if (phy_changed || freq_changed ||
 				    width_changed) {
@@ -1704,6 +1709,8 @@ static void hdd_country_change_update_sta(struct hdd_context *hdd_ctx)
 							link_info,
 							REASON_UNSPEC_FAILURE,
 							false);
+					hdd_set_vdev_phy_mode(adapter,
+							      vendor_phy_mode);
 					sta_ctx->reg_phymode = csr_phy_mode;
 				} else {
 					hdd_debug("Remain on current channel but update tx power");

+ 0 - 12
core/sme/inc/sme_api.h

@@ -4672,23 +4672,11 @@ enum csr_cfgdot11mode sme_phy_mode_to_dot11mode(enum wlan_phymode phy_mode);
  * Return: Max EHT channel width supported by FW (eg. 80, 160, 320)
  */
 uint32_t sme_get_eht_ch_width(void);
-
-/**
- * sme_is_11be_capable() - Check if 11 be is supported or not
- *
- * Return: True if 11be is supported
- */
-bool sme_is_11be_capable(void);
 #else /* !WLAN_FEATURE_11BE */
 static inline uint32_t sme_get_eht_ch_width(void)
 {
 	return 0;
 }
-
-static inline bool sme_is_11be_capable(void)
-{
-	return false;
-}
 #endif /* WLAN_FEATURE_11BE */
 
 /**

+ 4 - 10
core/sme/src/common/sme_api.c

@@ -16752,14 +16752,6 @@ QDF_STATUS sme_switch_channel(mac_handle_t mac_handle,
 }
 
 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
-
-#ifdef WLAN_FEATURE_11BE
-bool sme_is_11be_capable(void)
-{
-	return sme_is_feature_supported_by_fw(DOT11BE);
-}
-#endif
-
 QDF_STATUS sme_send_set_mac_addr(struct qdf_mac_addr mac_addr,
 				 struct qdf_mac_addr mld_addr,
 				 struct wlan_objmgr_vdev *vdev)
@@ -16819,6 +16811,7 @@ QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_vdev *vdev,
 	struct wlan_objmgr_peer *peer;
 	struct vdev_mlme_obj *vdev_mlme;
 	struct wlan_objmgr_psoc *psoc;
+	bool eht_enab = false;
 
 	psoc = wlan_vdev_get_psoc(vdev);
 
@@ -16827,8 +16820,9 @@ QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_vdev *vdev,
 	if (req_status)
 		goto p2p_self_peer_create;
 
+	ucfg_psoc_mlme_get_11be_capab(psoc, &eht_enab);
 	if (vdev_opmode == QDF_STA_MODE && update_sta_self_peer) {
-		if (sme_is_11be_capable() && update_mld_addr) {
+		if (eht_enab && update_mld_addr) {
 			old_macaddr = wlan_vdev_mlme_get_mldaddr(vdev);
 			new_macaddr = mld_addr.bytes;
 		} else {
@@ -16857,7 +16851,7 @@ QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_vdev *vdev,
 	}
 
 	/* Update VDEV MAC address */
-	if (sme_is_11be_capable() && update_mld_addr) {
+	if (eht_enab && update_mld_addr) {
 		if (update_sta_self_peer || vdev_opmode == QDF_SAP_MODE) {
 			qdf_ret_status = wlan_mlo_mgr_update_mld_addr(
 					    (struct qdf_mac_addr *)