linux/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c
<<
>>
Prefs
   1/*
   2 * SPDX-License-Identifier: MIT
   3 *
   4 * Copyright © 2016 Intel Corporation
   5 */
   6
   7#include "mock_dmabuf.h"
   8
   9static struct sg_table *mock_map_dma_buf(struct dma_buf_attachment *attachment,
  10                                         enum dma_data_direction dir)
  11{
  12        struct mock_dmabuf *mock = to_mock(attachment->dmabuf);
  13        struct sg_table *st;
  14        struct scatterlist *sg;
  15        int i, err;
  16
  17        st = kmalloc(sizeof(*st), GFP_KERNEL);
  18        if (!st)
  19                return ERR_PTR(-ENOMEM);
  20
  21        err = sg_alloc_table(st, mock->npages, GFP_KERNEL);
  22        if (err)
  23                goto err_free;
  24
  25        sg = st->sgl;
  26        for (i = 0; i < mock->npages; i++) {
  27                sg_set_page(sg, mock->pages[i], PAGE_SIZE, 0);
  28                sg = sg_next(sg);
  29        }
  30
  31        if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
  32                err = -ENOMEM;
  33                goto err_st;
  34        }
  35
  36        return st;
  37
  38err_st:
  39        sg_free_table(st);
  40err_free:
  41        kfree(st);
  42        return ERR_PTR(err);
  43}
  44
  45static void mock_unmap_dma_buf(struct dma_buf_attachment *attachment,
  46                               struct sg_table *st,
  47                               enum dma_data_direction dir)
  48{
  49        dma_unmap_sg(attachment->dev, st->sgl, st->nents, dir);
  50        sg_free_table(st);
  51        kfree(st);
  52}
  53
  54static void mock_dmabuf_release(struct dma_buf *dma_buf)
  55{
  56        struct mock_dmabuf *mock = to_mock(dma_buf);
  57        int i;
  58
  59        for (i = 0; i < mock->npages; i++)
  60                put_page(mock->pages[i]);
  61
  62        kfree(mock);
  63}
  64
  65static void *mock_dmabuf_vmap(struct dma_buf *dma_buf)
  66{
  67        struct mock_dmabuf *mock = to_mock(dma_buf);
  68
  69        return vm_map_ram(mock->pages, mock->npages, 0, PAGE_KERNEL);
  70}
  71
  72static void mock_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
  73{
  74        struct mock_dmabuf *mock = to_mock(dma_buf);
  75
  76        vm_unmap_ram(vaddr, mock->npages);
  77}
  78
  79static void *mock_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num)
  80{
  81        struct mock_dmabuf *mock = to_mock(dma_buf);
  82
  83        return kmap(mock->pages[page_num]);
  84}
  85
  86static void mock_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
  87{
  88        struct mock_dmabuf *mock = to_mock(dma_buf);
  89
  90        return kunmap(mock->pages[page_num]);
  91}
  92
  93static int mock_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
  94{
  95        return -ENODEV;
  96}
  97
  98static const struct dma_buf_ops mock_dmabuf_ops =  {
  99        .map_dma_buf = mock_map_dma_buf,
 100        .unmap_dma_buf = mock_unmap_dma_buf,
 101        .release = mock_dmabuf_release,
 102        .map = mock_dmabuf_kmap,
 103        .unmap = mock_dmabuf_kunmap,
 104        .mmap = mock_dmabuf_mmap,
 105        .vmap = mock_dmabuf_vmap,
 106        .vunmap = mock_dmabuf_vunmap,
 107};
 108
 109static struct dma_buf *mock_dmabuf(int npages)
 110{
 111        struct mock_dmabuf *mock;
 112        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 113        struct dma_buf *dmabuf;
 114        int i;
 115
 116        mock = kmalloc(sizeof(*mock) + npages * sizeof(struct page *),
 117                       GFP_KERNEL);
 118        if (!mock)
 119                return ERR_PTR(-ENOMEM);
 120
 121        mock->npages = npages;
 122        for (i = 0; i < npages; i++) {
 123                mock->pages[i] = alloc_page(GFP_KERNEL);
 124                if (!mock->pages[i])
 125                        goto err;
 126        }
 127
 128        exp_info.ops = &mock_dmabuf_ops;
 129        exp_info.size = npages * PAGE_SIZE;
 130        exp_info.flags = O_CLOEXEC;
 131        exp_info.priv = mock;
 132
 133        dmabuf = dma_buf_export(&exp_info);
 134        if (IS_ERR(dmabuf))
 135                goto err;
 136
 137        return dmabuf;
 138
 139err:
 140        while (i--)
 141                put_page(mock->pages[i]);
 142        kfree(mock);
 143        return ERR_PTR(-ENOMEM);
 144}
 145