Loading drivers/soc/qcom/icnss.c +51 −2 Original line number Diff line number Diff line Loading @@ -2187,7 +2187,7 @@ int icnss_smmu_map(struct device *dev, } len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE); iova = roundup(penv->smmu_iova_ipa_start, PAGE_SIZE); iova = roundup(penv->smmu_iova_ipa_current, PAGE_SIZE); if (iova >= priv->smmu_iova_ipa_start + priv->smmu_iova_ipa_len) { icnss_pr_err("No IOVA space to map, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", Loading @@ -2197,6 +2197,8 @@ int icnss_smmu_map(struct device *dev, return -ENOMEM; } icnss_pr_dbg("IOMMU Map: iova %lx, len %zu\n", iova, len); ret = iommu_map(priv->iommu_domain, iova, rounddown(paddr, PAGE_SIZE), len, IOMMU_READ | IOMMU_WRITE); Loading @@ -2205,13 +2207,59 @@ int icnss_smmu_map(struct device *dev, return ret; } priv->smmu_iova_ipa_start = iova + len; priv->smmu_iova_ipa_current = iova + len; *iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE)); icnss_pr_dbg("IOVA addr mapped to physical addr %lx\n", *iova_addr); return 0; } EXPORT_SYMBOL(icnss_smmu_map); int icnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size) { struct icnss_priv *priv = dev_get_drvdata(dev); unsigned long iova; size_t len, unmapped_len; if (!priv) { icnss_pr_err("Invalid drvdata: dev %pK, data %pK\n", dev, priv); return -EINVAL; } if (!iova_addr) { icnss_pr_err("iova_addr is NULL, size %zu\n", size); return -EINVAL; } len = roundup(size + iova_addr - rounddown(iova_addr, PAGE_SIZE), PAGE_SIZE); iova = rounddown(iova_addr, PAGE_SIZE); if (iova >= priv->smmu_iova_ipa_start + priv->smmu_iova_ipa_len) { icnss_pr_err("Out of IOVA space during unmap, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", iova, &priv->smmu_iova_ipa_start, priv->smmu_iova_ipa_len); return -ENOMEM; } icnss_pr_dbg("IOMMU Unmap: iova %lx, len %zu\n", iova, len); unmapped_len = iommu_unmap(priv->iommu_domain, iova, len); if (unmapped_len != len) { icnss_pr_err("Failed to unmap, %zu\n", unmapped_len); return -EINVAL; } priv->smmu_iova_ipa_current = iova; return 0; } EXPORT_SYMBOL(icnss_smmu_unmap); unsigned int icnss_socinfo_get_serial_number(struct device *dev) { return socinfo_get_serial_number(); Loading Loading @@ -3384,6 +3432,7 @@ static int icnss_smmu_dt_parse(struct icnss_priv *priv) icnss_pr_err("SMMU IOVA IPA not found\n"); } else { priv->smmu_iova_ipa_start = res->start; priv->smmu_iova_ipa_current = res->start; priv->smmu_iova_ipa_len = resource_size(res); icnss_pr_dbg("SMMU IOVA IPA start: %pa, len: %zx\n", &priv->smmu_iova_ipa_start, Loading drivers/soc/qcom/icnss_private.h +2 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef __ICNSS_PRIVATE_H__ Loading Loading @@ -292,6 +292,7 @@ struct icnss_priv { void __iomem *mem_base_va; struct iommu_domain *iommu_domain; dma_addr_t smmu_iova_ipa_start; dma_addr_t smmu_iova_ipa_current; size_t smmu_iova_ipa_len; struct qmi_handle qmi; struct list_head event_list; Loading include/soc/qcom/icnss.h +3 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #ifndef _ICNSS_WLAN_H_ #define _ICNSS_WLAN_H_ Loading Loading @@ -134,6 +134,8 @@ extern struct dma_iommu_mapping *icnss_smmu_get_mapping(struct device *dev); extern struct iommu_domain *icnss_smmu_get_domain(struct device *dev); extern int icnss_smmu_map(struct device *dev, phys_addr_t paddr, uint32_t *iova_addr, size_t size); extern int icnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size); extern unsigned int icnss_socinfo_get_serial_number(struct device *dev); extern bool icnss_is_qmi_disable(struct device *dev); extern bool icnss_is_fw_ready(void); Loading Loading
drivers/soc/qcom/icnss.c +51 −2 Original line number Diff line number Diff line Loading @@ -2187,7 +2187,7 @@ int icnss_smmu_map(struct device *dev, } len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE); iova = roundup(penv->smmu_iova_ipa_start, PAGE_SIZE); iova = roundup(penv->smmu_iova_ipa_current, PAGE_SIZE); if (iova >= priv->smmu_iova_ipa_start + priv->smmu_iova_ipa_len) { icnss_pr_err("No IOVA space to map, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", Loading @@ -2197,6 +2197,8 @@ int icnss_smmu_map(struct device *dev, return -ENOMEM; } icnss_pr_dbg("IOMMU Map: iova %lx, len %zu\n", iova, len); ret = iommu_map(priv->iommu_domain, iova, rounddown(paddr, PAGE_SIZE), len, IOMMU_READ | IOMMU_WRITE); Loading @@ -2205,13 +2207,59 @@ int icnss_smmu_map(struct device *dev, return ret; } priv->smmu_iova_ipa_start = iova + len; priv->smmu_iova_ipa_current = iova + len; *iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE)); icnss_pr_dbg("IOVA addr mapped to physical addr %lx\n", *iova_addr); return 0; } EXPORT_SYMBOL(icnss_smmu_map); int icnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size) { struct icnss_priv *priv = dev_get_drvdata(dev); unsigned long iova; size_t len, unmapped_len; if (!priv) { icnss_pr_err("Invalid drvdata: dev %pK, data %pK\n", dev, priv); return -EINVAL; } if (!iova_addr) { icnss_pr_err("iova_addr is NULL, size %zu\n", size); return -EINVAL; } len = roundup(size + iova_addr - rounddown(iova_addr, PAGE_SIZE), PAGE_SIZE); iova = rounddown(iova_addr, PAGE_SIZE); if (iova >= priv->smmu_iova_ipa_start + priv->smmu_iova_ipa_len) { icnss_pr_err("Out of IOVA space during unmap, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", iova, &priv->smmu_iova_ipa_start, priv->smmu_iova_ipa_len); return -ENOMEM; } icnss_pr_dbg("IOMMU Unmap: iova %lx, len %zu\n", iova, len); unmapped_len = iommu_unmap(priv->iommu_domain, iova, len); if (unmapped_len != len) { icnss_pr_err("Failed to unmap, %zu\n", unmapped_len); return -EINVAL; } priv->smmu_iova_ipa_current = iova; return 0; } EXPORT_SYMBOL(icnss_smmu_unmap); unsigned int icnss_socinfo_get_serial_number(struct device *dev) { return socinfo_get_serial_number(); Loading Loading @@ -3384,6 +3432,7 @@ static int icnss_smmu_dt_parse(struct icnss_priv *priv) icnss_pr_err("SMMU IOVA IPA not found\n"); } else { priv->smmu_iova_ipa_start = res->start; priv->smmu_iova_ipa_current = res->start; priv->smmu_iova_ipa_len = resource_size(res); icnss_pr_dbg("SMMU IOVA IPA start: %pa, len: %zx\n", &priv->smmu_iova_ipa_start, Loading
drivers/soc/qcom/icnss_private.h +2 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef __ICNSS_PRIVATE_H__ Loading Loading @@ -292,6 +292,7 @@ struct icnss_priv { void __iomem *mem_base_va; struct iommu_domain *iommu_domain; dma_addr_t smmu_iova_ipa_start; dma_addr_t smmu_iova_ipa_current; size_t smmu_iova_ipa_len; struct qmi_handle qmi; struct list_head event_list; Loading
include/soc/qcom/icnss.h +3 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #ifndef _ICNSS_WLAN_H_ #define _ICNSS_WLAN_H_ Loading Loading @@ -134,6 +134,8 @@ extern struct dma_iommu_mapping *icnss_smmu_get_mapping(struct device *dev); extern struct iommu_domain *icnss_smmu_get_domain(struct device *dev); extern int icnss_smmu_map(struct device *dev, phys_addr_t paddr, uint32_t *iova_addr, size_t size); extern int icnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size); extern unsigned int icnss_socinfo_get_serial_number(struct device *dev); extern bool icnss_is_qmi_disable(struct device *dev); extern bool icnss_is_fw_ready(void); Loading