diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2014-05-15 06:40:49 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2014-05-26 05:22:25 -0400 |
commit | dda7c2e4d3f160aecf21ca56d73ceb0ff6ede587 (patch) | |
tree | 4ecd22517afc46bf543967408ca1714e46eb48eb | |
parent | 9009f256596da78567d63c434691f7e409a99400 (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.c | 32 |
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 | ||
613 | static 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 | |||
613 | static int ipmmu_handle_mapping(struct ipmmu_vmsa_domain *domain, | 625 | static 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 | ||
647 | done: | 670 | done: |
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 | /* ----------------------------------------------------------------------------- |