Bladeren bron

qcacld-3.0: Select first clean channel for ACS to optimize SAP turn on time

Currently, ACS computation triggers when ACS scan complete event is
received after firmware has scanned all channels. This leads to
delay in selection on SAP channel.
As an optimization, this change selects the first clean channel
while scan is still in progress. The criteria for first clean channel
is that no beacon/probe response should be received on that channel.
If such channel is obtained while scan is in progress, then select this
channel as SAP channel and abort ongoing scan. Firmware sends
wma_chan_info_event per channel this change uses this event as an
indication that scan is completed on that channel.

To further increase the optimize the time to get clean channel, sort the
ACS frequency list in descending order in ACS SCAN request to
firmware. Firmware scans the channel in the order given by host
in scan request, as higher band channels are less occupied, the
probability of getting clean channel initially will increase, which
will lead to selecting the channel in less time and thereby reduce
the SAP turn on time.

Change-Id: I1a38556862b66943edea08783436f5e1e3a255f6
CRs-Fixed: 3245166
Surabhi Vishnoi 2 jaren geleden
bovenliggende
commit
ef08e7a4c4

+ 28 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -7855,3 +7855,31 @@ bool hdd_is_peer_associated(struct hdd_adapter *adapter,
 
 	return is_associated;
 }
+
+#ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
+bool hdd_sap_is_acs_in_progress(struct wlan_objmgr_vdev *vdev)
+{
+	struct hdd_adapter *adapter;
+	bool in_progress = false;
+
+	if (!vdev) {
+		hdd_err("vdev is NULL");
+		return in_progress;
+	}
+
+	adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
+	if (!adapter) {
+		hdd_err("null adapter");
+		return in_progress;
+	}
+
+	if (!hdd_adapter_is_ap(adapter)) {
+		hdd_err("vdev id %d is not AP", adapter->vdev_id);
+		return in_progress;
+	}
+
+	in_progress = qdf_atomic_read(&adapter->session.ap.acs_in_progress);
+
+	return in_progress;
+}
+#endif

+ 16 - 0
core/hdd/src/wlan_hdd_hostapd.h

@@ -483,4 +483,20 @@ static inline void wlan_hdd_mlo_reset(struct hdd_adapter *adapter)
 {
 }
 #endif /* end WLAN_FEATURE_11BE_MLO */
+
+#ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
+/**
+ * hdd_sap_is_acs_in_progress() - API to return if ACS is in progress
+ * @vdev: pointer t vdev object
+ *
+ * Return: bool
+ */
+bool hdd_sap_is_acs_in_progress(struct wlan_objmgr_vdev *vdev);
+#else
+static inline
+bool hdd_sap_is_acs_in_progress(struct wlan_objmgr_vdev *vdev)
+{
+	return false;
+}
+#endif
 #endif /* end #if !defined(WLAN_HDD_HOSTAPD_H) */

+ 9 - 0
core/sap/inc/sap_api.h

@@ -1825,11 +1825,20 @@ static inline bool sap_is_acs_scan_optimize_enable(void)
 {
 	return true;
 }
+
+void wlansap_process_chan_info_event(struct sap_context *sap_ctx,
+				     struct csr_roam_info *roam_info);
 #else
 static inline bool sap_is_acs_scan_optimize_enable(void)
 {
 	return false;
 }
+
+static inline
+void wlansap_process_chan_info_event(struct sap_context *sap_ctx,
+				     struct csr_roam_info *roam_info)
+{
+}
 #endif
 
 #ifdef __cplusplus

+ 90 - 0
core/sap/src/sap_api_link_cntl.c

@@ -53,6 +53,8 @@
 #include <wlan_scan_api.h>
 #include <wlan_scan_utils_api.h>
 #include "wlan_pre_cac_api.h"
+#include <wlan_cfg80211_scan.h>
+#include <wlan_hdd_hostapd.h>
 
 /* IF MGR API header file */
 #include "wlan_if_mgr_ucfg_api.h"
@@ -343,6 +345,11 @@ QDF_STATUS wlansap_pre_start_bss_acs_scan_callback(mac_handle_t mac_handle,
 	host_log_acs_scan_done(acs_scan_done_status_str(scan_status),
 			  sessionid, scanid);
 
+	if (sap_ctx->optimize_acs_chan_selected) {
+		sap_debug("SAP channel selected using first clean channel, ignore scan complete event");
+		return QDF_STATUS_SUCCESS;
+	}
+
 	/* This has to be done before the ACS selects default channel */
 	wlansap_filter_unsafe_ch(mac_ctx->psoc, sap_ctx);
 
@@ -1195,6 +1202,9 @@ QDF_STATUS wlansap_roam_callback(void *ctx,
 	case eCSR_ROAM_EXT_CHG_CHNL_IND:
 		sap_debug("Received set channel Indication");
 		break;
+	case eCSR_ROAM_CHANNEL_INFO_EVENT_IND:
+		wlansap_process_chan_info_event(sap_ctx, csr_roam_info);
+		break;
 	default:
 		break;
 	}
@@ -1455,3 +1465,83 @@ void sap_scan_event_callback(struct wlan_objmgr_vdev *vdev,
 						arg, session_id,
 						scan_id, scan_status);
 }
+
+#ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
+#define WLAN_INVALID_PDEV_ID 0xFFFFFFFF
+void wlansap_process_chan_info_event(struct sap_context *sap_ctx,
+				     struct csr_roam_info *roam_info)
+{
+	struct mac_context *mac;
+	struct scan_filter *filter;
+	qdf_list_t *list = NULL;
+
+	mac = sap_get_mac_context();
+	if (!mac) {
+		sap_err("Invalid MAC context");
+		return;
+	}
+
+	if (!hdd_sap_is_acs_in_progress(sap_ctx->vdev))
+		return;
+
+	if (SAP_INIT != sap_ctx->fsm_state)
+		return;
+
+	if (WLAN_REG_IS_24GHZ_CH_FREQ(roam_info->chan_info_freq) ||
+	    sap_ctx->acs_cfg->ch_width != CH_WIDTH_20MHZ)
+		return;
+
+	if (sap_ctx->optimize_acs_chan_selected)
+		return;
+
+	filter = qdf_mem_malloc(sizeof(*filter));
+	if (!filter)
+		return;
+
+	filter->age_threshold = qdf_get_time_of_the_day_ms() -
+				sap_ctx->acs_req_timestamp;
+	filter->num_of_channels = 1;
+	filter->chan_freq_list[0] = roam_info->chan_info_freq;
+
+	list = ucfg_scan_get_result(mac->pdev, filter);
+	qdf_mem_free(filter);
+	if (!list)
+		return;
+
+	if (qdf_list_size(list))
+		goto exit;
+
+	if (!policy_mgr_is_sap_freq_allowed(mac->psoc,
+					    roam_info->chan_info_freq))
+		goto exit;
+
+	sap_debug("ACS Best channel %d as no beacon/probe rsp found\n",
+		  roam_info->chan_info_freq);
+
+	sap_ctx->optimize_acs_chan_selected = true;
+
+	wlan_abort_scan(mac->pdev, WLAN_INVALID_PDEV_ID,
+			sap_ctx->sessionId, INVALID_SCAN_ID, false);
+
+	wlansap_set_acs_ch_freq(sap_ctx, roam_info->chan_info_freq);
+	sap_ctx->acs_cfg->pri_ch_freq = roam_info->chan_info_freq;
+	sap_config_acs_result(MAC_HANDLE(mac), sap_ctx,
+			      sap_ctx->acs_cfg->ht_sec_ch_freq);
+
+	wlansap_dump_acs_ch_freq(sap_ctx);
+
+	sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED;
+	sap_ctx->sap_status = eSAP_STATUS_SUCCESS;
+
+	if (sap_ctx->freq_list) {
+		qdf_mem_free(sap_ctx->freq_list);
+		sap_ctx->freq_list = NULL;
+		sap_ctx->num_of_channel = 0;
+	}
+
+	sap_hdd_signal_event_handler(sap_ctx);
+
+exit:
+	ucfg_scan_purge_results(list);
+}
+#endif

+ 20 - 0
core/sap/src/sap_fsm.c

@@ -1204,6 +1204,23 @@ validation_done:
 }
 
 #ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
+
+static void sap_sort_freq_list(struct chan_list *list,
+			       uint8_t num_ch)
+{
+	int i, j, temp;
+
+	for (i = 0; i < num_ch - 1; i++) {
+		for (j = 0 ; j < num_ch - i - 1; j++) {
+			if (list->chan[j].freq < list->chan[j + 1].freq) {
+				temp = list->chan[j].freq;
+				list->chan[j].freq = list->chan[j + 1].freq;
+				list->chan[j + 1].freq = temp;
+			}
+		}
+	}
+}
+
 /**
  * sap_acs_scan_freq_list_optimize - optimize the ACS scan freq list based
  * on when last scan was performed on particular frequency. If last scan
@@ -1247,6 +1264,8 @@ static void sap_acs_scan_freq_list_optimize(struct sap_context *sap_ctx,
 	}
 	if (*ch_count == 0)
 		sap_info("All ACS freq channels are scanned recently, skip ACS scan\n");
+	else
+		sap_sort_freq_list(list, *ch_count);
 }
 #else
 static void sap_acs_scan_freq_list_optimize(struct sap_context *sap_ctx,
@@ -1363,6 +1382,7 @@ QDF_STATUS sap_channel_sel(struct sap_context *sap_context)
 		req->scan_req.chan_list.num_chan = j;
 		sap_context->freq_list = freq_list;
 		sap_context->num_of_channel = num_of_channels;
+		sap_context->optimize_acs_chan_selected = false;
 		/* Set requestType to Full scan */
 
 		/*

+ 1 - 0
core/sap/src/sap_internal.h

@@ -243,6 +243,7 @@ struct sap_context {
 #endif
 	bool require_h2e;
 	bool partial_acs_scan;
+	bool optimize_acs_chan_selected;
 };
 
 /*----------------------------------------------------------------------------

+ 4 - 0
core/sme/inc/csr_api.h

@@ -286,6 +286,7 @@ typedef enum {
 	eCSR_ROAM_CHANNEL_COMPLETE_IND = 47,
 	eCSR_ROAM_CAC_COMPLETE_IND = 48,
 	eCSR_ROAM_SAE_COMPUTE = 49,
+	eCSR_ROAM_CHANNEL_INFO_EVENT_IND = 50,
 } eRoamCmdStatus;
 
 /* comment inside indicates what roaming callback gets */
@@ -593,6 +594,9 @@ struct csr_roam_info {
 #endif
 	struct assoc_ind *owe_pending_assoc_ind;
 	struct qdf_mac_addr peer_mld;
+#ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
+	uint32_t chan_info_freq;
+#endif
 };
 
 typedef struct sSirSmeAssocIndToUpperLayerCnf {

+ 48 - 0
core/sme/src/common/sme_api.c

@@ -2602,6 +2602,52 @@ static void sme_link_lost_ind(struct mac_context *mac,
 		mac->sme.lost_link_info_cb(mac->hdd_handle, ind);
 }
 
+#ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
+static void sme_indicate_chan_info_event(struct mac_context *mac,
+					 struct channel_status *chan_stats,
+					 uint8_t vdev_id)
+{
+	struct csr_roam_info *roam_info;
+	struct wlan_objmgr_vdev *vdev;
+	eRoamCmdStatus roam_status;
+	eCsrRoamResult roam_result;
+	enum QDF_OPMODE mode;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id,
+						    WLAN_LEGACY_SME_ID);
+	if (!vdev) {
+		sme_err("vdev not found for vdev %d", vdev_id);
+		return;
+	}
+
+	mode = wlan_vdev_mlme_get_opmode(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
+
+	if (mode != QDF_SAP_MODE)
+		return;
+
+	roam_info = qdf_mem_malloc(sizeof(*roam_info));
+	if (!roam_info)
+		return;
+
+	roam_info->chan_info_freq = chan_stats->channel_freq;
+	roam_status = eCSR_ROAM_CHANNEL_INFO_EVENT_IND;
+	roam_result = eCSR_ROAM_RESULT_NONE;
+
+	/* Indicate channel info event to SAP */
+	csr_roam_call_callback(mac, vdev_id, roam_info,
+			       roam_status, roam_result);
+
+	qdf_mem_free(roam_info);
+}
+#else
+static void sme_indicate_chan_info_event(struct mac_context *mac,
+					 struct channel_status *chan_stats,
+					 uint8_t vdev_id)
+{
+}
+#endif
+
 static void sme_process_chan_info_event(struct mac_context *mac,
 					struct channel_status *chan_stats,
 					uint8_t vdev_id)
@@ -2613,6 +2659,8 @@ static void sme_process_chan_info_event(struct mac_context *mac,
 
 	if (mac->sap.acs_with_more_param || sap_is_acs_scan_optimize_enable())
 		wlan_cp_stats_update_chan_info(mac->psoc, chan_stats, vdev_id);
+
+	sme_indicate_chan_info_event(mac, chan_stats, vdev_id);
 }
 
 QDF_STATUS sme_process_msg(struct mac_context *mac, struct scheduler_msg *pMsg)

+ 1 - 0
core/sme/src/csr/csr_util.c

@@ -67,6 +67,7 @@ const char *get_e_roam_cmd_status_str(eRoamCmdStatus val)
 		CASE_RETURN_STR(eCSR_ROAM_NDP_STATUS_UPDATE);
 		CASE_RETURN_STR(eCSR_ROAM_CHANNEL_COMPLETE_IND);
 		CASE_RETURN_STR(eCSR_ROAM_SAE_COMPUTE);
+		CASE_RETURN_STR(eCSR_ROAM_CHANNEL_INFO_EVENT_IND);
 	default:
 		return "unknown";
 	}