Kaynağa Gözat

qcacld-3.0: Enable STA CSA for bandwidth indication ie

Channel switch wrapper IE V2 includes bandwidth indication sub IE from
IEEE802.11be draft 3.0 optionally.
When receive CSA event, Eht STA parse bandwidth indication IE of connected
Eht AP for channel switch or puncture update.

Change-Id: Id5740a1394766b02b65c5d6791ce98780bbacbd4
CRs-Fixed: 3458348
Jianmin Zhu 2 yıl önce
ebeveyn
işleme
a761584aa7

+ 2 - 2
core/mac/src/pe/lim/lim_send_sme_rsp_messages.c

@@ -1908,8 +1908,8 @@ void lim_handle_sta_csa_param(struct mac_context *mac_ctx,
 
 	session_entry->htSupportedChannelWidthSet = false;
 	wlan_reg_read_current_country(mac_ctx->psoc, country_code);
-	if (!csa_params->ies_present_flag) {
-		/* no ies, means triggered by host */
+	if (!csa_params->ies_present_flag ||
+	    (csa_params->ies_present_flag & MLME_CSWRAP_IE_EXT_V2_PRESENT)) {
 		pe_debug("new freq: %u, width: %d", csa_params->csa_chan_freq,
 			 csa_params->new_ch_width);
 		ch_params.ch_width = csa_params->new_ch_width;

+ 100 - 8
core/wma/src/wma_features.c

@@ -76,14 +76,15 @@
 #include "target_if_cm_roam_event.h"
 #include <wlan_mlo_mgr_cmn.h>
 #include "hif.h"
-
+#include "wlan_cmn_ieee80211.h"
+#include "wlan_mlo_mgr_cmn.h"
 /**
  * WMA_SET_VDEV_IE_SOURCE_HOST - Flag to identify the source of VDEV SET IE
  * command. The value is 0x0 for the VDEV SET IE WMI commands from mobile
  * MCL platform.
  */
 #define WMA_SET_VDEV_IE_SOURCE_HOST 0x0
-#define CH_WR_IE_MAX_LEN 20
+#define CH_WR_IE_MAX_LEN 29
 
 /*
  * Max AMPDU Tx Aggr supported size
@@ -1335,16 +1336,20 @@ int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id)
 #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */
 
 static uint8_t *
-wma_parse_ch_switch_wrapper_ie(uint8_t *ch_wr_ie, uint8_t sub_ele_id)
+wma_parse_ch_switch_wrapper_ie(uint8_t *ch_wr_ie, uint8_t sub_ele_id,
+			       uint8_t ie_extn_id)
 {
 	uint8_t len = 0, sub_ele_len = 0;
 	struct ie_header *ele;
+	struct extn_ie_header *extn_ie;
 
 	ele = (struct ie_header *)ch_wr_ie;
 	if (ele->ie_id != WLAN_ELEMID_CHAN_SWITCH_WRAP ||
 	    ele->ie_len == 0 || ele->ie_len > (CH_WR_IE_MAX_LEN -
-					       sizeof(struct ie_header)))
+					       sizeof(struct ie_header))) {
+		wma_debug("Invalid len: %d", ele->ie_len);
 		return NULL;
+	}
 
 	len = ele->ie_len;
 	ele = (struct ie_header *)(ch_wr_ie + sizeof(struct ie_header));
@@ -1357,15 +1362,86 @@ wma_parse_ch_switch_wrapper_ie(uint8_t *ch_wr_ie, uint8_t sub_ele_id)
 			return NULL;
 		}
 		len -= sub_ele_len;
-		if (ele->ie_id == sub_ele_id)
-			return (uint8_t *)ele;
-
+		if (ele->ie_id == sub_ele_id) {
+			if (sub_ele_id == WLAN_ELEMID_EXTN_ELEM) {
+				extn_ie = (struct extn_ie_header *)ele;
+				if (extn_ie->ie_extn_id == ie_extn_id)
+					return (uint8_t *)ele;
+			} else {
+				return (uint8_t *)ele;
+			}
+		}
 		ele = (struct ie_header *)((uint8_t *)ele + sub_ele_len);
 	}
 
 	return NULL;
 }
 
+#ifdef WLAN_FEATURE_11BE
+/**
+ * wma_parse_bw_indication_ie(): STA parse bandwidth indication IE of connected
+ * AP for channel switch or puncture update.
+ * @ie: bandwidth indication IE
+ * @tlv_len: total length of ie tlv
+ * @csa_event: struct to save channel switch info
+ *
+ * Return - QDF_STATUS.
+ */
+static
+QDF_STATUS wma_parse_bw_indication_ie(uint8_t *ie,
+				      uint8_t tlv_len,
+				      struct csa_offload_params *csa_event)
+{
+	uint16_t puncture_bitmap = 0;
+	uint8_t *sub_ie;
+	struct wlan_ie_bw_ind *bw_ind;
+	struct ie_header *ie_head;
+	uint8_t ccfs0, ccfs1;
+	enum phy_ch_width ch_width;
+	QDF_STATUS status;
+
+	ie_head = (struct ie_header *)ie;
+	if (ie_head->ie_len + sizeof(struct ie_header) > tlv_len) {
+		wma_err("Invalid ie len: %d, buffer len: %d",
+			ie_head->ie_len, tlv_len);
+		return QDF_STATUS_E_INVAL;
+	}
+	qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+			   ie, tlv_len);
+
+	sub_ie = wma_parse_ch_switch_wrapper_ie(ie,
+						WLAN_ELEMID_EXTN_ELEM,
+						WLAN_EXTN_ELEMID_BW_IND);
+	if (!sub_ie) {
+		wma_err("Invalid ie");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	bw_ind = (struct wlan_ie_bw_ind *)sub_ie;
+
+	status = util_parse_bw_ind(bw_ind, &ccfs0, &ccfs1, &ch_width,
+				   &puncture_bitmap);
+
+	wma_debug("ch width: %d, ccfs0: %d, ccfs1: %d, puncture: %d", ch_width,
+		  ccfs0, ccfs1, puncture_bitmap);
+
+	csa_event->new_ch_width = ch_width;
+	csa_event->new_ch_freq_seg1 = ccfs0;
+	csa_event->new_ch_freq_seg2 = ccfs1;
+	csa_event->new_punct_bitmap = puncture_bitmap;
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static inline
+QDF_STATUS wma_parse_bw_indication_ie(uint8_t *ie,
+				      uint8_t tlv_len,
+				      struct csa_offload_params *csa_event)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+#endif
+
 /**
  * wma_csa_offload_handler() - CSA event handler
  * @handle: wma handle
@@ -1389,6 +1465,8 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
 	struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
 	struct ieee80211_ie_wide_bw_switch *wb_ie;
 	struct wma_txrx_node *intr = wma->interfaces;
+	QDF_STATUS status;
+	uint8_t tlv_len;
 
 	param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event;
 
@@ -1453,6 +1531,19 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
 		return -EINVAL;
 	}
 
+	if (csa_event->ies_present_flag & WMI_CSWRAP_IE_EXT_VER_2_PRESENT) {
+		wma_debug("WMI_CSWRAP_IE_EXT_VER_2 received");
+		tlv_len = csa_event->num_bytes_valid_in_cswrap_ie_ext_ver2;
+		status = wma_parse_bw_indication_ie(param_buf->cs_wrap_ie,
+						    tlv_len,
+						    csa_offload_event);
+		if (QDF_IS_STATUS_SUCCESS(status)) {
+			csa_offload_event->ies_present_flag |=
+					MLME_CSWRAP_IE_EXT_V2_PRESENT;
+			goto got_chan;
+		}
+	}
+
 	if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) {
 		wb_ie = (struct ieee80211_ie_wide_bw_switch *)
 						(&csa_event->wb_ie[0]);
@@ -1467,7 +1558,7 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
 		wb_ie = (struct ieee80211_ie_wide_bw_switch *)
 				wma_parse_ch_switch_wrapper_ie(
 				(uint8_t *)&csa_event->cswrap_ie_extended,
-				WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH);
+				WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH, 0);
 		if (wb_ie) {
 			csa_offload_event->new_ch_width =
 				wlan_mlme_convert_vht_op_bw_to_phy_ch_width(
@@ -1484,6 +1575,7 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
 			MLME_CSWRAP_IE_EXTENDED_PRESENT;
 	}
 
+got_chan:
 	wma_debug("CSA: BSSID "QDF_MAC_ADDR_FMT" chan %d freq %d flag 0x%x width = %d freq1 = %d freq2 = %d op class = %d",
 		 QDF_MAC_ADDR_REF(csa_offload_event->bssid.bytes),
 		 csa_offload_event->channel,