From: liuji Date: Tue, 20 Dec 2011 04:42:21 +0000 (+0800) Subject: Mtp: splite ioctl lock into operation lock and event lock X-Git-Tag: firefly_0821_release~9709^2 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=35ab4255763b59c9bc7833cc836c432c586849d4;p=firefly-linux-kernel-4.4.55.git Mtp: splite ioctl lock into operation lock and event lock 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. --- diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c index fce4346bb546..64ad4e6d234d 100644 --- a/drivers/usb/gadget/f_mtp.c +++ b/drivers/usb/gadget/f_mtp.c @@ -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);