Allow me to trim the message a bit. On Thu, Jul 25, 2019 at 11:27:45AM +0200, Dafna Hirschfeld wrote: > > > [ 70.219867] cma: cma_alloc(cma (____ptrval____), count 4050, > > > align 8) > > > [ 70.237878] cma: cma_alloc: alloc failed, req-size: 4050 pages, > > > ret: -12 It shows that cma_alloc() failed so the dma_alloc_contigudous() does fallback alloc_pages_node(). It should be same as previous __dma_direct_alloc_pages(), but would you like to confirm after partially reverting the change at kernel/dma/direct.c file? It is not necessary for debugging to entirely revert the commit as build break might happen since the helper functions are called by other files too. Something like this: diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index b67f0aa08aa3..6688e1cee7d1 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -96,6 +96,8 @@ static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size) struct page *__dma_direct_alloc_pages(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs) { + unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; + int page_order = get_order(size); struct page *page = NULL; u64 phys_mask; @@ -107,9 +109,20 @@ struct page *__dma_direct_alloc_pages(struct device *dev, size_t size, gfp |= __dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask, &phys_mask); again: - page = dma_alloc_contiguous(dev, size, gfp); + /* CMA can be used only in the context which permits sleeping */ + if (gfpflags_allow_blocking(gfp)) { + page = dma_alloc_from_contiguous(dev, count, page_order, + gfp & __GFP_NOWARN); + if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) { + dma_release_from_contiguous(dev, page, count); + page = NULL; + } + } + if (!page) + page = alloc_pages_node(dev_to_node(dev), gfp, page_order); + if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) { - dma_free_contiguous(dev, page, size); + __free_pages(page, page_order); page = NULL; if (IS_ENABLED(CONFIG_ZONE_DMA32) && @@ -141,7 +154,7 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size, if (PageHighMem(page)) { /* * Depending on the cma= arguments and per-arch setup - * dma_alloc_contiguous could return highmem pages. + * dma_alloc_from_contiguous could return highmem pages. * Without remapping there is no way to return them here, * so log an error and fail. */ @@ -170,7 +183,10 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size, void __dma_direct_free_pages(struct device *dev, size_t size, struct page *page) { - dma_free_contiguous(dev, page, size); + unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; + + if (!dma_release_from_contiguous(dev, page, count)) + __free_pages(page, get_order(size)); } void dma_direct_free_pages(struct device *dev, size_t size, void *cpu_addr, > > > [ 70.244599] cma: number of available pages: 72@184+3886@4306=> > > > 3958 free of 8192 total pages > > > [ 70.253066] cma: cma_alloc(): returned (____ptrval____) > > > [ 70.264893] cma: cma_release(page (____ptrval____)) > > > [ 70.272871] cma: cma_release(page (____ptrval____)) > > > [ 70.277800] BUG: Bad page state in process v4l2-ctl pfn:b5a00 > > > [ 70.283652] page:ffff7e0001d68000 refcount:13 mapcount:0 > > > mapping:0000000000000000 index:0x0 compound_mapcount: 0 > > > [ 70.293874] flags: 0xffff00000010000(head) > > > [ 70.297999] raw: 0ffff00000010000 dead000000000100 > > > dead000000000122 0000000000000000 > > > [ 70.305772] raw: 0000000000000000 0000000000000000 > > > 0000000dffffffff 0000000000000000 > > > [ 70.313526] page dumped because: nonzero _refcount > > > [ 70.318327] Modules linked in: > > > [ 70.321399] CPU: 2 PID: 482 Comm: v4l2-ctl Not tainted 5.3.0- > > > rc1+ #159 > > > [ 70.327927] Hardware name: Boundary Devices i.MX8MQ Nitrogen8M > > > (DT) > > > [ 70.334196] Call trace: > > > [ 70.336654] dump_backtrace+0x0/0x148 > > > [ 70.340319] show_stack+0x14/0x20 > > > [ 70.343640] dump_stack+0x9c/0xc4 > > > [ 70.346959] bad_page+0xe4/0x148 > > > [ 70.350188] free_pages_check_bad+0x70/0xa8 > > > [ 70.354375] __free_pages_ok+0x294/0x2b0 > > > [ 70.358301] __free_pages+0x38/0x50 > > > [ 70.361795] dma_free_contiguous+0x90/0x98 > > > [ 70.365892] __dma_direct_free_pages+0x18/0x20 Here shows cma_release() has failed as those pages aren't from CMA, so it uses the fallback __free_pages(). I just scrutinized my commit once again and found that the free routine has missed a PAGE_ALIGN() operation for the size parameter. Though it does not likely cause the problem, yet would you please try this? diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c index bfc0c17f2a3d..a2d872a82be9 100644 --- a/kernel/dma/contiguous.c +++ b/kernel/dma/contiguous.c @@ -266,7 +266,8 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp) */ void dma_free_contiguous(struct device *dev, struct page *page, size_t size) { - if (!cma_release(dev_get_cma_area(dev), page, size >> PAGE_SHIFT)) + if (!cma_release(dev_get_cma_area(dev), page, + PAGE_ALIGN(size) >> PAGE_SHIFT)) __free_pages(page, get_order(size)); }