dma_cache_maint_page

dma_cache_maint_page(page, off, size, dir, dmac_map_area);

dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);

static void dma_cache_maint_page(struct page *page, unsigned long offset,
    size_t size, enum dma_data_direction dir,
    void (*op)(const void *, size_t, int))
{
    unsigned long pfn;
    size_t left = size;

    pfn = page_to_pfn(page) + offset / PAGE_SIZE;
    offset %= PAGE_SIZE;

    /*
     * 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.
     */
    do {
        size_t len = left;
        void *vaddr;

        page = pfn_to_page(pfn);

        if (PageHighMem(page)) {
            if (len + offset > PAGE_SIZE)
                len = PAGE_SIZE - offset;

            if (cache_is_vipt_nonaliasing()) {
                vaddr = kmap_atomic(page);
                op(vaddr + offset, len, dir);
                kunmap_atomic(vaddr);
            } else {
                vaddr = kmap_high_get(page);
                if (vaddr) {
                    op(vaddr + offset, len, dir);
                    kunmap_high(page);
                }
            }
        } else {
            vaddr = page_address(page) + offset;
            op(vaddr, len, dir);
        }
        offset = 0;
        pfn++;
        left -= len;
    } while (left);
}
 

/*
 * These are private to the dma-mapping API.  Do not use directly.
 * Their sole purpose is to ensure that data held in the cache
 * is visible to DMA, or data written by DMA to system memory is
 * visible to the CPU.
 */
#define dmac_map_area            cpu_cache.dma_map_area
#define dmac_unmap_area         cpu_cache.dma_unmap_area
 

#define dmac_map_area            __glue(_CACHE,_dma_map_area)
#define dmac_unmap_area         __glue(_CACHE,_dma_unmap_area)

ENTRY(__dma_map_area)

cmp w2, #DMA_FROM_DEVICE

b.eq __dma_inv_area

b __dma_clean_area

ENDPIPROC(__dma_map_area)

/* * __dma_unmap_area(start, size, dir) * - start - kernel virtual start address * - size - size of region * - dir - DMA direction */

ENTRY(__dma_unmap_area)

cmp w2, #DMA_TO_DEVICE

b.ne __dma_inv_area ret

ENDPIPROC(__dma_unmap_area)
 

/*
 *    __dma_inv_area(start, size)
 *    - start   - virtual start address of region
 *    - size    - size in question
 */

__dma_inv_area:
    add    x1, x1, x0
    dcache_line_size x2, x3
    sub    x3, x2, #1
    tst    x1, x3                // end cache line aligned?
    bic    x1, x1, x3
    b.eq    1f
    dc    civac, x1            // clean & invalidate D / U line
1:    tst    x0, x3                // start cache line aligned?
    bic    x0, x0, x3
    b.eq    2f
    dc    civac, x0            // clean & invalidate D / U line
    b    3f
2:    dc    ivac, x0            // invalidate D / U line
3:    add    x0, x0, x2
    cmp    x0, x1
    b.lo    2b
    dsb    sy
    ret
ENDPIPROC(__inval_dcache_area)
ENDPROC(__dma_inv_area)

/*
 *    __dma_clean_area(start, size)
 *    - start   - virtual start address of region
 *    - size    - size in question
 */
__dma_clean_area:
    dcache_by_line_op cvac, sy, x0, x1, x2, x3
    ret
ENDPIPROC(__clean_dcache_area_poc)
ENDPROC(__dma_clean_area)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值