Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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}