From bf96382fb9220359fdffc3fe485a5b535a094a2d Mon Sep 17 00:00:00 2001 From: Chris Goldsworthy Date: Thu, 24 Feb 2022 16:13:30 -0800 Subject: [PATCH] ANDROID: dma-direct: Make DMA32 disablement work for CONFIG_NUMA zone_dma32_is_empty() currently lacks the proper validation to ensure that the NUMA node ID it receives as an argument is valid. This has no effect on kernels with CONFIG_NUMA=n as NODE_DATA() will return the same pglist_data on these devices, but on kernels with CONFIG_NUMA=y, this is not the case, and the node passed to NODE_DATA must be validated. Rather than trying to find the node containing ZONE_DMA32, replace calls of zone_dma32_is_empty() with zone_dma32_are_empty() (which iterates over all nodes and returns false if one of the nodes holds DMA32 and it is non-empty). Bug: 199917449 Fixes: c3c2bb34ac8f ("ANDROID: arm64/mm: Add command line option to make ZONE_DMA32 empty") Signed-off-by: Chris Goldsworthy Change-Id: I850fb9213b71a1ef29106728bfda0cc6de46fdbb --- include/linux/dma-direct.h | 5 +++++ kernel/dma/direct.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h index ed69618cf1fc..80f0dbac77c4 100644 --- a/include/linux/dma-direct.h +++ b/include/linux/dma-direct.h @@ -37,11 +37,16 @@ static inline bool zone_dma32_is_empty(int node) static inline bool zone_dma32_are_empty(void) { +#ifdef CONFIG_NUMA int node; for_each_node(node) if (!zone_dma32_is_empty(node)) return false; +#else + if (!zone_dma32_is_empty(numa_node_id())) + return false; +#endif return true; } diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index 6f58cde1558b..8ca84610d4d4 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -62,7 +62,7 @@ static gfp_t dma_direct_optimal_gfp_mask(struct device *dev, u64 dma_mask, if (*phys_limit <= DMA_BIT_MASK(zone_dma_bits)) return GFP_DMA; if (*phys_limit <= DMA_BIT_MASK(32) && - !zone_dma32_is_empty(dev_to_node(dev))) + !zone_dma32_are_empty()) return GFP_DMA32; return 0; } @@ -103,7 +103,7 @@ again: if (IS_ENABLED(CONFIG_ZONE_DMA32) && phys_limit < DMA_BIT_MASK(64) && !(gfp & (GFP_DMA32 | GFP_DMA)) && - !zone_dma32_is_empty(node)) { + !zone_dma32_are_empty()) { gfp |= GFP_DMA32; goto again; }