summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorINSUN PYO <insun.pyo@samsung.com>2018-10-04 10:26:22 +0900
committerSeung-Woo Kim <sw0312.kim@samsung.com>2018-10-11 12:44:15 +0900
commitfb8f8e60820f8d5428d6b02287c4373893f9a0f7 (patch)
tree72836622701127fce676c346213a03f0d2bff7e2
parenta205a11445ca26e72f7ef1ee6dddf075315f3b49 (diff)
downloadlinux-3.10-sc7730-accepted/tizen_5.0_unified.tar.gz
linux-3.10-sc7730-accepted/tizen_5.0_unified.tar.bz2
linux-3.10-sc7730-accepted/tizen_5.0_unified.zip
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>
-rw-r--r--drivers/usb/gadget/f_fs.c47
1 files changed, 20 insertions, 27 deletions
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index ac03922d..079dacc0 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -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;