iommu/vt-d: Remove scalable mode context entry setup from attach_dev
authorLu Baolu <baolu.lu@linux.intel.com>
Tue, 5 Mar 2024 12:21:20 +0000 (20:21 +0800)
committerJoerg Roedel <jroedel@suse.de>
Wed, 6 Mar 2024 16:35:59 +0000 (17:35 +0100)
The scalable mode context entry is now setup in the probe_device path,
eliminating the need to configure it in the attach_dev path. Removes the
redundant code from the attach_dev path to avoid dead code.

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

index 659c49f98f7f0b2e49e323eedc3a2fbb2cf64000..e752258d42b066ea1b81d57f229db0bc9b0dc121 100644 (file)
@@ -1802,34 +1802,17 @@ static void domain_exit(struct dmar_domain *domain)
        kfree(domain);
 }
 
-/*
- * Get the PASID directory size for scalable mode context entry.
- * Value of X in the PDTS field of a scalable mode context entry
- * indicates PASID directory with 2^(X + 7) entries.
- */
-static unsigned long context_get_sm_pds(struct pasid_table *table)
-{
-       unsigned long pds, max_pde;
-
-       max_pde = table->max_pasid >> PASID_PDE_SHIFT;
-       pds = find_first_bit(&max_pde, MAX_NR_PASID_BITS);
-       if (pds < 7)
-               return 0;
-
-       return pds - 7;
-}
-
 static int domain_context_mapping_one(struct dmar_domain *domain,
                                      struct intel_iommu *iommu,
-                                     struct pasid_table *table,
                                      u8 bus, u8 devfn)
 {
        struct device_domain_info *info =
                        domain_lookup_dev_info(domain, iommu, bus, devfn);
        u16 did = domain_id_iommu(domain, iommu);
        int translation = CONTEXT_TT_MULTI_LEVEL;
+       struct dma_pte *pgd = domain->pgd;
        struct context_entry *context;
-       int ret;
+       int agaw, ret;
 
        if (hw_pass_through && domain_type_is_si(domain))
                translation = CONTEXT_TT_PASS_THROUGH;
@@ -1872,65 +1855,37 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
        }
 
        context_clear_entry(context);
+       context_set_domain_id(context, did);
 
-       if (sm_supported(iommu)) {
-               unsigned long pds;
-
-               /* Setup the PASID DIR pointer: */
-               pds = context_get_sm_pds(table);
-               context->lo = (u64)virt_to_phys(table->table) |
-                               context_pdts(pds);
-
-               /* Setup the RID_PASID field: */
-               context_set_sm_rid2pasid(context, IOMMU_NO_PASID);
-
+       if (translation != CONTEXT_TT_PASS_THROUGH) {
                /*
-                * Setup the Device-TLB enable bit and Page request
-                * Enable bit:
+                * Skip top levels of page tables for iommu which has
+                * less agaw than default. Unnecessary for PT mode.
                 */
-               if (info && info->ats_supported)
-                       context_set_sm_dte(context);
-               if (info && info->pri_supported)
-                       context_set_sm_pre(context);
-               if (info && info->pasid_supported)
-                       context_set_pasid(context);
-       } else {
-               struct dma_pte *pgd = domain->pgd;
-               int agaw;
-
-               context_set_domain_id(context, did);
-
-               if (translation != CONTEXT_TT_PASS_THROUGH) {
-                       /*
-                        * Skip top levels of page tables for iommu which has
-                        * less agaw than default. Unnecessary for PT mode.
-                        */
-                       for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
-                               ret = -ENOMEM;
-                               pgd = phys_to_virt(dma_pte_addr(pgd));
-                               if (!dma_pte_present(pgd))
-                                       goto out_unlock;
-                       }
-
-                       if (info && info->ats_supported)
-                               translation = CONTEXT_TT_DEV_IOTLB;
-                       else
-                               translation = CONTEXT_TT_MULTI_LEVEL;
-
-                       context_set_address_root(context, virt_to_phys(pgd));
-                       context_set_address_width(context, agaw);
-               } else {
-                       /*
-                        * In pass through mode, AW must be programmed to
-                        * indicate the largest AGAW value supported by
-                        * hardware. And ASR is ignored by hardware.
-                        */
-                       context_set_address_width(context, iommu->msagaw);
+               for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
+                       ret = -ENOMEM;
+                       pgd = phys_to_virt(dma_pte_addr(pgd));
+                       if (!dma_pte_present(pgd))
+                               goto out_unlock;
                }
 
-               context_set_translation_type(context, translation);
+               if (info && info->ats_supported)
+                       translation = CONTEXT_TT_DEV_IOTLB;
+               else
+                       translation = CONTEXT_TT_MULTI_LEVEL;
+
+               context_set_address_root(context, virt_to_phys(pgd));
+               context_set_address_width(context, agaw);
+       } else {
+               /*
+                * In pass through mode, AW must be programmed to
+                * indicate the largest AGAW value supported by
+                * hardware. And ASR is ignored by hardware.
+                */
+               context_set_address_width(context, iommu->msagaw);
        }
 
+       context_set_translation_type(context, translation);
        context_set_fault_enable(context);
        context_set_present(context);
        if (!ecap_coherent(iommu->ecap))
@@ -1960,43 +1915,29 @@ out_unlock:
        return ret;
 }
 
-struct domain_context_mapping_data {
-       struct dmar_domain *domain;
-       struct intel_iommu *iommu;
-       struct pasid_table *table;
-};
-
 static int domain_context_mapping_cb(struct pci_dev *pdev,
                                     u16 alias, void *opaque)
 {
-       struct domain_context_mapping_data *data = opaque;
+       struct device_domain_info *info = dev_iommu_priv_get(&pdev->dev);
+       struct intel_iommu *iommu = info->iommu;
+       struct dmar_domain *domain = opaque;
 
-       return domain_context_mapping_one(data->domain, data->iommu,
-                                         data->table, PCI_BUS_NUM(alias),
-                                         alias & 0xff);
+       return domain_context_mapping_one(domain, iommu,
+                                         PCI_BUS_NUM(alias), alias & 0xff);
 }
 
 static int
 domain_context_mapping(struct dmar_domain *domain, struct device *dev)
 {
        struct device_domain_info *info = dev_iommu_priv_get(dev);
-       struct domain_context_mapping_data data;
        struct intel_iommu *iommu = info->iommu;
        u8 bus = info->bus, devfn = info->devfn;
-       struct pasid_table *table;
-
-       table = intel_pasid_get_table(dev);
 
        if (!dev_is_pci(dev))
-               return domain_context_mapping_one(domain, iommu, table,
-                                                 bus, devfn);
-
-       data.domain = domain;
-       data.iommu = iommu;
-       data.table = table;
+               return domain_context_mapping_one(domain, iommu, bus, devfn);
 
        return pci_for_each_dma_alias(to_pci_dev(dev),
-                                     &domain_context_mapping_cb, &data);
+                                     domain_context_mapping_cb, domain);
 }
 
 /* Returns a number of VTD pages, but aligned to MM page size */
@@ -2353,28 +2294,19 @@ static int dmar_domain_attach_device(struct dmar_domain *domain,
        list_add(&info->link, &domain->devices);
        spin_unlock_irqrestore(&domain->lock, flags);
 
-       /* PASID table is mandatory for a PCI device in scalable mode. */
-       if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
-               /* Setup the PASID entry for requests without PASID: */
-               if (hw_pass_through && domain_type_is_si(domain))
-                       ret = intel_pasid_setup_pass_through(iommu,
-                                       dev, IOMMU_NO_PASID);
-               else if (domain->use_first_level)
-                       ret = domain_setup_first_level(iommu, domain, dev,
-                                       IOMMU_NO_PASID);
-               else
-                       ret = intel_pasid_setup_second_level(iommu, domain,
-                                       dev, IOMMU_NO_PASID);
-               if (ret) {
-                       dev_err(dev, "Setup RID2PASID failed\n");
-                       device_block_translation(dev);
-                       return ret;
-               }
-       }
+       if (dev_is_real_dma_subdevice(dev))
+               return 0;
+
+       if (!sm_supported(iommu))
+               ret = domain_context_mapping(domain, dev);
+       else if (hw_pass_through && domain_type_is_si(domain))
+               ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID);
+       else if (domain->use_first_level)
+               ret = domain_setup_first_level(iommu, domain, dev, IOMMU_NO_PASID);
+       else
+               ret = intel_pasid_setup_second_level(iommu, domain, dev, IOMMU_NO_PASID);
 
-       ret = domain_context_mapping(domain, dev);
        if (ret) {
-               dev_err(dev, "Domain context map failed\n");
                device_block_translation(dev);
                return ret;
        }