diff options
Diffstat (limited to 'kernel/ethosu_buffer.c')
-rw-r--r-- | kernel/ethosu_buffer.c | 126 |
1 files changed, 37 insertions, 89 deletions
diff --git a/kernel/ethosu_buffer.c b/kernel/ethosu_buffer.c index 07c8033..bf7d745 100644 --- a/kernel/ethosu_buffer.c +++ b/kernel/ethosu_buffer.c @@ -15,7 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, you can access it online at * http://www.gnu.org/licenses/gpl-2.0.html. - * */ /**************************************************************************** @@ -45,17 +44,14 @@ static int ethosu_buffer_release(struct inode *inode, static int ethosu_buffer_mmap(struct file *file, struct vm_area_struct *vma); -static long ethosu_buffer_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg); +static loff_t ethosu_buffer_llseek(struct file *file, + loff_t offset, + int whence); static const struct file_operations ethosu_buffer_fops = { - .release = ðosu_buffer_release, - .mmap = ðosu_buffer_mmap, - .unlocked_ioctl = ðosu_buffer_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ðosu_buffer_ioctl, -#endif + .release = ðosu_buffer_release, + .mmap = ðosu_buffer_mmap, + .llseek = ðosu_buffer_llseek, }; /**************************************************************************** @@ -75,8 +71,8 @@ static void ethosu_buffer_destroy(struct kref *kref) dev_dbg(dev, "Buffer destroy. buf=0x%pK", buf); - memset(buf->cpu_addr, 0, buf->capacity); - dma_free_coherent(dev, buf->capacity, buf->cpu_addr, + memset(buf->cpu_addr, 0, buf->size); + dma_free_coherent(dev, buf->size, buf->cpu_addr, buf->dma_addr); memset(buf, 0, sizeof(*buf)); @@ -108,78 +104,43 @@ static int ethosu_buffer_mmap(struct file *file, file, buf); ret = dma_mmap_coherent(dev, vma, buf->cpu_addr, - buf->dma_addr, buf->capacity); + buf->dma_addr, buf->size); return ret; } -static long ethosu_buffer_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) +static loff_t ethosu_buffer_llseek(struct file *file, + loff_t offset, + int whence) { struct ethosu_buffer *buf = file->private_data; - struct device *dev = buf->dev; - void __user *udata = (void __user *)arg; - int ret; - - ret = device_lock_interruptible(dev); - if (ret) - return ret; - - switch (cmd) { - case ETHOSU_IOCTL_BUFFER_SET: { - struct ethosu_uapi_buffer uapi; - - if (copy_from_user(&uapi, udata, sizeof(uapi))) { - ret = -EFAULT; - break; - } - - dev_dbg(dev, - "Buffer ioctl: Buffer set. size=%u, offset=%u\n", - uapi.size, uapi.offset); - ret = ethosu_buffer_resize(buf, uapi.size, uapi.offset); - break; - } - case ETHOSU_IOCTL_BUFFER_GET: { - struct ethosu_uapi_buffer uapi = { 0 }; - - uapi.size = buf->size; - uapi.offset = buf->offset; - - dev_dbg(dev, - "Buffer ioctl: Buffer get. size=%u, offset=%u\n", - uapi.size, uapi.offset); - - if (copy_to_user(udata, &uapi, sizeof(uapi))) { - ret = -EFAULT; - break; - } + if (offset != 0) + return -EINVAL; - ret = 0; - break; - } - default: { - dev_err(dev, "Invalid ioctl. cmd=%u, arg=%lu", - cmd, arg); - ret = -ENOIOCTLCMD; - break; - } + /* + * SEEK_END and SEEK_SET is supported with a zero offset to allow buffer + * size discovery using seek functions e.g. + * size = lseek(buf_fd, 0, SEEK_END); + * lseek(buf_fd, 0, SEEK_SET); + */ + switch (whence) { + case SEEK_END: + return buf->size; + case SEEK_SET: + return 0; + default: + return -EINVAL; } - - device_unlock(dev); - - return ret; } int ethosu_buffer_create(struct device *dev, - size_t capacity) + size_t size) { struct ethosu_buffer *buf; int ret = -ENOMEM; - if (!capacity) + if (!size) return -EINVAL; buf = devm_kzalloc(dev, sizeof(*buf), GFP_KERNEL); @@ -187,13 +148,11 @@ int ethosu_buffer_create(struct device *dev, return -ENOMEM; buf->dev = dev; - buf->capacity = capacity; - buf->offset = 0; - buf->size = 0; + buf->size = size; kref_init(&buf->kref); - buf->cpu_addr = dma_alloc_coherent(dev, capacity, - &buf->dma_addr, GFP_KERNEL); + buf->cpu_addr = dma_alloc_coherent(dev, size, &buf->dma_addr, + GFP_KERNEL); if (!buf->cpu_addr) goto free_buf; @@ -203,17 +162,19 @@ int ethosu_buffer_create(struct device *dev, goto free_dma; buf->file = fget(ret); + buf->file->f_mode |= FMODE_LSEEK; + fput(buf->file); dev_dbg(dev, - "Buffer create. file=0x%pK, fd=%d, buf=0x%pK, capacity=%zu, cpu_addr=0x%pK, dma_addr=0x%llx, phys_addr=0x%llx\n", - buf->file, ret, buf, capacity, buf->cpu_addr, buf->dma_addr, + "Buffer create. file=0x%pK, fd=%d, buf=0x%pK, size=%zu, cpu_addr=0x%pK, dma_addr=0x%llx, phys_addr=0x%llx\n", + buf->file, ret, buf, size, buf->cpu_addr, buf->dma_addr, virt_to_phys(buf->cpu_addr)); return ret; free_dma: - dma_free_coherent(dev, buf->capacity, buf->cpu_addr, + dma_free_coherent(dev, buf->size, buf->cpu_addr, buf->dma_addr); free_buf: @@ -254,16 +215,3 @@ void ethosu_buffer_put(struct ethosu_buffer *buf) { kref_put(&buf->kref, ethosu_buffer_destroy); } - -int ethosu_buffer_resize(struct ethosu_buffer *buf, - size_t size, - size_t offset) -{ - if ((size + offset) > buf->capacity) - return -EINVAL; - - buf->size = size; - buf->offset = offset; - - return 0; -} |