Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a73c1566 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

iommu/amd: Initialize new aperture range before making it visible



Make sure the aperture range is fully initialized before it
is visible to the address allocator.

Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 7bfa5bd2
Loading
Loading
Loading
Loading
+20 −13
Original line number Diff line number Diff line
@@ -1425,8 +1425,10 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom,
			   bool populate, gfp_t gfp)
{
	int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT;
	struct amd_iommu *iommu;
	unsigned long i, old_size, pte_pgsize;
	struct aperture_range *range;
	struct amd_iommu *iommu;
	unsigned long flags;

#ifdef CONFIG_IOMMU_STRESS
	populate = false;
@@ -1435,17 +1437,17 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom,
	if (index >= APERTURE_MAX_RANGES)
		return -ENOMEM;

	dma_dom->aperture[index] = kzalloc(sizeof(struct aperture_range), gfp);
	if (!dma_dom->aperture[index])
	range = kzalloc(sizeof(struct aperture_range), gfp);
	if (!range)
		return -ENOMEM;

	dma_dom->aperture[index]->bitmap = (void *)get_zeroed_page(gfp);
	if (!dma_dom->aperture[index]->bitmap)
	range->bitmap = (void *)get_zeroed_page(gfp);
	if (!range->bitmap)
		goto out_free;

	dma_dom->aperture[index]->offset = dma_dom->aperture_size;
	range->offset = dma_dom->aperture_size;

	spin_lock_init(&dma_dom->aperture[index]->bitmap_lock);
	spin_lock_init(&range->bitmap_lock);

	if (populate) {
		unsigned long address = dma_dom->aperture_size;
@@ -1458,13 +1460,17 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom,
			if (!pte)
				goto out_free;

			dma_dom->aperture[index]->pte_pages[i] = pte_page;
			range->pte_pages[i] = pte_page;

			address += APERTURE_RANGE_SIZE / 64;
		}
	}

	/* First take the bitmap_lock and then publish the range */
	spin_lock_irqsave(&range->bitmap_lock, flags);

	old_size                 = dma_dom->aperture_size;
	dma_dom->aperture[index] = range;
	dma_dom->aperture_size  += APERTURE_RANGE_SIZE;

	/* Reserve address range used for MSI messages */
@@ -1512,15 +1518,16 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom,

	update_domain(&dma_dom->domain);

	spin_unlock_irqrestore(&range->bitmap_lock, flags);

	return 0;

out_free:
	update_domain(&dma_dom->domain);

	free_page((unsigned long)dma_dom->aperture[index]->bitmap);
	free_page((unsigned long)range->bitmap);

	kfree(dma_dom->aperture[index]);
	dma_dom->aperture[index] = NULL;
	kfree(range);

	return -ENOMEM;
}