Phenomenon:
Some internal or external DMA controller has address limitation, for example, which could only access lower 128MB physical memory. While not all driver will alloc proper physical memory to meet this limitation. How could Linux kernel do then?
Common Knowledge:
DMA
Dmabounce
zone
Analyse and Research:
Kernel split physical memory into three parts:
ZONE_DMA
ZONE_NORMAL
ZONE_HIGHMEM.
If platform not define function arch_adjust_zones in arch/arm/mach-* /include/mach/memory.h, which means use default doing nothing. And zone_size[0] ZONE_DMA will full of whole physical memory (What about ZONE_HIGHMEM? ), memory allocate with ZONE_NORMAL will also located here because of no ZONE_NORMAL defined yet. In this condition, DMA physical memory will not be clarify for random allocated by kernel.
Then how could DMA controller limitation mentioned above? Dmabounce does.
Special dma_{map/unmap/dma_sync}_* routines for systems that have limited DMA windows. These functions utilize bounce buffers to copy data to/from buffers located outside the DMA region. This only works for systems in which DMA memory is at the bottom of RAM, the remainder of memory is at the top and the DMA memory can be marked as ZONE_DMA. Anything beyond that such as discontiguous DMA windows will require custom implementations that reserve memory areas at early bootup.
Dma_mask defined in each driver’s platform_device structure: coherent_dma_mask and dma_mask, value defined in arch/arm/include/asm/sizes.h. In each driver’s probe function, dmabounce_register_dev() be called to initialize a dmabounce_info. When dma_map_single/sg map the kmalloc memory, map_single will judge if dma_mask is defined without 0xffffffff, dmabounce_info be defined and dma_needs_bounce() by checking dma_addr in limitation range. If true, kernel will allocate a safe buffer which physical address involved in limitation range, and virtual address within DMA virtual kernel memory layout 0xffc00000. For transfer data to device, kernel will copy existed data to safe buffer.
Defect
Duplicated memory allocation take place and CPU has more mips to perform copy between safe buffer and unsafe buffer.
ZONE_DMA has no needs to expand too large, for normal memory allocation will switch to ZONE_DMA if ZONE_NORMAL has no or little enough space, which makes CPU more load to do switch.