-
Notifications
You must be signed in to change notification settings - Fork 85
/
exporter-fd.c
135 lines (108 loc) · 3.07 KB
/
exporter-fd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
*/
#include <linux/dma-buf.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
struct dma_buf *dmabuf_exported;
EXPORT_SYMBOL(dmabuf_exported);
static struct sg_table *exporter_map_dma_buf(struct dma_buf_attachment *attachment,
enum dma_data_direction dir)
{
return NULL;
}
static void exporter_unmap_dma_buf(struct dma_buf_attachment *attachment,
struct sg_table *table,
enum dma_data_direction dir)
{
}
static void exporter_release(struct dma_buf *dmabuf)
{
kfree(dmabuf->priv);
dmabuf_exported = NULL;
}
static void *exporter_kmap_atomic(struct dma_buf *dmabuf, unsigned long page_num)
{
return NULL;
}
static void *exporter_kmap(struct dma_buf *dmabuf, unsigned long page_num)
{
return NULL;
}
static int exporter_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
{
void *vaddr = dmabuf->priv;
return remap_pfn_range(vma, vma->vm_start, virt_to_pfn(vaddr),
PAGE_SIZE, vma->vm_page_prot);
}
static const struct dma_buf_ops exp_dmabuf_ops = {
.map_dma_buf = exporter_map_dma_buf,
.unmap_dma_buf = exporter_unmap_dma_buf,
.release = exporter_release,
.map = exporter_kmap,
.map_atomic = exporter_kmap_atomic,
.mmap = exporter_mmap,
};
static struct dma_buf *exporter_alloc_page(void)
{
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct dma_buf *dmabuf;
void *vaddr;
vaddr = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!vaddr)
return NULL;
exp_info.ops = &exp_dmabuf_ops;
exp_info.size = PAGE_SIZE;
exp_info.flags = O_CLOEXEC;
exp_info.priv = vaddr;
dmabuf = dma_buf_export(&exp_info);
if (IS_ERR(dmabuf)) {
kfree(vaddr);
return NULL;
}
sprintf(vaddr, "hello world!");
return dmabuf;
}
static long exporter_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int fd = dma_buf_fd(dmabuf_exported, O_CLOEXEC);
if (copy_to_user((int __user *)arg, &fd, sizeof(fd)))
return -EFAULT;
return 0;
}
static struct file_operations exporter_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = exporter_ioctl,
};
static struct miscdevice mdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "exporter",
.fops = &exporter_fops,
};
static int __init exporter_init(void)
{
dmabuf_exported = exporter_alloc_page();
if (!dmabuf_exported) {
pr_err("error: exporter alloc page failed\n");
return -ENOMEM;
}
return misc_register(&mdev);
}
static void __exit exporter_exit(void)
{
misc_deregister(&mdev);
}
module_init(exporter_init);
module_exit(exporter_exit);
MODULE_AUTHOR("Leon He <343005384@qq.com>");
MODULE_DESCRIPTION("DMA-BUF Exporter example for cpu-access (mmap)");
MODULE_LICENSE("GPL v2");