From 1eb4e0ae5cf2e81aa8f292b184a6018926b93f8a Mon Sep 17 00:00:00 2001 From: Dustin Brown Date: Tue, 6 Jun 2017 15:07:01 -0700 Subject: [PATCH] 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 --- pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c | 146 +++++++++++---------- 1 file changed, 74 insertions(+), 72 deletions(-) diff --git a/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c b/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c index ada0d391d960..7493d5233d68 100644 --- a/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c +++ b/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) { - 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; + QDF_STATUS status = QDF_STATUS_SUCCESS; + QDF_STATUS resume_status; 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"); - 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,