diff options
Diffstat (limited to 'drivers/iommu/iommu.c')
-rw-r--r-- | drivers/iommu/iommu.c | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ed8b04867b1f..02e4313e937c 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
@@ -818,7 +818,15 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops) | |||
818 | kfree(nb); | 818 | kfree(nb); |
819 | return err; | 819 | return err; |
820 | } | 820 | } |
821 | return bus_for_each_dev(bus, NULL, &cb, add_iommu_group); | 821 | |
822 | err = bus_for_each_dev(bus, NULL, &cb, add_iommu_group); | ||
823 | if (err) { | ||
824 | bus_unregister_notifier(bus, nb); | ||
825 | kfree(nb); | ||
826 | return err; | ||
827 | } | ||
828 | |||
829 | return 0; | ||
822 | } | 830 | } |
823 | 831 | ||
824 | /** | 832 | /** |
@@ -836,13 +844,19 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops) | |||
836 | */ | 844 | */ |
837 | int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops) | 845 | int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops) |
838 | { | 846 | { |
847 | int err; | ||
848 | |||
839 | if (bus->iommu_ops != NULL) | 849 | if (bus->iommu_ops != NULL) |
840 | return -EBUSY; | 850 | return -EBUSY; |
841 | 851 | ||
842 | bus->iommu_ops = ops; | 852 | bus->iommu_ops = ops; |
843 | 853 | ||
844 | /* Do IOMMU specific setup for this bus-type */ | 854 | /* Do IOMMU specific setup for this bus-type */ |
845 | return iommu_bus_init(bus, ops); | 855 | err = iommu_bus_init(bus, ops); |
856 | if (err) | ||
857 | bus->iommu_ops = NULL; | ||
858 | |||
859 | return err; | ||
846 | } | 860 | } |
847 | EXPORT_SYMBOL_GPL(bus_set_iommu); | 861 | EXPORT_SYMBOL_GPL(bus_set_iommu); |
848 | 862 | ||
@@ -1124,6 +1138,38 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) | |||
1124 | } | 1138 | } |
1125 | EXPORT_SYMBOL_GPL(iommu_unmap); | 1139 | EXPORT_SYMBOL_GPL(iommu_unmap); |
1126 | 1140 | ||
1141 | size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova, | ||
1142 | struct scatterlist *sg, unsigned int nents, int prot) | ||
1143 | { | ||
1144 | struct scatterlist *s; | ||
1145 | size_t mapped = 0; | ||
1146 | unsigned int i; | ||
1147 | int ret; | ||
1148 | |||
1149 | for_each_sg(sg, s, nents, i) { | ||
1150 | phys_addr_t phys = page_to_phys(sg_page(s)); | ||
1151 | |||
1152 | /* We are mapping on page boundarys, so offset must be 0 */ | ||
1153 | if (s->offset) | ||
1154 | goto out_err; | ||
1155 | |||
1156 | ret = iommu_map(domain, iova + mapped, phys, s->length, prot); | ||
1157 | if (ret) | ||
1158 | goto out_err; | ||
1159 | |||
1160 | mapped += s->length; | ||
1161 | } | ||
1162 | |||
1163 | return mapped; | ||
1164 | |||
1165 | out_err: | ||
1166 | /* undo mappings already done */ | ||
1167 | iommu_unmap(domain, iova, mapped); | ||
1168 | |||
1169 | return 0; | ||
1170 | |||
1171 | } | ||
1172 | EXPORT_SYMBOL_GPL(default_iommu_map_sg); | ||
1127 | 1173 | ||
1128 | int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, | 1174 | int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, |
1129 | phys_addr_t paddr, u64 size, int prot) | 1175 | phys_addr_t paddr, u64 size, int prot) |