Loading drivers/net/wireless/cnss2/pci.c +49 −4 Original line number Diff line number Diff line Loading @@ -3439,12 +3439,17 @@ static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv) "smmu_iova_ipa"); if (res) { pci_priv->smmu_iova_ipa_start = res->start; pci_priv->smmu_iova_ipa_current = res->start; pci_priv->smmu_iova_ipa_len = resource_size(res); cnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: 0x%zx\n", &pci_priv->smmu_iova_ipa_start, pci_priv->smmu_iova_ipa_len); } pci_priv->iommu_geometry = of_property_read_bool(of_node, "qcom,iommu-geometry"); cnss_pr_dbg("iommu_geometry: %d\n", pci_priv->iommu_geometry); of_node_put(of_node); return 0; Loading Loading @@ -3519,10 +3524,11 @@ int cnss_smmu_map(struct device *dev, plat_priv = pci_priv->plat_priv; len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE); iova = roundup(pci_priv->smmu_iova_ipa_start, PAGE_SIZE); iova = roundup(pci_priv->smmu_iova_ipa_current, PAGE_SIZE); if (iova >= (pci_priv->smmu_iova_ipa_start + pci_priv->smmu_iova_ipa_len)) { if (pci_priv->iommu_geometry && iova >= pci_priv->smmu_iova_ipa_start + pci_priv->smmu_iova_ipa_len) { cnss_pr_err("No IOVA space to map, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", iova, &pci_priv->smmu_iova_ipa_start, Loading @@ -3549,6 +3555,8 @@ int cnss_smmu_map(struct device *dev, } } cnss_pr_dbg("IOMMU map: iova %lx, len %zu\n", iova, len); ret = iommu_map(pci_priv->iommu_domain, iova, rounddown(paddr, PAGE_SIZE), len, flag); if (ret) { Loading @@ -3556,13 +3564,50 @@ int cnss_smmu_map(struct device *dev, return ret; } pci_priv->smmu_iova_ipa_start = iova + len; pci_priv->smmu_iova_ipa_current = iova + len; *iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE)); cnss_pr_dbg("IOMMU map: iova_addr %lx\n", *iova_addr); return 0; } EXPORT_SYMBOL(cnss_smmu_map); int cnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size) { struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev)); unsigned long iova; size_t unmapped; size_t len; if (!pci_priv) return -ENODEV; iova = rounddown(iova_addr, PAGE_SIZE); len = roundup(size + iova_addr - iova, PAGE_SIZE); if (iova >= pci_priv->smmu_iova_ipa_start + pci_priv->smmu_iova_ipa_len) { cnss_pr_err("Out of IOVA space to unmap, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", iova, &pci_priv->smmu_iova_ipa_start, pci_priv->smmu_iova_ipa_len); return -ENOMEM; } cnss_pr_dbg("IOMMU unmap: iova %lx, len %zu\n", iova, len); unmapped = iommu_unmap(pci_priv->iommu_domain, iova, len); if (unmapped != len) { cnss_pr_err("IOMMU unmap failed, unmapped = %zu, requested = %zu\n", unmapped, len); return -EINVAL; } pci_priv->smmu_iova_ipa_current = iova; return 0; } EXPORT_SYMBOL(cnss_smmu_unmap); int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info) { struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev)); Loading drivers/net/wireless/cnss2/pci.h +2 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ struct cnss_pci_data { dma_addr_t smmu_iova_start; size_t smmu_iova_len; dma_addr_t smmu_iova_ipa_start; dma_addr_t smmu_iova_ipa_current; size_t smmu_iova_ipa_len; void __iomem *bar; struct cnss_msi_config *msi_config; Loading @@ -102,6 +103,7 @@ struct cnss_pci_data { u32 pcie_reg_size; struct cnss_misc_reg *wlaon_reg; u32 wlaon_reg_size; u8 iommu_geometry; }; static inline void cnss_set_pci_priv(struct pci_dev *pci_dev, void *data) Loading include/net/cnss2.h +1 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ extern int cnss_get_platform_cap(struct device *dev, extern struct iommu_domain *cnss_smmu_get_domain(struct device *dev); extern int cnss_smmu_map(struct device *dev, phys_addr_t paddr, uint32_t *iova_addr, size_t size); extern int cnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size); extern int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info); extern int cnss_request_bus_bandwidth(struct device *dev, int bandwidth); extern int cnss_power_up(struct device *dev); Loading Loading
drivers/net/wireless/cnss2/pci.c +49 −4 Original line number Diff line number Diff line Loading @@ -3439,12 +3439,17 @@ static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv) "smmu_iova_ipa"); if (res) { pci_priv->smmu_iova_ipa_start = res->start; pci_priv->smmu_iova_ipa_current = res->start; pci_priv->smmu_iova_ipa_len = resource_size(res); cnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: 0x%zx\n", &pci_priv->smmu_iova_ipa_start, pci_priv->smmu_iova_ipa_len); } pci_priv->iommu_geometry = of_property_read_bool(of_node, "qcom,iommu-geometry"); cnss_pr_dbg("iommu_geometry: %d\n", pci_priv->iommu_geometry); of_node_put(of_node); return 0; Loading Loading @@ -3519,10 +3524,11 @@ int cnss_smmu_map(struct device *dev, plat_priv = pci_priv->plat_priv; len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE); iova = roundup(pci_priv->smmu_iova_ipa_start, PAGE_SIZE); iova = roundup(pci_priv->smmu_iova_ipa_current, PAGE_SIZE); if (iova >= (pci_priv->smmu_iova_ipa_start + pci_priv->smmu_iova_ipa_len)) { if (pci_priv->iommu_geometry && iova >= pci_priv->smmu_iova_ipa_start + pci_priv->smmu_iova_ipa_len) { cnss_pr_err("No IOVA space to map, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", iova, &pci_priv->smmu_iova_ipa_start, Loading @@ -3549,6 +3555,8 @@ int cnss_smmu_map(struct device *dev, } } cnss_pr_dbg("IOMMU map: iova %lx, len %zu\n", iova, len); ret = iommu_map(pci_priv->iommu_domain, iova, rounddown(paddr, PAGE_SIZE), len, flag); if (ret) { Loading @@ -3556,13 +3564,50 @@ int cnss_smmu_map(struct device *dev, return ret; } pci_priv->smmu_iova_ipa_start = iova + len; pci_priv->smmu_iova_ipa_current = iova + len; *iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE)); cnss_pr_dbg("IOMMU map: iova_addr %lx\n", *iova_addr); return 0; } EXPORT_SYMBOL(cnss_smmu_map); int cnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size) { struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev)); unsigned long iova; size_t unmapped; size_t len; if (!pci_priv) return -ENODEV; iova = rounddown(iova_addr, PAGE_SIZE); len = roundup(size + iova_addr - iova, PAGE_SIZE); if (iova >= pci_priv->smmu_iova_ipa_start + pci_priv->smmu_iova_ipa_len) { cnss_pr_err("Out of IOVA space to unmap, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", iova, &pci_priv->smmu_iova_ipa_start, pci_priv->smmu_iova_ipa_len); return -ENOMEM; } cnss_pr_dbg("IOMMU unmap: iova %lx, len %zu\n", iova, len); unmapped = iommu_unmap(pci_priv->iommu_domain, iova, len); if (unmapped != len) { cnss_pr_err("IOMMU unmap failed, unmapped = %zu, requested = %zu\n", unmapped, len); return -EINVAL; } pci_priv->smmu_iova_ipa_current = iova; return 0; } EXPORT_SYMBOL(cnss_smmu_unmap); int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info) { struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev)); Loading
drivers/net/wireless/cnss2/pci.h +2 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ struct cnss_pci_data { dma_addr_t smmu_iova_start; size_t smmu_iova_len; dma_addr_t smmu_iova_ipa_start; dma_addr_t smmu_iova_ipa_current; size_t smmu_iova_ipa_len; void __iomem *bar; struct cnss_msi_config *msi_config; Loading @@ -102,6 +103,7 @@ struct cnss_pci_data { u32 pcie_reg_size; struct cnss_misc_reg *wlaon_reg; u32 wlaon_reg_size; u8 iommu_geometry; }; static inline void cnss_set_pci_priv(struct pci_dev *pci_dev, void *data) Loading
include/net/cnss2.h +1 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ extern int cnss_get_platform_cap(struct device *dev, extern struct iommu_domain *cnss_smmu_get_domain(struct device *dev); extern int cnss_smmu_map(struct device *dev, phys_addr_t paddr, uint32_t *iova_addr, size_t size); extern int cnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size); extern int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info); extern int cnss_request_bus_bandwidth(struct device *dev, int bandwidth); extern int cnss_power_up(struct device *dev); Loading