Hi Baolu,
On Sat, Mar 14, 2020 at 09:07:01AM +0800, Lu Baolu wrote:
+static int iommu_group_change_def_domain(struct iommu_group *group, int type)
+{
+ struct group_device *grp_dev, *temp;
+ struct iommu_domain *new, *old;
+ const struct iommu_ops *ops;
+ int ret = 0;
+
+ if ((type != IOMMU_DOMAIN_IDENTITY && type != IOMMU_DOMAIN_DMA) ||
+ !group->default_domain || type == group->default_domain->type ||
+ !group->default_domain->ops)
+ return -EINVAL;
+
+ if (group->domain != group->default_domain)
+ return -EBUSY;
+
+ iommu_group_ref_get(group);
+ old = group->default_domain;
+ ops = group->default_domain->ops;
+
+ /* Allocate a new domain of requested type. */
+ new = ops->domain_alloc(type);
+ if (!new) {
+ ret = -ENOMEM;
+ goto domain_out;
+ }
+ new->type = type;
+ new->ops = ops;
+ new->pgsize_bitmap = group->default_domain->pgsize_bitmap;
+
+ group->default_domain = new;
+ group->domain = new;
+ list_for_each_entry_safe(grp_dev, temp, &group->devices, list) {
+ struct device *dev;
+
+ dev = grp_dev->dev;
+ if (device_is_bound(dev)) {
+ ret = -EINVAL;
+ goto device_out;
+ }
+
+ iommu_group_create_direct_mappings(group, dev);
+ ret = __iommu_attach_device(group->domain, dev);
+ if (ret)
+ goto device_out;
In case of a failure here with a group containing multiple devices, the
other devices temporarily lose their mappings. Please only do the
device_is_bound() check in the loop and the actual re-attachment of the
group with a call to __iommu_attach_group().