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:

committed by
snandini

parent
04b495069b
commit
fd1b019165
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user