浏览代码

Merge "qcacmn: Add APIs to configure and switch to postNOL channel"

Linux Build Service Account 5 年之前
父节点
当前提交
54507b00ba

+ 89 - 0
umac/dfs/core/src/dfs.h

@@ -1139,6 +1139,10 @@ struct dfs_rcac_params {
  *                                   MHZ.
  * @dfs_rcac_param:                  Primary frequency and Channel params of
  *                                   the selected RCAC channel.
+ * @dfs_chan_postnol_freq:           Frequency the AP switches to, post NOL.
+ * @dfs_chan_postnol_mode:           Phymode the AP switches to, post NOL.
+ * @dfs_chan_postnol_cfreq2:         Secondary center frequency the AP
+ *                                   switches to, post NOL.
  */
 struct wlan_dfs {
 	uint32_t       dfs_debug_mask;
@@ -1311,6 +1315,11 @@ struct wlan_dfs {
 	struct dfs_rcac_params dfs_rcac_param;
 #endif
 	uint16_t       dfs_lowest_pri_limit;
+#if defined(QCA_SUPPORT_DFS_CHAN_POSTNOL)
+	qdf_freq_t     dfs_chan_postnol_freq;
+	enum phy_ch_width dfs_chan_postnol_mode;
+	qdf_freq_t     dfs_chan_postnol_cfreq2;
+#endif
 };
 
 #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS)
@@ -2987,4 +2996,84 @@ uint8_t dfs_find_dfs_sub_channels_for_freq(struct  wlan_dfs *dfs,
 					   struct dfs_channel *chan,
 					   uint16_t *subchan_arr);
 
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+/**
+ * dfs_set_postnol_freq() - DFS API to set postNOL frequency.
+ * @dfs: Pointer to wlan_dfs object.
+ * @postnol_freq: PostNOL frequency value configured by the user.
+ */
+void dfs_set_postnol_freq(struct wlan_dfs *dfs, qdf_freq_t postnol_freq);
+
+/**
+ * dfs_set_postnol_mode() - DFS API to set postNOL mode.
+ * @dfs: Pointer to wlan_dfs object.
+ * @postnol_mode: PostNOL frequency value configured by the user.
+ */
+void dfs_set_postnol_mode(struct wlan_dfs *dfs, uint8_t postnol_mode);
+
+/**
+ * dfs_set_postnol_cfreq2() - DFS API to set postNOL secondary center frequency.
+ * @dfs: Pointer to wlan_dfs object.
+ * @postnol_cfreq2: PostNOL secondary center frequency value configured by the
+ * user.
+ */
+void dfs_set_postnol_cfreq2(struct wlan_dfs *dfs, qdf_freq_t postnol_cfreq2);
+
+/**
+ * dfs_get_postnol_freq() - DFS API to get postNOL frequency.
+ * @dfs: Pointer to wlan_dfs object.
+ * @postnol_freq: PostNOL frequency value configured by the user.
+ */
+void dfs_get_postnol_freq(struct wlan_dfs *dfs, qdf_freq_t *postnol_freq);
+
+/**
+ * dfs_get_postnol_mode() - DFS API to get postNOL mode.
+ * @dfs: Pointer to wlan_dfs object.
+ * @postnol_mode: PostNOL frequency value configured by the user.
+ */
+void dfs_get_postnol_mode(struct wlan_dfs *dfs, uint8_t *postnol_mode);
+
+/**
+ * dfs_get_postnol_cfreq2() - DFS API to get postNOL secondary center frequency.
+ * @dfs: Pointer to wlan_dfs object.
+ * @postnol_cfreq2: PostNOL secondary center frequency value configured by the
+ * user.
+ */
+void dfs_get_postnol_cfreq2(struct wlan_dfs *dfs, qdf_freq_t *postnol_cfreq2);
+#else
+static inline void
+dfs_set_postnol_freq(struct wlan_dfs *dfs, qdf_freq_t postnol_freq)
+{
+}
+
+static inline void
+dfs_set_postnol_mode(struct wlan_dfs *dfs, uint8_t postnol_mode)
+{
+}
+
+static inline void
+dfs_set_postnol_cfreq2(struct wlan_dfs *dfs, qdf_freq_t postnol_cfreq2)
+{
+}
+
+static inline void
+dfs_get_postnol_freq(struct wlan_dfs *dfs, qdf_freq_t *postnol_freq)
+{
+	*postnol_freq = 0;
+}
+
+static inline void
+dfs_get_postnol_mode(struct wlan_dfs *dfs, uint8_t *postnol_mode)
+{
+	*postnol_mode = CH_WIDTH_INVALID;
+}
+
+static inline void
+dfs_get_postnol_cfreq2(struct wlan_dfs *dfs, qdf_freq_t *postnol_cfreq2)
+{
+	*postnol_cfreq2 = 0;
+}
+
+#endif /* QCA_SUPPORT_DFS_CHAN_POSTNOL */
+
 #endif  /* _DFS_H_ */

+ 71 - 0
umac/dfs/core/src/misc/dfs.c

@@ -996,3 +996,74 @@ uint8_t dfs_get_agile_detector_id(struct wlan_dfs *dfs)
 	return dfs->dfs_agile_detector_id;
 }
 #endif
+
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+void dfs_set_postnol_freq(struct wlan_dfs *dfs, qdf_freq_t postnol_freq)
+{
+	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+		 "dfs_chan_postnol_freq configured as %d", postnol_freq);
+
+	dfs->dfs_chan_postnol_freq = postnol_freq;
+}
+
+void dfs_set_postnol_mode(struct wlan_dfs *dfs, uint8_t postnol_mode)
+{
+	if (dfs->dfs_chan_postnol_cfreq2) {
+		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			 "postNOL cfreq2 has been set,reset it to change mode");
+		return;
+	}
+
+	switch (postnol_mode) {
+	case DFS_CHWIDTH_20_VAL:
+		dfs->dfs_chan_postnol_mode = CH_WIDTH_20MHZ;
+		break;
+	case DFS_CHWIDTH_40_VAL:
+		dfs->dfs_chan_postnol_mode = CH_WIDTH_40MHZ;
+		break;
+	case DFS_CHWIDTH_80_VAL:
+		dfs->dfs_chan_postnol_mode = CH_WIDTH_80MHZ;
+		break;
+	case DFS_CHWIDTH_160_VAL:
+		dfs->dfs_chan_postnol_mode = CH_WIDTH_160MHZ;
+		break;
+	default:
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			"Invalid postNOL mode configured");
+		return;
+	}
+
+	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+		 "DFS postnol mode configured as %d",
+		 dfs->dfs_chan_postnol_mode);
+}
+
+void dfs_set_postnol_cfreq2(struct wlan_dfs *dfs, qdf_freq_t postnol_cfreq2)
+{
+	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+		 "dfs_chan_postnol_cfreq2 configured as %d", postnol_cfreq2);
+
+	dfs->dfs_chan_postnol_cfreq2 = postnol_cfreq2;
+
+	if (postnol_cfreq2) {
+		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
+			 "postNOL cfreq2 is set, changing mode to 80P80");
+		dfs->dfs_chan_postnol_mode = CH_WIDTH_80P80MHZ;
+	}
+}
+
+void dfs_get_postnol_freq(struct wlan_dfs *dfs, qdf_freq_t *postnol_freq)
+{
+	*postnol_freq = dfs->dfs_chan_postnol_freq;
+}
+
+void dfs_get_postnol_mode(struct wlan_dfs *dfs, uint8_t *postnol_mode)
+{
+	*postnol_mode = dfs->dfs_chan_postnol_mode;
+}
+
+void dfs_get_postnol_cfreq2(struct wlan_dfs *dfs, qdf_freq_t *postnol_cfreq2)
+{
+	*postnol_cfreq2 = dfs->dfs_chan_postnol_cfreq2;
+}
+#endif

+ 130 - 2
umac/dfs/core/src/misc/dfs_nol.c

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

+ 112 - 0
umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h

@@ -67,6 +67,8 @@
  * @mlme_dfs_deliver_event:            Deliver DFS events to user space
  * @mlme_precac_chan_change_csa_for_freq:Channel change triggered by PrCAC using
  *                                     Channel Switch Announcement.
+ * @mlme_postnol_chan_switch:          Channel change post NOL using Channel
+ *                                     Switch Announcement.
  * @mlme_mark_dfs_for_freq:            Mark DFS channel frequency as radar.
  * @mlme_get_extchan_for_freq:         Get the extension channel.
  * @mlme_find_dot11_chan_for_freq:     Find a channel pointer.
@@ -211,6 +213,13 @@ struct dfs_to_mlme {
 					       uint8_t des_chan,
 					       enum wlan_phymode des_mode);
 #endif
+#endif
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+	QDF_STATUS
+	(*mlme_postnol_chan_switch)(struct wlan_objmgr_pdev *pdev,
+				    qdf_freq_t des_chan_freq,
+				    qdf_freq_t des_cfreq2,
+				    enum wlan_phymode des_mode);
 #endif
 	QDF_STATUS (*mlme_nol_timeout_notification)(
 			struct wlan_objmgr_pdev *pdev);
@@ -652,6 +661,109 @@ ucfg_dfs_set_rcac_freq(struct wlan_objmgr_pdev *pdev,
 }
 #endif
 
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+/**
+ * ucfg_dfs_set_postnol_freq() - Set PostNOL freq.
+ * @pdev: Pointer to DFS pdev object.
+ * @postnol_freq: User configured freq to switch to, post NOL, in MHZ.
+ *
+ */
+QDF_STATUS ucfg_dfs_set_postnol_freq(struct wlan_objmgr_pdev *pdev,
+				     qdf_freq_t postnol_freq);
+
+/**
+ * ucfg_dfs_set_postnol_mode() - Set PostNOL mode.
+ * @pdev: Pointer to DFS pdev object.
+ * @postnol_mode: User configured mode to switch to, post NOL, in MHZ.
+ *
+ */
+QDF_STATUS ucfg_dfs_set_postnol_mode(struct wlan_objmgr_pdev *pdev,
+				     uint8_t postnol_mode);
+
+/**
+ * ucfg_dfs_set_postnol_cfreq2() - Set PostNOL secondary center frequency.
+ * @pdev: Pointer to DFS pdev object.
+ * @postnol_freq: User configured secondary center frequency to switch to,
+ * post NOL, in MHZ.
+ *
+ */
+QDF_STATUS ucfg_dfs_set_postnol_cfreq2(struct wlan_objmgr_pdev *pdev,
+				       qdf_freq_t postnol_cfreq2);
+
+/**
+ * ucfg_dfs_get_postnol_freq() - Get PostNOL freq.
+ * @pdev: Pointer to DFS pdev object.
+ * @postnol_freq: Pointer to user configured freq to switch to, post NOL.
+ *
+ */
+QDF_STATUS ucfg_dfs_get_postnol_freq(struct wlan_objmgr_pdev *pdev,
+				     qdf_freq_t *postnol_freq);
+
+/**
+ * ucfg_dfs_get_postnol_mode() - Set PostNOL mode.
+ * @pdev: Pointer to DFS pdev object.
+ * @postnol_mode: Pointer to user configured mode to switch to, post NOL.
+ *
+ */
+QDF_STATUS ucfg_dfs_get_postnol_mode(struct wlan_objmgr_pdev *pdev,
+				     uint8_t *postnol_mode);
+
+/**
+ * ucfg_dfs_get_postnol_cfreq2() - Set PostNOL secondary center frequency.
+ * @pdev: Pointer to DFS pdev object.
+ * @postnol_freq: Pointer to user configured secondary center frequency to
+ * switch to post NOL.
+ *
+ */
+QDF_STATUS ucfg_dfs_get_postnol_cfreq2(struct wlan_objmgr_pdev *pdev,
+				       qdf_freq_t *postnol_cfreq2);
+#else
+static inline QDF_STATUS
+ucfg_dfs_set_postnol_freq(struct wlan_objmgr_pdev *pdev,
+			  qdf_freq_t postnol_freq)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+ucfg_dfs_set_postnol_mode(struct wlan_objmgr_pdev *pdev,
+			  uint8_t postnol_mode)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+ucfg_dfs_set_postnol_cfreq2(struct wlan_objmgr_pdev *pdev,
+			    qdf_freq_t postnol_cfreq2)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+ucfg_dfs_get_postnol_freq(struct wlan_objmgr_pdev *pdev,
+			  qdf_freq_t *postnol_freq)
+{
+	*postnol_freq = 0;
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+ucfg_dfs_get_postnol_mode(struct wlan_objmgr_pdev *pdev,
+			  uint8_t *postnol_mode)
+{
+	*postnol_mode = CH_WIDTH_INVALID;
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+ucfg_dfs_get_postnol_cfreq2(struct wlan_objmgr_pdev *pdev,
+			    qdf_freq_t *postnol_cfreq2)
+{
+	*postnol_cfreq2 = 0;
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 /**
  * ucfg_dfs_get_rcac_freq() - Get rcac freq.
  * @pdev: Pointer to DFS pdev object.

+ 24 - 0
umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c

@@ -74,6 +74,29 @@ register_dfs_precac_auto_chan_callbacks_freq(struct dfs_to_mlme *mlme_callback)
 #endif
 #endif
 
+/**
+ * register_dfs_postnol_csa_callback - Register postNOL channel switch callbacks
+ * @mlme_callback: Pointer to dfs_to_mlme.
+ */
+#ifndef QCA_MCL_DFS_SUPPORT
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+static inline void
+register_dfs_postnol_csa_callback(struct dfs_to_mlme *mlme_callback)
+{
+	if (!mlme_callback)
+		return;
+
+	mlme_callback->mlme_postnol_chan_switch =
+		mlme_dfs_postnol_chan_switch;
+}
+#else
+static inline void
+register_dfs_postnol_csa_callback(struct dfs_to_mlme *mlme_callback)
+{
+}
+#endif
+#endif
+
 /*
  * register_dfs_callbacks_for_freq() - Register dfs callbacks.
  * @mlme_callback: Pointer to dfs_to_mlme.
@@ -149,6 +172,7 @@ void register_dfs_callbacks(void)
 	register_dfs_precac_auto_chan_callbacks_freq(tmp_dfs_to_mlme);
 	/* Register freq based callbacks */
 	register_dfs_callbacks_for_freq(tmp_dfs_to_mlme);
+	register_dfs_postnol_csa_callback(tmp_dfs_to_mlme);
 }
 #else
 void register_dfs_callbacks(void)

+ 110 - 0
umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c

@@ -537,3 +537,113 @@ bool ucfg_dfs_is_agile_rcac_enabled(struct wlan_objmgr_pdev *pdev)
 
 qdf_export_symbol(ucfg_dfs_is_agile_rcac_enabled);
 #endif
+
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+QDF_STATUS ucfg_dfs_set_postnol_freq(struct wlan_objmgr_pdev *pdev,
+				     qdf_freq_t postnol_freq)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_set_postnol_freq(dfs, postnol_freq);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(ucfg_dfs_set_postnol_freq);
+
+QDF_STATUS ucfg_dfs_set_postnol_mode(struct wlan_objmgr_pdev *pdev,
+				     uint8_t postnol_mode)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_set_postnol_mode(dfs, postnol_mode);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(ucfg_dfs_set_postnol_mode);
+
+QDF_STATUS ucfg_dfs_set_postnol_cfreq2(struct wlan_objmgr_pdev *pdev,
+				       qdf_freq_t postnol_cfreq2)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_set_postnol_cfreq2(dfs, postnol_cfreq2);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(ucfg_dfs_set_postnol_cfreq2);
+
+QDF_STATUS ucfg_dfs_get_postnol_freq(struct wlan_objmgr_pdev *pdev,
+				     qdf_freq_t *postnol_freq)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_get_postnol_freq(dfs, postnol_freq);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(ucfg_dfs_get_postnol_freq);
+
+QDF_STATUS ucfg_dfs_get_postnol_mode(struct wlan_objmgr_pdev *pdev,
+				     uint8_t *postnol_mode)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_get_postnol_mode(dfs, postnol_mode);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(ucfg_dfs_get_postnol_mode);
+
+QDF_STATUS ucfg_dfs_get_postnol_cfreq2(struct wlan_objmgr_pdev *pdev,
+				       qdf_freq_t *postnol_cfreq2)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = wlan_pdev_get_dfs_obj(pdev);
+	if (!dfs) {
+		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null dfs");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	dfs_get_postnol_cfreq2(dfs, postnol_cfreq2);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(ucfg_dfs_get_postnol_cfreq2);
+#endif

+ 22 - 0
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -1524,6 +1524,14 @@ struct wlan_lmac_if_wifi_pos_rx_ops {
  * @dfs_complete_deferred_tasks:      Process mode switch completion in DFS.
  * @dfs_is_agile_rcac_enabled:        Checks if Agile RCAC is enabled.
  * @dfs_agile_sm_deliver_evt:         API to post events to DFS Agile  SM.
+ * @dfs_set_postnol_freq:             API to set frequency to switch, post NOL.
+ * @dfs_set_postnol_mode:             API to set phymode to switch to, post NOL.
+ * @dfs_set_postnol_cfreq2            API to set secondary center frequency to
+ *                                    switch to, post NOL.
+ * @dfs_get_postnol_freq:             API to get frequency to switch, post NOL.
+ * @dfs_get_postnol_mode:             API to get phymode to switch to, post NOL.
+ * @dfs_get_postnol_cfreq2:           API to get secondary center frequency to
+ *                                    switch to, post NOL.
  */
 struct wlan_lmac_if_dfs_rx_ops {
 	QDF_STATUS (*dfs_get_radars)(struct wlan_objmgr_pdev *pdev);
@@ -1721,6 +1729,20 @@ struct wlan_lmac_if_dfs_rx_ops {
 	void (*dfs_agile_sm_deliver_evt)(struct wlan_objmgr_pdev *pdev,
 					 enum dfs_agile_sm_evt event);
 #endif
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+	QDF_STATUS (*dfs_set_postnol_freq)(struct wlan_objmgr_pdev *pdev,
+					   qdf_freq_t postnol_freq);
+	QDF_STATUS (*dfs_set_postnol_mode)(struct wlan_objmgr_pdev *pdev,
+					   uint8_t postnol_mode);
+	QDF_STATUS (*dfs_set_postnol_cfreq2)(struct wlan_objmgr_pdev *pdev,
+					     qdf_freq_t postnol_cfreq2);
+	QDF_STATUS (*dfs_get_postnol_freq)(struct wlan_objmgr_pdev *pdev,
+					   qdf_freq_t *postnol_freq);
+	QDF_STATUS (*dfs_get_postnol_mode)(struct wlan_objmgr_pdev *pdev,
+					   uint8_t *postnol_mode);
+	QDF_STATUS (*dfs_get_postnol_cfreq2)(struct wlan_objmgr_pdev *pdev,
+					     qdf_freq_t *postnol_cfreq2);
+#endif
 };
 
 /**

+ 26 - 0
umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c

@@ -513,6 +513,31 @@ register_agile_dfs_rx_ops(struct wlan_lmac_if_dfs_rx_ops *rx_ops)
 }
 #endif
 
+#ifdef QCA_SUPPORT_DFS_CHAN_POSTNOL
+/* register_dfs_chan_postnol_rx_ops() - Register DFS Rx-Ops for postNOL
+ * channel change APIs.
+ * @rx_ops: Pointer to wlan_lmac_if_dfs_rx_ops.
+ */
+static void
+register_dfs_chan_postnol_rx_ops(struct wlan_lmac_if_dfs_rx_ops *rx_ops)
+{
+	if (!rx_ops)
+		return;
+
+	rx_ops->dfs_set_postnol_freq = ucfg_dfs_set_postnol_freq;
+	rx_ops->dfs_set_postnol_mode = ucfg_dfs_set_postnol_mode;
+	rx_ops->dfs_set_postnol_cfreq2 = ucfg_dfs_set_postnol_cfreq2;
+	rx_ops->dfs_get_postnol_freq = ucfg_dfs_get_postnol_freq;
+	rx_ops->dfs_get_postnol_mode = ucfg_dfs_get_postnol_mode;
+	rx_ops->dfs_get_postnol_cfreq2 = ucfg_dfs_get_postnol_cfreq2;
+}
+#else
+static inline void
+register_dfs_chan_postnol_rx_ops(struct wlan_lmac_if_dfs_rx_ops *rx_ops)
+{
+}
+#endif
+
 static QDF_STATUS
 wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
 {
@@ -598,6 +623,7 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
 	register_dfs_rx_ops_for_freq(dfs_rx_ops);
 	register_rcac_dfs_rx_ops(dfs_rx_ops);
 	register_agile_dfs_rx_ops(dfs_rx_ops);
+	register_dfs_chan_postnol_rx_ops(dfs_rx_ops);
 
 	return QDF_STATUS_SUCCESS;
 }