qcacld-3.0: Call cdp function to deregister IPA handler from pdev

A htt message arrived after ipa context is freed as part of
deinitialization which was dereferenced by event handler
assigned to pdev->ipa_uc_op_cb, resulting in crash.
To fix this, cdp function is called during deinit to
deregister pdev->ipa_uc_op_cb and assign it NULL. Also, adding
NULL check in wlan_ipa_uc_op_cb. Also, registering ipa_uc_op_cb
after work is created so as to not hit condition where work is
scheduled before creation.

Change-Id: Ib79136b1122625079d8173a401dba5516126c621
CRs-Fixed: 2794663
This commit is contained in:
Ananya Gupta
2020-10-09 22:03:58 +05:30
committato da snandini
parent 9078ea1486
commit bbe449f218

Vedi File

@@ -3502,7 +3502,7 @@ static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
struct op_msg_type *msg = op_msg; struct op_msg_type *msg = op_msg;
struct ipa_uc_fw_stats *uc_fw_stat; struct ipa_uc_fw_stats *uc_fw_stat;
if (!op_msg) { if (!ipa_ctx || !op_msg) {
ipa_err("INVALID ARG"); ipa_err("INVALID ARG");
return; return;
} }
@@ -3731,9 +3731,6 @@ QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
ipa_err("Failed to init perf level"); ipa_err("Failed to init perf level");
} }
cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id,
wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) { for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
ipa_ctx->uc_op_work[i].osdev = osdev; ipa_ctx->uc_op_work[i].osdev = osdev;
qdf_create_work(0, &ipa_ctx->uc_op_work[i].work, qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
@@ -3742,6 +3739,8 @@ QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
ipa_ctx->uc_op_work[i].msg = NULL; ipa_ctx->uc_op_work[i].msg = NULL;
} }
cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id,
wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
fail_return: fail_return:
ipa_debug("exit: status=%d", status); ipa_debug("exit: status=%d", status);
return status; return status;
@@ -3790,6 +3789,8 @@ QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
wlan_ipa_cleanup_pending_event(ipa_ctx); wlan_ipa_cleanup_pending_event(ipa_ctx);
qdf_mutex_release(&ipa_ctx->ipa_lock); 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++) { for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
qdf_cancel_work(&ipa_ctx->uc_op_work[i].work); qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
qdf_mem_free(ipa_ctx->uc_op_work[i].msg); qdf_mem_free(ipa_ctx->uc_op_work[i].msg);