From ceebeade7f6dbf16629ab6bac81371ec0ebbf27d Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Tue, 25 Jul 2017 17:52:52 -0700 Subject: qcacld-3.0: Add protection for pkt_log ops with module stop Packet log ops are protected against load-unload and SSR, but not against module stop. Take care to add check for module stop. Also takecare to NULLing of wdi_event_list and NULL check before accessing. Change-Id: I20d49ff587719fc14f60a53e86092383de6ef5b8 CRs-Fixed: 2082135 --- core/cds/inc/cds_api.h | 64 +++++++++++++++++++++++++++++++++++++++----- core/dp/txrx/ol_txrx_event.c | 6 +++-- core/hdd/src/wlan_hdd_main.c | 3 +++ core/utils/pktlog/linux_ac.c | 12 ++++----- 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index c0adc5eef107..46318c8f43ab 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -64,15 +64,18 @@ * CDS_DRIVER_STATE_UNLOADING: Driver remove is in progress. * CDS_DRIVER_STATE_RECOVERING: Recovery in progress. * CDS_DRIVER_STATE_BAD: Driver in bad state. + * CDS_DRIVER_STATE_FW_READY: + * CDS_DRIVER_STATE_MODULE_STOPPING: Module stop in progress. */ enum cds_driver_state { - CDS_DRIVER_STATE_UNINITIALIZED = 0, - CDS_DRIVER_STATE_LOADED = BIT(0), - CDS_DRIVER_STATE_LOADING = BIT(1), - CDS_DRIVER_STATE_UNLOADING = BIT(2), - CDS_DRIVER_STATE_RECOVERING = BIT(3), - CDS_DRIVER_STATE_BAD = BIT(4), - CDS_DRIVER_STATE_FW_READY = BIT(5), + CDS_DRIVER_STATE_UNINITIALIZED = 0, + CDS_DRIVER_STATE_LOADED = BIT(0), + CDS_DRIVER_STATE_LOADING = BIT(1), + CDS_DRIVER_STATE_UNLOADING = BIT(2), + CDS_DRIVER_STATE_RECOVERING = BIT(3), + CDS_DRIVER_STATE_BAD = BIT(4), + CDS_DRIVER_STATE_FW_READY = BIT(5), + CDS_DRIVER_STATE_MODULE_STOPPING = BIT(6), }; #define __CDS_IS_DRIVER_STATE(_state, _mask) (((_state) & (_mask)) == (_mask)) @@ -213,6 +216,38 @@ static inline bool cds_is_load_or_unload_in_progress(void) __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_UNLOADING); } +/** + * cds_is_module_stop_in_progress() - Is module stopping + * + * Return: true if module stop is in progress. + */ +static inline bool cds_is_module_stop_in_progress(void) +{ + enum cds_driver_state state = cds_get_driver_state(); + + return __CDS_IS_DRIVER_STATE(state, CDS_DRIVER_STATE_MODULE_STOPPING); +} + +/** + * cds_is_module_state_transitioning() - Is module state transitioning + * + * Return: true if module stop is in progress. + */ +static inline int cds_is_module_state_transitioning(void) +{ + if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering() || + cds_is_module_stop_in_progress()) { + pr_info("%s: Load/Unload %d or recovery %d or module_stop %d is in progress", + __func__, cds_is_load_or_unload_in_progress(), + cds_is_driver_recovering(), + cds_is_module_stop_in_progress()); + return true; + } else { + return false; + } +} + + /** * cds_is_fw_down() - Is FW down or not * @@ -321,6 +356,21 @@ static inline void cds_set_unload_in_progress(uint8_t value) cds_clear_driver_state(CDS_DRIVER_STATE_UNLOADING); } +/** + * cds_set_module_stop_in_progress() - Setting module stop in progress + * + * @value: value to set + * + * Return: none + */ +static inline void cds_set_module_stop_in_progress(bool value) +{ + if (value) + cds_set_driver_state(CDS_DRIVER_STATE_MODULE_STOPPING); + else + cds_clear_driver_state(CDS_DRIVER_STATE_MODULE_STOPPING); +} + /** * cds_is_driver_loaded() - Is driver loaded * diff --git a/core/dp/txrx/ol_txrx_event.c b/core/dp/txrx/ol_txrx_event.c index eef1e611dc1b..5141f2c3ad2b 100644 --- a/core/dp/txrx/ol_txrx_event.c +++ b/core/dp/txrx/ol_txrx_event.c @@ -113,9 +113,10 @@ wdi_event_sub(struct ol_txrx_pdev_t *txrx_pdev, uint32_t event_index; wdi_event_subscribe *wdi_sub; /* Input validation */ - if (!txrx_pdev) { + if (!txrx_pdev || !txrx_pdev->wdi_event_list) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, - "Invalid txrx_pdev in %s", __func__); + "Invalid txrx_pdev or wdi_event_list in %s", + __func__); return A_ERROR; } if (!event_cb_sub) { @@ -224,6 +225,7 @@ A_STATUS wdi_event_detach(struct ol_txrx_pdev_t *txrx_pdev) } /* txrx_pdev->wdi_event_list would be non-null */ qdf_mem_free(txrx_pdev->wdi_event_list); + txrx_pdev->wdi_event_list = NULL; return A_OK; } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index df187c71b0b2..21ac300af4c8 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -9347,6 +9347,7 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode) mutex_lock(&hdd_ctx->iface_change_lock); hdd_ctx->stop_modules_in_progress = true; + cds_set_module_stop_in_progress(true); active_threads = cds_return_external_threads_count(); if (active_threads > 0 || hdd_ctx->isWiphySuspended) { @@ -9360,6 +9361,7 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode) qdf_mc_timer_start(&hdd_ctx->iface_change_timer, hdd_ctx->config->iface_change_wait_time); hdd_ctx->stop_modules_in_progress = false; + cds_set_module_stop_in_progress(false); return 0; } } @@ -9437,6 +9439,7 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode) done: hdd_ctx->stop_modules_in_progress = false; + cds_set_module_stop_in_progress(false); mutex_unlock(&hdd_ctx->iface_change_lock); EXIT(); diff --git a/core/utils/pktlog/linux_ac.c b/core/utils/pktlog/linux_ac.c index e707932dc27d..e510d7547400 100644 --- a/core/utils/pktlog/linux_ac.c +++ b/core/utils/pktlog/linux_ac.c @@ -572,8 +572,8 @@ static int __pktlog_open(struct inode *i, struct file *f) return -EBUSY; } - if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) { - pr_info("%s: Load/Unload or recovery is in progress", __func__); + if (cds_is_module_state_transitioning()) { + pr_info("%s: module transition in progress", __func__); return -EAGAIN; } @@ -638,8 +638,8 @@ static int __pktlog_release(struct inode *i, struct file *f) if (!pl_info) return -EINVAL; - if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) { - pr_info("%s: Load/Unload or recovery is in progress", __func__); + if (cds_is_module_state_transitioning()) { + pr_info("%s: module transition in progress", __func__); return -EAGAIN; } @@ -859,8 +859,8 @@ __pktlog_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) struct ath_pktlog_info *pl_info; struct ath_pktlog_buf *log_buf; - if (cds_is_load_or_unload_in_progress() || cds_is_driver_recovering()) { - pr_info("%s: Load/Unload or recovery is in progress", __func__); + if (cds_is_module_state_transitioning()) { + pr_info("%s: module transition in progress", __func__); return -EAGAIN; } -- cgit v1.2.3