aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/inode.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index dda0dc4a5567..32bcbeba119e 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -24,6 +24,7 @@
24#include <linux/sched.h> 24#include <linux/sched.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/poll.h> 26#include <linux/poll.h>
27#include <linux/mmu_context.h>
27 28
28#include <linux/device.h> 29#include <linux/device.h>
29#include <linux/moduleparam.h> 30#include <linux/moduleparam.h>
@@ -513,6 +514,9 @@ static long ep_ioctl(struct file *fd, unsigned code, unsigned long value)
513struct kiocb_priv { 514struct kiocb_priv {
514 struct usb_request *req; 515 struct usb_request *req;
515 struct ep_data *epdata; 516 struct ep_data *epdata;
517 struct kiocb *iocb;
518 struct mm_struct *mm;
519 struct work_struct work;
516 void *buf; 520 void *buf;
517 const struct iovec *iv; 521 const struct iovec *iv;
518 unsigned long nr_segs; 522 unsigned long nr_segs;
@@ -540,15 +544,12 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
540 return value; 544 return value;
541} 545}
542 546
543static ssize_t ep_aio_read_retry(struct kiocb *iocb) 547static ssize_t ep_copy_to_user(struct kiocb_priv *priv)
544{ 548{
545 struct kiocb_priv *priv = iocb->private;
546 ssize_t len, total; 549 ssize_t len, total;
547 void *to_copy; 550 void *to_copy;
548 int i; 551 int i;
549 552
550 /* we "retry" to get the right mm context for this: */
551
552 /* copy stuff into user buffers */ 553 /* copy stuff into user buffers */
553 total = priv->actual; 554 total = priv->actual;
554 len = 0; 555 len = 0;
@@ -568,9 +569,26 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
568 if (total == 0) 569 if (total == 0)
569 break; 570 break;
570 } 571 }
572
573 return len;
574}
575
576static void ep_user_copy_worker(struct work_struct *work)
577{
578 struct kiocb_priv *priv = container_of(work, struct kiocb_priv, work);
579 struct mm_struct *mm = priv->mm;
580 struct kiocb *iocb = priv->iocb;
581 size_t ret;
582
583 use_mm(mm);
584 ret = ep_copy_to_user(priv);
585 unuse_mm(mm);
586
587 /* completing the iocb can drop the ctx and mm, don't touch mm after */
588 aio_complete(iocb, ret, ret);
589
571 kfree(priv->buf); 590 kfree(priv->buf);
572 kfree(priv); 591 kfree(priv);
573 return len;
574} 592}
575 593
576static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) 594static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
@@ -596,14 +614,14 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
596 aio_complete(iocb, req->actual ? req->actual : req->status, 614 aio_complete(iocb, req->actual ? req->actual : req->status,
597 req->status); 615 req->status);
598 } else { 616 } else {
599 /* retry() won't report both; so we hide some faults */ 617 /* ep_copy_to_user() won't report both; we hide some faults */
600 if (unlikely(0 != req->status)) 618 if (unlikely(0 != req->status))
601 DBG(epdata->dev, "%s fault %d len %d\n", 619 DBG(epdata->dev, "%s fault %d len %d\n",
602 ep->name, req->status, req->actual); 620 ep->name, req->status, req->actual);
603 621
604 priv->buf = req->buf; 622 priv->buf = req->buf;
605 priv->actual = req->actual; 623 priv->actual = req->actual;
606 kick_iocb(iocb); 624 schedule_work(&priv->work);
607 } 625 }
608 spin_unlock(&epdata->dev->lock); 626 spin_unlock(&epdata->dev->lock);
609 627
@@ -633,8 +651,10 @@ fail:
633 return value; 651 return value;
634 } 652 }
635 iocb->private = priv; 653 iocb->private = priv;
654 priv->iocb = iocb;
636 priv->iv = iv; 655 priv->iv = iv;
637 priv->nr_segs = nr_segs; 656 priv->nr_segs = nr_segs;
657 INIT_WORK(&priv->work, ep_user_copy_worker);
638 658
639 value = get_ready_ep(iocb->ki_filp->f_flags, epdata); 659 value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
640 if (unlikely(value < 0)) { 660 if (unlikely(value < 0)) {
@@ -646,6 +666,7 @@ fail:
646 get_ep(epdata); 666 get_ep(epdata);
647 priv->epdata = epdata; 667 priv->epdata = epdata;
648 priv->actual = 0; 668 priv->actual = 0;
669 priv->mm = current->mm; /* mm teardown waits for iocbs in exit_aio() */
649 670
650 /* each kiocb is coupled to one usb_request, but we can't 671 /* each kiocb is coupled to one usb_request, but we can't
651 * allocate or submit those if the host disconnected. 672 * allocate or submit those if the host disconnected.
@@ -674,7 +695,7 @@ fail:
674 kfree(priv); 695 kfree(priv);
675 put_ep(epdata); 696 put_ep(epdata);
676 } else 697 } else
677 value = (iv ? -EIOCBRETRY : -EIOCBQUEUED); 698 value = -EIOCBQUEUED;
678 return value; 699 return value;
679} 700}
680 701
@@ -692,7 +713,6 @@ ep_aio_read(struct kiocb *iocb, const struct iovec *iov,
692 if (unlikely(!buf)) 713 if (unlikely(!buf))
693 return -ENOMEM; 714 return -ENOMEM;
694 715
695 iocb->ki_retry = ep_aio_read_retry;
696 return ep_aio_rwtail(iocb, buf, iocb->ki_left, epdata, iov, nr_segs); 716 return ep_aio_rwtail(iocb, buf, iocb->ki_left, epdata, iov, nr_segs);
697} 717}
698 718