|
@@ -283,6 +283,119 @@ static void dfs_nol_delete(struct wlan_dfs *dfs,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
|
|
|
+/**
|
|
|
+ * dfs_switch_to_postnol_chan_if_nol_expired() - Find if NOL is expired
|
|
|
+ * in the postNOL channel configured. If true, trigger channel change.
|
|
|
+ * @dfs: Pointer to DFS of wlan_dfs structure.
|
|
|
+ *
|
|
|
+ * Return: True, if channel change is triggered, else false.
|
|
|
+ */
|
|
|
+static bool
|
|
|
+dfs_switch_to_postnol_chan_if_nol_expired(struct wlan_dfs *dfs)
|
|
|
+{
|
|
|
+ struct dfs_channel chan;
|
|
|
+ struct dfs_channel *curchan = dfs->dfs_curchan;
|
|
|
+ bool is_curchan_11ac = false, is_curchan_11axa = false;
|
|
|
+ enum wlan_phymode postnol_phymode;
|
|
|
+
|
|
|
+ if (!dfs->dfs_chan_postnol_freq)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (WLAN_IS_CHAN_11AC_VHT20(curchan) ||
|
|
|
+ WLAN_IS_CHAN_11AC_VHT40(curchan) ||
|
|
|
+ WLAN_IS_CHAN_11AC_VHT80(curchan) ||
|
|
|
+ WLAN_IS_CHAN_11AC_VHT160(curchan) ||
|
|
|
+ WLAN_IS_CHAN_11AC_VHT80_80(curchan))
|
|
|
+ is_curchan_11ac = true;
|
|
|
+ else if (WLAN_IS_CHAN_11AXA_HE20(curchan) ||
|
|
|
+ WLAN_IS_CHAN_11AXA_HE40PLUS(curchan) ||
|
|
|
+ WLAN_IS_CHAN_11AXA_HE40MINUS(curchan) ||
|
|
|
+ WLAN_IS_CHAN_11AXA_HE80(curchan) ||
|
|
|
+ WLAN_IS_CHAN_11AXA_HE160(curchan) ||
|
|
|
+ WLAN_IS_CHAN_11AXA_HE80_80(curchan))
|
|
|
+ is_curchan_11axa = true;
|
|
|
+
|
|
|
+ switch (dfs->dfs_chan_postnol_mode) {
|
|
|
+ case CH_WIDTH_20MHZ:
|
|
|
+ if (is_curchan_11ac)
|
|
|
+ postnol_phymode = WLAN_PHYMODE_11AC_VHT20;
|
|
|
+ else if (is_curchan_11axa)
|
|
|
+ postnol_phymode = WLAN_PHYMODE_11AXA_HE20;
|
|
|
+ else
|
|
|
+ return false;
|
|
|
+ break;
|
|
|
+ case CH_WIDTH_40MHZ:
|
|
|
+ if (is_curchan_11ac)
|
|
|
+ postnol_phymode = WLAN_PHYMODE_11AC_VHT40;
|
|
|
+ else if (is_curchan_11axa)
|
|
|
+ postnol_phymode = WLAN_PHYMODE_11AXA_HE40;
|
|
|
+ else
|
|
|
+ return false;
|
|
|
+ break;
|
|
|
+ case CH_WIDTH_80MHZ:
|
|
|
+ if (is_curchan_11ac)
|
|
|
+ postnol_phymode = WLAN_PHYMODE_11AC_VHT80;
|
|
|
+ else if (is_curchan_11axa)
|
|
|
+ postnol_phymode = WLAN_PHYMODE_11AXA_HE80;
|
|
|
+ else
|
|
|
+ return false;
|
|
|
+ break;
|
|
|
+ case CH_WIDTH_160MHZ:
|
|
|
+ if (is_curchan_11ac)
|
|
|
+ postnol_phymode = WLAN_PHYMODE_11AC_VHT160;
|
|
|
+ else if (is_curchan_11axa)
|
|
|
+ postnol_phymode = WLAN_PHYMODE_11AXA_HE160;
|
|
|
+ else
|
|
|
+ return false;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
|
|
|
+ "Invalid postNOL mode set. Cannot switch to the chan");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ qdf_mem_zero(&chan, sizeof(struct dfs_channel));
|
|
|
+ if (QDF_STATUS_SUCCESS !=
|
|
|
+ dfs_mlme_find_dot11_chan_for_freq(
|
|
|
+ dfs->dfs_pdev_obj,
|
|
|
+ dfs->dfs_chan_postnol_freq,
|
|
|
+ dfs->dfs_chan_postnol_cfreq2,
|
|
|
+ postnol_phymode,
|
|
|
+ &chan.dfs_ch_freq,
|
|
|
+ &chan.dfs_ch_flags,
|
|
|
+ &chan.dfs_ch_flagext,
|
|
|
+ &chan.dfs_ch_ieee,
|
|
|
+ &chan.dfs_ch_vhtop_ch_freq_seg1,
|
|
|
+ &chan.dfs_ch_vhtop_ch_freq_seg2,
|
|
|
+ &chan.dfs_ch_mhz_freq_seg1,
|
|
|
+ &chan.dfs_ch_mhz_freq_seg2)) {
|
|
|
+ dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
|
|
|
+ "Channel %d not found for mode %d and cfreq2 %d",
|
|
|
+ dfs->dfs_chan_postnol_freq,
|
|
|
+ postnol_phymode,
|
|
|
+ dfs->dfs_chan_postnol_cfreq2);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (WLAN_IS_CHAN_RADAR(&chan))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (global_dfs_to_mlme.mlme_postnol_chan_switch)
|
|
|
+ global_dfs_to_mlme.mlme_postnol_chan_switch(
|
|
|
+ dfs->dfs_pdev_obj,
|
|
|
+ dfs->dfs_chan_postnol_freq,
|
|
|
+ dfs->dfs_chan_postnol_cfreq2,
|
|
|
+ postnol_phymode);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline bool
|
|
|
+dfs_switch_to_postnol_chan_if_nol_expired(struct wlan_dfs *dfs)
|
|
|
+{
|
|
|
+ return false;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/**
|
|
|
* dfs_remove_from_nol() - Remove the freq from NOL list.
|
|
|
*
|
|
@@ -316,11 +429,26 @@ static os_timer_func(dfs_remove_from_nol)
|
|
|
dfs_debug(dfs, WLAN_DEBUG_DFS_NOL,
|
|
|
"remove channel %d from nol", chan);
|
|
|
utils_dfs_unmark_precac_nol_for_freq(dfs->dfs_pdev_obj, delfreq);
|
|
|
- utils_dfs_agile_sm_deliver_evt(dfs->dfs_pdev_obj,
|
|
|
- DFS_AGILE_SM_EV_AGILE_START);
|
|
|
+
|
|
|
utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj,
|
|
|
&delfreq, 1, DFS_NOL_RESET);
|
|
|
utils_dfs_save_nol(dfs->dfs_pdev_obj);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check if a channel is configured by the user to which we have to
|
|
|
+ * switch after it's NOL expiry. If that is the case, change
|
|
|
+ * channel immediately.
|
|
|
+ *
|
|
|
+ * If a channel switch is required (indicated by the return value of
|
|
|
+ * dfs_switch_to_postnol_chan_if_nol_expired), return from this function
|
|
|
+ * without posting Start event to Agile SM. That will be taken care
|
|
|
+ * of, after VAP start.
|
|
|
+ */
|
|
|
+ if (dfs_switch_to_postnol_chan_if_nol_expired(dfs))
|
|
|
+ return;
|
|
|
+
|
|
|
+ utils_dfs_agile_sm_deliver_evt(dfs->dfs_pdev_obj,
|
|
|
+ DFS_AGILE_SM_EV_AGILE_START);
|
|
|
}
|
|
|
#else
|
|
|
#ifdef CONFIG_CHAN_NUM_API
|