summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorManjunathappa Prakash <prakashpm@codeaurora.org>2017-07-25 17:52:52 -0700
committersnandini <snandini@codeaurora.org>2017-08-09 14:37:02 -0700
commitceebeade7f6dbf16629ab6bac81371ec0ebbf27d (patch)
tree82123fa99af31b1c623561ad2a7c9bed553d5701 /core
parentd1035f741aa35b1d70c92d5d1f0d768555af0a45 (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.h64
-rw-r--r--core/dp/txrx/ol_txrx_event.c6
-rw-r--r--core/hdd/src/wlan_hdd_main.c3
-rw-r--r--core/utils/pktlog/linux_ac.c12
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;
}