Re: [PATCH v2 2/2] alpha: enable contiguous memory allocation for coherent DMA
From: Matt Turner
Date: Sat Nov 14 2026 - 12:16:53 EST
On Sat, Nov 14, 2026 at 4:53 AM Magnus Lindholm <linmag7@xxxxxxxxx> wrote:
> @@ -408,12 +408,17 @@ static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
> {
> struct pci_dev *pdev = alpha_gendev_to_pci(dev);
> void *cpu_addr;
> - long order = get_order(size);
> + struct page *page;
>
> gfp &= ~GFP_DMA;
>
> try_again:
> - cpu_addr = (void *)__get_free_pages(gfp | __GFP_ZERO, order);
> + /* A low-memory retry must not return the same unsuitable CMA pages. */
> + page = (gfp & GFP_DMA) ? NULL : dma_alloc_contiguous(dev, size, gfp);
size here comes straight from the driver's dma_alloc_coherent() call
and isn't necessarily a multiple of PAGE_SIZE. dma_alloc_contiguous()
assumes it is: cma_alloc_aligned() passes size >> PAGE_SHIFT to
cma_alloc(), but dma_free_contiguous() releases
PAGE_ALIGN(size) >> PAGE_SHIFT pages.
So a 12K allocation gets a single 8K page from CMA, the memset() below
runs 4K off the end of it, and the free later releases two pages, one
of which we never owned. dma_direct_alloc() does size = PAGE_ALIGN(size)
before it gets this far. I think we need the same at the top of both
alpha_pci_alloc_coherent() and alpha_pci_free_coherent().
The 8K, 24K and 32M cases in your test are all page multiples, so they
wouldn't have caught this. Something like 12K or 20K would.
> + if (page)
> + cpu_addr = page_address(page);
> + else
> + cpu_addr = alloc_pages_exact(size, gfp | __GFP_ZERO);
> if (! cpu_addr) {
> printk(KERN_INFO "pci_alloc_consistent: "
> "get_free_pages failed from %ps\n",
Minor, but this message isn't accurate anymore. Maybe just say
"allocation failed".
Rest of it looks good to me. Skipping CMA on the GFP_DMA retry is the
right call.