]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iommu: Add iommu_driver_get_domain_for_dev() helper
authorNicolin Chen <nicolinc@nvidia.com>
Mon, 15 Dec 2025 21:42:18 +0000 (13:42 -0800)
committerJoerg Roedel <joerg.roedel@amd.com>
Sat, 10 Jan 2026 09:26:43 +0000 (10:26 +0100)
There is a need to stage a resetting PCI device to temporarily the blocked
domain and then attach back to its previously attached domain after reset.

This can be simply done by keeping the "previously attached domain" in the
iommu_group->domain pointer while adding an iommu_group->resetting_domain,
which gives troubles to IOMMU drivers using the iommu_get_domain_for_dev()
for a device's physical domain in order to program IOMMU hardware.

And in such for-driver use cases, the iommu_group->mutex must be held, so
it doesn't fit in external callers that don't hold the iommu_group->mutex.

Introduce a new iommu_driver_get_domain_for_dev() helper, exclusively for
driver use cases that hold the iommu_group->mutex, to separate from those
external use cases.

Add a lockdep_assert_not_held to the existing iommu_get_domain_for_dev()
and highlight that in a kdoc.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Tested-by: Dheeraj Kumar Srivastava <dheerajkumar.srivastava@amd.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
drivers/iommu/iommu.c
include/linux/iommu.h

index d16d35c78c06856bb080aa24bebd4c8a2e9939df..b8d2fef3ee6bd2587e9531aac53ff04028b1c8b5 100644 (file)
@@ -3125,7 +3125,8 @@ int arm_smmu_set_pasid(struct arm_smmu_master *master,
                       struct arm_smmu_domain *smmu_domain, ioasid_t pasid,
                       struct arm_smmu_cd *cd, struct iommu_domain *old)
 {
-       struct iommu_domain *sid_domain = iommu_get_domain_for_dev(master->dev);
+       struct iommu_domain *sid_domain =
+               iommu_driver_get_domain_for_dev(master->dev);
        struct arm_smmu_attach_state state = {
                .master = master,
                .ssid = pasid,
@@ -3191,7 +3192,7 @@ static int arm_smmu_blocking_set_dev_pasid(struct iommu_domain *new_domain,
         */
        if (!arm_smmu_ssids_in_use(&master->cd_table)) {
                struct iommu_domain *sid_domain =
-                       iommu_get_domain_for_dev(master->dev);
+                       iommu_driver_get_domain_for_dev(master->dev);
 
                if (sid_domain->type == IOMMU_DOMAIN_IDENTITY ||
                    sid_domain->type == IOMMU_DOMAIN_BLOCKED)
index 1e322f87b17107907145c224c0e1eb2885d3ed32..672597100e9a04df01a446e6c060173e8c8e8975 100644 (file)
@@ -2217,6 +2217,15 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(iommu_detach_device);
 
+/**
+ * iommu_get_domain_for_dev() - Return the DMA API domain pointer
+ * @dev: Device to query
+ *
+ * This function can be called within a driver bound to dev. The returned
+ * pointer is valid for the lifetime of the bound driver.
+ *
+ * It should not be called by drivers with driver_managed_dma = true.
+ */
 struct iommu_domain *iommu_get_domain_for_dev(struct device *dev)
 {
        /* Caller must be a probed driver on dev */
@@ -2225,10 +2234,29 @@ struct iommu_domain *iommu_get_domain_for_dev(struct device *dev)
        if (!group)
                return NULL;
 
+       lockdep_assert_not_held(&group->mutex);
+
        return group->domain;
 }
 EXPORT_SYMBOL_GPL(iommu_get_domain_for_dev);
 
+/**
+ * iommu_driver_get_domain_for_dev() - Return the driver-level domain pointer
+ * @dev: Device to query
+ *
+ * This function can be called by an iommu driver that wants to get the physical
+ * domain within an iommu callback function where group->mutex is held.
+ */
+struct iommu_domain *iommu_driver_get_domain_for_dev(struct device *dev)
+{
+       struct iommu_group *group = dev->iommu_group;
+
+       lockdep_assert_held(&group->mutex);
+
+       return group->domain;
+}
+EXPORT_SYMBOL_GPL(iommu_driver_get_domain_for_dev);
+
 /*
  * For IOMMU_DOMAIN_DMA implementations which already provide their own
  * guarantees that the group and its default domain are valid and correct.
index 8c66284a91a8b0486b7de2d811af78d9af19ffa4..ff097df318b940a21bbac9dc2ad4d05bce3ccb02 100644 (file)
@@ -910,6 +910,7 @@ extern int iommu_attach_device(struct iommu_domain *domain,
 extern void iommu_detach_device(struct iommu_domain *domain,
                                struct device *dev);
 extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev);
+struct iommu_domain *iommu_driver_get_domain_for_dev(struct device *dev);
 extern struct iommu_domain *iommu_get_dma_domain(struct device *dev);
 extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
                     phys_addr_t paddr, size_t size, int prot, gfp_t gfp);