From 31d8751c4ec8dc6ed691c0f2c723479a44e6198a Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Fri, 23 Oct 2020 18:24:56 +0530 Subject: [PATCH] qcacld-3.0: Do not sched IPA UC op work when de-init is in progress In the scenario where IPA UC ready work is processed after wlan_ipa_uc_ol_deinit, triggered as part of idle shutdown, there is a possibility for NULL wbm srng pointer derefernce when setting the tx doorbell address. Fix is to avoid scheduling UC op work when deinit is in progress. Change-Id: Ifa0908912b77f45b7d93c5f9c2f5aaf9e17685c5 CRs-Fixed: 2807218 --- components/ipa/core/inc/wlan_ipa_priv.h | 1 + components/ipa/core/src/wlan_ipa_core.c | 26 ++++++++++++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/components/ipa/core/inc/wlan_ipa_priv.h b/components/ipa/core/inc/wlan_ipa_priv.h index 040adaebfb3a..fcf22a5601ec 100644 --- a/components/ipa/core/inc/wlan_ipa_priv.h +++ b/components/ipa/core/inc/wlan_ipa_priv.h @@ -709,6 +709,7 @@ struct wlan_ipa_priv { bool is_smmu_enabled; /* IPA caps returned from ipa_wdi_init */ qdf_atomic_t stats_quota; uint8_t curr_bw_level; + qdf_atomic_t deinit_in_prog; }; #define WLAN_IPA_WLAN_FRAG_HEADER sizeof(struct frag_header) diff --git a/components/ipa/core/src/wlan_ipa_core.c b/components/ipa/core/src/wlan_ipa_core.c index 2826ae88ce16..f5973ebd553e 100644 --- a/components/ipa/core/src/wlan_ipa_core.c +++ b/components/ipa/core/src/wlan_ipa_core.c @@ -168,7 +168,13 @@ static void wlan_ipa_uc_loaded_uc_cb(void *priv_ctxt) goto done; uc_op_work->msg = msg; - qdf_sched_work(0, &uc_op_work->work); + + if (!qdf_atomic_read(&ipa_ctx->deinit_in_prog)) { + qdf_sched_work(0, &uc_op_work->work); + } else { + uc_op_work->msg = NULL; + goto done; + } /* work handler will free the msg buffer */ return; @@ -3167,6 +3173,7 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx, qdf_list_create(&ipa_ctx->pending_event, 1000); qdf_mutex_create(&ipa_ctx->event_lock); qdf_mutex_create(&ipa_ctx->ipa_lock); + qdf_atomic_init(&ipa_ctx->deinit_in_prog); status = wlan_ipa_wdi_setup_rm(ipa_ctx); if (status != QDF_STATUS_SUCCESS) @@ -3724,6 +3731,15 @@ QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx) wlan_ipa_uc_disable_pipes(ipa_ctx, true); + cdp_ipa_deregister_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id); + qdf_atomic_set(&ipa_ctx->deinit_in_prog, 1); + + for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) { + qdf_cancel_work(&ipa_ctx->uc_op_work[i].work); + qdf_mem_free(ipa_ctx->uc_op_work[i].msg); + ipa_ctx->uc_op_work[i].msg = NULL; + } + if (true == ipa_ctx->uc_loaded) { cdp_ipa_tx_buf_smmu_unmapping(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id); @@ -3740,14 +3756,6 @@ QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx) wlan_ipa_cleanup_pending_event(ipa_ctx); qdf_mutex_release(&ipa_ctx->ipa_lock); - cdp_ipa_deregister_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id); - - for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) { - qdf_cancel_work(&ipa_ctx->uc_op_work[i].work); - qdf_mem_free(ipa_ctx->uc_op_work[i].msg); - ipa_ctx->uc_op_work[i].msg = NULL; - } - ipa_debug("exit: ret=%d", status); return status; }