swiotlb和smmu区别在map page这个函数
来源:互联网 发布:js需要做保护层吗 编辑:程序博客网 时间:2024/06/05 15:33
swiotlb和smmu最大的区别在map page这个函数,前面分析过smmu的map page函数会自建页表也映射iova和pa之间的映射。我们下面看看swiotlb的的map page
static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
unsigned long attrs)
{
dma_addr_t dev_addr;
dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
if (!is_device_dma_coherent(dev))
__dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
return dev_addr;
}
由于我们用的是coherent,所以if (!is_device_dma_coherent(dev)) 这个条件不成来,直接调用swiotlb_map_page 将page 转换成hw用的dma address。
dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
unsigned long attrs)
{
phys_addr_t map, phys = page_to_phys(page) + offset;
dma_addr_t dev_addr = phys_to_dma(dev, phys);
BUG_ON(dir == DMA_NONE);
/*
* If the address happens to be in the device's DMA window,
* we can safely return the device addr and not worry about bounce
* buffering it.
*/
if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
return dev_addr;
trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
/* Oh well, have to allocate and map a bounce buffer. */
map = map_single(dev, phys, size, dir);
if (map == SWIOTLB_MAP_ERROR) {
swiotlb_full(dev, size, dir, 1);
return phys_to_dma(dev, io_tlb_overflow_buffer);
}
dev_addr = phys_to_dma(dev, map);
/* Ensure that the address returned is DMA'ble */
if (!dma_capable(dev, dev_addr, size)) {
swiotlb_tbl_unmap_single(dev, map, size, dir);
return phys_to_dma(dev, io_tlb_overflow_buffer);
}
return dev_addr;
}
在swiotlb_map_page 中如果要map的page 在dma 的capable之内的话,就直接返回page对应的物理地址
if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
return dev_addr;
dma_capable 就是看要映射的page 的address是否在mask 返回内,一般情况下kernel中dma_mask 一般是4G,也就是说map的page的address在4G范围内,采用swiotlb的方式得到的dma adress和 page对应的物理地址是一样的.
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
if (!dev->dma_mask)
return false;
return addr + size - 1 <= *dev->dma_mask;
}
如果超过4G就要用boundle buffer转一下.
static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
unsigned long attrs)
{
dma_addr_t dev_addr;
dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
if (!is_device_dma_coherent(dev))
__dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
return dev_addr;
}
由于我们用的是coherent,所以if (!is_device_dma_coherent(dev)) 这个条件不成来,直接调用swiotlb_map_page 将page 转换成hw用的dma address。
dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
unsigned long attrs)
{
phys_addr_t map, phys = page_to_phys(page) + offset;
dma_addr_t dev_addr = phys_to_dma(dev, phys);
BUG_ON(dir == DMA_NONE);
/*
* If the address happens to be in the device's DMA window,
* we can safely return the device addr and not worry about bounce
* buffering it.
*/
if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
return dev_addr;
trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
/* Oh well, have to allocate and map a bounce buffer. */
map = map_single(dev, phys, size, dir);
if (map == SWIOTLB_MAP_ERROR) {
swiotlb_full(dev, size, dir, 1);
return phys_to_dma(dev, io_tlb_overflow_buffer);
}
dev_addr = phys_to_dma(dev, map);
/* Ensure that the address returned is DMA'ble */
if (!dma_capable(dev, dev_addr, size)) {
swiotlb_tbl_unmap_single(dev, map, size, dir);
return phys_to_dma(dev, io_tlb_overflow_buffer);
}
return dev_addr;
}
在swiotlb_map_page 中如果要map的page 在dma 的capable之内的话,就直接返回page对应的物理地址
if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
return dev_addr;
dma_capable 就是看要映射的page 的address是否在mask 返回内,一般情况下kernel中dma_mask 一般是4G,也就是说map的page的address在4G范围内,采用swiotlb的方式得到的dma adress和 page对应的物理地址是一样的.
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
if (!dev->dma_mask)
return false;
return addr + size - 1 <= *dev->dma_mask;
}
如果超过4G就要用boundle buffer转一下.
0 0
- swiotlb和smmu区别在map page这个函数
- smmu 使能前后设备如何从swiotlb切换到smmu
- python2和python3 map函数的区别
- Page.RegisterClientScriptBlock 和Page.RegisterStartupScript区别
- 在oracle创建Split和Map函数
- smmu 学习笔记之mmap函数.
- Page和window的区别
- page和pageContext的区别
- smmu 学习笔记之ias和oas
- python中map,filter和reduce函数区别
- Swift 函数式编程: map 和 flatMap的区别
- python中map()和reduce()函数的区别
- Response.Write,Page.RegisterClientScriptBlock和Page.RegisterStartupScript 的区别
- Page.RegisterClientScriptBlock和Page.RegisterStartupScript有何区别?
- Page.RegisterClientScriptBlock和Page.RegisterStartupScript有何区别?
- Response.Write,Page.RegisterClientScriptBlock和Page.RegisterStartupScript的区别
- 用Page.ClientScript.RegisterClientScriptBlock 和Page.ClientScript.RegisterStartupScript:区别:
- Page.ClientScript.RegisterClientScriptBlock和Page.ClientScript.RegisterStartupScript区别
- 八大排序算法
- HDU 5295 Unstable
- springmvc web.xml配置dispatcherservlet导致访问项目只显示源码
- java堆内存模型
- java线程中run()方法和start()的区别
- swiotlb和smmu区别在map page这个函数
- eclipse中启动项目时出现java.lang.OutOfMemoryError错误
- json-lib 之jsonConfig详细使用(转载写的不错)
- Java 泛型
- app:showAsAction 和android:showAsAction的区别
- iOS 证书
- Android中的Handler使用方式
- 彻底理解Promise对象——用es5语法实现一个自己的Promise(上篇)
- json_value.asm: No such file or directory