1 /* 2 * SPDX-License-Identifier: MIT 3 * 4 * Copyright © 2016 Intel Corporation 5 */ 6 7 #include "mock_dmabuf.h" 8 9 static 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 37 err_st: 38 sg_free_table(st); 39 err_free: 40 kfree(st); 41 return ERR_PTR(err); 42 } 43 44 static 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 53 static 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 64 static void *mock_dmabuf_vmap(struct dma_buf *dma_buf) 65 { 66 struct mock_dmabuf *mock = to_mock(dma_buf); 67 68 return vm_map_ram(mock->pages, mock->npages, 0); 69 } 70 71 static void mock_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr) 72 { 73 struct mock_dmabuf *mock = to_mock(dma_buf); 74 75 vm_unmap_ram(vaddr, mock->npages); 76 } 77 78 static int mock_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) 79 { 80 return -ENODEV; 81 } 82 83 static const struct dma_buf_ops mock_dmabuf_ops = { 84 .map_dma_buf = mock_map_dma_buf, 85 .unmap_dma_buf = mock_unmap_dma_buf, 86 .release = mock_dmabuf_release, 87 .mmap = mock_dmabuf_mmap, 88 .vmap = mock_dmabuf_vmap, 89 .vunmap = mock_dmabuf_vunmap, 90 }; 91 92 static struct dma_buf *mock_dmabuf(int npages) 93 { 94 struct mock_dmabuf *mock; 95 DEFINE_DMA_BUF_EXPORT_INFO(exp_info); 96 struct dma_buf *dmabuf; 97 int i; 98 99 mock = kmalloc(sizeof(*mock) + npages * sizeof(struct page *), 100 GFP_KERNEL); 101 if (!mock) 102 return ERR_PTR(-ENOMEM); 103 104 mock->npages = npages; 105 for (i = 0; i < npages; i++) { 106 mock->pages[i] = alloc_page(GFP_KERNEL); 107 if (!mock->pages[i]) 108 goto err; 109 } 110 111 exp_info.ops = &mock_dmabuf_ops; 112 exp_info.size = npages * PAGE_SIZE; 113 exp_info.flags = O_CLOEXEC; 114 exp_info.priv = mock; 115 116 dmabuf = dma_buf_export(&exp_info); 117 if (IS_ERR(dmabuf)) 118 goto err; 119 120 return dmabuf; 121 122 err: 123 while (i--) 124 put_page(mock->pages[i]); 125 kfree(mock); 126 return ERR_PTR(-ENOMEM); 127 } 128