From 593bccb51c78b5c5d8ab00ce18bba3b8fe9fa778 Mon Sep 17 00:00:00 2001 From: Ilia Lin Date: Tue, 6 Jul 2021 10:28:26 +0300 Subject: [PATCH] ipa: Fix dangling HPC entry rndis/ecm composition switch when ULSO enabled in dts Rndis/ecm use hpc based header insertion for ulso. HPC entry and a linked header entry are added on init and removed on destruction of rndis/ecm. Previously, the HPC entry was left dangling, pointing to a deleted header entry. Change-Id: I59ed7ed5ee8b3dd012f3b7d4104370dd6deac60a Acked-by: Eliad Ben Yishay Signed-off-by: Ilia Lin --- drivers/platform/msm/ipa/ipa_common_i.h | 2 + drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 67 ++++++++++++++++++++- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h index d96f54d8ca..02ae153f64 100644 --- a/drivers/platform/msm/ipa/ipa_common_i.h +++ b/drivers/platform/msm/ipa/ipa_common_i.h @@ -703,6 +703,8 @@ int ipa3_add_hdr_hpc(struct ipa_ioc_add_hdr *hdrs); int ipa3_add_hdr_hpc_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only); +int ipa3_del_hdr_hpc(struct ipa_ioc_del_hdr *hdrs); + int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs); int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index 8fc3b42b8e..9a8e3c18f3 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -744,12 +744,13 @@ static int __ipa_add_hpc_hdr_insertion(struct ipa_hdr_add *hdr, bool user) IPADBG("adding processing context for header %s\n", hdr->name); proc_ctx.type = IPA_HDR_PROC_NONE; proc_ctx.hdr_hdl = hdr->hdr_hdl; - if (__ipa_add_hdr_proc_ctx(&proc_ctx, false, user)) { + if (__ipa_add_hdr_proc_ctx(&proc_ctx, true, user)) { IPAERR("failed to add hdr proc ctx\n"); goto fail_add_proc_ctx; } entry->proc_ctx = (struct ipa3_hdr_proc_ctx_entry *)ipa3_id_find(proc_ctx.proc_ctx_hdl); WARN_ON_RATELIMIT_IPA(!entry->proc_ctx); + entry->proc_ctx->ref_cnt++; return 0; @@ -891,6 +892,70 @@ bail: return result; } +/** + * ipa3_del_hdr_hpc_usr() - Remove the specified headers from SW + * and optionally commit them to IPA HW + * @hdls: [inout] set of headers to delete + * @by_user: Operation requested by user? + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa3_del_hdr_hpc_usr(struct ipa_ioc_del_hdr *hdls, bool by_user) +{ + int i; + int result = 0; + struct ipa3_hdr_entry *entry; + struct ipa3_hdr_proc_ctx_entry *proc_ctx_entry; + + if (hdls == NULL || hdls->num_hdls == 0) { + IPAERR_RL("bad parm\n"); + return -EINVAL; + } + + mutex_lock(&ipa3_ctx->lock); + for (i = 0; i < hdls->num_hdls; i++) { + entry = (struct ipa3_hdr_entry *)ipa3_id_find(hdls->hdl[i].hdl); + if (entry) { + proc_ctx_entry = entry->proc_ctx; + entry->ref_cnt--; + result = __ipa3_del_hdr(hdls->hdl[i].hdl, by_user) != 0; + if (proc_ctx_entry) { + proc_ctx_entry->ref_cnt--; + result = __ipa3_del_hdr_proc_ctx(proc_ctx_entry->id, false, false) != 0; + } + } + hdls->hdl[i].status = result; + } + + if (hdls->commit) { + if (ipa3_ctx->ctrl->ipa3_commit_hdr()) { + result = -EPERM; + goto bail; + } + } + result = 0; +bail: + mutex_unlock(&ipa3_ctx->lock); + return result; +} + +/** + * ipa3_del_hdr_hpc() - add the specified headers to SW and + * optionally commit them to IPA HW + * @hdrs: [inout] set of headers to add + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +int ipa3_del_hdr_hpc(struct ipa_ioc_del_hdr *hdrs) +{ + return ipa3_del_hdr_hpc_usr(hdrs, false); +} +EXPORT_SYMBOL(ipa3_del_hdr_hpc); + /** * ipa3_add_hdr() - add the specified headers to SW and optionally commit them * to IPA HW diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 6d45658567..5b596304ae 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -12232,7 +12232,7 @@ int ipa_hdrs_hpc_destroy(u32 hdr_hdl) hdr_del = &del_wrapper->hdl[0]; hdr_del->hdl = hdr_hdl; - result = ipa3_del_hdr(del_wrapper); + result = ipa3_del_hdr_hpc(del_wrapper); if (result || hdr_del->status) IPAERR("ipa3_del_hdr failed\n"); kfree(del_wrapper);