浏览代码

qcacmn: Declare puncturing SM states, APIs

Implement the data structures for DFS puncturing and
un-puncturing state machines. For details of state
machine implementation refer to the change id
I5accbf2866a830447bd776b989c31909060c45ca.

CRs-Fixed: 3462277
Change-Id: I026228fb72302408f2992325099a31a60e986e3c
Vijay Krishnan 2 年之前
父节点
当前提交
c75e7910c9

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

@@ -721,6 +721,8 @@ struct dfs_filtertype {
  *                              in MHZ applicable only for 80+80MHZ mode of
  *                              operation.
  * @dfs_ch_punc_pattern:        Bitmap representing puncturing patterns.
+ * @dfs_internal_radar_pattern: Bitmap representing puncturing patterns caused
+ *                              by radar.
  */
 struct dfs_channel {
 	uint16_t       dfs_ch_freq;
@@ -741,6 +743,9 @@ struct dfs_channel {
 	 */
 	uint16_t       dfs_ch_punc_pattern;
 #endif
+#if defined(QCA_DFS_BW_PUNCTURE) && !defined(CONFIG_REG_CLIENT)
+	uint16_t       dfs_internal_radar_pattern;
+#endif
 };
 
 /**
@@ -990,6 +995,74 @@ struct dfs_cacelem {
 };
 #endif
 
+#define DFS_PUNC_SM_SPIN_LOCK(_dfs_obj) \
+	qdf_spin_lock_bh(&((_dfs_obj)->dfs_punc_sm_lock))
+#define DFS_PUNC_SM_SPIN_UNLOCK(_dfs_obj) \
+	qdf_spin_unlock_bh(&((_dfs_obj)->dfs_punc_sm_lock))
+
+#define N_MAX_PUNC_SM 2
+
+/**
+ * enum dfs_punc_sm_evt - DFS Puncturing SM events.
+ * @DFS_PUNC_SM_EV_RADAR: Radar event on DFS puncturing SM.
+ * @DFS_PUNC_SM_EV_NOL_EXPIRY: NOL expiry event on DFS puncturing SM.
+ * @DFS_PUNC_SM_EV_CAC_EXPIRY: CAC expiry event on DFS puncturing SM.
+ * @DFS_PUNC_SM_EV_STOP: STOP event on DFS puncturing SM.
+ */
+enum dfs_punc_sm_evt {
+	DFS_PUNC_SM_EV_RADAR      = 0,
+	DFS_PUNC_SM_EV_NOL_EXPIRY = 1,
+	DFS_PUNC_SM_EV_CAC_EXPIRY = 2,
+	DFS_PUNC_SM_EV_STOP       = 3,
+};
+
+/**
+ * enum dfs_punc_sm_state - DFS Puncturing SM states.
+ * @DFS_S_UNPUNCTURED:    Default state or the start state of the puncturing SM.
+ * @DFS_S_PUNCTURED:      DFS channel is punctured.
+ * @DFS_S_CAC_WAIT:       The channel completed the NOL time and is waiting for
+ *                        CAC completion.
+ * @DFS_PUNCTURING_S_MAX: Max (invalid) state.
+ */
+enum dfs_punc_sm_state {
+	DFS_S_UNPUNCTURED    = 0,
+	DFS_S_PUNCTURED      = 1,
+	DFS_S_CAC_WAIT       = 2,
+	DFS_PUNCTURING_S_MAX = 3,
+};
+
+/**
+ * struct dfs_punc_obj -   DFS puncture object type. Each object represents one
+ *                         set of continuous punctured-channels. These channels
+ *                         were punctured by DFS component (NOT by other
+ *                         components).
+ * @punc_low_freq:         Low frequency of the continuous puncture object.
+ * @punc_high_freq:        High frequency of the continuous puncture object.
+ * @dfs_punc_cac_timer:    CAC timer for DFS unpuncturing for the puncture
+ *                         object.
+ * @dfs:                   Pointer to main DFS structure.
+ * @dfs_punc_sm_hdl:       The handle for the state machine.
+ * @dfs_punc_sm_cur_state: Current state of the Puncturing State Machine.
+ * @dfs_punc_sm_lock:      Puncturing state machine lock.
+ */
+struct dfs_punc_obj {
+	qdf_freq_t punc_low_freq;
+	qdf_freq_t punc_high_freq;
+	qdf_hrtimer_data_t dfs_punc_cac_timer;
+	struct wlan_dfs *dfs;
+	struct wlan_sm *dfs_punc_sm_hdl;
+	enum dfs_punc_sm_state dfs_punc_sm_cur_state;
+	qdf_spinlock_t dfs_punc_sm_lock;
+};
+
+/**
+ * struct dfs_punc_unpunc - The type of the list of the DFS puncture objects.
+ * @dfs_punc_arr:  Array of puncture objects.
+ */
+struct dfs_punc_unpunc {
+	struct dfs_punc_obj dfs_punc_arr[N_MAX_PUNC_SM];
+};
+
 /*
  * NB: not using kernel-doc format since the kernel-doc script doesn't
  *     handle the TAILQ_HEAD() or STAILQ_HEAD() macros
@@ -1175,6 +1248,7 @@ struct dfs_cacelem {
  * @dfs_cacelems:                    Stores the CAC related parameters of a
  *                                   channel such as: CAC started time, CAC
  *                                   completed time.
+ * @dfs_punc_lst:                    List of DFS puncture objects.
  */
 struct wlan_dfs {
 	uint32_t       dfs_debug_mask;
@@ -1352,6 +1426,9 @@ struct wlan_dfs {
 	enum channel_dfs_state dfs_channel_state_array[NUM_DFS_CHANS];
 	struct dfs_cacelem dfs_cacelems[NUM_DFS_CHANS];
 #endif /* WLAN_DISP_CHAN_INFO */
+#if defined(QCA_DFS_BW_PUNCTURE) && !defined(CONFIG_REG_CLIENT)
+	struct dfs_punc_unpunc dfs_punc_lst;
+#endif /* QCA_DFS_BW_PUNCTURE */
 #ifdef QCA_SUPPORT_AGILE_DFS
 #endif
 };
@@ -1435,6 +1512,7 @@ struct dfs_soc_priv_obj {
  *                              detection.
  * @WLAN_DEBUG_DFS_RANDOM_CHAN: Random channel selection.
  * @WLAN_DEBUG_DFS_AGILE:       Agile PreCAC/RCAC
+ * @WLAN_DEBUG_DFS_PUNCTURING:  DFS puncturing and unpuncturing.
  * @WLAN_DEBUG_DFS_MAX:         Max flag
  * @WLAN_DEBUG_DFS_ALWAYS:      Always debug
  */
@@ -1454,6 +1532,7 @@ enum dfs_debug {
 	WLAN_DEBUG_DFS_FALSE_DET2 = 0x00100000,
 	WLAN_DEBUG_DFS_RANDOM_CHAN = 0x00200000,
 	WLAN_DEBUG_DFS_AGILE       = 0x00400000,
+	WLAN_DEBUG_DFS_PUNCTURING  = 0x00800000,
 	WLAN_DEBUG_DFS_MAX        = 0x80000000,
 	WLAN_DEBUG_DFS_ALWAYS     = WLAN_DEBUG_DFS_MAX
 };

+ 30 - 0
umac/dfs/core/src/dfs_process_radar_found_ind.h

@@ -204,6 +204,36 @@ uint16_t dfs_generate_radar_bitmap(struct wlan_dfs *dfs,
 {
 	return 0;
 }
+#endif
+
+/**
+ * dfs_handle_radar_puncturing() - Check if the puncture bitmap is valid
+ *                                 and initialize puncture SM for the
+ *                                 punctured channels.
+ * @dfs:                      Pointer to wlan_dfs structure.
+ * @dfs_radar_bitmap:         Puncture bitmap.
+ * @freq_list:                Channel list affected by radar.
+ * @num_channels:             Number of channels affected by radar.
+ * @is_ignore_radar_puncture: Bool to check if radar should be ignored.
+ *
+ * Return: Nothing.
+ */
+#if defined(QCA_DFS_BW_PUNCTURE) && !defined(CONFIG_REG_CLIENT)
+void
+dfs_handle_radar_puncturing(struct wlan_dfs *dfs,
+			    uint16_t *dfs_radar_bitmap,
+			    uint16_t *freq_list,
+			    uint8_t num_channels,
+			    bool *is_ignore_radar_puncture);
+#else
+static inline
+void dfs_handle_radar_puncturing(struct wlan_dfs *dfs,
+				 uint16_t *dfs_radar_bitmap,
+				 uint16_t *freq_list,
+				 uint8_t num_channels,
+				 bool *is_ignore_radar_puncture)
+{
+}
 #endif /* QCA_DFS_BW_PUNCTURE */
 
 /**

+ 258 - 0
umac/dfs/core/src/dfs_zero_cac.h

@@ -1332,4 +1332,262 @@ bool dfs_get_configured_bwexpand_dfs_chan(struct wlan_dfs *dfs,
 	return false;
 }
 #endif /* QCA_DFS_BW_EXPAND */
+
+#if defined(QCA_DFS_BW_PUNCTURE) && !defined(CONFIG_REG_CLIENT)
+/**
+ * dfs_create_punc_sm() - Wrapper API to Create DFS puncture state machine.
+ * @dfs: pointer to wlan_dfs.
+ *
+ * Return: Nothing.
+ */
+void dfs_create_punc_sm(struct wlan_dfs *dfs);
+
+/**
+ * dfs_destroy_punc_sm() - Wrapper API to Destroy DFS puncture state machine.
+ * @dfs: pointer to wlan_dfs.
+ *
+ * Return: Nothing.
+ */
+void dfs_destroy_punc_sm(struct wlan_dfs *dfs);
+
+/**
+ * dfs_punc_sm_start() - Start DFS puncture state machine.
+ * @dfs:           Pointer to wlan_dfs.
+ * @indx:          Index of DFS puncture state machine.
+ * @dfs_punc_arr:  Pointer to DFS puncture state machine object.
+ *
+ * Return: Nothing.
+ */
+void dfs_punc_sm_start(struct wlan_dfs *dfs,
+		       uint8_t indx,
+		       struct dfs_punc_obj *dfs_punc_arr);
+
+/**
+ * dfs_punc_sm_stop() - Stop DFS puncture state machine.
+ * @dfs:           Pointer to wlan_dfs.
+ * @indx:          Index of DFS puncture state machine.
+ * @dfs_punc_arr:  Pointer to DFS puncture state machine object.
+ *
+ * Return: Nothing.
+ */
+void dfs_punc_sm_stop(struct wlan_dfs *dfs,
+		      uint8_t indx,
+		      struct dfs_punc_obj *dfs_punc_arr);
+
+/**
+ * dfs_punc_sm_create() - Create DFS puncture state machine.
+ * @dfs_punc:             Pointer to DFS puncture state machine object.
+ *
+ * Return: Success if SM is created.
+ */
+QDF_STATUS dfs_punc_sm_create(struct dfs_punc_obj *dfs_punc);
+
+/**
+ * dfs_punc_sm_destroy() - Destroy DFS puncture state machine.
+ * @dfs_punc:              Pointer to DFS puncture state machine object.
+ *
+ * Return: Success if SM is destroyed.
+ */
+QDF_STATUS dfs_punc_sm_destroy(struct dfs_punc_obj *dfs_punc);
+
+/**
+ * dfs_punc_cac_timer_attach() - Attach puncture CAC timer to DFS puncture
+ *                               state machine.
+ * @dfs:                         Pointer to wlan_dfs.
+ * @dfs_punc_arr:                Pointer to DFS puncture state machine object.
+ *
+ * Return: Nothing.
+ */
+void dfs_punc_cac_timer_attach(struct wlan_dfs *dfs,
+			       struct dfs_punc_obj *dfs_punc_arr);
+
+/**
+ * dfs_handle_dfs_puncture_unpuncture() - Handles DFS puncture and unpuncturing.
+ * @dfs:                                  Pointer to wlan_dfs.
+ *
+ * Return: Nothing.
+ */
+void dfs_handle_dfs_puncture_unpuncture(struct wlan_dfs *dfs);
+
+/**
+ * dfs_punc_cac_timer_reset() - Reset puncture CAC timer.
+ * @dfs_punc_arr:               Pointer to DFS puncture state machine object.
+ *
+ * Return: Nothing.
+ */
+void dfs_punc_cac_timer_reset(struct dfs_punc_obj *dfs_punc_arr);
+
+/**
+ * dfs_punc_cac_timer_detach() - Detach puncture CAC timer from DFS puncture
+ *                               state machine.
+ * @dfs_punc_arr:                Pointer to DFS puncture state machine object.
+ *
+ * Return: Nothing.
+ */
+void dfs_punc_cac_timer_detach(struct dfs_punc_obj *dfs_punc_arr);
+
+/**
+ * dfs_start_punc_cac_timer() - Start puncture CAC timer.
+ * @dfs_punc_arr:               Pointer to DFS puncture state machine object.
+ * @is_weather_chan:            check if the channel is weather channel.
+ *
+ * Return: Nothing.
+ */
+void dfs_start_punc_cac_timer(struct dfs_punc_obj *dfs_punc_arr,
+			      bool is_weather_chan);
+
+/**
+ * dfs_cancel_punc_cac_timer() - Cancel puncture CAC timer.
+ * @dfs_punc_arr:                Pointer to DFS puncture state machine object.
+ *
+ * Return: Nothing.
+ */
+void dfs_cancel_punc_cac_timer(struct dfs_punc_obj *dfs_punc_arr);
+
+/**
+ * utils_dfs_puncturing_sm_deliver_evt() - Utility API to post events to DFS
+ *                                         puncture state machine.
+ * @pdev:                          Pointer to DFS pdev object.
+ * @sm_indx:                       Index of state machine.
+ * @event:                         Event to be posted to DFS Puncturing SM.
+ *
+ * Return: Nothing.
+ */
+void utils_dfs_puncturing_sm_deliver_evt(struct wlan_objmgr_pdev *pdev,
+					 uint8_t sm_indx,
+					 enum dfs_punc_sm_evt event);
+/**
+ * dfs_puncturing_sm_deliver_evt() - API to post events to DFS puncture
+ *                                   state machine.
+ * @dfs:                           Pointer to wlan_dfs.
+ * @event:                         Event to be posted to DFS Puncturing SM.
+ * @event_data_len:                Size of event data.
+ * @event_data:                    Event data.
+ *
+ * Return: Nothing.
+ */
+QDF_STATUS dfs_puncturing_sm_deliver_evt(struct wlan_dfs *dfs,
+					 enum dfs_punc_sm_evt event,
+					 uint16_t event_data_len,
+					 void *event_data);
+
+/**
+ * dfs_handle_nol_puncture() - Send SM event post NOL expiry.
+ * @dfs:           Pointer to wlan_dfs.
+ * @nolfreq:       NOL channel frequency.
+ *
+ * Return: Nothing.
+ */
+void dfs_handle_nol_puncture(struct wlan_dfs *dfs, qdf_freq_t nolfreq);
+
+/**
+ * dfs_is_ignore_radar_for_punctured_chans() - Store the radar bitmap and check
+ *                                             if radar is found in already
+ *                                             punctured channel and ignore the
+ *                                             radar.
+ * @dfs:                       Wlan_dfs structure
+ * @dfs_curr_radar_bitmap:     Variable to store radar bitmap.
+ *
+ * Return: If radar is found on punctured channel then return true.
+ * Else return false.
+ */
+bool dfs_is_ignore_radar_for_punctured_chans(struct wlan_dfs *dfs,
+					     uint16_t dfs_curr_radar_bitmap);
+#else
+static inline
+void dfs_create_punc_sm(struct wlan_dfs *dfs)
+{
+}
+
+static inline
+void dfs_destroy_punc_sm(struct wlan_dfs *dfs)
+{
+}
+
+static inline
+void dfs_punc_sm_start(struct wlan_dfs *dfs,
+		       uint8_t indx,
+		       struct dfs_punc_obj *dfs_punc_arr)
+{
+}
+
+static inline
+void dfs_punc_sm_stop(struct wlan_dfs *dfs,
+		      uint8_t indx,
+		      struct dfs_punc_obj *dfs_punc_arr)
+{
+}
+
+static inline
+QDF_STATUS dfs_punc_sm_create(struct dfs_punc_obj *dfs_punc)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+
+static inline
+QDF_STATUS dfs_punc_sm_destroy(struct dfs_punc_obj *dfs_punc)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+
+static inline
+void dfs_punc_cac_timer_attach(struct wlan_dfs *dfs,
+			       struct dfs_punc_obj *dfs_punc_arr)
+{
+}
+
+static inline
+void dfs_handle_dfs_puncture_unpuncture(struct wlan_dfs *dfs)
+{
+}
+
+static inline
+void dfs_punc_cac_timer_reset(struct dfs_punc_obj *dfs_punc_arr)
+{
+}
+
+static inline
+void dfs_punc_cac_timer_detach(struct dfs_punc_obj *dfs_punc_arr)
+{
+}
+
+static inline
+void dfs_start_punc_cac_timer(struct dfs_punc_obj *dfs_punc_arr,
+			      bool is_weather_chan)
+{
+}
+
+static inline
+void dfs_cancel_punc_cac_timer(struct dfs_punc_obj *dfs_punc_arr)
+{
+}
+
+static inline
+void utils_dfs_puncturing_sm_deliver_evt(struct wlan_objmgr_pdev *pdev,
+					 uint8_t sm_indx,
+					 enum dfs_punc_sm_evt event)
+{
+}
+
+static inline
+QDF_STATUS dfs_puncturing_sm_deliver_evt(struct wlan_dfs *dfs,
+					 enum dfs_punc_sm_evt event,
+					 uint16_t event_data_len,
+					 void *event_data)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+
+static inline
+void dfs_handle_nol_puncture(struct wlan_dfs *dfs, qdf_freq_t nolfreq)
+{
+}
+
+static inline
+bool dfs_is_ignore_radar_for_punctured_chans(struct wlan_dfs *dfs,
+					     uint16_t dfs_curr_radar_bitmap)
+{
+	return false;
+}
+#endif /* DFS_BW_PUNCTURE */
 #endif /* _DFS_ZERO_CAC_H_ */

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

@@ -821,6 +821,8 @@ void dfs_set_current_channel_for_freq(struct wlan_dfs *dfs,
 
 	if (is_channel_updated)
 		*is_channel_updated = true;
+	if (dfs->dfs_use_puncture)
+		dfs_handle_dfs_puncture_unpuncture(dfs);
 }
 #endif
 

+ 7 - 0
umac/dfs/core/src/misc/dfs_nol.c

@@ -164,6 +164,7 @@ dfs_remove_from_nol(qdf_hrtimer_data_t *arg)
 {
 	struct wlan_dfs *dfs;
 	uint16_t delfreq;
+	qdf_freq_t nolfreq;
 	uint16_t delchwidth;
 	uint8_t chan;
 	struct dfs_nolelem *nol_arg;
@@ -171,6 +172,10 @@ dfs_remove_from_nol(qdf_hrtimer_data_t *arg)
 	nol_arg = container_of(arg, struct dfs_nolelem, nol_timer);
 	dfs = nol_arg->nol_dfs;
 	delfreq = nol_arg->nol_freq;
+	/* Since the content of delfreq might change remember it.
+	 * The NOL freq will be used by NOL puncture handler.
+	 */
+	nolfreq = delfreq;
 	delchwidth = nol_arg->nol_chwidth;
 
 	/* Delete the given NOL entry. */
@@ -191,6 +196,8 @@ dfs_remove_from_nol(qdf_hrtimer_data_t *arg)
 
 	utils_dfs_save_nol(dfs->dfs_pdev_obj);
 
+	if (dfs->dfs_use_puncture)
+		dfs_handle_nol_puncture(dfs, nolfreq);
 	/*
 	 * 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

+ 11 - 52
umac/dfs/core/src/misc/dfs_process_radar_found_ind.c

@@ -1014,52 +1014,6 @@ dfs_process_radar_ind(struct wlan_dfs *dfs,
 	return status;
 }
 
-#if defined(QCA_DFS_BW_PUNCTURE) && defined(WLAN_FEATURE_11BE)
-/**
- * dfs_is_ignore_radar_for_punctured_chans() - Store the radar bitmap and check
- *                                             if radar is found in already
- *                                             punctured channel and ignore the
- *                                             radar.
- * @dfs: Wlan_dfs structure
- * @dfs_radar_bitmap: Variable to store radar bitmap.
- * @freq_list: output array of sub-channel frequencies.
- * @num_channels: Number of sub-channels in target DFS channel.
- *
- * Return: If radar is found on punctured channel then return true.
- * Else return false.
- */
-static
-bool dfs_is_ignore_radar_for_punctured_chans(struct wlan_dfs *dfs,
-					     uint16_t *dfs_radar_bitmap,
-					     uint16_t *freq_list,
-					     uint8_t num_channels)
-{
-	uint16_t dfs_punc_pattern = dfs->dfs_curchan->dfs_ch_punc_pattern;
-
-	*dfs_radar_bitmap = dfs_generate_radar_bitmap(dfs,
-						      freq_list,
-						      num_channels);
-	*dfs_radar_bitmap |= dfs_punc_pattern;
-
-	if (*dfs_radar_bitmap == dfs_punc_pattern) {
-		dfs_err(dfs, WLAN_DEBUG_DFS,
-			"radar event received on invalid channel");
-		return true;
-	}
-
-	return false;
-}
-#else
-static
-bool dfs_is_ignore_radar_for_punctured_chans(struct wlan_dfs *dfs,
-					     uint16_t *dfs_radar_bitmap,
-					     uint16_t *freq_list,
-					     uint8_t num_channels)
-{
-	return false;
-}
-#endif /* QCA_DFS_BW_PUNCTURE */
-
 QDF_STATUS
 dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
 				   struct radar_found_info *radar_found)
@@ -1103,12 +1057,17 @@ dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
 							freq_list,
 							freq_center);
 
-	if (dfs->dfs_use_puncture &&
-	    dfs_is_ignore_radar_for_punctured_chans(dfs,
-						    &dfs_radar_bitmap,
-						    freq_list,
-						    num_channels))
-		goto exit;
+	if (dfs->dfs_use_puncture) {
+		bool is_ignore_radar_puncture = false;
+
+		dfs_handle_radar_puncturing(dfs,
+					    &dfs_radar_bitmap,
+					    freq_list,
+					    num_channels,
+					    &is_ignore_radar_puncture);
+		if (is_ignore_radar_puncture)
+			goto exit;
+	}
 
 	if (!dfs->dfs_use_nol) {
 		if (!dfs->dfs_is_offload_enabled)

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

@@ -53,6 +53,8 @@
  *                                     Channel Switch Announcement.
  * @mlme_postnol_chan_switch:          Channel change post NOL using Channel
  *                                     Switch Announcement.
+ * @mlme_unpunc_chan_switch:           After DFS unpuncture occurs send VDEV
+ *                                     restart.
  * @mlme_nol_timeout_notification:     NOL timeout notification.
  * @mlme_clist_update:                 Updates the channel list.
  * @mlme_is_opmode_sta:                Check if pdev opmode is STA.
@@ -163,6 +165,11 @@ struct dfs_to_mlme {
 				    qdf_freq_t des_chan_freq,
 				    qdf_freq_t des_cfreq2,
 				    enum wlan_phymode des_mode);
+#endif
+#if defined(QCA_DFS_BW_PUNCTURE) && !defined(CONFIG_REG_CLIENT)
+	QDF_STATUS
+	    (*mlme_unpunc_chan_switch)(struct wlan_objmgr_pdev *pdev,
+				       uint16_t new_punc_pattern);
 #endif
 	QDF_STATUS (*mlme_nol_timeout_notification)(
 			struct wlan_objmgr_pdev *pdev);

+ 26 - 1
umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-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
@@ -95,7 +95,29 @@ register_dfs_postnol_csa_callback(struct dfs_to_mlme *mlme_callback)
 {
 }
 #endif
+
+/**
+ * register_dfs_unpunc_chan_switch_callback() - Register unpuncture channel VDEV
+ *                                              restart callback.
+ * @mlme_callback:                            Pointer to dfs_to_mlme.
+ */
+#if defined(QCA_DFS_BW_PUNCTURE) && !defined(CONFIG_REG_CLIENT)
+static inline void
+register_dfs_unpunc_chan_switch_callback(struct dfs_to_mlme *mlme_callback)
+{
+	if (!mlme_callback)
+		return;
+
+	mlme_callback->mlme_unpunc_chan_switch =
+		mlme_dfs_unpunc_chan_switch;
+}
+#else
+static inline void
+register_dfs_unpunc_chan_switch_callback(struct dfs_to_mlme *mlme_callback)
+{
+}
 #endif
+#endif /* MOBILE_DFS_SUPPORT */
 
 /*
  * register_dfs_callbacks_for_freq() - Register dfs callbacks.
@@ -190,6 +212,7 @@ void register_dfs_callbacks(void)
 	/* Register freq based callbacks */
 	register_dfs_callbacks_for_freq(tmp_dfs_to_mlme);
 	register_dfs_postnol_csa_callback(tmp_dfs_to_mlme);
+	register_dfs_unpunc_chan_switch_callback(tmp_dfs_to_mlme);
 }
 #else
 void register_dfs_callbacks(void)
@@ -516,6 +539,7 @@ QDF_STATUS wlan_dfs_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
 							    WLAN_UMAC_COMP_DFS);
 	dfs->dfs_soc_obj = dfs_soc_obj;
 	dfs_agile_soc_obj_init(dfs, psoc);
+	dfs_create_punc_sm(dfs);
 
 	if (dfs_attach(dfs) == 1) {
 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_attch failed");
@@ -540,6 +564,7 @@ QDF_STATUS wlan_dfs_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev,
 
 	/* DFS is NULL during unload. should we call this function before */
 	if (dfs) {
+		dfs_destroy_punc_sm(dfs);
 		dfs_detach(dfs);
 		global_dfs_to_mlme.pdev_component_obj_detach(pdev,
 				WLAN_UMAC_COMP_DFS,