diff options
| author | Manjunathappa Prakash <prakashpm@codeaurora.org> | 2017-07-25 17:52:52 -0700 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-08-09 14:37:02 -0700 |
| commit | ceebeade7f6dbf16629ab6bac81371ec0ebbf27d (patch) | |
| tree | 82123fa99af31b1c623561ad2a7c9bed553d5701 /core | |
| parent | d1035f741aa35b1d70c92d5d1f0d768555af0a45 (diff) | |
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
Diffstat (limited to 'core')
| -rw-r--r-- | core/cds/inc/cds_api.h | 64 | ||||
| -rw-r--r-- | core/dp/txrx/ol_txrx_event.c | 6 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_main.c | 3 | ||||
| -rw-r--r-- | 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)) @@ -214,6 +217,38 @@ static inline bool cds_is_load_or_unload_in_progress(void) } /** + * 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 * * Return: true if FW is down and false otherwise. @@ -322,6 +357,21 @@ static inline void cds_set_unload_in_progress(uint8_t value) } /** + * 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 * * Return: true if driver is loaded or false otherwise. 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; } |
