ソースを参照

qcacld-3.0: LFR3 changes for MBSSID

Changes to support LFR3 roaming with MBSSID feature.

Change-Id: Ie968d23bbd2efc6b33b774d603394eb3df450cc1
CRs-Fixed: 2439989
Sandeep Puligilla 6 年 前
コミット
5e647f7f3e
1 ファイル変更219 行追加54 行削除
  1. 219 54
      core/mac/src/pe/lim/lim_api.c

+ 219 - 54
core/mac/src/pe/lim/lim_api.c

@@ -73,6 +73,7 @@
 #include <wlan_tdls_cfg_api.h>
 #include "cfg_ucfg_api.h"
 #include "wlan_mlme_public_struct.h"
+#include "wlan_scan_utils_api.h"
 
 static void __lim_init_bss_vars(struct mac_context *mac)
 {
@@ -1893,71 +1894,243 @@ static void sir_parse_bcn_fixed_fields(struct mac_context *mac_ctx,
 	sir_copy_caps_info(mac_ctx, dst, beacon_struct);
 }
 
+static QDF_STATUS
+lim_roam_gen_mbssid_beacon(struct mac_context *mac,
+			   struct roam_offload_synch_ind *roam_ind,
+			   tpSirProbeRespBeacon parsed_frm)
+{
+	qdf_list_t *scan_list;
+	struct mgmt_rx_event_params rx_param;
+	uint8_t list_count = 0, i;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	qdf_list_node_t *next_node = NULL, *cur_node = NULL;
+	struct scan_cache_node *scan_node;
+	struct scan_cache_entry *scan_entry;
+	uint8_t *bcn_prb_ptr;
+	uint32_t nontx_bcn_prbrsp_len = 0, offset, length;
+	uint8_t *nontx_bcn_prbrsp = NULL;
+
+	bcn_prb_ptr = (uint8_t *)roam_ind +
+				roam_ind->beaconProbeRespOffset;
+
+	rx_param.channel = wlan_freq_to_chan(roam_ind->chan_freq);
+	rx_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(mac->pdev);
+	rx_param.rssi = roam_ind->rssi;
+
+	scan_list = util_scan_unpack_beacon_frame(mac->pdev, bcn_prb_ptr,
+						  roam_ind->beaconProbeRespLength,
+						  MGMT_SUBTYPE_BEACON, &rx_param);
+	if (!scan_list) {
+		pe_err("failed to parse");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	list_count = qdf_list_size(scan_list);
+	status = qdf_list_peek_front(scan_list, &cur_node);
+	if (QDF_IS_STATUS_ERROR(status) || !cur_node) {
+		pe_debug("list peek front failure. list size %d", list_count);
+		goto error;
+	}
+
+	for (i = 1; i < list_count; i++) {
+		scan_node = qdf_container_of(cur_node,
+					     struct scan_cache_node, node);
+		scan_entry = scan_node->entry;
+		if (qdf_is_macaddr_equal(&roam_ind->bssid,
+					 &scan_entry->bssid)) {
+			pe_debug("matched BSSID %pM bcn len %d profiles %d",
+				 scan_entry->bssid.bytes,
+				 scan_entry->raw_frame.len,
+				 list_count);
+			nontx_bcn_prbrsp = scan_entry->raw_frame.ptr;
+			nontx_bcn_prbrsp_len = scan_entry->raw_frame.len;
+			QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
+					   QDF_TRACE_LEVEL_DEBUG,
+					   scan_entry->raw_frame.ptr,
+					   nontx_bcn_prbrsp_len);
+			break;
+		}
+		status = qdf_list_peek_next(scan_list, cur_node, &next_node);
+		if (QDF_IS_STATUS_ERROR(status) || !next_node) {
+			pe_debug("list remove failure i:%d, lsize:%d",
+				 i, list_count);
+			goto error;
+		}
+		cur_node = next_node;
+	}
+
+	if (!nontx_bcn_prbrsp_len) {
+		pe_debug("failed to generate/find MBSSID beacon");
+		goto error;
+	}
+
+	if (roam_ind->isBeacon) {
+		offset = SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET;
+		length = nontx_bcn_prbrsp_len - SIR_MAC_HDR_LEN_3A;
+		if (sir_parse_beacon_ie(mac, parsed_frm,
+					&nontx_bcn_prbrsp[offset],
+					length) != QDF_STATUS_SUCCESS ||
+			!parsed_frm->ssidPresent) {
+			pe_err("Parse error Beacon, length: %d",
+			       roam_ind->beaconProbeRespLength);
+			status =  QDF_STATUS_E_FAILURE;
+			goto error;
+		}
+	} else {
+		offset = SIR_MAC_HDR_LEN_3A;
+		length = nontx_bcn_prbrsp_len - SIR_MAC_HDR_LEN_3A;
+		if (sir_convert_probe_frame2_struct(mac,
+					    &nontx_bcn_prbrsp[offset],
+					    length,
+					    parsed_frm) != QDF_STATUS_SUCCESS ||
+			!parsed_frm->ssidPresent) {
+			pe_err("Parse error ProbeResponse, length: %d",
+			       roam_ind->beaconProbeRespLength);
+			status = QDF_STATUS_E_FAILURE;
+			goto error;
+		}
+	}
+
+error:
+	for (i = 0; i < list_count; i++) {
+		status = qdf_list_remove_front(scan_list, &next_node);
+		if (QDF_IS_STATUS_ERROR(status) || !next_node) {
+			pe_debug("list remove failure i:%d, lsize:%d",
+				 i, list_count);
+			break;
+		}
+		scan_node = qdf_container_of(next_node,
+					     struct scan_cache_node, node);
+		util_scan_free_cache_entry(scan_node->entry);
+		qdf_mem_free(scan_node);
+	}
+	if (scan_list)
+		qdf_mem_free(scan_list);
+
+	return status;
+}
+
+static QDF_STATUS
+lim_roam_gen_beacon_descr(struct mac_context *mac,
+			  struct roam_offload_synch_ind *roam_ind,
+			  tpSirProbeRespBeacon parsed_frm)
+{
+	QDF_STATUS status;
+	uint8_t *bcn_prb_ptr;
+	tpSirMacMgmtHdr mac_hdr;
+
+	bcn_prb_ptr = (uint8_t *)roam_ind +
+		roam_ind->beaconProbeRespOffset;
+	mac_hdr = (tpSirMacMgmtHdr)bcn_prb_ptr;
+
+	if (qdf_is_macaddr_zero((struct qdf_mac_addr *)mac_hdr->bssId)) {
+		pe_debug("bssid is 0 in beacon/probe update it with bssId %pM in sync ind",
+			roam_ind->bssid.bytes);
+		qdf_mem_copy(mac_hdr->bssId, roam_ind->bssid.bytes,
+			     sizeof(tSirMacAddr));
+	}
+
+	if (qdf_mem_cmp(&roam_ind->bssid.bytes,
+			&mac_hdr->bssId, QDF_MAC_ADDR_SIZE) != 0) {
+		pe_debug("LFR3:MBSSID Beacon/Prb Rsp: %d bssid %pM",
+			 roam_ind->isBeacon,
+			 mac_hdr->bssId);
+		/*
+		 * Its a MBSSID non-tx BSS roaming scenario.
+		 * Generate non tx BSS beacon/probe response
+		 */
+		status = lim_roam_gen_mbssid_beacon(mac,
+						    roam_ind,
+						    parsed_frm);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			pe_err("failed to gen mbssid beacon");
+			qdf_mem_free(parsed_frm);
+			return QDF_STATUS_E_FAILURE;
+		}
+	} else {
+		if (roam_ind->isBeacon) {
+			if (sir_parse_beacon_ie(mac, parsed_frm,
+				&bcn_prb_ptr[SIR_MAC_HDR_LEN_3A +
+				SIR_MAC_B_PR_SSID_OFFSET],
+				roam_ind->beaconProbeRespLength -
+				SIR_MAC_HDR_LEN_3A) != QDF_STATUS_SUCCESS ||
+				!parsed_frm->ssidPresent) {
+				pe_err("Parse error Beacon, length: %d",
+				       roam_ind->beaconProbeRespLength);
+				qdf_mem_free(parsed_frm);
+				return QDF_STATUS_E_FAILURE;
+			}
+		} else {
+			if (sir_convert_probe_frame2_struct(mac,
+				&bcn_prb_ptr[SIR_MAC_HDR_LEN_3A],
+				roam_ind->beaconProbeRespLength -
+				SIR_MAC_HDR_LEN_3A, parsed_frm) !=
+				QDF_STATUS_SUCCESS ||
+				!parsed_frm->ssidPresent) {
+				pe_err("Parse error ProbeResponse, length: %d",
+				       roam_ind->beaconProbeRespLength);
+				qdf_mem_free(parsed_frm);
+				return QDF_STATUS_E_FAILURE;
+			}
+		}
+	}
+	/*
+	 * For probe response, unpack core parses beacon interval, capabilities,
+	 * timestamp. For beacon IEs, these fields are not parsed.
+	 */
+	if (roam_ind->isBeacon)
+		sir_parse_bcn_fixed_fields(mac, parsed_frm,
+			&bcn_prb_ptr[SIR_MAC_HDR_LEN_3A]);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 static QDF_STATUS
 lim_roam_fill_bss_descr(struct mac_context *mac,
-			struct roam_offload_synch_ind *roam_offload_synch_ind_ptr,
+			struct roam_offload_synch_ind *roam_synch_ind_ptr,
 			struct bss_description *bss_desc_ptr)
 {
 	uint32_t ie_len = 0;
 	tpSirProbeRespBeacon parsed_frm_ptr;
 	tpSirMacMgmtHdr mac_hdr;
 	uint8_t *bcn_proberesp_ptr;
+	QDF_STATUS status;
 
-	bcn_proberesp_ptr = (uint8_t *)roam_offload_synch_ind_ptr +
-		roam_offload_synch_ind_ptr->beaconProbeRespOffset;
+	bcn_proberesp_ptr = (uint8_t *)roam_synch_ind_ptr +
+		roam_synch_ind_ptr->beaconProbeRespOffset;
 	mac_hdr = (tpSirMacMgmtHdr)bcn_proberesp_ptr;
 	parsed_frm_ptr = qdf_mem_malloc(sizeof(tSirProbeRespBeacon));
 	if (!parsed_frm_ptr)
 		return QDF_STATUS_E_NOMEM;
 
-	if (roam_offload_synch_ind_ptr->beaconProbeRespLength <=
+	if (roam_synch_ind_ptr->beaconProbeRespLength <=
 			SIR_MAC_HDR_LEN_3A) {
-		pe_err("%s: very few bytes in synchInd beacon / probe resp frame! length: %d",
-		__func__, roam_offload_synch_ind_ptr->beaconProbeRespLength);
+		pe_err("very few bytes in synchInd beacon / probe resp frame! length: %d",
+		       roam_synch_ind_ptr->beaconProbeRespLength);
 		qdf_mem_free(parsed_frm_ptr);
 		return QDF_STATUS_E_FAILURE;
 	}
-
-	pe_debug("LFR3:Beacon/Prb Rsp: %d", roam_offload_synch_ind_ptr->isBeacon);
+	pe_debug("LFR3:Beacon/Prb Rsp: %d bssid %pM beacon %pM",
+		 roam_synch_ind_ptr->isBeacon,
+		 roam_synch_ind_ptr->bssid.bytes,
+		 mac_hdr->bssId);
 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
-	bcn_proberesp_ptr, roam_offload_synch_ind_ptr->beaconProbeRespLength);
-	if (roam_offload_synch_ind_ptr->isBeacon) {
-		if (sir_parse_beacon_ie(mac, parsed_frm_ptr,
-			&bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A +
-			SIR_MAC_B_PR_SSID_OFFSET],
-			roam_offload_synch_ind_ptr->beaconProbeRespLength -
-			SIR_MAC_HDR_LEN_3A) != QDF_STATUS_SUCCESS ||
-			!parsed_frm_ptr->ssidPresent) {
-			pe_err("Parse error Beacon, length: %d",
-			roam_offload_synch_ind_ptr->beaconProbeRespLength);
-			qdf_mem_free(parsed_frm_ptr);
-			return QDF_STATUS_E_FAILURE;
-		}
-	} else {
-		if (sir_convert_probe_frame2_struct(mac,
-			&bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A],
-			roam_offload_synch_ind_ptr->beaconProbeRespLength -
-			SIR_MAC_HDR_LEN_3A, parsed_frm_ptr) != QDF_STATUS_SUCCESS ||
-			!parsed_frm_ptr->ssidPresent) {
-			pe_err("Parse error ProbeResponse, length: %d",
-			roam_offload_synch_ind_ptr->beaconProbeRespLength);
-			qdf_mem_free(parsed_frm_ptr);
-			return QDF_STATUS_E_FAILURE;
-		}
+			   bcn_proberesp_ptr,
+			   roam_synch_ind_ptr->beaconProbeRespLength);
+
+	status = lim_roam_gen_beacon_descr(mac,
+					   roam_synch_ind_ptr,
+					   parsed_frm_ptr);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		pe_err("Failed to parse beacon");
+		qdf_mem_free(parsed_frm_ptr);
+		return QDF_STATUS_E_FAILURE;
 	}
 
-	/*
-	 * For probe response, unpack core parses beacon interval, capabilities,
-	 * timestamp. For beacon IEs, these fields are not parsed.
-	 */
-	if (roam_offload_synch_ind_ptr->isBeacon)
-		sir_parse_bcn_fixed_fields(mac, parsed_frm_ptr,
-			&bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A]);
-
 	/* 24 byte MAC header and 12 byte to ssid IE */
-	if (roam_offload_synch_ind_ptr->beaconProbeRespLength >
+	if (roam_synch_ind_ptr->beaconProbeRespLength >
 		(SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) {
-		ie_len = roam_offload_synch_ind_ptr->beaconProbeRespLength -
+		ie_len = roam_synch_ind_ptr->beaconProbeRespLength -
 			(SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET);
 	}
 	/*
@@ -1976,7 +2149,7 @@ lim_roam_fill_bss_descr(struct mac_context *mac,
 					   ieFields[0]) -
 				sizeof(bss_desc_ptr->length) + ie_len);
 
-	bss_desc_ptr->fProbeRsp = !roam_offload_synch_ind_ptr->isBeacon;
+	bss_desc_ptr->fProbeRsp = !roam_synch_ind_ptr->isBeacon;
 	/* Copy Timestamp */
 	bss_desc_ptr->scansystimensec = qdf_get_monotonic_boottime_ns();
 	if (parsed_frm_ptr->dsParamsPresent) {
@@ -1989,7 +2162,7 @@ lim_roam_fill_bss_descr(struct mac_context *mac,
 		 * beacon, then use the channel frequency provided by firmware
 		 * to fill the channel in the BSS descriptor.*/
 		bss_desc_ptr->channelId =
-			cds_freq_to_chan(roam_offload_synch_ind_ptr->chan_freq);
+			cds_freq_to_chan(roam_synch_ind_ptr->chan_freq);
 	}
 	bss_desc_ptr->channelIdSelf = bss_desc_ptr->channelId;
 
@@ -2004,17 +2177,9 @@ lim_roam_fill_bss_descr(struct mac_context *mac,
 	qdf_mem_copy(&bss_desc_ptr->capabilityInfo,
 	&bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_CAPAB_OFFSET], 2);
 
-	if (qdf_is_macaddr_zero((struct qdf_mac_addr *)mac_hdr->bssId)) {
-		pe_debug("bssid is 0 in beacon/probe update it with bssId %pM in sync ind",
-			roam_offload_synch_ind_ptr->bssid.bytes);
-		qdf_mem_copy(mac_hdr->bssId,
-			roam_offload_synch_ind_ptr->bssid.bytes,
-			sizeof(tSirMacAddr));
-	}
-
 	qdf_mem_copy((uint8_t *) &bss_desc_ptr->bssId,
-			(uint8_t *) mac_hdr->bssId,
-			sizeof(tSirMacAddr));
+		     (uint8_t *)roam_synch_ind_ptr->bssid.bytes,
+		     sizeof(tSirMacAddr));
 	bss_desc_ptr->received_time =
 		      (uint64_t)qdf_mc_timer_get_system_time();
 	if (parsed_frm_ptr->mdiePresent) {