Browse Source

qcacld-3.0: Allow VHT channel width upgrade

In current design, host driver doesn't allow the
channel width upgrade directly via VHT operation IE.

Allow upgrade of VHT channel width through VHT
operation IE.This will cause VDEV restart to upgrade
the channel width

Change-Id: Ib6a63b72df03b4d4f56cdb0c91d1f5c8ca4612ce
CRs-Fixed: 3537460
Surya Prakash Sivaraj 1 year ago
parent
commit
2cb469800b

+ 1 - 1
core/mac/src/pe/lim/lim_process_action_frame.c

@@ -249,7 +249,7 @@ static void __lim_process_operating_mode_action_frame(struct mac_context *mac_ct
 	uint32_t status;
 	tpDphHashNode sta_ptr;
 	uint16_t aid;
-	uint8_t ch_bw = 0;
+	enum phy_ch_width ch_bw = 0;
 
 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);

+ 69 - 36
core/mac/src/pe/lim/lim_utils.c

@@ -4883,13 +4883,19 @@ bool lim_check_vht_op_mode_change(struct mac_context *mac,
 				  uint8_t chanWidth, uint8_t *peerMac)
 {
 	QDF_STATUS status;
-	bool update_allow = false;
+	bool update_allow;
 	struct ch_params ch_params;
 	struct csa_offload_params *csa_param;
+	enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(pe_session->vdev);
 
-	status = lim_get_update_bw_allow(pe_session, chanWidth, &update_allow);
-	if (QDF_IS_STATUS_ERROR(status))
-		return false;
+	if (mode == QDF_STA_MODE || mode == QDF_P2P_CLIENT_MODE) {
+		status = lim_get_update_bw_allow(pe_session, chanWidth,
+						 &update_allow);
+		if (QDF_IS_STATUS_ERROR(status))
+			return false;
+	} else {
+		update_allow = true;
+	}
 
 	if (update_allow) {
 		tUpdateVHTOpMode tempParam;
@@ -4904,6 +4910,10 @@ bool lim_check_vht_op_mode_change(struct mac_context *mac,
 		return true;
 	}
 
+	if (!wlan_cm_is_vdev_connected(pe_session->vdev))
+		return false;
+
+	/* use vdev restart to update STA mode */
 	qdf_mem_zero(&ch_params, sizeof(ch_params));
 	ch_params.ch_width = chanWidth;
 	wlan_reg_set_channel_params_for_pwrmode(mac->pdev,
@@ -11064,10 +11074,12 @@ void lim_update_nss(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
 bool lim_update_channel_width(struct mac_context *mac_ctx,
 			      tpDphHashNode sta_ptr,
 			      struct pe_session *session,
-			      uint8_t ch_width, uint8_t *new_ch_width)
+			      enum phy_ch_width ch_width,
+			      enum phy_ch_width *new_ch_width)
 {
-	uint8_t cb_mode, oper_mode;
-	uint32_t fw_vht_ch_wd;
+	uint8_t cb_mode;
+	enum phy_ch_width oper_mode;
+	enum phy_ch_width fw_vht_ch_wd;
 
 	if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq))
 		cb_mode = mac_ctx->roam.configParam.channelBondingMode24GHz;
@@ -11085,53 +11097,52 @@ bool lim_update_channel_width(struct mac_context *mac_ctx,
 	if (sta_ptr->htSupportedChannelWidthSet) {
 		if (sta_ptr->vhtSupportedChannelWidthSet >
 		    WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ)
-			oper_mode = eHT_CHANNEL_WIDTH_160MHZ;
+			oper_mode = CH_WIDTH_160MHZ;
 		else
 			oper_mode = sta_ptr->vhtSupportedChannelWidthSet + 1;
 	} else {
-		oper_mode = eHT_CHANNEL_WIDTH_20MHZ;
+		oper_mode = CH_WIDTH_20MHZ;
 	}
 
-	if (((oper_mode == eHT_CHANNEL_WIDTH_80MHZ) &&
-	     (ch_width > eHT_CHANNEL_WIDTH_80MHZ)) ||
-	     (oper_mode == ch_width))
-		return false;
+	fw_vht_ch_wd = wlan_mlme_get_max_bw();
 
-	fw_vht_ch_wd = wma_get_vht_ch_width();
+	if (ch_width > fw_vht_ch_wd) {
+		pe_debug_rl(QDF_MAC_ADDR_FMT ": Downgrade new bw: %d to max %d",
+			    QDF_MAC_ADDR_REF(sta_ptr->staAddr),
+			    ch_width, fw_vht_ch_wd);
+		ch_width = fw_vht_ch_wd;
+	}
+	if (oper_mode == ch_width)
+		return false;
 
-	pe_debug("ChannelWidth - Current : %d, New: %d mac : " QDF_MAC_ADDR_FMT,
-		 oper_mode, ch_width, QDF_MAC_ADDR_REF(sta_ptr->staAddr));
+	pe_debug(QDF_MAC_ADDR_FMT ": Current : %d, New: %d max %d ",
+		 QDF_MAC_ADDR_REF(sta_ptr->staAddr), oper_mode,
+		 ch_width, fw_vht_ch_wd);
 
-	if (ch_width >= eHT_CHANNEL_WIDTH_160MHZ &&
-	    (fw_vht_ch_wd >= eHT_CHANNEL_WIDTH_160MHZ)) {
+	if (ch_width >= CH_WIDTH_160MHZ) {
 		sta_ptr->vhtSupportedChannelWidthSet =
 				WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
-		sta_ptr->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_40MHZ;
-		*new_ch_width = eHT_CHANNEL_WIDTH_160MHZ;
-	} else if (ch_width >= eHT_CHANNEL_WIDTH_80MHZ) {
+		ch_width = CH_WIDTH_160MHZ;
+	} else if (ch_width == CH_WIDTH_80MHZ) {
 		sta_ptr->vhtSupportedChannelWidthSet =
 				WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
-		sta_ptr->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_40MHZ;
-		*new_ch_width = eHT_CHANNEL_WIDTH_80MHZ;
-	} else if (ch_width == eHT_CHANNEL_WIDTH_40MHZ) {
+	} else if (ch_width == CH_WIDTH_40MHZ) {
 		sta_ptr->vhtSupportedChannelWidthSet =
 				WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
-		sta_ptr->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_40MHZ;
-		*new_ch_width = eHT_CHANNEL_WIDTH_40MHZ;
-	} else if (ch_width == eHT_CHANNEL_WIDTH_20MHZ) {
+	} else if (ch_width == CH_WIDTH_20MHZ) {
 		sta_ptr->vhtSupportedChannelWidthSet =
 				WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
-		sta_ptr->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_20MHZ;
-		*new_ch_width = eHT_CHANNEL_WIDTH_20MHZ;
+	} else {
+		return false;
 	}
+	if (ch_width >= CH_WIDTH_40MHZ)
+		sta_ptr->htSupportedChannelWidthSet = CH_WIDTH_40MHZ;
+	else
+		sta_ptr->htSupportedChannelWidthSet = CH_WIDTH_20MHZ;
+	*new_ch_width = ch_width;
 
-	lim_check_vht_op_mode_change(mac_ctx, session, *new_ch_width,
-				     sta_ptr->staAddr);
-	return true;
+	return lim_check_vht_op_mode_change(mac_ctx, session, *new_ch_width,
+					    sta_ptr->staAddr);
 }
 
 uint8_t lim_get_vht_ch_width(tDot11fIEVHTCaps *vht_cap,
@@ -11484,3 +11495,25 @@ next:
 
 	return false;
 }
+
+enum phy_ch_width
+lim_convert_vht_chwidth_to_phy_chwidth(uint8_t ch_width, bool is_40)
+{
+	switch (ch_width) {
+	case WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ:
+		return CH_WIDTH_80P80MHZ;
+	case WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ:
+		return CH_WIDTH_160MHZ;
+	case WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ:
+		return CH_WIDTH_80MHZ;
+	case WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ:
+		if (is_40)
+			return CH_WIDTH_40MHZ;
+		else
+			return CH_WIDTH_20MHZ;
+	default:
+		pe_debug("Unknown VHT ch width %d", ch_width);
+			break;
+	}
+	return CH_WIDTH_20MHZ;
+}

+ 14 - 2
core/mac/src/pe/lim/lim_utils.h

@@ -3115,8 +3115,8 @@ void lim_update_nss(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
 bool lim_update_channel_width(struct mac_context *mac_ctx,
 			      tpDphHashNode sta_ptr,
 			      struct pe_session *session,
-			      uint8_t ch_width,
-			      uint8_t *new_ch_width);
+			      enum phy_ch_width ch_width,
+			      enum phy_ch_width *new_ch_width);
 
 /**
  * lim_get_vht_ch_width() - Function to get the VHT
@@ -3251,4 +3251,16 @@ bool
 lim_is_chan_connected_for_mode(struct wlan_objmgr_psoc *psoc,
 			       enum QDF_OPMODE opmode,
 			       qdf_freq_t freq);
+
+/**
+ * lim_convert_vht_chwidth_to_phy_chwidth() - Convert VHT operation
+ * ch width into phy ch width
+ *
+ * @ch_width: VHT op channel width
+ * @is_40: is 40 MHz
+ *
+ * Return: phy chwidth
+ */
+enum phy_ch_width
+lim_convert_vht_chwidth_to_phy_chwidth(uint8_t ch_width, bool is_40);
 #endif /* __LIM_UTILS_H */

+ 20 - 77
core/mac/src/pe/sch/sch_beacon_process.c

@@ -436,13 +436,12 @@ sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
 				struct pe_session *session, tpSchBeaconStruct bcn,
 				tpSirMacMgmtHdr mac_hdr, uint8_t cb_mode)
 {
-	bool skip_opmode_update = false;
-	uint8_t oper_mode;
-	uint32_t fw_vht_ch_wd = wma_get_vht_ch_width();
-	uint8_t ch_width = 0, ch_bw;
+	enum phy_ch_width ch_bw;
+	enum phy_ch_width ch_width = CH_WIDTH_20MHZ;
 	tDot11fIEVHTCaps *vht_caps = NULL;
 	tDot11fIEVHTOperation *vht_op = NULL;
 	uint8_t bcn_vht_chwidth = 0;
+	bool is_40 = false;
 
 	/*
 	 * Ignore opmode change during channel change The opmode will be updated
@@ -457,15 +456,6 @@ sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
 		return;
 	}
 
-	if (session->vhtCapability && bcn->OperatingMode.present) {
-		pe_debug("OMN IE is present in the beacon, update NSS/Ch width");
-		lim_update_nss(mac_ctx, sta_ds, bcn->OperatingMode.rxNSS,
-			       session);
-		lim_update_channel_width(mac_ctx, sta_ds, session,
-					 bcn->OperatingMode.chanWidth, &ch_bw);
-		return;
-	}
-
 	if (bcn->VHTCaps.present) {
 		vht_caps = &bcn->VHTCaps;
 		vht_op = &bcn->VHTOperation;
@@ -473,74 +463,27 @@ sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds,
 		vht_caps = &bcn->vendor_vht_ie.VHTCaps;
 		vht_op = &bcn->vendor_vht_ie.VHTOperation;
 	}
-
-	if (!(session->vhtCapability && (vht_op && vht_op->present)))
+	if (!session->vhtCapability ||
+	    !(bcn->OperatingMode.present ||
+	      (vht_op && vht_op->present && vht_caps)))
 		return;
 
-	bcn_vht_chwidth = lim_get_vht_ch_width(&bcn->VHTCaps,
-					       &bcn->VHTOperation,
-					       &bcn->HTInfo);
-
-	oper_mode = sta_ds->vhtSupportedChannelWidthSet;
-	if ((oper_mode == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) &&
-	    (oper_mode < bcn_vht_chwidth))
-		skip_opmode_update = true;
-
-	if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == cb_mode) {
-		/*
-		 * if channel bonding is disabled from INI do not
-		 * update the chan width
-		 */
-		pe_debug_rl("CB disabled skip bw update: old[%d] new[%d]",
-			    oper_mode, bcn->OperatingMode.chanWidth);
-
-		return;
-	}
+	is_40 = bcn->HTCaps.present ?
+			bcn->HTCaps.supportedChannelWidthSet : false;
 
-	if (!skip_opmode_update &&
-	    (oper_mode != bcn_vht_chwidth)) {
-		pe_debug("received VHTOP CHWidth %d", bcn_vht_chwidth);
-		pe_debug("MAC - %0x:%0x:%0x:%0x:%0x:%0x",
-		       mac_hdr->sa[0], mac_hdr->sa[1],
-		       mac_hdr->sa[2], mac_hdr->sa[3],
-		       mac_hdr->sa[4], mac_hdr->sa[5]);
-
-		if ((bcn_vht_chwidth >=
-			WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) &&
-			(fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) {
-			pe_debug("Updating the CH Width to 160MHz");
-			sta_ds->vhtSupportedChannelWidthSet =
-						bcn_vht_chwidth;
-			sta_ds->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_40MHZ;
-			ch_width = eHT_CHANNEL_WIDTH_160MHZ;
-		} else if (bcn_vht_chwidth >=
-			WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
-			pe_debug("Updating the CH Width to 80MHz");
-			sta_ds->vhtSupportedChannelWidthSet =
-				WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
-			sta_ds->htSupportedChannelWidthSet =
-				eHT_CHANNEL_WIDTH_40MHZ;
-			ch_width = eHT_CHANNEL_WIDTH_80MHZ;
-		} else if (bcn_vht_chwidth ==
-			WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) {
-			sta_ds->vhtSupportedChannelWidthSet =
-				WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
-			if (bcn->HTCaps.supportedChannelWidthSet) {
-				pe_debug("Updating the CH Width to 40MHz");
-				sta_ds->htSupportedChannelWidthSet =
-					eHT_CHANNEL_WIDTH_40MHZ;
-				ch_width = eHT_CHANNEL_WIDTH_40MHZ;
-			} else {
-				pe_debug("Updating the CH Width to 20MHz");
-				sta_ds->htSupportedChannelWidthSet =
-					eHT_CHANNEL_WIDTH_20MHZ;
-				ch_width = eHT_CHANNEL_WIDTH_20MHZ;
-			}
-		}
-		lim_check_vht_op_mode_change(mac_ctx, session, ch_width,
-						mac_hdr->sa);
+	if (bcn->OperatingMode.present) {
+		pe_debug("OMN IE is present in the beacon, update NSS/Ch width");
+		lim_update_nss(mac_ctx, sta_ds, bcn->OperatingMode.rxNSS,
+			       session);
+		ch_width = bcn->OperatingMode.chanWidth;
+	} else {
+		bcn_vht_chwidth = lim_get_vht_ch_width(vht_caps, vht_op,
+						       &bcn->HTInfo);
+		ch_width =
+			lim_convert_vht_chwidth_to_phy_chwidth(bcn_vht_chwidth,
+							       is_40);
 	}
+	lim_update_channel_width(mac_ctx, sta_ds, session, ch_width, &ch_bw);
 }
 
 #ifdef WLAN_FEATURE_SR