Skip to content

Commit a75b2be

Browse files
nicolincjoergroedel
authored andcommitted
iommu: Add iommu_driver_get_domain_for_dev() helper
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>
1 parent 4a73abb commit a75b2be

3 files changed

Lines changed: 32 additions & 2 deletions

File tree

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3125,7 +3125,8 @@ int arm_smmu_set_pasid(struct arm_smmu_master *master,
31253125
struct arm_smmu_domain *smmu_domain, ioasid_t pasid,
31263126
struct arm_smmu_cd *cd, struct iommu_domain *old)
31273127
{
3128-
struct iommu_domain *sid_domain = iommu_get_domain_for_dev(master->dev);
3128+
struct iommu_domain *sid_domain =
3129+
iommu_driver_get_domain_for_dev(master->dev);
31293130
struct arm_smmu_attach_state state = {
31303131
.master = master,
31313132
.ssid = pasid,
@@ -3191,7 +3192,7 @@ static int arm_smmu_blocking_set_dev_pasid(struct iommu_domain *new_domain,
31913192
*/
31923193
if (!arm_smmu_ssids_in_use(&master->cd_table)) {
31933194
struct iommu_domain *sid_domain =
3194-
iommu_get_domain_for_dev(master->dev);
3195+
iommu_driver_get_domain_for_dev(master->dev);
31953196

31963197
if (sid_domain->type == IOMMU_DOMAIN_IDENTITY ||
31973198
sid_domain->type == IOMMU_DOMAIN_BLOCKED)

drivers/iommu/iommu.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,6 +2217,15 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
22172217
}
22182218
EXPORT_SYMBOL_GPL(iommu_detach_device);
22192219

2220+
/**
2221+
* iommu_get_domain_for_dev() - Return the DMA API domain pointer
2222+
* @dev: Device to query
2223+
*
2224+
* This function can be called within a driver bound to dev. The returned
2225+
* pointer is valid for the lifetime of the bound driver.
2226+
*
2227+
* It should not be called by drivers with driver_managed_dma = true.
2228+
*/
22202229
struct iommu_domain *iommu_get_domain_for_dev(struct device *dev)
22212230
{
22222231
/* Caller must be a probed driver on dev */
@@ -2225,10 +2234,29 @@ struct iommu_domain *iommu_get_domain_for_dev(struct device *dev)
22252234
if (!group)
22262235
return NULL;
22272236

2237+
lockdep_assert_not_held(&group->mutex);
2238+
22282239
return group->domain;
22292240
}
22302241
EXPORT_SYMBOL_GPL(iommu_get_domain_for_dev);
22312242

2243+
/**
2244+
* iommu_driver_get_domain_for_dev() - Return the driver-level domain pointer
2245+
* @dev: Device to query
2246+
*
2247+
* This function can be called by an iommu driver that wants to get the physical
2248+
* domain within an iommu callback function where group->mutex is held.
2249+
*/
2250+
struct iommu_domain *iommu_driver_get_domain_for_dev(struct device *dev)
2251+
{
2252+
struct iommu_group *group = dev->iommu_group;
2253+
2254+
lockdep_assert_held(&group->mutex);
2255+
2256+
return group->domain;
2257+
}
2258+
EXPORT_SYMBOL_GPL(iommu_driver_get_domain_for_dev);
2259+
22322260
/*
22332261
* For IOMMU_DOMAIN_DMA implementations which already provide their own
22342262
* guarantees that the group and its default domain are valid and correct.

include/linux/iommu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,7 @@ extern int iommu_attach_device(struct iommu_domain *domain,
910910
extern void iommu_detach_device(struct iommu_domain *domain,
911911
struct device *dev);
912912
extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev);
913+
struct iommu_domain *iommu_driver_get_domain_for_dev(struct device *dev);
913914
extern struct iommu_domain *iommu_get_dma_domain(struct device *dev);
914915
extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
915916
phys_addr_t paddr, size_t size, int prot, gfp_t gfp);

0 commit comments

Comments
 (0)