Problems from dma

  

Dma transfer data is often used in the project driver process, and the memory required by dma has its own characteristics. It is generally considered that the physical address needs to be continuous, and the memory is not cacheable, and one is provided in the Linux kernel. The dma_alloc_coheren.md. *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp){void *ret;if (!dev | |  *dev->dma_mask >= 0xffffffffUL)gfp &= ~GFP_DMA;ret = (void *)__get_free_pages(gfp, get_order(size)); //(1)if (ret) {memset(ret, 0, Size);*dma_handle = virt_to_bus(ret); //(2)}return ret;}(1) Convert size to order, ie 2^order(2) Convert virtual address ret to bus address This function is a platform Related functions, the above is the implementation details of the x86 platform, from here we can see that the return value of this function is the linear address of the linux kernel, so it is convenient for the implementation of the mmap function of the driver development process. But this is not the case with the powerpc platform. I have encountered problems when porting the pci driver from the x86 platform to the powerpc platform. First let's take a look at the processing of DMA memory on both platforms. X86: The linux memory area is divided into DMA area, normal memory area and high-end memory area. The high-end memory area is used when the physical memory is higher than 768M. The general DMA area is 16M. This space is pre-processed by OS
stay. The DMA area and the Normal area all use linear mapping, which is used by logical addresses, and the high-end memory uses kernel virtual addresses. The partition of the kernel space is: physical area - 8M isolation - vmalloc area - 8k isolation - -4M high-end mapping area - fixed mapping area - 128kpowerpc: This section uses freescale mpc5121 chip as an example, the kernel does not The Normal memory area uses only two types of space: ZONE_DMA and ZONE_HIMEM. ZONE_DMA stores low-end memory, ZONE_HIMEN stores high-end memory, and the entire memory does not use the concept of logical addresses. So logical address based operations are not portable. Let's look at the specific difference: void * __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp){//Application of physical space page page = alloc_pages(gfp, order);//Clear the physical space cache{ unsigned long Kaddr = (unsigned long)page_address(page); memset(page_address(page), 0, size);flush_dcache_range(kaddr, kaddr + size);}//Request virtual space c = vm_region_alloc(&consistent_head, size, gfp & ;~(__GFP_DMA |  __GFP_HIGHMEM)); //achieve virtual address and physical address mapping if (c) {unsigned long vaddr = c-> vm_start; pte_t * pte = consistent_pte + CONSISTENT_OFFSET (vaddr); struct page *end = page + (1 < < order);split_page(page, order);/** Set the "dma handle"*/*handle = page_to_bus(page);do {BUG_ON(!pte_none(*pte));SetPageReserved(page);set_pte_at (&init_mm, vaddr,pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));page++;pte++;vaddr += PAGE_SIZE;} while (size -= PAGE_SIZE);//The return value is the kernel virtual address. Return (void *)c->vm_start

Copyright © Windows knowledge All Rights Reserved