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        err = dma_map_sgtable(attachment->dev, st, dir, 0);
  32        if (err)
  33                goto err_st;
  34
  35        return st;
  36
  37err_st:
  38        sg_free_table(st);
  39err_free:
  40        kfree(st);
  41        return ERR_PTR(err);
  42}
  43
  44static void mock_unmap_dma_buf(struct dma_buf_attachment *attachment,
  45                               struct sg_table *st,
  46                               enum dma_data_direction dir)
  47{
  48        dma_unmap_sgtable(attachment->dev, st, dir, 0);
  49        sg_free_table(st);
  50        kfree(st);
  51}
  52
  53static void mock_dmabuf_release(struct dma_buf *dma_buf)
  54{
  55        struct mock_dmabuf *mock = to_mock(dma_buf);
  56        int i;
  57
  58        for (i = 0; i < mock->npages; i++)
  59                put_page(mock->pages[i]);
  60
  61        kfree(mock);
  62}
  63
  64static int mock_dmabuf_vmap(struct dma_buf *dma_buf, struct dma_buf_map *map)
  65{
  66        struct mock_dmabuf *mock = to_mock(dma_buf);
  67        void *vaddr;
  68
  69        vaddr = vm_map_ram(mock->pages, mock->npages, 0);
  70        if (!vaddr)
  71                return -ENOMEM;
  72        dma_buf_map_set_vaddr(map, vaddr);
  73
  74        return 0;
  75}
  76
  77static void mock_dmabuf_vunmap(struct dma_buf *dma_buf, struct dma_buf_map *map)
  78{
  79        struct mock_dmabuf *mock = to_mock(dma_buf);
  80
  81        vm_unmap_ram(map->vaddr, mock->npages);
  82}
  83
  84static int mock_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
  85{
  86        return -ENODEV;
  87}
  88
  89static const struct dma_buf_ops mock_dmabuf_ops =  {
  90        .map_dma_buf = mock_map_dma_buf,
  91        .unmap_dma_buf = mock_unmap_dma_buf,
  92        .release = mock_dmabuf_release,
  93        .mmap = mock_dmabuf_mmap,
  94        .vmap = mock_dmabuf_vmap,
  95        .vunmap = mock_dmabuf_vunmap,
  96};
  97
  98static struct dma_buf *mock_dmabuf(int npages)
  99{
 100        struct mock_dmabuf *mock;
 101        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 102        struct dma_buf *dmabuf;
 103        int i;
 104
 105        mock = kmalloc(sizeof(*mock) + npages * sizeof(struct page *),
 106                       GFP_KERNEL);
 107        if (!mock)
 108                return ERR_PTR(-ENOMEM);
 109
 110        mock->npages = npages;
 111        for (i = 0; i < npages; i++) {
 112                mock->pages[i] = alloc_page(GFP_KERNEL);
 113                if (!mock->pages[i])
 114                        goto err;
 115        }
 116
 117        exp_info.ops = &mock_dmabuf_ops;
 118        exp_info.size = npages * PAGE_SIZE;
 119        exp_info.flags = O_CLOEXEC;
 120        exp_info.priv = mock;
 121
 122        dmabuf = dma_buf_export(&exp_info);
 123        if (IS_ERR(dmabuf))
 124                goto err;
 125
 126        return dmabuf;
 127
 128err:
 129        while (i--)
 130                put_page(mock->pages[i]);
 131        kfree(mock);
 132        return ERR_PTR(-ENOMEM);
 133}
 134