Browse Source

qcacld-3.0: Add logic to set wifi standard for vdev

Add logic to set wifi standard per the vendor
attribute QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE
and QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX for vdev.

Change-Id: Ib03d233bf6f290859e2d754b3193ae5020d872d5
CRs-Fixed: 3554395
Paul Zhang 1 year ago
parent
commit
012efd118b

+ 2 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -1248,6 +1248,7 @@ struct wlan_hdd_tx_power {
  * @delta_qtime: delta between host qtime and monotonic time
  * @traffic_end_ind_en: traffic end indication feature enable/disable
  * @is_dbam_configured:
+ * @user_phy_mode: phy mode is set per vdev
  * @deflink: Default link pointing to the 0th index of the linkinfo array
  * @link_info: Data structure to hold link specific information
  * @tx_power: Structure to hold connection tx Power info
@@ -1436,6 +1437,7 @@ struct hdd_adapter {
 #ifdef WLAN_FEATURE_DBAM_CONFIG
 	bool is_dbam_configured;
 #endif
+	enum qca_wlan_vendor_phy_mode user_phy_mode;
 	struct wlan_hdd_link_info *deflink;
 	struct wlan_hdd_link_info link_info[WLAN_MAX_ML_BSS_LINKS];
 	struct wlan_hdd_tx_power tx_power;

+ 68 - 6
core/hdd/src/wlan_hdd_cfg80211.c

@@ -8635,6 +8635,54 @@ wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct wlan_hdd_link_info *link_info,
 	return ret_val;
 }
 
+int hdd_set_vdev_phy_mode(struct hdd_adapter *adapter,
+			  enum qca_wlan_vendor_phy_mode vendor_phy_mode)
+{
+	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;
+	WMI_HOST_WIFI_STANDARD std;
+	enum hdd_dot11_mode dot11_mode;
+	uint8_t supported_band;
+	int ret;
+
+	if (hdd_cm_is_vdev_connected(link_info)) {
+		hdd_err("Station is connected, command is not supported");
+		return -EINVAL;
+	}
+
+	adapter->user_phy_mode = vendor_phy_mode;
+
+	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &phymode);
+	if (ret)
+		return ret;
+
+	ret = hdd_phymode_to_dot11_mode(phymode, &dot11_mode);
+	if (ret)
+		return ret;
+
+	ret = hdd_vendor_mode_to_band(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);
+
+	ret = sme_cli_set_command(link_info->vdev_id,
+				  wmi_vdev_param_wifi_standard_version,
+				  std, VDEV_CMD);
+	if (ret) {
+		hdd_err("Failed to set standard version to fw");
+		return ret;
+	}
+
+	ucfg_mlme_set_vdev_wifi_std(hdd_ctx->psoc, link_info->vdev_id, std);
+
+	return 0;
+}
+
 int hdd_set_phy_mode(struct hdd_adapter *adapter,
 		     enum qca_wlan_vendor_phy_mode vendor_phy_mode)
 {
@@ -8670,18 +8718,33 @@ int hdd_set_phy_mode(struct hdd_adapter *adapter,
 /**
  * hdd_config_phy_mode() - set PHY mode
  * @link_info: Link info pointer in HDD adapter
- * @attr: nla attr sent from userspace
+ * @tb: nla attr sent from userspace
  *
  * Return: 0 on success; error number otherwise
  */
 static int hdd_config_phy_mode(struct wlan_hdd_link_info *link_info,
-			       const struct nlattr *attr)
+			       struct nlattr *tb[])
 {
 	enum qca_wlan_vendor_phy_mode vendor_phy_mode;
+	uint32_t ifindex;
+	struct nlattr *phy_mode_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE];
+	struct nlattr *ifindex_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX];
 
-	vendor_phy_mode = nla_get_u32(attr);
+	if (!phy_mode_attr)
+		return 0;
+
+	vendor_phy_mode = nla_get_u32(phy_mode_attr);
+	if (!ifindex_attr)
+		return hdd_set_phy_mode(link_info->adapter, vendor_phy_mode);
 
-	return hdd_set_phy_mode(link_info->adapter, vendor_phy_mode);
+	ifindex = nla_get_u32(ifindex_attr);
+	if (ifindex == link_info->adapter->dev->ifindex)
+		return hdd_set_vdev_phy_mode(link_info->adapter,
+					     vendor_phy_mode);
+
+	hdd_err_rl("ifindex %d, expected ifindex %d", ifindex,
+		   link_info->adapter->dev->ifindex);
+	return -EINVAL;
 }
 
 /**
@@ -11512,8 +11575,6 @@ static const struct independent_setters independent_setters[] = {
 	 hdd_config_tx_stbc},
 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
 	 hdd_config_rx_stbc},
-	{QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE,
-	 hdd_config_phy_mode},
 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH,
 	 hdd_set_channel_width},
 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
@@ -12281,6 +12342,7 @@ static const interdependent_setter_fn interdependent_setters[] = {
 	hdd_config_ani,
 	hdd_config_tx_rx_nss,
 	hdd_process_generic_set_cmd,
+	hdd_config_phy_mode,
 };
 
 /**

+ 9 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -1122,6 +1122,15 @@ QDF_STATUS hdd_mlo_dev_t2lm_notify_link_update(struct wlan_objmgr_vdev *vdev,
 }
 #endif
 
+/** hdd_set_vdev_phy_mode() - Set vdev phy mode
+ * @adapter: adapter pointer
+ * @vendor_phy_mode: vendor phy mode
+ *
+ * Return: 0 for success
+ */
+int hdd_set_vdev_phy_mode(struct hdd_adapter *adapter,
+			  enum qca_wlan_vendor_phy_mode vendor_phy_mode);
+
 #if defined(WLAN_FEATURE_11BE_MLO) && \
 	defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT)
 /**

+ 60 - 0
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -1971,6 +1971,54 @@ static void lim_check_oui_and_update_session(struct mac_context *mac_ctx,
 		lim_update_he_caps_htc(session, !is_vendor_ap_present);
 }
 
+static enum mlme_dot11_mode
+lim_get_user_dot11_mode(struct wlan_objmgr_vdev *vdev)
+{
+	WMI_HOST_WIFI_STANDARD wifi_std;
+
+	wifi_std = mlme_get_vdev_wifi_std(vdev);
+
+	switch (wifi_std) {
+	case WMI_HOST_WIFI_STANDARD_4:
+		return MLME_DOT11_MODE_11N;
+	case WMI_HOST_WIFI_STANDARD_5:
+		return MLME_DOT11_MODE_11AC;
+	case WMI_HOST_WIFI_STANDARD_6:
+	case WMI_HOST_WIFI_STANDARD_6E:
+		return MLME_DOT11_MODE_11AX;
+	case WMI_HOST_WIFI_STANDARD_7:
+	default:
+		return MLME_DOT11_MODE_11BE;
+	}
+}
+
+static enum mlme_dot11_mode
+lim_intersect_user_dot11_mode(struct mac_context *mac_ctx,
+			      enum QDF_OPMODE opmode, uint8_t vdev_id,
+			      enum mlme_dot11_mode self_mode)
+{
+	struct wlan_objmgr_vdev *vdev;
+	enum mlme_dot11_mode user_mode;
+
+	switch (opmode) {
+	case QDF_STA_MODE:
+	case QDF_P2P_CLIENT_MODE:
+		break;
+	default:
+		return self_mode;
+	}
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id,
+						    WLAN_MLME_OBJMGR_ID);
+	if (!vdev)
+		return self_mode;
+
+	user_mode = lim_get_user_dot11_mode(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
+
+	return user_mode > self_mode ? self_mode : user_mode;
+}
+
 static enum mlme_dot11_mode
 lim_get_self_dot11_mode(struct mac_context *mac_ctx, enum QDF_OPMODE opmode,
 			uint8_t vdev_id)
@@ -2675,6 +2723,13 @@ lim_fill_dot11_mode(struct mac_context *mac_ctx, struct pe_session *session,
 
 	self_dot11_mode = lim_get_self_dot11_mode(mac_ctx, session->opmode,
 						  session->vdev_id);
+
+	/* if user set dot11 mode by cmd, need to do intersect first */
+	self_dot11_mode =
+		   lim_intersect_user_dot11_mode(mac_ctx, session->opmode,
+						 session->vdev_id,
+						 self_dot11_mode);
+
 	bss_dot11_mode = lim_get_bss_dot11_mode(mac_ctx, bss_desc, ie_struct);
 
 	pe_debug("vdev id %d opmode %d self dot11mode %d bss_dot11 mode %d",
@@ -5306,6 +5361,11 @@ lim_fill_preauth_req_dot11_mode(struct mac_context *mac_ctx,
 
 	self_dot11_mode = lim_get_self_dot11_mode(mac_ctx, QDF_STA_MODE,
 						  vdev_id);
+	/* if user set dot11 mode by cmd, need to do intersect first */
+	self_dot11_mode =
+		   lim_intersect_user_dot11_mode(mac_ctx, QDF_STA_MODE,
+						 vdev_id, self_dot11_mode);
+
 	bss_dot11_mode = lim_get_bss_dot11_mode(mac_ctx, bss_desc, ie_struct);
 
 	status = lim_get_intersected_dot11_mode_sta_ap(mac_ctx, self_dot11_mode,