From fe7233a7954d44e7646ac598c04db7d4627a02e5 Mon Sep 17 00:00:00 2001 From: Abhijit Pradhan Date: Wed, 12 Jul 2017 18:48:14 +0530 Subject: [PATCH] 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 --- umac/dfs/core/src/dfs.h | 14 ++++++-------- umac/dfs/core/src/misc/dfs.c | 11 +++++++---- umac/dfs/core/src/misc/dfs_nol.c | 5 ----- umac/dfs/core/src/misc/dfs_zero_cac.c | 1 - umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h | 6 ++++++ umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c | 14 ++++++++++++++ .../lmac_if/inc/wlan_lmac_if_def.h | 2 ++ .../lmac_if/src/wlan_lmac_if.c | 1 + 8 files changed, 36 insertions(+), 18 deletions(-) diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index d5039719826e..c656e4b9773d 100644 --- a/umac/dfs/core/src/dfs.h +++ b/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_ */ diff --git a/umac/dfs/core/src/misc/dfs.c b/umac/dfs/core/src/misc/dfs.c index 683f79012924..f44ab4470847 100644 --- a/umac/dfs/core/src/misc/dfs.c +++ b/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) diff --git a/umac/dfs/core/src/misc/dfs_nol.c b/umac/dfs/core/src/misc/dfs_nol.c index 870fb05e4f85..388babdf4ff8 100644 --- a/umac/dfs/core/src/misc/dfs_nol.c +++ b/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; diff --git a/umac/dfs/core/src/misc/dfs_zero_cac.c b/umac/dfs/core/src/misc/dfs_zero_cac.c index f28ac88dbf60..4e405a260e1e 100644 --- a/umac/dfs/core/src/misc/dfs_zero_cac.c +++ b/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) diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h index ad60efe97b74..f2fddc4163d2 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h +++ b/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_ */ diff --git a/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c b/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c index 6e46cc7f3530..8bd536778fac 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c +++ b/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); diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index b7aa04440d16..cd5b3e2baa54 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/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 { diff --git a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c index cf030a9d0185..554743b6a06a 100644 --- a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c +++ b/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; }