]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iommu: Detaching pasid by attaching to the blocked_domain
authorYi Liu <yi.l.liu@intel.com>
Wed, 4 Dec 2024 12:29:24 +0000 (04:29 -0800)
committerJoerg Roedel <jroedel@suse.de>
Wed, 18 Dec 2024 08:39:35 +0000 (09:39 +0100)
The iommu drivers are on the way to detach pasid by attaching to the blocked
domain. However, this cannot be done in one shot. During the transition, iommu
core would select between the remove_dev_pasid op and the blocked domain.

Suggested-by: Kevin Tian <kevin.tian@intel.com>
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Link: https://lore.kernel.org/r/20241204122928.11987-4-yi.l.liu@intel.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/iommu.c

index 2ff4fa60a86a7af225ae93625ef80b145efc17e6..2064dc8bb8b532d24962c561e5b881cf8cc6d537 100644 (file)
@@ -3316,8 +3316,18 @@ static void iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
                                   struct iommu_domain *domain)
 {
        const struct iommu_ops *ops = dev_iommu_ops(dev);
+       struct iommu_domain *blocked_domain = ops->blocked_domain;
+       int ret = 1;
 
-       ops->remove_dev_pasid(dev, pasid, domain);
+       if (blocked_domain && blocked_domain->ops->set_dev_pasid) {
+               ret = blocked_domain->ops->set_dev_pasid(blocked_domain,
+                                                        dev, pasid, domain);
+       } else {
+               ops->remove_dev_pasid(dev, pasid, domain);
+               ret = 0;
+       }
+
+       WARN_ON(ret);
 }
 
 static int __iommu_set_group_pasid(struct iommu_domain *domain,
@@ -3380,7 +3390,9 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
        ops = dev_iommu_ops(dev);
 
        if (!domain->ops->set_dev_pasid ||
-           !ops->remove_dev_pasid)
+           (!ops->remove_dev_pasid &&
+            (!ops->blocked_domain ||
+             !ops->blocked_domain->ops->set_dev_pasid)))
                return -EOPNOTSUPP;
 
        if (ops != domain->owner || pasid == IOMMU_NO_PASID)