summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Truong <truong@codeaurora.org>2017-04-07 18:33:10 -0700
committerTony Truong <truong@codeaurora.org>2017-04-07 19:24:08 -0700
commitdcbc60c11680230372b8c9ae25bad56a0202ff4d (patch)
tree8252c25498723cdc548503416104dbd808b69423
parent1da237c93bbfac333ba49398c5c85393829b5474 (diff)
msm: pcie: support QGIC MSI with SMMU fastmap enabled
IOVA used to map QGIC MSI address needs to come from client when fastmap is enabled. Change-Id: I1ce9e073dfb26d10dc18a99f5fe58d013aa538d4 Signed-off-by: Tony Truong <truong@codeaurora.org>
-rw-r--r--drivers/pci/host/pci-msm.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 121c994e6033..22b7969e6dea 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -5811,9 +5811,10 @@ static int msm_pcie_map_qgic_addr(struct msm_pcie_dev_t *dev,
struct msi_msg *msg)
{
struct iommu_domain *domain = iommu_get_domain_for_dev(&pdev->dev);
- int ret, bypass_en = 0;
+ struct iommu_domain_geometry geometry;
+ int ret, fastmap_en = 0, bypass_en = 0;
dma_addr_t iova;
- phys_addr_t pcie_base_addr, gicm_db_offset;
+ phys_addr_t gicm_db_offset;
msg->address_hi = 0;
msg->address_lo = dev->msi_gicm_addr;
@@ -5835,16 +5836,25 @@ static int msm_pcie_map_qgic_addr(struct msm_pcie_dev_t *dev,
if (bypass_en)
return 0;
- gicm_db_offset = dev->msi_gicm_addr -
- rounddown(dev->msi_gicm_addr, PAGE_SIZE);
- /*
- * Use PCIe DBI address as the IOVA since client cannot
- * use this address for their IOMMU mapping. This will
- * prevent any conflicts between PCIe host and
- * client's mapping.
- */
- pcie_base_addr = dev->res[MSM_PCIE_RES_DM_CORE].resource->start;
- iova = rounddown(pcie_base_addr, PAGE_SIZE);
+ iommu_domain_get_attr(domain, DOMAIN_ATTR_FAST, &fastmap_en);
+ if (fastmap_en) {
+ iommu_domain_get_attr(domain, DOMAIN_ATTR_GEOMETRY, &geometry);
+ iova = geometry.aperture_start;
+ PCIE_DBG(dev,
+ "PCIe: RC%d: Use client's IOVA 0x%llx to map QGIC MSI address\n",
+ dev->rc_idx, iova);
+ } else {
+ phys_addr_t pcie_base_addr;
+
+ /*
+ * Use PCIe DBI address as the IOVA since client cannot
+ * use this address for their IOMMU mapping. This will
+ * prevent any conflicts between PCIe host and
+ * client's mapping.
+ */
+ pcie_base_addr = dev->res[MSM_PCIE_RES_DM_CORE].resource->start;
+ iova = rounddown(pcie_base_addr, PAGE_SIZE);
+ }
ret = iommu_map(domain, iova, rounddown(dev->msi_gicm_addr, PAGE_SIZE),
PAGE_SIZE, IOMMU_READ | IOMMU_WRITE);
@@ -5855,6 +5865,8 @@ static int msm_pcie_map_qgic_addr(struct msm_pcie_dev_t *dev,
return -ENOMEM;
}
+ gicm_db_offset = dev->msi_gicm_addr -
+ rounddown(dev->msi_gicm_addr, PAGE_SIZE);
msg->address_lo = iova + gicm_db_offset;
return 0;