aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/iommu.c')
-rw-r--r--drivers/iommu/iommu.c50
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 */
837int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops) 845int 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}
847EXPORT_SYMBOL_GPL(bus_set_iommu); 861EXPORT_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}
1125EXPORT_SYMBOL_GPL(iommu_unmap); 1139EXPORT_SYMBOL_GPL(iommu_unmap);
1126 1140
1141size_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
1165out_err:
1166 /* undo mappings already done */
1167 iommu_unmap(domain, iova, mapped);
1168
1169 return 0;
1170
1171}
1172EXPORT_SYMBOL_GPL(default_iommu_map_sg);
1127 1173
1128int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, 1174int 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)