Merge "cnss2: Add cnss_smmu_unmap API"

This commit is contained in:
qctecmdr 2020-09-13 01:13:33 -07:00 • committed by Gerrit - the friendly Code Review server
commit 8e7791b3c0
3 changed files with 52 additions and 4 deletions

View file

@ -3469,12 +3469,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;
@ -3549,10 +3554,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,
@ -3579,6 +3585,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) {
@ -3586,13 +3594,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));

View file

@ -83,6 +83,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;
@ -101,6 +102,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)

View file

@ -196,6 +196,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);