Skip to content

Commit

Permalink
iommu: Fix bus notifier breakage
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mark Salter authored and Joerg Roedel committed Sep 25, 2014
1 parent 25b11ce commit fb3e306
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions drivers/iommu/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -799,18 +799,26 @@ static int iommu_bus_notifier(struct notifier_block *nb,
return 0;
}

static struct notifier_block iommu_bus_nb = {
.notifier_call = iommu_bus_notifier,
};

static void iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
{
int err;
struct notifier_block *nb;
struct iommu_callback_data cb = {
.ops = ops,
};

bus_register_notifier(bus, &iommu_bus_nb);
bus_for_each_dev(bus, NULL, &cb, add_iommu_group);
nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
if (!nb)
return -ENOMEM;

nb->notifier_call = iommu_bus_notifier;

err = bus_register_notifier(bus, nb);
if (err) {
kfree(nb);
return err;
}
return bus_for_each_dev(bus, NULL, &cb, add_iommu_group);
}

/**
Expand All @@ -834,9 +842,7 @@ int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops)
bus->iommu_ops = ops;

/* Do IOMMU specific setup for this bus-type */
iommu_bus_init(bus, ops);

return 0;
return iommu_bus_init(bus, ops);
}
EXPORT_SYMBOL_GPL(bus_set_iommu);

Expand Down

0 comments on commit fb3e306

Please sign in to comment.