iommu/vt-d: Make identity_domain_set_dev_pasid() to handle domain replacement
authorYi Liu <yi.l.liu@intel.com>
Fri, 8 Nov 2024 02:14:01 +0000 (10:14 +0800)
committerJoerg Roedel <jroedel@suse.de>
Fri, 8 Nov 2024 13:04:56 +0000 (14:04 +0100)
Let identity_domain_set_dev_pasid() call the pasid replace helpers hence
be able to do domain replacement.

Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Link: https://lore.kernel.org/r/20241107122234.7424-11-yi.l.liu@intel.com
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/intel/iommu.c

index 251cfeb..ba984cb 100644 (file)
@@ -1778,6 +1778,17 @@ static int domain_setup_second_level(struct intel_iommu *iommu,
                                                pasid);
 }
 
+static int domain_setup_passthrough(struct intel_iommu *iommu,
+                                   struct device *dev, ioasid_t pasid,
+                                   struct iommu_domain *old)
+{
+       if (!old)
+               return intel_pasid_setup_pass_through(iommu, dev, pasid);
+       return intel_pasid_replace_pass_through(iommu, dev,
+                                               iommu_domain_did(old, iommu),
+                                               pasid);
+}
+
 static int domain_setup_first_level(struct intel_iommu *iommu,
                                    struct dmar_domain *domain,
                                    struct device *dev,
@@ -4423,11 +4434,17 @@ static int identity_domain_set_dev_pasid(struct iommu_domain *domain,
 {
        struct device_domain_info *info = dev_iommu_priv_get(dev);
        struct intel_iommu *iommu = info->iommu;
+       int ret;
 
        if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev))
                return -EOPNOTSUPP;
 
-       return intel_pasid_setup_pass_through(iommu, dev, pasid);
+       ret = domain_setup_passthrough(iommu, dev, pasid, old);
+       if (ret)
+               return ret;
+
+       domain_remove_dev_pasid(old, dev, pasid);
+       return 0;
 }
 
 static struct iommu_domain identity_domain = {