From 71c74a4d6c8e8236a8e00141a4880c5a7dea4625 Mon Sep 17 00:00:00 2001 From: Manjunathappa Prakash Date: Thu, 19 Oct 2017 23:28:43 -0700 Subject: [PATCH] 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 | 62 ++++++++++++++++++++++++++++++++---- core/dp/txrx/ol_txrx_event.c | 6 ++-- core/hdd/src/wlan_hdd_main.c | 3 ++ 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index 64f5842c3933..d4aa7b679dc2 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -65,15 +65,17 @@ * 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_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)) @@ -199,6 +201,37 @@ 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 +354,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 0bb137887013..597235f3fb13 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -9509,6 +9509,7 @@ int hdd_wlan_stop_modules(struct hdd_context *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) { @@ -9525,6 +9526,7 @@ int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode) hdd_ctx->config->iface_change_wait_time, WIFI_POWER_EVENT_WAKELOCK_IFACE_CHANGE_TIMER); hdd_ctx->stop_modules_in_progress = false; + cds_set_module_stop_in_progress(false); return 0; } } @@ -9617,6 +9619,7 @@ int hdd_wlan_stop_modules(struct hdd_context *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); hdd_alert("stop WLAN module: exit driver status=%d", hdd_ctx->driver_status);