aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/arm-smmu.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-15 00:02:18 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-15 00:02:18 -0500
commit91838e2dab460ba589fb90db0fe1f504f5c04f12 (patch)
tree53974ed7a32ddd63d75e2da63f00d8308eb8d08a /drivers/iommu/arm-smmu.c
parentf080480488028bcc25357f85e8ae54ccc3bb7173 (diff)
parentbb51eeee5a947f61eeefaa55221c26460542654d (diff)
Merge tag 'iommu-updates-v3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU updates from Joerg Roedel: "This time the updates contain: - Tracepoints for certain IOMMU-API functions to make their use easier to debug - A tracepoint for IOMMU page faults to make it easier to get them in user space - Updates and fixes for the new ARM SMMU driver after the first hardware showed up - Various other fixes and cleanups in other IOMMU drivers" * tag 'iommu-updates-v3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (26 commits) iommu/shmobile: Enable the driver on all ARM platforms iommu/tegra-smmu: Staticize tegra_smmu_pm_ops iommu/tegra-gart: Staticize tegra_gart_pm_ops iommu/vt-d: Use list_for_each_entry_safe() for dmar_domain->devices traversal iommu/vt-d: Use for_each_drhd_unit() instead of list_for_each_entry() iommu/vt-d: Fixed interaction of VFIO_IOMMU_MAP_DMA with IOMMU address limits iommu/arm-smmu: Clear global and context bank fault status registers iommu/arm-smmu: Print context fault information iommu/arm-smmu: Check for num_context_irqs > 0 to avoid divide by zero exception iommu/arm-smmu: Refine check for proper size of mapped region iommu/arm-smmu: Switch to subsys_initcall for driver registration iommu/arm-smmu: use relaxed accessors where possible iommu/arm-smmu: replace devm_request_and_ioremap by devm_ioremap_resource iommu: Remove stack trace from broken irq remapping warning iommu: Change iommu driver to call io_page_fault trace event iommu: Add iommu_error class event to iommu trace iommu/tegra: gart: cleanup devm_* functions usage iommu/tegra: Print phys_addr_t using %pa iommu: No need to pass '0x' when '%pa' is used iommu: Change iommu driver to call unmap trace event ...
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r--drivers/iommu/arm-smmu.c69
1 files changed, 37 insertions, 32 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 2349d6272aef..1abfb5684ab7 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -590,6 +590,9 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
590 ret = IRQ_HANDLED; 590 ret = IRQ_HANDLED;
591 resume = RESUME_RETRY; 591 resume = RESUME_RETRY;
592 } else { 592 } else {
593 dev_err_ratelimited(smmu->dev,
594 "Unhandled context fault: iova=0x%08lx, fsynr=0x%x, cb=%d\n",
595 iova, fsynr, root_cfg->cbndx);
593 ret = IRQ_NONE; 596 ret = IRQ_NONE;
594 resume = RESUME_TERMINATE; 597 resume = RESUME_TERMINATE;
595 } 598 }
@@ -778,7 +781,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
778#ifdef __BIG_ENDIAN 781#ifdef __BIG_ENDIAN
779 reg |= SCTLR_E; 782 reg |= SCTLR_E;
780#endif 783#endif
781 writel(reg, cb_base + ARM_SMMU_CB_SCTLR); 784 writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR);
782} 785}
783 786
784static int arm_smmu_init_domain_context(struct iommu_domain *domain, 787static int arm_smmu_init_domain_context(struct iommu_domain *domain,
@@ -1562,9 +1565,13 @@ static struct iommu_ops arm_smmu_ops = {
1562static void arm_smmu_device_reset(struct arm_smmu_device *smmu) 1565static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
1563{ 1566{
1564 void __iomem *gr0_base = ARM_SMMU_GR0(smmu); 1567 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1565 void __iomem *sctlr_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB_SCTLR; 1568 void __iomem *cb_base;
1566 int i = 0; 1569 int i = 0;
1567 u32 scr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0); 1570 u32 reg;
1571
1572 /* Clear Global FSR */
1573 reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR);
1574 writel(reg, gr0_base + ARM_SMMU_GR0_sGFSR);
1568 1575
1569 /* Mark all SMRn as invalid and all S2CRn as bypass */ 1576 /* Mark all SMRn as invalid and all S2CRn as bypass */
1570 for (i = 0; i < smmu->num_mapping_groups; ++i) { 1577 for (i = 0; i < smmu->num_mapping_groups; ++i) {
@@ -1572,33 +1579,38 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
1572 writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i)); 1579 writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i));
1573 } 1580 }
1574 1581
1575 /* Make sure all context banks are disabled */ 1582 /* Make sure all context banks are disabled and clear CB_FSR */
1576 for (i = 0; i < smmu->num_context_banks; ++i) 1583 for (i = 0; i < smmu->num_context_banks; ++i) {
1577 writel_relaxed(0, sctlr_base + ARM_SMMU_CB(smmu, i)); 1584 cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);
1585 writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
1586 writel_relaxed(FSR_FAULT, cb_base + ARM_SMMU_CB_FSR);
1587 }
1578 1588
1579 /* Invalidate the TLB, just in case */ 1589 /* Invalidate the TLB, just in case */
1580 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_STLBIALL); 1590 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_STLBIALL);
1581 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH); 1591 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH);
1582 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH); 1592 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH);
1583 1593
1594 reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0);
1595
1584 /* Enable fault reporting */ 1596 /* Enable fault reporting */
1585 scr0 |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE); 1597 reg |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE);
1586 1598
1587 /* Disable TLB broadcasting. */ 1599 /* Disable TLB broadcasting. */
1588 scr0 |= (sCR0_VMIDPNE | sCR0_PTM); 1600 reg |= (sCR0_VMIDPNE | sCR0_PTM);
1589 1601
1590 /* Enable client access, but bypass when no mapping is found */ 1602 /* Enable client access, but bypass when no mapping is found */
1591 scr0 &= ~(sCR0_CLIENTPD | sCR0_USFCFG); 1603 reg &= ~(sCR0_CLIENTPD | sCR0_USFCFG);
1592 1604
1593 /* Disable forced broadcasting */ 1605 /* Disable forced broadcasting */
1594 scr0 &= ~sCR0_FB; 1606 reg &= ~sCR0_FB;
1595 1607
1596 /* Don't upgrade barriers */ 1608 /* Don't upgrade barriers */
1597 scr0 &= ~(sCR0_BSU_MASK << sCR0_BSU_SHIFT); 1609 reg &= ~(sCR0_BSU_MASK << sCR0_BSU_SHIFT);
1598 1610
1599 /* Push the button */ 1611 /* Push the button */
1600 arm_smmu_tlb_sync(smmu); 1612 arm_smmu_tlb_sync(smmu);
1601 writel(scr0, gr0_base + ARM_SMMU_GR0_sCR0); 1613 writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sCR0);
1602} 1614}
1603 1615
1604static int arm_smmu_id_size_to_bits(int size) 1616static int arm_smmu_id_size_to_bits(int size)
@@ -1703,13 +1715,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
1703 id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID1); 1715 id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID1);
1704 smmu->pagesize = (id & ID1_PAGESIZE) ? SZ_64K : SZ_4K; 1716 smmu->pagesize = (id & ID1_PAGESIZE) ? SZ_64K : SZ_4K;
1705 1717
1706 /* Check that we ioremapped enough */ 1718 /* Check for size mismatch of SMMU address space from mapped region */
1707 size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1); 1719 size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1);
1708 size *= (smmu->pagesize << 1); 1720 size *= (smmu->pagesize << 1);
1709 if (smmu->size < size) 1721 if (smmu->size != size)
1710 dev_warn(smmu->dev, 1722 dev_warn(smmu->dev, "SMMU address space size (0x%lx) differs "
1711 "device is 0x%lx bytes but only mapped 0x%lx!\n", 1723 "from mapped region size (0x%lx)!\n", size, smmu->size);
1712 size, smmu->size);
1713 1724
1714 smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) & 1725 smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) &
1715 ID1_NUMS2CB_MASK; 1726 ID1_NUMS2CB_MASK;
@@ -1784,15 +1795,10 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
1784 smmu->dev = dev; 1795 smmu->dev = dev;
1785 1796
1786 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1797 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1787 if (!res) { 1798 smmu->base = devm_ioremap_resource(dev, res);
1788 dev_err(dev, "missing base address/size\n"); 1799 if (IS_ERR(smmu->base))
1789 return -ENODEV; 1800 return PTR_ERR(smmu->base);
1790 }
1791
1792 smmu->size = resource_size(res); 1801 smmu->size = resource_size(res);
1793 smmu->base = devm_request_and_ioremap(dev, res);
1794 if (!smmu->base)
1795 return -EADDRNOTAVAIL;
1796 1802
1797 if (of_property_read_u32(dev->of_node, "#global-interrupts", 1803 if (of_property_read_u32(dev->of_node, "#global-interrupts",
1798 &smmu->num_global_irqs)) { 1804 &smmu->num_global_irqs)) {
@@ -1807,12 +1813,11 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
1807 smmu->num_context_irqs++; 1813 smmu->num_context_irqs++;
1808 } 1814 }
1809 1815
1810 if (num_irqs < smmu->num_global_irqs) { 1816 if (!smmu->num_context_irqs) {
1811 dev_warn(dev, "found %d interrupts but expected at least %d\n", 1817 dev_err(dev, "found %d interrupts but expected at least %d\n",
1812 num_irqs, smmu->num_global_irqs); 1818 num_irqs, smmu->num_global_irqs + 1);
1813 smmu->num_global_irqs = num_irqs; 1819 return -ENODEV;
1814 } 1820 }
1815 smmu->num_context_irqs = num_irqs - smmu->num_global_irqs;
1816 1821
1817 smmu->irqs = devm_kzalloc(dev, sizeof(*smmu->irqs) * num_irqs, 1822 smmu->irqs = devm_kzalloc(dev, sizeof(*smmu->irqs) * num_irqs,
1818 GFP_KERNEL); 1823 GFP_KERNEL);
@@ -1936,7 +1941,7 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
1936 free_irq(smmu->irqs[i], smmu); 1941 free_irq(smmu->irqs[i], smmu);
1937 1942
1938 /* Turn the thing off */ 1943 /* Turn the thing off */
1939 writel(sCR0_CLIENTPD, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_sCR0); 1944 writel_relaxed(sCR0_CLIENTPD, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_sCR0);
1940 return 0; 1945 return 0;
1941} 1946}
1942 1947
@@ -1984,7 +1989,7 @@ static void __exit arm_smmu_exit(void)
1984 return platform_driver_unregister(&arm_smmu_driver); 1989 return platform_driver_unregister(&arm_smmu_driver);
1985} 1990}
1986 1991
1987module_init(arm_smmu_init); 1992subsys_initcall(arm_smmu_init);
1988module_exit(arm_smmu_exit); 1993module_exit(arm_smmu_exit);
1989 1994
1990MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations"); 1995MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");