1 /* 2 * Copyright (c) 2019-2020 François Tigeot <ftigeot@wolfpond.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <linux/fs.h> 28 #include <linux/slab.h> 29 #include <linux/dma-buf.h> 30 #include <linux/dma-fence.h> 31 #include <linux/export.h> 32 #include <linux/module.h> 33 #include <linux/seq_file.h> 34 #include <linux/poll.h> 35 #include <linux/reservation.h> 36 #include <linux/mm.h> 37 38 static int 39 dmabuf_stat(struct file *fp, struct stat *sb, struct ucred *cred) 40 { 41 struct dma_buf *dmabuf = fp->f_data; 42 43 memset(sb, 0, sizeof(*sb)); 44 sb->st_size = dmabuf->size; 45 sb->st_mode = S_IFIFO; /* XXX */ 46 47 return (0); 48 } 49 50 static int 51 dmabuf_close(struct file *fp) 52 { 53 kprintf("dmabuf_close(): not implemented\n"); 54 return (EINVAL); 55 } 56 57 struct fileops dmabuf_fileops = { 58 .fo_read = badfo_readwrite, 59 .fo_write = badfo_readwrite, 60 .fo_ioctl = badfo_ioctl, 61 .fo_kqfilter = badfo_kqfilter, 62 .fo_stat = dmabuf_stat, 63 .fo_close = dmabuf_close, 64 }; 65 66 struct dma_buf * 67 dma_buf_export(const struct dma_buf_export_info *exp_info) 68 { 69 struct dma_buf *dmabuf; 70 struct file *fp; 71 72 falloc(curthread->td_lwp, &fp, NULL); 73 if (fp == NULL) 74 return ERR_PTR(-ENFILE); 75 76 dmabuf = kmalloc(sizeof(struct dma_buf), M_DRM, M_WAITOK); 77 fp->f_type = DTYPE_DMABUF; 78 fp->f_ops = &dmabuf_fileops; 79 fp->private_data = dmabuf; 80 dmabuf->priv = exp_info->priv; 81 dmabuf->ops = exp_info->ops; 82 dmabuf->size = exp_info->size; 83 dmabuf->file = fp; 84 85 return dmabuf; 86 } 87 88 int 89 dma_buf_fd(struct dma_buf *dmabuf, int flags) 90 { 91 int fd, error; 92 93 if (dmabuf == NULL) 94 return -EINVAL; 95 96 if (dmabuf->file == NULL) 97 return -EINVAL; 98 99 if (flags & O_CLOEXEC) { 100 /* XXX: CLOEXEC not handled yet */ 101 #if 0 102 __set_close_on_exec(fd, fdt); 103 else 104 __clear_close_on_exec(fd, fdt); 105 #endif 106 } 107 108 error = fdalloc(curproc, 0, &fd); 109 if (error != 0) 110 return -error; 111 112 fsetfd(curproc->p_fd, dmabuf->file, fd); 113 114 return fd; 115 } 116 117 struct dma_buf * 118 dma_buf_get(int fd) 119 { 120 struct file *fp; 121 struct dma_buf *dmabuf; 122 123 if ((fp = holdfp(curthread, fd, -1)) == NULL) 124 return ERR_PTR(-EBADF); 125 126 if (fp->f_ops != &dmabuf_fileops) { 127 kprintf("dma_buf_get(): file->f_ops != &dmabuf_fileops\n"); 128 fdrop(fp); 129 return ERR_PTR(-EBADF); 130 } 131 132 dmabuf = fp->private_data; 133 fdrop(fp); 134 135 return dmabuf; 136 } 137 138 struct sg_table * 139 dma_buf_map_attachment(struct dma_buf_attachment *attach, 140 enum dma_data_direction direction) 141 { 142 struct sg_table *sg_table; 143 144 if (attach == NULL) 145 return ERR_PTR(-EINVAL); 146 147 if (attach->dmabuf == NULL) 148 return ERR_PTR(-EINVAL); 149 150 sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); 151 if (sg_table == NULL) 152 return ERR_PTR(-ENOMEM); 153 154 return sg_table; 155 } 156 157 void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, 158 struct sg_table *sg_table, 159 enum dma_data_direction direction) 160 { 161 } 162 163