博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dma mapping
阅读量:2171 次
发布时间:2019-05-01

本文共 3108 字,大约阅读时间需要 10 分钟。

 

mips架构:

void *dma_alloc_coherent(struct device *dev, size_t size,

 dma_addr_t * dma_handle, gfp_t gfp)
{
 void *ret;

 if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))

  return ret;

 gfp = massage_gfp_flags(dev, gfp);

 ret = (void *) __get_free_pages(gfp, get_order(size));

 if (ret) {

  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);
   ret = UNCAC_ADDR(ret);
  }
 }

 return ret;

}

EXPORT_SYMBOL(dma_alloc_coherent);

参数dma_handle保存了获取到地址的物理地址,对mips架构而言,该函数的返回值(也就是返回的内核虚拟地址)位于unmapped & uncached的kseg1。

 

 在arm 平台上dma_alloc_coherent会得到禁止页表项中的 C (Cacheable) 域以及 B (Bufferable)域。

/*

 * Allocate DMA-coherent memory space and return both the kernel remapped
 * virtual and bus address for that space.
 */
void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
{
 void *memory;

 if (dma_alloc_from_coherent(dev, size, handle, &memory))

  return memory;

 return __dma_alloc(dev, size, handle, gfp,

      pgprot_dmacoherent(pgprot_kernel),
      __builtin_return_address(0));
}
EXPORT_SYMBOL(dma_alloc_coherent);

其中:

#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE

#define pgprot_dmacoherent(prot) \
 __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
#define __HAVE_PHYS_MEM_ACCESS_PROT
struct file;
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
         unsigned long size, pgprot_t vma_prot);
#else
#define pgprot_dmacoherent(prot) \
 __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
#endif

 

由此,再去理解 LDD3 上讲解的一致性 DMA 映射 与 流式 DMA 映射就比较容易了,一致性 DMA 映射调用的是上面的函数, 由于关闭了 cache/buffer, 性能自然比较低。 而流式则通过复杂的同步机制,没有付出性能的代价。

所以我们要尽量使用流式 DMA 来编程。

 

 

另外说明一下:

在linux-3.4\arch\mips\include\asm\Dma-mapping.h 中有:

#include <asm-generic/dma-mapping-common.h>

所以mips架构dma_map_single就位于dma-mapping-common.h中:

#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)

对arm架构而言,dma_map_single的实现在linux-3.4\arch\arm\include\asm\dma-mapping.h中:

static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,

  size_t size, enum dma_data_direction dir)
{
 unsigned long offset;
 struct page *page;
 dma_addr_t addr;

 BUG_ON(!virt_addr_valid(cpu_addr));

 BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
 BUG_ON(!valid_dma_direction(dir));

 page = virt_to_page(cpu_addr);

 offset = (unsigned long)cpu_addr & ~PAGE_MASK;
 addr = __dma_map_page(dev, page, offset, size, dir);
 debug_dma_map_page(dev, page, offset, size, dir, addr, true);

 return addr;

}

 

linux-3.4\documentation\DMA-API-HOWTO.txt解释是:

   If your architecture needs to support multiple types of IOMMUs, you can use include/linux/asm-generic/dma-mapping-common.h. It's a library to support the DMA API with multiple types of IOMMUs. Lots of architectures (x86, powerpc, sh, alpha, ia64, microblaze and sparc) use it. Choose one to see how it can be used. If you need to support multiple types of IOMMUs in a single system, the example of x86 or powerpc helps.

如果架构支持多种IOMMU,可以使用dma-mapping-common.h。

 

(2010-08-02 16:02)

DMA及cache一致性学习心得

linux之dma api -- 通用设备的动态dma映射

 

下面这篇文章是内核文档DMA-API-HOWTO.txt的翻译,可结合来看。

 DMA动态映射指南

 

转载地址:http://rpqzb.baihongyu.com/

你可能感兴趣的文章
深度学习的主要应用举例
查看>>
word2vec 模型思想和代码实现
查看>>
怎样做情感分析
查看>>
用深度神经网络处理NER命名实体识别问题
查看>>
用 RNN 训练语言模型生成文本
查看>>
RNN与机器翻译
查看>>
用 Recursive Neural Networks 得到分析树
查看>>
RNN的高级应用
查看>>
TensorFlow-7-TensorBoard Embedding可视化
查看>>
轻松看懂机器学习十大常用算法
查看>>
一个框架解决几乎所有机器学习问题
查看>>
特征工程怎么做
查看>>
机器学习算法应用中常用技巧-1
查看>>
机器学习算法应用中常用技巧-2
查看>>
通过一个kaggle实例学习解决机器学习问题
查看>>
决策树的python实现
查看>>
Sklearn 快速入门
查看>>
了解 Sklearn 的数据集
查看>>
用ARIMA模型做需求预测
查看>>
推荐系统
查看>>