Kaynağa Gözat

qcacld-3.0: Select Best/Clean channel for SAP

Currently, For CH_WIDTH 20 first clean channel is selected
to start the SAP but logic was not applicable to other band
wdiths because FW can start scan in parallel and for bandwidth
> 20 MHz multiple continuous channels may require to scan and
data was not maintained in host that which channel is scanned
and which is pending.
To Extend logic for bandwidth > 20 MHz, introduce bool array
to maintain data which channel is scanned and found clean. For next
Channel scan same array can be used to check if previous channels
are clean and SAP can be started on current frequency or not.

Change-Id: I9993c0b26885210b4173946e780833dc87830daf
CRs-Fixed: 3403455
Sheenam Monga 2 yıl önce
ebeveyn
işleme
d8093c7ab4

+ 138 - 2
core/sap/src/sap_api_link_cntl.c

@@ -1486,6 +1486,133 @@ void sap_scan_event_callback(struct wlan_objmgr_vdev *vdev,
 
 #ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
 #define WLAN_INVALID_PDEV_ID 0xFFFFFFFF
+/**
+ * sap_mark_freq_as_clean(): This API marks a channel is clean which means
+ * we didn't see any AP's on this channel
+ * @clean_channel_array: array of chan enum containing that chan free or not
+ * @freq: freq for which flag needs to be updated
+ *
+ * Return: void
+ */
+static
+void sap_mark_freq_as_clean(bool *clean_channel_array,
+			    qdf_freq_t freq)
+{
+	uint32_t ch_index;
+	ch_index = wlan_reg_get_chan_enum_for_freq(freq);
+	if (ch_index >= INVALID_CHANNEL)
+		return;
+	clean_channel_array[ch_index] = true;
+}
+
+/**
+ * sap_is_prev_n_freqs_free(): previous frequencies free or not based on channel
+ * width
+ * @clean_channel_array: array of chan enum containing that chan free or not
+ * @curr_index: Chan enum of current scanned channel
+ * @prev_n_freq_count: no. of freq  to be monitored based on BW
+ * @range: Bonded channel freq range
+ *
+ *Return: true if previous channels free else false
+ */
+static
+bool sap_is_prev_n_freqs_free(bool *clean_channel_array, uint32_t curr_index,
+			      uint32_t prev_n_freq_count,
+			      const struct bonded_channel_freq *range)
+{
+	uint32_t index;
+	uint32_t min_index = wlan_reg_get_chan_enum_for_freq(range->start_freq);
+	uint32_t max_index = wlan_reg_get_chan_enum_for_freq(range->end_freq);
+	if (max_index >= INVALID_CHANNEL ||
+	    min_index >= INVALID_CHANNEL)
+		return false;
+	if (curr_index > max_index || curr_index < min_index) {
+		sap_debug("invalid chan index %d", curr_index);
+		return false;
+	}
+	/*
+	 * curr_index will be present in range, so bonded freq
+	 * range can be checked to decide curr_index is best
+	 * available channel or not.
+	 */
+	for (index = min_index; index > 0 && index <= max_index;
+	     index++) {
+		if (!clean_channel_array[index])
+			return false;
+	}
+	if ((index - min_index) != prev_n_freq_count) {
+		sap_debug("previous %d are not validated", prev_n_freq_count);
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * is_freq_allowed_for_sap(): is frequency allowed to start SAP
+ * @pdev: object manager pdev
+ * @clean_channel_array: array of chan enum containing that chan free or not
+ * @freq: Scanned frequency
+ * @ch_width: phy channel width
+ *
+ * Return: true if frequency is allowed based on BW else false.
+ */
+static
+bool is_freq_allowed_for_sap(struct wlan_objmgr_pdev *pdev,
+			     bool *clean_channel_array,
+			     qdf_freq_t freq, enum phy_ch_width ch_width) {
+	uint16_t min_bw = 0;
+	uint16_t max_bw = 0;
+	uint16_t curr_bw;
+	QDF_STATUS status;
+	const struct bonded_channel_freq *range = NULL;
+	uint32_t curr_index = wlan_reg_get_chan_enum_for_freq(freq);
+	if (curr_index >= INVALID_CHANNEL)
+		return false;
+	status =
+	wlan_reg_get_min_max_bw_for_chan_index(pdev, curr_index, &min_bw,
+					       &max_bw);
+	if (status != QDF_STATUS_SUCCESS) {
+		sap_err("get bw for curr channel failed");
+		return false;
+	}
+	curr_bw = wlan_reg_get_bw_value(ch_width);
+	if (curr_bw < min_bw || curr_bw > max_bw) {
+		sap_debug("frequency doesn't support configured bw");
+		return false;
+	}
+	range = wlan_reg_get_bonded_chan_entry(freq, ch_width, 0);
+	if (!range) {
+		sap_debug("Invalid freq range for freq: %d and ch_width: %d",
+			  freq, ch_width);
+		return false;
+	}
+	sap_debug("freq range for bw %d is %d-%d", ch_width, range->start_freq,
+		  range->end_freq);
+
+	switch (ch_width) {
+	case CH_WIDTH_40MHZ:
+		return sap_is_prev_n_freqs_free(clean_channel_array,
+						curr_index, 40/20 - 1,
+						range);
+	case CH_WIDTH_80MHZ:
+		return sap_is_prev_n_freqs_free(clean_channel_array,
+						curr_index, 80/20 - 1,
+						range);
+	case CH_WIDTH_160MHZ:
+		return sap_is_prev_n_freqs_free(clean_channel_array,
+						curr_index, 160/20 - 1,
+						range);
+	case CH_WIDTH_320MHZ:
+		return sap_is_prev_n_freqs_free(clean_channel_array,
+						curr_index, 320/20 - 1,
+						range);
+	default:
+		return false;
+	}
+	return false;
+}
+
 void wlansap_process_chan_info_event(struct sap_context *sap_ctx,
 				     struct csr_roam_info *roam_info)
 {
@@ -1505,8 +1632,7 @@ void wlansap_process_chan_info_event(struct sap_context *sap_ctx,
 	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)
+	if (WLAN_REG_IS_24GHZ_CH_FREQ(roam_info->chan_info_freq))
 		return;
 
 	if (sap_ctx->optimize_acs_chan_selected)
@@ -1553,6 +1679,16 @@ void wlansap_process_chan_info_event(struct sap_context *sap_ctx,
 	if (!policy_mgr_is_sap_freq_allowed(mac->psoc,
 					    roam_info->chan_info_freq))
 		goto exit;
+	if (sap_ctx->acs_cfg->ch_width > CH_WIDTH_20MHZ) {
+		sap_mark_freq_as_clean(sap_ctx->clean_channel_array,
+				       roam_info->chan_info_freq);
+		if (!is_freq_allowed_for_sap(mac->pdev,
+					     sap_ctx->clean_channel_array,
+					     roam_info->chan_info_freq,
+					     sap_ctx->acs_cfg->ch_width)) {
+			goto exit;
+		}
+	}
 
 	sap_debug("ACS Best channel %d as no beacon/probe rsp found\n",
 		  roam_info->chan_info_freq);

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

@@ -1355,6 +1355,25 @@ static void sap_acs_scan_freq_list_optimize(struct sap_context *sap_ctx,
 }
 #endif
 
+#ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
+/**
+ * sap_reset_clean_freq_array(): clear freq array that contains info
+ * channel is free or not
+ * @sap_context: sap context
+ *
+ * Return: void
+ */
+static
+void sap_reset_clean_freq_array(struct sap_context *sap_context)
+{
+	memset(sap_context->clean_channel_array, 0, NUM_CHANNELS);
+}
+#else
+static inline
+void sap_reset_clean_freq_array(struct sap_context *sap_context)
+{}
+#endif
+
 QDF_STATUS sap_channel_sel(struct sap_context *sap_context)
 {
 	QDF_STATUS qdf_ret_status;
@@ -1463,6 +1482,7 @@ QDF_STATUS sap_channel_sel(struct sap_context *sap_context)
 		sap_context->freq_list = freq_list;
 		sap_context->num_of_channel = num_of_channels;
 		sap_context->optimize_acs_chan_selected = false;
+		sap_reset_clean_freq_array(sap_context);
 		/* Set requestType to Full scan */
 
 		/*

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -247,6 +247,13 @@ struct sap_context {
 	bool require_h2e;
 	bool partial_acs_scan;
 	bool optimize_acs_chan_selected;
+#ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
+/*
+ * This param is used to track clean channels where there
+ * is no AP found on these channels
+ */
+	bool clean_channel_array[NUM_CHANNELS];
+#endif
 };
 
 /*----------------------------------------------------------------------------