linux/kernel/dma/virt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * DMA operations that map to virtual addresses without flushing memory.
   4 */
   5#include <linux/export.h>
   6#include <linux/mm.h>
   7#include <linux/dma-mapping.h>
   8#include <linux/scatterlist.h>
   9
  10static void *dma_virt_alloc(struct device *dev, size_t size,
  11                            dma_addr_t *dma_handle, gfp_t gfp,
  12                            unsigned long attrs)
  13{
  14        void *ret;
  15
  16        ret = (void *)__get_free_pages(gfp | __GFP_ZERO, get_order(size));
  17        if (ret)
  18                *dma_handle = (uintptr_t)ret;
  19        return ret;
  20}
  21
  22static void dma_virt_free(struct device *dev, size_t size,
  23                          void *cpu_addr, dma_addr_t dma_addr,
  24                          unsigned long attrs)
  25{
  26        free_pages((unsigned long)cpu_addr, get_order(size));
  27}
  28
  29static dma_addr_t dma_virt_map_page(struct device *dev, struct page *page,
  30                                    unsigned long offset, size_t size,
  31                                    enum dma_data_direction dir,
  32                                    unsigned long attrs)
  33{
  34        return (uintptr_t)(page_address(page) + offset);
  35}
  36
  37static int dma_virt_map_sg(struct device *dev, struct scatterlist *sgl,
  38                           int nents, enum dma_data_direction dir,
  39                           unsigned long attrs)
  40{
  41        int i;
  42        struct scatterlist *sg;
  43
  44        for_each_sg(sgl, sg, nents, i) {
  45                BUG_ON(!sg_page(sg));
  46                sg_dma_address(sg) = (uintptr_t)sg_virt(sg);
  47                sg_dma_len(sg) = sg->length;
  48        }
  49
  50        return nents;
  51}
  52
  53const struct dma_map_ops dma_virt_ops = {
  54        .alloc                  = dma_virt_alloc,
  55        .free                   = dma_virt_free,
  56        .map_page               = dma_virt_map_page,
  57        .map_sg                 = dma_virt_map_sg,
  58};
  59EXPORT_SYMBOL(dma_virt_ops);
  60