summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorFrank Liu <qiliu@codeaurora.org>2018-07-27 14:32:53 +0800
committerGerrit - the friendly Code Review server <code-review@localhost>2018-08-01 03:21:40 -0700
commit26eff67153cf547158db519817fb61dfd6e9da30 (patch)
tree7f9a731e8d7106b8e9957fcf310dede46dc16575 /drivers/net
parent414b079b7f4ba955f4679cd87be64199b4e875c7 (diff)
cnss2: Add support for PCIe WLAN IPA uc SMMU feature
To add support for PCIe WLAN IPA uc SMMU feature, prvoide related platform api for wlan driver to get the smmu map handle and do the mapping. Change-Id: I672b1a48879ada65b3ddb3f16c4bd787dc1b70a6 Signed-off-by: Frank Liu <qiliu@codeaurora.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/cnss2/pci.c66
-rw-r--r--drivers/net/wireless/cnss2/pci.h2
2 files changed, 68 insertions, 0 deletions
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index ff053b098c22..0f4ef3712dd7 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -1414,6 +1414,61 @@ void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv)
CNSS_REASON_TIMEOUT);
}
+struct dma_iommu_mapping *cnss_smmu_get_mapping(struct device *dev)
+{
+ struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev));
+
+ if (!pci_priv)
+ return NULL;
+
+ return pci_priv->smmu_mapping;
+}
+EXPORT_SYMBOL(cnss_smmu_get_mapping);
+
+int cnss_smmu_map(struct device *dev,
+ phys_addr_t paddr, 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 len;
+ int ret = 0;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ if (!iova_addr) {
+ cnss_pr_err("iova_addr is NULL, paddr %pa, size %zu\n",
+ &paddr, size);
+ return -EINVAL;
+ }
+
+ len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE);
+ iova = roundup(pci_priv->smmu_iova_ipa_start, PAGE_SIZE);
+
+ if (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,
+ pci_priv->smmu_iova_ipa_len);
+ return -ENOMEM;
+ }
+
+ ret = iommu_map(pci_priv->smmu_mapping->domain, iova,
+ rounddown(paddr, PAGE_SIZE), len,
+ IOMMU_READ | IOMMU_WRITE);
+ if (ret) {
+ cnss_pr_err("PA to IOVA mapping failed, ret %d\n", ret);
+ return ret;
+ }
+
+ pci_priv->smmu_iova_ipa_start = iova + len;
+ *iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE));
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_smmu_map);
+
int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info)
{
int ret = 0;
@@ -2129,6 +2184,17 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
&pci_priv->smmu_iova_start,
pci_priv->smmu_iova_len);
+ res = platform_get_resource_byname(plat_priv->plat_dev,
+ IORESOURCE_MEM,
+ "smmu_iova_ipa");
+ if (res) {
+ pci_priv->smmu_iova_ipa_start = res->start;
+ pci_priv->smmu_iova_ipa_len = resource_size(res);
+ cnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: %zu\n",
+ &pci_priv->smmu_iova_ipa_start,
+ pci_priv->smmu_iova_ipa_len);
+ }
+
ret = cnss_pci_init_smmu(pci_priv);
if (ret) {
cnss_pr_err("Failed to init SMMU, err = %d\n", ret);
diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h
index 182355ae7577..e47f14e8a325 100644
--- a/drivers/net/wireless/cnss2/pci.h
+++ b/drivers/net/wireless/cnss2/pci.h
@@ -73,6 +73,8 @@ struct cnss_pci_data {
struct dma_iommu_mapping *smmu_mapping;
dma_addr_t smmu_iova_start;
size_t smmu_iova_len;
+ dma_addr_t smmu_iova_ipa_start;
+ size_t smmu_iova_ipa_len;
void __iomem *bar;
struct cnss_msi_config *msi_config;
u32 msi_ep_base_data;