iommu: Fix iommu_sva_bind_device to the same domain

Message ID 20240221061832.430-1-zhangfei.gao@linaro.org
State New
Headers
Series iommu: Fix iommu_sva_bind_device to the same domain |

Commit Message

Zhangfei Gao Feb. 21, 2024, 6:18 a.m. UTC
  The accelerator dev can provide multi-queue and bind to
the same domain in multi-thread for better performance,
and domain refcount takes care of it.

'commit 092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
removes the possibility, so fix it

Fixs: '092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
 drivers/iommu/iommu-sva.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
  

Comments

Tian, Kevin Feb. 21, 2024, 7:09 a.m. UTC | #1
> From: Zhangfei Gao <zhangfei.gao@linaro.org>
> Sent: Wednesday, February 21, 2024 2:19 PM
> 
> The accelerator dev can provide multi-queue and bind to
> the same domain in multi-thread for better performance,
> and domain refcount takes care of it.
> 
> 'commit 092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
> removes the possibility, so fix it
> 
> Fixs: '092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> ---
>  drivers/iommu/iommu-sva.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
> index c3fc9201d0be..a95c8f3a5407 100644
> --- a/drivers/iommu/iommu-sva.c
> +++ b/drivers/iommu/iommu-sva.c
> @@ -91,7 +91,7 @@ struct iommu_sva *iommu_sva_bind_device(struct
> device *dev, struct mm_struct *mm
>  	/* Search for an existing domain. */
>  	list_for_each_entry(domain, &mm->iommu_mm->sva_domains,
> next) {
>  		ret = iommu_attach_device_pasid(domain, dev, iommu_mm-
> >pasid);
> -		if (!ret) {
> +		if (!ret || ret == -EBUSY) {
>  			domain->users++;
>  			goto out;

-EBUSY is not a right indicator for reuse.

It may simply indicate that the pasid has been used for other purposes
e.g. attached to a domain different from what the caller expects here.
  
Zhangfei Gao Feb. 21, 2024, 7:57 a.m. UTC | #2
On Wed, 21 Feb 2024 at 15:09, Tian, Kevin <kevin.tian@intel.com> wrote:
>
> > From: Zhangfei Gao <zhangfei.gao@linaro.org>
> > Sent: Wednesday, February 21, 2024 2:19 PM
> >
> > The accelerator dev can provide multi-queue and bind to
> > the same domain in multi-thread for better performance,
> > and domain refcount takes care of it.
> >
> > 'commit 092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
> > removes the possibility, so fix it
> >
> > Fixs: '092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
> > Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> > ---
> >  drivers/iommu/iommu-sva.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
> > index c3fc9201d0be..a95c8f3a5407 100644
> > --- a/drivers/iommu/iommu-sva.c
> > +++ b/drivers/iommu/iommu-sva.c
> > @@ -91,7 +91,7 @@ struct iommu_sva *iommu_sva_bind_device(struct
> > device *dev, struct mm_struct *mm
> >       /* Search for an existing domain. */
> >       list_for_each_entry(domain, &mm->iommu_mm->sva_domains,
> > next) {
> >               ret = iommu_attach_device_pasid(domain, dev, iommu_mm-
> > >pasid);
> > -             if (!ret) {
> > +             if (!ret || ret == -EBUSY) {
> >                       domain->users++;
> >                       goto out;
>
> -EBUSY is not a right indicator for reuse.
>
> It may simply indicate that the pasid has been used for other purposes
> e.g. attached to a domain different from what the caller expects here.

Thanks Kevin.

How about this

diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index c3fc9201d0be..20b232c7675d 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -141,8 +141,8 @@ void iommu_sva_unbind_device(struct iommu_sva *handle)
        struct device *dev = handle->dev;

        mutex_lock(&iommu_sva_lock);
-       iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
        if (--domain->users == 0) {
+               iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
                list_del(&domain->next);
                iommu_domain_free(domain);
        }

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index d14413916f93..a16ade93db25 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3551,7 +3551,7 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
        mutex_lock(&group->mutex);
        curr = xa_cmpxchg(&group->pasid_array, pasid, NULL, domain, GFP_KERNEL);
        if (curr) {
-               ret = xa_err(curr) ? : -EBUSY;
+               ret = xa_err(curr) ? : 0;
                goto out_unlock;
        }

if pasid is already attached, does not treat as error,
and domain->user++ in iommu_sva_bind_device.

Thanks
  
Zhang, Tina Feb. 21, 2024, 7:59 a.m. UTC | #3
Hi,

> -----Original Message-----
> From: Zhangfei Gao <zhangfei.gao@linaro.org>
> Sent: Wednesday, February 21, 2024 2:19 PM
> To: Joerg Roedel <joro@8bytes.org>; Will Deacon <will@kernel.org>; jean-
> philippe <jean-philippe@linaro.org>; Jason Gunthorpe <jgg@nvidia.com>;
> baolu.lu@linux.intel.com; Zhang, Tina <tina.zhang@intel.com>
> Cc: iommu@lists.linux.dev; linux-kernel@vger.kernel.org; Zhangfei Gao
> <zhangfei.gao@linaro.org>
> Subject: [PATCH] iommu: Fix iommu_sva_bind_device to the same domain
> 
> The accelerator dev can provide multi-queue and bind to the same domain in
> multi-thread for better performance, and domain refcount takes care of it.
> 
> 'commit 092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
> removes the possibility, so fix it
> 
> Fixs: '092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> ---
>  drivers/iommu/iommu-sva.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c index
> c3fc9201d0be..a95c8f3a5407 100644
> --- a/drivers/iommu/iommu-sva.c
> +++ b/drivers/iommu/iommu-sva.c
> @@ -91,7 +91,7 @@ struct iommu_sva *iommu_sva_bind_device(struct
> device *dev, struct mm_struct *mm
>  	/* Search for an existing domain. */
>  	list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next)
> {
>  		ret = iommu_attach_device_pasid(domain, dev, iommu_mm-
> >pasid);
> -		if (!ret) {
> +		if (!ret || ret == -EBUSY) {
If rebinding is allowed, how could IOMMU core know if this invocation is intended (like the multi-thread case mentioned in the commit message) or is mistakenly invoked?

Thanks,
-Tina

>  			domain->users++;
>  			goto out;
>  		}
> @@ -141,8 +141,8 @@ void iommu_sva_unbind_device(struct iommu_sva
> *handle)
>  	struct device *dev = handle->dev;
> 
>  	mutex_lock(&iommu_sva_lock);
> -	iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
>  	if (--domain->users == 0) {
> +		iommu_detach_device_pasid(domain, dev, iommu_mm-
> >pasid);
>  		list_del(&domain->next);
>  		iommu_domain_free(domain);
>  	}
> --
> 2.34.1
  
Zhangfei Gao Feb. 21, 2024, 8:39 a.m. UTC | #4
On Wed, 21 Feb 2024 at 15:59, Zhang, Tina <tina.zhang@intel.com> wrote:
>
> Hi,
>
> > -----Original Message-----
> > From: Zhangfei Gao <zhangfei.gao@linaro.org>
> > Sent: Wednesday, February 21, 2024 2:19 PM
> > To: Joerg Roedel <joro@8bytes.org>; Will Deacon <will@kernel.org>; jean-
> > philippe <jean-philippe@linaro.org>; Jason Gunthorpe <jgg@nvidia.com>;
> > baolu.lu@linux.intel.com; Zhang, Tina <tina.zhang@intel.com>
> > Cc: iommu@lists.linux.dev; linux-kernel@vger.kernel.org; Zhangfei Gao
> > <zhangfei.gao@linaro.org>
> > Subject: [PATCH] iommu: Fix iommu_sva_bind_device to the same domain
> >
> > The accelerator dev can provide multi-queue and bind to the same domain in
> > multi-thread for better performance, and domain refcount takes care of it.
> >
> > 'commit 092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
> > removes the possibility, so fix it
> >
> > Fixs: '092edaddb660 ("iommu: Support mm PASID 1:n with sva domains")'
> > Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> > ---
> >  drivers/iommu/iommu-sva.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c index
> > c3fc9201d0be..a95c8f3a5407 100644
> > --- a/drivers/iommu/iommu-sva.c
> > +++ b/drivers/iommu/iommu-sva.c
> > @@ -91,7 +91,7 @@ struct iommu_sva *iommu_sva_bind_device(struct
> > device *dev, struct mm_struct *mm
> >       /* Search for an existing domain. */
> >       list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next)
> > {
> >               ret = iommu_attach_device_pasid(domain, dev, iommu_mm-
> > >pasid);
> > -             if (!ret) {
> > +             if (!ret || ret == -EBUSY) {
> If rebinding is allowed, how could IOMMU core know if this invocation is intended (like the multi-thread case mentioned in the commit message) or is mistakenly invoked?

I think it is the purpose of refcount, it should be no difference
whether same device or not.
Even different dev, IOMMU core can not make sure it is intended or
mistakenly invoked.

Add the limitation does not make sense.

Thanks
  

Patch

diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index c3fc9201d0be..a95c8f3a5407 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -91,7 +91,7 @@  struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
 	/* Search for an existing domain. */
 	list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
 		ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid);
-		if (!ret) {
+		if (!ret || ret == -EBUSY) {
 			domain->users++;
 			goto out;
 		}
@@ -141,8 +141,8 @@  void iommu_sva_unbind_device(struct iommu_sva *handle)
 	struct device *dev = handle->dev;
 
 	mutex_lock(&iommu_sva_lock);
-	iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
 	if (--domain->users == 0) {
+		iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
 		list_del(&domain->next);
 		iommu_domain_free(domain);
 	}