cregit-Linux how code gets into the kernel

Release 4.8 arch/mips/mm/dma-default.c

Directory: arch/mips/mm
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
 * Copyright (C) 2000, 2001, 06  Ralf Baechle <ralf@linux-mips.org>
 * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
 */

#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/string.h>
#include <linux/gfp.h>
#include <linux/highmem.h>
#include <linux/dma-contiguous.h>

#include <asm/cache.h>
#include <asm/cpu-type.h>
#include <asm/io.h>

#include <dma-coherence.h>

#ifdef CONFIG_DMA_MAYBE_COHERENT

int coherentio = 0;	
/* User defined DMA coherency from command line. */

EXPORT_SYMBOL_GPL(coherentio);

int hw_coherentio = 0;	
/* Actual hardware supported DMA coherency setting. */


static int __init setcoherentio(char *str) { coherentio = 1; pr_info("Hardware DMA cache coherency (command line)\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
steven j. hillsteven j. hill23100.00%1100.00%
Total23100.00%1100.00%

early_param("coherentio", setcoherentio);
static int __init setnocoherentio(char *str) { coherentio = 0; pr_info("Software DMA cache coherency (command line)\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
steven j. hillsteven j. hill23100.00%1100.00%
Total23100.00%1100.00%

early_param("nocoherentio", setnocoherentio); #endif
static inline struct page *dma_addr_to_page(struct device *dev, dma_addr_t dma_addr) { return pfn_to_page( plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT); }

Contributors

PersonTokensPropCommitsCommitProp
franck bui-huufranck bui-huu1446.67%133.33%
dezhong diaodezhong diao930.00%133.33%
kevin cernekeekevin cernekee723.33%133.33%
Total30100.00%3100.00%

/* * The affected CPUs below in 'cpu_needs_post_dma_flush()' can * speculatively fill random cachelines with stale data at any time, * requiring an extra flush post-DMA. * * Warning on the terminology - Linux calls an uncached area coherent; * MIPS terminology calls memory areas with hardware maintained coherency * coherent. * * Note that the R14000 and R16000 should also be checked for in this * condition. However this function is only called on non-I/O-coherent * systems and only the R10000 and R12000 are used in such systems, the * SGI IP28 Indigo² rsp. SGI IP32 aka O2. */
static inline int cpu_needs_post_dma_flush(struct device *dev) { return !plat_device_is_coherent(dev) && (boot_cpu_type() == CPU_R10000 || boot_cpu_type() == CPU_R12000 || boot_cpu_type() == CPU_BMIPS5000); }

Contributors

PersonTokensPropCommitsCommitProp
ralf baechleralf baechle2877.78%350.00%
jim quinlanjim quinlan513.89%116.67%
jerin jacobjerin jacob25.56%116.67%
maxime bizonmaxime bizon12.78%116.67%
Total36100.00%6100.00%


static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) { gfp_t dma_flag; /* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); #ifdef CONFIG_ISA if (dev == NULL) dma_flag = __GFP_DMA; else #endif #if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA) if (dev == NULL || dev->coherent_dma_mask < DMA_BIT_MASK(32)) dma_flag = __GFP_DMA; else if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) dma_flag = __GFP_DMA32; else #endif #if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA) if (dev == NULL || dev->coherent_dma_mask < DMA_BIT_MASK(64)) dma_flag = __GFP_DMA32; else #endif #if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32) if (dev == NULL || dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8)) dma_flag = __GFP_DMA; else #endif dma_flag = 0; /* Don't invoke OOM killer */ gfp |= __GFP_NORETRY; return gfp | dma_flag; }

Contributors

PersonTokensPropCommitsCommitProp
ralf baechleralf baechle13473.63%228.57%
andrew mortonandrew morton2915.93%228.57%
matt redfearnmatt redfearn126.59%114.29%
james hoganjames hogan63.30%114.29%
al viroal viro10.55%114.29%
Total182100.00%7100.00%


static void *mips_dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t * dma_handle, gfp_t gfp) { void *ret; gfp = massage_gfp_flags(dev, gfp); ret = (void *) __get_free_pages(gfp, get_order(size)); if (ret != NULL) { memset(ret, 0, size); *dma_handle = plat_map_dma_mem(dev, ret, size); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton4554.22%125.00%
ralf baechleralf baechle3643.37%250.00%
christoph hellwigchristoph hellwig22.41%125.00%
Total83100.00%4100.00%


static void *mips_dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs) { void *ret; struct page *page = NULL; unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; /* * XXX: seems like the coherent and non-coherent implementations could * be consolidated. */ if (attrs & DMA_ATTR_NON_CONSISTENT) return mips_dma_alloc_noncoherent(dev, size, dma_handle, gfp); gfp = massage_gfp_flags(dev, gfp); if (IS_ENABLED(CONFIG_DMA_CMA) && gfpflags_allow_blocking(gfp)) page = dma_alloc_from_contiguous(dev, count, get_order(size)); if (!page) page = alloc_pages(gfp, get_order(size)); if (!page) return NULL; ret = page_address(page); memset(ret, 0, size); *dma_handle = plat_map_dma_mem(dev, ret, size); if (!plat_device_is_coherent(dev)) { dma_cache_wback_inv((unsigned long) ret, size); if (!hw_coherentio) ret = UNCAC_ADDR(ret); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
zubair lutfullahzubair lutfullah6131.94%19.09%
andrew mortonandrew morton5729.84%19.09%
ralf baechleralf baechle3920.42%218.18%
christoph hellwigchristoph hellwig178.90%19.09%
steven j. hillsteven j. hill52.62%19.09%
krzysztof kozlowskikrzysztof kozlowski42.09%19.09%
qais yousefqais yousef31.57%19.09%
andrzej pietrasiewiczandrzej pietrasiewicz21.05%19.09%
david daneydavid daney21.05%19.09%
al viroal viro10.52%19.09%
Total191100.00%11100.00%


static void mips_dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL); free_pages((unsigned long) vaddr, get_order(size)); }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton3371.74%120.00%
david daneydavid daney715.22%240.00%
kevin cernekeekevin cernekee48.70%120.00%
christoph hellwigchristoph hellwig24.35%120.00%
Total46100.00%5100.00%


static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle, unsigned long attrs) { unsigned long addr = (unsigned long) vaddr; unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; struct page *page = NULL; if (attrs & DMA_ATTR_NON_CONSISTENT) { mips_dma_free_noncoherent(dev, size, vaddr, dma_handle); return; } plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL); if (!plat_device_is_coherent(dev) && !hw_coherentio) addr = CAC_ADDR(addr); page = virt_to_page((void *) addr); if (!dma_release_from_contiguous(dev, page, count)) __free_pages(page, get_order(size)); }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton4533.33%19.09%
zubair lutfullahzubair lutfullah4231.11%19.09%
christoph hellwigchristoph hellwig1813.33%19.09%
david daneydavid daney96.67%327.27%
ralf baechleralf baechle85.93%19.09%
kevin cernekeekevin cernekee42.96%19.09%
krzysztof kozlowskikrzysztof kozlowski42.96%19.09%
steven j. hillsteven j. hill32.22%19.09%
andrzej pietrasiewiczandrzej pietrasiewicz21.48%19.09%
Total135100.00%11100.00%


static int mips_dma_mmap(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, dma_addr_t dma_addr, size_t size, unsigned long attrs) { unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; unsigned long addr = (unsigned long)cpu_addr; unsigned long off = vma->vm_pgoff; unsigned long pfn; int ret = -ENXIO; if (!plat_device_is_coherent(dev) && !hw_coherentio) addr = CAC_ADDR(addr); pfn = page_to_pfn(virt_to_page((void *)addr)); if (attrs & DMA_ATTR_WRITE_COMBINE) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); else vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret)) return ret; if (off < count && user_count <= (count - off)) { ret = remap_pfn_range(vma, vma->vm_start, pfn + off, user_count << PAGE_SHIFT, vma->vm_page_prot); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
alex smithalex smith20398.07%150.00%
krzysztof kozlowskikrzysztof kozlowski41.93%150.00%
Total207100.00%2100.00%


static inline void __dma_sync_virtual(void *addr, size_t size, enum dma_data_direction direction) { switch (direction) { case DMA_TO_DEVICE: dma_cache_wback((unsigned long)addr, size); break; case DMA_FROM_DEVICE: dma_cache_inv((unsigned long)addr, size); break; case DMA_BIDIRECTIONAL: dma_cache_wback_inv((unsigned long)addr, size); break; default: BUG(); } }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton5879.45%150.00%
dezhong diaodezhong diao1520.55%150.00%
Total73100.00%2100.00%

/* * A single sg entry may refer to multiple physically contiguous * pages. But we still need to process highmem pages individually. * If highmem is not configured then the bulk of this loop gets * optimized out. */
static inline void __dma_sync(struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction) { size_t left = size; do { size_t len = left; if (PageHighMem(page)) { void *addr; if (offset + len > PAGE_SIZE) { if (offset >= PAGE_SIZE) { page += offset >> PAGE_SHIFT; offset &= ~PAGE_MASK; } len = PAGE_SIZE - offset; } addr = kmap_atomic(page); __dma_sync_virtual(addr + offset, len, direction); kunmap_atomic(addr); } else __dma_sync_virtual(page_address(page) + offset, size, direction); offset = 0; page++; left -= len; } while (left); }

Contributors

PersonTokensPropCommitsCommitProp
dezhong diaodezhong diao138100.00%1100.00%
Total138100.00%1100.00%


static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction, unsigned long attrs) { if (cpu_needs_post_dma_flush(dev)) __dma_sync(dma_addr_to_page(dev, dma_addr), dma_addr & ~PAGE_MASK, size, direction); plat_post_dma_flush(dev); plat_unmap_dma_mem(dev, dma_addr, size, direction); }

Contributors

PersonTokensPropCommitsCommitProp
ralf baechleralf baechle2537.31%220.00%
andrew mortonandrew morton2131.34%110.00%
david daneydavid daney68.96%220.00%
dezhong diaodezhong diao68.96%110.00%
kevin cernekeekevin cernekee68.96%220.00%
krzysztof kozlowskikrzysztof kozlowski22.99%110.00%
jim quinlanjim quinlan11.49%110.00%
Total67100.00%10100.00%


static int mips_dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction, unsigned long attrs) { int i; struct scatterlist *sg; for_each_sg(sglist, sg, nents, i) { if (!plat_device_is_coherent(dev)) __dma_sync(sg_page(sg), sg->offset, sg->length, direction); #ifdef CONFIG_NEED_SG_DMA_LENGTH sg->dma_length = sg->length; #endif sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) + sg->offset; } return nents; }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton4844.86%112.50%
dezhong diaodezhong diao1614.95%112.50%
akinobu mitaakinobu mita1514.02%112.50%
jayachandran cjayachandran c1312.15%112.50%
ralf baechleralf baechle76.54%112.50%
david daneydavid daney43.74%112.50%
thomas bogendoerferthomas bogendoerfer21.87%112.50%
krzysztof kozlowskikrzysztof kozlowski21.87%112.50%
Total107100.00%8100.00%


static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction, unsigned long attrs) { if (!plat_device_is_coherent(dev)) __dma_sync(page, offset, size, direction); return plat_map_dma_mem_page(dev, page) + offset; }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton3456.67%116.67%
david daneydavid daney1220.00%116.67%
dezhong diaodezhong diao711.67%116.67%
atsushi nemotoatsushi nemoto35.00%116.67%
krzysztof kozlowskikrzysztof kozlowski23.33%116.67%
ralf baechleralf baechle23.33%116.67%
Total60100.00%6100.00%


static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, int nhwentries, enum dma_data_direction direction, unsigned long attrs) { int i; struct scatterlist *sg; for_each_sg(sglist, sg, nhwentries, i) { if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) __dma_sync(sg_page(sg), sg->offset, sg->length, direction); plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction); } }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton3436.96%111.11%
ralf baechleralf baechle2021.74%111.11%
akinobu mitaakinobu mita1516.30%111.11%
dezhong diaodezhong diao77.61%111.11%
kevin cernekeekevin cernekee66.52%111.11%
david daneydavid daney66.52%222.22%
krzysztof kozlowskikrzysztof kozlowski22.17%111.11%
thiemo seuferthiemo seufer22.17%111.11%
Total92100.00%9100.00%


static void mips_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { if (cpu_needs_post_dma_flush(dev)) __dma_sync(dma_addr_to_page(dev, dma_handle), dma_handle & ~PAGE_MASK, size, direction); plat_post_dma_flush(dev); }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton2548.08%225.00%
ralf baechleralf baechle1426.92%225.00%
dezhong diaodezhong diao815.38%112.50%
david daneydavid daney23.85%112.50%
kevin cernekeekevin cernekee23.85%112.50%
jim quinlanjim quinlan11.92%112.50%
Total52100.00%8100.00%


static void mips_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { if (!plat_device_is_coherent(dev)) __dma_sync(dma_addr_to_page(dev, dma_handle), dma_handle & ~PAGE_MASK, size, direction); }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton2552.08%116.67%
ralf baechleralf baechle918.75%116.67%
dezhong diaodezhong diao816.67%116.67%
david daneydavid daney24.17%116.67%
thomas bogendoerferthomas bogendoerfer24.17%116.67%
kevin cernekeekevin cernekee24.17%116.67%
Total48100.00%6100.00%


static void mips_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { int i; struct scatterlist *sg; if (cpu_needs_post_dma_flush(dev)) { for_each_sg(sglist, sg, nelems, i) { __dma_sync(sg_page(sg), sg->offset, sg->length, direction); } } plat_post_dma_flush(dev); }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton3344.00%112.50%
akinobu mitaakinobu mita2026.67%112.50%
jayachandran cjayachandran c79.33%112.50%
ralf baechleralf baechle68.00%225.00%
dezhong diaodezhong diao45.33%112.50%
jens axboejens axboe34.00%112.50%
david daneydavid daney22.67%112.50%
Total75100.00%8100.00%


static void mips_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { int i; struct scatterlist *sg; if (!plat_device_is_coherent(dev)) { for_each_sg(sglist, sg, nelems, i) { __dma_sync(sg_page(sg), sg->offset, sg->length, direction); } } }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton3346.48%114.29%
akinobu mitaakinobu mita2028.17%114.29%
jayachandran cjayachandran c811.27%114.29%
dezhong diaodezhong diao45.63%114.29%
jens axboejens axboe34.23%114.29%
david daneydavid daney22.82%114.29%
ralf baechleralf baechle11.41%114.29%
Total71100.00%7100.00%


int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton956.25%125.00%
fujita tomonorifujita tomonori531.25%125.00%
felix fietkaufelix fietkau16.25%125.00%
david daneydavid daney16.25%125.00%
Total16100.00%4100.00%


int mips_dma_supported(struct device *dev, u64 mask) { return plat_dma_supported(dev, mask); }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton1361.90%125.00%
david daneydavid daney628.57%250.00%
ralf baechleralf baechle29.52%125.00%
Total21100.00%4100.00%


void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); if (!plat_device_is_coherent(dev)) __dma_sync_virtual(vaddr, size, direction); }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton2555.56%116.67%
ralf baechleralf baechle1737.78%350.00%
thomas bogendoerferthomas bogendoerfer24.44%116.67%
dezhong diaodezhong diao12.22%116.67%
Total45100.00%6100.00%

EXPORT_SYMBOL(dma_cache_sync); static struct dma_map_ops mips_default_dma_map_ops = { .alloc = mips_dma_alloc_coherent, .free = mips_dma_free_coherent, .mmap = mips_dma_mmap, .map_page = mips_dma_map_page, .unmap_page = mips_dma_unmap_page, .map_sg = mips_dma_map_sg, .unmap_sg = mips_dma_unmap_sg, .sync_single_for_cpu = mips_dma_sync_single_for_cpu, .sync_single_for_device = mips_dma_sync_single_for_device, .sync_sg_for_cpu = mips_dma_sync_sg_for_cpu, .sync_sg_for_device = mips_dma_sync_sg_for_device, .mapping_error = mips_dma_mapping_error, .dma_supported = mips_dma_supported }; struct dma_map_ops *mips_dma_map_ops = &mips_default_dma_map_ops; EXPORT_SYMBOL(mips_dma_map_ops); #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
static int __init mips_dma_init(void) { dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
david daneydavid daney17100.00%1100.00%
Total17100.00%1100.00%

fs_initcall(mips_dma_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton58829.18%36.12%
ralf baechleralf baechle36618.16%1224.49%
dezhong diaodezhong diao22711.27%12.04%
alex smithalex smith20810.32%12.04%
david daneydavid daney1617.99%36.12%
zubair lutfullahzubair lutfullah1065.26%12.04%
steven j. hillsteven j. hill854.22%12.04%
akinobu mitaakinobu mita703.47%12.04%
christoph hellwigchristoph hellwig391.94%12.04%
kevin cernekeekevin cernekee311.54%24.08%
jayachandran cjayachandran c281.39%24.08%
krzysztof kozlowskikrzysztof kozlowski200.99%12.04%
franck bui-huufranck bui-huu140.69%12.04%
matt redfearnmatt redfearn120.60%12.04%
jens axboejens axboe80.40%24.08%
jim quinlanjim quinlan70.35%12.04%
felix fietkaufelix fietkau60.30%24.08%
james hoganjames hogan60.30%12.04%
andrzej pietrasiewiczandrzej pietrasiewicz60.30%12.04%
thomas bogendoerferthomas bogendoerfer60.30%36.12%
fujita tomonorifujita tomonori50.25%12.04%
atsushi nemotoatsushi nemoto30.15%12.04%
qais yousefqais yousef30.15%12.04%
tejun heotejun heo30.15%12.04%
al viroal viro20.10%12.04%
thiemo seuferthiemo seufer20.10%12.04%
jerin jacobjerin jacob20.10%12.04%
maxime bizonmaxime bizon10.05%12.04%
Total2015100.00%49100.00%
Directory: arch/mips/mm
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.