* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define pr_fmt(fmt) "%s: " fmt, __func__
+#define pr_fmt(fmt) "iommu: " fmt
#include <linux/device.h>
#include <linux/kernel.h>
{
struct iommu_group *group = to_iommu_group(kobj);
+ pr_debug("Releasing group %d\n", group->id);
+
if (group->iommu_data_release)
group->iommu_data_release(group->iommu_data);
*/
kobject_put(&group->kobj);
+ pr_debug("Allocated group %d\n", group->id);
+
return group;
}
EXPORT_SYMBOL_GPL(iommu_group_alloc);
IOMMU_GROUP_NOTIFY_ADD_DEVICE, dev);
trace_add_device_to_group(group->id, dev);
+
+ pr_info("Adding device %s to group %d\n", dev_name(dev), group->id);
+
return 0;
}
EXPORT_SYMBOL_GPL(iommu_group_add_device);
struct iommu_group *group = dev->iommu_group;
struct iommu_device *tmp_device, *device = NULL;
+ pr_info("Removing device %s from group %d\n", dev_name(dev), group->id);
+
/* Pre-notify listeners that a device is being removed. */
blocking_notifier_call_chain(&group->notifier,
IOMMU_GROUP_NOTIFY_DEL_DEVICE, dev);
WARN_ON(dev->iommu_group);
- ops->add_device(dev);
+ 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;
}
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;
}
/**