Bladeren bron

qcacmn: Check for null resume handlers in suspend recovery

After an error, during the suspend process, previously suspended
components are resumed in reverse order. However, while the suspend case
checks for null handlers before dispatching them, the recovery case does
not. Ensure each resume handler is not null before calling it during
suspend recovery.

Change-Id: I86baa4cba9d2b64871da58427a4657b4b3642cdc
CRs-Fixed: 2057165
Dustin Brown 7 jaren geleden
bovenliggende
commit
1eb4e0ae5c
1 gewijzigde bestanden met toevoegingen van 75 en 73 verwijderingen
  1. 75 73
      pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c

+ 75 - 73
pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c

@@ -452,112 +452,114 @@ out:
 }
 
 QDF_STATUS pmo_suspend_all_components(struct wlan_objmgr_psoc *psoc,
-	enum qdf_suspend_type suspend_type)
+				      enum qdf_suspend_type suspend_type)
 {
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	QDF_STATUS resume_status;
+	struct wlan_pmo_ctx *pmo_ctx;
+	uint8_t i;
 	pmo_psoc_suspend_handler handler;
-	uint8_t index = 0;
-	QDF_STATUS suspend_status = QDF_STATUS_SUCCESS;
-	QDF_STATUS resume_status = QDF_STATUS_SUCCESS;
 	void *arg;
-	struct wlan_pmo_ctx *pmo_ctx;
 
 	PMO_ENTER();
+
 	pmo_ctx = pmo_get_context();
 	if (!pmo_ctx) {
-		QDF_ASSERT(0);
 		pmo_err("unable to get pmo ctx");
-		suspend_status = QDF_STATUS_E_FAILURE;
-		goto out;
+		QDF_ASSERT(0);
+		status = QDF_STATUS_E_FAILURE;
+		goto exit_with_status;
 	}
 
-	/* call all component's Suspend Handler */
-	while (index < WLAN_UMAC_MAX_COMPONENTS) {
+	/* call each component's suspend handler */
+	for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
 		qdf_spin_lock_bh(&pmo_ctx->lock);
-		if (pmo_ctx->pmo_suspend_handler[index]) {
-			handler = pmo_ctx->pmo_suspend_handler[index];
-			arg = pmo_ctx->pmo_suspend_handler_arg[index];
-			qdf_spin_unlock_bh(&pmo_ctx->lock);
-			suspend_status = handler(psoc, arg);
-			if (suspend_status != QDF_STATUS_SUCCESS) {
-				pmo_err("component id: %d failed to suspend status: %d",
-					index, suspend_status);
-				QDF_ASSERT(0);
-				/* break, no need to suspend next components */
-				break;
-			}
-		} else {
-			qdf_spin_unlock_bh(&pmo_ctx->lock);
+		handler = pmo_ctx->pmo_suspend_handler[i];
+		arg = pmo_ctx->pmo_suspend_handler_arg[i];
+		qdf_spin_unlock_bh(&pmo_ctx->lock);
+
+		if (!handler)
+			continue;
+
+		status = handler(psoc, arg);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			pmo_err("component %d failed to suspend; status: %d",
+				i, status);
+			QDF_ASSERT(0);
+			goto suspend_recovery;
 		}
-		index++;
-	}
-
-	/* resume the succefully suspended components */
-	if (suspend_status != QDF_STATUS_SUCCESS) {
-		while (index >= 0) {
-			/*
-			 * index points to id which refuse suspend
-			 * so go to previous id.
-			 */
-			index--;
-			qdf_spin_lock_bh(&pmo_ctx->lock);
-			handler = pmo_ctx->pmo_resume_handler[index];
-			arg = pmo_ctx->pmo_resume_handler_arg[index];
-			qdf_spin_unlock_bh(&pmo_ctx->lock);
-			/* TODO: if resume got failed for some component ?? */
-			resume_status = handler(psoc, arg);
-			if (resume_status != QDF_STATUS_SUCCESS) {
-				pmo_err("Component id: %d failed to resume status: %d",
-					index, resume_status);
-				QDF_ASSERT(0);
-			}
+	}
+
+	goto exit_with_status;
+
+suspend_recovery:
+	/* resume, starting with the last successfully suspended component */
+	for (i -= 1; i >= 0; i--) {
+		qdf_spin_lock_bh(&pmo_ctx->lock);
+		handler = pmo_ctx->pmo_resume_handler[i];
+		arg = pmo_ctx->pmo_resume_handler_arg[i];
+		qdf_spin_unlock_bh(&pmo_ctx->lock);
+
+		if (!handler)
+			continue;
+
+		resume_status = handler(psoc, arg);
+		if (QDF_IS_STATUS_ERROR(resume_status)) {
+			pmo_fatal("Non-recoverable failure occurred!");
+			pmo_fatal("component %d failed to resume; status: %d",
+				  i, resume_status);
+			QDF_BUG(0);
 		}
 	}
-out:
+
+exit_with_status:
 	PMO_EXIT();
 
-	return suspend_status;
+	return status;
 }
 
 QDF_STATUS pmo_resume_all_components(struct wlan_objmgr_psoc *psoc,
-	enum qdf_suspend_type suspend_type)
+				     enum qdf_suspend_type suspend_type)
 {
-	uint8_t index = 0;
-	QDF_STATUS component_ret = QDF_STATUS_SUCCESS;
-	void *arg;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	struct wlan_pmo_ctx *pmo_ctx;
+	uint8_t i;
 	pmo_psoc_suspend_handler handler;
+	void *arg;
 
 	PMO_ENTER();
+
 	pmo_ctx = pmo_get_context();
 	if (!pmo_ctx) {
-		QDF_ASSERT(0);
 		pmo_err("unable to get pmo ctx");
-		component_ret = QDF_STATUS_E_FAILURE;
-		goto out;
+		QDF_ASSERT(0);
+		status = QDF_STATUS_E_FAILURE;
+		goto exit_with_status;
 	}
 
-	/* call all components Resume Handler */
-	while (index < WLAN_UMAC_MAX_COMPONENTS) {
+	/* call each component's resume handler */
+	for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) {
 		qdf_spin_lock_bh(&pmo_ctx->lock);
-		if (pmo_ctx->pmo_resume_handler[index]) {
-			handler = pmo_ctx->pmo_resume_handler[index];
-			arg = pmo_ctx->pmo_resume_handler_arg[index];
-			qdf_spin_unlock_bh(&pmo_ctx->lock);
-			component_ret = handler(psoc, arg);
-			if (component_ret != QDF_STATUS_SUCCESS) {
-				pmo_err("Component id: %d failed to resume status: %d",
-					index, component_ret);
-				QDF_ASSERT(0);
-			}
-		} else {
-			qdf_spin_unlock_bh(&pmo_ctx->lock);
+		handler = pmo_ctx->pmo_resume_handler[i];
+		arg = pmo_ctx->pmo_resume_handler_arg[i];
+		qdf_spin_unlock_bh(&pmo_ctx->lock);
+
+		if (!handler)
+			continue;
+
+		status = handler(psoc, arg);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			pmo_fatal("Non-recoverable failure occurred!");
+			pmo_fatal("component %d failed to resume; status: %d",
+				  i, status);
+			QDF_BUG(0);
 		}
-		index++;
-}
-out:
+	}
+
+exit_with_status:
 	PMO_EXIT();
 
-	return component_ret;
+	return status;
 }
 
 QDF_STATUS pmo_register_pause_bitmap_notifier(struct wlan_objmgr_psoc *psoc,