Linux dma_map_sg API
-v0.1 2019.11.12 Sherlock init
如linux/Documentation/DMA-API-HOW.txt裏提到的:
With scatterlists, you map a region gathered from several regions by::
int i, count = dma_map_sg(dev, sglist, nents, direction);
struct scatterlist *sg;
for_each_sg(sglist, sg, count, i) {
hw_address[i] = sg_dma_address(sg);
hw_len[i] = sg_dma_len(sg);
}
where nents is the number of entries in the sglist.
The implementation is free to merge several consecutive sglist entries
into one (e.g. if DMA mapping is done with PAGE_SIZE granularity, any
consecutive sglist entries can be merged into one provided the first one
ends and the second one starts on a page boundary - in fact this is a huge
advantage for cards which either cannot do scatter-gather or have very
limited number of scatter-gather entries) and returns the actual number
of sg entries it mapped them to. On failure 0 is returned.
Then you should loop count times (note: this can be less than nents times)
and use sg_dma_address() and sg_dma_len() macros where you previously
accessed sg->address and sg->length as shown above.
To unmap a scatterlist, just call::
dma_unmap_sg(dev, sglist, nents, direction);
Again, make sure DMA activity has already finished.
.. note::
The 'nents' argument to the dma_unmap_sg call must be
the _same_ one you passed into the dma_map_sg call,
it should _NOT_ be the 'count' value _returned_ from the
dma_map_sg call.
dma_map_sg對一個sgl做map的時候,返回的map的sge的個數可能是小於輸入sgl的sge的個數
的,這是因爲連續頁做了合併操作,在有IOMMU的情況下,也可能是因爲IOMMU的存在把一段
連續的IOVA映射成了一些離散的物理地址塊,而這些離散的物理地址塊正是前面的sgl輸入,
這個連續的IOVA正式dma_map_sg的輸出。