|
@@ -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);
|