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
This commit is contained in:
Yeshwanth Sriram Guntuka
2020-10-23 18:24:56 +05:30
committed by snandini
parent 04b495069b
commit fd1b019165
2 changed files with 18 additions and 9 deletions

View File

@@ -710,6 +710,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)

View File

@@ -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;
@@ -3210,6 +3216,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)
@@ -3767,6 +3774,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);
@@ -3783,14 +3799,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;
}