On Tue, Nov 10, 2026 at 1:48 AM Marek Szyprowski
<[email protected]> wrote:
>
> arch_dma_prep_coherent() performs the cache maintenance on the address
> returned by page_address(). xtensa with CONFIG_HIGHMEM uses
> HASHED_PAGE_VIRTUAL, so page_address() returns NULL for a highmem page
> that is not kmapped, and the cache operation then works on the virtual
> range starting at 0 instead of the buffer, leaving any dirty cache lines
> of the buffer in place.
>
> Highmem pages do reach this function: dma_alloc_contiguous() can return
> a highmem CMA page, which dma_direct_alloc() handles by forcing the remap
> path and calling arch_dma_prep_coherent() on that page before creating
> the uncached mapping.
>
> Fix this by reusing do_cache_op(), which the arch_sync_dma_for_*() hooks
> already use and which maps highmem pages one page at a time with
> kmap_atomic(). For lowmem pages it does a single cache operation over
> the whole range, so the behaviour is unchanged there. A small wrapper
> is needed because __flush_invalidate_dcache_range() is a macro on cores
> with a write-through data cache.
>
> Fixes: 0f665b9e2a6d ("xtensa: use the generic uncached segment support")
> Signed-off-by: Marek Szyprowski <[email protected]>
> ---
>  arch/xtensa/kernel/pci-dma.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)

Reviewed-by: Max Filippov <[email protected]>

-- 
Thanks.
-- Max

Reply via email to