Mtp: splite ioctl lock into operation lock and event lock
authorliuji <liuji@rock-chips.com>
Tue, 20 Dec 2011 04:42:21 +0000 (12:42 +0800)
committerliuji <liuji@rock-chips.com>
Tue, 20 Dec 2011 04:42:21 +0000 (12:42 +0800)
Fix bug: operation and event cannot work concurrently.
remove/rename a file in android file explorer during coping/receiving
a large file to/from mtp device from pc, after all the operations
done, change in android would be ignore in pc explorer, because
file change event was block by the long operation and failed to send to
pc.

drivers/usb/gadget/f_mtp.c

index fce4346bb5462315103002387078669f9746f725..64ad4e6d234d42ba56e5784898ccd3b38a155ed4 100644 (file)
@@ -82,8 +82,9 @@ struct mtp_dev {
 
        /* synchronize access to our device file */
        atomic_t open_excl;
-       /* to enforce only one ioctl at a time */
-       atomic_t ioctl_excl;
+
+       atomic_t ioctl_opt_excl;   /* lock for operation */
+       atomic_t ioctl_event_excl; /* lock for event */
 
        struct list_head tx_idle;
        struct list_head intr_idle;
@@ -845,13 +846,13 @@ static long mtp_ioctl(struct file *fp, unsigned code, unsigned long value)
        struct file *filp = NULL;
        int ret = -EINVAL;
 
-       if (mtp_lock(&dev->ioctl_excl))
-               return -EBUSY;
 
        switch (code) {
        case MTP_SEND_FILE:
        case MTP_RECEIVE_FILE:
-       case MTP_SEND_FILE_WITH_HEADER:
+    case MTP_SEND_FILE_WITH_HEADER:
+        if (mtp_lock(&dev->ioctl_opt_excl))
+            return -EBUSY;
        {
                struct mtp_file_range   mfr;
                struct work_struct *work;
@@ -918,6 +919,10 @@ static long mtp_ioctl(struct file *fp, unsigned code, unsigned long value)
        case MTP_SEND_EVENT:
        {
                struct mtp_event        event;
+
+        if (mtp_lock(&dev->ioctl_event_excl))
+            return -EBUSY;
+
                /* return here so we don't change dev->state below,
                 * which would interfere with bulk transfer state.
                 */
@@ -937,7 +942,11 @@ fail:
                dev->state = STATE_READY;
        spin_unlock_irq(&dev->lock);
 out:
-       mtp_unlock(&dev->ioctl_excl);
+    if (MTP_SEND_EVENT == code)
+        mtp_unlock(&dev->ioctl_event_excl);
+    else
+        mtp_unlock(&dev->ioctl_opt_excl);
+
        DBG(dev->cdev, "ioctl returning %d\n", ret);
        return ret;
 }
@@ -1224,7 +1233,8 @@ static int mtp_setup(void)
        init_waitqueue_head(&dev->write_wq);
        init_waitqueue_head(&dev->intr_wq);
        atomic_set(&dev->open_excl, 0);
-       atomic_set(&dev->ioctl_excl, 0);
+       atomic_set(&dev->ioctl_opt_excl, 0);
+       atomic_set(&dev->ioctl_event_excl, 0);
        INIT_LIST_HEAD(&dev->tx_idle);
        INIT_LIST_HEAD(&dev->intr_idle);