]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
uio: dismiss waiters on device unregistration
authorZhaolong Zhang <zhangzl2013@126.com>
Fri, 16 Nov 2018 10:21:51 +0000 (18:21 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 27 Nov 2018 10:19:10 +0000 (11:19 +0100)
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>
drivers/uio/uio.c

index 0a357db4b31b37ddd3ceedd25ecde5f7572d7690..131342280b467eb7f84028ee1a9a7cb2e6dc3cd6 100644 (file)
@@ -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;