Browse Source

qcacld-3.0: Refactor De-init sequence to firmware when the modules are not enabled

With the new statemachine  cds start/stop will not be invoked without an
interface up from upperlayer. As part of cds stop host sends de-initialization
sequence to firmware, If there is no interface up from the upper layer and
driver gets removed, host driver doesn't send the de-init
inidication to firmware and starts closing its modules because of this
fw & host are out of sync.

To mitigate the issue send the de-init sequence during if the modules are
opened but not enabled.

Change-Id: I52fddc1b8765105c44192085ba93bf00d14eb0bd
CRs-Fixed: 1073599
Govind Singh 8 years ago
parent
commit
b048e87f2c
5 changed files with 60 additions and 41 deletions
  1. 2 0
      core/cds/inc/cds_api.h
  2. 0 2
      core/cds/inc/cds_sched.h
  3. 50 26
      core/cds/src/cds_api.c
  4. 8 0
      core/hdd/src/wlan_hdd_main.c
  5. 0 13
      core/wma/src/wma_main.c

+ 2 - 0
core/cds/inc/cds_api.h

@@ -213,6 +213,8 @@ QDF_STATUS cds_disable(v_CONTEXT_t cds_context);
  */
 void cds_flush_cache_rx_queue(void);
 
+QDF_STATUS cds_post_disable(v_CONTEXT_t cds_context);
+
 QDF_STATUS cds_close(v_CONTEXT_t cds_context);
 
 void cds_core_return_msg(void *pVContext, p_cds_msg_wrapper pMsgWrapper);

+ 0 - 2
core/cds/inc/cds_sched.h

@@ -321,8 +321,6 @@ typedef struct _cds_context_type {
 	bool do_hw_mode_change;
 	bool enable_fatal_event;
 	struct cds_config_info *cds_cfg;
-	/* WAR: Is cds disabled */
-	bool is_cds_disabled;
 } cds_context_type, *p_cds_contextType;
 
 /*---------------------------------------------------------------------------

+ 50 - 26
core/cds/src/cds_api.c

@@ -688,9 +688,6 @@ QDF_STATUS cds_disable(v_CONTEXT_t cds_context)
 		wma_setneedshutdown(cds_context);
 	}
 
-	hif_disable_isr(((cds_context_type *) cds_context)->pHIFContext);
-	hif_reset_soc(((cds_context_type *) cds_context)->pHIFContext);
-
 	handle = cds_get_context(QDF_MODULE_ID_PE);
 	if (!handle) {
 		cds_err("Invalid PE context return!");
@@ -708,27 +705,51 @@ QDF_STATUS cds_disable(v_CONTEXT_t cds_context)
 		QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
 	}
 
-	gp_cds_context->is_cds_disabled = 1;
 	return qdf_status;
 }
 
+#ifdef HIF_USB
+static inline void cds_suspend_target(tp_wma_handle wma_handle)
+{
+	QDF_STATUS status;
+	/* Suspend the target and disable interrupt */
+	status = wma_suspend_target(wma_handle, 0);
+	if (status)
+		cds_err("Failed to suspend target, status = %d", status);
+}
+#else
+static inline void cds_suspend_target(tp_wma_handle wma_handle)
+{
+	QDF_STATUS status;
+	/* Suspend the target and disable interrupt */
+	status = wma_suspend_target(wma_handle, 1);
+	if (status)
+		cds_err("Failed to suspend target, status = %d", status);
+}
+#endif /* HIF_USB */
+
 /**
- * cds_close() - close cds module
+ * cds_post_disable() - post disable cds module
  * @cds_context: CDS context
  *
  * Return: QDF status
  */
-QDF_STATUS cds_close(v_CONTEXT_t cds_context)
+QDF_STATUS cds_post_disable(v_CONTEXT_t cds_context)
 {
-	QDF_STATUS qdf_status;
 	tp_wma_handle wma_handle;
-
+	struct hif_opaque_softc *hif_ctx;
 	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
 	if (!wma_handle) {
 		cds_err("Failed to get wma_handle!");
 		return QDF_STATUS_E_INVAL;
 	}
 
+	hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
+	if (!hif_ctx) {
+		cds_err("Failed to get hif_handle!");
+		return QDF_STATUS_E_INVAL;
+	}
+
 	/*
 	 * With new state machine changes cds_close can be invoked without
 	 * cds_disable. So, send the following clean up prerequisites to fw,
@@ -738,23 +759,27 @@ QDF_STATUS cds_close(v_CONTEXT_t cds_context)
 	 * - Clean up CE tasklets.
 	 */
 
-	if (!gp_cds_context->is_cds_disabled) {
-		cds_info("send denint sequence to firmware");
-		if (!cds_is_driver_recovering()) {
-#ifdef HIF_USB
-			/* Suspend the target and enable interrupt */
-			if (wma_suspend_target(wma_handle, 0))
-				cds_err("Failed to suspend target");
-#else
-			/* Suspend the target and disable interrupt */
-			if (wma_suspend_target(wma_handle, 1))
-				cds_err("Failed to suspend target");
-#endif /* HIF_USB */
-		}
-		hif_disable_isr(
-			((cds_context_type *) cds_context)->pHIFContext);
-		hif_reset_soc(((cds_context_type *) cds_context)->pHIFContext);
-	}
+	cds_info("send denint sequence to firmware");
+	if (!cds_is_driver_recovering())
+		cds_suspend_target(wma_handle);
+	hif_disable_isr(hif_ctx);
+	hif_reset_soc(hif_ctx);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * cds_close() - close cds module
+ * @cds_context: CDS context
+ *
+ * This API allows user to close modules registered
+ * with connectivity device services.
+ *
+ * Return: QDF status
+ */
+QDF_STATUS cds_close(v_CONTEXT_t cds_context)
+{
+	QDF_STATUS qdf_status;
 
 	qdf_status = wma_wmi_work_close(cds_context);
 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
@@ -830,7 +855,6 @@ QDF_STATUS cds_close(v_CONTEXT_t cds_context)
 	cds_deinit_ini_config();
 	qdf_timer_module_deinit();
 
-	gp_cds_context->is_cds_disabled = 0;
 	return QDF_STATUS_SUCCESS;
 }
 

+ 8 - 0
core/hdd/src/wlan_hdd_main.c

@@ -7852,9 +7852,17 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx)
 		goto done;
 	}
 
+	qdf_status = cds_post_disable(hdd_ctx->pcds_context);
+	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+		hdd_err("Failed to process post CDS disable Modules! :%d",
+			qdf_status);
+		ret = -EINVAL;
+		QDF_ASSERT(0);
+	}
 	qdf_status = cds_close(hdd_ctx->pcds_context);
 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
 		hdd_warn("Failed to stop CDS:%d", qdf_status);
+		ret = -EINVAL;
 		QDF_ASSERT(0);
 	}
 	/* Clean up message queues of TX, RX and MC thread */

+ 0 - 13
core/wma/src/wma_main.c

@@ -3191,19 +3191,6 @@ QDF_STATUS wma_stop(void *cds_ctx, uint8_t reason)
 		WMA_LOGE("Failed to destroy the log completion timer");
 	}
 
-	/* There's no need suspend target which is already down during SSR. */
-	if (!cds_is_driver_recovering()) {
-#ifdef HIF_USB
-		/* Suspend the target and enable interrupt */
-		if (wma_suspend_target(wma_handle, 0))
-			WMA_LOGE("Failed to suspend target");
-#else
-		/* Suspend the target and disable interrupt */
-		if (wma_suspend_target(wma_handle, 1))
-			WMA_LOGE("Failed to suspend target");
-#endif /* HIF_USB */
-	}
-
 	/* clean up ll-queue for all vdev */
 	for (i = 0; i < wma_handle->max_bssid; i++) {
 		if (wma_handle->interfaces[i].handle &&