aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorJerry Zhang <zhangjerry@google.com>2016-11-11 12:19:58 -0800
committerMister Oyster <oysterized@gmail.com>2017-09-14 17:11:21 +0200
commit5fe0d89935609c6f30e450941949d22a9407868d (patch)
tree1e0e2d24a2954bec9a22a3d65b63c31bdf4e283e /drivers/usb
parent17882e4f29339cc4e67bb13ec425ffff1a9d7354 (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.c47
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;