linux/arch/arc/mm/dma.c
/*
 * ARCH specific callbacks for generic noncoherent DMA ops (dma/noncoherent.c)
 *  - hardware IOC not available (or "dma-coherent" not set for device in DT)
 *  - But still handle both coherent and non-coherent requests from caller
 *
 * For DMA coherent hardware (IOC) generic code suffices
 */
ARCH specific callbacks for generic noncoherent DMA ops (dma/noncoherent.c)
- hardware IOC not available (or "dma-coherent" not set for device in DT)
- But still handle both coherent and non-coherent requests from caller

For DMA coherent hardware (IOC) generic code suffices
ARCH specific callbacks for generic noncoherent DMA ops ( dma / noncoherent . c ) - hardware IOC not available ( or " dma - coherent " not set for device in DT ) - But still handle both coherent and non - coherent requests from caller For DMA coherent hardware ( IOC ) generic code suffices
void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
		gfp_t gfp, unsigned long attrs)
{
	unsigned long order = get_order(size);
	struct page *page;
	phys_addr_t paddr;
	void *kvaddr;
	bool need_coh = !(attrs & DMA_ATTR_NON_CONSISTENT);
	BUG_ON(gfp & __GFP_HIGHMEM);
	page = alloc_pages(gfp, order);
	if (!page)
		return NULL;
	paddr = page_to_phys(page);
	*dma_handle = paddr;
	if (need_coh) {
		kvaddr = ioremap_nocache(paddr, size);
		if (kvaddr == NULL) {
			__free_pages(page, order);
			return NULL;
		}
	} else {
		kvaddr = (void *)(u32)paddr;
	}
	if (need_coh)
		dma_cache_wback_inv(paddr, size);
	return kvaddr;
}
void * arch_dma_alloc ( struct device * dev , size_t size , dma_addr_t * dma_handle , gfp_t gfp , unsigned long attrs ) { unsigned long order = get_order ( size ) ; struct page * page ; phys_addr_t paddr ; void * kvaddr ; bool need_coh = ! ( attrs & DMA_ATTR_NON_CONSISTENT ) ; BUG_ON ( gfp & __GFP_HIGHMEM ) ; page = alloc_pages ( gfp , order ) ; if ( ! page ) return NULL ; paddr = page_to_phys ( page ) ; * dma_handle = paddr ; if ( need_coh ) { kvaddr = ioremap_nocache ( paddr , size ) ; if ( kvaddr == NULL ) { __free_pages ( page , order ) ; return NULL ; } } else { kvaddr = ( void * ) ( u32 ) paddr ; } if ( need_coh ) dma_cache_wback_inv ( paddr , size ) ; return kvaddr ; }
ARCH specific callbacks for generic noncoherent DMA ops (dma/noncoherent.c)
  - hardware IOC not available (or "dma-coherent" not set for device in DT)
  - But still handle both coherent and non-coherent requests from caller
ARCH specific callbacks for generic noncoherent DMA ops ( dma / noncoherent . c ) - hardware IOC not available ( or " dma - coherent " not set for device in DT ) - But still handle both coherent and non - coherent requests from caller
/*
	 * __GFP_HIGHMEM flag is cleared by upper layer functions
	 * (in include/linux/dma-mapping.h) so we should never get a
	 * __GFP_HIGHMEM here.
	 */ /* This is linear addr (0x8000_0000 based) */ /*
	 * A coherent buffer needs MMU mapping to enforce non-cachability.
	 * kvaddr is kernel Virtual address (0x7000_0000 based).
	 */ /*
	 * Evict any existing L1 and/or L2 lines for the backing page
	 * in case it was used earlier as a normal "cached" page.
	 * Yeah this bit us - STAR 9000898266
	 *
	 * Although core does call flush_cache_vmap(), it gets kvaddr hence
	 * can't be used to efficiently flush L1 and/or L2 which need paddr
	 * Currently flush_cache_vmap nukes the L1 cache completely which
	 * will be optimized as a separate commit
	 */