diff options
author | Arnd Bergmann <arnd@arndb.de> | 2010-06-01 16:53:05 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 16:47:43 -0400 |
commit | be1bc2889a4db4961ef69f47fb471ecae9f23ade (patch) | |
tree | fd6d5e46e69efd9d66e6baa184988461f608f49a | |
parent | 4e608671674b62e97166f903830d5553e37970e8 (diff) |
tty: introduce wait_event_interruptible_tty
Calling wait_event_interruptible implicitly
releases the BKL when it sleeps, but we need
to do this explcitly when we have converted
it to a mutex.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/char/cyclades.c | 2 | ||||
-rw-r--r-- | drivers/char/istallion.c | 12 | ||||
-rw-r--r-- | drivers/char/n_r3964.c | 2 | ||||
-rw-r--r-- | drivers/char/tty_port.c | 2 | ||||
-rw-r--r-- | drivers/char/vt_ioctl.c | 5 | ||||
-rw-r--r-- | drivers/serial/crisv10.c | 4 | ||||
-rw-r--r-- | include/linux/tty.h | 42 |
7 files changed, 59 insertions, 10 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 51acfe39a438..27aad9422332 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -1607,7 +1607,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
1607 | * If the port is the middle of closing, bail out now | 1607 | * If the port is the middle of closing, bail out now |
1608 | */ | 1608 | */ |
1609 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { | 1609 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { |
1610 | wait_event_interruptible(info->port.close_wait, | 1610 | wait_event_interruptible_tty(info->port.close_wait, |
1611 | !(info->port.flags & ASYNC_CLOSING)); | 1611 | !(info->port.flags & ASYNC_CLOSING)); |
1612 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; | 1612 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; |
1613 | } | 1613 | } |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 5e9a81d8ebcf..be28391adb79 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -954,7 +954,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l | |||
954 | * order of opens and closes may not be preserved across shared | 954 | * order of opens and closes may not be preserved across shared |
955 | * memory, so we must wait until it is complete. | 955 | * memory, so we must wait until it is complete. |
956 | */ | 956 | */ |
957 | wait_event_interruptible(portp->raw_wait, | 957 | wait_event_interruptible_tty(portp->raw_wait, |
958 | !test_bit(ST_CLOSING, &portp->state)); | 958 | !test_bit(ST_CLOSING, &portp->state)); |
959 | if (signal_pending(current)) { | 959 | if (signal_pending(current)) { |
960 | return -ERESTARTSYS; | 960 | return -ERESTARTSYS; |
@@ -989,7 +989,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l | |||
989 | set_bit(ST_OPENING, &portp->state); | 989 | set_bit(ST_OPENING, &portp->state); |
990 | spin_unlock_irqrestore(&brd_lock, flags); | 990 | spin_unlock_irqrestore(&brd_lock, flags); |
991 | 991 | ||
992 | wait_event_interruptible(portp->raw_wait, | 992 | wait_event_interruptible_tty(portp->raw_wait, |
993 | !test_bit(ST_OPENING, &portp->state)); | 993 | !test_bit(ST_OPENING, &portp->state)); |
994 | if (signal_pending(current)) | 994 | if (signal_pending(current)) |
995 | rc = -ERESTARTSYS; | 995 | rc = -ERESTARTSYS; |
@@ -1020,7 +1020,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1020 | * occurs on this port. | 1020 | * occurs on this port. |
1021 | */ | 1021 | */ |
1022 | if (wait) { | 1022 | if (wait) { |
1023 | wait_event_interruptible(portp->raw_wait, | 1023 | wait_event_interruptible_tty(portp->raw_wait, |
1024 | !test_bit(ST_CLOSING, &portp->state)); | 1024 | !test_bit(ST_CLOSING, &portp->state)); |
1025 | if (signal_pending(current)) { | 1025 | if (signal_pending(current)) { |
1026 | return -ERESTARTSYS; | 1026 | return -ERESTARTSYS; |
@@ -1052,7 +1052,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1052 | * to come back. | 1052 | * to come back. |
1053 | */ | 1053 | */ |
1054 | rc = 0; | 1054 | rc = 0; |
1055 | wait_event_interruptible(portp->raw_wait, | 1055 | wait_event_interruptible_tty(portp->raw_wait, |
1056 | !test_bit(ST_CLOSING, &portp->state)); | 1056 | !test_bit(ST_CLOSING, &portp->state)); |
1057 | if (signal_pending(current)) | 1057 | if (signal_pending(current)) |
1058 | rc = -ERESTARTSYS; | 1058 | rc = -ERESTARTSYS; |
@@ -1073,6 +1073,10 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1073 | 1073 | ||
1074 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) | 1074 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) |
1075 | { | 1075 | { |
1076 | /* | ||
1077 | * no need for wait_event_tty because clearing ST_CMDING cannot block | ||
1078 | * on BTM | ||
1079 | */ | ||
1076 | wait_event_interruptible(portp->raw_wait, | 1080 | wait_event_interruptible(portp->raw_wait, |
1077 | !test_bit(ST_CMDING, &portp->state)); | 1081 | !test_bit(ST_CMDING, &portp->state)); |
1078 | if (signal_pending(current)) | 1082 | if (signal_pending(current)) |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index f4bd2591e39f..a98290d7a2c5 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -1079,7 +1079,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1079 | goto unlock; | 1079 | goto unlock; |
1080 | } | 1080 | } |
1081 | /* block until there is a message: */ | 1081 | /* block until there is a message: */ |
1082 | wait_event_interruptible(pInfo->read_wait, | 1082 | wait_event_interruptible_tty(pInfo->read_wait, |
1083 | (pMsg = remove_msg(pInfo, pClient))); | 1083 | (pMsg = remove_msg(pInfo, pClient))); |
1084 | } | 1084 | } |
1085 | 1085 | ||
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index a3bd1d0b66cf..35eb30402f18 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
@@ -231,7 +231,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
231 | 231 | ||
232 | /* block if port is in the process of being closed */ | 232 | /* block if port is in the process of being closed */ |
233 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 233 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
234 | wait_event_interruptible(port->close_wait, | 234 | wait_event_interruptible_tty(port->close_wait, |
235 | !(port->flags & ASYNC_CLOSING)); | 235 | !(port->flags & ASYNC_CLOSING)); |
236 | if (port->flags & ASYNC_HUP_NOTIFY) | 236 | if (port->flags & ASYNC_HUP_NOTIFY) |
237 | return -EAGAIN; | 237 | return -EAGAIN; |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index cf87c5336229..2bbeaaea46e9 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -133,7 +133,7 @@ static void vt_event_wait(struct vt_event_wait *vw) | |||
133 | list_add(&vw->list, &vt_events); | 133 | list_add(&vw->list, &vt_events); |
134 | spin_unlock_irqrestore(&vt_event_lock, flags); | 134 | spin_unlock_irqrestore(&vt_event_lock, flags); |
135 | /* Wait for it to pass */ | 135 | /* Wait for it to pass */ |
136 | wait_event_interruptible(vt_event_waitqueue, vw->done); | 136 | wait_event_interruptible_tty(vt_event_waitqueue, vw->done); |
137 | /* Dequeue it */ | 137 | /* Dequeue it */ |
138 | spin_lock_irqsave(&vt_event_lock, flags); | 138 | spin_lock_irqsave(&vt_event_lock, flags); |
139 | list_del(&vw->list); | 139 | list_del(&vw->list); |
@@ -1761,10 +1761,13 @@ int vt_move_to_console(unsigned int vt, int alloc) | |||
1761 | return -EIO; | 1761 | return -EIO; |
1762 | } | 1762 | } |
1763 | release_console_sem(); | 1763 | release_console_sem(); |
1764 | tty_lock(); | ||
1764 | if (vt_waitactive(vt + 1)) { | 1765 | if (vt_waitactive(vt + 1)) { |
1765 | pr_debug("Suspend: Can't switch VCs."); | 1766 | pr_debug("Suspend: Can't switch VCs."); |
1767 | tty_unlock(); | ||
1766 | return -EINTR; | 1768 | return -EINTR; |
1767 | } | 1769 | } |
1770 | tty_unlock(); | ||
1768 | return prev; | 1771 | return prev; |
1769 | } | 1772 | } |
1770 | 1773 | ||
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index f848e188deae..94bfb9f238e1 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
@@ -3992,7 +3992,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3992 | */ | 3992 | */ |
3993 | if (tty_hung_up_p(filp) || | 3993 | if (tty_hung_up_p(filp) || |
3994 | (info->flags & ASYNC_CLOSING)) { | 3994 | (info->flags & ASYNC_CLOSING)) { |
3995 | wait_event_interruptible(info->close_wait, | 3995 | wait_event_interruptible_tty(info->close_wait, |
3996 | !(info->flags & ASYNC_CLOSING)); | 3996 | !(info->flags & ASYNC_CLOSING)); |
3997 | #ifdef SERIAL_DO_RESTART | 3997 | #ifdef SERIAL_DO_RESTART |
3998 | if (info->flags & ASYNC_HUP_NOTIFY) | 3998 | if (info->flags & ASYNC_HUP_NOTIFY) |
@@ -4150,7 +4150,7 @@ rs_open(struct tty_struct *tty, struct file * filp) | |||
4150 | */ | 4150 | */ |
4151 | if (tty_hung_up_p(filp) || | 4151 | if (tty_hung_up_p(filp) || |
4152 | (info->flags & ASYNC_CLOSING)) { | 4152 | (info->flags & ASYNC_CLOSING)) { |
4153 | wait_event_interruptible(info->close_wait, | 4153 | wait_event_interruptible_tty(info->close_wait, |
4154 | !(info->flags & ASYNC_CLOSING)); | 4154 | !(info->flags & ASYNC_CLOSING)); |
4155 | #ifdef SERIAL_DO_RESTART | 4155 | #ifdef SERIAL_DO_RESTART |
4156 | return ((info->flags & ASYNC_HUP_NOTIFY) ? | 4156 | return ((info->flags & ASYNC_HUP_NOTIFY) ? |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 6ead6b60c743..955d72ea71c0 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -607,5 +607,47 @@ static inline void tty_unlock(void) __releases(kernel_lock) | |||
607 | } | 607 | } |
608 | #define tty_locked() (kernel_locked()) | 608 | #define tty_locked() (kernel_locked()) |
609 | 609 | ||
610 | /* | ||
611 | * wait_event_interruptible_tty -- wait for a condition with the tty lock held | ||
612 | * | ||
613 | * The condition we are waiting for might take a long time to | ||
614 | * become true, or might depend on another thread taking the | ||
615 | * BTM. In either case, we need to drop the BTM to guarantee | ||
616 | * forward progress. This is a leftover from the conversion | ||
617 | * from the BKL and should eventually get removed as the BTM | ||
618 | * falls out of use. | ||
619 | * | ||
620 | * Do not use in new code. | ||
621 | */ | ||
622 | #define wait_event_interruptible_tty(wq, condition) \ | ||
623 | ({ \ | ||
624 | int __ret = 0; \ | ||
625 | if (!(condition)) { \ | ||
626 | __wait_event_interruptible_tty(wq, condition, __ret); \ | ||
627 | } \ | ||
628 | __ret; \ | ||
629 | }) | ||
630 | |||
631 | #define __wait_event_interruptible_tty(wq, condition, ret) \ | ||
632 | do { \ | ||
633 | DEFINE_WAIT(__wait); \ | ||
634 | \ | ||
635 | for (;;) { \ | ||
636 | prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \ | ||
637 | if (condition) \ | ||
638 | break; \ | ||
639 | if (!signal_pending(current)) { \ | ||
640 | tty_unlock(); \ | ||
641 | schedule(); \ | ||
642 | tty_lock(); \ | ||
643 | continue; \ | ||
644 | } \ | ||
645 | ret = -ERESTARTSYS; \ | ||
646 | break; \ | ||
647 | } \ | ||
648 | finish_wait(&wq, &__wait); \ | ||
649 | } while (0) | ||
650 | |||
651 | |||
610 | #endif /* __KERNEL__ */ | 652 | #endif /* __KERNEL__ */ |
611 | #endif | 653 | #endif |