瀏覽代碼

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
Manjunathappa Prakash 7 年之前
父節點
當前提交
71c74a4d6c
共有 3 個文件被更改,包括 62 次插入9 次删除
  1. 55 7
      core/cds/inc/cds_api.h
  2. 4 2
      core/dp/txrx/ol_txrx_event.c
  3. 3 0
      core/hdd/src/wlan_hdd_main.c

+ 55 - 7
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
  *

+ 4 - 2
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;
 }
 

+ 3 - 0
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);