Skip to content

Commit

Permalink
dma/direct: turn ARCH_ZONE_DMA_BITS into a variable
Browse files Browse the repository at this point in the history
commit 8b5369e upstream.

Some architectures, notably ARM, are interested in tweaking this
depending on their runtime DMA addressing limitations.

Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
  • Loading branch information
Nicolas Saenz Julienne authored and pelwell committed Mar 11, 2020
1 parent fabea2c commit 274b318
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 28 deletions.
2 changes: 0 additions & 2 deletions arch/arm64/include/asm/page.h
Expand Up @@ -38,6 +38,4 @@ extern int pfn_valid(unsigned long);

#include <asm-generic/getorder.h>

#define ARCH_ZONE_DMA_BITS 30

#endif
9 changes: 7 additions & 2 deletions arch/arm64/mm/init.c
Expand Up @@ -20,6 +20,7 @@
#include <linux/sort.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/dma-direct.h>
#include <linux/dma-mapping.h>
#include <linux/dma-contiguous.h>
#include <linux/efi.h>
Expand All @@ -41,6 +42,8 @@
#include <asm/tlb.h>
#include <asm/alternative.h>

#define ARM64_ZONE_DMA_BITS 30

/*
* We need to be able to catch inadvertent references to memstart_addr
* that occur (potentially in generic code) before arm64_memblock_init()
Expand Down Expand Up @@ -440,8 +443,10 @@ void __init arm64_memblock_init(void)

early_init_fdt_scan_reserved_mem();

if (IS_ENABLED(CONFIG_ZONE_DMA))
arm64_dma_phys_limit = max_zone_phys(ARCH_ZONE_DMA_BITS);
if (IS_ENABLED(CONFIG_ZONE_DMA)) {
zone_dma_bits = ARM64_ZONE_DMA_BITS;
arm64_dma_phys_limit = max_zone_phys(ARM64_ZONE_DMA_BITS);
}

if (IS_ENABLED(CONFIG_ZONE_DMA32))
arm64_dma32_phys_limit = max_zone_phys(32);
Expand Down
9 changes: 0 additions & 9 deletions arch/powerpc/include/asm/page.h
Expand Up @@ -334,13 +334,4 @@ struct vm_area_struct;
#endif /* __ASSEMBLY__ */
#include <asm/slice.h>

/*
* Allow 30-bit DMA for very limited Broadcom wifi chips on many powerbooks.
*/
#ifdef CONFIG_PPC32
#define ARCH_ZONE_DMA_BITS 30
#else
#define ARCH_ZONE_DMA_BITS 31
#endif

#endif /* _ASM_POWERPC_PAGE_H */
20 changes: 15 additions & 5 deletions arch/powerpc/mm/mem.c
Expand Up @@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/memremap.h>
#include <linux/dma-direct.h>

#include <asm/pgalloc.h>
#include <asm/prom.h>
Expand Down Expand Up @@ -223,10 +224,10 @@ static int __init mark_nonram_nosave(void)
* everything else. GFP_DMA32 page allocations automatically fall back to
* ZONE_DMA.
*
* By using 31-bit unconditionally, we can exploit ARCH_ZONE_DMA_BITS to
* inform the generic DMA mapping code. 32-bit only devices (if not handled
* by an IOMMU anyway) will take a first dip into ZONE_NORMAL and get
* otherwise served by ZONE_DMA.
* By using 31-bit unconditionally, we can exploit zone_dma_bits to inform the
* generic DMA mapping code. 32-bit only devices (if not handled by an IOMMU
* anyway) will take a first dip into ZONE_NORMAL and get otherwise served by
* ZONE_DMA.
*/
static unsigned long max_zone_pfns[MAX_NR_ZONES];

Expand Down Expand Up @@ -259,9 +260,18 @@ void __init paging_init(void)
printk(KERN_DEBUG "Memory hole size: %ldMB\n",
(long int)((top_of_ram - total_ram) >> 20));

/*
* Allow 30-bit DMA for very limited Broadcom wifi chips on many
* powerbooks.
*/
if (IS_ENABLED(CONFIG_PPC32))
zone_dma_bits = 30;
else
zone_dma_bits = 31;

#ifdef CONFIG_ZONE_DMA
max_zone_pfns[ZONE_DMA] = min(max_low_pfn,
1UL << (ARCH_ZONE_DMA_BITS - PAGE_SHIFT));
1UL << (zone_dma_bits - PAGE_SHIFT));
#endif
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
#ifdef CONFIG_HIGHMEM
Expand Down
2 changes: 0 additions & 2 deletions arch/s390/include/asm/page.h
Expand Up @@ -179,8 +179,6 @@ static inline int devmem_is_allowed(unsigned long pfn)
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)

#define ARCH_ZONE_DMA_BITS 31

#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>

Expand Down
1 change: 1 addition & 0 deletions arch/s390/mm/init.c
Expand Up @@ -118,6 +118,7 @@ void __init paging_init(void)

sparse_memory_present_with_active_regions(MAX_NUMNODES);
sparse_init();
zone_dma_bits = 31;
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
Expand Down
2 changes: 1 addition & 1 deletion include/linux/dma-direct.h
Expand Up @@ -6,7 +6,7 @@
#include <linux/memblock.h> /* for min_low_pfn */
#include <linux/mem_encrypt.h>

static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
extern unsigned int zone_dma_bits;

#ifdef CONFIG_ARCH_HAS_PHYS_TO_DMA
#include <asm/dma-direct.h>
Expand Down
13 changes: 6 additions & 7 deletions kernel/dma/direct.c
Expand Up @@ -16,12 +16,11 @@
#include <linux/swiotlb.h>

/*
* Most architectures use ZONE_DMA for the first 16 Megabytes, but
* some use it for entirely different regions:
* Most architectures use ZONE_DMA for the first 16 Megabytes, but some use it
* it for entirely different regions. In that case the arch code needs to
* override the variable below for dma-direct to work properly.
*/
#ifndef ARCH_ZONE_DMA_BITS
#define ARCH_ZONE_DMA_BITS 24
#endif
unsigned int zone_dma_bits __ro_after_init = 24;

static void report_addr(struct device *dev, dma_addr_t dma_addr, size_t size)
{
Expand Down Expand Up @@ -69,7 +68,7 @@ static gfp_t __dma_direct_optimal_gfp_mask(struct device *dev, u64 dma_mask,
* Note that GFP_DMA32 and GFP_DMA are no ops without the corresponding
* zones.
*/
if (*phys_mask <= DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
if (*phys_mask <= DMA_BIT_MASK(zone_dma_bits))
return GFP_DMA;
if (*phys_mask <= DMA_BIT_MASK(32))
return GFP_DMA32;
Expand Down Expand Up @@ -395,7 +394,7 @@ int dma_direct_supported(struct device *dev, u64 mask)
u64 min_mask;

if (IS_ENABLED(CONFIG_ZONE_DMA))
min_mask = DMA_BIT_MASK(ARCH_ZONE_DMA_BITS);
min_mask = DMA_BIT_MASK(zone_dma_bits);
else
min_mask = DMA_BIT_MASK(30);

Expand Down

0 comments on commit 274b318

Please sign in to comment.