aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/function
diff options
context:
space:
mode:
authorRobert Baldyga <r.baldyga@samsung.com>2015-01-23 07:41:01 -0500
committerFelipe Balbi <balbi@ti.com>2015-01-27 10:34:59 -0500
commit5e33f6fdf735cda1d4580fe6f1878da05718fe73 (patch)
tree7e6e041131600b431ab284118750a7539245a43a /drivers/usb/gadget/function
parentacba23fec527012e901636e4ba091ee25461c943 (diff)
usb: gadget: ffs: add eventfd notification about ffs events
Add eventfd which notifies userspace about ep0 events and AIO completion events. It simplifies using of FunctionFS with event loop, because now we need to poll on single file (instead of polling on ep0 and eventfd's supplied to AIO layer). FunctionFS eventfd is not triggered if another eventfd is supplied to AIO layer (in AIO request). It can be useful, for example, when we want to handle AIO transations for chosen endpoint in separate thread. Signed-off-by: Robert Baldyga <r.baldyga@samsung.com> Acked-by: Michal Nazarewicz <mina86@mina86.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/function')
-rw-r--r--drivers/usb/gadget/function/f_fs.c29
-rw-r--r--drivers/usb/gadget/function/u_fs.h1
2 files changed, 29 insertions, 1 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 14e44d7083a1..af98b096af2f 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -31,6 +31,7 @@
31#include <linux/aio.h> 31#include <linux/aio.h>
32#include <linux/mmu_context.h> 32#include <linux/mmu_context.h>
33#include <linux/poll.h> 33#include <linux/poll.h>
34#include <linux/eventfd.h>
34 35
35#include "u_fs.h" 36#include "u_fs.h"
36#include "u_f.h" 37#include "u_f.h"
@@ -153,6 +154,8 @@ struct ffs_io_data {
153 154
154 struct usb_ep *ep; 155 struct usb_ep *ep;
155 struct usb_request *req; 156 struct usb_request *req;
157
158 struct ffs_data *ffs;
156}; 159};
157 160
158struct ffs_desc_helper { 161struct ffs_desc_helper {
@@ -674,6 +677,9 @@ static void ffs_user_copy_worker(struct work_struct *work)
674 677
675 aio_complete(io_data->kiocb, ret, ret); 678 aio_complete(io_data->kiocb, ret, ret);
676 679
680 if (io_data->ffs->ffs_eventfd && !io_data->kiocb->ki_eventfd)
681 eventfd_signal(io_data->ffs->ffs_eventfd, 1);
682
677 usb_ep_free_request(io_data->ep, io_data->req); 683 usb_ep_free_request(io_data->ep, io_data->req);
678 684
679 io_data->kiocb->private = NULL; 685 io_data->kiocb->private = NULL;
@@ -827,6 +833,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
827 io_data->buf = data; 833 io_data->buf = data;
828 io_data->ep = ep->ep; 834 io_data->ep = ep->ep;
829 io_data->req = req; 835 io_data->req = req;
836 io_data->ffs = epfile->ffs;
830 837
831 req->context = io_data; 838 req->context = io_data;
832 req->complete = ffs_epfile_async_io_complete; 839 req->complete = ffs_epfile_async_io_complete;
@@ -1510,6 +1517,9 @@ static void ffs_data_clear(struct ffs_data *ffs)
1510 if (ffs->epfiles) 1517 if (ffs->epfiles)
1511 ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count); 1518 ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count);
1512 1519
1520 if (ffs->ffs_eventfd)
1521 eventfd_ctx_put(ffs->ffs_eventfd);
1522
1513 kfree(ffs->raw_descs_data); 1523 kfree(ffs->raw_descs_data);
1514 kfree(ffs->raw_strings); 1524 kfree(ffs->raw_strings);
1515 kfree(ffs->stringtabs); 1525 kfree(ffs->stringtabs);
@@ -2169,7 +2179,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
2169 FUNCTIONFS_HAS_HS_DESC | 2179 FUNCTIONFS_HAS_HS_DESC |
2170 FUNCTIONFS_HAS_SS_DESC | 2180 FUNCTIONFS_HAS_SS_DESC |
2171 FUNCTIONFS_HAS_MS_OS_DESC | 2181 FUNCTIONFS_HAS_MS_OS_DESC |
2172 FUNCTIONFS_VIRTUAL_ADDR)) { 2182 FUNCTIONFS_VIRTUAL_ADDR |
2183 FUNCTIONFS_EVENTFD)) {
2173 ret = -ENOSYS; 2184 ret = -ENOSYS;
2174 goto error; 2185 goto error;
2175 } 2186 }
@@ -2180,6 +2191,20 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
2180 goto error; 2191 goto error;
2181 } 2192 }
2182 2193
2194 if (flags & FUNCTIONFS_EVENTFD) {
2195 if (len < 4)
2196 goto error;
2197 ffs->ffs_eventfd =
2198 eventfd_ctx_fdget((int)get_unaligned_le32(data));
2199 if (IS_ERR(ffs->ffs_eventfd)) {
2200 ret = PTR_ERR(ffs->ffs_eventfd);
2201 ffs->ffs_eventfd = NULL;
2202 goto error;
2203 }
2204 data += 4;
2205 len -= 4;
2206 }
2207
2183 /* Read fs_count, hs_count and ss_count (if present) */ 2208 /* Read fs_count, hs_count and ss_count (if present) */
2184 for (i = 0; i < 3; ++i) { 2209 for (i = 0; i < 3; ++i) {
2185 if (!(flags & (1 << i))) { 2210 if (!(flags & (1 << i))) {
@@ -2454,6 +2479,8 @@ static void __ffs_event_add(struct ffs_data *ffs,
2454 pr_vdebug("adding event %d\n", type); 2479 pr_vdebug("adding event %d\n", type);
2455 ffs->ev.types[ffs->ev.count++] = type; 2480 ffs->ev.types[ffs->ev.count++] = type;
2456 wake_up_locked(&ffs->ev.waitq); 2481 wake_up_locked(&ffs->ev.waitq);
2482 if (ffs->ffs_eventfd)
2483 eventfd_signal(ffs->ffs_eventfd, 1);
2457} 2484}
2458 2485
2459static void ffs_event_add(struct ffs_data *ffs, 2486static void ffs_event_add(struct ffs_data *ffs,
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index 284a1f00a980..60139854e0b1 100644
--- a/drivers/usb/gadget/function/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -272,6 +272,7 @@ struct ffs_data {
272 kgid_t gid; 272 kgid_t gid;
273 } file_perms; 273 } file_perms;
274 274
275 struct eventfd_ctx *ffs_eventfd;
275 bool no_disconnect; 276 bool no_disconnect;
276 struct work_struct reset_work; 277 struct work_struct reset_work;
277 278