usb: gadget: function: f_fs: Move epfile waitqueue to ffs_data.
authorJerry Zhang <zhangjerry@google.com>
Tue, 18 Apr 2017 23:11:48 +0000 (16:11 -0700)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Fri, 2 Jun 2017 08:22:31 +0000 (11:22 +0300)
There were individual waitqueues for each epfile but eps_enable
would iterate through all of them, resulting in essentially the
same wakeup time.

The waitqueue represents the function being enabled, so a central
waitqueue in ffs_data makes more sense and is less redundant.

Also use wake_up_interruptible to reflect use of
wait_event_interruptible.

Acked-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Jerry Zhang <zhangjerry@google.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/u_fs.h

index a24f9bf9c1c0c35f4d24469ac57b72bf68641f09..519ea34ca699733439b9620470d3f6d5433d10e3 100644 (file)
@@ -127,7 +127,6 @@ struct ffs_ep {
 struct ffs_epfile {
        /* Protects ep->ep and ep->req. */
        struct mutex                    mutex;
-       wait_queue_head_t               wait;
 
        struct ffs_data                 *ffs;
        struct ffs_ep                   *ep;    /* P: ffs->eps_lock */
@@ -889,7 +888,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
                if (file->f_flags & O_NONBLOCK)
                        return -EAGAIN;
 
-               ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
+               ret = wait_event_interruptible(
+                               epfile->ffs->wait, (ep = epfile->ep));
                if (ret)
                        return -EINTR;
        }
@@ -1203,7 +1203,8 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
                if (file->f_flags & O_NONBLOCK)
                        return -EAGAIN;
 
-               ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
+               ret = wait_event_interruptible(
+                               epfile->ffs->wait, (ep = epfile->ep));
                if (ret)
                        return -EINTR;
        }
@@ -1608,7 +1609,8 @@ static void ffs_data_put(struct ffs_data *ffs)
                pr_info("%s(): freeing\n", __func__);
                ffs_data_clear(ffs);
                BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
-                      waitqueue_active(&ffs->ep0req_completion.wait));
+                      waitqueue_active(&ffs->ep0req_completion.wait) ||
+                      waitqueue_active(&ffs->wait));
                kfree(ffs->dev_name);
                kfree(ffs);
        }
@@ -1655,6 +1657,7 @@ static struct ffs_data *ffs_data_new(void)
        mutex_init(&ffs->mutex);
        spin_lock_init(&ffs->eps_lock);
        init_waitqueue_head(&ffs->ev.waitq);
+       init_waitqueue_head(&ffs->wait);
        init_completion(&ffs->ep0req_completion);
 
        /* XXX REVISIT need to update it in some places, or do we? */
@@ -1776,7 +1779,6 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
        for (i = 1; i <= count; ++i, ++epfile) {
                epfile->ffs = ffs;
                mutex_init(&epfile->mutex);
-               init_waitqueue_head(&epfile->wait);
                if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
                        sprintf(epfile->name, "ep%02x", ffs->eps_addrmap[i]);
                else
@@ -1801,8 +1803,7 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
        ENTER();
 
        for (; count; --count, ++epfile) {
-               BUG_ON(mutex_is_locked(&epfile->mutex) ||
-                      waitqueue_active(&epfile->wait));
+               BUG_ON(mutex_is_locked(&epfile->mutex));
                if (epfile->dentry) {
                        d_delete(epfile->dentry);
                        dput(epfile->dentry);
@@ -1889,11 +1890,11 @@ static int ffs_func_eps_enable(struct ffs_function *func)
                        break;
                }
 
-               wake_up(&epfile->wait);
-
                ++ep;
                ++epfile;
        }
+
+       wake_up_interruptible(&ffs->wait);
        spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
 
        return ret;
index 4378cc2fcac36fd69c71cdea53fef6e7ce6ce6e9..540f1c48c1a8d1a8bf058609bc5f455e3cf1dc57 100644 (file)
@@ -216,6 +216,9 @@ struct ffs_data {
 #define FFS_FL_CALL_CLOSED_CALLBACK 0
 #define FFS_FL_BOUND                1
 
+       /* For waking up blocked threads when function is enabled. */
+       wait_queue_head_t               wait;
+
        /* Active function */
        struct ffs_function             *func;