Skip to content

Commit 2380f1e

Browse files
jgunthorpejoergroedel
authored andcommitted
iommu: Fix false ownership failure on AMD systems with PASID activated
The AMD IOMMU driver cannot activate PASID mode on a RID without the RID's translation being set to IDENTITY. Further it requires changing the RID's page table layout from the normal v1 IOMMU_DOMAIN_IDENTITY layout to a different v2 layout. It does this by creating a new iommu_domain, configuring that domain for v2 identity operation and then attaching it to the group, from within the driver. This logic assumes the group is already set to the IDENTITY domain and is being used by the DMA API. However, since the ownership logic is based on the group's domain pointer equaling the default domain to detect DMA API ownership, this causes it to look like the group is not attached to the DMA API any more. This blocks attaching drivers to any other devices in the group. In a real system this manifests itself as the HD-audio devices on some AMD platforms losing their device drivers. Work around this unique behavior of the AMD driver by checking for equality of IDENTITY domains based on their type, not their pointer value. This allows the AMD driver to have two IDENTITY domains for internal purposes without breaking the check. Have the AMD driver properly declare that the special domain it created is actually an IDENTITY domain. Cc: Robin Murphy <[email protected]> Cc: [email protected] Fixes: 512881e ("bus: platform,amba,fsl-mc,PCI: Add device DMA ownership management") Reported-by: Takashi Iwai <[email protected]> Tested-by: Takashi Iwai <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Reviewed-by: Robin Murphy <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 9cd4f14 commit 2380f1e

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

drivers/iommu/amd/iommu_v2.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,8 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids)
777777
if (dev_state->domain == NULL)
778778
goto out_free_states;
779779

780+
/* See iommu_is_default_domain() */
781+
dev_state->domain->type = IOMMU_DOMAIN_IDENTITY;
780782
amd_iommu_domain_direct_map(dev_state->domain);
781783

782784
ret = amd_iommu_domain_enable_v2(dev_state->domain, pasids);

drivers/iommu/iommu.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3076,6 +3076,24 @@ static ssize_t iommu_group_store_type(struct iommu_group *group,
30763076
return ret;
30773077
}
30783078

3079+
static bool iommu_is_default_domain(struct iommu_group *group)
3080+
{
3081+
if (group->domain == group->default_domain)
3082+
return true;
3083+
3084+
/*
3085+
* If the default domain was set to identity and it is still an identity
3086+
* domain then we consider this a pass. This happens because of
3087+
* amd_iommu_init_device() replacing the default idenytity domain with an
3088+
* identity domain that has a different configuration for AMDGPU.
3089+
*/
3090+
if (group->default_domain &&
3091+
group->default_domain->type == IOMMU_DOMAIN_IDENTITY &&
3092+
group->domain && group->domain->type == IOMMU_DOMAIN_IDENTITY)
3093+
return true;
3094+
return false;
3095+
}
3096+
30793097
/**
30803098
* iommu_device_use_default_domain() - Device driver wants to handle device
30813099
* DMA through the kernel DMA API.
@@ -3094,8 +3112,7 @@ int iommu_device_use_default_domain(struct device *dev)
30943112

30953113
mutex_lock(&group->mutex);
30963114
if (group->owner_cnt) {
3097-
if (group->domain != group->default_domain ||
3098-
group->owner) {
3115+
if (group->owner || !iommu_is_default_domain(group)) {
30993116
ret = -EBUSY;
31003117
goto unlock_out;
31013118
}

0 commit comments

Comments
 (0)