فهرست منبع

qcacld-3.0: Execute sme_stop and mac_stop in mc thread context

sme_stop and mac_stop are accessing share data structures which
create a race condition when it is called from rmmod context.
Change context of sme_stop and mac_stop from rmmod thread to
mc thread.

Change-Id: Ie30f99d6b0c2f7c6cf20371dd66323d156360474
CRs-Fixed: 2148771
Naveen Rawat 7 سال پیش
والد
کامیت
bcd3d019d8
3فایلهای تغییر یافته به همراه117 افزوده شده و 31 حذف شده
  1. 1 10
      core/cds/src/cds_api.c
  2. 17 16
      core/mac/src/sys/common/inc/wlan_qct_sys.h
  3. 99 5
      core/mac/src/sys/common/src/wlan_qct_sys.c

+ 1 - 10
core/cds/src/cds_api.c

@@ -1030,17 +1030,8 @@ QDF_STATUS cds_disable(struct wlan_objmgr_psoc *psoc)
 		cds_err("Invalid PE context return!");
 		return QDF_STATUS_E_INVAL;
 	}
-	qdf_status = sme_stop(handle, HAL_STOP_TYPE_SYS_DEEP_SLEEP);
-	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
-		cds_err("Failed to stop SME: %d", qdf_status);
-		QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
-	}
-	qdf_status = mac_stop(handle, HAL_STOP_TYPE_SYS_DEEP_SLEEP);
 
-	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
-		cds_err("Failed to stop MAC");
-		QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
-	}
+	umac_stop();
 
 	return qdf_status;
 }

+ 17 - 16
core/mac/src/sys/common/inc/wlan_qct_sys.h

@@ -53,22 +53,16 @@
    Type declarations
    -------------------------------------------------------------------------*/
 
-/*----------------------------------------------------------------------------
-
-   \brief sysResponseCback() - SYS async resonse callback
-
-   This is a protype for the callback function that SYS makes to various
-   modules in the system.
-
-   \param  pUserData - user data that is passed to the Callback function
-   when it is invoked.
-
-   \return Nothing
-
-   \sa sysMcStart(), sysMcThreadProbe(), sysTxThreadProbe()
-
-   --------------------------------------------------------------------------*/
-typedef void (*sysResponseCback)(void *pUserData);
+/**
+ * sys_rsp_cb() - SYS async resonse callback
+ * @user_data: context data for callback
+ *
+ * This is a protype for the callback function that SYS makes to various
+ * modules in the system.
+ *
+ * Return: None
+ */
+typedef void (*sys_rsp_cb)(void *user_data);
 
 /*---------------------------------------------------------------------------
    Preprocessor definitions and constants
@@ -104,6 +98,13 @@ typedef void (*sysResponseCback)(void *pUserData);
    --------------------------------------------------------------------------*/
 QDF_STATUS sys_build_message_header(SYS_MSG_ID sysMsgId,
 				    struct scheduler_msg *pMsg);
+/**
+ * umac_stop() - send schedule message to mc thread to stop umac (sme and mac)
+ * @p_cds_context: cds context
+ *
+ * Return: status of operation
+ */
+QDF_STATUS umac_stop(void);
 
 QDF_STATUS sys_mc_process_handler(struct scheduler_msg *msg);
 

+ 99 - 5
core/mac/src/sys/common/src/wlan_qct_sys.c

@@ -37,24 +37,99 @@
 #include "mac_init_api.h"
 #include "qdf_trace.h"
 
+/*
+ * Cookie for SYS messages.  Note that anyone posting a SYS Message
+ * has to write the COOKIE in the reserved field of the message.  The
+ * SYS Module relies on this COOKIE
+ */
+#define SYS_MSG_COOKIE      0xFACE
+
+/* SYS stop timeout 30 seconds */
+#define SYS_STOP_TIMEOUT (30000)
+static qdf_event_t g_stop_evt;
+
 /**
  * sys_build_message_header() - to build the sys message header
- * @sysMsgId: message id
+ * @umac_stop_msgId: message id
  * @pMsg: pointer to message context
  *
  * This API is used to build the sys message header.
  *
  * Return: QDF_STATUS
  */
-QDF_STATUS sys_build_message_header(SYS_MSG_ID sysMsgId,
-				    struct scheduler_msg *pMsg)
+QDF_STATUS sys_build_message_header(SYS_MSG_ID umac_stop_msg_id,
+				    struct scheduler_msg *msg)
 {
-	pMsg->type = sysMsgId;
-	pMsg->reserved = SYS_MSG_COOKIE;
+	msg->type = umac_stop_msg_id;
+	msg->reserved = SYS_MSG_COOKIE;
 
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * umac_stop_complete_cb() - a callback when system stop completes
+ * @user_data: pointer to user provided data context
+ *
+ * this callback is used once system stop is completed.
+ *
+ * Return: none
+ */
+#ifdef QDF_ENABLE_TRACING
+static void umac_stop_complete_cb(void *user_data)
+{
+	qdf_event_t *stop_evt = (qdf_event_t *) user_data;
+	QDF_STATUS qdf_status = qdf_event_set(stop_evt);
+
+	QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
+
+}
+#else
+static void umac_stop_complete_cb(void *user_data)
+{
+	return;
+}
+#endif
+
+/**
+ * umac_stop() - To post stop message to system module
+ *
+ * This API is used post a stop message to system module
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS umac_stop(void)
+{
+	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
+	struct scheduler_msg umac_stop_msg;
+
+	/* Initialize the stop event */
+	qdf_status = qdf_event_create(&g_stop_evt);
+
+	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
+		return qdf_status;
+
+	/* post a message to SYS module in MC to stop SME and MAC */
+	sys_build_message_header(SYS_MSG_ID_UMAC_STOP, &umac_stop_msg);
+
+	/* Save the user callback and user data */
+	umac_stop_msg.callback = umac_stop_complete_cb;
+	umac_stop_msg.bodyptr = (void *)&g_stop_evt;
+
+	/* post the message.. */
+	qdf_status = scheduler_post_msg(QDF_MODULE_ID_SYS, &umac_stop_msg);
+	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
+		qdf_status = QDF_STATUS_E_BADMSG;
+
+	qdf_status = qdf_wait_for_event_completion(&g_stop_evt,
+			SYS_STOP_TIMEOUT);
+	QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
+
+	qdf_status = qdf_event_destroy(&g_stop_evt);
+	QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
+
+	return qdf_status;
+}
+
 /**
  * sys_mc_process_msg() - to process system mc thread messages
  * @p_cds_context: pointer to cds context
@@ -88,6 +163,25 @@ static QDF_STATUS sys_mc_process_msg(struct scheduler_msg *pMsg)
 	if (SYS_MSG_COOKIE == pMsg->reserved) {
 		/* Process all the new SYS messages.. */
 		switch (pMsg->type) {
+		case SYS_MSG_ID_UMAC_STOP:
+			QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR,
+				"Processing SYS MC STOP");
+			hHal = cds_get_context(QDF_MODULE_ID_PE);
+			if (NULL == hHal) {
+				QDF_TRACE(QDF_MODULE_ID_SYS,
+					QDF_TRACE_LEVEL_ERROR,
+					"%s: Invalid hHal", __func__);
+				break;
+			}
+			qdf_status = sme_stop(hHal,
+					      HAL_STOP_TYPE_SYS_DEEP_SLEEP);
+			QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
+			qdf_status = mac_stop(hHal,
+					      HAL_STOP_TYPE_SYS_DEEP_SLEEP);
+			QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
+			((sys_rsp_cb) pMsg->callback)(pMsg->bodyptr);
+			qdf_status = QDF_STATUS_SUCCESS;
+			break;
 		case SYS_MSG_ID_MC_THR_PROBE:
 			/*
 			 * Process MC thread probe.  Just callback to the