iommu: Clean up after a failed bus initialization
authorJoerg Roedel <jroedel@suse.de>
Thu, 28 May 2015 16:41:27 +0000 (18:41 +0200)
committerJoerg Roedel <jroedel@suse.de>
Fri, 5 Jun 2015 13:13:10 +0000 (15:13 +0200)
Make sure we call the ->remove_device call-back on all
devices already initialized with ->add_device when the bus
initialization fails.

Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/iommu.c

index 9c9336a923cd7d8f0730225f0fa128b6c72d6d6d..f0e0a233c902efb13f030bad471f9f5774a832e3 100644 (file)
@@ -753,6 +753,17 @@ static int add_iommu_group(struct device *dev, void *data)
        return ops->add_device(dev);
 }
 
+static int remove_iommu_group(struct device *dev, void *data)
+{
+       struct iommu_callback_data *cb = data;
+       const struct iommu_ops *ops = cb->ops;
+
+       if (ops->remove_device && dev->iommu_group)
+               ops->remove_device(dev);
+
+       return 0;
+}
+
 static int iommu_bus_notifier(struct notifier_block *nb,
                              unsigned long action, void *data)
 {
@@ -821,19 +832,25 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
        nb->notifier_call = iommu_bus_notifier;
 
        err = bus_register_notifier(bus, nb);
-       if (err) {
-               kfree(nb);
-               return err;
-       }
+       if (err)
+               goto out_free;
 
        err = bus_for_each_dev(bus, NULL, &cb, add_iommu_group);
-       if (err) {
-               bus_unregister_notifier(bus, nb);
-               kfree(nb);
-               return err;
-       }
+       if (err)
+               goto out_err;
+
 
        return 0;
+
+out_err:
+       /* Clean up */
+       bus_for_each_dev(bus, NULL, &cb, remove_iommu_group);
+       bus_unregister_notifier(bus, nb);
+
+out_free:
+       kfree(nb);
+
+       return err;
 }
 
 /**