aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorMark Salter <msalter@redhat.com>2014-09-21 13:58:24 -0400
committerJoerg Roedel <jroedel@suse.de>2014-09-25 10:46:37 -0400
commitfb3e306515ba6a012364b698b8ca71c337424ed3 (patch)
treedd1e4d8eb4e448d944e05fdc122796c0372f4728 /drivers/iommu
parent25b11ce2a3607d7c39a2ca121eea0c67c722b34e (diff)
iommu: Fix bus notifier breakage
iommu_bus_init() registers a bus notifier on the given bus by using a statically defined notifier block: static struct notifier_block iommu_bus_nb = { .notifier_call = iommu_bus_notifier, }; This same notifier block is used for all busses. This causes a problem for notifiers registered after iommu has registered this callback on multiple busses. The problem is that a subsequent notifier being registered on a bus which has this iommu notifier will also get linked in to the notifier list of all other busses which have this iommu notifier. This patch fixes this by allocating the notifier_block at runtime. Some error checking is also added to catch any allocation failure or notifier registration error. Signed-off-by: Mark Salter <msalter@redhat.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/iommu.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index b59826aa5531..ed8b04867b1f 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -799,18 +799,26 @@ static int iommu_bus_notifier(struct notifier_block *nb,
799 return 0; 799 return 0;
800} 800}
801 801
802static struct notifier_block iommu_bus_nb = { 802static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
803 .notifier_call = iommu_bus_notifier,
804};
805
806static void iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
807{ 803{
804 int err;
805 struct notifier_block *nb;
808 struct iommu_callback_data cb = { 806 struct iommu_callback_data cb = {
809 .ops = ops, 807 .ops = ops,
810 }; 808 };
811 809
812 bus_register_notifier(bus, &iommu_bus_nb); 810 nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
813 bus_for_each_dev(bus, NULL, &cb, add_iommu_group); 811 if (!nb)
812 return -ENOMEM;
813
814 nb->notifier_call = iommu_bus_notifier;
815
816 err = bus_register_notifier(bus, nb);
817 if (err) {
818 kfree(nb);
819 return err;
820 }
821 return bus_for_each_dev(bus, NULL, &cb, add_iommu_group);
814} 822}
815 823
816/** 824/**
@@ -834,9 +842,7 @@ int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops)
834 bus->iommu_ops = ops; 842 bus->iommu_ops = ops;
835 843
836 /* Do IOMMU specific setup for this bus-type */ 844 /* Do IOMMU specific setup for this bus-type */
837 iommu_bus_init(bus, ops); 845 return iommu_bus_init(bus, ops);
838
839 return 0;
840} 846}
841EXPORT_SYMBOL_GPL(bus_set_iommu); 847EXPORT_SYMBOL_GPL(bus_set_iommu);
842 848