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: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
Родитель
7bfa5bd270
Коммит
a73c156665
|
@ -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,14 +1460,18 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
old_size = dma_dom->aperture_size;
|
||||
dma_dom->aperture_size += APERTURE_RANGE_SIZE;
|
||||
/* 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 */
|
||||
if (old_size < MSI_ADDR_BASE_LO &&
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче