diff options
Diffstat (limited to 'drivers/iommu/iommu.c')
-rw-r--r-- | drivers/iommu/iommu.c | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ddbdacad7768..b972d430d92b 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
@@ -734,7 +734,8 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, | |||
734 | size_t orig_size = size; | 734 | size_t orig_size = size; |
735 | int ret = 0; | 735 | int ret = 0; |
736 | 736 | ||
737 | if (unlikely(domain->ops->map == NULL)) | 737 | if (unlikely(domain->ops->unmap == NULL || |
738 | domain->ops->pgsize_bitmap == 0UL)) | ||
738 | return -ENODEV; | 739 | return -ENODEV; |
739 | 740 | ||
740 | /* find out the minimum page size supported */ | 741 | /* find out the minimum page size supported */ |
@@ -808,7 +809,8 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) | |||
808 | size_t unmapped_page, unmapped = 0; | 809 | size_t unmapped_page, unmapped = 0; |
809 | unsigned int min_pagesz; | 810 | unsigned int min_pagesz; |
810 | 811 | ||
811 | if (unlikely(domain->ops->unmap == NULL)) | 812 | if (unlikely(domain->ops->unmap == NULL || |
813 | domain->ops->pgsize_bitmap == 0UL)) | ||
812 | return -ENODEV; | 814 | return -ENODEV; |
813 | 815 | ||
814 | /* find out the minimum page size supported */ | 816 | /* find out the minimum page size supported */ |
@@ -850,6 +852,26 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) | |||
850 | } | 852 | } |
851 | EXPORT_SYMBOL_GPL(iommu_unmap); | 853 | EXPORT_SYMBOL_GPL(iommu_unmap); |
852 | 854 | ||
855 | |||
856 | int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, | ||
857 | phys_addr_t paddr, u64 size) | ||
858 | { | ||
859 | if (unlikely(domain->ops->domain_window_enable == NULL)) | ||
860 | return -ENODEV; | ||
861 | |||
862 | return domain->ops->domain_window_enable(domain, wnd_nr, paddr, size); | ||
863 | } | ||
864 | EXPORT_SYMBOL_GPL(iommu_domain_window_enable); | ||
865 | |||
866 | void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr) | ||
867 | { | ||
868 | if (unlikely(domain->ops->domain_window_disable == NULL)) | ||
869 | return; | ||
870 | |||
871 | return domain->ops->domain_window_disable(domain, wnd_nr); | ||
872 | } | ||
873 | EXPORT_SYMBOL_GPL(iommu_domain_window_disable); | ||
874 | |||
853 | static int __init iommu_init(void) | 875 | static int __init iommu_init(void) |
854 | { | 876 | { |
855 | iommu_group_kset = kset_create_and_add("iommu_groups", | 877 | iommu_group_kset = kset_create_and_add("iommu_groups", |
@@ -861,13 +883,15 @@ static int __init iommu_init(void) | |||
861 | 883 | ||
862 | return 0; | 884 | return 0; |
863 | } | 885 | } |
864 | subsys_initcall(iommu_init); | 886 | arch_initcall(iommu_init); |
865 | 887 | ||
866 | int iommu_domain_get_attr(struct iommu_domain *domain, | 888 | int iommu_domain_get_attr(struct iommu_domain *domain, |
867 | enum iommu_attr attr, void *data) | 889 | enum iommu_attr attr, void *data) |
868 | { | 890 | { |
869 | struct iommu_domain_geometry *geometry; | 891 | struct iommu_domain_geometry *geometry; |
892 | bool *paging; | ||
870 | int ret = 0; | 893 | int ret = 0; |
894 | u32 *count; | ||
871 | 895 | ||
872 | switch (attr) { | 896 | switch (attr) { |
873 | case DOMAIN_ATTR_GEOMETRY: | 897 | case DOMAIN_ATTR_GEOMETRY: |
@@ -875,6 +899,19 @@ int iommu_domain_get_attr(struct iommu_domain *domain, | |||
875 | *geometry = domain->geometry; | 899 | *geometry = domain->geometry; |
876 | 900 | ||
877 | break; | 901 | break; |
902 | case DOMAIN_ATTR_PAGING: | ||
903 | paging = data; | ||
904 | *paging = (domain->ops->pgsize_bitmap != 0UL); | ||
905 | break; | ||
906 | case DOMAIN_ATTR_WINDOWS: | ||
907 | count = data; | ||
908 | |||
909 | if (domain->ops->domain_get_windows != NULL) | ||
910 | *count = domain->ops->domain_get_windows(domain); | ||
911 | else | ||
912 | ret = -ENODEV; | ||
913 | |||
914 | break; | ||
878 | default: | 915 | default: |
879 | if (!domain->ops->domain_get_attr) | 916 | if (!domain->ops->domain_get_attr) |
880 | return -EINVAL; | 917 | return -EINVAL; |
@@ -889,9 +926,26 @@ EXPORT_SYMBOL_GPL(iommu_domain_get_attr); | |||
889 | int iommu_domain_set_attr(struct iommu_domain *domain, | 926 | int iommu_domain_set_attr(struct iommu_domain *domain, |
890 | enum iommu_attr attr, void *data) | 927 | enum iommu_attr attr, void *data) |
891 | { | 928 | { |
892 | if (!domain->ops->domain_set_attr) | 929 | int ret = 0; |
893 | return -EINVAL; | 930 | u32 *count; |
894 | 931 | ||
895 | return domain->ops->domain_set_attr(domain, attr, data); | 932 | switch (attr) { |
933 | case DOMAIN_ATTR_WINDOWS: | ||
934 | count = data; | ||
935 | |||
936 | if (domain->ops->domain_set_windows != NULL) | ||
937 | ret = domain->ops->domain_set_windows(domain, *count); | ||
938 | else | ||
939 | ret = -ENODEV; | ||
940 | |||
941 | break; | ||
942 | default: | ||
943 | if (domain->ops->domain_set_attr == NULL) | ||
944 | return -EINVAL; | ||
945 | |||
946 | ret = domain->ops->domain_set_attr(domain, attr, data); | ||
947 | } | ||
948 | |||
949 | return ret; | ||
896 | } | 950 | } |
897 | EXPORT_SYMBOL_GPL(iommu_domain_set_attr); | 951 | EXPORT_SYMBOL_GPL(iommu_domain_set_attr); |