diff options
author | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2016-07-01 12:50:10 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2016-07-08 13:06:04 -0400 |
commit | 16c11325cc44f0614a45e584d439e195059c3f5a (patch) | |
tree | 627f73411c416acee852480df7f88f228e7dfe49 /arch/arm64/mm | |
parent | 19a469a58720ea96b649b06fb09ddfd3e831aa69 (diff) |
arm64: mm: change IOMMU notifier action to attach DMA ops
Current bus notifier in ARM64 (__iommu_attach_notifier)
attempts to attach dma_ops to a device on BUS_NOTIFY_ADD_DEVICE
action notification.
This will cause issues on ACPI based systems, where PCI devices
can be added before the IOMMUs the devices are attached to
had a chance to be probed, causing failures on attempts to
attach dma_ops in that the domain for the respective IOMMU
may not be set-up yet by the time the bus notifier is run.
Devices dma_ops do not require to be set-up till the matching
device drivers are probed. This means that instead of running
the notifier attaching dma_ops to devices (__iommu_attach_notifier)
on BUS_NOTIFY_ADD_DEVICE action, it can be run just before the
device driver is bound to the device in question (on action
BUS_NOTIFY_BIND_DRIVER) so that it is certain that its IOMMU
group and domain are set-up accordingly at the time the
notifier is triggered.
This patch changes the notifier action upon which dma_ops
are attached to devices and defer it to driver binding time,
so that IOMMU devices have a chance to be probed and to register
their bus notifiers before the dma_ops attach sequence for a
device is actually carried out.
As a result we also no longer need worry about racing with
iommu_bus_notifier(), or about retrying the queue in case devices
were added too early on DT-based systems, so clean up the notifier
itself plus the additional workaround from 722ec35f7fae ("arm64:
dma-mapping: fix handling of devices registered before arch_initcall")
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
[rm: get rid of other now-redundant bits]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64/mm')
-rw-r--r-- | arch/arm64/mm/dma-mapping.c | 22 |
1 files changed, 5 insertions, 17 deletions
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 46a4157adc17..f6c55afab3e2 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c | |||
@@ -861,15 +861,16 @@ static int __iommu_attach_notifier(struct notifier_block *nb, | |||
861 | { | 861 | { |
862 | struct iommu_dma_notifier_data *master, *tmp; | 862 | struct iommu_dma_notifier_data *master, *tmp; |
863 | 863 | ||
864 | if (action != BUS_NOTIFY_ADD_DEVICE) | 864 | if (action != BUS_NOTIFY_BIND_DRIVER) |
865 | return 0; | 865 | return 0; |
866 | 866 | ||
867 | mutex_lock(&iommu_dma_notifier_lock); | 867 | mutex_lock(&iommu_dma_notifier_lock); |
868 | list_for_each_entry_safe(master, tmp, &iommu_dma_masters, list) { | 868 | list_for_each_entry_safe(master, tmp, &iommu_dma_masters, list) { |
869 | if (do_iommu_attach(master->dev, master->ops, | 869 | if (data == master->dev && do_iommu_attach(master->dev, |
870 | master->dma_base, master->size)) { | 870 | master->ops, master->dma_base, master->size)) { |
871 | list_del(&master->list); | 871 | list_del(&master->list); |
872 | kfree(master); | 872 | kfree(master); |
873 | break; | ||
873 | } | 874 | } |
874 | } | 875 | } |
875 | mutex_unlock(&iommu_dma_notifier_lock); | 876 | mutex_unlock(&iommu_dma_notifier_lock); |
@@ -883,17 +884,8 @@ static int __init register_iommu_dma_ops_notifier(struct bus_type *bus) | |||
883 | 884 | ||
884 | if (!nb) | 885 | if (!nb) |
885 | return -ENOMEM; | 886 | return -ENOMEM; |
886 | /* | 887 | |
887 | * The device must be attached to a domain before the driver probe | ||
888 | * routine gets a chance to start allocating DMA buffers. However, | ||
889 | * the IOMMU driver also needs a chance to configure the iommu_group | ||
890 | * via its add_device callback first, so we need to make the attach | ||
891 | * happen between those two points. Since the IOMMU core uses a bus | ||
892 | * notifier with default priority for add_device, do the same but | ||
893 | * with a lower priority to ensure the appropriate ordering. | ||
894 | */ | ||
895 | nb->notifier_call = __iommu_attach_notifier; | 888 | nb->notifier_call = __iommu_attach_notifier; |
896 | nb->priority = -100; | ||
897 | 889 | ||
898 | ret = bus_register_notifier(bus, nb); | 890 | ret = bus_register_notifier(bus, nb); |
899 | if (ret) { | 891 | if (ret) { |
@@ -917,10 +909,6 @@ static int __init __iommu_dma_init(void) | |||
917 | if (!ret) | 909 | if (!ret) |
918 | ret = register_iommu_dma_ops_notifier(&pci_bus_type); | 910 | ret = register_iommu_dma_ops_notifier(&pci_bus_type); |
919 | #endif | 911 | #endif |
920 | |||
921 | /* handle devices queued before this arch_initcall */ | ||
922 | if (!ret) | ||
923 | __iommu_attach_notifier(NULL, BUS_NOTIFY_ADD_DEVICE, NULL); | ||
924 | return ret; | 912 | return ret; |
925 | } | 913 | } |
926 | arch_initcall(__iommu_dma_init); | 914 | arch_initcall(__iommu_dma_init); |