diff options
| author | Jerry Zhang <zhangjerry@google.com> | 2016-11-11 12:19:58 -0800 |
|---|---|---|
| committer | Mister Oyster <oysterized@gmail.com> | 2017-09-14 17:11:21 +0200 |
| commit | 5fe0d89935609c6f30e450941949d22a9407868d (patch) | |
| tree | 1e0e2d24a2954bec9a22a3d65b63c31bdf4e283e /drivers/usb | |
| parent | 17882e4f29339cc4e67bb13ec425ffff1a9d7354 (diff) | |
usb: gadget: f_fs: Add ioctl for allocating endpoint buffers.
This creates an ioctl named FUNCTIONFS_ENDPOINT_ALLOC which will
preallocate buffers for a given size. Any reads/writes on that
endpoint below that size will use those buffers instead of allocating
their own. If the endpoint is not active, the buffer will not be
allocated until it becomes active.
Change-Id: I4da517620ed913161ea9e21a31f6b92c9a012b44
Signed-off-by: Jerry Zhang <zhangjerry@google.com>
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/gadget/f_fs.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index dce917ed3..ef910d05e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -332,6 +332,9 @@ struct ffs_epfile { unsigned char isoc; /* P: ffs->eps_lock */ unsigned char _pad; + + unsigned long buf_len; + char *buffer; }; static int __must_check ffs_epfiles_create(struct ffs_data *ffs); @@ -767,7 +770,7 @@ static ssize_t ffs_epfile_io(struct file *file, char *data = NULL; ssize_t ret; int halt; - int buffer_len = 0; + size_t buffer_len = 0; pr_debug("%s: len %lld, read %d\n", __func__, (u64)len, read); @@ -830,9 +833,13 @@ first_try: /* Allocate & copy */ if (!halt && !data) { #if defined(CONFIG_64BIT) && defined(CONFIG_MTK_LM_MODE) - data = kzalloc(buffer_len, GFP_KERNEL | GFP_DMA); + data = buffer_len > epfile->buf_len ? + kzalloc(buffer_len, GFP_KERNEL| GFP_DMA) : + epfile->buffer; #else - data = kzalloc(buffer_len, GFP_KERNEL); + data = buffer_len > epfile->buf_len ? + kzalloc(buffer_len, GFP_KERNEL) : + epfile->buffer; #endif if (unlikely(!data)) return -ENOMEM; @@ -922,7 +929,8 @@ first_try: mutex_unlock(&epfile->mutex); error: - kfree(data); + if (buffer_len > epfile->buf_len) + kfree(data); return ret; } @@ -985,7 +993,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, return -ENODEV; spin_lock_irq(&epfile->ffs->eps_lock); - if (likely(epfile->ep)) { + if (epfile->ep) { switch (code) { case FUNCTIONFS_FIFO_STATUS: ret = usb_ep_fifo_status(epfile->ep->ep); @@ -1023,11 +1031,28 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, ret = -EFAULT; return ret; } + case FUNCTIONFS_ENDPOINT_ALLOC: + kfree(epfile->buffer); + epfile->buffer = NULL; + epfile->buf_len = value; + if (epfile->buf_len) { + epfile->buffer = kzalloc(epfile->buf_len, + GFP_KERNEL); + if (!epfile->buffer) + ret = -ENOMEM; + } + break; default: ret = -ENOTTY; } } else { - ret = -ENODEV; + switch (code) { + case FUNCTIONFS_ENDPOINT_ALLOC: + epfile->buf_len = value; + break; + default: + ret = -ENODEV; + } } spin_unlock_irq(&epfile->ffs->eps_lock); @@ -1635,6 +1660,8 @@ static void ffs_func_eps_disable(struct ffs_function *func) do { atomic_set(&epfile->error, 1); epfile->ep = NULL; + kfree(epfile->buffer); + epfile->buffer = NULL; /* pending requests get nuked */ if (likely(ep->ep)) { @@ -1677,6 +1704,14 @@ static int ffs_func_eps_enable(struct ffs_function *func) ep->ep->driver_data = ep; ep->ep->desc = ds; + if (epfile->buf_len) { + epfile->buffer = kzalloc(epfile->buf_len, + GFP_KERNEL); + if (!epfile->buffer) { + ret = -ENOMEM; + break; + } + } ret = usb_ep_enable(ep->ep); if (likely(!ret)) { epfile->ep = ep; |
