Browse Source

qcacmn: Fix DFS kernel panic

As part of DFS component destroy, "ic" is accessed to reset
NOL list and PRECAC channel list, but "ic" is already deleted
as part of MLME component destroy. And therefore invalid memory
access happens.

Reset NOL list and PRECAC channel list before "ic" deletion.

Change-Id: I1dbf273f1ea51945493140bfce9bfa116ad0c488
CRs-Fixed: 2071164
Abhijit Pradhan 8 years ago
parent
commit
fe7233a795

+ 6 - 8
umac/dfs/core/src/dfs.h

@@ -1061,14 +1061,6 @@ void dfs_nol_update(struct wlan_dfs *dfs);
  */
 void dfs_nol_timer_cleanup(struct wlan_dfs *dfs);
 
-/**
- * dfs_nol_detach() - Free NOL variables.
- * @dfs: Pointer to wlan_dfs structure.
- *
- * Cancels the NOL timer and frees the NOL elements.
- */
-void dfs_nol_detach(struct wlan_dfs *dfs);
-
 /**
  * dfs_retain_bin5_burst_pattern() - Retain the BIN5 burst pattern.
  * @dfs: Pointer to wlan_dfs structure.
@@ -1924,4 +1916,10 @@ void dfs_main_timer_init(struct wlan_dfs *dfs);
  * @dfs: Pointer to wlan_dfs structure.
  */
 void dfs_main_timer_reset(struct wlan_dfs *dfs);
+
+/**
+ * dfs_stop() - Clear dfs timers.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+void dfs_stop(struct wlan_dfs *dfs);
 #endif  /* _DFS_H_ */

+ 7 - 4
umac/dfs/core/src/misc/dfs.c

@@ -326,6 +326,13 @@ int dfs_attach(struct wlan_dfs *dfs)
 	return 0;
 }
 
+void dfs_stop(struct wlan_dfs *dfs)
+{
+	dfs_init_precac_list(dfs);
+	dfs_nol_timer_cleanup(dfs);
+	dfs_clear_nolhistory(dfs);
+}
+
 void dfs_main_timer_reset(struct wlan_dfs *dfs)
 {
 	if (dfs->wlan_radar_tasksched) {
@@ -350,9 +357,6 @@ void dfs_reset(struct wlan_dfs *dfs)
 	dfs_cac_timer_reset(dfs);
 	dfs_zero_cac_reset(dfs);
 	dfs_main_timer_reset(dfs);
-
-	dfs_nol_timer_cleanup(dfs);
-	dfs_clear_nolhistory(dfs);
 }
 
 void dfs_main_detach(struct wlan_dfs *dfs)
@@ -419,7 +423,6 @@ void dfs_detach(struct wlan_dfs *dfs)
 {
 	dfs_main_detach(dfs);
 	dfs_zero_cac_detach(dfs);
-	dfs_nol_detach(dfs);
 }
 
 void dfs_destroy_object(struct wlan_dfs *dfs)

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

@@ -497,11 +497,6 @@ void dfs_nol_timer_cleanup(struct wlan_dfs *dfs)
 	dfs_nol_update(dfs);
 }
 
-void dfs_nol_detach(struct wlan_dfs *dfs)
-{
-	dfs_nol_timer_cleanup(dfs);
-}
-
 int dfs_get_rn_use_nol(struct wlan_dfs *dfs)
 {
 	return dfs->dfs_rinfo.rn_use_nol;

+ 0 - 1
umac/dfs/core/src/misc/dfs_zero_cac.c

@@ -101,7 +101,6 @@ void dfs_zero_cac_reset(struct wlan_dfs *dfs)
 	qdf_timer_stop(&dfs->dfs_precac_timer);
 	dfs->dfs_precac_primary_freq = 0;
 	dfs->dfs_precac_secondary_freq = 0;
-	dfs_init_precac_list(dfs);
 }
 
 int dfs_override_precac_timeout(struct wlan_dfs *dfs, int precac_timeout)

+ 6 - 0
umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h

@@ -185,4 +185,10 @@ QDF_STATUS tgt_dfs_cac_complete(struct wlan_objmgr_pdev *pdev,
  */
 QDF_STATUS tgt_dfs_reg_ev_handler(struct wlan_objmgr_psoc *psoc,
 		bool dfs_offload);
+
+/**
+ * tgt_dfs_stop() - Clear dfs timers.
+ * @dfs: Pointer to wlan_dfs structure.
+ */
+QDF_STATUS tgt_dfs_stop(struct wlan_objmgr_pdev *pdev);
 #endif /* _WLAN_DFS_TGT_API_H_ */

+ 14 - 0
umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c

@@ -248,3 +248,17 @@ QDF_STATUS tgt_dfs_reg_ev_handler(struct wlan_objmgr_psoc *psoc,
 	return status;
 }
 EXPORT_SYMBOL(tgt_dfs_reg_ev_handler);
+
+QDF_STATUS tgt_dfs_stop(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_dfs *dfs;
+
+	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
+	if (dfs == NULL)
+		return  QDF_STATUS_E_FAILURE;
+
+	dfs_stop(dfs);
+
+	return QDF_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(tgt_dfs_stop);

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

@@ -801,6 +801,7 @@ struct wlan_lmac_if_nan_rx_ops {
  * @dfs_set_current_channel:          Set DFS current channel.
  * @dfs_process_radar_ind:            Process radar found indication.
  * @dfs_dfs_cac_complete_ind:         Process cac complete indication.
+ * @dfs_stop:                         Clear dfs timers.
  */
 struct wlan_lmac_if_dfs_rx_ops {
 	QDF_STATUS (*dfs_get_radars)(struct wlan_objmgr_pdev *pdev);
@@ -856,6 +857,7 @@ struct wlan_lmac_if_dfs_rx_ops {
 	QDF_STATUS (*dfs_dfs_cac_complete_ind)(struct wlan_objmgr_pdev *pdev,
 			uint32_t vdev_id);
 #endif
+	QDF_STATUS (*dfs_stop)(struct wlan_objmgr_pdev *pdev);
 };
 
 struct wlan_lmac_if_mlme_rx_ops {

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

@@ -248,6 +248,7 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
 	dfs_rx_ops->dfs_set_current_channel = tgt_dfs_set_current_channel;
 	dfs_rx_ops->dfs_process_radar_ind = tgt_dfs_process_radar_ind;
 	dfs_rx_ops->dfs_dfs_cac_complete_ind = tgt_dfs_cac_complete;
+	dfs_rx_ops->dfs_stop = tgt_dfs_stop;
 
 	return QDF_STATUS_SUCCESS;
 }