| @@ -55,33 +55,6 @@ MODULE_PARM_DESC(mem_accounting, · 54 unmodified lines |
| 55 | "Enable cgroup-based memory accounting for dma-buf heap allocations (default=false)."); | 55 | "Enable cgroup-based memory accounting for dma-buf heap allocations (default=false)."); |
| 56 | EXPORT_SYMBOL_NS_GPL(mem_accounting, "DMA_BUF_HEAP"); | 56 | EXPORT_SYMBOL_NS_GPL(mem_accounting, "DMA_BUF_HEAP"); |
| 57 | | 57 | |
| 58 | static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, | | |
| 59 | u32 fd_flags, | | |
| 60 | u64 heap_flags) | | |
| 61 | { | | |
| 62 | struct dma_buf *dmabuf; | | |
| 63 | int fd; | | |
| 64 | | | |
| 65 | /* | | |
| 66 | * Allocations from all heaps have to begin | | |
| 67 | * and end on page boundaries. | | |
| 68 | */ | | |
| 69 | len = PAGE_ALIGN(len); | | |
| 70 | if (!len) | | |
| 71 | return -EINVAL; | | |
| 72 | | | |
| 73 | dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags); | | |
| 74 | if (IS_ERR(dmabuf)) | | |
| 75 | return PTR_ERR(dmabuf); | | |
| 76 | | | |
| 77 | fd = dma_buf_fd(dmabuf, fd_flags); | | |
| 78 | if (fd < 0) { | | |
| 79 | dma_buf_put(dmabuf); | | |
| 80 | /* just return, as put will call release and that will free */ | | |
| 81 | } | | |
| 82 | return fd; | | |
| 83 | } | | |
| 84 | | | |
| 85 | static int dma_heap_open(struct inode *inode, struct file *file) | 58 | static int dma_heap_open(struct inode *inode, struct file *file) |
| 86 | { | 59 | { |
| 87 | struct dma_heap *heap; | 60 | struct dma_heap *heap; |
| @@ -99,30 +72,42 @@ static int dma_heap_open(struct inode *inode, struct file *file) · 11 unmodified lines |
| 99 | return 0; | 72 | return 0; |
| 100 | } | 73 | } |
| 101 | | 74 | |
| 102 | static long dma_heap_ioctl_allocate(struct file *file, void *data) | 75 | static struct dma_buf *dma_heap_ioctl_allocate(struct file *file, void *data) |
| 103 | { | 76 | { |
| 104 | struct dma_heap_allocation_data *heap_allocation = data; | 77 | struct dma_heap_allocation_data *heap_allocation = data; |
| 105 | struct dma_heap *heap = file->private_data; | 78 | struct dma_heap *heap = file->private_data; |
| | 79 | struct dma_buf *dmabuf; |
| 106 | int fd; | 80 | int fd; |
| | 81 | size_t len; |
| 107 | | 82 | |
| 108 | if (heap_allocation->fd) | 83 | if (heap_allocation->fd) |
| 109 | return -EINVAL; | 84 | return ERR_PTR(-EINVAL); |
| 110 | | 85 | |
| 111 | if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS) | 86 | if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS) |
| 112 | return -EINVAL; | 87 | return ERR_PTR(-EINVAL); |
| 113 | | 88 | |
| 114 | if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS) | 89 | if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS) |
| 115 | return -EINVAL; | 90 | return ERR_PTR(-EINVAL); |
| | 91 | |
| | 92 | len = PAGE_ALIGN(heap_allocation->len); |
| | 93 | if (!len) |
| | 94 | return ERR_PTR(-EINVAL); |
| | 95 | |
| | 96 | dmabuf = heap->ops->allocate(heap, len, heap_allocation->fd_flags, |
| | 97 | heap_allocation->heap_flags); |
| 116 | | 98 | |
| 117 | fd = dma_heap_buffer_alloc(heap, heap_allocation->len, | 99 | if (IS_ERR(dmabuf)) |
| 118 | heap_allocation->fd_flags, | 100 | return dmabuf; |
| 119 | heap_allocation->heap_flags); | 101 | |
| 120 | if (fd < 0) | 102 | fd = get_unused_fd_flags(heap_allocation->fd_flags); |
| 121 | return fd; | 103 | if (fd < 0) { |
| | 104 | dma_buf_put(dmabuf); |
| | 105 | return ERR_PTR(fd); |
| | 106 | } |
| 122 | | 107 | |
| 123 | heap_allocation->fd = fd; | 108 | heap_allocation->fd = fd; |
| 124 | | 109 | |
| 125 | return 0; | 110 | return dmabuf; |
| 126 | } | 111 | } |
| 127 | | 112 | |
| 128 | static unsigned int dma_heap_ioctl_cmds[] = { | 113 | static unsigned int dma_heap_ioctl_cmds[] = { |
| @@ -138,6 +123,8 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd, · 9 unmodified lines |
| 138 | unsigned int in_size, out_size, drv_size, ksize; | 123 | unsigned int in_size, out_size, drv_size, ksize; |
| 139 | int nr = _IOC_NR(ucmd); | 124 | int nr = _IOC_NR(ucmd); |
| 140 | int ret = 0; | 125 | int ret = 0; |
| | 126 | int fd; |
| | 127 | struct dma_buf *dmabuf; |
| 141 | | 128 | |
| 142 | if (nr >= ARRAY_SIZE(dma_heap_ioctl_cmds)) | 129 | if (nr >= ARRAY_SIZE(dma_heap_ioctl_cmds)) |
| 143 | return -EINVAL; | 130 | return -EINVAL; |
| @@ -174,15 +161,28 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd, · 30 unmodified lines |
| 174 | | 161 | |
| 175 | switch (kcmd) { | 162 | switch (kcmd) { |
| 176 | case DMA_HEAP_IOCTL_ALLOC: | 163 | case DMA_HEAP_IOCTL_ALLOC: |
| 177 | ret = dma_heap_ioctl_allocate(file, kdata); | 164 | dmabuf = dma_heap_ioctl_allocate(file, kdata); |
| | 165 | |
| | 166 | if (IS_ERR(dmabuf)) { |
| | 167 | ret = PTR_ERR(dmabuf); |
| | 168 | break; |
| | 169 | } |
| | 170 | |
| | 171 | fd = ((struct dma_heap_allocation_data *)kdata)->fd; |
| | 172 | if (copy_to_user((void __user *)arg, kdata, out_size) != 0) { |
| | 173 | put_unused_fd(fd); |
| | 174 | dma_buf_put(dmabuf); |
| | 175 | ret = -EFAULT; |
| | 176 | } else { |
| | 177 | dma_buf_fd_install(dmabuf, fd); |
| | 178 | } |
| | 179 | |
| 178 | break; | 180 | break; |
| 179 | default: | 181 | default: |
| 180 | ret = -ENOTTY; | 182 | ret = -ENOTTY; |
| 181 | goto err; | 183 | goto err; |
| 182 | } | 184 | } |
| 183 | | 185 | |
| 184 | if (copy_to_user((void __user *)arg, kdata, out_size) != 0) | | |
| 185 | ret = -EFAULT; | | |
| 186 | err: | 186 | err: |
| 187 | if (kdata != stack_kdata) | 187 | if (kdata != stack_kdata) |
| 188 | kfree(kdata); | 188 | kfree(kdata); |