usb: gadget: ffs: handle I/O completion in-order
PATCH 1/1 usb: gadget: ffs: handle I/O completion in-order
By submitting completed transfers to the system workqueue there is no guarantee that completion events will be queued up in the correct order, so if a large bulk transfer is being read with aio the data may arrive in the wrong order.
Create a single-threaded workqueue for FunctionFS so that completed requests are passed to userspace in the order in which they complete.
Signed-off-by John Keeping <[email protected]>
--- drivers/usb/gadget/function/f_fs.c | 10 +++++++++- drivers/usb/gadget/function/u_fs.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-)
drivers/usb/gadget/function/f_fs.c +9 -1
@@ -780,11 +780,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep, struct usb_request *req) {struct ffs_io_data *io_data = req->context; +struct ffs_data *ffs = io_data->ffs;ENTER ();INIT_WORK (&io_data->work, ffs_user_copy_worker); -schedule_work (&io_data->work); +queue_work (ffs->io_completion_wq, &io_data->work); }static void __ffs_epfile_read_buffer_free (struct ffs_epfile *epfile)
@@ -1611,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs)BUG_ON (waitqueue_active (&ffs->ev.waitq) ||waitqueue_active (&ffs->ep0req_completion.wait) ||waitqueue_active (&ffs->wait)); +destroy_workqueue (ffs->io_completion_wq);kfree (ffs->dev_name);kfree (ffs); }
@@ -1651,6 +1653,12 @@ static struct ffs_data *ffs_data_new(void)ENTER (); + ffs->io_completion_wq =create_singlethread_workqueue ("ffs-completion" ); +if (!ffs->io_completion_wq) { +kfree (ffs); +return NULL ; + } +refcount_set (&ffs->ref,1 );atomic_set (&ffs->opened,0 ); ffs->state =FFS_READ_DESCRIPTORS ;
drivers/usb/gadget/function/u_fs.h +1 -0
@@ -279,6 +279,7 @@ struct ffs_data { } file_perms;struct eventfd_ctx *ffs_eventfd; +struct workqueue_struct *io_completion_wq;bool no_disconnect;struct work_struct reset_work;
Signature · 1 line
2.12.2.648.g6730d8bc62.dirty