Open ikwzm opened 1 year ago
Does this issue only happen on Arm64 when the CMA region is over 256MB?
Does this issue only happen on Arm64 when the CMA region is over 256MB?
The cause is currently under investigation, but I guess it's some kind of Linux Kernel limitation.
The Linux Kernel issued a warning at __alloc_pages_nodemask() in mm/page_alloc.c.
struct page *
__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid,
nodemask_t *nodemask)
{
struct page *page;
unsigned int alloc_flags = ALLOC_WMARK_LOW;
gfp_t alloc_mask; /* The gfp_t that was actually used for allocation */
struct alloc_context ac = { };
/*
* There are several places where we assume that the order value is sane
* so bail out early if the request is out of bound.
*/
if (unlikely(order >= MAX_ORDER)) {
WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN));
return NULL;
}
And alloc_pages_nodemask() is called by page_alloc_node() in dma_direct_alloc_pages() in kernel/dma/direct.c.
struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
size_t alloc_size = PAGE_ALIGN(size);
int node = dev_to_node(dev);
struct page *page = NULL;
u64 phys_mask;
if (attrs & DMA_ATTR_NO_WARN)
gfp |= __GFP_NOWARN;
/* we always manually zero the memory once we are done: */
gfp &= ~__GFP_ZERO;
gfp |= __dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
&phys_mask);
page = dma_alloc_contiguous(dev, alloc_size, gfp);
if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
dma_free_contiguous(dev, page, alloc_size);
page = NULL;
}
again:
if (!page)
page = alloc_pages_node(node, gfp, get_order(alloc_size));
if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
dma_free_contiguous(dev, page, size);
page = NULL;
if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
phys_mask < DMA_BIT_MASK(64) &&
!(gfp & (GFP_DMA32 | GFP_DMA))) {
gfp |= GFP_DMA32;
goto again;
}
if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) {
gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
goto again;
}
}
return page;
}
And MAX_ORDER is defined in include/linux/mmzone.h.
/* Free memory management - zoned buddy allocator. */
#ifndef CONFIG_FORCE_MAX_ZONEORDER
#define MAX_ORDER 11
#else
#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
#endif
#define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))
After allocating a buffer, trying to allocate a page area for mapping seems to have exceeded some limit of the linux kernel.
This limit seems to vary by Linux kernel version and architecture. Since u-dma-buf operates within the framework of the linux kernel, it accepts the limitations of the linux kernel as they are. Therefore, I cannot solve this problem because it is necessary to change the framework of the linux kernel to solve this. Also, it is not possible to predict what this limit will be in the future.
At the moment, I would like to only alert you that there are some limitations on the amount of buffer space that u-dma-buf can allocate.
Related issues: #60, #97 Board: Xilinx ZCU102 Chip: ZynqMP Arch: arm64 OS: Petalinux 2020.2 (Linux 5.4.0-xilinx-v2020.2 )
Device Tree:
The error information: