diff options
author | Zhaolong Zhang <zhangzl2013@126.com> | 2018-11-16 13:21:51 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-11-27 13:19:10 +0300 |
commit | b5570ca7c475bffbc5fc2e9af994dc6d249eb13e (patch) | |
tree | 789278e2d7ff374f34261e140d9ef54a2042777d | |
parent | 3b1ad360acad6052c2568f891bb3d0f3f057016f (diff) | |
download | linux-b5570ca7c475bffbc5fc2e9af994dc6d249eb13e.tar.xz |
uio: dismiss waiters on device unregistration
When the device is unregistered, it should wake up the blocking waiters.
Otherwise, they will sleep forever.
Signed-off-by: Zhaolong Zhang <zhangzl2013@126.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/uio/uio.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 0a357db4b31b..131342280b46 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -569,20 +569,20 @@ static ssize_t uio_read(struct file *filep, char __user *buf, ssize_t retval = 0; s32 event_count; - mutex_lock(&idev->info_lock); - if (!idev->info || !idev->info->irq) - retval = -EIO; - mutex_unlock(&idev->info_lock); - - if (retval) - return retval; - if (count != sizeof(s32)) return -EINVAL; add_wait_queue(&idev->wait, &wait); do { + mutex_lock(&idev->info_lock); + if (!idev->info || !idev->info->irq) { + retval = -EIO; + mutex_unlock(&idev->info_lock); + break; + } + mutex_unlock(&idev->info_lock); + set_current_state(TASK_INTERRUPTIBLE); event_count = atomic_read(&idev->event); @@ -1017,6 +1017,9 @@ void uio_unregister_device(struct uio_info *info) idev->info = NULL; mutex_unlock(&idev->info_lock); + wake_up_interruptible(&idev->wait); + kill_fasync(&idev->async_queue, SIGIO, POLL_HUP); + device_unregister(&idev->dev); return; |