[1/2] iommu: call detach also for default_domain before attaching to new one

Message ID 1455633632-16873-2-git-send-email-m.szyprowski@samsung.com
State New
Headers show

Commit Message

Marek Szyprowski Feb. 16, 2016, 2:40 p.m.
This patch ensures that devices attached to the default_domain will be
first detached from it before attaching to new domain. To avoid forward
declaration, __iommu_attach_group() function has been moved to new place
in the source code.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/iommu.c | 38 ++++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 16 deletions(-)

Comments

Marek Szyprowski Feb. 17, 2016, 7:35 a.m. | #1
Hello,

On 2016-02-16 16:59, Joerg Roedel wrote:
> On Tue, Feb 16, 2016 at 03:40:31PM +0100, Marek Szyprowski wrote:
>> This patch ensures that devices attached to the default_domain will be
>> first detached from it before attaching to new domain. To avoid forward
>> declaration, __iommu_attach_group() function has been moved to new place
>> in the source code.
> Actually it was intentional to not invoke the detach_device call-back in
> the attach_device path.
>
> The reason is that detaching first and than attaching again leaves the
> device without a domain for a short period of time, until it is attached
> to the new domain.
>
> The attach_device call-back is supposed to handle this situation and
> just silently overwrite any other domain->device binding it finds for
> the device.
>
> This allows to do re-attachment with less iommu flushes and to get rid
> of the detach_device call-back at some point.

Huh, I wasn't aware of this change in the iommu drivers api. For some
drivers attach/detach callbacks does something more than just programming
page table base register, like for example in case of exynos iommu it is
enabling runtime power management and clocks. The code is really much 
simpler
if those calls are balanced, but if the goal is to allow multiple 
unballanced
attach calls, I will try to fix this in our driver.

Maybe it should be documented somewhere, that attach calls can be 
unbalanced?

Best regards
Marek Szyprowski Feb. 17, 2016, 2:42 p.m. | #2
Hello,

On 2016-02-17 12:14, Joerg Roedel wrote:
> On Wed, Feb 17, 2016 at 08:35:10AM +0100, Marek Szyprowski wrote:
>> Huh, I wasn't aware of this change in the iommu drivers api. For some
>> drivers attach/detach callbacks does something more than just programming
>> page table base register, like for example in case of exynos iommu it is
>> enabling runtime power management and clocks. The code is really
>> much simpler
>> if those calls are balanced, but if the goal is to allow multiple
>> unballanced
>> attach calls, I will try to fix this in our driver.
>>
>> Maybe it should be documented somewhere, that attach calls can be
>> unbalanced?
> Well, when your driver uses default-domains, the detach_dev call-back is
> not used anymore. The attach_dev call-back is supposed to just overwrite
> any existing binding that may exist for the device. So the calls are not
> unbalanced, the detach_dev calls just don't happen anymore.

 From driver perspective the default_domains don't really differ from the
'other' domains. They are just allocated from the IOMMU core and used by
the IOMMU/DMA-mapping glue code. That's what I got from reading the code.

There should be also a way to detach the driver even from the default domain
to implement the arch_tear_down_dma_ops function.

Best regards

Patch hide | download patch | download mbox

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 0e3b009..db231ad 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1198,22 +1198,6 @@  static int iommu_group_do_attach_device(struct device *dev, void *data)
 	return __iommu_attach_device(domain, dev);
 }
 
-static int __iommu_attach_group(struct iommu_domain *domain,
-				struct iommu_group *group)
-{
-	int ret;
-
-	if (group->default_domain && group->domain != group->default_domain)
-		return -EBUSY;
-
-	ret = __iommu_group_for_each_dev(group, domain,
-					 iommu_group_do_attach_device);
-	if (ret == 0)
-		group->domain = domain;
-
-	return ret;
-}
-
 int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
 {
 	int ret;
@@ -1235,6 +1219,28 @@  static int iommu_group_do_detach_device(struct device *dev, void *data)
 	return 0;
 }
 
+static int __iommu_attach_group(struct iommu_domain *domain,
+				struct iommu_group *group)
+{
+	int ret;
+
+	if (group->default_domain && group->domain != group->default_domain)
+		return -EBUSY;
+
+	if (group->default_domain && group->default_domain == group->domain) {
+		__iommu_group_for_each_dev(group, group->domain,
+					   iommu_group_do_detach_device);
+		group->domain = NULL;
+	}
+
+	ret = __iommu_group_for_each_dev(group, domain,
+					 iommu_group_do_attach_device);
+	if (ret == 0)
+		group->domain = domain;
+
+	return ret;
+}
+
 static void __iommu_detach_group(struct iommu_domain *domain,
 				 struct iommu_group *group)
 {