On Tue, May 22, 2018 at 12:50:09PM +0100, Robin Murphy wrote:
> We would generally expect pagetables to be read by the IOMMU more than
> written by the CPU, so in NUMA systems it makes sense to locate them
> close to the former and avoid cross-node pagetable walks if at all
> possible. As it turns out, we already have a handle on the IOMMU device
> for the sake of coherency management, so it's trivial to grab the
> appropriate NUMA node when allocating new pagetable pages.
>
> Note that we drop the semantics of alloc_pages_exact(), but that's fine
> since they have never been necessary: the only time we're allocating
> more than one page is for stage 2 top-level concatenation, but since
> that is based on the number of IPA bits, the size is always some exact
> power of two anyway.
>
> Acked-by: Will Deacon <[email protected]>
> Signed-off-by: Robin Murphy <[email protected]>
> ---
>
> v2: Retain equivalent highmem check
>
> drivers/iommu/io-pgtable-arm.c | 13 +++++++++----
> 1 file changed, 9 insertions(+), 4 deletions(-)
Thanks, Robin.
Joerg -- please you can pick this up for 4.18? I don't have any other SMMU
patches pending, so it doesn't seem worth putting together a pull request
just for this.
Cheers,
Will
> diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> index 39c2a056da21..5194755bba29 100644
> --- a/drivers/iommu/io-pgtable-arm.c
> +++ b/drivers/iommu/io-pgtable-arm.c
> @@ -231,12 +231,17 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t
> gfp,
> struct io_pgtable_cfg *cfg)
> {
> struct device *dev = cfg->iommu_dev;
> + int order = get_order(size);
> + struct page *p;
> dma_addr_t dma;
> - void *pages = alloc_pages_exact(size, gfp | __GFP_ZERO);
> + void *pages;
>
> - if (!pages)
> + VM_BUG_ON((gfp & __GFP_HIGHMEM));
> + p = alloc_pages_node(dev_to_node(dev), gfp | __GFP_ZERO, order);
> + if (!p)
> return NULL;
>
> + pages = page_address(p);
> if (!(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA)) {
> dma = dma_map_single(dev, pages, size, DMA_TO_DEVICE);
> if (dma_mapping_error(dev, dma))
> @@ -256,7 +261,7 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t
> gfp,
> dev_err(dev, "Cannot accommodate DMA translation for IOMMU page
> tables\n");
> dma_unmap_single(dev, dma, size, DMA_TO_DEVICE);
> out_free:
> - free_pages_exact(pages, size);
> + __free_pages(p, order);
> return NULL;
> }
>
> @@ -266,7 +271,7 @@ static void __arm_lpae_free_pages(void *pages, size_t
> size,
> if (!(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA))
> dma_unmap_single(cfg->iommu_dev, __arm_lpae_dma_addr(pages),
> size, DMA_TO_DEVICE);
> - free_pages_exact(pages, size);
> + free_pages((unsigned long)pages, get_order(size));
> }
>
> static void __arm_lpae_sync_pte(arm_lpae_iopte *ptep,
> --
> 2.17.0.dirty
>
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu