usb: gadget: f_fs: remove global epin/epout fileio completion 61/190561/5 accepted/tizen_5.0_unified accepted/tizen/5.0/unified/20181106.202900 accepted/tizen/unified/20181011.095032 submit/tizen/20181011.060219 submit/tizen_5.0/20181101.000009 submit/tizen_5.0/20181106.000001
authorINSUN PYO <insun.pyo@samsung.com>
Thu, 4 Oct 2018 01:26:22 +0000 (10:26 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Thu, 11 Oct 2018 03:44:15 +0000 (12:44 +0900)
In product code, global epin/epi fileio completion is applied but
if more than one multiple instance of functionfs are used, the
global completions cause transfer error. Remove global epin/epout
fileio to resolve transfer error in functionfs.

Change-Id: Ic71b34bbc83e0cfd9e76321fc4b8f86c2e259bfd
Signed-off-by: INSUN PYO <insun.pyo@samsung.com>
[sw0312.kim: rebase and remove related unnecessary part also]
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
drivers/usb/gadget/f_fs.c

index ac03922..079dacc 100644 (file)
@@ -146,8 +146,6 @@ struct ffs_data {
        struct usb_request              *ep0req;                /* P: mutex */
        struct completion               ep0req_completion;      /* P: mutex */
        int                             ep0req_status;          /* P: mutex */
-       struct completion               epin_completion;           /* P: mutex */
-       struct completion               epout_completion;               /* P: mutex */  
 
        /* reference counter */
        atomic_t                        ref;
@@ -795,10 +793,8 @@ static const struct file_operations ffs_ep0_operations = {
 
 static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
 {
-       struct  ffs_ep *ep = _ep->driver_data;
        ENTER();
-       /* req may be freed during unbind */
-       if (ep && ep->req && likely(req->context)) {
+       if (likely(req->context)) {
                struct ffs_ep *ep = _ep->driver_data;
                ep->status = req->status ? req->status : req->actual;
                complete(req->context);
@@ -809,7 +805,6 @@ static ssize_t ffs_epfile_io(struct file *file,
                             char __user *buf, size_t len, int read)
 {
        struct ffs_epfile *epfile = file->private_data;
-       struct ffs_data         *ffs = epfile->ffs;
        struct ffs_ep *ep;
        char *data = NULL;
        ssize_t ret, data_len;
@@ -892,37 +887,37 @@ first_try:
                spin_unlock_irq(&epfile->ffs->eps_lock);
                ret = -EBADMSG;
        } else {
-               /* Fire the request */
-               struct completion               *done;
-
+               DECLARE_COMPLETION_ONSTACK(done);
                struct usb_request *req = ep->req;
+               req->context  = &done;
                req->complete = ffs_epfile_io_complete;
                req->buf      = data;
                req->length   = data_len;
 
-               if (read) {
-                               INIT_COMPLETION(ffs->epout_completion);
-                               req->context = done = &ffs->epout_completion;
-               } else {
-                               INIT_COMPLETION(ffs->epin_completion);
-                               req->context = done = &ffs->epin_completion;
-               }
-
                ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
 
                spin_unlock_irq(&epfile->ffs->eps_lock);
 
                if (unlikely(ret < 0)) {
                        /* nop */
-               } else  if (unlikely(wait_for_completion_interruptible(done))) {
-                               ret = -EINTR;
-                               usb_ep_dequeue(ep->ep, req);
+               } else  if (unlikely(
+                           wait_for_completion_interruptible(&done))) {
+                       ret = -EINTR;
+                       usb_ep_dequeue(ep->ep, req);
                } else {
-                               ret = ep->status;
-                               if (read && ret > 0){
-                                       ret = min_t(size_t, ret, len);
-                                       if(unlikely(copy_to_user(buf, data, ret)))
-                                               ret = -EFAULT;
+                       /*
+                        * XXX We may end up silently droping data
+                        * here.  Since data_len (i.e. req->length) may
+                        * be bigger than len (after being rounded up
+                        * to maxpacketsize), we may end up with more
+                        * data then user space has space for.
+                        */
+                       ret = ep->status;
+                       if (read && ret > 0) {
+                               ret = min_t(size_t, ret, len);
+
+                               if(unlikely(copy_to_user(buf, data, ret)))
+                                       ret = -EFAULT;
                        }
                }
        }
@@ -1433,8 +1428,6 @@ static struct ffs_data *ffs_data_new(void)
        spin_lock_init(&ffs->eps_lock);
        init_waitqueue_head(&ffs->ev.waitq);
        init_completion(&ffs->ep0req_completion);
-       init_completion(&ffs->epin_completion);
-       init_completion(&ffs->epout_completion);
 
        /* XXX REVISIT need to update it in some places, or do we? */
        ffs->ev.can_stall = 1;