From bc5baf5ca6246161f78b0136ca496fa44dbc15ea Mon Sep 17 00:00:00 2001 From: Jingxiang Ge Date: Tue, 23 Feb 2021 11:50:37 +0800 Subject: [PATCH] qcacmn: Add lock protection for prevent_suspend_list Need to protect prevent_suspend_list by runtime_lock. Issue happens when 1 printing lock0 of prevent_suspend_list in thread0 2 thread0 scheduled out and lock0 is released. 3 return back to thread0, it will using lock0 pointer to check next lock, then issue happens. Fix is adding runtime_lock to protect. Change-Id: I7182651e445cf5008dba73e15b2c261cc125577f CRs-Fixed: 2883052 --- hif/src/hif_runtime_pm.c | 42 ++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/hif/src/hif_runtime_pm.c b/hif/src/hif_runtime_pm.c index de7394f6ba21..e027c55c477d 100644 --- a/hif/src/hif_runtime_pm.c +++ b/hif/src/hif_runtime_pm.c @@ -42,6 +42,8 @@ #include "hif_exec.h" #ifdef FEATURE_RUNTIME_PM +#define PREVENT_LIST_STRING_LEN 200 + /** * hif_pci_pm_runtime_enabled() - To check if Runtime PM is enabled * @scn: hif context @@ -733,29 +735,40 @@ void hif_process_runtime_suspend_failure(struct hif_opaque_softc *hif_ctx) hif_runtime_pm_set_state_on(scn); } -static void hif_pm_runtime_print_prevent_list(struct hif_softc *scn) -{ - struct hif_runtime_pm_ctx *rpm_ctx = hif_bus_get_rpm_ctx(scn); - struct hif_pm_runtime_lock *ctx; - - hif_info("prevent_suspend_cnt %u", rpm_ctx->prevent_suspend_cnt); - list_for_each_entry(ctx, &rpm_ctx->prevent_suspend_list, list) - hif_info("%s", ctx->name); -} - static bool hif_pm_runtime_is_suspend_allowed(struct hif_softc *scn) { struct hif_runtime_pm_ctx *rpm_ctx = hif_bus_get_rpm_ctx(scn); - bool ret; + struct hif_pm_runtime_lock *ctx; + uint32_t prevent_suspend_cnt; + char *str_buf; + bool is_suspend_allowed; + int len = 0; if (!scn->hif_config.enable_runtime_pm) - return 0; + return false; + + str_buf = qdf_mem_malloc(PREVENT_LIST_STRING_LEN); + if (!str_buf) + return false; spin_lock_bh(&rpm_ctx->runtime_lock); - ret = (rpm_ctx->prevent_suspend_cnt == 0); + prevent_suspend_cnt = rpm_ctx->prevent_suspend_cnt; + is_suspend_allowed = (prevent_suspend_cnt == 0); + if (!is_suspend_allowed) { + list_for_each_entry(ctx, &rpm_ctx->prevent_suspend_list, list) + len += qdf_scnprintf(str_buf + len, + PREVENT_LIST_STRING_LEN - len, + "%s ", ctx->name); + } spin_unlock_bh(&rpm_ctx->runtime_lock); - return ret; + if (!is_suspend_allowed) + hif_info("prevent_suspend_cnt %u, prevent_list: %s", + rpm_ctx->prevent_suspend_cnt, str_buf); + + qdf_mem_free(str_buf); + + return is_suspend_allowed; } /** @@ -783,7 +796,6 @@ int hif_pre_runtime_suspend(struct hif_opaque_softc *hif_ctx) /* keep this after set suspending */ if (!hif_pm_runtime_is_suspend_allowed(scn)) { hif_info("Runtime PM not allowed now"); - hif_pm_runtime_print_prevent_list(scn); return -EINVAL; }