Skip to content

Commit fc2c8d0

Browse files
committed
Merge tag 'iommu-fixes-v5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull iommu fixes from Joerg Roedel: - Fix a sleeping-while-atomic issue in the AMD IOMMU code - Disable lazy IOTLB flush for untrusted devices in the Intel VT-d driver - Fix status code definitions for Intel VT-d - Fix IO Page Fault issue in Tegra IOMMU driver * tag 'iommu-fixes-v5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu/vt-d: Fix status code for Allocate/Free PASID command iommu: Don't use lazy flush for untrusted device iommu/tegra-smmu: Fix mc errors on tegra124-nyan iommu/amd: Fix sleeping in atomic in increase_address_space()
2 parents f09b04c + 444d66a commit fc2c8d0

File tree

4 files changed

+87
-14
lines changed

4 files changed

+87
-14
lines changed

drivers/iommu/amd/io_pgtable.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ static bool increase_address_space(struct protection_domain *domain,
182182
bool ret = true;
183183
u64 *pte;
184184

185+
pte = (void *)get_zeroed_page(gfp);
186+
if (!pte)
187+
return false;
188+
185189
spin_lock_irqsave(&domain->lock, flags);
186190

187191
if (address <= PM_LEVEL_SIZE(domain->iop.mode))
@@ -191,10 +195,6 @@ static bool increase_address_space(struct protection_domain *domain,
191195
if (WARN_ON_ONCE(domain->iop.mode == PAGE_MODE_6_LEVEL))
192196
goto out;
193197

194-
pte = (void *)get_zeroed_page(gfp);
195-
if (!pte)
196-
goto out;
197-
198198
*pte = PM_LEVEL_PDE(domain->iop.mode, iommu_virt_to_phys(domain->iop.root));
199199

200200
domain->iop.root = pte;
@@ -208,10 +208,12 @@ static bool increase_address_space(struct protection_domain *domain,
208208
*/
209209
amd_iommu_domain_set_pgtable(domain, pte, domain->iop.mode);
210210

211+
pte = NULL;
211212
ret = true;
212213

213214
out:
214215
spin_unlock_irqrestore(&domain->lock, flags);
216+
free_page((unsigned long)pte);
215217

216218
return ret;
217219
}

drivers/iommu/dma-iommu.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,11 @@ static void iommu_dma_flush_iotlb_all(struct iova_domain *iovad)
311311
domain->ops->flush_iotlb_all(domain);
312312
}
313313

314+
static bool dev_is_untrusted(struct device *dev)
315+
{
316+
return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
317+
}
318+
314319
/**
315320
* iommu_dma_init_domain - Initialise a DMA mapping domain
316321
* @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
@@ -365,8 +370,9 @@ static int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
365370

366371
init_iova_domain(iovad, 1UL << order, base_pfn);
367372

368-
if (!cookie->fq_domain && !iommu_domain_get_attr(domain,
369-
DOMAIN_ATTR_DMA_USE_FLUSH_QUEUE, &attr) && attr) {
373+
if (!cookie->fq_domain && (!dev || !dev_is_untrusted(dev)) &&
374+
!iommu_domain_get_attr(domain, DOMAIN_ATTR_DMA_USE_FLUSH_QUEUE, &attr) &&
375+
attr) {
370376
if (init_iova_flush_queue(iovad, iommu_dma_flush_iotlb_all,
371377
iommu_dma_entry_dtor))
372378
pr_warn("iova flush queue initialization failed\n");
@@ -508,11 +514,6 @@ static void __iommu_dma_unmap_swiotlb(struct device *dev, dma_addr_t dma_addr,
508514
iova_align(iovad, size), dir, attrs);
509515
}
510516

511-
static bool dev_is_untrusted(struct device *dev)
512-
{
513-
return dev_is_pci(dev) && to_pci_dev(dev)->untrusted;
514-
}
515-
516517
static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
517518
size_t size, int prot, u64 dma_mask)
518519
{

drivers/iommu/intel/pasid.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
#define VCMD_VRSP_IP 0x1
3131
#define VCMD_VRSP_SC(e) (((e) >> 1) & 0x3)
3232
#define VCMD_VRSP_SC_SUCCESS 0
33-
#define VCMD_VRSP_SC_NO_PASID_AVAIL 1
34-
#define VCMD_VRSP_SC_INVALID_PASID 1
33+
#define VCMD_VRSP_SC_NO_PASID_AVAIL 2
34+
#define VCMD_VRSP_SC_INVALID_PASID 2
3535
#define VCMD_VRSP_RESULT_PASID(e) (((e) >> 8) & 0xfffff)
3636
#define VCMD_CMD_OPERAND(e) ((e) << 8)
3737
/*

drivers/iommu/tegra-smmu.c

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,10 +798,70 @@ static phys_addr_t tegra_smmu_iova_to_phys(struct iommu_domain *domain,
798798
return SMMU_PFN_PHYS(pfn) + SMMU_OFFSET_IN_PAGE(iova);
799799
}
800800

801+
static struct tegra_smmu *tegra_smmu_find(struct device_node *np)
802+
{
803+
struct platform_device *pdev;
804+
struct tegra_mc *mc;
805+
806+
pdev = of_find_device_by_node(np);
807+
if (!pdev)
808+
return NULL;
809+
810+
mc = platform_get_drvdata(pdev);
811+
if (!mc)
812+
return NULL;
813+
814+
return mc->smmu;
815+
}
816+
817+
static int tegra_smmu_configure(struct tegra_smmu *smmu, struct device *dev,
818+
struct of_phandle_args *args)
819+
{
820+
const struct iommu_ops *ops = smmu->iommu.ops;
821+
int err;
822+
823+
err = iommu_fwspec_init(dev, &dev->of_node->fwnode, ops);
824+
if (err < 0) {
825+
dev_err(dev, "failed to initialize fwspec: %d\n", err);
826+
return err;
827+
}
828+
829+
err = ops->of_xlate(dev, args);
830+
if (err < 0) {
831+
dev_err(dev, "failed to parse SW group ID: %d\n", err);
832+
iommu_fwspec_free(dev);
833+
return err;
834+
}
835+
836+
return 0;
837+
}
838+
801839
static struct iommu_device *tegra_smmu_probe_device(struct device *dev)
802840
{
803-
struct tegra_smmu *smmu = dev_iommu_priv_get(dev);
841+
struct device_node *np = dev->of_node;
842+
struct tegra_smmu *smmu = NULL;
843+
struct of_phandle_args args;
844+
unsigned int index = 0;
845+
int err;
846+
847+
while (of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
848+
&args) == 0) {
849+
smmu = tegra_smmu_find(args.np);
850+
if (smmu) {
851+
err = tegra_smmu_configure(smmu, dev, &args);
852+
of_node_put(args.np);
804853

854+
if (err < 0)
855+
return ERR_PTR(err);
856+
857+
break;
858+
}
859+
860+
of_node_put(args.np);
861+
index++;
862+
}
863+
864+
smmu = dev_iommu_priv_get(dev);
805865
if (!smmu)
806866
return ERR_PTR(-ENODEV);
807867

@@ -1028,6 +1088,16 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev,
10281088
if (!smmu)
10291089
return ERR_PTR(-ENOMEM);
10301090

1091+
/*
1092+
* This is a bit of a hack. Ideally we'd want to simply return this
1093+
* value. However the IOMMU registration process will attempt to add
1094+
* all devices to the IOMMU when bus_set_iommu() is called. In order
1095+
* not to rely on global variables to track the IOMMU instance, we
1096+
* set it here so that it can be looked up from the .probe_device()
1097+
* callback via the IOMMU device's .drvdata field.
1098+
*/
1099+
mc->smmu = smmu;
1100+
10311101
size = BITS_TO_LONGS(soc->num_asids) * sizeof(long);
10321102

10331103
smmu->asids = devm_kzalloc(dev, size, GFP_KERNEL);

0 commit comments

Comments
 (0)