From 22bd494f8ed51f4dae3a1c22b8793f150cfac415 Mon Sep 17 00:00:00 2001 From: Jagadeesh Ponduru Date: Thu, 14 Oct 2021 14:10:02 +0530 Subject: [PATCH 1/6] msm: ipa3: Pointer Check and Fix overflow in Header Deletion During header deletion, if there is a HPC referencing to a header, and the header is deleted, the later commit will cause writing garbage values to the HW during commit. Change-Id: Ib8bb490e38c57d975c21e5848850cd79263c95fe Signed-off-by: Jagadeesh Ponduru --- drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index ab04374b3afe..96d783245e39 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include "ipa_i.h" @@ -90,6 +90,12 @@ static int ipa3_hdr_proc_ctx_to_hw_format(struct ipa_mem_buffer *mem, 0 : 1; } } + /* Check the pointer and header length to avoid dangerous overflow in HW */ + if (unlikely(!entry->hdr || !entry->hdr->offset_entry || + !entry->offset_entry || + entry->hdr->hdr_len == 0 || + entry->hdr->hdr_len > ipa_hdr_bin_sz[IPA_HDR_BIN_MAX - 1])) + return -EINVAL; ret = ipahal_cp_proc_ctx_to_hw_buff(entry->type, mem->base, entry->offset_entry->offset, @@ -747,7 +753,7 @@ int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) return 0; } - if (entry->is_hdr_proc_ctx) { + if (entry->is_hdr_proc_ctx || entry->proc_ctx) { dma_unmap_single(ipa3_ctx->pdev, entry->phys_base, entry->hdr_len, From cfe6d558b261d799bffa7ffc56a232ee5cec6b68 Mon Sep 17 00:00:00 2001 From: Ashok Vuyyuru Date: Wed, 20 Oct 2021 01:13:15 +0530 Subject: [PATCH 2/6] msm: ipa3: Fix to NULL terminate the header pointer in proc header table While resetting the header rules if it find invalid header ID it will return before freeting proc header table it was leading to use after free when accessing the header pointer from proc header table. Adding changes to NULL terminating header pointer in proc header table after header table deleted from the list. Change-Id: If270d855d3907e61368336316161a250053e1e62 Signed-off-by: Ashok Vuyyuru --- drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index 96d783245e39..1183d8e275c0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -1084,6 +1084,7 @@ int ipa3_reset_hdr(bool user_only) if (ipa3_id_find(entry->id) == NULL) { mutex_unlock(&ipa3_ctx->lock); + IPAERR_RL("Invalid header ID\n"); WARN_ON_RATELIMIT_IPA(1); return -EFAULT; } @@ -1094,6 +1095,7 @@ int ipa3_reset_hdr(bool user_only) entry->phys_base, entry->hdr_len, DMA_TO_DEVICE); + entry->proc_ctx->hdr = NULL; entry->proc_ctx = NULL; } else { /* move the offset entry to free list */ @@ -1151,6 +1153,7 @@ int ipa3_reset_hdr(bool user_only) if (ipa3_id_find(ctx_entry->id) == NULL) { mutex_unlock(&ipa3_ctx->lock); + IPAERR_RL("Invalid proc header ID\n"); WARN_ON_RATELIMIT_IPA(1); return -EFAULT; } From 1573aa5bb1e2346e9389b8e8312737056d2561be Mon Sep 17 00:00:00 2001 From: Ashok Vuyyuru Date: Fri, 4 Jun 2021 14:28:33 +0530 Subject: [PATCH 3/6] msm: ipa3: Adding changes to support the deep sleep mode Adding changes to support the deep sleep mode on monaco target. Change-Id: I50016848fde9533a856203bc2ad89bf851179a7b Signed-off-by: Ashok Vuyyuru --- drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 07c9fc828d24..d14a04e22540 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -2965,6 +2965,9 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, } switch (code) { +#if IS_ENABLED(CONFIG_DEEPSLEEP) + case SUBSYS_BEFORE_DS_ENTRY: +#endif case SUBSYS_BEFORE_SHUTDOWN: IPAWANINFO("IPA received MPSS BEFORE_SHUTDOWN\n"); /*Stop netdev first to stop queueing pkts to Q6 */ @@ -2986,6 +2989,9 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, ipa3_odl_pipe_cleanup(true); IPAWANINFO("IPA BEFORE_SHUTDOWN handling is complete\n"); break; +#if IS_ENABLED(CONFIG_DEEPSLEEP) + case SUBSYS_AFTER_DS_ENTRY: +#endif case SUBSYS_AFTER_SHUTDOWN: IPAWANINFO("IPA Received MPSS AFTER_SHUTDOWN\n"); if (atomic_read(&rmnet_ipa3_ctx->is_ssr) && @@ -2997,6 +3003,9 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, IPAWANINFO("IPA AFTER_SHUTDOWN handling is complete\n"); break; +#if IS_ENABLED(CONFIG_DEEPSLEEP) + case SUBSYS_BEFORE_DS_EXIT: +#endif case SUBSYS_BEFORE_POWERUP: IPAWANINFO("IPA received MPSS BEFORE_POWERUP\n"); if (atomic_read(&rmnet_ipa3_ctx->is_ssr)) { @@ -3009,6 +3018,9 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, ipa3_reset_freeze_vote(); IPAWANINFO("IPA BEFORE_POWERUP handling is complete\n"); break; +#if IS_ENABLED(CONFIG_DEEPSLEEP) + case SUBSYS_AFTER_DS_EXIT: +#endif case SUBSYS_AFTER_POWERUP: IPAWANINFO("IPA received MPSS AFTER_POWERUP\n"); if (!atomic_read(&rmnet_ipa3_ctx->is_initialized) && From 7f159650b10334bc77f274b2245ff29f3480cddc Mon Sep 17 00:00:00 2001 From: Raghavendar rao l Date: Thu, 21 Oct 2021 22:20:55 +0530 Subject: [PATCH 4/6] msm: ipa3: Retry to attach smmu nodes if fails Updated change to retry attaching smmu nodes if it fails, in a deffered work queue with 500msec delay. Change-Id: Ia54d801543224caf81085fedfd16305eca99995e Signed-off-by: Raghavendar rao l --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 67 +++++++++++++++++++------ drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 1 + 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 8e0055204e1c..4621d5f6140b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -6815,14 +6815,15 @@ static void ipa3_load_ipa_fw(struct work_struct *work) IPADBG("Entry\n"); IPA_ACTIVE_CLIENTS_INC_SIMPLE(); - if(!ipa3_ctx->ipa_pil_load) - { - result = ipa3_attach_to_smmu(); - if (result) { - IPAERR("IPA attach to smmu failed %d\n", result); - IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); - return; - } + + result = ipa3_attach_to_smmu(); + if (result) { + IPAERR("IPA attach to smmu failed %d\n", result); + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); + queue_delayed_work(ipa3_ctx->transport_power_mgmt_wq, + &ipa3_fw_load_failure_handle, + msecs_to_jiffies(DELAY_BEFORE_FW_LOAD)); + return; } if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION && @@ -8817,6 +8818,7 @@ static int ipa_smmu_wlan_cb_probe(struct device *dev) } } + cb->done = true; return 0; } @@ -8896,10 +8898,35 @@ static int ipa_smmu_uc_cb_probe(struct device *dev) ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_UC] = (bypass != 0); ipa3_ctx->uc_pdev = dev; - + cb->done = true; return 0; } +static void ipa3_ap_iommu_unmap(struct ipa_smmu_cb_ctx *cb, const u32 *add_map, u32 add_map_size) { + + int i, res; + + /* iterate of each entry of the additional mapping array */ + for (i = 0; i < add_map_size / sizeof(u32); i += 3) { + u32 iova = be32_to_cpu(add_map[i]); + u32 pa = be32_to_cpu(add_map[i + 1]); + u32 size = be32_to_cpu(add_map[i + 2]); + unsigned long iova_p; + phys_addr_t pa_p; + u32 size_p; + + IPA_SMMU_ROUND_TO_PAGE(iova, pa, size, + iova_p, pa_p, size_p); + IPADBG_LOW("unmapping 0x%lx to 0x%pa size %d\n", + iova_p, &pa_p, size_p); + + res = iommu_unmap(cb->iommu_domain,iova_p, size_p); + if(res != size_p) { + pr_err("iommu unmap failed for AP cb\n"); + ipa_assert(); + } + } +} static int ipa_smmu_ap_cb_probe(struct device *dev) { struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP); @@ -9034,6 +9061,8 @@ static int ipa_smmu_ap_cb_probe(struct device *dev) if (ret < 0 && ret != -EEXIST) { IPAERR("unable to allocate smem MODEM entry\n"); cb->valid = false; + if(add_map) + ipa3_ap_iommu_unmap(cb, add_map, add_map_size); return -EFAULT; } smem_addr = qcom_smem_get(SMEM_MODEM, @@ -9042,6 +9071,8 @@ static int ipa_smmu_ap_cb_probe(struct device *dev) if (IS_ERR(smem_addr)) { IPAERR("unable to acquire smem MODEM entry\n"); cb->valid = false; + if(add_map) + ipa3_ap_iommu_unmap(cb, add_map, add_map_size); return -EFAULT; } if (smem_size != ipa_smem_size) @@ -9062,6 +9093,7 @@ static int ipa_smmu_ap_cb_probe(struct device *dev) smmu_info.present[IPA_SMMU_CB_AP] = true; + cb->done = true; ipa3_ctx->pdev = dev; cb->next_addr = cb->va_end; @@ -9114,18 +9146,26 @@ static int ipa_smmu_11ad_cb_probe(struct device *dev) IPADBG("11AD using shared CB\n"); cb->shared = true; } - + cb->done = true; return 0; } static int ipa_smmu_cb_probe(struct device *dev, enum ipa_smmu_cb_type cb_type) { + struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(cb_type); + + if((cb != NULL) && (cb->done == true)) { + IPADBG("SMMU CB type %d already initialized\n", cb_type); + return 0; + } switch (cb_type) { case IPA_SMMU_CB_AP: + ipa3_ctx->pdev = &ipa3_ctx->master_pdev->dev; return ipa_smmu_ap_cb_probe(dev); case IPA_SMMU_CB_WLAN: return ipa_smmu_wlan_cb_probe(dev); case IPA_SMMU_CB_UC: + ipa3_ctx->uc_pdev = &ipa3_ctx->master_pdev->dev; return ipa_smmu_uc_cb_probe(dev); case IPA_SMMU_CB_11AD: return ipa_smmu_11ad_cb_probe(dev); @@ -9140,16 +9180,15 @@ static int ipa3_attach_to_smmu(void) struct ipa_smmu_cb_ctx *cb; int i, result; - ipa3_ctx->pdev = &ipa3_ctx->master_pdev->dev; - ipa3_ctx->uc_pdev = &ipa3_ctx->master_pdev->dev; - if (smmu_info.arm_smmu) { IPADBG("smmu is enabled\n"); for (i = 0; i < IPA_SMMU_CB_MAX; i++) { cb = ipa3_get_smmu_ctx(i); result = ipa_smmu_cb_probe(cb->dev, i); - if (result) + if (result) { IPAERR("probe failed for cb %d\n", i); + return result; + } } } else { IPADBG("smmu is disabled\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index c4e9c7c78e40..ed025daa26ba 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -544,6 +544,7 @@ struct ipa_smmu_cb_ctx { u32 va_end; bool shared; bool is_cache_coherent; + bool done; }; /** From f34eede3cb2127afa8c350b5dd8cc515caa7c5fe Mon Sep 17 00:00:00 2001 From: Michael Adisumarta Date: Thu, 26 Aug 2021 11:46:30 -0700 Subject: [PATCH 5/6] msm: ipa: remove initing head again if dma mapping fails Remove Initializing rx_pkt link if dma mapping fails. Change-Id: I49d08555c875fc9039805ef8775be3b676f51d08 Signed-off-by: Michael Adisumarta --- drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 5ba5c7c6fb81..25bc4cb2bc53 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -2611,7 +2611,6 @@ static void ipa3_replenish_rx_cache_recycle(struct ipa3_sys_context *sys) fail_dma_mapping: spin_lock_bh(&sys->spinlock); list_add_tail(&rx_pkt->link, &sys->rcycl_list); - INIT_LIST_HEAD(&rx_pkt->link); spin_unlock_bh(&sys->spinlock); fail_kmem_cache_alloc: if (rx_len_cached == 0) { From 676280f3558cead6391251a85aeaac68954d9d4c Mon Sep 17 00:00:00 2001 From: Michael Adisumarta Date: Wed, 22 Sep 2021 12:23:37 -0700 Subject: [PATCH 6/6] msm: ipa: add skb recycle if dma fails during replenish Add skb recycle when dma mapping fails during rx cache replenishing. Change-Id: I4ea2b1581f4d9a404248ce39bb916e58e368b7e4 Signed-off-by: Michael Adisumarta --- drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 5ba5c7c6fb81..31f687130598 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -2569,7 +2569,7 @@ static void ipa3_replenish_rx_cache_recycle(struct ipa3_sys_context *sys) spin_lock_bh(&sys->spinlock); rx_pkt = list_first_entry(&sys->rcycl_list, struct ipa3_rx_pkt_wrapper, link); - list_del(&rx_pkt->link); + list_del_init(&rx_pkt->link); spin_unlock_bh(&sys->spinlock); ptr = skb_put(rx_pkt->data.skb, sys->rx_buff_sz); rx_pkt->data.dma_addr = dma_map_single(ipa3_ctx->pdev, @@ -2610,6 +2610,7 @@ static void ipa3_replenish_rx_cache_recycle(struct ipa3_sys_context *sys) goto done; fail_dma_mapping: spin_lock_bh(&sys->spinlock); + ipa3_skb_recycle(rx_pkt->data.skb); list_add_tail(&rx_pkt->link, &sys->rcycl_list); INIT_LIST_HEAD(&rx_pkt->link); spin_unlock_bh(&sys->spinlock);