aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2014-05-15 06:40:49 -0400
committerJoerg Roedel <jroedel@suse.de>2014-05-26 05:22:25 -0400
commitdda7c2e4d3f160aecf21ca56d73ceb0ff6ede587 (patch)
tree4ecd22517afc46bf543967408ca1714e46eb48eb
parent9009f256596da78567d63c434691f7e409a99400 (diff)
iommu/ipmmu-vmsa: Support 2MB mappings
Add support for 2MB block mappings at the PMD level. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/ipmmu-vmsa.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 87703c3faf58..7f0522048c6b 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -479,7 +479,7 @@ static void ipmmu_free_pmds(pud_t *pud)
479 unsigned int i; 479 unsigned int i;
480 480
481 for (i = 0; i < IPMMU_PTRS_PER_PMD; ++i) { 481 for (i = 0; i < IPMMU_PTRS_PER_PMD; ++i) {
482 if (pmd_none(*pmd)) 482 if (!pmd_table(*pmd))
483 continue; 483 continue;
484 484
485 ipmmu_free_ptes(pmd); 485 ipmmu_free_ptes(pmd);
@@ -610,6 +610,18 @@ static int ipmmu_alloc_init_pte(struct ipmmu_vmsa_device *mmu, pmd_t *pmd,
610 return 0; 610 return 0;
611} 611}
612 612
613static int ipmmu_alloc_init_pmd(struct ipmmu_vmsa_device *mmu, pmd_t *pmd,
614 unsigned long iova, unsigned long pfn,
615 int prot)
616{
617 pmdval_t pmdval = ipmmu_page_prot(prot, PMD_TYPE_SECT);
618
619 *pmd = pfn_pmd(pfn, __pgprot(pmdval));
620 ipmmu_flush_pgtable(mmu, pmd, sizeof(*pmd));
621
622 return 0;
623}
624
613static int ipmmu_handle_mapping(struct ipmmu_vmsa_domain *domain, 625static int ipmmu_handle_mapping(struct ipmmu_vmsa_domain *domain,
614 unsigned long iova, phys_addr_t paddr, 626 unsigned long iova, phys_addr_t paddr,
615 size_t size, int prot) 627 size_t size, int prot)
@@ -642,7 +654,18 @@ static int ipmmu_handle_mapping(struct ipmmu_vmsa_domain *domain,
642 goto done; 654 goto done;
643 } 655 }
644 656
645 ret = ipmmu_alloc_init_pte(mmu, pmd, iova, pfn, size, prot); 657 switch (size) {
658 case SZ_2M:
659 ret = ipmmu_alloc_init_pmd(mmu, pmd, iova, pfn, prot);
660 break;
661 case SZ_64K:
662 case SZ_4K:
663 ret = ipmmu_alloc_init_pte(mmu, pmd, iova, pfn, size, prot);
664 break;
665 default:
666 ret = -EINVAL;
667 break;
668 }
646 669
647done: 670done:
648 spin_unlock_irqrestore(&domain->lock, flags); 671 spin_unlock_irqrestore(&domain->lock, flags);
@@ -792,6 +815,9 @@ static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain *io_domain,
792 if (pmd_none(pmd)) 815 if (pmd_none(pmd))
793 return 0; 816 return 0;
794 817
818 if (pmd_sect(pmd))
819 return __pfn_to_phys(pmd_pfn(pmd)) | (iova & ~PMD_MASK);
820
795 pte = *(pmd_page_vaddr(pmd) + pte_index(iova)); 821 pte = *(pmd_page_vaddr(pmd) + pte_index(iova));
796 if (pte_none(pte)) 822 if (pte_none(pte))
797 return 0; 823 return 0;
@@ -930,7 +956,7 @@ static struct iommu_ops ipmmu_ops = {
930 .iova_to_phys = ipmmu_iova_to_phys, 956 .iova_to_phys = ipmmu_iova_to_phys,
931 .add_device = ipmmu_add_device, 957 .add_device = ipmmu_add_device,
932 .remove_device = ipmmu_remove_device, 958 .remove_device = ipmmu_remove_device,
933 .pgsize_bitmap = SZ_64K | SZ_4K, 959 .pgsize_bitmap = SZ_2M | SZ_64K | SZ_4K,
934}; 960};
935 961
936/* ----------------------------------------------------------------------------- 962/* -----------------------------------------------------------------------------